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);
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.