medfall

A super great game engine
Log | Files | Refs

unpack_bc5.cc (2457B)


      1 #include "intrinsics.h"
      2 #include "array.h"
      3 
      4 #define STB_DXT_IMPLEMENTATION
      5 #include "stb_dxt.h"
      6 
      7 struct AlphaBlock {
      8 	union {
      9 		u64 block;
     10 		struct {
     11 			u8 endpoints[ 2 ];
     12 			u8 selectors[ 6 ];
     13 		};
     14 	};
     15 };
     16 
     17 struct RG8 {
     18 	u8 r, g;
     19 };
     20 
     21 static void get_values0( u8 * values, u8 e0, u8 e1 ) {
     22 	values[ 0 ] = e0;
     23 	values[ 1 ] = e1;
     24 	values[ 2 ] = ( e0 * 6 + e1     ) / 7;
     25 	values[ 3 ] = ( e0 * 5 + e1 * 2 ) / 7;
     26 	values[ 4 ] = ( e0 * 4 + e1 * 3 ) / 7;
     27 	values[ 5 ] = ( e0 * 3 + e1 * 4 ) / 7;
     28 	values[ 6 ] = ( e0 * 2 + e1 * 5 ) / 7;
     29 	values[ 7 ] = ( e0     + e1 * 6 ) / 7;
     30 }
     31 
     32 static void get_values1( u8 * values, u8 e0, u8 e1 ) {
     33 	values[ 0 ] = e0;
     34 	values[ 1 ] = e1;
     35 	values[ 2 ] = ( e0 * 4 + e1     ) / 5;
     36 	values[ 3 ] = ( e0 * 3 + e1 * 2 ) / 5;
     37 	values[ 4 ] = ( e0 * 2 + e1 * 3 ) / 5;
     38 	values[ 5 ] = ( e0     + e1 * 4 ) / 5;
     39 	values[ 6 ] = 0;
     40 	values[ 7 ] = 255;
     41 }
     42 
     43 template< typename T, typename Comp >
     44 static void decompress_alpha_block( array2d< T > img, Comp comp, size_t img_x, size_t img_y, const AlphaBlock * block ) {
     45 	u8 values[ 8 ];
     46 	if( block->endpoints[ 0 ] > block->endpoints[ 1 ] ) {
     47 		get_values0( values, block->endpoints[ 0 ], block->endpoints[ 1 ] );
     48 	}
     49 	else {
     50 		get_values1( values, block->endpoints[ 0 ], block->endpoints[ 1 ] );
     51 	}
     52 
     53 	for( u32 y = 0; y < 4; y++ ) {
     54 		for( u32 x = 0; x < 4; x++ ) {
     55 			u32 selector_bit = 3 * ( y * 4 + x );
     56 			u64 selector = ( block->block >> ( 16 + selector_bit ) ) & 7;
     57 
     58 			comp( img( img_x + x, img_y + y ) ) = values[ selector ];
     59 		}
     60 	}
     61 }
     62 
     63 static u8 & R( RG8 & rg ) {
     64 	return rg.r;
     65 }
     66 
     67 static u8 & G( RG8 & rg ) {
     68 	return rg.g;
     69 }
     70 
     71 void decompress_bc5( array2d< RG8 > img, const u8 * bc5 ) {
     72 	const AlphaBlock * blocks = ( const AlphaBlock * ) bc5;
     73 
     74 	size_t i = 0;
     75 	for( size_t y = 0; y < img.h; y += 4 ) {
     76 		for( size_t x = 0; x < img.w; x += 4 ) {
     77 			decompress_alpha_block( img, R, x, y, &blocks[ i ] );
     78 			i++;
     79 			decompress_alpha_block( img, G, x, y, &blocks[ i ] );
     80 			i++;
     81 		}
     82 	}
     83 }
     84 
     85 int main() {
     86 	u8 img[ 32 ];
     87 	for( int i = 0; i < 32; i += 2 ) {
     88 		img[ i ] = i / 2;
     89 		img[ i + 1 ] = ( 32 - i ) / 2;
     90 	}
     91 
     92 	for( int i = 0; i < 32; i++ ) {
     93 		printf( "%2hhu ", img[ i ] );
     94 		if( i % 8 == 7 ) printf( "\n" );
     95 	}
     96 	printf( "\n" );
     97 
     98 	u64 bc5;
     99 	stb_compress_bc5_block( ( u8 * ) &bc5, img );
    100 
    101 	u8 D[ 32 ];
    102 	array2d< RG8 > d( ( RG8 * ) D, 4, 4 );
    103 
    104 	decompress_bc5( d, ( const u8 * ) &bc5 );
    105 
    106 	for( int i = 0; i < 32; i++ ) {
    107 		printf( "%2hhu ", D[ i ] );
    108 		if( i % 8 == 7 ) printf( "\n" );
    109 	}
    110 
    111 	return 0;
    112 }