From: hgn Date: Thu, 1 Dec 2022 18:10:10 +0000 (+0000) Subject: add motion vectors to all shaders X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;ds=inline;h=f7db507815e2822d971031c30f25e02b45e9c914;p=carveJwlIkooP6JGAAIwe30JlM.git add motion vectors to all shaders --- diff --git a/audio.h b/audio.h index f13280b..8282c06 100644 --- a/audio.h +++ b/audio.h @@ -305,7 +305,7 @@ VG_STATIC void audio_sample_occlusion( v3f origin ) float occlusion = 1.0f - (d * (1.0f/(sample_dist*(float)sample_count))), rate = VG_TIMESTEP_FIXED * k_audio_occlusion_rate, - target = powf( occlusion, 6.0f ); + target = powf( vg_maxf(occlusion,0.0f), 6.0f ); audio_occlusion_current = vg_lerpf( audio_occlusion_current, target, rate ); } diff --git a/build.c b/build.c index 053154f..61ac1c4 100644 --- a/build.c +++ b/build.c @@ -118,23 +118,31 @@ void build_shaders(void) { vg_shader_set_include_dir( "shaders" ); + // 2D _shader( "blit", "shaders/blit.vs", "shaders/blit.fs" ); _shader( "blitblur", "shaders/blit.vs", "shaders/blitblur.fs" ); + _shader( "blitcolour","shaders/blit.vs", "shaders/colour.fs" ); + _shader( "routeui", "shaders/routeui.vs", "shaders/routeui.fs" ); + + // 3D Standard _shader( "standard", "shaders/standard.vs", "shaders/standard.fs" ); _shader( "vblend", "shaders/standard.vs", "shaders/vblend.fs" ); + _shader( "scoretext", "shaders/scoretext.vs", "shaders/vblend.fs" ); _shader( "terrain", "shaders/standard.vs", "shaders/terrain.fs" ); - _shader( "sky", "shaders/standard.vs", "shaders/sky.fs" ); - _shader( "planeinf", "shaders/standard.vs", "shaders/planeinf.fs" ); - _shader( "gpos", "shaders/standard.vs", "shaders/gpos.fs" ); - _shader( "fscolour", "shaders/blit.vs", "shaders/colour.fs" ); _shader( "alphatest", "shaders/standard.vs", "shaders/std_alphatest.fs" ); - _shader( "scoretext", "shaders/scoretext.vs", "shaders/vblend.fs" ); + _shader( "route", "shaders/standard.vs", "shaders/route.fs" ); + _shader( "menu", "shaders/standard.vs", "shaders/menu.fs" ); + + // 3D Skinned + _shader( "viewchar", "shaders/standard_skinned.vs", "shaders/viewchar.fs" ); + + // 3D extra/effects + _shader( "gpos", "shaders/standard.vs", "shaders/gpos.fs" ); + _shader( "sky", "shaders/standard.vs", "shaders/sky.fs" ); _shader( "water", "shaders/standard.vs", "shaders/water.fs" ); _shader( "water_fast","shaders/standard.vs", "shaders/water_fast.fs" ); - _shader( "gate", "shaders/gate.vs", "shaders/gate.fs" ); _shader( "gatelq", "shaders/gate.vs", "shaders/gate_lq.fs" ); - _shader( "route", "shaders/standard.vs", "shaders/route.fs" ); - _shader( "routeui", "shaders/routeui.vs", "shaders/routeui.fs" ); - _shader( "viewchar", "shaders/standard_skinned.vs", "shaders/viewchar.fs" ); - _shader( "menu", "shaders/standard.vs", "shaders/menu.fs" ); + + //_shader( "planeinf", "shaders/standard.vs", "shaders/planeinf.fs" ); + //_shader( "gate", "shaders/gate.vs", "shaders/gate.fs" ); } diff --git a/camera.h b/camera.h index 1c265a7..5964099 100644 --- a/camera.h +++ b/camera.h @@ -3,24 +3,104 @@ #include "common.h" -VG_STATIC v2f camera_angles; -VG_STATIC v3f camera_pos; +typedef struct camera camera; -VG_STATIC m4x3f camera_mtx, - camera_mtx_inverse; +struct camera +{ + /* Input */ + v2f angles; + v3f pos; + float fov, nearz, farz; + + /* Output */ + m4x3f transform, + transform_inverse; -VG_STATIC void camera_update(void) + struct camera_mtx + { + m4x4f p, + v, + pv; + } + mtx, + mtx_prev; +} +VG_STATIC main_camera; + +/* + * 1) [angles, pos] -> transform + */ +VG_STATIC void camera_update_transform( camera *cam ) { - /* Update camera matrices */ v4f qyaw, qpitch, qcam; - q_axis_angle( qyaw, (v3f){ 0.0f, 1.0f, 0.0f }, -camera_angles[0] ); - q_axis_angle( qpitch, (v3f){ 1.0f, 0.0f, 0.0f }, -camera_angles[1] ); + q_axis_angle( qyaw, (v3f){ 0.0f, 1.0f, 0.0f }, -cam->angles[0] ); + q_axis_angle( qpitch, (v3f){ 1.0f, 0.0f, 0.0f }, -cam->angles[1] ); q_mul( qyaw, qpitch, qcam ); - q_m3x3( qcam, camera_mtx ); - v3_copy( camera_pos, camera_mtx[3] ); + q_m3x3( qcam, cam->transform ); + v3_copy( cam->pos, cam->transform[3] ); +} + +/* + * 2) [transform] -> transform_inverse, view matrix + */ +VG_STATIC void camera_update_view( camera *cam ) +{ + m4x4_copy( cam->mtx.v, cam->mtx_prev.v ); + m4x3_invert_affine( cam->transform, cam->transform_inverse ); + m4x3_expand( cam->transform_inverse, cam->mtx.v ); +} + +/* + * 3) [fov,nearz,farz] -> projection matrix + */ +VG_STATIC void camera_update_projection( camera *cam ) +{ + m4x4_copy( cam->mtx.p, cam->mtx_prev.p ); + m4x4_projection( cam->mtx.p, cam->fov, + (float)vg.window_x / (float)vg.window_y, + cam->nearz, cam->farz ); +} + +/* + * 4) [projection matrix, view matrix] -> previous pv, new pv + */ +VG_STATIC void camera_finalize( camera *cam ) +{ + m4x4_copy( cam->mtx.pv, cam->mtx_prev.pv ); + m4x4_mul( cam->mtx.p, cam->mtx.v, cam->mtx.pv ); +} + +/* + * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf + */ +VG_STATIC void m4x4_clip_projection( m4x4f mat, v4f plane ) +{ + v4f c = + { + (vg_signf(plane[0]) + mat[2][0]) / mat[0][0], + (vg_signf(plane[1]) + mat[2][1]) / mat[1][1], + -1.0f, + (1.0f + mat[2][2]) / mat[3][2] + }; + + v4_muls( plane, 2.0f / v4_dot(plane,c), c ); - m4x3_invert_affine( camera_mtx, camera_mtx_inverse ); + mat[0][2] = c[0]; + mat[1][2] = c[1]; + mat[2][2] = c[2] + 1.0f; + mat[3][2] = c[3]; +} + +/* + * Undoes the above operation + */ +VG_STATIC void m4x4_reset_clipping( m4x4f mat, float ffar, float fnear ) +{ + mat[0][2] = 0.0f; + mat[1][2] = 0.0f; + mat[2][2] = -(ffar + fnear) / (ffar - fnear); + mat[3][2] = -2.0f * ffar * fnear / (ffar - fnear); } #endif /* CAMERA_H */ diff --git a/common.h b/common.h index 2e254f9..bac81a7 100644 --- a/common.h +++ b/common.h @@ -25,7 +25,6 @@ enum menu_controller_type }; VG_STATIC enum menu_controller_type menu_display_controller; -VG_STATIC float g_fov_option = 0.86f; typedef struct ray_hit ray_hit; struct ray_hit diff --git a/conf.h b/conf.h new file mode 100644 index 0000000..99d0e9f --- /dev/null +++ b/conf.h @@ -0,0 +1,48 @@ +#ifndef CONF_H +#define CONF_H + +#define VG_GAME +#include "vg/vg.h" + +VG_STATIC float cl_fov = 0.86f, + cl_volume = 1.0f, + cl_blur_strength = 2.0f; +VG_STATIC int cl_blur = 1, + cl_playermdl_id = 0; + +VG_STATIC void g_conf_init(void) +{ + vg_convar_push( (struct vg_convar){ + .name = "cl_fov", + .data = &cl_fov, + .data_type = k_convar_dtype_f32, + .opt_f32 = { .clamp = 0 }, + .persistent = 1 + }); + + vg_convar_push( (struct vg_convar){ + .name = "cl_blur_strength", + .data = &cl_blur_strength, + .data_type = k_convar_dtype_f32, + .opt_f32 = { .clamp = 0 }, + .persistent = 1 + }); + + vg_convar_push( (struct vg_convar){ + .name = "cl_blur", + .data = &cl_blur, + .data_type = k_convar_dtype_i32, + .opt_i32 = { .min=0, .max=1, .clamp=1 }, + .persistent = 1 + }); + + vg_convar_push( (struct vg_convar){ + .name = "cl_playermdl_id", + .data = &cl_playermdl_id, + .data_type = k_convar_dtype_i32, + .opt_i32 = { .min=0, .max=2, .clamp=1 }, + .persistent = 1 + }); +} + +#endif /* CONF_H */ diff --git a/maps_src/mp_mtzero.mdl b/maps_src/mp_mtzero.mdl index d7ed5d4..24c3c03 100644 Binary files a/maps_src/mp_mtzero.mdl and b/maps_src/mp_mtzero.mdl differ diff --git a/menu.h b/menu.h index e52f3d7..1b73bea 100644 --- a/menu.h +++ b/menu.h @@ -36,6 +36,7 @@ VG_STATIC struct input_binding input_menu_h, VG_STATIC void menu_btn_quit( int event ); VG_STATIC void menu_btn_skater( int event ); +VG_STATIC void menu_btn_blur( int event ); VG_STATIC void menu_btn_fuckoff( int event ); VG_STATIC void menu_btn_reset( int event ); VG_STATIC void menu_btn_map( int event ); @@ -43,7 +44,10 @@ VG_STATIC void menu_btn_settings( int event ); VG_STATIC mdl_node *menu_pnode_fov_slider, *menu_pnode_fov_min, - *menu_pnode_fov_max; + *menu_pnode_fov_max, + *menu_pnode_vol_slider, + *menu_pnode_vol_min, + *menu_pnode_vol_max; struct { @@ -72,25 +76,46 @@ enum menu_page k_menu_page_map = 0x10 }; -VG_STATIC int menu_vis( int group_mask ) +struct menu_btn_userdata { - if( group_mask & game_menu.page ) + union + { + int i; + void *ptr_generic; + }; +}; + +VG_STATIC int menu_settings_if( struct menu_btn_userdata ud ) +{ + if( game_menu.page & k_menu_page_settings ) + { + int *ptr = ud.ptr_generic; + return *ptr; + } + else + return 0; +} + +VG_STATIC int menu_vis( struct menu_btn_userdata ud ) +{ + if( ud.i & game_menu.page ) return 1; else return 0; } -VG_STATIC int menu_controller( int ctr ) +VG_STATIC int menu_controller( struct menu_btn_userdata ud ) { if( (game_menu.page & (k_menu_page_main|k_menu_page_settings)) - && (ctr == menu_display_controller) ) + && (ud.i == menu_display_controller) ) return 1; return 0; } -VG_STATIC int menu_controller_inf( int ctr ) +VG_STATIC int menu_controller_inf( struct menu_btn_userdata ud ) { - if( (game_menu.page & k_menu_page_settings) && (ctr == menu_display_controller) ) + if( (game_menu.page & k_menu_page_settings) + && (ud.i == menu_display_controller) ) return 1; return 0; } @@ -99,8 +124,8 @@ struct menu_button { const char *name; - int (*fn_visibility)( int user ); - int user; + int (*fn_visibility)( struct menu_btn_userdata ud ); + struct menu_btn_userdata user; void (*fn_press)( int event ); @@ -115,59 +140,77 @@ struct menu_button VG_STATIC menu_buttons[] = { { - "text_quit", menu_vis, k_menu_page_main|k_menu_page_quit, + "text_quit", menu_vis, {.i=k_menu_page_main|k_menu_page_quit}, .fn_press = menu_btn_quit, .ld="text_reset", .lr="text_settings", .ll="text_map" }, { - "text_quitty", menu_vis, k_menu_page_quit + "text_quitty", menu_vis, {.i=k_menu_page_quit} }, { - "text_yes", menu_vis, k_menu_page_quit, + "text_yes", menu_vis, {.i=k_menu_page_quit}, .fn_press = menu_btn_fuckoff }, { - "text_reset", menu_vis, k_menu_page_main, + "text_reset", menu_vis, {.i=k_menu_page_main}, .fn_press = menu_btn_reset, .lu="text_quit", .ld="text_skater", .ll="text_map", .lr="text_settings" }, { - "text_skater", menu_vis, k_menu_page_main|k_menu_page_skater, + "text_skater", menu_vis, {.i=k_menu_page_main|k_menu_page_skater}, .fn_press = menu_btn_skater, .lu="text_reset", .ll="text_map", .lr="text_settings" }, { - "text_map", menu_vis, k_menu_page_main, + "text_map", menu_vis, {.i=k_menu_page_main}, .fn_press = menu_btn_map, - .lr="text_skater" + .lr="text_reset" }, { - "text_settings", menu_vis, k_menu_page_main|k_menu_page_settings, + "text_settings", menu_vis, {.i=k_menu_page_main|k_menu_page_settings}, .fn_press = menu_btn_settings, - .ll="text_skater" + .ll="text_reset" +}, +{ + "skater_left", menu_vis, {k_menu_page_skater} }, { - "skater_left", menu_vis, k_menu_page_skater + "skater_right", menu_vis, {k_menu_page_skater} +}, + +{ + "fov_slider", menu_vis, {k_menu_page_settings}, + .ld="text_blur" +}, +{ "fov_info", menu_vis, {k_menu_page_settings} }, + +{ + "vol_slider", menu_vis, {k_menu_page_settings}, + .lu="text_blur" +}, +{ "vol_info", menu_vis, {k_menu_page_settings} }, + +{ + "text_blur", menu_vis, {k_menu_page_settings}, + .fn_press = menu_btn_blur, + .lu="fov_slider", .ld="vol_slider" }, { - "skater_right", menu_vis, k_menu_page_skater + "text_blur_check", menu_settings_if, {.ptr_generic=&cl_blur} }, -{ "fov_slider", menu_vis, k_menu_page_settings }, -{ "fov_info", menu_vis, k_menu_page_settings }, - -{ "ctr_xbox", menu_controller_inf, k_menu_controller_type_xbox, }, -{ "ctr_xbox_text", menu_controller_inf, k_menu_controller_type_xbox }, -{ "ctr_steam", menu_controller_inf, k_menu_controller_type_steam }, -{ "ctr_steam_text", menu_controller_inf, k_menu_controller_type_steam }, -{ "ctr_deck", menu_controller_inf, k_menu_controller_type_steam_deck }, -{ "ctr_deck_text", menu_controller_inf, k_menu_controller_type_steam_deck }, -{ "ctr_ps", menu_controller_inf, k_menu_controller_type_playstation }, -{ "ctr_ps_text", menu_controller_inf, k_menu_controller_type_playstation }, -{ "ctr_kbm", menu_controller_inf, k_menu_controller_type_keyboard }, -{ "ctr_kbm_text", menu_controller_inf, k_menu_controller_type_keyboard }, -{ - "text_paused", menu_vis, k_menu_page_main +{ "ctr_xbox", menu_controller_inf, {k_menu_controller_type_xbox}}, +{ "ctr_xbox_text", menu_controller_inf, {k_menu_controller_type_xbox}}, +{ "ctr_steam", menu_controller_inf, {k_menu_controller_type_steam}}, +{ "ctr_steam_text", menu_controller_inf, {k_menu_controller_type_steam}}, +{ "ctr_deck", menu_controller_inf, {k_menu_controller_type_steam_deck}}, +{ "ctr_deck_text", menu_controller_inf, {k_menu_controller_type_steam_deck}}, +{ "ctr_ps", menu_controller_inf, {k_menu_controller_type_playstation}}, +{ "ctr_ps_text", menu_controller_inf, {k_menu_controller_type_playstation}}, +{ "ctr_kbm", menu_controller_inf, {k_menu_controller_type_keyboard}}, +{ "ctr_kbm_text", menu_controller_inf, {k_menu_controller_type_keyboard}}, +{ + "text_paused", menu_vis, {k_menu_page_main} }, }; @@ -212,6 +255,11 @@ VG_STATIC void menu_btn_skater( int event ) game_menu.page = k_menu_page_skater; } +VG_STATIC void menu_btn_blur( int event ) +{ + cl_blur ^= 0x1; +} + VG_STATIC void menu_btn_map( int event ) { game_menu.page = k_menu_page_map; @@ -336,12 +384,18 @@ VG_STATIC void menu_init(void) btn->pnode = mdl_node_from_name( &menu_model, btn->name ); if( !btn->pnode ) + { + vg_info( "info: %s\n", btn->name ); vg_fatal_exit_loop( "Menu programming error" ); + } } menu_pnode_fov_max = mdl_node_from_name( &menu_model, "fov_slider_max" ); menu_pnode_fov_min = mdl_node_from_name( &menu_model, "fov_slider_min" ); menu_pnode_fov_slider = mdl_node_from_name( &menu_model, "fov_slider" ); + menu_pnode_vol_max = mdl_node_from_name( &menu_model, "vol_slider_max" ); + menu_pnode_vol_min = mdl_node_from_name( &menu_model, "vol_slider_min" ); + menu_pnode_vol_slider = mdl_node_from_name( &menu_model, "vol_slider" ); shader_menu_register(); @@ -531,17 +585,36 @@ VG_STATIC void menu_page_skater(void) } } -VG_STATIC void menu_page_settings(void) +VG_STATIC void menu_slider( float *value, float min, float max, + mdl_node *slider, mdl_node *pmin, mdl_node *pmax ) { float h = input_menu_h.axis.value; + if( fabsf(h) > 0.04f ) - g_fov_option += h * vg.frame_delta; - g_fov_option = vg_clampf( g_fov_option, 0.0f, 1.0f ); + *value += h * vg.frame_delta; + *value = vg_clampf( *value, min, max ); + + v3_lerp( pmin->co, pmax->co, *value, slider->co ); +} + +VG_STATIC void menu_page_settings(void) +{ + menu_run_directional(); - v3_lerp( menu_pnode_fov_min->co, menu_pnode_fov_max->co, g_fov_option, - menu_pnode_fov_slider->co ); + if( game_menu.loc == menu_get_loc( "fov_slider" ) ) + { + menu_slider( &cl_fov, 0.0f, 1.0f, + menu_pnode_fov_slider, menu_pnode_fov_min, + menu_pnode_fov_max ); - menu_fov_target = vg_lerpf( 97.0f, 135.0f, g_fov_option ) * 0.8f; + menu_fov_target = vg_lerpf( 97.0f, 135.0f, cl_fov ) * 0.8f; + } + else if( game_menu.loc == menu_get_loc( "vol_slider" ) ) + { + menu_slider( &cl_volume, 0.0f, 1.0f, + menu_pnode_vol_slider, menu_pnode_vol_min, + menu_pnode_vol_max ); + } if( menu_page_should_backout() ) { @@ -656,10 +729,13 @@ VG_STATIC void menu_update(void) /* Update camera */ { - camera_angles[0] = vg_alerpf( camera_angles[0], angles[0], menu_opacity ); - camera_angles[1] = vg_lerpf ( camera_angles[1], angles[1], menu_opacity ); - v3_lerp( camera_pos, pos, menu_opacity, camera_pos ); - camera_update(); + main_camera.angles[0] = + vg_alerpf( main_camera.angles[0], angles[0], menu_opacity ); + main_camera.angles[1] = + vg_lerpf ( main_camera.angles[1], angles[1], menu_opacity ); + v3_lerp( main_camera.pos, pos, menu_opacity, main_camera.pos ); + + camera_update_transform( &main_camera ); } float dt = vg.frame_delta * 6.0f; @@ -686,7 +762,7 @@ float expSustainedImpulse( float x, float f, float k ) return fminf( x*x/(f*f), 1.0f+(2.0f/f)*s*expf(-k*s)); } -VG_STATIC void menu_render( m4x4f projection ) +VG_STATIC void menu_render( camera *cam ) { glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); @@ -707,7 +783,8 @@ VG_STATIC void menu_render( m4x4f projection ) shader_menu_uTexMain( 1 ); vg_tex2d_bind( &tex_menu, 1 ); - shader_menu_uPv( projection ); + shader_menu_uPv( cam->mtx.pv ); + shader_menu_uPvmPrev( cam->mtx_prev.pv ); mesh_bind( &menu_glmesh ); for( int i=0; itransform[3] ); + shader_viewchar_uPv( cam->mtx.pv ); shader_link_standard_ub( _shader_viewchar.id, 2 ); glUniformMatrix4x3fv( _uniform_viewchar_uTransforms, player.mdl.sk.bone_count, diff --git a/player_audio.h b/player_audio.h index 3c86e3b..8e5c0d2 100644 --- a/player_audio.h +++ b/player_audio.h @@ -53,7 +53,7 @@ VG_STATIC void player_audio(void) v3f ears = { 1.0f,0.0f,0.0f }; v3f delta; - float *cam = camera_pos, + float *cam = main_camera.transform[3], *pos = phys->rb.co; audio_player_set_position( &audio_player0, phys->rb.co ); @@ -63,16 +63,16 @@ VG_STATIC void player_audio(void) audio_player_set_position( &audio_player_gate, world.render_gate_pos ); audio_player_set_vol( &audio_player_gate, 5.0f ); - v3_sub( phys->rb.co, camera_pos, delta ); + v3_sub( phys->rb.co, main_camera.transform[3], delta ); v3_normalize( delta ); - m3x3_mulv( camera_mtx, ears, ears ); + m3x3_mulv( main_camera.transform, ears, ears ); /* TODO, Make function */ v3_copy( ears, vg_audio.listener_ears ); - v3_copy( camera_pos, vg_audio.listener_pos ); + v3_copy( main_camera.transform[3], vg_audio.listener_pos ); /* Tunnel / occlusion */ - audio_sample_occlusion( camera_pos ); + audio_sample_occlusion( main_camera.transform[3] ); int sprite_avail = -1; for( int i=0; igrind = 1; v3f up = { 0.0f, 1.0f, 0.0f }; float angle = v3_dot( phys->rb.up, up ); - v3f axis; - v3_cross( phys->rb.up, up, axis ); if( fabsf(angle) < 0.99f ) { + v3f axis; + v3_cross( phys->rb.up, up, axis ); + v4f correction; q_axis_angle( correction, axis, VG_TIMESTEP_FIXED * 10.0f * acosf(angle) ); @@ -1130,8 +1131,8 @@ VG_STATIC void player_freecam(void) v3f lookdir = { 0.0f, 0.0f, -1.0f }, sidedir = { 1.0f, 0.0f, 0.0f }; - m3x3_mulv( camera_mtx, lookdir, lookdir ); - m3x3_mulv( camera_mtx, sidedir, sidedir ); + m3x3_mulv( main_camera.transform, lookdir, lookdir ); + m3x3_mulv( main_camera.transform, sidedir, sidedir ); static v3f move_vel = { 0.0f, 0.0f, 0.0f }; @@ -1193,6 +1194,13 @@ VG_STATIC int reset_player( int argc, char const *argv[] ) if( !rp ) { vg_error( "No spawn found\n" ); + vg_info( "Player position: %f %f %f\n", player.phys.rb.co[0], + player.phys.rb.co[1], + player.phys.rb.co[2] ); + vg_info( "Player velocity: %f %f %f\n", player.phys.rb.v[0], + player.phys.rb.v[1], + player.phys.rb.v[2] ); + if( !world.spawn_count ) return 0; diff --git a/render.h b/render.h index 3399822..58c8831 100644 --- a/render.h +++ b/render.h @@ -4,17 +4,18 @@ #include "common.h" #include "model.h" +#include "camera.h" #include "shaders/blit.h" #include "shaders/blitblur.h" #include "shaders/standard.h" #include "shaders/vblend.h" -VG_STATIC void render_water_texture( m4x3f camera ); -VG_STATIC void render_water_surface( m4x4f pv, m4x3f camera ); -VG_STATIC void render_world( m4x4f projection, m4x3f camera ); +VG_STATIC void render_water_texture( camera *cam ); +VG_STATIC void render_water_surface( camera *cam ); +VG_STATIC void render_world( camera *cam ); VG_STATIC void shader_link_standard_ub( GLuint shader, int texture_id ); -VG_STATIC void render_world_depth( m4x4f projection, m4x3f camera ); +VG_STATIC void render_world_depth( camera *cam ); #ifndef RENDER_H #define RENDER_H @@ -28,13 +29,20 @@ struct framebuffer int allocated; }; +/* + * All standard buffers used in rendering + */ VG_STATIC struct pipeline { +#if 0 float fov; +#endif glmesh fsquad; GLuint fb_background, - rgb_background; + rgb_background, + mv_background, + rb_background; /* STD140 */ struct ub_world_lighting @@ -99,38 +107,6 @@ gpipeline = } }; -/* - * Matrix Projections - */ -/* - * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf - */ -VG_STATIC void plane_clip_projection( m4x4f mat, v4f plane ) -{ - v4f c = - { - (vg_signf(plane[0]) + mat[2][0]) / mat[0][0], - (vg_signf(plane[1]) + mat[2][1]) / mat[1][1], - -1.0f, - (1.0f + mat[2][2]) / mat[3][2] - }; - - v4_muls( plane, 2.0f / v4_dot(plane,c), c ); - - mat[0][2] = c[0]; - mat[1][2] = c[1]; - mat[2][2] = c[2] + 1.0f; - mat[3][2] = c[3]; -} - -VG_STATIC void pipeline_projection( m4x4f mat, float nearz, float farz ) -{ - m4x4_projection( mat, - gpipeline.fov, - (float)vg.window_x / (float)vg.window_y, - nearz, farz ); -} - /* * Shaders */ @@ -189,7 +165,7 @@ VG_STATIC void fb_use( struct framebuffer *fb ) { if( !fb ) { - glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background ); glViewport( 0, 0, vg.window_x, vg.window_y ); } else @@ -264,13 +240,14 @@ VG_STATIC void render_fb_resize(void) glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg.window_x, vg.window_y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL ); + + /* FIXME: Resizeother textures and rb */ } } -/* used for drawing player onto */ VG_STATIC void render_init_temp_buffer(void) { - vg_info( "[render] Allocate temporary framebuffer\n" ); + vg_info( "[render] Allocate framebuffer\n" ); glGenFramebuffers( 1, &gpipeline.fb_background ); glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background ); @@ -278,16 +255,58 @@ VG_STATIC void render_init_temp_buffer(void) glGenTextures( 1, &gpipeline.rgb_background ); glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg.window_x, vg.window_y, - 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - + 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - gpipeline.rgb_background, 0); + gpipeline.rgb_background, 0 ); + glGenTextures( 1, &gpipeline.mv_background ); + glBindTexture( GL_TEXTURE_2D, gpipeline.mv_background ); +#if 0 + glTexImage2D( GL_TEXTURE_2D, 0, GL_RG, vg.window_x, vg.window_y, + 0, GL_RG, GL_FLOAT, NULL); +#endif + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA16F, vg.window_x, vg.window_y, + 0, GL_RGBA, GL_FLOAT, NULL); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, + GL_TEXTURE_2D, + gpipeline.mv_background, 0 ); + + /* render buffer */ + glGenRenderbuffers( 1, &gpipeline.rb_background ); + glBindRenderbuffer( GL_RENDERBUFFER, gpipeline.rb_background ); + glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, + vg.window_x, vg.window_y ); + glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, gpipeline.rb_background ); + + GLuint attachments[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; + glDrawBuffers( 2, attachments ); + + GLenum result = glCheckFramebufferStatus( GL_FRAMEBUFFER ); + + if( result != GL_FRAMEBUFFER_COMPLETE ) + { + if( result == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ) + vg_fatal_exit_loop( "Main RT: Incomplete attachment" ); + else if( result == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT ) + vg_fatal_exit_loop( "Main RT: Missing attachment" ); + else if( result == GL_FRAMEBUFFER_UNSUPPORTED ) + vg_fatal_exit_loop( "Main RT: Unsupported framebuffer format" ); + else + vg_fatal_exit_loop( "Main RT: Generic Error" ); + } + + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); VG_CHECK_GL_ERR(); } diff --git a/rigidbody.h b/rigidbody.h index 16d38ea..83d32c7 100644 --- a/rigidbody.h +++ b/rigidbody.h @@ -446,6 +446,13 @@ VG_STATIC void rb_init( rigidbody *rb ) VG_STATIC void rb_iter( rigidbody *rb ) { + if( isnanf( rb->v[0] ) || + isnanf( rb->v[1] ) || + isnanf( rb->v[2] ) ) + { + vg_fatal_exit_loop( "NaN velocity" ); + } + v3f gravity = { 0.0f, -9.8f, 0.0f }; v3_muladds( rb->v, gravity, k_rb_delta, rb->v ); diff --git a/shaders/alphatest.h b/shaders/alphatest.h index 13d11ae..d5c38d0 100644 --- a/shaders/alphatest.h +++ b/shaders/alphatest.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_alphatest = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "out vec4 aColour;\n" "out vec2 aUv;\n" @@ -28,20 +40,23 @@ static struct vg_shader _shader_alphatest = { "\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4( a_co, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 );\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = { .static_src = -"out vec4 FragColor;\n" -"\n" "uniform sampler2D uTexGarbage;\n" "uniform sampler2D uTexMain;\n" "uniform vec3 uCamera;\n" @@ -54,6 +69,8 @@ static struct vg_shader _shader_alphatest = { "in vec3 aWorldCo;\n" "\n" "#line 1 1 \n" +"layout (location = 0) out vec4 oColour;\n" +"\n" "layout (std140) uniform ub_world_lighting\n" "{\n" " vec4 g_light_colours[3];\n" @@ -157,10 +174,27 @@ static struct vg_shader _shader_alphatest = { " return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n" "}\n" "\n" -"#line 15 0 \n" +"#line 13 0 \n" +"#line 1 2 \n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +" oMotionVec = vmotion1-vmotion0;\n" +"}\n" +"\n" +"#line 14 0 \n" "\n" "void main()\n" "{\n" +" compute_motion_vectors();\n" +"\n" " vec3 vfrag = vec3(0.5,0.5,0.5);\n" " vec4 vsamplemain = texture( uTexMain, aUv );\n" " vec3 qnorm = normalize(aNorm);\n" @@ -185,13 +219,14 @@ static struct vg_shader _shader_alphatest = { " vfrag = do_light_shadowing( vfrag );\n" " vfrag = apply_fog( vfrag, fdist );\n" "\n" -" FragColor = vec4(vfrag, 1.0);\n" +" oColour = vec4(vfrag, 1.0);\n" "}\n" ""}, }; static GLuint _uniform_alphatest_uMdl; static GLuint _uniform_alphatest_uPv; +static GLuint _uniform_alphatest_uPvmPrev; static GLuint _uniform_alphatest_uTexGarbage; static GLuint _uniform_alphatest_uTexMain; static GLuint _uniform_alphatest_uCamera; @@ -203,6 +238,9 @@ static void shader_alphatest_uMdl(m4x3f m){ static void shader_alphatest_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_alphatest_uPv,1,GL_FALSE,(float*)m); } +static void shader_alphatest_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_alphatest_uPvmPrev,1,GL_FALSE,(float*)m); +} static void shader_alphatest_uTexGarbage(int i){ glUniform1i(_uniform_alphatest_uTexGarbage,i); } @@ -225,6 +263,7 @@ static void shader_alphatest_use(void){ glUseProgram(_shader_alphatest.id); } static void shader_alphatest_link(void){ _uniform_alphatest_uMdl = glGetUniformLocation( _shader_alphatest.id, "uMdl" ); _uniform_alphatest_uPv = glGetUniformLocation( _shader_alphatest.id, "uPv" ); + _uniform_alphatest_uPvmPrev = glGetUniformLocation( _shader_alphatest.id, "uPvmPrev" ); _uniform_alphatest_uTexGarbage = glGetUniformLocation( _shader_alphatest.id, "uTexGarbage" ); _uniform_alphatest_uTexMain = glGetUniformLocation( _shader_alphatest.id, "uTexMain" ); _uniform_alphatest_uCamera = glGetUniformLocation( _shader_alphatest.id, "uCamera" ); diff --git a/shaders/blitblur.fs b/shaders/blitblur.fs index eac828e..8606022 100644 --- a/shaders/blitblur.fs +++ b/shaders/blitblur.fs @@ -1,5 +1,8 @@ out vec4 FragColor; uniform sampler2D uTexMain; +uniform sampler2D uTexMotion; +uniform float uBlurStrength; +uniform float uBlurExponent; in vec2 aUv; @@ -12,10 +15,16 @@ vec2 rand_hash22( vec2 p ) void main() { - vec2 voffset = rand_hash22( aUv ); + vec2 vcenter = (aUv-vec2(0.5))*vec2(2.0); + vec2 vrand = rand_hash22( aUv ) * 2.0 - vec2(1.0); + vec2 vrand1 = rand_hash22( vrand ) * 2.0 - vec2(1.0); - float bamt = abs(aUv.x-0.5)*2.0; - bamt = pow(bamt,4.0)*0.05; + vec2 vdir = texture( uTexMotion, aUv ).xy * uBlurStrength; - FragColor = texture( uTexMain, aUv + voffset*bamt ); + vec4 vcolour0 = texture( uTexMain, aUv + vdir*vrand.x ); + vec4 vcolour1 = texture( uTexMain, aUv + vdir*vrand.y ); + vec4 vcolour2 = texture( uTexMain, aUv + vdir*vrand1.x ); + vec4 vcolour3 = texture( uTexMain, aUv + vdir*vrand1.y ); + + FragColor = ( vcolour0 + vcolour1 + vcolour2 + vcolour3 ) * 0.25; } diff --git a/shaders/blitblur.h b/shaders/blitblur.h index b754d12..e341cea 100644 --- a/shaders/blitblur.h +++ b/shaders/blitblur.h @@ -22,6 +22,9 @@ static struct vg_shader _shader_blitblur = { .static_src = "out vec4 FragColor;\n" "uniform sampler2D uTexMain;\n" +"uniform sampler2D uTexMotion;\n" +"uniform float uBlurStrength;\n" +"uniform float uBlurExponent;\n" "\n" "in vec2 aUv;\n" "\n" @@ -34,25 +37,46 @@ static struct vg_shader _shader_blitblur = { "\n" "void main()\n" "{\n" -" vec2 voffset = rand_hash22( aUv );\n" +" vec2 vcenter = (aUv-vec2(0.5))*vec2(2.0);\n" +" vec2 vrand = rand_hash22( aUv ) * 2.0 - vec2(1.0);\n" +" vec2 vrand1 = rand_hash22( vrand ) * 2.0 - vec2(1.0);\n" " \n" -" float bamt = abs(aUv.x-0.5)*2.0;\n" -" bamt = pow(bamt,4.0)*0.05;\n" +" vec2 vdir = texture( uTexMotion, aUv ).xy * uBlurStrength;\n" "\n" -" FragColor = texture( uTexMain, aUv + voffset*bamt );\n" +" vec4 vcolour0 = texture( uTexMain, aUv + vdir*vrand.x );\n" +" vec4 vcolour1 = texture( uTexMain, aUv + vdir*vrand.y );\n" +" vec4 vcolour2 = texture( uTexMain, aUv + vdir*vrand1.x );\n" +" vec4 vcolour3 = texture( uTexMain, aUv + vdir*vrand1.y );\n" +"\n" +" FragColor = ( vcolour0 + vcolour1 + vcolour2 + vcolour3 ) * 0.25;\n" "}\n" ""}, }; static GLuint _uniform_blitblur_uTexMain; +static GLuint _uniform_blitblur_uTexMotion; +static GLuint _uniform_blitblur_uBlurStrength; +static GLuint _uniform_blitblur_uBlurExponent; static void shader_blitblur_uTexMain(int i){ glUniform1i(_uniform_blitblur_uTexMain,i); } +static void shader_blitblur_uTexMotion(int i){ + glUniform1i(_uniform_blitblur_uTexMotion,i); +} +static void shader_blitblur_uBlurStrength(float f){ + glUniform1f(_uniform_blitblur_uBlurStrength,f); +} +static void shader_blitblur_uBlurExponent(float f){ + glUniform1f(_uniform_blitblur_uBlurExponent,f); +} static void shader_blitblur_register(void){ vg_shader_register( &_shader_blitblur ); } static void shader_blitblur_use(void){ glUseProgram(_shader_blitblur.id); } static void shader_blitblur_link(void){ _uniform_blitblur_uTexMain = glGetUniformLocation( _shader_blitblur.id, "uTexMain" ); + _uniform_blitblur_uTexMotion = glGetUniformLocation( _shader_blitblur.id, "uTexMotion" ); + _uniform_blitblur_uBlurStrength = glGetUniformLocation( _shader_blitblur.id, "uBlurStrength" ); + _uniform_blitblur_uBlurExponent = glGetUniformLocation( _shader_blitblur.id, "uBlurExponent" ); } #endif /* SHADER_blitblur_H */ diff --git a/shaders/blitcolour.h b/shaders/blitcolour.h new file mode 100644 index 0000000..68880e3 --- /dev/null +++ b/shaders/blitcolour.h @@ -0,0 +1,46 @@ +#ifndef SHADER_blitcolour_H +#define SHADER_blitcolour_H +static void shader_blitcolour_link(void); +static void shader_blitcolour_register(void); +static struct vg_shader _shader_blitcolour = { + .name = "blitcolour", + .link = shader_blitcolour_link, + .vs = +{ +.static_src = +"layout (location=0) in vec2 a_co;\n" +"out vec2 aUv;\n" +"\n" +"void main()\n" +"{\n" +" gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);\n" +" aUv = a_co;\n" +"}\n" +""}, + .fs = +{ +.static_src = +"out vec4 FragColor;\n" +"uniform vec4 uColour;\n" +"\n" +"in vec2 aUv;\n" +"\n" +"void main()\n" +"{\n" +" FragColor = uColour;\n" +"}\n" +""}, +}; + +static GLuint _uniform_blitcolour_uColour; +static void shader_blitcolour_uColour(v4f v){ + glUniform4fv(_uniform_blitcolour_uColour,1,v); +} +static void shader_blitcolour_register(void){ + vg_shader_register( &_shader_blitcolour ); +} +static void shader_blitcolour_use(void){ glUseProgram(_shader_blitcolour.id); } +static void shader_blitcolour_link(void){ + _uniform_blitcolour_uColour = glGetUniformLocation( _shader_blitcolour.id, "uColour" ); +} +#endif /* SHADER_blitcolour_H */ diff --git a/shaders/common_world.glsl b/shaders/common_world.glsl index d7b3ccf..a394acb 100644 --- a/shaders/common_world.glsl +++ b/shaders/common_world.glsl @@ -1,3 +1,5 @@ +layout (location = 0) out vec4 oColour; + layout (std140) uniform ub_world_lighting { vec4 g_light_colours[3]; diff --git a/shaders/gpos.h b/shaders/gpos.h index 8549ec4..b60fb75 100644 --- a/shaders/gpos.h +++ b/shaders/gpos.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_gpos = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "out vec4 aColour;\n" "out vec2 aUv;\n" @@ -28,13 +40,18 @@ static struct vg_shader _shader_gpos = { "\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4( a_co, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 );\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = @@ -51,6 +68,8 @@ static struct vg_shader _shader_gpos = { "in vec3 aWorldCo;\n" "\n" "#line 1 1 \n" +"layout (location = 0) out vec4 oColour;\n" +"\n" "layout (std140) uniform ub_world_lighting\n" "{\n" " vec4 g_light_colours[3];\n" @@ -180,6 +199,7 @@ static struct vg_shader _shader_gpos = { static GLuint _uniform_gpos_uMdl; static GLuint _uniform_gpos_uPv; +static GLuint _uniform_gpos_uPvmPrev; static GLuint _uniform_gpos_uCamera; static GLuint _uniform_gpos_g_world_depth; static void shader_gpos_uMdl(m4x3f m){ @@ -188,6 +208,9 @@ static void shader_gpos_uMdl(m4x3f m){ static void shader_gpos_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_gpos_uPv,1,GL_FALSE,(float*)m); } +static void shader_gpos_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_gpos_uPvmPrev,1,GL_FALSE,(float*)m); +} static void shader_gpos_uCamera(v3f v){ glUniform3fv(_uniform_gpos_uCamera,1,v); } @@ -201,6 +224,7 @@ static void shader_gpos_use(void){ glUseProgram(_shader_gpos.id); } static void shader_gpos_link(void){ _uniform_gpos_uMdl = glGetUniformLocation( _shader_gpos.id, "uMdl" ); _uniform_gpos_uPv = glGetUniformLocation( _shader_gpos.id, "uPv" ); + _uniform_gpos_uPvmPrev = glGetUniformLocation( _shader_gpos.id, "uPvmPrev" ); _uniform_gpos_uCamera = glGetUniformLocation( _shader_gpos.id, "uCamera" ); _uniform_gpos_g_world_depth = glGetUniformLocation( _shader_gpos.id, "g_world_depth" ); } diff --git a/shaders/menu.h b/shaders/menu.h index 75ed0dd..2a14ac1 100644 --- a/shaders/menu.h +++ b/shaders/menu.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_menu = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "out vec4 aColour;\n" "out vec2 aUv;\n" @@ -28,13 +40,18 @@ static struct vg_shader _shader_menu = { "\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4( a_co, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 );\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = @@ -64,6 +81,7 @@ static struct vg_shader _shader_menu = { static GLuint _uniform_menu_uMdl; static GLuint _uniform_menu_uPv; +static GLuint _uniform_menu_uPvmPrev; static GLuint _uniform_menu_uTexMain; static GLuint _uniform_menu_uColour; static void shader_menu_uMdl(m4x3f m){ @@ -72,6 +90,9 @@ static void shader_menu_uMdl(m4x3f m){ static void shader_menu_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_menu_uPv,1,GL_FALSE,(float*)m); } +static void shader_menu_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_menu_uPvmPrev,1,GL_FALSE,(float*)m); +} static void shader_menu_uTexMain(int i){ glUniform1i(_uniform_menu_uTexMain,i); } @@ -85,6 +106,7 @@ static void shader_menu_use(void){ glUseProgram(_shader_menu.id); } static void shader_menu_link(void){ _uniform_menu_uMdl = glGetUniformLocation( _shader_menu.id, "uMdl" ); _uniform_menu_uPv = glGetUniformLocation( _shader_menu.id, "uPv" ); + _uniform_menu_uPvmPrev = glGetUniformLocation( _shader_menu.id, "uPvmPrev" ); _uniform_menu_uTexMain = glGetUniformLocation( _shader_menu.id, "uTexMain" ); _uniform_menu_uColour = glGetUniformLocation( _shader_menu.id, "uColour" ); } diff --git a/shaders/motion_vectors_fs.glsl b/shaders/motion_vectors_fs.glsl new file mode 100644 index 0000000..e6d2759 --- /dev/null +++ b/shaders/motion_vectors_fs.glsl @@ -0,0 +1,12 @@ +layout (location = 1) out vec2 oMotionVec; + +in vec3 aMotionVec0; +in vec3 aMotionVec1; + +void compute_motion_vectors() +{ + // Write motion vectors + vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z; + vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z; + oMotionVec = vmotion1-vmotion0; +} diff --git a/shaders/motion_vectors_vs.glsl b/shaders/motion_vectors_vs.glsl new file mode 100644 index 0000000..25c176d --- /dev/null +++ b/shaders/motion_vectors_vs.glsl @@ -0,0 +1,8 @@ +out vec3 aMotionVec0; +out vec3 aMotionVec1; + +void vs_motion_out( vec4 vproj0, vec4 vproj1 ) +{ + aMotionVec0 = vec3( vproj0.xy, vproj0.w ); + aMotionVec1 = vec3( vproj1.xy, vproj1.w ); +} diff --git a/shaders/planeinf.h b/shaders/planeinf.h index 4cf5c32..e617768 100644 --- a/shaders/planeinf.h +++ b/shaders/planeinf.h @@ -20,21 +20,34 @@ static struct vg_shader _shader_planeinf = { "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" "\n" +"uniform mat4x3 uMotion;\n" +"\n" "out vec4 aColour;\n" "out vec2 aUv;\n" "out vec3 aNorm;\n" "out vec3 aCo;\n" "out vec3 aWorldCo;\n" "\n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4(a_co,1.0);\n" +" vec3 world_pos1 = uMotion * vec4(world_pos0,1.0);\n" +" \n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPv * vec4( world_pos1, 1.0 );\n" +"\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = @@ -72,6 +85,7 @@ static struct vg_shader _shader_planeinf = { static GLuint _uniform_planeinf_uMdl; static GLuint _uniform_planeinf_uPv; +static GLuint _uniform_planeinf_uMotion; static GLuint _uniform_planeinf_uCamera; static GLuint _uniform_planeinf_uPlane; static void shader_planeinf_uMdl(m4x3f m){ @@ -80,6 +94,9 @@ static void shader_planeinf_uMdl(m4x3f m){ static void shader_planeinf_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_planeinf_uPv,1,GL_FALSE,(float*)m); } +static void shader_planeinf_uMotion(m4x3f m){ + glUniformMatrix4x3fv(_uniform_planeinf_uMotion,1,GL_FALSE,(float*)m); +} static void shader_planeinf_uCamera(v3f v){ glUniform3fv(_uniform_planeinf_uCamera,1,v); } @@ -93,6 +110,7 @@ static void shader_planeinf_use(void){ glUseProgram(_shader_planeinf.id); } static void shader_planeinf_link(void){ _uniform_planeinf_uMdl = glGetUniformLocation( _shader_planeinf.id, "uMdl" ); _uniform_planeinf_uPv = glGetUniformLocation( _shader_planeinf.id, "uPv" ); + _uniform_planeinf_uMotion = glGetUniformLocation( _shader_planeinf.id, "uMotion" ); _uniform_planeinf_uCamera = glGetUniformLocation( _shader_planeinf.id, "uCamera" ); _uniform_planeinf_uPlane = glGetUniformLocation( _shader_planeinf.id, "uPlane" ); } diff --git a/shaders/route.fs b/shaders/route.fs index dfaa7f9..3e82be7 100644 --- a/shaders/route.fs +++ b/shaders/route.fs @@ -1,5 +1,3 @@ -out vec4 FragColor; - uniform sampler2D uTexGarbage; uniform sampler2D uTexGradients; uniform vec3 uCamera; @@ -12,9 +10,12 @@ in vec3 aCo; in vec3 aWorldCo; #include "common_world.glsl" +#include "motion_vectors_fs.glsl" void main() { + compute_motion_vectors(); + vec3 vfrag = vec3(0.5,0.5,0.5); // ws modulation @@ -52,5 +53,5 @@ void main() vfrag = do_light_shadowing( vfrag ); vfrag = apply_fog( vfrag, fdist ); - FragColor = vec4(vfrag, 1.0 ); + oColour = vec4(vfrag, 1.0 ); } diff --git a/shaders/route.h b/shaders/route.h index 44fc213..521df23 100644 --- a/shaders/route.h +++ b/shaders/route.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_route = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "out vec4 aColour;\n" "out vec2 aUv;\n" @@ -28,20 +40,23 @@ static struct vg_shader _shader_route = { "\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4( a_co, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 );\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = { .static_src = -"out vec4 FragColor;\n" -"\n" "uniform sampler2D uTexGarbage;\n" "uniform sampler2D uTexGradients;\n" "uniform vec3 uCamera;\n" @@ -54,6 +69,8 @@ static struct vg_shader _shader_route = { "in vec3 aWorldCo;\n" "\n" "#line 1 1 \n" +"layout (location = 0) out vec4 oColour;\n" +"\n" "layout (std140) uniform ub_world_lighting\n" "{\n" " vec4 g_light_colours[3];\n" @@ -157,10 +174,27 @@ static struct vg_shader _shader_route = { " return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n" "}\n" "\n" -"#line 15 0 \n" +"#line 13 0 \n" +"#line 1 2 \n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +" oMotionVec = vmotion1-vmotion0;\n" +"}\n" +"\n" +"#line 14 0 \n" "\n" "void main()\n" "{\n" +" compute_motion_vectors();\n" +"\n" " vec3 vfrag = vec3(0.5,0.5,0.5);\n" "\n" " // ws modulation\n" @@ -198,13 +232,14 @@ static struct vg_shader _shader_route = { " vfrag = do_light_shadowing( vfrag );\n" " vfrag = apply_fog( vfrag, fdist );\n" "\n" -" FragColor = vec4(vfrag, 1.0 );\n" +" oColour = vec4(vfrag, 1.0 );\n" "}\n" ""}, }; static GLuint _uniform_route_uMdl; static GLuint _uniform_route_uPv; +static GLuint _uniform_route_uPvmPrev; static GLuint _uniform_route_uTexGarbage; static GLuint _uniform_route_uTexGradients; static GLuint _uniform_route_uCamera; @@ -216,6 +251,9 @@ static void shader_route_uMdl(m4x3f m){ static void shader_route_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_route_uPv,1,GL_FALSE,(float*)m); } +static void shader_route_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_route_uPvmPrev,1,GL_FALSE,(float*)m); +} static void shader_route_uTexGarbage(int i){ glUniform1i(_uniform_route_uTexGarbage,i); } @@ -238,6 +276,7 @@ static void shader_route_use(void){ glUseProgram(_shader_route.id); } static void shader_route_link(void){ _uniform_route_uMdl = glGetUniformLocation( _shader_route.id, "uMdl" ); _uniform_route_uPv = glGetUniformLocation( _shader_route.id, "uPv" ); + _uniform_route_uPvmPrev = glGetUniformLocation( _shader_route.id, "uPvmPrev" ); _uniform_route_uTexGarbage = glGetUniformLocation( _shader_route.id, "uTexGarbage" ); _uniform_route_uTexGradients = glGetUniformLocation( _shader_route.id, "uTexGradients" ); _uniform_route_uCamera = glGetUniformLocation( _shader_route.id, "uCamera" ); diff --git a/shaders/scoretext.h b/shaders/scoretext.h index fae077e..55734a3 100644 --- a/shaders/scoretext.h +++ b/shaders/scoretext.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_scoretext = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" -"uniform mat4 uPv;\n" "uniform mat4x3 uMdl;\n" +"uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "uniform vec3 uInfo;\n" "\n" @@ -47,8 +59,16 @@ static struct vg_shader _shader_scoretext = { " mlocal[2] = vec3(0.0,0.0,1.0);\n" " mlocal[3] = vec3(c*r,uInfo.y*0.875 + s*r,uInfo.x*0.5);\n" "\n" -" vec3 world_pos = uMdl * vec4(mlocal * vec4(a_co,1.0),1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 local_pos = mlocal * vec4( a_co, 1.0 );\n" +" vec3 world_pos = uMdl * vec4( local_pos, 1.0 );\n" +"\n" +" vec4 vproj0 = uPv * vec4( world_pos, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( local_pos, 1.0 );\n" +"\n" +" // Output\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" " aColour = a_colour;\n" " aUv = a_uv + vec2( floor(uInfo.z+0.5)*(1.0/64.0), yoff );\n" " aNorm = mat3(uMdl) * mat3(mlocal) * a_norm;\n" @@ -59,8 +79,6 @@ static struct vg_shader _shader_scoretext = { .fs = { .static_src = -"out vec4 FragColor;\n" -"\n" "uniform sampler2D uTexGarbage;\n" "uniform sampler2D uTexGradients;\n" "uniform vec3 uCamera;\n" @@ -72,6 +90,8 @@ static struct vg_shader _shader_scoretext = { "in vec3 aWorldCo;\n" "\n" "#line 1 1 \n" +"layout (location = 0) out vec4 oColour;\n" +"\n" "layout (std140) uniform ub_world_lighting\n" "{\n" " vec4 g_light_colours[3];\n" @@ -175,10 +195,27 @@ static struct vg_shader _shader_scoretext = { " return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n" "}\n" "\n" -"#line 14 0 \n" +"#line 12 0 \n" +"#line 1 2 \n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +" oMotionVec = vmotion1-vmotion0;\n" +"}\n" +"\n" +"#line 13 0 \n" "\n" "void main()\n" "{\n" +" compute_motion_vectors();\n" +"\n" " vec3 vfrag = vec3(0.5,0.5,0.5);\n" "\n" " // ws modulation\n" @@ -217,23 +254,27 @@ static struct vg_shader _shader_scoretext = { " vfrag = do_light_shadowing( vfrag );\n" " vfrag = apply_fog( vfrag, fdist );\n" "\n" -" FragColor = vec4(vfrag, 1.0 );\n" +" oColour = vec4(vfrag, 1.0 );\n" "}\n" ""}, }; -static GLuint _uniform_scoretext_uPv; static GLuint _uniform_scoretext_uMdl; +static GLuint _uniform_scoretext_uPv; +static GLuint _uniform_scoretext_uPvmPrev; static GLuint _uniform_scoretext_uInfo; static GLuint _uniform_scoretext_uTexGarbage; static GLuint _uniform_scoretext_uTexGradients; static GLuint _uniform_scoretext_uCamera; static GLuint _uniform_scoretext_g_world_depth; +static void shader_scoretext_uMdl(m4x3f m){ + glUniformMatrix4x3fv(_uniform_scoretext_uMdl,1,GL_FALSE,(float*)m); +} static void shader_scoretext_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_scoretext_uPv,1,GL_FALSE,(float*)m); } -static void shader_scoretext_uMdl(m4x3f m){ - glUniformMatrix4x3fv(_uniform_scoretext_uMdl,1,GL_FALSE,(float*)m); +static void shader_scoretext_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_scoretext_uPvmPrev,1,GL_FALSE,(float*)m); } static void shader_scoretext_uInfo(v3f v){ glUniform3fv(_uniform_scoretext_uInfo,1,v); @@ -255,8 +296,9 @@ static void shader_scoretext_register(void){ } static void shader_scoretext_use(void){ glUseProgram(_shader_scoretext.id); } static void shader_scoretext_link(void){ - _uniform_scoretext_uPv = glGetUniformLocation( _shader_scoretext.id, "uPv" ); _uniform_scoretext_uMdl = glGetUniformLocation( _shader_scoretext.id, "uMdl" ); + _uniform_scoretext_uPv = glGetUniformLocation( _shader_scoretext.id, "uPv" ); + _uniform_scoretext_uPvmPrev = glGetUniformLocation( _shader_scoretext.id, "uPvmPrev" ); _uniform_scoretext_uInfo = glGetUniformLocation( _shader_scoretext.id, "uInfo" ); _uniform_scoretext_uTexGarbage = glGetUniformLocation( _shader_scoretext.id, "uTexGarbage" ); _uniform_scoretext_uTexGradients = glGetUniformLocation( _shader_scoretext.id, "uTexGradients" ); diff --git a/shaders/scoretext.vs b/shaders/scoretext.vs index bcd5b95..ab714d6 100644 --- a/shaders/scoretext.vs +++ b/shaders/scoretext.vs @@ -1,7 +1,9 @@ #include "vertex_standard.glsl" +#include "motion_vectors_vs.glsl" -uniform mat4 uPv; uniform mat4x3 uMdl; +uniform mat4 uPv; +uniform mat4 uPvmPrev; uniform vec3 uInfo; @@ -30,8 +32,16 @@ void main() mlocal[2] = vec3(0.0,0.0,1.0); mlocal[3] = vec3(c*r,uInfo.y*0.875 + s*r,uInfo.x*0.5); - vec3 world_pos = uMdl * vec4(mlocal * vec4(a_co,1.0),1.0); - gl_Position = uPv * vec4( world_pos, 1.0 ); + vec3 local_pos = mlocal * vec4( a_co, 1.0 ); + vec3 world_pos = uMdl * vec4( local_pos, 1.0 ); + + vec4 vproj0 = uPv * vec4( world_pos, 1.0 ); + vec4 vproj1 = uPvmPrev * vec4( local_pos, 1.0 ); + + // Output + vs_motion_out( vproj0, vproj1 ); + + gl_Position = vproj0; aColour = a_colour; aUv = a_uv + vec2( floor(uInfo.z+0.5)*(1.0/64.0), yoff ); aNorm = mat3(uMdl) * mat3(mlocal) * a_norm; diff --git a/shaders/sky.fs b/shaders/sky.fs index ad050db..036f244 100644 --- a/shaders/sky.fs +++ b/shaders/sky.fs @@ -1,4 +1,4 @@ -out vec4 FragColor; +layout (location = 0) out vec4 oColour; uniform vec4 uColour; uniform sampler2D uTexGarbage; @@ -9,8 +9,12 @@ in vec2 aUv; in vec3 aNorm; in vec3 aCo; +#include "motion_vectors_fs.glsl" + void main() { + compute_motion_vectors(); + float fintensity = 1.0-(abs(aNorm.y)*0.7); float fblend = pow(fintensity,4.0); vec3 horizon = vec3( 0.8, 0.9, 0.9 ); @@ -29,5 +33,5 @@ void main() float fhorizon = step( aNorm.y * 0.5 + 0.5, 0.5 ); vec3 skycomp = mix(diffuse, vec3(1.0,1.0,1.0), cloud_e); - FragColor = vec4(pow(skycomp, vec3(1.5)),1.0); + oColour = vec4(pow(skycomp, vec3(1.5)),1.0); } diff --git a/shaders/sky.h b/shaders/sky.h index b93549b..fa0546f 100644 --- a/shaders/sky.h +++ b/shaders/sky.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_sky = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "out vec4 aColour;\n" "out vec2 aUv;\n" @@ -28,19 +40,24 @@ static struct vg_shader _shader_sky = { "\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4( a_co, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 );\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = { .static_src = -"out vec4 FragColor;\n" +"layout (location = 0) out vec4 oColour;\n" "\n" "uniform vec4 uColour;\n" "uniform sampler2D uTexGarbage;\n" @@ -51,8 +68,26 @@ static struct vg_shader _shader_sky = { "in vec3 aNorm;\n" "in vec3 aCo;\n" "\n" +"#line 1 1 \n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +" oMotionVec = vmotion1-vmotion0;\n" +"}\n" +"\n" +"#line 13 0 \n" +"\n" "void main()\n" "{\n" +" compute_motion_vectors();\n" +"\n" " float fintensity = 1.0-(abs(aNorm.y)*0.7);\n" " float fblend = pow(fintensity,4.0);\n" " vec3 horizon = vec3( 0.8, 0.9, 0.9 );\n" @@ -71,13 +106,14 @@ static struct vg_shader _shader_sky = { " float fhorizon = step( aNorm.y * 0.5 + 0.5, 0.5 );\n" "\n" " vec3 skycomp = mix(diffuse, vec3(1.0,1.0,1.0), cloud_e);\n" -" FragColor = vec4(pow(skycomp, vec3(1.5)),1.0);\n" +" oColour = vec4(pow(skycomp, vec3(1.5)),1.0);\n" "}\n" ""}, }; static GLuint _uniform_sky_uMdl; static GLuint _uniform_sky_uPv; +static GLuint _uniform_sky_uPvmPrev; static GLuint _uniform_sky_uColour; static GLuint _uniform_sky_uTexGarbage; static GLuint _uniform_sky_uTime; @@ -87,6 +123,9 @@ static void shader_sky_uMdl(m4x3f m){ static void shader_sky_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_sky_uPv,1,GL_FALSE,(float*)m); } +static void shader_sky_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_sky_uPvmPrev,1,GL_FALSE,(float*)m); +} static void shader_sky_uColour(v4f v){ glUniform4fv(_uniform_sky_uColour,1,v); } @@ -103,6 +142,7 @@ static void shader_sky_use(void){ glUseProgram(_shader_sky.id); } static void shader_sky_link(void){ _uniform_sky_uMdl = glGetUniformLocation( _shader_sky.id, "uMdl" ); _uniform_sky_uPv = glGetUniformLocation( _shader_sky.id, "uPv" ); + _uniform_sky_uPvmPrev = glGetUniformLocation( _shader_sky.id, "uPvmPrev" ); _uniform_sky_uColour = glGetUniformLocation( _shader_sky.id, "uColour" ); _uniform_sky_uTexGarbage = glGetUniformLocation( _shader_sky.id, "uTexGarbage" ); _uniform_sky_uTime = glGetUniformLocation( _shader_sky.id, "uTime" ); diff --git a/shaders/standard.fs b/shaders/standard.fs index d3a6842..58678f0 100644 --- a/shaders/standard.fs +++ b/shaders/standard.fs @@ -1,5 +1,3 @@ -out vec4 FragColor; - uniform sampler2D uTexGarbage; uniform sampler2D uTexMain; uniform vec3 uCamera; @@ -12,9 +10,12 @@ in vec3 aCo; in vec3 aWorldCo; #include "common_world.glsl" +#include "motion_vectors_fs.glsl" void main() { + compute_motion_vectors(); + vec3 vfrag = vec3(0.5,0.5,0.5); vec4 vsamplemain = texture( uTexMain, aUv ); vec3 qnorm = normalize(aNorm); @@ -36,5 +37,5 @@ void main() vfrag = do_light_shadowing( vfrag ); vfrag = apply_fog( vfrag, fdist ); - FragColor = vec4(vfrag, 1.0); + oColour = vec4(vfrag, 1.0); } diff --git a/shaders/standard.h b/shaders/standard.h index 4d52aa8..3c759b6 100644 --- a/shaders/standard.h +++ b/shaders/standard.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_standard = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "out vec4 aColour;\n" "out vec2 aUv;\n" @@ -28,20 +40,23 @@ static struct vg_shader _shader_standard = { "\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4( a_co, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 );\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = { .static_src = -"out vec4 FragColor;\n" -"\n" "uniform sampler2D uTexGarbage;\n" "uniform sampler2D uTexMain;\n" "uniform vec3 uCamera;\n" @@ -54,6 +69,8 @@ static struct vg_shader _shader_standard = { "in vec3 aWorldCo;\n" "\n" "#line 1 1 \n" +"layout (location = 0) out vec4 oColour;\n" +"\n" "layout (std140) uniform ub_world_lighting\n" "{\n" " vec4 g_light_colours[3];\n" @@ -157,10 +174,27 @@ static struct vg_shader _shader_standard = { " return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n" "}\n" "\n" -"#line 15 0 \n" +"#line 13 0 \n" +"#line 1 2 \n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +" oMotionVec = vmotion1-vmotion0;\n" +"}\n" +"\n" +"#line 14 0 \n" "\n" "void main()\n" "{\n" +" compute_motion_vectors();\n" +"\n" " vec3 vfrag = vec3(0.5,0.5,0.5);\n" " vec4 vsamplemain = texture( uTexMain, aUv );\n" " vec3 qnorm = normalize(aNorm);\n" @@ -182,13 +216,14 @@ static struct vg_shader _shader_standard = { " vfrag = do_light_shadowing( vfrag );\n" " vfrag = apply_fog( vfrag, fdist );\n" "\n" -" FragColor = vec4(vfrag, 1.0);\n" +" oColour = vec4(vfrag, 1.0);\n" "}\n" ""}, }; static GLuint _uniform_standard_uMdl; static GLuint _uniform_standard_uPv; +static GLuint _uniform_standard_uPvmPrev; static GLuint _uniform_standard_uTexGarbage; static GLuint _uniform_standard_uTexMain; static GLuint _uniform_standard_uCamera; @@ -200,6 +235,9 @@ static void shader_standard_uMdl(m4x3f m){ static void shader_standard_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_standard_uPv,1,GL_FALSE,(float*)m); } +static void shader_standard_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_standard_uPvmPrev,1,GL_FALSE,(float*)m); +} static void shader_standard_uTexGarbage(int i){ glUniform1i(_uniform_standard_uTexGarbage,i); } @@ -222,6 +260,7 @@ static void shader_standard_use(void){ glUseProgram(_shader_standard.id); } static void shader_standard_link(void){ _uniform_standard_uMdl = glGetUniformLocation( _shader_standard.id, "uMdl" ); _uniform_standard_uPv = glGetUniformLocation( _shader_standard.id, "uPv" ); + _uniform_standard_uPvmPrev = glGetUniformLocation( _shader_standard.id, "uPvmPrev" ); _uniform_standard_uTexGarbage = glGetUniformLocation( _shader_standard.id, "uTexGarbage" ); _uniform_standard_uTexMain = glGetUniformLocation( _shader_standard.id, "uTexMain" ); _uniform_standard_uCamera = glGetUniformLocation( _shader_standard.id, "uCamera" ); diff --git a/shaders/standard.vs b/shaders/standard.vs index 33f4154..679eae8 100644 --- a/shaders/standard.vs +++ b/shaders/standard.vs @@ -1,7 +1,9 @@ #include "vertex_standard.glsl" +#include "motion_vectors_vs.glsl" uniform mat4x3 uMdl; uniform mat4 uPv; +uniform mat4 uPvmPrev; out vec4 aColour; out vec2 aUv; @@ -11,11 +13,16 @@ out vec3 aWorldCo; void main() { - vec3 world_pos = uMdl * vec4(a_co,1.0); - gl_Position = uPv * vec4( world_pos, 1.0 ); + vec3 world_pos0 = uMdl * vec4( a_co, 1.0 ); + vec4 vproj0 = uPv * vec4( world_pos0, 1.0 ); + vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 ); + + vs_motion_out( vproj0, vproj1 ); + + gl_Position = vproj0; + aWorldCo = world_pos0; aColour = a_colour; aUv = a_uv; aNorm = mat3(uMdl) * a_norm; aCo = a_co; - aWorldCo = world_pos; } diff --git a/shaders/standard_skinned.vs b/shaders/standard_skinned.vs index 5c959a0..0893795 100644 --- a/shaders/standard_skinned.vs +++ b/shaders/standard_skinned.vs @@ -1,6 +1,10 @@ #include "vertex_standard.glsl" +#include "motion_vectors_vs.glsl" uniform mat4 uPv; + +// TODO: Send a previous transform matrix stack +// uniform mat4x3 uTransforms[32]; out vec4 aColour; @@ -28,4 +32,8 @@ void main() aNorm = world_normal; aCo = a_co; aWorldCo = world_pos; + + // TODO: + aMotionVec0 = vec3(1.0); + aMotionVec1 = vec3(1.0); } diff --git a/shaders/std_alphatest.fs b/shaders/std_alphatest.fs index 7881b51..b0f18fd 100644 --- a/shaders/std_alphatest.fs +++ b/shaders/std_alphatest.fs @@ -1,5 +1,3 @@ -out vec4 FragColor; - uniform sampler2D uTexGarbage; uniform sampler2D uTexMain; uniform vec3 uCamera; @@ -12,9 +10,12 @@ in vec3 aCo; in vec3 aWorldCo; #include "common_world.glsl" +#include "motion_vectors_fs.glsl" void main() { + compute_motion_vectors(); + vec3 vfrag = vec3(0.5,0.5,0.5); vec4 vsamplemain = texture( uTexMain, aUv ); vec3 qnorm = normalize(aNorm); @@ -39,5 +40,5 @@ void main() vfrag = do_light_shadowing( vfrag ); vfrag = apply_fog( vfrag, fdist ); - FragColor = vec4(vfrag, 1.0); + oColour = vec4(vfrag, 1.0); } diff --git a/shaders/terrain.fs b/shaders/terrain.fs index f093904..6e01684 100644 --- a/shaders/terrain.fs +++ b/shaders/terrain.fs @@ -1,5 +1,3 @@ -out vec4 FragColor; - uniform sampler2D uTexGarbage; uniform sampler2D uTexGradients; uniform vec3 uCamera; @@ -13,9 +11,14 @@ in vec3 aCo; in vec3 aWorldCo; #include "common_world.glsl" +#include "motion_vectors_fs.glsl" void main() { + compute_motion_vectors(); + + // Colour + // ------ vec3 vfrag = vec3(0.5,0.5,0.5); // ws modulation @@ -55,5 +58,5 @@ void main() vfrag = do_light_shadowing( vfrag ); vfrag = apply_fog( vfrag, fdist ); - FragColor = vec4(vfrag, 1.0 ); + oColour = vec4(vfrag, 1.0 ); } diff --git a/shaders/terrain.h b/shaders/terrain.h index 6b4c3de..460ba9e 100644 --- a/shaders/terrain.h +++ b/shaders/terrain.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_terrain = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "out vec4 aColour;\n" "out vec2 aUv;\n" @@ -28,20 +40,23 @@ static struct vg_shader _shader_terrain = { "\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4( a_co, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 );\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = { .static_src = -"out vec4 FragColor;\n" -"\n" "uniform sampler2D uTexGarbage;\n" "uniform sampler2D uTexGradients;\n" "uniform vec3 uCamera;\n" @@ -55,6 +70,8 @@ static struct vg_shader _shader_terrain = { "in vec3 aWorldCo;\n" "\n" "#line 1 1 \n" +"layout (location = 0) out vec4 oColour;\n" +"\n" "layout (std140) uniform ub_world_lighting\n" "{\n" " vec4 g_light_colours[3];\n" @@ -158,10 +175,29 @@ static struct vg_shader _shader_terrain = { " return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n" "}\n" "\n" -"#line 16 0 \n" +"#line 14 0 \n" +"#line 1 2 \n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +" oMotionVec = vmotion1-vmotion0;\n" +"}\n" +"\n" +"#line 15 0 \n" "\n" "void main()\n" "{\n" +" compute_motion_vectors();\n" +"\n" +" // Colour\n" +" // ------\n" " vec3 vfrag = vec3(0.5,0.5,0.5);\n" "\n" " // ws modulation\n" @@ -201,13 +237,14 @@ static struct vg_shader _shader_terrain = { " vfrag = do_light_shadowing( vfrag );\n" " vfrag = apply_fog( vfrag, fdist );\n" "\n" -" FragColor = vec4(vfrag, 1.0 );\n" +" oColour = vec4(vfrag, 1.0 );\n" "}\n" ""}, }; static GLuint _uniform_terrain_uMdl; static GLuint _uniform_terrain_uPv; +static GLuint _uniform_terrain_uPvmPrev; static GLuint _uniform_terrain_uTexGarbage; static GLuint _uniform_terrain_uTexGradients; static GLuint _uniform_terrain_uCamera; @@ -220,6 +257,9 @@ static void shader_terrain_uMdl(m4x3f m){ static void shader_terrain_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_terrain_uPv,1,GL_FALSE,(float*)m); } +static void shader_terrain_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_terrain_uPvmPrev,1,GL_FALSE,(float*)m); +} static void shader_terrain_uTexGarbage(int i){ glUniform1i(_uniform_terrain_uTexGarbage,i); } @@ -245,6 +285,7 @@ static void shader_terrain_use(void){ glUseProgram(_shader_terrain.id); } static void shader_terrain_link(void){ _uniform_terrain_uMdl = glGetUniformLocation( _shader_terrain.id, "uMdl" ); _uniform_terrain_uPv = glGetUniformLocation( _shader_terrain.id, "uPv" ); + _uniform_terrain_uPvmPrev = glGetUniformLocation( _shader_terrain.id, "uPvmPrev" ); _uniform_terrain_uTexGarbage = glGetUniformLocation( _shader_terrain.id, "uTexGarbage" ); _uniform_terrain_uTexGradients = glGetUniformLocation( _shader_terrain.id, "uTexGradients" ); _uniform_terrain_uCamera = glGetUniformLocation( _shader_terrain.id, "uCamera" ); diff --git a/shaders/vblend.fs b/shaders/vblend.fs index a30f83c..9eddd6b 100644 --- a/shaders/vblend.fs +++ b/shaders/vblend.fs @@ -1,5 +1,3 @@ -out vec4 FragColor; - uniform sampler2D uTexGarbage; uniform sampler2D uTexGradients; uniform vec3 uCamera; @@ -11,9 +9,12 @@ in vec3 aCo; in vec3 aWorldCo; #include "common_world.glsl" +#include "motion_vectors_fs.glsl" void main() { + compute_motion_vectors(); + vec3 vfrag = vec3(0.5,0.5,0.5); // ws modulation @@ -52,5 +53,5 @@ void main() vfrag = do_light_shadowing( vfrag ); vfrag = apply_fog( vfrag, fdist ); - FragColor = vec4(vfrag, 1.0 ); + oColour = vec4(vfrag, 1.0 ); } diff --git a/shaders/vblend.h b/shaders/vblend.h index 9e7b0e2..2a5dacf 100644 --- a/shaders/vblend.h +++ b/shaders/vblend.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_vblend = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "out vec4 aColour;\n" "out vec2 aUv;\n" @@ -28,20 +40,23 @@ static struct vg_shader _shader_vblend = { "\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4( a_co, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 );\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = { .static_src = -"out vec4 FragColor;\n" -"\n" "uniform sampler2D uTexGarbage;\n" "uniform sampler2D uTexGradients;\n" "uniform vec3 uCamera;\n" @@ -53,6 +68,8 @@ static struct vg_shader _shader_vblend = { "in vec3 aWorldCo;\n" "\n" "#line 1 1 \n" +"layout (location = 0) out vec4 oColour;\n" +"\n" "layout (std140) uniform ub_world_lighting\n" "{\n" " vec4 g_light_colours[3];\n" @@ -156,10 +173,27 @@ static struct vg_shader _shader_vblend = { " return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n" "}\n" "\n" -"#line 14 0 \n" +"#line 12 0 \n" +"#line 1 2 \n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +" oMotionVec = vmotion1-vmotion0;\n" +"}\n" +"\n" +"#line 13 0 \n" "\n" "void main()\n" "{\n" +" compute_motion_vectors();\n" +"\n" " vec3 vfrag = vec3(0.5,0.5,0.5);\n" "\n" " // ws modulation\n" @@ -198,13 +232,14 @@ static struct vg_shader _shader_vblend = { " vfrag = do_light_shadowing( vfrag );\n" " vfrag = apply_fog( vfrag, fdist );\n" "\n" -" FragColor = vec4(vfrag, 1.0 );\n" +" oColour = vec4(vfrag, 1.0 );\n" "}\n" ""}, }; static GLuint _uniform_vblend_uMdl; static GLuint _uniform_vblend_uPv; +static GLuint _uniform_vblend_uPvmPrev; static GLuint _uniform_vblend_uTexGarbage; static GLuint _uniform_vblend_uTexGradients; static GLuint _uniform_vblend_uCamera; @@ -215,6 +250,9 @@ static void shader_vblend_uMdl(m4x3f m){ static void shader_vblend_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_vblend_uPv,1,GL_FALSE,(float*)m); } +static void shader_vblend_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_vblend_uPvmPrev,1,GL_FALSE,(float*)m); +} static void shader_vblend_uTexGarbage(int i){ glUniform1i(_uniform_vblend_uTexGarbage,i); } @@ -234,6 +272,7 @@ static void shader_vblend_use(void){ glUseProgram(_shader_vblend.id); } static void shader_vblend_link(void){ _uniform_vblend_uMdl = glGetUniformLocation( _shader_vblend.id, "uMdl" ); _uniform_vblend_uPv = glGetUniformLocation( _shader_vblend.id, "uPv" ); + _uniform_vblend_uPvmPrev = glGetUniformLocation( _shader_vblend.id, "uPvmPrev" ); _uniform_vblend_uTexGarbage = glGetUniformLocation( _shader_vblend.id, "uTexGarbage" ); _uniform_vblend_uTexGradients = glGetUniformLocation( _shader_vblend.id, "uTexGradients" ); _uniform_vblend_uCamera = glGetUniformLocation( _shader_vblend.id, "uCamera" ); diff --git a/shaders/viewchar.fs b/shaders/viewchar.fs index 57edff5..f7e0370 100644 --- a/shaders/viewchar.fs +++ b/shaders/viewchar.fs @@ -1,5 +1,3 @@ -out vec4 FragColor; - uniform sampler2D uTexMain; uniform vec3 uCamera; @@ -10,9 +8,12 @@ in vec3 aCo; in vec3 aWorldCo; #include "common_world.glsl" +#include "motion_vectors_fs.glsl" void main() { + compute_motion_vectors(); + vec3 vfrag = texture( uTexMain, aUv ).rgb; // Lighting @@ -28,5 +29,5 @@ void main() vfrag = apply_fog( vfrag, fdist ); float opacity = clamp( fdist*fdist, 0.1, 1.0 ); - FragColor = vec4(vfrag,opacity); + oColour = vec4(vfrag,opacity); } diff --git a/shaders/viewchar.h b/shaders/viewchar.h index 21d98c0..20f33d3 100644 --- a/shaders/viewchar.h +++ b/shaders/viewchar.h @@ -16,8 +16,22 @@ static struct vg_shader _shader_viewchar = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4 uPv;\n" +"\n" +"// TODO: Send a previous transform matrix stack\n" +"//\n" "uniform mat4x3 uTransforms[32];\n" "\n" "out vec4 aColour;\n" @@ -45,13 +59,15 @@ static struct vg_shader _shader_viewchar = { " aNorm = world_normal;\n" " aCo = a_co;\n" " aWorldCo = world_pos;\n" +"\n" +" // TODO:\n" +" aMotionVec0 = vec3(1.0);\n" +" aMotionVec1 = vec3(1.0);\n" "}\n" ""}, .fs = { .static_src = -"out vec4 FragColor;\n" -"\n" "uniform sampler2D uTexMain;\n" "uniform vec3 uCamera;\n" "\n" @@ -62,6 +78,8 @@ static struct vg_shader _shader_viewchar = { "in vec3 aWorldCo;\n" "\n" "#line 1 1 \n" +"layout (location = 0) out vec4 oColour;\n" +"\n" "layout (std140) uniform ub_world_lighting\n" "{\n" " vec4 g_light_colours[3];\n" @@ -165,10 +183,27 @@ static struct vg_shader _shader_viewchar = { " return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n" "}\n" "\n" -"#line 13 0 \n" +"#line 11 0 \n" +"#line 1 2 \n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +" oMotionVec = vmotion1-vmotion0;\n" +"}\n" +"\n" +"#line 12 0 \n" "\n" "void main()\n" "{\n" +" compute_motion_vectors();\n" +"\n" " vec3 vfrag = texture( uTexMain, aUv ).rgb;\n" "\n" " // Lighting\n" @@ -184,7 +219,7 @@ static struct vg_shader _shader_viewchar = { " vfrag = apply_fog( vfrag, fdist );\n" "\n" " float opacity = clamp( fdist*fdist, 0.1, 1.0 );\n" -" FragColor = vec4(vfrag,opacity);\n" +" oColour = vec4(vfrag,opacity);\n" "}\n" ""}, }; diff --git a/shaders/water.fs b/shaders/water.fs index 938c6d1..eced89a 100644 --- a/shaders/water.fs +++ b/shaders/water.fs @@ -1,5 +1,3 @@ -out vec4 FragColor; - uniform sampler2D uTexMain; uniform sampler2D uTexDudv; uniform sampler2D uTexBack; @@ -19,6 +17,7 @@ in vec3 aCo; in vec3 aWorldCo; #include "common_world.glsl" +#include "motion_vectors_fs.glsl" vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue, vec4 beneath, vec4 above ) @@ -43,6 +42,8 @@ vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue, void main() { + compute_motion_vectors(); + // Create texture coords vec2 ssuv = gl_FragCoord.xy*uInvRes; @@ -74,5 +75,5 @@ void main() // Composite vec4 vsurface = water_surf( halfview, surfnorm, depthvalue, beneath, above ); vsurface.a -= fdist; - FragColor = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband ); + oColour = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband ); } diff --git a/shaders/water.h b/shaders/water.h index 6c76dfe..109f29d 100644 --- a/shaders/water.h +++ b/shaders/water.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_water = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "out vec4 aColour;\n" "out vec2 aUv;\n" @@ -28,20 +40,23 @@ static struct vg_shader _shader_water = { "\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4( a_co, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 );\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = { .static_src = -"out vec4 FragColor;\n" -"\n" "uniform sampler2D uTexMain;\n" "uniform sampler2D uTexDudv;\n" "uniform sampler2D uTexBack;\n" @@ -61,6 +76,8 @@ static struct vg_shader _shader_water = { "in vec3 aWorldCo;\n" "\n" "#line 1 1 \n" +"layout (location = 0) out vec4 oColour;\n" +"\n" "layout (std140) uniform ub_world_lighting\n" "{\n" " vec4 g_light_colours[3];\n" @@ -164,7 +181,22 @@ static struct vg_shader _shader_water = { " return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n" "}\n" "\n" -"#line 22 0 \n" +"#line 20 0 \n" +"#line 1 2 \n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +" oMotionVec = vmotion1-vmotion0;\n" +"}\n" +"\n" +"#line 21 0 \n" "\n" "vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue, \n" " vec4 beneath, vec4 above )\n" @@ -189,6 +221,8 @@ static struct vg_shader _shader_water = { "\n" "void main()\n" "{\n" +" compute_motion_vectors();\n" +"\n" " // Create texture coords\n" " vec2 ssuv = gl_FragCoord.xy*uInvRes;\n" " \n" @@ -220,13 +254,14 @@ static struct vg_shader _shader_water = { " // Composite\n" " vec4 vsurface = water_surf( halfview, surfnorm, depthvalue, beneath, above );\n" " vsurface.a -= fdist;\n" -" FragColor = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband );\n" +" oColour = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband );\n" "}\n" ""}, }; static GLuint _uniform_water_uMdl; static GLuint _uniform_water_uPv; +static GLuint _uniform_water_uPvmPrev; static GLuint _uniform_water_uTexMain; static GLuint _uniform_water_uTexDudv; static GLuint _uniform_water_uTexBack; @@ -243,6 +278,9 @@ static void shader_water_uMdl(m4x3f m){ static void shader_water_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_water_uPv,1,GL_FALSE,(float*)m); } +static void shader_water_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_water_uPvmPrev,1,GL_FALSE,(float*)m); +} static void shader_water_uTexMain(int i){ glUniform1i(_uniform_water_uTexMain,i); } @@ -280,6 +318,7 @@ static void shader_water_use(void){ glUseProgram(_shader_water.id); } static void shader_water_link(void){ _uniform_water_uMdl = glGetUniformLocation( _shader_water.id, "uMdl" ); _uniform_water_uPv = glGetUniformLocation( _shader_water.id, "uPv" ); + _uniform_water_uPvmPrev = glGetUniformLocation( _shader_water.id, "uPvmPrev" ); _uniform_water_uTexMain = glGetUniformLocation( _shader_water.id, "uTexMain" ); _uniform_water_uTexDudv = glGetUniformLocation( _shader_water.id, "uTexDudv" ); _uniform_water_uTexBack = glGetUniformLocation( _shader_water.id, "uTexBack" ); diff --git a/shaders/water_fast.fs b/shaders/water_fast.fs index 2919e09..821e47f 100644 --- a/shaders/water_fast.fs +++ b/shaders/water_fast.fs @@ -1,5 +1,3 @@ -out vec4 FragColor; - uniform sampler2D uTexDudv; uniform float uTime; @@ -16,6 +14,7 @@ in vec3 aCo; in vec3 aWorldCo; #include "common_world.glsl" +#include "motion_vectors_fs.glsl" vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue ) { @@ -32,6 +31,8 @@ vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue ) void main() { + compute_motion_vectors(); + // Surface colour composite float depthvalue = clamp( -world_depth_sample( aCo )*(1.0/25.0), 0.0, 1.0 ); @@ -56,5 +57,5 @@ void main() // Composite vec4 vsurface = water_surf( halfview, surfnorm, depthvalue ); vsurface.a -= fdist; - FragColor = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband ); + oColour = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband ); } diff --git a/shaders/water_fast.h b/shaders/water_fast.h index 8cc3f50..3da3db2 100644 --- a/shaders/water_fast.h +++ b/shaders/water_fast.h @@ -16,9 +16,21 @@ static struct vg_shader _shader_water_fast = { "layout (location=5) in ivec4 a_groups;\n" "\n" "#line 2 0 \n" +"#line 1 2 \n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 3 0 \n" "\n" "uniform mat4x3 uMdl;\n" "uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" "\n" "out vec4 aColour;\n" "out vec2 aUv;\n" @@ -28,20 +40,23 @@ static struct vg_shader _shader_water_fast = { "\n" "void main()\n" "{\n" -" vec3 world_pos = uMdl * vec4(a_co,1.0);\n" -" gl_Position = uPv * vec4( world_pos, 1.0 );\n" +" vec3 world_pos0 = uMdl * vec4( a_co, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( a_co, 1.0 );\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" aWorldCo = world_pos0;\n" " aColour = a_colour;\n" " aUv = a_uv;\n" " aNorm = mat3(uMdl) * a_norm;\n" " aCo = a_co;\n" -" aWorldCo = world_pos;\n" "}\n" ""}, .fs = { .static_src = -"out vec4 FragColor;\n" -"\n" "uniform sampler2D uTexDudv;\n" "\n" "uniform float uTime;\n" @@ -58,6 +73,8 @@ static struct vg_shader _shader_water_fast = { "in vec3 aWorldCo;\n" "\n" "#line 1 1 \n" +"layout (location = 0) out vec4 oColour;\n" +"\n" "layout (std140) uniform ub_world_lighting\n" "{\n" " vec4 g_light_colours[3];\n" @@ -161,7 +178,22 @@ static struct vg_shader _shader_water_fast = { " return mix( vfrag, vec3(0.55,0.76,1.0), min( 1.0, dist ) );\n" "}\n" "\n" -"#line 19 0 \n" +"#line 17 0 \n" +"#line 1 2 \n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +" oMotionVec = vmotion1-vmotion0;\n" +"}\n" +"\n" +"#line 18 0 \n" "\n" "vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue )\n" "{\n" @@ -178,6 +210,8 @@ static struct vg_shader _shader_water_fast = { "\n" "void main()\n" "{\n" +" compute_motion_vectors();\n" +"\n" " // Surface colour composite\n" " float depthvalue = clamp( -world_depth_sample( aCo )*(1.0/25.0), 0.0, 1.0 );\n" "\n" @@ -202,13 +236,14 @@ static struct vg_shader _shader_water_fast = { " // Composite\n" " vec4 vsurface = water_surf( halfview, surfnorm, depthvalue );\n" " vsurface.a -= fdist;\n" -" FragColor = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband );\n" +" oColour = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband );\n" "}\n" ""}, }; static GLuint _uniform_water_fast_uMdl; static GLuint _uniform_water_fast_uPv; +static GLuint _uniform_water_fast_uPvmPrev; static GLuint _uniform_water_fast_uTexDudv; static GLuint _uniform_water_fast_uTime; static GLuint _uniform_water_fast_uCamera; @@ -222,6 +257,9 @@ static void shader_water_fast_uMdl(m4x3f m){ static void shader_water_fast_uPv(m4x4f m){ glUniformMatrix4fv(_uniform_water_fast_uPv,1,GL_FALSE,(float*)m); } +static void shader_water_fast_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_water_fast_uPvmPrev,1,GL_FALSE,(float*)m); +} static void shader_water_fast_uTexDudv(int i){ glUniform1i(_uniform_water_fast_uTexDudv,i); } @@ -250,6 +288,7 @@ static void shader_water_fast_use(void){ glUseProgram(_shader_water_fast.id); } static void shader_water_fast_link(void){ _uniform_water_fast_uMdl = glGetUniformLocation( _shader_water_fast.id, "uMdl" ); _uniform_water_fast_uPv = glGetUniformLocation( _shader_water_fast.id, "uPv" ); + _uniform_water_fast_uPvmPrev = glGetUniformLocation( _shader_water_fast.id, "uPvmPrev" ); _uniform_water_fast_uTexDudv = glGetUniformLocation( _shader_water_fast.id, "uTexDudv" ); _uniform_water_fast_uTime = glGetUniformLocation( _shader_water_fast.id, "uTime" ); _uniform_water_fast_uCamera = glGetUniformLocation( _shader_water_fast.id, "uCamera" ); diff --git a/skaterift.c b/skaterift.c index 0b3310a..bb278ff 100644 --- a/skaterift.c +++ b/skaterift.c @@ -12,8 +12,8 @@ */ #define SR_NETWORKED - #include "common.h" +#include "conf.h" #include "steam.h" #include "render.h" #include "audio.h" @@ -22,7 +22,8 @@ #include "network.h" #include "menu.h" -static int cl_ui = 1; +static int cl_ui = 1, + cl_view_id = 0; int main( int argc, char *argv[] ) { @@ -45,20 +46,22 @@ VG_STATIC void vg_launch_opt(void) VG_STATIC void vg_preload(void) { + g_conf_init(); + vg_convar_push( (struct vg_convar){ .name = "cl_ui", .data = &cl_ui, .data_type = k_convar_dtype_i32, .opt_i32 = { .min=0, .max=1, .clamp=1 }, - .persistent = 1 + .persistent = 0 }); vg_convar_push( (struct vg_convar){ - .name = "cl_fov", - .data = &g_fov_option, - .data_type = k_convar_dtype_f32, - .opt_f32 = { .clamp = 0 }, - .persistent = 1 + .name = "cl_view_id", + .data = &cl_view_id, + .data_type = k_convar_dtype_i32, + .opt_i32 = { .min=0, .max=1, .clamp=1 }, + .persistent = 0 }); vg_info(" Copyright . . . -----, ,----- ,---. .---. \n" ); @@ -147,95 +150,121 @@ VG_STATIC void vg_framebuffer_resize( int w, int h ) water_fb_resize(); } -VG_STATIC void render_main_game(void) +VG_STATIC void present_view_with_post_processing(void) { - m4x4f world_4x4; - m4x3_expand( camera_mtx_inverse, world_4x4 ); + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - static float fov = 60.0f; + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA); + glBlendEquation(GL_FUNC_ADD); - float fov_target = vg_lerpf( 90.0f, 110.0f, g_fov_option ); + shader_blitblur_use(); + shader_blitblur_uTexMain( 0 ); + shader_blitblur_uTexMotion( 1 ); + shader_blitblur_uBlurStrength( cl_blur_strength ); + glActiveTexture( GL_TEXTURE0 ); - if( player.phys.on_board ) - fov_target = vg_lerpf( 97.0f, 135.0f, g_fov_option ); + if( cl_view_id == 0 ) + glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background ); + else if( cl_view_id == 1 ) + glBindTexture( GL_TEXTURE_2D, gpipeline.mv_background ); + else + glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background ); - if( cl_menu ) - fov_target = menu_fov_target; + glActiveTexture( GL_TEXTURE1 ); + glBindTexture( GL_TEXTURE_2D, gpipeline.mv_background ); - fov = vg_lerpf( fov, fov_target, vg.frame_delta * 2.0f ); + render_fsquad(); +} - gpipeline.fov = freecam? 60.0f: fov; /* 120 */ - m4x4_projection( vg.pv, gpipeline.fov, - (float)vg.window_x / (float)vg.window_y, - 0.1f, 2100.0f ); +VG_STATIC void render_scene(void) +{ + glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background ); + glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); - m4x4_mul( vg.pv, world_4x4, vg.pv ); + /* Draw world */ glEnable( GL_DEPTH_TEST ); - - /* - * Draw world - */ - int draw_solid = player.is_dead | freecam; - render_world( vg.pv, camera_mtx ); + render_world( &main_camera ); + render_water_texture( &main_camera ); + glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background ); + render_water_surface( &main_camera ); + render_world_gates( &main_camera ); +} + +VG_STATIC void render_menu(void) +{ + glClear( GL_DEPTH_BUFFER_BIT ); + menu_render( &main_camera ); +} - if( draw_solid ) - draw_player( camera_mtx ); +VG_STATIC void render_player_into_world(void) +{ + glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_background ); + draw_player( &main_camera ); +} + +VG_STATIC void render_player_transparent(void) +{ + camera small_cam; + m4x3_copy( main_camera.transform, small_cam.transform ); - render_water_texture( camera_mtx ); + small_cam.fov = main_camera.fov; + small_cam.nearz = 0.05f; + small_cam.farz = 60.0f; + + camera_update_view( &small_cam ); + camera_update_projection( &small_cam ); + camera_finalize( &small_cam ); + + /* Draw player to window buffer and blend background ontop */ glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - render_water_surface( vg.pv, camera_mtx ); - render_world_gates( vg.pv, player.phys.rb.co, camera_mtx ); + draw_player( &small_cam ); +} +VG_STATIC void render_main_game(void) +{ + static float fov = 60.0f; + float fov_target = vg_lerpf( 90.0f, 110.0f, cl_fov ); + if( player.phys.on_board ) + fov_target = vg_lerpf( 97.0f, 135.0f, cl_fov ); if( cl_menu ) - { - glClear( GL_DEPTH_BUFFER_BIT ); - menu_render( vg.pv ); - } - - /* Copy the RGB of what we have into the background buffer */ - glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 ); - glBindFramebuffer( GL_DRAW_FRAMEBUFFER, gpipeline.fb_background ); - glBlitFramebuffer( 0,0, vg.window_x, vg.window_y, - 0,0, vg.window_x, vg.window_y, - GL_COLOR_BUFFER_BIT, - GL_LINEAR ); - - /* Clear out the colour buffer, but keep depth */ - glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); + fov_target = menu_fov_target; + fov = vg_lerpf( fov, fov_target, vg.frame_delta * 2.0f ); + fov = freecam? 60.0f: fov; - if( !player.is_dead ) - glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); - else - glClear( GL_COLOR_BUFFER_BIT ); + main_camera.fov = fov; + main_camera.nearz = 0.1f; + main_camera.farz = 2100.0f; + + camera_update_view( &main_camera ); + camera_update_projection( &main_camera ); + camera_finalize( &main_camera ); + + /* ========== Begin Frame ========== */ + + render_scene(); - if( !draw_solid ) + if( !cl_menu ) { - m4x4_projection( vg.pv, gpipeline.fov, - (float)vg.window_x / (float)vg.window_y, - 0.05f, 60.0f ); - m4x4_mul( vg.pv, world_4x4, vg.pv ); - draw_player( camera_mtx ); + if( player.is_dead | freecam ) + render_player_into_world(); + else + render_player_transparent(); } - /* Draw back in the background - * - * TODO: need to disable alpha write in the terrain shader so this works - * again. - */ - glEnable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA); - glBlendEquation(GL_FUNC_ADD); - - shader_blit_use(); - shader_blit_uTexMain( 0 ); - glActiveTexture(GL_TEXTURE0); - glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_background ); + present_view_with_post_processing(); - render_fsquad(); + if( cl_menu ) + { + render_menu(); + render_player_transparent(); + } + + /* =========== End Frame =========== */ } VG_STATIC void vg_render(void) @@ -245,15 +274,15 @@ VG_STATIC void vg_render(void) glViewport( 0,0, vg.window_x, vg.window_y ); glDisable( GL_DEPTH_TEST ); - glClearColor( 0.11f, 0.35f, 0.37f, 1.0f ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); + glClearColor( 1.0f, 0.0f, 0.0f, 0.0f ); + glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); render_main_game(); /* Other shite */ glDisable(GL_BLEND); glDisable( GL_DEPTH_TEST ); - vg_lines_drawall( (float *)vg.pv ); + vg_lines_drawall( (float *)main_camera.mtx.pv ); glViewport( 0,0, vg.window_x, vg.window_y ); } diff --git a/world.h b/world.h index d307278..8ae85fc 100644 --- a/world.h +++ b/world.h @@ -436,10 +436,7 @@ VG_STATIC void world_init(void) vg_linear_clear( vg_mem.scratch ); mdl_context *msky = mdl_load_full( vg_mem.scratch, "models/rs_skydome.mdl" ); - mdl_node *nlower = mdl_node_from_name( msky, "dome_lower" ), - *nupper = mdl_node_from_name( msky, "dome_upper" ); - - world.dome_lower = *mdl_node_submesh( msky, nlower, 0 ); + mdl_node *nupper = mdl_node_from_name( msky, "dome_complete" ); world.dome_upper = *mdl_node_submesh( msky, nupper, 0 ); vg_acquire_thread_sync(); diff --git a/world_gate.h b/world_gate.h index b57c799..004ee8a 100644 --- a/world_gate.h +++ b/world_gate.h @@ -8,6 +8,7 @@ #include "common.h" #include "model.h" #include "render.h" +#include "camera.h" #include "shaders/gatelq.h" #include "world_water.h" @@ -43,69 +44,70 @@ VG_STATIC void world_gates_init(void) vg_release_thread_sync(); } -VG_STATIC int render_gate( teleport_gate *gate, v3f viewpos, m4x3f camera ) +VG_STATIC int render_gate( teleport_gate *gate, camera *cam ) { v3f viewdir, gatedir; - m3x3_mulv( camera, (v3f){0.0f,0.0f,-1.0f}, viewdir ); + m3x3_mulv( cam->transform, (v3f){0.0f,0.0f,-1.0f}, viewdir ); m3x3_mulv( gate->to_world, (v3f){0.0f,0.0f,-1.0f}, gatedir ); v3f v0; - v3_sub( viewpos, gate->co[0], v0 ); + v3_sub( cam->pos, gate->co[0], v0 ); if( v3_dot(v0, gatedir) >= 0.0f ) return 0; - if( v3_dist( viewpos, gate->co[0] ) > 100.0f ) + if( v3_dist( cam->pos, gate->co[0] ) > 100.0f ) return 0; - v3f a,b,c,d; - - float sx = gate->dims[0], - sy = gate->dims[1]; - m4x3_mulv( gate->to_world, (v3f){-sx,-sy,0.0f}, a ); - m4x3_mulv( gate->to_world, (v3f){ sx,-sy,0.0f}, b ); - m4x3_mulv( gate->to_world, (v3f){ sx, sy,0.0f}, c ); - m4x3_mulv( gate->to_world, (v3f){-sx, sy,0.0f}, d ); + { + v3f a,b,c,d; - vg_line( a,b, 0xffffa000 ); - vg_line( b,c, 0xffffa000 ); - vg_line( c,d, 0xffffa000 ); - vg_line( d,a, 0xffffa000 ); + float sx = gate->dims[0], + sy = gate->dims[1]; + m4x3_mulv( gate->to_world, (v3f){-sx,-sy,0.0f}, a ); + m4x3_mulv( gate->to_world, (v3f){ sx,-sy,0.0f}, b ); + m4x3_mulv( gate->to_world, (v3f){ sx, sy,0.0f}, c ); + m4x3_mulv( gate->to_world, (v3f){-sx, sy,0.0f}, d ); - vg_line2( gate->co[0], gate->co[1], 0xff0000ff, 0x00000000 ); + vg_line( a,b, 0xffffa000 ); + vg_line( b,c, 0xffffa000 ); + vg_line( c,d, 0xffffa000 ); + vg_line( d,a, 0xffffa000 ); - m4x3f cam_new; - m4x3_mul( gate->transport, camera, cam_new ); - - vg_line_pt3( cam_new[3], 0.3f, 0xff00ff00 ); + vg_line2( gate->co[0], gate->co[1], 0xff0000ff, 0x00000000 ); + } - m4x3f gate_xform; - m4x3_copy( gate->to_world, gate_xform ); - m4x3_scalev( gate_xform, (v3f){ gate->dims[0], gate->dims[1], 1.0f } ); - - m4x3f inverse; - m4x3_invert_affine( cam_new, inverse ); + /* update gate camera */ + static camera gate_view; + gate_view.fov = cam->fov; + gate_view.nearz = 0.1f; + gate_view.farz = 900.0f; - m4x4f view; - m4x3_expand( inverse, view ); + m4x3_mul( gate->transport, cam->transform, gate_view.transform ); + camera_update_view( &gate_view ); + camera_update_projection( &gate_view ); + /* Add special clipping plane to projection */ v4f surface; m3x3_mulv( gate->recv_to_world, (v3f){0.0f,0.0f,-1.0f}, surface ); surface[3] = v3_dot( surface, gate->co[1] ); - - m4x4f projection; - pipeline_projection( projection, 0.1f, 900.0f ); - m4x3_mulp( inverse, surface, surface ); + m4x3_mulp( gate_view.transform_inverse, surface, surface ); surface[3] = -fabsf(surface[3]); - plane_clip_projection( projection, surface ); + m4x4_clip_projection( gate_view.mtx.p, surface ); - m4x4_mul( projection, view, projection ); + /* Ready to draw with new camrea */ + camera_finalize( &gate_view ); + vg_line_pt3( gate_view.transform[3], 0.3f, 0xff00ff00 ); { + m4x3f gate_xform; + m4x3_copy( gate->to_world, gate_xform ); + m4x3_scalev( gate_xform, (v3f){ gate->dims[0], gate->dims[1], 1.0f } ); + shader_gatelq_use(); - shader_gatelq_uPv( vg.pv ); + shader_gatelq_uPv( cam->mtx.pv ); shader_gatelq_uMdl( gate_xform ); - shader_gatelq_uCam( viewpos ); + shader_gatelq_uCam( cam->pos ); shader_gatelq_uTime( vg.time*0.25f ); shader_gatelq_uInvRes( (v2f){ 1.0f / (float)vg.window_x, @@ -124,16 +126,16 @@ VG_STATIC int render_gate( teleport_gate *gate, v3f viewpos, m4x3f camera ) glStencilMask( 0x00 ); } - render_world( projection, cam_new ); + render_world( &gate_view ); { glDisable( GL_STENCIL_TEST ); - render_water_texture( cam_new ); + render_water_texture( &gate_view ); fb_use( NULL ); glEnable( GL_STENCIL_TEST ); - render_water_surface( projection, cam_new ); + render_water_surface( &gate_view ); glStencilMask( 0xFF ); glStencilFunc( GL_ALWAYS, 1, 0xFF ); @@ -152,12 +154,16 @@ VG_STATIC int gate_intersect( teleport_gate *gate, v3f pos, v3f last ) v3f v0, c, delta, p0; v3_sub( pos, last, v0 ); float l = v3_length( v0 ); + + if( l == 0.0f ) + return 0; + v3_divs( v0, l, v0 ); v3_muls( surface, surface[3], c ); v3_sub( c, last, delta ); - float d = v3_dot(surface, v0); + float d = v3_dot( surface, v0 ); if( d > 0.00001f ) { diff --git a/world_gen.h b/world_gen.h index ee774bb..d18c2c3 100644 --- a/world_gen.h +++ b/world_gen.h @@ -39,6 +39,8 @@ VG_STATIC void world_apply_procedural_foliage( struct world_material *mat ) if( vg.quality_profile == k_quality_profile_low ) return; + vg_info( "Applying foliage (%u)\n", mat->info.pstr_name ); + vg_linear_clear( vg_mem.scratch ); mdl_context *mfoliage = @@ -461,13 +463,6 @@ VG_STATIC void world_generate(void) world.scene_no_collide = scene_init( world.dynamic_vgl, 200000, 500000 ); -#if 0 - vg_info( "Applying foliage\n" ); - srand(0); - world_apply_procedural_foliage(); - scene_copy_slice( world.scene_no_collide, &world.sm_foliage_main ); -#endif - for( int i=0; ibbx[1], world.scene_geo->bbx[0], extent ); @@ -537,13 +531,15 @@ VG_STATIC void world_post_process(void) rl = 1.0f / (fr-fl), tb = 1.0f / (ft-fb); - m4x4_zero( ortho ); - ortho[0][0] = 2.0f * rl; - ortho[2][1] = 2.0f * tb; - ortho[3][0] = (fr + fl) * -rl; - ortho[3][1] = (ft + fb) * -tb; - ortho[3][3] = 1.0f; - m4x3_identity( camera ); + m4x4_zero( ortho.mtx.p ); + ortho.mtx.p[0][0] = 2.0f * rl; + ortho.mtx.p[2][1] = 2.0f * tb; + ortho.mtx.p[3][0] = (fr + fl) * -rl; + ortho.mtx.p[3][1] = (ft + fb) * -tb; + ortho.mtx.p[3][3] = 1.0f; + m4x3_identity( ortho.transform ); + camera_update_view( &ortho ); + camera_finalize( &ortho ); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); @@ -558,12 +554,12 @@ VG_STATIC void world_post_process(void) glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glBlendEquation(GL_MAX); - render_world_depth( ortho, camera ); + + render_world_depth( &ortho ); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - /* * TODO: World settings entity */ diff --git a/world_render.h b/world_render.h index ae9399b..68c0ceb 100644 --- a/world_render.h +++ b/world_render.h @@ -5,6 +5,7 @@ #ifndef WORLD_RENDER_H #define WORLD_RENDER_H +#include "camera.h" #include "world.h" vg_tex2d tex_terrain_noise = { .path = "textures/garbage.qoi", @@ -21,7 +22,7 @@ VG_STATIC void world_render_init(void) vg_release_thread_sync(); } -VG_STATIC void render_world_depth( m4x4f projection, m4x3f camera ); +VG_STATIC void render_world_depth( camera *cam ); /* * Rendering @@ -74,7 +75,7 @@ VG_STATIC void bindpoint_diffuse_texture1( struct world_material *mat ) glBindTexture( GL_TEXTURE_2D, world.textures[ mat->info.tex_diffuse ] ); } -VG_STATIC void render_world_vb( m4x4f projection, v3f camera ) +VG_STATIC void render_world_vb( camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -85,15 +86,16 @@ VG_STATIC void render_world_vb( m4x4f projection, v3f camera ) shader_link_standard_ub( _shader_vblend.id, 2 ); vg_tex2d_bind( &tex_terrain_noise, 0 ); - shader_vblend_uPv( projection ); + shader_vblend_uPv( cam->mtx.pv ); + shader_vblend_uPvmPrev( cam->mtx_prev.pv ); shader_vblend_uMdl( identity_matrix ); - shader_vblend_uCamera( camera ); + shader_vblend_uCamera( cam->transform[3] ); world_render_both_stages( k_shader_standard_vertex_blend, bindpoint_diffuse_texture1 ); } -VG_STATIC void render_world_standard( m4x4f projection, v3f camera ) +VG_STATIC void render_world_standard( camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -101,18 +103,19 @@ VG_STATIC void render_world_standard( m4x4f projection, v3f camera ) shader_standard_use(); shader_standard_uTexGarbage(0); shader_standard_uTexMain(1); + shader_standard_uPv( cam->mtx.pv ); + shader_standard_uPvmPrev( cam->mtx_prev.pv ); shader_link_standard_ub( _shader_standard.id, 2 ); bind_terrain_noise(); - shader_standard_uPv( projection ); shader_standard_uMdl( identity_matrix ); - shader_standard_uCamera( camera ); + shader_standard_uCamera( cam->transform[3] ); world_render_both_stages( k_shader_standard, bindpoint_diffuse_texture1 ); } -VG_STATIC void render_world_alphatest( m4x4f projection, v3f camera ) +VG_STATIC void render_world_alphatest( camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -120,12 +123,13 @@ VG_STATIC void render_world_alphatest( m4x4f projection, v3f camera ) shader_alphatest_use(); shader_alphatest_uTexGarbage(0); shader_alphatest_uTexMain(1); + shader_alphatest_uPv( cam->mtx.pv ); + shader_alphatest_uPvmPrev( cam->mtx_prev.pv ); shader_link_standard_ub( _shader_alphatest.id, 2 ); bind_terrain_noise(); - shader_alphatest_uPv( projection ); shader_alphatest_uMdl( identity_matrix ); - shader_alphatest_uCamera( camera ); + shader_alphatest_uCamera( cam->transform[3] ); glDisable(GL_CULL_FACE); @@ -144,7 +148,7 @@ VG_STATIC void bindpoint_terrain( struct world_material *mat ) shader_terrain_uBlendOffset( mat->info.colour1 ); } -VG_STATIC void render_terrain( m4x4f projection, v3f camera ) +VG_STATIC void render_terrain( camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -156,53 +160,48 @@ VG_STATIC void render_terrain( m4x4f projection, v3f camera ) vg_tex2d_bind( &tex_terrain_noise, 0 ); - shader_terrain_uPv( projection ); + shader_terrain_uPv( cam->mtx.pv ); + shader_terrain_uPvmPrev( cam->mtx_prev.pv ); + shader_terrain_uMdl( identity_matrix ); - shader_terrain_uCamera( camera ); + shader_terrain_uCamera( cam->transform[3] ); world_render_both_stages( k_shader_terrain_blend, bindpoint_terrain ); } -VG_STATIC void render_lowerdome( m4x3f camera ) -{ - m4x4f projection, full; - pipeline_projection( projection, 0.4f, 1000.0f ); - - m4x3f inverse; - m3x3_transpose( camera, inverse ); - v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]); - m4x3_expand( inverse, full ); - m4x4_mul( projection, full, full ); - - m4x3f identity_matrix; - m4x3_identity( identity_matrix ); - - shader_planeinf_use(); - shader_planeinf_uMdl(identity_matrix); - shader_planeinf_uPv(full); - shader_planeinf_uCamera(camera[3]); - shader_planeinf_uPlane( (v4f){0.0f,1.0f,0.0f,0.0f} ); - - mdl_draw_submesh( &world.dome_lower ); -} - -VG_STATIC void render_sky(m4x3f camera) +VG_STATIC void render_sky( camera *cam ) { - m4x4f projection, full; - pipeline_projection( projection, 0.4f, 1000.0f ); - - m4x3f inverse; - m3x3_transpose( camera, inverse ); - v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]); - m4x3_expand( inverse, full ); - m4x4_mul( projection, full, full ); + /* + * Modify matrix to remove clipping and view translation + */ + m4x4f v, + v_prev, + pv, + pv_prev; + + m4x4_copy( cam->mtx.v, v ); + m4x4_copy( cam->mtx_prev.v, v_prev ); + v3_zero( v[3] ); + v3_zero( v_prev[3] ); + + m4x4_copy( cam->mtx.p, pv ); + m4x4_copy( cam->mtx_prev.p, pv_prev ); + m4x4_reset_clipping( pv, cam->farz, cam->nearz ); + m4x4_reset_clipping( pv_prev, cam->farz, cam->nearz ); + + m4x4_mul( pv, v, pv ); + m4x4_mul( pv_prev, v_prev, pv_prev ); m4x3f identity_matrix; m4x3_identity( identity_matrix ); + /* + * Draw + */ shader_sky_use(); - shader_sky_uMdl(identity_matrix); - shader_sky_uPv(full); + shader_sky_uMdl( identity_matrix ); + shader_sky_uPv( pv ); + shader_sky_uPvmPrev( pv_prev ); shader_sky_uTexGarbage(0); shader_sky_uTime( world.sky_time ); @@ -218,7 +217,7 @@ VG_STATIC void render_sky(m4x3f camera) glDepthMask( GL_TRUE ); } -VG_STATIC void render_world_gates( m4x4f projection, v3f playerco, m4x3f camera ) +VG_STATIC void render_world_gates( camera *cam ) { if( !world.gate_count ) return; @@ -229,7 +228,7 @@ VG_STATIC void render_world_gates( m4x4f projection, v3f playerco, m4x3f camera for( int i=0; igate.co[0], camera[3] ); + float dist = v3_dist2( rg->gate.co[0], cam->transform[3] ); if( dist < closest ) { @@ -238,22 +237,24 @@ VG_STATIC void render_world_gates( m4x4f projection, v3f playerco, m4x3f camera } } - render_gate( &world.gates[id].gate, playerco, camera ); + render_gate( &world.gates[id].gate, cam ); v3_lerp( world.render_gate_pos, world.gates[id].gate.co[0], 1.0f, world.render_gate_pos ); } -VG_STATIC void render_world( m4x4f projection, m4x3f camera ) +VG_STATIC void render_world( camera *cam ) { - render_sky( camera ); - render_world_routes( projection, camera[3] ); - render_world_standard( projection, camera[3] ); - render_world_vb( projection, camera[3] ); - render_world_alphatest( projection, camera[3] ); - render_terrain( projection, camera[3] ); + render_sky( cam ); + + render_world_routes( cam ); + render_world_standard( cam ); + render_world_vb( cam ); + render_world_alphatest( cam ); + render_terrain( cam ); + /* Render SFD's */ int closest = 0; float min_dist = INFINITY; @@ -262,8 +263,7 @@ VG_STATIC void render_world( m4x4f projection, m4x3f camera ) for( int i=0; ipos); if( dist < min_dist ) { @@ -272,18 +272,18 @@ VG_STATIC void render_world( m4x4f projection, m4x3f camera ) } } - sfd_render( projection, camera[3], - world.routes[closest].scoreboard_transform ); + sfd_render( cam, world.routes[closest].scoreboard_transform ); } -VG_STATIC void render_world_depth( m4x4f projection, m4x3f camera ) +VG_STATIC void render_world_depth( camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); shader_gpos_use(); - shader_gpos_uCamera( camera[3] ); - shader_gpos_uPv( projection ); + shader_gpos_uCamera( cam->transform[3] ); + shader_gpos_uPv( cam->mtx.pv ); + shader_gpos_uPvmPrev( cam->mtx_prev.pv ); shader_gpos_uMdl( identity_matrix ); mesh_bind( &world.mesh_geo ); diff --git a/world_routes.h b/world_routes.h index 795f57b..7d4ef7c 100644 --- a/world_routes.h +++ b/world_routes.h @@ -1132,7 +1132,7 @@ VG_STATIC void world_routes_update(void) } VG_STATIC void bind_terrain_noise(void); -VG_STATIC void render_world_routes( m4x4f projection, v3f camera ) +VG_STATIC void render_world_routes( camera *cam ) { m4x3f identity_matrix; m4x3_identity( identity_matrix ); @@ -1142,9 +1142,10 @@ VG_STATIC void render_world_routes( m4x4f projection, v3f camera ) shader_link_standard_ub( _shader_route.id, 2 ); bind_terrain_noise(); - shader_route_uPv( projection ); + shader_route_uPv( cam->mtx.pv ); + shader_route_uPvmPrev( cam->mtx_prev.pv ); shader_route_uMdl( identity_matrix ); - shader_route_uCamera( camera ); + shader_route_uCamera( cam->transform[3] ); mesh_bind( &world.mesh_route_lines ); diff --git a/world_sfd.h b/world_sfd.h index 3f94c4e..9f41992 100644 --- a/world_sfd.h +++ b/world_sfd.h @@ -102,7 +102,7 @@ VG_STATIC void sfd_update(void) } VG_STATIC void bind_terrain_noise(void); -VG_STATIC void sfd_render( m4x4f projection, v3f camera, m4x3f transform ) +VG_STATIC void sfd_render( camera *cam, m4x3f transform ) { mesh_bind( &world.sfd.mesh_display ); @@ -113,9 +113,14 @@ VG_STATIC void sfd_render( m4x4f projection, v3f camera, m4x3f transform ) bind_terrain_noise(); vg_tex2d_bind( &tex_scoretext, 1 ); - shader_scoretext_uPv( projection ); + m4x4f pvm_prev; + m4x3_expand( transform, pvm_prev ); + m4x4_mul( cam->mtx_prev.pv, pvm_prev, pvm_prev ); + + shader_scoretext_uPv( cam->mtx.pv ); + shader_scoretext_uPvmPrev( pvm_prev ); shader_scoretext_uMdl( transform ); - shader_scoretext_uCamera( camera ); + shader_scoretext_uCamera( cam->transform[3] ); for( int y=0;ymtx.pv ); + shader_vblend_uPvmPrev( pvm_prev ); + shader_vblend_uMdl( transform ); - shader_vblend_uCamera( camera ); + shader_vblend_uCamera( cam->transform[3] ); mesh_bind( &world.sfd.mesh_base ); mesh_draw( &world.sfd.mesh_base ); diff --git a/world_water.h b/world_water.h index 4281981..e054a11 100644 --- a/world_water.h +++ b/world_water.h @@ -51,7 +51,10 @@ VG_STATIC void water_set_surface( float height ) v4_copy( (v4f){ 0.0f, 1.0f, 0.0f, height }, world.water.plane ); } -VG_STATIC void render_water_texture( m4x3f camera ) +/* + * Does not write motion vectors + */ +VG_STATIC void render_water_texture( camera *cam ) { if( !world.water.enabled || (vg.quality_profile == k_quality_profile_low) ) return; @@ -60,69 +63,66 @@ VG_STATIC void render_water_texture( m4x3f camera ) fb_use( &world.water.fbreflect ); glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); - m4x3f new_cam, inverse; - v3_copy( camera[3], new_cam[3] ); - new_cam[3][1] -= 2.0f * (camera[3][1] - world.water.height); + /* + * Create flipped view matrix. Don't care about motion vectors + */ + float cam_height = cam->transform[3][1] - world.water.height; + + camera water_cam; + v3_copy( cam->transform[3], water_cam.transform[3] ); + water_cam.transform[3][1] -= 2.0f * cam_height; m3x3f flip; m3x3_identity( flip ); flip[1][1] = -1.0f; - m3x3_mul( flip, camera, new_cam ); - - - v3f p0; - m3x3_mulv( new_cam, (v3f){0.0f,0.0f,-1.0f}, p0 ); - v3_add( new_cam[3], p0, p0 ); - vg_line( new_cam[3], p0, 0xffffffff ); - - m4x4f view; - vg_line_pt3( new_cam[3], 0.3f, 0xff00ffff ); + m3x3_mul( flip, cam->transform, water_cam.transform ); - m4x3_invert_affine( new_cam, inverse ); - m4x3_expand( inverse, view ); + camera_update_view( &water_cam ); + /* + * Create clipped projection + */ v4f clippa = { 0.0f, 1.0f, 0.0f, world.water.height-0.1f }; - m4x3_mulp( inverse, clippa, clippa ); + m4x3_mulp( water_cam.transform_inverse, clippa, clippa ); clippa[3] *= -1.0f; - m4x4f projection; - m4x4_projection( projection, - gpipeline.fov, - (float)vg.window_x / (float)vg.window_y, - 0.1f, 900.0f ); - plane_clip_projection( projection, clippa ); - m4x4_mul( projection, view, projection ); + m4x4_copy( cam->mtx.p, water_cam.mtx.p ); + m4x4_clip_projection( water_cam.mtx.p, clippa ); + camera_finalize( &water_cam ); + + /* + * Draw world + */ glCullFace( GL_FRONT ); - render_world( projection, new_cam ); + render_world( &water_cam ); glCullFace( GL_BACK ); - - - /* Draw beneath texture */ + + /* + * Create beneath view matrix + */ + camera beneath_cam; fb_use( &world.water.fbdepth ); glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); - m4x3_invert_affine( camera, inverse ); - m4x3_expand( inverse, view ); + m4x3_copy( cam->transform, beneath_cam.transform ); + camera_update_view( &beneath_cam ); + + float bias = -(cam->transform[3][1]-world.water.height)*0.1f; - float bias = -(camera[3][1]-world.water.height)*0.1f; v4f clippb = { 0.0f, -1.0f, 0.0f, -(world.water.height) + bias }; - m4x3_mulp( inverse, clippb, clippb ); + m4x3_mulp( beneath_cam.transform_inverse, clippb, clippb ); clippb[3] *= -1.0f; - m4x4_projection( projection, - gpipeline.fov, - (float)vg.window_x / (float)vg.window_y, - 0.1f, 900.0f ); + m4x4_copy( cam->mtx.p, beneath_cam.mtx.p ); + m4x4_clip_projection( beneath_cam.mtx.p, clippb ); + camera_finalize( &beneath_cam ); - plane_clip_projection( projection, clippb ); - m4x4_mul( projection, view, projection ); - render_world_depth( projection, camera ); - + render_world_depth( &beneath_cam ); glViewport( 0, 0, vg.window_x, vg.window_y ); } -VG_STATIC void render_water_surface( m4x4f pv, m4x3f camera ) +VG_STATIC void render_water_surface( camera *cam ) { if( !world.water.enabled ) return; @@ -146,10 +146,11 @@ VG_STATIC void render_water_surface( m4x4f pv, m4x3f camera ) fb_bindtex( &world.water.fbdepth, 3 ); shader_water_uTexBack( 3 ); shader_water_uTime( world.time ); - shader_water_uCamera( camera[3] ); + shader_water_uCamera( cam->transform[3] ); shader_water_uSurfaceY( world.water.height ); - shader_water_uPv( pv ); + shader_water_uPv( cam->mtx.pv ); + shader_water_uPvmPrev( cam->mtx_prev.pv ); m4x3f full; m4x3_identity( full ); @@ -183,14 +184,15 @@ VG_STATIC void render_water_surface( m4x4f pv, m4x3f camera ) vg_tex2d_bind( &tex_water_surf, 1 ); shader_water_fast_uTexDudv( 1 ); shader_water_fast_uTime( world.time ); - shader_water_fast_uCamera( camera[3] ); + shader_water_fast_uCamera( cam->transform[3] ); shader_water_fast_uSurfaceY( world.water.height ); shader_link_standard_ub( _shader_water_fast.id, 2 ); m4x3f full; m4x3_identity( full ); shader_water_fast_uMdl( full ); - shader_water_fast_uPv( pv ); + shader_water_fast_uPv( cam->mtx.pv ); + shader_water_fast_uPvmPrev( cam->mtx_prev.pv ); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);