medfall

A super great game engine
Log | Files | Refs

commit bf2264e5a5f916e0cf3880dfb475890a377e10dd
parent c1f80da0f6691535129dd5d7dca561a29f250493
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Fri,  3 Nov 2017 00:06:27 +0200

Not yet functional BC5 decoder

Diffstat:
unpack_bc5.cc | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 112 insertions(+), 0 deletions(-)

diff --git a/unpack_bc5.cc b/unpack_bc5.cc @@ -0,0 +1,112 @@ +#include "intrinsics.h" +#include "array.h" + +#define STB_DXT_IMPLEMENTATION +#include "stb_dxt.h" + +struct AlphaBlock { + union { + u64 block; + struct { + u8 endpoints[ 2 ]; + u8 selectors[ 6 ]; + }; + }; +}; + +struct RG8 { + u8 r, g; +}; + +static void get_values0( u8 * values, u8 e0, u8 e1 ) { + values[ 0 ] = e0; + values[ 1 ] = e1; + values[ 2 ] = ( e0 * 6 + e1 ) / 7; + values[ 3 ] = ( e0 * 5 + e1 * 2 ) / 7; + values[ 4 ] = ( e0 * 4 + e1 * 3 ) / 7; + values[ 5 ] = ( e0 * 3 + e1 * 4 ) / 7; + values[ 6 ] = ( e0 * 2 + e1 * 5 ) / 7; + values[ 7 ] = ( e0 + e1 * 6 ) / 7; +} + +static void get_values1( u8 * values, u8 e0, u8 e1 ) { + values[ 0 ] = e0; + values[ 1 ] = e1; + values[ 2 ] = ( e0 * 4 + e1 ) / 5; + values[ 3 ] = ( e0 * 3 + e1 * 2 ) / 5; + values[ 4 ] = ( e0 * 2 + e1 * 3 ) / 5; + values[ 5 ] = ( e0 + e1 * 4 ) / 5; + values[ 6 ] = 0; + values[ 7 ] = 255; +} + +template< typename T, typename Comp > +static void decompress_alpha_block( array2d< T > img, Comp comp, size_t img_x, size_t img_y, const AlphaBlock * block ) { + u8 values[ 8 ]; + if( block->endpoints[ 0 ] > block->endpoints[ 1 ] ) { + get_values0( values, block->endpoints[ 0 ], block->endpoints[ 1 ] ); + } + else { + get_values1( values, block->endpoints[ 0 ], block->endpoints[ 1 ] ); + } + + for( u32 y = 0; y < 4; y++ ) { + for( u32 x = 0; x < 4; x++ ) { + u32 selector_bit = 3 * ( y * 4 + x ); + u64 selector = ( block->block >> ( 16 + selector_bit ) ) & 7; + + comp( img( img_x + x, img_y + y ) ) = values[ selector ]; + } + } +} + +static u8 & R( RG8 & rg ) { + return rg.r; +} + +static u8 & G( RG8 & rg ) { + return rg.g; +} + +void decompress_bc5( array2d< RG8 > img, const u8 * bc5 ) { + const AlphaBlock * blocks = ( const AlphaBlock * ) bc5; + + size_t i = 0; + for( size_t y = 0; y < img.h; y += 4 ) { + for( size_t x = 0; x < img.w; x += 4 ) { + decompress_alpha_block( img, R, x, y, &blocks[ i ] ); + i++; + decompress_alpha_block( img, G, x, y, &blocks[ i ] ); + i++; + } + } +} + +int main() { + u8 img[ 32 ]; + for( int i = 0; i < 32; i += 2 ) { + img[ i ] = i / 2; + img[ i + 1 ] = ( 32 - i ) / 2; + } + + for( int i = 0; i < 32; i++ ) { + printf( "%2hhu ", img[ i ] ); + if( i % 8 == 7 ) printf( "\n" ); + } + printf( "\n" ); + + u64 bc5; + stb_compress_bc5_block( ( u8 * ) &bc5, img ); + + u8 D[ 32 ]; + array2d< RG8 > d( ( RG8 * ) D, 4, 4 ); + + decompress_bc5( d, ( const u8 * ) &bc5 ); + + for( int i = 0; i < 32; i++ ) { + printf( "%2hhu ", D[ i ] ); + if( i % 8 == 7 ) printf( "\n" ); + } + + return 0; +}