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