unpackSnorm2x16
unpackSnorm2x16 用于把一个打包好的 32 位无符号整数 (uint) 解码成 [-1, 1] 范围的二维浮点向量 (vec2)。它与 packSnorm2x16 使用相同的有符号标准化 (snorm) 编码规则,是 packSnorm2x16 的反向操作。
核心优势
提供与 GPU 内置 unpackSnorm2x16 等价的解码操作,可以在着色器中从紧凑的 uint 表示恢复出原始的归一化向量。这样可以在缓冲区或纹理中用一个 uint 存储两个方向/向量分量,在需要使用时再在 GPU 上即时解包,兼顾带宽与精度。
常见用途
从 G-Buffer 或存储缓冲中读取用 packSnorm2x16 压缩过的法线 XY 分量,在线恢复为 [-1, 1] 的 vec2 并重建完整法线。
解码以 snorm2x16 方式存储的 2D 速度、偏移或方向数据,用于后续运动模糊、流体方向、视差偏移等效果。
配合 packSnorm2x16 设计自定义的紧凑数据格式,在 CPU 写入打包后的 uint,GPU 端用 unpackSnorm2x16 解包并参与光照或粒子等计算。
如何调整
unpackSnorm2x16 自身没有可调参数,它依赖输入的 uint 是按照 snorm2x16 规则编码得到的(通常由 packSnorm2x16 或 GPU 侧等价编码产生)。若输入并非合法的 snorm2x16 数据,解码结果会不可预期。使用时要保证:1)CPU 或前一阶段着色器写入的值确实是 packSnorm2x16 得到的结果;2)如果你在 pack 阶段做了任何额外的缩放或偏移,解包后需要对 vec2 进行对应的逆变换;3)由于每个分量只有 16 位精度,解包后的值是量化过的近似值,连续变化会呈现有限阶梯,这在法线、速度这类数据上通常可以接受。通常将 unpackSnorm2x16 视为 packSnorm2x16 的一对操作同时设计,会最安全、最不易出错。
代码示例
1// 1. 从顶点属性中读取打包过的法线(snorm2x16)
2const packedNormal = attribute( 'packedNormal', 'uint' );
3
4// 2. 解包为 [-1, 1] 范围的 XY 分量
5const normalXY = unpackSnorm2x16( packedNormal ); // vec2
6
7// 3. 假设原始是单位向量,用 XY 重建 Z 分量
8const n2 = clamp( dot( normalXY, normalXY ), 0.0, 1.0 );
9const normalTS = vec3( normalXY, sqrt( 1.0 - n2 ) );
10
11meshStandardNodeMaterial( {
12 normalNode: normalTS
13} );