Я выполняю очистку глубины с помощью очень простой функции фрагмента:
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 процесс не завершается.Есть некоторые (не все) фрагменты, которые, несмотря на то, что они были визуализированы в предыдущем проходе, не удаляются в последующих проходах.
Какие различия платформ могут вызвать это?
Является ли координата z атрибута position всегда значением, записанным в буфер глубины?
По словам инженера Apple, это не логарифмический буфер глубины.
Обратите внимание, чтоЯ не могу просто ограничить количество проходов (я не использую это для OIT).
Обновление:
Вот как выглядит текстура глубины на 3-м проходечерез захват графического процессора (зеленый цвет представляет границы визуализированной геометрии):
Распределение точек делает это похожим на проблему точности с плавающей запятой.
Более того, если я добавлю эпсилон в предыдущий буфер глубины:
p.z <= previousDepth.read(uint2(p.xy))+.0000001
, то процесс на iPad будет прекращен.Однако результаты недостаточно точны для последующего использования.