medfall

A super great game engine
Log | Files | Refs

commit 2438ada52281c22148e0238bdf889de2146db01f
parent b5179b74e503175277c05b18c4ca1a79f167d186
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Tue Jul  4 21:45:56 +0300

Store horizon maps as 8bit PNG. 34MB to 1.8MB

Diffstat:
gpubtt.cc | 5+++--
gpubtt.h | 2+-
libs/lodepng.lua | 4++--
make.lua | 2+-
pp.cc | 45+++++++++++++++++++++++++++++++++++++++++----
terrain_manager.cc | 24+++++++++++++-----------
terrain_manager.h | 4++--
7 files changed, 63 insertions(+), 23 deletions(-)
diff --git a/gpubtt.cc b/gpubtt.cc @@ -38,7 +38,7 @@ static void gpubtt_build( void gpubtt_init( MemoryArena * arena, GPUBTT * gpubtt, BTTs btts, - const OffsetHeightmap * ohm, const v3 * normals, const float * horizons + const OffsetHeightmap * ohm, const v3 * normals, const u8 * horizons ) { PROFILE_FUNCTION(); @@ -79,8 +79,9 @@ void gpubtt_init( TextureConfig horizons_config; horizons_config.width = ohm->hm.width; horizons_config.height = ohm->hm.height; - horizons_config.format = TEXFMT_R_FLOAT; + horizons_config.format = TEXFMT_R_U8; horizons_config.data = horizons; + horizons_config.wrap = TEXWRAP_CLAMP; // TODO: this is a hack and should be removed gpubtt->horizon_map = renderer_new_texture( horizons_config ); } diff --git a/gpubtt.h b/gpubtt.h @@ -12,6 +12,6 @@ struct GPUBTT { }; void gpubtt_init( MemoryArena * arena, GPUBTT * gpubtt, BTTs btts, - const OffsetHeightmap * ohm, const v3 * normals, const float * horizons ); + const OffsetHeightmap * ohm, const v3 * normals, const u8 * horizons ); void gpubtt_destroy( GPUBTT * gpubtt ); void gpubtt_render( const GPUBTT * gpubtt, RenderState render_state ); diff --git a/libs/lodepng.lua b/libs/lodepng.lua @@ -1,3 +1,3 @@ lib( "lodepng", { "libs/lodepng/lodepng" } ) -msvc_obj_cxxflags( "libs/lodepng/lodepng", "/O2 /g0 /DLODEPNG_NO_COMPILE_CPP /DLODEPNG_NO_COMPILE_ENCODER" ) -gcc_obj_cxxflags( "libs/lodepng/lodepng", "-O3 -g0 -DLODEPNG_NO_COMPILE_CPP -DLODEPNG_NO_COMPILE_ENCODER" ) +msvc_obj_cxxflags( "libs/lodepng/lodepng", "/O2 /g0 /DLODEPNG_NO_COMPILE_CPP" ) +gcc_obj_cxxflags( "libs/lodepng/lodepng", "-O3 -g0 -DLODEPNG_NO_COMPILE_CPP" ) diff --git a/make.lua b/make.lua @@ -18,7 +18,7 @@ if OS == "macos" then game_ldflags = "-framework Cocoa -framework CoreVideo -framework IOKit" end -bin( "medfall", { "main", "hm", "heightmap", "terrain_manager", "btt", "gpubtt", "skybox", "http", game_objs }, { "lz4", game_libs } ) +bin( "medfall", { "main", "hm", "heightmap", "terrain_manager", "btt", "gpubtt", "skybox", "http", game_objs }, { "lodepng", "lz4", game_libs } ) msvc_bin_ldflags( "medfall", "opengl32.lib gdi32.lib Ws2_32.lib" ) gcc_bin_ldflags( "medfall", game_ldflags ) diff --git a/pp.cc b/pp.cc @@ -5,6 +5,7 @@ #include <string> #include "intrinsics.h" +#include "int_conversions.h" #include "memory_arena.h" #include "array.h" #include "str.h" @@ -16,7 +17,6 @@ #include "rng/well512.h" #define LODEPNG_NO_COMPILE_CPP -#define LODEPNG_NO_COMPILE_ENCODER #include "libs/lodepng/lodepng.h" #include "libs/lz4/lz4.h" @@ -181,7 +181,7 @@ static void write_compressed_file( MemoryArena * arena, const void * data, size_ size_t compressed_len = LZ4_compress_HC( ( const char * ) data, compressed, len, LZ4_compressBound( len ), COMPRESSION_LEVEL ); - ggprint( "{}: compressed {} to {} ({.2}%)\n", path, len, compressed_len, 100.0f * compressed_len / len ); + ggprint( "compressed {} to {} ({.2}%)\n", len, compressed_len, 100.0f * compressed_len / len ); // write FILE * file = fopen( path.c_str(), "wb" ); @@ -192,6 +192,28 @@ static void write_compressed_file( MemoryArena * arena, const void * data, size_ } template< typename T > +static array2d< T > get_tile( + MemoryArena * arena, const array2d< T > data, T border, + int tx, int ty +) { + array2d< T > tile = memarena_push_array2d( arena, T, OUT_SIZE, OUT_SIZE ); + + const u32 left = tx * TILE_SIZE; + const u32 top = ty * TILE_SIZE; + + for( int local_y = 0; local_y < OUT_SIZE; local_y++ ) { + for( int local_x = 0; local_x < OUT_SIZE; local_x++ ) { + int global_x = left + local_x; + int global_y = top + local_y; + + tile( local_x, local_y ) = data.try_get( global_x, global_y, border ); + } + } + + return tile; +} + +template< typename T > static void write_tile( MemoryArena * arena, const std::string & dir, const std::string & extension, const array2d< T > data, T border, int tx, int ty @@ -346,8 +368,23 @@ int main( int argc, char ** argv ) { for( int ty = 0; ty < ytiles; ty++ ) { for( int tx = 0; tx < xtiles; tx++ ) { - // write_horizons( &arena, dir, horizons, tx, ty ); - write_tile( &arena, dir, "_horizons.lz4", horizons, 0.0f, tx, ty ); + array2d< float > tile = get_tile( &arena, horizons, 0.0f, tx, ty ); + // align4 is because opengl insists texture rows are aligned to 4 bytes + array2d< u8 > png = memarena_push_array2d( &arena, u8, align4( OUT_SIZE ), OUT_SIZE ); + memset( png.ptr(), 0, png.num_bytes() ); + + for( size_t y = 0; y < tile.h; y++ ) { + for( size_t x = 0; x < tile.w; x++ ) { + float theta01 = atanf( tile( x, y ) ) * 2.0f / float( M_PI ); + u8 q = checked_cast< u8 >( quantize01( theta01, 8 ) ); + png( x, y ) = q; + } + } + + const str< 256 > png_path( "{}/{}_{}_horizons.png", dir.c_str(), tx, ty ); + ggprint( "writing {}_{}_horizons.png...\n", tx, ty ); + unsigned encode_ok = lodepng_encode_file( png_path.c_str(), ( const u8 * ) png.ptr(), png.w, png.h, LCT_GREY, 8 ); + ASSERT( encode_ok == 0 ); } } } diff --git a/terrain_manager.cc b/terrain_manager.cc @@ -16,6 +16,8 @@ #include "renderer.h" #include "shaders.h" +#include "libs/lodepng/lodepng.h" + #include "libs/lz4/lz4.h" struct AsyncLoadTile { @@ -97,15 +99,15 @@ static WORK_QUEUE_CALLBACK( async_load_tile ) { dt.normalmap = decompressed_normalmap; // horizonmap - // size_t decompressed_horizonmap_size = squish::GetStorageRequirements( TILE_SIZE + 1, TILE_SIZE + 1, squish::kBc4 ); - size_t decompressed_horizonmap_size = num_points * sizeof( float ); - float * decompressed_horizonmap = ( float * ) malloc( decompressed_horizonmap_size ); - ASSERT( decompressed_horizonmap != NULL ); - int ok_horizonmap = LZ4_decompress_safe( - ct.horizonmap.ptr(), - ( char * ) decompressed_horizonmap, - ct.horizonmap.num_bytes(), decompressed_horizonmap_size ); - ASSERT( ok_horizonmap > 0 ); + u8 * decompressed_horizonmap; + size_t decompressed_horizonmap_size = align4( TILE_SIZE + 1 ) * ( TILE_SIZE + 1 ) * sizeof( u8 ); + { + u32 w, h; + unsigned ok_horizonmap = lodepng_decode_memory( &decompressed_horizonmap, &w, &h, + ct.horizonmap.ptr(), ct.horizonmap.n, LCT_GREY, 8 ); + ASSERT( ok_horizonmap == 0 ); + ASSERT( decompressed_horizonmap != NULL ); + } // quadtree size_t max_decompressed_quadtree_size = heightmap_quadtree_max_nodes( &dt.heightmap ) * sizeof( HeightmapQuadTreeNode ); @@ -200,13 +202,13 @@ void terrain_init( for( u32 tx = 0; tx < tm->width / TILE_SIZE; tx++ ) { str< 512 > heightmap_path( "{}/{}_{}_heightmap.lz4", tiles_dir, tx, ty ); str< 512 > normalmap_path( "{}/{}_{}_normals.lz4", tiles_dir, tx, ty ); - str< 512 > horizonmap_path( "{}/{}_{}_horizons.lz4", tiles_dir, tx, ty ); + str< 512 > horizonmap_path( "{}/{}_{}_horizons.png", tiles_dir, tx, ty ); str< 512 > quadtree_path( "{}/{}_{}_quadtree.lz4", tiles_dir, tx, ty ); CompressedTile & ct = tm->compressed_tiles[ tx ][ ty ]; ct.heightmap = file_get_array< char >( heightmap_path.c_str() ); ct.normalmap = file_get_array< char >( normalmap_path.c_str() ); - ct.horizonmap = file_get_array< char >( horizonmap_path.c_str() ); + ct.horizonmap = file_get_array< u8 >( horizonmap_path.c_str() ); ct.quadtree = file_get_array< char >( quadtree_path.c_str() ); tm->tile_states[ tx ][ ty ] = TILE_EMPTY; diff --git a/terrain_manager.h b/terrain_manager.h @@ -18,14 +18,14 @@ static const u16 VIEW_HALF = VIEW_SIZE / 2; struct CompressedTile { array< char > heightmap; array< char > normalmap; - array< char > horizonmap; + array< u8 > horizonmap; array< char > quadtree; }; struct GPUTileData { BTTs btt; void * btt_memory; - float * horizonmap; + u8 * horizonmap; size_t horizonmap_size; };