2 * Test GL_ARB_vertex_buffer_object
3 * Also test GL_ARB_vertex_array_object if supported
18 #define NUM_OBJECTS 10
22 GLuint ArrayObjectID
; /** GL_ARB_vertex_array_object */
23 GLuint VertexBufferID
;
25 GLuint ElementsBufferID
;
35 static struct object Objects
[NUM_OBJECTS
];
36 static GLuint NumObjects
;
40 static GLfloat Xrot
= 0, Yrot
= 0, Zrot
= 0;
41 static GLboolean Anim
= GL_TRUE
;
42 static GLboolean Have_ARB_vertex_array_object
= GL_FALSE
;
45 static void CheckError(int line
)
47 GLenum err
= glGetError();
49 printf("GL Error 0x%x at line %d\n", (int) err
, line
);
54 static void DrawObject( const struct object
*obj
)
56 if (Have_ARB_vertex_array_object
&& obj
->ArrayObjectID
) {
57 glBindVertexArray(obj
->ArrayObjectID
);
59 if (obj
->NumElements
> 0) {
61 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, obj
->ElementsBufferID
);
62 glDrawRangeElements(GL_LINE_LOOP
, 0, obj
->MaxElement
,
63 obj
->NumElements
, GL_UNSIGNED_INT
, NULL
);
66 /* non-indexed arrays */
67 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 0);
68 glDrawArrays(GL_LINE_LOOP
, 0, obj
->NumVerts
);
74 /* no vertex array objects, must set vertex/color pointers per draw */
76 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
77 glVertexPointer(3, GL_FLOAT
, obj
->VertexStride
, (void *) obj
->VertexOffset
);
78 glEnableClientState(GL_VERTEX_ARRAY
);
80 /* test push/pop attrib */
81 /* XXX this leads to a segfault with NVIDIA's 53.36 driver */
85 glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT
);
86 /*glVertexPointer(3, GL_FLOAT, 0, (void *) (obj->VertexOffset + 10000));*/
87 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, 999999);
91 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->ColorBufferID
);
92 glColorPointer(3, GL_FLOAT
, obj
->ColorStride
, (void *) obj
->ColorOffset
);
93 glEnableClientState(GL_COLOR_ARRAY
);
95 if (obj
->NumElements
> 0) {
97 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, obj
->ElementsBufferID
);
98 glDrawElements(GL_LINE_LOOP
, obj
->NumElements
, GL_UNSIGNED_INT
, NULL
);
101 /* non-indexed arrays */
102 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 0);
103 glDrawArrays(GL_LINE_LOOP
, 0, obj
->NumVerts
);
109 static void Idle( void )
111 Zrot
= 0.05 * glutGet(GLUT_ELAPSED_TIME
);
116 static void Display( void )
120 glClear( GL_COLOR_BUFFER_BIT
);
122 for (i
= 0; i
< NumObjects
; i
++) {
123 float x
= 7.0 * ((float) i
/ (NumObjects
-1) - 0.5);
125 glTranslatef(x
, 0, 0);
126 glRotatef(Xrot
, 1, 0, 0);
127 glRotatef(Yrot
, 0, 1, 0);
128 glRotatef(Zrot
, 0, 0, 1);
130 DrawObject(Objects
+ i
);
135 CheckError(__LINE__
);
140 static void Reshape( int width
, int height
)
142 float ar
= (float) width
/ (float) height
;
143 glViewport( 0, 0, width
, height
);
144 glMatrixMode( GL_PROJECTION
);
146 glFrustum( -ar
, ar
, -1.0, 1.0, 5.0, 25.0 );
147 glMatrixMode( GL_MODELVIEW
);
149 glTranslatef( 0.0, 0.0, -15.0 );
153 static void FreeBuffers(void)
156 for (i
= 0; i
< NUM_OBJECTS
; i
++) {
157 glDeleteBuffersARB(1, &Objects
[i
].VertexBufferID
);
158 glDeleteBuffersARB(1, &Objects
[i
].ColorBufferID
);
159 glDeleteBuffersARB(1, &Objects
[i
].ElementsBufferID
);
164 static void Key( unsigned char key
, int x
, int y
)
166 const GLfloat step
= 3.0;
185 glutDestroyWindow(Win
);
193 static void SpecialKey( int key
, int x
, int y
)
195 const GLfloat step
= 3.0;
217 * If GL_ARB_vertex_array_object is supported, create an array object
218 * and set all the per-array state.
221 CreateVertexArrayObject(struct object
*obj
)
223 glGenVertexArrays(1, &obj
->ArrayObjectID
);
224 glBindVertexArray(obj
->ArrayObjectID
);
226 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
227 glVertexPointer(3, GL_FLOAT
, obj
->VertexStride
, (void *) obj
->VertexOffset
);
228 glEnableClientState(GL_VERTEX_ARRAY
);
230 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->ColorBufferID
);
231 glColorPointer(3, GL_FLOAT
, obj
->ColorStride
, (void *) obj
->ColorOffset
);
232 glEnableClientState(GL_COLOR_ARRAY
);
234 glBindVertexArray(0);
239 * Non-interleaved position/color data.
241 static void MakeObject1(struct object
*obj
)
248 for (i
= 0; i
< 500; i
++)
249 buffer
[i
] = i
& 0xff;
251 obj
->VertexBufferID
= 0;
252 glGenBuffersARB(1, &obj
->VertexBufferID
);
253 obj
->ColorBufferID
= obj
->VertexBufferID
;
254 assert(obj
->VertexBufferID
!= 0);
255 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
256 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, 500, buffer
, GL_STATIC_DRAW_ARB
);
258 for (i
= 0; i
< 500; i
++)
261 glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB
, 0, 500, buffer
);
263 for (i
= 0; i
< 500; i
++)
264 assert(buffer
[i
] == (i
& 0xff));
266 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_MAPPED_ARB
, &i
);
269 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_USAGE_ARB
, &i
);
271 v
= (GLfloat
*) glMapBufferARB(GL_ARRAY_BUFFER_ARB
, GL_WRITE_ONLY_ARB
);
273 /* do some sanity tests */
274 glGetBufferPointervARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_MAP_POINTER_ARB
, &p
);
277 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_SIZE_ARB
, &i
);
280 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_USAGE_ARB
, &i
);
281 assert(i
== GL_STATIC_DRAW_ARB
);
283 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_ACCESS_ARB
, &i
);
284 assert(i
== GL_WRITE_ONLY_ARB
);
286 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_MAPPED_ARB
, &i
);
290 v
[0] = -1; v
[1] = -1; v
[2] = 0;
291 v
[3] = 1; v
[4] = -1; v
[5] = 0;
292 v
[6] = 1; v
[7] = 1; v
[8] = 0;
293 v
[9] = -1; v
[10] = 1; v
[11] = 0;
295 c
[0] = 1; c
[1] = 0; c
[2] = 0;
296 c
[3] = 1; c
[4] = 0; c
[5] = 0;
297 c
[6] = 1; c
[7] = 0; c
[8] = 1;
298 c
[9] = 1; c
[10] = 0; c
[11] = 1;
300 obj
->VertexOffset
= 0;
301 obj
->ColorOffset
= 3 * sizeof(GLfloat
) * obj
->NumVerts
;
302 obj
->VertexStride
= 0;
303 obj
->ColorStride
= 0;
304 obj
->NumElements
= 0;
307 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB
);
309 glGetBufferPointervARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_MAP_POINTER_ARB
, &p
);
312 glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB
, GL_BUFFER_MAPPED_ARB
, &i
);
315 if (Have_ARB_vertex_array_object
) {
316 CreateVertexArrayObject(obj
);
322 * Interleaved position/color data.
324 static void MakeObject2(struct object
*obj
)
327 int start
= 40; /* bytes, to test non-zero array offsets */
329 glGenBuffersARB(1, &obj
->VertexBufferID
);
330 obj
->ColorBufferID
= obj
->VertexBufferID
;
332 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
333 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, 1000, NULL
, GL_STATIC_DRAW_ARB
);
334 v
= (GLfloat
*) glMapBufferARB(GL_ARRAY_BUFFER_ARB
, GL_WRITE_ONLY_ARB
);
336 v
+= start
/ sizeof(GLfloat
);
338 /* Make triangle: interleaved colors, then positions */
340 v
[0] = 0; v
[1] = 1; v
[2] = 0; v
[3] = -1; v
[4] = -1; v
[5] = 0;
341 v
[6] = 0; v
[7] = 1; v
[8] = 0; v
[9] = 1; v
[10] = -1; v
[11] = 0;
342 v
[12] = 1; v
[13] = 1; v
[14] = 0; v
[15] = 0; v
[16] = 1; v
[17] = 0;
345 obj
->VertexOffset
= start
+ 3 * sizeof(GLfloat
);
346 obj
->ColorOffset
= start
;
347 obj
->VertexStride
= 6 * sizeof(GLfloat
);
348 obj
->ColorStride
= 6 * sizeof(GLfloat
);
350 obj
->NumElements
= 0;
353 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB
);
355 if (Have_ARB_vertex_array_object
) {
356 CreateVertexArrayObject(obj
);
362 * Use an index buffer and glDrawElements().
364 static void MakeObject3(struct object
*obj
)
366 GLfloat vertexData
[1000];
373 v
[0] = -1; v
[1] = -0.5; v
[2] = 0;
374 v
[3] = 1; v
[4] = -0.5; v
[5] = 0;
375 v
[6] = 1; v
[7] = 0.5; v
[8] = 0;
376 v
[9] = -1; v
[10] = 0.5; v
[11] = 0;
378 c
[0] = 0; c
[1] = 0; c
[2] = 1;
379 c
[3] = 0; c
[4] = 0; c
[5] = 1;
380 c
[6] = 0; c
[7] = 1; c
[8] = 1;
381 c
[9] = 0; c
[10] = 1; c
[11] = 1;
383 obj
->VertexOffset
= 0;
384 obj
->ColorOffset
= 3 * sizeof(GLfloat
) * obj
->NumVerts
;
385 obj
->VertexStride
= 0;
386 obj
->ColorStride
= 0;
388 bytes
= obj
->NumVerts
* (3 + 3) * sizeof(GLfloat
);
390 /* Don't use glMap/UnmapBuffer for this object */
391 glGenBuffersARB(1, &obj
->VertexBufferID
);
392 obj
->ColorBufferID
= obj
->VertexBufferID
;
394 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
395 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, bytes
, vertexData
, GL_STATIC_DRAW_ARB
);
397 /* Setup a buffer of indices to test the ELEMENTS path */
398 glGenBuffersARB(1, &obj
->ElementsBufferID
);
399 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, obj
->ElementsBufferID
);
400 glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 100, NULL
, GL_STATIC_DRAW_ARB
);
401 i
= (GLuint
*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, GL_READ_WRITE_ARB
);
406 glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
);
407 obj
->NumElements
= 4;
410 if (Have_ARB_vertex_array_object
) {
411 CreateVertexArrayObject(obj
);
417 * Vertex and color data in different buffers.
419 static void MakeObject4(struct object
*obj
)
421 static const GLfloat vertexData
[] = {
427 static const GLfloat colorData
[] = {
434 obj
->VertexOffset
= 0;
435 obj
->VertexStride
= 0;
436 obj
->ColorOffset
= 0;
437 obj
->ColorStride
= 0;
440 glGenBuffersARB(1, &obj
->VertexBufferID
);
441 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->VertexBufferID
);
442 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, sizeof(vertexData
), vertexData
,
445 glGenBuffersARB(1, &obj
->ColorBufferID
);
446 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, obj
->ColorBufferID
);
447 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, sizeof(colorData
), colorData
,
450 /* Setup a buffer of indices to test the ELEMENTS path */
451 obj
->ElementsBufferID
= 0;
452 obj
->NumElements
= 0;
455 if (Have_ARB_vertex_array_object
) {
456 CreateVertexArrayObject(obj
);
462 static void Init( void )
464 if (!glutExtensionSupported("GL_ARB_vertex_buffer_object")) {
465 printf("GL_ARB_vertex_buffer_object not found!\n");
468 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
470 Have_ARB_vertex_array_object
=
471 glutExtensionSupported("GL_ARB_vertex_array_object");
473 printf("Using GL_ARB_vertex_array_object: %s\n",
474 (Have_ARB_vertex_array_object
? "yes" : "no"));
477 /* Test buffer object deletion */
479 static GLubyte data
[1000];
481 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, id
);
482 glBufferDataARB(GL_ARRAY_BUFFER_ARB
, 1000, data
, GL_STATIC_DRAW_ARB
);
483 glVertexPointer(3, GL_FLOAT
, 0, (void *) 0);
484 glDeleteBuffersARB(1, &id
);
485 assert(!glIsBufferARB(id
));
486 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, 0);
487 glVertexPointer(3, GL_FLOAT
, 0, (void *) 0);
488 assert(!glIsBufferARB(id
));
491 memset(Objects
, 0, sizeof(Objects
));
492 MakeObject1(Objects
+ 0);
493 MakeObject2(Objects
+ 1);
494 MakeObject3(Objects
+ 2);
495 MakeObject4(Objects
+ 3);
500 int main( int argc
, char *argv
[] )
502 glutInit( &argc
, argv
);
503 glutInitWindowPosition( 0, 0 );
504 glutInitWindowSize( 600, 300 );
505 glutInitDisplayMode( GLUT_RGB
| GLUT_DOUBLE
);
506 Win
= glutCreateWindow(argv
[0]);
508 glutReshapeFunc( Reshape
);
509 glutKeyboardFunc( Key
);
510 glutSpecialFunc( SpecialKey
);
511 glutDisplayFunc( Display
);