iOS上的深度缓冲区精度损失

时间:2018-09-21 19:12:02

标签: metal depth-buffer

我正在使用一个非常简单的片段函数进行深度剥离:

struct VertexOut {
    float4 position  [[ position ]];
};

fragment void depthPeelFragment(VertexOut in [[ stage_in ]],
                                depth2d<float, access::read> previousDepth)
{
    float4 p = in.position;
    if(!is_null_texture(previousDepth) && p.z <= previousDepth.read(uint2(p.xy)))
    {
        discard_fragment();
    }
}

(我的深度缓冲像素格式为MTLPixelFormatDepth32Float

这在我的Mac上效果很好。在每遍中,我提交相同的几何图形,最终不再写入任何片段,并且过程终止。例如,对于一个测试球体,有两个通道,每个通道都写入相同数量的片段(前半球和后半球)。

但是,在iPad上,该过程不会终止。有一些(不是全部)片段,尽管在前一遍中已渲染,但在后续遍中并未被丢弃。

哪些平台差异可能导致此问题?

position属性的z坐标是否总是写入深度缓冲区的值?

根据Apple工程师的说法,它不是对数深度缓冲区。

请注意,我不能简单地限制通过次数(我没有将其用于OIT)。

更新

这是通过GPU捕获在第三遍中显示的深度纹理的样子(绿色代表渲染的几何体的边界):

Depth texture for test sphere

点的分布使它看起来像一个浮点精度问题。

此外,如果我在先前的深度缓冲区中添加epsilon:

p.z <= previousDepth.read(uint2(p.xy))+.0000001

然后该过程在iPad上终止。但是结果不足以用于下游。

0 个答案:

没有答案