iOS Metal Shader - Доступ к текстам для чтения и записи?
Я использую металлический шейдер, чтобы рисовать много частиц на экране. Каждая частица имеет свою собственную позицию (которая может меняться), и часто две частицы имеют одинаковую позицию. Как я могу проверить, если texture2d
Я пишу в не имеет пикселя в определенной позиции еще? (Я хочу убедиться, что я рисую частицу только в определенной позиции, если еще не была нарисована частица, потому что я получаю ужасное мерцание, если много частиц нарисовано в одном и том же положении)
я пробовал outTexture.read(particlePosition)
, но это, очевидно, не работает, из-за квалификатора доступа к текстуре, который access::write
,
Есть ли способ, которым я могу иметь доступ для чтения и записи к texture2d
в то же время? (Если нет, как я могу решить свою проблему?)
1 ответ
Есть несколько подходов, которые могли бы работать здесь. В параллельном системном программировании то, о чем вы говорите, называется победой первой записи.
1) Если частицы должны только препятствовать отрисовке других частиц (и не могут быть скрыты другими элементами сцены на одном и том же проходе рендеринга), вы можете записать специальное значение в буфер глубины, чтобы указать, что фрагмент имеет уже были записаны с определенной координатой. Например, вы включили бы тест глубины (используя функцию сравнения глубины Equal), очистили буфер глубины до некоторого удаленного значения (например, 1,0), а затем записали значение 0,0 в буфер глубины в функции фрагмента. Любая последующая запись в данный пиксель не пройдет проверку глубины и не будет прорисована.
2) Используйте чтение кадрового буфера. На iOS Metal позволяет вам читать из текущего текущего основного рендербуфера, присваивая параметр вашей функции фрагмента с помощью [[color(0)]]
, Этот параметр будет содержать текущее значение цвета в renderbuffer, с которым вы можете проверить, чтобы определить, было ли оно записано. Это требует от вас очистки текстуры до заданного цвета, который никогда не будет получен вашей функцией фрагмента, поэтому он более ограничен, чем описанный выше подход, и, возможно, менее производителен.
Все вышеперечисленное применимо, независимо от того, визуализируете ли вы на рисованную текстуру для непосредственного представления на экране или на какой-либо внеэкранной текстуре.
Вы можете указать доступ для чтения / записи для выходной текстуры как таковой:
texture2d<float, access::read_write> outTexture [[texture(1)]],
Кроме того, дескриптор текстуры должен указывать использование:
textureDescriptor?.usage = [.shaderRead, .shaderWrite]