从 Unity 3D 中的 RGBAFloat 纹理读取浮点值
Read float values from RGBAFloat texture in Unity 3D
似乎人们并没有就浮点纹理讨论太多。我用它们进行一些计算,然后将结果转发给另一个表面着色器(以获得一些特定的变形),这很酷,如果我在着色器中消化结果,它总是对我有用,但这次我需要获得这些值 CPU 端,所以我得到一个包含结果的 float[] 数组(就在调用填充浮点纹理的 Graphics.Blit 之后)。如何实现?
旁注:到目前为止,我看到唯一使用这种方法的人是 Keijiro,例如在他的 Kvant Wall 中;如果您有其他来源,请告诉我,我将不胜感激。
顺便说一句,我知道有计算着色器、OpenCL 和 CUDA。这就是我现在需要的方法。
所以我想到了这个解决方案。
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;
}
似乎人们并没有就浮点纹理讨论太多。我用它们进行一些计算,然后将结果转发给另一个表面着色器(以获得一些特定的变形),这很酷,如果我在着色器中消化结果,它总是对我有用,但这次我需要获得这些值 CPU 端,所以我得到一个包含结果的 float[] 数组(就在调用填充浮点纹理的 Graphics.Blit 之后)。如何实现?
旁注:到目前为止,我看到唯一使用这种方法的人是 Keijiro,例如在他的 Kvant Wall 中;如果您有其他来源,请告诉我,我将不胜感激。
顺便说一句,我知道有计算着色器、OpenCL 和 CUDA。这就是我现在需要的方法。
所以我想到了这个解决方案。
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;
}