1/* 2 * Test glMapBuffer() and glMapBufferRange() 3 * 4 * Fill a VBO with vertex data to draw several colored quads. 5 * On each redraw, update the geometry for just one rect in the VBO. 6 * 7 * Brian Paul 8 * 4 March 2009 9 */ 10 11 12#include <assert.h> 13#include <math.h> 14#include <stdio.h> 15#include <stdlib.h> 16#include <string.h> 17#include <GL/glew.h> 18#include <GL/glew.h> 19#include "glut_wrap.h" 20 21static GLuint Win; 22static const GLuint NumRects = 10; 23static GLuint BufferID; 24static GLboolean Anim = GL_TRUE; 25static GLboolean UseBufferRange = GL_FALSE; 26 27 28 29static const float RectData[] = { 30 /* vertex */ /* color */ 31 0, -1, 0, 1, 0, 0, 32 1, 0, 0, 1, 1, 0, 33 0, 1, 0, 0, 1, 1, 34 -1, 0, 0, 1, 0, 1 35}; 36 37 38/** 39 * The buffer contains vertex positions (float[3]) and colors (float[3]) 40 * for 'NumRects' quads. 41 * This function updates/rotates one quad in the buffer. 42 */ 43static void 44UpdateRect(int r, float angle) 45{ 46 float *rect; 47 int i; 48 49 assert(r < NumRects); 50 51 glBindBufferARB(GL_ARRAY_BUFFER_ARB, BufferID); 52 if (UseBufferRange) { 53 GLintptr offset = r * sizeof(RectData); 54 GLsizeiptr length = sizeof(RectData); 55 GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT; 56 float *buf = (float *) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 57 offset, length, access); 58 rect = buf; 59 } 60 else { 61 /* map whole buffer */ 62 float *buf = (float *) 63 glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); 64 rect = buf + r * 24; 65 } 66 67 /* set rect verts/colors */ 68 memcpy(rect, RectData, sizeof(RectData)); 69 70 /* loop over four verts, updating vertices */ 71 for (i = 0; i < 4; i++) { 72 float x = 0.2 * RectData[i*6+0]; 73 float y = 0.2 * RectData[i*6+1]; 74 float xpos = -2.5 + 0.5 * r; 75 float ypos = 0.0; 76 77 /* translate and rotate vert */ 78 rect[i * 6 + 0] = xpos + x * cos(angle) + y * sin(angle); 79 rect[i * 6 + 1] = ypos + x * sin(angle) - y * cos(angle); 80 } 81 82 glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); 83} 84 85 86static void 87LoadBuffer(void) 88{ 89 static int frame = 0; 90 float angle = glutGet(GLUT_ELAPSED_TIME) * 0.001; 91 UpdateRect(frame % NumRects, angle); 92 frame++; 93} 94 95 96static void 97Draw(void) 98{ 99 glBindBufferARB(GL_ARRAY_BUFFER_ARB, BufferID); 100 glVertexPointer(3, GL_FLOAT, 24, 0); 101 glEnableClientState(GL_VERTEX_ARRAY); 102 103 glColorPointer(3, GL_FLOAT, 24, (void*) 12); 104 glEnableClientState(GL_COLOR_ARRAY); 105 106 glDrawArrays(GL_QUADS, 0, NumRects * 4); 107 108 if (0) 109 glFinish(); 110} 111 112 113static void 114Display(void) 115{ 116 glClear(GL_COLOR_BUFFER_BIT); 117 Draw(); 118 glutSwapBuffers(); 119} 120 121 122static void 123Reshape(int width, int height) 124{ 125 glViewport(0, 0, width, height); 126 glMatrixMode(GL_PROJECTION); 127 glLoadIdentity(); 128 glOrtho(-3.0, 3.0, -1.0, 1.0, -1.0, 1.0); 129 glMatrixMode(GL_MODELVIEW); 130 glLoadIdentity(); 131} 132 133 134static void 135Idle(void) 136{ 137 LoadBuffer(); 138 glutPostRedisplay(); 139} 140 141 142static void 143Key(unsigned char key, int x, int y) 144{ 145 (void) x; 146 (void) y; 147 if (key == 'a') { 148 Anim = !Anim; 149 glutIdleFunc(Anim ? Idle : NULL); 150 } 151 else if (key == 's') { 152 LoadBuffer(); 153 } 154 else if (key == 27) { 155 glutDestroyWindow(Win); 156 exit(0); 157 } 158 glutPostRedisplay(); 159} 160 161 162static void 163Init(void) 164{ 165 GLuint BufferSize = NumRects * sizeof(RectData); 166 float *buf; 167 168 if (!glutExtensionSupported("GL_ARB_vertex_buffer_object")) { 169 printf("GL_ARB_vertex_buffer_object not found!\n"); 170 exit(0); 171 } 172 173 UseBufferRange = glutExtensionSupported("GL_ARB_map_buffer_range"); 174 printf("Use GL_ARB_map_buffer_range: %c\n", "NY"[UseBufferRange]); 175 176 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 177 178 /* initially load buffer with zeros */ 179 buf = (float *) calloc(1, BufferSize); 180 181 glGenBuffersARB(1, &BufferID); 182 glBindBufferARB(GL_ARRAY_BUFFER_ARB, BufferID); 183 glBufferDataARB(GL_ARRAY_BUFFER_ARB, BufferSize, buf, GL_DYNAMIC_DRAW_ARB); 184 185 free(buf); 186} 187 188 189int 190main(int argc, char *argv[]) 191{ 192 glutInit(&argc, argv); 193 glutInitWindowSize(800, 200); 194 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 195 Win = glutCreateWindow(argv[0]); 196 glewInit(); 197 glewInit(); 198 glutReshapeFunc(Reshape); 199 glutKeyboardFunc(Key); 200 glutDisplayFunc(Display); 201 glutIdleFunc(Anim ? Idle : NULL); 202 Init(); 203 glutMainLoop(); 204 return 0; 205} 206