帧缓冲深度伪影

时间:2016-02-01 11:38:19

标签: c++ opengl glsl framebuffer depth-buffer

我的FrameBuffer深度纹理上有一些神器我无法摆脱:

Artefacts

用于初始化FrameBuffer的代码:

glGenFramebuffers(1, &fbo);
 glBindFramebuffer(GL_FRAMEBUFFER, fbo);

 glGenTextures(1, &color);
 glBindTexture(GL_TEXTURE_2D, color);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);


 glGenTextures(1, &depth);
 glBindTexture(GL_TEXTURE_2D, depth);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, color, 0);
 glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, depth, 0);

 GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
 glDrawBuffers(2, attachments);
 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
  std::cout << "FBO FEHLER" << std::endl;
 }

用于绘制FrameBuffer的代码:

    shader->bind();
  // Bind Textures
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, color);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, depth);
    glUniform1i(shader->getUniform("tex"), 0);
    glUniform1i(shader->getUniform("depth"), 1);
    glUniformMatrix4fv(shader->getUniform("matrix"), 1, GL_FALSE, glm::value_ptr(ortho));
    // Draw Call
    glBindBuffer(GL_ARRAY_BUFFER,fbovbo);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 20, (void*)0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, (void*)12);

    glDrawArrays(GL_TRIANGLE_STRIP,0,4);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    // Unbind
    shader->unbind();//*/

实际渲染的FragmentShader:

#version 330 core

layout(location = 0) out vec4 out_color;
layout(location = 1) out vec4 out_depth;
in float temp;

void main(void){
 out_color = vec4(1,0.0,0.0,1.0);
 out_depth = vec4(gl_FragCoord.z);
}

FrameBuffer渲染的FragmentShader:

#version 330 core

in vec2 fuv;

out vec4 color;

uniform sampler2D tex;
uniform sampler2D depth;


void main(){
 vec4 d = texture2D(depth, fuv);
 gl_FragDepth = d.a;
 vec4 c = texture2D(tex,fuv);
 if(c.a<0.1){
  discard;
 }
 color = c;
 //color = vec4(texture2D(depth, fuv).zzz,1.0);
 //color.a = 0.8;
 //color = vec4(1,0,0,0.5);
}

红色&#34; Mesh&#34;在棕色表面后面,但它的边界仍然出现。这就是问题

1 个答案:

答案 0 :(得分:0)

问题可能来自深度缓冲区的精度有限。基本上,近距离和远距离之间的距离必须由深度缓冲器表示。在您的情况下,深度缓冲区有8位,因此只能表示256个不同的深度值。当两个对象比这更靠近时,它们将被映射到深度缓冲区中的相同值。

要解决此问题,您可以尝试提高深度缓冲区的精度,例如,使用

glGenTextures(1, &depth);
glBindTexture(GL_TEXTURE_2D, depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_SHORT, NULL);

旁注:我不确定为什么深度纹理有四个通道。如果您不需要它们,我会将其更改为单通道格式。