2015-02-05 168 views
-1

我在渲染深度緩衝區時遇到問題。當我嘗試將我的深度緩衝區渲染爲紋理時,我得到了一些奇怪的工件。最後,我想渲染地形數據。作爲一個玩具的例子,我想渲染一個正方形。正方形的顏色應該是相機的距離。最後,我想要一個深度圖,其中每個像素顯示我距離相機的距離。深度緩衝區未正確渲染

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

有沒有人有一個想法如何解決這個問題?

回答

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

謝謝,工作! – Thomas 2015-02-06 08:42:00