// This code example is created for educational purpose // by Thorsten Thormaehlen (contact: www.thormae.de). // It is distributed without any warranty. #include #include // we use glut here as window manager #define _USE_MATH_DEFINES #include #include #include #include #include using namespace std; class Renderer { private: struct Vertex { float position[3]; float color[4]; }; public: float t; 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); } }; //this is a static pointer to a Renderer used in the glut callback functions static Renderer *renderer; //glut static callbacks start static void glutResize(int w, int h) { renderer->resize(w,h); } static void glutDisplay() { renderer->display(); glutSwapBuffers(); glutReportErrors(); } static void timer(int v) { float offset = 1.0f; renderer->t += offset; glutDisplay(); glutTimerFunc(unsigned(20), timer, ++v); } int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowPosition(100,100); glutInitWindowSize(320, 320); glutCreateWindow("Vertex Array Object (VAO) Demo"); GLenum err = glewInit(); if (GLEW_OK != err) { fprintf(stderr, "Glew error: %s\n", glewGetErrorString(err)); } glutDisplayFunc(glutDisplay); //glutIdleFunc(glutDisplay); glutReshapeFunc(glutResize); renderer = new Renderer; renderer->init(); glutTimerFunc(unsigned(20), timer, 0); glutMainLoop(); }