Skip to content

Instantly share code, notes, and snippets.

@float3
Last active February 9, 2022 14:17
Show Gist options
  • Select an option

  • Save float3/3bd231ffe66e46f97958c26b42beff39 to your computer and use it in GitHub Desktop.

Select an option

Save float3/3bd231ffe66e46f97958c26b42beff39 to your computer and use it in GitHub Desktop.
2 Bitpacking methods
// Method 1:
// by MerlinVR
// You can convert the uints to full precision floats using asfloat(half3ToUint(input)) and store floats using uintToHalf3(asuint(inputfloat))
// Packing/unpacking routines for saving integers to R16G16B16A16_FLOAT textures
// Heavily based off of https://github.com/apitrace/dxsdk/blob/master/Include/d3dx_dxgiformatconvert.inl
// For some reason the last 2 bits get stomped so we'll only allow uint14 for now :(
float uint14ToFloat(uint input)
{
precise float output = (f16tof32((input & 0x00003fff)));
return output;
}
uint floatToUint14(precise float input)
{
uint output = (f32tof16(input)) & 0x00003fff;
return output;
}
// Encodes a 32 bit uint into 3 half precision floats
float3 uintToHalf3(uint input)
{
precise float3 output = float3(uint14ToFloat(input), uint14ToFloat(input >> 14), uint14ToFloat((input >> 28) & 0x0000000f));
return output;
}
uint half3ToUint(precise float3 input)
{
return floatToUint14(input.x) | (floatToUint14(input.y) << 14) | ((floatToUint14(input.z) & 0x0000000f) << 28);
}
//Method 2:
//Using these 2 functions to bit pack four 8bit variables into a single 32bit variable
uint PackByteQ(uint byte1, uint byte2, uint byte3, uint byte4)
{
return (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
}
uint4 UnpackByteQ(uint byteQ)
{
return uint4(byteQ >> 24, (byteQ >> 16) & 0xff, (byteQ >> 8) & 0xff, (byteQ) & 0xff);
}
//These could be changed to pack and unpack different data widths
//Example using 8bit variables:
struct v2f_example
{
float4 vertex : SV_POSITION;
//... // Any pre-required properties
uint4 byteQx4_1 : TEXCOORD1;
uint4 byteQx4_2 : TEXCOORD2;
//...
// uint4 byteQx4_Nth : TEXCOORDNth;
};
//Inside v2f vert()
//v2f o;
//...
// Pack 16 8bit variables into a 128bit buffer
// Values are set somehow
// uint var1 = 0x11;
// uint var2 = 0x22;
// uint var3 = 0x33;
// uint var4 = 0x44;
// uint var5 = 0x55;
// uint var6 = 0x66;
// uint var7 = 0x77;
// uint var8 = 0x88;
// uint var9 = 0x99;
// uint var10 = 0xaa;
// uint var11 = 0xbb;
// uint var12 = 0xcc;
// uint var13 = 0xdd;
// uint var14 = 0xee;
// uint var15 = 0xff;
// uint var16 = 0x00;
// Values are assumed to be less than 255
// (This could be asserted by masking values with 255)
// eg:
// var1 &= 0xff;
// uint varQ1 = PackByteQ(var1, var2, var3, var4);
// uint varQ2 = PackByteQ(var5, var6, var7, var8);
// uint varQ3 = PackByteQ(var9, var10, var11, var12);
// uint varQ4 = PackByteQ(var13, var14, var15, var16);
// o.byteQx4_1 = uint4(varQ1, varQ2, varQ3, varQ4);
//...
// Inside frag(v2f in)
// ...
// Unpack 16 8bit variables out of a 128bit buffer
// uint4 ByteQ1 = UnpackByteQ(in.byteQx4_1.x);
// uint4 ByteQ2 = UnpackByteQ(in.byteQx4_1.y);
// uint4 ByteQ3 = UnpackByteQ(in.byteQx4_1.y);
// uint4 ByteQ4 = UnpackByteQ(in.byteQx4_1.z);
// uint var1 = ByteQ1.x;
// uint var2 = ByteQ1.y;
// uint var3 = ByteQ1.w;
// uint var4 = ByteQ1.z;
// uint var5 = ByteQ2.x;
// uint var6 = ByteQ2.y;
// uint var7 = ByteQ2.w;
// uint var8 = ByteQ2.z;
// uint var9 = ByteQ3.x;
// uint var10 = ByteQ3.y;
// uint var11 = ByteQ3.w;
// uint var12 = ByteQ3.z;
// uint var13 = ByteQ4.x;
// uint var14 = ByteQ4.y;
// uint var15 = ByteQ4.w;
// uint var16 = ByteQ4.z;
//...
// Here are some functions that can also pack 2 floats into one 32bit variable:
// This packer reduces the mantissa size, affecting percision of smaller numbers (non IEEE-754 standard)
// Can also result in some values of NaN becoming Inf or -Inf
uint PackHalf2(float x, float y)
{
return (asuint(x) & 0xffff0000) | (asuint(y) >> 16);
}
float2 UnpackHalf2(uint pair)
{
return float2(asfloat(pair & 0xffff0000), asfloat(pair << 16));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment