使用计算着色器返回纹理是否具有特定颜色

时间:2018-01-07 21:55:24

标签: unity3d shader directx-11 compute-shader

我正在编写计算着色器(在统一环境中,使用DirectX11 DirectCompute),我需要做一个非常简单的任务:检查图像中的任何像素是否为绿色== 1和蓝色> 0.5。 (为清楚起见 - 绿色通道是2d"灯光#34;蓝色通道是灯光"跟踪" - 我想检测光线何时越过它的路径。)

我为了调试目的而显示重叠(以白色显示),但我不知道如何做一些简单的事情,如返回指示纹理是否实际包含重叠的值。我的困惑源于线程如何工作。我有一个浮动缓冲区,有一个浮动空间 - 我只需要1或0。

为了澄清,以下两张图片显示了"之前" """" - 我所需要的只是一个" true"价值告诉我第二张图片中存在一些白色。

The original image The "overlap"

计算着色器如下:

#pragma kernel CSMain

Texture2D<float4> InputTexture;
RWTexture2D<float4> OutputTexture;
RWStructuredBuffer<float> FloatBuffer;

[numthreads(8,8,1)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
    // need to detect any region where g == 1 and blue > 0.5

    float green = InputTexture[id.xy].g;
    float blue = round(InputTexture[id.xy].b);

    float overlap = round((green + blue) / 2.0);

    OutputTexture[id.xy] = float4(overlap, overlap, overlap, 1);

    // answer here?? Note that the output texture is only for debugging purposes
    FloatBuffer[0] = ??
}

1 个答案:

答案 0 :(得分:2)

您可以选择使用原子操作并计算像素数。您使用每个像素一个线程运行计算着色器,如果像素符合条件,则递增rwbuffer。

这样的事情:

Texture2D<float4> InputTexture;
RWBuffer<uint> NotAFloatBuffer;

[numthreads(8,8,1)]
void CSMain(uint3 id : SV_DispatchThreadID {
    // need to detect any region where g == 1 and blue > 0.5
    float green = InputTexture[id.xy].g;
    float blue = round(InputTexture[id.xy].b);

    float overlap = round((green + blue) / 2.0);
    if (overlap > 0)
        InterlockedAdd(NotAFloatBuffer[0],1);
}

在你的情况下,你可以在这里停下来,但是原子学有一些成本损失,并且通常通过将来自组中的单个线程的调用与先前的减少进行分组来优化它们,但这只是在最极端的情况下,你做的不必担心。