2012-03-27 79 views
19

我正在学习WebGL中的阴影映射。我看到复制在各种库中的同一片着色器代码和实现这一点的示例。然而我没有找到解释它是如何工作的。将float浮动到vec4中 - 此代码如何工作?

想法是将深度值(单个浮点数)保存到颜色缓冲区(vec4)中。有一个包函数可以将float保存到vec4中,并且可以从vec4中解压浮动函数。

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应该是一个很重要的问题,只是把它复制到4个插槽vec4中的一套,让别人使用。这就是为什么上面代码中的位移逻辑令我感到困惑。

任何人都可以点亮一下吗?

回答

12

它没有在GLSL vec4中存储GLSL float。它所做的是将值存储在vec4中,当写入RGBA8帧缓冲区(32位值)时,可以将其读取为vec4,然后重新组合成之前给出的相同float

如果你做了你的建议,只要将浮点值写入帧缓冲区的红色通道,你只能得到8位的精度。使用这种方法,您可以获得所有32位数据。

+0

我明白了。对我来说,即使我们给它一个vec4,颜色缓冲区在内部也不会将颜色值存储为4个整数。如果是这样,那么上面的代码是有道理的。谢谢。 – Jayesh 2012-03-27 04:12:19

+0

严格来说,转换是一个32位的定点数 - 而不是一个浮点数。 – Mortennobel 2012-03-27 08:54:08

3

除了上述的答案,你可能有兴趣在这里所描述的浮点纹理扩展:

http://www.khronos.org/registry/webgl/extensions/OES_texture_float/

注意,有硬件/软件设置了那里有此扩展名不存在/运行,但如果这样做肯定是一个很好的扩展。我的经验是,它也很快。如果您使用此功能,则可以使用其余三个通道来存储其他信息,例如来自投影纹理的颜色。

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类型。第二种是实现选择的格式。

相关问题