打包到vec4 - 这段代码如何工作?

Jay*_*esh 19 opengl-es glsl webgl

我正在尝试在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;
}
Run Code Online (Sandbox Code Playgroud)

我想象将一个浮动包装到vec4应该是一个微不足道的问题,只需将其复制到vec4的4个插槽中的一个并留下其他未使用的.这就是为什么上面代码中的位移逻辑让我感到困惑的原因.

任何人都能解释一下吗?

Nic*_*las 12

它不是在GLSL float中存储GLSL vec4.它正在做的是在a中存储一个值vec4,当写入RGBA8时,帧缓冲区(32位值)可以作为a读取vec4,然后重构为float先前给出的相同值.

如果你按照你的建议做了,只需将浮点值写入帧缓冲区的红色通道,你就只能获得8位的精度.使用此方法,您可以获得所有32位.

  • 严格来说,转换为 32 位定点数,而不是浮点数。 (2认同)

Mar*_* A. 5

如果您对这些例程如何工作的具体细节感兴趣,我建议您阅读我的博客文章。我在这里添加一些有关该代码如何工作的详细信息并解决一些可能的用例。

正如您可能想到的,该代码将标准化浮点值编码为vec4. OpenGL ES 2.0 或 WebGL(在撰写本文时)可能会利用这些打包/解包例程通过RGBA8纹理提供 32 位精度浮点(更多内容请参见规范)。

即使使用 Mikael ( ) 发布的扩展,OES_texture_float也可能有必要(例如出于调试目的)转储完整的 32 位精度标准化浮点,并且如规范中所述,readPixels目前受到以下限制

仅接受格式和类型的两种组合。第一个是 RGBA 格式和 UNSIGNED_BYTE 类型。第二个是实现选择的格式。