From c4879e991d1e2e5592c3383b9b2ac8d86389037f Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Thu, 16 Apr 2020 14:42:20 +0100 Subject: [PATCH] Enabled AO in darkness, better light attenuation --- assets/voxygen/shaders/include/light.glsl | 6 ++-- assets/voxygen/shaders/terrain-frag.glsl | 11 +++++-- assets/voxygen/shaders/terrain-vert.glsl | 4 ++- voxygen/src/mesh/segment.rs | 14 +++++---- voxygen/src/mesh/terrain.rs | 36 +++++++++++++++-------- voxygen/src/mesh/vol.rs | 26 +++++++++------- voxygen/src/render/pipelines/terrain.rs | 5 ++-- world/src/site/dungeon/mod.rs | 2 +- 8 files changed, 65 insertions(+), 39 deletions(-) diff --git a/assets/voxygen/shaders/include/light.glsl b/assets/voxygen/shaders/include/light.glsl index 1fbe9b1876..ee0920ccc6 100644 --- a/assets/voxygen/shaders/include/light.glsl +++ b/assets/voxygen/shaders/include/light.glsl @@ -25,7 +25,9 @@ vec3 illuminate(vec3 color, vec3 light, vec3 diffuse, vec3 ambience) { } float attenuation_strength(vec3 rpos) { - return 0.3 / pow(rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z, 0.5); + // This is not how light attenuation works at all, but it produces visually pleasing and mechanically useful properties + float d2 = rpos.x * rpos.x + rpos.y * rpos.y + rpos.z * rpos.z; + return max(2.0 / pow(d2 + 10, 0.35) - pow(d2 / 50000.0, 0.8), 0.0); } vec3 light_at(vec3 wpos, vec3 wnorm) { @@ -43,7 +45,7 @@ vec3 light_at(vec3 wpos, vec3 wnorm) { // Pre-calculate difference between light and fragment vec3 difference = light_pos - wpos; - float strength = pow(attenuation_strength(difference), 0.6); + float strength = attenuation_strength(difference); // Multiply the vec3 only once vec3 color = srgb_to_linear(L.light_col.rgb) * (strength * L.light_col.a); diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 069cc01f11..21001e4f7c 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -6,6 +6,7 @@ in vec3 f_pos; flat in uint f_pos_norm; in vec3 f_col; in float f_light; +in float f_ao; layout (std140) uniform u_locals { @@ -29,14 +30,18 @@ void main() { // Use an array to avoid conditional branching vec3 f_norm = normals[(f_pos_norm >> 29) & 0x7u]; + float ao = pow(f_ao, 0.5) * 0.9 + 0.1; + vec3 light, diffuse_light, ambient_light; get_sun_diffuse(f_norm, time_of_day.x, light, diffuse_light, ambient_light, 1.0); float point_shadow = shadow_at(f_pos, f_norm); - diffuse_light *= f_light * point_shadow; - ambient_light *= f_light * point_shadow; + diffuse_light *= point_shadow; + ambient_light *= point_shadow; vec3 point_light = light_at(f_pos, f_norm); light += point_light; - diffuse_light += point_light; + ambient_light *= min(f_light, ao); + diffuse_light *= min(f_light, ao); + diffuse_light += point_light * ao; vec3 surf_color = illuminate(srgb_to_linear(f_col), light, diffuse_light, ambient_light); float fog_level = fog(f_pos.xyz, focus_pos.xyz, medium.x); diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index 8632190220..a1a0bb6be9 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -16,6 +16,7 @@ out vec3 f_pos; flat out uint f_pos_norm; out vec3 f_col; out float f_light; +out float f_ao; const float EXTRA_NEG_Z = 65536.0; @@ -27,7 +28,8 @@ void main() { f_col = vec3((uvec3(v_col_light) >> uvec3(8, 16, 24)) & uvec3(0xFFu)) / 255.0; - f_light = float(v_col_light & 0xFFu) / 255.0; + f_light = float(v_col_light & 0x3Fu) / 64.0; + f_ao = float((v_col_light >> 6u) & 3u) / 4.0; f_pos_norm = v_pos_norm; diff --git a/voxygen/src/mesh/segment.rs b/voxygen/src/mesh/segment.rs index c88635681e..4558c88f09 100644 --- a/voxygen/src/mesh/segment.rs +++ b/voxygen/src/mesh/segment.rs @@ -31,6 +31,7 @@ impl Meshable for Segment { offs + pos.map(|e| e as f32), &[[[Rgba::from_opaque(col); 3]; 3]; 3], |origin, norm, col, ao, light| { + let ao = ao * 0.95 + 0.05; FigureVertex::new( origin, norm, @@ -39,7 +40,7 @@ impl Meshable for Segment { ) }, &{ - let mut ls = [[[0.0; 3]; 3]; 3]; + let mut ls = [[[None; 3]; 3]; 3]; for x in 0..3 { for y in 0..3 { for z in 0..3 { @@ -48,9 +49,9 @@ impl Meshable for Segment { .map(|v| v.is_empty()) .unwrap_or(true) { - 1.0 + Some(1.0) } else { - 0.0 + None }; } } @@ -84,6 +85,7 @@ impl Meshable for Segment { offs + pos.map(|e| e as f32), &[[[Rgba::from_opaque(col); 3]; 3]; 3], |origin, norm, col, ao, light| { + let ao = ao * 0.95 + 0.05; SpriteVertex::new( origin, norm, @@ -91,7 +93,7 @@ impl Meshable for Segment { ) }, &{ - let mut ls = [[[0.0; 3]; 3]; 3]; + let mut ls = [[[None; 3]; 3]; 3]; for x in 0..3 { for y in 0..3 { for z in 0..3 { @@ -100,9 +102,9 @@ impl Meshable for Segment { .map(|v| v.is_empty()) .unwrap_or(true) { - 1.0 + Some(1.0) } else { - 0.0 + None }; } } diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 362fb81408..d3fe6dabb2 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -28,7 +28,7 @@ impl Blendable for BlockKind { fn calc_light + ReadVol + Debug>( bounds: Aabb, vol: &VolGrid2d, -) -> impl Fn(Vec3) -> f32 { +) -> impl FnMut(Vec3) -> Option + '_ { const UNKNOWN: u8 = 255; const OPAQUE: u8 = 254; const SUNLIGHT: u8 = 24; @@ -189,12 +189,20 @@ fn calc_light + ReadVol + Debug>( } move |wpos| { - let pos = wpos - outer.min; - light_map - .get(lm_idx(pos.x, pos.y, pos.z)) - .filter(|l| **l != OPAQUE && **l != UNKNOWN) - .map(|l| *l as f32 / SUNLIGHT as f32) - .unwrap_or(0.0) + if vol_cached + .get(wpos) + .map(|block| block.is_opaque()) + .unwrap_or(false) + { + None + } else { + let pos = wpos - outer.min; + Some(light_map + .get(lm_idx(pos.x, pos.y, pos.z)) + .filter(|l| **l != OPAQUE && **l != UNKNOWN) + .map(|l| *l as f32 / SUNLIGHT as f32) + .unwrap_or(0.0)) + } } } @@ -212,7 +220,7 @@ impl + ReadVol + Debug> Meshable + ReadVol + Debug> Meshable + ReadVol + Debug> Meshable + ReadVol + Debug> Meshable + ReadVol + Debug> Meshable, dirs: &[Vec3], - darknesses: &[[[f32; 3]; 3]; 3], + darknesses: &[[[Option; 3]; 3]; 3], ) -> Vec4<(f32, f32)> { dirs.windows(2) .map(|offs| { @@ -23,7 +23,7 @@ fn get_ao_quad( .get_unchecked(pos.z) .get_unchecked(pos.y) .get_unchecked(pos.x) - <= &0.0 + .is_none() } }; @@ -41,17 +41,21 @@ fn get_ao_quad( ); let mut darkness = 0.0; + let mut total = 0.0f32; for x in 0..2 { for y in 0..2 { let dark_pos = shift + offs[0] * x + offs[1] * y + 1; - darkness += unsafe { - darknesses - .get_unchecked(dark_pos.z as usize) - .get_unchecked(dark_pos.y as usize) - .get_unchecked(dark_pos.x as usize) - } / 4.0; + if let Some(dark) = unsafe { darknesses + .get_unchecked(dark_pos.z as usize) + .get_unchecked(dark_pos.y as usize) + .get_unchecked(dark_pos.x as usize) } + { + darkness += dark; + total += 1.0; + } } } + let darkness = darkness / total.max(1.0); ( darkness, @@ -60,7 +64,7 @@ fn get_ao_quad( } else { let corner = vox_opaque(shift + offs[0] + offs[1]); // Map both 1 and 2 neighbors to 0.5 occlusion. - if s1 || s2 || corner { 0.5 } else { 1.0 } + if s1 || s2 || corner { 0.4 } else { 1.0 } }, ) }) @@ -112,7 +116,7 @@ fn create_quad, Vec3, Rgb, f32, f32) -> P let darkness = darkness_ao.map(|e| e.0); let ao = darkness_ao.map(|e| e.1); - let ao_map = ao * 0.85 + 0.15; + let ao_map = ao; if ao[0].min(ao[2]).min(darkness[0]).min(darkness[2]) < ao[1].min(ao[3]).min(darkness[1]).min(darkness[3]) @@ -151,7 +155,7 @@ pub fn push_vox_verts( offs: Vec3, cols: &[[[Rgba; 3]; 3]; 3], vcons: impl Fn(Vec3, Vec3, Rgb, f32, f32) -> P::Vertex, - darknesses: &[[[f32; 3]; 3]; 3], + darknesses: &[[[Option; 3]; 3]; 3], ) { let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z()); diff --git a/voxygen/src/render/pipelines/terrain.rs b/voxygen/src/render/pipelines/terrain.rs index 48281f616a..9d6f884ff4 100644 --- a/voxygen/src/render/pipelines/terrain.rs +++ b/voxygen/src/render/pipelines/terrain.rs @@ -37,7 +37,7 @@ gfx_defines! { } impl Vertex { - pub fn new(norm_bits: u32, light: u32, pos: Vec3, col: Rgb) -> Self { + pub fn new(norm_bits: u32, light: u32, ao: u32, pos: Vec3, col: Rgb) -> Self { const EXTRA_NEG_Z: f32 = 65536.0; Self { @@ -50,7 +50,8 @@ impl Vertex { | ((col.r.mul(255.0) as u32) & 0xFF) << 8 | ((col.g.mul(255.0) as u32) & 0xFF) << 16 | ((col.b.mul(255.0) as u32) & 0xFF) << 24 - | (light & 0xFF) << 0, + | (ao >> 6) << 6 + | ((light >> 2) & 0x3F) << 0, } } } diff --git a/world/src/site/dungeon/mod.rs b/world/src/site/dungeon/mod.rs index b42b09db26..cb181b8c57 100644 --- a/world/src/site/dungeon/mod.rs +++ b/world/src/site/dungeon/mod.rs @@ -216,7 +216,7 @@ impl Floor { // Ensure no overlap if self.rooms .iter() - .any(|r| r.collides_with_rect(room_border))// || r.contains_point(self.stair_tile)) + .any(|r| r.collides_with_rect(room_border) || r.contains_point(self.stair_tile)) { return None; }