reworked lighting uniforms
authorhgn <hgodden00@gmail.com>
Fri, 8 Jul 2022 18:46:45 +0000 (19:46 +0100)
committerhgn <hgodden00@gmail.com>
Fri, 8 Jul 2022 18:46:45 +0000 (19:46 +0100)
43 files changed:
.gitignore
blender_export.py
bvh.h
lighting.h [new file with mode: 0644]
main.c
render.h
scene.h
shaders/colour.fs [new file with mode: 0644]
shaders/common_world.glsl [new file with mode: 0644]
shaders/fscolour.h [new file with mode: 0644]
shaders/gpos.fs [new file with mode: 0644]
shaders/gpos.h [new file with mode: 0644]
shaders/noise.glsl [new file with mode: 0644]
shaders/planeinf.h
shaders/sky.h
shaders/sway.glsl [new file with mode: 0644]
shaders/terrain.fs
shaders/terrain.h
shaders/vblend.fs [new file with mode: 0644]
shaders/vblend.h [new file with mode: 0644]
shaders/vertex_standard.glsl [new file with mode: 0644]
shaders/vg/blit.fs.glsl [new file with mode: 0644]
shaders/vg/blit.vs.glsl [new file with mode: 0644]
shaders/vg/character.fs.glsl [new file with mode: 0644]
shaders/vg/character.vs.glsl [new file with mode: 0644]
shaders/vg/gate.fs.glsl [new file with mode: 0644]
shaders/vg/gate.vs.glsl [new file with mode: 0644]
shaders/vg/standard.fs.glsl [new file with mode: 0644]
shaders/vg/standard.vs.glsl [new file with mode: 0644]
shaders/vg/terrain.fs.glsl [new file with mode: 0644]
shaders/vg/terrain.vs.glsl [new file with mode: 0644]
shaders/vg/unlit.fs.glsl [new file with mode: 0644]
shaders/vg/water.fs.glsl [new file with mode: 0644]
shaders/vg/water.vs.glsl [new file with mode: 0644]
shaders/water.fs
shaders/water.h
shaders/water.vs
shaders/water_ref.glsl [new file with mode: 0644]
terrain.h
textures/gradients.png
vg.conf
water.h
world.h

index c4001642301cb5590fc49db1b60b6a680821e34a..31dfd3c13a3573183bec94f765da609ff2d6edec 100755 (executable)
@@ -27,6 +27,7 @@ restricted/
 !*.fs
 !*.vs
 !*.gls
+!*.glsl
 
 # Python source files
 !*.py
index a13e84eb4a95b926018528902d7b26c9aee250b2..16b97645b306d758406b4233c8da3ca9b93e0bc3 100644 (file)
@@ -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 a6a7468b7141f6a7c7f13f8cae11725121840b6d..27e23b5af516dd0fc8ae809b7c6844400741cf7d 100644 (file)
--- 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; i<inode->count; i++ )
                buffer[ count ++ ] = inode->start+i;
diff --git a/lighting.h b/lighting.h
new file mode 100644 (file)
index 0000000..8f9bdb3
--- /dev/null
@@ -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; z<gi->pt_dims[2]; z++ )
+   {
+      for( int y=0; y<gi->pt_dims[1]; y++ )
+      {
+         for( int x=0; x<gi->pt_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; i<sc->vertex_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 b80a1a20527f7c2bfd99f5390d93a30ed12122b3..ba6f384ca48debf596103cdfce8fc4c24c3866f0 100644 (file)
--- 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();
 }
index d8bdc95ea21503662a93fc85d06690d5b49299ae..8285317aaf5106f757979b2ca70600e753efecc0 100644 (file)
--- 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 6f7c28cbe63b3ac4a0bfd1e6feed6eab22a45f40..76baf547f77b50e69d6c1881b5b24557e411b766 100644 (file)
--- 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; i<submodel->indice_count; i++ )
diff --git a/shaders/colour.fs b/shaders/colour.fs
new file mode 100644 (file)
index 0000000..7eb290e
--- /dev/null
@@ -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 (file)
index 0000000..329226a
--- /dev/null
@@ -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 (file)
index 0000000..ccef7b0
--- /dev/null
@@ -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 (file)
index 0000000..b21f7a7
--- /dev/null
@@ -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 (file)
index 0000000..6b8d9cb
--- /dev/null
@@ -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 (file)
index 0000000..6736e35
--- /dev/null
@@ -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;
+}
index 0cc17cd2ec95e1e59464994855efeb6414264b79..d2a227a15d5f9801137ac19b511d721530e5167a 100644 (file)
@@ -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"
index 01bc5c2fbce9d26ae0d5ae0a5dfd490c0f5fa106..8e8c2c7ed88c1632bdd993b9e063d7c21d8d3ba0 100644 (file)
@@ -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 (file)
index 0000000..6cd92d0
--- /dev/null
@@ -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;"
+       "}"
index a6d24006fbfdf9a224a5fff0f6c4891e2d6a7ea7..84482af91af1a9fc8b7fd9e5b90f1d04abbe4bda 100644 (file)
@@ -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 );
 }
index 9bbb939439e330b0e1e1b9b1d9447deff45bfd09..ce834d42cd3ba2c8a8f0788a2dd1d29a0e2e05a2 100644 (file)
@@ -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 (file)
index 0000000..690f5c7
--- /dev/null
@@ -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 (file)
index 0000000..26d7a51
--- /dev/null
@@ -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 (file)
index 0000000..0b46d33
--- /dev/null
@@ -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 (file)
index 0000000..b98d5e8
--- /dev/null
@@ -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 (file)
index 0000000..2593725
--- /dev/null
@@ -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 (file)
index 0000000..d3c2bea
--- /dev/null
@@ -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 (file)
index 0000000..7f79f4d
--- /dev/null
@@ -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 (file)
index 0000000..ba48f1e
--- /dev/null
@@ -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 (file)
index 0000000..e33c754
--- /dev/null
@@ -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 (file)
index 0000000..e3f05c8
--- /dev/null
@@ -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 (file)
index 0000000..f755542
--- /dev/null
@@ -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 (file)
index 0000000..7bcdab8
--- /dev/null
@@ -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 (file)
index 0000000..5bb262b
--- /dev/null
@@ -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 (file)
index 0000000..ec4d7ae
--- /dev/null
@@ -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 (file)
index 0000000..b352e39
--- /dev/null
@@ -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 (file)
index 0000000..7751336
--- /dev/null
@@ -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;
+}
index 1de00ecac59ec0c9345e040331f2afc68a734673..0be43893cb803fea710a7c86a7f689f5b4c7163c 100644 (file)
@@ -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
index 995cdb8012adf7b69c119c254c098afa02f04c74..e9c08835bdb4794409a060e3f3beccd2ca96cba9 100644 (file)
@@ -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 */
index a78bf308c9656c2974f72f9f936d1667f3b4752b..6fbee776615a0dae1f21d03f355d4ca4bba80bcd 100644 (file)
@@ -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 (file)
index 0000000..e69de29
index 81b311ac737d64c861d67a67fc6b841e3d8c0bc7..b5e7e5333b555efa6f851699242e6533a977578d 100644 (file)
--- 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
index 201e051be348de5d38248dcb411fd30b101cb852..64f8ae00be155dd101a0be63a45a6b97e299b27e 100644 (file)
Binary files a/textures/gradients.png and b/textures/gradients.png differ
diff --git a/vg.conf b/vg.conf
index 634e451e305ab26ddd8724d5cf7010ec507e8a47..9dce13190957785e34e11d9796d85bd9c08c9a71 100644 (file)
--- 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 ac1db00dbafaf53001728bc6253f70b855a95a49..1de2554abf8e459175a30438cb6146e0f24b09a3 100644 (file)
--- 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 af0507fafc0db0f33b0a4f33e6ba0a10d6b3f9f3..66922cd2604e8f31b726769f245c026977f01353 100644 (file)
--- 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; i<mworld->layer_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; i<mworld->layer_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; i<mworld->layer_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 */