我在渲染深度缓冲区时遇到问题。当我尝试将深度缓冲区渲染到纹理时,我得到了一些奇怪的工件。最后,我想渲染地形数据。作为一个玩具的例子,我想渲染一个正方形。方块的颜色应该是到相机的距离。在最后,我想要一个深度图,每个像素显示我与相机的距离。
// 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 :(得分:0)
为了渲染深度纹理,您需要添加深度缓冲附件,然后正常渲染。
你在片段着色器中正在做什么,你正在渲染渲染缓冲区中已经有深度纹理的东西,根据我的理解,你现在想要渲染TO深度纹理,而不是FROM。
如果你想渲染FROM(意思是看到深度纹理),你只需要颜色就足够了(不需要进行额外的变换,一切都已经在0和1之间)。
如果您的GPU上没有深度缓冲附件扩展,您可以通过将Z从顶点着色器作为out参数渲染到帧缓冲附件,然后您的片段着色器应该是这样的:
// 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);
}