From 1f187394d2e114ce38e117ef11930749c883330d Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 10 Feb 2021 19:38:37 +0000 Subject: [PATCH] Directional baked lights for figures --- assets/voxygen/shaders/figure-frag.glsl | 3 +- assets/voxygen/shaders/figure-vert.glsl | 1 + .../shaders/light-shadows-figure-vert.glsl | 1 + .../voxygen/shaders/player-shadow-frag.glsl | 1 + assets/voxygen/shaders/terrain-frag.glsl | 2 +- voxygen/src/mesh/terrain.rs | 4 +-- voxygen/src/render/pipelines/figure.rs | 8 +++-- voxygen/src/scene/figure/mod.rs | 11 +++--- voxygen/src/scene/terrain.rs | 34 ++++++++++++++++++- 9 files changed, 52 insertions(+), 13 deletions(-) diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 3b69a17d8b..a1a74cad20 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -50,6 +50,7 @@ uniform u_locals { mat4 model_mat; vec4 highlight_col; vec4 model_light; + vec4 model_glow; ivec4 atlas_offs; vec3 model_pos; // bit 0 - is player @@ -181,7 +182,7 @@ void main() { float ao = f_ao * sqrt(f_ao);//0.25 + f_ao * 0.75; ///*pow(f_ao, 0.5)*/f_ao * 0.85 + 0.15; - vec3 glow = pow(model_light.y, 3) * 4 * GLOW_COLOR; + vec3 glow = pow(pow(model_glow.w, 2.0) * (max(dot(f_norm, normalize(model_glow.xyz)), 0.0) * 1.0 + max(1.0 - length(model_glow.xyz), 0.0)), 1) * 4 * GLOW_COLOR; emitted_light += glow; reflected_light *= ao; diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index 50acb8e4eb..c126f76095 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -28,6 +28,7 @@ uniform u_locals { mat4 model_mat; vec4 highlight_col; vec4 model_light; + vec4 model_glow; ivec4 atlas_offs; vec3 model_pos; // bit 0 - is player diff --git a/assets/voxygen/shaders/light-shadows-figure-vert.glsl b/assets/voxygen/shaders/light-shadows-figure-vert.glsl index 154cc23b88..10adaed520 100644 --- a/assets/voxygen/shaders/light-shadows-figure-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-figure-vert.glsl @@ -40,6 +40,7 @@ uniform u_locals { mat4 model_mat; vec4 highlight_col; vec4 model_light; + vec4 model_glow; ivec4 atlas_offs; vec3 model_pos; // bit 0 - is player diff --git a/assets/voxygen/shaders/player-shadow-frag.glsl b/assets/voxygen/shaders/player-shadow-frag.glsl index dd28aaba34..bb7da1b60d 100644 --- a/assets/voxygen/shaders/player-shadow-frag.glsl +++ b/assets/voxygen/shaders/player-shadow-frag.glsl @@ -26,6 +26,7 @@ uniform u_locals { mat4 model_mat; vec4 highlight_col; vec4 model_light; + vec4 model_glow; ivec4 atlas_offs; vec3 model_pos; int flags; diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index d81466ea6c..025429d64b 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -266,7 +266,7 @@ void main() { max_light *= f_light; // TODO: Apply AO after this - vec3 glow = GLOW_COLOR * (pow(f_glow, 6) * 8 + pow(f_glow, 2) * 0.5); + vec3 glow = GLOW_COLOR * (pow(f_glow, 6) * 8 + pow(f_glow, 1.5) * 1.0); emitted_light += glow; reflected_light += glow; diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 09b8e79549..551b3267a0 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -30,8 +30,8 @@ enum FaceKind { Fluid, } -const SUNLIGHT: u8 = 24; -const MAX_LIGHT_DIST: i32 = SUNLIGHT as i32; +pub const SUNLIGHT: u8 = 24; +pub const MAX_LIGHT_DIST: i32 = SUNLIGHT as i32; fn calc_light + ReadVol + Debug>( is_sunlight: bool, diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 662a44953f..d9f5f45b74 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -14,6 +14,7 @@ gfx_defines! { model_mat: [[f32; 4]; 4] = "model_mat", highlight_col: [f32; 4] = "highlight_col", model_light: [f32; 4] = "model_light", + model_glow: [f32; 4] = "model_glow", atlas_offs: [i32; 4] = "atlas_offs", model_pos: [f32; 3] = "model_pos", flags: u32 = "flags", @@ -60,7 +61,7 @@ impl Locals { atlas_offs: Vec2, is_player: bool, light: f32, - glow: f32, + glow: (Vec3, f32), ) -> Self { let mut flags = 0; flags |= is_player as u32; @@ -70,7 +71,8 @@ impl Locals { highlight_col: [col.r, col.g, col.b, 1.0], model_pos: pos.into_array(), atlas_offs: Vec4::from(atlas_offs).into_array(), - model_light: [light, glow, 1.0, 1.0], + model_light: [light, 1.0, 1.0, 1.0], + model_glow: [glow.0.x, glow.0.y, glow.0.z, glow.1], flags, } } @@ -85,7 +87,7 @@ impl Default for Locals { Vec2::default(), false, 1.0, - 0.0, + (Vec3::zero(), 0.0), ) } } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 3ccbdf2a04..7d61cd1ee6 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -4602,7 +4602,7 @@ pub struct FigureStateMeta { last_pos: Option>, avg_vel: anim::vek::Vec3, last_light: f32, - last_glow: f32, + last_glow: (Vec3, f32), acc_vel: f32, } @@ -4649,7 +4649,7 @@ impl FigureState { last_pos: None, avg_vel: anim::vek::Vec3::zero(), last_light: 1.0, - last_glow: 0.0, + last_glow: (Vec3::zero(), 0.0), acc_vel: 0.0, }, skeleton, @@ -4743,14 +4743,15 @@ impl FigureState { let s = Lerp::lerp(s_10, s_11, (wpos.x.fract() - 0.5).abs() * 2.0); */ - Vec2::new(t.light_at_wpos(wposi), t.glow_at_wpos(wposi)).into_tuple() + (t.light_at_wpos(wposi), t.glow_normal_at_wpos(wpos)) }) - .unwrap_or((1.0, 0.0)); + .unwrap_or((1.0, (Vec3::zero(), 0.0))); // Fade between light and glow levels // TODO: Making this temporal rather than spatial is a bit dumb but it's a very // subtle difference self.last_light = vek::Lerp::lerp(self.last_light, light, 16.0 * dt); - self.last_glow = vek::Lerp::lerp(self.last_glow, glow, 16.0 * dt); + self.last_glow.0 = vek::Lerp::lerp(self.last_glow.0, glow.0, 16.0 * dt); + self.last_glow.1 = vek::Lerp::lerp(self.last_glow.1, glow.1, 16.0 * dt); let locals = FigureLocals::new( mat, diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 8767b639cd..6dfe29d498 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -3,7 +3,7 @@ mod watcher; pub use self::watcher::BlocksOfInterest; use crate::{ - mesh::{greedy::GreedyMesh, Meshable}, + mesh::{greedy::GreedyMesh, Meshable, terrain::SUNLIGHT}, render::{ ColLightFmt, ColLightInfo, Consts, FluidPipeline, GlobalModel, Instances, Mesh, Model, RenderError, Renderer, ShadowPipeline, SpriteInstance, SpriteLocals, SpritePipeline, @@ -508,6 +508,38 @@ impl Terrain { .unwrap_or(0.0) } + pub fn glow_normal_at_wpos(&self, wpos: Vec3) -> (Vec3, f32) { + let wpos_chunk = wpos.xy().map2(TerrainChunk::RECT_SIZE, |e: f32, sz| { + (e as i32).div_euclid(sz as i32) + }); + + const AMBIANCE: f32 = 0.2; // 0-1, the proportion of light that should illuminate the rear of an object + + let (bias, total, max) = Spiral2d::new() + .take(9) + .map(|rpos| { + let chunk_pos = wpos_chunk + rpos; + self.chunks + .get(&chunk_pos) + .map(|c| c.blocks_of_interest.lights.iter()) + .into_iter() + .flatten() + .map(move |(lpos, level)| (Vec3::::from(chunk_pos * TerrainChunk::RECT_SIZE.map(|e| e as i32)) + *lpos, level)) + }) + .flatten() + .fold((Vec3::broadcast(0.001), 0.0, 0.0f32), |(bias, total, max), (lpos, level)| { + let rpos = lpos.map(|e| e as f32 + 0.5) - wpos; + let level = (*level as f32 - rpos.magnitude()).max(0.0) / SUNLIGHT as f32; + ( + bias + rpos.try_normalized().unwrap_or_else(Vec3::zero) * level * (1.0 - AMBIANCE), + total + level, + max.max(level), + ) + }); + + (bias.try_normalized().unwrap_or_else(Vec3::zero) / total.max(0.001), self.glow_at_wpos(wpos.map(|e| e.floor() as i32))) + } + /// Maintain terrain data. To be called once per tick. #[allow(clippy::for_loops_over_fallibles)] // TODO: Pending review in #587 #[allow(clippy::len_zero)] // TODO: Pending review in #587