needs a lot of cleaning but lights are OK
authorhgn <hgodden00@gmail.com>
Thu, 2 Mar 2023 02:58:35 +0000 (02:58 +0000)
committerhgn <hgodden00@gmail.com>
Thu, 2 Mar 2023 02:58:35 +0000 (02:58 +0000)
35 files changed:
blender_export.py
common.h
maps_src/mp_gridmap.mdl
maps_src/mp_home.mdl
maps_src/mp_mtzero.mdl
model.h
shaders/blit.h
shaders/blitblur.h
shaders/blitcolour.h
shaders/common_scene.glsl
shaders/common_world.glsl
shaders/light_clearskies.glsl [new file with mode: 0644]
shaders/model_character_view.fs
shaders/model_character_view.h
shaders/model_gate.h
shaders/model_menu.h
shaders/model_sky.fs
shaders/model_sky.h
shaders/model_sky_simple.fs [new file with mode: 0644]
shaders/routeui.h
shaders/scene.vs
shaders/scene_depth.h
shaders/scene_position.h
shaders/scene_route.h
shaders/scene_standard.h
shaders/scene_standard_alphatest.h
shaders/scene_terrain.h
shaders/scene_vertex_blend.h
shaders/scene_water.fs
shaders/scene_water.h
shaders/scene_water_fast.h
world.h
world_gen.h
world_render.h
world_water.h

index ccad7bfcb04d001d45f56c083d8dc2f8b8d6262e..b60b2e02fc8cf14550c3f2ace276c11545c48bec 100644 (file)
@@ -807,22 +807,36 @@ class classtype_audio(Structure):
 
 # Classtype 200
 # 
-#  Purpose: point light
+#  Purpose: world light
 #
-class classtype_point_light(Structure):
+class classtype_world_light( Structure ):
 #{
    _pack_ = 1
-   _fields_ = [("colour",c_float*4)]
+   _fields_ = [("type",c_uint32),
+               ("colour",c_float*4),
+               ("angle",c_float)]
 
    def encode_obj(_, node, node_def):
    #{
       node.classtype = 200
 
-      data = node_def['obj'].data
+      obj  = node_def['obj']
+      data = obj.data
       _.colour[0] = data.color[0]
       _.colour[1] = data.color[1]
       _.colour[2] = data.color[2]
       _.colour[3] = data.energy
+
+      if obj.data.type == 'POINT':
+      #{
+         _.type = 0
+         _.angle = 0.0
+      #}
+      elif obj.data.type == 'SPOT':
+      #{
+         _.type = 1
+         _.angle = math.cos(data.spot_size*0.5)
+      #}
    #}
 
    @staticmethod
@@ -1907,8 +1921,7 @@ def encoder_process_definition( node_def ):
          obj_classtype = 'classtype_skeleton'
       elif obj_type == 'LIGHT':
       #{
-         if obj.data.type == 'POINT':
-            obj_classtype = 'classtype_point_light'
+         obj_classtype = 'classtype_world_light'
       #}
       else:
       #{
index 0621e7caba99232342d78aec4bd628f8190bac2b..c1f325e232f5d9f57b2f41f6cd71fc85d13f88f2 100644 (file)
--- a/common.h
+++ b/common.h
@@ -102,6 +102,9 @@ VG_STATIC float
    k_cam_spring            = 20.0f,
    k_cam_damp              = 6.7f;
 
+VG_STATIC float
+   k_day_length            = 30.0f; /* minutes */
+
 VG_STATIC float k_ragdoll_floatyiness = 20.0f,
                 k_ragdoll_floatydrag  = 1.0f,
                 k_ragdoll_limit_scale = 1.0f;
@@ -111,6 +114,7 @@ VG_STATIC int   k_ragdoll_div = 1,
                 k_ragdoll_debug_collider = 1,
                 k_ragdoll_debug_constraints = 0;
 
+VG_STATIC int   k_debug_light_index = 1;
 
 VG_STATIC int freecam = 0;
 VG_STATIC int walk_grid_iterations = 1;
@@ -119,6 +123,8 @@ VG_STATIC int cl_thirdperson = 0;
 
 VG_STATIC void common_var_temp(void)
 {
+   VG_VAR_F32( k_day_length );
+
    VG_VAR_F32( k_cam_punch );
    VG_VAR_F32( k_cam_damp );
    VG_VAR_F32( k_cam_spring );
index ca0c37a08cd17b4a2a631a0cc7d5570e6086b551..b2cc013a18d3c4f01a85e2e8222448ae0a92d7cc 100644 (file)
Binary files a/maps_src/mp_gridmap.mdl and b/maps_src/mp_gridmap.mdl differ
index 0f9f4d6da5a537d5ff2e189978ad6d335617bec8..d68b2d56cea744d7304d1c619f00c99247ec777b 100644 (file)
Binary files a/maps_src/mp_home.mdl and b/maps_src/mp_home.mdl differ
index f3a6aee96559aa9f4de948db4bdafbbe1d7b91fe..0c4d0ab63588503e051c76626f31b0b8e54bc2a9 100644 (file)
Binary files a/maps_src/mp_mtzero.mdl and b/maps_src/mp_mtzero.mdl differ
diff --git a/model.h b/model.h
index 95d6676e4d8589c512fd86a6a93436651250f28c..b2d258deb282916dfead2dd647893259e39b87ec 100644 (file)
--- a/model.h
+++ b/model.h
@@ -42,7 +42,7 @@ enum classtype
    k_classtype_trigger              = 100,
    k_classtype_logic_achievement    = 101,
    k_classtype_logic_relay          = 102,
-   k_classtype_point_light          = 200,
+   k_classtype_world_light          = 200,
    k_classtype_nonlocal_gate        = 300
 };
 
@@ -271,9 +271,17 @@ struct classtype_audio
    float volume;
 };
 
-struct classtype_point_light
+struct classtype_world_light
 {
+   enum light_type 
+   {
+      k_light_type_point,
+      k_light_type_spot
+   } 
+   type;
+
    v4f colour; /* RGB, Energy */
+   float angle;
 };
 
 #pragma pack(pop)
index 7dcbc772527219c1f0148063b6c7923c69afd644..12a0dcb2c293823f2b21104175ac7252c56b2b34 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_blit = {
    .link = shader_blit_link,
    .vs = 
 {
+.orig_file = "shaders/blit.vs",
 .static_src = 
 "layout (location=0) in vec2 a_co;\n"
 "out vec2 aUv;\n"
@@ -19,6 +20,7 @@ static struct vg_shader _shader_blit = {
 ""},
    .fs = 
 {
+.orig_file = "shaders/blit.fs",
 .static_src = 
 "out vec4 FragColor;\n"
 "uniform sampler2D uTexMain;\n"
index fcea6452f9c195aac35c671f2325ff1b4401d3b9..0eca2cefa1d7278195cc2e3e6aa0d7297208887c 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_blitblur = {
    .link = shader_blitblur_link,
    .vs = 
 {
+.orig_file = "shaders/blit.vs",
 .static_src = 
 "layout (location=0) in vec2 a_co;\n"
 "out vec2 aUv;\n"
@@ -19,6 +20,7 @@ static struct vg_shader _shader_blitblur = {
 ""},
    .fs = 
 {
+.orig_file = "shaders/blitblur.fs",
 .static_src = 
 "out vec4 FragColor;\n"
 "uniform sampler2D uTexMain;\n"
index 68880e3e89e24e862939295d569fcb899f8d5646..3d5dd5ed83c0ea9563b328420b3c9f125a4733da 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_blitcolour = {
    .link = shader_blitcolour_link,
    .vs = 
 {
+.orig_file = "shaders/blit.vs",
 .static_src = 
 "layout (location=0) in vec2 a_co;\n"
 "out vec2 aUv;\n"
@@ -19,6 +20,7 @@ static struct vg_shader _shader_blitcolour = {
 ""},
    .fs = 
 {
+.orig_file = "shaders/colour.fs",
 .static_src = 
 "out vec4 FragColor;\n"
 "uniform vec4 uColour;\n"
index c71f5e2dbb4dbbd3359be1afa933eaaf5ba6f1c3..2cf00b9878d0427d386964f645e99463f0fb60bd 100644 (file)
@@ -4,10 +4,12 @@ in vec2 aUv;
 in vec4 aNorm;
 in vec3 aCo;
 in vec3 aWorldCo;
-flat in vec4 light_colours[3];
-flat in vec4 light_positions[3];
+flat in ivec4 light_indices;
+
+uniform samplerBuffer uLightsArray;
 
 #include "common_world.glsl"
+#include "light_clearskies.glsl"
 
 float sdLine( vec3 p, vec3 a, vec3 b )
 {
@@ -28,47 +30,79 @@ float compute_board_shadow()
    return 1.0 - player_shadow*0.8;
 }
 
+vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )
+{
+   float dist = pow(fdist*0.0010,0.78);
+   return mix( vfrag, colour, min( 1.0, dist ) );
+}
+
 vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )
 {
+   world_info world;
+   scene_state( g_time, world );
+
    // Lighting
    vec3 halfview = uCamera - aWorldCo;
    float fdist = length(halfview);
    halfview /= fdist;
 
-   vec3 total_light = newlight_compute_ambient();
-   
-   // Compute world lighting contribution and apply it according to the
-   // shadow map
-   //
-   vec3 world_light = newlight_compute_world_diffuse( wnormal );
-   world_light += newlight_compute_sun_spec( wnormal, halfview, 0.1 );
+   vec3 total_light = vec3(0.0);
+
 
-   float world_shadow = newlight_compute_sun_shadow();
+   float world_shadow = newlight_compute_sun_shadow( world.sun_dir 
+                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );
    float board_shadow = compute_board_shadow();
 
-   total_light += world_light * min( board_shadow, world_shadow );
+   total_light += scene_lighting( wnormal, min( board_shadow, world_shadow ), 
+                                  halfview, world );
+
+   //total_light += scene_lighting_old( wnormal, world );
 
    // Compute the other lights that exist in the map, not effected by the sun
    // shadow
 
-   total_light += newlight_compute_quadratic
+   // read lights
+   vec4 light_colour_0 = texelFetch( uLightsArray, light_indices.x*3+0 );
+   vec4 light_colour_1 = texelFetch( uLightsArray, light_indices.y*3+0 );
+   vec4 light_colour_2 = texelFetch( uLightsArray, light_indices.z*3+0 );
+   vec4 light_co_0     = texelFetch( uLightsArray, light_indices.x*3+1 );
+   vec4 light_co_1     = texelFetch( uLightsArray, light_indices.y*3+1 );
+   vec4 light_co_2     = texelFetch( uLightsArray, light_indices.z*3+1 );
+   vec4 light_dir_0    = texelFetch( uLightsArray, light_indices.x*3+2 );
+   vec4 light_dir_1    = texelFetch( uLightsArray, light_indices.y*3+2 );
+   vec4 light_dir_2    = texelFetch( uLightsArray, light_indices.z*3+2 );
+
+   //return vec3(fract(distance(light_co_0.xyz,aWorldCo)),
+   //            fract(distance(light_co_1.xyz,aWorldCo)),
+   //            fract(distance(light_co_2.xyz,aWorldCo)));
+
+  // return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),
+  //             fract(light_indices.z * 0.125 ));
+
+   total_light += newlight_compute_spot
                   ( 
                      wnormal, halfview,
-                     light_positions[0].xyz,
-                     light_colours[0].rgb 
+                     light_colour_0.rgb,
+                     light_co_0.xyz,
+                     light_dir_0
                   ) * board_shadow;
-   total_light += newlight_compute_quadratic
+
+   total_light += newlight_compute_spot
                   ( 
                      wnormal, halfview,
-                     light_positions[1].xyz,
-                     light_colours[1].rgb 
+                     light_colour_1.rgb,
+                     light_co_1.xyz,
+                     light_dir_1
                   ) * board_shadow;
-   total_light += newlight_compute_quadratic
+   total_light += newlight_compute_spot
                   ( 
                      wnormal, halfview,
-                     light_positions[2].xyz,
-                     light_colours[2].rgb 
+                     light_colour_2.rgb,
+                     light_co_2.xyz,
+                     light_dir_2
                   ) * board_shadow;
 
-   return apply_fog( diffuse * total_light, fdist );
+   vec3 fog_colour = scene_sky( -halfview, world );
+   
+   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );
 }
index 043cf26898971b270032a2b5ff5bd78c4bacd202..43934098a427d5d5839a2736ed105961f2a136fc 100644 (file)
@@ -9,6 +9,7 @@ layout (std140) uniform ub_world_lighting
    vec4 g_water_plane;
    vec4 g_depth_bounds;
    float g_water_fog;
+   float g_time;
    int g_light_count;
    int g_light_preview;
    int g_shadow_samples;
@@ -57,7 +58,7 @@ vec3 newlight_compute_ambient()
    return g_ambient_colour.rgb;
 }
 
-float newlight_compute_sun_shadow()
+float newlight_compute_sun_shadow( vec3 dir )
 {
    if( g_shadow_samples == 0 )
    {
@@ -65,7 +66,7 @@ float newlight_compute_sun_shadow()
    }
 
    float fspread = g_light_colours[0].w;
-   vec3  vdir = g_light_directions[0].xyz;
+   vec3  vdir = dir;
    float flength = g_light_directions[0].w;
 
    float famt = 0.0;
@@ -107,8 +108,14 @@ vec3 newlight_compute_sun_spec( vec3 wnormal, vec3 halfview, float fintensity )
    return vcolour*spec*fintensity;
 }
 
+float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )
+{
+   vec3 specdir = reflect( -dir, wnormal );
+   return pow(max(dot( halfview, specdir ), 0.0), exponent);
+}
+
 vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, 
-                                 vec3 light_pos, vec3 light_colour )
+                                 vec3 light_colour, vec3 light_pos )
 {
    vec3 light_delta = (light_pos-aWorldCo) * 10.0;
 
@@ -118,3 +125,21 @@ vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview,
 
    return light_colour*attenuation;
 }
+
+vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, 
+                            vec3 light_colour, vec3 light_pos,
+                            vec4 light_dir )
+{
+   vec3 light_delta = (light_pos-aWorldCo) * 10.0;
+
+   float quadratic = dot(light_delta,light_delta);
+   float attenuation = 1.0f/( 1.0f + quadratic );
+
+   light_delta = normalize( light_delta );
+   attenuation *= max( 0.0, dot( light_delta, wnormal ) );
+
+   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),
+            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );
+
+   return light_colour*attenuation*falloff;
+}
diff --git a/shaders/light_clearskies.glsl b/shaders/light_clearskies.glsl
new file mode 100644 (file)
index 0000000..b16cb9e
--- /dev/null
@@ -0,0 +1,144 @@
+const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );
+const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );
+const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );
+const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );
+const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );
+const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;
+
+const float SUN_ANGLE       = 0.0001;
+const float TIME_RATE       = 0.025;
+
+const float PI              = 3.14159265;
+
+struct world_info
+{
+   float time,
+         time_of_day,
+         day_phase,
+         sunset_phase;
+   
+   vec3 sun_dir;
+};
+
+float luminance( vec3 v )
+{
+   return dot( v, vec3(0.2126, 0.7152, 0.0722) );
+}
+
+vec3 scene_ambient( vec3 dir, const world_info w )
+{
+   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;
+   float sky_gradient = dir.y;
+   
+   /* Blend phase colours */
+   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);
+        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;
+        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);
+   
+   /* Add gradient */
+        ambient -= sky_gradient * luminance(ambient);
+        
+   return ambient;
+}
+
+vec3 scene_sky( vec3 ray_dir, const world_info w )
+{
+   ray_dir.y = abs( ray_dir.y );
+   vec3 sky_colour  = scene_ambient( ray_dir, w );
+   
+   /* Sun */
+   float sun_theta  = dot( ray_dir, w.sun_dir );
+   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );
+   float sun_shape  = pow( sun_size, 2000.0 );
+         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;
+         
+   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );
+        sun_colour *= sun_shape;
+   
+   vec3 composite   = sky_colour + sun_colour;
+   return composite;
+}
+
+vec3 scene_compute_ambient( vec3 normal, const world_info w )
+{
+   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );
+}
+
+vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )
+{
+   vec3 dir3 = vec3
+   (
+      cos(dir.y) * cos(dir.x),
+                   sin(dir.x),
+      sin(dir.y) * cos(dir.x)
+   );
+
+   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );
+   
+   return flight * colour;
+}
+
+vec3 scene_lighting_old( vec3 normal, const world_info w )
+{
+   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );
+   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );
+   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );
+   
+   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +
+          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + 
+          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;
+}
+
+vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )
+{
+   float fresnel = 1.0 - abs(dot(normal,halfview));
+
+   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );
+   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR 
+                           * w.day_phase;
+
+   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );
+
+   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );
+
+   return ambient + (light_sun + sky_reflection) * shadow;
+
+
+
+
+
+
+   float  sun_theta = dot( normal, w.sun_dir );
+
+   float  softness_min = 0.5;
+   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);
+   float  light_min    = 0.0 * w.day_phase;
+   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);
+          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;
+   
+   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );
+          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );
+          
+   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);
+   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );
+   
+   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) 
+                            * 0.2 * shadow * w.day_phase;
+   
+   return mix(dark_colour, light_colour, light_direct) + 
+              spec +
+              dark_colour * light_bounce;
+}
+
+void scene_state( float world_time, out world_info w )
+{
+   w.time         = world_time;
+   w.time_of_day  = fract( w.time );
+   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;
+   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;
+   w.sunset_phase = pow( w.sunset_phase, 6.0 );
+   
+   float a        = w.time_of_day * PI * 2.0;
+   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );
+}
+
index a85e124d8a862947ce3b26f2da13a7f2551459fc..7a3d63ec39651fb22b875ffdc78f2684f39706f7 100644 (file)
@@ -27,7 +27,7 @@ void main()
    vec3 total_light = newlight_compute_ambient();
    vec3 world_light = newlight_compute_world_diffuse( qnorm );
 
-   float world_shadow = newlight_compute_sun_shadow();
+   float world_shadow = newlight_compute_sun_shadow( vec3(1.0) );
    total_light += world_light * world_shadow;
 
    vfrag = apply_fog( vfrag * total_light, fdist );
index 18d5c19062ec5d9afc1b92e55b68d3d1e19ec2e3..68a46679a7b8001f383c465334a4612ffe9a3388 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_model_character_view = {
    .link = shader_model_character_view_link,
    .vs = 
 {
+.orig_file = "shaders/model_skinned.vs",
 .static_src = 
 "layout (location=0) in vec3 a_co;\n"
 "layout (location=1) in vec3 a_norm;\n"
@@ -71,6 +72,7 @@ static struct vg_shader _shader_model_character_view = {
 ""},
    .fs = 
 {
+.orig_file = "shaders/model_character_view.fs",
 .static_src = 
 "uniform sampler2D uTexMain;\n"
 "uniform vec3 uCamera;\n"
@@ -93,6 +95,7 @@ static struct vg_shader _shader_model_character_view = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -141,7 +144,7 @@ static struct vg_shader _shader_model_character_view = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -149,7 +152,7 @@ static struct vg_shader _shader_model_character_view = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -191,8 +194,14 @@ static struct vg_shader _shader_model_character_view = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -203,6 +212,24 @@ static struct vg_shader _shader_model_character_view = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
 "#line     11        0 \n"
 "#line       1        2 \n"
 "const float k_motion_lerp_amount = 0.01;\n"
@@ -242,7 +269,7 @@ static struct vg_shader _shader_model_character_view = {
 "   vec3 total_light = newlight_compute_ambient();\n"
 "   vec3 world_light = newlight_compute_world_diffuse( qnorm );\n"
 "\n"
-"   float world_shadow = newlight_compute_sun_shadow();\n"
+"   float world_shadow = newlight_compute_sun_shadow( vec3(1.0) );\n"
 "   total_light += world_light * world_shadow;\n"
 "\n"
 "   vfrag = apply_fog( vfrag * total_light, fdist );\n"
index e89929d78922dc1a473cbb25e19bf7ed952fa150..013c916a5e9d6a9af0e1aef89ec119541e1d7442 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_model_gate = {
    .link = shader_model_gate_link,
    .vs = 
 {
+.orig_file = "shaders/model_gate.vs",
 .static_src = 
 "layout (location=0) in vec3 a_co;\n"
 "layout (location=1) in vec3 a_norm;\n"
@@ -34,6 +35,7 @@ static struct vg_shader _shader_model_gate = {
 ""},
    .fs = 
 {
+.orig_file = "shaders/model_gate_lq.fs",
 .static_src = 
 "out vec4 FragColor;\n"
 "\n"
index 17623901b94a8ae85a39df98c4f3749b64d90e2f..1d17aa06cae4a10352768d32e89f691012b36d94 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_model_menu = {
    .link = shader_model_menu_link,
    .vs = 
 {
+.orig_file = "shaders/model.vs",
 .static_src = 
 "layout (location=0) in vec3 a_co;\n"
 "layout (location=1) in vec3 a_norm;\n"
@@ -63,6 +64,7 @@ static struct vg_shader _shader_model_menu = {
 ""},
    .fs = 
 {
+.orig_file = "shaders/model_menu.fs",
 .static_src = 
 "out vec4 FragColor;\n"
 "\n"
index e89379944e0c4135285ce8e2c2e1345516e0560f..1439cdd03dae04360176010304c3441962b6f602 100644 (file)
@@ -1,5 +1,4 @@
 uniform sampler2D uTexGarbage;
-uniform float uTime;
 
 in vec4 aColour;
 in vec2 aUv;
@@ -9,38 +8,28 @@ in vec3 aWorldCo;
 
 #include "common_world.glsl"
 #include "motion_vectors_fs.glsl"
+#include "light_clearskies.glsl"
 
 void main()
 {
    compute_motion_vectors();
 
-   vec3 rd = normalize(aNorm);
+   world_info world;
+   scene_state( g_time, world );
 
-   float fintensity = 1.0-(abs(rd.y)*0.7);
-   float fblend = pow(fintensity,4.0);
-   vec3 horizon = vec3( 0.87, 0.93, 0.98 );
-   vec3 skycolour = vec3( 0.16, 0.58, 0.95 ) - rd.y*rd.y*0.5;
-   vec3 diffuse = mix( skycolour, horizon, fblend );
+   vec3 rd = normalize(aNorm);
 
-   float fmove = uTime * 0.004;
-   vec2 cloudplane = (rd.xz / (rd.y*sign(rd.y))) * 0.05;
+   float fmove = g_time * 0.004;
+   vec2 cloudplane = (rd.xz / (rd.y*sign(rd.y))) * 0.025;
    vec4 clouds1 = texture( uTexGarbage, cloudplane + vec2(0.1,0.4)*fmove*2.0 );
    vec4 clouds2 = texture( uTexGarbage, cloudplane*2.0 + vec2(0.3,0.1)*fmove );
 
    float cloud_d = max(clouds1.b*clouds2.r -0.2 - clouds2.g*0.4,0.0);
    float cloud_e = pow(cloud_d,1.5)*pow(abs(rd.y),0.3)*2.0;
 
-   vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 );
-   float fhorizon = step( rd.y * 0.5 + 0.5, 0.5 );
-
-   vec3 skycomp = mix(diffuse, vec3(1.0,1.0,1.0), cloud_e);
-
-
-   float sundot = clamp(dot(rd, -g_light_directions[0].xyz), 0.0, 1.0);
-   vec3 sun = 0.25 * vec3(1.0,0.7,0.4) * pow( sundot,5.0 );
-   sun += 0.25 * vec3(1.0,0.8,0.6) * pow( sundot,64.0 );
-   sun += 0.2 * vec3(1.0,0.8,0.6) * pow( sundot,512.0 );
-   skycomp += sun * g_light_colours[0].rgb;
+   oColour = vec4( scene_sky( -rd, world ) ,1.0);
 
-   oColour = vec4(skycomp,1.0);
+   vec3 cloud_colour    = mix( mix(NIGHTSKY_COLOUR,vec3(1.0),world.day_phase), 
+                                    SUNSET_COLOUR, world.sunset_phase );
+   oColour.rgb = mix( oColour.rgb, cloud_colour, cloud_e );
 }
index 2da4c32a4c8d62b429c153f4dec52336edcc45dc..d1edd1dd50b84aa72e8ce14f16a5008284c5297f 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_model_sky = {
    .link = shader_model_sky_link,
    .vs = 
 {
+.orig_file = "shaders/model.vs",
 .static_src = 
 "layout (location=0) in vec3 a_co;\n"
 "layout (location=1) in vec3 a_norm;\n"
@@ -63,9 +64,9 @@ static struct vg_shader _shader_model_sky = {
 ""},
    .fs = 
 {
+.orig_file = "shaders/model_sky.fs",
 .static_src = 
 "uniform sampler2D uTexGarbage;\n"
-"uniform float uTime;\n"
 "\n"
 "in vec4 aColour;\n"
 "in vec2 aUv;\n"
@@ -85,6 +86,7 @@ static struct vg_shader _shader_model_sky = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -133,7 +135,7 @@ static struct vg_shader _shader_model_sky = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -141,7 +143,7 @@ static struct vg_shader _shader_model_sky = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -183,8 +185,14 @@ static struct vg_shader _shader_model_sky = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -195,7 +203,25 @@ static struct vg_shader _shader_model_sky = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
-"#line     11        0 \n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
+"#line     10        0 \n"
 "#line       1        2 \n"
 "const float k_motion_lerp_amount = 0.01;\n"
 "\n"
@@ -215,41 +241,177 @@ static struct vg_shader _shader_model_sky = {
 "   oMotionVec = (vmotion1-vmotion0) * (1.0/k_motion_lerp_amount);\n"
 "}\n"
 "\n"
+"#line     11        0 \n"
+"#line       1        3 \n"
+"const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float TIME_RATE       = 0.025;\n"
+"\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"struct world_info\n"
+"{\n"
+"   float time,\n"
+"         time_of_day,\n"
+"         day_phase,\n"
+"         sunset_phase;\n"
+"   \n"
+"   vec3 sun_dir;\n"
+"};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 scene_ambient( vec3 dir, const world_info w )\n"
+"{\n"
+"   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);\n"
+"        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;\n"
+"        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 scene_sky( vec3 ray_dir, const world_info w )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = scene_ambient( ray_dir, w );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, w.sun_dir );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_ambient( vec3 normal, const world_info w )\n"
+"{\n"
+"   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );\n"
+"}\n"
+"\n"
+"vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )\n"
+"{\n"
+"   vec3 dir3 = vec3\n"
+"   (\n"
+"      cos(dir.y) * cos(dir.x),\n"
+"                   sin(dir.x),\n"
+"      sin(dir.y) * cos(dir.x)\n"
+"   );\n"
+"\n"
+"   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );\n"
+"   \n"
+"   return flight * colour;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting_old( vec3 normal, const world_info w )\n"
+"{\n"
+"   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );\n"
+"   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );\n"
+"   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );\n"
+"   \n"
+"   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +\n"
+"          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + \n"
+"          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );\n"
+"   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR \n"
+"                           * w.day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );\n"
+"\n"
+"   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"   float  sun_theta = dot( normal, w.sun_dir );\n"
+"\n"
+"   float  softness_min = 0.5;\n"
+"   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);\n"
+"   float  light_min    = 0.0 * w.day_phase;\n"
+"   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);\n"
+"          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;\n"
+"   \n"
+"   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );\n"
+"          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );\n"
+"          \n"
+"   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);\n"
+"   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"   \n"
+"   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) \n"
+"                            * 0.2 * shadow * w.day_phase;\n"
+"   \n"
+"   return mix(dark_colour, light_colour, light_direct) + \n"
+"              spec +\n"
+"              dark_colour * light_bounce;\n"
+"}\n"
+"\n"
+"void scene_state( float world_time, out world_info w )\n"
+"{\n"
+"   w.time         = world_time;\n"
+"   w.time_of_day  = fract( w.time );\n"
+"   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;\n"
+"   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;\n"
+"   w.sunset_phase = pow( w.sunset_phase, 6.0 );\n"
+"   \n"
+"   float a        = w.time_of_day * PI * 2.0;\n"
+"   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );\n"
+"}\n"
+"\n"
+"\n"
 "#line     12        0 \n"
 "\n"
 "void main()\n"
 "{\n"
 "   compute_motion_vectors();\n"
 "\n"
-"   vec3 rd = normalize(aNorm);\n"
+"   world_info world;\n"
+"   scene_state( g_time, world );\n"
 "\n"
-"   float fintensity = 1.0-(abs(rd.y)*0.7);\n"
-"   float fblend = pow(fintensity,4.0);\n"
-"   vec3 horizon = vec3( 0.87, 0.93, 0.98 );\n"
-"   vec3 skycolour = vec3( 0.16, 0.58, 0.95 ) - rd.y*rd.y*0.5;\n"
-"   vec3 diffuse = mix( skycolour, horizon, fblend );\n"
+"   vec3 rd = normalize(aNorm);\n"
 "\n"
-"   float fmove = uTime * 0.004;\n"
-"   vec2 cloudplane = (rd.xz / (rd.y*sign(rd.y))) * 0.05;\n"
+"   float fmove = g_time * 0.004;\n"
+"   vec2 cloudplane = (rd.xz / (rd.y*sign(rd.y))) * 0.025;\n"
 "   vec4 clouds1 = texture( uTexGarbage, cloudplane + vec2(0.1,0.4)*fmove*2.0 );\n"
 "   vec4 clouds2 = texture( uTexGarbage, cloudplane*2.0 + vec2(0.3,0.1)*fmove );\n"
 "\n"
 "   float cloud_d = max(clouds1.b*clouds2.r -0.2 - clouds2.g*0.4,0.0);\n"
 "   float cloud_e = pow(cloud_d,1.5)*pow(abs(rd.y),0.3)*2.0;\n"
 "\n"
-"   vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 );\n"
-"   float fhorizon = step( rd.y * 0.5 + 0.5, 0.5 );\n"
-"\n"
-"   vec3 skycomp = mix(diffuse, vec3(1.0,1.0,1.0), cloud_e);\n"
+"   oColour = vec4( scene_sky( -rd, world ) ,1.0);\n"
 "\n"
-"\n"
-"   float sundot = clamp(dot(rd, -g_light_directions[0].xyz), 0.0, 1.0);\n"
-"   vec3 sun = 0.25 * vec3(1.0,0.7,0.4) * pow( sundot,5.0 );\n"
-"   sun += 0.25 * vec3(1.0,0.8,0.6) * pow( sundot,64.0 );\n"
-"   sun += 0.2 * vec3(1.0,0.8,0.6) * pow( sundot,512.0 );\n"
-"   skycomp += sun * g_light_colours[0].rgb;\n"
-"\n"
-"   oColour = vec4(skycomp,1.0);\n"
+"   vec3 cloud_colour    = mix( mix(NIGHTSKY_COLOUR,vec3(1.0),world.day_phase), \n"
+"                                    SUNSET_COLOUR, world.sunset_phase );\n"
+"   oColour.rgb = mix( oColour.rgb, cloud_colour, cloud_e );\n"
 "}\n"
 ""},
 };
@@ -258,7 +420,6 @@ static GLuint _uniform_model_sky_uMdl;
 static GLuint _uniform_model_sky_uPv;
 static GLuint _uniform_model_sky_uPvmPrev;
 static GLuint _uniform_model_sky_uTexGarbage;
-static GLuint _uniform_model_sky_uTime;
 static GLuint _uniform_model_sky_g_world_depth;
 static void shader_model_sky_uMdl(m4x3f m){
    glUniformMatrix4x3fv(_uniform_model_sky_uMdl,1,GL_FALSE,(float*)m);
@@ -272,9 +433,6 @@ static void shader_model_sky_uPvmPrev(m4x4f m){
 static void shader_model_sky_uTexGarbage(int i){
    glUniform1i(_uniform_model_sky_uTexGarbage,i);
 }
-static void shader_model_sky_uTime(float f){
-   glUniform1f(_uniform_model_sky_uTime,f);
-}
 static void shader_model_sky_g_world_depth(int i){
    glUniform1i(_uniform_model_sky_g_world_depth,i);
 }
@@ -287,7 +445,6 @@ static void shader_model_sky_link(void){
    _uniform_model_sky_uPv = glGetUniformLocation( _shader_model_sky.id, "uPv" );
    _uniform_model_sky_uPvmPrev = glGetUniformLocation( _shader_model_sky.id, "uPvmPrev" );
    _uniform_model_sky_uTexGarbage = glGetUniformLocation( _shader_model_sky.id, "uTexGarbage" );
-   _uniform_model_sky_uTime = glGetUniformLocation( _shader_model_sky.id, "uTime" );
    _uniform_model_sky_g_world_depth = glGetUniformLocation( _shader_model_sky.id, "g_world_depth" );
 }
 #endif /* SHADER_model_sky_H */
diff --git a/shaders/model_sky_simple.fs b/shaders/model_sky_simple.fs
new file mode 100644 (file)
index 0000000..e893799
--- /dev/null
@@ -0,0 +1,46 @@
+uniform sampler2D uTexGarbage;
+uniform float uTime;
+
+in vec4 aColour;
+in vec2 aUv;
+in vec3 aNorm;
+in vec3 aCo;
+in vec3 aWorldCo;
+
+#include "common_world.glsl"
+#include "motion_vectors_fs.glsl"
+
+void main()
+{
+   compute_motion_vectors();
+
+   vec3 rd = normalize(aNorm);
+
+   float fintensity = 1.0-(abs(rd.y)*0.7);
+   float fblend = pow(fintensity,4.0);
+   vec3 horizon = vec3( 0.87, 0.93, 0.98 );
+   vec3 skycolour = vec3( 0.16, 0.58, 0.95 ) - rd.y*rd.y*0.5;
+   vec3 diffuse = mix( skycolour, horizon, fblend );
+
+   float fmove = uTime * 0.004;
+   vec2 cloudplane = (rd.xz / (rd.y*sign(rd.y))) * 0.05;
+   vec4 clouds1 = texture( uTexGarbage, cloudplane + vec2(0.1,0.4)*fmove*2.0 );
+   vec4 clouds2 = texture( uTexGarbage, cloudplane*2.0 + vec2(0.3,0.1)*fmove );
+
+   float cloud_d = max(clouds1.b*clouds2.r -0.2 - clouds2.g*0.4,0.0);
+   float cloud_e = pow(cloud_d,1.5)*pow(abs(rd.y),0.3)*2.0;
+
+   vec3 colour_ocean = vec3( 0.61, 0.84, 0.9 );
+   float fhorizon = step( rd.y * 0.5 + 0.5, 0.5 );
+
+   vec3 skycomp = mix(diffuse, vec3(1.0,1.0,1.0), cloud_e);
+
+
+   float sundot = clamp(dot(rd, -g_light_directions[0].xyz), 0.0, 1.0);
+   vec3 sun = 0.25 * vec3(1.0,0.7,0.4) * pow( sundot,5.0 );
+   sun += 0.25 * vec3(1.0,0.8,0.6) * pow( sundot,64.0 );
+   sun += 0.2 * vec3(1.0,0.8,0.6) * pow( sundot,512.0 );
+   skycomp += sun * g_light_colours[0].rgb;
+
+   oColour = vec4(skycomp,1.0);
+}
index 00d54fc0329b3a0e29c7d7b8ef36791e147ec0f6..9e571aba42ede7dcb32a8a6c7d06dc8bbf45d9e9 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_routeui = {
    .link = shader_routeui_link,
    .vs = 
 {
+.orig_file = "shaders/routeui.vs",
 .static_src = 
 "layout (location=0) in vec2 a_co;\n"
 "\n"
@@ -20,6 +21,7 @@ static struct vg_shader _shader_routeui = {
 ""},
    .fs = 
 {
+.orig_file = "shaders/routeui.fs",
 .static_src = 
 "out vec4 FragColor;\n"
 "\n"
index 34ec16b235fd96d934ff6f39064b69b8a07edc3e..d352d35548de6c2b8851e49702e8f79989077597 100644 (file)
@@ -8,14 +8,13 @@ layout (location=3) in ivec4 a_lights;
 uniform mat4x3 uMdl;
 uniform mat4   uPv;
 uniform mat4   uPvmPrev;
-uniform samplerBuffer uLightsArray;
 
 out vec2 aUv;
 out vec4 aNorm;
 out vec3 aCo;
 out vec3 aWorldCo;
-flat out vec4 light_colours[3];
-flat out vec4 light_positions[3];
+
+flat out ivec4 light_indices;
 
 void main()
 {
@@ -32,11 +31,5 @@ void main()
    aCo = a_co;
    aWorldCo = world_pos0;
 
-   // read lights
-   light_colours[0] = texelFetch( uLightsArray, a_lights.x*2+0 );
-   light_colours[1] = texelFetch( uLightsArray, a_lights.y*2+0 );
-   light_colours[2] = texelFetch( uLightsArray, a_lights.z*2+0 );
-   light_positions[0] = texelFetch( uLightsArray, a_lights.x*2+1 );
-   light_positions[1] = texelFetch( uLightsArray, a_lights.y*2+1 );
-   light_positions[2] = texelFetch( uLightsArray, a_lights.z*2+1 );
+   light_indices = a_lights;
 }
index 462833273f060fa21be4beefa20e4b7ab80f4472..63ff70263a051731d2f9b292992a0ff31884cd4c 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_scene_depth = {
    .link = shader_scene_depth_link,
    .vs = 
 {
+.orig_file = "shaders/scene.vs",
 .static_src = 
 "layout (location=0) in vec3  a_co;\n"
 "layout (location=1) in vec4  a_norm;\n"
@@ -36,14 +37,13 @@ static struct vg_shader _shader_scene_depth = {
 "uniform mat4x3 uMdl;\n"
 "uniform mat4   uPv;\n"
 "uniform mat4   uPvmPrev;\n"
-"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "out vec2 aUv;\n"
 "out vec4 aNorm;\n"
 "out vec3 aCo;\n"
 "out vec3 aWorldCo;\n"
-"flat out vec4 light_colours[3];\n"
-"flat out vec4 light_positions[3];\n"
+"\n"
+"flat out ivec4 light_indices;\n"
 "\n"
 "void main()\n"
 "{\n"
@@ -60,17 +60,12 @@ static struct vg_shader _shader_scene_depth = {
 "   aCo = a_co;\n"
 "   aWorldCo = world_pos0;\n"
 "\n"
-"   // read lights\n"
-"   light_colours[0] = texelFetch( uLightsArray, a_lights.x*2+0 );\n"
-"   light_colours[1] = texelFetch( uLightsArray, a_lights.y*2+0 );\n"
-"   light_colours[2] = texelFetch( uLightsArray, a_lights.z*2+0 );\n"
-"   light_positions[0] = texelFetch( uLightsArray, a_lights.x*2+1 );\n"
-"   light_positions[1] = texelFetch( uLightsArray, a_lights.y*2+1 );\n"
-"   light_positions[2] = texelFetch( uLightsArray, a_lights.z*2+1 );\n"
+"   light_indices = a_lights;\n"
 "}\n"
 ""},
    .fs = 
 {
+.orig_file = "shaders/scene_depth.fs",
 .static_src = 
 "out vec4 FragColor;\n"
 "\n"
@@ -85,8 +80,9 @@ static struct vg_shader _shader_scene_depth = {
 "in vec4 aNorm;\n"
 "in vec3 aCo;\n"
 "in vec3 aWorldCo;\n"
-"flat in vec4 light_colours[3];\n"
-"flat in vec4 light_positions[3];\n"
+"flat in ivec4 light_indices;\n"
+"\n"
+"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
@@ -100,6 +96,7 @@ static struct vg_shader _shader_scene_depth = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -148,7 +145,7 @@ static struct vg_shader _shader_scene_depth = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -156,7 +153,7 @@ static struct vg_shader _shader_scene_depth = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -198,8 +195,14 @@ static struct vg_shader _shader_scene_depth = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -210,7 +213,172 @@ static struct vg_shader _shader_scene_depth = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
-"#line     11        0 \n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        2 \n"
+"const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float TIME_RATE       = 0.025;\n"
+"\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"struct world_info\n"
+"{\n"
+"   float time,\n"
+"         time_of_day,\n"
+"         day_phase,\n"
+"         sunset_phase;\n"
+"   \n"
+"   vec3 sun_dir;\n"
+"};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 scene_ambient( vec3 dir, const world_info w )\n"
+"{\n"
+"   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);\n"
+"        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;\n"
+"        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 scene_sky( vec3 ray_dir, const world_info w )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = scene_ambient( ray_dir, w );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, w.sun_dir );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_ambient( vec3 normal, const world_info w )\n"
+"{\n"
+"   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );\n"
+"}\n"
+"\n"
+"vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )\n"
+"{\n"
+"   vec3 dir3 = vec3\n"
+"   (\n"
+"      cos(dir.y) * cos(dir.x),\n"
+"                   sin(dir.x),\n"
+"      sin(dir.y) * cos(dir.x)\n"
+"   );\n"
+"\n"
+"   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );\n"
+"   \n"
+"   return flight * colour;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting_old( vec3 normal, const world_info w )\n"
+"{\n"
+"   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );\n"
+"   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );\n"
+"   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );\n"
+"   \n"
+"   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +\n"
+"          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + \n"
+"          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );\n"
+"   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR \n"
+"                           * w.day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );\n"
+"\n"
+"   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"   float  sun_theta = dot( normal, w.sun_dir );\n"
+"\n"
+"   float  softness_min = 0.5;\n"
+"   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);\n"
+"   float  light_min    = 0.0 * w.day_phase;\n"
+"   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);\n"
+"          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;\n"
+"   \n"
+"   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );\n"
+"          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );\n"
+"          \n"
+"   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);\n"
+"   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"   \n"
+"   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) \n"
+"                            * 0.2 * shadow * w.day_phase;\n"
+"   \n"
+"   return mix(dark_colour, light_colour, light_direct) + \n"
+"              spec +\n"
+"              dark_colour * light_bounce;\n"
+"}\n"
+"\n"
+"void scene_state( float world_time, out world_info w )\n"
+"{\n"
+"   w.time         = world_time;\n"
+"   w.time_of_day  = fract( w.time );\n"
+"   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;\n"
+"   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;\n"
+"   w.sunset_phase = pow( w.sunset_phase, 6.0 );\n"
+"   \n"
+"   float a        = w.time_of_day * PI * 2.0;\n"
+"   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );\n"
+"}\n"
+"\n"
+"\n"
+"#line     13        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -231,49 +399,81 @@ static struct vg_shader _shader_scene_depth = {
 "   return 1.0 - player_shadow*0.8;\n"
 "}\n"
 "\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
+"   world_info world;\n"
+"   scene_state( g_time, world );\n"
+"\n"
 "   // Lighting\n"
 "   vec3 halfview = uCamera - aWorldCo;\n"
 "   float fdist = length(halfview);\n"
 "   halfview /= fdist;\n"
 "\n"
-"   vec3 total_light = newlight_compute_ambient();\n"
-"   \n"
-"   // Compute world lighting contribution and apply it according to the\n"
-"   // shadow map\n"
-"   //\n"
-"   vec3 world_light = newlight_compute_world_diffuse( wnormal );\n"
-"   world_light += newlight_compute_sun_spec( wnormal, halfview, 0.1 );\n"
+"   vec3 total_light = vec3(0.0);\n"
+"\n"
 "\n"
-"   float world_shadow = newlight_compute_sun_shadow();\n"
+"   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
+"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\n"
-"   total_light += world_light * min( board_shadow, world_shadow );\n"
+"   total_light += scene_lighting( wnormal, min( board_shadow, world_shadow ), \n"
+"                                  halfview, world );\n"
+"\n"
+"   //total_light += scene_lighting_old( wnormal, world );\n"
 "\n"
 "   // Compute the other lights that exist in the map, not effected by the sun\n"
 "   // shadow\n"
 "\n"
-"   total_light += newlight_compute_quadratic\n"
+"   // read lights\n"
+"   vec4 light_colour_0 = texelFetch( uLightsArray, light_indices.x*3+0 );\n"
+"   vec4 light_colour_1 = texelFetch( uLightsArray, light_indices.y*3+0 );\n"
+"   vec4 light_colour_2 = texelFetch( uLightsArray, light_indices.z*3+0 );\n"
+"   vec4 light_co_0     = texelFetch( uLightsArray, light_indices.x*3+1 );\n"
+"   vec4 light_co_1     = texelFetch( uLightsArray, light_indices.y*3+1 );\n"
+"   vec4 light_co_2     = texelFetch( uLightsArray, light_indices.z*3+1 );\n"
+"   vec4 light_dir_0    = texelFetch( uLightsArray, light_indices.x*3+2 );\n"
+"   vec4 light_dir_1    = texelFetch( uLightsArray, light_indices.y*3+2 );\n"
+"   vec4 light_dir_2    = texelFetch( uLightsArray, light_indices.z*3+2 );\n"
+"\n"
+"   //return vec3(fract(distance(light_co_0.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_1.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_2.xyz,aWorldCo)));\n"
+"\n"
+"  // return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
+"  //             fract(light_indices.z * 0.125 ));\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[0].xyz,\n"
-"                     light_colours[0].rgb \n"
+"                     light_colour_0.rgb,\n"
+"                     light_co_0.xyz,\n"
+"                     light_dir_0\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[1].xyz,\n"
-"                     light_colours[1].rgb \n"
+"                     light_colour_1.rgb,\n"
+"                     light_co_1.xyz,\n"
+"                     light_dir_1\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[2].xyz,\n"
-"                     light_colours[2].rgb \n"
+"                     light_colour_2.rgb,\n"
+"                     light_co_2.xyz,\n"
+"                     light_dir_2\n"
 "                  ) * board_shadow;\n"
 "\n"
-"   return apply_fog( diffuse * total_light, fdist );\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   \n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
 "#line      8        0 \n"
@@ -303,10 +503,10 @@ static struct vg_shader _shader_scene_depth = {
 static GLuint _uniform_scene_depth_uMdl;
 static GLuint _uniform_scene_depth_uPv;
 static GLuint _uniform_scene_depth_uPvmPrev;
-static GLuint _uniform_scene_depth_uLightsArray;
 static GLuint _uniform_scene_depth_uCamera;
 static GLuint _uniform_scene_depth_uBoard0;
 static GLuint _uniform_scene_depth_uBoard1;
+static GLuint _uniform_scene_depth_uLightsArray;
 static GLuint _uniform_scene_depth_g_world_depth;
 static void shader_scene_depth_uMdl(m4x3f m){
    glUniformMatrix4x3fv(_uniform_scene_depth_uMdl,1,GL_FALSE,(float*)m);
@@ -337,10 +537,10 @@ static void shader_scene_depth_link(void){
    _uniform_scene_depth_uMdl = glGetUniformLocation( _shader_scene_depth.id, "uMdl" );
    _uniform_scene_depth_uPv = glGetUniformLocation( _shader_scene_depth.id, "uPv" );
    _uniform_scene_depth_uPvmPrev = glGetUniformLocation( _shader_scene_depth.id, "uPvmPrev" );
-   _uniform_scene_depth_uLightsArray = glGetUniformLocation( _shader_scene_depth.id, "uLightsArray" );
    _uniform_scene_depth_uCamera = glGetUniformLocation( _shader_scene_depth.id, "uCamera" );
    _uniform_scene_depth_uBoard0 = glGetUniformLocation( _shader_scene_depth.id, "uBoard0" );
    _uniform_scene_depth_uBoard1 = glGetUniformLocation( _shader_scene_depth.id, "uBoard1" );
+   _uniform_scene_depth_uLightsArray = glGetUniformLocation( _shader_scene_depth.id, "uLightsArray" );
    _uniform_scene_depth_g_world_depth = glGetUniformLocation( _shader_scene_depth.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_depth_H */
index 895b03bd97e6a4f914244691e2118898667a8f72..5fed74774106ddcad531ee499cb0340b3bfd3640 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_scene_position = {
    .link = shader_scene_position_link,
    .vs = 
 {
+.orig_file = "shaders/scene.vs",
 .static_src = 
 "layout (location=0) in vec3  a_co;\n"
 "layout (location=1) in vec4  a_norm;\n"
@@ -36,14 +37,13 @@ static struct vg_shader _shader_scene_position = {
 "uniform mat4x3 uMdl;\n"
 "uniform mat4   uPv;\n"
 "uniform mat4   uPvmPrev;\n"
-"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "out vec2 aUv;\n"
 "out vec4 aNorm;\n"
 "out vec3 aCo;\n"
 "out vec3 aWorldCo;\n"
-"flat out vec4 light_colours[3];\n"
-"flat out vec4 light_positions[3];\n"
+"\n"
+"flat out ivec4 light_indices;\n"
 "\n"
 "void main()\n"
 "{\n"
@@ -60,17 +60,12 @@ static struct vg_shader _shader_scene_position = {
 "   aCo = a_co;\n"
 "   aWorldCo = world_pos0;\n"
 "\n"
-"   // read lights\n"
-"   light_colours[0] = texelFetch( uLightsArray, a_lights.x*2+0 );\n"
-"   light_colours[1] = texelFetch( uLightsArray, a_lights.y*2+0 );\n"
-"   light_colours[2] = texelFetch( uLightsArray, a_lights.z*2+0 );\n"
-"   light_positions[0] = texelFetch( uLightsArray, a_lights.x*2+1 );\n"
-"   light_positions[1] = texelFetch( uLightsArray, a_lights.y*2+1 );\n"
-"   light_positions[2] = texelFetch( uLightsArray, a_lights.z*2+1 );\n"
+"   light_indices = a_lights;\n"
 "}\n"
 ""},
    .fs = 
 {
+.orig_file = "shaders/scene_position.fs",
 .static_src = 
 "out vec4 FragColor;\n"
 "\n"
@@ -85,8 +80,9 @@ static struct vg_shader _shader_scene_position = {
 "in vec4 aNorm;\n"
 "in vec3 aCo;\n"
 "in vec3 aWorldCo;\n"
-"flat in vec4 light_colours[3];\n"
-"flat in vec4 light_positions[3];\n"
+"flat in ivec4 light_indices;\n"
+"\n"
+"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
@@ -100,6 +96,7 @@ static struct vg_shader _shader_scene_position = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -148,7 +145,7 @@ static struct vg_shader _shader_scene_position = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -156,7 +153,7 @@ static struct vg_shader _shader_scene_position = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -198,8 +195,14 @@ static struct vg_shader _shader_scene_position = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -210,7 +213,172 @@ static struct vg_shader _shader_scene_position = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
-"#line     11        0 \n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        2 \n"
+"const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float TIME_RATE       = 0.025;\n"
+"\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"struct world_info\n"
+"{\n"
+"   float time,\n"
+"         time_of_day,\n"
+"         day_phase,\n"
+"         sunset_phase;\n"
+"   \n"
+"   vec3 sun_dir;\n"
+"};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 scene_ambient( vec3 dir, const world_info w )\n"
+"{\n"
+"   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);\n"
+"        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;\n"
+"        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 scene_sky( vec3 ray_dir, const world_info w )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = scene_ambient( ray_dir, w );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, w.sun_dir );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_ambient( vec3 normal, const world_info w )\n"
+"{\n"
+"   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );\n"
+"}\n"
+"\n"
+"vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )\n"
+"{\n"
+"   vec3 dir3 = vec3\n"
+"   (\n"
+"      cos(dir.y) * cos(dir.x),\n"
+"                   sin(dir.x),\n"
+"      sin(dir.y) * cos(dir.x)\n"
+"   );\n"
+"\n"
+"   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );\n"
+"   \n"
+"   return flight * colour;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting_old( vec3 normal, const world_info w )\n"
+"{\n"
+"   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );\n"
+"   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );\n"
+"   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );\n"
+"   \n"
+"   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +\n"
+"          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + \n"
+"          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );\n"
+"   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR \n"
+"                           * w.day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );\n"
+"\n"
+"   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"   float  sun_theta = dot( normal, w.sun_dir );\n"
+"\n"
+"   float  softness_min = 0.5;\n"
+"   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);\n"
+"   float  light_min    = 0.0 * w.day_phase;\n"
+"   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);\n"
+"          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;\n"
+"   \n"
+"   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );\n"
+"          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );\n"
+"          \n"
+"   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);\n"
+"   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"   \n"
+"   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) \n"
+"                            * 0.2 * shadow * w.day_phase;\n"
+"   \n"
+"   return mix(dark_colour, light_colour, light_direct) + \n"
+"              spec +\n"
+"              dark_colour * light_bounce;\n"
+"}\n"
+"\n"
+"void scene_state( float world_time, out world_info w )\n"
+"{\n"
+"   w.time         = world_time;\n"
+"   w.time_of_day  = fract( w.time );\n"
+"   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;\n"
+"   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;\n"
+"   w.sunset_phase = pow( w.sunset_phase, 6.0 );\n"
+"   \n"
+"   float a        = w.time_of_day * PI * 2.0;\n"
+"   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );\n"
+"}\n"
+"\n"
+"\n"
+"#line     13        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -231,49 +399,81 @@ static struct vg_shader _shader_scene_position = {
 "   return 1.0 - player_shadow*0.8;\n"
 "}\n"
 "\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
+"   world_info world;\n"
+"   scene_state( g_time, world );\n"
+"\n"
 "   // Lighting\n"
 "   vec3 halfview = uCamera - aWorldCo;\n"
 "   float fdist = length(halfview);\n"
 "   halfview /= fdist;\n"
 "\n"
-"   vec3 total_light = newlight_compute_ambient();\n"
-"   \n"
-"   // Compute world lighting contribution and apply it according to the\n"
-"   // shadow map\n"
-"   //\n"
-"   vec3 world_light = newlight_compute_world_diffuse( wnormal );\n"
-"   world_light += newlight_compute_sun_spec( wnormal, halfview, 0.1 );\n"
+"   vec3 total_light = vec3(0.0);\n"
+"\n"
 "\n"
-"   float world_shadow = newlight_compute_sun_shadow();\n"
+"   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
+"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\n"
-"   total_light += world_light * min( board_shadow, world_shadow );\n"
+"   total_light += scene_lighting( wnormal, min( board_shadow, world_shadow ), \n"
+"                                  halfview, world );\n"
+"\n"
+"   //total_light += scene_lighting_old( wnormal, world );\n"
 "\n"
 "   // Compute the other lights that exist in the map, not effected by the sun\n"
 "   // shadow\n"
 "\n"
-"   total_light += newlight_compute_quadratic\n"
+"   // read lights\n"
+"   vec4 light_colour_0 = texelFetch( uLightsArray, light_indices.x*3+0 );\n"
+"   vec4 light_colour_1 = texelFetch( uLightsArray, light_indices.y*3+0 );\n"
+"   vec4 light_colour_2 = texelFetch( uLightsArray, light_indices.z*3+0 );\n"
+"   vec4 light_co_0     = texelFetch( uLightsArray, light_indices.x*3+1 );\n"
+"   vec4 light_co_1     = texelFetch( uLightsArray, light_indices.y*3+1 );\n"
+"   vec4 light_co_2     = texelFetch( uLightsArray, light_indices.z*3+1 );\n"
+"   vec4 light_dir_0    = texelFetch( uLightsArray, light_indices.x*3+2 );\n"
+"   vec4 light_dir_1    = texelFetch( uLightsArray, light_indices.y*3+2 );\n"
+"   vec4 light_dir_2    = texelFetch( uLightsArray, light_indices.z*3+2 );\n"
+"\n"
+"   //return vec3(fract(distance(light_co_0.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_1.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_2.xyz,aWorldCo)));\n"
+"\n"
+"  // return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
+"  //             fract(light_indices.z * 0.125 ));\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[0].xyz,\n"
-"                     light_colours[0].rgb \n"
+"                     light_colour_0.rgb,\n"
+"                     light_co_0.xyz,\n"
+"                     light_dir_0\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[1].xyz,\n"
-"                     light_colours[1].rgb \n"
+"                     light_colour_1.rgb,\n"
+"                     light_co_1.xyz,\n"
+"                     light_dir_1\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[2].xyz,\n"
-"                     light_colours[2].rgb \n"
+"                     light_colour_2.rgb,\n"
+"                     light_co_2.xyz,\n"
+"                     light_dir_2\n"
 "                  ) * board_shadow;\n"
 "\n"
-"   return apply_fog( diffuse * total_light, fdist );\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   \n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
 "#line      8        0 \n"
@@ -294,10 +494,10 @@ static struct vg_shader _shader_scene_position = {
 static GLuint _uniform_scene_position_uMdl;
 static GLuint _uniform_scene_position_uPv;
 static GLuint _uniform_scene_position_uPvmPrev;
-static GLuint _uniform_scene_position_uLightsArray;
 static GLuint _uniform_scene_position_uCamera;
 static GLuint _uniform_scene_position_uBoard0;
 static GLuint _uniform_scene_position_uBoard1;
+static GLuint _uniform_scene_position_uLightsArray;
 static GLuint _uniform_scene_position_g_world_depth;
 static void shader_scene_position_uMdl(m4x3f m){
    glUniformMatrix4x3fv(_uniform_scene_position_uMdl,1,GL_FALSE,(float*)m);
@@ -328,10 +528,10 @@ static void shader_scene_position_link(void){
    _uniform_scene_position_uMdl = glGetUniformLocation( _shader_scene_position.id, "uMdl" );
    _uniform_scene_position_uPv = glGetUniformLocation( _shader_scene_position.id, "uPv" );
    _uniform_scene_position_uPvmPrev = glGetUniformLocation( _shader_scene_position.id, "uPvmPrev" );
-   _uniform_scene_position_uLightsArray = glGetUniformLocation( _shader_scene_position.id, "uLightsArray" );
    _uniform_scene_position_uCamera = glGetUniformLocation( _shader_scene_position.id, "uCamera" );
    _uniform_scene_position_uBoard0 = glGetUniformLocation( _shader_scene_position.id, "uBoard0" );
    _uniform_scene_position_uBoard1 = glGetUniformLocation( _shader_scene_position.id, "uBoard1" );
+   _uniform_scene_position_uLightsArray = glGetUniformLocation( _shader_scene_position.id, "uLightsArray" );
    _uniform_scene_position_g_world_depth = glGetUniformLocation( _shader_scene_position.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_position_H */
index 0de37fca94e8947db05ee060551a391619dc56b2..9d951119c45670b6fb8d4f892e6e88ee8819c0dd 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_scene_route = {
    .link = shader_scene_route_link,
    .vs = 
 {
+.orig_file = "shaders/scene.vs",
 .static_src = 
 "layout (location=0) in vec3  a_co;\n"
 "layout (location=1) in vec4  a_norm;\n"
@@ -36,14 +37,13 @@ static struct vg_shader _shader_scene_route = {
 "uniform mat4x3 uMdl;\n"
 "uniform mat4   uPv;\n"
 "uniform mat4   uPvmPrev;\n"
-"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "out vec2 aUv;\n"
 "out vec4 aNorm;\n"
 "out vec3 aCo;\n"
 "out vec3 aWorldCo;\n"
-"flat out vec4 light_colours[3];\n"
-"flat out vec4 light_positions[3];\n"
+"\n"
+"flat out ivec4 light_indices;\n"
 "\n"
 "void main()\n"
 "{\n"
@@ -60,17 +60,12 @@ static struct vg_shader _shader_scene_route = {
 "   aCo = a_co;\n"
 "   aWorldCo = world_pos0;\n"
 "\n"
-"   // read lights\n"
-"   light_colours[0] = texelFetch( uLightsArray, a_lights.x*2+0 );\n"
-"   light_colours[1] = texelFetch( uLightsArray, a_lights.y*2+0 );\n"
-"   light_colours[2] = texelFetch( uLightsArray, a_lights.z*2+0 );\n"
-"   light_positions[0] = texelFetch( uLightsArray, a_lights.x*2+1 );\n"
-"   light_positions[1] = texelFetch( uLightsArray, a_lights.y*2+1 );\n"
-"   light_positions[2] = texelFetch( uLightsArray, a_lights.z*2+1 );\n"
+"   light_indices = a_lights;\n"
 "}\n"
 ""},
    .fs = 
 {
+.orig_file = "shaders/scene_route.fs",
 .static_src = 
 "uniform sampler2D uTexGarbage;\n"
 "uniform sampler2D uTexGradients;\n"
@@ -86,8 +81,9 @@ static struct vg_shader _shader_scene_route = {
 "in vec4 aNorm;\n"
 "in vec3 aCo;\n"
 "in vec3 aWorldCo;\n"
-"flat in vec4 light_colours[3];\n"
-"flat in vec4 light_positions[3];\n"
+"flat in ivec4 light_indices;\n"
+"\n"
+"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
@@ -101,6 +97,7 @@ static struct vg_shader _shader_scene_route = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -149,7 +146,7 @@ static struct vg_shader _shader_scene_route = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -157,7 +154,7 @@ static struct vg_shader _shader_scene_route = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -199,8 +196,14 @@ static struct vg_shader _shader_scene_route = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -211,7 +214,172 @@ static struct vg_shader _shader_scene_route = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
-"#line     11        0 \n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        2 \n"
+"const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float TIME_RATE       = 0.025;\n"
+"\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"struct world_info\n"
+"{\n"
+"   float time,\n"
+"         time_of_day,\n"
+"         day_phase,\n"
+"         sunset_phase;\n"
+"   \n"
+"   vec3 sun_dir;\n"
+"};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 scene_ambient( vec3 dir, const world_info w )\n"
+"{\n"
+"   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);\n"
+"        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;\n"
+"        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 scene_sky( vec3 ray_dir, const world_info w )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = scene_ambient( ray_dir, w );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, w.sun_dir );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_ambient( vec3 normal, const world_info w )\n"
+"{\n"
+"   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );\n"
+"}\n"
+"\n"
+"vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )\n"
+"{\n"
+"   vec3 dir3 = vec3\n"
+"   (\n"
+"      cos(dir.y) * cos(dir.x),\n"
+"                   sin(dir.x),\n"
+"      sin(dir.y) * cos(dir.x)\n"
+"   );\n"
+"\n"
+"   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );\n"
+"   \n"
+"   return flight * colour;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting_old( vec3 normal, const world_info w )\n"
+"{\n"
+"   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );\n"
+"   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );\n"
+"   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );\n"
+"   \n"
+"   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +\n"
+"          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + \n"
+"          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );\n"
+"   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR \n"
+"                           * w.day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );\n"
+"\n"
+"   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"   float  sun_theta = dot( normal, w.sun_dir );\n"
+"\n"
+"   float  softness_min = 0.5;\n"
+"   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);\n"
+"   float  light_min    = 0.0 * w.day_phase;\n"
+"   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);\n"
+"          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;\n"
+"   \n"
+"   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );\n"
+"          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );\n"
+"          \n"
+"   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);\n"
+"   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"   \n"
+"   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) \n"
+"                            * 0.2 * shadow * w.day_phase;\n"
+"   \n"
+"   return mix(dark_colour, light_colour, light_direct) + \n"
+"              spec +\n"
+"              dark_colour * light_bounce;\n"
+"}\n"
+"\n"
+"void scene_state( float world_time, out world_info w )\n"
+"{\n"
+"   w.time         = world_time;\n"
+"   w.time_of_day  = fract( w.time );\n"
+"   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;\n"
+"   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;\n"
+"   w.sunset_phase = pow( w.sunset_phase, 6.0 );\n"
+"   \n"
+"   float a        = w.time_of_day * PI * 2.0;\n"
+"   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );\n"
+"}\n"
+"\n"
+"\n"
+"#line     13        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -232,49 +400,81 @@ static struct vg_shader _shader_scene_route = {
 "   return 1.0 - player_shadow*0.8;\n"
 "}\n"
 "\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
+"   world_info world;\n"
+"   scene_state( g_time, world );\n"
+"\n"
 "   // Lighting\n"
 "   vec3 halfview = uCamera - aWorldCo;\n"
 "   float fdist = length(halfview);\n"
 "   halfview /= fdist;\n"
 "\n"
-"   vec3 total_light = newlight_compute_ambient();\n"
-"   \n"
-"   // Compute world lighting contribution and apply it according to the\n"
-"   // shadow map\n"
-"   //\n"
-"   vec3 world_light = newlight_compute_world_diffuse( wnormal );\n"
-"   world_light += newlight_compute_sun_spec( wnormal, halfview, 0.1 );\n"
+"   vec3 total_light = vec3(0.0);\n"
+"\n"
 "\n"
-"   float world_shadow = newlight_compute_sun_shadow();\n"
+"   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
+"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\n"
-"   total_light += world_light * min( board_shadow, world_shadow );\n"
+"   total_light += scene_lighting( wnormal, min( board_shadow, world_shadow ), \n"
+"                                  halfview, world );\n"
+"\n"
+"   //total_light += scene_lighting_old( wnormal, world );\n"
 "\n"
 "   // Compute the other lights that exist in the map, not effected by the sun\n"
 "   // shadow\n"
 "\n"
-"   total_light += newlight_compute_quadratic\n"
+"   // read lights\n"
+"   vec4 light_colour_0 = texelFetch( uLightsArray, light_indices.x*3+0 );\n"
+"   vec4 light_colour_1 = texelFetch( uLightsArray, light_indices.y*3+0 );\n"
+"   vec4 light_colour_2 = texelFetch( uLightsArray, light_indices.z*3+0 );\n"
+"   vec4 light_co_0     = texelFetch( uLightsArray, light_indices.x*3+1 );\n"
+"   vec4 light_co_1     = texelFetch( uLightsArray, light_indices.y*3+1 );\n"
+"   vec4 light_co_2     = texelFetch( uLightsArray, light_indices.z*3+1 );\n"
+"   vec4 light_dir_0    = texelFetch( uLightsArray, light_indices.x*3+2 );\n"
+"   vec4 light_dir_1    = texelFetch( uLightsArray, light_indices.y*3+2 );\n"
+"   vec4 light_dir_2    = texelFetch( uLightsArray, light_indices.z*3+2 );\n"
+"\n"
+"   //return vec3(fract(distance(light_co_0.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_1.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_2.xyz,aWorldCo)));\n"
+"\n"
+"  // return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
+"  //             fract(light_indices.z * 0.125 ));\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[0].xyz,\n"
-"                     light_colours[0].rgb \n"
+"                     light_colour_0.rgb,\n"
+"                     light_co_0.xyz,\n"
+"                     light_dir_0\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[1].xyz,\n"
-"                     light_colours[1].rgb \n"
+"                     light_colour_1.rgb,\n"
+"                     light_co_1.xyz,\n"
+"                     light_dir_1\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[2].xyz,\n"
-"                     light_colours[2].rgb \n"
+"                     light_colour_2.rgb,\n"
+"                     light_co_2.xyz,\n"
+"                     light_dir_2\n"
 "                  ) * board_shadow;\n"
 "\n"
-"   return apply_fog( diffuse * total_light, fdist );\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   \n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
 "#line      9        0 \n"
@@ -342,13 +542,13 @@ static struct vg_shader _shader_scene_route = {
 static GLuint _uniform_scene_route_uMdl;
 static GLuint _uniform_scene_route_uPv;
 static GLuint _uniform_scene_route_uPvmPrev;
-static GLuint _uniform_scene_route_uLightsArray;
 static GLuint _uniform_scene_route_uTexGarbage;
 static GLuint _uniform_scene_route_uTexGradients;
 static GLuint _uniform_scene_route_uCamera;
 static GLuint _uniform_scene_route_uColour;
 static GLuint _uniform_scene_route_uBoard0;
 static GLuint _uniform_scene_route_uBoard1;
+static GLuint _uniform_scene_route_uLightsArray;
 static GLuint _uniform_scene_route_g_world_depth;
 static void shader_scene_route_uMdl(m4x3f m){
    glUniformMatrix4x3fv(_uniform_scene_route_uMdl,1,GL_FALSE,(float*)m);
@@ -388,13 +588,13 @@ static void shader_scene_route_link(void){
    _uniform_scene_route_uMdl = glGetUniformLocation( _shader_scene_route.id, "uMdl" );
    _uniform_scene_route_uPv = glGetUniformLocation( _shader_scene_route.id, "uPv" );
    _uniform_scene_route_uPvmPrev = glGetUniformLocation( _shader_scene_route.id, "uPvmPrev" );
-   _uniform_scene_route_uLightsArray = glGetUniformLocation( _shader_scene_route.id, "uLightsArray" );
    _uniform_scene_route_uTexGarbage = glGetUniformLocation( _shader_scene_route.id, "uTexGarbage" );
    _uniform_scene_route_uTexGradients = glGetUniformLocation( _shader_scene_route.id, "uTexGradients" );
    _uniform_scene_route_uCamera = glGetUniformLocation( _shader_scene_route.id, "uCamera" );
    _uniform_scene_route_uColour = glGetUniformLocation( _shader_scene_route.id, "uColour" );
    _uniform_scene_route_uBoard0 = glGetUniformLocation( _shader_scene_route.id, "uBoard0" );
    _uniform_scene_route_uBoard1 = glGetUniformLocation( _shader_scene_route.id, "uBoard1" );
+   _uniform_scene_route_uLightsArray = glGetUniformLocation( _shader_scene_route.id, "uLightsArray" );
    _uniform_scene_route_g_world_depth = glGetUniformLocation( _shader_scene_route.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_route_H */
index d3051bc59610af1885908087534d12c429524336..239a8ad7498f3935b6b18b15d4c0f2d53ca29e8d 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_scene_standard = {
    .link = shader_scene_standard_link,
    .vs = 
 {
+.orig_file = "shaders/scene.vs",
 .static_src = 
 "layout (location=0) in vec3  a_co;\n"
 "layout (location=1) in vec4  a_norm;\n"
@@ -36,14 +37,13 @@ static struct vg_shader _shader_scene_standard = {
 "uniform mat4x3 uMdl;\n"
 "uniform mat4   uPv;\n"
 "uniform mat4   uPvmPrev;\n"
-"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "out vec2 aUv;\n"
 "out vec4 aNorm;\n"
 "out vec3 aCo;\n"
 "out vec3 aWorldCo;\n"
-"flat out vec4 light_colours[3];\n"
-"flat out vec4 light_positions[3];\n"
+"\n"
+"flat out ivec4 light_indices;\n"
 "\n"
 "void main()\n"
 "{\n"
@@ -60,17 +60,12 @@ static struct vg_shader _shader_scene_standard = {
 "   aCo = a_co;\n"
 "   aWorldCo = world_pos0;\n"
 "\n"
-"   // read lights\n"
-"   light_colours[0] = texelFetch( uLightsArray, a_lights.x*2+0 );\n"
-"   light_colours[1] = texelFetch( uLightsArray, a_lights.y*2+0 );\n"
-"   light_colours[2] = texelFetch( uLightsArray, a_lights.z*2+0 );\n"
-"   light_positions[0] = texelFetch( uLightsArray, a_lights.x*2+1 );\n"
-"   light_positions[1] = texelFetch( uLightsArray, a_lights.y*2+1 );\n"
-"   light_positions[2] = texelFetch( uLightsArray, a_lights.z*2+1 );\n"
+"   light_indices = a_lights;\n"
 "}\n"
 ""},
    .fs = 
 {
+.orig_file = "shaders/scene_standard.fs",
 .static_src = 
 "uniform sampler2D uTexGarbage;\n"
 "uniform sampler2D uTexMain;\n"
@@ -86,8 +81,9 @@ static struct vg_shader _shader_scene_standard = {
 "in vec4 aNorm;\n"
 "in vec3 aCo;\n"
 "in vec3 aWorldCo;\n"
-"flat in vec4 light_colours[3];\n"
-"flat in vec4 light_positions[3];\n"
+"flat in ivec4 light_indices;\n"
+"\n"
+"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
@@ -101,6 +97,7 @@ static struct vg_shader _shader_scene_standard = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -149,7 +146,7 @@ static struct vg_shader _shader_scene_standard = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -157,7 +154,7 @@ static struct vg_shader _shader_scene_standard = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -199,8 +196,14 @@ static struct vg_shader _shader_scene_standard = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -211,7 +214,172 @@ static struct vg_shader _shader_scene_standard = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
-"#line     11        0 \n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        2 \n"
+"const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float TIME_RATE       = 0.025;\n"
+"\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"struct world_info\n"
+"{\n"
+"   float time,\n"
+"         time_of_day,\n"
+"         day_phase,\n"
+"         sunset_phase;\n"
+"   \n"
+"   vec3 sun_dir;\n"
+"};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 scene_ambient( vec3 dir, const world_info w )\n"
+"{\n"
+"   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);\n"
+"        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;\n"
+"        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 scene_sky( vec3 ray_dir, const world_info w )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = scene_ambient( ray_dir, w );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, w.sun_dir );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_ambient( vec3 normal, const world_info w )\n"
+"{\n"
+"   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );\n"
+"}\n"
+"\n"
+"vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )\n"
+"{\n"
+"   vec3 dir3 = vec3\n"
+"   (\n"
+"      cos(dir.y) * cos(dir.x),\n"
+"                   sin(dir.x),\n"
+"      sin(dir.y) * cos(dir.x)\n"
+"   );\n"
+"\n"
+"   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );\n"
+"   \n"
+"   return flight * colour;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting_old( vec3 normal, const world_info w )\n"
+"{\n"
+"   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );\n"
+"   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );\n"
+"   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );\n"
+"   \n"
+"   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +\n"
+"          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + \n"
+"          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );\n"
+"   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR \n"
+"                           * w.day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );\n"
+"\n"
+"   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"   float  sun_theta = dot( normal, w.sun_dir );\n"
+"\n"
+"   float  softness_min = 0.5;\n"
+"   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);\n"
+"   float  light_min    = 0.0 * w.day_phase;\n"
+"   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);\n"
+"          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;\n"
+"   \n"
+"   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );\n"
+"          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );\n"
+"          \n"
+"   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);\n"
+"   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"   \n"
+"   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) \n"
+"                            * 0.2 * shadow * w.day_phase;\n"
+"   \n"
+"   return mix(dark_colour, light_colour, light_direct) + \n"
+"              spec +\n"
+"              dark_colour * light_bounce;\n"
+"}\n"
+"\n"
+"void scene_state( float world_time, out world_info w )\n"
+"{\n"
+"   w.time         = world_time;\n"
+"   w.time_of_day  = fract( w.time );\n"
+"   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;\n"
+"   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;\n"
+"   w.sunset_phase = pow( w.sunset_phase, 6.0 );\n"
+"   \n"
+"   float a        = w.time_of_day * PI * 2.0;\n"
+"   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );\n"
+"}\n"
+"\n"
+"\n"
+"#line     13        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -232,49 +400,81 @@ static struct vg_shader _shader_scene_standard = {
 "   return 1.0 - player_shadow*0.8;\n"
 "}\n"
 "\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
+"   world_info world;\n"
+"   scene_state( g_time, world );\n"
+"\n"
 "   // Lighting\n"
 "   vec3 halfview = uCamera - aWorldCo;\n"
 "   float fdist = length(halfview);\n"
 "   halfview /= fdist;\n"
 "\n"
-"   vec3 total_light = newlight_compute_ambient();\n"
-"   \n"
-"   // Compute world lighting contribution and apply it according to the\n"
-"   // shadow map\n"
-"   //\n"
-"   vec3 world_light = newlight_compute_world_diffuse( wnormal );\n"
-"   world_light += newlight_compute_sun_spec( wnormal, halfview, 0.1 );\n"
+"   vec3 total_light = vec3(0.0);\n"
+"\n"
 "\n"
-"   float world_shadow = newlight_compute_sun_shadow();\n"
+"   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
+"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\n"
-"   total_light += world_light * min( board_shadow, world_shadow );\n"
+"   total_light += scene_lighting( wnormal, min( board_shadow, world_shadow ), \n"
+"                                  halfview, world );\n"
+"\n"
+"   //total_light += scene_lighting_old( wnormal, world );\n"
 "\n"
 "   // Compute the other lights that exist in the map, not effected by the sun\n"
 "   // shadow\n"
 "\n"
-"   total_light += newlight_compute_quadratic\n"
+"   // read lights\n"
+"   vec4 light_colour_0 = texelFetch( uLightsArray, light_indices.x*3+0 );\n"
+"   vec4 light_colour_1 = texelFetch( uLightsArray, light_indices.y*3+0 );\n"
+"   vec4 light_colour_2 = texelFetch( uLightsArray, light_indices.z*3+0 );\n"
+"   vec4 light_co_0     = texelFetch( uLightsArray, light_indices.x*3+1 );\n"
+"   vec4 light_co_1     = texelFetch( uLightsArray, light_indices.y*3+1 );\n"
+"   vec4 light_co_2     = texelFetch( uLightsArray, light_indices.z*3+1 );\n"
+"   vec4 light_dir_0    = texelFetch( uLightsArray, light_indices.x*3+2 );\n"
+"   vec4 light_dir_1    = texelFetch( uLightsArray, light_indices.y*3+2 );\n"
+"   vec4 light_dir_2    = texelFetch( uLightsArray, light_indices.z*3+2 );\n"
+"\n"
+"   //return vec3(fract(distance(light_co_0.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_1.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_2.xyz,aWorldCo)));\n"
+"\n"
+"  // return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
+"  //             fract(light_indices.z * 0.125 ));\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[0].xyz,\n"
-"                     light_colours[0].rgb \n"
+"                     light_colour_0.rgb,\n"
+"                     light_co_0.xyz,\n"
+"                     light_dir_0\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[1].xyz,\n"
-"                     light_colours[1].rgb \n"
+"                     light_colour_1.rgb,\n"
+"                     light_co_1.xyz,\n"
+"                     light_dir_1\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[2].xyz,\n"
-"                     light_colours[2].rgb \n"
+"                     light_colour_2.rgb,\n"
+"                     light_co_2.xyz,\n"
+"                     light_dir_2\n"
 "                  ) * board_shadow;\n"
 "\n"
-"   return apply_fog( diffuse * total_light, fdist );\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   \n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
 "#line      9        0 \n"
@@ -323,13 +523,13 @@ static struct vg_shader _shader_scene_standard = {
 static GLuint _uniform_scene_standard_uMdl;
 static GLuint _uniform_scene_standard_uPv;
 static GLuint _uniform_scene_standard_uPvmPrev;
-static GLuint _uniform_scene_standard_uLightsArray;
 static GLuint _uniform_scene_standard_uTexGarbage;
 static GLuint _uniform_scene_standard_uTexMain;
 static GLuint _uniform_scene_standard_uCamera;
 static GLuint _uniform_scene_standard_uPlane;
 static GLuint _uniform_scene_standard_uBoard0;
 static GLuint _uniform_scene_standard_uBoard1;
+static GLuint _uniform_scene_standard_uLightsArray;
 static GLuint _uniform_scene_standard_g_world_depth;
 static void shader_scene_standard_uMdl(m4x3f m){
    glUniformMatrix4x3fv(_uniform_scene_standard_uMdl,1,GL_FALSE,(float*)m);
@@ -369,13 +569,13 @@ static void shader_scene_standard_link(void){
    _uniform_scene_standard_uMdl = glGetUniformLocation( _shader_scene_standard.id, "uMdl" );
    _uniform_scene_standard_uPv = glGetUniformLocation( _shader_scene_standard.id, "uPv" );
    _uniform_scene_standard_uPvmPrev = glGetUniformLocation( _shader_scene_standard.id, "uPvmPrev" );
-   _uniform_scene_standard_uLightsArray = glGetUniformLocation( _shader_scene_standard.id, "uLightsArray" );
    _uniform_scene_standard_uTexGarbage = glGetUniformLocation( _shader_scene_standard.id, "uTexGarbage" );
    _uniform_scene_standard_uTexMain = glGetUniformLocation( _shader_scene_standard.id, "uTexMain" );
    _uniform_scene_standard_uCamera = glGetUniformLocation( _shader_scene_standard.id, "uCamera" );
    _uniform_scene_standard_uPlane = glGetUniformLocation( _shader_scene_standard.id, "uPlane" );
    _uniform_scene_standard_uBoard0 = glGetUniformLocation( _shader_scene_standard.id, "uBoard0" );
    _uniform_scene_standard_uBoard1 = glGetUniformLocation( _shader_scene_standard.id, "uBoard1" );
+   _uniform_scene_standard_uLightsArray = glGetUniformLocation( _shader_scene_standard.id, "uLightsArray" );
    _uniform_scene_standard_g_world_depth = glGetUniformLocation( _shader_scene_standard.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_standard_H */
index 8e7b1b016d0e3fe10b60ccde6bc24c8aebd70c59..c2c479ac1b933c3f64f0ce02433a17433778c2cc 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_scene_standard_alphatest = {
    .link = shader_scene_standard_alphatest_link,
    .vs = 
 {
+.orig_file = "shaders/scene.vs",
 .static_src = 
 "layout (location=0) in vec3  a_co;\n"
 "layout (location=1) in vec4  a_norm;\n"
@@ -36,14 +37,13 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "uniform mat4x3 uMdl;\n"
 "uniform mat4   uPv;\n"
 "uniform mat4   uPvmPrev;\n"
-"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "out vec2 aUv;\n"
 "out vec4 aNorm;\n"
 "out vec3 aCo;\n"
 "out vec3 aWorldCo;\n"
-"flat out vec4 light_colours[3];\n"
-"flat out vec4 light_positions[3];\n"
+"\n"
+"flat out ivec4 light_indices;\n"
 "\n"
 "void main()\n"
 "{\n"
@@ -60,17 +60,12 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   aCo = a_co;\n"
 "   aWorldCo = world_pos0;\n"
 "\n"
-"   // read lights\n"
-"   light_colours[0] = texelFetch( uLightsArray, a_lights.x*2+0 );\n"
-"   light_colours[1] = texelFetch( uLightsArray, a_lights.y*2+0 );\n"
-"   light_colours[2] = texelFetch( uLightsArray, a_lights.z*2+0 );\n"
-"   light_positions[0] = texelFetch( uLightsArray, a_lights.x*2+1 );\n"
-"   light_positions[1] = texelFetch( uLightsArray, a_lights.y*2+1 );\n"
-"   light_positions[2] = texelFetch( uLightsArray, a_lights.z*2+1 );\n"
+"   light_indices = a_lights;\n"
 "}\n"
 ""},
    .fs = 
 {
+.orig_file = "shaders/scene_standard_alphatest.fs",
 .static_src = 
 "uniform sampler2D uTexGarbage;\n"
 "uniform sampler2D uTexMain;\n"
@@ -86,8 +81,9 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "in vec4 aNorm;\n"
 "in vec3 aCo;\n"
 "in vec3 aWorldCo;\n"
-"flat in vec4 light_colours[3];\n"
-"flat in vec4 light_positions[3];\n"
+"flat in ivec4 light_indices;\n"
+"\n"
+"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
@@ -101,6 +97,7 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -149,7 +146,7 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -157,7 +154,7 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -199,8 +196,14 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -211,7 +214,172 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
-"#line     11        0 \n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        2 \n"
+"const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float TIME_RATE       = 0.025;\n"
+"\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"struct world_info\n"
+"{\n"
+"   float time,\n"
+"         time_of_day,\n"
+"         day_phase,\n"
+"         sunset_phase;\n"
+"   \n"
+"   vec3 sun_dir;\n"
+"};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 scene_ambient( vec3 dir, const world_info w )\n"
+"{\n"
+"   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);\n"
+"        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;\n"
+"        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 scene_sky( vec3 ray_dir, const world_info w )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = scene_ambient( ray_dir, w );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, w.sun_dir );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_ambient( vec3 normal, const world_info w )\n"
+"{\n"
+"   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );\n"
+"}\n"
+"\n"
+"vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )\n"
+"{\n"
+"   vec3 dir3 = vec3\n"
+"   (\n"
+"      cos(dir.y) * cos(dir.x),\n"
+"                   sin(dir.x),\n"
+"      sin(dir.y) * cos(dir.x)\n"
+"   );\n"
+"\n"
+"   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );\n"
+"   \n"
+"   return flight * colour;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting_old( vec3 normal, const world_info w )\n"
+"{\n"
+"   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );\n"
+"   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );\n"
+"   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );\n"
+"   \n"
+"   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +\n"
+"          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + \n"
+"          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );\n"
+"   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR \n"
+"                           * w.day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );\n"
+"\n"
+"   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"   float  sun_theta = dot( normal, w.sun_dir );\n"
+"\n"
+"   float  softness_min = 0.5;\n"
+"   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);\n"
+"   float  light_min    = 0.0 * w.day_phase;\n"
+"   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);\n"
+"          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;\n"
+"   \n"
+"   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );\n"
+"          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );\n"
+"          \n"
+"   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);\n"
+"   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"   \n"
+"   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) \n"
+"                            * 0.2 * shadow * w.day_phase;\n"
+"   \n"
+"   return mix(dark_colour, light_colour, light_direct) + \n"
+"              spec +\n"
+"              dark_colour * light_bounce;\n"
+"}\n"
+"\n"
+"void scene_state( float world_time, out world_info w )\n"
+"{\n"
+"   w.time         = world_time;\n"
+"   w.time_of_day  = fract( w.time );\n"
+"   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;\n"
+"   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;\n"
+"   w.sunset_phase = pow( w.sunset_phase, 6.0 );\n"
+"   \n"
+"   float a        = w.time_of_day * PI * 2.0;\n"
+"   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );\n"
+"}\n"
+"\n"
+"\n"
+"#line     13        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -232,49 +400,81 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   return 1.0 - player_shadow*0.8;\n"
 "}\n"
 "\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
+"   world_info world;\n"
+"   scene_state( g_time, world );\n"
+"\n"
 "   // Lighting\n"
 "   vec3 halfview = uCamera - aWorldCo;\n"
 "   float fdist = length(halfview);\n"
 "   halfview /= fdist;\n"
 "\n"
-"   vec3 total_light = newlight_compute_ambient();\n"
-"   \n"
-"   // Compute world lighting contribution and apply it according to the\n"
-"   // shadow map\n"
-"   //\n"
-"   vec3 world_light = newlight_compute_world_diffuse( wnormal );\n"
-"   world_light += newlight_compute_sun_spec( wnormal, halfview, 0.1 );\n"
+"   vec3 total_light = vec3(0.0);\n"
+"\n"
 "\n"
-"   float world_shadow = newlight_compute_sun_shadow();\n"
+"   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
+"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\n"
-"   total_light += world_light * min( board_shadow, world_shadow );\n"
+"   total_light += scene_lighting( wnormal, min( board_shadow, world_shadow ), \n"
+"                                  halfview, world );\n"
+"\n"
+"   //total_light += scene_lighting_old( wnormal, world );\n"
 "\n"
 "   // Compute the other lights that exist in the map, not effected by the sun\n"
 "   // shadow\n"
 "\n"
-"   total_light += newlight_compute_quadratic\n"
+"   // read lights\n"
+"   vec4 light_colour_0 = texelFetch( uLightsArray, light_indices.x*3+0 );\n"
+"   vec4 light_colour_1 = texelFetch( uLightsArray, light_indices.y*3+0 );\n"
+"   vec4 light_colour_2 = texelFetch( uLightsArray, light_indices.z*3+0 );\n"
+"   vec4 light_co_0     = texelFetch( uLightsArray, light_indices.x*3+1 );\n"
+"   vec4 light_co_1     = texelFetch( uLightsArray, light_indices.y*3+1 );\n"
+"   vec4 light_co_2     = texelFetch( uLightsArray, light_indices.z*3+1 );\n"
+"   vec4 light_dir_0    = texelFetch( uLightsArray, light_indices.x*3+2 );\n"
+"   vec4 light_dir_1    = texelFetch( uLightsArray, light_indices.y*3+2 );\n"
+"   vec4 light_dir_2    = texelFetch( uLightsArray, light_indices.z*3+2 );\n"
+"\n"
+"   //return vec3(fract(distance(light_co_0.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_1.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_2.xyz,aWorldCo)));\n"
+"\n"
+"  // return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
+"  //             fract(light_indices.z * 0.125 ));\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[0].xyz,\n"
-"                     light_colours[0].rgb \n"
+"                     light_colour_0.rgb,\n"
+"                     light_co_0.xyz,\n"
+"                     light_dir_0\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[1].xyz,\n"
-"                     light_colours[1].rgb \n"
+"                     light_colour_1.rgb,\n"
+"                     light_co_1.xyz,\n"
+"                     light_dir_1\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[2].xyz,\n"
-"                     light_colours[2].rgb \n"
+"                     light_colour_2.rgb,\n"
+"                     light_co_2.xyz,\n"
+"                     light_dir_2\n"
 "                  ) * board_shadow;\n"
 "\n"
-"   return apply_fog( diffuse * total_light, fdist );\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   \n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
 "#line      9        0 \n"
@@ -326,13 +526,13 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 static GLuint _uniform_scene_standard_alphatest_uMdl;
 static GLuint _uniform_scene_standard_alphatest_uPv;
 static GLuint _uniform_scene_standard_alphatest_uPvmPrev;
-static GLuint _uniform_scene_standard_alphatest_uLightsArray;
 static GLuint _uniform_scene_standard_alphatest_uTexGarbage;
 static GLuint _uniform_scene_standard_alphatest_uTexMain;
 static GLuint _uniform_scene_standard_alphatest_uBoard0;
 static GLuint _uniform_scene_standard_alphatest_uBoard1;
 static GLuint _uniform_scene_standard_alphatest_uCamera;
 static GLuint _uniform_scene_standard_alphatest_uPlane;
+static GLuint _uniform_scene_standard_alphatest_uLightsArray;
 static GLuint _uniform_scene_standard_alphatest_g_world_depth;
 static void shader_scene_standard_alphatest_uMdl(m4x3f m){
    glUniformMatrix4x3fv(_uniform_scene_standard_alphatest_uMdl,1,GL_FALSE,(float*)m);
@@ -372,13 +572,13 @@ static void shader_scene_standard_alphatest_link(void){
    _uniform_scene_standard_alphatest_uMdl = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uMdl" );
    _uniform_scene_standard_alphatest_uPv = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uPv" );
    _uniform_scene_standard_alphatest_uPvmPrev = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uPvmPrev" );
-   _uniform_scene_standard_alphatest_uLightsArray = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uLightsArray" );
    _uniform_scene_standard_alphatest_uTexGarbage = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uTexGarbage" );
    _uniform_scene_standard_alphatest_uTexMain = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uTexMain" );
    _uniform_scene_standard_alphatest_uBoard0 = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uBoard0" );
    _uniform_scene_standard_alphatest_uBoard1 = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uBoard1" );
    _uniform_scene_standard_alphatest_uCamera = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uCamera" );
    _uniform_scene_standard_alphatest_uPlane = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uPlane" );
+   _uniform_scene_standard_alphatest_uLightsArray = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uLightsArray" );
    _uniform_scene_standard_alphatest_g_world_depth = glGetUniformLocation( _shader_scene_standard_alphatest.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_standard_alphatest_H */
index a70ee32fdd1eae7cb2bf83cde805ccc7eab2ed00..cf19762aafa8a3478f2de73bc5fae251f208bb1b 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_scene_terrain = {
    .link = shader_scene_terrain_link,
    .vs = 
 {
+.orig_file = "shaders/scene.vs",
 .static_src = 
 "layout (location=0) in vec3  a_co;\n"
 "layout (location=1) in vec4  a_norm;\n"
@@ -36,14 +37,13 @@ static struct vg_shader _shader_scene_terrain = {
 "uniform mat4x3 uMdl;\n"
 "uniform mat4   uPv;\n"
 "uniform mat4   uPvmPrev;\n"
-"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "out vec2 aUv;\n"
 "out vec4 aNorm;\n"
 "out vec3 aCo;\n"
 "out vec3 aWorldCo;\n"
-"flat out vec4 light_colours[3];\n"
-"flat out vec4 light_positions[3];\n"
+"\n"
+"flat out ivec4 light_indices;\n"
 "\n"
 "void main()\n"
 "{\n"
@@ -60,17 +60,12 @@ static struct vg_shader _shader_scene_terrain = {
 "   aCo = a_co;\n"
 "   aWorldCo = world_pos0;\n"
 "\n"
-"   // read lights\n"
-"   light_colours[0] = texelFetch( uLightsArray, a_lights.x*2+0 );\n"
-"   light_colours[1] = texelFetch( uLightsArray, a_lights.y*2+0 );\n"
-"   light_colours[2] = texelFetch( uLightsArray, a_lights.z*2+0 );\n"
-"   light_positions[0] = texelFetch( uLightsArray, a_lights.x*2+1 );\n"
-"   light_positions[1] = texelFetch( uLightsArray, a_lights.y*2+1 );\n"
-"   light_positions[2] = texelFetch( uLightsArray, a_lights.z*2+1 );\n"
+"   light_indices = a_lights;\n"
 "}\n"
 ""},
    .fs = 
 {
+.orig_file = "shaders/scene_terrain.fs",
 .static_src = 
 "uniform sampler2D uTexGarbage;\n"
 "uniform sampler2D uTexGradients;\n"
@@ -87,8 +82,9 @@ static struct vg_shader _shader_scene_terrain = {
 "in vec4 aNorm;\n"
 "in vec3 aCo;\n"
 "in vec3 aWorldCo;\n"
-"flat in vec4 light_colours[3];\n"
-"flat in vec4 light_positions[3];\n"
+"flat in ivec4 light_indices;\n"
+"\n"
+"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
@@ -102,6 +98,7 @@ static struct vg_shader _shader_scene_terrain = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -150,7 +147,7 @@ static struct vg_shader _shader_scene_terrain = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -158,7 +155,7 @@ static struct vg_shader _shader_scene_terrain = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -200,8 +197,14 @@ static struct vg_shader _shader_scene_terrain = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -212,7 +215,172 @@ static struct vg_shader _shader_scene_terrain = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
-"#line     11        0 \n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        2 \n"
+"const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float TIME_RATE       = 0.025;\n"
+"\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"struct world_info\n"
+"{\n"
+"   float time,\n"
+"         time_of_day,\n"
+"         day_phase,\n"
+"         sunset_phase;\n"
+"   \n"
+"   vec3 sun_dir;\n"
+"};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 scene_ambient( vec3 dir, const world_info w )\n"
+"{\n"
+"   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);\n"
+"        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;\n"
+"        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 scene_sky( vec3 ray_dir, const world_info w )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = scene_ambient( ray_dir, w );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, w.sun_dir );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_ambient( vec3 normal, const world_info w )\n"
+"{\n"
+"   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );\n"
+"}\n"
+"\n"
+"vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )\n"
+"{\n"
+"   vec3 dir3 = vec3\n"
+"   (\n"
+"      cos(dir.y) * cos(dir.x),\n"
+"                   sin(dir.x),\n"
+"      sin(dir.y) * cos(dir.x)\n"
+"   );\n"
+"\n"
+"   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );\n"
+"   \n"
+"   return flight * colour;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting_old( vec3 normal, const world_info w )\n"
+"{\n"
+"   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );\n"
+"   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );\n"
+"   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );\n"
+"   \n"
+"   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +\n"
+"          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + \n"
+"          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );\n"
+"   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR \n"
+"                           * w.day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );\n"
+"\n"
+"   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"   float  sun_theta = dot( normal, w.sun_dir );\n"
+"\n"
+"   float  softness_min = 0.5;\n"
+"   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);\n"
+"   float  light_min    = 0.0 * w.day_phase;\n"
+"   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);\n"
+"          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;\n"
+"   \n"
+"   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );\n"
+"          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );\n"
+"          \n"
+"   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);\n"
+"   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"   \n"
+"   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) \n"
+"                            * 0.2 * shadow * w.day_phase;\n"
+"   \n"
+"   return mix(dark_colour, light_colour, light_direct) + \n"
+"              spec +\n"
+"              dark_colour * light_bounce;\n"
+"}\n"
+"\n"
+"void scene_state( float world_time, out world_info w )\n"
+"{\n"
+"   w.time         = world_time;\n"
+"   w.time_of_day  = fract( w.time );\n"
+"   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;\n"
+"   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;\n"
+"   w.sunset_phase = pow( w.sunset_phase, 6.0 );\n"
+"   \n"
+"   float a        = w.time_of_day * PI * 2.0;\n"
+"   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );\n"
+"}\n"
+"\n"
+"\n"
+"#line     13        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -233,49 +401,81 @@ static struct vg_shader _shader_scene_terrain = {
 "   return 1.0 - player_shadow*0.8;\n"
 "}\n"
 "\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
+"   world_info world;\n"
+"   scene_state( g_time, world );\n"
+"\n"
 "   // Lighting\n"
 "   vec3 halfview = uCamera - aWorldCo;\n"
 "   float fdist = length(halfview);\n"
 "   halfview /= fdist;\n"
 "\n"
-"   vec3 total_light = newlight_compute_ambient();\n"
-"   \n"
-"   // Compute world lighting contribution and apply it according to the\n"
-"   // shadow map\n"
-"   //\n"
-"   vec3 world_light = newlight_compute_world_diffuse( wnormal );\n"
-"   world_light += newlight_compute_sun_spec( wnormal, halfview, 0.1 );\n"
+"   vec3 total_light = vec3(0.0);\n"
+"\n"
 "\n"
-"   float world_shadow = newlight_compute_sun_shadow();\n"
+"   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
+"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\n"
-"   total_light += world_light * min( board_shadow, world_shadow );\n"
+"   total_light += scene_lighting( wnormal, min( board_shadow, world_shadow ), \n"
+"                                  halfview, world );\n"
+"\n"
+"   //total_light += scene_lighting_old( wnormal, world );\n"
 "\n"
 "   // Compute the other lights that exist in the map, not effected by the sun\n"
 "   // shadow\n"
 "\n"
-"   total_light += newlight_compute_quadratic\n"
+"   // read lights\n"
+"   vec4 light_colour_0 = texelFetch( uLightsArray, light_indices.x*3+0 );\n"
+"   vec4 light_colour_1 = texelFetch( uLightsArray, light_indices.y*3+0 );\n"
+"   vec4 light_colour_2 = texelFetch( uLightsArray, light_indices.z*3+0 );\n"
+"   vec4 light_co_0     = texelFetch( uLightsArray, light_indices.x*3+1 );\n"
+"   vec4 light_co_1     = texelFetch( uLightsArray, light_indices.y*3+1 );\n"
+"   vec4 light_co_2     = texelFetch( uLightsArray, light_indices.z*3+1 );\n"
+"   vec4 light_dir_0    = texelFetch( uLightsArray, light_indices.x*3+2 );\n"
+"   vec4 light_dir_1    = texelFetch( uLightsArray, light_indices.y*3+2 );\n"
+"   vec4 light_dir_2    = texelFetch( uLightsArray, light_indices.z*3+2 );\n"
+"\n"
+"   //return vec3(fract(distance(light_co_0.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_1.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_2.xyz,aWorldCo)));\n"
+"\n"
+"  // return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
+"  //             fract(light_indices.z * 0.125 ));\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[0].xyz,\n"
-"                     light_colours[0].rgb \n"
+"                     light_colour_0.rgb,\n"
+"                     light_co_0.xyz,\n"
+"                     light_dir_0\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[1].xyz,\n"
-"                     light_colours[1].rgb \n"
+"                     light_colour_1.rgb,\n"
+"                     light_co_1.xyz,\n"
+"                     light_dir_1\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[2].xyz,\n"
-"                     light_colours[2].rgb \n"
+"                     light_colour_2.rgb,\n"
+"                     light_co_2.xyz,\n"
+"                     light_dir_2\n"
 "                  ) * board_shadow;\n"
 "\n"
-"   return apply_fog( diffuse * total_light, fdist );\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   \n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
 "#line     10        0 \n"
@@ -346,7 +546,6 @@ static struct vg_shader _shader_scene_terrain = {
 static GLuint _uniform_scene_terrain_uMdl;
 static GLuint _uniform_scene_terrain_uPv;
 static GLuint _uniform_scene_terrain_uPvmPrev;
-static GLuint _uniform_scene_terrain_uLightsArray;
 static GLuint _uniform_scene_terrain_uTexGarbage;
 static GLuint _uniform_scene_terrain_uTexGradients;
 static GLuint _uniform_scene_terrain_uCamera;
@@ -354,6 +553,7 @@ static GLuint _uniform_scene_terrain_uSandColour;
 static GLuint _uniform_scene_terrain_uBlendOffset;
 static GLuint _uniform_scene_terrain_uBoard0;
 static GLuint _uniform_scene_terrain_uBoard1;
+static GLuint _uniform_scene_terrain_uLightsArray;
 static GLuint _uniform_scene_terrain_g_world_depth;
 static void shader_scene_terrain_uMdl(m4x3f m){
    glUniformMatrix4x3fv(_uniform_scene_terrain_uMdl,1,GL_FALSE,(float*)m);
@@ -396,7 +596,6 @@ static void shader_scene_terrain_link(void){
    _uniform_scene_terrain_uMdl = glGetUniformLocation( _shader_scene_terrain.id, "uMdl" );
    _uniform_scene_terrain_uPv = glGetUniformLocation( _shader_scene_terrain.id, "uPv" );
    _uniform_scene_terrain_uPvmPrev = glGetUniformLocation( _shader_scene_terrain.id, "uPvmPrev" );
-   _uniform_scene_terrain_uLightsArray = glGetUniformLocation( _shader_scene_terrain.id, "uLightsArray" );
    _uniform_scene_terrain_uTexGarbage = glGetUniformLocation( _shader_scene_terrain.id, "uTexGarbage" );
    _uniform_scene_terrain_uTexGradients = glGetUniformLocation( _shader_scene_terrain.id, "uTexGradients" );
    _uniform_scene_terrain_uCamera = glGetUniformLocation( _shader_scene_terrain.id, "uCamera" );
@@ -404,6 +603,7 @@ static void shader_scene_terrain_link(void){
    _uniform_scene_terrain_uBlendOffset = glGetUniformLocation( _shader_scene_terrain.id, "uBlendOffset" );
    _uniform_scene_terrain_uBoard0 = glGetUniformLocation( _shader_scene_terrain.id, "uBoard0" );
    _uniform_scene_terrain_uBoard1 = glGetUniformLocation( _shader_scene_terrain.id, "uBoard1" );
+   _uniform_scene_terrain_uLightsArray = glGetUniformLocation( _shader_scene_terrain.id, "uLightsArray" );
    _uniform_scene_terrain_g_world_depth = glGetUniformLocation( _shader_scene_terrain.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_terrain_H */
index 365cd044bd213b8edc89cd16b39116ad28001e6e..028392d04379bf0e70740f7d92779ffa9786625e 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_scene_vertex_blend = {
    .link = shader_scene_vertex_blend_link,
    .vs = 
 {
+.orig_file = "shaders/scene.vs",
 .static_src = 
 "layout (location=0) in vec3  a_co;\n"
 "layout (location=1) in vec4  a_norm;\n"
@@ -36,14 +37,13 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "uniform mat4x3 uMdl;\n"
 "uniform mat4   uPv;\n"
 "uniform mat4   uPvmPrev;\n"
-"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "out vec2 aUv;\n"
 "out vec4 aNorm;\n"
 "out vec3 aCo;\n"
 "out vec3 aWorldCo;\n"
-"flat out vec4 light_colours[3];\n"
-"flat out vec4 light_positions[3];\n"
+"\n"
+"flat out ivec4 light_indices;\n"
 "\n"
 "void main()\n"
 "{\n"
@@ -60,17 +60,12 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   aCo = a_co;\n"
 "   aWorldCo = world_pos0;\n"
 "\n"
-"   // read lights\n"
-"   light_colours[0] = texelFetch( uLightsArray, a_lights.x*2+0 );\n"
-"   light_colours[1] = texelFetch( uLightsArray, a_lights.y*2+0 );\n"
-"   light_colours[2] = texelFetch( uLightsArray, a_lights.z*2+0 );\n"
-"   light_positions[0] = texelFetch( uLightsArray, a_lights.x*2+1 );\n"
-"   light_positions[1] = texelFetch( uLightsArray, a_lights.y*2+1 );\n"
-"   light_positions[2] = texelFetch( uLightsArray, a_lights.z*2+1 );\n"
+"   light_indices = a_lights;\n"
 "}\n"
 ""},
    .fs = 
 {
+.orig_file = "shaders/scene_vertex_blend.fs",
 .static_src = 
 "uniform sampler2D uTexGarbage;\n"
 "uniform sampler2D uTexGradients;\n"
@@ -85,8 +80,9 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "in vec4 aNorm;\n"
 "in vec3 aCo;\n"
 "in vec3 aWorldCo;\n"
-"flat in vec4 light_colours[3];\n"
-"flat in vec4 light_positions[3];\n"
+"flat in ivec4 light_indices;\n"
+"\n"
+"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
@@ -100,6 +96,7 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -148,7 +145,7 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -156,7 +153,7 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -198,8 +195,14 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -210,7 +213,172 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
-"#line     11        0 \n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        2 \n"
+"const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float TIME_RATE       = 0.025;\n"
+"\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"struct world_info\n"
+"{\n"
+"   float time,\n"
+"         time_of_day,\n"
+"         day_phase,\n"
+"         sunset_phase;\n"
+"   \n"
+"   vec3 sun_dir;\n"
+"};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 scene_ambient( vec3 dir, const world_info w )\n"
+"{\n"
+"   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);\n"
+"        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;\n"
+"        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 scene_sky( vec3 ray_dir, const world_info w )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = scene_ambient( ray_dir, w );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, w.sun_dir );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_ambient( vec3 normal, const world_info w )\n"
+"{\n"
+"   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );\n"
+"}\n"
+"\n"
+"vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )\n"
+"{\n"
+"   vec3 dir3 = vec3\n"
+"   (\n"
+"      cos(dir.y) * cos(dir.x),\n"
+"                   sin(dir.x),\n"
+"      sin(dir.y) * cos(dir.x)\n"
+"   );\n"
+"\n"
+"   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );\n"
+"   \n"
+"   return flight * colour;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting_old( vec3 normal, const world_info w )\n"
+"{\n"
+"   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );\n"
+"   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );\n"
+"   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );\n"
+"   \n"
+"   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +\n"
+"          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + \n"
+"          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );\n"
+"   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR \n"
+"                           * w.day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );\n"
+"\n"
+"   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"   float  sun_theta = dot( normal, w.sun_dir );\n"
+"\n"
+"   float  softness_min = 0.5;\n"
+"   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);\n"
+"   float  light_min    = 0.0 * w.day_phase;\n"
+"   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);\n"
+"          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;\n"
+"   \n"
+"   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );\n"
+"          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );\n"
+"          \n"
+"   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);\n"
+"   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"   \n"
+"   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) \n"
+"                            * 0.2 * shadow * w.day_phase;\n"
+"   \n"
+"   return mix(dark_colour, light_colour, light_direct) + \n"
+"              spec +\n"
+"              dark_colour * light_bounce;\n"
+"}\n"
+"\n"
+"void scene_state( float world_time, out world_info w )\n"
+"{\n"
+"   w.time         = world_time;\n"
+"   w.time_of_day  = fract( w.time );\n"
+"   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;\n"
+"   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;\n"
+"   w.sunset_phase = pow( w.sunset_phase, 6.0 );\n"
+"   \n"
+"   float a        = w.time_of_day * PI * 2.0;\n"
+"   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );\n"
+"}\n"
+"\n"
+"\n"
+"#line     13        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -231,49 +399,81 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   return 1.0 - player_shadow*0.8;\n"
 "}\n"
 "\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
+"   world_info world;\n"
+"   scene_state( g_time, world );\n"
+"\n"
 "   // Lighting\n"
 "   vec3 halfview = uCamera - aWorldCo;\n"
 "   float fdist = length(halfview);\n"
 "   halfview /= fdist;\n"
 "\n"
-"   vec3 total_light = newlight_compute_ambient();\n"
-"   \n"
-"   // Compute world lighting contribution and apply it according to the\n"
-"   // shadow map\n"
-"   //\n"
-"   vec3 world_light = newlight_compute_world_diffuse( wnormal );\n"
-"   world_light += newlight_compute_sun_spec( wnormal, halfview, 0.1 );\n"
+"   vec3 total_light = vec3(0.0);\n"
+"\n"
 "\n"
-"   float world_shadow = newlight_compute_sun_shadow();\n"
+"   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
+"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\n"
-"   total_light += world_light * min( board_shadow, world_shadow );\n"
+"   total_light += scene_lighting( wnormal, min( board_shadow, world_shadow ), \n"
+"                                  halfview, world );\n"
+"\n"
+"   //total_light += scene_lighting_old( wnormal, world );\n"
 "\n"
 "   // Compute the other lights that exist in the map, not effected by the sun\n"
 "   // shadow\n"
 "\n"
-"   total_light += newlight_compute_quadratic\n"
+"   // read lights\n"
+"   vec4 light_colour_0 = texelFetch( uLightsArray, light_indices.x*3+0 );\n"
+"   vec4 light_colour_1 = texelFetch( uLightsArray, light_indices.y*3+0 );\n"
+"   vec4 light_colour_2 = texelFetch( uLightsArray, light_indices.z*3+0 );\n"
+"   vec4 light_co_0     = texelFetch( uLightsArray, light_indices.x*3+1 );\n"
+"   vec4 light_co_1     = texelFetch( uLightsArray, light_indices.y*3+1 );\n"
+"   vec4 light_co_2     = texelFetch( uLightsArray, light_indices.z*3+1 );\n"
+"   vec4 light_dir_0    = texelFetch( uLightsArray, light_indices.x*3+2 );\n"
+"   vec4 light_dir_1    = texelFetch( uLightsArray, light_indices.y*3+2 );\n"
+"   vec4 light_dir_2    = texelFetch( uLightsArray, light_indices.z*3+2 );\n"
+"\n"
+"   //return vec3(fract(distance(light_co_0.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_1.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_2.xyz,aWorldCo)));\n"
+"\n"
+"  // return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
+"  //             fract(light_indices.z * 0.125 ));\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[0].xyz,\n"
-"                     light_colours[0].rgb \n"
+"                     light_colour_0.rgb,\n"
+"                     light_co_0.xyz,\n"
+"                     light_dir_0\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[1].xyz,\n"
-"                     light_colours[1].rgb \n"
+"                     light_colour_1.rgb,\n"
+"                     light_co_1.xyz,\n"
+"                     light_dir_1\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[2].xyz,\n"
-"                     light_colours[2].rgb \n"
+"                     light_colour_2.rgb,\n"
+"                     light_co_2.xyz,\n"
+"                     light_dir_2\n"
 "                  ) * board_shadow;\n"
 "\n"
-"   return apply_fog( diffuse * total_light, fdist );\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   \n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
 "#line      8        0 \n"
@@ -340,12 +540,12 @@ static struct vg_shader _shader_scene_vertex_blend = {
 static GLuint _uniform_scene_vertex_blend_uMdl;
 static GLuint _uniform_scene_vertex_blend_uPv;
 static GLuint _uniform_scene_vertex_blend_uPvmPrev;
-static GLuint _uniform_scene_vertex_blend_uLightsArray;
 static GLuint _uniform_scene_vertex_blend_uTexGarbage;
 static GLuint _uniform_scene_vertex_blend_uTexGradients;
 static GLuint _uniform_scene_vertex_blend_uCamera;
 static GLuint _uniform_scene_vertex_blend_uBoard0;
 static GLuint _uniform_scene_vertex_blend_uBoard1;
+static GLuint _uniform_scene_vertex_blend_uLightsArray;
 static GLuint _uniform_scene_vertex_blend_g_world_depth;
 static void shader_scene_vertex_blend_uMdl(m4x3f m){
    glUniformMatrix4x3fv(_uniform_scene_vertex_blend_uMdl,1,GL_FALSE,(float*)m);
@@ -382,12 +582,12 @@ static void shader_scene_vertex_blend_link(void){
    _uniform_scene_vertex_blend_uMdl = glGetUniformLocation( _shader_scene_vertex_blend.id, "uMdl" );
    _uniform_scene_vertex_blend_uPv = glGetUniformLocation( _shader_scene_vertex_blend.id, "uPv" );
    _uniform_scene_vertex_blend_uPvmPrev = glGetUniformLocation( _shader_scene_vertex_blend.id, "uPvmPrev" );
-   _uniform_scene_vertex_blend_uLightsArray = glGetUniformLocation( _shader_scene_vertex_blend.id, "uLightsArray" );
    _uniform_scene_vertex_blend_uTexGarbage = glGetUniformLocation( _shader_scene_vertex_blend.id, "uTexGarbage" );
    _uniform_scene_vertex_blend_uTexGradients = glGetUniformLocation( _shader_scene_vertex_blend.id, "uTexGradients" );
    _uniform_scene_vertex_blend_uCamera = glGetUniformLocation( _shader_scene_vertex_blend.id, "uCamera" );
    _uniform_scene_vertex_blend_uBoard0 = glGetUniformLocation( _shader_scene_vertex_blend.id, "uBoard0" );
    _uniform_scene_vertex_blend_uBoard1 = glGetUniformLocation( _shader_scene_vertex_blend.id, "uBoard1" );
+   _uniform_scene_vertex_blend_uLightsArray = glGetUniformLocation( _shader_scene_vertex_blend.id, "uLightsArray" );
    _uniform_scene_vertex_blend_g_world_depth = glGetUniformLocation( _shader_scene_vertex_blend.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_vertex_blend_H */
index 892f0db6132e6d6d53186fc4560ca2f602d7a7ef..9cf652d9ae7711d82b54f48a1eeb33abefc4616e 100644 (file)
@@ -72,4 +72,5 @@ void main()
    vec4 vsurface = water_surf( halfview, surfnorm, depthvalue, beneath, above );
    vsurface.a -= fdist;
    oColour = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband );
+   oColour.rgb = scene_do_lighting( oColour.rgb, aNorm.xyz );
 }
index dfba719da96e4dc9e4a59ac110c209f7808a3650..a6fa804d8e9d25d861442d545b88fa619f42d2fd 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_scene_water = {
    .link = shader_scene_water_link,
    .vs = 
 {
+.orig_file = "shaders/scene.vs",
 .static_src = 
 "layout (location=0) in vec3  a_co;\n"
 "layout (location=1) in vec4  a_norm;\n"
@@ -36,14 +37,13 @@ static struct vg_shader _shader_scene_water = {
 "uniform mat4x3 uMdl;\n"
 "uniform mat4   uPv;\n"
 "uniform mat4   uPvmPrev;\n"
-"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "out vec2 aUv;\n"
 "out vec4 aNorm;\n"
 "out vec3 aCo;\n"
 "out vec3 aWorldCo;\n"
-"flat out vec4 light_colours[3];\n"
-"flat out vec4 light_positions[3];\n"
+"\n"
+"flat out ivec4 light_indices;\n"
 "\n"
 "void main()\n"
 "{\n"
@@ -60,17 +60,12 @@ static struct vg_shader _shader_scene_water = {
 "   aCo = a_co;\n"
 "   aWorldCo = world_pos0;\n"
 "\n"
-"   // read lights\n"
-"   light_colours[0] = texelFetch( uLightsArray, a_lights.x*2+0 );\n"
-"   light_colours[1] = texelFetch( uLightsArray, a_lights.y*2+0 );\n"
-"   light_colours[2] = texelFetch( uLightsArray, a_lights.z*2+0 );\n"
-"   light_positions[0] = texelFetch( uLightsArray, a_lights.x*2+1 );\n"
-"   light_positions[1] = texelFetch( uLightsArray, a_lights.y*2+1 );\n"
-"   light_positions[2] = texelFetch( uLightsArray, a_lights.z*2+1 );\n"
+"   light_indices = a_lights;\n"
 "}\n"
 ""},
    .fs = 
 {
+.orig_file = "shaders/scene_water.fs",
 .static_src = 
 "uniform sampler2D uTexMain;\n"
 "uniform sampler2D uTexDudv;\n"
@@ -93,8 +88,9 @@ static struct vg_shader _shader_scene_water = {
 "in vec4 aNorm;\n"
 "in vec3 aCo;\n"
 "in vec3 aWorldCo;\n"
-"flat in vec4 light_colours[3];\n"
-"flat in vec4 light_positions[3];\n"
+"flat in ivec4 light_indices;\n"
+"\n"
+"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
@@ -108,6 +104,7 @@ static struct vg_shader _shader_scene_water = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -156,7 +153,7 @@ static struct vg_shader _shader_scene_water = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -164,7 +161,7 @@ static struct vg_shader _shader_scene_water = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -206,8 +203,14 @@ static struct vg_shader _shader_scene_water = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -218,7 +221,172 @@ static struct vg_shader _shader_scene_water = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
-"#line     11        0 \n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        2 \n"
+"const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float TIME_RATE       = 0.025;\n"
+"\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"struct world_info\n"
+"{\n"
+"   float time,\n"
+"         time_of_day,\n"
+"         day_phase,\n"
+"         sunset_phase;\n"
+"   \n"
+"   vec3 sun_dir;\n"
+"};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 scene_ambient( vec3 dir, const world_info w )\n"
+"{\n"
+"   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);\n"
+"        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;\n"
+"        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 scene_sky( vec3 ray_dir, const world_info w )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = scene_ambient( ray_dir, w );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, w.sun_dir );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_ambient( vec3 normal, const world_info w )\n"
+"{\n"
+"   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );\n"
+"}\n"
+"\n"
+"vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )\n"
+"{\n"
+"   vec3 dir3 = vec3\n"
+"   (\n"
+"      cos(dir.y) * cos(dir.x),\n"
+"                   sin(dir.x),\n"
+"      sin(dir.y) * cos(dir.x)\n"
+"   );\n"
+"\n"
+"   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );\n"
+"   \n"
+"   return flight * colour;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting_old( vec3 normal, const world_info w )\n"
+"{\n"
+"   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );\n"
+"   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );\n"
+"   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );\n"
+"   \n"
+"   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +\n"
+"          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + \n"
+"          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );\n"
+"   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR \n"
+"                           * w.day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );\n"
+"\n"
+"   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"   float  sun_theta = dot( normal, w.sun_dir );\n"
+"\n"
+"   float  softness_min = 0.5;\n"
+"   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);\n"
+"   float  light_min    = 0.0 * w.day_phase;\n"
+"   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);\n"
+"          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;\n"
+"   \n"
+"   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );\n"
+"          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );\n"
+"          \n"
+"   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);\n"
+"   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"   \n"
+"   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) \n"
+"                            * 0.2 * shadow * w.day_phase;\n"
+"   \n"
+"   return mix(dark_colour, light_colour, light_direct) + \n"
+"              spec +\n"
+"              dark_colour * light_bounce;\n"
+"}\n"
+"\n"
+"void scene_state( float world_time, out world_info w )\n"
+"{\n"
+"   w.time         = world_time;\n"
+"   w.time_of_day  = fract( w.time );\n"
+"   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;\n"
+"   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;\n"
+"   w.sunset_phase = pow( w.sunset_phase, 6.0 );\n"
+"   \n"
+"   float a        = w.time_of_day * PI * 2.0;\n"
+"   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );\n"
+"}\n"
+"\n"
+"\n"
+"#line     13        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -239,49 +407,81 @@ static struct vg_shader _shader_scene_water = {
 "   return 1.0 - player_shadow*0.8;\n"
 "}\n"
 "\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
+"   world_info world;\n"
+"   scene_state( g_time, world );\n"
+"\n"
 "   // Lighting\n"
 "   vec3 halfview = uCamera - aWorldCo;\n"
 "   float fdist = length(halfview);\n"
 "   halfview /= fdist;\n"
 "\n"
-"   vec3 total_light = newlight_compute_ambient();\n"
-"   \n"
-"   // Compute world lighting contribution and apply it according to the\n"
-"   // shadow map\n"
-"   //\n"
-"   vec3 world_light = newlight_compute_world_diffuse( wnormal );\n"
-"   world_light += newlight_compute_sun_spec( wnormal, halfview, 0.1 );\n"
+"   vec3 total_light = vec3(0.0);\n"
+"\n"
 "\n"
-"   float world_shadow = newlight_compute_sun_shadow();\n"
+"   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
+"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\n"
-"   total_light += world_light * min( board_shadow, world_shadow );\n"
+"   total_light += scene_lighting( wnormal, min( board_shadow, world_shadow ), \n"
+"                                  halfview, world );\n"
+"\n"
+"   //total_light += scene_lighting_old( wnormal, world );\n"
 "\n"
 "   // Compute the other lights that exist in the map, not effected by the sun\n"
 "   // shadow\n"
 "\n"
-"   total_light += newlight_compute_quadratic\n"
+"   // read lights\n"
+"   vec4 light_colour_0 = texelFetch( uLightsArray, light_indices.x*3+0 );\n"
+"   vec4 light_colour_1 = texelFetch( uLightsArray, light_indices.y*3+0 );\n"
+"   vec4 light_colour_2 = texelFetch( uLightsArray, light_indices.z*3+0 );\n"
+"   vec4 light_co_0     = texelFetch( uLightsArray, light_indices.x*3+1 );\n"
+"   vec4 light_co_1     = texelFetch( uLightsArray, light_indices.y*3+1 );\n"
+"   vec4 light_co_2     = texelFetch( uLightsArray, light_indices.z*3+1 );\n"
+"   vec4 light_dir_0    = texelFetch( uLightsArray, light_indices.x*3+2 );\n"
+"   vec4 light_dir_1    = texelFetch( uLightsArray, light_indices.y*3+2 );\n"
+"   vec4 light_dir_2    = texelFetch( uLightsArray, light_indices.z*3+2 );\n"
+"\n"
+"   //return vec3(fract(distance(light_co_0.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_1.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_2.xyz,aWorldCo)));\n"
+"\n"
+"  // return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
+"  //             fract(light_indices.z * 0.125 ));\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[0].xyz,\n"
-"                     light_colours[0].rgb \n"
+"                     light_colour_0.rgb,\n"
+"                     light_co_0.xyz,\n"
+"                     light_dir_0\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[1].xyz,\n"
-"                     light_colours[1].rgb \n"
+"                     light_colour_1.rgb,\n"
+"                     light_co_1.xyz,\n"
+"                     light_dir_1\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[2].xyz,\n"
-"                     light_colours[2].rgb \n"
+"                     light_colour_2.rgb,\n"
+"                     light_co_2.xyz,\n"
+"                     light_dir_2\n"
 "                  ) * board_shadow;\n"
 "\n"
-"   return apply_fog( diffuse * total_light, fdist );\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   \n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
 "#line     16        0 \n"
@@ -363,6 +563,7 @@ static struct vg_shader _shader_scene_water = {
 "   vec4 vsurface = water_surf( halfview, surfnorm, depthvalue, beneath, above );\n"
 "   vsurface.a -= fdist;\n"
 "   oColour = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband );\n"
+"   oColour.rgb = scene_do_lighting( oColour.rgb, aNorm.xyz );\n"
 "}\n"
 ""},
 };
@@ -370,7 +571,6 @@ static struct vg_shader _shader_scene_water = {
 static GLuint _uniform_scene_water_uMdl;
 static GLuint _uniform_scene_water_uPv;
 static GLuint _uniform_scene_water_uPvmPrev;
-static GLuint _uniform_scene_water_uLightsArray;
 static GLuint _uniform_scene_water_uTexMain;
 static GLuint _uniform_scene_water_uTexDudv;
 static GLuint _uniform_scene_water_uTexBack;
@@ -382,6 +582,7 @@ static GLuint _uniform_scene_water_uBoard0;
 static GLuint _uniform_scene_water_uBoard1;
 static GLuint _uniform_scene_water_uShoreColour;
 static GLuint _uniform_scene_water_uOceanColour;
+static GLuint _uniform_scene_water_uLightsArray;
 static GLuint _uniform_scene_water_g_world_depth;
 static void shader_scene_water_uMdl(m4x3f m){
    glUniformMatrix4x3fv(_uniform_scene_water_uMdl,1,GL_FALSE,(float*)m);
@@ -436,7 +637,6 @@ static void shader_scene_water_link(void){
    _uniform_scene_water_uMdl = glGetUniformLocation( _shader_scene_water.id, "uMdl" );
    _uniform_scene_water_uPv = glGetUniformLocation( _shader_scene_water.id, "uPv" );
    _uniform_scene_water_uPvmPrev = glGetUniformLocation( _shader_scene_water.id, "uPvmPrev" );
-   _uniform_scene_water_uLightsArray = glGetUniformLocation( _shader_scene_water.id, "uLightsArray" );
    _uniform_scene_water_uTexMain = glGetUniformLocation( _shader_scene_water.id, "uTexMain" );
    _uniform_scene_water_uTexDudv = glGetUniformLocation( _shader_scene_water.id, "uTexDudv" );
    _uniform_scene_water_uTexBack = glGetUniformLocation( _shader_scene_water.id, "uTexBack" );
@@ -448,6 +648,7 @@ static void shader_scene_water_link(void){
    _uniform_scene_water_uBoard1 = glGetUniformLocation( _shader_scene_water.id, "uBoard1" );
    _uniform_scene_water_uShoreColour = glGetUniformLocation( _shader_scene_water.id, "uShoreColour" );
    _uniform_scene_water_uOceanColour = glGetUniformLocation( _shader_scene_water.id, "uOceanColour" );
+   _uniform_scene_water_uLightsArray = glGetUniformLocation( _shader_scene_water.id, "uLightsArray" );
    _uniform_scene_water_g_world_depth = glGetUniformLocation( _shader_scene_water.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_water_H */
index 576ee65880110a3c255abe0835a627cd167f3d97..7708caca72c96090823b26f7687b3f6b2c2de06c 100644 (file)
@@ -7,6 +7,7 @@ static struct vg_shader _shader_scene_water_fast = {
    .link = shader_scene_water_fast_link,
    .vs = 
 {
+.orig_file = "shaders/scene.vs",
 .static_src = 
 "layout (location=0) in vec3  a_co;\n"
 "layout (location=1) in vec4  a_norm;\n"
@@ -36,14 +37,13 @@ static struct vg_shader _shader_scene_water_fast = {
 "uniform mat4x3 uMdl;\n"
 "uniform mat4   uPv;\n"
 "uniform mat4   uPvmPrev;\n"
-"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "out vec2 aUv;\n"
 "out vec4 aNorm;\n"
 "out vec3 aCo;\n"
 "out vec3 aWorldCo;\n"
-"flat out vec4 light_colours[3];\n"
-"flat out vec4 light_positions[3];\n"
+"\n"
+"flat out ivec4 light_indices;\n"
 "\n"
 "void main()\n"
 "{\n"
@@ -60,17 +60,12 @@ static struct vg_shader _shader_scene_water_fast = {
 "   aCo = a_co;\n"
 "   aWorldCo = world_pos0;\n"
 "\n"
-"   // read lights\n"
-"   light_colours[0] = texelFetch( uLightsArray, a_lights.x*2+0 );\n"
-"   light_colours[1] = texelFetch( uLightsArray, a_lights.y*2+0 );\n"
-"   light_colours[2] = texelFetch( uLightsArray, a_lights.z*2+0 );\n"
-"   light_positions[0] = texelFetch( uLightsArray, a_lights.x*2+1 );\n"
-"   light_positions[1] = texelFetch( uLightsArray, a_lights.y*2+1 );\n"
-"   light_positions[2] = texelFetch( uLightsArray, a_lights.z*2+1 );\n"
+"   light_indices = a_lights;\n"
 "}\n"
 ""},
    .fs = 
 {
+.orig_file = "shaders/scene_water_fast.fs",
 .static_src = 
 "uniform sampler2D uTexDudv;\n"
 "\n"
@@ -90,8 +85,9 @@ static struct vg_shader _shader_scene_water_fast = {
 "in vec4 aNorm;\n"
 "in vec3 aCo;\n"
 "in vec3 aWorldCo;\n"
-"flat in vec4 light_colours[3];\n"
-"flat in vec4 light_positions[3];\n"
+"flat in ivec4 light_indices;\n"
+"\n"
+"uniform samplerBuffer uLightsArray;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
@@ -105,6 +101,7 @@ static struct vg_shader _shader_scene_water_fast = {
 "   vec4 g_water_plane;\n"
 "   vec4 g_depth_bounds;\n"
 "   float g_water_fog;\n"
+"   float g_time;\n"
 "   int g_light_count;\n"
 "   int g_light_preview;\n"
 "   int g_shadow_samples;\n"
@@ -153,7 +150,7 @@ static struct vg_shader _shader_scene_water_fast = {
 "   return g_ambient_colour.rgb;\n"
 "}\n"
 "\n"
-"float newlight_compute_sun_shadow()\n"
+"float newlight_compute_sun_shadow( vec3 dir )\n"
 "{\n"
 "   if( g_shadow_samples == 0 )\n"
 "   {\n"
@@ -161,7 +158,7 @@ static struct vg_shader _shader_scene_water_fast = {
 "   }\n"
 "\n"
 "   float fspread = g_light_colours[0].w;\n"
-"   vec3  vdir = g_light_directions[0].xyz;\n"
+"   vec3  vdir = dir;\n"
 "   float flength = g_light_directions[0].w;\n"
 "\n"
 "   float famt = 0.0;\n"
@@ -203,8 +200,14 @@ static struct vg_shader _shader_scene_water_fast = {
 "   return vcolour*spec*fintensity;\n"
 "}\n"
 "\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
 "vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
-"                                 vec3 light_pos, vec3 light_colour )\n"
+"                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
 "   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
 "\n"
@@ -215,7 +218,172 @@ static struct vg_shader _shader_scene_water_fast = {
 "   return light_colour*attenuation;\n"
 "}\n"
 "\n"
-"#line     11        0 \n"
+"vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
+"                            vec3 light_colour, vec3 light_pos,\n"
+"                            vec4 light_dir )\n"
+"{\n"
+"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"\n"
+"   float quadratic = dot(light_delta,light_delta);\n"
+"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"   attenuation *= max( 0.0, dot( light_delta, wnormal ) );\n"
+"\n"
+"   float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) ),\n"
+"            falloff = max( 0.0,( spot_theta - light_dir.w ) / (1.0-light_dir.w) );\n"
+"\n"
+"   return light_colour*attenuation*falloff;\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        2 \n"
+"const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 ) * 1.125;\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float TIME_RATE       = 0.025;\n"
+"\n"
+"const float PI              = 3.14159265;\n"
+"\n"
+"struct world_info\n"
+"{\n"
+"   float time,\n"
+"         time_of_day,\n"
+"         day_phase,\n"
+"         sunset_phase;\n"
+"   \n"
+"   vec3 sun_dir;\n"
+"};\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 scene_ambient( vec3 dir, const world_info w )\n"
+"{\n"
+"   float sun_azimuth  = dot( dir.xz, w.sun_dir.xz ) * 0.4 + 0.6;\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = DAYSKY_COLOUR   * (w.day_phase-w.sunset_phase*0.1);\n"
+"        ambient += SUNSET_COLOUR   * (1.0-dir.y*0.5) * w.sunset_phase * sun_azimuth;\n"
+"        ambient += NIGHTSKY_COLOUR * (1.0-w.day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 scene_sky( vec3 ray_dir, const world_info w )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = scene_ambient( ray_dir, w );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, w.sun_dir );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(w.sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), SUNSET_COLOUR, w.sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_ambient( vec3 normal, const world_info w )\n"
+"{\n"
+"   return scene_ambient( (normal * vec3(1.0,-1.0,1.0)) * 0.5 + 0.5, w );\n"
+"}\n"
+"\n"
+"vec3 SR_LIGHT( vec3 normal, vec2 dir, vec3 colour )\n"
+"{\n"
+"   vec3 dir3 = vec3\n"
+"   (\n"
+"      cos(dir.y) * cos(dir.x),\n"
+"                   sin(dir.x),\n"
+"      sin(dir.y) * cos(dir.x)\n"
+"   );\n"
+"\n"
+"   float flight = max( dot( normal, dir3 ) * 0.75 + 0.25, 0.0 );\n"
+"   \n"
+"   return flight * colour;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting_old( vec3 normal, const world_info w )\n"
+"{\n"
+"   vec3 SR_COLOUR_SUN  = vec3( 1.36,  1.35, 1.01 );\n"
+"   vec3 SR_COLOUR_FILL = vec3( 0.33,  0.56, 0.64 );\n"
+"   vec3 SR_COLOUR_RIM  = vec3( 0.05,  0.05, 0.23 );\n"
+"   \n"
+"   return SR_LIGHT( normal, vec2(  0.63, -0.08 ), SR_COLOUR_SUN ) +\n"
+"          SR_LIGHT( normal, vec2( -2.60, -0.13 ), SR_COLOUR_FILL ) + \n"
+"          SR_LIGHT( normal, vec2(  2.60, -0.84 ), SR_COLOUR_RIM ) ;\n"
+"}\n"
+"\n"
+"vec3 scene_lighting( vec3 normal, float shadow, vec3 halfview, const world_info w )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * mix( DAYSKY_COLOUR, SUNSET_COLOUR, w.sunset_phase );\n"
+"   vec3  light_sun      = max(0.0,dot(normal,w.sun_dir)*0.75+0.25) * SUN_COLOUR \n"
+"                           * w.day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(w.sun_dir.y,0.0) );\n"
+"\n"
+"   vec3 ambient = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"\n"
+"   float  sun_theta = dot( normal, w.sun_dir );\n"
+"\n"
+"   float  softness_min = 0.5;\n"
+"   float  softness     = softness_min + w.sunset_phase * (1.0-softness_min);\n"
+"   float  light_min    = 0.0 * w.day_phase;\n"
+"   float  light_direct = light_min + smoothstep( -softness, softness, sun_theta ) * (1.0-light_min);\n"
+"          light_direct *= clamp(w.sun_dir.y * 4.0 + 1.0,0.0,1.0) * shadow;\n"
+"   \n"
+"   float  light_bounce  = 0.5 + 0.5 * dot( -normal, w.sun_dir );\n"
+"          light_bounce *= light_bounce * max( w.sun_dir.y, 0.0 );\n"
+"          \n"
+"   vec3   light_colour = SUN_COLOUR*w.day_phase + (SUNSET_COLOUR*w.sunset_phase + 0.1);\n"
+"   vec3   dark_colour  = mix( AMBIENT_COLOUR, SUNSET_AMBIENT, w.sunset_phase );\n"
+"   \n"
+"   float  spec         = newlight_specular( normal, w.sun_dir, halfview, 2.0 ) \n"
+"                            * 0.2 * shadow * w.day_phase;\n"
+"   \n"
+"   return mix(dark_colour, light_colour, light_direct) + \n"
+"              spec +\n"
+"              dark_colour * light_bounce;\n"
+"}\n"
+"\n"
+"void scene_state( float world_time, out world_info w )\n"
+"{\n"
+"   w.time         = world_time;\n"
+"   w.time_of_day  = fract( w.time );\n"
+"   w.day_phase    = cos( w.time_of_day * PI * 2.0 )      * 0.5 + 0.5;\n"
+"   w.sunset_phase = cos( w.time_of_day * PI * 4.0 + PI ) * 0.5 + 0.5;\n"
+"   w.sunset_phase = pow( w.sunset_phase, 6.0 );\n"
+"   \n"
+"   float a        = w.time_of_day * PI * 2.0;\n"
+"   w.sun_dir      = normalize( vec3( sin( a ), cos( a ), 0.2) );\n"
+"}\n"
+"\n"
+"\n"
+"#line     13        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -236,49 +404,81 @@ static struct vg_shader _shader_scene_water_fast = {
 "   return 1.0 - player_shadow*0.8;\n"
 "}\n"
 "\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )\n"
+"{\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
+"   world_info world;\n"
+"   scene_state( g_time, world );\n"
+"\n"
 "   // Lighting\n"
 "   vec3 halfview = uCamera - aWorldCo;\n"
 "   float fdist = length(halfview);\n"
 "   halfview /= fdist;\n"
 "\n"
-"   vec3 total_light = newlight_compute_ambient();\n"
-"   \n"
-"   // Compute world lighting contribution and apply it according to the\n"
-"   // shadow map\n"
-"   //\n"
-"   vec3 world_light = newlight_compute_world_diffuse( wnormal );\n"
-"   world_light += newlight_compute_sun_spec( wnormal, halfview, 0.1 );\n"
+"   vec3 total_light = vec3(0.0);\n"
+"\n"
 "\n"
-"   float world_shadow = newlight_compute_sun_shadow();\n"
+"   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
+"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\n"
-"   total_light += world_light * min( board_shadow, world_shadow );\n"
+"   total_light += scene_lighting( wnormal, min( board_shadow, world_shadow ), \n"
+"                                  halfview, world );\n"
+"\n"
+"   //total_light += scene_lighting_old( wnormal, world );\n"
 "\n"
 "   // Compute the other lights that exist in the map, not effected by the sun\n"
 "   // shadow\n"
 "\n"
-"   total_light += newlight_compute_quadratic\n"
+"   // read lights\n"
+"   vec4 light_colour_0 = texelFetch( uLightsArray, light_indices.x*3+0 );\n"
+"   vec4 light_colour_1 = texelFetch( uLightsArray, light_indices.y*3+0 );\n"
+"   vec4 light_colour_2 = texelFetch( uLightsArray, light_indices.z*3+0 );\n"
+"   vec4 light_co_0     = texelFetch( uLightsArray, light_indices.x*3+1 );\n"
+"   vec4 light_co_1     = texelFetch( uLightsArray, light_indices.y*3+1 );\n"
+"   vec4 light_co_2     = texelFetch( uLightsArray, light_indices.z*3+1 );\n"
+"   vec4 light_dir_0    = texelFetch( uLightsArray, light_indices.x*3+2 );\n"
+"   vec4 light_dir_1    = texelFetch( uLightsArray, light_indices.y*3+2 );\n"
+"   vec4 light_dir_2    = texelFetch( uLightsArray, light_indices.z*3+2 );\n"
+"\n"
+"   //return vec3(fract(distance(light_co_0.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_1.xyz,aWorldCo)),\n"
+"   //            fract(distance(light_co_2.xyz,aWorldCo)));\n"
+"\n"
+"  // return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
+"  //             fract(light_indices.z * 0.125 ));\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[0].xyz,\n"
-"                     light_colours[0].rgb \n"
+"                     light_colour_0.rgb,\n"
+"                     light_co_0.xyz,\n"
+"                     light_dir_0\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[1].xyz,\n"
-"                     light_colours[1].rgb \n"
+"                     light_colour_1.rgb,\n"
+"                     light_co_1.xyz,\n"
+"                     light_dir_1\n"
 "                  ) * board_shadow;\n"
-"   total_light += newlight_compute_quadratic\n"
+"   total_light += newlight_compute_spot\n"
 "                  ( \n"
 "                     wnormal, halfview,\n"
-"                     light_positions[2].xyz,\n"
-"                     light_colours[2].rgb \n"
+"                     light_colour_2.rgb,\n"
+"                     light_co_2.xyz,\n"
+"                     light_dir_2\n"
 "                  ) * board_shadow;\n"
 "\n"
-"   return apply_fog( diffuse * total_light, fdist );\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   \n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
 "#line     13        0 \n"
@@ -352,7 +552,6 @@ static struct vg_shader _shader_scene_water_fast = {
 static GLuint _uniform_scene_water_fast_uMdl;
 static GLuint _uniform_scene_water_fast_uPv;
 static GLuint _uniform_scene_water_fast_uPvmPrev;
-static GLuint _uniform_scene_water_fast_uLightsArray;
 static GLuint _uniform_scene_water_fast_uTexDudv;
 static GLuint _uniform_scene_water_fast_uTime;
 static GLuint _uniform_scene_water_fast_uCamera;
@@ -361,6 +560,7 @@ static GLuint _uniform_scene_water_fast_uBoard0;
 static GLuint _uniform_scene_water_fast_uBoard1;
 static GLuint _uniform_scene_water_fast_uShoreColour;
 static GLuint _uniform_scene_water_fast_uOceanColour;
+static GLuint _uniform_scene_water_fast_uLightsArray;
 static GLuint _uniform_scene_water_fast_g_world_depth;
 static void shader_scene_water_fast_uMdl(m4x3f m){
    glUniformMatrix4x3fv(_uniform_scene_water_fast_uMdl,1,GL_FALSE,(float*)m);
@@ -406,7 +606,6 @@ static void shader_scene_water_fast_link(void){
    _uniform_scene_water_fast_uMdl = glGetUniformLocation( _shader_scene_water_fast.id, "uMdl" );
    _uniform_scene_water_fast_uPv = glGetUniformLocation( _shader_scene_water_fast.id, "uPv" );
    _uniform_scene_water_fast_uPvmPrev = glGetUniformLocation( _shader_scene_water_fast.id, "uPvmPrev" );
-   _uniform_scene_water_fast_uLightsArray = glGetUniformLocation( _shader_scene_water_fast.id, "uLightsArray" );
    _uniform_scene_water_fast_uTexDudv = glGetUniformLocation( _shader_scene_water_fast.id, "uTexDudv" );
    _uniform_scene_water_fast_uTime = glGetUniformLocation( _shader_scene_water_fast.id, "uTime" );
    _uniform_scene_water_fast_uCamera = glGetUniformLocation( _shader_scene_water_fast.id, "uCamera" );
@@ -415,6 +614,7 @@ static void shader_scene_water_fast_link(void){
    _uniform_scene_water_fast_uBoard1 = glGetUniformLocation( _shader_scene_water_fast.id, "uBoard1" );
    _uniform_scene_water_fast_uShoreColour = glGetUniformLocation( _shader_scene_water_fast.id, "uShoreColour" );
    _uniform_scene_water_fast_uOceanColour = glGetUniformLocation( _shader_scene_water_fast.id, "uOceanColour" );
+   _uniform_scene_water_fast_uLightsArray = glGetUniformLocation( _shader_scene_water_fast.id, "uLightsArray" );
    _uniform_scene_water_fast_g_world_depth = glGetUniformLocation( _shader_scene_water_fast.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_water_fast_H */
diff --git a/world.h b/world.h
index 1b540d0d9d17176197003f04729b4f5ed4595803..3f806cb8714e00dbabf0d8564dede4a7b9acd43b 100644 (file)
--- a/world.h
+++ b/world.h
@@ -88,6 +88,7 @@ struct world_instance
           g_depth_bounds;
 
       float g_water_fog;
+      float g_time;
       int g_light_count;
       int g_light_preview;
       int g_shadow_samples;
@@ -210,8 +211,11 @@ struct world_instance
     */
    struct world_light
    {
-      v3f co;
-      v4f colour;
+      mdl_node *node;
+      struct classtype_world_light *inf;
+
+      /* enabled.. etc? 
+       * TODO: we should order entities in the binary by their type */
    }
    * lights;
    u32 light_count;
@@ -616,6 +620,18 @@ VG_STATIC void world_run_relay( world_instance *world,
 
 VG_STATIC void world_update( world_instance *world, v3f pos )
 {
+   /* TEMP!!!!!! */
+   static double g_time = 0.0;
+   g_time += vg.time_delta * (1.0/(k_day_length*60.0));
+
+   world->ub_lighting.g_time = g_time;
+
+   glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
+   glBufferSubData( GL_UNIFORM_BUFFER, 0, 
+                    sizeof(struct ub_world_lighting), &world->ub_lighting );
+   /* TEMP!!!!!! */
+
+
 #if 0
    if( world.switching_to_new_world )
    {
@@ -718,22 +734,23 @@ VG_STATIC void world_update( world_instance *world, v3f pos )
                                                         0xff00ff00 );
    }
 
-   if( 0 )
+   if( k_debug_light_index )
    {
       for( int i=0; i<world->light_count; i++ )
       {
          struct world_light *light = &world->lights[i];
+         struct classtype_world_light *inf = light->inf;
 
          u32 colour = 0xff000000;
-         u8 r = light->colour[0] * 255.0f,
-            g = light->colour[1] * 255.0f,
-            b = light->colour[2] * 255.0f;
+         u8 r = inf->colour[0] * 255.0f,
+            g = inf->colour[1] * 255.0f,
+            b = inf->colour[2] * 255.0f;
 
          colour |= r;
          colour |= g << 8;
          colour |= b << 16;
 
-         vg_line_pt3( light->co, 0.25f, colour );
+         vg_line_pt3( light->node->co, 0.25f, colour );
       }
    }
 
index 59bed34a282cfdd8ae05687b4c94d261168c76ef..b6c2f15db41125191eb1b871332a06b43b318500 100644 (file)
@@ -184,7 +184,7 @@ VG_STATIC void world_ents_allocate( world_instance *world )
          sizeof(struct logic_achievement)
       },
       {
-         k_classtype_point_light,
+         k_classtype_world_light,
          (void*)&world->lights,
          sizeof(struct world_light)
       },
@@ -335,15 +335,11 @@ VG_STATIC void world_pct_achievement( world_instance *world, mdl_node *pnode )
    world->achievement_count ++;
 }
 
-VG_STATIC void world_pct_point_light( world_instance *world, mdl_node *pnode )
+VG_STATIC void world_pct_world_light( world_instance *world, mdl_node *pnode )
 {
-   struct world_light *light = &world->lights[ world->light_count ];
-   v3_copy( pnode->co, light->co );
-
-   struct classtype_point_light *inf = mdl_get_entdata( world->meta, pnode );
-   v4_copy( inf->colour, light->colour );
-
-   world->light_count ++;
+   struct world_light *light = &world->lights[ world->light_count ++ ];
+   light->node = pnode;
+   light->inf  = mdl_get_entdata( world->meta, pnode );
 }
 
 VG_STATIC void world_pct_nonlocal_gate( world_instance *world, mdl_node *pnode )
@@ -373,7 +369,7 @@ VG_STATIC void world_entities_process( world_instance *world )
       { k_classtype_trigger,  world_pct_trigger },
       { k_classtype_logic_relay, world_pct_relay },
       { k_classtype_logic_achievement, world_pct_achievement },
-      { k_classtype_point_light, world_pct_point_light },
+      { k_classtype_world_light, world_pct_world_light },
       { k_classtype_nonlocal_gate, world_pct_nonlocal_gate }
    };
 
@@ -448,37 +444,87 @@ VG_STATIC void world_link_nonlocal_gates( int index_a, int index_b )
    }
 }
 
+VG_STATIC float colour_luminance( v3f v )
+{
+   return v3_dot( v, (v3f){0.2126f, 0.7152f, 0.0722f} );
+}
+
+VG_STATIC float calc_light_influence( world_instance *world, v3f position, 
+                                      v3f normal, int light )
+{
+   struct world_light *world_light = &world->lights[ light ];
+   struct classtype_world_light *inf = world_light->inf;
+
+   v3f light_delta;
+   v3_sub( world_light->node->co, position, light_delta );
+   v3_muls( light_delta, 10.0f, light_delta );
+
+   float quadratic = v3_dot( light_delta, light_delta ),
+         attenuation = 1.0f/( 1.0f + quadratic );
+
+   v3_normalize( light_delta );
+   //attenuation *= vg_maxf( 0.0, v3_dot( light_delta, normal ) );
+
+   float quadratic_light = attenuation * colour_luminance( inf->colour );
+
+   if( inf->type == k_light_type_point )
+   {
+      return quadratic_light;
+   }
+   else if( inf->type == k_light_type_spot )
+   {
+      v3f dir;
+      q_mulv( world_light->node->q, (v3f){0.0f,1.0f,0.0f}, dir );
+
+      float spot_theta = vg_maxf( 0.0f, v3_dot( light_delta, dir ) ),
+            falloff    = spot_theta >= 0.0f? 1.0f: 0.0f;
+
+      return quadratic_light * falloff;
+   }
+   else
+      return 0.0f;
+}
+
 VG_STATIC void world_scene_compute_light_clusters( world_instance *world,
                                                    scene *sc )
 {
    for( int i=0; i<sc->vertex_count; i++ )
    {
       scene_vert *vert = &sc->arrvertices[i];
-      vert->lights[0] = 255;
-      vert->lights[1] = 255;
-      vert->lights[2] = 255;
-      vert->lights[3] = 255;
+      vert->lights[0] = 0;
+      vert->lights[1] = 1;
+      vert->lights[2] = 2;
+      vert->lights[3] = 3;
 
-      float distances[4] = { INFINITY, INFINITY, INFINITY, INFINITY };
+      float influences[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+
+      v3f co, norm;
+      v3_copy( vert->co, co );
+
+      norm[0] = vert->norm[0];
+      norm[1] = vert->norm[1];
+      norm[2] = vert->norm[2];
+
+      v3_muls( norm, 1.0f/127.0f, norm );
 
       for( int j=0; j<world->light_count; j ++ )
       {
-         float dist = v3_dist2( world->lights[j].co, vert->co );
+         float influence = calc_light_influence( world, co, norm, j );
 
          int best_pos = 4;
          for( int k=best_pos-1; k>=0; k -- )
-            if( dist < distances[k] )
+            if( influence > influences[k] )
                best_pos = k;
 
          if( best_pos < 4 )
          {
             for( int k=3; k>best_pos; k -- )
             {
-               distances[k] = distances[k-1];
+               influences[k] = influences[k-1];
                vert->lights[k] = vert->lights[k-1];
             }
 
-            distances[best_pos] = dist;
+            influences[best_pos] = influence;
             vert->lights[best_pos] = j;
          }
       }
@@ -597,19 +643,40 @@ VG_STATIC void world_post_process( world_instance *world )
    vg_acquire_thread_sync();
    {
       /* create scene lighting buffer */
+
+      u32 size = VG_MAX(world->light_count,1) * sizeof(float)*12;
+
+      vg_info( "Upload %ubytes (lighting)\n", size );
+
       glGenBuffers( 1, &world->tbo_light_entities );
       glBindBuffer( GL_TEXTURE_BUFFER, world->tbo_light_entities );
-      glBufferData( GL_TEXTURE_BUFFER, world->light_count*sizeof(float)*8,
-                    NULL, GL_DYNAMIC_DRAW );
+      glBufferData( GL_TEXTURE_BUFFER, size, NULL, GL_DYNAMIC_DRAW );
+      
+      /* buffer layout
+       *  
+       *  colour               position         direction (spots)
+       * | .   .   .   .     | .   .   .   .  | .   .   .   .  |
+       * | Re  Ge  Be  Night | Xco Yco Zco    | Dx  Dy  Dz  Da |
+       *
+       */
 
       v4f *light_dst = glMapBuffer( GL_TEXTURE_BUFFER, GL_WRITE_ONLY );
       
       for( int i=0; i<world->light_count; i++ )
       {
          struct world_light *light = &world->lights[i];
+         struct classtype_world_light *inf = light->inf;
 
-         v3_muls( light->colour, light->colour[3] * 2.0f, light_dst[i*2+0] );
-         v3_copy( light->co, light_dst[i*2+1] );
+         /* colour  + night */
+         v3_muls( inf->colour, inf->colour[3] * 2.0f, light_dst[i*3+0] );
+         light_dst[i*3+0][3] = 1.0f;
+         
+         /* position + nothing */
+         v3_copy( light->node->co, light_dst[i*3+1] );
+
+         /* direction + angle */
+         q_mulv( light->node->q, (v3f){0.0f,-1.0f,0.0f}, light_dst[i*3+2]);
+         light_dst[i*3+2][3] = inf->angle;
       }
 
       glUnmapBuffer( GL_TEXTURE_BUFFER );
@@ -761,6 +828,9 @@ VG_STATIC void world_unload( world_instance *world )
    mesh_free( &world->mesh_geo );
    mesh_free( &world->mesh_no_collide );
 
+   glDeleteBuffers( 1, &world->tbo_light_entities );
+   glDeleteTextures( 1, &world->tex_light_entities );
+
    /* FIXME: CANT DO THIS HERE */
    world_global.time = 0.0;
    world_global.rewind_from = 0.0;
index 1926364c6b437fa03ba206a82ae74af47a620af4..f66ae0487e43e8f61b608c655b3a67f472207ee9 100644 (file)
@@ -281,7 +281,7 @@ VG_STATIC void render_terrain( world_instance *world, camera *cam )
    world_render_both_stages( world, k_shader_terrain_blend, bindpoint_terrain );
 }
 
-VG_STATIC void render_sky( camera *cam )
+VG_STATIC void render_sky( world_instance *world, camera *cam )
 {
    /* 
     * Modify matrix to remove clipping and view translation
@@ -315,7 +315,7 @@ VG_STATIC void render_sky( camera *cam )
    shader_model_sky_uPv( pv );
    shader_model_sky_uPvmPrev( pv_prev );
    shader_model_sky_uTexGarbage(0);
-   shader_model_sky_uTime( world_global.sky_time );
+   world_link_lighting_ub( world, _shader_model_sky.id );
 
    vg_tex2d_bind( &tex_terrain_noise, 0 );
 
@@ -379,7 +379,7 @@ VG_STATIC void render_world_gates( world_instance *world, camera *cam )
 
 VG_STATIC void render_world( world_instance *world, camera *cam )
 {
-   render_sky( cam );
+   render_sky( world, cam );
 
    render_world_routes( world, cam );
    render_world_standard( world, cam );
index c16e2c556f60caa9864826f46cc6396778998b7c..6d77a9855bbfbb7599a3e41ad644ff64b63d35a4 100644 (file)
@@ -38,6 +38,9 @@ VG_STATIC void world_link_lighting_ub( world_instance *world, GLuint shader );
 VG_STATIC void world_bind_position_texture( world_instance *world, 
                                             GLuint shader, GLuint location,
                                             int slot );
+VG_STATIC void world_bind_light_array( world_instance *world,
+                                       GLuint shader, GLuint location, 
+                                       int slot );
 
 /*
  * Does not write motion vectors
@@ -135,6 +138,8 @@ VG_STATIC void render_water_surface( world_instance *world, camera *cam )
       world_link_lighting_ub( world, _shader_scene_water.id );
       world_bind_position_texture( world, _shader_scene_water.id, 
                                     _uniform_scene_water_g_world_depth, 2 );
+      world_bind_light_array( world, _shader_scene_water.id,
+                                    _uniform_scene_water_uLightsArray, 4 );
 
       render_fb_bind_texture( gpipeline.fb_water_beneath, 0, 3 );
       shader_scene_water_uTexBack( 3 );
@@ -182,6 +187,8 @@ VG_STATIC void render_water_surface( world_instance *world, camera *cam )
       world_link_lighting_ub( world, _shader_scene_water_fast.id );
       world_bind_position_texture( world, _shader_scene_water_fast.id,
                                    _uniform_scene_water_fast_g_world_depth, 2 );
+      world_bind_light_array( world, _shader_scene_water_fast.id,
+                                    _uniform_scene_water_fast_uLightsArray, 4 );
 
       m4x3f full;
       m4x3_identity( full );