unpackSnorm2x16
unpackSnorm2x16 decodes a packed 32-bit unsigned integer into a vec2 of floating-point values in the range [-1, 1]. It uses the same signed normalized (snorm) scheme as packSnorm2x16 and effectively performs the inverse operation.
Core Advantages
It provides a shader-side equivalent of the GPU's built-in unpackSnorm2x16, allowing you to reconstruct normalized vectors from a compact uint representation. This lets you store two directional or vector components in a single uint in buffers or textures and only expand them when needed on the GPU, saving bandwidth while maintaining predictable precision.
Common Uses
Reading snorm2x16-packed normal XY components from a G-buffer or storage buffer and reconstructing a normalized vec2 (and then a full normal) for lighting.
Decoding snorm2x16-encoded 2D velocity, offset, or direction data for motion blur, flow fields, parallax offsets, and similar effects.
Pairing with packSnorm2x16 to design custom compact data formats where the CPU or a previous pass writes packed uint values and the current shader unpacks them for shading or particle simulations.
How to adjust
The node itself has no adjustable parameters; its behavior depends entirely on the input uint being encoded with the snorm2x16 scheme (typically via packSnorm2x16 or an equivalent GPU-side encoder). If the input is not valid snorm2x16 data, the decoded result will be undefined. In practice, ensure that (1) the written value really comes from packSnorm2x16; (2) if you applied any extra scaling or bias before packing, you apply the inverse transform to the decoded vec2; and (3) you are aware that each component is quantized to 16 bits, so the reconstructed values are approximate and will show discrete steps, which is usually acceptable for normals or velocity data. Treating unpackSnorm2x16 and packSnorm2x16 as a matched pair when designing your data layout is the safest way to avoid errors.
Code Examples
1// 1. Read a packed normal (snorm2x16) from a vertex attribute
2const packedNormal = attribute( 'packedNormal', 'uint' );
3
4// 2. Unpack into a vec2 in the range [-1, 1]
5const normalXY = unpackSnorm2x16( packedNormal ); // vec2
6
7// 3. Assuming the original was unit length, reconstruct the Z component
8const n2 = clamp( dot( normalXY, normalXY ), 0.0, 1.0 );
9const normalTS = vec3( normalXY, sqrt( 1.0 - n2 ) );
10
11meshStandardNodeMaterial( {
12 normalNode: normalTS
13} );