iOS Metal Shader - 纹理读写访问?

时间:2016-03-21 13:09:52

标签: ios shader metal

我使用金属着色器在屏幕上绘制许多粒子。每个粒子都有自己的位置(可以改变),并且通常两个粒子具有相同的位置。如何检查我写入的texture2d是否在某个位置没有像素? (如果还没有绘制粒子,我想确保我只在某个位置绘制一个粒子,因为如果在同一个位置绘制了许多粒子,我会得到一个难看的闪烁)

我已尝试outTexture.read(particlePosition),但由于纹理访问限定符access::write,这显然无效。

有没有办法可以同时对texture2d进行读写访问? (如果没有,我怎么还能解决我的问题?)

2 个答案:

答案 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]