如何将一个float的小数部分保存成RGBA4个8位的byte

shadow map的时候经常看到这两个函数

vec4 packFloatToVec4i(const float value) {
  const vec4 bitSh = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);
  const vec4 bitMsk = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
  vec4 res = fract(value * bitSh);
  res -= res.xxyz * bitMsk;
  return res;
}

float unpackFloatFromVec4i(const vec4 value) {
  const vec4 bitSh = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);
  return(dot(value, bitSh));
}

用于将0-1之间的深度值保存到RGBA8纹理里面。

参考http://marcodiiga.github.io/encoding-normalized-floats-to-rgba8-vectors解释下原理:

------------------------------------------------------------------------------------------------------------------------------------------------------

首先上述方法只能编码/解码小数部分,也就是0-1之间的值。

------------------------------------------------------------------------------------------------------------------------------------------------------

IEEE754 floats

也就是说:0.3可以分解成:{2^(-2) + 2^(-5) + 2^(-6)} + {2^(-9) + 2^(-10) + 2^(-13) + 2^(-14)} + {2^(-17) + 2^(-18) + 2^(-21) + 2^(-22)} + {2^(-25)}

也就是说:如果我们能分别拿到上面的四部分,就能重新拼出这个0.3,那么如何得到每一部分的值呢?

{2^(-25)}:这个比较简单,fract(0.3 << 24) >> 24; [fract函数为取小数部分]

{2^(-17) + 2^(-18) + 2^(-21) + 2^(-22)}:(fract(0.3 << 16) - (fract(0.3 << 24) >> 8)) >> 16

我们来分析一下:

  • a:=fract(0.3 << 16),先右移16位再取小数部分,这样得到的结果是({2^(-17) + 2^(-18) + 2^(-21) + 2^(-22)} {2^(-25)})<< 16
  • b:= fract(0.3 << 24) >> 8, 结果是{2^(-25)}<<16
  • 哈哈,(a - b)>>16 就得到了蓝色部分{2^(-17) + 2^(-18) + 2^(-21) + 2^(-22)} 

依次类推:

{2^(-9) + 2^(-10) + 2^(-13) + 2^(-14)} :(fract(0.3 << 8) - (fract(0.3 << 16) >> 8)) >> 8

{2^(-2) + 2^(-5) + 2^(-6)}: (fract(0.3) - (fract(0.3 << 8) >> 8)) >> 0

------------------------------------------------------------------------------------------------------------------------------------------------------

To Sum Up : 上面的两个函数。

猜你喜欢

转载自www.cnblogs.com/redips-l/p/11882887.html