我正在尝试在WebGL中研究阴影贴图。我看到在各种库和实例中复制了相同的着色器代码。然而,我找不到它是如何工作的解释。
这个想法是将深度值(单个浮点数)保存到颜色缓冲区(vec4)中。有一个pack函数可以将float保存到vec4和unpack函数,从vec4中检索float。
vec4 pack_depth(const in float depth)
{
const vec4 bit_shift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);
const vec4 bit_mask = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
vec4 res = fract(depth * bit_shift);
res -= res.xxyz * bit_mask;
return res;
}
float unpack_depth(const in vec4 rgba_depth)
{
const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);
float depth = dot(rgba_depth, bit_shift);
return depth;
}
我原本想象将一个浮动包装到vec4应该是一个微不足道的问题,只需将其复制到vec4的4个插槽中的一个,并留下其他未使用的。这就是为什么上面代码中的位移逻辑对我来说很困惑。
任何人都能解释一下吗?
答案 0 :(得分:12)
它没有在GLSL float
中存储GLSL vec4
。它正在做的是在vec4
中存储一个值,当写入RGBA8帧缓冲区(32位值)时,可以将其读作vec4
,然后重构为float
,先前已经过了。
如果你按照你的建议做,只需将浮点值写入帧缓冲区的红色通道,你只能得到8位精度。使用此方法,您将获得所有32位的工作。
答案 1 :(得分:3)
除了上面的答案,你可能会对这里描述的浮点纹理扩展感兴趣:
http://www.khronos.org/registry/webgl/extensions/OES_texture_float/
请注意,此扩展程序不存在/运行时有硬件/软件设置,但如果确实存在,则确定是一个很好的扩展。我的经验是,它也很快。如果使用此功能,则可以使用其余三个通道存储其他信息,例如投影纹理的颜色。
答案 2 :(得分:2)
如果您对这些例程如何运作的细节感兴趣,我建议您阅读my blog post。我在这里添加了一些有关代码如何工作的细节以及解决一些可能的用例。
正如您可能已经想到的那样,该代码将标准化浮点值编码为vec4
。 OpenGL ES 2.0或WebGL(在撰写本文时)可能会利用这些打包/解包例程通过RGBA8
纹理(more on this in the spec)提供32位精度浮点。
即使Mikael(OES_texture_float
)发布了扩展,也可能需要(例如用于调试)转储完整的32位精度规范化浮点,并且正如规范readPixels
中所述受以下限制
只接受两种格式和类型的组合。第一种是RGBA格式,输入UNSIGNED_BYTE。第二种是实现选择的格式。