Unsolved How to render multiple shapes on QOpenGLWidget
-
I'm using Qt-5.4. Now I want to draw several 3D shapes on QOpenGLWidget. I tried by create 2 VBOs to set vertices positions, but only one shape is rendered. And there is a "QOpenGLVertexArrayObject::create() VAO is already created" showing in debug info.
Is there anyone who can tell me what to do?
My implementation of QOpenGLWidget is below:static const char *vertexShaderSourceCore = "#version 150\n" "in vec4 vertex;\n" "in vec3 normal;\n" "in vec3 color;\n" "out vec3 vert;\n" "out vec3 vertNormal;\n" "out vec3 vertColor;\n" "uniform mat4 projMatrix;\n" "uniform mat4 mvMatrix;\n" "uniform mat3 normalMatrix;\n" "void main() {\n" " vert = vertex.xyz;\n" " vertNormal = normalMatrix * normal;\n" " vertColor = color;\n" " gl_Position = projMatrix * mvMatrix * vertex;\n" "}\n"; static const char *fragmentShaderSourceCore = "#version 150\n" "in highp vec3 vert;\n" "in highp vec3 vertNormal;\n" "in highp vec3 vertColor;\n" "out highp vec4 fragColor;\n" "uniform highp vec3 lightPos;\n" "void main() {\n" " highp vec3 L = normalize(lightPos - vert);\n" " highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n" " highp vec3 color = vec3(0.5, 0.5, 0);\n" " highp vec3 col = clamp(vertColor * 0.2 + vertColor * 0.8 * NL, 0.0, 1.0);\n" " fragColor = vec4(col, 1.0);\n" "}\n"; static const char *vertexShaderSource = "attribute vec4 vertex;\n" "attribute vec3 normal;\n" "attribute vec3 color;\n" "varying vec3 vert;\n" "varying vec3 vertNormal;\n" "varying vec3 vertColor;\n" "uniform mat4 projMatrix;\n" "uniform mat4 mvMatrix;\n" "uniform mat3 normalMatrix;\n" "void main() {\n" " vert = vertex.xyz;\n" " vertColor = color;\n" " vertNormal = normalMatrix * normal;\n" " gl_Position = projMatrix * mvMatrix * vertex;\n" "}\n"; static const char *fragmentShaderSource = "varying highp vec3 vert;\n" "varying highp vec3 vertNormal;\n" "varying highp vec3 vertColor;\n" "uniform highp vec3 lightPos;\n" "void main() {\n" " highp vec3 L = normalize(lightPos - vert);\n" " highp float NL = max(dot(normalize(vertNormal), L), 0.0);\n" " highp vec3 color = vec3(0.39, 1.0, 0.0);\n" " highp vec3 col = clamp(vertColor * 0.2 + vertColor * 0.8 * NL, 0.0, 1.0);\n" " gl_FragColor = vec4(col, 1.0);\n" "}\n"; void DisplayGLWidget::initializeGL() { // In this example the widget's corresponding top-level window can change // several times during the widget's lifetime. Whenever this happens, the // QOpenGLWidget's associated context is destroyed and a new one is created. // Therefore we have to be prepared to clean up the resources on the // aboutToBeDestroyed() signal, instead of the destructor. The emission of // the signal will be followed by an invocation of initializeGL() where we // can recreate all resources. initializeOpenGLFunctions(); glClearColor(255, 255, 255, m_transparent ? 0 : 1); m_program = new QOpenGLShaderProgram; m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, m_core ? vertexShaderSourceCore : vertexShaderSource); m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, m_core ? fragmentShaderSourceCore : fragmentShaderSource); m_program->bindAttributeLocation("vertex", 0); m_program->bindAttributeLocation("normal", 1); m_program->bindAttributeLocation("color", 2); m_program->link(); m_program->bind(); m_projMatrixLoc = m_program->uniformLocation("projMatrix"); m_mvMatrixLoc = m_program->uniformLocation("mvMatrix"); m_normalMatrixLoc = m_program->uniformLocation("normalMatrix"); m_lightPosLoc = m_program->uniformLocation("lightPos"); m_camera.setToIdentity(); QVector3D eye(0, 0, 8.0); QVector3D up(0, 1.0, 0); QVector3D center(0, 0, 0.0); m_camera.lookAt(eye, center, up); // Store the vertex attribute bindings for the program. setupVertexAttribs(); // Light position is fixed. m_program->setUniformValue(m_lightPosLoc, QVector3D(0, 0, 70)); m_program->release(); } void DisplayGLWidget::setupVertexAttribs() { // Create a vertex array object. In OpenGL ES 2.0 and OpenGL 2.x // implementations this is optional and support may not be present // at all. Nonetheless the below code works in all cases and makes // sure there is a VAO when one is needed. m_vao.create(); QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao); // Setup our vertex buffer object. m_meshModelVbo.create(); m_meshModelVbo.bind(); m_meshModelVbo.allocate(m_model->constData(), m_model->count() * sizeof(GLfloat)); m_meshModelVbo.bind(); QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); f->glEnableVertexAttribArray(0); f->glEnableVertexAttribArray(1); f->glEnableVertexAttribArray(2); f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), 0); f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), reinterpret_cast<void *>(3 * sizeof(GLfloat))); f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), reinterpret_cast<void *>(6 * sizeof(GLfloat))); m_meshModelVbo.release(); m_pcModelVbo.create(); m_pcModelVbo.bind(); m_pcModelVbo.allocate(m_model2->constData(), m_model2->count() * sizeof(GLfloat)); m_pcModelVbo.bind(); f->glEnableVertexAttribArray(0); f->glEnableVertexAttribArray(1); f->glEnableVertexAttribArray(2); f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), 0); f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), reinterpret_cast<void *>(3 * sizeof(GLfloat))); f->glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(GLfloat), reinterpret_cast<void *>(6 * sizeof(GLfloat))); m_pcModelVbo.release(); m_vao.release(); } void DisplayGLWidget::paintGL() { /* paint 1st object */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_vao.bind(); m_meshModelVbo.bind(); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); m_world.setToIdentity(); m_world.translate(m_model->getCenter().x(), m_model->getCenter().y(), m_model->getCenter().z()); m_world.rotate(m_xRot / 16.0f, 1, 0, 0); m_world.rotate(m_yRot / 16.0f, 0, 1, 0); m_world.rotate(m_zRot / 16.0f, 0, 0, 1); m_world.translate(-m_model->getCenter().x(), -m_model->getCenter().y(), -m_model->getCenter().z()); QOpenGLVertexArrayObject::Binder vaoBinder(&m_vao); m_program->bind(); m_program->setUniformValue(m_projMatrixLoc, m_proj); m_program->setUniformValue(m_mvMatrixLoc, m_camera * m_world); QMatrix3x3 normalMatrix = m_world.normalMatrix(); m_program->setUniformValue(m_normalMatrixLoc, normalMatrix); glPointSize(2.0); glDrawArrays(GL_POINTS, 0, m_model->vertexCount()); glFinish(); m_program->release(); /* paint 2nd object */ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_pcModelVbo.bind(); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); m_world.setToIdentity(); m_world.translate(m_model2->getCenter().x(), m_model2->getCenter().y(), m_model2->getCenter().z()); m_world.rotate(m_xRot / 16.0f, 1, 0, 0); m_world.rotate(m_yRot / 16.0f, 0, 1, 0); m_world.rotate(m_zRot / 16.0f, 0, 0, 1); m_world.translate(-m_model2->getCenter().x(), -m_model2->getCenter().y(), -m_model2->getCenter().z()); m_program->bind(); m_program->setUniformValue(m_projMatrixLoc, m_proj); m_program->setUniformValue(m_mvMatrixLoc, m_camera * m_world); m_program->setUniformValue(m_normalMatrixLoc, normalMatrix); glPointSize(2.0); glDrawArrays(GL_POINTS, 0, m_model2->vertexCount()); glFinish(); m_program->release(); m_vao.release(); } void DisplayGLWidget::resizeGL(int w, int h) { if (width != w) width = w; if (height != h) height = h; m_proj.setToIdentity(); m_proj.perspective(30.0f, GLfloat(w) / h, 2.0f, 20.0f); }