【问题标题】:WebGl packing a float into v4WebGl 将浮点数打包到 v4 中
【发布时间】:2015-12-29 14:11:27
【问题描述】:

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

  1. 有人能解释一下这个逻辑在做什么以及 256 的用途吗?我了解按位掩码和移位。

我也看过这个链接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 );
        }
    

【问题讨论】:

    标签: opengl-es three.js webgl


    【解决方案1】:

    连同@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 当前写入的内容(画布、渲染缓冲区、纹理)时被转换。

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

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

    【讨论】:

    • 事情对我来说变得更清楚了。感谢您的详细回答。
    【解决方案2】:
    1. 256 是 8 位数据可以表示的不同值的数量。让我们暂时停止以二进制工作,并以熟悉的十进制工作。如果我们有 2 个通道,每个通道只能存储 1 个数字(0-9),我们如何打包 45 之类的东西?显然,我们将 5 打包成一个数字,将 40/10 或 4 打包成另一个数字。然后在我们的解包函数中,我们只是做相反的事情:4*10 + 5 = 45。256 类似于我们十进制示例中的 10。

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

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

    【讨论】:

    • 关于我的问题 3,我的理解是 vec4 有 4 个组件:例如。 (1.4, 4.6, 3.8, 44.6)。由于每个组件都是一个 float ,因此每个组件占用 4 个字节。由于有 4 个组件,vec 4 总共需要 4 * 4 = 16 个字节。这达到 16 * 8 = 128 位。但既然 RGBA 是 32 位空间,那么 128 位如何适应 32 位空间呢? .我确信我的理解在这里的某个地方根本是错误的。请耐心等待,因为我是图形新手
    • 你不适合 128 位到 32 位。您正在将 >one
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    • 2016-02-15
    相关资源
    最近更新 更多