作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
内置的 Unity 着色器支持将 32 位 RGBA 值编码和解码为 32 位浮点数的技术。这可以通过简单地将每个 channel 与它之前的 channel 的最高可能值相乘来完成。由于它存储在浮点数中,因此预计会出现一些精度损失。
着色器显然有一些我试图理解的优化。
UnityCG.cginc 代码中的着色器如下所示:
// Encoding/decoding [0..1) floats into 8 bit/channel RGBA. Note that 1.0 will not be encoded properly.
inline float4 EncodeFloatRGBA( float v )
{
float4 kEncodeMul = float4(1.0, 255.0, 65025.0, 16581375.0);
float kEncodeBit = 1.0/255.0;
float4 enc = kEncodeMul * v;
enc = frac (enc);
enc -= enc.yzww * kEncodeBit;
return enc;
}
inline float DecodeFloatRGBA( float4 enc )
{
float4 kDecodeDot = float4(1.0, 1/255.0, 1/65025.0, 1/16581375.0);
return dot( enc, kDecodeDot );
}
f = R + 255 * G + 65025 * B + 16581375 * A
不会给出兼容的结果。为什么要做出这个选择? 最佳答案
从检查来看,Unity 代码看起来像是要转换介于 0.0
之间的浮点值。和 1.0
(不包括 1)成 4 个介于 0.0
之间的浮点值和 1.0
这样,这些值可以通过乘以 255 转换为从 0 到 255 的整数值。
但是,该死,您对这段代码持怀疑态度确实是正确的。它有很多缺陷(但通常会产生足够接近的结果以供大部分使用)。
他们乘以 255 而不是 256 的原因是因为他们错误地认为通过将值保持为浮点数可以获得合理的结果(并计划稍后将浮点数转换为 0-255 值的整数,正如其他人在注释)。但是,然后他们使用了 frac()
称呼。您需要将看起来像这样的浮点代码识别为具有不良代码气味 TM。
正确的代码如下所示:
inline float4 EncodeFloatRGBA(float v)
{
var vi = (uint)(v * (256.0f * 256.0f * 256.0f * 256.0f));
var ex = (int)(vi / (256 * 256 * 256) % 256);
var ey = (int)((vi / (256 * 256)) % 256);
var ez = (int)((vi / (256)) % 256);
var ew = (int)(vi % 256);
var e = float4(ex / 255.0f, ey / 255.0f, ez / 255.0f, ew / 255.0f);
return e;
}
inline float DecodeFloatRGBA(float4 enc)
{
var ex = (uint)(enc.x * 255);
var ey = (uint)(enc.y * 255);
var ez = (uint)(enc.z * 255);
var ew = (uint)(enc.w * 255);
var v = (ex << 24) + (ey << 16) + (ez << 8) + ew;
return v / (256.0f * 256.0f * 256.0f * 256.0f);
}
ew
值并编码为 RGB 而不是 RGBA。
0.0
之间的值。和
1.0
.您甚至可以编码无穷大和
NaN
s。该代码如下所示:
inline float4 EncodeFloatRGBA(float v)
{
byte[] eb = BitConverter.GetBytes(v);
if (BitConverter.IsLittleEndian)
{
return float4(eb[3] / 255.0f, eb[2] / 255.0f, eb[1] / 255.0f, eb[0] / 255.0f);
}
return float4(eb[0] / 255.0f, eb[1] / 255.0f, eb[2] / 255.0f, eb[3] / 255.0f);
}
inline float DecodeFloatRGBA(float4 enc)
{
var eb = BitConverter.IsLittleEndian ?
new[] { (byte)(enc.w * 255), (byte)(enc.z * 255),
(byte)(enc.y * 255), (byte)(enc.x * 255) } :
new[] { (byte)(enc.x * 255), (byte)(enc.y * 255),
(byte)(enc.z * 255), (byte)(enc.w * 255) };
return BitConverter.ToSingle(eb, 0);
}
关于unity3d - 理解 Unitys 中的 RGBA 编码 float (EncodeFloatRGBA),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41566049/
内置的 Unity 着色器支持将 32 位 RGBA 值编码和解码为 32 位浮点数的技术。这可以通过简单地将每个 channel 与它之前的 channel 的最高可能值相乘来完成。由于它存储在浮点
我是一名优秀的程序员,十分优秀!