Преобразование текстуры в массив значений 1d с использованием вычислительного шейдера - PullRequest
0 голосов
/ 09 мая 2018

У меня довольно простое требование для вычислительного шейдера (DirectCompute через Unity).У меня есть текстура 128x128, и я хотел бы превратить красный канал этой текстуры в 1d массив с плавающей точкой.Мне нужно делать это очень часто, поэтому простое выполнение цикла на стороне процессора для каждого текселя не обрежет его.

Инициализация:

    m_outputBuffer = new ComputeBuffer(m_renderTexture.width * m_renderTexture.height, sizeof(float));
    m_kernelIndex = m_computeShader.FindKernel("CSMain");

Вот метод C #:

/// <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;
}

и весь вычислительный шейдер:

// 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;
}

метод C # возвращает массив ожидаемого размера, и он обычно в некотором роде соответствует ожидаемому.Однако, даже если моя входная текстура будет равномерно красной, все равно будут некоторые нули.

1 Ответ

0 голосов
/ 12 мая 2018

Я пересмотрел и решил свой вопрос. Ответ состоял из двух частей: я странным образом комбинировал координаты x и y (id.x и id.y) и использовал неверную семантику ввода. (SV_GroupThreadID вместо SV_DispatchThreadID)

Итак, вот решение. Я также перевернул ось у, чтобы соответствовать своей интуиции.

// 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...