diff --git a/CHANGELOG.md b/CHANGELOG.md index 541c4cc63f..41153569a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Players can now mount and ride pets - Experimental shaders, that can be enabled in Voxygen's settings (see the book for more information) - Added arthropods +- A 'point light glow' effect, making lanterns and other point lights more visually pronounced ### Changed diff --git a/assets/voxygen/shaders/clouds-frag.glsl b/assets/voxygen/shaders/clouds-frag.glsl index 7d02bf0f1d..f7628d4d00 100644 --- a/assets/voxygen/shaders/clouds-frag.glsl +++ b/assets/voxygen/shaders/clouds-frag.glsl @@ -21,6 +21,9 @@ #include #include #include +#include +// This *MUST* come after `cloud.glsl`: it contains a function that depends on `cloud.glsl` when clouds are enabled +#include layout(set = 1, binding = 0) uniform texture2D t_src_color; @@ -42,7 +45,6 @@ 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; mat4 inv = view_mat_inv * proj_mat_inv;//inverse(all_mat); @@ -60,13 +62,17 @@ vec3 wpos_at(vec2 uv) { void main() { vec4 color = texture(sampler2D(t_src_color, s_src_color), uv); + vec3 wpos = wpos_at(uv); + float dist = distance(wpos, cam_pos.xyz); + vec3 dir = (wpos - cam_pos.xyz) / dist; + // Apply clouds #if (CLOUD_MODE != CLOUD_MODE_NONE) - vec3 wpos = wpos_at(uv); - float dist = distance(wpos, cam_pos.xyz); - vec3 dir = (wpos - cam_pos.xyz) / dist; - color.rgb = get_cloud_color(color.rgb, dir, cam_pos.xyz, time_of_day.x, dist, 1.0); + #else + #ifdef BLOOM_FACTOR + color.rgb = apply_point_glow(cam_pos.xyz + focus_off.xyz, dir, dist, color.rgb, BLOOM_FACTOR); + #endif #endif tgt_color = vec4(color.rgb, 1); diff --git a/assets/voxygen/shaders/fluid-frag/shiny.glsl b/assets/voxygen/shaders/fluid-frag/shiny.glsl index aee8c55051..067b8c0512 100644 --- a/assets/voxygen/shaders/fluid-frag/shiny.glsl +++ b/assets/voxygen/shaders/fluid-frag/shiny.glsl @@ -145,8 +145,8 @@ void main() { nmap = mix(f_norm, normalize(nmap), min(1.0 / pow(frag_dist, 0.75), 1)); //float suppress_waves = max(dot(), 0); - vec3 norm = normalize(vec3(0, 0, 1) * nmap.z + b_norm * nmap.x + c_norm * nmap.y); - // vec3 norm = f_norm; + vec3 norm = normalize(f_norm * nmap.z + b_norm * nmap.x + c_norm * nmap.y); + //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) @@ -177,7 +177,7 @@ void main() { // Squared to account for prior saturation. float f_light = 1.0;// pow(f_light, 1.5); vec3 reflect_color = get_sky_color(/*reflect_ray_dir*/beam_view_dir, time_of_day.x, f_pos, vec3(-100000), 0.125, true); - reflect_color = get_cloud_color(reflect_color, reflect_ray_dir, cam_pos.xyz, time_of_day.x, 100000.0, 0.1); + reflect_color = get_cloud_color(reflect_color, reflect_ray_dir, f_pos.xyz, time_of_day.x, 100000.0, 0.1); reflect_color *= f_light; // Prevent the sky affecting light when underground diff --git a/assets/voxygen/shaders/include/cloud/regular.glsl b/assets/voxygen/shaders/include/cloud/regular.glsl index 8d35104548..c91e498815 100644 --- a/assets/voxygen/shaders/include/cloud/regular.glsl +++ b/assets/voxygen/shaders/include/cloud/regular.glsl @@ -1,5 +1,6 @@ #include #include +#include #include float falloff(float x) { @@ -200,6 +201,10 @@ float dist_to_step(float dist, float quality) { return pow(dist / STEP_SCALE * quality, 0.5); } +// This *MUST* go here: when clouds are enabled, it relies on the declaration of `clouds_at` above. Sadly, GLSL doesn't +// consistently support forward declarations (not surprising, it's designed for single-pass compilers). +#include + vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of_day, float max_dist, const float quality) { // Limit the marching distance to reduce maximum jumps max_dist = min(max_dist, DIST_CAP); @@ -259,5 +264,10 @@ vec3 get_cloud_color(vec3 surf_color, vec3 dir, vec3 origin, const float time_of emission * density_integrals.y * step; } + // Apply point glow + #ifdef BLOOM_FACTOR + surf_color = apply_point_glow(origin, dir, max_dist, surf_color, BLOOM_FACTOR); + #endif + return surf_color; } diff --git a/assets/voxygen/shaders/include/light.glsl b/assets/voxygen/shaders/include/light.glsl index a4eb7728ba..3918b9b4e4 100644 --- a/assets/voxygen/shaders/include/light.glsl +++ b/assets/voxygen/shaders/include/light.glsl @@ -1,3 +1,6 @@ +#ifndef LIGHT_GLSL +#define LIGHT_GLSL + #include #include @@ -28,6 +31,11 @@ float attenuation_strength(vec3 rpos) { return max(2.0 / pow(d2 + 10, 0.35) - pow(d2 / 50000.0, 0.8), 0.0); } +float attenuation_strength_real(vec3 rpos) { + float d2 = rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z; + return 1.0 / (0.025 + d2); +} + // // Compute attenuation due to light passing through a substance that fills an area below a horizontal plane // // (e.g. in most cases, water below the water surface depth). // // @@ -243,3 +251,5 @@ float lights_at(vec3 wpos, vec3 wnorm, vec3 /*cam_to_frag*/view_dir, vec3 mu, ve float lights_at(vec3 wpos, vec3 wnorm, vec3 view_dir, vec3 k_a, vec3 k_d, vec3 k_s, float alpha, inout vec3 emitted_light, inout vec3 reflected_light) { return lights_at(wpos, wnorm, view_dir, vec3(0.0), vec3(1.0), 0.0, k_a, k_d, k_s, alpha, wnorm, 1.0, emitted_light, reflected_light); } + +#endif diff --git a/assets/voxygen/shaders/include/lod.glsl b/assets/voxygen/shaders/include/lod.glsl index e40da75ea8..d027e57058 100644 --- a/assets/voxygen/shaders/include/lod.glsl +++ b/assets/voxygen/shaders/include/lod.glsl @@ -313,7 +313,18 @@ vec3 lod_norm(vec2 f_pos/*vec3 pos*/, vec4 square) { vec3 lod_norm(vec2 f_pos/*vec3 pos*/) { const float SAMPLE_W = 32; - return lod_norm(f_pos, vec4(f_pos - vec2(SAMPLE_W), f_pos + vec2(SAMPLE_W))); + vec3 norm = lod_norm(f_pos, vec4(f_pos - vec2(SAMPLE_W), f_pos + vec2(SAMPLE_W))); + + #ifdef EXPERIMENTAL_PROCEDURALLODDETAIL + vec2 wpos = f_pos + focus_off.xy; + norm.xy += vec2( + textureLod(sampler2D(t_noise, s_noise), wpos / 200, 0).x - 0.5, + textureLod(sampler2D(t_noise, s_noise), wpos / 200 + 0.5, 0).x - 0.5 + ) * 0.35; + norm = normalize(norm); + #endif + + return norm; } @@ -340,11 +351,27 @@ layout(set = 0, binding = 11) uniform sampler s_map; vec3 lod_col(vec2 pos) { - //return vec3(0, 0.5, 0); - // return /*linear_to_srgb*/vec3(alt_at(pos), textureBicubic(t_map, pos_to_tex(pos)).gb); - return /*linear_to_srgb*/(textureBicubic(t_map, s_map, pos_to_tex(pos)).rgb) - ;//+ (texture(t_noise, pos * 0.04 + texture(t_noise, pos * 0.005).xy * 2.0 + texture(t_noise, pos * 0.06).xy * 0.6).x - 0.5) * 0.1; - //+ (texture(t_noise, pos * 0.04 + texture(t_noise, pos * 0.005).xy * 2.0 + texture(t_noise, pos * 0.06).xy * 0.6).x - 0.5) * 0.1; + #ifdef EXPERIMENTAL_PROCEDURALLODDETAIL + vec2 wpos = pos + focus_off.xy; + vec2 shift = vec2( + textureLod(sampler2D(t_noise, s_noise), wpos / 200, 0).x - 0.5, + textureLod(sampler2D(t_noise, s_noise), wpos / 200 + 0.5, 0).x - 0.5 + ) * 64; + pos += shift; + wpos += shift; + #endif + + vec3 col = textureBicubic(t_map, s_map, pos_to_tex(pos)).rgb; + + #ifdef EXPERIMENTAL_PROCEDURALLODDETAIL + col *= pow(vec3( + textureLod(sampler2D(t_noise, s_noise), wpos / 40, 0).x, + textureLod(sampler2D(t_noise, s_noise), wpos / 50 + 0.5, 0).x, + textureLod(sampler2D(t_noise, s_noise), wpos / 45 + 0.75, 0).x + ), vec3(0.5)); + #endif + + return col; } #endif diff --git a/assets/voxygen/shaders/include/point_glow.glsl b/assets/voxygen/shaders/include/point_glow.glsl new file mode 100644 index 0000000000..d4dbfa0ace --- /dev/null +++ b/assets/voxygen/shaders/include/point_glow.glsl @@ -0,0 +1,43 @@ +#ifndef POINT_GLOW_GLSL +#define POINT_GLOW_GLSL + +vec3 apply_point_glow(vec3 wpos, vec3 dir, float max_dist, vec3 color, const float factor) { + #ifndef EXPERIMENTAL_NOPOINTGLOW + for (uint i = 0u; i < light_shadow_count.x; i ++) { + // Only access the array once + Light L = lights[i]; + + vec3 light_pos = L.light_pos.xyz; + // Project light_pos to dir line + float t = max(dot(light_pos - wpos, dir), 0); + vec3 nearest = wpos + dir * min(t, max_dist); + + vec3 difference = light_pos - nearest; + float distance_2 = dot(difference, difference); + if (distance_2 > 100000.0) { + continue; + } + + #if (CLOUD_MODE >= CLOUD_MODE_HIGH) + vec3 _unused; + float unused2; + float spread = 1.0 / (1.0 + cloud_at(nearest, 0.0, _unused, unused2).z * 0.005); + #else + const float spread = 1.0; + #endif + + float strength = pow(attenuation_strength_real(difference), spread); + + vec3 light_color = srgb_to_linear(L.light_col.rgb) * strength * L.light_col.a; + + const float LIGHT_AMBIANCE = 0.025; + color += light_color + * 0.025 + // Constant, *should* const fold + * pow(factor, 0.65); + } + #endif + return color; +} + +#endif diff --git a/assets/voxygen/voxel/humanoid_lantern_manifest.ron b/assets/voxygen/voxel/humanoid_lantern_manifest.ron index 42750ace3b..f5877b10ca 100644 --- a/assets/voxygen/voxel/humanoid_lantern_manifest.ron +++ b/assets/voxygen/voxel/humanoid_lantern_manifest.ron @@ -5,7 +5,7 @@ ), map: { "Green0": ( - vox_spec: ("lantern.green-0", (-2.0, -2.0, -7.0)), + vox_spec: ("lantern.green-0", (-2.5, -2.0, -9.0)), color: None ), "Magic": ( @@ -13,7 +13,7 @@ color: None ), "Black0": ( - vox_spec: ("lantern.black-0", (-2.0, -2.0, -8.5)), + vox_spec: ("lantern.black-0", (-2.5, -2.0, -8.5)), color: None ), "Red0": ( @@ -21,7 +21,7 @@ color: None ), "Blue0": ( - vox_spec: ("lantern.blue-0", (-2.0, -2.0, -7.0)), + vox_spec: ("lantern.blue-0", (-2.5, -2.0, -8.0)), color: None ), "GeodePurp": ( @@ -29,11 +29,11 @@ color: None ), "PumpkinLantern": ( - vox_spec: ("lantern.pumpkin", (-3.5, -4.0, -8.5)), + vox_spec: ("lantern.pumpkin", (-4.0, -4.0, -8.5)), color: None ), "PolarisLantern": ( - vox_spec: ("lantern.polaris", (-3.0, -4.0, -9.5)), + vox_spec: ("lantern.polaris", (-3.5, -4.0, -8.5)), color: None ), }, diff --git a/voxygen/anim/src/character/mod.rs b/voxygen/anim/src/character/mod.rs index d176eb326c..57e8d5d5a0 100644 --- a/voxygen/anim/src/character/mod.rs +++ b/voxygen/anim/src/character/mod.rs @@ -145,7 +145,7 @@ impl Skeleton for CharacterSkeleton { make_bone(control_mat * hand_l_mat * Mat4::::from(self.hold)), ]; Offsets { - lantern: Some((lantern_mat * Vec4::new(0.0, 0.0, -4.0, 1.0)).xyz()), + lantern: Some((lantern_mat * Vec4::new(0.0, 0.5, -6.0, 1.0)).xyz()), // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: common::comp::Body::Humanoid(body) diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index c3ef32fe2f..d17502e66c 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -280,16 +280,16 @@ pub enum BloomFactor { } impl Default for BloomFactor { - fn default() -> Self { Self::Low } + fn default() -> Self { Self::Medium } } impl BloomFactor { /// Fraction of output image luminosity that is blurred bloom pub fn fraction(self) -> f32 { match self { - Self::Low => 0.05, - Self::Medium => 0.10, - Self::High => 0.25, + Self::Low => 0.1, + Self::Medium => 0.2, + Self::High => 0.3, Self::Custom(val) => val.max(0.0).min(1.0), } } @@ -300,7 +300,7 @@ impl BloomFactor { pub struct BloomConfig { /// Controls fraction of output image luminosity that is blurred bloom /// - /// Defaults to `Low` + /// Defaults to `Medium` pub factor: BloomFactor, /// Turning this on make the bloom blur less sharply concentrated around the /// high intensity phenomena (removes adding in less blurred layers to the @@ -391,6 +391,10 @@ struct OtherModes { profiler_enabled: bool, } +/// Experimental shader modes. +/// +/// You can enable these using Voxygen's `settings.ron`. See +/// [here](https://book.veloren.net/players/voxygen.html#experimental-shaders) for more information. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ExperimentalShader { /// Add brick-like normal mapping to the world. @@ -399,4 +403,9 @@ pub enum ExperimentalShader { NoNoise, /// Simulated a curved world. CurvedWorld, + /// Remove the glow effect around point lights (this is *not* the same thing + /// as bloom). + NoPointGlow, + /// Adds extra detail to distant LoD (Level of Detail) terrain procedurally. + ProceduralLodDetail, } diff --git a/voxygen/src/render/renderer/pipeline_creation.rs b/voxygen/src/render/renderer/pipeline_creation.rs index 1760c516ed..800942c853 100644 --- a/voxygen/src/render/renderer/pipeline_creation.rs +++ b/voxygen/src/render/renderer/pipeline_creation.rs @@ -141,6 +141,7 @@ impl ShaderModules { let random = shaders.get("include.random").unwrap(); let lod = shaders.get("include.lod").unwrap(); let shadows = shaders.get("include.shadows").unwrap(); + let point_glow = shaders.get("include.point_glow").unwrap(); // We dynamically add extra configuration settings to the constants file. let mut constants = format!( @@ -241,6 +242,7 @@ impl ShaderModules { "lod.glsl" => lod.0.to_owned(), "anti-aliasing.glsl" => anti_alias.0.to_owned(), "cloud.glsl" => cloud.0.to_owned(), + "point_glow.glsl" => point_glow.0.to_owned(), other => { return Err(format!( "Include {} in {} is not defined", diff --git a/voxygen/src/render/renderer/shaders.rs b/voxygen/src/render/renderer/shaders.rs index 3bcf92cf55..0904d37c66 100644 --- a/voxygen/src/render/renderer/shaders.rs +++ b/voxygen/src/render/renderer/shaders.rs @@ -37,6 +37,7 @@ impl assets::Compound for Shaders { "include.random", "include.lod", "include.shadows", + "include.point_glow", "antialias.none", "antialias.fxaa", "antialias.msaa-x4",