简体   繁体   中英

OpenGL multiple draw calls with unique shaders gives blank screen

I am trying to render two different vertex collections on top of one another. Right now, my main loop renders one correctly when it's by itself, and the other correctly when it's by itself, but when I call both of my draw functions, I see a blank window. Why might this be happening?

The first draw call uses one shader, while the second draw call uses a different one. I don't clear the screen in between.

If it makes the code more clear, my shader programs are stored as class variables, as are the texture IDs after they're loaded elsehwere in my program.

This is my main loop:

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

My drawModel1() function renders points:

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

And my drawModel2() function renders indexed triangles:

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

You need to bind your vertex arrays at the start of your function, not right before the draw call itself. The Vertex Array is responsible for maintaining the state associated with a given object[-type] and any calls made that will setup state (like glVertexAttribPointer or glEnableVertexAttribArray ) will be maintained on that Vertex Array. What you were essentially doing with your old code is that you were setting up state for your object, then switching to an entirely different VAO, then drawing, which meant model1 was using model2's bindings and setup, and vice-versa. Unless they have identical rules and setups, it's extremely unlikely that they'll both draw.

Incidentally, because VAO's store state, the only things that need to be in your draw calls are the draw call itself, and any data that changed that frame. So you'll want to consider spending some time refactoring your code, as it looks like most of those settings (like buffer binding) don't change on a frame-by-frame basis.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM