From dd74fa7e4a53667b38811d7aec58d7f6a68889bb Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Fri, 1 May 2020 22:58:55 +0200 Subject: [PATCH] LOD shading closer to voxel shading. --- assets/voxygen/shaders/figure-frag.glsl | 2 +- assets/voxygen/shaders/figure-vert.glsl | 1 + assets/voxygen/shaders/fluid-frag/cheap.glsl | 31 +++--- assets/voxygen/shaders/fluid-frag/shiny.glsl | 13 ++- assets/voxygen/shaders/fluid-vert.glsl | 1 + assets/voxygen/shaders/include/sky.glsl | 29 +++-- assets/voxygen/shaders/include/srgb.glsl | 107 ++++++++++++++++++- assets/voxygen/shaders/lod-terrain-frag.glsl | 82 +++++++++++++- assets/voxygen/shaders/lod-terrain-vert.glsl | 38 ++++++- assets/voxygen/shaders/skybox-frag.glsl | 4 +- assets/voxygen/shaders/sprite-vert.glsl | 1 + assets/voxygen/shaders/terrain-frag.glsl | 52 +++++---- assets/voxygen/shaders/terrain-vert.glsl | 49 ++++++++- 13 files changed, 351 insertions(+), 59 deletions(-) diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 3be03a7312..274fae9e12 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -115,7 +115,7 @@ void main() { float opacity = clamp(distance / distance_divider, 0, 1); if(threshold_matrix[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4] > opacity) { - tgt_color = vec4(color, 0.0); + discard; return; } } diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index 3e13da9599..0d528d0a03 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -64,5 +64,6 @@ void main() { // f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); gl_Position = all_mat * vec4(f_pos, 1); + // gl_Position.z = -gl_Position.z / 100.0; gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); } diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index 6399cae482..71837dcd5e 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -39,7 +39,7 @@ void main() { // vec3 view_dir = normalize(-vec3(vert_pos4)/* / vert_pos4.w*/); vec3 view_dir = -cam_to_frag; // vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0)); - /*const */vec3 water_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)); + /*const */vec3 water_color = 1.0 - MU_WATER;//srgb_to_linear(vec3(0.2, 0.5, 1.0)); // /*const */vec3 water_color = srgb_to_linear(vec3(0.0, 0.25, 0.5)); vec3 sun_dir = get_sun_dir(time_of_day.x); @@ -52,13 +52,18 @@ void main() { // float moon_shade_frac = horizon_at(/*f_shadow, f_pos.z, */f_pos, moon_dir); float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac; + float fluid_alt = max(ceil(f_pos.z), floor(f_alt));// f_alt;//max(f_alt - f_pos.z, 0.0); + const float alpha = 0.255/* / 4.0 / sqrt(2.0)*/; const float n2 = 1.3325; const float R_s2s0 = pow((1.0 - n2) / (1.0 + n2), 2); const float R_s1s0 = pow((1.3325 - n2) / (1.3325 + n2), 2); const float R_s2s1 = pow((1.0 - 1.3325) / (1.0 + 1.3325), 2); const float R_s1s2 = pow((1.3325 - 1.0) / (1.3325 + 1.0), 2); - float R_s = (f_pos.z < f_alt) ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x); + float R_s = (f_pos.z < fluid_alt) ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x); + + // NOTE: Assumes normal is vertical. + vec3 sun_view_dir = cam_pos.z <= fluid_alt ? /*refract(view_dir, -f_norm, 1.0 / n2)*//*reflect(view_dir, -f_norm)*/vec3(view_dir.xy, -view_dir.z) : view_dir; vec3 k_a = vec3(1.0); vec3 k_d = vec3(1.0); @@ -78,7 +83,7 @@ void main() { // vec3 surf_color = /*srgb_to_linear*/(vec3(0.4, 0.7, 2.0)); float max_light = 0.0; - max_light += get_sun_diffuse2(f_norm, /*time_of_day.x*/sun_dir, moon_dir, /*-cam_to_frag*/view_dir, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(0.0), k_s, alpha, emitted_light, reflected_light); + max_light += get_sun_diffuse2(f_norm, /*time_of_day.x*/sun_dir, moon_dir, /*-cam_to_frag*/sun_view_dir, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, /*vec3(0.0)*/k_d, k_s, alpha, emitted_light, reflected_light); reflected_light *= f_light * point_shadow * shade_frac; emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW); max_light *= f_light * point_shadow * shade_frac; @@ -96,16 +101,18 @@ void main() { emitted_light += point_light; reflected_light += point_light; */ - vec3 diffuse_light_point = vec3(0.0); - max_light += lights_at(f_pos, f_norm, view_dir, k_a, vec3(1.0), k_s, alpha, emitted_light, diffuse_light_point); + max_light += lights_at(f_pos, f_norm, view_dir, /*vec3(0.0), vec3(1.0), fluid_alt, */k_a, k_d, k_s, alpha, emitted_light, reflected_light); + // vec3 diffuse_light_point = vec3(0.0); + // max_light += lights_at(f_pos, f_norm, view_dir, k_a, vec3(1.0), k_s, alpha, emitted_light, diffuse_light_point); - vec3 dump_light = vec3(0.0); - vec3 specular_light_point = vec3(0.0); - lights_at(f_pos, f_norm, view_dir, vec3(0.0), vec3(0.0), /*vec3(1.0)*/k_s, alpha, dump_light, specular_light_point); - diffuse_light_point -= specular_light_point; + float reflected_light_point = length(reflected_light);///*length*/(diffuse_light_point.r) + f_light * point_shadow; + // vec3 dump_light = vec3(0.0); + // vec3 specular_light_point = vec3(0.0); + // lights_at(f_pos, f_norm, view_dir, vec3(0.0), vec3(0.0), /*vec3(1.0)*/k_s, alpha, dump_light, specular_light_point); + // diffuse_light_point -= specular_light_point; - float reflected_light_point = /*length*/(diffuse_light_point.r) + f_light * point_shadow; - reflected_light += k_d * (diffuse_light_point + f_light * point_shadow * shade_frac) + specular_light_point; + // float reflected_light_point = /*length*/(diffuse_light_point.r) + f_light * point_shadow; + // reflected_light += k_d * (diffuse_light_point + f_light * point_shadow * shade_frac) + specular_light_point; float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); vec4 clouds; @@ -114,7 +121,7 @@ void main() { float passthrough = /*pow(*/dot(faceforward(f_norm, f_norm, cam_to_frag/*view_dir*/), -cam_to_frag/*view_dir*/)/*, 0.5)*/; vec3 surf_color = illuminate(max_light, water_color * fog_color * emitted_light, /*surf_color * */water_color * reflected_light); - vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*//*(f_light * point_shadow + point_light)*/reflected_light_point/* * 0.25*/)), passthrough); + vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*//*(f_light * point_shadow + point_light)*/4.0 * reflected_light_point/* * 0.25*/)), passthrough); tgt_color = mix(mix(color, vec4(fog_color, 0.0), fog_level), vec4(clouds.rgb, 0.0), clouds.a); } diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index bbf73aa627..7be35e1118 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -101,8 +101,9 @@ void main() { nmap = mix(f_norm, normalize(nmap), min(1.0 / pow(frag_dist, 0.75), 1)); vec3 norm = vec3(0, 0, 1) * nmap.z + b_norm * nmap.x + c_norm * nmap.y; + // vec3 norm = f_norm; - float f_alt = alt_at_real(f_pos.xy); + float f_alt = alt_at(f_pos.xy); float fluid_alt = max(ceil(f_pos.z), floor(f_alt));// f_alt;//max(f_alt - f_pos.z, 0.0); const float alpha = 0.255/*/ / 4.0*//* / 4.0 / sqrt(2.0)*/; @@ -118,7 +119,8 @@ void main() { vec4 _clouds; vec3 reflect_ray_dir = reflect(cam_to_frag/*-view_dir*/, norm); vec3 refract_ray_dir = refract(cam_to_frag/*-view_dir*/, norm, 1.0 / n2); - vec3 sun_view_dir = cam_pos.z <= fluid_alt ? -view_dir : view_dir; + vec3 sun_view_dir = /*sign(cam_pos.z - fluid_alt) * view_dir;*/cam_pos.z <= fluid_alt ? -view_dir : view_dir; + // vec3 sun_view_dir = cam_pos.z <= fluid_alt ? -view_dir : view_dir; vec3 beam_view_dir = reflect_ray_dir;//cam_pos.z <= fluid_alt ? -refract_ray_dir : reflect_ray_dir; /* vec4 reflect_ray_dir4 = view_mat * vec4(reflect_ray_dir, 1.0); reflect_ray_dir = normalize(vec3(reflect_ray_dir4) / reflect_ray_dir4.w); */ @@ -130,7 +132,7 @@ void main() { // /*const */vec3 water_color = srgb_to_linear(vec3(0.8, 0.9, 1.0)); // NOTE: Linear RGB, attenuation coefficients for water at roughly R, G, B wavelengths. // See https://en.wikipedia.org/wiki/Electromagnetic_absorption_by_water - /*const */vec3 water_attenuation = vec3(0.8, 0.05, 0.01); + /*const */vec3 water_attenuation = MU_WATER;// vec3(0.8, 0.05, 0.01); // /*const */vec3 water_color = vec3(0.2, 0.95, 0.99); vec3 sun_dir = get_sun_dir(time_of_day.x); @@ -192,7 +194,7 @@ void main() { float passthrough = /*pow(*/dot(faceforward(f_norm, f_norm, cam_to_frag/*view_dir*/), -cam_to_frag/*view_dir*/)/*, 0.5)*/; float max_light = 0.0; - max_light += get_sun_diffuse2(norm, /*time_of_day.x*/sun_dir, moon_dir, sun_view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(k_d), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s, alpha, emitted_light, reflected_light); + max_light += get_sun_diffuse2(norm, /*time_of_day.x*/sun_dir, moon_dir, sun_view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, vec3(k_d), /*vec3(f_light * point_shadow)*//*reflect_color*/k_s, alpha, 1.0, emitted_light, reflected_light); reflected_light *= /*water_color_direct * */reflect_color * f_light * point_shadow * shade_frac; emitted_light *= /*water_color_direct*//*ambient_attenuation * */f_light * point_shadow * max(shade_frac, MIN_SHADOW); max_light *= f_light * point_shadow * shade_frac; @@ -252,7 +254,8 @@ void main() { //vec4 color = vec4(surf_color, 1.0); // vec4 color = mix(vec4(reflect_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*/(/*f_light * point_shadow*/reflected_light_point/* + point_light*//*reflected_light*/))), passthrough); - vec4 color = vec4(surf_color, 1.0 - passthrough * /*log(1.0 + cam_attenuation)*/cam_attenuation); + float log_cam = log(min(cam_attenuation.r, min(cam_attenuation.g, cam_attenuation.b))); + vec4 color = vec4(surf_color, passthrough * (1.0 - /*log(1.0 + cam_attenuation)*//*cam_attenuation*/1.0 / (1.0 - log_cam))); // vec4 color = vec4(surf_color, mix(1.0, 1.0 / (1.0 + /*0.25 * *//*diffuse_light*/(/*f_light * point_shadow*/reflected_light_point)), passthrough)); // vec4 color = vec4(surf_color, mix(1.0, length(cam_attenuation), passthrough)); diff --git a/assets/voxygen/shaders/fluid-vert.glsl b/assets/voxygen/shaders/fluid-vert.glsl index 227fd646be..73ee026219 100644 --- a/assets/voxygen/shaders/fluid-vert.glsl +++ b/assets/voxygen/shaders/fluid-vert.glsl @@ -41,5 +41,6 @@ void main() { gl_Position = all_mat * vec4(f_pos, 1); + // gl_Position.z = -gl_Position.z / 100.0; gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); } diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index 746be5546a..10f2f33d54 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -8,13 +8,13 @@ const float PI = 3.141592; const vec3 SKY_DAY_TOP = vec3(0.1, 0.5, 0.9); const vec3 SKY_DAY_MID = vec3(0.02, 0.28, 0.8); const vec3 SKY_DAY_BOT = vec3(0.1, 0.2, 0.3); -const vec3 DAY_LIGHT = vec3(1.0, 1.0, 1.0); +const vec3 DAY_LIGHT = vec3(1.5, 1.4, 1.0); const vec3 SUN_HALO_DAY = vec3(0.35, 0.35, 0.0); const vec3 SKY_DUSK_TOP = vec3(0.06, 0.1, 0.20); const vec3 SKY_DUSK_MID = vec3(0.35, 0.1, 0.15); const vec3 SKY_DUSK_BOT = vec3(0.0, 0.1, 0.23); -const vec3 DUSK_LIGHT = vec3(3.0, 1.5, 0.3); +const vec3 DUSK_LIGHT = vec3(8.0, 1.5, 0.15); const vec3 SUN_HALO_DUSK = vec3(1.2, 0.15, 0.0); const vec3 SKY_NIGHT_TOP = vec3(0.001, 0.001, 0.0025); @@ -135,7 +135,7 @@ vec3 get_moon_color(vec3 moon_dir) { // mu is the attenuation coefficient for any substance on a horizontal plane. // cam_attenuation is the total light attenuation due to the substance for beams between the point and the camera. // surface_alt is the altitude of the attenuating surface. -float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wpos, vec3 mu, vec3 cam_attenuation, float surface_alt, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, out vec3 emitted_light, out vec3 reflected_light) { +float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wpos, vec3 mu, vec3 cam_attenuation, float surface_alt, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, float voxel_lighting, out vec3 emitted_light, out vec3 reflected_light) { const vec3 SUN_AMBIANCE = MU_SCATTER;//0.23;/* / 1.8*/;// 0.1 / 3.0; const vec3 MOON_AMBIANCE = MU_SCATTER;//0.23;//0.1; @@ -239,7 +239,7 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wp vec3 R_t_r = R_d + R_r; // vec3 half_vec = normalize(-norm + dir); - vec3 light_frac = R_t_b * (sun_chroma * SUN_AMBIANCE + moon_chroma * MOON_AMBIANCE) * light_reflection_factor(norm, /*norm*//*dir*/dir, /*-norm*/-dir, /*k_d*/k_d/* * (1.0 - k_s)*/, /*k_s*/vec3(0.0), alpha); + vec3 light_frac = R_t_b * (sun_chroma * SUN_AMBIANCE + moon_chroma * MOON_AMBIANCE) * light_reflection_factor(norm, /*norm*//*dir*/dir, /*-norm*/-dir, /*k_d*/k_d/* * (1.0 - k_s)*/, /*k_s*/vec3(0.0), alpha, voxel_lighting); // vec3 light_frac = /*vec3(1.0)*//*H_d * */ // SUN_AMBIANCE * /*sun_light*/sun_chroma * light_reflection_factor(norm, dir, /*vec3(0, 0, -1.0)*/-norm, vec3((1.0 + cos_sun) * 0.5), vec3(k_s * (1.0 - cos_sun) * 0.5), alpha) + // MOON_AMBIANCE * /*sun_light*/moon_chroma * light_reflection_factor(norm, dir, /*vec3(0, 0, -1.0)*/-norm, vec3((1.0 + cos_moon) * 0.5), vec3(k_s * (1.0 - cos_moon) * 0.5), alpha); @@ -259,10 +259,10 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wp // TODO: Add shadows. reflected_light = R_t_r * ( - (1.0 - SUN_AMBIANCE) * sun_chroma * (light_reflection_factor(norm, dir, sun_dir, k_d, k_s, alpha) /*+ + (1.0 - SUN_AMBIANCE) * sun_chroma * (light_reflection_factor(norm, dir, sun_dir, k_d, k_s, alpha, voxel_lighting) /*+ light_reflection_factor(norm, dir, normalize(sun_dir + vec3(0.0, 0.1, 0.0)), k_d, k_s, alpha) + light_reflection_factor(norm, dir, normalize(sun_dir - vec3(0.0, 0.1, 0.0)), k_d, k_s, alpha)*/) + - (1.0 - MOON_AMBIANCE) * moon_chroma * 1.0 * /*4.0 * */light_reflection_factor(norm, dir, moon_dir, k_d, k_s, alpha) + (1.0 - MOON_AMBIANCE) * moon_chroma * 1.0 * /*4.0 * */light_reflection_factor(norm, dir, moon_dir, k_d, k_s, alpha, voxel_lighting) ); /* light = sun_chroma + moon_chroma + PERSISTENT_AMBIANCE; @@ -274,8 +274,12 @@ float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 wp return rel_luminance(emitted_light + reflected_light);//rel_luminance(emitted_light + reflected_light);//sun_chroma + moon_chroma + PERSISTENT_AMBIANCE; } +float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, float voxel_lighting, out vec3 emitted_light, out vec3 reflected_light) { + return get_sun_diffuse2(norm, sun_dir, moon_dir, dir, vec3(0.0), vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, voxel_lighting, emitted_light, reflected_light); +} + float get_sun_diffuse2(vec3 norm, vec3 sun_dir, vec3 moon_dir, vec3 dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, out vec3 emitted_light, out vec3 reflected_light) { - return get_sun_diffuse2(norm, sun_dir, moon_dir, dir, vec3(0.0), vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, emitted_light, reflected_light); + return get_sun_diffuse2(norm, sun_dir, moon_dir, dir, vec3(0.0), vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, 1.0, emitted_light, reflected_light); } // This has been extracted into a function to allow quick exit when detecting a star. @@ -299,11 +303,14 @@ float is_star_at(vec3 dir) { return 0.0; } -vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars, out vec4 clouds) { +vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars, float refractionIndex, out vec4 clouds) { // Sky color vec3 sun_dir = get_sun_dir(time_of_day); vec3 moon_dir = get_moon_dir(time_of_day); + // sun_dir = sun_dir.z <= 0 ? refract(sun_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), refractionIndex) : sun_dir; + // moon_dir = moon_dir.z <= 0 ? refract(moon_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), refractionIndex) : moon_dir; + // Add white dots for stars. Note these flicker and jump due to FXAA float star = 0.0; if (with_stars) { @@ -321,7 +328,7 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q ); vec3 sun_halo = pow(max(dot(dir, -sun_dir) + 0.1, 0.0), 8.0) * sun_halo_color; - vec3 sun_surf = pow(max(dot(dir, -sun_dir) - 0.001, 0.0), 3000.0) * SUN_SURF_COLOR; + vec3 sun_surf = pow(max(dot(dir, -sun_dir) - 0.001, 0.0), 3000.0) * SUN_SURF_COLOR * SUN_COLOR_FACTOR; vec3 sun_light = (sun_halo + sun_surf) * clamp(dir.z * 10.0, 0, 1); // Moon @@ -388,6 +395,10 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q return mix(sky_color, clouds.rgb, clouds.a); } +vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars, out vec4 clouds) { + return get_sky_color(dir, time_of_day, origin, f_pos, quality, with_stars, 1.0, clouds); +} + float fog(vec3 f_pos, vec3 focus_pos, uint medium) { return max(1.0 - 5000.0 / (1.0 + distance(f_pos.xy, focus_pos.xy)), 0.0); diff --git a/assets/voxygen/shaders/include/srgb.glsl b/assets/voxygen/shaders/include/srgb.glsl index 303086a5fa..8d85d0a701 100644 --- a/assets/voxygen/shaders/include/srgb.glsl +++ b/assets/voxygen/shaders/include/srgb.glsl @@ -25,6 +25,11 @@ float pow5(float x) { return x2 * x2 * x; } +vec4 pow5(vec4 x) { + vec4 x2 = x * x; + return x2 * x2 * x; +} + // Fresnel angle for perfectly specular dialectric materials. // Schlick approximation @@ -43,6 +48,54 @@ float BeckmannDistribution_D(float NdotH, float alpha) { return mix(k_spec, 0.0, NdotH == 0.0); } +// Voxel Distribution +float BeckmannDistribution_D_Voxel(vec3 wh, vec3 norm, float alpha) { + vec3 sides = sign(norm); + // vec3 cos_sides_i = /*sides * */sides * norm; + // vec3 cos_sides_o = max(sides * view_dir, 0.0); + + vec3 NdotH = max(wh * sides, 0.0);/*cos_sides_i*///max(sides * wh, 0.0); + + const float PI = 3.1415926535897932384626433832795; + vec3 NdotH2 = NdotH * NdotH; + vec3 NdotH2m2 = NdotH2 * alpha * alpha; + vec3 k_spec = exp((NdotH2 - 1) / NdotH2m2) / (PI * NdotH2m2 * NdotH2); + return dot(mix(k_spec, /*cos_sides_o*/vec3(0.0), equal(NdotH, vec3(0.0))), /*cos_sides_i*/abs(norm)); + // // const float PI = 3.1415926535897932384626433832795; + // const vec3 normals[6] = vec3[](vec3(1,0,0), vec3(0,1,0), vec3(0,0,1), vec3(-1,0,0), vec3(0,-1,0), vec3(0,0,-1)); + + // float voxel_norm = 0.0; + // for (int i = 0; i < 6; i ++) { + // // Light reflecting off the half-angle can shine on up to three sides. + // // So, the idea here is to figure out the ratio of visibility of each of these + // // three sides such that their sum adds to 1, then computing a Beckmann Distribution for each side times + // // the this ratio. + // // + // // The ratio of these normals in each direction should be the sum of their cosines with the light over π, + // // I think. + // // + // // cos (wh, theta) + // // + // // - one normal + // // + // // The ratio of each of the three exposed sides should just be the slope. + // vec3 side = normals[i]; + // float side_share = max(dot(norm, side), 0.0); + // float NdotH = max(dot(wh, side), 0.0); + // voxel_norm += side_share * BeckmannDistribution_D(NdotH, alpha); + // // voxel_norm += normals[i] * side_visible * max(dot(-cam_dir, normals[i]), 0.0); + // // voxel_norm += normals[i] * side_visible * max(dot(-cam_dir, normals[i]), 0.0); + // } + + // /* float NdotH = dot(wh, norm); + // float NdotH2 = NdotH * NdotH; + // float NdotH2m2 = NdotH2 * alpha * alpha; + + // float k_spec = exp((NdotH2 - 1) / NdotH2m2) / (PI * NdotH2m2 * NdotH2); + // return mix(k_spec, 0.0, NdotH == 0.0); */ + // return voxel_norm; +} + float BeckmannDistribution_Lambda(vec3 norm, vec3 dir, float alpha) { float CosTheta = /*max(dot(norm, dir), 0.0);*/dot(norm, dir); /* if (CosTheta == 0.0) { @@ -98,6 +151,7 @@ vec3 FresnelBlend_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, flo alpha = alpha * sqrt(2.0); float cos_wi = /*max(*/dot(-light_dir, norm)/*, 0.0)*/; float cos_wo = /*max(*/dot(dir, norm)/*, 0.0)*/; + vec3 diffuse = (28.0 / (23.0 * PI)) * R_d * (1.0 - R_s) * (1.0 - pow5(1.0 - 0.5 * abs(cos_wi))) * @@ -134,6 +188,41 @@ vec3 FresnelBlend_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, flo return mix(/*diffuse*//* + specular*/diffuse + specular, vec3(0.0), bvec3(all(equal(light_dir, dir)))); } +// Fresnel blending +// +// http://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models.html#fragment-MicrofacetDistributionPublicMethods-2 +// and +// http://www.pbr-book.org/3ed-2018/Reflection_Models/Fresnel_Incidence_Effects.html +vec3 FresnelBlend_Voxel_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, float alpha, float dist) { + const float PI = 3.1415926535897932384626433832795; + alpha = alpha * sqrt(2.0); + float cos_wi = /*max(*/dot(-light_dir, norm)/*, 0.0)*/; + float cos_wo = /*max(*/dot(dir, norm)/*, 0.0)*/; + + vec3 sides = sign(norm); + vec4 diffuse_factor = + (1.0 - pow5(1.0 - 0.5 * max(vec4(-light_dir * sides, abs(cos_wi)), 0.0))) * + (1.0 - pow5(1.0 - 0.5 * max(vec4(dir * sides, abs(cos_wo)), 0.0))); + + vec3 diffuse = (28.0 / (23.0 * PI)) * R_d * + (1.0 - R_s) * + dot(diffuse_factor, vec4(abs(norm) * (1.0 - dist), dist)); + + vec3 wh = -light_dir + dir; + if (cos_wi <= 0.0 || cos_wo <= 0.0) { + return vec3(/*diffuse*/0.0); + } + wh = normalize(wh);//mix(normalize(wh), vec3(0.0), equal(light_dir, dir)); + float dot_wi_wh = dot(-light_dir, wh); + float distr = BeckmannDistribution_D_Voxel(wh, norm, alpha); + // float distr = BeckmannDistribution_D(dot(wh, norm), alpha); + vec3 specular = distr / + (4 * abs(dot_wi_wh)) * + max(abs(cos_wi), abs(cos_wo)) * + schlick_fresnel(R_s, dot_wi_wh); + return mix(/*diffuse*//* + specular*/diffuse + specular, vec3(0.0), bvec3(all(equal(light_dir, dir)))); +} + // Phong reflection. // // Note: norm, dir, light_dir must all be normalizd. @@ -201,6 +290,14 @@ vec3 light_reflection_factor(vec3 norm, vec3 dir, vec3 light_dir, vec3 k_d, vec3 // // return vec3(0.0); } +vec3 light_reflection_factor(vec3 norm, vec3 dir, vec3 light_dir, vec3 k_d, vec3 k_s, float alpha, float voxel_lighting) { + if (voxel_lighting < 1.0) { + return FresnelBlend_Voxel_f(norm, dir, light_dir, k_d/* * max(dot(norm, -light_dir), 0.0)*/, k_s, alpha, voxel_lighting); + } else { + return FresnelBlend_f(norm, dir, light_dir, k_d/* * max(dot(norm, -light_dir), 0.0)*/, k_s, alpha); + } +} + float rel_luminance(vec3 rgb) { // https://en.wikipedia.org/wiki/Relative_luminance @@ -242,13 +339,14 @@ bool IntersectRayPlane(vec3 rayOrigin, vec3 rayDirection, vec3 posOnPlane, vec3 // Ideally, defaultpos is set so we can avoid branching on error. vec3 compute_attenuation(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_alt, vec3 defaultpos) { // return vec3(1.0); - /*if (dot(mu, mu) == 0.0) { + /*if (mu == vec3(0.0)) { return vec3(1.0); }*//* else { return vec3(0.0); }*/ // return vec3(0.0); - vec3 surface_dir = surface_alt < wpos.z ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); + vec3 surface_dir = /*surface_alt < wpos.z ? vec3(0.0, 0.0, -1.0) : vec3(0.0, 0.0, 1.0)*/vec3(0.0, 0.0, sign(surface_alt - wpos.z)); + // vec3 surface_dir = surface_alt < wpos.z ? vec3(0.0, 0.0, -1.0) : vec3(0.0, 0.0, 1.0); // vec3 surface_dir = faceforward(vec3(0.0, 0.0, 1.0), ray_dir, vec3(0.0, 0.0, 1.0)); bool _intersects_surface = IntersectRayPlane(wpos, ray_dir, vec3(0.0, 0.0, surface_alt), surface_dir, defaultpos); float depth = length(defaultpos - wpos); @@ -259,13 +357,14 @@ vec3 compute_attenuation(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_alt, ve // from the default point. vec3 compute_attenuation_point(vec3 wpos, vec3 ray_dir, vec3 mu, float surface_alt, vec3 defaultpos) { // return vec3(1.0); - /*if (dot(mu, mu) == 0.0) { + /*if (mu == vec3(0.0)) { return vec3(1.0); }*//* else { return vec3(0.0); }*/ // return vec3(0.0); - vec3 surface_dir = surface_alt < wpos.z ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); + vec3 surface_dir = /*surface_alt < wpos.z ? vec3(0.0, 0.0, -1.0) : vec3(0.0, 0.0, 1.0)*/vec3(0.0, 0.0, sign(wpos.z - surface_alt)); + // vec3 surface_dir = surface_alt < wpos.z ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); // vec3 surface_dir = faceforward(vec3(0.0, 0.0, 1.0), ray_dir, vec3(0.0, 0.0, 1.0)); float max_length = dot(defaultpos - wpos, defaultpos - wpos); bool _intersects_surface = IntersectRayPlane(wpos, ray_dir, vec3(0.0, 0.0, surface_alt), surface_dir, defaultpos); diff --git a/assets/voxygen/shaders/lod-terrain-frag.glsl b/assets/voxygen/shaders/lod-terrain-frag.glsl index 8396d742ce..1ed1ddbacd 100644 --- a/assets/voxygen/shaders/lod-terrain-frag.glsl +++ b/assets/voxygen/shaders/lod-terrain-frag.glsl @@ -87,6 +87,82 @@ void main() { vec3 view_dir = -cam_to_frag; // vec3 view_dir = normalize(f_pos - cam_pos.xyz); + // const vec3 normals[3] = vec3[](vec3(1,0,0), vec3(0,1,0), vec3(0,0,1));//, vec3(-1,0,0), vec3(0,-1,0), vec3(0,0,-1)); + // const mat3 side_norms = vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1); + // mat3 sides = mat3( + // /*vec3(1, 0, 0), + // vec3(0, 1, 0), + // vec3(0, 0, 1)*/ + // vec3(1, 0, 0), + // // faceforward(vec3(1, 0, 0), -f_norm, vec3(1, 0, 0)), + // vec3(0, 1, 0), + // // faceforward(vec3(0, 1, 0), -f_norm, vec3(0, 1, 0)), + // vec3(0, 0, 1) + // // faceforward(vec3(0, 0, 1), -f_norm, vec3(0, 0, 1)) + // ); + + // This vector is shorthand for a diagonal matrix, which works because: + // (1) our voxel normal vectors are exactly the basis vectors in worldspace; + // (2) only 3 of them can be in the direction of the actual normal anyway. + // (NOTE: This normal should always be pointing up, so implicitly sides.z = 1.0). + // vec3 sides = sign(f_norm); + // // NOTE: Should really be sides * f_norm, i.e. abs(f_norm), but voxel_norm would then re-multiply by sides so it cancels out. + // vec3 cos_sides_i = sides * f_norm; + // vec3 cos_sides_o = sides * view_dir; + // // vec3 side_factor_i = cos_sides_i; + // // vec3 side_factor_i = f_norm; + // // vec3 side_factor_i = cos_sides_o; + // vec3 side_factor_i = 1.0 - pow(1.0 - 0.5 * cos_sides_i, vec3(5)); + // // vec3 side_factor_i = /*abs*/sign(f_norm) * cos_sides_i;//max(cos_sides_i, 0.0);// 1.0 - pow(1.0 - 0.5 * cos_sides_i, vec3(5.0)); // max(sides * f_norm, vec3(0.0));// + // // vec3 side_factor_i = /*abs*/sign(f_norm) * cos_sides_i;//max(cos_sides_i, 0.0);// 1.0 - pow(1.0 - 0.5 * cos_sides_i, vec3(5.0)); // max(sides * f_norm, vec3(0.0));// + // // vec3 side_factor_o = max(cos_sides_o, 0.0);// 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, 0.0), vec3(5)); + // vec3 side_factor_o = 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, 0.0), vec3(5)); + // // vec3 side_factor_o = max(cos_sides_o, 0.0);// 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, vec3(0.0)), vec3(5.0));//max(sides * view_dir/* * sign(cos_sides_i) */, vec3(0.0)); + // // vec3 side_factor_o = max(sides * view_dir/* * cos_sides_o*/, 0.0);// 1.0 - pow(1.0 - 0.5 * max(cos_sides_o, vec3(0.0)), vec3(5.0));//max(sides * view_dir/* * sign(cos_sides_i) */, vec3(0.0)); + // // NOTE: side = transpose(sides), so we avoid the extra operatin. + // // We multply the vector by the matrix from the *left*, so each normal gets multiplied by the corresponding factor. + // // vec3 voxel_norm = normalize(/*sides * *//*sqrt(1.0 - cos_sides_i * cos_sides_i)*/(side_factor_i * side_factor_o)); + // vec3 voxel_norm = normalize(/*sides * *//*sqrt(1.0 - cos_sides_i * cos_sides_i)*/((28.0 / (23.0 * PI)) * side_factor_i * side_factor_o * sides)); + // vec3 voxel_norm = normalize(sign(f_norm) * sqrt(abs(f_norm)) * max(sign(f_norm) * view_dir, 0.0)); + float f_ao = 1.0;//1.0;//sqrt(dot(cos_sides_i, cos_sides_i) / 3.0); + // float f_ao = 0.2; + // sqrt(dot(sqrt(1.0 - cos_sides_i * cos_sides_i)), 1.0 - cos_sides_o/* * cos_sides_o*/);// length(sqrt(1.0 - cos_sides_o * cos_sides_o) / cos_sides_i * cos_sides_o); + // f_ao = f_ao * f_ao; + + // /* vec3 voxel_norm = vec3(0.0); + // for (int i = 0; i < 3; i ++) { + // // Light reflecting off the half-angle can shine on up to three sides. + // // So, the idea here is to figure out the ratio of visibility of each of these + // // three sides such that their sum adds to 1, then computing a Beckmann Distribution for each side times + // // the this ratio. + // // + // // The ratio of these normals in each direction should be the sum of their cosines with the light over π, + // // I think. + // // + // // cos (wh, theta) + // // + // // - one normal + // // + // // The ratio of each of the three exposed sides should just be the slope. + // vec3 side = normals[i]; + // side = faceforward(side, -f_norm, side); + // float cos_wi = max(dot(f_norm, side), 0.0); + // float cos_wo = max(dot(view_dir, side), 0.0); + // float share = cos_wi * cos_wo; + // // float share = (1.0 - pow5(1.0 - 0.5 * cos_wi)) * (1.0 - pow5(1.0 - 0.5 * cos_wo)); + // voxel_norm += share * side; + // // voxel_norm += normals[i] * side_visible * max(dot(-cam_dir, normals[i]), 0.0); + // // voxel_norm += normals[i] * side_visible * max(dot(-cam_dir, normals[i]), 0.0); + // } + // voxel_norm = normalize(voxel_norm); */ + + float dist_lerp = clamp(pow(max(distance(focus_pos.xy, f_pos.xy) - view_distance.x, 0.0) / 1024.0, 2.0), 0, 1); + // dist_lerp = 0.0; + // voxel_norm = normalize(mix(voxel_norm, f_norm, /*pow(dist_lerp, 1.0)*/dist_lerp)); + + vec3 voxel_norm = f_norm; + // voxel_norm = f_norm; + // Note: because voxels, we reduce the normal for reflections to just its z component, dpendng on distance to camera. // Idea: the closer we are to facing top-down, the more the norm should tend towards up-z. // vec3 l_norm; // = vec3(0.0, 0.0, 1.0); @@ -150,13 +226,17 @@ void main() { // vec3 light, diffuse_light, ambient_light; // get_sun_diffuse(f_norm, time_of_day.x, cam_to_frag, (0.25 * shade_frac + 0.25 * light_frac) * f_col, 0.5 * shade_frac * f_col, 0.5 * shade_frac * /*vec3(1.0)*/f_col, 2.0, emitted_light, reflected_light); float max_light = 0.0; - max_light += get_sun_diffuse2(f_norm/*l_norm*/, sun_dir, moon_dir, view_dir, vec3(1.0)/* * (0.5 * light_frac + vec3(0.5 * shade_frac))*/, vec3(1.0), /*0.5 * shade_frac * *//*vec3(1.0)*//*f_col*/vec3(R_s), alpha, emitted_light, reflected_light); + max_light += get_sun_diffuse2(/*f_norm*/voxel_norm/*l_norm*/, sun_dir, moon_dir, view_dir, vec3(1.0)/* * (0.5 * light_frac + vec3(0.5 * shade_frac))*/, vec3(1.0), /*0.5 * shade_frac * *//*vec3(1.0)*//*f_col*/vec3(R_s), alpha, dist_lerp/*max(distance(focus_pos.xy, f_pos.xyz) - view_distance.x, 0.0) / 1000 < 1.0*/, emitted_light, reflected_light); // emitted_light = vec3(1.0); emitted_light *= max(shade_frac, MIN_SHADOW); reflected_light *= shade_frac; max_light *= shade_frac; // reflected_light = vec3(0.0); + float ao = /*pow(f_ao, 0.5)*/f_ao * 0.9 + 0.1; + emitted_light *= ao; + reflected_light *= ao; + // emitted_light += 0.5 * vec3(SUN_AMBIANCE * sun_shade_frac * sun_light + moon_shade_frac * moon_light) * f_col * (ambient_sides + 1.0); // Ambient lighting attempt: vertical light. diff --git a/assets/voxygen/shaders/lod-terrain-vert.glsl b/assets/voxygen/shaders/lod-terrain-vert.glsl index 01a1e28dc3..f83cf491d2 100644 --- a/assets/voxygen/shaders/lod-terrain-vert.glsl +++ b/assets/voxygen/shaders/lod-terrain-vert.glsl @@ -36,13 +36,49 @@ void main() { // f_pos.z -= 100.0 * pow(1.0 + 0.01 / view_distance.x, -pow(distance(focus_pos.xy, f_pos.xy), 2.0)); // f_pos.z = mix(-f_pos.z, f_pos.z, view_distance.x <= distance(focus_pos.xy, f_pos.xy) + 32.0); + + // bool faces_fluid = false;// bool((f_pos_norm >> 28) & 0x1u); + // // TODO: Measure real water surface altitude here. + // float surfaceAlt = mix(view_distance.z, /*floor*/(min(f_pos.z, floor(alt_at_real(cam_pos.xy)))), medium.x); + // // float surfaceAlt = mix(view_distance.z, floor(max(cam_pos.z, alt_at_real(cam_pos.xy))), medium.x); + // // float surfaceAlt = min(floor(f_pos.z), floor(alt_at_real(cam_pos.xy))); // faces_fluid ? max(ceil(f_pos.z), floor(f_alt)) : floor(f_alt); + + // f_pos.z -= max(sign(view_distance.x - distance(focus_pos.xy, f_pos.xy)), 0.0) * (32.0 * view_distance.z / 255 + 32.0 * max(0.0, f_pos.z - cam_pos.z)); f_pos.z -= max(view_distance.x - distance(focus_pos.xy, f_pos.xy), 0.0) * (1.0 + max(0.0, f_pos.z - focus_pos.z)); + // vec3 wRayinitial = f_pos; // cam_pos.z < f_pos.z ? f_pos : cam_pos.xyz; + // vec3 wRayfinal = cam_pos.xyz; // cam_pos.z < f_pos.z ? cam_pos.xyz : f_pos; + // wRayfinal = dot(wRayfinal - wRayinitial, focus_pos.xyz - cam_pos.xyz) < 0.0 ? wRayfinal : wRayinitial; + // vec3 wRayNormal = /*surfaceAlt < wRayinitial.z ? vec3(0.0, 0.0, -1.0) : */vec3(0.0, 0.0, 1.0); + // float n_camera = mix(1.0, 1.3325, medium.x); + // float n_vertex = faces_fluid ? 1.3325 : 1.0; + // float n1 = n_vertex; // cam_pos.z < f_pos.z ? n_vertex : n_camera; + // float n2 = n_camera; // cam_pos.z < f_pos.z ? n_camera : n_vertex; + + // float wRayLength0 = length(wRayfinal - wRayinitial); + // vec3 wRayDir = (wRayfinal - wRayinitial) / wRayLength0; + // vec3 wPoint = wRayfinal; + // bool wIntersectsSurface = IntersectRayPlane(wRayinitial, wRayDir, vec3(0.0, 0.0, surfaceAlt), -wRayNormal, wPoint); + // float wRayLength = length(wPoint - wRayinitial); + // wPoint = wRayLength < wRayLength0 ? wPoint : wRayfinal; + // wRayLength = min(wRayLength, wRayLength0); // min(max_length, dot(wRayfinal - wpos, defaultpos - wpos)); + + // // vec3 wRayDir2 = (wRayfinal - wRayinitial) / wRayLength; + + // vec3 wRayDir3 = (dot(wRayDir, wRayNormal) < 0.0 && surfaceAlt < wRayinitial.z && wIntersectsSurface/* && medium.x == 1u*/) ? refract(wRayDir, wRayNormal, n2 / n1) : wRayDir; + // // wPoint -= wRayDir3 * wRayLength * n2 / n1; + + // vec3 newRay = (dot(wRayDir3, focus_pos.xyz - cam_pos.xyz) < 0.0 && /*dot(wRayDir, wRayNormal) > 0.0 && *//*surfaceAlt < wRayinitial.z && */wIntersectsSurface && medium.x == 1u) ? wPoint - wRayDir3 * wRayLength * n2 / n1/*wPoint - wRayDir3 * wRayLength * n2 / n1*/ : f_pos;// - (wRayfinal - wPoint) * n2 / n1; // wPoint + n2 * (wRayfinal - wPoint) - n2 / n1 * wRayLength * wRayDir3; + + // newRay.z -= max(view_distance.x - distance(focus_pos.xy, f_pos.xy), 0.0) * (1.0 + max(0.0, f_pos.z - focus_pos.z)); + + // f_light = 1.0; gl_Position = proj_mat * view_mat * - vec4(f_pos, 1); + vec4(f_pos/*newRay*/, 1); + // gl_Position.z = -gl_Position.z / 100.0; gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); } diff --git a/assets/voxygen/shaders/skybox-frag.glsl b/assets/voxygen/shaders/skybox-frag.glsl index aaba592dfc..6c94e1afe5 100644 --- a/assets/voxygen/shaders/skybox-frag.glsl +++ b/assets/voxygen/shaders/skybox-frag.glsl @@ -21,10 +21,12 @@ void main() { float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); float dist = 100000.0; + + float refractionIndex = medium.x == 1u ? 1.0 / 1.3325 : 1.0; /* if (medium.x == 1u) { dist = UNDERWATER_MIST_DIST; } */ vec3 wpos = cam_pos.xyz + /*normalize(f_pos)*/cam_dir * dist; - tgt_color = vec4(get_sky_color(normalize(f_pos), time_of_day.x, cam_pos.xyz, wpos, 1.0, true, _clouds), 1.0); + tgt_color = vec4(get_sky_color(normalize(f_pos), time_of_day.x, cam_pos.xyz, wpos, 1.0, true, refractionIndex, _clouds), 1.0); } diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 359b8ec74e..c99a58e6fd 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -58,5 +58,6 @@ void main() { gl_Position = all_mat * vec4(f_pos, 1); + // gl_Position.z = -gl_Position.z / 100.0; gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); } diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 90886efb07..9ccefa8edb 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -6,8 +6,8 @@ in vec3 f_pos; in vec3 f_chunk_pos; flat in uint f_pos_norm; -in float f_alt; -in vec4 f_shadow; +// in float f_alt; +// in vec4 f_shadow; in vec3 f_col; in float f_light; in float f_ao; @@ -39,6 +39,26 @@ void main() { vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 moon_dir = get_moon_dir(time_of_day.x); + + float f_alt = alt_at(f_pos.xy); + vec4 f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + + float alpha = 1.0; + // TODO: Possibly angle with water surface into account? Since we can basically assume it's horizontal. + const float n2 = 1.01; + const float R_s2s0 = pow((1.0 - n2) / (1.0 + n2), 2); + const float R_s1s0 = pow((1.3325 - n2) / (1.3325 + n2), 2); + const float R_s2s1 = pow((1.0 - 1.3325) / (1.0 + 1.3325), 2); + const float R_s1s2 = pow((1.3325 - 1.0) / (1.3325 + 1.0), 2); + // float faces_fluid = faces_fluid && f_pos.z <= floor(f_alt); + float fluid_alt = max(ceil(f_pos.z), floor(f_alt)); + float R_s = /*(f_pos.z < f_alt)*/faces_fluid /*&& f_pos.z <= fluid_alt*/ ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x); + + // vec3 surf_color = /*srgb_to_linear*/(f_col); + vec3 k_a = vec3(1.0); + vec3 k_d = vec3(1.0); + vec3 k_s = vec3(R_s); + // float sun_light = get_sun_brightness(sun_dir); // float moon_light = get_moon_brightness(moon_dir); /* float sun_shade_frac = horizon_at(f_pos, sun_dir); @@ -55,33 +75,23 @@ void main() { // for the sun and moon (since they have different brightnesses / colors so the shadows shouldn't attenuate equally). float shade_frac = /*1.0;*/sun_shade_frac + moon_shade_frac; - vec3 surf_color = /*srgb_to_linear*/(f_col); - float alpha = 1.0; - // TODO: Possibly angle with water surface into account? Since we can basically assume it's horizontal. - const float n2 = 1.01; - const float R_s2s0 = pow((1.0 - n2) / (1.0 + n2), 2); - const float R_s1s0 = pow((1.3325 - n2) / (1.3325 + n2), 2); - const float R_s2s1 = pow((1.0 - 1.3325) / (1.0 + 1.3325), 2); - const float R_s1s2 = pow((1.3325 - 1.0) / (1.3325 + 1.0), 2); - // float faces_fluid = faces_fluid && f_pos.z <= floor(f_alt); - float fluid_alt = max(ceil(f_pos.z), floor(f_alt)); - float R_s = /*(f_pos.z < f_alt)*/faces_fluid /*&& f_pos.z <= fluid_alt*/ ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x); - vec3 k_a = vec3(1.0); - vec3 k_d = vec3(1.0); - vec3 k_s = vec3(R_s); float max_light = 0.0; + // After shadows are computed, we use a refracted sun and moon direction. + // sun_dir = faces_fluid && sun_shade_frac > 0.0 ? refract(sun_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), 1.0 / 1.3325) : sun_dir; + // moon_dir = faces_fluid && moon_shade_frac > 0.0 ? refract(moon_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), 1.0 / 1.3325) : moon_dir; + // Compute attenuation due to water from the camera. vec3 mu = faces_fluid/* && f_pos.z <= fluid_alt*/ ? MU_WATER : vec3(0.0); // NOTE: Default intersection point is camera position, meaning if we fail to intersect we assume the whole camera is in water. - vec3 cam_attenuation = compute_attenuation_point(f_pos, view_dir, mu, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/cam_pos.xyz); + vec3 cam_attenuation = compute_attenuation_point(f_pos, -view_dir, mu, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/cam_pos.xyz); // Computing light attenuation from water. vec3 emitted_light, reflected_light; // To account for prior saturation - float f_light = pow(f_light, 1.5); + float f_light = faces_fluid ? 1.0 : pow(f_light, 1.5); float point_shadow = shadow_at(f_pos, f_norm); - max_light += get_sun_diffuse2(f_norm, /*time_of_day.x, */sun_dir, moon_dir, view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, emitted_light, reflected_light); + max_light += get_sun_diffuse2(f_norm, /*time_of_day.x, */sun_dir, moon_dir, view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a/* * (shade_frac * 0.5 + light_frac * 0.5)*/, k_d, k_s, alpha, 1.0, emitted_light, reflected_light); emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW); reflected_light *= f_light * point_shadow * shade_frac; @@ -89,6 +99,8 @@ void main() { max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, emitted_light, reflected_light); + // float f_ao = 1.0; + float ao = /*pow(f_ao, 0.5)*/f_ao * 0.9 + 0.1; emitted_light *= ao; reflected_light *= ao; @@ -115,7 +127,7 @@ void main() { // vec3 surf_color = illuminate(srgb_to_linear(f_col), light, diffuse_light, ambient_light); vec3 col = srgb_to_linear(f_col + hash(vec4(floor(f_chunk_pos * 3.0 - f_norm * 0.5), 0)) * 0.02); // Small-scale noise - surf_color = illuminate(max_light, col * emitted_light, col * reflected_light); + vec3 surf_color = illuminate(max_light, col * emitted_light, col * reflected_light); float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); vec4 clouds; diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index 95bd0a7651..1e67ef8b08 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -16,8 +16,8 @@ uniform u_locals { out vec3 f_pos; out vec3 f_chunk_pos; flat out uint f_pos_norm; -out float f_alt; -out vec4 f_shadow; +// out float f_alt; +// out vec4 f_shadow; out vec3 f_col; out float f_light; out float f_ao; @@ -25,6 +25,7 @@ out float f_ao; const int EXTRA_NEG_Z = 32768; void main() { + // over it (if this vertex to see if it intersects. f_chunk_pos = vec3(ivec3((uvec3(v_pos_norm) >> uvec3(0, 6, 12)) & uvec3(0x3Fu, 0x3Fu, 0xFFFFu)) - ivec3(0, 0, EXTRA_NEG_Z)); f_pos = f_chunk_pos + model_offs; @@ -39,11 +40,49 @@ void main() { f_pos_norm = v_pos_norm; // Also precalculate shadow texture and estimated terrain altitude. - f_alt = alt_at_real(f_pos.xy); - f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + // f_alt = alt_at(f_pos.xy); + // f_shadow = textureBicubic(t_horizon, pos_to_tex(f_pos.xy)); + + // IDEA: Cast a ray from the vertex to the camera (if this vertex is above the camera) or from the camera to the vertex (if this + // vertex is below the camera) to see where it intersects the plane of water. All of this only applies if either the terrain + // vertex is in water, or the camera is in water. + // + // If an intersection is found, refract the ray across the barrier using the correct ratio of indices of refraction (1 / N_WATER + // if the vertex is above the camera [ray is going from air to water], N_WATER if the camera is above the vertex + // [ray is going from water to air]). + // + // In order to make sure that terrain and other objects below such an interface are properly renered, we then "un-refract" by + // reversing the refracted vector, and multiplying that by the distance from the object from which we cast the ray to the + // intersectng point, in order to make the object appear to the viewer where it should after refraction. + // bool faces_fluid = bool((f_pos_norm >> 28) & 0x1u); + // // TODO: Measure real water surface altitude here. + // float surfaceAlt = faces_fluid ? max(ceil(f_pos.z), floor(f_alt)) : /*floor(f_alt);*/mix(view_distance.z, min(f_alt, floor(alt_at_real(cam_pos.xy))), medium.x); + + // vec3 wRayinitial = f_pos; // cam_pos.z < f_pos.z ? f_pos : cam_pos.xyz; + // vec3 wRayfinal = cam_pos.xyz; // cam_pos.z < f_pos.z ? cam_pos.xyz : f_pos; + // vec3 wRayNormal = surfaceAlt < wRayinitial.z ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); + // float n_camera = mix(1.0, 1.3325, medium.x); + // float n_vertex = faces_fluid ? 1.3325 : 1.0; + // float n1 = n_vertex; // cam_pos.z < f_pos.z ? n_vertex : n_camera; + // float n2 = n_camera; // cam_pos.z < f_pos.z ? n_camera : n_vertex; + + // float wRayLength0 = length(wRayfinal - wRayinitial); + // vec3 wRayDir = (wRayfinal - wRayinitial) / wRayLength0; + // vec3 wPoint = wRayfinal; + // bool wIntersectsSurface = IntersectRayPlane(wRayinitial, wRayDir, vec3(0.0, 0.0, surfaceAlt), -wRayNormal, wPoint); + // float wRayLength = length(wPoint - wRayinitial); + // wPoint = wRayLength < wRayLength0 ? wPoint : wRayfinal; + // wRayLength = min(wRayLength, wRayLength0); // min(max_length, dot(wRayfinal - wpos, defaultpos - wpos)); + + // // vec3 wRayDir2 = (wRayfinal - wRayinitial) / wRayLength; + + // vec3 wRayDir3 = (dot(wRayDir, wRayNormal) < 0.0 && wIntersectsSurface) ? refract(wRayDir, wRayNormal, n2 / n1) : wRayDir; + // // wPoint -= wRayDir3 * wRayLength * n2 / n1; + // vec3 newRay = dot(wRayDir, wRayNormal) < 0.0 && wIntersectsSurface ? wPoint - wRayDir3 * wRayLength * n2 / n1 : f_pos;// - (wRayfinal - wPoint) * n2 / n1; // wPoint + n2 * (wRayfinal - wPoint) - n2 / n1 * wRayLength * wRayDir3; gl_Position = all_mat * - vec4(f_pos, 1); + vec4(f_pos/*newRay*/, 1); + // gl_Position.z = -gl_Position.z / 100.0; gl_Position.z = -1000.0 / (gl_Position.z + 10000.0); }