首先,这是我在顶点着色器中计算对数深度的方法:
gl_Position = MVP * vec4(inPosition, 1.0);
gl_Position.z = log2(max(ZNEAR, 1.0 + gl_Position.w)) * FCOEF - 1.0;
flogz = 1.0 + gl_Position.w;
这是我在片元着色器中修复深度值的方法:
gl_FragDepth = log2(flogz) * HALF_FCOEF;
当 ZNEAR = 0.0001
,ZFAR = 1000000.0
,FCOEF = 2.0 / log2(ZFAR + 1.0)
,以及HALF_FCOEF = 0.5 * FCOEF
。在我的情况下,C
为1.0,以简化我的代码并减少计算。
首先,我非常满意获得的精度水平。使用普通深度缓存(znear = 0.1,zfar = 1000.0),我在视距边缘处遇到了很多z-fighting。现在,由于我的 znear:zfar 远远更远,我在第一个地面平面下方放置了第二个地面平面(间距为0.01单位),无论我将摄像机拉远多远,我都找不到任何z-fighting(当它离0.0001(0.1毫米)时,我会有一些z-fighting,但不那么严重)。
然而,我确实有一些问题和顾虑。
1)我使用正常深度缓冲时没有的近平面裁剪更多,看起来很丑。这种情况在逻辑上不应该发生。以下是我所说的一些截图:
地面被裁剪。
剪裁网格。
这两种情况都是我在普通深度缓冲区中没有遇到过的,而且我不想看到它们(尤其是前者)。编辑:问题1已通过使用glEnable(GL_DEPTH_CLAMP)
正式解决。
2)为了使其工作,我需要写入gl_FragDepth
。我尝试不这样做,但结果令人无法接受。写入gl_FragDepth
意味着我的图形卡不能进行早期的z优化。这将不可避免地让我发疯,所以我想尽快解决它。
3)我需要能够检索深度缓冲区中存储的值(我已经有一个帧缓冲区和纹理),然后将其转换为线性视图空间坐标。我真的不知道从哪里开始,我以前所做的方式涉及到逆投影矩阵,但我在这里真的做不到。有什么建议吗?