使用计算着色器将纹理转换为浮点值的1d数组

时间:2018-05-09 20:21:04

标签: c# unity3d shader compute-shader directcompute

我对计算着色器(通过Unity的DirectCompute)有一个相当简单的要求。我有一个128x128的纹理,我想把那个纹理的红色通道变成一个浮动的1d数组。我需要经常这样做,所以只需在每个纹素上执行cpu-side for循环就不会削减它。

初​​始化:

/// <summary>
/// This method converts the red channel of the given RenderTexture to a
/// one dimensional array of floats of size width * height.
/// </summary>
private float[] ConvertToFloatArray(RenderTexture renderTexture)
{
    m_computeShader.SetTexture(m_kernelIndex, INPUT_TEXTURE, renderTexture);

    float[] result = new float[renderTexture.width * renderTexture.height];

    m_outputBuffer.SetData(result);
    m_computeShader.SetBuffer(m_kernelIndex, OUTPUT_BUFFER, m_outputBuffer);

    m_computeShader.Dispatch(m_kernelIndex, renderTexture.width / 8, renderTexture.height / 8, 1);

    m_outputBuffer.GetData(result);

    return result;
}

这是C#方法:

// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain

// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
Texture2D<float4> InputTexture;
RWBuffer<float> OutputBuffer;

[numthreads(8, 8, 1)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
    OutputBuffer[id.x * id.y] = InputTexture[id.xy].r;
}

和整个计算着色器:

{{1}}

C#方法返回一个预期大小的数组,它通常与我期望的排序相对应。但是,即使我的输入纹理是均匀的红色,仍然会有一些零。

1 个答案:

答案 0 :(得分:0)

我重新考虑并解决了自己的问题。答案分为两部分:我奇怪地将x和y坐标(id.x和id.y)组合在一起,而我使用了错误的输入语义。 (SV_GroupThreadID而不是SV_DispatchThreadID)

所以这是解决方案。我也翻了y轴以符合我的直觉。

// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain

// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
Texture2D<float4> InputTexture;
RWBuffer<float> OutputBuffer;

[numthreads(8, 8, 1)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
    uint w, h;
    InputTexture.GetDimensions(w, h);

    OutputBuffer[id.x + id.y * w] = InputTexture[float2(id.x, h - 1 - id.y)].r;
}