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

标签 unity3d shader directx-11 compute-shader

我正在编写一个计算着色器(在统一环境中,它使用 DirectX11 DirectCompute),我需要执行一个非常简单的任务:检查图像中是否有任何像素具有绿色 == 1 和蓝色 > 0.5。 (为清楚起见 - 绿色 channel 是二维“光”,蓝色 channel 是光“轨迹” - 我想检测光何时越过它的轨迹。)

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

为了澄清,以下两张图片显示了“之前”和“之后”——我只需要一个“真”值,告诉我第二张图片中存在一些白色。

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] = ??
}

最佳答案

您可以选择使用原子操作并计算像素。您使用每个像素一个线程运行计算着色器,如果像素满足条件,则增加您的 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);
}

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

关于unity3d - 使用计算着色器返回纹理是否具有特定颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48141904/

相关文章:

glsl - THREE.js 在着色器中重复包装纹理

c# - Unity中的简单键盘输入

c# - 如果场景中的多个游戏对象使用该脚本,脚本中声明的公共(public)委托(delegate)是否一定是单个实例?

javascript - WebGL alpha 取决于与原点的距离

android - 异步或在 Android 上的不同线程中编译 GLSL 着色器

hlsl - 如何使用顶点缓冲区将计算着色器结果输入顶点着色器?

c# - 从顶点位置以编程方式创建 3D 棱镜

c# - Unity3d 动画事件未持续触发

c++ - 点光照错误 Directx 11

c++ - 了解 DXGI DirectX 11 桌面复制以获取缓冲区或数组的问题