-1

I'm facing a problem rendering the depth buffer. I get some strange artifacts when I try to render my depth buffer to a texture. In the end, I want to render topography data. As a toy example, I would like to render a square. The colour of the square should be the distance to the camera. At the very end, I'd like to have a depthmap where each pixel shows me distance to the camera.

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

my shaders:

vertex:

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

fragment:

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

Does anyone have an idea how to solve the problem?

Thomas
  • 13
  • 1

1 Answers1

0

In order to render a depth texture you need to add a Depth Buffer attachment then render normally.

What you are doing in your fragment shader , you are rendering to the Render Buffer something that you already have in a depth texture , and from my understanding you want right now to render TO that depth texture, and not FROM.

If you want to render FROM (meaning seeing your depth texture), you just take the color and it's enough (no need to make additional transformations, everything will already be between 0 and 1).

If you don't have a depth buffer attachment extension on your GPU , you can render to a frame buffer attachment by passing the Z from the vertex shader as a out parameter , then your fragment shader should be something like this :

    // 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);
    }
MichaelCMS
  • 4,703
  • 2
  • 23
  • 29