From: hgn Date: Fri, 1 Jul 2022 22:40:26 +0000 (+0100) Subject: stuff X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=dfee9022b3513fddec36f7ea70867ee5961a44da;p=carveJwlIkooP6JGAAIwe30JlM.git stuff --- diff --git a/gate.h b/gate.h index 6e9b95f..7088c7d 100644 --- a/gate.h +++ b/gate.h @@ -13,16 +13,20 @@ typedef struct teleport_gate teleport_gate; static struct { - GLuint fb, rgb, rb; + struct framebuffer fb; glmesh mdl; int high_qual; /* If in high performance mode, we don't use RT's, and - instead use stencil buffers. - There is therefore no heat warp effect. */ + instead use stencil buffers. + There is therefore no heat warp effect. */ } grender = { - .high_qual = 0 + .high_qual = 0, + .fb = { + .format = GL_RGB, + .div = 1 + } }; struct teleport_gate @@ -56,7 +60,7 @@ static void gate_register(void) static void gate_init(void) { - create_renderbuffer_std( &grender.fb, &grender.rgb, &grender.rb ); + fb_init( &grender.fb ); model *mgate = vg_asset_read( "models/rs_gate.mdl" ); model_unpack( mgate, &grender.mdl ); @@ -65,7 +69,7 @@ static void gate_init(void) static void gate_fb_resize(void) { - resize_renderbuffer_std( &grender.fb, &grender.rgb, &grender.rb ); + fb_resize( &grender.fb ); } static void render_gate( teleport_gate *gate, m4x3f camera ) @@ -129,7 +133,7 @@ static void render_gate( teleport_gate *gate, m4x3f camera ) if( grender.high_qual ) { - glBindFramebuffer( GL_FRAMEBUFFER, grender.fb ); + fb_use( &grender.fb ); glClearColor( 0.11f, 0.35f, 0.37f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); } @@ -167,17 +171,18 @@ static void render_gate( teleport_gate *gate, m4x3f camera ) */ render_water_texture( cam_new ); - glBindFramebuffer( GL_FRAMEBUFFER, grender.fb ); - render_water_surface( projection ); - glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + fb_use( &grender.fb ); + + render_water_surface( projection, cam_new ); + fb_use( NULL ); shader_gate_use(); shader_gate_uPv( vg_pv ); shader_gate_uMdl( gate_xform ); - glActiveTexture( GL_TEXTURE0 ); - glBindTexture( GL_TEXTURE_2D, grender.rgb ); + fb_bindtex( &grender.fb, 0 ); + shader_gate_uCam( viewpos ); shader_gate_uTexMain( 0 ); shader_gate_uTexWater( 1 ); diff --git a/main.c b/main.c index 6b38fc5..def609d 100644 --- a/main.c +++ b/main.c @@ -59,17 +59,6 @@ int main( int argc, char *argv[] ) vg_init( argc, argv, "Voyager Game Engine" ); } -#if 0 -rigidbody mr_box = { - .bbx = {{ -1.0f, -0.25f, -0.25f }, { 1.0f, 0.25f, 0.25f }} -}; - -rigidbody mrs_box = { - .bbx = {{ -0.5f, -0.25f, -0.25f }, { 0.5f, 0.25f, 0.25f }} -}; - -#endif - static int playermodel( int argc, char const *argv[] ) { if( argc < 1 ) return 0; @@ -145,6 +134,11 @@ void vg_start(void) player_transform_update(); } +void vg_free(void) +{ + vg_tex2d_free( texture_list, vg_list_size(texture_list) ); +} + void vg_update(void) { player_update(); @@ -170,30 +164,6 @@ void vg_render(void) v3f shake = { vg_randf()-0.5f, vg_randf()-0.5f, vg_randf()-0.5f }; v3_muls( shake, speed*0.01f, shake ); - if( player.is_dead ) - { -#if 0 - v3f delta; - v3_sub( player.mdl.ragdoll[k_chpart_head].co, player.follow, delta ); - v3_normalize(delta); - - v3f follow_pos; - v3_muladds( player.mdl.ragdoll[k_chpart_head].co, delta, - -1.5f, follow_pos ); - v3_lerp( player.follow, follow_pos, 0.1f, player.follow ); - v3_negate( player.follow, final ); - - - float yaw = atan2f( delta[0], -delta[2] ); - float pitch = asinf( delta[1] ); - m4x3_rotate_x( world_matrix, -pitch ); - m4x3_rotate_y( world_matrix, yaw ); -#endif - } - else - { - } - m4x4f world_4x4; m4x3_expand( player.camera_inverse, world_4x4 ); @@ -218,7 +188,7 @@ void vg_render(void) render_water_texture( player.camera ); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - render_water_surface( vg_pv ); + render_water_surface( vg_pv, player.camera ); vg_tex2d_bind( &tex_water, 1 ); @@ -247,7 +217,11 @@ void vg_render(void) draw_player(); - /* Draw back in the background */ + /* 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); @@ -264,39 +238,6 @@ void vg_render(void) /* Other shite */ glDisable( GL_DEPTH_TEST ); vg_lines_drawall( (float *)vg_pv ); - - /* Debugger camera */ -#if 0 - glViewport( 0,0, 800, 800 ); - glClearColor( 0.1f, 0.0f, 0.2f, 1.0f ); - glClear( GL_DEPTH_BUFFER_BIT ); - - m4x3_identity( world_matrix ); - - v3f debugcam; - v3_negate( player.co, debugcam ); - debugcam[2] -= 2.0f; - debugcam[1] -= 0.7f; - - m4x3_translate( world_matrix, debugcam ); - m4x3_expand( world_matrix, world_4x4 ); - - m4x4_projection( vg_pv, - 100.0f, - (float)128.0f / (float)128.0f, - 0.1f, 1000.0f ); - m4x4_mul( vg_pv, world_4x4, vg_pv ); - - if(sv_debugcam) - { - glEnable( GL_DEPTH_TEST ); - draw_player(); - } -#endif - - glDisable( GL_DEPTH_TEST ); - vg_lines_drawall( (float *)vg_pv ); - glViewport( 0,0, vg_window_x, vg_window_y ); } @@ -329,5 +270,3 @@ void vg_ui(void) "Gamepad not ready", 1, k_text_align_left ); } } - -void vg_free(void){} diff --git a/player.h b/player.h index 7ab0e63..6c81980 100644 --- a/player.h +++ b/player.h @@ -31,7 +31,7 @@ static struct gplayer v3f land_target_log[22]; u32 land_target_colours[22]; int land_log_count; - m3x3f vr; + m3x3f vr,vr_pstep; m4x3f to_world, to_local; @@ -93,6 +93,7 @@ static void player_mouseview(void) if( vg_get_button_down( "primary" ) ) v2_copy( vg_mouse, mouse_last ); + else if( vg_get_button( "primary" ) ) { v2f delta; @@ -102,10 +103,12 @@ static void player_mouseview(void) v2_muladds( view_vel, delta, 0.005f, view_vel ); } + v2_muladds( view_vel, + (v2f){ vg_get_axis("h1"), vg_get_axis("v1") }, + 0.05f, view_vel ); v2_muls( view_vel, 0.7f, view_vel ); v2_add( view_vel, player.angles, player.angles ); player.angles[1] = vg_clampf( player.angles[1], -VG_PIf*0.5f, VG_PIf*0.5f ); - } static void player_freecam(void) @@ -219,7 +222,8 @@ static void player_start_air(void) best_velocity_mod = vmod; v3_copy( contact.pos, player.land_target ); - + + m3x3_copy( vr, player.vr_pstep ); q_axis_angle( vr_q, axis, vmod*0.1f ); q_m3x3( vr_q, player.vr ); } @@ -364,7 +368,9 @@ static void player_physics_ground(void) for( int i=0; i<5; i++ ) { vel[2] = stable_force( vel[2], vg_signf( vel[2] ) * fwd_resistance ); - vel[0] = stable_force( vel[0], vg_signf( vel[0] ) * -7.0f *substep ); + + /* This used to be -7.0 */ + vel[0] = stable_force( vel[0], vg_signf( vel[0] ) * -10.0f *substep ); } static double start_push = 0.0; @@ -454,6 +460,7 @@ static void player_physics_air(void) for( int i=0; i<50; i++ ) { v3_copy( pco, pco1 ); + m3x3_mulv( player.vr_pstep, pv, pv ); apply_gravity( pv, pstep ); v3_muladds( pco, pv, pstep, pco ); @@ -498,7 +505,8 @@ static void player_physics_air(void) player.iY -= vg_get_axis( "horizontal" ) * 3.6f * ktimestep; { - float iX = vg_get_axis( "vertical" ) * 3.6f * limiter * ktimestep; + float iX = vg_get_axis( "vertical" ) * + player.reverse * 3.6f * limiter * ktimestep; static float siX = 0.0f; siX = vg_lerpf( siX, iX, 0.3f ); @@ -617,10 +625,6 @@ struct walkgrid } samples[WALKGRID_SIZE][WALKGRID_SIZE]; -#if 0 - u32 geo[256]; -#endif - boxf region; float move; /* Current amount of movement we have left to apply */ @@ -639,10 +643,6 @@ static void player_walkgrid_samplepole( struct grid_sample *s ) boxf region = {{ s->pos[0] -0.01f, s->pos[1] - 4.0f, s->pos[2] -0.01f}, { s->pos[0] +0.01f, s->pos[1] + 4.0f, s->pos[2] +0.01f}}; -#if 0 - vg_line( region[0],region[1], 0x20ffffff ); -#endif - u32 geo[256]; v3f tri[3]; int len = bh_select( &world.geo.bhtris, region, geo, 256 ); @@ -678,18 +678,11 @@ static void player_walkgrid_samplepole( struct grid_sample *s ) { walk_height = p0[1]; } - -#if 0 - draw_cross( p0, 0xffffffff, 0.05f ); -#endif } else { if( p0[1] > block_height ) block_height = p0[1]; -#if 0 - draw_cross( p0, 0xff0000ff, 0.05f ); -#endif } } } @@ -703,39 +696,6 @@ static void player_walkgrid_samplepole( struct grid_sample *s ) s->type = k_sample_type_valid; else s->type = k_sample_type_air; - -#if 0 - if( s->type == k_sample_type_valid ) - { - vg_line_pt3( s->pos, 0.01f, 0xff00ff00 ); - } -#endif - -#if 0 - int count = 0; - - ray_hit hit; - hit.dist = 10.0f; - count = bvh_raycast( &world.geo, sample_pos, vdir, &hit ); - - if( count ) - { - v3_copy( hit.pos, s->pos ); - - if( !player_walkgrid_tri_walkable( hit.tri ) ) - { - draw_cross( pos, 0xff0000ff, 0.05f ); - return 0; - } - else - { - draw_cross( pos, 0xff00ff00, 0.05f ); - return count; - } - } - else - return 0; -#endif } float const k_gridscale = 0.5f; @@ -876,29 +836,6 @@ static void player_walkgrid_clip_edge( struct grid_sample *sa, } } -static void player_walkgrid_clip( struct grid_sample *sa, - struct grid_sample *sb, - enum eclipdir dir ) -{ - int mintype = VG_MIN( sa->type, sb->type ), - maxtype = VG_MAX( sa->type, sb->type ); - - if( maxtype == k_sample_type_valid ) - { - if( mintype == k_sample_type_air || mintype == k_sample_type_invalid ) - { - player_walkgrid_clip_edge( sa, sb, sa, dir ); - } - -#if 0 - else if( mintype == k_sample_type_invalid ) - { - player_walkgrid_clip_blocker( sa, sb, dir ); - } -#endif - } -} - static const struct conf { struct confedge @@ -1032,19 +969,6 @@ static void player_walkgrid_iter(struct walkgrid *wg, int iter) * the intersections with the grid, and any edges that are present */ -#if 0 - if( wg->cell_id[0] < 0 || wg->cell_id[0] >= WALKGRID_SIZE-1 || - wg->cell_id[1] < 0 || wg->cell_id[1] >= WALKGRID_SIZE-1 ) - { - /* - * This condition should never be reached if the grid size is big - * enough - */ - wg->move = -1.0f; - return; - } -#endif - u32 icolours[] = { 0xffff00ff, 0xff00ffff, 0xffffff00 }; v3f pa, pb, pc, pd, pl0, pl1; @@ -1061,6 +985,7 @@ static void player_walkgrid_iter(struct walkgrid *wg, int iter) pd[1] = pa[1]; pd[2] = pa[2]; #if 0 + /* if you want to draw the current cell */ vg_line( pa, pb, 0xff00ffff ); vg_line( pb, pc, 0xff00ffff ); vg_line( pc, pd, 0xff00ffff ); @@ -1419,6 +1344,11 @@ static void player_walkgrid_getsurface(void) v3_muladds( delta, side, -ktimestep*k_walkspeed, delta ); if( glfwGetKey( vg_window, GLFW_KEY_D ) ) v3_muladds( delta, side, ktimestep*k_walkspeed, delta ); + + v3_muladds( delta, fwd, + vg_get_axis("vertical")*-ktimestep*k_walkspeed, delta ); + v3_muladds( delta, side, + vg_get_axis("horizontal")*ktimestep*k_walkspeed, delta ); } /* @@ -1440,73 +1370,6 @@ static void player_walkgrid_getsurface(void) wg.cell_id[0] = region_cell_pos[0]; wg.cell_id[1] = region_cell_pos[1]; - -#if 0 - /* Get surface samples - * - * TODO: Replace this with a spiral starting from the player position - */ - for( int y=0; ypos ); - s->pos[1] = cell[1]; - player_walkgrid_samplepole( s ); - } - } - - /* - * Calculate h+v clipping distances. - * Distances are stored in A always, so you know that if the sample is - * invalid, this signifies the start of the manifold as opposed to the - * extent or bounds of it. - */ - for( int i=0; i<2; i++ ) - { - for( int x=0; xtype == k_sample_type_valid && - sb->type == k_sample_type_valid ) - vg_line( sa->pos, sb->pos, 0xffffffff ); -#if 0 - if( sa->valid != sb->valid ) - { - clipdir[i*2] = (float)(sa->valid - sb->valid) * k_gridscale; - - player_walkgrid_clip( sa->valid? sa->pos: sb->pos, - clipdir, sa->clip[i] ); - } - else - { - if( sa->valid ) - { - vg_line( sa->pos, sb->pos, 0xffffffff ); - } - } -#endif - } - } - } -#endif - for(int y=0; y0.0f) reset_player(0,NULL); + if( vg_get_button_down( "switchmode" ) ) + { + player.on_board ^= 0x1; + } + if( freecam ) { player_freecam(); @@ -2177,8 +2029,41 @@ static void player_update(void) { if( player.is_dead ) { + /* + * Follow camera + */ character_ragdoll_iter( &player.mdl ); character_debug_ragdoll( &player.mdl ); + + v3f delta; + v3f head_pos; + v3_copy( player.mdl.ragdoll[k_chpart_head].co, head_pos ); + + v3_sub( head_pos, player.camera_pos, delta ); + v3_normalize( delta ); + + v3f follow_pos; + v3_muladds( head_pos, delta, -2.5f, follow_pos ); + v3_lerp( player.camera_pos, follow_pos, 0.1f, player.camera_pos ); + + /* + * Make sure the camera stays above the ground + */ + v3f min_height = {0.0f,1.0f,0.0f}; + + v3f sample; + v3_add( player.camera_pos, min_height, sample ); + ray_hit hit; + hit.dist = min_height[1]*2.0f; + + if( ray_world( sample, (v3f){0.0f,-1.0f,0.0f}, &hit )) + v3_add( hit.pos, min_height, player.camera_pos ); + + player.camera_pos[1] = + vg_maxf( wrender.height + 2.0f, player.camera_pos[1] ); + + player.angles[0] = atan2f( delta[0], -delta[2] ); + player.angles[1] = -asinf( delta[1] ); } else { diff --git a/render.h b/render.h index ef7a82f..d8bdc95 100644 --- a/render.h +++ b/render.h @@ -14,8 +14,15 @@ static struct pipeline } gpipeline; +struct framebuffer +{ + GLuint fb, colour, rb; + int div; + GLuint format; +}; + static void render_water_texture( m4x3f camera ); -static void render_water_surface( m4x4f pv ); +static void render_water_surface( m4x4f pv, m4x3f camera ); static void render_world( m4x4f projection, m4x3f camera ); /* @@ -47,41 +54,63 @@ static void pipeline_projection( m4x4f mat, float nearz, float farz ) nearz, farz ); } -static void create_renderbuffer_std( GLuint *fb, GLuint *rgb, GLuint *rb ) +static void fb_use( struct framebuffer *fb ) { - glGenFramebuffers( 1, fb ); - glBindFramebuffer( GL_FRAMEBUFFER, *fb ); + if( !fb ) + { + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + glViewport( 0, 0, vg_window_x, vg_window_y ); + } + else + { + glBindFramebuffer( GL_FRAMEBUFFER, fb->fb ); + glViewport( 0, 0, vg_window_x / fb->div, vg_window_y / fb->div ); + } +} - glGenTextures( 1, rgb ); - glBindTexture( GL_TEXTURE_2D, *rgb ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y, - 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); +static void fb_init( struct framebuffer *fb ) +{ + i32 ix = vg_window_x / fb->div, + iy = vg_window_y / fb->div; + + glGenFramebuffers( 1, &fb->fb ); + glBindFramebuffer( GL_FRAMEBUFFER, fb->fb ); + + glGenTextures( 1, &fb->colour ); + glBindTexture( GL_TEXTURE_2D, fb->colour ); + glTexImage2D( GL_TEXTURE_2D, 0, fb->format, ix, iy, + 0, fb->format, GL_UNSIGNED_BYTE, NULL); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, *rgb, 0); + GL_TEXTURE_2D, fb->colour, 0); - /* TODO: Check for DEPTH32f availiblity and use if possible */ - - glGenRenderbuffers( 1, rb ); - glBindRenderbuffer( GL_RENDERBUFFER, *rb ); - glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, - vg_window_x, vg_window_y ); + glGenRenderbuffers( 1, &fb->rb ); + glBindRenderbuffer( GL_RENDERBUFFER, fb->rb ); + glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ix, iy ); glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, *rb ); + GL_RENDERBUFFER, fb->rb ); } -static void resize_renderbuffer_std( GLuint *fb, GLuint *rgb, GLuint *rb ) +static void fb_bindtex( struct framebuffer *fb, int texture ) { - glBindTexture( GL_TEXTURE_2D, *rgb ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y, 0, - GL_RGB, GL_UNSIGNED_BYTE, NULL ); + glActiveTexture( GL_TEXTURE0 + texture ); + glBindTexture( GL_TEXTURE_2D, fb->colour ); +} + +static void fb_resize( struct framebuffer *fb ) +{ + i32 ix = vg_window_x / fb->div, + iy = vg_window_y / fb->div; + + glBindTexture( GL_TEXTURE_2D, fb->colour ); + glTexImage2D( GL_TEXTURE_2D, 0, fb->format, ix, iy, 0, + fb->format, GL_UNSIGNED_BYTE, NULL ); - glBindRenderbuffer( GL_RENDERBUFFER, *rb ); - glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, - vg_window_x, vg_window_y ); + glBindRenderbuffer( GL_RENDERBUFFER, fb->rb ); + glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, ix, iy ); } static void render_fb_resize(void) diff --git a/rigidbody.h b/rigidbody.h index aa74a84..845237f 100644 --- a/rigidbody.h +++ b/rigidbody.h @@ -4,15 +4,15 @@ */ #include "common.h" +#include "bvh.h" + static void rb_tangent_basis( v3f n, v3f tx, v3f ty ); +static bh_system bh_system_rigidbodies; #ifndef RIGIDBODY_H #define RIGIDBODY_H -#include "bvh.h" - #define RB_DEPR - #define k_rb_delta (1.0f/60.0f) typedef struct rigidbody rigidbody; @@ -289,7 +289,6 @@ static void rb_constraint_angle_limit( struct rb_angle_limit *limit ) } - RB_DEPR static void rb_constraint_angle( rigidbody *rba, v3f va, rigidbody *rbb, v3f vb, @@ -384,6 +383,10 @@ static void rb_constraint_position( rigidbody *ra, v3f lca, v3_add( impulse, ra->I, ra->I ); #if 0 + /* + * this could be used for spring joints + * its not good for position constraint + */ v3f impulse; v3_muls( delta, 0.5f*spring, impulse ); diff --git a/scene.h b/scene.h index b76aaee..6f7c28c 100644 --- a/scene.h +++ b/scene.h @@ -6,9 +6,6 @@ #include "bvh.h" typedef struct scene scene; -#if 0 -typedef struct bvh_node bvh_node; -#endif struct scene { @@ -17,17 +14,7 @@ struct scene model_vert *verts; u32 *indices; -#if 0 - struct - { - bvh_node *nodes; - u32 node_count; - } - bvh; -#else bh_tree bhtris; -#endif - u32 vertex_count, indice_count, vertex_cap, diff --git a/shaders/sky.fs b/shaders/sky.fs index 9e08967..653f4b9 100644 --- a/shaders/sky.fs +++ b/shaders/sky.fs @@ -12,25 +12,24 @@ in vec3 aCo; void main() { float fintensity = 1.0-(abs(aNorm.y)*0.7); - float angle = -dot(vec3(0.95,0.0,-0.3),aNorm)*0.5+0.5; - float fblend = pow(fintensity,6.0) * angle; - vec3 horizon = vec3(0.9,0.9,0.8); - vec3 skycolour = vec3(0.4,0.5,0.8); + float fblend = pow(fintensity,6.0); + vec3 horizon = vec3( 0.61, 0.71, 0.86 )*1.5; + vec3 skycolour = vec3( 0.31, 0.56, 0.91 ); vec3 diffuse = mix( skycolour, horizon, fblend ); - float fmove = uTime * 0.001; + float fmove = uTime * 0.004; vec2 cloudplane = (aCo.xz / (aCo.y*sign(aNorm.y))) * 0.03; vec4 clouds1 = texture( uTexGarbage, cloudplane + vec2(0.1,0.4)*fmove*2.0 ); vec4 clouds2 = texture( uTexGarbage, cloudplane + vec2(0.3,0.1)*fmove ); float cloud_d = max(clouds1.b*clouds2.r -0.2 - clouds2.g*0.4,0.0); - float cloud_e = pow(cloud_d,1.8)*pow(abs(aNorm.y),0.3)*2.0; + float cloud_e = pow(cloud_d,1.5)*pow(abs(aNorm.y),0.3)*2.0; vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 ); float fhorizon = step( aNorm.y * 0.5 + 0.5, 0.5 ); - vec3 skycomp = mix(diffuse, vec3(1.0), cloud_e); + vec3 skycomp = mix(diffuse, vec3(1.0,1.0,1.0), cloud_e); skycomp = mix(mix(pow(colour_ocean,vec3(6.0))*0.6,skycomp, 0.7),skycomp,fhorizon); - FragColor = vec4(skycomp, 1.0); + FragColor = vec4(skycomp, 0.0); } diff --git a/shaders/sky.h b/shaders/sky.h index 920036a..653173e 100644 --- a/shaders/sky.h +++ b/shaders/sky.h @@ -51,27 +51,26 @@ static struct vg_shader _shader_sky = { "void main()\n" "{\n" " float fintensity = 1.0-(abs(aNorm.y)*0.7);\n" -" float angle = -dot(vec3(0.95,0.0,-0.3),aNorm)*0.5+0.5;\n" -" float fblend = pow(fintensity,6.0) * angle;\n" -" vec3 horizon = vec3(0.9,0.9,0.8);\n" -" vec3 skycolour = vec3(0.4,0.5,0.8);\n" +" float fblend = pow(fintensity,6.0);\n" +" vec3 horizon = vec3( 0.61, 0.71, 0.86 )*1.5;\n" +" vec3 skycolour = vec3( 0.31, 0.56, 0.91 );\n" " vec3 diffuse = mix( skycolour, horizon, fblend );\n" "\n" -" float fmove = uTime * 0.001;\n" +" float fmove = uTime * 0.004;\n" " vec2 cloudplane = (aCo.xz / (aCo.y*sign(aNorm.y))) * 0.03;\n" " vec4 clouds1 = texture( uTexGarbage, cloudplane + vec2(0.1,0.4)*fmove*2.0 );\n" " vec4 clouds2 = texture( uTexGarbage, cloudplane + vec2(0.3,0.1)*fmove );\n" "\n" " float cloud_d = max(clouds1.b*clouds2.r -0.2 - clouds2.g*0.4,0.0);\n" -" float cloud_e = pow(cloud_d,1.8)*pow(abs(aNorm.y),0.3)*2.0;\n" +" float cloud_e = pow(cloud_d,1.5)*pow(abs(aNorm.y),0.3)*2.0;\n" "\n" " vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 );\n" " float fhorizon = step( aNorm.y * 0.5 + 0.5, 0.5 );\n" "\n" -" vec3 skycomp = mix(diffuse, vec3(1.0), cloud_e);\n" +" vec3 skycomp = mix(diffuse, vec3(1.0,1.0,1.0), cloud_e);\n" " skycomp = mix(mix(pow(colour_ocean,vec3(6.0))*0.6,skycomp, 0.7),skycomp,fhorizon);\n" "\n" -" FragColor = vec4(skycomp, 1.0);\n" +" FragColor = vec4(skycomp, 0.0);\n" "}\n" ""}, }; diff --git a/shaders/terrain.fs b/shaders/terrain.fs index fbfa276..98895a0 100644 --- a/shaders/terrain.fs +++ b/shaders/terrain.fs @@ -3,36 +3,52 @@ out vec4 FragColor; uniform sampler2D uTexGarbage; uniform sampler2D uTexGradients; uniform vec3 uCamera; +uniform vec4 uPlane; in vec4 aColour; in vec2 aUv; in vec3 aNorm; in vec3 aCo; +float water_depth( vec3 pos, vec3 dir, vec4 plane ) +{ + float d = dot( plane.xyz, dir ); + float t = dot((plane.xyz*plane.w - pos),plane.xyz) / d; + return t*0.05; +} + void main() { vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 ); + + // Creating normal patches vec3 modnorm = (wgarbage.rgb-0.4) * 1.4; - vec3 qnorm = floor(aNorm*4.0+modnorm) * 0.25; - + vec3 qnorm = normalize(floor(aNorm*4.0+modnorm) * 0.25); vec2 dir = normalize(qnorm.xz); vec2 uvdiffuse = aCo.xz * 0.02; uvdiffuse = mat2(dir.y, dir.x, -dir.x, dir.y) * uvdiffuse; - + + // Patch local noise vec4 rgarbage = texture( uTexGarbage, uvdiffuse ); + + // Colour blending float amtgrass = step(qnorm.y,0.6); + float amtsand = min(max((aCo.y + 90.0) * -0.08,0.0)*qnorm.y,1.0); vec2 uvgradients = vec2( rgarbage.a, -amtgrass*0.125 ) + aUv; vec3 diffuse = texture( uTexGradients, uvgradients ).rgb; - + diffuse = mix( diffuse, vec3(1.0,0.9,0.7), amtsand ); + + // Lighting vec3 lightdir = vec3(0.95,0.0,-0.3); vec3 shadow = pow(vec3(0.014,0.034,0.084),vec3(1.0/3.2)); - float light1 = 1.0-(dot( lightdir, qnorm )*0.5+0.5); + float light1 = dot( lightdir, mix(qnorm,aNorm,amtsand) )*0.5+0.5; + diffuse = diffuse * (light1*vec3(1.0,0.96,0.9)*1.2 + shadow*(1.0-light1)); - qnorm = floor(aNorm*8.0)*0.125; - vec3 viewdelta = normalize( uCamera - aCo ); + // Specular lighting + vec3 halfview = normalize( uCamera - aCo ); vec3 specdir = reflect( -lightdir, qnorm ); - float spec = pow(max(dot(viewdelta,specdir),0.0),10.0) * 0.2*rgarbage.r; - - diffuse = diffuse*(1.0-light1)+diffuse*shadow*light1; - FragColor = vec4(diffuse+spec, 1.0); + float spec = pow(max(dot(halfview,specdir),0.0),10.0) * 0.2*rgarbage.r; + diffuse += spec * vec3(1.0,0.8,0.8); + + FragColor = vec4(diffuse, water_depth(aCo,halfview,uPlane)); } diff --git a/shaders/terrain.h b/shaders/terrain.h index 0e22487..983e0ba 100644 --- a/shaders/terrain.h +++ b/shaders/terrain.h @@ -42,38 +42,54 @@ static struct vg_shader _shader_terrain = { "uniform sampler2D uTexGarbage;\n" "uniform sampler2D uTexGradients;\n" "uniform vec3 uCamera;\n" +"uniform vec4 uPlane;\n" "\n" "in vec4 aColour;\n" "in vec2 aUv;\n" "in vec3 aNorm;\n" "in vec3 aCo;\n" "\n" +"float water_depth( vec3 pos, vec3 dir, vec4 plane )\n" +"{\n" +" float d = dot( plane.xyz, dir );\n" +" float t = dot((plane.xyz*plane.w - pos),plane.xyz) / d;\n" +" return t*0.05;\n" +"}\n" +"\n" "void main()\n" "{\n" " vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 );\n" +" \n" +" // Creating normal patches\n" " vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;\n" -" vec3 qnorm = floor(aNorm*4.0+modnorm) * 0.25;\n" -"\n" +" vec3 qnorm = normalize(floor(aNorm*4.0+modnorm) * 0.25);\n" " vec2 dir = normalize(qnorm.xz);\n" " vec2 uvdiffuse = aCo.xz * 0.02;\n" " uvdiffuse = mat2(dir.y, dir.x, -dir.x, dir.y) * uvdiffuse;\n" -"\n" +" \n" +" // Patch local noise\n" " vec4 rgarbage = texture( uTexGarbage, uvdiffuse );\n" +"\n" +" // Colour blending\n" " float amtgrass = step(qnorm.y,0.6);\n" +" float amtsand = min(max((aCo.y + 90.0) * -0.08,0.0)*qnorm.y,1.0);\n" " vec2 uvgradients = vec2( rgarbage.a, -amtgrass*0.125 ) + aUv;\n" " vec3 diffuse = texture( uTexGradients, uvgradients ).rgb;\n" -" \n" +" diffuse = mix( diffuse, vec3(1.0,0.9,0.7), amtsand );\n" +"\n" +" // Lighting\n" " vec3 lightdir = vec3(0.95,0.0,-0.3);\n" " vec3 shadow = pow(vec3(0.014,0.034,0.084),vec3(1.0/3.2));\n" -" float light1 = 1.0-(dot( lightdir, qnorm )*0.5+0.5);\n" +" float light1 = dot( lightdir, mix(qnorm,aNorm,amtsand) )*0.5+0.5;\n" +" diffuse = diffuse * (light1*vec3(1.0,0.96,0.9)*1.2 + shadow*(1.0-light1));\n" " \n" -" qnorm = floor(aNorm*8.0)*0.125;\n" -" vec3 viewdelta = normalize( uCamera - aCo );\n" +" // Specular lighting\n" +" vec3 halfview = normalize( uCamera - aCo );\n" " vec3 specdir = reflect( -lightdir, qnorm );\n" -" float spec = pow(max(dot(viewdelta,specdir),0.0),10.0) * 0.2*rgarbage.r;\n" -" \n" -" diffuse = diffuse*(1.0-light1)+diffuse*shadow*light1;\n" -" FragColor = vec4(diffuse+spec, 1.0);\n" +" float spec = pow(max(dot(halfview,specdir),0.0),10.0) * 0.2*rgarbage.r;\n" +" diffuse += spec * vec3(1.0,0.8,0.8);\n" +"\n" +" FragColor = vec4(diffuse, water_depth(aCo,halfview,uPlane));\n" "}\n" ""}, }; @@ -83,6 +99,7 @@ static GLuint _uniform_terrain_uMdl; static GLuint _uniform_terrain_uTexGarbage; static GLuint _uniform_terrain_uTexGradients; static GLuint _uniform_terrain_uCamera; +static GLuint _uniform_terrain_uPlane; static void shader_terrain_uPv(m4x4f m){ glUniformMatrix4fv( _uniform_terrain_uPv, 1, GL_FALSE, (float *)m ); } @@ -98,6 +115,9 @@ static void shader_terrain_uTexGradients(int i){ static void shader_terrain_uCamera(v3f v){ glUniform3fv( _uniform_terrain_uCamera, 1, v ); } +static void shader_terrain_uPlane(v4f v){ + glUniform4fv( _uniform_terrain_uPlane, 1, v ); +} static void shader_terrain_register(void){ vg_shader_register( &_shader_terrain ); } @@ -108,5 +128,6 @@ static void shader_terrain_link(void){ _uniform_terrain_uTexGarbage = glGetUniformLocation( _shader_terrain.id, "uTexGarbage" ); _uniform_terrain_uTexGradients = glGetUniformLocation( _shader_terrain.id, "uTexGradients" ); _uniform_terrain_uCamera = glGetUniformLocation( _shader_terrain.id, "uCamera" ); + _uniform_terrain_uPlane = glGetUniformLocation( _shader_terrain.id, "uPlane" ); } #endif /* SHADER_terrain_H */ diff --git a/shaders/water.fs b/shaders/water.fs index da92d13..077a8e6 100644 --- a/shaders/water.fs +++ b/shaders/water.fs @@ -3,32 +3,57 @@ out vec4 FragColor; uniform sampler2D uTexMain; uniform sampler2D uTexDudv; uniform sampler2D uTexDepth; +uniform sampler2D uTexBack; + uniform vec2 uInvRes; uniform float uTime; +uniform vec3 uCamera; +uniform float uSurfaceY; + in vec4 aUv; in vec3 aCo; +in float aDepth; void main() { + // Reflected and warped texture vec2 ssuv = gl_FragCoord.xy*uInvRes; - vec4 dudva = texture( uTexDudv, aUv.xy + vec2(uTime*0.04f,uTime*0.03f) ); - vec4 dudvb = texture( uTexDudv, aUv.xy - vec2(uTime*0.1,uTime*0.054) ); - vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 2.0; + vec4 dudva = texture( uTexDudv, aUv.xy - vec2(uTime*0.004f,uTime*0.003f) ); + vec4 dudvb = texture( uTexDudv, aUv.xy*0.7 - vec2(uTime*0.01,uTime*0.0054) ); + vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 0.6; vec4 reflected = texture( uTexMain, ssuv+distortamt ); + + // Surface colour composite float depthvalue = texture( uTexDepth, aUv.zw ).r; - float opacity = smoothstep( 0.0, 0.1, depthvalue ); - vec3 colour_shore = vec3( 0.96, 0.98, 0.9 ); - vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 ); - vec3 surface_tint = mix( colour_shore, colour_ocean, depthvalue ); + vec3 colour_shore = vec3( 0.21, 0.6, 0.8 ); + vec3 colour_ocean = vec3( 0.01, 0.1, 0.2 ); + vec3 surface_tint = mix(colour_shore, colour_ocean, pow(depthvalue,1.8))*1.5; + + // Foam + float fband = fract( aCo.z*0.1+uTime*0.1-depthvalue*10.0 ); + fband = step( fband+dudvb.g*0.8, 0.5 ) * max((1.0-depthvalue*4.0),0.0); - vec3 comp_surf = mix(pow(surface_tint,vec3(6.0))*0.6,reflected.rgb, 0.7); + // Lighting + vec3 surfnorm = vec3(distortamt.x,1.0,distortamt.y); - float band = fract( aCo.z*0.1+uTime*0.1-depthvalue*10.0 ); - band = step( band + dudvb.g*0.8, 0.5 ) * max((1.0-depthvalue*4.0),0.0); + vec3 halfview = -normalize( aCo-uCamera ); + float ffresnel = pow(1.0-dot( surfnorm, halfview ),5.0); - FragColor = vec4(comp_surf + band*0.2,opacity+band*0.2); + vec3 lightdir = vec3(0.95,0.0,-0.3); + vec3 specdir = reflect( -lightdir, surfnorm ); + float spec = pow(max(dot(halfview,specdir),0.0),20.0)*0.3; + + // Depth + vec4 backsample = texture( uTexBack, ssuv+distortamt*0.1 ); + float depthblend = pow(backsample.a,0.8); + + // Composite + vec3 vsurface = mix(surface_tint*backsample.rgb, reflected.rgb, ffresnel ); + vsurface += spec; + + FragColor = mix( vec4(vsurface,depthblend), vec4(1.0,1.0,1.0,0.8), fband ); } diff --git a/shaders/water.h b/shaders/water.h index 8572613..67b0745 100644 --- a/shaders/water.h +++ b/shaders/water.h @@ -22,6 +22,7 @@ static struct vg_shader _shader_water = { "\n" "out vec4 aUv;\n" "out vec3 aCo;\n" +"out float aDepth;\n" "\n" "void main()\n" "{\n" @@ -29,8 +30,10 @@ static struct vg_shader _shader_water = { " gl_Position = uPv * vec4(world_pos,1.0);\n" "\n" " vec2 depth_coords = (world_pos.xz-uDepthBounds.xy)*uDepthBounds.zw;\n" -" aUv = vec4(world_pos.xz*0.1,depth_coords);\n" +" aUv = vec4(world_pos.xz*0.01,depth_coords);\n" " aCo = world_pos;\n" +"\n" +" aDepth = gl_Position.z;\n" "}\n" ""}, .fs = @@ -42,34 +45,59 @@ static struct vg_shader _shader_water = { "uniform sampler2D uTexMain;\n" "uniform sampler2D uTexDudv;\n" "uniform sampler2D uTexDepth;\n" +"uniform sampler2D uTexBack;\n" +"\n" "uniform vec2 uInvRes;\n" "uniform float uTime;\n" "\n" +"uniform vec3 uCamera;\n" +"uniform float uSurfaceY;\n" +"\n" "in vec4 aUv;\n" "in vec3 aCo;\n" +"in float aDepth;\n" "\n" "void main()\n" "{\n" +" // Reflected and warped texture\n" " vec2 ssuv = gl_FragCoord.xy*uInvRes;\n" -" vec4 dudva = texture( uTexDudv, aUv.xy + vec2(uTime*0.04f,uTime*0.03f) );\n" -" vec4 dudvb = texture( uTexDudv, aUv.xy - vec2(uTime*0.1,uTime*0.054) );\n" "\n" -" vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 2.0;\n" +" vec4 dudva = texture( uTexDudv, aUv.xy - vec2(uTime*0.004f,uTime*0.003f) );\n" +" vec4 dudvb = texture( uTexDudv, aUv.xy*0.7 - vec2(uTime*0.01,uTime*0.0054) );\n" +" vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 0.6;\n" "\n" " vec4 reflected = texture( uTexMain, ssuv+distortamt );\n" +" \n" +" // Surface colour composite\n" " float depthvalue = texture( uTexDepth, aUv.zw ).r;\n" -" float opacity = smoothstep( 0.0, 0.1, depthvalue );\n" "\n" -" vec3 colour_shore = vec3( 0.96, 0.98, 0.9 );\n" -" vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 );\n" -" vec3 surface_tint = mix( colour_shore, colour_ocean, depthvalue );\n" +" vec3 colour_shore = vec3( 0.21, 0.6, 0.8 );\n" +" vec3 colour_ocean = vec3( 0.01, 0.1, 0.2 );\n" +" vec3 surface_tint = mix(colour_shore, colour_ocean, pow(depthvalue,1.8))*1.5;\n" +" \n" +" // Foam\n" +" float fband = fract( aCo.z*0.1+uTime*0.1-depthvalue*10.0 );\n" +" fband = step( fband+dudvb.g*0.8, 0.5 ) * max((1.0-depthvalue*4.0),0.0);\n" "\n" -" vec3 comp_surf = mix(pow(surface_tint,vec3(6.0))*0.6,reflected.rgb, 0.7);\n" +" // Lighting\n" +" vec3 surfnorm = vec3(distortamt.x,1.0,distortamt.y);\n" " \n" -" float band = fract( aCo.z*0.1+uTime*0.1-depthvalue*10.0 );\n" -" band = step( band + dudvb.g*0.8, 0.5 ) * max((1.0-depthvalue*4.0),0.0);\n" +" vec3 halfview = -normalize( aCo-uCamera );\n" +" float ffresnel = pow(1.0-dot( surfnorm, halfview ),5.0);\n" "\n" -" FragColor = vec4(comp_surf + band*0.2,opacity+band*0.2);\n" +" vec3 lightdir = vec3(0.95,0.0,-0.3);\n" +" vec3 specdir = reflect( -lightdir, surfnorm );\n" +" float spec = pow(max(dot(halfview,specdir),0.0),20.0)*0.3;\n" +" \n" +" // Depth \n" +" vec4 backsample = texture( uTexBack, ssuv+distortamt*0.1 );\n" +" float depthblend = pow(backsample.a,0.8);\n" +"\n" +" // Composite\n" +" vec3 vsurface = mix(surface_tint*backsample.rgb, reflected.rgb, ffresnel );\n" +" vsurface += spec;\n" +" \n" +" FragColor = mix( vec4(vsurface,depthblend), vec4(1.0,1.0,1.0,0.8), fband );\n" "}\n" ""}, }; @@ -80,8 +108,11 @@ static GLuint _uniform_water_uDepthBounds; static GLuint _uniform_water_uTexMain; static GLuint _uniform_water_uTexDudv; static GLuint _uniform_water_uTexDepth; +static GLuint _uniform_water_uTexBack; static GLuint _uniform_water_uInvRes; static GLuint _uniform_water_uTime; +static GLuint _uniform_water_uCamera; +static GLuint _uniform_water_uSurfaceY; static void shader_water_uPv(m4x4f m){ glUniformMatrix4fv( _uniform_water_uPv, 1, GL_FALSE, (float *)m ); } @@ -100,12 +131,21 @@ static void shader_water_uTexDudv(int i){ static void shader_water_uTexDepth(int i){ glUniform1i( _uniform_water_uTexDepth, i ); } +static void shader_water_uTexBack(int i){ + glUniform1i( _uniform_water_uTexBack, i ); +} static void shader_water_uInvRes(v2f v){ glUniform2fv( _uniform_water_uInvRes, 1, v ); } static void shader_water_uTime(float f){ glUniform1f( _uniform_water_uTime, f ); } +static void shader_water_uCamera(v3f v){ + glUniform3fv( _uniform_water_uCamera, 1, v ); +} +static void shader_water_uSurfaceY(float f){ + glUniform1f( _uniform_water_uSurfaceY, f ); +} static void shader_water_register(void){ vg_shader_register( &_shader_water ); } @@ -117,7 +157,10 @@ static void shader_water_link(void){ _uniform_water_uTexMain = glGetUniformLocation( _shader_water.id, "uTexMain" ); _uniform_water_uTexDudv = glGetUniformLocation( _shader_water.id, "uTexDudv" ); _uniform_water_uTexDepth = glGetUniformLocation( _shader_water.id, "uTexDepth" ); + _uniform_water_uTexBack = glGetUniformLocation( _shader_water.id, "uTexBack" ); _uniform_water_uInvRes = glGetUniformLocation( _shader_water.id, "uInvRes" ); _uniform_water_uTime = glGetUniformLocation( _shader_water.id, "uTime" ); + _uniform_water_uCamera = glGetUniformLocation( _shader_water.id, "uCamera" ); + _uniform_water_uSurfaceY = glGetUniformLocation( _shader_water.id, "uSurfaceY" ); } #endif /* SHADER_water_H */ diff --git a/shaders/water.vs b/shaders/water.vs index 3d6372c..c8ac51b 100644 --- a/shaders/water.vs +++ b/shaders/water.vs @@ -6,6 +6,7 @@ uniform vec4 uDepthBounds; out vec4 aUv; out vec3 aCo; +out float aDepth; void main() { @@ -13,6 +14,8 @@ void main() gl_Position = uPv * vec4(world_pos,1.0); vec2 depth_coords = (world_pos.xz-uDepthBounds.xy)*uDepthBounds.zw; - aUv = vec4(world_pos.xz*0.1,depth_coords); + aUv = vec4(world_pos.xz*0.01,depth_coords); aCo = world_pos; + + aDepth = gl_Position.z; } diff --git a/terrain.h b/terrain.h index 3005c93..d35dc0a 100644 --- a/terrain.h +++ b/terrain.h @@ -1,10 +1,14 @@ +#include "common.h" + +static void render_terrain(m4x4f projection, v3f camera); +static void render_sky(m4x3f camera); + #ifndef TERRAIN_H #define TERRAIN_H -#define VG_3D -#include "vg/vg.h" #include "model.h" #include "render.h" +#include "water.h" #include "shaders/terrain.h" #include "shaders/sky.h" @@ -52,6 +56,7 @@ static void render_terrain(m4x4f projection, v3f camera) shader_terrain_uPv( projection ); shader_terrain_uMdl( identity_matrix ); shader_terrain_uCamera( camera ); + shader_terrain_uPlane( (v4f){ 0.0f,1.0f,0.0f, wrender.height } ); } static void render_sky(m4x3f camera) diff --git a/textures/gradients.png b/textures/gradients.png index 660ec90..201e051 100644 Binary files a/textures/gradients.png and b/textures/gradients.png differ diff --git a/textures/water_surf.png b/textures/water_surf.png index 90417f7..493f823 100644 Binary files a/textures/water_surf.png and b/textures/water_surf.png differ diff --git a/vg_config.h b/vg_config.h index 4b305e9..92fd2e8 100644 --- a/vg_config.h +++ b/vg_config.h @@ -20,7 +20,8 @@ static struct button_binding vg_button_binds[] = static struct button_binding vg_controller_binds[] = { { "push", GLFW_GAMEPAD_BUTTON_A }, - { "break", GLFW_GAMEPAD_BUTTON_B } + { "break", GLFW_GAMEPAD_BUTTON_B }, + { "switchmode", GLFW_GAMEPAD_BUTTON_Y } }; static struct axis_binding vg_axis_binds[] = diff --git a/water.h b/water.h index 83a6cf8..bcd0c68 100644 --- a/water.h +++ b/water.h @@ -1,10 +1,17 @@ +#include "common.h" +#include "model.h" + +static void water_register(void); +static void water_init(void); +static void water_fb_resize(void); +static void water_compute_depth( boxf bounds ); +static void water_set_surface( glmesh *surf, float height ); +static float water_height(void); + #ifndef WATER_H #define WATER_H -#define VG_3D -#include "vg/vg.h" - -#include "model.h" +#include "world.h" #include "render.h" #include "shaders/water.h" #include "scene.h" @@ -13,7 +20,7 @@ vg_tex2d tex_water_surf = { .path = "textures/water_surf.qoi" }; static struct { - GLuint fb, rgb, rb; + struct framebuffer fbreflect, fbdepth; glmesh mdl; GLuint depthmap; @@ -23,7 +30,16 @@ static struct float height; int enabled; } -wrender; +wrender = +{ + .fbreflect = { .format = GL_RGB, .div = 2 }, + .fbdepth = { .format = GL_RGBA, .div = 2 } +}; + +static float water_height(void) +{ + return wrender.height; +} static void water_register(void) { @@ -33,11 +49,21 @@ static void water_register(void) static void water_init(void) { /* TODO: probably dont do this every time */ - create_renderbuffer_std( &wrender.fb, &wrender.rgb, &wrender.rb ); wrender.enabled = 1; + + fb_init( &wrender.fbreflect ); + fb_init( &wrender.fbdepth ); +} + +static void water_fb_resize(void) +{ + if( !wrender.enabled ) + return; + + fb_resize( &wrender.fbreflect ); + fb_resize( &wrender.fbdepth ); } -static int ray_world( v3f pos, v3f dir, ray_hit *hit ); static void water_compute_depth( boxf bounds ) { if( !wrender.enabled ) @@ -104,22 +130,13 @@ static void water_set_surface( glmesh *surf, float height ) wrender.height = height; } -static void water_fb_resize(void) -{ - if( !wrender.enabled ) - return; - - resize_renderbuffer_std( &wrender.fb, &wrender.rgb, &wrender.rb ); -} - static void render_water_texture( m4x3f camera ) { if( !wrender.enabled ) return; /* Draw reflection buffa */ - glBindFramebuffer( GL_FRAMEBUFFER, wrender.fb ); - glClearColor( 0.11f, 0.35f, 0.37f, 1.0f ); + fb_use( &wrender.fbreflect ); glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); m4x3f new_cam, inverse; @@ -158,9 +175,34 @@ static void render_water_texture( m4x3f camera ) glCullFace( GL_FRONT ); render_world( projection, new_cam ); glCullFace( GL_BACK ); + + + /* Draw beneath texture */ + fb_use( &wrender.fbdepth ); + glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); + + m4x3_invert_affine( camera, inverse ); + m4x3_expand( inverse, view ); + + v4f clippb = { 0.0f, -1.0f, 0.0f, -(wrender.height) }; + m4x3_mulp( inverse, clippb, clippb ); + clippb[3] *= -1.0f; + + float depth_loss = camera[3][1]-wrender.height; + + m4x4_projection( projection, + gpipeline.fov, + (float)vg_window_x / (float)vg_window_y, + 0.1f, 900.0f ); + + plane_clip_projection( projection, clippb ); + m4x4_mul( projection, view, projection ); + render_world( projection, camera ); + + glViewport( 0, 0, vg_window_x, vg_window_y ); } -static void render_water_surface( m4x4f pv ) +static void render_water_surface( m4x4f pv, m4x3f camera ) { if( !wrender.enabled ) return; @@ -168,8 +210,7 @@ static void render_water_surface( m4x4f pv ) /* Draw surface */ shader_water_use(); - glActiveTexture( GL_TEXTURE0 ); - glBindTexture( GL_TEXTURE_2D, wrender.rgb ); + fb_bindtex( &wrender.fbreflect, 0 ); shader_water_uTexMain( 0 ); vg_tex2d_bind( &tex_water_surf, 1 ); @@ -187,7 +228,13 @@ static void render_water_surface( m4x4f pv ) 1.0f/ (wrender.depthbounds[1][0]-wrender.depthbounds[0][0]), 1.0f/ (wrender.depthbounds[1][2]-wrender.depthbounds[0][2])} ); + fb_bindtex( &wrender.fbdepth, 3 ); + shader_water_uTexBack( 3 ); + shader_water_uTime( vg_time ); + shader_water_uCamera( camera[3] ); + shader_water_uSurfaceY( wrender.height ); + shader_water_uPv( pv ); m4x3f full; diff --git a/world.h b/world.h index ea5a5c4..73b42a4 100644 --- a/world.h +++ b/world.h @@ -1,9 +1,10 @@ +#include "common.h" + +static int ray_world( v3f pos, v3f dir, ray_hit *hit ); + #ifndef WORLD_H #define WORLD_H -#define VG_3D -#include "vg/vg.h" - #include "scene.h" #include "terrain.h" #include "render.h" @@ -22,10 +23,6 @@ static struct gworld v3f tutorial; -#if 0 - rigidbody box; -#endif - teleport_gate gates[16]; u32 gate_count; @@ -69,7 +66,6 @@ static int ray_hit_is_ramp( ray_hit *hit ) return hit->tri[0] < world.sm_road.vertex_count; } -static bh_system bh_system_rigidbodies; static void world_load(void) { /* Setup scene */ @@ -207,7 +203,7 @@ static void world_load(void) if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit )) { if( hit.normal[1] > 0.8f && !ray_hit_is_ramp(&hit) && - hit.pos[1] > wrender.height ) + hit.pos[1] > water_height()+10.0f ) { v4f qsurface, qrandom; v3f axis; @@ -222,7 +218,7 @@ static void world_load(void) v3_copy( hit.pos, transform[3] ); - if( vg_randf() < 0.00000006f ) + if( vg_randf() < 0.0006f ) { m3x3_identity( transform ); scene_add_foliage( &world.foliage, mfoliage, sm_tree, transform);