diff --git a/CHANGELOG.md b/CHANGELOG.md index 76714a79b2..63584f78d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Pets can now be traded with. - Crafting recipe for black lantern - Added redwood and dead trees +- Water will now move according to its apparent flow direction +- Added screen-space reflection and refraction shaders +- Added reflection quality setting ### Changed - Use fluent for translations @@ -60,6 +63,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Pets no longer aggro on pet owners after being healed - Pets no longer lose their intrinsic weapons/armour when loaded on login. - Fixed npcs using `/say` instead of `/tell` +- Camera jittering in third person has been significantly reduced +- Many water shader issues have been fixed ## [0.13.0] - 2022-07-23 diff --git a/assets/voxygen/i18n/en/hud/settings.ftl b/assets/voxygen/i18n/en/hud/settings.ftl index cb895bebe5..847e428fc9 100644 --- a/assets/voxygen/i18n/en/hud/settings.ftl +++ b/assets/voxygen/i18n/en/hud/settings.ftl @@ -72,8 +72,13 @@ hud-settings-antialiasing_mode = AntiAliasing Mode hud-settings-upscale_factor = Internal Resolution hud-settings-cloud_rendering_mode = Cloud Rendering Mode hud-settings-fluid_rendering_mode = Fluid Rendering Mode -hud-settings-fluid_rendering_mode-cheap = Cheap -hud-settings-fluid_rendering_mode-shiny = Shiny +hud-settings-fluid_rendering_mode-low = Low +hud-settings-fluid_rendering_mode-medium = Medium +hud-settings-fluid_rendering_mode-high = High +hud-settings-reflection_rendering_mode = Reflection Rendering Mode +hud-settings-reflection_rendering_mode-low = Low +hud-settings-reflection_rendering_mode-medium = Medium +hud-settings-reflection_rendering_mode-high = High hud-settings-cloud_rendering_mode-minimal = Minimal hud-settings-cloud_rendering_mode-low = Low hud-settings-cloud_rendering_mode-medium = Medium @@ -93,7 +98,7 @@ hud-settings-resolution = Resolution hud-settings-bit_depth = Bit Depth hud-settings-refresh_rate = Refresh Rate hud-settings-lighting_rendering_mode = Lighting Rendering Mode -hud-settings-lighting_rendering_mode-ashikhmin = Type A - High +hud-settings-lighting_rendering_mode-ashikhmin = Type A - High hud-settings-lighting_rendering_mode-blinnphong = Type B - Medium hud-settings-lighting_rendering_mode-lambertian = Type L - Cheap hud-settings-shadow_rendering_mode = Shadow Rendering Mode diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index 273bf4f4db..b0ef33fa4e 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -27,6 +27,7 @@ #include <light.glsl> // This *MUST* come after `cloud.glsl`: it contains a function that depends on `cloud.glsl` when clouds are enabled #include <point_glow.glsl> +#include <random.glsl> layout(set = 2, binding = 0) uniform texture2D t_src_color; @@ -48,7 +49,9 @@ uniform u_locals { layout(location = 0) out vec4 tgt_color; vec3 wpos_at(vec2 uv) { - float buf_depth = texture(sampler2D(t_src_depth, s_src_depth), uv).x; + uvec2 sz = textureSize(sampler2D(t_src_depth, s_src_depth), 0); + float buf_depth = texelFetch(sampler2D(t_src_depth, s_src_depth), clamp(ivec2(uv * sz), ivec2(0), ivec2(sz) - 1), 0).x; + //float buf_depth = texture(sampler2D(t_src_depth, s_src_depth), uv).x; vec4 clip_space = vec4((uv * 2.0 - 1.0) * vec2(1, -1), buf_depth, 1.0); vec4 view_space = all_mat_inv * clip_space; view_space /= view_space.w; @@ -60,6 +63,19 @@ vec3 wpos_at(vec2 uv) { } } +float depth_at(vec2 uv) { + uvec2 sz = textureSize(sampler2D(t_src_depth, s_src_depth), 0); + float buf_depth = texelFetch(sampler2D(t_src_depth, s_src_depth), clamp(ivec2(uv * sz), ivec2(0), ivec2(sz) - 1), 0).x; + if (buf_depth == 0.0) { + return 524288.0; + } else { + vec4 clip_space = vec4((uv * 2.0 - 1.0) * vec2(1, -1), buf_depth, 1.0); + vec4 view_space = all_mat_inv * clip_space; + view_space /= view_space.w; + return -(view_mat * view_space).z; + } +} + void main() { vec4 color = texture(sampler2D(t_src_color, s_src_color), uv); @@ -70,13 +86,113 @@ void main() { vec3 wpos = wpos_at(uv); float dist = distance(wpos, cam_pos.xyz); - vec3 dir = (wpos - cam_pos.xyz) / dist; + vec3 cam_dir = (wpos - cam_pos.xyz) / dist; + vec3 dir = cam_dir; // Apply clouds float cloud_blend = 1.0; if (color.a < 1.0) { - cloud_blend = 1.0 - color.a; - dist = DIST_CAP; + vec2 nz = vec2(0); + uvec2 col_sz = textureSize(sampler2D(t_src_color, s_src_color), 0); + #if (REFLECTION_MODE >= REFLECTION_MODE_MEDIUM) + nz = (vec2( + noise_3d(vec3((wpos.xy + focus_off.xy) * 0.1, tick.x * 0.2 + wpos.x * 0.01)).x, + noise_3d(vec3((wpos.yx + focus_off.yx) * 0.1, tick.x * 0.2 + wpos.y * 0.01)).x + ) - 0.5) * (dir.z < 0.0 ? color.a : 1.0); + + const float n2 = 1.3325; + vec3 refr_dir; + // TODO: Proper refraction + // if (medium.x == MEDIUM_WATER) { + // vec3 surf_norm = normalize(vec3(nz * 0.03 / (1.0 + dist * 0.1), 1)); + // refr_dir = refract(dir, surf_norm * -sign(dir.z), 1.0 / n2); + // } else { + refr_dir = normalize(dir + vec3(nz * 1.5 / dist, 0.0)); + // } + + vec4 clip = (all_mat * vec4(cam_pos.xyz + refr_dir, 1.0)); + vec2 new_uv = (clip.xy / max(clip.w, 0)) * 0.5 * vec2(1, -1) + 0.5; + + float uv_merge = clamp((1.0 - abs(new_uv.y - 0.5) * 2) * 5.0, 0, 1); + new_uv = mix(uv, new_uv, uv_merge); + + vec4 new_col = texelFetch(sampler2D(t_src_color, s_src_color), clamp(ivec2(new_uv * col_sz), ivec2(0), ivec2(col_sz) - 1), 0); + if (new_col.a < 1.0) { + color = new_col; + dir = refr_dir; + } + #endif + { + cloud_blend = 1.0 - color.a; + + #if (FLUID_MODE >= FLUID_MODE_MEDIUM || REFLECTION_MODE >= REFLECTION_MODE_MEDIUM) + if (dir.z < 0.0) { + vec3 surf_norm = normalize(vec3(nz * 0.3 / (1.0 + dist * 0.1), 1)); + vec3 refl_dir = reflect(dir, surf_norm); + + vec4 clip = (all_mat * vec4(cam_pos.xyz + refl_dir, 1.0)); + vec2 new_uv = (clip.xy / max(clip.w, 0)) * 0.5 * vec2(1, -1) + 0.5; + + #if (REFLECTION_MODE >= REFLECTION_MODE_HIGH) + vec3 ray_end = wpos + refl_dir * 5.0 * dist; + // Trace through the screen-space depth buffer to find the ray intersection + const int MAIN_ITERS = 64; + for (int i = 0; i < MAIN_ITERS; i ++) { + float t = float(i) / float(MAIN_ITERS); + // TODO: Trace in screen space, not world space + vec3 swpos = mix(wpos, ray_end, t); + vec3 svpos = (view_mat * vec4(swpos, 1)).xyz; + vec4 clippos = proj_mat * vec4(svpos, 1); + vec2 suv = (clippos.xy / clippos.w) * 0.5 * vec2(1, -1) + 0.5; + float d = -depth_at(suv); + if (d < svpos.z * 0.8 && d > svpos.z * 0.999) { + // Don't cast into water! + if (texelFetch(sampler2D(t_src_color, s_src_color), clamp(ivec2(suv * col_sz), ivec2(0), ivec2(col_sz) - 1), 0).a >= 1.0) { + /* t -= 1.0 / float(MAIN_ITERS); */ + // Do a bit of extra iteration to try to refine the estimate + const int ITERS = 8; + float diff = 1.0 / float(MAIN_ITERS); + for (int i = 0; i < ITERS; i ++) { + vec3 swpos = mix(wpos, ray_end, t); + svpos = (view_mat * vec4(swpos, 1)).xyz; + vec4 clippos = proj_mat * vec4(svpos, 1); + suv = (clippos.xy / clippos.w) * 0.5 * vec2(1, -1) + 0.5; + float d = -depth_at(suv); + t += ((d > svpos.z * 0.999) ? -1.0 : 1.0) * diff; + diff *= 0.5; + } + // Small offset to push us into obscured territory + new_uv = suv - vec2(0, 0.001); + break; + } + } + } + #endif + + new_uv = clamp(new_uv, vec2(0), vec2(1)); + + vec3 new_wpos = wpos_at(new_uv); + float new_dist = distance(new_wpos, cam_pos.xyz); + float merge = min( + // Off-screen merge factor + clamp((1.0 - abs(new_uv.y - 0.5) * 2) * 3.0, 0, 1), + // Depth merge factor + clamp((new_dist - dist * 0.5) / (dist * 0.5), 0.0, 1.0) + ); + + if (merge > 0.0) { + vec3 new_col = texelFetch(sampler2D(t_src_color, s_src_color), clamp(ivec2(new_uv * col_sz), ivec2(0), ivec2(col_sz) - 1), 0).rgb; + new_col = get_cloud_color(new_col.rgb, refl_dir, wpos, time_of_day.x, distance(new_wpos, wpos.xyz), 1.0); + color.rgb = mix(color.rgb, new_col, min(merge * (color.a * 2.0), 0.75)); + } + cloud_blend = 1; + } else { + #else + { + #endif + cloud_blend = 1; + } + } } color.rgb = mix(color.rgb, get_cloud_color(color.rgb, dir, cam_pos.xyz, time_of_day.x, dist, 1.0), cloud_blend); @@ -86,7 +202,7 @@ void main() { if (medium.x == MEDIUM_AIR && rain_density > 0.001) { vec3 cam_wpos = cam_pos.xyz + focus_off.xyz; - vec3 adjusted_dir = (vec4(dir, 0) * rain_dir_mat).xyz; + vec3 adjusted_dir = (vec4(cam_dir, 0) * rain_dir_mat).xyz; vec2 dir2d = adjusted_dir.xy; vec3 rorigin = cam_pos.xyz + focus_off.xyz + 0.5; diff --git a/assets/voxygen/shaders/clouds-vert.glsl b/assets/voxygen/shaders/clouds-vert.glsl index 933d3a3dc3..039af8a38d 100644 --- a/assets/voxygen/shaders/clouds-vert.glsl +++ b/assets/voxygen/shaders/clouds-vert.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 1dbd776170..52da9e37e6 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -8,9 +8,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -32,6 +32,8 @@ layout(location = 0) in vec3 f_pos; // flat in uint f_pos_norm; layout(location = 1) flat in vec3 f_norm; /*centroid */layout(location = 2) in vec2 f_uv_pos; +layout(location = 3) in vec3 m_pos; +layout(location = 4) in float scale; // in float f_alt; // in vec4 f_shadow; // in vec3 light_pos[2]; @@ -135,9 +137,9 @@ void main() { // float moon_light = get_moon_brightness(moon_dir); /* float sun_shade_frac = horizon_at(f_pos, sun_dir); float moon_shade_frac = horizon_at(f_pos, moon_dir); */ -#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY) +#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE >= FLUID_MODE_MEDIUM) float f_alt = alt_at(f_pos.xy); -#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP) +#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_LOW) float f_alt = f_pos.z; #endif @@ -161,7 +163,24 @@ void main() { DirectionalLight sun_info = get_sun_info(sun_dir, point_shadow * sun_shade_frac, /*sun_pos*/f_pos); DirectionalLight moon_info = get_moon_info(moon_dir, point_shadow * moon_shade_frac/*, light_pos*/); - vec3 surf_color = /*srgb_to_linear*/f_col; + vec3 surf_color; + // If the figure is large enough to be 'terrain-like', we apply a noise effect to it + #ifndef EXPERIMENTAL_NONOISE + if (scale >= 0.5) { + float noise = hash(vec4(floor(m_pos * 3.0 - f_norm * 0.5), 0)); + + const float A = 0.055; + const float W_INV = 1 / (1 + A); + const float W_2 = W_INV * W_INV; + const float NOISE_FACTOR = 0.015; + vec3 noise_delta = (sqrt(f_col) * W_INV + noise * NOISE_FACTOR); + surf_color = noise_delta * noise_delta * W_2; + } else + #endif + { + surf_color = f_col; + } + float alpha = 1.0; const float n2 = 1.5; @@ -206,7 +225,7 @@ void main() { vec3 cam_attenuation = vec3(1); float fluid_alt = max(f_pos.z + 1, floor(f_alt + 1)); vec3 mu = medium.x == MEDIUM_WATER ? MU_WATER : vec3(0.0); - #if (FLUID_MODE == FLUID_MODE_SHINY) + #if (FLUID_MODE >= FLUID_MODE_MEDIUM) cam_attenuation = medium.x == MEDIUM_WATER ? compute_attenuation_point(cam_pos.xyz, view_dir, mu, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/f_pos) : compute_attenuation_point(f_pos, -view_dir, mu, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/cam_pos.xyz); diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index 602cc51066..d24b299872 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -70,6 +70,8 @@ layout(location = 0) out vec3 f_pos; layout(location = 1) flat out vec3 f_norm; // float dummy; /*centroid */layout(location = 2) out vec2 f_uv_pos; +layout(location = 3) out vec3 m_pos; +layout(location = 4) out float scale; // out vec3 f_col; // out float f_ao; // out float f_alt; @@ -90,6 +92,9 @@ void main() { // vec4 bone_pos = bones[bone_idx].bone_mat * vec4(pos, 1); + m_pos = pos; + scale = length(bones[bone_idx].bone_mat[0]); + f_pos = ( bones[bone_idx].bone_mat * vec4(pos, 1.0) diff --git a/assets/voxygen/shaders/fluid-frag/cheap.glsl b/assets/voxygen/shaders/fluid-frag/cheap.glsl index 39903c1324..1e4f5b6a8f 100644 --- a/assets/voxygen/shaders/fluid-frag/cheap.glsl +++ b/assets/voxygen/shaders/fluid-frag/cheap.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -23,6 +23,7 @@ layout(location = 0) in vec3 f_pos; layout(location = 1) flat in uint f_pos_norm; +layout(location = 2) in vec2 f_vel; // in vec3 f_col; // in float f_light; // in vec3 light_pos[2]; @@ -50,6 +51,29 @@ layout(location = 0) out vec4 tgt_color; #include <light.glsl> #include <lod.glsl> +vec4 water_col(vec4 posx, vec4 posy) { + posx = (posx + focus_off.x) * 0.1; + posy = (posy + focus_off.y) * 0.1; + return 0.5 + (vec4( + textureLod(sampler2D(t_noise, s_noise), vec2(posx.x, posy.x), 0).x, + textureLod(sampler2D(t_noise, s_noise), vec2(posx.y, posy.y), 0).x, + textureLod(sampler2D(t_noise, s_noise), vec2(posx.z, posy.z), 0).x, + textureLod(sampler2D(t_noise, s_noise), vec2(posx.w, posy.w), 0).x + ) - 0.5) * 1.0; +} + +float water_col_vel(vec2 pos){ + vec4 cols = water_col( + pos.x - tick.x * floor(f_vel.x) - vec2(0.0, tick.x).xyxy, + pos.y - tick.x * floor(f_vel.y) - vec2(0.0, tick.x).xxyy + ); + return mix( + mix(cols.x, cols.y, fract(f_vel.x + 1.0)), + mix(cols.z, cols.w, fract(f_vel.x + 1.0)), + fract(f_vel.y + 1.0) + ); +} + void main() { #ifdef EXPERIMENTAL_BAREMINIMUM tgt_color = vec4(simple_lighting(f_pos.xyz, MU_SCATTER, 1.0), 0.5); @@ -83,14 +107,15 @@ 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 = (1.0 - MU_WATER) * MU_SCATTER;//srgb_to_linear(vec3(0.2, 0.5, 1.0)); - // /*const */vec3 water_color = srgb_to_linear(vec3(0.0, 0.25, 0.5)); + + float water_shade = water_col_vel(f_pos.xy); + vec3 water_color = (1.0 - mix(MU_WATER, pow(vec3(0.8, 0.9, 0.08), vec3(0.25)), water_shade)) * MU_SCATTER; /* vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 moon_dir = get_moon_dir(time_of_day.x); */ -#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY) +#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE >= FLUID_MODE_MEDIUM) float f_alt = alt_at(f_pos.xy); -#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP) +#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_LOW) float f_alt = f_pos.z; #endif @@ -134,10 +159,18 @@ void main() { vec3 k_d = vec3(1.0); vec3 k_s = vec3(R_s); + vec3 reflect_ray_dir = reflect(cam_to_frag, f_norm); + + vec3 reflect_color = vec3(0.0); + #if (REFLECTION_MODE >= REFLECTION_MODE_MEDIUM) + reflect_color = get_sky_color(reflect_ray_dir, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac); + #endif + vec3 emitted_light, reflected_light; // Prevent the sky affecting light when underground float not_underground = clamp((f_pos.z - f_alt) / 128.0 + 1.0, 0.0, 1.0); + reflect_color *= not_underground; // float point_shadow = shadow_at(f_pos, f_norm); // vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); @@ -191,15 +224,18 @@ 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) * 0.75; + float passthrough = max(dot(cam_norm, -cam_to_frag), 0); + float min_refl = 0.0; - if (medium.x != MEDIUM_WATER) { - min_refl = min(emitted_light.r, min(emitted_light.g, emitted_light.b)); + float opacity = (1.0 - passthrough) * 1.0 / (1.0 + min_refl); + if (medium.x == MEDIUM_WATER) { + // Hack to make the transparency of the surface fade when underwater to avoid artifacts + opacity = min(sqrt(max(opacity, clamp((f_pos.z - cam_pos.z) * 0.05, 0.0, 1.0))), 0.99); } - vec3 surf_color = illuminate(max_light, view_dir, water_color * /* fog_color * */emitted_light, /*surf_color * */water_color * reflected_light); + vec3 surf_color = illuminate(max_light, view_dir, water_color * /* fog_color * */emitted_light, /*surf_color * */reflect_color * water_shade + water_color * reflected_light); // vec4 color = vec4(surf_color, passthrough * 1.0 / (1.0 + min_refl));// * (1.0 - /*log(1.0 + cam_attenuation)*//*cam_attenuation*/1.0 / (2.0 - log_cam))); - vec4 color = vec4(surf_color, (1.0 - passthrough) * 1.0 / (1.0 + min_refl)); + vec4 color = vec4(surf_color, opacity); tgt_color = color; } diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index 4c4b58a961..d1b64fb837 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -25,6 +25,7 @@ layout(location = 0) in vec3 f_pos; layout(location = 1) flat in uint f_pos_norm; +layout(location = 2) in vec2 f_vel; // in vec3 f_col; // in float f_light; // in vec3 light_pos[2]; @@ -52,35 +53,72 @@ layout(location = 0) out vec4 tgt_color; #include <light.glsl> #include <lod.glsl> -vec2 wavedx(vec2 position, vec2 direction, float speed, float frequency, float timeshift) { - float x = dot(direction, position) * frequency + timeshift * speed; - float wave = pow(sin(x) + 0.5, 2); - float dx = wave * cos(x); - return vec2(wave, -dx); +void wave_dx(vec4 posx, vec4 posy, vec2 dir, float speed, float frequency, float timeshift, out vec4 wave, out vec4 dx) { + vec4 x = vec4( + dot(dir, vec2(posx.x, posy.x)), + dot(dir, vec2(posx.y, posy.y)), + dot(dir, vec2(posx.z, posy.z)), + dot(dir, vec2(posx.w, posy.w)) + ) * frequency + timeshift * speed; + wave = sin(x) + 0.5; + wave *= wave; + dx = -wave * cos(x); } -// Based on https://www.shadertoy.com/view/MdXyzX -float wave_height(vec3 pos){ - pos *= 0.3; +// Based loosely on https://www.shadertoy.com/view/MdXyzX. +// Modified to allow calculating the wave function 4 times at once using different positions (used for intepolation +// for moving water). The general idea is to sample the wave function at different positions, where those positions +// depend on increments of the velocity, and then interpolate between those velocities to get a smooth water velocity. +vec4 wave_height(vec4 posx, vec4 posy) { float iter = 0.0; - float phase = 6.0; - float speed = 2.0; - float weight = 1.0; - float w = 0.0; + float phase = 4.0; + float weight = 1.5; + vec4 w = vec4(0.0); float ws = 0.0; - const float drag_factor = 0.048; - for(int i = 0; i < 11; i ++){ + const float speed_per_iter = 0.1; + #if (FLUID_MODE == FLUID_MODE_HIGH) + float speed = 1.0; + posx *= 0.2; + posy *= 0.2; + const float drag_factor = 0.035; + const int iters = 21; + const float scale = 25.0; + #else + float speed = 2.0; + posx *= 0.3; + posy *= 0.3; + const float drag_factor = 0.04; + const int iters = 11; + const float scale = 5.0; + #endif + const float iter_shift = (3.14159 * 2.0) / 7.3; + + for(int i = 0; i < iters; 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; + vec4 wave, dx; + wave_dx(posx, posy, p, speed, phase, tick.x, wave, dx); + posx += p.x * dx * weight * drag_factor; + posy += p.y * dx * weight * drag_factor; + w += wave * weight; + iter += iter_shift * 1.5; ws += weight; - weight = mix(weight, 0.0, 0.15); - phase *= 1.18; - speed *= 1.07; + weight = mix(weight, 0.0, 0.2); + phase *= 1.2; + speed += speed_per_iter; } - return w / ws * 10.0; + return w / ws * scale; +} + +float wave_height_vel(vec2 pos) { + vec4 heights = wave_height( + pos.x - tick.x * floor(f_vel.x) - vec2(0.0, tick.x).xyxy, + pos.y - tick.x * floor(f_vel.y) - vec2(0.0, tick.x).xxyy + ); + return mix( + mix(heights.x, heights.y, fract(f_vel.x + 1.0)), + mix(heights.z, heights.w, fract(f_vel.x + 1.0)), + fract(f_vel.y + 1.0) + ); } void main() { @@ -127,11 +165,11 @@ void main() { } vec3 c_norm = cross(f_norm, b_norm); - 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)); - float wave01 = wave_height(wave_pos + vec3(0, wave_sample_dist, 0)); + vec3 wave_pos = mod(f_pos + focus_off.xyz, vec3(3000.0)) - (f_pos.z + focus_off.z) * 0.2; + float wave_sample_dist = 0.1; + float wave00 = wave_height_vel(wave_pos.xy); + float wave10 = wave_height_vel(wave_pos.xy + vec2(wave_sample_dist, 0)); + float wave01 = wave_height_vel(wave_pos.xy + vec2(0, wave_sample_dist)); // Possibility of div by zero when slope = 0, // however this only results in no water surface appearing @@ -175,9 +213,9 @@ void main() { //norm = f_norm; vec3 water_color = (1.0 - MU_WATER) * MU_SCATTER; -#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY) +#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE >= FLUID_MODE_MEDIUM) float f_alt = alt_at(f_pos.xy); -#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP) +#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_LOW) float f_alt = f_pos.z; #endif @@ -209,14 +247,6 @@ void main() { // 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); - reflect_color = get_cloud_color(reflect_color, ray_dir, f_pos.xyz, time_of_day.x, 100000.0, 0.1); - reflect_color *= f_light; - - // Prevent the sky affecting light when underground - float not_underground = clamp((f_pos.z - f_alt) / 32.0 + 1.0, 0.0, 1.0); - reflect_color *= not_underground; // /*const */vec3 water_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)); // /*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. @@ -237,6 +267,21 @@ 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; + vec3 reflect_color; + #if (REFLECTION_MODE >= REFLECTION_MODE_MEDIUM) + reflect_color = get_sky_color(ray_dir, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac); + reflect_color = get_cloud_color(reflect_color, ray_dir, f_pos.xyz, time_of_day.x, 100000.0, 0.1); + #else + reflect_color = get_sky_color(ray_dir, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac); + #endif + // Sort of non-physical, but we try to balance the reflection intensity with the direct light from the sun, + // resulting in decent reflection of the ambient environment even after the sun has gone down. + reflect_color *= f_light * (sun_shade_frac * 0.75 + 0.25); + + // Prevent the sky affecting light when underground + float not_underground = clamp((f_pos.z - f_alt) / 32.0 + 1.0, 0.0, 1.0); + reflect_color *= not_underground; + // DirectionalLight sun_info = get_sun_info(sun_dir, sun_shade_frac, light_pos); float point_shadow = shadow_at(f_pos, f_norm); DirectionalLight sun_info = get_sun_info(sun_dir, point_shadow * sun_shade_frac, /*sun_pos*/f_pos); @@ -271,6 +316,7 @@ void main() { vec3 mu = MU_WATER; // 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.xyz); + //reflect_color *= cam_attenuation; // float water_depth_to_vertical = max(/*f_alt - f_pos.z*/f_light, 0.0); // For ambient color, we just take the distance to the surface out of laziness. // See https://en.wikipedia.org/wiki/Beer%E2%80%93Lambert_law. @@ -288,10 +334,10 @@ void main() { // 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) * 0.75; + float passthrough = max(dot(cam_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); + max_light += get_sun_diffuse2(sun_info, moon_info, cam_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); emitted_light *= not_underground; reflected_light *= not_underground; @@ -332,7 +378,7 @@ void main() { // diffuse_light += point_light; // reflected_light += point_light; // vec3 surf_color = srgb_to_linear(vec3(0.2, 0.5, 1.0)) * light * diffuse_light * ambient_light; - const float REFLECTANCE = 0.5; + const float REFLECTANCE = 1.0; vec3 surf_color = illuminate(max_light, view_dir, water_color * emitted_light/* * log(1.0 - MU_WATER)*/, /*cam_attenuation * *//*water_color * */reflect_color * REFLECTANCE + water_color * reflected_light/* * log(1.0 - MU_WATER)*/); // passthrough = pow(passthrough, 1.0 / (1.0 + water_depth_to_camera)); @@ -359,10 +405,18 @@ void main() { // float log_cam = log(min(cam_attenuation.r, min(cam_attenuation.g, cam_attenuation.b))); float min_refl = 0.0; + float opacity = (1.0 - passthrough) * 0.5 / (1.0 + min_refl); if (medium.x != MEDIUM_WATER) { min_refl = min(emitted_light.r, min(emitted_light.g, emitted_light.b)); + } else { + // Hack to make the transparency of the surface fade when underwater to avoid artifacts + if (dot(refract_ray_dir, cam_to_frag) > 0.0) { + opacity = 0.99; + } else { + opacity = min(sqrt(max(opacity, clamp((f_pos.z - cam_pos.z) * 0.05, 0.0, 1.0))), 0.99); + } } - vec4 color = vec4(surf_color, (1.0 - passthrough) * 1.0 / (1.0 + min_refl));// * (1.0 - /*log(1.0 + cam_attenuation)*//*cam_attenuation*/1.0 / (2.0 - log_cam))); + vec4 color = vec4(surf_color, opacity);// * (1.0 - /*log(1.0 + cam_attenuation)*//*cam_attenuation*/1.0 / (2.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 b078b87407..16d3a12dfa 100644 --- a/assets/voxygen/shaders/fluid-vert.glsl +++ b/assets/voxygen/shaders/fluid-vert.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -21,6 +21,7 @@ #include <random.glsl> layout(location = 0) in uint v_pos_norm; +layout(location = 1) in uint v_vel; // in uint v_col_light; layout(std140, set = 2, binding = 0) @@ -42,6 +43,7 @@ uniform u_locals { layout(location = 0) out vec3 f_pos; layout(location = 1) flat out uint f_pos_norm; +layout(location = 2) out vec2 f_vel; // out vec3 f_col; // out float f_light; // out vec3 light_pos[2]; @@ -50,6 +52,10 @@ const float EXTRA_NEG_Z = 65536.0/*65536.1*/; void main() { f_pos = vec3(v_pos_norm & 0x3Fu, (v_pos_norm >> 6) & 0x3Fu, float((v_pos_norm >> 12) & 0x1FFFFu) - EXTRA_NEG_Z) + model_offs - focus_off.xyz; + f_vel = vec2( + (float(v_vel & 0xFFFFu) - 32768.0) / 1000.0, + (float((v_vel >> 16u) & 0xFFFFu) - 32768.0) / 1000.0 + ); // f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0)); // f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0)); @@ -63,7 +69,7 @@ void main() { #endif float pull_down = pow(distance(focus_pos.xy, f_pos.xy) / (view_distance.x * 0.95), 20.0) * 0.7; - f_pos.z -= pull_down; + //f_pos.z -= pull_down; #ifdef EXPERIMENTAL_CURVEDWORLD f_pos.z -= pow(distance(f_pos.xy + focus_off.xy, focus_pos.xy + focus_off.xy) * 0.05, 2); @@ -73,7 +79,7 @@ void main() { // f_pos.xy += 0.01; // Avoid z-fighting // f_pos.x += 0.1 * sin(tick.x / 60 * hash(vec4(f_pos.xyz, 1.0))); // f_pos.y += 0.1 * sin(tick.x / 60 * hash(vec4(f_pos.xyz, 2.0))); -#if (FLUID_MODE == FLUID_MODE_SHINY) +#if (FLUID_MODE >= FLUID_MODE_MEDIUM) // f_pos.z -= 0.1 + 0.1 * (sin(tick.x/* / 60.0*/* 2.0 + f_pos.x * 2.0 + f_pos.y * 2.0) + 1.0) * 0.5; #endif diff --git a/assets/voxygen/shaders/include/cloud/none.glsl b/assets/voxygen/shaders/include/cloud/none.glsl index 5d52deb96d..97a6e610e5 100644 --- a/assets/voxygen/shaders/include/cloud/none.glsl +++ b/assets/voxygen/shaders/include/cloud/none.glsl @@ -1,8 +1,14 @@ #include <lod.glsl> +#include <sky.glsl> vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, float time_of_day, float max_dist, float quality) { // Underwater light attenuation surf_color = water_diffuse(surf_color, dir, max_dist); + if (max_dist < DIST_CAP) { + vec3 sky_light = get_sky_light(dir, time_of_day, false); + surf_color = mix(sky_light, surf_color, 1.0 / exp(max_dist / 5000.0)); + } + return surf_color; } diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index f3155a0416..1dca0d58d3 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -232,92 +232,86 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of vec3 moon_color = get_moon_color(); // Clouds aren't visible underwater - #ifdef IS_POSTPROCESS - if (medium.x != 1) { - #endif - float cdist = max_dist; - float ldist = cdist; - // i is an emergency brake - float min_dist = clamp(max_dist / 4, 0.25, 24); - int i; + float cdist = max_dist; + float ldist = cdist; + // i is an emergency brake + float min_dist = clamp(max_dist / 4, 0.25, 24); + int i; - #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) + #if (CLOUD_MODE >= CLOUD_MODE_MEDIUM) + #ifndef EXPERIMENTAL_NORAINBOWS + // TODO: Make it a double rainbow + float rainbow_t = (0.7 - dot(sun_dir.xyz, dir)) * 8 / 0.05; + int rainbow_c = int(floor(rainbow_t)); + rainbow_t = fract(rainbow_t); + rainbow_t = rainbow_t * rainbow_t; + #endif + #endif + + for (i = 0; cdist > min_dist && i < 250; i ++) { + ldist = cdist; + cdist = step_to_dist(trunc(dist_to_step(cdist - 0.25, quality)), quality); + + vec3 emission; + float not_underground; // Used to prevent sunlight leaking underground + vec3 pos = origin + dir * ldist * splay; + // `sample` is a reserved keyword + vec4 sample_ = cloud_at(origin + dir * ldist * splay, ldist, emission, not_underground); + + vec2 density_integrals = max(sample_.zw, vec2(0)); + + float sun_access = max(sample_.x, 0); + float moon_access = max(sample_.y, 0); + float cloud_scatter_factor = density_integrals.x; + float global_scatter_factor = density_integrals.y; + + float step = (ldist - cdist) * 0.01; + float cloud_darken = pow(1.0 / (1.0 + cloud_scatter_factor), step); + float global_darken = pow(1.0 / (1.0 + global_scatter_factor), step); + // Proportion of light diffusely scattered instead of absorbed + float cloud_diffuse = 0.25; + + surf_color = + // Attenuate light passing through the clouds + surf_color * cloud_darken * global_darken + + // Add the directed light light scattered into the camera by the clouds and the atmosphere (global illumination) + sun_color * sun_scatter * get_sun_brightness() * (sun_access * (1.0 - cloud_darken) * cloud_diffuse /*+ sky_color * global_scatter_factor*/) + + 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 + max_dist * 0.003) + + emission * density_integrals.y * step; + + // Rainbow + #if (CLOUD_MODE >= CLOUD_MODE_ULTRA) #ifndef EXPERIMENTAL_NORAINBOWS - // TODO: Make it a double rainbow - float rainbow_t = (0.7 - dot(sun_dir.xyz, dir)) * 8 / 0.05; - int rainbow_c = int(floor(rainbow_t)); - rainbow_t = fract(rainbow_t); - rainbow_t = rainbow_t * rainbow_t; + if (rainbow_c >= 0 && rainbow_c < 8) { + vec3 colors[9] = { + surf_color, + vec3(0.9, 0.5, 0.9), + vec3(0.25, 0.0, 0.5), + vec3(0.0, 0.0, 1.0), + vec3(0.0, 0.5, 0.0), + vec3(1.0, 1.0, 0.0), + vec3(1.0, 0.6, 0.0), + vec3(1.0, 0.0, 0.0), + surf_color, + }; + float h = max(0.0, min(pos.z, 900.0 - pos.z) / 450.0); + float rain = rain_density_at(pos.xy) * pow(h, 0.1); + + float sun = sun_access * get_sun_brightness(); + float energy = pow(rain * sun * min(cdist / 500.0, 1.0), 2.0) * 0.4; + + surf_color = mix( + surf_color, + mix(colors[rainbow_c], colors[rainbow_c + 1], rainbow_t), + energy + ); + } #endif #endif - - for (i = 0; cdist > min_dist && i < 250; i ++) { - ldist = cdist; - cdist = step_to_dist(trunc(dist_to_step(cdist - 0.25, quality)), quality); - - vec3 emission; - float not_underground; // Used to prevent sunlight leaking underground - vec3 pos = origin + dir * ldist * splay; - // `sample` is a reserved keyword - vec4 sample_ = cloud_at(origin + dir * ldist * splay, ldist, emission, not_underground); - - vec2 density_integrals = max(sample_.zw, vec2(0)); - - float sun_access = max(sample_.x, 0); - float moon_access = max(sample_.y, 0); - float cloud_scatter_factor = density_integrals.x; - float global_scatter_factor = density_integrals.y; - - float step = (ldist - cdist) * 0.01; - float cloud_darken = pow(1.0 / (1.0 + cloud_scatter_factor), step); - float global_darken = pow(1.0 / (1.0 + global_scatter_factor), step); - // Proportion of light diffusely scattered instead of absorbed - float cloud_diffuse = 0.25; - - surf_color = - // Attenuate light passing through the clouds - surf_color * cloud_darken * global_darken + - // Add the directed light light scattered into the camera by the clouds and the atmosphere (global illumination) - sun_color * sun_scatter * get_sun_brightness() * (sun_access * (1.0 - cloud_darken) * cloud_diffuse /*+ sky_color * global_scatter_factor*/) + - 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 + max_dist * 0.003) + - emission * density_integrals.y * step; - - // Rainbow - #if (CLOUD_MODE >= CLOUD_MODE_ULTRA) - #ifndef EXPERIMENTAL_NORAINBOWS - if (rainbow_c >= 0 && rainbow_c < 8) { - vec3 colors[9] = { - surf_color, - vec3(0.9, 0.5, 0.9), - vec3(0.25, 0.0, 0.5), - vec3(0.0, 0.0, 1.0), - vec3(0.0, 0.5, 0.0), - vec3(1.0, 1.0, 0.0), - vec3(1.0, 0.6, 0.0), - vec3(1.0, 0.0, 0.0), - surf_color, - }; - float h = max(0.0, min(pos.z, 900.0 - pos.z) / 450.0); - float rain = rain_density_at(pos.xy) * pow(h, 0.1); - - float sun = sun_access * get_sun_brightness(); - float energy = pow(rain * sun * min(cdist / 500.0, 1.0), 2.0) * 0.4; - - surf_color = mix( - surf_color, - mix(colors[rainbow_c], colors[rainbow_c + 1], rainbow_t), - energy - ); - } - #endif - #endif - } - #ifdef IS_POSTPROCESS - } - #endif + } // Underwater light attenuation surf_color = water_diffuse(surf_color, dir, max_dist); diff --git a/assets/voxygen/shaders/include/constants.glsl b/assets/voxygen/shaders/include/constants.glsl index edd1e27b91..e727e49563 100644 --- a/assets/voxygen/shaders/include/constants.glsl +++ b/assets/voxygen/shaders/include/constants.glsl @@ -6,8 +6,13 @@ #define VOXYGEN_COMPUTATION_PREFERENCE_FRAGMENT 0 #define VOXYGEN_COMPUTATION_PREFERENCE_VERTEX 1 -#define FLUID_MODE_CHEAP 0 -#define FLUID_MODE_SHINY 1 +#define FLUID_MODE_LOW 0 +#define FLUID_MODE_MEDIUM 1 +#define FLUID_MODE_HIGH 2 + +#define REFLECTION_MODE_LOW 0 +#define REFLECTION_MODE_MEDIUM 1 +#define REFLECTION_MODE_HIGH 2 #define CLOUD_MODE_NONE 0 #define CLOUD_MODE_MINIMAL 1 diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index d2efde0737..782770044a 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -138,7 +138,7 @@ float alt_at(vec2 pos) { float alt_at_real(vec2 pos) { // Basic idea: only really need the real altitude for an accurate water height estimation, so if we are in the cheap shader take a shortcut. -// #if (FLUID_MODE == FLUID_MODE_CHEAP) +// #if (FLUID_MODE == FLUID_MODE_LOW) // return alt_at(pos); // #elif (FLUID_MODE == FLUID_MODE_SHINY) return (/*round*/(textureBicubic16(t_alt, s_alt, pos_to_tex(pos)).r * (/*1300.0*//*1278.7266845703125*/view_distance.w)) + /*140.0*/view_distance.z - focus_off.z); @@ -391,13 +391,13 @@ vec3 water_diffuse(vec3 color, vec3 dir, float max_dist) { float f_alt = alt_at(cam_pos.xy); float fluid_alt = max(cam_pos.z + 1, floor(f_alt + 1)); - float water_dist = clamp((fluid_alt - cam_pos.z) / pow(max(dir.z, 0), 5), 0, max_dist); + float water_dist = clamp((fluid_alt - cam_pos.z) / pow(max(dir.z, 0), 2), 0, max_dist); - float fade = pow(0.97, water_dist); + float fade = pow(0.95, water_dist); return mix(vec3(0.0, 0.2, 0.5) * (get_sun_brightness() * get_sun_color() + get_moon_brightness() * get_moon_color()) - * pow(0.99, max((fluid_alt - cam_pos.z) * 12.0 - dir.z * 200, 0)), color.rgb, fade); + * pow(0.99, max((fluid_alt - cam_pos.z) * 12.0 - dir.z * 200, 0)), color.rgb * exp(-MU_WATER * water_dist * 0.1), fade); } else { return color; } diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index 15efe21f86..46c3336668 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -26,7 +26,7 @@ const vec3 DAWN_LIGHT = vec3(5.0, 2.0, 1.15); const vec3 SUN_HALO_DAWN = vec3(8.2, 3.0, 2.1); 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_MID = vec3(0.18, 0.28, 0.6); const vec3 SKY_DAY_BOT = vec3(0.1, 0.2, 0.3); const vec3 DAY_LIGHT = vec3(3.8, 3.0, 1.8); const vec3 SUN_HALO_DAY = vec3(0.25, 0.25, 0.001); @@ -503,7 +503,12 @@ float is_star_at(vec3 dir) { //return 0.0; - return 5.0 / (1.0 + pow(dist * 750, 8)); + #if (CLOUD_MODE == CLOUD_MODE_NONE) + const float power = 5.0; + #else + const float power = 50.0; + #endif + return power * max(sun_dir.z, 0.1) / (1.0 + pow(dist * 750, 8)); } vec3 get_sky_light(vec3 dir, float time_of_day, bool with_stars) { @@ -570,7 +575,7 @@ vec3 get_sky_light(vec3 dir, float time_of_day, bool with_stars) { return sky_color * magnetosphere_tint; } -vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_features, float refractionIndex) { +vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_features, float refractionIndex, bool fake_clouds, float sun_shade_frac) { // Sky color /* vec3 sun_dir = get_sun_dir(time_of_day); vec3 moon_dir = get_moon_dir(time_of_day); */ @@ -581,7 +586,7 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q // moon_dir = moon_dir.z <= 0 ? refract(moon_dir/*-view_dir*/, vec3(0.0, 0.0, 1.0), refractionIndex) : moon_dir; // Sun - const vec3 SUN_SURF_COLOR = vec3(1.5, 0.9, 0.35) * 50.0; + const vec3 SUN_SURF_COLOR = vec3(1.5, 0.9, 0.35) * 10.0; vec3 sun_halo_color = mix( (sun_dir.x > 0 ? SUN_HALO_DUSK : SUN_HALO_DAWN)* magnetosphere_tint, @@ -591,15 +596,29 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q float sun_halo_power = 20.0; #if (CLOUD_MODE == CLOUD_MODE_NONE) - sun_halo_power = 1000.0; - sun_halo_color *= 0.1; + if (true) { + #else + if (fake_clouds || medium.x == MEDIUM_WATER) { #endif + sun_halo_power = 30.0; + sun_halo_color *= 0.01; + } vec3 sun_halo = sun_halo_color * 25 * pow(max(dot(dir, -sun_dir), 0), sun_halo_power); vec3 sun_surf = vec3(0); if (with_features) { float angle = 0.00035; - sun_surf = clamp((dot(dir, -sun_dir) - (1.0 - angle)) * 4 / angle, 0, 1) * SUN_SURF_COLOR * SUN_COLOR_FACTOR; + sun_surf = clamp((dot(dir, -sun_dir) - (1.0 - angle)) * 4 / angle, 0, 1) + * SUN_SURF_COLOR + * SUN_COLOR_FACTOR + * sun_shade_frac; + } + #if (CLOUD_MODE == CLOUD_MODE_NONE) + if (true) { + #else + if (fake_clouds || medium.x == MEDIUM_WATER) { + #endif + sun_surf *= 0.1; } vec3 sun_light = sun_halo + sun_surf; @@ -610,25 +629,34 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q vec3 moon_halo_color = MOON_HALO_COLOR; float moon_halo_power = 20.0; - #if (CLOUD_MODE == CLOUD_MODE_NONE) - moon_halo_power = 2500.0; - moon_halo_color *= 0.1; - #endif - vec3 moon_halo = moon_halo_color * pow(max(dot(dir, -moon_dir), 0), moon_halo_power); vec3 moon_surf = vec3(0); if (with_features) { float angle = 0.00035; moon_surf = clamp((dot(dir, -moon_dir) - (1.0 - angle)) * 4 / angle, 0, 1) * MOON_SURF_COLOR; } + #if (CLOUD_MODE == CLOUD_MODE_NONE) + if (true) { + #else + if (fake_clouds || medium.x == MEDIUM_WATER) { + #endif + moon_halo_power = 50.0; + moon_halo_color *= 0.2; + moon_surf *= 0.05; + } + vec3 moon_halo = moon_halo_color * pow(max(dot(dir, -moon_dir), 0), moon_halo_power); vec3 moon_light = moon_halo + moon_surf; // Replaced all clamp(sun_dir, 0, 1) with max(sun_dir, 0) because sun_dir is calculated from sin and cos, which are never > 1 + vec3 sky_color; #if (CLOUD_MODE == CLOUD_MODE_NONE) - vec3 sky_color = get_sky_light(dir, time_of_day, true); + if (true) { #else - vec3 sky_color; + if (fake_clouds || medium.x == MEDIUM_WATER) { + #endif + sky_color = get_sky_light(dir, time_of_day, !fake_clouds); + } else { if (medium.x == MEDIUM_WATER) { sky_color = get_sky_light(dir, time_of_day, true); } else { @@ -636,13 +664,17 @@ vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float q float star = is_star_at(star_dir); sky_color = vec3(0) + star; } - #endif + } return sky_color + sun_light + moon_light; } +vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_features, float refractionIndex) { + return get_sky_color(dir, time_of_day, origin, f_pos, quality, with_features, refractionIndex, false, 1.0); +} + vec3 get_sky_color(vec3 dir, float time_of_day, vec3 origin, vec3 f_pos, float quality, bool with_stars) { - return get_sky_color(dir, time_of_day, origin, f_pos, quality, with_stars, 1.0); + return get_sky_color(dir, time_of_day, origin, f_pos, quality, with_stars, 1.0, false, 1.0); } float fog(vec3 f_pos, vec3 focus_pos, uint medium) { diff --git a/assets/voxygen/shaders/include/srgb.glsl b/assets/voxygen/shaders/include/srgb.glsl index a04edaf138..c7047404ad 100644 --- a/assets/voxygen/shaders/include/srgb.glsl +++ b/assets/voxygen/shaders/include/srgb.glsl @@ -536,7 +536,7 @@ 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) { #if (LIGHTING_TRANSPORT_MODE == LIGHTING_TRANSPORT_MODE_IMPORTANCE) - return vec3(1.0); + return pow(1.0 - mu, vec3(3)); #elif (LIGHTING_TRANSPORT_MODE == LIGHTING_TRANSPORT_MODE_RADIANCE) // return vec3(1.0); /*if (mu == vec3(0.0)) { diff --git a/assets/voxygen/shaders/light-shadows-directed-vert.glsl b/assets/voxygen/shaders/light-shadows-directed-vert.glsl index 1ff6fbffd9..38486aa808 100644 --- a/assets/voxygen/shaders/light-shadows-directed-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-directed-vert.glsl @@ -7,9 +7,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/light-shadows-figure-vert.glsl b/assets/voxygen/shaders/light-shadows-figure-vert.glsl index 1df58ae055..c48240c1b3 100644 --- a/assets/voxygen/shaders/light-shadows-figure-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-figure-vert.glsl @@ -9,9 +9,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/light-shadows-frag.glsl b/assets/voxygen/shaders/light-shadows-frag.glsl index 3671ace978..d6aded48d7 100644 --- a/assets/voxygen/shaders/light-shadows-frag.glsl +++ b/assets/voxygen/shaders/light-shadows-frag.glsl @@ -11,9 +11,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/light-shadows-geom.glsl b/assets/voxygen/shaders/light-shadows-geom.glsl index 459232a926..dbc2529c63 100644 --- a/assets/voxygen/shaders/light-shadows-geom.glsl +++ b/assets/voxygen/shaders/light-shadows-geom.glsl @@ -11,9 +11,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/light-shadows-vert.glsl b/assets/voxygen/shaders/light-shadows-vert.glsl index 4bdbae25f4..dd98eeb8e9 100644 --- a/assets/voxygen/shaders/light-shadows-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-vert.glsl @@ -7,9 +7,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/lod-object-frag.glsl b/assets/voxygen/shaders/lod-object-frag.glsl index feb33a4362..9e445870b7 100644 --- a/assets/voxygen/shaders/lod-object-frag.glsl +++ b/assets/voxygen/shaders/lod-object-frag.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -41,9 +41,9 @@ void main() { vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); vec3 view_dir = -cam_to_frag; -#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY) +#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE >= FLUID_MODE_MEDIUM) float f_alt = alt_at(f_pos.xy); -#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP) +#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_LOW) float f_alt = f_pos.z; #endif diff --git a/assets/voxygen/shaders/lod-terrain-frag.glsl b/assets/voxygen/shaders/lod-terrain-frag.glsl index 2358611b0a..4318c2967f 100644 --- a/assets/voxygen/shaders/lod-terrain-frag.glsl +++ b/assets/voxygen/shaders/lod-terrain-frag.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -445,10 +445,10 @@ void main() { vec3 moon_dir = get_moon_dir(time_of_day.x); */ // voxel_norm = vec3(0.0); -#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY) +#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE >= FLUID_MODE_MEDIUM) float shadow_alt = /*f_pos.z;*/alt_at(f_pos.xy);//max(alt_at(f_pos.xy), f_pos.z); // float shadow_alt = f_pos.z; -#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP) +#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_LOW) float shadow_alt = f_pos.z; #endif @@ -579,9 +579,9 @@ void main() { vec3 emitted_light, reflected_light; - vec3 mu = medium.x == MEDIUM_WATER/* && f_pos.z <= fluid_alt*/ ? MU_WATER : vec3(0.0); + vec3 mu = medium.x == MEDIUM_WATER ? 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(cam_pos.xyz, view_dir, mu, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/f_pos); + 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); // Use f_norm here for better shadows. // vec3 light_frac = light_reflection_factor(f_norm/*l_norm*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(/*1.0*/R_s), alpha); @@ -648,34 +648,43 @@ void main() { // vec3 surf_color = illuminate(f_col, light, diffuse_light, ambient_light); // f_col = f_col + (hash(vec4(floor(vec3(focus_pos.xy + splay(v_pos_orig), f_pos.z)) * 3.0 - round(f_norm) * 0.5, 0)) - 0.5) * 0.05; // Small-scale noise vec3 surf_color; - #if (FLUID_MODE == FLUID_MODE_SHINY) - if (length(f_col_raw - vec3(0.02, 0.06, 0.22)) < 0.025 && dot(vec3(0, 0, 1), f_norm) > 0.9) { + float surf_alpha = 1.0; + if (length(f_col_raw - vec3(0.02, 0.06, 0.22)) < 0.025 && dot(vec3(0, 0, 1), f_norm) > 0.9) { + vec3 reflect_ray = cam_to_frag * vec3(1, 1, -1); + #if (FLUID_MODE >= FLUID_MODE_MEDIUM) vec3 water_color = (1.0 - MU_WATER) * MU_SCATTER; - vec3 reflect_ray = cam_to_frag * vec3(1, 1, -1); float passthrough = dot(faceforward(f_norm, f_norm, cam_to_frag), -cam_to_frag); - vec3 reflect_color = get_sky_color(reflect_ray, time_of_day.x, f_pos, vec3(-100000), 0.125, true); - reflect_color = get_cloud_color(reflect_color, reflect_ray, cam_pos.xyz, time_of_day.x, 100000.0, 0.1); + vec3 reflect_color; + #if (FLUID_MODE == FLUID_MODE_HIGH) + reflect_color = get_sky_color(reflect_ray, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac); + reflect_color = get_cloud_color(reflect_color, reflect_ray, cam_pos.xyz, time_of_day.x, 100000.0, 0.1); + #else + reflect_color = get_sky_color(reflect_ray, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac); + #endif + reflect_color *= sun_shade_frac * 0.75 + 0.25; - const float REFLECTANCE = 0.5; + const float REFLECTANCE = 1.0; surf_color = illuminate(max_light, view_dir, f_col * emitted_light, reflect_color * REFLECTANCE + water_color * reflected_light); const vec3 underwater_col = vec3(0.0); float min_refl = min(emitted_light.r, min(emitted_light.g, emitted_light.b)); surf_color = mix(underwater_col, surf_color, (1.0 - passthrough) * 1.0 / (1.0 + min_refl)); - } else { - surf_color = illuminate(max_light, view_dir, f_col * emitted_light, f_col * reflected_light); - } - #else + surf_alpha = 1.0 - passthrough; + #else + surf_alpha = 0.9; + surf_color = get_sky_color(reflect_ray, time_of_day.x, f_pos, vec3(-100000), 0.125, true, 1.0, true, sun_shade_frac); + #endif + } else { surf_color = illuminate(max_light, view_dir, f_col * emitted_light, f_col * reflected_light); - #endif + } // float mist_factor = max(1 - (f_pos.z + (texture(t_noise, f_pos.xy * 0.0005 + time_of_day.x * 0.0003).x - 0.5) * 128.0) / 400.0, 0.0); // //float mist_factor = f_norm.z * 2.0; // color = mix(color, vec3(1.0) * /*diffuse_light*/reflected_light, clamp(mist_factor * 0.00005 * distance(f_pos.xy, focus_pos.xy), 0, 0.3)); // color = surf_color; - tgt_color = vec4(surf_color, 1.0); + tgt_color = vec4(surf_color, surf_alpha); } diff --git a/assets/voxygen/shaders/lod-terrain-vert.glsl b/assets/voxygen/shaders/lod-terrain-vert.glsl index da9f890bfd..0cd3eccd11 100644 --- a/assets/voxygen/shaders/lod-terrain-vert.glsl +++ b/assets/voxygen/shaders/lod-terrain-vert.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/particle-frag.glsl b/assets/voxygen/shaders/particle-frag.glsl index a9259598c8..83f8ff6e1c 100644 --- a/assets/voxygen/shaders/particle-frag.glsl +++ b/assets/voxygen/shaders/particle-frag.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -42,9 +42,9 @@ void main() { vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); vec3 view_dir = -cam_to_frag; -#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY) +#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE >= FLUID_MODE_MEDIUM) float f_alt = alt_at(f_pos.xy); -#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP) +#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_LOW) float f_alt = f_pos.z; #endif @@ -88,7 +88,7 @@ void main() { vec3 cam_attenuation = vec3(1); float fluid_alt = max(f_pos.z + 1, floor(f_alt + 1)); vec3 mu = medium.x == MEDIUM_WATER ? MU_WATER : vec3(0.0); - #if (FLUID_MODE == FLUID_MODE_SHINY) + #if (FLUID_MODE >= FLUID_MODE_MEDIUM) cam_attenuation = medium.x == MEDIUM_WATER ? compute_attenuation_point(cam_pos.xyz, view_dir, MU_WATER, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/f_pos) : compute_attenuation_point(f_pos, -view_dir, vec3(0), fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/cam_pos.xyz); diff --git a/assets/voxygen/shaders/point-light-shadows-vert.glsl b/assets/voxygen/shaders/point-light-shadows-vert.glsl index 507c831bc0..705f2efe8b 100644 --- a/assets/voxygen/shaders/point-light-shadows-vert.glsl +++ b/assets/voxygen/shaders/point-light-shadows-vert.glsl @@ -7,9 +7,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index 4276bde368..89863db99b 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -288,7 +288,7 @@ void main() { vec4 final_color = aa_color; -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) if (medium.x == MEDIUM_WATER) { final_color *= vec4(0.2, 0.2, 0.8, 1.0); } diff --git a/assets/voxygen/shaders/postprocess-vert.glsl b/assets/voxygen/shaders/postprocess-vert.glsl index 21a6b3d8c2..f15ec174b2 100644 --- a/assets/voxygen/shaders/postprocess-vert.glsl +++ b/assets/voxygen/shaders/postprocess-vert.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/rain-occlusion-directed-vert.glsl b/assets/voxygen/shaders/rain-occlusion-directed-vert.glsl index c8bfd187e4..eab9446343 100644 --- a/assets/voxygen/shaders/rain-occlusion-directed-vert.glsl +++ b/assets/voxygen/shaders/rain-occlusion-directed-vert.glsl @@ -7,9 +7,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/rain-occlusion-figure-vert.glsl b/assets/voxygen/shaders/rain-occlusion-figure-vert.glsl index b7f940ea2b..34edba46be 100644 --- a/assets/voxygen/shaders/rain-occlusion-figure-vert.glsl +++ b/assets/voxygen/shaders/rain-occlusion-figure-vert.glsl @@ -9,9 +9,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/skybox-frag.glsl b/assets/voxygen/shaders/skybox-frag.glsl index af28a40aa9..60930b469d 100644 --- a/assets/voxygen/shaders/skybox-frag.glsl +++ b/assets/voxygen/shaders/skybox-frag.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -55,5 +55,5 @@ void main() { } */ vec3 wpos = cam_pos.xyz + /*normalize(f_pos)*/cam_dir * dist; - tgt_color = vec4(cam_attenuation * get_sky_color(normalize(f_pos), time_of_day.x, cam_pos.xyz, wpos, 1.0, true, refractionIndex), 1.0); + tgt_color = vec4(cam_attenuation * get_sky_color(normalize(f_pos), time_of_day.x, cam_pos.xyz, wpos, 1.0, true, refractionIndex, false, 1.0), 1.0); } diff --git a/assets/voxygen/shaders/skybox-vert.glsl b/assets/voxygen/shaders/skybox-vert.glsl index 9f362fedb7..e410cd221f 100644 --- a/assets/voxygen/shaders/skybox-vert.glsl +++ b/assets/voxygen/shaders/skybox-vert.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_SPECULAR -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index fd3ebdd503..700a5eee05 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -51,9 +51,9 @@ void main() { vec3 cam_to_frag = normalize(f_pos - cam_pos.xyz); vec3 view_dir = -cam_to_frag; -#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY) +#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE >= FLUID_MODE_MEDIUM) float f_alt = alt_at(f_pos.xy); -#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP) +#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_LOW) float f_alt = f_pos.z; #endif @@ -94,7 +94,7 @@ void main() { vec3 cam_attenuation = vec3(1); float fluid_alt = max(f_pos.z + 1, floor(f_alt + 1)); vec3 mu = medium.x == MEDIUM_WATER ? MU_WATER : vec3(0.0); - #if (FLUID_MODE == FLUID_MODE_SHINY) + #if (FLUID_MODE >= FLUID_MODE_MEDIUM) cam_attenuation = medium.x == MEDIUM_WATER ? compute_attenuation_point(cam_pos.xyz, view_dir, mu, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/f_pos) : compute_attenuation_point(f_pos, -view_dir, mu, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/cam_pos.xyz); diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 34e38ef55c..16480d77b6 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -7,9 +7,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif @@ -209,9 +209,9 @@ void main() { /* vec3 sun_dir = get_sun_dir(time_of_day.x); vec3 moon_dir = get_moon_dir(time_of_day.x); */ -#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE == FLUID_MODE_SHINY) +#if (SHADOW_MODE == SHADOW_MODE_CHEAP || SHADOW_MODE == SHADOW_MODE_MAP || FLUID_MODE >= FLUID_MODE_MEDIUM) float f_alt = alt_at(f_pos.xy); -#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_CHEAP) +#elif (SHADOW_MODE == SHADOW_MODE_NONE || FLUID_MODE == FLUID_MODE_LOW) float f_alt = f_pos.z; #endif @@ -234,6 +234,11 @@ void main() { // Toggle to see rain_occlusion // tgt_color = vec4(rain_occlusion_at(f_pos.xyz), 0.0, 0.0, 1.0); // return; + #if (REFLECTION_MODE >= REFLECTION_MODE_HIGH) + float f_alpha = 1.0; + #else + const float f_alpha = 1.0; + #endif #if (CLOUD_MODE != CLOUD_MODE_NONE) if (rain_density > 0 && !faces_fluid && f_norm.z > 0.5) { vec3 pos = f_pos + focus_off.xyz; @@ -244,23 +249,26 @@ void main() { drop_pos.z *= 0.5 + hash_fast(uvec3(cell2d, 0)); vec3 cell = vec3(cell2d, floor(drop_pos.z * drop_density.z)); - #ifdef EXPERIMENTAL_WETNESS - float puddle = clamp((noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.03) - 0.5) * 20.0, 0.0, 1.0) + #if (REFLECTION_MODE >= REFLECTION_MODE_HIGH) + float puddle = clamp((noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.02) - 0.5) * 20.0, 0.0, 1.0) * min(rain_density * 10.0, 1.0) - * clamp((f_sky_exposure - 0.9) * 50.0, 0.0, 1.0); + * clamp((f_sky_exposure - 0.95) * 50.0, 0.0, 1.0); #else const float puddle = 1.0; #endif - #ifdef EXPERIMENTAL_WETNESS + #if (REFLECTION_MODE >= REFLECTION_MODE_HIGH) if (puddle > 0.0) { - float h = (noise_2d((f_pos.xy + focus_off.xy) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3) - + (noise_2d((f_pos.xy + focus_off.xy) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6); - float hx = (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3) - + (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6); - float hy = (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3) - + (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6); - f_norm.xy += mix(vec2(0), vec2(h - hx, h - hy) / 0.1 * 0.03, puddle); + f_alpha = puddle * 0.2 * max(1.0 + cam_to_frag.z, 0.3); + #ifdef EXPERIMENTAL_PUDDLEDETAILS + float h = (noise_2d((f_pos.xy + focus_off.xy) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3) + + (noise_2d((f_pos.xy + focus_off.xy) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6); + float hx = (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3) + + (noise_2d((f_pos.xy + focus_off.xy + vec2(0.1, 0)) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6); + float hy = (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.3) - 0.5) * sin(tick.x * 8.0 + f_pos.x * 3) + + (noise_2d((f_pos.xy + focus_off.xy + vec2(0, 0.1)) * 0.6) - 0.5) * sin(tick.x * 3.5 - f_pos.y * 6); + f_norm.xy += mix(vec2(0), vec2(h - hx, h - hy) / 0.1 * 0.03, puddle); + #endif alpha = mix(1.0, 0.2, puddle); f_col.rgb *= mix(1.0, 0.7, puddle); k_s = mix(k_s, vec3(0.7, 0.7, 1.0), puddle); @@ -268,21 +276,17 @@ void main() { #endif if (rain_occlusion_at(f_pos.xyz + vec3(0, 0, 0.25)) > 0.5) { - if (fract(hash(fract(vec4(cell, 0) * 0.01))) < rain_density * 2.0 && puddle > 0.3) { + if (fract(hash(fract(vec4(cell, 0) * 0.01))) < rain_density * 2.0) { vec3 off = vec3(hash_fast(uvec3(cell * 13)), hash_fast(uvec3(cell * 5)), 0); vec3 near_cell = (cell + 0.5 + (off - 0.5) * 0.5) / drop_density; float dist = length((drop_pos - near_cell) / vec3(1, 1, 2)); - float drop_rad = 0.1; + float drop_rad = 0.075 + puddle * 0.05; float distort = max(1.0 - abs(dist - drop_rad) * 100, 0) * 1.5 * max(drop_pos.z - near_cell.z, 0); k_a += distort; k_d += distort; k_s += distort; - #ifdef EXPERIMENTAL_WETNESS - /* puddle = mix(puddle, 1.0, distort * 10); */ - #endif - f_norm.xy += (drop_pos - near_cell).xy * max(1.0 - abs(dist - drop_rad) * 30, 0) * 500.0 @@ -362,14 +366,18 @@ void main() { // NOTE: Default intersection point is camera position, meaning if we fail to intersect we assume the whole camera is in water. // Computing light attenuation from water. vec3 cam_attenuation = - medium.x == MEDIUM_WATER ? compute_attenuation_point(cam_pos.xyz, view_dir, MU_WATER, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/f_pos) + false/*medium.x == MEDIUM_WATER*/ ? compute_attenuation_point(cam_pos.xyz, view_dir, MU_WATER, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/f_pos) : compute_attenuation_point(f_pos, -view_dir, mu, fluid_alt, /*cam_pos.z <= fluid_alt ? cam_pos.xyz : f_pos*/cam_pos.xyz); // Prevent the sky affecting light when underground float not_underground = clamp((f_pos.z - f_alt) / 128.0 + 1.0, 0.0, 1.0); // To account for prior saturation - /*float */f_light = faces_fluid ? not_underground : f_light * sqrt(f_light); + #if (FLUID_MODE == FLUID_MODE_LOW) + f_light = f_light * sqrt(f_light); + #else + f_light = faces_fluid ? not_underground : f_light * sqrt(f_light); + #endif vec3 emitted_light = vec3(1.0); vec3 reflected_light = vec3(1.0); @@ -396,7 +404,7 @@ void main() { reflected_light *= 0.4 + f_ao * 0.6; #ifndef EXPERIMENTAL_NOCAUSTICS - #if (FLUID_MODE == FLUID_MODE_SHINY) + #if (FLUID_MODE >= FLUID_MODE_MEDIUM) 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.25; @@ -521,5 +529,5 @@ void main() { float f_select = (select_pos.w > 0 && select_pos.xyz == floor(f_pos - f_norm * 0.5)) ? 1.0 : 0.0; surf_color += f_select * (surf_color + 0.1) * vec3(0.5, 0.5, 0.5); - tgt_color = vec4(surf_color, 1.0); + tgt_color = vec4(surf_color, f_alpha); } diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index d13a240587..55eea74c1b 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/assets/voxygen/shaders/trail-frag.glsl b/assets/voxygen/shaders/trail-frag.glsl index 23d6585f49..dc1ee7e232 100644 --- a/assets/voxygen/shaders/trail-frag.glsl +++ b/assets/voxygen/shaders/trail-frag.glsl @@ -6,9 +6,9 @@ #define LIGHTING_REFLECTION_KIND LIGHTING_REFLECTION_KIND_GLOSSY -#if (FLUID_MODE == FLUID_MODE_CHEAP) +#if (FLUID_MODE == FLUID_MODE_LOW) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_IMPORTANCE -#elif (FLUID_MODE == FLUID_MODE_SHINY) +#elif (FLUID_MODE >= FLUID_MODE_MEDIUM) #define LIGHTING_TRANSPORT_MODE LIGHTING_TRANSPORT_MODE_RADIANCE #endif diff --git a/voxygen/src/hud/settings_window/video.rs b/voxygen/src/hud/settings_window/video.rs index 81b7ba116d..7c9950adf5 100644 --- a/voxygen/src/hud/settings_window/video.rs +++ b/voxygen/src/hud/settings_window/video.rs @@ -7,7 +7,7 @@ use crate::{ }, render::{ AaMode, BloomConfig, BloomFactor, BloomMode, CloudMode, FluidMode, LightingMode, - PresentMode, RenderMode, ShadowMapMode, ShadowMode, UpscaleMode, + PresentMode, ReflectionMode, RenderMode, ShadowMapMode, ShadowMode, UpscaleMode, }, session::settings_change::Graphics as GraphicsChange, settings::Fps, @@ -90,6 +90,8 @@ widget_ids! { cloud_mode_list, fluid_mode_text, fluid_mode_list, + reflection_mode_text, + reflection_mode_list, fullscreen_mode_text, fullscreen_mode_list, // @@ -1038,12 +1040,14 @@ impl<'a> Widget for Video<'a> { .color(TEXT_COLOR) .set(state.ids.fluid_mode_text, ui); - let mode_list = [FluidMode::Cheap, FluidMode::Shiny]; + let mode_list = [FluidMode::Low, FluidMode::Medium, FluidMode::High]; let mode_label_list = [ self.localized_strings - .get_msg("hud-settings-fluid_rendering_mode-cheap"), + .get_msg("hud-settings-fluid_rendering_mode-low"), self.localized_strings - .get_msg("hud-settings-fluid_rendering_mode-shiny"), + .get_msg("hud-settings-fluid_rendering_mode-medium"), + self.localized_strings + .get_msg("hud-settings-fluid_rendering_mode-high"), ]; // Get which fluid rendering mode is currently active @@ -1063,13 +1067,56 @@ impl<'a> Widget for Video<'a> { }))); } + // ReflectionMode + Text::new( + &self + .localized_strings + .get_msg("hud-settings-reflection_rendering_mode"), + ) + .down_from(state.ids.fluid_mode_list, 8.0) + .font_size(self.fonts.cyri.scale(14)) + .font_id(self.fonts.cyri.conrod_id) + .color(TEXT_COLOR) + .set(state.ids.reflection_mode_text, ui); + + let mode_list = [ + ReflectionMode::Low, + ReflectionMode::Medium, + ReflectionMode::High, + ]; + let mode_label_list = [ + self.localized_strings + .get_msg("hud-settings-reflection_rendering_mode-low"), + self.localized_strings + .get_msg("hud-settings-reflection_rendering_mode-medium"), + self.localized_strings + .get_msg("hud-settings-reflection_rendering_mode-high"), + ]; + + // Get which fluid rendering mode is currently active + let selected = mode_list.iter().position(|x| *x == render_mode.reflection); + + if let Some(clicked) = DropDownList::new(&mode_label_list, selected) + .w_h(400.0, 22.0) + .color(MENU_BG) + .label_color(TEXT_COLOR) + .label_font_id(self.fonts.cyri.conrod_id) + .down_from(state.ids.reflection_mode_text, 8.0) + .set(state.ids.reflection_mode_list, ui) + { + events.push(GraphicsChange::ChangeRenderMode(Box::new(RenderMode { + reflection: mode_list[clicked], + ..render_mode.clone() + }))); + } + // LightingMode Text::new( &self .localized_strings .get_msg("hud-settings-lighting_rendering_mode"), ) - .down_from(state.ids.fluid_mode_list, 8.0) + .down_from(state.ids.reflection_mode_list, 8.0) .font_size(self.fonts.cyri.scale(14)) .font_id(self.fonts.cyri.conrod_id) .color(TEXT_COLOR) diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 13619b51df..baf526febd 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -9,7 +9,7 @@ use crate::{ scene::terrain::BlocksOfInterest, }; use common::{ - terrain::Block, + terrain::{Block, TerrainChunk}, util::either_with, vol::{ReadVol, RectRasterableVol}, volumes::vol_grid_2d::{CachedVolGrid2d, VolGrid2d}, @@ -226,8 +226,8 @@ fn calc_light<V: RectRasterableVol<Vox = Block> + ReadVol + Debug>( } #[allow(clippy::type_complexity)] -pub fn generate_mesh<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug + 'static>( - vol: &'a VolGrid2d<V>, +pub fn generate_mesh<'a>( + vol: &'a VolGrid2d<TerrainChunk>, (range, max_texture_size, _boi): (Aabb<i32>, Vec2<u16>, &'a BlocksOfInterest), ) -> MeshGen< TerrainVertex, @@ -390,7 +390,37 @@ pub fn generate_mesh<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug + ' let mesh_delta = Vec3::new(0.0, 0.0, (z_start + range.min.z) as f32); let create_opaque = |atlas_pos, pos, norm, meta| TerrainVertex::new(atlas_pos, pos + mesh_delta, norm, meta); - let create_transparent = |_atlas_pos, pos, norm| FluidVertex::new(pos + mesh_delta, norm); + let create_transparent = |_atlas_pos, pos: Vec3<f32>, norm| { + // TODO: It *should* be possible to pull most of this code out of this function + // and compute it per-chunk. For some reason, this doesn't work! If you, + // dear reader, feel like giving it a go then feel free. For now + // it's been kept as-is because I'm lazy and water vertices aren't nearly common + // enough for this to matter much. If you want to test whether your + // change works, look carefully at how waves interact between water + // polygons in different chunks. If the join is smooth, you've solved the + // problem! + let key = vol.pos_key(range.min + pos.as_()); + let v00 = vol + .get_key(key + Vec2::new(0, 0)) + .map_or(Vec3::zero(), |c| c.meta().river_velocity()); + let v10 = vol + .get_key(key + Vec2::new(1, 0)) + .map_or(Vec3::zero(), |c| c.meta().river_velocity()); + let v01 = vol + .get_key(key + Vec2::new(0, 1)) + .map_or(Vec3::zero(), |c| c.meta().river_velocity()); + let v11 = vol + .get_key(key + Vec2::new(1, 1)) + .map_or(Vec3::zero(), |c| c.meta().river_velocity()); + let factor = + (range.min + pos.as_()).map(|e| e as f32) / TerrainChunk::RECT_SIZE.map(|e| e as f32); + let vel = Lerp::lerp( + Lerp::lerp(v00, v10, factor.x.rem_euclid(1.0)), + Lerp::lerp(v01, v11, factor.x.rem_euclid(1.0)), + factor.y.rem_euclid(1.0), + ); + FluidVertex::new(pos + mesh_delta, norm, vel.xy()) + }; let mut greedy = GreedyMesh::<guillotiere::SimpleAtlasAllocator>::new(max_size, greedy::general_config()); diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 5ddc5e8974..2ce83b4c31 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -151,14 +151,15 @@ impl Default for CloudMode { /// Fluid modes #[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)] pub enum FluidMode { - /// "Cheap" water. This water implements no waves, no reflections, no + /// "Low" water. This water implements no waves, no reflections, no /// diffraction, and no light attenuation through water. As a result, /// it can be much cheaper than shiny reflection. - Cheap, - /// "Shiny" water. This water implements waves on the surfaces, some - /// attempt at reflections, and tries to compute accurate light - /// attenuation through water (this is what results in the - /// colors changing as you descend into deep water). + Low, + High, + /// This water implements waves on the surfaces, some attempt at + /// reflections, and tries to compute accurate light attenuation through + /// water (this is what results in the colors changing as you descend + /// into deep water). /// /// Unfortunately, the way the engine is currently set up, calculating /// accurate attenuation is a bit difficult; we use estimates from @@ -172,11 +173,28 @@ pub enum FluidMode { /// which causes attenuation to be computed incorrectly; this can be /// addressed by using shadow maps (at least for terrain). #[serde(other)] - Shiny, + Medium, } impl Default for FluidMode { - fn default() -> Self { FluidMode::Shiny } + fn default() -> Self { FluidMode::Medium } +} + +/// Reflection modes +#[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize)] +pub enum ReflectionMode { + /// No or minimal reflections. + Low, + /// High quality reflections with screen-space raycasting and + /// all the bells & whistles. + High, + // Medium quality screen-space reflections. + #[serde(other)] + Medium, +} + +impl Default for ReflectionMode { + fn default() -> Self { ReflectionMode::Medium } } /// Lighting modes @@ -358,6 +376,7 @@ impl BloomMode { pub struct RenderMode { pub aa: AaMode, pub cloud: CloudMode, + pub reflection: ReflectionMode, pub fluid: FluidMode, pub lighting: LightingMode, pub shadow: ShadowMode, @@ -381,6 +400,7 @@ impl Default for RenderMode { aa: AaMode::default(), cloud: CloudMode::default(), fluid: FluidMode::default(), + reflection: ReflectionMode::default(), lighting: LightingMode::default(), shadow: ShadowMode::default(), rain_occlusion: ShadowMapMode::default(), @@ -402,6 +422,7 @@ impl RenderMode { aa: self.aa, cloud: self.cloud, fluid: self.fluid, + reflection: self.reflection, lighting: self.lighting, shadow: self.shadow, rain_occlusion: self.rain_occlusion, @@ -426,6 +447,7 @@ pub struct PipelineModes { aa: AaMode, pub cloud: CloudMode, fluid: FluidMode, + reflection: ReflectionMode, lighting: LightingMode, pub shadow: ShadowMode, pub rain_occlusion: ShadowMapMode, @@ -497,6 +519,6 @@ pub enum ExperimentalShader { DirectionalShadowMapTexelGrid, /// Disable rainbows NoRainbows, - /// Make objects appear wet when appropriate. - Wetness, + /// Add extra detailing to puddles. + PuddleDetails, } diff --git a/voxygen/src/render/pipelines/fluid.rs b/voxygen/src/render/pipelines/fluid.rs index a5c37fe961..331e73cac0 100644 --- a/voxygen/src/render/pipelines/fluid.rs +++ b/voxygen/src/render/pipelines/fluid.rs @@ -7,10 +7,11 @@ use vek::*; #[derive(Copy, Clone, Debug, Zeroable, Pod)] pub struct Vertex { pos_norm: u32, + vel: u32, } impl Vertex { - pub fn new(pos: Vec3<f32>, norm: Vec3<f32>) -> Self { + pub fn new(pos: Vec3<f32>, norm: Vec3<f32>, river_velocity: Vec2<f32>) -> Self { let (norm_axis, norm_dir) = norm .as_slice() .iter() @@ -27,11 +28,19 @@ impl Vertex { | ((pos.y as u32) & 0x003F) << 6 | (((pos.z + EXTRA_NEG_Z).max(0.0).min((1 << 17) as f32) as u32) & 0x1FFFF) << 12 | (norm_bits & 0x7) << 29, + vel: river_velocity + .map2(Vec2::new(0, 16), |e, off| { + ((e * 1000.0 + 32768.9) as u16 as u32) << off + }) + .reduce_bitor(), } } fn desc<'a>() -> wgpu::VertexBufferLayout<'a> { - const ATTRIBUTES: [wgpu::VertexAttribute; 1] = wgpu::vertex_attr_array![0 => Uint32]; + const ATTRIBUTES: [wgpu::VertexAttribute; 2] = wgpu::vertex_attr_array![ + 0 => Uint32, + 1 => Uint32, + ]; wgpu::VertexBufferLayout { array_stride: Self::STRIDE, step_mode: wgpu::InputStepMode::Vertex, @@ -124,7 +133,7 @@ impl FluidPipeline { alpha: wgpu::BlendComponent { src_factor: wgpu::BlendFactor::One, dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add, + operation: wgpu::BlendOperation::Min, }, }), write_mask: wgpu::ColorWrite::ALL, diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index b7d8a00afe..0da02dfb2d 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -6,8 +6,8 @@ use super::{ blit, bloom, clouds, debug, figure, fluid, lod_object, lod_terrain, particle, postprocess, shadow, skybox, sprite, terrain, trail, ui, }, - AaMode, BloomMode, CloudMode, FluidMode, LightingMode, PipelineModes, RenderError, - ShadowMode, + AaMode, BloomMode, CloudMode, FluidMode, LightingMode, PipelineModes, ReflectionMode, + RenderError, ShadowMode, }, shaders::Shaders, ImmutableLayouts, Layouts, @@ -173,6 +173,7 @@ impl ShaderModules { #define VOXYGEN_COMPUTATION_PREFERENCE {} #define FLUID_MODE {} #define CLOUD_MODE {} +#define REFLECTION_MODE {} #define LIGHTING_ALGORITHM {} #define SHADOW_MODE {} @@ -181,8 +182,9 @@ impl ShaderModules { // TODO: Configurable vertex/fragment shader preference. "VOXYGEN_COMPUTATION_PREFERENCE_FRAGMENT", match pipeline_modes.fluid { - FluidMode::Cheap => "FLUID_MODE_CHEAP", - FluidMode::Shiny => "FLUID_MODE_SHINY", + FluidMode::Low => "FLUID_MODE_LOW", + FluidMode::Medium => "FLUID_MODE_MEDIUM", + FluidMode::High => "FLUID_MODE_HIGH", }, match pipeline_modes.cloud { CloudMode::None => "CLOUD_MODE_NONE", @@ -192,6 +194,11 @@ impl ShaderModules { CloudMode::High => "CLOUD_MODE_HIGH", CloudMode::Ultra => "CLOUD_MODE_ULTRA", }, + match pipeline_modes.reflection { + ReflectionMode::Low => "REFLECTION_MODE_LOW", + ReflectionMode::Medium => "REFLECTION_MODE_MEDIUM", + ReflectionMode::High => "REFLECTION_MODE_HIGH", + }, match pipeline_modes.lighting { LightingMode::Ashikhmin => "LIGHTING_ALGORITHM_ASHIKHMIN", LightingMode::BlinnPhong => "LIGHTING_ALGORITHM_BLINN_PHONG", @@ -298,8 +305,8 @@ impl ShaderModules { }; let selected_fluid_shader = ["fluid-frag.", match pipeline_modes.fluid { - FluidMode::Cheap => "cheap", - FluidMode::Shiny => "shiny", + FluidMode::Low => "cheap", + _ => "shiny", }] .concat(); diff --git a/voxygen/src/scene/camera.rs b/voxygen/src/scene/camera.rs index 26ed0a74a7..0cb276d878 100644 --- a/voxygen/src/scene/camera.rs +++ b/voxygen/src/scene/camera.rs @@ -1,6 +1,6 @@ use common::{terrain::TerrainGrid, vol::ReadVol}; use common_base::span; -use core::{f32::consts::PI, fmt::Debug}; +use core::{f32::consts::PI, fmt::Debug, ops::Range}; use num::traits::{real::Real, FloatConst}; use treeculler::Frustum; use vek::*; @@ -12,7 +12,7 @@ const FIRST_PERSON_INTERP_TIME: f32 = 0.1; const THIRD_PERSON_INTERP_TIME: f32 = 0.1; const FREEFLY_INTERP_TIME: f32 = 0.0; const LERP_ORI_RATE: f32 = 15.0; -const CLIPPING_MODE_DISTANCE: f32 = 20.0; +const CLIPPING_MODE_RANGE: Range<f32> = 2.0..20.0; pub const MIN_ZOOM: f32 = 0.1; // Possible TODO: Add more modes @@ -368,7 +368,7 @@ impl Camera { ) { span!(_guard, "compute_dependents", "Camera::compute_dependents"); // TODO: More intelligent function to decide on which strategy to use - if self.tgt_dist < CLIPPING_MODE_DISTANCE { + if self.tgt_dist < CLIPPING_MODE_RANGE.end { self.compute_dependents_near(terrain, is_transparent) } else { self.compute_dependents_far(terrain, is_transparent) @@ -425,18 +425,23 @@ impl Camera { .unwrap_or(0.0) }; - if self.dist >= dist { - self.dist = dist; - } - - // Recompute only if needed - if (dist - self.tgt_dist).abs() > f32::EPSILON { - let dependents = self.compute_dependents_helper(dist); - self.frustum = self.compute_frustum(&dependents); - self.dependents = dependents; + // If the camera ends up being too close to the focus point, switch policies. + if dist < CLIPPING_MODE_RANGE.start { + self.compute_dependents_far(terrain, is_transparent); } else { - self.dependents = local_dependents; - self.frustum = frustum; + if self.dist >= dist { + self.dist = dist; + } + + // Recompute only if needed + if (dist - self.tgt_dist).abs() > f32::EPSILON { + let dependents = self.compute_dependents_helper(dist); + self.frustum = self.compute_frustum(&dependents); + self.dependents = dependents; + } else { + self.dependents = local_dependents; + self.frustum = frustum; + } } } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index c26244ff26..bbbb9c1111 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -224,12 +224,12 @@ impl assets::Asset for SpriteSpec { /// skip_remesh is either None (do the full remesh, including recomputing the /// light map), or Some((light_map, glow_map)). -fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug + 'static>( +fn mesh_worker( pos: Vec2<i32>, z_bounds: (f32, f32), skip_remesh: Option<(LightMapFn, LightMapFn)>, started_tick: u64, - volume: <VolGrid2d<V> as SampleVol<Aabr<i32>>>::Sample, + volume: <VolGrid2d<TerrainChunk> as SampleVol<Aabr<i32>>>::Sample, max_texture_size: u16, chunk: Arc<TerrainChunk>, range: Aabb<i32>, @@ -274,11 +274,12 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug + ' prof_span!("extract sprite_instances"); let mut instances = [(); SPRITE_LOD_LEVELS].map(|()| Vec::new()); - for x in 0..V::RECT_SIZE.x as i32 { - for y in 0..V::RECT_SIZE.y as i32 { + for x in 0..TerrainChunk::RECT_SIZE.x as i32 { + for y in 0..TerrainChunk::RECT_SIZE.y as i32 { for z in z_bounds.0 as i32..z_bounds.1 as i32 + 1 { let rel_pos = Vec3::new(x, y, z); - let wpos = Vec3::from(pos * V::RECT_SIZE.map(|e: u32| e as i32)) + rel_pos; + let wpos = Vec3::from(pos * TerrainChunk::RECT_SIZE.map(|e: u32| e as i32)) + + rel_pos; let block = if let Ok(block) = volume.get(wpos) { block