使用唯一着色器的OpenGL多次绘制调用会显示空白屏幕

时间:2017-04-25 04:31:21

标签: c++ opengl rendering shader

我正在尝试将两个不同的顶点集合呈现在彼此之上。现在,我的主循环在它本身时正确渲染一个,而另一个在它本身时正确渲染,但是当我调用两个绘制函数时,我看到一个空白窗口。为什么会发生这种情况?

第一个绘制调用使用一个着色器,而第二个绘制调用使用不同的着色器。我不清楚它们之间的屏幕。

如果它使代码更清晰,我的着色器程序将存储为类变量,因为纹理ID是在我们的程序中加载后的纹理ID。

这是我的主要循环:

while (true)
{
    // Clear the colorbuffer
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    drawModel1(); // This works when drawModel2() is commented out
    drawModel2(); // This works when drawModel1() is commented out

    // Unbind buffer
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // Swap the screen buffers
    glfwSwapBuffers(_window);
}

我的drawModel1()函数呈现点数:

void drawModel1()
{
    // Use the image shader
    _img_shader.use();

    // Feed the position data to the shader
    glBindBuffer(GL_ARRAY_BUFFER, _img_pos_VBO);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);

    // Feed the color data to the shader
    glBindBuffer(GL_ARRAY_BUFFER, _img_color_VBO);
    glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, GL_TRUE, 3 * sizeof(GLubyte), (GLvoid*)0);
    glEnableVertexAttribArray(1);

    // Set the projection matrix in the vertex shader
    GLuint projM = glGetUniformLocation(_img_shader.program(), "proj");
    glm::mat4 proj = _ndc * _persMat;
    glUniformMatrix4fv(projM, 1, GL_TRUE, glm::value_ptr(proj));

    // Set the view matrix in the vertex shader
    GLuint viewM = glGetUniformLocation(_img_shader.program(), "view");
    glUniformMatrix4fv(viewM, 1, GL_TRUE, glm::value_ptr(_viewMat));

    // Draw the points
    glBindVertexArray(_img_VAO);
    glDrawArrays(GL_POINTS, 0, _numImageVertices);

    // Disable attributes
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
}

我的drawModel2()函数渲染了索引三角形:

void drawModel2()
{
    _model_shader.use();

    // Load the mesh texture
    GLuint texID = _loaded_textures.at(mesh.tex_file());
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texID);
    glUniform1i(glGetUniformLocation(_model_shader.program(), "texture_img"), 0);

    // Set the proj matrix in the vertex shader
    GLuint nvpmM = glGetUniformLocation(_model_shader.program(), "npvm");
    glm::mat4 npvm = _ndc * _persMat * _viewMat * mat;
    glUniformMatrix4fv(nvpmM, 1, GL_FALSE, glm::value_ptr(npvm));

    // Feed the position data to the shader
    glBindBuffer(GL_ARRAY_BUFFER, mesh.pos_VBO());
    GLuint pos_att = glGetAttribLocation(_model_shader.program(), "position");
    glEnableVertexAttribArray(pos_att);
    glVertexAttribPointer(pos_att, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);

    // Feed the texture coordinate data to the shader
    glBindBuffer(GL_ARRAY_BUFFER, mesh.tex_VBO());
    GLuint tex_coord_att = glGetAttribLocation(_model_shader.program(), "texCoords");
    glEnableVertexAttribArray(tex_coord_att);
    glVertexAttribPointer(tex_coord_att, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);

    // Draw mesh
    glBindVertexArray(mesh.VAO());
    glDrawElements(GL_TRIANGLES, mesh.numIndices(), GL_UNSIGNED_SHORT, (void*)0);

    // Disable attributes
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);

    // Release resources
    glBindTexture(GL_TEXTURE_2D, 0);
}

1 个答案:

答案 0 :(得分:1)

您需要在函数的开头绑定顶点数组,而不是在绘制调用本身之前。顶点数组负责维护与给定对象[-type]相关联的状态,并且将在该顶点阵列上维护任何将设置状态(如glVertexAttribPointerglEnableVertexAttribArray)的调用。您基本上使用旧代码执行的操作是您为对象设置状态,然后切换到完全不同的VAO,然后绘制,这意味着model1正在使用model2的绑定和设置,反之亦然。除非他们有相同的规则和设置,否则他们都不太可能画画。

顺便说一下,由于VAO的存储状态,需要在绘制调用中的唯一内容是绘制调用本身以及更改该帧的任何数据。因此,您需要花一些时间来重构代码,因为看起来大多数设置(如缓冲区绑定)都不会逐帧更改。