Logarithmic depth buffer issues with near objects

Started by
2 comments, last by Hodgman 7 years, 4 months ago

Hello,

I started writing on a virtual reality extension for an existing Google Earth-like project (which I haven't written myself).

Drawing the scene (mostly terrain and buildings in the far distance) works, but drawing the controllers with the same shader doesn't and I

see ugly artifacts/z fighting.

[sharedmedia=gallery:images:8028]
The problems seems to be the logarithmic z buffer that is beeing used because if I move the controllers further away from my face these artifacts seem to disappear,

The important code parts are

Vertex Shader:


#version 420
[..]
uniform float farPlane;
smooth out float flogz;

void main()
{
[..]
    gl_Position = viewProjModel * position;

    float C = 10.0;
    float Fcoef = 2.0 / log2(farPlane * C + 1.0);
    gl_Position.z = log2(max(1e-6, gl_Position.w * C + 1.0)) * Fcoef - 1.0;
    flogz = 1.0 + gl_Position.w * C;
}

Fragment Shader:


#version 420

#extension GL_ARB_conservative_depth : enable

layout(depth_less) out float gl_FragDepth;

uniform float farPlane;
smooth in float flogz;

[..]

void main()
{
[..]
    float C = 10.0;
    float Fcoef = 2.0 / log2(farPlane * C + 1.0);
    gl_FragDepth = log2(flogz) * Fcoef * 0.5;
}

The Framebuffer is created with


glGenFramebuffers(1, &renderFramebufferId);
glBindFramebuffer(GL_FRAMEBUFFER, renderFramebufferId);
		   
glGenRenderbuffers(1, &depthBufferId);
glBindRenderbuffer(GL_RENDERBUFFER, depthBufferId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT32, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBufferId);
		   
glGenTextures(1, &renderTextureId);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, renderTextureId);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, width, height, true);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, renderTextureId, 0);

GLenum statusRenderFB = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (statusRenderFB != GL_FRAMEBUFFER_COMPLETE)
{
    [..] // abort
}

I also played with different C-constants, different depth texture formats and with glEnable(GL_DEPTH_CLAMP) and nothing seems to help.

Does anyone know a solution? These artifacts bother me for days.

Advertisement

Okay, I think I fixed it. It had nothing todo with the logarithmic depth buffer and was more of a problem with the 32 bit floating point precision (the position of my controller was around ~100000 in x,y,z).

Using a double matrix on a certain place fixed it (even though it seems more like a workaround).

Don't move the camera around the world - instead move the world around the camera, which should always be at 0,0,0. This will avoid needing any double precision hacks.

Seeing you're using OpenGL4, you could just use an inverted-z depth buffer instead of a logarithmic one, which has zero performance impact and doesn't cause interpolation artifacts.

https://nlguillemot.wordpress.com/2016/12/07/reversed-z-in-opengl/

(This was possible in D3D9 and has been the standard way to do Z-buffering for ever since, but GL needed to add glClipControl in GL4 before it was possible there)

This topic is closed to new replies.

Advertisement