对数深度缓冲区OpenGL

Hay*_*ach 7 c++ opengl 3d depth-buffer

我已经设法在OpenGL中实现了一个对数深度缓冲区,主要是来自Outerra的文章(你可以在这里,这里这里阅读).但是,我遇到了一些问题,我不确定这些问题是否是使用对数深度缓冲区所固有的,或者是否有一些我无法想到的解决方法.

刚开始,这就是我在顶点着色器中计算对数深度的方法:

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;
Run Code Online (Sandbox Code Playgroud)

这就是我在片段着色器中修复深度值的方法:

gl_FragDepth = log2(flogz) * HALF_FCOEF;
Run Code Online (Sandbox Code Playgroud)

在哪里ZNEAR = 0.0001,ZFAR = 1000000.0FCOEF = 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,无论我将相机放大多远(我得到一点z-战斗时只有0.0001(0.1毫米),但是meh).

不过,我确实有一些问题/疑虑.

1)我得到的平面剪裁比我的普通深度缓冲更多,看起来很难看.它发生在逻辑上它确实不应该的情况下.以下是我的意思的几个屏幕截图:

剪掉地面. 剪裁网格.

这两种情况都是我用普通深度缓冲区没有遇到的情况,我宁愿看不到(特别是前者).编辑:问题1通过使用正式解决glEnable(GL_DEPTH_CLAMP).

2)为了使其工作,我需要写入gl_FragDepth.我试过不这样做,但结果是不可接受的.写入gl_FragDepth意味着我的显卡无法进行早期z优化.这将不可避免地让我爬上墙,所以我想尽快解决它.

3)我需要能够检索存储在深度缓冲区中的值(我已经有了帧缓冲区和纹理),然后将其转换为线性视图空间坐标.我真的不知道从哪里开始这个,我之前做过它的方式涉及逆投影矩阵,但我不能在这里真正做到这一点.有什么建议?

dat*_*olf 3

近平面裁剪独立于深度测试而发生,而是通过针对cli 空间体积进行裁剪。在现代 OpenGL 中,我们可以使用深度钳位来使事物看起来再次漂亮。请参阅http://opengl.datenwolf.net/gltut/html/Positioning/Tut05%20Depth%20Clamping.html#d0e5707