我有一个3D场景和一个使用gluPerspective定义的相机.我有一个固定的FOV,我知道任何几何体与相机的最小距离(它是第一人称视角,因此这是从视点到角色碰撞体积的最小距离).
无论玩家如何移动和观看,我怎样才能选择最近的剪裁平面(最佳深度缓冲分辨率),不会造成任何剪裁?
这些距离不是简单相等,因为近平面的角离原点比中心更远.
我已经设法在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.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,无论我将相机放大多远(我得到一点z-战斗时只有0.0001(0.1毫米),但是meh).
不过,我确实有一些问题/疑虑.
1)我得到的平面剪裁比我的普通深度缓冲更多,看起来很难看.它发生在逻辑上它确实不应该的情况下.以下是我的意思的几个屏幕截图:
这两种情况都是我用普通深度缓冲区没有遇到的情况,我宁愿看不到(特别是前者).编辑:问题1通过使用正式解决glEnable(GL_DEPTH_CLAMP).
2)为了使其工作,我需要写入gl_FragDepth.我试过不这样做,但结果是不可接受的.写入gl_FragDepth意味着我的显卡无法进行早期z优化.这将不可避免地让我爬上墙,所以我想尽快解决它.
3)我需要能够检索存储在深度缓冲区中的值(我已经有了帧缓冲区和纹理),然后将其转换为线性视图空间坐标.我真的不知道从哪里开始这个,我之前做过它的方式涉及逆投影矩阵,但我不能在这里真正做到这一点.有什么建议?
我正在尝试实现本教程中的代码,但比例要大得多(半径 = 100000 单位)。
我不知道大小是否重要,但在我的地球上渲染云有一个奇怪的渲染。正如教程中所做的那样,我使用两个球体和三个纹理(地球贴图、凹凸贴图、云)。
结果如下(如果云更近,情况会更糟):

云层距离行星表面越近,这种故障就越明显。如果云足够远(但这不现实),问题就会完全消失。
我能做些什么?
3d ×2
webgl ×2
c++ ×1
depth-buffer ×1
javascript ×1
opengl ×1
projection ×1
three.js ×1
zbuffer ×1