我在深度测试中遇到了不一致的行为,我不知道是否在任何地方指定了此行为。
我的问题是:当使用
EQUAL
作为深度测试函数时,当深度清除值和基元的深度值都恰好是1.0
时,预期的行为是什么?有明确的行为吗?或者深度测试不是专门用于与深度缓冲区的“清晰/空”区域进行比较?
我看到深度测试在 Mac(Intel 和 M3)和 Mali-G52 上通过,但在 Snapdragon 685 上失败。
这里的问题更清楚:如果您使用以下配置创建一个 WebGL 程序:
gl.enable(gl.DEPTH_TEST);
gl.clearDepth(1.0);
gl.depthFunc(gl.EQUAL);
...然后在顶点着色器中指定:
gl_Position.z = 1.0;
...您希望程序渲染任何内容吗?
在我的 M3 Mac、Intel Mac 和 Mali GPU 上,可以渲染图元,但在两个 Snapdragon 上则不然。在使用浮点计算器进行进一步调查后,我确定使用
gl.clearDepth(0.9999828338623046875)
更改上述配置确实适用于 Snapdragon,这表明在深度测试操作期间,这些设备上的剪辑空间深度会缩放(但不会钳制)到小于 1.0。我已经在片段着色器中确认,经过深度测试,片段深度仍然是1.0。
那个奇怪的值(0.9999828338623046875)需要18位尾数,这比
depth16unorm
或半精度浮点精度更高(诚然,我不知道双精度JS数字如何在WebGL中转换为标准化整数)。
这是一个错误吗?或者未定义的行为?浏览完规范后,我看不到任何有用的东西。
GLSL ES 1.0 规范(§4.5.2)仅指定给定精度的最小范围,而不是底层表示,当数据写入帧缓冲区时,目标特定的转换/舍入发生在最后,因此我假设您处于未定义的行为领域。您可以尝试通过使用 ALWAYS
(或禁用深度测试)渲染屏幕空间四边形来将内容保留在 GPU 上,而不是使用
clear
和
clearDepth
。