grid based
authorhgn <hgodden00@gmail.com>
Sat, 4 Mar 2023 02:51:28 +0000 (02:51 +0000)
committerhgn <hgodden00@gmail.com>
Sat, 4 Mar 2023 02:51:28 +0000 (02:51 +0000)
24 files changed:
blender_export.py
maps_src/mp_gridmap.mdl
maps_src/mp_home.mdl
maps_src/mp_mtzero.mdl
model.h
shaders/common_scene.glsl
shaders/common_world.glsl
shaders/model_character_view.h
shaders/model_sky.h
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.h
shaders/scene_water_fast.h
skaterift.c
world.h
world_gen.h
world_render.h
world_routes.h
world_water.h

index 6117ff871b80bbd0ead49466cec553776ac0176b..a12850b2b347f02b0391166b8cb90ed191716083 100644 (file)
@@ -814,7 +814,8 @@ class classtype_world_light( Structure ):
    _pack_ = 1
    _fields_ = [("type",c_uint32),
                ("colour",c_float*4),
-               ("angle",c_float)]
+               ("angle",c_float),
+               ("range",c_float)]
 
    def encode_obj(_, node, node_def):
    #{
@@ -826,6 +827,9 @@ class classtype_world_light( Structure ):
       _.colour[1] = data.color[1]
       _.colour[2] = data.color[2]
       _.colour[3] = data.energy
+      _.range = data.cutoff_distance # this has to be manually set
+                                     # TODO: At some point, automate a min
+                                     #       threshold value
 
       if obj.data.type == 'POINT':
       #{
@@ -835,7 +839,7 @@ class classtype_world_light( Structure ):
       elif obj.data.type == 'SPOT':
       #{
          _.type = 1
-         _.angle = math.cos(data.spot_size*0.5)
+         _.angle = data.spot_size*0.5
       #}
 
       if data.cv_data.bp0:
index b2cc013a18d3c4f01a85e2e8222448ae0a92d7cc..83930f58abfe4e01409e9308751878d5e2da1005 100644 (file)
Binary files a/maps_src/mp_gridmap.mdl and b/maps_src/mp_gridmap.mdl differ
index d68b2d56cea744d7304d1c619f00c99247ec777b..365dce4c839b99081bd2e15eb6615f512fc54223 100644 (file)
Binary files a/maps_src/mp_home.mdl and b/maps_src/mp_home.mdl differ
index d20a0e8af04343db0096f7881958faff155e5232..0c6120ef8807cc5a153a31c74ffb54fdc2d2e3ee 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 7c4e0d9cbade5266c18b85d45a2b3f09fe8d8e8a..dff23af564ead71d21092642f8950bf9545e413b 100644 (file)
--- a/model.h
+++ b/model.h
@@ -283,7 +283,7 @@ struct classtype_world_light
    type;
 
    v4f colour; /* RGB, Energy */
-   float angle;
+   float angle, range;
 };
 
 #pragma pack(pop)
index 91dc6a19cf7116cae9b1a1e5a110418ab4dbc1ae..8be69c1bfa16eb9f4f69009b240ea22f82bc1061 100644 (file)
@@ -7,6 +7,7 @@ in vec3 aWorldCo;
 flat in ivec4 light_indices;
 
 uniform samplerBuffer uLightsArray;
+uniform usampler3D uLightsIndex;
 
 #include "common_world.glsl"
 #include "light_clearskies.glsl"
@@ -36,6 +37,69 @@ vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist )
    return mix( vfrag, colour, min( 1.0, dist ) );
 }
 
+vec3 rand33(vec3 p3)
+{
+       p3 = fract(p3 * vec3(.1031, .1030, .0973));
+   p3 += dot(p3, p3.yxz+33.33);
+   return fract((p3.xxy + p3.yxx)*p3.zyx);
+}
+
+vec3 scene_calculate_light( int light_index, 
+                            vec3 halfview, vec3 co, vec3 normal )
+{
+   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );
+   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );
+   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );
+
+   vec3 light_delta = light_co.xyz-co;
+   float dist2 = dot(light_delta,light_delta);
+
+   light_delta = normalize( light_delta );
+
+   float quadratic = dist2*100.0;
+   float attenuation  = 1.0f/( 1.0f + quadratic );
+         attenuation *= max( dot( light_delta, normal ), 0.0 );
+
+   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );
+
+   if( light_dir.w < 0.999999 )
+   {
+      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.rgb * attenuation * falloff;
+}
+
+vec3 scene_calculate_packed_light_patch( uint packed_index, 
+                                         vec3 halfview, vec3 co, vec3 normal )
+{
+   uint light_count = packed_index & 0x3u;
+
+   vec3 l = vec3(0.0);
+
+   if( light_count >= 1u )
+   {
+      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );
+      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );
+      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );
+
+      l += scene_calculate_light( index_0, halfview, co, normal );
+
+      if( light_count >= 2u )
+      {
+         l += scene_calculate_light( index_1, halfview, co, normal );
+
+         if( light_count >= 3u )
+         {
+            l += scene_calculate_light( index_2, halfview, co, normal );
+         }
+      }
+   }
+
+   return l;
+}
+
 vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )
 {
    world_info world;
@@ -47,84 +111,44 @@ vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )
    halfview /= fdist;
 
    vec3 total_light = vec3(0.0);
-
-
    float world_shadow = newlight_compute_sun_shadow( world.sun_dir 
-                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );
+                                    * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );
    float board_shadow = compute_board_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
-
-   // 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 );
+   vec3 cube_coord = (aWorldCo - g_cube_min.xyz) * g_cube_inv_range.xyz;
+        cube_coord = floor( cube_coord );
 
    if( g_debug_indices == 1 )
    {
-      float rings = min( fract(distance(light_co_0.xyz,aWorldCo)),
-                      min( 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 )) + (rings-0.5) * 0.25;
+      return rand33(cube_coord);
    }
 
    if( g_debug_complexity == 1 )
    {
-      return vec3(1.0,0.0,0.0) * ( light_indices.w/3.0 );
-   }
+      ivec3 coord = ivec3( cube_coord );
+      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );
 
-   if( light_indices.w >= 1 )
-   {
-      total_light += newlight_compute_spot
-                     ( 
-                        wnormal, halfview,
-                        light_colour_0.rgb,
-                        light_co_0.xyz,
-                        light_dir_0
-                     ) * board_shadow 
-                       * step( world.day_phase, light_colour_0.w );
-
-      if( light_indices.w >= 2 )
-      {
-         total_light += newlight_compute_spot
-                        ( 
-                           wnormal, halfview,
-                           light_colour_1.rgb,
-                           light_co_1.xyz,
-                           light_dir_1
-                        ) * board_shadow
-                          * step( world.day_phase, light_colour_1.w );
-
-         if( light_indices.w >= 3 )
-         {
-            total_light += newlight_compute_spot
-                           ( 
-                              wnormal, halfview,
-                              light_colour_2.rgb,
-                              light_co_2.xyz,
-                              light_dir_2
-                           ) * board_shadow
-                             * step( world.day_phase, light_colour_2.w );
-         }
-      }
+      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);
+      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );
    }
 
-   vec3 fog_colour = scene_sky( -halfview, world );
+   // FIXME: this should absolutely must be clamped!
    
+   ivec3 coord = ivec3( cube_coord );
+   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );
+
+   total_light += 
+      scene_calculate_packed_light_patch( index_sample.x,
+                                          halfview, aWorldCo, wnormal ) 
+                                          * board_shadow;
+   total_light += 
+      scene_calculate_packed_light_patch( index_sample.y,
+                                          halfview, aWorldCo, wnormal )
+                                          * board_shadow;
+
+   vec3 fog_colour = scene_sky( -halfview, world );
    return scene_apply_fog( diffuse * total_light, fog_colour, fdist );
 }
index ccf416eadd9a3d88469cb89388bab31167838ebc..a3b5ae3488b7acb8e083c82ab5827800a65c97b5 100644 (file)
@@ -2,6 +2,9 @@ layout (location = 0) out vec4 oColour;
 
 layout (std140) uniform ub_world_lighting
 {
+   vec4 g_cube_min;
+   vec4 g_cube_inv_range;
+
    vec4 g_light_colours[3];
    vec4 g_light_directions[3];
    vec4 g_ambient_colour;
@@ -117,16 +120,19 @@ float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )
    return pow(max(dot( halfview, specdir ), 0.0), exponent);
 }
 
-vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, 
+vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,
                                  vec3 light_colour, vec3 light_pos )
 {
-   vec3 light_delta = (light_pos-aWorldCo) * 10.0;
+   vec3 light_delta = light_pos-aWorldCo;
 
-   float quadratic = dot(light_delta,light_delta);
-   float attenuation = 1.0f/( 1.0f + quadratic );
-   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );
+   float dist2 = dot(light_delta,light_delta);
+
+   float quadratic = dist2*100.0;
+   float attenuation  = 1.0f/( 1.0f + quadratic );
+         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );
 
-   return light_colour*attenuation;
+   float falloff = max( 0.0, 1.0-(dist2*max_dist) );
+   return light_colour * attenuation * falloff;
 }
 
 vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, 
index 2017f7db76b844a612d883e67393a0a50df45751..b5073c19796ab789dd4cd5c929e1b91658b31683 100644 (file)
@@ -88,6 +88,9 @@ static struct vg_shader _shader_model_character_view = {
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -203,16 +206,19 @@ static struct vg_shader _shader_model_character_view = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
index 2fb62ff6564cd9fa84d5cb21c294957046ec21f4..8fe64c41dd373ad3e294a3964a7139b9d801624f 100644 (file)
@@ -79,6 +79,9 @@ static struct vg_shader _shader_model_sky = {
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -194,16 +197,19 @@ static struct vg_shader _shader_model_sky = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
index f40c46147dc900a9f1c997f6338310ce962929c0..7a8db43f644d4ce52663f8a269fcf5a49fe6e15f 100644 (file)
@@ -83,12 +83,16 @@ static struct vg_shader _shader_scene_depth = {
 "flat in ivec4 light_indices;\n"
 "\n"
 "uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -204,16 +208,19 @@ static struct vg_shader _shader_scene_depth = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
@@ -234,7 +241,7 @@ static struct vg_shader _shader_scene_depth = {
 "   return light_colour*attenuation*falloff;\n"
 "}\n"
 "\n"
-"#line     12        0 \n"
+"#line     13        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"
@@ -381,7 +388,7 @@ static struct vg_shader _shader_scene_depth = {
 "}\n"
 "\n"
 "\n"
-"#line     13        0 \n"
+"#line     14        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -408,6 +415,69 @@ static struct vg_shader _shader_scene_depth = {
 "   return mix( vfrag, colour, min( 1.0, dist ) );\n"
 "}\n"
 "\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 )\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"
+"\n"
+"   return light_colour.rgb * attenuation * falloff;\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u )\n"
+"   {\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u )\n"
+"      {\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u )\n"
+"         {\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
 "   world_info world;\n"
@@ -419,85 +489,45 @@ static struct vg_shader _shader_scene_depth = {
 "   halfview /= fdist;\n"
 "\n"
 "   vec3 total_light = vec3(0.0);\n"
-"\n"
-"\n"
 "   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
-"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
+"                                    * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\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"
-"   // 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"
+"   vec3 cube_coord = (aWorldCo - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
 "\n"
 "   if( g_debug_indices == 1 )\n"
 "   {\n"
-"      float rings = min( fract(distance(light_co_0.xyz,aWorldCo)),\n"
-"                      min( fract(distance(light_co_1.xyz,aWorldCo)),\n"
-"                           fract(distance(light_co_2.xyz,aWorldCo)) ) \n"
-"                        );\n"
-"               \n"
-"      return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
-"                  fract(light_indices.z * 0.125 )) + (rings-0.5) * 0.25;\n"
+"      return rand33(cube_coord);\n"
 "   }\n"
 "\n"
 "   if( g_debug_complexity == 1 )\n"
 "   {\n"
-"      return vec3(1.0,0.0,0.0) * ( light_indices.w/3.0 );\n"
-"   }\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
 "\n"
-"   if( light_indices.w >= 1 )\n"
-"   {\n"
-"      total_light += newlight_compute_spot\n"
-"                     ( \n"
-"                        wnormal, halfview,\n"
-"                        light_colour_0.rgb,\n"
-"                        light_co_0.xyz,\n"
-"                        light_dir_0\n"
-"                     ) * board_shadow \n"
-"                       * step( world.day_phase, light_colour_0.w );\n"
-"\n"
-"      if( light_indices.w >= 2 )\n"
-"      {\n"
-"         total_light += newlight_compute_spot\n"
-"                        ( \n"
-"                           wnormal, halfview,\n"
-"                           light_colour_1.rgb,\n"
-"                           light_co_1.xyz,\n"
-"                           light_dir_1\n"
-"                        ) * board_shadow\n"
-"                          * step( world.day_phase, light_colour_1.w );\n"
-"\n"
-"         if( light_indices.w >= 3 )\n"
-"         {\n"
-"            total_light += newlight_compute_spot\n"
-"                           ( \n"
-"                              wnormal, halfview,\n"
-"                              light_colour_2.rgb,\n"
-"                              light_co_2.xyz,\n"
-"                              light_dir_2\n"
-"                           ) * board_shadow\n"
-"                             * step( world.day_phase, light_colour_2.w );\n"
-"         }\n"
-"      }\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
 "   }\n"
 "\n"
-"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   // FIXME: this should absolutely must be clamped!\n"
 "   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, aWorldCo, wnormal ) \n"
+"                                          * board_shadow;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, aWorldCo, wnormal )\n"
+"                                          * board_shadow;\n"
+"\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
 "   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
@@ -532,6 +562,7 @@ 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_uLightsIndex;
 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);
@@ -566,6 +597,7 @@ static void shader_scene_depth_link(void){
    _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_uLightsIndex = glGetUniformLocation( _shader_scene_depth.id, "uLightsIndex" );
    _uniform_scene_depth_g_world_depth = glGetUniformLocation( _shader_scene_depth.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_depth_H */
index 89669553cc90128f814b4fd2b17c630a991ad6ec..b6d51eb6b973da2c1735f4b1c05e601040abcd5a 100644 (file)
@@ -83,12 +83,16 @@ static struct vg_shader _shader_scene_position = {
 "flat in ivec4 light_indices;\n"
 "\n"
 "uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -204,16 +208,19 @@ static struct vg_shader _shader_scene_position = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
@@ -234,7 +241,7 @@ static struct vg_shader _shader_scene_position = {
 "   return light_colour*attenuation*falloff;\n"
 "}\n"
 "\n"
-"#line     12        0 \n"
+"#line     13        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"
@@ -381,7 +388,7 @@ static struct vg_shader _shader_scene_position = {
 "}\n"
 "\n"
 "\n"
-"#line     13        0 \n"
+"#line     14        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -408,6 +415,69 @@ static struct vg_shader _shader_scene_position = {
 "   return mix( vfrag, colour, min( 1.0, dist ) );\n"
 "}\n"
 "\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 )\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"
+"\n"
+"   return light_colour.rgb * attenuation * falloff;\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u )\n"
+"   {\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u )\n"
+"      {\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u )\n"
+"         {\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
 "   world_info world;\n"
@@ -419,85 +489,45 @@ static struct vg_shader _shader_scene_position = {
 "   halfview /= fdist;\n"
 "\n"
 "   vec3 total_light = vec3(0.0);\n"
-"\n"
-"\n"
 "   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
-"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
+"                                    * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\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"
-"   // 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"
+"   vec3 cube_coord = (aWorldCo - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
 "\n"
 "   if( g_debug_indices == 1 )\n"
 "   {\n"
-"      float rings = min( fract(distance(light_co_0.xyz,aWorldCo)),\n"
-"                      min( fract(distance(light_co_1.xyz,aWorldCo)),\n"
-"                           fract(distance(light_co_2.xyz,aWorldCo)) ) \n"
-"                        );\n"
-"               \n"
-"      return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
-"                  fract(light_indices.z * 0.125 )) + (rings-0.5) * 0.25;\n"
+"      return rand33(cube_coord);\n"
 "   }\n"
 "\n"
 "   if( g_debug_complexity == 1 )\n"
 "   {\n"
-"      return vec3(1.0,0.0,0.0) * ( light_indices.w/3.0 );\n"
-"   }\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
 "\n"
-"   if( light_indices.w >= 1 )\n"
-"   {\n"
-"      total_light += newlight_compute_spot\n"
-"                     ( \n"
-"                        wnormal, halfview,\n"
-"                        light_colour_0.rgb,\n"
-"                        light_co_0.xyz,\n"
-"                        light_dir_0\n"
-"                     ) * board_shadow \n"
-"                       * step( world.day_phase, light_colour_0.w );\n"
-"\n"
-"      if( light_indices.w >= 2 )\n"
-"      {\n"
-"         total_light += newlight_compute_spot\n"
-"                        ( \n"
-"                           wnormal, halfview,\n"
-"                           light_colour_1.rgb,\n"
-"                           light_co_1.xyz,\n"
-"                           light_dir_1\n"
-"                        ) * board_shadow\n"
-"                          * step( world.day_phase, light_colour_1.w );\n"
-"\n"
-"         if( light_indices.w >= 3 )\n"
-"         {\n"
-"            total_light += newlight_compute_spot\n"
-"                           ( \n"
-"                              wnormal, halfview,\n"
-"                              light_colour_2.rgb,\n"
-"                              light_co_2.xyz,\n"
-"                              light_dir_2\n"
-"                           ) * board_shadow\n"
-"                             * step( world.day_phase, light_colour_2.w );\n"
-"         }\n"
-"      }\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
 "   }\n"
 "\n"
-"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   // FIXME: this should absolutely must be clamped!\n"
 "   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, aWorldCo, wnormal ) \n"
+"                                          * board_shadow;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, aWorldCo, wnormal )\n"
+"                                          * board_shadow;\n"
+"\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
 "   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
@@ -523,6 +553,7 @@ 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_uLightsIndex;
 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);
@@ -557,6 +588,7 @@ static void shader_scene_position_link(void){
    _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_uLightsIndex = glGetUniformLocation( _shader_scene_position.id, "uLightsIndex" );
    _uniform_scene_position_g_world_depth = glGetUniformLocation( _shader_scene_position.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_position_H */
index 61c14e61336cfa8500927bdff3d00d1c001c991e..99b275f195bcfa9a2fc8d4bca4c481248f78bfeb 100644 (file)
@@ -84,12 +84,16 @@ static struct vg_shader _shader_scene_route = {
 "flat in ivec4 light_indices;\n"
 "\n"
 "uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -205,16 +209,19 @@ static struct vg_shader _shader_scene_route = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
@@ -235,7 +242,7 @@ static struct vg_shader _shader_scene_route = {
 "   return light_colour*attenuation*falloff;\n"
 "}\n"
 "\n"
-"#line     12        0 \n"
+"#line     13        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"
@@ -382,7 +389,7 @@ static struct vg_shader _shader_scene_route = {
 "}\n"
 "\n"
 "\n"
-"#line     13        0 \n"
+"#line     14        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -409,6 +416,69 @@ static struct vg_shader _shader_scene_route = {
 "   return mix( vfrag, colour, min( 1.0, dist ) );\n"
 "}\n"
 "\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 )\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"
+"\n"
+"   return light_colour.rgb * attenuation * falloff;\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u )\n"
+"   {\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u )\n"
+"      {\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u )\n"
+"         {\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
 "   world_info world;\n"
@@ -420,85 +490,45 @@ static struct vg_shader _shader_scene_route = {
 "   halfview /= fdist;\n"
 "\n"
 "   vec3 total_light = vec3(0.0);\n"
-"\n"
-"\n"
 "   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
-"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
+"                                    * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\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"
-"   // 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"
+"   vec3 cube_coord = (aWorldCo - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
 "\n"
 "   if( g_debug_indices == 1 )\n"
 "   {\n"
-"      float rings = min( fract(distance(light_co_0.xyz,aWorldCo)),\n"
-"                      min( fract(distance(light_co_1.xyz,aWorldCo)),\n"
-"                           fract(distance(light_co_2.xyz,aWorldCo)) ) \n"
-"                        );\n"
-"               \n"
-"      return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
-"                  fract(light_indices.z * 0.125 )) + (rings-0.5) * 0.25;\n"
+"      return rand33(cube_coord);\n"
 "   }\n"
 "\n"
 "   if( g_debug_complexity == 1 )\n"
 "   {\n"
-"      return vec3(1.0,0.0,0.0) * ( light_indices.w/3.0 );\n"
-"   }\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
 "\n"
-"   if( light_indices.w >= 1 )\n"
-"   {\n"
-"      total_light += newlight_compute_spot\n"
-"                     ( \n"
-"                        wnormal, halfview,\n"
-"                        light_colour_0.rgb,\n"
-"                        light_co_0.xyz,\n"
-"                        light_dir_0\n"
-"                     ) * board_shadow \n"
-"                       * step( world.day_phase, light_colour_0.w );\n"
-"\n"
-"      if( light_indices.w >= 2 )\n"
-"      {\n"
-"         total_light += newlight_compute_spot\n"
-"                        ( \n"
-"                           wnormal, halfview,\n"
-"                           light_colour_1.rgb,\n"
-"                           light_co_1.xyz,\n"
-"                           light_dir_1\n"
-"                        ) * board_shadow\n"
-"                          * step( world.day_phase, light_colour_1.w );\n"
-"\n"
-"         if( light_indices.w >= 3 )\n"
-"         {\n"
-"            total_light += newlight_compute_spot\n"
-"                           ( \n"
-"                              wnormal, halfview,\n"
-"                              light_colour_2.rgb,\n"
-"                              light_co_2.xyz,\n"
-"                              light_dir_2\n"
-"                           ) * board_shadow\n"
-"                             * step( world.day_phase, light_colour_2.w );\n"
-"         }\n"
-"      }\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
 "   }\n"
 "\n"
-"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   // FIXME: this should absolutely must be clamped!\n"
 "   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, aWorldCo, wnormal ) \n"
+"                                          * board_shadow;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, aWorldCo, wnormal )\n"
+"                                          * board_shadow;\n"
+"\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
 "   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
@@ -574,6 +604,7 @@ 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_uLightsIndex;
 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);
@@ -620,6 +651,7 @@ static void shader_scene_route_link(void){
    _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_uLightsIndex = glGetUniformLocation( _shader_scene_route.id, "uLightsIndex" );
    _uniform_scene_route_g_world_depth = glGetUniformLocation( _shader_scene_route.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_route_H */
index a385437d445fb1157eab620ee8d350a2c72f19fb..4948da5c883e8934f6c54e54aa328869a532967a 100644 (file)
@@ -84,12 +84,16 @@ static struct vg_shader _shader_scene_standard = {
 "flat in ivec4 light_indices;\n"
 "\n"
 "uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -205,16 +209,19 @@ static struct vg_shader _shader_scene_standard = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
@@ -235,7 +242,7 @@ static struct vg_shader _shader_scene_standard = {
 "   return light_colour*attenuation*falloff;\n"
 "}\n"
 "\n"
-"#line     12        0 \n"
+"#line     13        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"
@@ -382,7 +389,7 @@ static struct vg_shader _shader_scene_standard = {
 "}\n"
 "\n"
 "\n"
-"#line     13        0 \n"
+"#line     14        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -409,6 +416,69 @@ static struct vg_shader _shader_scene_standard = {
 "   return mix( vfrag, colour, min( 1.0, dist ) );\n"
 "}\n"
 "\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 )\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"
+"\n"
+"   return light_colour.rgb * attenuation * falloff;\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u )\n"
+"   {\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u )\n"
+"      {\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u )\n"
+"         {\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
 "   world_info world;\n"
@@ -420,85 +490,45 @@ static struct vg_shader _shader_scene_standard = {
 "   halfview /= fdist;\n"
 "\n"
 "   vec3 total_light = vec3(0.0);\n"
-"\n"
-"\n"
 "   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
-"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
+"                                    * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\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"
-"   // 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"
+"   vec3 cube_coord = (aWorldCo - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
 "\n"
 "   if( g_debug_indices == 1 )\n"
 "   {\n"
-"      float rings = min( fract(distance(light_co_0.xyz,aWorldCo)),\n"
-"                      min( fract(distance(light_co_1.xyz,aWorldCo)),\n"
-"                           fract(distance(light_co_2.xyz,aWorldCo)) ) \n"
-"                        );\n"
-"               \n"
-"      return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
-"                  fract(light_indices.z * 0.125 )) + (rings-0.5) * 0.25;\n"
+"      return rand33(cube_coord);\n"
 "   }\n"
 "\n"
 "   if( g_debug_complexity == 1 )\n"
 "   {\n"
-"      return vec3(1.0,0.0,0.0) * ( light_indices.w/3.0 );\n"
-"   }\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
 "\n"
-"   if( light_indices.w >= 1 )\n"
-"   {\n"
-"      total_light += newlight_compute_spot\n"
-"                     ( \n"
-"                        wnormal, halfview,\n"
-"                        light_colour_0.rgb,\n"
-"                        light_co_0.xyz,\n"
-"                        light_dir_0\n"
-"                     ) * board_shadow \n"
-"                       * step( world.day_phase, light_colour_0.w );\n"
-"\n"
-"      if( light_indices.w >= 2 )\n"
-"      {\n"
-"         total_light += newlight_compute_spot\n"
-"                        ( \n"
-"                           wnormal, halfview,\n"
-"                           light_colour_1.rgb,\n"
-"                           light_co_1.xyz,\n"
-"                           light_dir_1\n"
-"                        ) * board_shadow\n"
-"                          * step( world.day_phase, light_colour_1.w );\n"
-"\n"
-"         if( light_indices.w >= 3 )\n"
-"         {\n"
-"            total_light += newlight_compute_spot\n"
-"                           ( \n"
-"                              wnormal, halfview,\n"
-"                              light_colour_2.rgb,\n"
-"                              light_co_2.xyz,\n"
-"                              light_dir_2\n"
-"                           ) * board_shadow\n"
-"                             * step( world.day_phase, light_colour_2.w );\n"
-"         }\n"
-"      }\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
 "   }\n"
 "\n"
-"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   // FIXME: this should absolutely must be clamped!\n"
 "   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, aWorldCo, wnormal ) \n"
+"                                          * board_shadow;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, aWorldCo, wnormal )\n"
+"                                          * board_shadow;\n"
+"\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
 "   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
@@ -555,6 +585,7 @@ 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_uLightsIndex;
 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);
@@ -601,6 +632,7 @@ static void shader_scene_standard_link(void){
    _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_uLightsIndex = glGetUniformLocation( _shader_scene_standard.id, "uLightsIndex" );
    _uniform_scene_standard_g_world_depth = glGetUniformLocation( _shader_scene_standard.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_standard_H */
index 46c1976a7933631ca933439b49578fc4ee4e78cf..5cab9a80321f73403d266eddffd0b14d397a18a1 100644 (file)
@@ -84,12 +84,16 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "flat in ivec4 light_indices;\n"
 "\n"
 "uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -205,16 +209,19 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
@@ -235,7 +242,7 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   return light_colour*attenuation*falloff;\n"
 "}\n"
 "\n"
-"#line     12        0 \n"
+"#line     13        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"
@@ -382,7 +389,7 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "}\n"
 "\n"
 "\n"
-"#line     13        0 \n"
+"#line     14        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -409,6 +416,69 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   return mix( vfrag, colour, min( 1.0, dist ) );\n"
 "}\n"
 "\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 )\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"
+"\n"
+"   return light_colour.rgb * attenuation * falloff;\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u )\n"
+"   {\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u )\n"
+"      {\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u )\n"
+"         {\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
 "   world_info world;\n"
@@ -420,85 +490,45 @@ static struct vg_shader _shader_scene_standard_alphatest = {
 "   halfview /= fdist;\n"
 "\n"
 "   vec3 total_light = vec3(0.0);\n"
-"\n"
-"\n"
 "   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
-"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
+"                                    * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\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"
-"   // 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"
+"   vec3 cube_coord = (aWorldCo - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
 "\n"
 "   if( g_debug_indices == 1 )\n"
 "   {\n"
-"      float rings = min( fract(distance(light_co_0.xyz,aWorldCo)),\n"
-"                      min( fract(distance(light_co_1.xyz,aWorldCo)),\n"
-"                           fract(distance(light_co_2.xyz,aWorldCo)) ) \n"
-"                        );\n"
-"               \n"
-"      return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
-"                  fract(light_indices.z * 0.125 )) + (rings-0.5) * 0.25;\n"
+"      return rand33(cube_coord);\n"
 "   }\n"
 "\n"
 "   if( g_debug_complexity == 1 )\n"
 "   {\n"
-"      return vec3(1.0,0.0,0.0) * ( light_indices.w/3.0 );\n"
-"   }\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
 "\n"
-"   if( light_indices.w >= 1 )\n"
-"   {\n"
-"      total_light += newlight_compute_spot\n"
-"                     ( \n"
-"                        wnormal, halfview,\n"
-"                        light_colour_0.rgb,\n"
-"                        light_co_0.xyz,\n"
-"                        light_dir_0\n"
-"                     ) * board_shadow \n"
-"                       * step( world.day_phase, light_colour_0.w );\n"
-"\n"
-"      if( light_indices.w >= 2 )\n"
-"      {\n"
-"         total_light += newlight_compute_spot\n"
-"                        ( \n"
-"                           wnormal, halfview,\n"
-"                           light_colour_1.rgb,\n"
-"                           light_co_1.xyz,\n"
-"                           light_dir_1\n"
-"                        ) * board_shadow\n"
-"                          * step( world.day_phase, light_colour_1.w );\n"
-"\n"
-"         if( light_indices.w >= 3 )\n"
-"         {\n"
-"            total_light += newlight_compute_spot\n"
-"                           ( \n"
-"                              wnormal, halfview,\n"
-"                              light_colour_2.rgb,\n"
-"                              light_co_2.xyz,\n"
-"                              light_dir_2\n"
-"                           ) * board_shadow\n"
-"                             * step( world.day_phase, light_colour_2.w );\n"
-"         }\n"
-"      }\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
 "   }\n"
 "\n"
-"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   // FIXME: this should absolutely must be clamped!\n"
 "   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, aWorldCo, wnormal ) \n"
+"                                          * board_shadow;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, aWorldCo, wnormal )\n"
+"                                          * board_shadow;\n"
+"\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
 "   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
@@ -558,6 +588,7 @@ 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_uLightsIndex;
 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);
@@ -604,6 +635,7 @@ static void shader_scene_standard_alphatest_link(void){
    _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_uLightsIndex = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uLightsIndex" );
    _uniform_scene_standard_alphatest_g_world_depth = glGetUniformLocation( _shader_scene_standard_alphatest.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_standard_alphatest_H */
index da847978891afe57102c4689d151095c28abad64..871d0d6724290b5768eaf499ce53234b23be4c86 100644 (file)
@@ -85,12 +85,16 @@ static struct vg_shader _shader_scene_terrain = {
 "flat in ivec4 light_indices;\n"
 "\n"
 "uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -206,16 +210,19 @@ static struct vg_shader _shader_scene_terrain = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
@@ -236,7 +243,7 @@ static struct vg_shader _shader_scene_terrain = {
 "   return light_colour*attenuation*falloff;\n"
 "}\n"
 "\n"
-"#line     12        0 \n"
+"#line     13        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"
@@ -383,7 +390,7 @@ static struct vg_shader _shader_scene_terrain = {
 "}\n"
 "\n"
 "\n"
-"#line     13        0 \n"
+"#line     14        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -410,6 +417,69 @@ static struct vg_shader _shader_scene_terrain = {
 "   return mix( vfrag, colour, min( 1.0, dist ) );\n"
 "}\n"
 "\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 )\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"
+"\n"
+"   return light_colour.rgb * attenuation * falloff;\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u )\n"
+"   {\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u )\n"
+"      {\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u )\n"
+"         {\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
 "   world_info world;\n"
@@ -421,85 +491,45 @@ static struct vg_shader _shader_scene_terrain = {
 "   halfview /= fdist;\n"
 "\n"
 "   vec3 total_light = vec3(0.0);\n"
-"\n"
-"\n"
 "   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
-"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
+"                                    * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\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"
-"   // 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"
+"   vec3 cube_coord = (aWorldCo - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
 "\n"
 "   if( g_debug_indices == 1 )\n"
 "   {\n"
-"      float rings = min( fract(distance(light_co_0.xyz,aWorldCo)),\n"
-"                      min( fract(distance(light_co_1.xyz,aWorldCo)),\n"
-"                           fract(distance(light_co_2.xyz,aWorldCo)) ) \n"
-"                        );\n"
-"               \n"
-"      return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
-"                  fract(light_indices.z * 0.125 )) + (rings-0.5) * 0.25;\n"
+"      return rand33(cube_coord);\n"
 "   }\n"
 "\n"
 "   if( g_debug_complexity == 1 )\n"
 "   {\n"
-"      return vec3(1.0,0.0,0.0) * ( light_indices.w/3.0 );\n"
-"   }\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
 "\n"
-"   if( light_indices.w >= 1 )\n"
-"   {\n"
-"      total_light += newlight_compute_spot\n"
-"                     ( \n"
-"                        wnormal, halfview,\n"
-"                        light_colour_0.rgb,\n"
-"                        light_co_0.xyz,\n"
-"                        light_dir_0\n"
-"                     ) * board_shadow \n"
-"                       * step( world.day_phase, light_colour_0.w );\n"
-"\n"
-"      if( light_indices.w >= 2 )\n"
-"      {\n"
-"         total_light += newlight_compute_spot\n"
-"                        ( \n"
-"                           wnormal, halfview,\n"
-"                           light_colour_1.rgb,\n"
-"                           light_co_1.xyz,\n"
-"                           light_dir_1\n"
-"                        ) * board_shadow\n"
-"                          * step( world.day_phase, light_colour_1.w );\n"
-"\n"
-"         if( light_indices.w >= 3 )\n"
-"         {\n"
-"            total_light += newlight_compute_spot\n"
-"                           ( \n"
-"                              wnormal, halfview,\n"
-"                              light_colour_2.rgb,\n"
-"                              light_co_2.xyz,\n"
-"                              light_dir_2\n"
-"                           ) * board_shadow\n"
-"                             * step( world.day_phase, light_colour_2.w );\n"
-"         }\n"
-"      }\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
 "   }\n"
 "\n"
-"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   // FIXME: this should absolutely must be clamped!\n"
 "   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, aWorldCo, wnormal ) \n"
+"                                          * board_shadow;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, aWorldCo, wnormal )\n"
+"                                          * board_shadow;\n"
+"\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
 "   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
@@ -579,6 +609,7 @@ 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_uLightsIndex;
 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);
@@ -629,6 +660,7 @@ static void shader_scene_terrain_link(void){
    _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_uLightsIndex = glGetUniformLocation( _shader_scene_terrain.id, "uLightsIndex" );
    _uniform_scene_terrain_g_world_depth = glGetUniformLocation( _shader_scene_terrain.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_terrain_H */
index 097046fe397afbb628d7e7472c27d9a35d6caa04..60945cd4d59730a7bf3fcdef07dba12a37c5105a 100644 (file)
@@ -83,12 +83,16 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "flat in ivec4 light_indices;\n"
 "\n"
 "uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -204,16 +208,19 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
@@ -234,7 +241,7 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   return light_colour*attenuation*falloff;\n"
 "}\n"
 "\n"
-"#line     12        0 \n"
+"#line     13        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"
@@ -381,7 +388,7 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "}\n"
 "\n"
 "\n"
-"#line     13        0 \n"
+"#line     14        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -408,6 +415,69 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   return mix( vfrag, colour, min( 1.0, dist ) );\n"
 "}\n"
 "\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 )\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"
+"\n"
+"   return light_colour.rgb * attenuation * falloff;\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u )\n"
+"   {\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u )\n"
+"      {\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u )\n"
+"         {\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
 "   world_info world;\n"
@@ -419,85 +489,45 @@ static struct vg_shader _shader_scene_vertex_blend = {
 "   halfview /= fdist;\n"
 "\n"
 "   vec3 total_light = vec3(0.0);\n"
-"\n"
-"\n"
 "   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
-"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
+"                                    * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\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"
-"   // 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"
+"   vec3 cube_coord = (aWorldCo - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
 "\n"
 "   if( g_debug_indices == 1 )\n"
 "   {\n"
-"      float rings = min( fract(distance(light_co_0.xyz,aWorldCo)),\n"
-"                      min( fract(distance(light_co_1.xyz,aWorldCo)),\n"
-"                           fract(distance(light_co_2.xyz,aWorldCo)) ) \n"
-"                        );\n"
-"               \n"
-"      return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
-"                  fract(light_indices.z * 0.125 )) + (rings-0.5) * 0.25;\n"
+"      return rand33(cube_coord);\n"
 "   }\n"
 "\n"
 "   if( g_debug_complexity == 1 )\n"
 "   {\n"
-"      return vec3(1.0,0.0,0.0) * ( light_indices.w/3.0 );\n"
-"   }\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
 "\n"
-"   if( light_indices.w >= 1 )\n"
-"   {\n"
-"      total_light += newlight_compute_spot\n"
-"                     ( \n"
-"                        wnormal, halfview,\n"
-"                        light_colour_0.rgb,\n"
-"                        light_co_0.xyz,\n"
-"                        light_dir_0\n"
-"                     ) * board_shadow \n"
-"                       * step( world.day_phase, light_colour_0.w );\n"
-"\n"
-"      if( light_indices.w >= 2 )\n"
-"      {\n"
-"         total_light += newlight_compute_spot\n"
-"                        ( \n"
-"                           wnormal, halfview,\n"
-"                           light_colour_1.rgb,\n"
-"                           light_co_1.xyz,\n"
-"                           light_dir_1\n"
-"                        ) * board_shadow\n"
-"                          * step( world.day_phase, light_colour_1.w );\n"
-"\n"
-"         if( light_indices.w >= 3 )\n"
-"         {\n"
-"            total_light += newlight_compute_spot\n"
-"                           ( \n"
-"                              wnormal, halfview,\n"
-"                              light_colour_2.rgb,\n"
-"                              light_co_2.xyz,\n"
-"                              light_dir_2\n"
-"                           ) * board_shadow\n"
-"                             * step( world.day_phase, light_colour_2.w );\n"
-"         }\n"
-"      }\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
 "   }\n"
 "\n"
-"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   // FIXME: this should absolutely must be clamped!\n"
 "   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, aWorldCo, wnormal ) \n"
+"                                          * board_shadow;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, aWorldCo, wnormal )\n"
+"                                          * board_shadow;\n"
+"\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
 "   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
@@ -571,6 +601,7 @@ 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_uLightsIndex;
 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);
@@ -613,6 +644,7 @@ static void shader_scene_vertex_blend_link(void){
    _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_uLightsIndex = glGetUniformLocation( _shader_scene_vertex_blend.id, "uLightsIndex" );
    _uniform_scene_vertex_blend_g_world_depth = glGetUniformLocation( _shader_scene_vertex_blend.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_vertex_blend_H */
index e9e052b4798bb60d5ba5542edb92dc63ca3d5c29..3eceda04e65d0aeb4a1b9970d85daac5febf809b 100644 (file)
@@ -91,12 +91,16 @@ static struct vg_shader _shader_scene_water = {
 "flat in ivec4 light_indices;\n"
 "\n"
 "uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -212,16 +216,19 @@ static struct vg_shader _shader_scene_water = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
@@ -242,7 +249,7 @@ static struct vg_shader _shader_scene_water = {
 "   return light_colour*attenuation*falloff;\n"
 "}\n"
 "\n"
-"#line     12        0 \n"
+"#line     13        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"
@@ -389,7 +396,7 @@ static struct vg_shader _shader_scene_water = {
 "}\n"
 "\n"
 "\n"
-"#line     13        0 \n"
+"#line     14        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -416,6 +423,69 @@ static struct vg_shader _shader_scene_water = {
 "   return mix( vfrag, colour, min( 1.0, dist ) );\n"
 "}\n"
 "\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 )\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"
+"\n"
+"   return light_colour.rgb * attenuation * falloff;\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u )\n"
+"   {\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u )\n"
+"      {\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u )\n"
+"         {\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
 "   world_info world;\n"
@@ -427,85 +497,45 @@ static struct vg_shader _shader_scene_water = {
 "   halfview /= fdist;\n"
 "\n"
 "   vec3 total_light = vec3(0.0);\n"
-"\n"
-"\n"
 "   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
-"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
+"                                    * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\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"
-"   // 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"
+"   vec3 cube_coord = (aWorldCo - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
 "\n"
 "   if( g_debug_indices == 1 )\n"
 "   {\n"
-"      float rings = min( fract(distance(light_co_0.xyz,aWorldCo)),\n"
-"                      min( fract(distance(light_co_1.xyz,aWorldCo)),\n"
-"                           fract(distance(light_co_2.xyz,aWorldCo)) ) \n"
-"                        );\n"
-"               \n"
-"      return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
-"                  fract(light_indices.z * 0.125 )) + (rings-0.5) * 0.25;\n"
+"      return rand33(cube_coord);\n"
 "   }\n"
 "\n"
 "   if( g_debug_complexity == 1 )\n"
 "   {\n"
-"      return vec3(1.0,0.0,0.0) * ( light_indices.w/3.0 );\n"
-"   }\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
 "\n"
-"   if( light_indices.w >= 1 )\n"
-"   {\n"
-"      total_light += newlight_compute_spot\n"
-"                     ( \n"
-"                        wnormal, halfview,\n"
-"                        light_colour_0.rgb,\n"
-"                        light_co_0.xyz,\n"
-"                        light_dir_0\n"
-"                     ) * board_shadow \n"
-"                       * step( world.day_phase, light_colour_0.w );\n"
-"\n"
-"      if( light_indices.w >= 2 )\n"
-"      {\n"
-"         total_light += newlight_compute_spot\n"
-"                        ( \n"
-"                           wnormal, halfview,\n"
-"                           light_colour_1.rgb,\n"
-"                           light_co_1.xyz,\n"
-"                           light_dir_1\n"
-"                        ) * board_shadow\n"
-"                          * step( world.day_phase, light_colour_1.w );\n"
-"\n"
-"         if( light_indices.w >= 3 )\n"
-"         {\n"
-"            total_light += newlight_compute_spot\n"
-"                           ( \n"
-"                              wnormal, halfview,\n"
-"                              light_colour_2.rgb,\n"
-"                              light_co_2.xyz,\n"
-"                              light_dir_2\n"
-"                           ) * board_shadow\n"
-"                             * step( world.day_phase, light_colour_2.w );\n"
-"         }\n"
-"      }\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
 "   }\n"
 "\n"
-"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   // FIXME: this should absolutely must be clamped!\n"
 "   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, aWorldCo, wnormal ) \n"
+"                                          * board_shadow;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, aWorldCo, wnormal )\n"
+"                                          * board_shadow;\n"
+"\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
 "   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
@@ -608,6 +638,7 @@ 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_uLightsIndex;
 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);
@@ -674,6 +705,7 @@ static void shader_scene_water_link(void){
    _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_uLightsIndex = glGetUniformLocation( _shader_scene_water.id, "uLightsIndex" );
    _uniform_scene_water_g_world_depth = glGetUniformLocation( _shader_scene_water.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_water_H */
index bab38cd07110035514c9cc33225dda8181a37741..1bd4ed64d22c14dd43e498fd5c6e207e6bac9d66 100644 (file)
@@ -88,12 +88,16 @@ static struct vg_shader _shader_scene_water_fast = {
 "flat in ivec4 light_indices;\n"
 "\n"
 "uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
 "\n"
 "#line       1        1 \n"
 "layout (location = 0) out vec4 oColour;\n"
 "\n"
 "layout (std140) uniform ub_world_lighting\n"
 "{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
 "   vec4 g_light_colours[3];\n"
 "   vec4 g_light_directions[3];\n"
 "   vec4 g_ambient_colour;\n"
@@ -209,16 +213,19 @@ static struct vg_shader _shader_scene_water_fast = {
 "   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
 "}\n"
 "\n"
-"vec3 newlight_compute_quadratic( vec3 wnormal, vec3 halfview, \n"
+"vec3 newlight_compute_quadratic( vec3 wnormal, float max_dist,\n"
 "                                 vec3 light_colour, vec3 light_pos )\n"
 "{\n"
-"   vec3 light_delta = (light_pos-aWorldCo) * 10.0;\n"
+"   vec3 light_delta = light_pos-aWorldCo;\n"
 "\n"
-"   float quadratic = dot(light_delta,light_delta);\n"
-"   float attenuation = 1.0f/( 1.0f + quadratic );\n"
-"   attenuation *= max( 0.0, dot( normalize(light_delta), wnormal ) );\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
 "\n"
-"   return light_colour*attenuation;\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( normalize(light_delta), wnormal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*max_dist) );\n"
+"   return light_colour * attenuation * falloff;\n"
 "}\n"
 "\n"
 "vec3 newlight_compute_spot( vec3 wnormal, vec3 halfview, \n"
@@ -239,7 +246,7 @@ static struct vg_shader _shader_scene_water_fast = {
 "   return light_colour*attenuation*falloff;\n"
 "}\n"
 "\n"
-"#line     12        0 \n"
+"#line     13        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"
@@ -386,7 +393,7 @@ static struct vg_shader _shader_scene_water_fast = {
 "}\n"
 "\n"
 "\n"
-"#line     13        0 \n"
+"#line     14        0 \n"
 "\n"
 "float sdLine( vec3 p, vec3 a, vec3 b )\n"
 "{\n"
@@ -413,6 +420,69 @@ static struct vg_shader _shader_scene_water_fast = {
 "   return mix( vfrag, colour, min( 1.0, dist ) );\n"
 "}\n"
 "\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0f/( 1.0f + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 )\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"
+"\n"
+"   return light_colour.rgb * attenuation * falloff;\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u )\n"
+"   {\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u )\n"
+"      {\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u )\n"
+"         {\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
 "vec3 scene_do_lighting( vec3 diffuse, vec3 wnormal )\n"
 "{\n"
 "   world_info world;\n"
@@ -424,85 +494,45 @@ static struct vg_shader _shader_scene_water_fast = {
 "   halfview /= fdist;\n"
 "\n"
 "   vec3 total_light = vec3(0.0);\n"
-"\n"
-"\n"
 "   float world_shadow = newlight_compute_sun_shadow( world.sun_dir \n"
-"                                          * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
+"                                    * (1.0/(max(world.sun_dir.y,0.0)+0.2)) );\n"
 "   float board_shadow = compute_board_shadow();\n"
 "\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"
-"   // 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"
+"   vec3 cube_coord = (aWorldCo - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
 "\n"
 "   if( g_debug_indices == 1 )\n"
 "   {\n"
-"      float rings = min( fract(distance(light_co_0.xyz,aWorldCo)),\n"
-"                      min( fract(distance(light_co_1.xyz,aWorldCo)),\n"
-"                           fract(distance(light_co_2.xyz,aWorldCo)) ) \n"
-"                        );\n"
-"               \n"
-"      return vec3(fract(light_indices.x * 0.125), fract(light_indices.y*0.125),\n"
-"                  fract(light_indices.z * 0.125 )) + (rings-0.5) * 0.25;\n"
+"      return rand33(cube_coord);\n"
 "   }\n"
 "\n"
 "   if( g_debug_complexity == 1 )\n"
 "   {\n"
-"      return vec3(1.0,0.0,0.0) * ( light_indices.w/3.0 );\n"
-"   }\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
 "\n"
-"   if( light_indices.w >= 1 )\n"
-"   {\n"
-"      total_light += newlight_compute_spot\n"
-"                     ( \n"
-"                        wnormal, halfview,\n"
-"                        light_colour_0.rgb,\n"
-"                        light_co_0.xyz,\n"
-"                        light_dir_0\n"
-"                     ) * board_shadow \n"
-"                       * step( world.day_phase, light_colour_0.w );\n"
-"\n"
-"      if( light_indices.w >= 2 )\n"
-"      {\n"
-"         total_light += newlight_compute_spot\n"
-"                        ( \n"
-"                           wnormal, halfview,\n"
-"                           light_colour_1.rgb,\n"
-"                           light_co_1.xyz,\n"
-"                           light_dir_1\n"
-"                        ) * board_shadow\n"
-"                          * step( world.day_phase, light_colour_1.w );\n"
-"\n"
-"         if( light_indices.w >= 3 )\n"
-"         {\n"
-"            total_light += newlight_compute_spot\n"
-"                           ( \n"
-"                              wnormal, halfview,\n"
-"                              light_colour_2.rgb,\n"
-"                              light_co_2.xyz,\n"
-"                              light_dir_2\n"
-"                           ) * board_shadow\n"
-"                             * step( world.day_phase, light_colour_2.w );\n"
-"         }\n"
-"      }\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
 "   }\n"
 "\n"
-"   vec3 fog_colour = scene_sky( -halfview, world );\n"
+"   // FIXME: this should absolutely must be clamped!\n"
 "   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, aWorldCo, wnormal ) \n"
+"                                          * board_shadow;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, aWorldCo, wnormal )\n"
+"                                          * board_shadow;\n"
+"\n"
+"   vec3 fog_colour = scene_sky( -halfview, world );\n"
 "   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
 "}\n"
 "\n"
@@ -586,6 +616,7 @@ 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_uLightsIndex;
 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);
@@ -640,6 +671,7 @@ static void shader_scene_water_fast_link(void){
    _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_uLightsIndex = glGetUniformLocation( _shader_scene_water_fast.id, "uLightsIndex" );
    _uniform_scene_water_fast_g_world_depth = glGetUniformLocation( _shader_scene_water_fast.id, "g_world_depth" );
 }
 #endif /* SHADER_scene_water_fast_H */
index b0324cc7facb93a1fcc64f15f8d40d143ddeba7e..a410301d171e836ae82697678606ce19a4941ef2 100644 (file)
@@ -257,13 +257,10 @@ VG_STATIC void vg_load(void)
    world_audio_init();
 
    /* 'systems' are completely loaded now */
-#if 0
-   strcpy( world.world_name, "maps/mp_mtzero.mdl" );
-   strcpy( world.world_name, "maps/mp_gridmap.mdl" );
-#endif
 
    /* load home world */
    world_load( &world_global.worlds[0], "maps/mp_home.mdl" );
+
    world_load( &world_global.worlds[1], "maps/mp_gridmap.mdl" );
    world_load( &world_global.worlds[2], "maps/mp_mtzero.mdl" );
    world_link_nonlocal_gates( 0, 1 );
diff --git a/world.h b/world.h
index ef935968257fd422b9be0f7f592c332fcefbdb55..cfa809c4dfe2d852ecf9af9edf0ba07bd0b3d3e6 100644 (file)
--- a/world.h
+++ b/world.h
@@ -53,6 +53,8 @@ enum geo_type
    k_geo_type_water = 2
 };
 
+static const float k_light_cube_size = 8.0f;
+
 struct world_instance 
 {
    /* This is a small flag we use to changelevel.
@@ -79,6 +81,9 @@ struct world_instance
    /* STD140 */
    struct ub_world_lighting
    {
+      v4f g_cube_min,
+          g_cube_inv_range;
+
       /* v3f (padded) */
       v4f g_light_colours[3],
           g_light_directions[3],
@@ -106,7 +111,10 @@ struct world_instance
    int    ubo_bind_point;
 
    GLuint tbo_light_entities,
-          tex_light_entities;
+          tex_light_entities,
+          tex_light_cubes;
+
+   v3i light_cubes;
 
    struct framebuffer heightmap;
 
@@ -216,6 +224,8 @@ struct world_instance
    {
       mdl_node *node;
       struct classtype_world_light *inf;
+      m4x3f inverse_world;
+      v2f angle_sin_cos;
 
       /* enabled.. etc? 
        * TODO: we should order entities in the binary by their type */
index 026701a1bf89148d574543fe9c4120b4d70438ec..fea44fc8d9ded2926860f1c83410a9e2c9fd98da 100644 (file)
@@ -340,6 +340,13 @@ VG_STATIC void world_pct_world_light( world_instance *world, mdl_node *pnode )
    struct world_light *light = &world->lights[ world->light_count ++ ];
    light->node = pnode;
    light->inf  = mdl_get_entdata( world->meta, pnode );
+
+   q_m3x3( pnode->q,   light->inverse_world );
+   v3_copy( pnode->co, light->inverse_world[3] );
+   m4x3_invert_affine( light->inverse_world, light->inverse_world );
+
+   light->angle_sin_cos[0] = sinf( light->inf->angle * 0.5f );
+   light->angle_sin_cos[1] = cosf( light->inf->angle * 0.5f );
 }
 
 VG_STATIC void world_pct_nonlocal_gate( world_instance *world, mdl_node *pnode )
@@ -615,6 +622,19 @@ VG_STATIC void world_generate( world_instance *world )
    world->scene_no_collide = NULL;
 }
 
+float fsd_cone_infinite( v3f p, v2f c )
+{
+   v2f q = { v2_length( (v2f){ p[0], p[2] } ), -p[1] };
+   float s = vg_maxf( 0.0f, v2_dot( q, c ) );
+
+   v2f v0;
+   v2_muls( c, s, v0 );
+   v2_sub( q, v0, v0 );
+
+   float d = v2_length( v0 );
+   return d * ((q[0]*c[1]-q[1]*c[0]<0.0f)?-1.0f:1.0f);
+}
+
 VG_STATIC int reset_player( int argc, char const *argv[] );
 VG_STATIC void world_post_process( world_instance *world )
 {
@@ -651,9 +671,9 @@ VG_STATIC void world_post_process( world_instance *world )
       
       /* buffer layout
        *  
-       *  colour               position         direction (spots)
-       * | .   .   .   .     | .   .   .   .  | .   .   .   .  |
-       * | Re  Ge  Be  Night | Xco Yco Zco    | Dx  Dy  Dz  Da |
+       *  colour               position                direction (spots)
+       * | .   .   .   .     | .   .   .   .         | .   .   .   .  |
+       * | Re  Ge  Be  Night | Xco Yco Zco Range     | Dx  Dy  Dz  Da |
        *
        */
 
@@ -666,7 +686,7 @@ VG_STATIC void world_post_process( world_instance *world )
 
          /* colour  + night */
          v3_muls( inf->colour, inf->colour[3] * 2.0f, light_dst[i*3+0] );
-         light_dst[i*3+0][3] = 0.0f;
+         light_dst[i*3+0][3] = -1.0f;
 
          if( (inf->type == k_light_type_spot_nighttime_only) ||
              (inf->type == k_light_type_point_nighttime_only ) )
@@ -678,12 +698,13 @@ VG_STATIC void world_post_process( world_instance *world )
             light_dst[i*3+0][3] = 0.44f + switch_on * 0.015f;
          }
          
-         /* position + nothing */
+         /* position + 1/range^2 */
          v3_copy( light->node->co, light_dst[i*3+1] );
+         light_dst[i*3+1][3] = 1.0f/(inf->range*inf->range);
 
          /* 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;
+         light_dst[i*3+2][3] = cosf( inf->angle );
       }
 
       glUnmapBuffer( GL_TEXTURE_BUFFER );
@@ -706,11 +727,6 @@ VG_STATIC void world_post_process( world_instance *world )
       info_vec[3] = 1.0f/ (bounds[1][2]-bounds[0][2]);
       v4_copy( info_vec, world->ub_lighting.g_depth_bounds );
 
-      /* upload full buffer */
-      glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
-      glBufferSubData( GL_UNIFORM_BUFFER, 0, 
-                       sizeof(struct ub_world_lighting), &world->ub_lighting );
-
 
       /* 
        * Rendering the depth map
@@ -755,6 +771,187 @@ VG_STATIC void world_post_process( world_instance *world )
       glEnable(GL_DEPTH_TEST);
       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
 
+
+
+
+      /* light cubes */
+      
+      v3f cubes_min, cubes_max;
+      v3_muls( world->scene_geo->bbx[0], 1.0f/k_light_cube_size, cubes_min );
+      v3_muls( world->scene_geo->bbx[1], 1.0f/k_light_cube_size, cubes_max );
+
+      v3_sub( cubes_min, (v3f){ 0.5f, 0.5f, 0.5f }, cubes_min );
+      v3_add( cubes_max, (v3f){ 0.5f, 0.5f, 0.5f }, cubes_max );
+
+      v3_floor( cubes_min, cubes_min );
+      v3_floor( cubes_max, cubes_max );
+
+      v3i icubes_min, icubes_max;
+
+      for( int i=0; i<3; i++ )
+      {
+         icubes_min[i] = cubes_min[i];
+         icubes_max[i] = cubes_max[i];
+      }
+
+      v3i icubes_count;
+      v3i_sub( icubes_max, icubes_min, icubes_count );
+      
+      for( int i=0; i<3; i++ )
+      {
+         icubes_count[i] = VG_MIN( 128, icubes_count[i]+1 );
+         cubes_max[i] = icubes_min[i] + icubes_count[i];
+      }
+
+      v3_muls( cubes_min, k_light_cube_size, cubes_min );
+      v3_muls( cubes_max, k_light_cube_size, cubes_max );
+
+      for( int i=0; i<3; i++ )
+      {
+         float range = cubes_max[i]-cubes_min[i];
+         world->ub_lighting.g_cube_inv_range[i] = 1.0f / range;
+         world->ub_lighting.g_cube_inv_range[i] *= (float)icubes_count[i];
+
+         vg_info( "cubes[%d]: %d\n", i, icubes_count[i] );
+      }
+
+      int total_cubes = icubes_count[0]*icubes_count[1]*icubes_count[2];
+
+      u32 *cubes_index = vg_linear_alloc( world_global.generic_heap, 
+                                          total_cubes * sizeof(u32) * 2.0f );
+                                          
+      vg_info( "Computing light cubes (%d) [%f %f %f] -> [%f %f %f]\n", 
+                total_cubes, cubes_min[0], -cubes_min[2], cubes_min[1],
+                             cubes_max[0], -cubes_max[2], cubes_max[1] );
+
+      v3_copy( cubes_min, world->ub_lighting.g_cube_min );
+
+      vg_info( "g_cube_min[%f %f %f]\n", 
+                  world->ub_lighting.g_cube_min[0],
+                  world->ub_lighting.g_cube_min[1],
+                  world->ub_lighting.g_cube_min[2] );
+      vg_info( "g_cube_inv_range[%f %f %f]\n", 
+                  world->ub_lighting.g_cube_inv_range[0],
+                  world->ub_lighting.g_cube_inv_range[1],
+                  world->ub_lighting.g_cube_inv_range[2] );
+
+      v3f cube_size;
+      v3_div( (v3f){1.0f,1.0f,1.0f}, world->ub_lighting.g_cube_inv_range, 
+               cube_size );
+      float bound_radius = v3_length( cube_size );
+
+      for( int iz = 0; iz<icubes_count[2]; iz ++ )
+      {
+         for( int iy = 0; iy<icubes_count[1]; iy++ )
+         {
+            for( int ix = 0; ix<icubes_count[0]; ix++ )
+            {
+               boxf bbx;
+               v3_div( (v3f){ ix, iy, iz }, world->ub_lighting.g_cube_inv_range, 
+                     bbx[0] );
+               v3_div( (v3f){ ix+1, iy+1, iz+1 }, 
+                     world->ub_lighting.g_cube_inv_range, 
+                     bbx[1] );
+
+               v3_add( bbx[0], world->ub_lighting.g_cube_min, bbx[0] );
+               v3_add( bbx[1], world->ub_lighting.g_cube_min, bbx[1] );
+
+               v3f center;
+               v3_add( bbx[0], bbx[1], center );
+               v3_muls( center, 0.5f, center );
+               
+               u32 indices[6] = { 0, 0, 0, 0, 0, 0 };
+               u32 count = 0;
+
+               float influences[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
+               const int N = vg_list_size( influences );
+
+               for( int j=0; j<world->light_count; j ++ )
+               {
+                  struct world_light *light = &world->lights[j];
+                  v3f closest;
+                  closest_point_aabb( light->node->co, bbx, closest );
+
+                  float dist = v3_dist( closest, light->node->co ),
+                        influence = 1.0f/(dist+1.0f);
+
+                  if( dist > light->inf->range )
+                     continue;
+
+                  if( (light->inf->type == k_light_type_spot) ||
+                      (light->inf->type == k_light_type_spot_nighttime_only) )
+                  {
+                     v3f local;
+                     m4x3_mulv( light->inverse_world, center, local );
+
+                     float r = fsd_cone_infinite( local, light->angle_sin_cos );
+
+                     if( r > bound_radius )
+                        continue;
+                  }
+
+                  int best_pos = N;
+                  for( int k=best_pos-1; k>=0; k -- )
+                     if( influence > influences[k] )
+                        best_pos = k;
+
+                  if( best_pos < N )
+                  {
+                     for( int k=N-1; k>best_pos; k -- )
+                     {
+                        influences[k] = influences[k-1];
+                        indices[k] = indices[k-1];
+                     }
+
+                     influences[best_pos] = influence;
+                     indices[best_pos] = j;
+                  }
+               }
+
+               for( int j=0; j<N; j++ )
+                  if( influences[j] > 0.0f )
+                     count ++;
+
+               int base_index = iz * (icubes_count[0]*icubes_count[1]) +
+                                iy * (icubes_count[0]) +
+                                ix;
+
+               int lower_count = VG_MIN( 3, count );
+               u32 packed_index_lower = lower_count;
+               packed_index_lower |= indices[0]<<2;
+               packed_index_lower |= indices[1]<<12;
+               packed_index_lower |= indices[2]<<22;
+
+               int upper_count = VG_MAX( 0, count - lower_count );
+               u32 packed_index_upper = upper_count;
+               packed_index_upper |= indices[3]<<2;
+               packed_index_upper |= indices[4]<<12;
+               packed_index_upper |= indices[5]<<22;
+
+               cubes_index[ base_index * 2 + 0 ] = packed_index_lower;
+               cubes_index[ base_index * 2 + 1 ] = packed_index_upper;
+            }
+         }
+      }
+
+      glGenTextures( 1, &world->tex_light_cubes ); /* FIXME: glDeleteTextures */
+      glBindTexture( GL_TEXTURE_3D, world->tex_light_cubes );
+      glTexImage3D( GL_TEXTURE_3D, 0, GL_RG32UI,
+                    icubes_count[0], icubes_count[1], icubes_count[2],
+                    0, GL_RG_INTEGER, GL_UNSIGNED_INT, cubes_index );
+      glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+      glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+
+      vg_linear_del( world_global.generic_heap, cubes_index );
+
+
+
+
+
+      /* upload full buffer */
+      glBindBuffer( GL_UNIFORM_BUFFER, world->ubo_lighting );
+      glBufferSubData( GL_UNIFORM_BUFFER, 0, 
+                       sizeof(struct ub_world_lighting), &world->ub_lighting );
    }
 
    vg_release_thread_sync();
index f66ae0487e43e8f61b608c655b3a67f472207ee9..7eccc6e45518d9351722ea994146ee566dd3f745 100644 (file)
@@ -92,6 +92,15 @@ VG_STATIC void world_bind_light_array( world_instance *world,
    glUniform1i( location, slot );
 }
 
+VG_STATIC void world_bind_light_index( world_instance *world,
+                                       GLuint shader, GLuint location,
+                                       int slot )
+{
+   glActiveTexture( GL_TEXTURE0 + slot );
+   glBindTexture( GL_TEXTURE_3D, world->tex_light_cubes );
+   glUniform1i( location, slot );
+}
+
 VG_STATIC void render_world_depth( world_instance *world, camera *cam );
 
 /*
@@ -168,6 +177,8 @@ VG_STATIC void render_world_vb( world_instance *world, camera *cam )
                                 _uniform_scene_vertex_blend_g_world_depth, 2 );
    world_bind_light_array( world, _shader_scene_vertex_blend.id,
                                 _uniform_scene_vertex_blend_uLightsArray, 3 );
+   world_bind_light_index( world, _shader_scene_vertex_blend.id,
+                                _uniform_scene_vertex_blend_uLightsIndex, 4 );
 
    vg_tex2d_bind( &tex_terrain_noise, 0 );
 
@@ -198,6 +209,8 @@ VG_STATIC void render_world_standard( world_instance *world, camera *cam )
                                 _uniform_scene_standard_g_world_depth, 2 );
    world_bind_light_array( world, _shader_scene_standard.id,
                                 _uniform_scene_standard_uLightsArray, 3 );
+   world_bind_light_index( world, _shader_scene_standard.id,
+                                _uniform_scene_standard_uLightsIndex, 4 );
 
    bind_terrain_noise();
 
@@ -226,6 +239,8 @@ VG_STATIC void render_world_alphatest( world_instance *world, camera *cam )
                         _uniform_scene_standard_alphatest_g_world_depth, 2 );
    world_bind_light_array( world, _shader_scene_standard_alphatest.id,
                         _uniform_scene_standard_alphatest_uLightsArray, 3 );
+   world_bind_light_index( world, _shader_scene_standard_alphatest.id,
+                           _uniform_scene_standard_alphatest_uLightsIndex, 4 );
 
 
    bind_terrain_noise();
@@ -267,6 +282,8 @@ VG_STATIC void render_terrain( world_instance *world, camera *cam )
                         _uniform_scene_terrain_g_world_depth, 2 );
    world_bind_light_array( world, _shader_scene_terrain.id,
                         _uniform_scene_terrain_uLightsArray, 3 );
+   world_bind_light_index( world, _shader_scene_terrain.id,
+                           _uniform_scene_terrain_uLightsIndex, 4 );
 
    vg_tex2d_bind( &tex_terrain_noise, 0 );
 
index bd4ce0cf803fa91ac97eec10acfa429e31b1233d..34ba50bd210e40e0f1ef4ee1c1ddbf8c7d439356 100644 (file)
@@ -1145,6 +1145,9 @@ VG_STATIC void bind_terrain_noise(void);
 VG_STATIC void world_bind_light_array( world_instance *world,
                                        GLuint shader, GLuint location, 
                                        int slot );
+VG_STATIC void world_bind_light_index( world_instance *world,
+                                       GLuint shader, GLuint location, 
+                                       int slot );
 
 VG_STATIC void render_world_routes( world_instance *world, camera *cam )
 {
@@ -1158,6 +1161,8 @@ VG_STATIC void render_world_routes( world_instance *world, camera *cam )
                         _uniform_scene_route_g_world_depth, 2 );
    world_bind_light_array( world, _shader_scene_route.id,
                         _uniform_scene_route_uLightsArray, 3 );
+   world_bind_light_index( world, _shader_scene_route.id,
+                                 _uniform_scene_route_uLightsIndex, 4 );
    bind_terrain_noise();
 
    shader_scene_route_uPv( cam->mtx.pv );
index 6d77a9855bbfbb7599a3e41ad644ff64b63d35a4..9e282be89f6eaf459aef241107c8aeee4345bbf7 100644 (file)
@@ -41,6 +41,9 @@ VG_STATIC void world_bind_position_texture( world_instance *world,
 VG_STATIC void world_bind_light_array( world_instance *world,
                                        GLuint shader, GLuint location, 
                                        int slot );
+VG_STATIC void world_bind_light_index( world_instance *world,
+                                       GLuint shader, GLuint location, 
+                                       int slot );
 
 /*
  * Does not write motion vectors
@@ -140,6 +143,8 @@ VG_STATIC void render_water_surface( world_instance *world, camera *cam )
                                     _uniform_scene_water_g_world_depth, 2 );
       world_bind_light_array( world, _shader_scene_water.id,
                                     _uniform_scene_water_uLightsArray, 4 );
+      world_bind_light_index( world, _shader_scene_water.id,
+                              _uniform_scene_water_uLightsIndex, 5 );
 
       render_fb_bind_texture( gpipeline.fb_water_beneath, 0, 3 );
       shader_scene_water_uTexBack( 3 );