WebGl将一个浮动包装到v4中

时间:2015-12-28 08:57:21

标签: opengl-es three.js webgl

我有来自threejs示例[http://threejs.org/examples/#webgl_animation_cloth]的代码示例,其中浮点值转换为vec4。我在其他几个论坛上看到了这个逻辑,但没有解释。

  1. 有人可以解释这个逻辑在做什么以及使用256吗?我理解按位屏蔽和移位。
  2. 我也见过这个链接Packing float into vec4 - how does this code work?

    1. 它说vec4最终将存储在32位RGBA8缓冲区中 由于我们将深度值传递给颜色缓冲区,opengl将如何知道如何处理?

    2. 此外,由于vec4有4个组件,每个4个字节使其为16个字节,使其为16 * 8位,这如何适合32位RGBA8?

           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;
             }
      
          void main() {
              vec4 pixel = texture2D( texture, vUV );
              if ( pixel.a < 0.5 ) discard;
              gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );
          }
      

2 个答案:

答案 0 :(得分:2)

除了@ WaclawJasper的答案之外,这段代码将浮点值(32位)打包成4个8位值。

gl_FragData[ 0 ]在纹理中呈现单个像素,在这种情况下是每个通道8位(总共32位)的纹理。如果我写

gl_FragData[0] = vec4(0.25, 0.5, 0.75, 1.0);

正在写入的纹理(假设它是一个8位纹理)实际上会得到值

r = Math.floor(0.25 * 255) = 63;
g = Math.floor(0.5  * 255) = 127;
b = Math.floor(0.75 * 255) = 191;
a = Math.floor(1.0  * 255) = 255;

规范中的实际公式实际上是

unsignedIntValue = floor(clamp(floatValue, 0., 1.) * (pow(2., numberOfBits) - 1.));

因此即使pack_depth返回一个vec4,它是浮点数,gl_FragData被定义为vec4,它最终会在写入当前正在写入的WebGL时被转换(画布,a renderbuffer,纹理)。

如果写入浮点纹理pack_depth则不必要。由于pack_depth正在做什么,我们可以推断它是否写入8位RGBA纹理。

为什么这需要呢?因为在WebGL中支持浮点纹理是可选的。因此,如果用户的机器不支持浮点纹理,并且您需要浮点数据(如阴影贴图的深度缓冲区),那么将数据打包成8位纹理就是一种解决方案。

答案 1 :(得分:1)

  1. 256是8位数据可以表示的不同值的数量。让我们停止二进制工作一秒钟,然后使用熟悉的十进制数。如果我们有2个频道,每个频道只能存储1个数字(0-9),我们如何打包45个?显然,我们将5个打包成一个数字,将40/10或4打包成另一个数字。然后在我们的解包函数中我们反过来:4 * 10 + 5 = 45. 256与我们的十进制示例中的10类似。

  2. Opengl没有,但你自己的应用程序代码可以理解它。

  3. 我不确定我是否正确理解这部分内容。但是你所显示的代码是将一个浮点数打包成8 * 4位RGBA。