From: hgn Date: Fri, 8 Jul 2022 18:46:45 +0000 (+0100) Subject: reworked lighting uniforms X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=ecc4dfbfb3adf91d2dfc03ba0ec9a821fcc2390c;hp=3bb0287d544a4cb75de9afe2927ac8e946f3a18e;p=carveJwlIkooP6JGAAIwe30JlM.git reworked lighting uniforms --- diff --git a/.gitignore b/.gitignore index c400164..31dfd3c 100755 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ restricted/ !*.fs !*.vs !*.gls +!*.glsl # Python source files !*.py diff --git a/blender_export.py b/blender_export.py index a13e84e..16b9764 100644 --- a/blender_export.py +++ b/blender_export.py @@ -212,16 +212,22 @@ def write_model(name): for j in range(3): vert = data.vertices[tri.vertices[j]] + li = tri.loops[j] co = vert.co - norm = data.loops[tri.loops[j]].normal + norm = data.loops[li].normal uv = (0,0) + colour = (1,1,1,1) if data.uv_layers: - uv = data.uv_layers.active.data[tri.loops[j]].uv + uv = data.uv_layers.active.data[li].uv + if data.vertex_colors: + colour = data.vertex_colors.active.data[li].color key = (round(co[0],4),round(co[1],4),round(co[2],4),\ round(norm[0],4),round(norm[1],4),round(norm[2],4),\ - round(uv[0],4),round(uv[1],4)) + round(uv[0],4),round(uv[1],4),\ + round(colour[0],4),round(colour[1],4),\ + round(colour[2],4),round(colour[3],4)) if key in boffa: indice_buffer += [boffa[key]] @@ -244,10 +250,10 @@ def write_model(name): v.norm[2] = -norm[1] v.uv[0] = uv[0] v.uv[1] = uv[1] - v.colour[0] = 1.0 - v.colour[1] = 1.0 - v.colour[2] = 1.0 - v.colour[3] = 1.0 + v.colour[0] = colour[0] + v.colour[1] = colour[1] + v.colour[2] = colour[2] + v.colour[3] = colour[3] vertex_buffer += [v] for i in range(3): diff --git a/bvh.h b/bvh.h index a6a7468..27e23b5 100644 --- a/bvh.h +++ b/bvh.h @@ -251,10 +251,7 @@ static int bh_select( bh_tree *bh, boxf box, u32 *buffer, int len ) if( inode->count ) { if( count + inode->count >= len ) - { - vg_error( "Maximum buffer reached!\n" ); return count; - } for( u32 i=0; icount; i++ ) buffer[ count ++ ] = inode->start+i; diff --git a/lighting.h b/lighting.h new file mode 100644 index 0000000..8f9bdb3 --- /dev/null +++ b/lighting.h @@ -0,0 +1,104 @@ +#ifndef LIGHTING_H +#define LIGHTING_H + +#include "common.h" +#include "scene.h" + +static int ray_world( v3f pos, v3f dir, ray_hit *hit ); + +typedef struct voxel_gi voxel_gi; + +struct voxel_gi +{ + GLuint hw_texture, + pt_texture; + + v3i pt_dims; /* Page table dimentions */ + i32 page_size; + + v3f origin; +}; + +static void voxel_gi_setup( voxel_gi *gi, scene *sc, + i32 page_size, float voxel_res ) +{ + v3_copy( sc->bbx[0], gi->origin ); + gi->page_size = page_size; + + v3f extent; + v3_sub( sc->bbx[1], sc->bbx[0], extent ); + + float fpage_size = voxel_res * (float)page_size; + + for( int i=0; i<3; i++ ) + { + i32 voxel_count = extent[i] / voxel_res; + gi->pt_dims[i] = (voxel_count+page_size-1) / page_size; + } + + i32 pt_capacity = gi->pt_dims[0]*gi->pt_dims[1]*gi->pt_dims[2]; + vg_info( "Page table size: %dkb\n", (pt_capacity*2*2)/1024 ); + + u16 *page_table = malloc( pt_capacity*sizeof(u16)*3 ); + + + u32 active_count = 0; + + for( int z=0; zpt_dims[2]; z++ ) + { + for( int y=0; ypt_dims[1]; y++ ) + { + for( int x=0; xpt_dims[0]; x++ ) + { + v3f base = {x,y,z}, + end = {x+1,y+1,z+1}; + + boxf page_region; + + v3_muladds( sc->bbx[0], base, ((float)page_size)*voxel_res, base ); + v3_muladds( sc->bbx[0], end, ((float)page_size)*voxel_res, end ); + v3_copy( base, page_region[0] ); + v3_copy( end, page_region[1] ); + + u32 nothing[2]; + if( bh_select( &sc->bhtris, page_region, nothing, 2 )) + { + active_count ++; + + /* Calculate lighting */ + } + } + } + } + + /* Calculate physical storage size */ + vg_info( "Hardware texture required size: %dmb\n", + ((active_count*page_size*page_size*page_size*1)/1024)/1024 ); + vg_info( "Required physical blocks: %d\n", active_count ); + + free( page_table ); +} + +static void compute_lighting_vertex( scene *sc ) +{ + v3f light_dir = { 0.2f, 1.0f, 1.0f }; + v3_normalize( light_dir ); + + for( int i=0; ivertex_count; i++ ) + { + model_vert *mv = &sc->verts[i]; + + ray_hit hit; + hit.dist = 100.0f; + + ray_world( mv->co, light_dir, &hit ); + float amt = hit.dist / 100.0f; + + mv->colour[0] = amt; + mv->colour[1] = amt; + mv->colour[2] = amt; + mv->colour[3] = 1.0f; + } +} + +#endif /* LIGHTING_H */ diff --git a/main.c b/main.c index b80a1a2..ba6f384 100644 --- a/main.c +++ b/main.c @@ -40,9 +40,10 @@ void vg_register(void) { shader_blit_register(); shader_standard_register(); + shader_vblend_register(); shader_unlit_register(); - terrain_register(); + world_register(); character_register(); water_register(); gate_register(); @@ -52,7 +53,7 @@ static void init_other(void) { render_init(); gate_init(); - terrain_init(); + world_init(); character_init(); audio_init(); } diff --git a/render.h b/render.h index d8bdc95..8285317 100644 --- a/render.h +++ b/render.h @@ -11,20 +11,35 @@ static struct pipeline GLuint fb_background, rgb_background; + + /* STD140 */ + struct ub_world_lighting + { + /* v3f (padded) */ + v4f g_directional, + g_sun_colour, + g_shadow_colour; + + v4f g_water_plane, + g_depth_bounds; + float g_water_fog; + } + ub_world_lighting; + + GLuint fb_depthmap, rgb_depthmap; + GLuint ubo_world_lighting, + ubo_world; } 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, m4x3f camera ); static void render_world( m4x4f projection, m4x3f camera ); +static void render_world_depth( m4x4f projection, m4x3f camera ); +/* + * Matrix Projections + */ /* * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf */ @@ -54,6 +69,48 @@ static void pipeline_projection( m4x4f mat, float nearz, float farz ) nearz, farz ); } +/* + * Shaders + */ +static void shader_link_standard_ub( GLuint shader, int texture_id ) +{ + GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" ); + glUniformBlockBinding( shader, idx, 0 ); + + glActiveTexture( GL_TEXTURE0 + texture_id ); + glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_depthmap ); + glUniform1i( glGetUniformLocation( shader, "g_world_depth" ), texture_id ); +} + +static void render_update_lighting_ub(void) +{ + glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting ); + + glBufferSubData( GL_UNIFORM_BUFFER, 0, sizeof(struct ub_world_lighting), + &gpipeline.ub_world_lighting ); +} + +static void render_alloc_ub(void) +{ + glGenBuffers( 1, &gpipeline.ubo_world_lighting ); + glBindBuffer( GL_UNIFORM_BUFFER, gpipeline.ubo_world_lighting ); + glBufferData( GL_UNIFORM_BUFFER, sizeof(struct ub_world_lighting), + NULL, GL_DYNAMIC_DRAW ); + + render_update_lighting_ub(); + glBindBufferBase( GL_UNIFORM_BUFFER, 0, gpipeline.ubo_world_lighting ); +} + +/* + * Framebuffers + */ +struct framebuffer +{ + GLuint fb, colour, rb; + int div; + GLuint format; +}; + static void fb_use( struct framebuffer *fb ) { if( !fb ) @@ -120,6 +177,9 @@ static void render_fb_resize(void) GL_RGB, GL_UNSIGNED_BYTE, NULL ); } +/* + * Vg + */ static void render_init(void) { glGenFramebuffers( 1, &gpipeline.fb_background ); @@ -136,6 +196,25 @@ static void render_init(void) GL_TEXTURE_2D, gpipeline.rgb_background, 0); + /* + * World depth map, maybe this should be moved to world.h + * TODO: review + */ + glGenFramebuffers( 1, &gpipeline.fb_depthmap ); + glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_depthmap ); + + glGenTextures( 1, &gpipeline.rgb_depthmap ); + glBindTexture( GL_TEXTURE_2D, gpipeline.rgb_depthmap ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, 1024, 1024, 0, + GL_RED, GL_FLOAT, NULL ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + vg_tex2d_clamp(); + + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + gpipeline.rgb_depthmap, 0); + float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }; @@ -149,8 +228,18 @@ static void render_init(void) sizeof(float)*2, (void*)0 ); glEnableVertexAttribArray( 0 ); VG_CHECK_GL(); + + render_alloc_ub(); } +static void render_free(void) +{ + /* TODO: ... */ +} + +/* + * Utility + */ static void render_fsquad(void) { glBindVertexArray( gpipeline.fsquad.vao ); diff --git a/scene.h b/scene.h index 6f7c28c..76baf54 100644 --- a/scene.h +++ b/scene.h @@ -178,10 +178,6 @@ static void scene_add_foliage( scene *pscene, model *mdl, submodel *submodel, v4_copy( src->colour, pvert->colour ); v2_copy( src->uv, pvert->uv ); - - float rel_y = src->co[1] / submodel->bbx[1][1]; - pvert->colour[0] = rel_y; - pvert->colour[2] = rand_hue; } for( u32 i=0; iindice_count; i++ ) diff --git a/shaders/colour.fs b/shaders/colour.fs new file mode 100644 index 0000000..7eb290e --- /dev/null +++ b/shaders/colour.fs @@ -0,0 +1,9 @@ +out vec4 FragColor; +uniform vec4 uColour; + +in vec2 aUv; + +void main() +{ + FragColor = uColour; +} diff --git a/shaders/common_world.glsl b/shaders/common_world.glsl new file mode 100644 index 0000000..329226a --- /dev/null +++ b/shaders/common_world.glsl @@ -0,0 +1,57 @@ +layout (std140) uniform ub_world_lighting +{ + vec3 g_directional; + vec3 g_sun_colour; + vec3 g_shadow_colour; + vec4 g_water_plane; + vec4 g_depth_bounds; + float g_water_fog; +}; + +uniform sampler2D g_world_depth; + +// Standard diffuse + spec models +// ============================== + +vec3 do_light_diffuse( vec3 vfrag, vec3 wnormal ) +{ + float flight = dot( g_directional, wnormal )*0.5+0.5; + return vfrag * mix( g_shadow_colour, g_sun_colour, flight ); +} + +vec3 do_light_spec( vec3 vfrag, vec3 wnormal, vec3 halfview, float fintensity ) +{ + vec3 specdir = reflect( -g_directional, wnormal ); + float spec = pow(max(dot( halfview, specdir ), 0.0), 10.0); + return vfrag + g_sun_colour*spec*fintensity; +} + +float world_depth_sample( vec3 pos ) +{ + vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; + return texture( g_world_depth, depth_coord ).r; +} + +float shadow_sample( vec3 vdir ) +{ + vec3 sample_pos = aCo + vdir; + float height_sample = world_depth_sample( sample_pos ); + + float fdelta = height_sample - sample_pos.y; + return clamp( fdelta, 0.1, 0.2 )-0.1; +} + +vec3 do_light_shadowing( vec3 vfrag ) +{ + float faccum = 0.0; + faccum += shadow_sample( vec3( 0.0, 0.5, 0.0 )); + faccum += shadow_sample( vec3( 2.0, 0.3, 0.0 )); + faccum += shadow_sample( vec3( 3.0, 1.0, 0.0 )); + faccum += shadow_sample( vec3( 5.0, 1.0, 0.0 )); + faccum += shadow_sample( vec3( 0.0, 0.5, 0.0 )*1.5); + faccum += shadow_sample( vec3( 2.0, 0.3, 0.0 )*1.5); + faccum += shadow_sample( vec3( 3.0, 1.0, 0.0 )*1.5); + faccum += shadow_sample( vec3( 5.0, 1.0, 0.0 )*1.5); + return mix( vfrag, g_shadow_colour, faccum ); +} + diff --git a/shaders/fscolour.h b/shaders/fscolour.h new file mode 100644 index 0000000..ccef7b0 --- /dev/null +++ b/shaders/fscolour.h @@ -0,0 +1,48 @@ +#ifndef SHADER_fscolour_H +#define SHADER_fscolour_H +static void shader_fscolour_link(void); +static void shader_fscolour_register(void); +static struct vg_shader _shader_fscolour = { + .name = "fscolour", + .link = shader_fscolour_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/colour.fs", +.static_src = +"out vec4 FragColor;\n" +"uniform vec4 uColour;\n" +"\n" +"in vec2 aUv;\n" +"\n" +"void main()\n" +"{\n" +" FragColor = uColour;\n" +"}\n" +""}, +}; + +static GLuint _uniform_fscolour_uColour; +static void shader_fscolour_uColour(v4f v){ + glUniform4fv( _uniform_fscolour_uColour, 1, v ); +} +static void shader_fscolour_register(void){ + vg_shader_register( &_shader_fscolour ); +} +static void shader_fscolour_use(void){ glUseProgram(_shader_fscolour.id); } +static void shader_fscolour_link(void){ + _uniform_fscolour_uColour = glGetUniformLocation( _shader_fscolour.id, "uColour" ); +} +#endif /* SHADER_fscolour_H */ diff --git a/shaders/gpos.fs b/shaders/gpos.fs new file mode 100644 index 0000000..b21f7a7 --- /dev/null +++ b/shaders/gpos.fs @@ -0,0 +1,30 @@ +out vec4 FragColor; + +uniform vec3 uCamera; + +in vec4 aColour; +in vec2 aUv; +in vec3 aNorm; +in vec3 aCo; + +#include "common_world.glsl" + +// Water blending +// ============== + +float water_depth( vec3 pos, vec3 halfview ) +{ + vec3 pnorm = g_water_plane.xyz; + float pdist = g_water_plane.w; + + float d = dot( pnorm, halfview ); + float t = dot((pnorm*pdist - pos), pnorm) / d; + return t * g_water_fog; +} + +void main() +{ + vec3 halfview = normalize( uCamera - aCo ); + vec3 world_pos = vec3( aCo.y, aCo.x, aCo.z ); + FragColor = vec4( world_pos, water_depth( aCo, halfview ) ); +} diff --git a/shaders/gpos.h b/shaders/gpos.h new file mode 100644 index 0000000..6b8d9cb --- /dev/null +++ b/shaders/gpos.h @@ -0,0 +1,158 @@ +#ifndef SHADER_gpos_H +#define SHADER_gpos_H +static void shader_gpos_link(void); +static void shader_gpos_register(void); +static struct vg_shader _shader_gpos = { + .name = "gpos", + .link = shader_gpos_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/gpos.fs", +.static_src = +"out vec4 FragColor;\n" +"\n" +"uniform vec3 uCamera;\n" +"\n" +"in vec4 aColour;\n" +"in vec2 aUv;\n" +"in vec3 aNorm;\n" +"in vec3 aCo;\n" +"\n" +"#line 1 1 \n" +"layout (std140) uniform ub_world_lighting\n" +"{\n" +" vec3 g_directional;\n" +" vec3 g_sun_colour;\n" +" vec3 g_shadow_colour;\n" +" vec4 g_water_plane;\n" +" vec4 g_depth_bounds;\n" +" float g_water_fog;\n" +"};\n" +"\n" +"uniform sampler2D g_world_depth;\n" +"\n" +"// Standard diffuse + spec models\n" +"// ==============================\n" +"\n" +"vec3 do_light_diffuse( vec3 vfrag, vec3 wnormal )\n" +"{\n" +" float flight = dot( g_directional, wnormal )*0.5+0.5;\n" +" return vfrag * mix( g_shadow_colour, g_sun_colour, flight );\n" +"}\n" +"\n" +"vec3 do_light_spec( vec3 vfrag, vec3 wnormal, vec3 halfview, float fintensity )\n" +"{\n" +" vec3 specdir = reflect( -g_directional, wnormal );\n" +" float spec = pow(max(dot( halfview, specdir ), 0.0), 10.0);\n" +" return vfrag + g_sun_colour*spec*fintensity;\n" +"}\n" +"\n" +"float world_depth_sample( vec3 pos )\n" +"{\n" +" vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n" +" return texture( g_world_depth, depth_coord ).r;\n" +"}\n" +"\n" +"float shadow_sample( vec3 vdir )\n" +"{\n" +" vec3 sample_pos = aCo + vdir;\n" +" float height_sample = world_depth_sample( sample_pos );\n" +"\n" +" float fdelta = height_sample - sample_pos.y;\n" +" return clamp( fdelta, 0.1, 0.2 )-0.1;\n" +"}\n" +"\n" +"vec3 do_light_shadowing( vec3 vfrag )\n" +"{\n" +" float faccum = 0.0;\n" +" faccum += shadow_sample( vec3( 0.0, 0.5, 0.0 ));\n" +" faccum += shadow_sample( vec3( 2.0, 0.3, 0.0 ));\n" +" faccum += shadow_sample( vec3( 3.0, 1.0, 0.0 ));\n" +" faccum += shadow_sample( vec3( 5.0, 1.0, 0.0 ));\n" +" faccum += shadow_sample( vec3( 0.0, 0.5, 0.0 )*1.5);\n" +" faccum += shadow_sample( vec3( 2.0, 0.3, 0.0 )*1.5);\n" +" faccum += shadow_sample( vec3( 3.0, 1.0, 0.0 )*1.5);\n" +" faccum += shadow_sample( vec3( 5.0, 1.0, 0.0 )*1.5);\n" +" return mix( vfrag, g_shadow_colour, faccum );\n" +"}\n" +"\n" +"\n" +"#line 11 0 \n" +"\n" +"// Water blending\n" +"// ==============\n" +"\n" +"float water_depth( vec3 pos, vec3 halfview )\n" +"{\n" +" vec3 pnorm = g_water_plane.xyz;\n" +" float pdist = g_water_plane.w;\n" +"\n" +" float d = dot( pnorm, halfview );\n" +" float t = dot((pnorm*pdist - pos), pnorm) / d;\n" +" return t * g_water_fog;\n" +"}\n" +"\n" +"void main()\n" +"{\n" +" vec3 halfview = normalize( uCamera - aCo );\n" +" vec3 world_pos = vec3( aCo.y, aCo.x, aCo.z );\n" +" FragColor = vec4( world_pos, water_depth( aCo, halfview ) );\n" +"}\n" +""}, +}; + +static GLuint _uniform_gpos_uPv; +static GLuint _uniform_gpos_uMdl; +static GLuint _uniform_gpos_uCamera; +static GLuint _uniform_gpos_g_world_depth; +static void shader_gpos_uPv(m4x4f m){ + glUniformMatrix4fv( _uniform_gpos_uPv, 1, GL_FALSE, (float *)m ); +} +static void shader_gpos_uMdl(m4x3f m){ + glUniformMatrix4x3fv( _uniform_gpos_uMdl, 1, GL_FALSE, (float *)m ); +} +static void shader_gpos_uCamera(v3f v){ + glUniform3fv( _uniform_gpos_uCamera, 1, v ); +} +static void shader_gpos_g_world_depth(int i){ + glUniform1i( _uniform_gpos_g_world_depth, i ); +} +static void shader_gpos_register(void){ + vg_shader_register( &_shader_gpos ); +} +static void shader_gpos_use(void){ glUseProgram(_shader_gpos.id); } +static void shader_gpos_link(void){ + _uniform_gpos_uPv = glGetUniformLocation( _shader_gpos.id, "uPv" ); + _uniform_gpos_uMdl = glGetUniformLocation( _shader_gpos.id, "uMdl" ); + _uniform_gpos_uCamera = glGetUniformLocation( _shader_gpos.id, "uCamera" ); + _uniform_gpos_g_world_depth = glGetUniformLocation( _shader_gpos.id, "g_world_depth" ); +} +#endif /* SHADER_gpos_H */ diff --git a/shaders/noise.glsl b/shaders/noise.glsl new file mode 100644 index 0000000..6736e35 --- /dev/null +++ b/shaders/noise.glsl @@ -0,0 +1,26 @@ +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; +} diff --git a/shaders/planeinf.h b/shaders/planeinf.h index 0cc17cd..d2a227a 100644 --- a/shaders/planeinf.h +++ b/shaders/planeinf.h @@ -37,28 +37,6 @@ static struct vg_shader _shader_planeinf = { { .orig_file = "../shaders/planeinf.fs", .static_src = -"vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue, \n" -" vec4 beneath, vec4 above )\n" -"{\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, depthvalue);\n" -"\n" -" float ffresnel = pow(1.0-dot( vnorm, halfview ),5.0);\n" -"\n" -" vec3 lightdir = vec3(0.95,0.0,-0.3);\n" -" vec3 specdir = reflect( -lightdir, vnorm );\n" -" float spec = pow(max(dot(halfview,specdir),0.0),20.0)*0.3;\n" -" \n" -" // Depth \n" -" float depthblend = pow( beneath.a,0.8 );\n" -"\n" -" // Composite\n" -" vec3 vsurface = mix(surface_tint, above.rgb, ffresnel );\n" -" //vsurface += spec;\n" -"\n" -" return vec4( vsurface,depthblend );\n" -"}\n" "\n" "#line 2 0 \n" "\n" diff --git a/shaders/sky.h b/shaders/sky.h index 01bc5c2..8e8c2c7 100644 --- a/shaders/sky.h +++ b/shaders/sky.h @@ -67,7 +67,7 @@ static struct vg_shader _shader_sky = { " 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,1.0,1.0), cloud_e*(1.0-fblend*3.0));\n" +" vec3 skycomp = mix(diffuse, vec3(1.0,1.0,1.0), cloud_e);\n" " FragColor = vec4(skycomp,1.0);\n" "}\n" ""}, diff --git a/shaders/sway.glsl b/shaders/sway.glsl new file mode 100644 index 0000000..6cd92d0 --- /dev/null +++ b/shaders/sway.glsl @@ -0,0 +1,112 @@ + + "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;" + "}" diff --git a/shaders/terrain.fs b/shaders/terrain.fs index a6d2400..84482af 100644 --- a/shaders/terrain.fs +++ b/shaders/terrain.fs @@ -3,27 +3,24 @@ 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.04; -} +#include "common_world.glsl" void main() { + vec3 vfrag = vec3(0.5,0.5,0.5); + + // ws modulation vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 ); // Creating normal patches vec3 modnorm = (wgarbage.rgb-0.4) * 1.4; - vec3 qnorm = normalize(floor(aNorm*4.0+modnorm) * 0.25); + vec3 qnorm = normalize(floor(aNorm*4.0+modnorm)*0.25) + vec3(0.001,0.0,0.0); vec2 dir = normalize(qnorm.xz); vec2 uvdiffuse = aCo.xz * 0.02; uvdiffuse = mat2(dir.y, dir.x, -dir.x, dir.y) * uvdiffuse; @@ -33,22 +30,16 @@ void main() // Colour blending float amtgrass = step(qnorm.y,0.6); - float amtsand = min(max((aCo.y - 10.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 ); + float amtsand = min(max((aCo.y - 10.0) * -0.1,0.0)*qnorm.y,1.0); + vec2 uvgradients = aUv + vec2( amtgrass*0.5 + rgarbage.a*0.4, 0.0 ); + vfrag = texture( uTexGradients, uvgradients ).rgb; + vfrag = mix( vfrag, vec3(1.0,0.9,0.8), amtsand ); // Lighting - vec3 lightdir = vec3(0.95,0.0,-0.3); - vec3 shadow = vec3(0.27,0.25,0.34); - 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)); - - // Specular lighting vec3 halfview = normalize( uCamera - aCo ); - vec3 specdir = reflect( -lightdir, qnorm ); - float spec = pow(max(dot(halfview,specdir),0.0),10.0) * 0.2*rgarbage.r; - diffuse += spec * vec3(1.0,0.8,0.8); + vfrag = do_light_diffuse( vfrag, qnorm ); + vfrag = do_light_spec( vfrag, qnorm, halfview, 0.2 * rgarbage.a ); + vfrag = do_light_shadowing( vfrag ); - FragColor = vec4(diffuse, water_depth(aCo,halfview,uPlane)); + FragColor = vec4( vfrag, 1.0 ); } diff --git a/shaders/terrain.h b/shaders/terrain.h index 9bbb939..ce834d4 100644 --- a/shaders/terrain.h +++ b/shaders/terrain.h @@ -42,27 +42,83 @@ 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" +"#line 1 1 \n" +"layout (std140) uniform ub_world_lighting\n" "{\n" -" float d = dot( plane.xyz, dir );\n" -" float t = dot((plane.xyz*plane.w - pos),plane.xyz) / d;\n" -" return t*0.04;\n" +" vec3 g_directional;\n" +" vec3 g_sun_colour;\n" +" vec3 g_shadow_colour;\n" +" vec4 g_water_plane;\n" +" vec4 g_depth_bounds;\n" +" float g_water_fog;\n" +"};\n" +"\n" +"uniform sampler2D g_world_depth;\n" +"\n" +"// Standard diffuse + spec models\n" +"// ==============================\n" +"\n" +"vec3 do_light_diffuse( vec3 vfrag, vec3 wnormal )\n" +"{\n" +" float flight = dot( g_directional, wnormal )*0.5+0.5;\n" +" return vfrag * mix( g_shadow_colour, g_sun_colour, flight );\n" "}\n" "\n" +"vec3 do_light_spec( vec3 vfrag, vec3 wnormal, vec3 halfview, float fintensity )\n" +"{\n" +" vec3 specdir = reflect( -g_directional, wnormal );\n" +" float spec = pow(max(dot( halfview, specdir ), 0.0), 10.0);\n" +" return vfrag + g_sun_colour*spec*fintensity;\n" +"}\n" +"\n" +"float world_depth_sample( vec3 pos )\n" +"{\n" +" vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n" +" return texture( g_world_depth, depth_coord ).r;\n" +"}\n" +"\n" +"float shadow_sample( vec3 vdir )\n" +"{\n" +" vec3 sample_pos = aCo + vdir;\n" +" float height_sample = world_depth_sample( sample_pos );\n" +"\n" +" float fdelta = height_sample - sample_pos.y;\n" +" return clamp( fdelta, 0.1, 0.2 )-0.1;\n" +"}\n" +"\n" +"vec3 do_light_shadowing( vec3 vfrag )\n" +"{\n" +" float faccum = 0.0;\n" +" faccum += shadow_sample( vec3( 0.0, 0.5, 0.0 ));\n" +" faccum += shadow_sample( vec3( 2.0, 0.3, 0.0 ));\n" +" faccum += shadow_sample( vec3( 3.0, 1.0, 0.0 ));\n" +" faccum += shadow_sample( vec3( 5.0, 1.0, 0.0 ));\n" +" faccum += shadow_sample( vec3( 0.0, 0.5, 0.0 )*1.5);\n" +" faccum += shadow_sample( vec3( 2.0, 0.3, 0.0 )*1.5);\n" +" faccum += shadow_sample( vec3( 3.0, 1.0, 0.0 )*1.5);\n" +" faccum += shadow_sample( vec3( 5.0, 1.0, 0.0 )*1.5);\n" +" return mix( vfrag, g_shadow_colour, faccum );\n" +"}\n" +"\n" +"\n" +"#line 13 0 \n" +"\n" "void main()\n" "{\n" +" vec3 vfrag = vec3(0.5,0.5,0.5);\n" +"\n" +" // ws modulation\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 = normalize(floor(aNorm*4.0+modnorm) * 0.25);\n" +" vec3 qnorm = normalize(floor(aNorm*4.0+modnorm)*0.25) + vec3(0.001,0.0,0.0);\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" @@ -72,24 +128,18 @@ static struct vg_shader _shader_terrain = { "\n" " // Colour blending\n" " float amtgrass = step(qnorm.y,0.6);\n" -" float amtsand = min(max((aCo.y - 10.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" -" diffuse = mix( diffuse, vec3(1.0,0.9,0.7), amtsand );\n" +" float amtsand = min(max((aCo.y - 10.0) * -0.1,0.0)*qnorm.y,1.0);\n" +" vec2 uvgradients = aUv + vec2( amtgrass*0.5 + rgarbage.a*0.4, 0.0 );\n" +" vfrag = texture( uTexGradients, uvgradients ).rgb;\n" +" vfrag = mix( vfrag, vec3(1.0,0.9,0.8), amtsand );\n" "\n" " // Lighting\n" -" vec3 lightdir = vec3(0.95,0.0,-0.3);\n" -" vec3 shadow = vec3(0.3,0.25,0.34);\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" -" // Specular lighting\n" " vec3 halfview = normalize( uCamera - aCo );\n" -" vec3 specdir = reflect( -lightdir, qnorm );\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" +" vfrag = do_light_diffuse( vfrag, qnorm );\n" +" vfrag = do_light_spec( vfrag, qnorm, halfview, 0.2 * rgarbage.a );\n" +" vfrag = do_light_shadowing( vfrag );\n" "\n" -" FragColor = vec4(diffuse, water_depth(aCo,halfview,uPlane));\n" +" FragColor = vec4( vfrag, 1.0 );\n" "}\n" ""}, }; @@ -99,7 +149,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 GLuint _uniform_terrain_g_world_depth; static void shader_terrain_uPv(m4x4f m){ glUniformMatrix4fv( _uniform_terrain_uPv, 1, GL_FALSE, (float *)m ); } @@ -115,8 +165,8 @@ 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_g_world_depth(int i){ + glUniform1i( _uniform_terrain_g_world_depth, i ); } static void shader_terrain_register(void){ vg_shader_register( &_shader_terrain ); @@ -128,6 +178,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" ); + _uniform_terrain_g_world_depth = glGetUniformLocation( _shader_terrain.id, "g_world_depth" ); } #endif /* SHADER_terrain_H */ diff --git a/shaders/vblend.fs b/shaders/vblend.fs new file mode 100644 index 0000000..690f5c7 --- /dev/null +++ b/shaders/vblend.fs @@ -0,0 +1,80 @@ +out vec4 FragColor; + +uniform sampler2D uTexGarbage; +uniform sampler2D uTexGradients; +uniform sampler2D uTexDepth; +uniform vec4 uDepthBounds; +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.04; +} + +float sample_height( vec3 pos ) +{ + vec2 depth_coords = (pos.xz-uDepthBounds.xy)*uDepthBounds.zw; + return texture( uTexDepth, depth_coords ).r; +} + +float create_shadowing( vec3 vdir ) +{ + return clamp( sample_height( aCo+vdir ) - (aCo.y+vdir.y), 0.1, 0.2 )-0.1; +} + +void main() +{ + vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.160 ); + + // Creating normal patches + vec3 modnorm = (wgarbage.rgb-0.4) * 1.4; + vec3 qnorm = normalize(floor(aNorm*4.0+modnorm)*0.25) + vec3(0.001,0.0,0.0); + + vec3 tangent0 = normalize(cross(qnorm,vec3(0.0,1.0,0.0))); + vec3 tangent1 = cross(qnorm,tangent0); + vec2 uvdiffuse = vec2( dot(tangent0,aCo), dot(tangent1,aCo) ) * 0.160; + + // Patch local noise + vec4 rgarbage = texture( uTexGarbage, uvdiffuse ); + + // Colour blending + float fblendclip = step(0.380,aColour.r + (rgarbage.r-0.5)*-1.740)*0.320; + vec2 uvgradients = aUv + vec2( fblendclip, 0.0 ); + + vec3 diffuse = texture( uTexGradients, uvgradients ).rgb; + diffuse -= rgarbage.a*0.04; + + // Lighting + vec3 lightdir = normalize(vec3(0.5,0.5,-0.1)); + vec3 shadow = vec3(0.27,0.25,0.34); + float light1 = dot( lightdir, aNorm )*0.5+0.5; + diffuse = diffuse * (light1*vec3(1.0,0.96,0.9)*1.2 + shadow*(1.0-light1)); + + // Specular lighting + vec3 halfview = normalize( uCamera - aCo ); + vec3 specdir = reflect( -lightdir, qnorm ); + float spec = pow(max(dot(halfview,specdir),0.0),10.0) * 0.3*rgarbage.r; + //diffuse += spec * vec3(1.0,0.8,0.8); + + float faccum = 0.0; + vec3 offs = vec3(rgarbage.x, 0.0, rgarbage.z)*4.0; + faccum += create_shadowing( vec3( 0.0, 0.5, 0.0 )*0.6); + faccum += create_shadowing( vec3( 2.0, 0.3, 0.0 )*0.6); + faccum += create_shadowing( vec3( 3.0, 1.0, 0.0 )*0.6); + faccum += create_shadowing( vec3( 5.0, 1.0, 0.0 )*0.6); + faccum += create_shadowing( vec3( 0.0, 0.5, 0.0 )*0.6*1.5+offs); + faccum += create_shadowing( vec3( 2.0, 0.3, 0.0 )*0.6*1.5); + faccum += create_shadowing( vec3( 3.0, 1.0, 0.0 )*0.6*1.5-offs); + faccum += create_shadowing( vec3( 5.0, 1.0, 0.0 )*0.6*1.5); + diffuse = mix( diffuse, vec3(0.15,0.1,0.2), min(faccum*1.0,1.0)); + + FragColor = vec4(diffuse, water_depth(aCo,halfview,uPlane)); +} diff --git a/shaders/vblend.h b/shaders/vblend.h new file mode 100644 index 0000000..26d7a51 --- /dev/null +++ b/shaders/vblend.h @@ -0,0 +1,169 @@ +#ifndef SHADER_vblend_H +#define SHADER_vblend_H +static void shader_vblend_link(void); +static void shader_vblend_register(void); +static struct vg_shader _shader_vblend = { + .name = "vblend", + .link = shader_vblend_link, + .vs = +{ +.orig_file = "../shaders/terrain.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/vblend.fs", +.static_src = +"out vec4 FragColor;\n" +"\n" +"uniform sampler2D uTexGarbage;\n" +"uniform sampler2D uTexGradients;\n" +"uniform sampler2D uTexDepth;\n" +"uniform vec4 uDepthBounds;\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.04;\n" +"}\n" +"\n" +"float sample_height( vec3 pos )\n" +"{\n" +" vec2 depth_coords = (pos.xz-uDepthBounds.xy)*uDepthBounds.zw;\n" +" return texture( uTexDepth, depth_coords ).r;\n" +"}\n" +"\n" +"float create_shadowing( vec3 vdir )\n" +"{\n" +" return clamp( sample_height( aCo+vdir ) - (aCo.y+vdir.y), 0.1, 0.2 )-0.1;\n" +"}\n" +"\n" +"void main()\n" +"{\n" +" vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.160 );\n" +" \n" +" // Creating normal patches\n" +" vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;\n" +" vec3 qnorm = normalize(floor(aNorm*4.0+modnorm)*0.25) + vec3(0.001,0.0,0.0);\n" +"\n" +" vec3 tangent0 = normalize(cross(qnorm,vec3(0.0,1.0,0.0)));\n" +" vec3 tangent1 = cross(qnorm,tangent0);\n" +" vec2 uvdiffuse = vec2( dot(tangent0,aCo), dot(tangent1,aCo) ) * 0.160;\n" +" \n" +" // Patch local noise\n" +" vec4 rgarbage = texture( uTexGarbage, uvdiffuse );\n" +"\n" +" // Colour blending\n" +" float fblendclip = step(0.380,aColour.r + (rgarbage.r-0.5)*-1.740)*0.320;\n" +" vec2 uvgradients = aUv + vec2( fblendclip, 0.0 );\n" +"\n" +" vec3 diffuse = texture( uTexGradients, uvgradients ).rgb;\n" +" diffuse -= rgarbage.a*0.04;\n" +"\n" +" // Lighting\n" +" vec3 lightdir = normalize(vec3(0.5,0.5,-0.1));\n" +" vec3 shadow = vec3(0.27,0.25,0.34);\n" +" float light1 = dot( lightdir, aNorm )*0.5+0.5;\n" +" diffuse = diffuse * (light1*vec3(1.0,0.96,0.9)*1.2 + shadow*(1.0-light1));\n" +" \n" +" // Specular lighting\n" +" vec3 halfview = normalize( uCamera - aCo );\n" +" vec3 specdir = reflect( -lightdir, qnorm );\n" +" float spec = pow(max(dot(halfview,specdir),0.0),10.0) * 0.3*rgarbage.r;\n" +" //diffuse += spec * vec3(1.0,0.8,0.8);\n" +"\n" +" float faccum = 0.0;\n" +" vec3 offs = vec3(rgarbage.x, 0.0, rgarbage.z)*4.0;\n" +" faccum += create_shadowing( vec3( 0.0, 0.5, 0.0 )*0.6);\n" +" faccum += create_shadowing( vec3( 2.0, 0.3, 0.0 )*0.6);\n" +" faccum += create_shadowing( vec3( 3.0, 1.0, 0.0 )*0.6);\n" +" faccum += create_shadowing( vec3( 5.0, 1.0, 0.0 )*0.6);\n" +" faccum += create_shadowing( vec3( 0.0, 0.5, 0.0 )*0.6*1.5+offs);\n" +" faccum += create_shadowing( vec3( 2.0, 0.3, 0.0 )*0.6*1.5);\n" +" faccum += create_shadowing( vec3( 3.0, 1.0, 0.0 )*0.6*1.5-offs);\n" +" faccum += create_shadowing( vec3( 5.0, 1.0, 0.0 )*0.6*1.5);\n" +" diffuse = mix( diffuse, vec3(0.15,0.1,0.2), min(faccum*1.0,1.0));\n" +"\n" +" FragColor = vec4(diffuse, water_depth(aCo,halfview,uPlane));\n" +"}\n" +""}, +}; + +static GLuint _uniform_vblend_uPv; +static GLuint _uniform_vblend_uMdl; +static GLuint _uniform_vblend_uTexGarbage; +static GLuint _uniform_vblend_uTexGradients; +static GLuint _uniform_vblend_uTexDepth; +static GLuint _uniform_vblend_uDepthBounds; +static GLuint _uniform_vblend_uCamera; +static GLuint _uniform_vblend_uPlane; +static void shader_vblend_uPv(m4x4f m){ + glUniformMatrix4fv( _uniform_vblend_uPv, 1, GL_FALSE, (float *)m ); +} +static void shader_vblend_uMdl(m4x3f m){ + glUniformMatrix4x3fv( _uniform_vblend_uMdl, 1, GL_FALSE, (float *)m ); +} +static void shader_vblend_uTexGarbage(int i){ + glUniform1i( _uniform_vblend_uTexGarbage, i ); +} +static void shader_vblend_uTexGradients(int i){ + glUniform1i( _uniform_vblend_uTexGradients, i ); +} +static void shader_vblend_uTexDepth(int i){ + glUniform1i( _uniform_vblend_uTexDepth, i ); +} +static void shader_vblend_uDepthBounds(v4f v){ + glUniform4fv( _uniform_vblend_uDepthBounds, 1, v ); +} +static void shader_vblend_uCamera(v3f v){ + glUniform3fv( _uniform_vblend_uCamera, 1, v ); +} +static void shader_vblend_uPlane(v4f v){ + glUniform4fv( _uniform_vblend_uPlane, 1, v ); +} +static void shader_vblend_register(void){ + vg_shader_register( &_shader_vblend ); +} +static void shader_vblend_use(void){ glUseProgram(_shader_vblend.id); } +static void shader_vblend_link(void){ + _uniform_vblend_uPv = glGetUniformLocation( _shader_vblend.id, "uPv" ); + _uniform_vblend_uMdl = glGetUniformLocation( _shader_vblend.id, "uMdl" ); + _uniform_vblend_uTexGarbage = glGetUniformLocation( _shader_vblend.id, "uTexGarbage" ); + _uniform_vblend_uTexGradients = glGetUniformLocation( _shader_vblend.id, "uTexGradients" ); + _uniform_vblend_uTexDepth = glGetUniformLocation( _shader_vblend.id, "uTexDepth" ); + _uniform_vblend_uDepthBounds = glGetUniformLocation( _shader_vblend.id, "uDepthBounds" ); + _uniform_vblend_uCamera = glGetUniformLocation( _shader_vblend.id, "uCamera" ); + _uniform_vblend_uPlane = glGetUniformLocation( _shader_vblend.id, "uPlane" ); +} +#endif /* SHADER_vblend_H */ diff --git a/shaders/vertex_standard.glsl b/shaders/vertex_standard.glsl new file mode 100644 index 0000000..0b46d33 --- /dev/null +++ b/shaders/vertex_standard.glsl @@ -0,0 +1,4 @@ +layout (location=0) in vec3 a_co; +layout (location=1) in vec3 a_norm; +layout (location=2) in vec4 a_colour; +layout (location=3) in vec2 a_uv; diff --git a/shaders/vg/blit.fs.glsl b/shaders/vg/blit.fs.glsl new file mode 100644 index 0000000..b98d5e8 --- /dev/null +++ b/shaders/vg/blit.fs.glsl @@ -0,0 +1,9 @@ +out vec4 FragColor; +uniform sampler2D uTexMain; + +in vec2 aUv; + +void main() +{ + FragColor = texture( uTexMain, aUv ); +} diff --git a/shaders/vg/blit.vs.glsl b/shaders/vg/blit.vs.glsl new file mode 100644 index 0000000..2593725 --- /dev/null +++ b/shaders/vg/blit.vs.glsl @@ -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/vg/character.fs.glsl b/shaders/vg/character.fs.glsl new file mode 100644 index 0000000..d3c2bea --- /dev/null +++ b/shaders/vg/character.fs.glsl @@ -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/vg/character.vs.glsl b/shaders/vg/character.vs.glsl new file mode 100644 index 0000000..7f79f4d --- /dev/null +++ b/shaders/vg/character.vs.glsl @@ -0,0 +1,28 @@ +layout (location=0) in vec3 a_co; +layout (location=1) in vec3 a_norm; +layout (location=2) in vec4 a_colour; +layout (location=3) in vec2 a_uv; + +#line 2 0 + +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/vg/gate.fs.glsl b/shaders/vg/gate.fs.glsl new file mode 100644 index 0000000..ba48f1e --- /dev/null +++ b/shaders/vg/gate.fs.glsl @@ -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/vg/gate.vs.glsl b/shaders/vg/gate.vs.glsl new file mode 100644 index 0000000..e33c754 --- /dev/null +++ b/shaders/vg/gate.vs.glsl @@ -0,0 +1,22 @@ +layout (location=0) in vec3 a_co; +layout (location=1) in vec3 a_norm; +layout (location=2) in vec4 a_colour; +layout (location=3) in vec2 a_uv; + +#line 2 0 +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/vg/standard.fs.glsl b/shaders/vg/standard.fs.glsl new file mode 100644 index 0000000..e3f05c8 --- /dev/null +++ b/shaders/vg/standard.fs.glsl @@ -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/vg/standard.vs.glsl b/shaders/vg/standard.vs.glsl new file mode 100644 index 0000000..f755542 --- /dev/null +++ b/shaders/vg/standard.vs.glsl @@ -0,0 +1,23 @@ +layout (location=0) in vec3 a_co; +layout (location=1) in vec3 a_norm; +layout (location=2) in vec4 a_colour; +layout (location=3) in vec2 a_uv; + +#line 2 0 + +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/vg/terrain.fs.glsl b/shaders/vg/terrain.fs.glsl new file mode 100644 index 0000000..7bcdab8 --- /dev/null +++ b/shaders/vg/terrain.fs.glsl @@ -0,0 +1,8 @@ +// Nothing + +#line 2 0 + +void main() +{ + +} diff --git a/shaders/vg/terrain.vs.glsl b/shaders/vg/terrain.vs.glsl new file mode 100644 index 0000000..5bb262b --- /dev/null +++ b/shaders/vg/terrain.vs.glsl @@ -0,0 +1,6 @@ +uniform mat4x3 uMdl; + +void main() +{ + +} diff --git a/shaders/vg/unlit.fs.glsl b/shaders/vg/unlit.fs.glsl new file mode 100644 index 0000000..ec4d7ae --- /dev/null +++ b/shaders/vg/unlit.fs.glsl @@ -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/vg/water.fs.glsl b/shaders/vg/water.fs.glsl new file mode 100644 index 0000000..b352e39 --- /dev/null +++ b/shaders/vg/water.fs.glsl @@ -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*1.0,reflected.a); +} diff --git a/shaders/vg/water.vs.glsl b/shaders/vg/water.vs.glsl new file mode 100644 index 0000000..7751336 --- /dev/null +++ b/shaders/vg/water.vs.glsl @@ -0,0 +1,18 @@ +layout (location=0) in vec3 a_co; +layout (location=1) in vec3 a_norm; +layout (location=2) in vec4 a_colour; +layout (location=3) in vec2 a_uv; + +#line 2 0 + +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/shaders/water.fs b/shaders/water.fs index 1de00ec..0be4389 100644 --- a/shaders/water.fs +++ b/shaders/water.fs @@ -1,21 +1,43 @@ -#include "water_ref.glsl" - 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 vec4 aColour; +in vec2 aUv; +in vec3 aNorm; in vec3 aCo; -in float aDepth; + +#include "common_world.glsl" + +vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue, + vec4 beneath, vec4 above ) +{ + 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, depthvalue); + + float ffresnel = pow(1.0-dot( vnorm, halfview ),5.0); + + vec3 lightdir = vec3(0.95,0.0,-0.3); + vec3 specdir = reflect( -lightdir, vnorm ); + float spec = pow(max(dot(halfview,specdir),0.0),20.0)*0.3; + + // Depth + float depthblend = pow( beneath.a,0.8 ); + + // Composite + vec3 vsurface = mix(surface_tint, above.rgb, ffresnel ); + //vsurface += spec; + + return vec4( vsurface,depthblend ); +} void main() { @@ -23,10 +45,12 @@ void main() vec2 ssuv = gl_FragCoord.xy*uInvRes; // Surface colour composite - float depthvalue = texture( uTexDepth, aUv.zw ).r; + float depthvalue = clamp( -world_depth_sample( aCo )*(1.0/25.0), 0.0, 1.0 ); - vec4 dudva = texture(uTexDudv, aUv.xy + vec2(uTime*0.008,uTime*0.006))-0.5; - vec4 dudvb = texture(uTexDudv, aUv.xy*7.0-vec2(uTime*0.003,uTime*0.03))-0.5; + vec2 world_coord = aCo.xz * 0.008; + vec4 time_offsets = vec4( uTime ) * vec4( 0.008, 0.006, 0.003, 0.03 ); + vec4 dudva = texture( uTexDudv, world_coord + time_offsets.xy )-0.5; + vec4 dudvb = texture( uTexDudv, world_coord *7.0 - time_offsets.zw )-0.5; vec3 surfnorm = dudva.rgb + dudvb.rgb; surfnorm = normalize(vec3(0.0,1.0,0.0) + dudva.xyz*0.4 + dudvb.xyz*0.1); @@ -43,8 +67,6 @@ void main() vec4 beneath = texture( uTexBack, ssuv ); // Fog - //vec4 horizon = vec4( 0.5, 0.6, 0.9, 1.0 ); - vec4 horizon = vec4( 0.7,0.8,0.88, 1.0 ); float fdist = pow(length( aCo.xz-uCamera.xz ) * 0.00047, 2.6); // Composite diff --git a/shaders/water.h b/shaders/water.h index 995cdb8..e9c0883 100644 --- a/shaders/water.h +++ b/shaders/water.h @@ -7,7 +7,7 @@ static struct vg_shader _shader_water = { .link = shader_water_link, .vs = { -.orig_file = "../shaders/water.vs", +.orig_file = "../shaders/standard.vs", .static_src = "layout (location=0) in vec3 a_co;\n" "layout (location=1) in vec3 a_norm;\n" @@ -18,28 +18,102 @@ static struct vg_shader _shader_water = { "\n" "uniform mat4 uPv;\n" "uniform mat4x3 uMdl;\n" -"uniform vec4 uDepthBounds;\n" "\n" -"out vec4 aUv;\n" +"out vec4 aColour;\n" +"out vec2 aUv;\n" +"out vec3 aNorm;\n" "out vec3 aCo;\n" -"out float aDepth;\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" -" vec2 depth_coords = (world_pos.xz-uDepthBounds.xy)*uDepthBounds.zw;\n" -" aUv = vec4(world_pos.xz*0.005,depth_coords);\n" -" aCo = world_pos;\n" -"\n" -" aDepth = gl_Position.z;\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/water.fs", .static_src = +"out vec4 FragColor;\n" +"\n" +"uniform sampler2D uTexMain;\n" +"uniform sampler2D uTexDudv;\n" +"uniform sampler2D uTexBack;\n" +"\n" +"uniform vec2 uInvRes;\n" +"uniform float uTime;\n" +"uniform vec3 uCamera;\n" +"uniform float uSurfaceY;\n" +"\n" +"in vec4 aColour;\n" +"in vec2 aUv;\n" +"in vec3 aNorm;\n" +"in vec3 aCo;\n" +"\n" +"#line 1 1 \n" +"layout (std140) uniform ub_world_lighting\n" +"{\n" +" vec3 g_directional;\n" +" vec3 g_sun_colour;\n" +" vec3 g_shadow_colour;\n" +" vec4 g_water_plane;\n" +" vec4 g_depth_bounds;\n" +" float g_water_fog;\n" +"};\n" +"\n" +"uniform sampler2D g_world_depth;\n" +"\n" +"// Standard diffuse + spec models\n" +"// ==============================\n" +"\n" +"vec3 do_light_diffuse( vec3 vfrag, vec3 wnormal )\n" +"{\n" +" float flight = dot( g_directional, wnormal )*0.5+0.5;\n" +" return vfrag * mix( g_shadow_colour, g_sun_colour, flight );\n" +"}\n" +"\n" +"vec3 do_light_spec( vec3 vfrag, vec3 wnormal, vec3 halfview, float fintensity )\n" +"{\n" +" vec3 specdir = reflect( -g_directional, wnormal );\n" +" float spec = pow(max(dot( halfview, specdir ), 0.0), 10.0);\n" +" return vfrag + g_sun_colour*spec*fintensity;\n" +"}\n" +"\n" +"float world_depth_sample( vec3 pos )\n" +"{\n" +" vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n" +" return texture( g_world_depth, depth_coord ).r;\n" +"}\n" +"\n" +"float shadow_sample( vec3 vdir )\n" +"{\n" +" vec3 sample_pos = aCo + vdir;\n" +" float height_sample = world_depth_sample( sample_pos );\n" +"\n" +" float fdelta = height_sample - sample_pos.y;\n" +" return clamp( fdelta, 0.1, 0.2 )-0.1;\n" +"}\n" +"\n" +"vec3 do_light_shadowing( vec3 vfrag )\n" +"{\n" +" float faccum = 0.0;\n" +" faccum += shadow_sample( vec3( 0.0, 0.5, 0.0 ));\n" +" faccum += shadow_sample( vec3( 2.0, 0.3, 0.0 ));\n" +" faccum += shadow_sample( vec3( 3.0, 1.0, 0.0 ));\n" +" faccum += shadow_sample( vec3( 5.0, 1.0, 0.0 ));\n" +" faccum += shadow_sample( vec3( 0.0, 0.5, 0.0 )*1.5);\n" +" faccum += shadow_sample( vec3( 2.0, 0.3, 0.0 )*1.5);\n" +" faccum += shadow_sample( vec3( 3.0, 1.0, 0.0 )*1.5);\n" +" faccum += shadow_sample( vec3( 5.0, 1.0, 0.0 )*1.5);\n" +" return mix( vfrag, g_shadow_colour, faccum );\n" +"}\n" +"\n" +"\n" +"#line 18 0 \n" +"\n" "vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue, \n" " vec4 beneath, vec4 above )\n" "{\n" @@ -63,35 +137,18 @@ static struct vg_shader _shader_water = { " return vec4( vsurface,depthblend );\n" "}\n" "\n" -"#line 2 0 \n" -"\n" -"out vec4 FragColor;\n" -"\n" -"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" " // Create texture coords\n" " vec2 ssuv = gl_FragCoord.xy*uInvRes;\n" " \n" " // Surface colour composite\n" -" float depthvalue = texture( uTexDepth, aUv.zw ).r;\n" +" float depthvalue = clamp( -world_depth_sample( aCo )*(1.0/25.0), 0.0, 1.0 );\n" "\n" -" vec4 dudva = texture(uTexDudv, aUv.xy + vec2(uTime*0.008,uTime*0.006))-0.5;\n" -" vec4 dudvb = texture(uTexDudv, aUv.xy*7.0-vec2(uTime*0.003,uTime*0.03))-0.5;\n" +" vec2 world_coord = aCo.xz * 0.008;\n" +" vec4 time_offsets = vec4( uTime ) * vec4( 0.008, 0.006, 0.003, 0.03 );\n" +" vec4 dudva = texture( uTexDudv, world_coord + time_offsets.xy )-0.5;\n" +" vec4 dudvb = texture( uTexDudv, world_coord *7.0 - time_offsets.zw )-0.5;\n" "\n" " vec3 surfnorm = dudva.rgb + dudvb.rgb;\n" " surfnorm = normalize(vec3(0.0,1.0,0.0) + dudva.xyz*0.4 + dudvb.xyz*0.1);\n" @@ -108,8 +165,6 @@ static struct vg_shader _shader_water = { " vec4 beneath = texture( uTexBack, ssuv );\n" "\n" " // Fog\n" -" //vec4 horizon = vec4( 0.5, 0.6, 0.9, 1.0 );\n" -" vec4 horizon = vec4( 0.7,0.8,0.88, 1.0 );\n" " float fdist = pow(length( aCo.xz-uCamera.xz ) * 0.00047, 2.6);\n" "\n" " // Composite\n" @@ -122,33 +177,26 @@ static struct vg_shader _shader_water = { static GLuint _uniform_water_uPv; static GLuint _uniform_water_uMdl; -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 GLuint _uniform_water_g_world_depth; 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_uDepthBounds(v4f v){ - glUniform4fv( _uniform_water_uDepthBounds, 1, v ); -} 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_uTexDepth(int i){ - glUniform1i( _uniform_water_uTexDepth, i ); -} static void shader_water_uTexBack(int i){ glUniform1i( _uniform_water_uTexBack, i ); } @@ -164,6 +212,9 @@ static void shader_water_uCamera(v3f v){ static void shader_water_uSurfaceY(float f){ glUniform1f( _uniform_water_uSurfaceY, f ); } +static void shader_water_g_world_depth(int i){ + glUniform1i( _uniform_water_g_world_depth, i ); +} static void shader_water_register(void){ vg_shader_register( &_shader_water ); } @@ -171,14 +222,13 @@ 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_uDepthBounds = glGetUniformLocation( _shader_water.id, "uDepthBounds" ); _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" ); + _uniform_water_g_world_depth = glGetUniformLocation( _shader_water.id, "g_world_depth" ); } #endif /* SHADER_water_H */ diff --git a/shaders/water.vs b/shaders/water.vs index a78bf30..6fbee77 100644 --- a/shaders/water.vs +++ b/shaders/water.vs @@ -2,20 +2,15 @@ uniform mat4 uPv; uniform mat4x3 uMdl; -uniform vec4 uDepthBounds; out vec4 aUv; out vec3 aCo; -out float aDepth; void main() { vec3 world_pos = uMdl * vec4( a_co, 1.0 ); gl_Position = uPv * vec4(world_pos,1.0); - vec2 depth_coords = (world_pos.xz-uDepthBounds.xy)*uDepthBounds.zw; aUv = vec4(world_pos.xz*0.005,depth_coords); aCo = world_pos; - - aDepth = gl_Position.z; } diff --git a/shaders/water_ref.glsl b/shaders/water_ref.glsl new file mode 100644 index 0000000..e69de29 diff --git a/terrain.h b/terrain.h index 81b311a..b5e7e53 100644 --- a/terrain.h +++ b/terrain.h @@ -3,6 +3,7 @@ static void render_terrain(m4x4f projection, v3f camera); static void render_sky(m4x3f camera); +#if 0 #ifndef TERRAIN_H #define TERRAIN_H @@ -50,6 +51,12 @@ static void terrain_init(void) free(msky); } +static void bind_terrain_textures(void) +{ + vg_tex2d_bind( &tex_terrain_noise, 0 ); + vg_tex2d_bind( &tex_terrain_colours, 1 ); +} + static void render_terrain(m4x4f projection, v3f camera) { shader_terrain_use(); @@ -65,6 +72,15 @@ static void render_terrain(m4x4f projection, v3f camera) shader_terrain_uMdl( identity_matrix ); shader_terrain_uCamera( camera ); shader_terrain_uPlane( (v4f){ 0.0f,1.0f,0.0f, wrender.height } ); + + glActiveTexture( GL_TEXTURE2 ); + glBindTexture( GL_TEXTURE_2D, wrender.depthmap ); + shader_terrain_uTexDepth( 2 ); + shader_terrain_uDepthBounds( (v4f){ + wrender.depthbounds[0][0], + wrender.depthbounds[0][2], + 1.0f/ (wrender.depthbounds[1][0]-wrender.depthbounds[0][0]), + 1.0f/ (wrender.depthbounds[1][2]-wrender.depthbounds[0][2])} ); } static void render_lowerdome( m4x3f camera ) @@ -124,3 +140,4 @@ static void render_sky(m4x3f camera) } #endif +#endif diff --git a/textures/gradients.png b/textures/gradients.png index 201e051..64f8ae0 100644 Binary files a/textures/gradients.png and b/textures/gradients.png differ diff --git a/vg.conf b/vg.conf index 634e451..9dce131 100644 --- a/vg.conf +++ b/vg.conf @@ -2,12 +2,15 @@ vg_src="main.c" vg_target="game" shader blit blit.vs blit.fs +shader fscolour blit.vs colour.fs shader terrain terrain.vs terrain.fs +shader vblend terrain.vs vblend.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 gatelq gate.vs gate_lq.fs -shader water water.vs water.fs +shader water standard.vs water.fs shader sky standard.vs sky.fs shader planeinf standard.vs planeinf.fs +shader gpos standard.vs gpos.fs diff --git a/water.h b/water.h index ac1db00..1de2554 100644 --- a/water.h +++ b/water.h @@ -4,7 +4,6 @@ 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); @@ -23,12 +22,12 @@ static struct struct framebuffer fbreflect, fbdepth; glmesh mdl; - GLuint depthmap; boxf depthbounds; int depth_computed; float height; int enabled; + v4f plane; } wrender = { @@ -64,6 +63,7 @@ static void water_fb_resize(void) fb_resize( &wrender.fbdepth ); } +#if 0 static void water_compute_depth( boxf bounds ) { if( !wrender.enabled ) @@ -72,11 +72,11 @@ static void water_compute_depth( boxf bounds ) #ifdef VG_RELEASE int const kres = 512; #else - int const kres = 64; + int const kres = 1024; #endif vg_info( "Computing depth map\n" ); - u8 *img = malloc( kres*kres ); + float *img = malloc( kres*kres*sizeof(float) ); boxf interior; v3_add(bounds[0],(v3f){1.0f,1.0f,1.0f},interior[0]); @@ -92,25 +92,22 @@ static void water_compute_depth( boxf bounds ) { v3f pos = { x, 0.0f, y }; pos[0] += 0.5f; - pos[1] += 0.5f; + pos[2] += 0.5f; v3_divs( pos, kres+1, pos ); v3_muladd( interior[0], pos, volume, pos ); pos[1] = 2000.0f; ray_hit hit; hit.dist = INFINITY; - u8 *dst = &img[ y*kres+x ]; + float *dst = &img[ y*kres+x ]; if( ray_world( pos, (v3f){0.0f,-1.0f,0.0f}, &hit )) { - float h = wrender.height - hit.pos[1]; - h *= 1.0f/25.0f; - h = vg_clampf( h, 0.0f, 1.0f ); - *dst = (u8)(h*255.0f); + *dst = hit.pos[1]; } else { - *dst = 0; + *dst = 0.0f; } } } @@ -120,8 +117,8 @@ static void water_compute_depth( boxf bounds ) glGenTextures( 1, &wrender.depthmap ); glBindTexture( GL_TEXTURE_2D, wrender.depthmap ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RED, kres, kres, 0, - GL_RED, GL_UNSIGNED_BYTE, img ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_R32F, kres, kres, 0, + GL_RED, GL_FLOAT, img ); vg_tex2d_mipmap(); vg_tex2d_linear_mipmap(); @@ -131,11 +128,14 @@ static void water_compute_depth( boxf bounds ) free( img ); vg_success( "Done.\n" ); } +#endif static void water_set_surface( glmesh *surf, float height ) { wrender.mdl = *surf; wrender.height = height; + + v4_copy( (v4f){ 0.0f, 1.0f, 0.0f, height }, wrender.plane ); } static void render_water_texture( m4x3f camera ) @@ -204,7 +204,7 @@ static void render_water_texture( m4x3f camera ) plane_clip_projection( projection, clippb ); m4x4_mul( projection, view, projection ); - render_world( projection, camera ); + render_world_depth( projection, camera ); glViewport( 0, 0, vg_window_x, vg_window_y ); } @@ -226,18 +226,10 @@ static void render_water_surface( m4x4f pv, m4x3f camera ) 1.0f / (float)vg_window_x, 1.0f / (float)vg_window_y }); - glActiveTexture( GL_TEXTURE2 ); - glBindTexture( GL_TEXTURE_2D, wrender.depthmap ); - shader_water_uTexDepth( 2 ); - shader_water_uDepthBounds( (v4f){ - wrender.depthbounds[0][0], - wrender.depthbounds[0][2], - 1.0f/ (wrender.depthbounds[1][0]-wrender.depthbounds[0][0]), - 1.0f/ (wrender.depthbounds[1][2]-wrender.depthbounds[0][2])} ); + shader_link_standard_ub( _shader_water.id, 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 ); diff --git a/world.h b/world.h index af0507f..66922cd 100644 --- a/world.h +++ b/world.h @@ -12,45 +12,44 @@ static int ray_world( v3f pos, v3f dir, ray_hit *hit ); #include "rigidbody.h" #include "gate.h" #include "bvh.h" +#include "lighting.h" +#include "model.h" +#include "shaders/terrain.h" +#include "shaders/sky.h" +#include "shaders/planeinf.h" #include "shaders/standard.h" +#include "shaders/vblend.h" +#include "shaders/gpos.h" +#include "shaders/fscolour.h" static struct gworld { - scene geo, foliage; - submodel sm_road, sm_terrain; - glmesh skybox; - + /* gameplay */ v3f tutorial; - teleport_gate gates[64]; u32 gate_count; + /* Physics */ rigidbody temp_rbs[128]; u32 rb_count; - bh_tree bhcubes; + + /* Rendering & geometry */ + scene geo, foliage, props; + submodel sm_road, sm_terrain; + + glmesh skybox, skydome; + submodel dome_upper, + dome_lower; } world; -static void render_world( m4x4f projection, m4x3f camera ) -{ - render_sky( camera ); - - m4x3f identity_matrix; - m4x3_identity( identity_matrix ); +vg_tex2d tex_terrain_colours = { .path = "textures/gradients.qoi", + .flags = VG_TEXTURE_CLAMP|VG_TEXTURE_NEAREST }; - render_terrain( projection, camera[3] ); - scene_bind( &world.geo ); - scene_draw( &world.geo ); - - glDisable(GL_CULL_FACE); - scene_bind( &world.foliage ); - scene_draw( &world.foliage ); - glEnable(GL_CULL_FACE); - - vg_line_boxf( world.geo.bbx, 0xff00ff00 ); -} +vg_tex2d tex_terrain_noise = { .path = "textures/garbage.qoi", + .flags = VG_TEXTURE_NEAREST }; static void ray_world_get_tri( ray_hit *hit, v3f tri[3] ) { @@ -68,9 +67,29 @@ static int ray_hit_is_ramp( ray_hit *hit ) return hit->tri[0] < world.sm_road.vertex_count; } +static void world_register(void) +{ + shader_terrain_register(); + shader_sky_register(); + shader_planeinf_register(); + shader_gpos_register(); + shader_fscolour_register(); +} + +static void world_free(void) +{ + /* TODO.. */ +} + +static void render_world_depth( m4x4f projection, m4x3f camera ); static void world_load(void) { - /* Setup scene */ + /* + * Setup scene + * + * TODO: Call world_free when its ready here + * + */ scene_init( &world.geo ); model *mworld = vg_asset_read( "models/mp_dev.mdl" ); @@ -81,6 +100,17 @@ static void world_load(void) scene_add_model( &world.geo, mworld, sm, sm->pivot, 0.0f, 1.0f ); } + for( int i=0; ilayer_count; i++ ) + { + submodel *sm = model_get_submodel( mworld, i ); + if( !strcmp( sm->material, "vertex_blend" ) ) + { + m4x3f transform; + q_m3x3( sm->q, transform ); + v3_copy( sm->pivot, transform[3] ); + scene_add_foliage( &world.geo, mworld, sm, transform ); + } + } scene_copy_slice( &world.geo, &world.sm_road ); for( int i=0; ilayer_count; i++ ) @@ -90,11 +120,8 @@ static void world_load(void) scene_add_model( &world.geo, mworld, sm, sm->pivot, 0.0f, 1.0f ); } - scene_copy_slice( &world.geo, &world.sm_terrain ); - vg_info( "BBX: %.3f %.3f %.3f -> %.3f %.3f %.3f\n", - world.geo.bbx[0][0], world.geo.bbx[0][1], world.geo.bbx[0][2], - world.geo.bbx[1][0], world.geo.bbx[1][1], world.geo.bbx[1][2] ); + scene_copy_slice( &world.geo, &world.sm_terrain ); /* * TODO: Parametric marker import @@ -150,11 +177,9 @@ static void world_load(void) break; } } - - scene_upload( &world.geo ); - scene_bh_create( &world.geo ); - water_compute_depth( world.geo.bbx ); + scene_bh_create( &world.geo ); + scene_upload( &world.geo ); scene_init( &world.foliage ); model *mfoliage = vg_asset_read("models/rs_foliage.mdl"); @@ -171,7 +196,8 @@ static void world_load(void) submodel *sm = model_get_submodel( mworld, i ); if( !strcmp( sm->material, "surf" ) || !strcmp( sm->material, "terrain" ) || - !strcmp( sm->material, "water" ) ) + !strcmp( sm->material, "water" ) || + !strcmp( sm->material, "vertex_blend") ) continue; m4x3f transform; @@ -188,8 +214,6 @@ static void world_load(void) rb_update_transform( rb ); } - free( mworld ); - v3f volume; v3_sub( world.geo.bbx[1], world.geo.bbx[0], volume ); volume[1] = 1.0f; @@ -241,8 +265,237 @@ static void world_load(void) free( mfoliage ); scene_upload( &world.foliage ); + + /* Prop layer */ + scene_init( &world.props ); + for( int i=0; ilayer_count; i++ ) + { + submodel *sm = model_get_submodel( mworld, i ); + if( !strcmp( sm->material, "vertex_blend" ) ) + { + m4x3f transform; + q_m3x3( sm->q, transform ); + v3_copy( sm->pivot, transform[3] ); + scene_add_foliage( &world.props, mworld, sm, transform ); + } + } + + scene_upload( &world.props ); + free( mworld ); bh_create( &world.bhcubes, &bh_system_rigidbodies, world.temp_rbs, world.rb_count ); + + /* + * Rendering the depth map + */ + m4x4f ortho; + m4x3f camera; + + v3f extent; + v3_sub( world.geo.bbx[1], world.geo.bbx[0], extent ); + + float fl = world.geo.bbx[0][0], + fr = world.geo.bbx[1][0], + fb = world.geo.bbx[0][2], + ft = world.geo.bbx[1][2], + rl = 1.0f / (fr-fl), + tb = 1.0f / (ft-fb); + + m4x4_zero( ortho ); + ortho[0][0] = 2.0f * rl; + ortho[2][1] = 2.0f * tb; + ortho[3][0] = (fr + fl) * -rl; + ortho[3][1] = (ft + fb) * -tb; + ortho[3][3] = 1.0f; + m4x3_identity( camera ); + + glViewport( 0, 0, 1024, 1024 ); + glDisable(GL_DEPTH_TEST); + glBindFramebuffer( GL_FRAMEBUFFER, gpipeline.fb_depthmap ); + shader_fscolour_use(); + shader_fscolour_uColour( (v4f){-9999.0f,-9999.0f,-9999.0f,-9999.0f} ); + render_fsquad(); + + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + glBlendEquation(GL_MAX); + render_world_depth( ortho, camera ); + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); + + /* + * TODO: World settings entity + */ + struct ub_world_lighting *winfo = &gpipeline.ub_world_lighting; + + v3f sundir = { 0.5f, 0.8f, 0.2f }; + v3_normalize( sundir ); + v3_copy( sundir, winfo->g_directional ); + v3_copy( (v3f){ 1.2f,1.152f,1.08f }, winfo->g_sun_colour ); + v3_copy( (v3f){ 0.15f,0.1f,0.2f }, winfo->g_shadow_colour ); + v4_copy( wrender.plane, winfo->g_water_plane ); + + v4f bounds; + bounds[0] = world.geo.bbx[0][0]; + bounds[1] = world.geo.bbx[0][2]; + bounds[2] = 1.0f/ (world.geo.bbx[1][0]-world.geo.bbx[0][0]); + bounds[3] = 1.0f/ (world.geo.bbx[1][2]-world.geo.bbx[0][2]); + v4_copy( bounds, winfo->g_depth_bounds ); + + winfo->g_water_fog = 0.04f; + render_update_lighting_ub(); +} + +static void world_init(void) +{ + vg_tex2d_init( (vg_tex2d *[]){ &tex_terrain_colours, + &tex_terrain_noise }, 2 ); + + + model *msky = vg_asset_read("models/rs_skydome.mdl"); + model_unpack( msky, &world.skydome ); + + world.dome_lower = *submodel_get( msky, "dome_lower" ); + world.dome_upper = *submodel_get( msky, "dome_upper" ); + + free(msky); +} + +/* + * Rendering + */ + +static void bind_terrain_textures(void) +{ + vg_tex2d_bind( &tex_terrain_noise, 0 ); + vg_tex2d_bind( &tex_terrain_colours, 1 ); +} + +static void render_props( m4x4f projection, v3f camera ) +{ + m4x3f identity_matrix; + m4x3_identity( identity_matrix ); + + shader_vblend_use(); + shader_vblend_uTexGarbage(0); + shader_vblend_uTexGradients(1); + shader_link_standard_ub( _shader_vblend.id, 2 ); + bind_terrain_textures(); + + shader_vblend_uPv( projection ); + shader_vblend_uMdl( identity_matrix ); + shader_vblend_uCamera( camera ); + + scene_bind( &world.props ); + scene_draw( &world.props ); +} + +static void render_terrain( m4x4f projection, v3f camera ) +{ + m4x3f identity_matrix; + m4x3_identity( identity_matrix ); + + shader_terrain_use(); + shader_terrain_uTexGarbage(0); + shader_terrain_uTexGradients(1); + shader_link_standard_ub( _shader_terrain.id, 2 ); + bind_terrain_textures(); + + shader_terrain_uPv( projection ); + shader_terrain_uMdl( identity_matrix ); + shader_terrain_uCamera( camera ); + + scene_bind( &world.geo ); + scene_draw( &world.geo ); + + glDisable(GL_CULL_FACE); + scene_bind( &world.foliage ); + scene_draw( &world.foliage ); + glEnable(GL_CULL_FACE); +} + +static void render_lowerdome( m4x3f camera ) +{ + m4x4f projection, full; + pipeline_projection( projection, 0.4f, 1000.0f ); + + m4x3f inverse; + m3x3_transpose( camera, inverse ); + v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]); + m4x3_expand( inverse, full ); + m4x4_mul( projection, full, full ); + + m4x3f identity_matrix; + m4x3_identity( identity_matrix ); + + shader_planeinf_use(); + shader_planeinf_uMdl(identity_matrix); + shader_planeinf_uPv(full); + shader_planeinf_uCamera(camera[3]); + shader_planeinf_uPlane( (v4f){0.0f,1.0f,0.0f, water_height()} ); + + submodel_draw( &world.dome_lower ); +} + +static void render_sky(m4x3f camera) +{ + m4x4f projection, full; + pipeline_projection( projection, 0.4f, 1000.0f ); + + m4x3f inverse; + m3x3_transpose( camera, inverse ); + v3_copy((v3f){0.0f,0.0f,0.0f}, inverse[3]); + m4x3_expand( inverse, full ); + m4x4_mul( projection, full, full ); + + m4x3f identity_matrix; + m4x3_identity( identity_matrix ); + + shader_sky_use(); + shader_sky_uMdl(identity_matrix); + shader_sky_uPv(full); + shader_sky_uTexGarbage(0); + shader_sky_uTime( vg_time ); + + vg_tex2d_bind( &tex_terrain_noise, 0 ); + + glDepthMask( GL_FALSE ); + glDisable( GL_DEPTH_TEST ); + + mesh_bind( &world.skydome ); + submodel_draw( &world.dome_upper ); + + glEnable( GL_DEPTH_TEST ); + glDepthMask( GL_TRUE ); +} + +static void render_world( m4x4f projection, m4x3f camera ) +{ + render_sky( camera ); + render_terrain( projection, camera[3] ); + /* render props... */ +} + +static void render_world_depth( m4x4f projection, m4x3f camera ) +{ + m4x3f identity_matrix; + m4x3_identity( identity_matrix ); + + shader_gpos_use(); + shader_gpos_uCamera( camera[3] ); + shader_gpos_uPv( projection ); + shader_gpos_uMdl( identity_matrix ); + + scene_bind( &world.geo ); + scene_draw( &world.geo ); + + glDisable(GL_CULL_FACE); + scene_bind( &world.foliage ); + scene_draw( &world.foliage ); + glEnable(GL_CULL_FACE); + + scene_bind( &world.props ); + scene_draw( &world.props ); } #endif /* WORLD_H */