packSnorm2x16
packSnorm2x16
将一个 [-1, 1] 范围的二维浮点向量 (vec2) 压缩为单个无符号整数 (uint) 的节点。它会把每个分量按有符号标准化 (snorm) 规则转换为 16 位整数,并打包到 32 位整型中,方便在 GPU 上以更紧凑的格式存储方向或向量数据。
核心优势
以与 GPU 内置 packSnorm2x16 相同的编码方式,将两个浮点分量压缩到一个 uint 中,相比直接存储两个 32 位 float 可显著节省带宽与存储,同时保持跨 WebGL / WebGPU 后端一致、可预测的解码结果,非常适合 G-Buffer、顶点属性或 Storage Buffer 中的紧凑数据布局。
常见用途
将切线空间法线的 x,y 分量打包为一个 uint,用于法线贴图或延迟渲染的 G-Buffer。
将二维速度、偏移或方向等 [-1, 1] 范围的数据压缩后写入 Storage Buffer 或数据纹理,以降低内存占用。
与整数类型 (uint / uvec2 等) 组合,设计自定义的紧凑数据结构和 bit 打包格式,用于高级 GPGPU 算法。
如何调整
packSnorm2x16 本身没有可调参数,其行为完全由输入 vec2 决定。使用时应确保每个分量已经归一化到 [-1, 1],否则会被 clamp 到该范围;可以在前面显式调用 normalize 或 clamp 以保证数值合法。编码过程中每个分量会被量化为 16 位有符号整数,细节将以约 1/32767 的步长被离散化:越接近 1 或 -1,量化误差越明显。若需要更大的动态范围或更高精度,可以改用其他编码方式(例如 float16 或 unorm 打包),但在读回时必须使用匹配的解码方式以避免失真。
代码示例
1// 将视图空间法线的 x,y(范围 [-1, 1])压缩到一个 uint
2const n = normalize( normalView );
3const packedNormalXY = packSnorm2x16( n.xy );
4
5// 例如在计算着色器中,将打包结果写入无符号缓冲区
6normalBuffer.element( index ).assign( packedNormalXY );