Graphics Programming
Buffer Objects
Thorsten Thormählen
December 10, 2021
Part 8, Chapter 1
Thorsten Thormählen
December 10, 2021
Part 8, Chapter 1
This is the print version of the slides.
Advance slides with the → key or
by clicking on the right border of the slide
Slides can also be advanced by clicking on the left or right border of the slide.
Type | Font | Examples |
---|---|---|
Variables (scalars) | italics | $a, b, x, y$ |
Functions | upright | $\mathrm{f}, \mathrm{g}(x), \mathrm{max}(x)$ |
Vectors | bold, elements row-wise | $\mathbf{a}, \mathbf{b}= \begin{pmatrix}x\\y\end{pmatrix} = (x, y)^\top,$ $\mathbf{B}=(x, y, z)^\top$ |
Matrices | Typewriter | $\mathtt{A}, \mathtt{B}= \begin{bmatrix}a & b\\c & d\end{bmatrix}$ |
Sets | calligraphic | $\mathcal{A}, B=\{a, b\}, b \in \mathcal{B}$ |
Number systems, Coordinate spaces | double-struck | $\mathbb{N}, \mathbb{Z}, \mathbb{R}^2, \mathbb{R}^3$ |
... glColor3f(1.0f, 1.0f, 0.0f); glBegin(GL_POLYGON); glTexCoord2f(0.25f,0.50f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.25f,0.25f); glVertex3f(-1.0f,-1.0f, 1.0f); glTexCoord2f(0.50f,0.25f); glVertex3f( 1.0f,-1.0f, 1.0f); glTexCoord2f(0.50f,0.50f); glVertex3f( 1.0f, 1.0f, 1.0f); glEnd(); ...
glBegin
, glVertex
, etc.)
are only supported in the "Compatibility Profile"init()
glGenBuffers(1, &bufID)
is generating an unique identifier glBindBuffer(GL_ARRAY_BUFFER, bufID)
a new VBO is created.
Possible targets are GL_ARRAY_BUFFER
or GL_ELEMENT_ARRAY_BUFFER
glBufferData(GL_ARRAY_BUFFER, size, inData, GL_STATIC_DRAW)
transfers the vertex dataglBindBuffer(GL_ARRAY_BUFFER, bufID)
glEnableClientState(GL_VERTEX_ARRAY)
.GL_VERTEX_ARRAY
, GL_COLOR_ARRAY
, GL_SECONDARY_COLOR_ARRAY
, GL_INDEX_ARRAY
,
GL_NORMAL_ARRAY
, GL_TEXTURE_COORD_ARRAY
usw.glDrawArrays(GL_POLYGON, first, count);Possible arguments are the same as those of
glBegin(...)
, such as GL_POLYGON
, GL_LINE_LOOP
, GL_LINES
, GL_POINTS
, etc.
glDeleteBuffers(1, &bufID)
class Renderer { public: float t; int mode; private: GLuint bufID; int bufSize; public: // constructor Renderer() : t(0.0), mode(0), bufID(0), bufSize(0) {} //destructor ~Renderer() { if(bufID !=0) glDeleteBuffers( 1, &bufID); } public: void init() { glEnable(GL_DEPTH_TEST); // generating VBO input data std::vector<float> dataIn; unsigned ayimutSegs = 1000; unsigned polarSegs = 1000; float ayimutStep = 2.0f * M_PI / float(ayimutSegs); float polarStep = M_PI / float(polarSegs); float r = 1.0; bufSize = 0; for(unsigned m=0; m < ayimutSegs; m++) { for(unsigned n=0; n < polarSegs; n++) { float phi = ayimutStep*m; float theta = polarStep * n; // compute xyz from spherical coordinates float x = r * sin(theta) * cos(phi); float y = r * sin(theta) * sin(phi); float z = r * cos(theta); dataIn.push_back(x); dataIn.push_back(y); dataIn.push_back(z); bufSize++; } } // generating VBO glGenBuffers(1, &bufID); glBindBuffer(GL_ARRAY_BUFFER, bufID); glBufferData(GL_ARRAY_BUFFER, dataIn.size()*sizeof(float), &dataIn[0], GL_STATIC_DRAW); } void resize(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (30.0, (float)w/(float)h, 0.1, 50.0); } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // set camera gluLookAt(3.5, -1.0, 3.5, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); // draw scene glRotatef(t, 0.0f, 0.0f, 1.0f); // activating VBO glBindBuffer(GL_ARRAY_BUFFER, bufID); int stride = 0; glVertexPointer(3, GL_FLOAT, stride, NULL); glEnableClientState(GL_VERTEX_ARRAY); if(mode == 0) { glColor3f(1.0f,1.0f,1.0f); }else{ glColorPointer(3, GL_FLOAT, stride, NULL); glEnableClientState(GL_COLOR_ARRAY); } // render VBO glDrawArrays(GL_POINTS, 0, bufSize); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); } };
float vertexData[] = {-1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f }; int indicesData[] = { 0, 1, 2, 3, 0, 4, 5, 1, 4, 7, 6, 5, 2, 6, 7, 3, 1, 5, 6, 2, 3, 7, 4, 0 };
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufID)
glDrawElements(GL_POLYGON, count, GL_UNSIGNED_INT);
class Renderer { public: float t; int mode; unsigned ayimutSegs; unsigned polarSegs; private: GLuint vertBufID, indicesBufID; int vertSize; public: // constructor Renderer() : t(0.0), mode(1), ayimutSegs(10), polarSegs(10), vertBufID(0), indicesBufID(0), vertSize(0) {} //destructor ~Renderer() { if(vertBufID !=0) glDeleteBuffers( 1, &vertBufID); if(indicesBufID !=0) glDeleteBuffers( 1, &indicesBufID); } public: void init() { glEnable(GL_DEPTH_TEST); recreateVBOs(); } void recreateVBOs() { if(vertBufID !=0) glDeleteBuffers( 1, &vertBufID); if(indicesBufID !=0) glDeleteBuffers( 1, &indicesBufID); // generating VBO input data std::vector<float> vertexData; std::vector<int> indicesData; int totalSegs = ayimutSegs * polarSegs; float ayimutStep = 2.0f * M_PI / float(ayimutSegs); float polarStep = M_PI / float(polarSegs); float r = 1.0; vertSize = 0; for(unsigned m=0; m < ayimutSegs; m++) { for(unsigned n=0; n < polarSegs; n++) { float phi = ayimutStep*m; float theta = polarStep * n; // random radius int rval = rand(); r = 1.0 - 0.3 * (fabs(float(rval))/float(RAND_MAX)); // create xyz from spherical coordinates float x = r * sin(theta) * cos(phi); float y = r * sin(theta) * sin(phi); float z = r * cos(theta); vertexData.push_back(x); vertexData.push_back(y); vertexData.push_back(z); // create vertex indices indicesData.push_back(vertSize % totalSegs); indicesData.push_back((vertSize+ayimutSegs)%totalSegs); indicesData.push_back((vertSize+ayimutSegs+1)%totalSegs); indicesData.push_back((vertSize+1)%totalSegs); vertSize++; } } // generating vertex VBO glGenBuffers(1, &vertBufID); glBindBuffer(GL_ARRAY_BUFFER, vertBufID); glBufferData(GL_ARRAY_BUFFER, vertexData.size()*sizeof(float), &vertexData[0], GL_STATIC_DRAW); // generating index VBO // generating index VBO glGenBuffers(1, &indicesBufID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesBufID); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesData.size()*sizeof(int), &indicesData[0], GL_STATIC_DRAW); } void resize(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (30.0, (float)w/(float)h, 0.1, 50.0); } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // set camera gluLookAt(3.5, -1.0, 3.5, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); // draw scene glRotatef(t, 0.0f, 0.0f, 1.0f); // activating VBO glBindBuffer(GL_ARRAY_BUFFER, vertBufID); int stride = 0; glVertexPointer(3, GL_FLOAT, stride, NULL); glEnableClientState(GL_VERTEX_ARRAY); if(mode == 0) { glColor3f(1.0f,1.0f,1.0f); }else{ glColorPointer(3, GL_FLOAT, stride, NULL); glEnableClientState(GL_COLOR_ARRAY); } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesBufID); glDrawElements(GL_QUADS, vertSize*4, GL_UNSIGNED_INT, NULL); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); } };
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW)
GL_STATIC_DRAW
the parameters GL_DYNAMIC_DRAW
should be usedGL_STREAM_DRAW
can be employedglBufferSubData(GL_ARRAY_BUFFER, offset, size, data)
struct Vertex { float position[3]; float color[4]; float texCoord[2]; float normal[3]; }; std::vector<Vertex> vertexData;
vertexData
is created as one large VBO, memory access to the individual components is defined by
specifying the stride
, which is the number of bytes between consecutive elements of the same type,
and the start address offset
:
int stride = sizeof(Vertex); char* offset = (char*) NULL + (3+4+2)*sizeof(float); glNormalPointer(GL_FLOAT, stride, offset);
class Renderer { private: struct Vertex { float position[3]; float color[4]; float texCoord[2]; float normal[3]; }; public: float t; int mode; private: GLuint vertBufID; GLuint texID; int vertNo; public: // constructor Renderer() : t(0.0), mode(0), vertBufID(0), texID(0), vertNo(0) {} //destructor ~Renderer() { if(vertBufID !=0) glDeleteBuffers( 1, &vertBufID); if(texID !=0) glDeleteTextures( 1, &texID); } public: void init() { glEnable(GL_DEPTH_TEST); // generating VBO input data float vertexData[] = { 0.0f, 0.0f, 2.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f, 0.0000f,-0.9701f, 0.2425f, -0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0000f,-0.9701f, 0.2425f, 0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0000f,-0.9701f, 0.2425f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.5f, 1.0f, 0.9701f, 0.0000f, 0.2425f, 0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.9701f, 0.0000f, 0.2425f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.9701f, 0.0000f, 0.2425f, 0.0f, 0.0f, 2.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f, 1.0f, 0.0000f, 0.9701f, 0.2425f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0000f, 0.9701f, 0.2425f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0000f, 0.9701f, 0.2425f, 0.0f, 0.0f, 2.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.5f, 1.0f,-0.9701f, 0.0000f, 0.2425f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,-0.9701f, 0.0000f, 0.2425f, -0.5f,-0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,-0.9701f, 0.0000f, 0.2425f }; vertNo = 12; // generating vertex VBO glGenBuffers(1, &vertBufID); glBindBuffer(GL_ARRAY_BUFFER, vertBufID); glBufferData(GL_ARRAY_BUFFER, vertNo*sizeof(Vertex), vertexData, GL_STATIC_DRAW); std::string fileName("checkerboard.ppm"); texID = loadTexture(fileName); } void resize(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (30.0, (float)w/(float)h, 0.1, 50.0); } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // set camera gluLookAt(3.0, -1.0, 4.5, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0); // draw scene glRotatef(t, 0.0f, 0.0f, 1.0f); // activating VBO glBindBuffer(GL_ARRAY_BUFFER, vertBufID); int stride = sizeof(Vertex); char *offset = (char*)NULL; // position glVertexPointer(3, GL_FLOAT, stride, offset); glEnableClientState(GL_VERTEX_ARRAY); // color offset = (char*)NULL + 3*sizeof(float); glColorPointer(4, GL_FLOAT, stride, offset); glEnableClientState(GL_COLOR_ARRAY); // texture offset = (char*)NULL + (3+4)*sizeof(float); glTexCoordPointer(2, GL_FLOAT, stride, offset); glEnableClientState(GL_TEXTURE_COORD_ARRAY); // normals offset = (char*)NULL + (3+4+2)*sizeof(float); glNormalPointer(GL_FLOAT, stride, offset); glEnableClientState(GL_NORMAL_ARRAY); // bind texture if(mode == 0) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texID); }else{ glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); } // render data glDrawArrays(GL_TRIANGLES, 0, vertNo); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisable(GL_TEXTURE_2D); } ... };
display()
function in the previous example, it is noticeable that in addition to the actual render call with glDrawArrays(...)
several additional function calls to glBindBuffer(...)
,
glXXXPointer(...)
and glEnableClientState(...)
are needed
glGenVertexArrays(1, &vaoID);
glBindVertexArray(...)
and setting of the VBO states, they are stored to the currently bound VAO
glBindVertexArray(vaoID); glBindBuffer(GL_ARRAY_BUFFER, bufID); glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); glVertexPointer(3, GL_FLOAT, stride, offset); glEnableClientState(GL_VERTEX_ARRAY); ...
glBindVertexArray(vaoID); glDrawArrays(GL_TRIANGLES, 0, numOfTris);
glDeleteVertexArrays(1, &vaoID);When deleting the VAO its associated VBOs are not deleted. If desired, they must be released separately
class Renderer { private: struct Vertex { float position[3]; float color[4]; }; public: float t; int mode; private: enum {Pyramid, Cube, numVAOs}; enum {PyramidAll, CubePos, CubeCol, CubeIndices, numVBOs}; GLuint vaoID[numVAOs]; GLuint bufID[numVBOs]; int pyramidVertNo; int cubeIndicesNo; public: // constructor Renderer() : t(0.0), pyramidVertNo(0), cubeIndicesNo(0) {} //destructor ~Renderer() { glDeleteVertexArrays(numVAOs, vaoID); glDeleteBuffers(numVBOs, bufID); } public: void init() { glEnable(GL_DEPTH_TEST); // now we create 2 Vertex Array Objects (VAO): // one for a pyramid and one for a cube. // The pyramid uses one interleaved VBO // which is later drawn with "glDrawArrays", // while the cube uses 3 separate VBOs // which are later drawn with "glDrawElements" // create the Vertex Array Objects glGenVertexArrays(numVAOs, vaoID); // generating Vertex Buffer Objects (VBO) glGenBuffers(numVBOs, bufID); // specifying the pyramid VAO glBindVertexArray(vaoID[Pyramid]); float pyramidVertexData[] = { 0.0f, 0.0f, 2.0f, 1.0f, 0.0f, 0.0f, 0.0f, -0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 2.0f, 1.0f, 1.0f, 0.0f, 0.0f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -0.5f,-0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, }; pyramidVertNo = 12; glBindBuffer(GL_ARRAY_BUFFER, bufID[PyramidAll]); glBufferData(GL_ARRAY_BUFFER, pyramidVertNo*sizeof(Vertex), pyramidVertexData, GL_STATIC_DRAW); int stride = sizeof(Vertex); char *offset = (char*)NULL; // position glVertexPointer(3, GL_FLOAT, stride, offset); glEnableClientState(GL_VERTEX_ARRAY); // color offset = (char*)NULL + 3*sizeof(float); glColorPointer(4, GL_FLOAT, stride, offset); glEnableClientState(GL_COLOR_ARRAY); // specifying the cube VAO glBindVertexArray(vaoID[Cube]); float cubePosData[] = { -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f }; float cubeColorData[] = { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, }; int cubeIndicesData[] = { 0, 1, 2, 3, 0, 4, 5, 1, 4, 7, 6, 5, 2, 6, 7, 3, 1, 5, 6, 2, 3, 7, 4, 0 }; cubeIndicesNo = 24; // position glBindBuffer(GL_ARRAY_BUFFER, bufID[CubePos]); glBufferData(GL_ARRAY_BUFFER, sizeof(cubePosData), cubePosData, GL_STATIC_DRAW); glVertexPointer(3, GL_FLOAT, 0, NULL); glEnableClientState(GL_VERTEX_ARRAY); // color glBindBuffer(GL_ARRAY_BUFFER, bufID[CubeCol]); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeColorData), cubeColorData, GL_STATIC_DRAW); glColorPointer(3, GL_FLOAT, 0, NULL); glEnableClientState(GL_COLOR_ARRAY); // indices glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufID[CubeIndices]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndicesData), cubeIndicesData, GL_STATIC_DRAW); } void resize(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (60.0, (float)w/(float)h, 0.1, 50.0); } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // set camera gluLookAt(3.0, -1.0, 4.5, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0); // draw scene glRotatef(t, 0.0f, 0.0f, 1.0f); // bind cube VAO glBindVertexArray(vaoID[Cube]); // render data glDrawElements(GL_QUADS, cubeIndicesNo, GL_UNSIGNED_INT, NULL); glTranslatef(0.0f, 0.0f, 1.0f); // bind pyramid VAO glBindVertexArray(vaoID[Pyramid]); // render data glDrawArrays(GL_TRIANGLES, 0, pyramidVertNo); } };
v 0.6 -2.5 0.1
vt 0.5 0.75
vn 0.0 -1.0 0.0
f v/vt/vn v/vt/vn v/vt/vn v/vt/vnwhere the respective first index refers to the list of vertices, the second one to the list of texture coordinates, and the third one to the list of normals
# Wavefront OBJ file example # o Cube v -1.0 1.0 1.0 v -1.0 -1.0 1.0 v 1.0 -1.0 1.0 v 1.0 1.0 1.0 v -1.0 1.0 -1.0 v -1.0 -1.0 -1.0 v 1.0 -1.0 -1.0 v 1.0 1.0 -1.0 # 8 vertices vt 0.0 0.0 vt 1.0 0.0 vt 1.0 1.0 vt 0.0 1.0 # 4 texture coordinates vn 0.0 0.0 1.0 vn -0.0 -0.0 -1.0 vn -1.0 -0.0 0.0 vn 0.0 -1.0 0.0 vn 1.0 0.0 -0.0 vn -0.0 1.0 -0.0 # 6 normals f 1/1/1 2/2/1 3/3/1 4/4/1 f 5/1/2 8/2/2 7/3/2 6/4/2 f 1/1/3 5/2/3 6/3/3 2/4/3 f 2/1/4 6/2/4 7/3/4 3/4/4 f 3/1/5 7/2/5 8/3/5 4/4/5 f 5/1/6 1/2/6 4/3/6 8/4/6 # 6 quads # indices start with 1 not 0
f v/vt/vn v/vt/vn v/vt/vn
f v v v
f v/vt v/vt v/vt
f v//vn v//vn v//vn
includedPerVertexData[]
allows to adjust the composition of the generated float array so that
it fits to the required format of the VBOs (details in the source code)struct Vertex { float position[3]; float color[4]; float texCoord[2]; float normal[3]; };
int includedPerVertexData[] = {POS_3f, DIFFUSE_3f, ALPHA_1f, TEXCOORD_2f, NORMAL_3f};
class Renderer { private: struct Vertex { float position[3]; float color[4]; }; public: float t; private: enum {Triangle, numVAOs}; enum {TriangleAll, numVBOs}; GLuint vaoID[numVAOs]; GLuint bufID[numVBOs]; int triangleVertNo; int cubeIndicesNo; public: // constructor Renderer() : t(0.0), triangleVertNo(0), cubeIndicesNo(0) {} //destructor ~Renderer() { glDeleteVertexArrays(numVAOs, vaoID); glDeleteBuffers(numVBOs, bufID); } public: void init() { initExtensions(); glEnable(GL_DEPTH_TEST); // create a Vertex Array Objects (VAO) glGenVertexArrays(numVAOs, vaoID); // generate a Vertex Buffer Object (VBO) glGenBuffers(numVBOs, bufID); // binding the Triangle VAO glBindVertexArray(vaoID[Triangle]); float triangleVertexData[] = { 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, -0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.5f,-0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, }; triangleVertNo = 3; glBindBuffer(GL_ARRAY_BUFFER, bufID[TriangleAll]); glBufferData(GL_ARRAY_BUFFER, triangleVertNo*sizeof(Vertex), triangleVertexData, GL_STATIC_DRAW); int stride = sizeof(Vertex); char *offset = (char*)NULL; // position int vertexLoc = 0; glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(vertexLoc); } void resize(int w, int h) { glViewport(0, 0, w, h); } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // bind Triangle VAO glBindVertexArray(vaoID[Triangle]); // render data glDrawArrays(GL_TRIANGLES, 0, triangleVertNo); } };
Please notify me by e-mail if you have questions, suggestions for improvement, or found typos: Contact