unpackHalf2x16
将一个 32 位无符号整数视为由两个 16 位 half 浮点拼接而成,并将其解包为一个 vec2,返回对应的两个 32 位浮点值。
核心优势
与 packHalf2x16 成对使用,可以在缓冲区或纹理中用一个 uint 紧凑存储两路 half 精度浮点数据,在需要使用时再方便地还原为 vec2 浮点。具体的 float16 解包实现由底层 builder 统一处理,避免手写复杂的 bit 操作和跨后端兼容逻辑。
常见用途
在前序 pass 中使用 packHalf2x16 将 roughness + metallic 等参数压缩为 uint,随后在光照或后处理 pass 中用 unpackHalf2x16 还原为 vec2,继续以普通 float 使用。
在 storage buffer / SSBO 中存储大量半精度向量(比如流体速度、噪声参数等)的压缩版本,在 compute 阶段读取时再解包为 vec2。
从自定义贴图或查找表中读取以 half 格式编码的两个标量通道,通过解包获得更高效的带宽利用率。
与其他打包/解包节点混合使用,构建自定义的“压缩 G-Buffer”或特效数据缓冲:某些通道用 float16 half,某些通道用 UNORM、SNORM 等。
如何调整
unpackHalf2x16 本身没有可调参数,关键在于保证输入的 uint 与 packHalf2x16 使用的是同一种 float16 布局:1)通常应与 packHalf2x16 成对使用,确保打包与解包编码方式一致;2)输入必须是有效的 half2x16 编码数据,如果传入的是其他编码方式(如 UNORM 等),解包结果会失真;3)half 精度存在量化误差和动态范围限制,解包后得到的是近似值,适合对精度不敏感或已归一化/缩放的数据;4)在管线设计时,建议明确约定某个 uint 通道是“half2”语义,以避免与其他 bit 打包格式混用导致的调试困难。
代码示例
1// 前序 pass 中:将两个 float 参数打包为一个 uint(示意)
2const rm = vec2( roughnessNode, metalnessNode );
3const packedRM = packHalf2x16( rm );
4
5// 当前 pass 中:从某个 uint 源(缓冲或纹理)读取并解包
6const loadedPackedRM = packedRM; // 这里示意为同一节点,实际可来自 texture/buffer
7
8// 解包回 vec2,近似恢复原始浮点值
9const decodedRM = unpackHalf2x16( loadedPackedRM );
10
11// 分别取回 roughness 与 metalness
12const decodedRoughness = decodedRM.x;
13const decodedMetalness = decodedRM.y;
14
15material.roughnessNode = decodedRoughness;
16material.metalnessNode = decodedMetalness;