Артефакты глубины фреймбуфера

На моей глубине текстуры FrameBuffer есть некоторые артефакты, от которых я не могу избавиться:

Артефакты

Код, используемый для инициации 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);
}

FragmentShader рендеринга FrameBuffer:

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

Красная "Сетка" находится за коричневой поверхностью, но ее границы все еще появляются. Это проблема

1 ответ

Проблема может быть связана с ограниченной точностью буфера глубины. По сути, диапазон между ближней и дальней плоскостями должен быть представлен буфером глубины. В вашем случае буфер глубины имеет 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);

Примечание: я не уверен, почему текстура глубины имеет четыре канала. Если они вам не нужны, я бы изменил это на одноканальный формат.

Другие вопросы по тегам