使用共享上下文进行渲染时,OpenGL深度缓冲或深度测试不起作用

时间:2017-08-09 07:22:44

标签: opengl opengl-3 fbo

我有一个非常具体的OpenGL设置,其中场景中的3D几何体不会渲染。在OpenGL环境中存在一些与我无关的深度相关状态。

这是在生产引擎中,我们在多个窗口上下文中添加了共享上下文支持。我们正在对共享上下文拥有的帧缓冲对象进行渲染,然后使用不同的上下文将颜色附件渲染缓冲区渲染到窗口。

清晰的颜色显示在窗口的结果blit中,而不是3D场景几何体本身,因此我们知道帧缓冲区和渲染缓冲区对象至少部分正确。

为了说明,我从LearnOpenGL网站重构了一个样本来说明我的错误。它也出现在那里,所以我很清楚这是我所缺少的。

这是GitHub项目,我对一个正在运行的framebuffer示例进行了三次提交,以便使用共享上下文渲染到帧缓冲区然后blits结果:Framebuffer Shared Context Experiment

以下是产生错误结果的大多数源代码。我剪了一些没改变的部分。

    // glfw dummy window creation
    // --------------------
    GLFWwindow* dummy = NULL;
#if USE_SHARED_CONTEXT
    dummy = glfwCreateWindow(1, 1, "Dummy", NULL, NULL);
    if (dummy == NULL)
    {
        std::cout << "Failed to create dummy GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(dummy);
#endif

    // glfw window creation
    // --------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, dummy);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwShowWindow(window);
#if !USE_SHARED_CONTEXT
    glfwMakeContextCurrent(window);
#endif

    // <snip creation of shared resources>
    // <snip creation of un-shared vertex array>

    // framebuffer configuration
    // -------------------------
    unsigned int framebuffer;
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

#if 1
    // create a color attachment render buffer
    unsigned int Colorbuffer;
    glGenRenderbuffers(1, &Colorbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, Colorbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer.
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, Colorbuffer); // now actually attach it
#else
    // create a color attachment texture
    unsigned int textureColorbuffer;
    glGenTextures(1, &textureColorbuffer);
    glBindTexture(GL_TEXTURE_2D, textureColorbuffer);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorbuffer, 0);
#endif

    // create a renderbuffer object for depth and stencil attachment (we won't be sampling these)
    unsigned int rbo;
    glGenRenderbuffers(1, &rbo);
    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer.
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // now actually attach it
    // now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        // <snip timing and input>

    #if USE_SHARED_CONTEXT
        // use shared context because that is what is holding our framebuffer and vao.
        // -----
        glfwMakeContextCurrent(dummy);
    #endif

        // render
        // ------
        // bind to framebuffer and draw scene as we normally would to color texture 
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
        glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad)

        // make sure we clear the framebuffer's content
        glClearColor(1.0f, 0.1f, 0.1f, 1.0f);
        glClearDepth(1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // following render is unchanged
        shader.use();
        glm::mat4 model;
        glm::mat4 view = camera.GetViewMatrix();
        glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        shader.setMat4("view", view);
        shader.setMat4("projection", projection);
        // cubes
        glBindVertexArray(cubeVAO);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, cubeTexture);
        model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
        shader.setMat4("model", model);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        model = glm::mat4();
        model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
        shader.setMat4("model", model);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        // floor
        glBindVertexArray(planeVAO);
        glBindTexture(GL_TEXTURE_2D, floorTexture);
        shader.setMat4("model", glm::mat4());
        glDrawArrays(GL_TRIANGLES, 0, 6);
        glBindVertexArray(0);

#if 1
    #if USE_SHARED_CONTEXT
        // use window context for presentation via blit.
        // -----
        glfwMakeContextCurrent(window);

        // temorary framebuffer for visible window since framebuffers are not shared
        // -------------------------
        unsigned int readFramebuffer;
        glGenFramebuffers(1, &readFramebuffer);
        glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, Colorbuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SCR_WIDTH, SCR_HEIGHT);
        glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, Colorbuffer);
    #endif

        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
        glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);

    #if USE_SHARED_CONTEXT
        glDeleteFramebuffers(1, &readFramebuffer);
    #endif
#else
        // now bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glDisable(GL_DEPTH_TEST); // disable depth test so screen-space quad isn't discarded due to depth test.
        // clear all relevant buffers
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways)
        glClear(GL_COLOR_BUFFER_BIT);

        screenShader.use();
        glBindVertexArray(quadVAO);
        glBindTexture(GL_TEXTURE_2D, textureColorbuffer);   // use the color attachment texture as the texture of the quad plane
        glDrawArrays(GL_TRIANGLES, 0, 6);
#endif

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
// <snip epilog>

您可以切换USE_SHARED_CONTEXT编译时开关,以删除使用共享上下文渲染的一小部分代码。

1 个答案:

答案 0 :(得分:1)

我错过了对glViewport的共享渲染上下文的调用。

视口的值默认为(0,0) - &gt; (可见窗口使用的上下文的宽度,高度)。共享渲染上下文已默认为(0,0) - &gt; (1,1)因为我对不可见的GLFW窗口使用了宽度和高度1。