medfall

A super great game engine
Log | Files | Refs

commit e878ae9c8dbe6ab0ba45c2c44cbc18d272991ead
parent e71b8e1b60965f0805bc71e9279014823a52ff32
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Sat,  4 Nov 2017 15:38:31 +0200

Clean up BC5 decoder

Diffstat:
decompress_bc.cc | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
decompress_bc.h | 7+++++++
unpack_bc5.cc | 112-------------------------------------------------------------------------------
3 files changed, 79 insertions(+), 112 deletions(-)

diff --git a/decompress_bc.cc b/decompress_bc.cc @@ -0,0 +1,72 @@ +#include "intrinsics.h" +#include "linear_algebra.h" +#include "array.h" + +struct AlphaBlock { + union { + u64 block; + struct { + u8 endpoints[ 2 ]; + u8 selectors[ 6 ]; + }; + }; +}; + +static void get_values( float ( &values )[ 8 ], u8 e0, u8 e1 ) { + values[ 0 ] = e0 / 255.0f; + values[ 1 ] = e1 / 255.0f; + + if( e0 > e1 ) { + values[ 2 ] = ( values[ 0 ] * 6 + values[ 1 ] * 1 ) / 7; + values[ 3 ] = ( values[ 0 ] * 5 + values[ 1 ] * 2 ) / 7; + values[ 4 ] = ( values[ 0 ] * 4 + values[ 1 ] * 3 ) / 7; + values[ 5 ] = ( values[ 0 ] * 3 + values[ 1 ] * 4 ) / 7; + values[ 6 ] = ( values[ 0 ] * 2 + values[ 1 ] * 5 ) / 7; + values[ 7 ] = ( values[ 0 ] * 1 + values[ 1 ] * 6 ) / 7; + } + else { + values[ 2 ] = ( values[ 0 ] * 4 + values[ 1 ] * 1 ) / 5; + values[ 3 ] = ( values[ 0 ] * 3 + values[ 1 ] * 2 ) / 5; + values[ 4 ] = ( values[ 0 ] * 2 + values[ 1 ] * 3 ) / 5; + values[ 5 ] = ( values[ 0 ] * 1 + values[ 1 ] * 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 ) { + float values[ 8 ]; + get_values( 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 float & R( v2 & rg ) { + return rg.x; +} + +static float & G( v2 & rg ) { + return rg.y; +} + +void decompress_bc5( array2d< v2 > 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++; + } + } +} diff --git a/decompress_bc.h b/decompress_bc.h @@ -0,0 +1,7 @@ +#pragma once + +#include "intrinsics.h" +#include "linear_algebra.h" +#include "array.h" + +void decompress_bc5( array2d< v2 > img, const u8 * bc5 ); diff --git a/unpack_bc5.cc b/unpack_bc5.cc @@ -1,112 +0,0 @@ -#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; -}