Skip to content

Instantly share code, notes, and snippets.

@rygorous
Created July 7, 2023 03:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rygorous/897185a1e8cee7c1b252ac50e5a92b31 to your computer and use it in GitHub Desktop.
Save rygorous/897185a1e8cee7c1b252ac50e5a92b31 to your computer and use it in GitHub Desktop.
BC7 encoding for single-color blocks
void bc7_encode_single_color_block(U8 * output_bc7, const U8 rgba[4])
{
U64 r = rgba[0];
U64 g = rgba[1];
U64 b = rgba[2];
U64 a = rgba[3];
const U64 bit6_mask = (0x40 << 8) | (0x40 << 22) | (0x40ull << 36);
const U64 lo7_mask = (0x7f << 8) | (0x7f << 22) | (0x7full << 36);
U64 color_bits;
// Color channels (see bc7solid/main.cpp)
// this is the bit-hack version written to process 3 color chans at once
color_bits = (r << 8) | (g << 22) | (b << 36);
// The basic idea here is this: for every color channel, we get the right
// results with
// e0 = val >> 1
// e1 = (val + (val < 128 ? 1 : -1)) >> 1
// the bias in the e1 computation
// (val < 128 ? 1 : -1)
// can be written as
// 1 - ((val >> 6) & 2)
// and the rest is just bit fiddling and accounting for the layout of mode 5.
U64 t = color_bits << 6;
color_bits = ((color_bits >> 1) & lo7_mask) - (color_bits & ~lo7_mask);
color_bits += t + (t & bit6_mask);
// alpha: just set endpoint 0 to target value then use all-0 inds
color_bits |= a << 50;
// insert mode bits
color_bits |= 0x20; // mode 5, rotation=0
RR_PUT64_LE_UNALIGNED(output_bc7 + 0, color_bits); // this covers 64 out of the 66 mode/color bits
RR_PUT64_LE_UNALIGNED(output_bc7 + 8, 0xaaaaaaac); // last 2 color bits, color index bits, alpha index bits
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment