medfall

A super great game engine
Log | Files | Refs

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 }