medfall

A super great game engine
Log | Files | Refs

fullscreen.cc (6558B)


      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 FB gbuffer;
     15 static Mesh tree_mesh;
     16 
     17 static const u32 SHADOW_SIZE = 1024;
     18 
     19 static v3 light_pos( -0, -10, 15 );
     20 static v3 light_dir = v3_forward( -60, 90 );
     21 
     22 static void draw_scene( RenderState render_state, bool draw_light = false ) {
     23 	m4 I = m4_identity();
     24 	render_state.set_uniform( "model", renderer_uniforms( I ) );
     25 
     26 	immediate_sphere( v3( 0, 0, 2 ), 2, v4( 1, 0, 0, 1 ) );
     27 	immediate_sphere( v3( -3, 7, 2 ), 2, v4( 0, 1, 0, 1 ) );
     28 
     29 	immediate_aabb( v3( 3, 3, 0 ), v3( 5, 5, 2 ), v4( 0, 0, 1, 1 ) );
     30 	immediate_aabb( v3( 3, 0, 0 ), v3( 5, 2, 2 ), v4( 0, 0, 1, 1 ) );
     31 	immediate_aabb( v3( 3, -3, 0 ), v3( 5, -1, 2 ), v4( 0, 0, 1, 1 ) );
     32 	immediate_aabb( v3( 3, -6, 0 ), v3( 5, -4, 2 ), v4( 0, 0, 1, 1 ) );
     33 
     34 	if( draw_light ) {
     35 		immediate_sphere( light_pos, 0.1f, v4( 1, 1, 1, 1 ) );
     36 		immediate_arrow( light_pos, light_dir, 0.5f, v4( 1, 1, 1, 1 ) );
     37 	}
     38 
     39 	v3 tl( -50,  50, 0 );
     40 	v3 tr(  50,  50, 0 );
     41 	v3 bl( -50, -50, 0 );
     42 	v3 br(  50, -50, 0 );
     43 	immediate_triangle( tr, tl, bl, v4( 0.5, 0.5, 0.5, 1.0 ) );
     44 	immediate_triangle( bl, br, tr, v4( 0.5, 0.5, 0.5, 1.0 ) );
     45 
     46 	immediate_render( render_state );
     47 
     48 	m4 M = m4_translation( v3( -7, -2, 0 ) ) * m4_rotx( deg_to_rad( 90 ) );
     49 	render_state.set_uniform( "model", renderer_uniforms( M ) );
     50 	renderer_draw_mesh( tree_mesh, render_state );
     51 }
     52 
     53 GAME_INIT( game_init ) {
     54 	{
     55 		TextureConfig config;
     56 		config.width = SHADOW_SIZE;
     57 		config.height = SHADOW_SIZE;
     58 		config.format = TEXFMT_DEPTH;
     59 		config.wrap = TEXWRAP_BORDER;
     60 		config.border_colour = v4( 1, 1, 1, 1 );
     61 		shadow_fb = renderer_new_fb( config, FB_DEPTH );
     62 	}
     63 
     64 	gbuffer = { };
     65 
     66 	game->pos = v3( -10, -10, 5 );
     67 	game->pitch = 0;
     68 	game->yaw = 45;
     69 
     70 	{
     71 		float verts[] = {
     72 			-1.0f, -1.0f, 0.0f,
     73 			-0.8f, -1.0f, 0.0f,
     74 			-1.0f, -0.7f, 0.0f,
     75 			-0.8f, -0.7f, 0.0f,
     76 		};
     77 		MeshConfig config;
     78 		config.positions = renderer_new_vb( verts, sizeof( verts ) );
     79 		config.num_vertices = 4;
     80 		config.primitive_type = PRIMITIVETYPE_TRIANGLE_STRIP;
     81 		square = renderer_new_mesh( config );
     82 	}
     83 
     84 	tree_mesh = load_obj( "models/trees/PineTree.obj", &mem->persistent_arena );
     85 }
     86 
     87 static void recreate_framebuffers() {
     88 	renderer_delete_fb( gbuffer );
     89 
     90 	v2u32 window_size = get_window_size();
     91 
     92 	TextureConfig texture_config;
     93 	texture_config.width = window_size.x;
     94 	texture_config.height = window_size.y;
     95 
     96 	FramebufferConfig fb_config;
     97 
     98 	texture_config.format = TEXFMT_RGB_U8;
     99 	fb_config.textures[ OUTPUT_ALBEDO ].config = texture_config;
    100 	fb_config.textures[ OUTPUT_ALBEDO ].attachment = FB_COLOUR;
    101 
    102 	texture_config.format = TEXFMT_RGB_HALF;
    103 	fb_config.textures[ OUTPUT_NORMAL ].config = texture_config;
    104 	fb_config.textures[ OUTPUT_NORMAL ].attachment = FB_NORMAL;
    105 
    106 	texture_config.format = TEXFMT_DEPTH;
    107 	fb_config.textures[ OUTPUT_DEPTH ].config = texture_config;
    108 	fb_config.textures[ OUTPUT_DEPTH ].attachment = FB_DEPTH;
    109 
    110 	gbuffer = renderer_new_fb( fb_config );
    111 }
    112 
    113 GAME_FRAME( game_frame ) {
    114 	if( input->resized ) {
    115 		recreate_framebuffers();
    116 	}
    117 
    118 	const float speed = 6.0f;
    119 	const float angular_speed = 100.0f;
    120 
    121 	float fb = float( input->keys[ KEY_W ] - input->keys[ KEY_S ] );
    122 	float lr = float( input->keys[ KEY_D ] - input->keys[ KEY_A ] );
    123 	float dz = float( input->keys[ KEY_SPACE ] - input->keys[ KEY_LEFTSHIFT ] );
    124 
    125 	float dpitch = float( input->keys[ KEY_DOWNARROW ] - input->keys[ KEY_UPARROW ] );
    126 	float dyaw = float( input->keys[ KEY_LEFTARROW ] - input->keys[ KEY_RIGHTARROW ] );
    127 
    128 	dpitch += input->keys[ KEY_K ] - input->keys[ KEY_I ];
    129 	dyaw += input->keys[ KEY_J ] - input->keys[ KEY_L ];
    130 
    131 	game->pitch += dpitch * dt * angular_speed;
    132 	game->yaw += dyaw * dt * angular_speed;
    133 
    134 	const v3 world_up = v3( 0, 0, 1 );
    135 	v3 forward = v3_forward( game->pitch, game->yaw );
    136 	v3 right = normalize( cross( forward, world_up ) );
    137 	v3 up = normalize( cross( right, forward ) );
    138 
    139 	game->pos += forward * dt * fb * speed;
    140 	game->pos += right * dt * lr * speed;
    141 	game->pos.z += dt * dz * speed;
    142 
    143 	const m4 P = m4_perspective( VERTICAL_FOV, get_aspect_ratio(), NEAR_PLANE_DEPTH, FAR_PLANE_DEPTH );
    144 	m4 V = m4_view( forward, right, up, game->pos );
    145 
    146 	light_pos = v3( float( cos( current_time ) * 10 ), float( sin( current_time ) * 10 ), 10 );
    147 
    148 	renderer_begin_frame();
    149 
    150 	u8 shadowmap_pass = renderer_add_pass( "Write shadowmap", shadow_fb, RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_DEPTH_DO );
    151 	u8 gbuffer_pass = renderer_add_pass( "Write gbuffer", gbuffer, RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
    152 	u8 compose_pass = renderer_add_pass( "Compose" );
    153 	u8 ui_pass = renderer_add_pass( "Render UI" );
    154 
    155 	UniformBinding light_view_uniforms;
    156 
    157 	{
    158 		m4 lightVP;
    159 		v3 target( 0, 0, 0 );
    160 		light_dir = normalize( target - light_pos );
    161 		const m4 lightP = m4_perspective( 90, 1, NEAR_PLANE_DEPTH, 500.0f );
    162 		m4 lightV = m4_lookat( light_pos, target, world_up );
    163 
    164 		light_view_uniforms = renderer_uniforms( lightP * lightV, light_pos );
    165 	}
    166 
    167 	// fill shadow map
    168 	{
    169 		RenderState render_state;
    170 		render_state.pass = shadowmap_pass;
    171 		render_state.shader = get_shader( SHADER_WRITE_SHADOW_MAP );
    172 		render_state.set_uniform( "light_view", light_view_uniforms );
    173 
    174 		draw_scene( render_state );
    175 	}
    176 
    177 	// fill gbuffers
    178 	{
    179 		RenderState render_state;
    180 		render_state.pass = gbuffer_pass;
    181 		render_state.shader = get_shader( SHADER_SHADOWED_VERTEX_COLOURS_TO_GBUFFER );
    182 		render_state.set_uniform( "view", renderer_uniforms( V, P, game->pos ) );
    183 		render_state.set_uniform( "light_view", light_view_uniforms );
    184 		render_state.set_texture( "shadowmap", shadow_fb.textures[ OUTPUT_DEPTH ] );
    185 		render_state.set_texture( "dither_noise", renderer_blue_noise() );
    186 
    187 		draw_scene( render_state, true );
    188 	}
    189 
    190 	// final pass
    191 	{
    192 		RenderState render_state;
    193 		render_state.pass = compose_pass;
    194 		render_state.shader = get_shader( SHADER_GBUFFER );
    195 		render_state.depth_func = DEPTHFUNC_DISABLED;
    196 		render_state.set_texture( "outline_depth", gbuffer.textures[ OUTPUT_ALBEDO ] );
    197 		render_state.set_texture( "world_normal", gbuffer.textures[ OUTPUT_NORMAL ] );
    198 		render_state.set_texture( "world_depth", gbuffer.textures[ OUTPUT_DEPTH ] );
    199 		render_state.set_texture( "blue_noise", renderer_blue_noise() );
    200 
    201 		renderer_draw_fullscreen_triangle( render_state );
    202 	}
    203 
    204 	{
    205 		const str< 128 > status( "Frame time: {.1}ms FPS: {.1}", dt * 1000.0f, 1.0f / dt );
    206 		draw_text( ui_pass, status.c_str(), 2, 2, 16 );
    207 	}
    208 
    209 	renderer_end_frame();
    210 }