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 }