U3D EncodeFloatRGBA&DecodeFloatRGBA
(2014-08-04 17:43:30)
标签:
it |
UnityCG.cginc中的原函数代码如下:
inline float4 EncodeFloatRGBA( float v )
{
float4 kEncodeMul = float4(1.0, 255.0, 65025.0,
160581375.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/160581375.0);
return dot( enc, kDecodeDot );
}
单单看代码实在让人摸不着头脑,展开后可得EncodeFloatRGBA的最终结果为:
x = 1/v - 1/(v*255^2);//R
y = 1/(v*255) - 1/(v*255^3);//G
z = 1/(v*255^2) - 1/(v*255^4);//B
w = 1/(v*255^3) - 1/(v*255^4);//A
感觉抓到了一点东西,但是还是不是很清楚,再看Decode函数计算结果:
[1/v-1/(v*255^2)] + [1/(v*255^2)-1/(v*255^4)] +
[1/(v*255^4)-1/(v*255^6)] + [1/(v*255^6)-1/(v*255^7)]
=1/v-1/(v*255^7)
这下应该一目了然了,Encode函数是把一个float类型的值存进四个RGBA中,为了提高精度(float值的有效位数只有7位),R值存的是[0,
1/255^2]段的值,G值存的是[1/255^2, 1/255^4]的值,往后依次类推。GBA三个分量分别乘以了255,
255^2,255^3。这样保证其精度落在float类型的有效位数内。至于1/255^7后面的数值,则基本可以忽略不计了,而且float也存不下了。
说的再简单一点,举个例子,比如现在有个float类型的值h=1.23456...,我如果把h存在一个int整形的变量里面,那么小数后面的精度肯定丢失了。如果我想保留,那么可以用四个整形变量a,
r, g, b来保存,a = 1, r = 2, g = 3, b = 4。这样g可以表示为:h =
a+0.1*r+0.01*g+0.001*b。这个原理其实和上面的Encode和Decode是一样的,只不过这个例子用的是10倍,而U3D中是255倍。

加载中…