From: hgn Date: Mon, 20 Jun 2022 14:54:24 +0000 (+0100) Subject: update to new shader system X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=1f1d636056450dcd23cce55c0795ec6276272531;p=carveJwlIkooP6JGAAIwe30JlM.git update to new shader system --- diff --git a/character.h b/character.h index f161f7d..f86830a 100644 --- a/character.h +++ b/character.h @@ -1,57 +1,15 @@ #ifndef CHARACTER_H #define CHARACTER_H +/* TODO: -> Common.h */ +#define VG_3D #include "vg/vg.h" + #include "model.h" #include "scene.h" #include "ik.h" #include "rigidbody.h" - -SHADER_DEFINE( shader_player, - - /*Include*/ VERTEX_STANDARD_ATTRIBUTES - - "uniform mat4 uPv;" - "uniform mat4x3 uMdl;" - "uniform float uOpacity;" - "" - "out vec4 aColour;" - "out vec2 aUv;" - "out vec3 aNorm;" - "out vec3 aCo;" - "out float aOpacity;" - "" - "void main()" - "{" - "vec3 world_pos = uMdl * vec4(a_co,1.0);" - "gl_Position = uPv * vec4(world_pos,1.0);" - - "aColour = a_colour;" - "aUv = a_uv;" - "aNorm = mat3(uMdl) * a_norm;" - "aCo = a_co;" - "aOpacity = 1.0-(gl_Position.y+0.5)*uOpacity;" - "}", - /* Fragment */ - "out vec4 FragColor;" - "" - "uniform sampler2D uTexMain;" - "uniform vec4 uColour;" - "" - "in vec4 aColour;" - "in vec2 aUv;" - "in vec3 aNorm;" - "in vec3 aCo;" - "in float aOpacity;" - "" - "void main()" - "{" - "vec3 diffuse = texture( uTexMain, aUv ).rgb;" - "FragColor = vec4(pow(diffuse,vec3(1.0)),aOpacity);" - "}" - , - UNIFORMS({ "uTexMain", "uPv", "uMdl", "uOpacity" }) -) +#include "shaders/character.h" #define FOREACH_PART(FN) \ FN( foot_l ) \ @@ -544,14 +502,11 @@ static void character_testpose( struct character *ch, float t ) static void character_draw( struct character *ch, float temp ) { - SHADER_USE(shader_player); - glUniformMatrix4fv( SHADER_UNIFORM( shader_player, "uPv" ), - 1, GL_FALSE, (float *)vg_pv ); - - glUniform1i( SHADER_UNIFORM( shader_player, "uTexMain" ), 0 ); - glUniform1f( SHADER_UNIFORM( shader_player, "uOpacity" ), temp ); + shader_character_use(); - GLint kuMdl = SHADER_UNIFORM( shader_player, "uMdl" ); + shader_character_uPv( vg_pv ); + shader_character_uTexMain( 0 ); + shader_character_uOpacity( temp ); glEnable( GL_CULL_FACE ); glCullFace( GL_BACK ); @@ -560,7 +515,7 @@ static void character_draw( struct character *ch, float temp ) for( int i=4; imatrices[i] ); + shader_character_uMdl( ch->matrices[i] ); submodel_draw( &ch->parts[i] ); } @@ -568,22 +523,22 @@ static void character_draw( struct character *ch, float temp ) { if( ch->shoes[i] ) { - glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)ch->matrices[i] ); + shader_character_uMdl( ch->matrices[i] ); submodel_draw( &ch->parts[i] ); } else { - glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)ch->matrices[i+2] ); + shader_character_uMdl( ch->matrices[i+2] ); submodel_draw( &ch->parts[i] ); - glUniformMatrix4x3fv( kuMdl, 1, GL_FALSE, (float *)ch->matrices[i] ); + shader_character_uMdl( ch->matrices[i] ); submodel_draw( &ch->parts[i+2] ); } } } -static void character_shader_register(void) +static void character_register(void) { - SHADER_INIT(shader_player); + shader_character_register(); } diff --git a/gate.h b/gate.h index c0bdbaa..65dda90 100644 --- a/gate.h +++ b/gate.h @@ -1,40 +1,18 @@ #ifndef GATE_H #define GATE_H +#define VG_3D #include "vg/vg.h" - -static const float k_gatesize = 4.0f; - -SHADER_DEFINE( shader_gate, - "layout (location=0) in vec3 a_co;" - "uniform mat4 uPv;" - "uniform mat4x3 uMdl;" - "" - "void main()" - "{" - "gl_Position = uPv * vec4(uMdl * vec4( a_co, 1.0 ),1.0);" - "}", - - /* Fragment */ - "out vec4 FragColor;" - "" - "uniform sampler2D uTexMain;" - "uniform vec2 uInvRes;" - "" - "void main()" - "{" - "vec2 uv = gl_FragCoord.xy*uInvRes;" - "FragColor = texture( uTexMain, uv );" - "}" - , - UNIFORMS({ "uPv", "uMdl", "uTexMain", "uInvRes" }) -) +#include "model.h" +#include "render.h" +#include "shaders/gate.h" typedef struct teleport_gate teleport_gate; static struct { GLuint fb, rgb, rb, vao, vbo; + glmesh mdl; } grender; @@ -42,6 +20,7 @@ struct teleport_gate { v3f co; v4f q; + v2f dims; m4x3f to_world, to_local; teleport_gate *other; @@ -57,40 +36,18 @@ static void gate_transform_update( teleport_gate *gate ) static void gate_register(void) { - SHADER_INIT( shader_gate ); + shader_gate_register(); } -static void gate_init(void) +static void gate_init( void (*newfb)(GLuint*,GLuint*,GLuint*) ) { - glGenFramebuffers( 1, &grender.fb ); - glBindFramebuffer( GL_FRAMEBUFFER, grender.fb ); - - glGenTextures( 1, &grender.rgb ); - glBindTexture( GL_TEXTURE_2D, grender.rgb ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y, - 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 ); - glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, grender.rgb, 0); - - /* TODO: Check for DEPTH32f availiblity and use if possible */ - - glGenRenderbuffers( 1, &grender.rb ); - glBindRenderbuffer( GL_RENDERBUFFER, grender.rb ); - glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, - vg_window_x, vg_window_y ); - - glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, grender.rb ); - + newfb( &grender.fb, &grender.rgb, &grender.rb ); { - float ksz = k_gatesize; + float ksz = 1.0f; float quad[] = { -ksz,-ksz,0.0f, ksz, ksz,0.0f, -ksz, ksz,0.0f, -ksz,-ksz,0.0f, ksz,-ksz,0.0f, ksz, ksz,0.0f, - -ksz,-ksz,0.0f, -ksz, ksz,0.0f, ksz, ksz,0.0f, - -ksz,-ksz,0.0f, ksz, ksz,0.0f, ksz,-ksz,0.0f }; + -ksz,-ksz,-0.1f, ksz, ksz,-0.1f, -ksz, ksz,-0.1f, + -ksz,-ksz,-0.1f, ksz,-ksz,-0.1f, ksz, ksz,-0.1f }; glGenVertexArrays( 1, &grender.vao ); glGenBuffers( 1, &grender.vbo ); @@ -103,44 +60,43 @@ static void gate_init(void) glEnableVertexAttribArray( 0 ); VG_CHECK_GL(); } -} -static void render_world(m4x4f pv); + model *mgate = vg_asset_read( "models/rs_gate.mdl" ); + model_unpack( mgate, &grender.mdl ); + free( mgate ); +} -/* - * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf - */ -static void plane_clip_projection( m4x4f mat, v4f plane ) +static void gate_fb_resize( void (*resize)(GLuint*,GLuint*,GLuint*) ) { - 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]; + resize( &grender.fb, &grender.rgb, &grender.rb ); } -static void render_gate( teleport_gate *gate, m4x3f camera, float fov ) +static void render_gate( teleport_gate *gate, m4x3f camera ) { - m4x3f transport; + v3f viewpos, viewdir, gatedir; + v3_copy( camera[3], viewpos ); + m3x3_mulv( camera, (v3f){0.0f,0.0f,-1.0f}, viewdir ); + m3x3_mulv( gate->to_world, (v3f){0.0f,0.0f,-1.0f}, gatedir ); + + if( v3_dot(viewdir, gatedir) <= 0.0f ) + return; + + v3f v0; + v3_sub( viewpos, gate->co, v0 ); + if( v3_dot(v0, gatedir) >= 0.0f ) + return; + m4x3f transport; m4x3_mul( gate->other->to_world, gate->to_local, transport ); v3f a,b,c,d; - - float ksz = k_gatesize; - m4x3_mulv( gate->to_world, (v3f){-ksz,-ksz,0.0f}, a ); - m4x3_mulv( gate->to_world, (v3f){ ksz,-ksz,0.0f}, b ); - m4x3_mulv( gate->to_world, (v3f){ ksz, ksz,0.0f}, c ); - m4x3_mulv( gate->to_world, (v3f){-ksz, ksz,0.0f}, 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 ); vg_line( a,b, 0xffffa000 ); vg_line( b,c, 0xffffa000 ); @@ -155,10 +111,9 @@ static void render_gate( teleport_gate *gate, m4x3f camera, float fov ) vg_line_pt3( cam_new[3], 0.3f, 0xff00ff00 ); glBindFramebuffer( GL_FRAMEBUFFER, grender.fb ); - glClearColor( 0.0f, 0.0f, 1.0f, 1.0f ); + glClearColor( 0.11f, 0.35f, 0.37f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); - m4x3f inverse; m4x3_invert_affine( cam_new, inverse ); @@ -171,9 +126,9 @@ static void render_gate( teleport_gate *gate, m4x3f camera, float fov ) m4x4f projection; m4x4_projection( projection, - fov, + gpipeline.fov, (float)vg_window_x / (float)vg_window_y, - 0.01f, 900.0f ); + 0.1f, 900.0f ); #if 0 /* For debugging frustum */ { @@ -244,22 +199,39 @@ static void render_gate( teleport_gate *gate, m4x3f camera, float fov ) m4x4_mul( projection, view, projection ); render_world( projection ); + render_water_texture( cam_new ); + glBindFramebuffer( GL_FRAMEBUFFER, grender.fb ); + render_water_surface( projection ); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - SHADER_USE( shader_gate ); + shader_gate_use(); + + m4x3f full; + m4x3_copy( gate->to_world, full ); + m4x3_scalev( full, (v3f){ gate->dims[0], gate->dims[1], 1.0f } ); - glUniformMatrix4fv( SHADER_UNIFORM( shader_gate, "uPv" ), - 1, GL_FALSE, (float *)vg_pv ); - glUniformMatrix4x3fv( SHADER_UNIFORM( shader_gate, "uMdl" ), - 1, GL_FALSE, (float *)gate->to_world ); + shader_gate_uPv( vg_pv ); + shader_gate_uMdl( full ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, grender.rgb ); - glUniform1i( SHADER_UNIFORM( shader_gate, "uTexMain"), 0 ); - glUniform2f( SHADER_UNIFORM( shader_gate, "uInvRes"), + shader_gate_uCam( viewpos ); + shader_gate_uTexMain( 0 ); + shader_gate_uTexWater( 1 ); + shader_gate_uTime( vg_time*0.25f ); + shader_gate_uInvRes( (v2f){ 1.0f / (float)vg_window_x, - 1.0f / (float)vg_window_y ); + 1.0f / (float)vg_window_y }); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + + mesh_bind( &grender.mdl ); + mesh_draw( &grender.mdl ); + glDisable(GL_BLEND); + return; glBindVertexArray( grender.vao ); glDrawArrays( GL_TRIANGLES, 0, 12 ); } @@ -295,7 +267,7 @@ static int gate_intersect( teleport_gate *gate, v3f pos, v3f last ) v2f xy = { v3_dot( rel, vside ), v3_dot( rel, vup ) }; - if( fabsf(xy[0]) <= k_gatesize && fabsf(xy[1]) <= k_gatesize ) + if( fabsf(xy[0]) <= gate->dims[0] && fabsf(xy[1]) <= gate->dims[1] ) { return 1; } diff --git a/main.c b/main.c index 9b7bef6..5772858 100644 --- a/main.c +++ b/main.c @@ -10,41 +10,7 @@ vg_tex2d tex_gradients = { .path = "textures/gradients.qoi", .flags = VG_TEXTURE_CLAMP }; vg_tex2d tex_cement = { .path = "textures/cement512.qoi" }; vg_tex2d tex_pallet = { .path = "textures/ch_gradient.qoi" }; - -vg_tex2d *texture_list[] = -{ - &tex_norwey, - &tex_gradients, - &tex_grid, - &tex_sky, - &tex_cement, - &tex_pallet -}; - -SHADER_DEFINE( shader_blit, - "layout (location=0) in vec2 a_co;" - "out vec2 aUv;" - "" - "void main()" - "{" - "gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);" - "aUv = a_co;" - "}", - - /* Fragment */ - "out vec4 FragColor;" - "" - "uniform sampler2D uTexMain;" - "" - "in vec2 aUv;" - "" - "void main()" - "{" - "FragColor = texture( uTexMain, aUv );" - "}" - , - UNIFORMS({ "uTexMain" }) -) +vg_tex2d tex_water = { .path = "textures/water.qoi" }; /* Convars */ static int freecam = 0; @@ -69,7 +35,37 @@ static int replay_buffer_frame = 0; #include "terrain.h" #include "ragdoll.h" #include "rigidbody.h" +#include "render.h" #include "gate.h" +#include "water.h" + +#include "shaders/blit.h" +#include "shaders/standard.h" +#include "shaders/unlit.h" + +void vg_register(void) +{ + shader_blit_register(); + shader_standard_register(); + shader_unlit_register(); + + terrain_register(); + character_register(); + water_register(); + gate_register(); +} + +vg_tex2d *texture_list[] = +{ + &tex_norwey, + &tex_gradients, + &tex_grid, + &tex_sky, + &tex_cement, + &tex_pallet, + &tex_water, + &tex_water_surf +}; int main( int argc, char *argv[] ) { @@ -81,7 +77,7 @@ m4x3f world_matrix; static struct gplayer { /* Physics */ - v3f co, v, a, v_last; + v3f co, v, a, v_last, m, bob; v4f rot; float vswitch, slip, slip_last, reverse; @@ -118,6 +114,7 @@ static struct gworld { scene geo; submodel sm_road, sm_terrain; + glmesh skybox; v3f tutorial; } @@ -195,12 +192,41 @@ static int playermodel( int argc, char const *argv[] ) return 1; } -void vg_register(void) +static void create_renderbuffer_std( GLuint *fb, GLuint *rgb, GLuint *rb ) { - scene_register(); - gate_register(); - character_shader_register(); - SHADER_INIT( shader_blit ); + glGenFramebuffers( 1, fb ); + glBindFramebuffer( GL_FRAMEBUFFER, *fb ); + + 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); + + 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); + + /* 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 ); + + glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, *rb ); +} + +static void resize_renderbuffer_std( GLuint *fb, GLuint *rgb, GLuint *rb ) +{ + 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 ); + + glBindRenderbuffer( GL_RENDERBUFFER, *rb ); + glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, + vg_window_x, vg_window_y ); } void vg_start(void) @@ -320,6 +346,9 @@ void vg_start(void) v3_copy( gb->co, gate_b.co ); v4_copy( ga->q, gate_a.q ); v4_copy( gb->q, gate_b.q ); + v2_copy( ga->s, gate_a.dims ); + v2_copy( gb->s, gate_b.dims ); + gate_a.other = &gate_b; gate_b.other = &gate_a; @@ -327,11 +356,26 @@ void vg_start(void) gate_transform_update( &gate_b ); } + /* WATER DEV */ + { + glmesh surf; + submodel *sm = submodel_get(mworld,"mp_dev_water"); + model_unpack_submodel( mworld, &surf, sm ); + + water_init( create_renderbuffer_std ); + water_set_surface( &surf, sm->pivot[1] ); + } + { + model *msky = vg_asset_read("models/rs_skydome.mdl"); + model_unpack( msky, &world.skybox ); + free(msky); + } + free( mworld ); scene_upload( &world.geo ); bvh_create( &world.geo ); - reset_player( 0, NULL ); + reset_player( 1, (const char *[]){ "tutorial" } ); player_transform_update(); /* Create framebuffers */ @@ -349,7 +393,7 @@ void vg_start(void) GL_TEXTURE_2D, render.rgb_background, 0); - gate_init(); + gate_init( create_renderbuffer_std ); { float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, @@ -627,8 +671,10 @@ static void player_physics_ground(void) m3x3_mulv( player.to_local, player.v, vel ); /* Calculate local forces */ + + if( fabsf(vel[2]) > 0.01f ) + slip = fabsf(-vel[0] / vel[2]) * vg_signf(vel[0]); - slip = fabsf(-vel[0] / vel[2]) * vg_signf(vel[0]); if( fabsf( slip ) > 1.2f ) slip = vg_signf( slip ) * 1.2f; player.slip = slip; @@ -857,10 +903,6 @@ static void player_update(void) q_axis_angle( rotate, vup, siY ); q_mul( rotate, player.rot, player.rot ); - player.look_dir[0] = atan2f( player.v[0], -player.v[2] ); - player.look_dir[1] = atan2f( -player.v[1], sqrtf(player.v[0]*player.v[0]+ - player.v[2]*player.v[2]) ) * 0.3f; - player.iY = 0.0f; /* temp */ /* GATE COLLISION */ @@ -873,6 +915,8 @@ static void player_update(void) m4x3_mulv( transport, player.co, player.co ); m3x3_mulv( transport, player.v, player.v ); m3x3_mulv( transport, player.v_last, player.v_last ); + m3x3_mulv( transport, player.m, player.m ); + m3x3_mulv( transport, player.bob, player.bob ); v4f transport_rotation; m3x3_q( transport, transport_rotation ); @@ -881,8 +925,11 @@ static void player_update(void) /* Camera and character */ player_transform_update(); - q_normalize(player.rot); player_animate(); + + player.look_dir[0] = atan2f( player.v[0], -player.v[2] ); + player.look_dir[1] = atan2f( -player.v[1], sqrtf(player.v[0]*player.v[0]+ + player.v[2]*player.v[2]) ) * 0.3f; } void vg_update(void) @@ -933,20 +980,18 @@ void vg_update(void) static void player_animate(void) { /* Camera position */ - static v3f momentum, bob; - v3_sub( player.v, player.v_last, player.a ); v3_copy( player.v, player.v_last ); - v3_add( momentum, player.a, momentum ); - v3_lerp( momentum, (v3f){0.0f,0.0f,0.0f}, 0.1f, momentum ); + v3_add( player.m, player.a, player.m ); + v3_lerp( player.m, (v3f){0.0f,0.0f,0.0f}, 0.1f, player.m ); v3f target; - momentum[0] = vg_clampf( momentum[0], -2.0f, 2.0f ); - momentum[1] = vg_clampf( momentum[1], -0.2f, 5.0f ); - momentum[2] = vg_clampf( momentum[2], -2.0f, 2.0f ); - v3_copy( momentum, target ); - v3_lerp( bob, target, 0.2f, bob ); + player.m[0] = vg_clampf( player.m[0], -2.0f, 2.0f ); + player.m[1] = vg_clampf( player.m[1], -0.2f, 5.0f ); + player.m[2] = vg_clampf( player.m[2], -2.0f, 2.0f ); + v3_copy( player.m, target ); + v3_lerp( player.bob, target, 0.2f, player.bob ); /* Head */ float lslip = fabsf(player.slip); //vg_minf( 0.4f, slip ); @@ -963,7 +1008,7 @@ static void player_animate(void) head[2] = 0.0f; v3f offset; - m3x3_mulv( player.to_local, bob, offset ); + m3x3_mulv( player.to_local, player.bob, offset ); offset[0] *= 0.3333f; offset[1] *= -0.25f; @@ -1147,24 +1192,38 @@ static void vg_framebuffer_resize( int w, int h ) glBindTexture( GL_TEXTURE_2D, render.rgb_background ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL ); + + gate_fb_resize( resize_renderbuffer_std ); + water_fb_resize( resize_renderbuffer_std ); } static void render_world( m4x4f projection ) { - SHADER_USE(shader_standard_lit); - m4x3f identity_matrix; m4x3_identity( identity_matrix ); - glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit, "uPv" ), - 1, GL_FALSE, (float *)projection ); - glUniformMatrix4x3fv( SHADER_UNIFORM( shader_standard_lit, "uMdl" ), - 1, GL_FALSE, (float *)identity_matrix ); + shader_unlit_use(); + shader_unlit_uPv( projection ); + shader_unlit_uTexMain( 0 ); + vg_tex2d_bind( &tex_sky, 0 ); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + + mesh_bind( &world.skybox ); + mesh_draw( &world.skybox ); + + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); + + + shader_standard_use(); + shader_standard_uPv( projection ); + shader_standard_uMdl( identity_matrix ); vg_tex2d_bind( &tex_grid, 0 ); - glUniform1i( SHADER_UNIFORM( shader_standard_lit, "uTexMain" ), 0 ); - glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), - 0.4f,0.4f,0.4f,1.0f ); + shader_standard_uTexMain( 0 ); + shader_standard_uColour( (v4f){0.4f,0.4f,0.4f,1.0f} ); scene_bind( &world.geo ); scene_draw( &world.geo ); @@ -1176,12 +1235,7 @@ void vg_render(void) glViewport( 0,0, vg_window_x, vg_window_y ); glDisable( GL_DEPTH_TEST ); - glClearColor( 0.1f, 0.0f, 0.2f, 1.0f ); - glClearColor(111.0f/255.0f, 46.0f/255.0f, 45.0f/255.0f,1.0f); - - glClearColor( powf(0.066f,1.0f/2.2f), - powf(0.050f,1.0f/2.2f), - powf(0.046f,1.0f/2.2f), 1.0f ); + glClearColor( 0.11f, 0.35f, 0.37f, 1.0f ); glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); v3f pos_inv; @@ -1251,9 +1305,10 @@ void vg_render(void) m4x4f world_4x4; m4x3_expand( world_matrix, world_4x4 ); - float fov = freecam? 60.0f: 120.0f; - m4x4_projection( vg_pv, fov, (float)vg_window_x / (float)vg_window_y, - 0.01f, 1000.0f ); + gpipeline.fov = freecam? 60.0f: 120.0f; + m4x4_projection( vg_pv, gpipeline.fov, + (float)vg_window_x / (float)vg_window_y, + 0.1f, 1000.0f ); m4x4_mul( vg_pv, world_4x4, vg_pv ); @@ -1266,48 +1321,18 @@ void vg_render(void) /* * Draw world */ - SHADER_USE(shader_standard_lit); - - m4x3f identity_matrix; - m4x3_identity( identity_matrix ); - - glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit, "uPv" ), - 1, GL_FALSE, (float *)vg_pv ); - glUniformMatrix4x3fv( SHADER_UNIFORM( shader_standard_lit, "uMdl" ), - 1, GL_FALSE, (float *)identity_matrix ); - - vg_tex2d_bind( &tex_grid, 0 ); - glUniform1i( SHADER_UNIFORM( shader_standard_lit, "uTexMain" ), 0 ); - - glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), - 0.4f,0.4f,0.4f,1.0f ); - - scene_bind( &world.geo ); - scene_draw( &world.geo ); - -#if 0 - if( !replay_record ) - { - m4x3f *base = &replay_buffer[(PART_COUNT)*replay_buffer_frame]; - - for( int i=0; iindice_start, sm->indice_count ); } +static void model_unpack_submodel( model *model, glmesh *mesh, submodel *sm ) +{ + mesh_upload( mesh, + model_vertex_base( model ) + sm->vertex_start, sm->vertex_count, + model_indice_base( model ) + sm->indice_start, sm->indice_count ); +} + static void model_unpack( model *model, glmesh *mesh ) { u32 offset = model_get_submodel( model, 0 )->vertex_count; diff --git a/render.h b/render.h new file mode 100644 index 0000000..0abbdae --- /dev/null +++ b/render.h @@ -0,0 +1,37 @@ +#ifndef RENDER_H +#define RENDER_H +#define VG_3D +#include "vg/vg.h" + +static struct pipeline +{ + float fov; +} +gpipeline; + +static void render_water_texture( m4x3f camera ); +static void render_water_surface( m4x4f pv ); +static void render_world( m4x4f pv ); + +/* + * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf + */ +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]; +} + +#endif /* RENDER_H */ diff --git a/scene.h b/scene.h index e00445a..af24b6c 100644 --- a/scene.h +++ b/scene.h @@ -94,242 +94,6 @@ static void scene_init( scene *pscene ) } } -/* https://www.shadertoy.com/view/4sfGzS */ -#define SHADER_VALUE_NOISE_3D \ -"uniform sampler2D uTexNoise;" \ -"" \ -"float noise( vec3 x )" \ -"{" \ - "vec3 i = floor(x);" \ - "vec3 f = fract(x);" \ - "f = f*f*(3.0-2.0*f);" \ - "vec2 uv = (i.xy+vec2(37.0,17.0)*i.z) + f.xy;" \ - "vec2 rg = texture( uTexNoise, (uv+0.5)/256.0).yx;"\ - "return mix( rg.x, rg.y, f.z );" \ -"}" \ -"" \ -"const mat3 m = mat3( 0.00, 0.80, 0.60," \ - "-0.80, 0.36, -0.48," \ - "-0.60, -0.48, 0.64 );" \ -"" \ -"float fractalNoise( vec3 x )" \ -"{" \ - "vec3 q = 8.0*x;" \ - "float f;" \ - "f = 0.5000*noise( q ); q = m*q*2.01;" \ - "f += 0.2500*noise( q ); q = m*q*2.02;" \ - "f += 0.1250*noise( q ); q = m*q*2.03;" \ - "f += 0.0625*noise( q ); q = m*q*2.01;" \ - "return f;" \ -"}" - -SHADER_DEFINE( shader_debug_vcol, - - /*Include*/ VERTEX_STANDARD_ATTRIBUTES - - "uniform mat4 uPv;" - "uniform mat4x3 uMdl;" - "uniform float uTime;" - "uniform float uSwayAmt;" - "" - "out vec4 aColour;" - "out vec2 aUv;" - "out vec3 aNorm;" - "out vec3 aCo;" - "" - "vec3 compute_sway( vec3 pos )" - "{" - "vec4 sines = vec4( sin(uTime + pos.x)*1.0," - "sin(uTime*1.2 + pos.z*2.0)*1.1," - "sin(uTime*2.33)*0.5," - "sin(uTime*0.6 + pos.x*0.3)*1.3 );" - - "vec3 offset = vec3( sines.x+sines.y*sines.w, 0.0, sines.x+sines.z );" - "return pos + offset*a_colour.r*uSwayAmt;" - "}" - "" - "void main()" - "{" - "vec3 swaypos = compute_sway( a_co );" - "gl_Position = uPv * vec4(uMdl * vec4(swaypos,1.0), 1.0 );" - "aColour = a_colour;" - "aUv = a_uv;" - "aNorm = normalize(mat3(uMdl) * a_norm);" - "aCo = a_co;" - "}", - /* Fragment */ - "out vec4 FragColor;" - "" - "uniform int uMode;" - "uniform sampler2D uTexMain;" - "uniform sampler2D uTexGradients;" - "" - /*Include*/ SHADER_VALUE_NOISE_3D - "" - "in vec4 aColour;" - "in vec2 aUv;" - "in vec3 aNorm;" - "in vec3 aCo;" - "" - "void main()" - "{" - "vec4 colour = vec4(1.0,0.0,0.5,1.0);" - "vec4 diffuse = texture( uTexMain, aUv );" - - "if( uMode == 1 )" - "{" - "colour = vec4(aNorm * 0.5 + 0.5, 1.0);" - "}" - "if( uMode == 2 )" - "{" - "colour = aColour;" - "}" - "if( uMode == 3 )" - "{" - "float light = dot(aNorm, vec3(0.2,0.8,0.1));" - "vec3 grid3 = fract(aCo);" - - "colour = vec4(vec3(light)*(1.0-grid3*0.3),1.0);" - "}" - "if( uMode == 4 )" - "{" - "colour = vec4( aUv, 0.0, 1.0 );" - "}" - "if( uMode == 5 )" - "{" - "if( diffuse.a < 0.45 ) discard;" - "colour = diffuse;" - "}" - "if( uMode == 6 )" - "{" - "float r1 = fractalNoise(aCo);" - "colour = vec4( vec3(r1), 1.0 );" - "}" - "if( uMode == 7 )" - "{" - "if( diffuse.a < 0.2 ) discard;" - "float lighting = 1.0 - aColour.g*0.8;" - - "float light1 = max(0.0,dot(-vec3(0.5,-0.8,0.25), aNorm));" - "float light2 = max(0.0,dot(-vec3(-0.8,0.5,-0.25), aNorm));" - "vec3 lt = vec3(0.2,0.2,0.2 ) + " - "vec3(1.0,1.0,0.9)*light1 + " - "vec3(0.1,0.3,0.4 )*light2;" - - - "colour = vec4(vec3(pow(lighting,1.6)*(diffuse.r*0.7+0.5)),1.0);" - "colour = vec4(colour.rgb*lt,1.0);" - - "vec2 gradUV = vec2(lighting*1.9,aColour.b*0.8);" - "vec4 gradient_sample = texture( uTexGradients, gradUV );" - "colour = colour*gradient_sample;" - "}" - "if( uMode == 8 )" - "{" - "if( diffuse.a < 0.45 ) discard;" - "float light = 1.0 - aColour.g;" - "light = pow(light,1.6)*(diffuse.r*0.7+0.5);" - "float r1 = fractalNoise(aCo*0.01);" - - "vec2 gradUV = vec2(light*1.9,r1+aColour.b);" - "vec4 gradient_sample = texture( uTexGradients, gradUV );" - "colour = gradient_sample*light;" - "}" - - "FragColor = colour;" - "}" - , - UNIFORMS({ "uPv", "uMode", "uTexMain", "uTexGradients", "uTexNoise", \ - "uTime", "uSwayAmt", "uMdl" }) -) - -SHADER_DEFINE( shader_standard_lit, - - /*Include*/ VERTEX_STANDARD_ATTRIBUTES - - "uniform mat4 uPv;" - "uniform mat4x3 uMdl;" - "" - "out vec4 aColour;" - "out vec2 aUv;" - "out vec3 aNorm;" - "out vec3 aCo;" - "" - "void main()" - "{" - "gl_Position = uPv * vec4( uMdl * vec4(a_co,1.0), 1.0 );" - "aColour = a_colour;" - "aUv = a_uv;" - "aNorm = mat3(uMdl) * a_norm;" - "aCo = a_co;" - "}", - /* Fragment */ - "out vec4 FragColor;" - "" - "uniform sampler2D uTexMain;" - "uniform vec4 uColour;" - "" - "in vec4 aColour;" - "in vec2 aUv;" - "in vec3 aNorm;" - "in vec3 aCo;" - "" - "void main()" - "{" - "vec3 diffuse = texture( uTexMain, aUv ).rgb;" - - "float light1 = max(0.0,dot(-vec3(0.5,-0.8,0.25), aNorm));" - "float light2 = max(0.0,dot(-vec3(-0.8,0.5,-0.25), aNorm));" - "diffuse += vec3(0.2,0.2,0.2) + " - "vec3(1.0,1.0,0.9)*light1 + " - "vec3(0.1,0.3,0.4)*light2;" - - "FragColor = vec4(diffuse*uColour.rgb, aColour.a*uColour.a);" - "}" - , - UNIFORMS({ "uColour","uTexMain","uPv","uMdl" }) -) - -SHADER_DEFINE( shader_unlit, - - /*Include*/ VERTEX_STANDARD_ATTRIBUTES - - "uniform mat4 uPv;" - "uniform mat4x3 uMdl;" - "" - "out vec4 aColour;" - "out vec2 aUv;" - "out vec3 aNorm;" - "out vec3 aCo;" - "" - "void main()" - "{" - "gl_Position = uPv * vec4(uMdl * vec4(a_co,1.0), 1.0);" - "aColour = a_colour;" - "aUv = a_uv;" - "aNorm = mat3(uMdl) * a_norm;" - "aCo = a_co;" - "}", - /* Fragment */ - "out vec4 FragColor;" - "" - "uniform sampler2D uTexMain;" - "uniform vec4 uColour;" - "" - "in vec4 aColour;" - "in vec2 aUv;" - "in vec3 aNorm;" - "in vec3 aCo;" - "" - "void main()" - "{" - "vec3 diffuse = texture( uTexMain, aUv ).rgb;" - "FragColor = vec4(pow(diffuse,vec3(1.0)),1.0);" - "}" - , - UNIFORMS({ "uTexMain", "uPv", "uMdl" }) -) - static void *buffer_reserve( void *buffer, u32 count, u32 *cap, u32 amount, size_t emsize ) { @@ -824,9 +588,6 @@ static void scene_debugsdf( scene *pscene ) static void scene_register(void) { - SHADER_INIT( shader_debug_vcol ); - SHADER_INIT( shader_standard_lit ); - SHADER_INIT( shader_unlit ); } diff --git a/shaders/blit.fs b/shaders/blit.fs new file mode 100644 index 0000000..b98d5e8 --- /dev/null +++ b/shaders/blit.fs @@ -0,0 +1,9 @@ +out vec4 FragColor; +uniform sampler2D uTexMain; + +in vec2 aUv; + +void main() +{ + FragColor = texture( uTexMain, aUv ); +} diff --git a/shaders/blit.h b/shaders/blit.h new file mode 100644 index 0000000..f05194e --- /dev/null +++ b/shaders/blit.h @@ -0,0 +1,48 @@ +#ifndef SHADER_blit_H +#define SHADER_blit_H +static void shader_blit_link(void); +static void shader_blit_register(void); +static struct vg_shader _shader_blit = { + .name = "blit", + .link = shader_blit_link, + .vs = +{ +.orig_file = "../shaders/blit.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 = +{ +.orig_file = "../shaders/blit.fs", +.static_src = +"out vec4 FragColor;\n" +"uniform sampler2D uTexMain;\n" +"\n" +"in vec2 aUv;\n" +"\n" +"void main()\n" +"{\n" +" FragColor = texture( uTexMain, aUv );\n" +"}\n" +""}, +}; + +static GLuint _uniform_blit_uTexMain; +static void shader_blit_uTexMain(int i){ + glUniform1i( _uniform_blit_uTexMain, i ); +} +static void shader_blit_register(void){ + vg_shader_register( &_shader_blit ); +} +static void shader_blit_use(void){ glUseProgram(_shader_blit.id); } +static void shader_blit_link(void){ + _uniform_blit_uTexMain = glGetUniformLocation( _shader_blit.id, "uTexMain" ); +} +#endif /* SHADER_blit_H */ diff --git a/shaders/blit.vs b/shaders/blit.vs new file mode 100644 index 0000000..2593725 --- /dev/null +++ b/shaders/blit.vs @@ -0,0 +1,8 @@ +layout (location=0) in vec2 a_co; +out vec2 aUv; + +void main() +{ + gl_Position = vec4(a_co*2.0-1.0,0.0,1.0); + aUv = a_co; +} diff --git a/shaders/character.fs b/shaders/character.fs new file mode 100644 index 0000000..d3c2bea --- /dev/null +++ b/shaders/character.fs @@ -0,0 +1,16 @@ +out vec4 FragColor; + +uniform sampler2D uTexMain; +uniform vec4 uColour; + +in vec4 aColour; +in vec2 aUv; +in vec3 aNorm; +in vec3 aCo; +in float aOpacity; + +void main() +{ + vec3 diffuse = texture( uTexMain, aUv ).rgb; + FragColor = vec4(pow(diffuse,vec3(1.0)),aOpacity); +} diff --git a/shaders/character.h b/shaders/character.h new file mode 100644 index 0000000..6c3ce7a --- /dev/null +++ b/shaders/character.h @@ -0,0 +1,95 @@ +#ifndef SHADER_character_H +#define SHADER_character_H +static void shader_character_link(void); +static void shader_character_register(void); +static struct vg_shader _shader_character = { + .name = "character", + .link = shader_character_link, + .vs = +{ +.orig_file = "../shaders/character.vs", +.static_src = +"layout (location=0) in vec3 a_co;\n" +"layout (location=1) in vec3 a_norm;\n" +"layout (location=2) in vec4 a_colour;\n" +"layout (location=3) in vec2 a_uv;\n" +"\n" +"#line 2 0 \n" +"\n" +"uniform mat4 uPv;\n" +"uniform mat4x3 uMdl;\n" +"uniform float uOpacity;\n" +"\n" +"out vec4 aColour;\n" +"out vec2 aUv;\n" +"out vec3 aNorm;\n" +"out vec3 aCo;\n" +"out float aOpacity;\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" +"\n" +" aColour = a_colour;\n" +" aUv = a_uv;\n" +" aNorm = mat3(uMdl) * a_norm;\n" +" aCo = a_co;\n" +" aOpacity = 1.0-(gl_Position.y+0.5)*uOpacity;\n" +"}\n" +""}, + .fs = +{ +.orig_file = "../shaders/character.fs", +.static_src = +"out vec4 FragColor;\n" +"\n" +"uniform sampler2D uTexMain;\n" +"uniform vec4 uColour;\n" +"\n" +"in vec4 aColour;\n" +"in vec2 aUv;\n" +"in vec3 aNorm;\n" +"in vec3 aCo;\n" +"in float aOpacity;\n" +"\n" +"void main()\n" +"{\n" +" vec3 diffuse = texture( uTexMain, aUv ).rgb;\n" +" FragColor = vec4(pow(diffuse,vec3(1.0)),aOpacity);\n" +"}\n" +""}, +}; + +static GLuint _uniform_character_uPv; +static GLuint _uniform_character_uMdl; +static GLuint _uniform_character_uOpacity; +static GLuint _uniform_character_uTexMain; +static GLuint _uniform_character_uColour; +static void shader_character_uPv(m4x4f m){ + glUniformMatrix4fv( _uniform_character_uPv, 1, GL_FALSE, (float *)m ); +} +static void shader_character_uMdl(m4x3f m){ + glUniformMatrix4x3fv( _uniform_character_uMdl, 1, GL_FALSE, (float *)m ); +} +static void shader_character_uOpacity(float f){ + glUniform1f( _uniform_character_uOpacity, f ); +} +static void shader_character_uTexMain(int i){ + glUniform1i( _uniform_character_uTexMain, i ); +} +static void shader_character_uColour(v4f v){ + glUniform4fv( _uniform_character_uColour, 1, v ); +} +static void shader_character_register(void){ + vg_shader_register( &_shader_character ); +} +static void shader_character_use(void){ glUseProgram(_shader_character.id); } +static void shader_character_link(void){ + _uniform_character_uPv = glGetUniformLocation( _shader_character.id, "uPv" ); + _uniform_character_uMdl = glGetUniformLocation( _shader_character.id, "uMdl" ); + _uniform_character_uOpacity = glGetUniformLocation( _shader_character.id, "uOpacity" ); + _uniform_character_uTexMain = glGetUniformLocation( _shader_character.id, "uTexMain" ); + _uniform_character_uColour = glGetUniformLocation( _shader_character.id, "uColour" ); +} +#endif /* SHADER_character_H */ diff --git a/shaders/character.vs b/shaders/character.vs new file mode 100644 index 0000000..63b755b --- /dev/null +++ b/shaders/character.vs @@ -0,0 +1,23 @@ +#include "vertex_standard.glsl" + +uniform mat4 uPv; +uniform mat4x3 uMdl; +uniform float uOpacity; + +out vec4 aColour; +out vec2 aUv; +out vec3 aNorm; +out vec3 aCo; +out float aOpacity; + +void main() +{ + vec3 world_pos = uMdl * vec4(a_co,1.0); + gl_Position = uPv * vec4(world_pos,1.0); + + aColour = a_colour; + aUv = a_uv; + aNorm = mat3(uMdl) * a_norm; + aCo = a_co; + aOpacity = 1.0-(gl_Position.y+0.5)*uOpacity; +} diff --git a/shaders/gate.fs b/shaders/gate.fs new file mode 100644 index 0000000..ba48f1e --- /dev/null +++ b/shaders/gate.fs @@ -0,0 +1,27 @@ +out vec4 FragColor; + +uniform sampler2D uTexMain; +uniform sampler2D uTexWater; +uniform vec2 uInvRes; +uniform float uTime; +uniform vec3 uCam; + +in vec3 aNorm; +in vec2 aUv; +in vec3 aCo; + +void main() +{ + vec2 ssuv = gl_FragCoord.xy*uInvRes; + vec4 mapwater = texture( uTexWater, vec2(aUv.x,aUv.y-uTime)); + + float undistort = smoothstep(0.1,0.6,distance( uCam, aCo )*0.1); + vec2 trimedge = smoothstep(0.0,0.2,1.0-abs(ssuv-0.5)*2.0); + undistort *= trimedge.x * trimedge.y; + + vec2 warpamt = (mapwater.rg-0.5)*0.05*aUv.y*undistort; + vec4 mapbackbuffer = texture( uTexMain, ssuv + warpamt ); + + float opacity = 1.0-smoothstep(0.4,1.0,aUv.y); + FragColor = vec4( mapbackbuffer.rgb, opacity ); +} diff --git a/shaders/gate.h b/shaders/gate.h new file mode 100644 index 0000000..58e80bc --- /dev/null +++ b/shaders/gate.h @@ -0,0 +1,110 @@ +#ifndef SHADER_gate_H +#define SHADER_gate_H +static void shader_gate_link(void); +static void shader_gate_register(void); +static struct vg_shader _shader_gate = { + .name = "gate", + .link = shader_gate_link, + .vs = +{ +.orig_file = "../shaders/gate.vs", +.static_src = +"layout (location=0) in vec3 a_co;\n" +"layout (location=1) in vec3 a_norm;\n" +"layout (location=2) in vec4 a_colour;\n" +"layout (location=3) in vec2 a_uv;\n" +"\n" +"#line 2 0 \n" +"uniform mat4 uPv;\n" +"uniform mat4x3 uMdl;\n" +"\n" +"out vec3 aNorm;\n" +"out vec2 aUv;\n" +"out vec3 aCo;\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" +"\n" +" aNorm = a_norm;\n" +" aCo = world_pos;\n" +" aUv = a_uv;\n" +"}\n" +""}, + .fs = +{ +.orig_file = "../shaders/gate.fs", +.static_src = +"out vec4 FragColor;\n" +"\n" +"uniform sampler2D uTexMain;\n" +"uniform sampler2D uTexWater;\n" +"uniform vec2 uInvRes;\n" +"uniform float uTime;\n" +"uniform vec3 uCam;\n" +"\n" +"in vec3 aNorm;\n" +"in vec2 aUv;\n" +"in vec3 aCo;\n" +"\n" +"void main()\n" +"{\n" +" vec2 ssuv = gl_FragCoord.xy*uInvRes;\n" +" vec4 mapwater = texture( uTexWater, vec2(aUv.x,aUv.y-uTime));\n" +"\n" +" float undistort = smoothstep(0.1,0.6,distance( uCam, aCo )*0.1);\n" +" vec2 trimedge = smoothstep(0.0,0.2,1.0-abs(ssuv-0.5)*2.0);\n" +" undistort *= trimedge.x * trimedge.y;\n" +"\n" +" vec2 warpamt = (mapwater.rg-0.5)*0.05*aUv.y*undistort;\n" +" vec4 mapbackbuffer = texture( uTexMain, ssuv + warpamt );\n" +"\n" +" float opacity = 1.0-smoothstep(0.4,1.0,aUv.y);\n" +" FragColor = vec4( mapbackbuffer.rgb, opacity );\n" +"}\n" +""}, +}; + +static GLuint _uniform_gate_uPv; +static GLuint _uniform_gate_uMdl; +static GLuint _uniform_gate_uTexMain; +static GLuint _uniform_gate_uTexWater; +static GLuint _uniform_gate_uInvRes; +static GLuint _uniform_gate_uTime; +static GLuint _uniform_gate_uCam; +static void shader_gate_uPv(m4x4f m){ + glUniformMatrix4fv( _uniform_gate_uPv, 1, GL_FALSE, (float *)m ); +} +static void shader_gate_uMdl(m4x3f m){ + glUniformMatrix4x3fv( _uniform_gate_uMdl, 1, GL_FALSE, (float *)m ); +} +static void shader_gate_uTexMain(int i){ + glUniform1i( _uniform_gate_uTexMain, i ); +} +static void shader_gate_uTexWater(int i){ + glUniform1i( _uniform_gate_uTexWater, i ); +} +static void shader_gate_uInvRes(v2f v){ + glUniform2fv( _uniform_gate_uInvRes, 1, v ); +} +static void shader_gate_uTime(float f){ + glUniform1f( _uniform_gate_uTime, f ); +} +static void shader_gate_uCam(v3f v){ + glUniform3fv( _uniform_gate_uCam, 1, v ); +} +static void shader_gate_register(void){ + vg_shader_register( &_shader_gate ); +} +static void shader_gate_use(void){ glUseProgram(_shader_gate.id); } +static void shader_gate_link(void){ + _uniform_gate_uPv = glGetUniformLocation( _shader_gate.id, "uPv" ); + _uniform_gate_uMdl = glGetUniformLocation( _shader_gate.id, "uMdl" ); + _uniform_gate_uTexMain = glGetUniformLocation( _shader_gate.id, "uTexMain" ); + _uniform_gate_uTexWater = glGetUniformLocation( _shader_gate.id, "uTexWater" ); + _uniform_gate_uInvRes = glGetUniformLocation( _shader_gate.id, "uInvRes" ); + _uniform_gate_uTime = glGetUniformLocation( _shader_gate.id, "uTime" ); + _uniform_gate_uCam = glGetUniformLocation( _shader_gate.id, "uCam" ); +} +#endif /* SHADER_gate_H */ diff --git a/shaders/gate.vs b/shaders/gate.vs new file mode 100644 index 0000000..9d5853c --- /dev/null +++ b/shaders/gate.vs @@ -0,0 +1,17 @@ +#include "vertex_standard.glsl" +uniform mat4 uPv; +uniform mat4x3 uMdl; + +out vec3 aNorm; +out vec2 aUv; +out vec3 aCo; + +void main() +{ + vec3 world_pos = uMdl * vec4( a_co, 1.0 ); + gl_Position = uPv * vec4(world_pos,1.0); + + aNorm = a_norm; + aCo = world_pos; + aUv = a_uv; +} diff --git a/shaders/standard.fs b/shaders/standard.fs new file mode 100644 index 0000000..e3f05c8 --- /dev/null +++ b/shaders/standard.fs @@ -0,0 +1,20 @@ +out vec4 FragColor; + +uniform sampler2D uTexMain; +uniform vec4 uColour; + +in vec4 aColour; +in vec2 aUv; +in vec3 aNorm; +in vec3 aCo; + +void main() +{ + vec3 diffuse = texture( uTexMain, aUv ).rgb; + float light1 = max(0.0,dot(-vec3(0.5,-0.8,0.25), aNorm)); + float light2 = max(0.0,dot(-vec3(-0.8,0.5,-0.25), aNorm)); + diffuse += vec3(0.2,0.2,0.2) + + vec3(1.0,1.0,0.9)*light1 + + vec3(0.1,0.3,0.4)*light2; + FragColor = vec4(diffuse*uColour.rgb, aColour.a*uColour.a); +} diff --git a/shaders/standard.h b/shaders/standard.h new file mode 100644 index 0000000..59aa1d9 --- /dev/null +++ b/shaders/standard.h @@ -0,0 +1,89 @@ +#ifndef SHADER_standard_H +#define SHADER_standard_H +static void shader_standard_link(void); +static void shader_standard_register(void); +static struct vg_shader _shader_standard = { + .name = "standard", + .link = shader_standard_link, + .vs = +{ +.orig_file = "../shaders/standard.vs", +.static_src = +"layout (location=0) in vec3 a_co;\n" +"layout (location=1) in vec3 a_norm;\n" +"layout (location=2) in vec4 a_colour;\n" +"layout (location=3) in vec2 a_uv;\n" +"\n" +"#line 2 0 \n" +"\n" +"uniform mat4 uPv;\n" +"uniform mat4x3 uMdl;\n" +"\n" +"out vec4 aColour;\n" +"out vec2 aUv;\n" +"out vec3 aNorm;\n" +"out vec3 aCo;\n" +"\n" +"void main()\n" +"{\n" +" gl_Position = uPv * vec4( uMdl * vec4(a_co,1.0), 1.0 );\n" +" aColour = a_colour;\n" +" aUv = a_uv;\n" +" aNorm = mat3(uMdl) * a_norm;\n" +" aCo = a_co;\n" +"}\n" +""}, + .fs = +{ +.orig_file = "../shaders/standard.fs", +.static_src = +"out vec4 FragColor;\n" +"\n" +"uniform sampler2D uTexMain;\n" +"uniform vec4 uColour;\n" +"\n" +"in vec4 aColour;\n" +"in vec2 aUv;\n" +"in vec3 aNorm;\n" +"in vec3 aCo;\n" +"\n" +"void main()\n" +"{\n" +" vec3 diffuse = texture( uTexMain, aUv ).rgb;\n" +" float light1 = max(0.0,dot(-vec3(0.5,-0.8,0.25), aNorm));\n" +" float light2 = max(0.0,dot(-vec3(-0.8,0.5,-0.25), aNorm));\n" +" diffuse += vec3(0.2,0.2,0.2) +\n" +" vec3(1.0,1.0,0.9)*light1 + \n" +" vec3(0.1,0.3,0.4)*light2;\n" +" FragColor = vec4(diffuse*uColour.rgb, aColour.a*uColour.a);\n" +"}\n" +""}, +}; + +static GLuint _uniform_standard_uPv; +static GLuint _uniform_standard_uMdl; +static GLuint _uniform_standard_uTexMain; +static GLuint _uniform_standard_uColour; +static void shader_standard_uPv(m4x4f m){ + glUniformMatrix4fv( _uniform_standard_uPv, 1, GL_FALSE, (float *)m ); +} +static void shader_standard_uMdl(m4x3f m){ + glUniformMatrix4x3fv( _uniform_standard_uMdl, 1, GL_FALSE, (float *)m ); +} +static void shader_standard_uTexMain(int i){ + glUniform1i( _uniform_standard_uTexMain, i ); +} +static void shader_standard_uColour(v4f v){ + glUniform4fv( _uniform_standard_uColour, 1, v ); +} +static void shader_standard_register(void){ + vg_shader_register( &_shader_standard ); +} +static void shader_standard_use(void){ glUseProgram(_shader_standard.id); } +static void shader_standard_link(void){ + _uniform_standard_uPv = glGetUniformLocation( _shader_standard.id, "uPv" ); + _uniform_standard_uMdl = glGetUniformLocation( _shader_standard.id, "uMdl" ); + _uniform_standard_uTexMain = glGetUniformLocation( _shader_standard.id, "uTexMain" ); + _uniform_standard_uColour = glGetUniformLocation( _shader_standard.id, "uColour" ); +} +#endif /* SHADER_standard_H */ diff --git a/shaders/standard.vs b/shaders/standard.vs new file mode 100644 index 0000000..db7f980 --- /dev/null +++ b/shaders/standard.vs @@ -0,0 +1,18 @@ +#include "vertex_standard.glsl" + +uniform mat4 uPv; +uniform mat4x3 uMdl; + +out vec4 aColour; +out vec2 aUv; +out vec3 aNorm; +out vec3 aCo; + +void main() +{ + gl_Position = uPv * vec4( uMdl * vec4(a_co,1.0), 1.0 ); + aColour = a_colour; + aUv = a_uv; + aNorm = mat3(uMdl) * a_norm; + aCo = a_co; +} diff --git a/shaders/terrain.fs b/shaders/terrain.fs new file mode 100644 index 0000000..04751e9 --- /dev/null +++ b/shaders/terrain.fs @@ -0,0 +1,6 @@ +#include "common.glsl" + +void main() +{ + +} diff --git a/shaders/terrain.h b/shaders/terrain.h new file mode 100644 index 0000000..e10d371 --- /dev/null +++ b/shaders/terrain.h @@ -0,0 +1,45 @@ +#ifndef SHADER_terrain_H +#define SHADER_terrain_H +static void shader_terrain_link(void); +static void shader_terrain_register(void); +static struct vg_shader _shader_terrain = { + .name = "terrain", + .link = shader_terrain_link, + .vs = +{ +.orig_file = "../shaders/terrain.vs", +.static_src = +"uniform mat4x3 uMdl;\n" +"\n" +"void main()\n" +"{\n" +"\n" +"}\n" +""}, + .fs = +{ +.orig_file = "../shaders/terrain.fs", +.static_src = +"// Nothing\n" +"\n" +"#line 2 0 \n" +"\n" +"void main()\n" +"{\n" +"\n" +"}\n" +""}, +}; + +static GLuint _uniform_terrain_uMdl; +static void shader_terrain_uMdl(m4x3f m){ + glUniformMatrix4x3fv( _uniform_terrain_uMdl, 1, GL_FALSE, (float *)m ); +} +static void shader_terrain_register(void){ + vg_shader_register( &_shader_terrain ); +} +static void shader_terrain_use(void){ glUseProgram(_shader_terrain.id); } +static void shader_terrain_link(void){ + _uniform_terrain_uMdl = glGetUniformLocation( _shader_terrain.id, "uMdl" ); +} +#endif /* SHADER_terrain_H */ diff --git a/shaders/terrain.vs b/shaders/terrain.vs new file mode 100644 index 0000000..5bb262b --- /dev/null +++ b/shaders/terrain.vs @@ -0,0 +1,6 @@ +uniform mat4x3 uMdl; + +void main() +{ + +} diff --git a/shaders/unlit.fs b/shaders/unlit.fs new file mode 100644 index 0000000..ec4d7ae --- /dev/null +++ b/shaders/unlit.fs @@ -0,0 +1,15 @@ +out vec4 FragColor; + +uniform sampler2D uTexMain; +uniform vec4 uColour; + +in vec4 aColour; +in vec2 aUv; +in vec3 aNorm; +in vec3 aCo; + +void main() +{ + vec3 diffuse = texture( uTexMain, aUv ).rgb; + FragColor = vec4(pow(diffuse,vec3(1.0)),1.0); +} diff --git a/shaders/unlit.h b/shaders/unlit.h new file mode 100644 index 0000000..afba67c --- /dev/null +++ b/shaders/unlit.h @@ -0,0 +1,84 @@ +#ifndef SHADER_unlit_H +#define SHADER_unlit_H +static void shader_unlit_link(void); +static void shader_unlit_register(void); +static struct vg_shader _shader_unlit = { + .name = "unlit", + .link = shader_unlit_link, + .vs = +{ +.orig_file = "../shaders/standard.vs", +.static_src = +"layout (location=0) in vec3 a_co;\n" +"layout (location=1) in vec3 a_norm;\n" +"layout (location=2) in vec4 a_colour;\n" +"layout (location=3) in vec2 a_uv;\n" +"\n" +"#line 2 0 \n" +"\n" +"uniform mat4 uPv;\n" +"uniform mat4x3 uMdl;\n" +"\n" +"out vec4 aColour;\n" +"out vec2 aUv;\n" +"out vec3 aNorm;\n" +"out vec3 aCo;\n" +"\n" +"void main()\n" +"{\n" +" gl_Position = uPv * vec4( uMdl * vec4(a_co,1.0), 1.0 );\n" +" aColour = a_colour;\n" +" aUv = a_uv;\n" +" aNorm = mat3(uMdl) * a_norm;\n" +" aCo = a_co;\n" +"}\n" +""}, + .fs = +{ +.orig_file = "../shaders/unlit.fs", +.static_src = +"out vec4 FragColor;\n" +"\n" +"uniform sampler2D uTexMain;\n" +"uniform vec4 uColour;\n" +"\n" +"in vec4 aColour;\n" +"in vec2 aUv;\n" +"in vec3 aNorm;\n" +"in vec3 aCo;\n" +"\n" +"void main()\n" +"{\n" +" vec3 diffuse = texture( uTexMain, aUv ).rgb;\n" +" FragColor = vec4(pow(diffuse,vec3(1.0)),1.0);\n" +"}\n" +""}, +}; + +static GLuint _uniform_unlit_uPv; +static GLuint _uniform_unlit_uMdl; +static GLuint _uniform_unlit_uTexMain; +static GLuint _uniform_unlit_uColour; +static void shader_unlit_uPv(m4x4f m){ + glUniformMatrix4fv( _uniform_unlit_uPv, 1, GL_FALSE, (float *)m ); +} +static void shader_unlit_uMdl(m4x3f m){ + glUniformMatrix4x3fv( _uniform_unlit_uMdl, 1, GL_FALSE, (float *)m ); +} +static void shader_unlit_uTexMain(int i){ + glUniform1i( _uniform_unlit_uTexMain, i ); +} +static void shader_unlit_uColour(v4f v){ + glUniform4fv( _uniform_unlit_uColour, 1, v ); +} +static void shader_unlit_register(void){ + vg_shader_register( &_shader_unlit ); +} +static void shader_unlit_use(void){ glUseProgram(_shader_unlit.id); } +static void shader_unlit_link(void){ + _uniform_unlit_uPv = glGetUniformLocation( _shader_unlit.id, "uPv" ); + _uniform_unlit_uMdl = glGetUniformLocation( _shader_unlit.id, "uMdl" ); + _uniform_unlit_uTexMain = glGetUniformLocation( _shader_unlit.id, "uTexMain" ); + _uniform_unlit_uColour = glGetUniformLocation( _shader_unlit.id, "uColour" ); +} +#endif /* SHADER_unlit_H */ diff --git a/shaders/water.fs b/shaders/water.fs new file mode 100644 index 0000000..a8220a4 --- /dev/null +++ b/shaders/water.fs @@ -0,0 +1,20 @@ +out vec4 FragColor; + +uniform sampler2D uTexMain; +uniform sampler2D uTexDudv; +uniform vec2 uInvRes; +uniform float uTime; + +in vec2 aUv; + +void main() +{ + vec2 ssuv = gl_FragCoord.xy*uInvRes; + vec4 dudva = texture( uTexDudv, aUv + vec2(uTime*0.04f,uTime*0.03f) ); + vec4 dudvb = texture( uTexDudv, aUv - vec2(uTime*0.1,uTime*0.054) ); + + vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 2.0; + + vec4 reflected = texture( uTexMain, ssuv+distortamt ); + FragColor = vec4(reflected.rgb*0.9,reflected.a); +} diff --git a/shaders/water.h b/shaders/water.h new file mode 100644 index 0000000..749067e --- /dev/null +++ b/shaders/water.h @@ -0,0 +1,94 @@ +#ifndef SHADER_water_H +#define SHADER_water_H +static void shader_water_link(void); +static void shader_water_register(void); +static struct vg_shader _shader_water = { + .name = "water", + .link = shader_water_link, + .vs = +{ +.orig_file = "../shaders/water.vs", +.static_src = +"layout (location=0) in vec3 a_co;\n" +"layout (location=1) in vec3 a_norm;\n" +"layout (location=2) in vec4 a_colour;\n" +"layout (location=3) in vec2 a_uv;\n" +"\n" +"#line 2 0 \n" +"\n" +"uniform mat4 uPv;\n" +"uniform mat4x3 uMdl;\n" +"\n" +"out vec2 aUv;\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" +" aUv = vec2(world_pos[0],world_pos[2])*0.15;\n" +"}\n" +""}, + .fs = +{ +.orig_file = "../shaders/water.fs", +.static_src = +"out vec4 FragColor;\n" +"\n" +"uniform sampler2D uTexMain;\n" +"uniform sampler2D uTexDudv;\n" +"uniform vec2 uInvRes;\n" +"uniform float uTime;\n" +"\n" +"in vec2 aUv;\n" +"\n" +"void main()\n" +"{\n" +" vec2 ssuv = gl_FragCoord.xy*uInvRes;\n" +" vec4 dudva = texture( uTexDudv, aUv + vec2(uTime*0.04f,uTime*0.03f) );\n" +" vec4 dudvb = texture( uTexDudv, aUv - vec2(uTime*0.1,uTime*0.054) );\n" +"\n" +" vec2 distortamt = (dudva.rg-0.5) * (dudvb.ba-0.5) * 2.0;\n" +"\n" +" vec4 reflected = texture( uTexMain, ssuv+distortamt );\n" +" FragColor = vec4(reflected.rgb*0.1,reflected.a);\n" +"}\n" +""}, +}; + +static GLuint _uniform_water_uPv; +static GLuint _uniform_water_uMdl; +static GLuint _uniform_water_uTexMain; +static GLuint _uniform_water_uTexDudv; +static GLuint _uniform_water_uInvRes; +static GLuint _uniform_water_uTime; +static void shader_water_uPv(m4x4f m){ + glUniformMatrix4fv( _uniform_water_uPv, 1, GL_FALSE, (float *)m ); +} +static void shader_water_uMdl(m4x3f m){ + glUniformMatrix4x3fv( _uniform_water_uMdl, 1, GL_FALSE, (float *)m ); +} +static void shader_water_uTexMain(int i){ + glUniform1i( _uniform_water_uTexMain, i ); +} +static void shader_water_uTexDudv(int i){ + glUniform1i( _uniform_water_uTexDudv, 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_register(void){ + vg_shader_register( &_shader_water ); +} +static void shader_water_use(void){ glUseProgram(_shader_water.id); } +static void shader_water_link(void){ + _uniform_water_uPv = glGetUniformLocation( _shader_water.id, "uPv" ); + _uniform_water_uMdl = glGetUniformLocation( _shader_water.id, "uMdl" ); + _uniform_water_uTexMain = glGetUniformLocation( _shader_water.id, "uTexMain" ); + _uniform_water_uTexDudv = glGetUniformLocation( _shader_water.id, "uTexDudv" ); + _uniform_water_uInvRes = glGetUniformLocation( _shader_water.id, "uInvRes" ); + _uniform_water_uTime = glGetUniformLocation( _shader_water.id, "uTime" ); +} +#endif /* SHADER_water_H */ diff --git a/shaders/water.vs b/shaders/water.vs new file mode 100644 index 0000000..dd8b661 --- /dev/null +++ b/shaders/water.vs @@ -0,0 +1,13 @@ +#include "vertex_standard.glsl" + +uniform mat4 uPv; +uniform mat4x3 uMdl; + +out vec2 aUv; + +void main() +{ + vec3 world_pos = uMdl * vec4( a_co, 1.0 ); + gl_Position = uPv * vec4(world_pos,1.0); + aUv = vec2(world_pos[0],world_pos[2])*0.15; +} diff --git a/terrain.h b/terrain.h index e9cb162..22b2723 100644 --- a/terrain.h +++ b/terrain.h @@ -1,5 +1,21 @@ +#ifndef TERRAIN_H +#define TERRAIN_H + +#define VG_3D #include "vg/vg.h" -#include "scene.h" +#include "model.h" +#include "render.h" + +#include "shaders/terrain.h" +static void terrain_register(void) +{ + shader_terrain_register(); +} +void test(void) +{ + +} +#endif diff --git a/textures/norway_foliage.png b/textures/norway_foliage.png index 707558a..6ca93f8 100644 Binary files a/textures/norway_foliage.png and b/textures/norway_foliage.png differ diff --git a/textures/sky.png b/textures/sky.png index fb3fb5b..f9cdae4 100644 Binary files a/textures/sky.png and b/textures/sky.png differ diff --git a/textures/water.png b/textures/water.png new file mode 100644 index 0000000..f0045e4 Binary files /dev/null and b/textures/water.png differ diff --git a/textures/water_surf.png b/textures/water_surf.png new file mode 100644 index 0000000..90417f7 Binary files /dev/null and b/textures/water_surf.png differ diff --git a/vg.conf b/vg.conf index 896d68a..5453b23 100644 --- a/vg.conf +++ b/vg.conf @@ -1,2 +1,10 @@ vg_src="main.c" vg_target="game" + +shader blit blit.vs blit.fs +shader terrain terrain.vs terrain.fs +shader standard standard.vs standard.fs +shader unlit standard.vs unlit.fs +shader character character.vs character.fs +shader gate gate.vs gate.fs +shader water water.vs water.fs diff --git a/water.h b/water.h new file mode 100644 index 0000000..94c7b34 --- /dev/null +++ b/water.h @@ -0,0 +1,116 @@ +#ifndef WATER_H +#define WATER_H + +#define VG_3D +#include "vg/vg.h" + +#include "model.h" +#include "render.h" +#include "shaders/water.h" + +vg_tex2d tex_water_surf = { .path = "textures/water_surf.qoi" }; + +static struct +{ + GLuint fb, rgb, rb; + glmesh mdl; + + float height; +} +wrender; + +static void water_register(void) +{ + shader_water_register(); +} + +static void water_init( void (*newfb)(GLuint*,GLuint*,GLuint*)) +{ + newfb( &wrender.fb, &wrender.rgb, &wrender.rb ); +} + +static void water_set_surface( glmesh *surf, float height ) +{ + wrender.mdl = *surf; + wrender.height = height; +} + +static void water_fb_resize( void (*resize)(GLuint*,GLuint*,GLuint*) ) +{ + resize( &wrender.fb, &wrender.rgb, &wrender.fb ); +} + +static void render_water_texture( m4x3f camera ) +{ + /* Draw reflection buffa */ + glBindFramebuffer( GL_FRAMEBUFFER, wrender.fb ); + glClearColor( 0.11f, 0.35f, 0.37f, 1.0f ); + 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] - wrender.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 ); + + m4x3_invert_affine( new_cam, inverse ); + m4x3_expand( inverse, view ); + + v4f clippa = { 0.0f, 1.0f, 0.0f, wrender.height-0.1f }; + m4x3_mulp( 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 ); + + glCullFace( GL_FRONT ); + render_world( projection ); + glCullFace( GL_BACK ); +} + +static void render_water_surface( m4x4f pv ) +{ + /* Draw surface */ + shader_water_use(); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, wrender.rgb ); + shader_water_uTexMain( 0 ); + + vg_tex2d_bind( &tex_water_surf, 1 ); + shader_water_uTexDudv( 1 ); + shader_water_uInvRes( (v2f){ + 1.0f / (float)vg_window_x, + 1.0f / (float)vg_window_y }); + + shader_water_uTime( vg_time ); + shader_water_uPv( pv ); + + m4x3f full; + m4x3_identity( full ); + full[3][1] = wrender.height; + + shader_water_uMdl( full ); + + mesh_bind( &wrender.mdl ); + mesh_draw( &wrender.mdl ); +} + +#endif /* WATER_H */