我正在使用一个非常简单的片段函数进行深度剥离:
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捕获在第三遍中显示的深度纹理的样子(绿色代表渲染的几何体的边界):
点的分布使它看起来像一个浮点精度问题。
此外,如果我在先前的深度缓冲区中添加epsilon:
p.z <= previousDepth.read(uint2(p.xy))+.0000001
然后该过程在iPad上终止。但是结果不足以用于下游。