c++ - 具有独特着色器的 OpenGL 多次绘制调用会出现空白屏幕

标签 c++ opengl rendering shader

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

第一个绘制调用使用一个着色器,而第二个绘制调用使用另一个着色器。我不会清除中间的屏幕。

如果它使代码更清晰,我的着色器程序存储为类变量,加载后的纹理 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);
}

最佳答案

您需要在函数的开头绑定(bind)顶点数组,而不是在绘制调用本身之前。顶点数组负责维护与给定对象[-type]相关联的状态,并且任何将设置状态的调用(如 glVertexAttribPointerglEnableVertexAttribArray)将在那个顶点数组。您对旧代码所做的实质是为您的对象设置状态,然后切换到完全不同的 VAO,然后进行绘图,这意味着 model1 使用 model2 的绑定(bind)和设置,反之亦然。除非他们有相同的规则和设置,否则他们都抽签的可能性极小。

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

关于c++ - 具有独特着色器的 OpenGL 多次绘制调用会出现空白屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43601634/

相关文章:

c++ - 使用 GDB 从核心文件调试 C++

c++ - `xxxx' : looks like a function definition, 但是没有参数列表;跳过明显的 body

c++ - 如何将子目录库与 QMake 链接起来?

c++ - 删除动态数组的一部分并增加其他部分

c++ - 覆盖未调用的虚拟方法

c++ - 如何显示带有 opengl 纹理的灰度图像

python - 如何在python中使用S3TC/DXT算法压缩PNG图像?

c++ - 在 DX11 中缩放广告牌矩阵

HTML5 swipe.js css3 过渡;页面元素的离屏渲染和缓存

jsf - 如何使用 h :commandLink and f:ajax 渲染面板组