Re-rendering the object doesn't work
-
Hello everyone!
I have the problem when try to re-render the object in GLWidget: the object does not appear when I press the button second time. Probably the answer is very simple, but I'm new in Qt development and would be very appreciate for any help.
In my application I have two objects with different properties so I make them through two different QOpenGL shader programs. To render the objects I make two VBOs. For the first one the vertices and colours are known from the start so I initialise the correspondent VBO in initializeGL() function:
void GLWidget::initializeGL()
{
initializeOpenGLFunctions();
glClearColor(1, 1, 1, 1.0);... defining vertex and fragment shaders....
m_program1 = new QOpenGLShaderProgram; m_program1->addShader(m_vshader1); m_program1->addShader(m_fshader1); m_program1->link(); m_program2 = new QOpenGLShaderProgram; m_program2->addShader(m_vshader2); m_program2->addShader(m_fshader2); m_program2->link();
...adding vertices, normals, colours, matrices, light to the shader programs....
createGeometry(); // create the vertices for the first object m_vbo1.create(); m_vbo1.bind(); const int vertexCount = m_vertices.count(); QVector<GLfloat> buf; buf.resize(vertexCount * 3 * 2); GLfloat *p = buf.data(); for (int i = 0; i < vertexCount; ++i) { *p++ = m_vertices[i].x(); *p++ = m_vertices[i].y(); *p++ = m_vertices[i].z(); *p++ = m_normals[i].x(); *p++ = m_normals[i].y(); *p++ = m_normals[i].z(); } m_vbo1.allocate(buf.constData(), buf.count() * sizeof(GLfloat)); m_vbo1.release(); m_program1->release();
}
The second object vertices, normals and colours are calculated later in the program so I make the special function to initialise and upload the VBO2:
...calculation of the vertices, normals and colours for the second object....
if (m_vbo2.isCreated() == false){ m_vbo2.create(); m_vbo2.bind(); } else { m_vbo2.destroy(); m_vbo2.create(); m_vbo2.bind(); } const int dataCount = m_vertices_video.count(); buf2.clear(); buf2.resize(dataCount * 3 * 3); GLfloat *ptr = buf2.data(); for (int j = 0; j < dataCount; j++){ *ptr++ = m_vertices_video[j].x(); *ptr++ = m_vertices_video[j].y(); *ptr++ = m_vertices_video[j].z(); *ptr++ = m_normals_video[j].x(); *ptr++ = m_normals_video[j].y(); *ptr++ = m_normals_video[j].z(); *ptr++ = m_color_video[j].x(); *ptr++ = m_color_video[j].y(); *ptr++ = m_color_video[j].z(); } m_vbo2.allocate(buf2.constData(), buf2.count() * sizeof(GLfloat)); m_vbo2.release(); m_program2->release();
The idea is to call this function each time I press the correspondent button.
Then in the paintGL() function depending on the booling variable I render either first object or the second one:
- For the first object:
m_camera.setToIdentity();
m_camera.translate(-0.5, -0.5, -4.0);
m_camera.rotate(30.0, 0.0, 1.0, 0.0);timer.start(12, this); m_world.setToIdentity(); 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); //draw cube m_program1->bind(); m_program1->setUniformValue(m_projMatrixLoc, m_proj); m_program1->setUniformValue(m_mvMatrixLoc, m_camera * m_world); QMatrix3x3 normalMatrix = m_world.normalMatrix(); m_program1->setUniformValue(m_normalMatrixLoc, normalMatrix); QVector3D light3(100.0, 1.0, 0.0); m_program1->setUniformValue(m_lightPosLoc, light3);
QVector3D color(0.7f, 0.7f, 0.7f);
m_program1->setUniformValue(m_colorAttr1, color); m_program1->enableAttributeArray(m_vertexAttr1); m_program1->enableAttributeArray(m_normalAttr1); m_vbo1.bind(); m_program1->setAttributeBuffer(m_vertexAttr1, GL_FLOAT, 0, 3, 6 * sizeof(GLfloat)); m_program1->setAttributeBuffer(m_normalAttr1, GL_FLOAT, 3 * sizeof(GLfloat), 3, 6 * sizeof(GLfloat)); m_vbo1.release(); glDrawArrays(GL_QUADS, 0, m_vertices.size()); m_program1->disableAttributeArray(m_normalAttr1); m_program1->disableAttributeArray(m_vertexAttr1); m_program1->release();
-
for the second object:
m_camera.setToIdentity();
m_camera.translate(-0.5, -0.5, -4);
m_camera.rotate(40.0, 0.0, 1.0, 0.0);m_world.setToIdentity();
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_program2->bind();
m_program2->setUniformValue(m_projMatrixLoc, m_proj);
m_program2->setUniformValue(m_mvMatrixLoc, m_camera * m_world);
QMatrix3x3 normalMatrix = m_world.normalMatrix();
m_program2->setUniformValue(m_normalMatrixLoc, normalMatrix);QVector3D light3(2.0, 2.0, 3.0);
m_program2->setUniformValue(m_lightPosLoc, light3);
m_vbo2.bind();
m_program2->enableAttributeArray(m_vertexAttr2);
m_program2->setAttributeBuffer(m_vertexAttr2, GL_FLOAT, 0, 3, 9 * sizeof(GLfloat));m_program2->enableAttributeArray(m_normalAttr2);
m_program2->setAttributeBuffer(m_normalAttr2, GL_FLOAT, 3 * sizeof(GLfloat), 3, 9 * sizeof(GLfloat));m_program2->enableAttributeArray(m_colorAttr2);
m_program2->setAttributeBuffer(m_colorAttr2, GL_FLOAT, 6 * sizeof(GLfloat), 3, 9 * sizeof(GLfloat));
m_vbo2.release();int ii;
int dataCount2 = m_vertices_video.count() / (aD->tStep*aD->isections);
ii = aD->frameLoc;
for (int i = 0; i < aD->isections; i++){
glDrawArrays(GL_QUADS, idataCount2 + iiaD->isections*dataCount2, dataCount2);
}m_program2->disableAttributeArray(m_normalAttr2);
m_program2->disableAttributeArray(m_vertexAttr2);
m_program2->disableAttributeArray(m_colorAttr2);m_program2->release();
The idea is torender the correspondent object when I press the correspondent button. The first object renders all the times no problem. However, the second one renders only once, with the first time button pressed.
It looks to me I upload the object data in VBOs OK, so the problem probably lays in the rendering itself. Unfortunately, I can't see it.