medfall

A super great game engine
Log | Files | Refs

gpubtt.cc (3196B)


      1 #include "intrinsics.h"
      2 #include "memory_arena.h"
      3 #include "btt.h"
      4 #include "heightmap.h"
      5 #include "gpubtt.h"
      6 #include "linear_algebra.h"
      7 #include "profiler.h"
      8 
      9 static u32 btt_count_leaves( const BTT * btt ) {
     10 	if( btt->left ) {
     11 		ASSERT( btt->right != NULL );
     12 		return btt_count_leaves( btt->left ) + btt_count_leaves( btt->right );
     13 	}
     14 
     15 	return 1;
     16 }
     17 
     18 static void gpubtt_build(
     19 	v3 * verts, u32 * i, const array2d< u16 > hm, v3 offset,
     20 	const BTT * btt, v2s32 p0, v2s32 p1, v2s32 p2
     21 ) {
     22 	if( btt->left != NULL ) {
     23 		v2s32 mid = ( p0 + p2 ) / 2;
     24 
     25 		gpubtt_build( verts, i, hm, offset, btt->left, p1, mid, p0 );
     26 		ASSERT( btt->right != NULL );
     27 		gpubtt_build( verts, i, hm, offset, btt->right, p2, mid, p1 );
     28 	}
     29 	else {
     30 		verts[ *i + 0 ] = heightmap_point( hm, p0.x, p0.y ) + offset;
     31 		verts[ *i + 1 ] = heightmap_point( hm, p1.x, p1.y ) + offset;
     32 		verts[ *i + 2 ] = heightmap_point( hm, p2.x, p2.y ) + offset;
     33 		*i += 3;
     34 	}
     35 }
     36 
     37 void gpubtt_init(
     38 	MemoryArena * arena, GPUBTT * gpubtt, BTTs btts,
     39 	const array2d< u16 > hm, v2u32 offset, const v3 * normals, const u8 * horizons
     40 ) {
     41 	PROFILE_FUNCTION();
     42 
     43 	MEMARENA_SCOPED_CHECKPOINT( arena );
     44 
     45 	const u32 num_leaves = btt_count_leaves( btts.left_root ) + btt_count_leaves( btts.right_root );
     46 
     47 	v3 * verts = memarena_push_many( arena, v3, num_leaves * 3 );
     48 	u32 num_vertices = 0;
     49 
     50 	// bottom left, bottom right, top left, top right
     51 	const v2s32 bl( 0, 0 );
     52 	const v2s32 br( hm.w - 1, 0 );
     53 	const v2s32 tl( 0, hm.h - 1 );
     54 	const v2s32 tr( hm.w - 1, hm.h - 1 );
     55 
     56 	v3 offset_v3( offset.x, offset.y, 0 );
     57 
     58 	{
     59 		PROFILE_BLOCK( "Convert BTT to mesh" );
     60 		gpubtt_build( verts, &num_vertices, hm, offset_v3, btts.left_root, tr, tl, bl );
     61 		gpubtt_build( verts, &num_vertices, hm, offset_v3, btts.right_root, bl, br, tr );
     62 		ASSERT( num_leaves * 3 == num_vertices );
     63 	}
     64 
     65 	{
     66 		PROFILE_BLOCK( "Upload normal map" );
     67 		TextureConfig normals_config;
     68 		normals_config.width = hm.w;
     69 		normals_config.height = hm.h;
     70 		normals_config.format = TEXFMT_RGB_FLOAT;
     71 		normals_config.data = normals;
     72 		normals_config.wrap = TEXWRAP_CLAMP; // TODO: this is a hack and should be removed
     73 		gpubtt->normal_map = renderer_new_texture( normals_config );
     74 	}
     75 
     76 	{
     77 		PROFILE_BLOCK( "Upload horizon map" );
     78 		TextureConfig horizons_config;
     79 		horizons_config.width = hm.w;
     80 		horizons_config.height = hm.h;
     81 		horizons_config.format = TEXFMT_R_U8;
     82 		horizons_config.data = horizons;
     83 		horizons_config.wrap = TEXWRAP_CLAMP; // TODO: this is a hack and should be removed
     84 		gpubtt->horizon_map = renderer_new_texture( horizons_config );
     85 	}
     86 
     87 	{
     88 		PROFILE_BLOCK( "Upload mesh" );
     89 		MeshConfig mesh_config;
     90 		mesh_config.positions = renderer_new_vb( verts, num_vertices * sizeof( v3 ) );
     91 		mesh_config.num_vertices = num_vertices;
     92 		gpubtt->mesh = renderer_new_mesh( mesh_config );
     93 	}
     94 }
     95 
     96 void gpubtt_destroy( GPUBTT * gpubtt ) {
     97 	renderer_delete_mesh( gpubtt->mesh );
     98 	renderer_delete_texture( gpubtt->normal_map );
     99 	renderer_delete_texture( gpubtt->horizon_map );
    100 }
    101 
    102 void gpubtt_render( const GPUBTT * gpubtt, RenderState render_state ) {
    103 	render_state.textures[ 0 ] = gpubtt->normal_map;
    104 	render_state.textures[ 1 ] = gpubtt->horizon_map;
    105 	renderer_draw_mesh( gpubtt->mesh, render_state );
    106 }