【问题标题】:Read float values from RGBAFloat texture in Unity 3D从 Unity 3D 中的 RGBAFloat 纹理读取浮点值
【发布时间】:2016-10-22 05:46:38
【问题描述】:

似乎人们对浮点纹理的讨论不多。我用它们进行一些计算,然后将结果转发到另一个表面着色器(以获得一些特定的变形),这很酷,如果我在着色器中消化结果,它总是对我有用,但这次我需要获取这些值 CPU所以我得到一个带有结果的 float[] 数组(就在调用填充浮点纹理的 Graphics.Blit 之后)。如何实现?

附带说明:到目前为止,我看到的唯一使用这种方法的人是 Keijiro,例如在他的 Kvant Wall 中;如果您有其他来源,请告诉我。

顺便说一句,我知道有计算着色器、OpenCL 和 CUDA。这是我现在需要的方法。

【问题讨论】:

  • 我可能遗漏了一些东西,但 Texture2D.ReadPixels 没有为您提供所需的功能?
  • 嘿@Bart 我使用ReadPixels 将RenderTexture 结果转换为texture2D(仍然是FloatARGB 格式)但是然后呢?我不能使用 GetPixels,因为它返回一个颜色数组并且值会被截断。我现在正在查看 GetRawTextureData,我想我会得到它。
  • 嗯,我应该看看,但 GetPixels(相对于 Color32 替代方案)不能为您提供全精度浮点结果吗?
  • 是吗?我过去试过。我得到了意想不到的结果,但我可能错过了一些东西。

标签: unity3d gpgpu


【解决方案1】:

所以我想出了这个解决方案。

 float[] DecodeFloatTexture()
{
    Texture2D decTex = new Texture2D(resultBuffer.width, resultBuffer.height, TextureFormat.RGBAFloat, false);
    RenderTexture.active = resultBuffer;
    decTex.ReadPixels(new Rect(0, 0, resultBuffer.width, resultBuffer.height), 0, 0);
    decTex.Apply();
    RenderTexture.active = null;
    Color[] colors = decTex.GetPixels();
    // HERE YOU CAN GET ALL 4 FLOATS OUT OR JUST THOSE YOU NEED.
    // IN MY CASE ALL 4 VALUES HAVE A MEANING SO I'M GETTING THEM ALL.
    float[] results = new float[colors.Length*4];
    for(int i=0; i<colors.Length; i++)
    {
        results[i * 4] = colors[i].r;
        results[i * 4 + 1] = colors[i].g;
        results[i * 4 + 2] = colors[i].b;
        results[i * 4 + 3] = colors[i].a;
    }
    return results;
}

或者,如果我们需要的不是浮点数,GetRawTextureData 可用于将字节转换为具有 System.BitConverter 的新类型,这为您从着色器传递的数据提供了一些灵活性(例如,如果您的片段着色器正在输出 half4)。如果你需要 float 虽然第一种方法更好。

 float[] DecodeFloatTexture()
{
    Texture2D decTex = new Texture2D(resultBuffer.width, resultBuffer.height, TextureFormat.RGBAFloat, false);
    RenderTexture.active = resultBuffer;
    decTex.ReadPixels(new Rect(0, 0, resultBuffer.width, resultBuffer.height), 0, 0);
    decTex.Apply();
    RenderTexture.active = null;
    byte[] bytes = decTex.GetRawTextureData();
    float[] results = new float[resultBuffer.width * resultBuffer.height];
    for (int i = 0; i < results.Length; i++)
    {
        int byteIndex = i * 4;
        byte[] localBytes = new byte[] { bytes[i], bytes[i + 1], bytes[i + 2], bytes[i + 3] }; // converts 4 bytes to a float
        results[i] = System.BitConverter.ToSingle(localBytes, 0);
    }
    return results;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-31
    • 2019-08-19
    • 1970-01-01
    • 2019-01-15
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多