shadow_map.cc (5338B)
1 #include "game.h" 2 #include "intrinsics.h" 3 #include "linear_algebra.h" 4 #include "gl.h" 5 #include "renderer.h" 6 #include "shaders.h" 7 #include "immediate.h" 8 #include "text_renderer.h" 9 #include "log.h" 10 #include "obj.h" 11 12 static Mesh square; 13 static FB shadow_fb; 14 static Mesh tree_mesh; 15 16 static const u32 SHADOW_SIZE = 1024; 17 18 static v3 light_pos( -0, -10, 15 ); 19 static v3 light_dir = v3_forward( -60, 90 ); 20 21 static void draw_scene( RenderState render_state, bool draw_light = false ) { 22 m4 I = m4_identity(); 23 render_state.set_uniform( "model", renderer_uniforms( I ) ); 24 25 immediate_sphere( v3( 0, 0, 2 ), 2, v4( 1, 0, 0, 1 ) ); 26 immediate_sphere( v3( -3, 7, 2 ), 2, v4( 0, 1, 0, 1 ) ); 27 28 immediate_aabb( v3( 3, 3, 0 ), v3( 5, 5, 2 ), v4( 0, 0, 1, 1 ) ); 29 immediate_aabb( v3( 3, 0, 0 ), v3( 5, 2, 2 ), v4( 0, 0, 1, 1 ) ); 30 immediate_aabb( v3( 3, -3, 0 ), v3( 5, -1, 2 ), v4( 0, 0, 1, 1 ) ); 31 immediate_aabb( v3( 3, -6, 0 ), v3( 5, -4, 2 ), v4( 0, 0, 1, 1 ) ); 32 33 if( draw_light ) { 34 immediate_sphere( light_pos, 0.1f, v4( 1, 1, 1, 1 ) ); 35 immediate_arrow( light_pos, light_dir, 0.5f, v4( 1, 1, 1, 1 ) ); 36 } 37 38 v3 tl( -50, 50, 0 ); 39 v3 tr( 50, 50, 0 ); 40 v3 bl( -50, -50, 0 ); 41 v3 br( 50, -50, 0 ); 42 immediate_triangle( tr, tl, bl, v4( 0.5, 0.5, 0.5, 1.0 ) ); 43 immediate_triangle( bl, br, tr, v4( 0.5, 0.5, 0.5, 1.0 ) ); 44 45 immediate_render( render_state ); 46 47 m4 M = m4_translation( v3( -7, -2, 0 ) ) * m4_rotx( deg_to_rad( 90 ) ); 48 render_state.set_uniform( "model", renderer_uniforms( M ) ); 49 renderer_draw_mesh( tree_mesh, render_state ); 50 } 51 52 GAME_INIT( game_init ) { 53 { 54 TextureConfig config; 55 config.width = SHADOW_SIZE; 56 config.height = SHADOW_SIZE; 57 config.format = TEXFMT_DEPTH; 58 config.wrap = TEXWRAP_BORDER; 59 config.border_colour = v4( 1, 1, 1, 1 ); 60 shadow_fb = renderer_new_fb( config, FB_DEPTH ); 61 } 62 63 game->pos = v3( -10, -10, 5 ); 64 game->pitch = 0; 65 game->yaw = 45; 66 67 { 68 float verts[] = { 69 -1.0f, -1.0f, 0.0f, 70 -0.8f, -1.0f, 0.0f, 71 -1.0f, -0.7f, 0.0f, 72 -0.8f, -0.7f, 0.0f, 73 }; 74 MeshConfig config; 75 config.positions = renderer_new_vb( verts, sizeof( verts ) ); 76 config.num_vertices = 4; 77 config.primitive_type = PRIMITIVETYPE_TRIANGLE_STRIP; 78 square = renderer_new_mesh( config ); 79 } 80 81 tree_mesh = load_obj( "models/trees/PineTree.obj", &mem->persistent_arena ); 82 } 83 84 GAME_FRAME( game_frame ) { 85 const float speed = 6.0f; 86 const float angular_speed = 100.0f; 87 88 float fb = float( input->keys[ KEY_W ] - input->keys[ KEY_S ] ); 89 float lr = float( input->keys[ KEY_D ] - input->keys[ KEY_A ] ); 90 float dz = float( input->keys[ KEY_SPACE ] - input->keys[ KEY_LEFTSHIFT ] ); 91 92 float dpitch = float( input->keys[ KEY_DOWNARROW ] - input->keys[ KEY_UPARROW ] ); 93 float dyaw = float( input->keys[ KEY_LEFTARROW ] - input->keys[ KEY_RIGHTARROW ] ); 94 95 dpitch += input->keys[ KEY_K ] - input->keys[ KEY_I ]; 96 dyaw += input->keys[ KEY_J ] - input->keys[ KEY_L ]; 97 98 game->pitch += dpitch * dt * angular_speed; 99 game->yaw += dyaw * dt * angular_speed; 100 101 const v3 world_up = v3( 0, 0, 1 ); 102 v3 forward = v3_forward( game->pitch, game->yaw ); 103 v3 right = normalize( cross( forward, world_up ) ); 104 v3 up = normalize( cross( right, forward ) ); 105 106 game->pos += forward * dt * fb * speed; 107 game->pos += right * dt * lr * speed; 108 game->pos.z += dt * dz * speed; 109 110 const m4 P = m4_perspective( VERTICAL_FOV, get_aspect_ratio(), NEAR_PLANE_DEPTH, FAR_PLANE_DEPTH ); 111 m4 V = m4_view( forward, right, up, game->pos ); 112 113 light_pos = v3( float( cos( current_time ) * 10 ), float( sin( current_time ) * 10 ), 10 ); 114 115 renderer_begin_frame(); 116 117 u8 write_shadowmap_pass = renderer_add_pass( "Write shadowmap", shadow_fb, RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_DEPTH_DO ); 118 u8 world_pass = renderer_add_pass( "Render world", RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO ); 119 u8 ui_pass = renderer_add_pass( "Render UI" ); 120 121 UniformBinding light_view_uniforms; 122 123 { 124 m4 lightVP; 125 v3 target( 0, 0, 0 ); 126 light_dir = normalize( target - light_pos ); 127 const m4 lightP = m4_perspective( 90, 1, NEAR_PLANE_DEPTH, 500.0f ); 128 m4 lightV = m4_lookat( light_pos, target, world_up ); 129 130 light_view_uniforms = renderer_uniforms( lightP * lightV, light_pos ); 131 } 132 133 // fill shadow map 134 { 135 RenderState render_state; 136 render_state.pass = write_shadowmap_pass; 137 render_state.shader = get_shader( SHADER_WRITE_SHADOW_MAP ); 138 render_state.set_uniform( "light_view", light_view_uniforms ); 139 140 draw_scene( render_state ); 141 } 142 143 // render shadow map 144 { 145 RenderState render_state; 146 render_state.pass = ui_pass; 147 render_state.shader = get_shader( SHADER_DEBUG_RENDER_SHADOW_MAP ); 148 render_state.set_texture( "tex", shadow_fb.textures[ OUTPUT_DEPTH ] ); 149 renderer_draw_mesh( square, render_state ); 150 } 151 152 // draw world 153 { 154 RenderState render_state; 155 render_state.pass = world_pass; 156 render_state.shader = get_shader( SHADER_SHADOWED_VERTEX_COLOURS ); 157 render_state.set_uniform( "view", renderer_uniforms( V, P, game->pos ) ); 158 render_state.set_uniform( "light_view", light_view_uniforms ); 159 render_state.set_texture( "shadowmap", shadow_fb.textures[ OUTPUT_DEPTH ] ); 160 render_state.set_texture( "dither_noise", renderer_blue_noise() ); 161 162 draw_scene( render_state, true ); 163 } 164 165 { 166 const str< 128 > status( "Frame time: {.1}ms FPS: {.1}", dt * 1000.0f, 1.0f / dt ); 167 draw_text( ui_pass, status.c_str(), 2, 2, 16 ); 168 } 169 170 renderer_end_frame(); 171 }