将 int16 包装成 fixed2(红色 + 绿色)
Packing int16 into fixed2 (Red + Green)
在Unity中,高度图在内部被简称为Int16(注意只使用0-32767)。我想将高度图发送到 GPU,最好只使用 16 位。
似乎最好的方法是将高度图值编码为 RG16 渲染纹理(因为在 Unity 中我不能选择单通道 16 位整数格式),并且 pack/unpack 根据需要。
这是我发送到 GPU 的高度贴图纹理(通过 CPU 端 C# 脚本):
const int Size = 1024;
Color32[] colours = new Color32[Size * Size];
for (int y = 0; y < Size; y++) {
for (int x = 0; x < Size; x++) {
float height = heights[y, x]; // With Unity it's correct to flip the x/y axes
short s = (short)(heights[y, x] * short.MaxValue);
byte upper = (byte)(s >> 7); // Shift 7 and not 8 since we don't want values outside of 0-32767 anyway.
byte lower = (byte)(s & 255);
colours[y * size + x] = new Color32(upper, lower, 0, 0);
}
}
tex.SetPixels32(colours);
tex.Apply();
我 运行 遇到了一个令人困惑的问题,在解压缩高度图样本时似乎精度损失很大。我试过按位方式:
float HeightmapSample(float u, float v) {
fixed2 height = tex2Dlod(_Heightmap, float4(u, v, 0.f, 0.f)).rg;
int2 heightInt = height * 255.f;
int unpacked = (heightInt.r << 7) | heightInt.g;
return unpacked / 32767.f; // Renormalize
}
还有一个(可能)时髦的浮点方法:
float HeightmapSample(float u, float v) {
fixed2 height = tex2Dlod(_Heightmap, float4(u, v, 0.f, 0.f)).rg;
return height.r + (height.g / 128.f) - (1.f / 128.f);
}
这两种方法都不会产生与基本事实相同的结果:
在寻找罪魁祸首将近 2 天后,我意识到我的着色器在每次加载插件时都会错误地重新编码高度图。我故意没有修复那个着色器,因为我专注于上面的问题,但它变成了问题所在!
在Unity中,高度图在内部被简称为Int16(注意只使用0-32767)。我想将高度图发送到 GPU,最好只使用 16 位。
似乎最好的方法是将高度图值编码为 RG16 渲染纹理(因为在 Unity 中我不能选择单通道 16 位整数格式),并且 pack/unpack 根据需要。
这是我发送到 GPU 的高度贴图纹理(通过 CPU 端 C# 脚本):
const int Size = 1024;
Color32[] colours = new Color32[Size * Size];
for (int y = 0; y < Size; y++) {
for (int x = 0; x < Size; x++) {
float height = heights[y, x]; // With Unity it's correct to flip the x/y axes
short s = (short)(heights[y, x] * short.MaxValue);
byte upper = (byte)(s >> 7); // Shift 7 and not 8 since we don't want values outside of 0-32767 anyway.
byte lower = (byte)(s & 255);
colours[y * size + x] = new Color32(upper, lower, 0, 0);
}
}
tex.SetPixels32(colours);
tex.Apply();
我 运行 遇到了一个令人困惑的问题,在解压缩高度图样本时似乎精度损失很大。我试过按位方式:
float HeightmapSample(float u, float v) {
fixed2 height = tex2Dlod(_Heightmap, float4(u, v, 0.f, 0.f)).rg;
int2 heightInt = height * 255.f;
int unpacked = (heightInt.r << 7) | heightInt.g;
return unpacked / 32767.f; // Renormalize
}
还有一个(可能)时髦的浮点方法:
float HeightmapSample(float u, float v) {
fixed2 height = tex2Dlod(_Heightmap, float4(u, v, 0.f, 0.f)).rg;
return height.r + (height.g / 128.f) - (1.f / 128.f);
}
这两种方法都不会产生与基本事实相同的结果:
在寻找罪魁祸首将近 2 天后,我意识到我的着色器在每次加载插件时都会错误地重新编码高度图。我故意没有修复那个着色器,因为我专注于上面的问题,但它变成了问题所在!