From b48b3eea02fa08568ceba7ef7ba81d16da208bbb Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 22 Sep 2022 21:12:20 +0100 Subject: [PATCH 1/5] Improved caustic shaders --- assets/voxygen/shaders/include/random.glsl | 32 ++++++++++++++++++++++ assets/voxygen/shaders/terrain-frag.glsl | 7 +++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/assets/voxygen/shaders/include/random.glsl b/assets/voxygen/shaders/include/random.glsl index 4330ca3770..b3f64b2c05 100644 --- a/assets/voxygen/shaders/include/random.glsl +++ b/assets/voxygen/shaders/include/random.glsl @@ -119,4 +119,36 @@ float norm2tri(float n) { n = flip ? 1.0 - n : n; return n; } + +// Caustics, ported and modified from https://www.shadertoy.com/view/3tlfR7, originally David Hoskins. +// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License: https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode. +// Modifying these three functions mean that you agree to release your changes under the above license, *not* under GPL 3 as with the rest of the project. + +float hashvec2(vec2 p) {return fract(sin(p.x * 1e2 + p.y) * 1e5 + sin(p.y * 1e3) * 1e3 + sin(p.x * 735. + p.y * 11.1) * 1.5e2); } + +float n12(vec2 p) { + vec2 i = floor(p); + vec2 f = fract(p); + f *= f * (3.-2.*f); + return mix( + mix(hashvec2(i+vec2(0.,0.)),hashvec2(i+vec2(1.,0.)),f.x), + mix(hashvec2(i+vec2(0.,1.)),hashvec2(i+vec2(1.,1.)),f.x), + f.y + ); +} + +float caustics(vec2 p, float t) { + vec3 k = vec3(p,t); + float l; + mat3 m = mat3(-2.,-1.,2.,3.,-2.,1.,1.,2.,2.); + float n = n12(p); + k = k*m*.5; + l = length(.5 - fract(k+n)); + k = k*m*.4; + l = min(l, length(.5-fract(k+n))); + k = k*m*.3; + l = min(l, length(.5-fract(k+n))); + return pow(l,4.)*5.5; +} + #endif diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index fb2dafb7fa..2c15f6ec56 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -399,9 +399,10 @@ void main() { #if (FLUID_MODE == FLUID_MODE_SHINY) if (faces_fluid) { vec3 wpos = f_pos + vec3(focus_off.xy, 0); - vec3 spos = (wpos + (fluid_alt - wpos.z) * vec3(sun_dir.xy, 0)) * 0.05; - reflected_light += max(1.0 - pow(abs(noise_3d(vec3(spos.xy, tick.x * 0.1 + dot(sin(wpos.xy * 0.8), vec2(1)) * 0.05)) - 0.5) * 10, 0.001), 0) - * 1000 + vec3 spos = (wpos + (fluid_alt - wpos.z) * vec3(sun_dir.xy, 0)) * 0.25; + reflected_light += caustics(spos.xy * 1.0, tick.x * 0.5) + * 2 + * (1.0 + abs(fluid_alt - wpos.z) * 0.2) * cam_attenuation * max(dot(f_norm, -sun_dir.xyz), 0) * sun_diffuse From 4bb5660f40a84661409ce93f57d1401cf8366d23 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 22 Sep 2022 22:40:16 +0100 Subject: [PATCH 2/5] Fixed incorrect specular light in water --- assets/voxygen/shaders/include/srgb.glsl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/voxygen/shaders/include/srgb.glsl b/assets/voxygen/shaders/include/srgb.glsl index adc3fc8149..a04edaf138 100644 --- a/assets/voxygen/shaders/include/srgb.glsl +++ b/assets/voxygen/shaders/include/srgb.glsl @@ -226,10 +226,10 @@ vec3 FresnelBlend_f(vec3 norm, vec3 dir, vec3 light_dir, vec3 R_d, vec3 R_s, flo } */ wh = normalize(wh);//mix(normalize(wh), vec3(0.0), equal(light_dir, dir)); float dot_wi_wh = dot(-light_dir, wh); - vec3 specular = BeckmannDistribution_D(dot(wh, norm), alpha) / + vec3 specular = dot(norm, dir) > 0.0 ? vec3(0.0) : (BeckmannDistribution_D(dot(wh, norm), alpha) / (4 * abs(dot_wi_wh) * max(abs(cos_wi), abs(cos_wo))) * - schlick_fresnel(R_s, dot_wi_wh); + schlick_fresnel(R_s, dot_wi_wh)); // Spectrum specular = distribution->D(wh) / // (4 * AbsDot(wi, wh) * // std::max(AbsCosTheta(wi), AbsCosTheta(wo))) * From 3b195fbd550f78312f2cfa0f3477232dd9b387fb Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 22 Sep 2022 23:08:32 +0100 Subject: [PATCH 3/5] Improved shiny water shader --- CHANGELOG.md | 1 + assets/voxygen/shaders/fluid-frag/cheap.glsl | 2 +- assets/voxygen/shaders/fluid-frag/shiny.glsl | 71 +++++++++---------- .../shaders/include/cloud/regular.glsl | 2 +- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f84e1598f..430d70224d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Present mode options renamed for clarity: Fifo -> 'Vsync capped', Mailbox -> 'Vsync uncapped', Immediate -> 'Vsync off'. - Item pickup UI now displays items that members of your group pick up. +- Improved shiny water shaders ### Removed diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index 9655562845..39903c1324 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -191,7 +191,7 @@ void main() { // 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 passthrough = max(dot(f_norm, -cam_to_frag), 0); + float passthrough = max(dot(f_norm, -cam_to_frag), 0) * 0.75; float min_refl = 0.0; if (medium.x != MEDIUM_WATER) { min_refl = min(emitted_light.r, min(emitted_light.g, emitted_light.b)); diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index 413e9809ea..4383131db5 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -52,40 +52,35 @@ layout(location = 0) out vec4 tgt_color; #include #include -vec3 warp_normal(vec3 norm, vec3 pos, float time) { - return normalize(norm - + smooth_rand(pos * 1.0, time * 1.0) * 0.05 - + smooth_rand(pos * 0.25, time * 0.25) * 0.1); +vec2 wavedx(vec2 position, vec2 direction, float speed, float frequency, float timeshift) { + float x = dot(direction, position) * frequency + timeshift * speed; + float wave = exp(sin(x) - 1.0); + float dx = wave * cos(x); + return vec2(wave, -dx); } -float wave_height(vec3 pos) { - float timer = tick.x * 0.75; - - pos *= 0.5; - vec3 big_warp = ( - texture(sampler2D(t_noise, s_noise), fract(pos.xy * 0.03 + timer * 0.01)).xyz * 0.5 + - texture(sampler2D(t_noise, s_noise), fract(pos.yx * 0.03 - timer * 0.01)).xyz * 0.5 + - vec3(0) - ); - - vec3 warp = ( - texture(sampler2D(t_noise, s_noise), fract(pos.yx * 0.1 + timer * 0.02)).xyz * 0.3 + - texture(sampler2D(t_noise, s_noise), fract(pos.yx * 0.1 - timer * 0.02)).xyz * 0.3 + - vec3(0) - ); - - float height = ( - (texture(sampler2D(t_noise, s_noise), (pos.xy + pos.z) * 0.03 + big_warp.xy + timer * 0.05).y - 0.5) * 1.0 + - (texture(sampler2D(t_noise, s_noise), (pos.yx + pos.z) * 0.03 + big_warp.yx - timer * 0.05).y - 0.5) * 1.0 + - (texture(sampler2D(t_noise, s_noise), (pos.xy + pos.z) * 0.1 + warp.xy + timer * 0.1).x - 0.5) * 0.5 + - (texture(sampler2D(t_noise, s_noise), (pos.yx + pos.z) * 0.1 + warp.yx - timer * 0.1).x - 0.5) * 0.5 + - (texture(sampler2D(t_noise, s_noise), (pos.yx + pos.z) * 0.3 + warp.xy * 0.5 + timer * 0.1).x - 0.5) * 0.2 + - (texture(sampler2D(t_noise, s_noise), (pos.xy + pos.z) * 0.3 + warp.yx * 0.5 - timer * 0.1).x - 0.5) * 0.2 + - (texture(sampler2D(t_noise, s_noise), (pos.yx + pos.z) * 1.0 + warp.yx * 0.0 - timer * 0.1).x - 0.5) * 0.05 + - 0.0 - ); - - return pow(abs(height), 0.5) * sign(height) * 15.0; +// Based on https://www.shadertoy.com/view/MdXyzX +float wave_height(vec3 pos){ + pos *= 0.3; + float iter = 0.0; + float phase = 6.0; + float speed = 2.0; + float weight = 1.0; + float w = 0.0; + float ws = 0.0; + const float drag_factor = 0.048; + for(int i = 0; i < 10; i ++){ + vec2 p = vec2(sin(iter), cos(iter)); + vec2 res = wavedx(pos.xy, p, speed, phase, tick.x); + pos.xy += p * res.y * weight * drag_factor; + w += res.x * weight; + iter += 10.0; + ws += weight; + weight = mix(weight, 0.0, 0.1); + phase *= 1.18; + speed *= 1.07; + } + return w / ws * 10.0; } void main() { @@ -132,7 +127,7 @@ void main() { } vec3 c_norm = cross(f_norm, b_norm); - vec3 wave_pos = mod(f_pos + focus_off.xyz, vec3(100.0)); + vec3 wave_pos = mod(f_pos + focus_off.xyz, vec3(3000.0)); float wave_sample_dist = 0.025; float wave00 = wave_height(wave_pos); float wave10 = wave_height(wave_pos + vec3(wave_sample_dist, 0, 0)); @@ -210,7 +205,9 @@ void main() { if (medium.x == MEDIUM_WATER) { ray_dir = refract(cam_to_frag, -norm, 1.33); } else { - ray_dir = reflect_ray_dir; + // Ensure the ray doesn't accidentally point underwater + // TODO: Make this more efficient? + ray_dir = normalize(max(reflect_ray_dir, vec3(-1.0, -1.0, 0.0))); } vec3 reflect_color = get_sky_color(/*reflect_ray_dir*/ray_dir, time_of_day.x, f_pos, vec3(-100000), 0.125, true); @@ -284,14 +281,14 @@ void main() { vec3 k_a = vec3(1.0); // Oxygen is light blue. - vec3 k_d = vec3(/*vec3(0.2, 0.9, 0.99)*/1.0); - vec3 k_s = vec3(R_s);//2.0 * reflect_color; + vec3 k_d = vec3(1.0); + vec3 k_s = vec3(0.0);//2.0 * reflect_color; vec3 emitted_light, reflected_light; // vec3 light, diffuse_light, ambient_light; // vec3 light_frac = /*vec3(1.0);*/light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha); // 0 = 100% reflection, 1 = translucent water - float passthrough = max(dot(norm, -cam_to_frag), 0); + float passthrough = max(dot(norm, -cam_to_frag), 0) * 0.75; float max_light = 0.0; max_light += get_sun_diffuse2(sun_info, moon_info, norm, /*time_of_day.x*/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, f_norm, 1.0, emitted_light, reflected_light); diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index a6905984df..f3155a0416 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -282,7 +282,7 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of moon_color * moon_scatter * get_moon_brightness() * (moon_access * (1.0 - cloud_darken) * cloud_diffuse /*+ sky_color * global_scatter_factor*/) + sky_light * (1.0 - global_darken) * not_underground + // A small amount fake ambient light underground - (1.0 - not_underground) * vec3(0.2, 0.35, 0.5) * (1.0 - global_darken) + + (1.0 - not_underground) * vec3(0.2, 0.35, 0.5) * (1.0 - global_darken) / (1.0 + max_dist * 0.003) + emission * density_integrals.y * step; // Rainbow From 34522b39bd870611054dbc0fa81c3962262a4a83 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 22 Sep 2022 23:45:16 +0100 Subject: [PATCH 4/5] Balance caustics with depth better --- assets/voxygen/shaders/include/random.glsl | 2 +- assets/voxygen/shaders/terrain-frag.glsl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/voxygen/shaders/include/random.glsl b/assets/voxygen/shaders/include/random.glsl index b3f64b2c05..c174b10c99 100644 --- a/assets/voxygen/shaders/include/random.glsl +++ b/assets/voxygen/shaders/include/random.glsl @@ -148,7 +148,7 @@ float caustics(vec2 p, float t) { l = min(l, length(.5-fract(k+n))); k = k*m*.3; l = min(l, length(.5-fract(k+n))); - return pow(l,4.)*5.5; + return pow(l,3.)*5.5; } #endif diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 2c15f6ec56..34e38ef55c 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -401,8 +401,8 @@ void main() { vec3 wpos = f_pos + vec3(focus_off.xy, 0); vec3 spos = (wpos + (fluid_alt - wpos.z) * vec3(sun_dir.xy, 0)) * 0.25; reflected_light += caustics(spos.xy * 1.0, tick.x * 0.5) - * 2 - * (1.0 + abs(fluid_alt - wpos.z) * 0.2) + * 3 + / (1.0 + pow(abs(fluid_alt - wpos.z) * 0.075, 2)) * cam_attenuation * max(dot(f_norm, -sun_dir.xyz), 0) * sun_diffuse From 0b0fde5254c9aff4ba7e90d239bf8abccaf6f523 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Fri, 23 Sep 2022 00:08:23 +0100 Subject: [PATCH 5/5] Faster wave shader --- assets/voxygen/shaders/fluid-frag/shiny.glsl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index 4383131db5..4c4b58a961 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -54,7 +54,7 @@ layout(location = 0) out vec4 tgt_color; vec2 wavedx(vec2 position, vec2 direction, float speed, float frequency, float timeshift) { float x = dot(direction, position) * frequency + timeshift * speed; - float wave = exp(sin(x) - 1.0); + float wave = pow(sin(x) + 0.5, 2); float dx = wave * cos(x); return vec2(wave, -dx); } @@ -62,21 +62,21 @@ vec2 wavedx(vec2 position, vec2 direction, float speed, float frequency, float t // Based on https://www.shadertoy.com/view/MdXyzX float wave_height(vec3 pos){ pos *= 0.3; - float iter = 0.0; + float iter = 0.0; float phase = 6.0; float speed = 2.0; float weight = 1.0; float w = 0.0; float ws = 0.0; const float drag_factor = 0.048; - for(int i = 0; i < 10; i ++){ + for(int i = 0; i < 11; i ++){ vec2 p = vec2(sin(iter), cos(iter)); vec2 res = wavedx(pos.xy, p, speed, phase, tick.x); pos.xy += p * res.y * weight * drag_factor; w += res.x * weight; iter += 10.0; ws += weight; - weight = mix(weight, 0.0, 0.1); + weight = mix(weight, 0.0, 0.15); phase *= 1.18; speed *= 1.07; }