// This code example is created for educational purpose // by Thorsten Thormaehlen (contact: www.thormae.de). // It is distributed without any warranty. #include #include #include #include #include #include #include using namespace std; #include #include class Renderer : protected QOpenGLFunctions_3_0 { 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) {} public: void init() { initializeOpenGLFunctions(); glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH); // 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); } void dispose() { glDeleteVertexArrays(numVAOs, vaoID); glDeleteBuffers(numVBOs, bufID); } }; class MyWidget : public QOpenGLWidget { private: Renderer *renderer; QTimer *timer; public: MyWidget(QWidget *parent = NULL) : QOpenGLWidget(parent) { this->setWindowTitle("Vertex Array Object (VAO) Demo"); this->resize(320, 320); renderer = new Renderer(); timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer->start(30); } ~MyWidget() { makeCurrent(); renderer->dispose(); doneCurrent(); delete renderer; delete timer; } protected: void initializeGL() { renderer->init(); } void resizeGL(int w, int h){ renderer->resize(w, h); } void paintGL() { float offset = 1.0f; renderer->t += offset; renderer->display(); } }; int main (int argc, char* argv[]) { // create a QApplication object that handles initialization, // finalization, and the main event loop QApplication appl(argc, argv); MyWidget widget; // create a widget widget.show(); //show the widget and its children return appl.exec(); // execute the application }