我使用金属着色器在屏幕上绘制许多粒子。每个粒子都有自己的位置(可以改变),并且通常两个粒子具有相同的位置。如何检查我写入的texture2d
是否在某个位置没有像素? (如果还没有绘制粒子,我想确保我只在某个位置绘制一个粒子,因为如果在同一个位置绘制了许多粒子,我会得到一个难看的闪烁)
我已尝试outTexture.read(particlePosition)
,但由于纹理访问限定符access::write
,这显然无效。
有没有办法可以同时对texture2d
进行读写访问? (如果没有,我怎么还能解决我的问题?)
答案 0 :(得分:3)
有几种方法可以在这里工作。在并发系统编程中,您所谈论的内容被称为首次写入胜利。
1)如果粒子只需要阻止绘制其他粒子(并且在同一渲染过程中不会被场景中的其他元素遮挡),您可以将特殊值写入深度缓冲区表示片段已写入特定坐标。例如,您打开深度测试(使用深度比较功能Equal),将深度缓冲区清除到某个远程值(如1.0),然后将值0.0写入片段函数中的深度缓冲区。对给定像素的任何后续写入都将无法通过深度测试,并且不会被绘制。
2)使用framebuffer回读。在iOS上,Metal允许您通过使用[[color(0)]]
将参数归因于片段函数来从当前绑定的主渲染缓冲区中读取。此参数将包含renderbuffer中的当前颜色值,您可以对其进行测试以确定是否已将其写入。这确实需要您将纹理清除为预定的颜色,否则您的片段函数将永远不会产生这种颜色,因此它比上述方法更受限制,并且性能可能更低。
以上所有内容均适用于您是否渲染为可绘制的纹理,以便直接呈现到屏幕或某些屏幕外纹理。
答案 1 :(得分:-1)
您可以这样指定输出纹理的读/写访问权限:
texture2d<float, access::read_write> outTexture [[texture(1)]],
此外,您的纹理描述符必须指定用法:
textureDescriptor?.usage = [.shaderRead, .shaderWrite]