最近使用glsl做毕设,遇到一些很有意思的问题,其中一个就是如何将depth值存储在RGBA格式的纹理中。
最开始时只用了8位来存储,和normal值存在一张RGBA纹理中,把depth放在了alpha通道上,但是在后续处理的时候发生了很严重的问题,尤其是类似SSAO这样的算法,可以精确检测出depth的不连续变化,画面中就会产生一条条的线。
看gameDev上也有一些人在讨论这个问题,也有人贴出来了将depth值编码存入RGBA纹理,需要时再解码的代码:
/// Packing a [0-1] float value into a 4D vector where each component will be a 8-bits integer
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;
}
/// Unpacking a [0-1] float value from a 4D vector where each component was a 8-bits integer
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));
}
有人说这个算法会产生一个gap,比较明显,但是也有人说it works very well,这取决于使用人的需求,然而我就属于前者。。。虽然depth的精度提高了,画面中不会再有一条条的线,但是在某一个距离还是会存在一个gap,这是这个算法的一个缺陷。
后来琢磨了一下,纹理中每8位是一个浮点数,1.0的二进制表示为0xff,它的整数形式其实是255,于是将所有的256换成255,大功告成,gap消失了,真是痛快。