深度缓冲区未正确呈现

depth buffer is not rendered properly

我在渲染深度缓冲区时遇到问题。当我尝试将我的深度缓冲区渲染为纹理时,我得到了一些奇怪的伪像。最后,我想渲染地形数据。作为玩具示例,我想渲染一个正方形。正方形的颜色应该是到相机的距离。最后,我想要一个深度图,其中每个像素显示我到相机的距离。

// Include standard headers
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>

// Include GLEW
#include <GL/glew.h>

// Include GLFW
#include <glfw3.h>
GLFWwindow* window;

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;

#include "common/shader.hpp"
//#include "common/texture.hpp"
//#include "common/controls.hpp"
//#include "common/objloader.hpp"
//#include "common/vboindexer.hpp"

using namespace std;


int main( void )
{
    cout << "Error 1: " << glGetError() << endl;
    // Initialise GLFW
    if( !glfwInit() )
    {
            fprintf( stderr, "Failed to initialize GLFW\n" );
            return -1;
    }
    cout << "Error 2: " << glGetError() << endl;
    glfwWindowHint(GLFW_SAMPLES, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    cout << "Error 3: " << glGetError() << endl;

    // Open a window and create its OpenGL context
    window = glfwCreateWindow( 1024, 768, "Toydata", NULL, NULL);
    if( window == NULL ){
        fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
        glfwTerminate();
        return -1;
    }
    cout << "Error 4: " << glGetError() << endl;
    glfwMakeContextCurrent(window);
    cout << "Error 5: " << glGetError() << endl;
    // Initialize GLEW
    glewExperimental = true; // Needed for core profile
    if (glewInit() != GLEW_OK) {
            fprintf(stderr, "Failed to initialize GLEW\n");
            return -1;
    }
    cout << "Error 6: " << glGetError() << endl;
    // Ensure we can capture the escape key being pressed below
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);


    cout << "Error 7: " << glGetError() << endl;
    // Dark blue background
    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
    cout << "Error 7a: " << glGetError() << endl;
    glClearDepth(1.0f);
    cout << "Error 7b: " << glGetError() << endl;

    glClearBufferData(GL_ARRAY_BUFFER, GL_TEXTURE_2D, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    cout << "Error 9: " << glGetError() << endl;

    // Enable depth test
    glEnable(GL_DEPTH_TEST);
    glDepthRange(0.1f, 100.0f);
    glDepthFunc(GL_LESS);
    glDepthMask(GL_TRUE);
    // Cull triangles which normal is not towards the camera
    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);



    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    // Create and compile our GLSL program from the shaders
    GLuint programID = LoadShaders( "../SimpleTransform.vertexshader", "../SingleColor.fragmentshader" );
    // Get a handle for our "MVP" uniform
    GLuint MatrixID = glGetUniformLocation(programID, "MVP");
    // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
    glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 1.0f, 100.0f);

    // Camera matrix
    glm::mat4 View       = glm::lookAt(
        glm::vec3(0,1,3), // Camera is at (0,1,3), in World Space
        glm::vec3(0,0,0), // and looks at the origin
        glm::vec3(0,1,0)  // Head is up (set to 0,-1,0 to look upside-down)
    );
    glm::mat4 Model      = glm::mat4(1.0f);
    glm::mat4 MVP        = Projection * View * Model; // Remember, matrix multiplication is the other way around


    static const GLfloat g_vertex_buffer_data[] = {
        -1.0f, -1.0f, 0.0f,
         1.0f, -1.0f, 0.0f,
         0.0f,  1.0f, -50.0f,

         1.0f, -1.0f, 0.0f,
         2.0f, 1.0f, -50.0f,
         0.0f, 1.0f, -50.0f,
    };


    cout << "Generate Framebuffer..." << endl;
    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_DYNAMIC_DRAW);
    cout << "Error: " << glGetError() << endl;

    ////////////////////////////////////////////////////////////////////////////
    // TEXTURE RENDERING
    ////////////////////////////////////////////////////////////////////////////

    // The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth buffer.
    GLuint FramebufferName = 0;
    glGenFramebuffers(1, &FramebufferName);
    glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
    cout << "Error: " << glGetError() << endl;


    // Alternative : Depth texture. Slower, but you can sample it later in your shader
    GLuint depthTexture = 0;
    glGenTextures(1, &depthTexture);
    glBindTexture(GL_TEXTURE_2D, depthTexture);
    glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT32, 1024, 768, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    cout << "Error: " << glGetError() << endl;

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
    cout << "Error 9a: " << glGetError() << endl;

    glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);

    // Depth texture alternative :
    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0);
    cout << "Error: " << glGetError() << endl;

    // Set the list of draw buffers.
    GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
    glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers
    cout << "Error 10: " << glGetError() << endl;
    // Always check that our framebuffer is ok
    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    {
            cout << "Framebuffer not complete!" << endl;
            return false;
    }
    cout << "Error 11: " << glGetError() << endl;

    // The fullscreen quad's FBO
    static const GLfloat g_quad_vertex_buffer_data[] = {
            -1.0f, -1.0f, 0.0f,
             1.0f, -1.0f, 0.0f,
            -1.0f,  1.0f, 0.0f,
            -1.0f,  1.0f, 0.0f,
             1.0f, -1.0f, 0.0f,
             1.0f,  1.0f, 0.0f,
    };


    GLuint quad_vertexbuffer;
    glGenBuffers(1, &quad_vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);

    cout << "Error 12: " << glGetError() << endl;
    // Create and compile our GLSL program from the shaders
    GLuint quad_programID = LoadShaders( "../Passthrough.vertexshader", "../WobblyTexture.fragmentshader" );
    GLuint texID = glGetUniformLocation(quad_programID, "depthTexture");

    cout << "Error 13: " << glGetError() << endl;


    do{

        // Clear the screen
        glClear( GL_COLOR_BUFFER_BIT );

        // Use our shader
        glUseProgram(programID);

        // Send our transformation to the currently bound shader,
        // in the "MVP" uniform
        glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

        // 1rst attribute buffer : vertices
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(
                0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
                3,                  // size
                GL_FLOAT,           // type
                GL_FALSE,           // normalized?
                0,                  // stride
                (void*)0            // array buffer offset
        );

        // Draw the triangle !
        glDrawArrays(GL_TRIANGLES, 0, 6); // 3 indices starting at 0 -> 1 triangle

        glDisableVertexAttribArray(0);

        // Render to the screen
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glViewport(0,0,1024,768); // Render on the whole framebuffer, complete from the lower left corner to the upper right

        // Clear the screen
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        // Use our shader
        glUseProgram(quad_programID);

        // Bind our texture in Texture Unit 0
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, depthTexture);
        // Set our "depthTexture" sampler to user Texture Unit 0
        glUniform1i(texID, 0);


        // 1rst attribute buffer : vertices
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
        glVertexAttribPointer(
                0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
                3,                  // size
                GL_FLOAT,           // type
                GL_FALSE,           // normalized?
                0,                  // stride
                (void*)0            // array buffer offset
        );

        // Draw the triangles !
        glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles

        glDisableVertexAttribArray(0);



        // Swap buffers
        glfwSwapBuffers(window);
        glfwPollEvents();

    } // Check if the ESC key was pressed or the window was closed
    while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
               glfwWindowShouldClose(window) == 0 );

    // Cleanup VBO and shader
    glDeleteBuffers(1, &vertexbuffer);
    glDeleteProgram(programID);
    glDeleteBuffers(1, &quad_vertexbuffer);
    glDeleteProgram(quad_programID);
    glDeleteVertexArrays(1, &VertexArrayID);
    glDeleteFramebuffers(1, &FramebufferName);
    glDeleteTextures(1, &depthTexture);


    // Close OpenGL window and terminate GLFW
    glfwTerminate();

    return 0;
}

我的着色器:

顶点:

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;

// Output data ; will be interpolated for each fragment.
out vec2 UV;

void main(){
    gl_Position = vec4(vertexPosition_modelspace,1);
    UV = (vertexPosition_modelspace.xy+vec2(1,1))/2.0;
}

片段:

#version 330 core

in vec2 UV;

out vec4 color;

uniform sampler2D depthTexture;


void main(){

    float z = texture2D(depthTexture, UV).x;
    float n = 1.0;
    float f = 100.0;
    float c = (2.0 * n) / (f + n - z * (f - n));


    color = vec4(c,c,c,1.0);    
}

有人知道如何解决这个问题吗?

为了渲染深度纹理,您需要添加深度缓冲附件然后正常渲染。

您在片段着色器中正在做什么,您正在向渲染缓冲区渲染深度纹理中已有的东西,据我了解,您现在想要渲染到该深度纹理,而不是从中渲染。

如果你想渲染 FROM(意思是看到你的深度纹理),你只需要颜色就足够了(不需要做额外的转换,一切都已经在 0 和 1 之间)。

如果您的 GPU 上没有深度缓冲区附件扩展,您可以通过将顶点着色器中的 Z 作为输出参数传递到帧缓冲区附件来渲染到帧缓冲区附件,那么您的片段着色器应该是这样的:

    // vs to send depth information to fs -> case without depth buffer attachment
    ...
    out float outz;
    ...
    void main()
    {
         ...
         outz = vertexposition_modelspace.z; // btw, shouldn't this be projection space ?
         ...
    }

    // fs to render depth information without depth buffer attachment
    in float outz;
    out vec4 color;
    void main()
    {
       color = vec4(outz,outz,outz,1);
    }