Qt-如何在QOpenGLWidget上渲染多个形状

时间:2016-05-19 06:25:08

标签: qt opengl

我使用的是Qt-5.4。现在我想在QOpenGLWidget上绘制几个3D形状。我尝试通过创建2个VBO来设置顶点位置,但只渲染了一个形状。并且有一个" QOpenGLVertexArrayObject :: create()已经创建了VAO"在调试信息中显示。 有没有人可以告诉我该怎么做? 我的QOpenGLWidget实现如下:

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

1 个答案:

答案 0 :(得分:0)

你不应该打电话给&#34; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);&#34;在绘制第二个形状之前:它会清除当前帧缓冲区(可能是屏幕)

关于你的&#34; QOpenGLVertexArrayObject :: create()已经创建了VAO&#34;警告,我不知道,也许你的方法&#34; setupVertexAttribs&#34;被叫两次?