From 27e7fd072795f7a0c8261cb09ae05813a9cefa5f Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 21 Nov 2020 15:51:42 +0000 Subject: [PATCH] Preserved light/glow maps to prevent sprites/entities being lit when they shouldn't be --- assets/voxygen/shaders/figure-frag.glsl | 8 +++++ assets/voxygen/shaders/figure-vert.glsl | 1 + assets/voxygen/shaders/include/sky.glsl | 12 +++++--- .../shaders/light-shadows-figure-vert.glsl | 1 + assets/voxygen/shaders/particle-frag.glsl | 7 +++++ .../voxygen/shaders/player-shadow-frag.glsl | 1 + assets/voxygen/shaders/sprite-frag.glsl | 8 +++++ assets/voxygen/shaders/sprite-vert.glsl | 5 +++- assets/voxygen/shaders/terrain-frag.glsl | 7 +++-- voxygen/src/mesh/terrain.rs | 30 ++++++++++++------- voxygen/src/render/pipelines/figure.rs | 12 ++++++-- voxygen/src/render/pipelines/sprite.rs | 6 ++-- voxygen/src/scene/figure/mod.rs | 29 +++++++++++++++++- voxygen/src/scene/mod.rs | 10 +++++-- voxygen/src/scene/simple.rs | 2 ++ voxygen/src/scene/terrain.rs | 28 +++++++++++++++-- 16 files changed, 138 insertions(+), 29 deletions(-) diff --git a/assets/voxygen/shaders/figure-frag.glsl b/assets/voxygen/shaders/figure-frag.glsl index 4f7627d788..17ff990498 100644 --- a/assets/voxygen/shaders/figure-frag.glsl +++ b/assets/voxygen/shaders/figure-frag.glsl @@ -49,6 +49,7 @@ layout (std140) uniform u_locals { mat4 model_mat; vec4 highlight_col; + vec4 model_light; ivec4 atlas_offs; vec3 model_pos; // bit 0 - is player @@ -159,6 +160,10 @@ void main() { vec3 emitted_light, reflected_light; + // Make voxel shadows block the sun and moon + sun_info.block *= model_light.x; + moon_info.block *= model_light.x; + // vec3 light_frac = /*vec3(1.0);*//*vec3(max(dot(f_norm, -sun_dir) * 0.5 + 0.5, 0.0));*/light_reflection_factor(f_norm, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha); // vec3 point_light = light_at(f_pos, f_norm); // vec3 light, diffuse_light, ambient_light; @@ -176,6 +181,9 @@ 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; + float glow = model_light.y; + emitted_light += glow; + reflected_light *= ao; emitted_light *= ao; /* reflected_light *= cloud_shadow(f_pos); */ diff --git a/assets/voxygen/shaders/figure-vert.glsl b/assets/voxygen/shaders/figure-vert.glsl index dc2f09c351..50acb8e4eb 100644 --- a/assets/voxygen/shaders/figure-vert.glsl +++ b/assets/voxygen/shaders/figure-vert.glsl @@ -27,6 +27,7 @@ layout (std140) uniform u_locals { mat4 model_mat; vec4 highlight_col; + vec4 model_light; ivec4 atlas_offs; vec3 model_pos; // bit 0 - is player diff --git a/assets/voxygen/shaders/include/sky.glsl b/assets/voxygen/shaders/include/sky.glsl index d9fc0ef611..97b1f1c038 100644 --- a/assets/voxygen/shaders/include/sky.glsl +++ b/assets/voxygen/shaders/include/sky.glsl @@ -7,6 +7,8 @@ struct DirectionalLight { // vec3 dir; float shadow; + // Fully blocks all light, including ambience + float block; // vec3 color; // float brightness; }; @@ -135,6 +137,7 @@ vec3 get_moon_color(/*vec3 moon_dir*/) { DirectionalLight get_sun_info(vec4 _dir, float shade_frac/*, vec4 light_pos[2]*/, /*vec4 sun_pos*/vec3 f_pos) { float shadow = shade_frac; + float block = 1.0; #ifdef HAS_SHADOW_MAPS #if (SHADOW_MODE == SHADOW_MODE_MAP) if (sun_dir.z < /*0.6*/0.0) { @@ -151,15 +154,16 @@ DirectionalLight get_sun_info(vec4 _dir, float shade_frac/*, vec4 light_pos[2]*/ } #endif #endif - return DirectionalLight(/*dir, */shadow/*, get_sun_color(dir), get_sun_brightness(dir)*/); + return DirectionalLight(/*dir, */shadow, block/*, get_sun_color(dir), get_sun_brightness(dir)*/); } DirectionalLight get_moon_info(vec4 _dir, float shade_frac/*, vec4 light_pos[2]*/) { float shadow = shade_frac; + float block = 1.0; // #ifdef HAS_SHADOW_MAPS // shadow = min(shade_frac, ShadowCalculationDirected(light_pos, 1u)); // #endif - return DirectionalLight(/*dir, */shadow/*, get_moon_color(dir), get_moon_brightness(dir)*/); + return DirectionalLight(/*dir, */shadow, block/*, get_moon_color(dir), get_moon_brightness(dir)*/); } // // Calculates extra emission and reflectance (due to sunlight / moonlight). @@ -227,8 +231,8 @@ float get_sun_diffuse2(DirectionalLight sun_info, DirectionalLight moon_info, ve vec3 sun_dir = sun_dir.xyz; vec3 moon_dir = moon_dir.xyz; - float sun_light = get_sun_brightness(/*sun_dir*/);//sun_info.brightness;; - float moon_light = get_moon_brightness(/*moon_dir*/);//moon_info.brightness; + float sun_light = get_sun_brightness(/*sun_dir*/) * sun_info.block;//sun_info.brightness;; + float moon_light = get_moon_brightness(/*moon_dir*/) * moon_info.block;//moon_info.brightness; vec3 sun_color = get_sun_color(/*sun_dir*/) * SUN_COLOR_FACTOR;//sun_info.color * SUN_COLOR_FACTOR; vec3 moon_color = get_moon_color(/*moon_dir*/);//moon_info.color; diff --git a/assets/voxygen/shaders/light-shadows-figure-vert.glsl b/assets/voxygen/shaders/light-shadows-figure-vert.glsl index 1aa10a6728..154cc23b88 100644 --- a/assets/voxygen/shaders/light-shadows-figure-vert.glsl +++ b/assets/voxygen/shaders/light-shadows-figure-vert.glsl @@ -39,6 +39,7 @@ layout (std140) uniform u_locals { mat4 model_mat; vec4 highlight_col; + vec4 model_light; ivec4 atlas_offs; vec3 model_pos; // bit 0 - is player diff --git a/assets/voxygen/shaders/particle-frag.glsl b/assets/voxygen/shaders/particle-frag.glsl index 8a2c48cb9d..b5efe862a0 100644 --- a/assets/voxygen/shaders/particle-frag.glsl +++ b/assets/voxygen/shaders/particle-frag.glsl @@ -66,6 +66,13 @@ void main() { vec3 emitted_light, reflected_light; + // This is a bit of a hack. Because we can't find the volumetric lighting of each particle (they don't talk to the + // CPU) we need to some how find an approximation of how much the sun is blocked. We do this by fading out the sun + // as the particle moves underground. This isn't perfect, but it does at least mean that particles don't look like + // they're exposed to the sun when in dungeons + const float SUN_FADEOUT_DIST = 20.0; + sun_info.block *= clamp((f_pos.z - f_alt) / SUN_FADEOUT_DIST + 1, 0, 1); + // To account for prior saturation. float max_light = 0.0; max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, view_dir, k_a, k_d, k_s, alpha, emitted_light, reflected_light); diff --git a/assets/voxygen/shaders/player-shadow-frag.glsl b/assets/voxygen/shaders/player-shadow-frag.glsl index e8b7bf15c4..dd28aaba34 100644 --- a/assets/voxygen/shaders/player-shadow-frag.glsl +++ b/assets/voxygen/shaders/player-shadow-frag.glsl @@ -25,6 +25,7 @@ layout (std140) uniform u_locals { mat4 model_mat; vec4 highlight_col; + vec4 model_light; ivec4 atlas_offs; vec3 model_pos; int flags; diff --git a/assets/voxygen/shaders/sprite-frag.glsl b/assets/voxygen/shaders/sprite-frag.glsl index 945302cf27..ee85968ca5 100644 --- a/assets/voxygen/shaders/sprite-frag.glsl +++ b/assets/voxygen/shaders/sprite-frag.glsl @@ -21,6 +21,7 @@ flat in vec3 f_norm; flat in float f_light; // flat in vec3 f_pos_norm; in vec2 f_uv_pos; +in vec2 f_inst_light; // flat in uint f_atlas_pos; // in vec3 f_col; // in float f_ao; @@ -133,6 +134,10 @@ void main() { vec3 emitted_light, reflected_light; + // Make voxel shadows block the sun and moon + sun_info.block = f_inst_light.x; + moon_info.block = f_inst_light.x; + // To account for prior saturation. // float vert_light = pow(f_light, 1.5); // vec3 light_frac = light_reflection_factor(f_norm/*vec3(0, 0, 1.0)*/, view_dir, vec3(0, 0, -1.0), vec3(1.0), vec3(R_s), alpha); @@ -169,6 +174,9 @@ void main() { reflected_light += point_light; */ // float ao = /*pow(f_ao, 0.5)*/f_ao * 0.85 + 0.15; + float glow = f_inst_light.y; + emitted_light += glow; + float ao = f_ao; emitted_light *= ao; reflected_light *= ao; diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 73aa6f92e7..0d1d166307 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -25,7 +25,7 @@ in vec4 inst_mat0; in vec4 inst_mat1; in vec4 inst_mat2; in vec4 inst_mat3; -// in vec3 inst_col; +in vec4 inst_light; in float inst_wind_sway; struct SpriteLocals { @@ -77,6 +77,7 @@ flat out float f_light; // out vec3 f_col; // out float f_ao; out vec2 f_uv_pos; +out vec2 f_inst_light; // flat out uint f_atlas_pos; // out vec3 light_pos[2]; // out float f_light; @@ -117,6 +118,8 @@ void main() { // float inst_wind_sway = wind_sway.w; // vec3 inst_offs = model_offs - focus_off.xyz; + f_inst_light = inst_light.xy; + // vec3 sprite_pos = floor(inst_mat3.xyz * SCALE) + inst_offs; // f_pos_norm = v_pos; diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 447ff5b862..ca1d665f13 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -261,12 +261,15 @@ void main() { // emitted_light *= f_light * point_shadow * max(shade_frac, MIN_SHADOW); // reflected_light *= f_light * point_shadow * shade_frac; // max_light *= f_light * point_shadow * shade_frac; - emitted_light += pow(f_glow, 5) * 16; - reflected_light += pow(f_glow, 5) * 16; emitted_light *= f_light; reflected_light *= f_light; max_light *= f_light; + // TODO: Apply AO after this + float l = pow(f_glow, 6) * 8 + pow(f_glow, 2) * 0.5; + emitted_light += l; + reflected_light += l; + max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light); // float f_ao = 1.0; diff --git a/voxygen/src/mesh/terrain.rs b/voxygen/src/mesh/terrain.rs index 8c193cbc9c..d4d50e4bda 100644 --- a/voxygen/src/mesh/terrain.rs +++ b/voxygen/src/mesh/terrain.rs @@ -35,10 +35,12 @@ const MAX_LIGHT_DIST: i32 = SUNLIGHT as i32; fn calc_light + ReadVol + Debug>( is_sunlight: bool, + // When above bounds + default_light: f32, bounds: Aabb, vol: &VolGrid2d, lit_blocks: impl Iterator, u8)>, -) -> impl FnMut(Vec3) -> f32 + '_ { +) -> impl Fn(Vec3) -> f32 + 'static + Send + Sync { span!(_guard, "calc_light"); const UNKNOWN: u8 = 255; const OPAQUE: u8 = 254; @@ -210,17 +212,25 @@ fn calc_light + ReadVol + Debug>( 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) + .map(|l| if *l != OPAQUE && *l != UNKNOWN { + *l as f32 / SUNLIGHT as f32 + } else { + 0.0 + }) + .unwrap_or(default_light) } } -impl<'a, V: RectRasterableVol + ReadVol + Debug> +impl<'a, V: RectRasterableVol + ReadVol + Debug + 'static> Meshable for &'a VolGrid2d { type Pipeline = TerrainPipeline; - type Result = (Aabb, ColLightInfo); + type Result = ( + Aabb, + ColLightInfo, + Box) -> f32 + Send + Sync>, + Box) -> f32 + Send + Sync>, + ); type ShadowPipeline = ShadowPipeline; type Supplement = (Aabb, Vec2, &'a BlocksOfInterest); type TranslucentPipeline = FluidPipeline; @@ -266,9 +276,9 @@ impl<'a, V: RectRasterableVol + ReadVol + Debug> } } - // Calculate chunk lighting - let mut light = calc_light(true, range, self, core::iter::empty()); - let mut glow = calc_light(false, range, self, glow_blocks.into_iter()); + // Calculate chunk lighting (sunlight defaults to 1.0, glow to 0.0) + let mut light = calc_light(true, 1.0, range, self, core::iter::empty()); + let mut glow = calc_light(false, 0.0, range, self, glow_blocks.into_iter()); let mut opaque_limits = None::; let mut fluid_limits = None::; @@ -433,7 +443,7 @@ impl<'a, V: RectRasterableVol + ReadVol + Debug> opaque_mesh, fluid_mesh, Mesh::new(), - (bounds, (col_lights, col_lights_size)), + (bounds, (col_lights, col_lights_size), Box::new(light), Box::new(glow)), ) } } diff --git a/voxygen/src/render/pipelines/figure.rs b/voxygen/src/render/pipelines/figure.rs index 74bb1b7a79..36c44b3538 100644 --- a/voxygen/src/render/pipelines/figure.rs +++ b/voxygen/src/render/pipelines/figure.rs @@ -13,6 +13,7 @@ gfx_defines! { constant Locals { model_mat: [[f32; 4]; 4] = "model_mat", highlight_col: [f32; 4] = "highlight_col", + model_light: [f32; 4] = "model_light", atlas_offs: [i32; 4] = "atlas_offs", model_pos: [f32; 3] = "model_pos", flags: u32 = "flags", @@ -54,19 +55,22 @@ gfx_defines! { impl Locals { pub fn new( model_mat: anim::vek::Mat4, - col: Rgba, + col: Rgb, pos: anim::vek::Vec3, atlas_offs: Vec2, is_player: bool, + light: f32, + glow: f32, ) -> Self { let mut flags = 0; flags |= is_player as u32; Self { model_mat: model_mat.into_col_arrays(), - highlight_col: col.into_array(), + highlight_col: [col.r, col.g, col.b, glow], model_pos: pos.into_array(), atlas_offs: Vec4::from(atlas_offs).into_array(), + model_light: [light, glow, 1.0, 1.0], flags, } } @@ -76,10 +80,12 @@ impl Default for Locals { fn default() -> Self { Self::new( anim::vek::Mat4::identity(), - Rgba::broadcast(1.0), + Rgb::broadcast(1.0), anim::vek::Vec3::default(), Vec2::default(), false, + 1.0, + 0.0, ) } } diff --git a/voxygen/src/render/pipelines/sprite.rs b/voxygen/src/render/pipelines/sprite.rs index 9ac8ed369f..5f25d8aacc 100644 --- a/voxygen/src/render/pipelines/sprite.rs +++ b/voxygen/src/render/pipelines/sprite.rs @@ -39,6 +39,7 @@ gfx_defines! { inst_mat1: [f32; 4] = "inst_mat1", inst_mat2: [f32; 4] = "inst_mat2", inst_mat3: [f32; 4] = "inst_mat3", + inst_light: [f32; 4] = "inst_light", inst_wind_sway: f32 = "inst_wind_sway", } @@ -114,7 +115,7 @@ impl Vertex { } impl Instance { - pub fn new(mat: Mat4, wind_sway: f32, pos: Vec3, ori_bits: u8) -> Self { + pub fn new(mat: Mat4, wind_sway: f32, pos: Vec3, ori_bits: u8, light: f32, glow: f32) -> Self { const EXTRA_NEG_Z: i32 = 32768; let mat_arr = mat.into_col_arrays(); @@ -127,13 +128,14 @@ impl Instance { inst_mat1: mat_arr[1], inst_mat2: mat_arr[2], inst_mat3: mat_arr[3], + inst_light: [light, glow, 1.0, 1.0], inst_wind_sway: wind_sway, } } } impl Default for Instance { - fn default() -> Self { Self::new(Mat4::identity(), 0.0, Vec3::zero(), 0) } + fn default() -> Self { Self::new(Mat4::identity(), 0.0, Vec3::zero(), 0, 1.0, 0.0) } } impl Default for Locals { diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 538874319b..88beaf5f73 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -13,6 +13,7 @@ use crate::{ scene::{ camera::{Camera, CameraMode, Dependents}, math, LodData, SceneData, + terrain::Terrain, }, }; use anim::{ @@ -455,6 +456,7 @@ impl FigureMgr { // Visible chunk data. visible_psr_bounds: math::Aabr, camera: &Camera, + terrain: Option<&Terrain>, ) -> anim::vek::Aabb { span!(_guard, "maintain", "FigureManager::maintain"); let state = scene_data.state; @@ -1329,6 +1331,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::QuadrupedSmall(body) => { @@ -1439,6 +1442,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::QuadrupedMedium(body) => { @@ -1560,6 +1564,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::QuadrupedLow(body) => { @@ -1668,6 +1673,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::BirdMedium(body) => { @@ -1773,6 +1779,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::FishMedium(body) => { @@ -1859,6 +1866,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::Dragon(body) => { @@ -1941,6 +1949,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::Theropod(body) => { @@ -2025,6 +2034,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::BirdSmall(body) => { @@ -2111,6 +2121,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::FishSmall(body) => { @@ -2197,6 +2208,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::BipedLarge(body) => { @@ -2603,6 +2615,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::Golem(body) => { @@ -2707,6 +2720,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, Body::Object(body) => { @@ -2740,6 +2754,7 @@ impl FigureMgr { is_player, camera, &mut update_buf, + terrain, ); }, } @@ -3393,6 +3408,7 @@ impl FigureState { is_player: bool, _camera: &Camera, buf: &mut [anim::FigureBoneData; anim::MAX_BONE_COUNT], + terrain: Option<&Terrain>, ) { // NOTE: As long as update() always gets called after get_or_create_model(), and // visibility is not set again until after the model is rendered, we @@ -3429,12 +3445,23 @@ impl FigureState { * anim::vek::Mat4::scaling_3d(anim::vek::Vec3::from(0.8 * scale)); let atlas_offs = model.allocation.rectangle.min; + + let (light, glow) = terrain + .map(|t| { + // Sample the location a little above to avoid clipping into terrain + let wpos = (Vec3::from(pos.into_array()) + Vec3::unit_z() * 0.5).map(|e: f32| e.floor() as i32); + (t.light_at_wpos(wpos), t.glow_at_wpos(wpos)) + }) + .unwrap_or((1.0, 0.0)); + let locals = FigureLocals::new( mat, - col, + col.rgb(), pos, vek::Vec2::new(atlas_offs.x, atlas_offs.y), is_player, + light, + glow, ); renderer.update_consts(&mut self.locals, &[locals]).unwrap(); diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index a8f450200b..a91f8f4cf9 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -698,9 +698,13 @@ impl Scene { ); // Maintain the figures. - let _figure_bounds = - self.figure_mgr - .maintain(renderer, scene_data, visible_psr_bounds, &self.camera); + let _figure_bounds = self.figure_mgr.maintain( + renderer, + scene_data, + visible_psr_bounds, + &self.camera, + Some(&self.terrain), + ); let sun_dir = scene_data.get_sun_dir(); let is_daylight = sun_dir.z < 0.0; diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 32ae142e41..30381a2beb 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -187,6 +187,7 @@ impl Scene { false, &camera, &mut buf, + None, ); (model, state) }), @@ -353,6 +354,7 @@ impl Scene { false, &self.camera, &mut buf, + None, ); } } diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 7dd05a447a..d25641d37c 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -61,6 +61,8 @@ pub struct TerrainChunkData { opaque_model: Model, fluid_model: Option>, col_lights: guillotiere::AllocId, + light_map: Box) -> f32 + Send + Sync>, + glow_map: Box) -> f32 + Send + Sync>, sprite_instances: HashMap<(SpriteKind, usize), Instances>, locals: Consts, pub blocks_of_interest: BlocksOfInterest, @@ -87,6 +89,8 @@ struct MeshWorkerResponse { opaque_mesh: Mesh, fluid_mesh: Mesh, col_lights_info: ColLightInfo, + light_map: Box) -> f32 + Send + Sync>, + glow_map: Box) -> f32 + Send + Sync>, sprite_instances: HashMap<(SpriteKind, usize), Vec>, started_tick: u64, blocks_of_interest: BlocksOfInterest, @@ -126,7 +130,7 @@ type SpriteSpec = sprite::sprite_kind::PureCases>>; /// Function executed by worker threads dedicated to chunk meshing. #[allow(clippy::or_fun_call)] // TODO: Pending review in #587 -fn mesh_worker + RectRasterableVol + ReadVol + Debug>( +fn mesh_worker + RectRasterableVol + ReadVol + Debug + 'static>( pos: Vec2, z_bounds: (f32, f32), started_tick: u64, @@ -139,7 +143,7 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug>( ) -> MeshWorkerResponse { span!(_guard, "mesh_worker"); let blocks_of_interest = BlocksOfInterest::from_chunk(&chunk); - let (opaque_mesh, fluid_mesh, _shadow_mesh, (bounds, col_lights_info)) = + let (opaque_mesh, fluid_mesh, _shadow_mesh, (bounds, col_lights_info, light_map, glow_map)) = volume.generate_mesh((range, Vec2::new(max_texture_size, max_texture_size), &blocks_of_interest)); MeshWorkerResponse { pos, @@ -190,6 +194,8 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug>( cfg.wind_sway, rel_pos, ori, + light_map(wpos), + glow_map(wpos), ); instances.entry(key).or_insert(Vec::new()).push(instance); @@ -200,6 +206,8 @@ fn mesh_worker + RectRasterableVol + ReadVol + Debug>( instances }, + light_map, + glow_map, blocks_of_interest, started_tick, } @@ -213,7 +221,7 @@ struct SpriteData { offset: Vec3, } -pub struct Terrain { +pub struct Terrain { atlas: AtlasAllocator, sprite_config: Arc, chunks: HashMap, TerrainChunkData>, @@ -462,6 +470,18 @@ impl Terrain { } } + /// Find the light level (sunlight) at the given world position. + pub fn light_at_wpos(&self, wpos: Vec3) -> f32 { + let chunk_pos = Vec2::from(wpos).map2(TerrainChunk::RECT_SIZE, |e: i32, sz| e.div_euclid(sz as i32)); + self.chunks.get(&chunk_pos).map(|c| (c.light_map)(wpos)).unwrap_or(1.0) + } + + /// Find the glow level (light from lamps) at the given world position. + pub fn glow_at_wpos(&self, wpos: Vec3) -> f32 { + let chunk_pos = Vec2::from(wpos).map2(TerrainChunk::RECT_SIZE, |e: i32, sz| e.div_euclid(sz as i32)); + self.chunks.get(&chunk_pos).map(|c| (c.glow_map)(wpos)).unwrap_or(0.0) + } + /// 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 @@ -732,6 +752,8 @@ impl Terrain { None }, col_lights: allocation.id, + light_map: response.light_map, + glow_map: response.glow_map, sprite_instances: response .sprite_instances .into_iter()