mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
base occlusion texture size of off voxels
This commit is contained in:
parent
a6fd5d5c8b
commit
3eabe24f12
28
Cargo.lock
generated
28
Cargo.lock
generated
@ -654,16 +654,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.1.8"
|
||||
version = "3.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71c47df61d9e16dc010b55dba1952a57d8c215dbb533fd13cdd13369aac73b1c"
|
||||
checksum = "3124f3f75ce09e22d1410043e1e24f2ecc44fad3afe4f08408f1f7663d68da2b"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"indexmap",
|
||||
"lazy_static",
|
||||
"os_str_bytes",
|
||||
"strsim 0.10.0",
|
||||
"termcolor",
|
||||
"textwrap 0.15.0",
|
||||
@ -682,6 +682,15 @@ dependencies = [
|
||||
"syn 1.0.90",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "3.1.1"
|
||||
@ -3980,9 +3989,6 @@ name = "os_str_bytes"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owned_ttf_parser"
|
||||
@ -6362,7 +6368,7 @@ dependencies = [
|
||||
"async-channel",
|
||||
"authc",
|
||||
"byteorder",
|
||||
"clap 3.1.8",
|
||||
"clap 3.1.10",
|
||||
"hashbrown 0.11.2",
|
||||
"image",
|
||||
"num 0.4.0",
|
||||
@ -6551,7 +6557,7 @@ dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
"bytes",
|
||||
"clap 3.1.8",
|
||||
"clap 3.1.10",
|
||||
"criterion",
|
||||
"crossbeam-channel",
|
||||
"futures-core",
|
||||
@ -6674,7 +6680,7 @@ name = "veloren-server-cli"
|
||||
version = "0.12.0"
|
||||
dependencies = [
|
||||
"ansi-parser",
|
||||
"clap 3.1.8",
|
||||
"clap 3.1.10",
|
||||
"crossterm 0.23.2",
|
||||
"lazy_static",
|
||||
"mimalloc",
|
||||
@ -6825,7 +6831,7 @@ dependencies = [
|
||||
name = "veloren-voxygen-i18n"
|
||||
version = "0.10.0"
|
||||
dependencies = [
|
||||
"clap 3.1.8",
|
||||
"clap 3.1.10",
|
||||
"deunicode",
|
||||
"git2",
|
||||
"hashbrown 0.11.2",
|
||||
@ -6842,7 +6848,7 @@ dependencies = [
|
||||
"arr_macro",
|
||||
"bincode",
|
||||
"bitvec",
|
||||
"clap 3.1.8",
|
||||
"clap 3.1.10",
|
||||
"criterion",
|
||||
"csv",
|
||||
"deflate",
|
||||
|
@ -139,13 +139,13 @@ void main() {
|
||||
break;
|
||||
}
|
||||
float rain_density = rain_density_at(cam_wpos.xy + rpos.xy) * rain_occlusion_at(cam_pos.xyz + rpos.xyz) * 10.0;
|
||||
vec2 drop_size = vec2(0.0008, 0.05);
|
||||
|
||||
if (fract(hash(fract(vec4(cell, rain_dist, 0) * 0.01))) > rain_density) {
|
||||
if (rain_density < 0.001 || fract(hash(fract(vec4(cell, rain_dist, 0) * 0.01))) > rain_density) {
|
||||
continue;
|
||||
}
|
||||
vec2 near_drop = cell + (vec2(0.5) + (vec2(hash(vec4(cell, 0, 0)), 0.5) - 0.5) * vec2(2, 0)) / drop_density;
|
||||
|
||||
vec2 drop_size = vec2(0.0008, 0.05);
|
||||
float avg_alpha = (drop_size.x * drop_size.y) * 10 / 1;
|
||||
float alpha = sign(max(1 - length((rain_pos - near_drop) / drop_size * 0.1), 0));
|
||||
float light = sqrt(dot(old_color, vec3(1))) + (get_sun_brightness() + get_moon_brightness()) * 0.01;
|
||||
|
@ -121,11 +121,8 @@ float cloud_tendency_at(vec2 pos) {
|
||||
return sample_weather(pos).r;
|
||||
}
|
||||
|
||||
const float RAIN_CLOUD = 0.05;
|
||||
|
||||
float rain_density_at(vec2 pos) {
|
||||
return sample_weather(pos).g;
|
||||
//return clamp((cloud_tendency_at(pos) - RAIN_CLOUD) * 10, 0, 1);
|
||||
}
|
||||
|
||||
float cloud_shadow(vec3 pos, vec3 light_dir) {
|
||||
|
@ -234,6 +234,7 @@ void main() {
|
||||
#ifdef EXPERIMENTAL_RAIN
|
||||
vec3 pos = f_pos + focus_off.xyz;
|
||||
float rain_density = rain_density_at(pos.xy) * rain_occlusion_at(f_pos.xyz) * 50.0;
|
||||
// Toggle to see rain_occlusion
|
||||
// tgt_color = vec4(rain_occlusion_at(f_pos.xyz), 0.0, 0.0, 1.0);
|
||||
// return;
|
||||
if (rain_density > 0 && !faces_fluid && f_norm.z > 0.5) {
|
||||
|
@ -163,6 +163,7 @@ impl WeatherLerp {
|
||||
}
|
||||
|
||||
fn update(&mut self, to_update: &mut WeatherGrid) {
|
||||
prof_span!("WeatherLerp::update");
|
||||
let old = &self.old.0;
|
||||
let new = &self.new.0;
|
||||
if new.size() == Vec2::zero() {
|
||||
|
@ -82,6 +82,21 @@ pub struct WeatherGrid {
|
||||
weather: Grid<Weather>,
|
||||
}
|
||||
|
||||
fn to_cell_pos(wpos: Vec2<f32>) -> Vec2<f32> { wpos / CELL_SIZE as f32 - 0.5 }
|
||||
|
||||
// TODO: Move consts from world to common to avoid duplication
|
||||
const LOCALITY: [Vec2<i32>; 9] = [
|
||||
Vec2::new(0, 0),
|
||||
Vec2::new(0, 1),
|
||||
Vec2::new(1, 0),
|
||||
Vec2::new(0, -1),
|
||||
Vec2::new(-1, 0),
|
||||
Vec2::new(1, 1),
|
||||
Vec2::new(1, -1),
|
||||
Vec2::new(-1, 1),
|
||||
Vec2::new(-1, -1),
|
||||
];
|
||||
|
||||
impl WeatherGrid {
|
||||
pub fn new(size: Vec2<u32>) -> Self {
|
||||
Self {
|
||||
@ -100,7 +115,7 @@ impl WeatherGrid {
|
||||
/// Get the weather at a given world position by doing bilinear
|
||||
/// interpolation between four cells.
|
||||
pub fn get_interpolated(&self, wpos: Vec2<f32>) -> Weather {
|
||||
let cell_pos = wpos / CELL_SIZE as f32;
|
||||
let cell_pos = to_cell_pos(wpos);
|
||||
let rpos = cell_pos.map(|e| e.fract());
|
||||
let cell_pos = cell_pos.map(|e| e.floor());
|
||||
|
||||
@ -125,4 +140,24 @@ impl WeatherGrid {
|
||||
rpos.y,
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the max weather near a position
|
||||
pub fn get_max_near(&self, wpos: Vec2<f32>) -> Weather {
|
||||
let cell_pos: Vec2<i32> = to_cell_pos(wpos).as_();
|
||||
LOCALITY
|
||||
.iter()
|
||||
.map(|l| {
|
||||
self.weather
|
||||
.get(cell_pos + l)
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
})
|
||||
.reduce(|a, b| Weather {
|
||||
cloud: a.cloud.max(b.cloud),
|
||||
rain: a.rain.max(b.rain),
|
||||
wind: a.wind.map2(b.wind, |a, b| a.max(b)),
|
||||
})
|
||||
// There will always be 9 elements in locality
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -359,6 +359,10 @@ impl State {
|
||||
self.weather_grid().get_interpolated(pos)
|
||||
}
|
||||
|
||||
pub fn max_weather_near(&self, pos: Vec2<f32>) -> Weather {
|
||||
self.weather_grid().get_max_near(pos)
|
||||
}
|
||||
|
||||
/// Get the current in-game time of day.
|
||||
///
|
||||
/// Note that this should not be used for physics, animations or other such
|
||||
|
@ -1,4 +1,4 @@
|
||||
use common::weather::{WeatherGrid, CHUNKS_PER_CELL, WEATHER_DT};
|
||||
use common::weather::{CHUNKS_PER_CELL, WEATHER_DT};
|
||||
use common_ecs::{dispatch, System};
|
||||
use common_state::State;
|
||||
use specs::DispatcherBuilder;
|
||||
|
@ -1,15 +1,21 @@
|
||||
use common::{
|
||||
grid::Grid,
|
||||
resources::TimeOfDay,
|
||||
terrain::TerrainChunkSize,
|
||||
vol::RectVolSize,
|
||||
weather::{Weather, WeatherGrid, CELL_SIZE, CHUNKS_PER_CELL},
|
||||
weather::{WeatherGrid, CELL_SIZE},
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use noise::{NoiseFn, SuperSimplex, Turbulence};
|
||||
use vek::*;
|
||||
use world::World;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
#[derive(Clone, Copy, Default)]
|
||||
struct Cell {
|
||||
wind: Vec2<f32>,
|
||||
temperature: f32,
|
||||
moisture: f32,
|
||||
cloud: f32,
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct Constants {
|
||||
alt: f32,
|
||||
@ -18,13 +24,6 @@ pub struct Constants {
|
||||
temp: f32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
struct Cell {
|
||||
wind: Vec2<f32>,
|
||||
temperature: f32,
|
||||
moisture: f32,
|
||||
cloud: f32,
|
||||
}
|
||||
/// Used to sample weather that isn't simulated
|
||||
fn sample_cell(_p: Vec2<i32>, _time: f64) -> Cell {
|
||||
Cell {
|
||||
@ -40,12 +39,6 @@ pub struct WeatherInfo {
|
||||
pub lightning_chance: f32,
|
||||
}
|
||||
|
||||
pub struct WeatherSim {
|
||||
cells: Grid<Cell>, // The variables used for simulation
|
||||
consts: Grid<Constants>, // The constants from the world used for simulation
|
||||
info: Grid<WeatherInfo>,
|
||||
}
|
||||
|
||||
fn sample_plane_normal(points: &[Vec3<f32>]) -> Option<Vec3<f32>> {
|
||||
if points.len() < 3 {
|
||||
return None;
|
||||
@ -82,13 +75,21 @@ fn sample_plane_normal(points: &[Vec3<f32>]) -> Option<Vec3<f32>> {
|
||||
Some(Vec3::new(xy * yz - xz * yy, xy * xz - yz * xx, det_z).normalized())
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
fn cell_to_wpos(p: Vec2<i32>) -> Vec2<i32> { p * CELL_SIZE as i32 }
|
||||
|
||||
pub struct WeatherSim {
|
||||
// cells: Grid<Cell>, // The variables used for simulation
|
||||
// consts: Grid<Constants>, // The constants from the world used for simulation
|
||||
// info: Grid<WeatherInfo>,
|
||||
size: Vec2<u32>,
|
||||
}
|
||||
|
||||
impl WeatherSim {
|
||||
pub fn new(size: Vec2<u32>, world: &World) -> Self {
|
||||
pub fn new(size: Vec2<u32>, _world: &World) -> Self {
|
||||
/*
|
||||
let size = size.as_();
|
||||
let mut this = Self {
|
||||
let this = Self {
|
||||
cells: Grid::new(size, Cell::default()),
|
||||
consts: Grid::from_raw(
|
||||
size,
|
||||
@ -138,6 +139,8 @@ impl WeatherSim {
|
||||
*cell = sample_cell(point, time);
|
||||
});
|
||||
this
|
||||
*/
|
||||
Self { size }
|
||||
}
|
||||
|
||||
/*
|
||||
@ -380,5 +383,5 @@ impl WeatherSim {
|
||||
*/
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Vec2<u32> { self.cells.size().as_() }
|
||||
pub fn size(&self) -> Vec2<u32> { self.size }
|
||||
}
|
||||
|
@ -5,8 +5,6 @@ use specs::{Join, ReadExpect, ReadStorage, Write};
|
||||
|
||||
use crate::{client::Client, sys::SysScheduler};
|
||||
|
||||
use super::sim::WeatherSim;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Sys;
|
||||
|
||||
|
@ -151,7 +151,7 @@ impl AmbientMgr {
|
||||
+ ((cam_pos.z - terrain_alt).abs() / 150.0).powi(2))
|
||||
.min(1.0);
|
||||
|
||||
return alt_multiplier * tree_multiplier > 0.0;
|
||||
alt_multiplier * tree_multiplier > 0.0
|
||||
},
|
||||
AmbientChannelTag::Rain => {
|
||||
let focus_off = camera.get_focus_pos().map(f32::trunc);
|
||||
@ -165,9 +165,9 @@ impl AmbientMgr {
|
||||
let camera_multiplier =
|
||||
1.0 - ((cam_pos.z - terrain_alt).abs() / 75.0).powi(2).min(1.0);
|
||||
|
||||
return client.weather_at_player().rain > 0.001 || camera_multiplier > 0.0;
|
||||
client.weather_at_player().rain > 0.001 || camera_multiplier > 0.0
|
||||
},
|
||||
AmbientChannelTag::Thunder => return client.weather_at_player().rain * 500.0 > 0.7,
|
||||
AmbientChannelTag::Thunder => client.weather_at_player().rain * 500.0 > 0.7,
|
||||
AmbientChannelTag::Leaves => {
|
||||
let focus_off = camera.get_focus_pos().map(f32::trunc);
|
||||
let cam_pos = camera.dependents().cam_pos + focus_off;
|
||||
@ -182,7 +182,7 @@ impl AmbientMgr {
|
||||
+ ((cam_pos.z - terrain_alt + 20.0).abs() / 150.0).powi(2))
|
||||
.min(1.0));
|
||||
|
||||
return tree_multiplier > 0.1;
|
||||
tree_multiplier > 0.1
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -199,7 +199,7 @@ impl AmbientChannel {
|
||||
|
||||
target_volume = self.check_camera(state, client, cam_pos, target_volume);
|
||||
|
||||
return target_volume;
|
||||
target_volume
|
||||
}
|
||||
|
||||
fn check_camera(
|
||||
@ -268,10 +268,10 @@ impl AmbientChannel {
|
||||
/ 30.0_f32.powi(2))
|
||||
.min(1.0);
|
||||
|
||||
return alt_multiplier
|
||||
alt_multiplier
|
||||
* tree_multiplier
|
||||
* (wind_speed_multiplier + ((cam_pos.z - terrain_alt).abs() / 150.0).powi(2))
|
||||
.min(1.0);
|
||||
.min(1.0)
|
||||
},
|
||||
AmbientChannelTag::Rain => {
|
||||
let focus_off = camera.get_focus_pos().map(f32::trunc);
|
||||
@ -288,7 +288,7 @@ impl AmbientChannel {
|
||||
|
||||
let rain_intensity = (client.weather_at_player().rain * 500.0) * camera_multiplier;
|
||||
|
||||
return rain_intensity.min(0.9);
|
||||
rain_intensity.min(0.9)
|
||||
},
|
||||
AmbientChannelTag::Thunder => {
|
||||
let rain_intensity = client.weather_at_player().rain * 500.0;
|
||||
|
@ -371,12 +371,9 @@ impl AudioFrontend {
|
||||
}
|
||||
if tag_match {
|
||||
return found_channel;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// Unused code that may be useful in the future:
|
||||
|
@ -367,8 +367,7 @@ impl Default for RenderMode {
|
||||
fluid: FluidMode::default(),
|
||||
lighting: LightingMode::default(),
|
||||
shadow: ShadowMode::default(),
|
||||
// TODO: should 0.5 be default for rain_occlusion?
|
||||
rain_occlusion: ShadowMapMode { resolution: 0.5 },
|
||||
rain_occlusion: ShadowMapMode::default(),
|
||||
bloom: BloomMode::default(),
|
||||
point_glow: 0.35,
|
||||
experimental_shaders: HashSet::default(),
|
||||
|
@ -104,7 +104,7 @@ impl RainOcclusionFigurePipeline {
|
||||
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: None,
|
||||
cull_mode: Some(wgpu::Face::Back),
|
||||
clamp_depth: true,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
conservative: false,
|
||||
|
@ -49,6 +49,10 @@ pub type ColLightInfo = (Vec<[u8; 4]>, Vec2<u16>);
|
||||
const QUAD_INDEX_BUFFER_U16_START_VERT_LEN: u16 = 3000;
|
||||
const QUAD_INDEX_BUFFER_U32_START_VERT_LEN: u32 = 3000;
|
||||
|
||||
// For rain occlusion we only need to render the closest chunks.
|
||||
// TODO: Is this a good value?
|
||||
pub const RAIN_OCCLUSION_CHUNKS: usize = 9;
|
||||
|
||||
/// A type that stores all the layouts associated with this renderer that never
|
||||
/// change when the RenderMode is modified.
|
||||
struct ImmutableLayouts {
|
||||
@ -366,15 +370,12 @@ impl Renderer {
|
||||
})
|
||||
.ok();
|
||||
|
||||
let rain_occlusion_view = RainOcclusionMap::create_view(
|
||||
&device,
|
||||
(dims.width, dims.height),
|
||||
&pipeline_modes.rain_occlusion,
|
||||
)
|
||||
.map_err(|err| {
|
||||
warn!("Could not create rain occlusion map views: {:?}", err);
|
||||
})
|
||||
.ok();
|
||||
let rain_occlusion_view =
|
||||
RainOcclusionMap::create_view(&device, &pipeline_modes.rain_occlusion)
|
||||
.map_err(|err| {
|
||||
warn!("Could not create rain occlusion map views: {:?}", err);
|
||||
})
|
||||
.ok();
|
||||
|
||||
let shaders = Shaders::load_expect("");
|
||||
let shaders_watcher = shaders.reload_watcher();
|
||||
@ -747,7 +748,6 @@ impl Renderer {
|
||||
if let Some(rain_depth) = rain_views {
|
||||
match RainOcclusionMap::create_view(
|
||||
&self.device,
|
||||
(dims.x, dims.y),
|
||||
&self.pipeline_modes.rain_occlusion,
|
||||
) {
|
||||
Ok(new_rain_depth) => {
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::render::pipelines::rain_occlusion;
|
||||
use crate::render::{pipelines::rain_occlusion, renderer::RAIN_OCCLUSION_CHUNKS};
|
||||
|
||||
use super::{
|
||||
super::{texture::Texture, RenderError, ShadowMapMode},
|
||||
Renderer,
|
||||
};
|
||||
use common::{terrain::TerrainChunkSize, vol::RectVolSize};
|
||||
use vek::*;
|
||||
|
||||
/// A type that holds shadow map data. Since shadow mapping may not be
|
||||
@ -115,15 +116,17 @@ impl RainOcclusionMap {
|
||||
/// Returns (point, directed)
|
||||
pub(super) fn create_view(
|
||||
device: &wgpu::Device,
|
||||
size: (u32, u32),
|
||||
mode: &ShadowMapMode,
|
||||
) -> Result<Texture, RenderError> {
|
||||
// (Attempt to) apply resolution factor to rain occlusion map resolution.
|
||||
let resolution_factor = mode.resolution.clamped(0.25, 4.0);
|
||||
|
||||
let max_texture_size = Renderer::max_texture_size_raw(device);
|
||||
let size =
|
||||
(RAIN_OCCLUSION_CHUNKS as f32).sqrt().ceil() as u32 * TerrainChunkSize::RECT_SIZE * 2;
|
||||
|
||||
// Limit to max texture size, rather than erroring.
|
||||
let size = Vec2::new(size.0, size.1).map(|e| {
|
||||
let size = size.map(|e| {
|
||||
let size = e as f32 * resolution_factor;
|
||||
// NOTE: We know 0 <= e since we clamped the resolution factor to be between
|
||||
// 0.25 and 4.0.
|
||||
@ -221,6 +224,4 @@ impl RainOcclusionMap {
|
||||
Self::Disabled(dummy) => dummy,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_enabled(&self) -> bool { matches!(self, Self::Enabled(_)) }
|
||||
}
|
||||
|
@ -797,7 +797,7 @@ impl Scene {
|
||||
// space (left-handed).
|
||||
let bounds0 = math::fit_psr(
|
||||
light_all_mat,
|
||||
visible_light_volume.iter().copied(),
|
||||
volume.iter().copied(),
|
||||
math::Vec4::homogenized,
|
||||
);
|
||||
// Vague idea: project z_n from the camera view to the light view (where it's
|
||||
@ -976,7 +976,7 @@ impl Scene {
|
||||
},
|
||||
} = math::fit_psr(
|
||||
shadow_all_mat,
|
||||
visible_light_volume.iter().copied(),
|
||||
volume.iter().copied(),
|
||||
math::Vec4::homogenized,
|
||||
);
|
||||
let s_x = 2.0 / (xmax - xmin);
|
||||
@ -998,10 +998,11 @@ impl Scene {
|
||||
)
|
||||
};
|
||||
|
||||
let weather = client.state().weather_at(focus_off.xy() + cam_pos.xy());
|
||||
if true || weather.rain > 0.001
|
||||
// TODO: check if rain map mode is on
|
||||
{
|
||||
let weather = client
|
||||
.state()
|
||||
.max_weather_near(focus_off.xy() + cam_pos.xy());
|
||||
if weather.rain > 0.0 {
|
||||
let weather = client.state().weather_at(focus_off.xy() + cam_pos.xy());
|
||||
let rain_dir = math::Vec3::from(weather.rain_dir());
|
||||
let rain_view_mat = math::Mat4::look_at_rh(look_at, look_at + rain_dir, up);
|
||||
|
||||
@ -1009,6 +1010,7 @@ impl Scene {
|
||||
directed_mats(rain_view_mat, rain_dir, &visible_occlusion_volume);
|
||||
|
||||
let rain_occlusion_locals = RainOcclusionLocals::new(shadow_mat, texture_mat);
|
||||
|
||||
renderer.update_consts(&mut self.data.rain_occlusion_mats, &[rain_occlusion_locals]);
|
||||
}
|
||||
|
||||
@ -1131,6 +1133,7 @@ impl Scene {
|
||||
let is_daylight = sun_dir.z < 0.0;
|
||||
let focus_pos = self.camera.get_focus_pos();
|
||||
let cam_pos = self.camera.dependents().cam_pos + focus_pos.map(|e| e.trunc());
|
||||
let is_rain = state.max_weather_near(cam_pos.xy()).rain > 0.0;
|
||||
|
||||
let camera_data = (&self.camera, scene_data.figure_lod_render_distance);
|
||||
|
||||
@ -1161,20 +1164,20 @@ impl Scene {
|
||||
self.terrain.chunks_for_point_shadows(focus_pos),
|
||||
)
|
||||
}
|
||||
// Render rain occlusion texture
|
||||
{
|
||||
prof_span!("rain occlusion");
|
||||
if let Some(mut occlusion_pass) = drawer.rain_occlusion_pass() {
|
||||
self.terrain
|
||||
.render_occlusion(&mut occlusion_pass.draw_terrain_shadows(), cam_pos);
|
||||
}
|
||||
// Render rain occlusion texture
|
||||
if is_rain {
|
||||
prof_span!("rain occlusion");
|
||||
if let Some(mut occlusion_pass) = drawer.rain_occlusion_pass() {
|
||||
self.terrain
|
||||
.render_occlusion(&mut occlusion_pass.draw_terrain_shadows(), cam_pos);
|
||||
|
||||
self.figure_mgr.render_shadows(
|
||||
&mut occlusion_pass.draw_figure_shadows(),
|
||||
state,
|
||||
tick,
|
||||
camera_data,
|
||||
);
|
||||
}
|
||||
self.figure_mgr.render_shadows(
|
||||
&mut occlusion_pass.draw_figure_shadows(),
|
||||
state,
|
||||
tick,
|
||||
camera_data,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ use crate::{
|
||||
},
|
||||
render::{
|
||||
pipelines::{self, ColLights},
|
||||
renderer::RAIN_OCCLUSION_CHUNKS,
|
||||
ColLightInfo, FirstPassDrawer, FluidVertex, GlobalModel, Instances, LodData, Mesh, Model,
|
||||
RenderError, Renderer, SpriteGlobalsBindGroup, SpriteInstance, SpriteVertex, SpriteVerts,
|
||||
TerrainLocals, TerrainShadowDrawer, TerrainVertex, SPRITE_VERT_PAGE_SIZE,
|
||||
@ -1295,6 +1296,10 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
min: focus_pos - 2.0,
|
||||
max: focus_pos + 2.0,
|
||||
});
|
||||
let inv_proj_view =
|
||||
math::Mat4::from_col_arrays((proj_mat_treeculler * view_mat).into_col_arrays())
|
||||
.as_::<f64>()
|
||||
.inverted();
|
||||
|
||||
// PSCs: Potential shadow casters
|
||||
let ray_direction = scene_data.get_sun_dir();
|
||||
@ -1315,10 +1320,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
};
|
||||
let focus_off = math::Vec3::from(focus_off);
|
||||
let visible_bounds_fine = visible_bounding_box.as_::<f64>();
|
||||
let inv_proj_view =
|
||||
math::Mat4::from_col_arrays((proj_mat_treeculler * view_mat).into_col_arrays())
|
||||
.as_::<f64>()
|
||||
.inverted();
|
||||
let ray_direction = math::Vec3::<f32>::from(ray_direction);
|
||||
// NOTE: We use proj_mat_treeculler here because
|
||||
// calc_focused_light_volume_points makes the assumption that the
|
||||
@ -1402,45 +1403,35 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
};
|
||||
drop(guard);
|
||||
span!(guard, "Rain occlusion magic");
|
||||
let weather = scene_data.state.weather_at(focus_pos.xy());
|
||||
let visible_occlusion_volume = if weather.rain > 0.0 {
|
||||
let occlusion_box = Aabb {
|
||||
min: visible_bounding_box
|
||||
.min
|
||||
.map2(focus_pos - 10.0, |a, b| a.max(b)),
|
||||
max: visible_bounding_box
|
||||
.max
|
||||
.map2(focus_pos + 10.0, |a, b| a.min(b)),
|
||||
};
|
||||
// Check if there is rain near the camera
|
||||
let max_weather = scene_data.state.max_weather_near(focus_pos.xy());
|
||||
let visible_occlusion_volume = if max_weather.rain > 0.0 {
|
||||
let occlusion_box = visible_bounding_box/*.intersection(Aabb {
|
||||
min: focus_pos + camera.dependents().cam_pos - 100.0,
|
||||
max: focus_pos + camera.dependents().cam_pos + 100.0,
|
||||
})*/;
|
||||
let visible_bounding_box = math::Aabb::<f32> {
|
||||
min: math::Vec3::from(occlusion_box.min - focus_off),
|
||||
max: math::Vec3::from(occlusion_box.max - focus_off),
|
||||
};
|
||||
let visible_bounds_fine = math::Aabb {
|
||||
min: math::Vec3::from(visible_bounding_box.min.as_::<f64>()),
|
||||
max: math::Vec3::from(visible_bounding_box.max.as_::<f64>()),
|
||||
min: visible_bounding_box.min.as_::<f64>(),
|
||||
max: visible_bounding_box.max.as_::<f64>(),
|
||||
};
|
||||
// TODO: move out shared calculations
|
||||
let inv_proj_view =
|
||||
math::Mat4::from_col_arrays((proj_mat_treeculler * view_mat).into_col_arrays())
|
||||
.as_::<f64>()
|
||||
.inverted();
|
||||
|
||||
let weather = scene_data.state.weather_at(focus_pos.xy());
|
||||
let ray_direction = math::Vec3::<f32>::from(weather.rain_dir());
|
||||
|
||||
// NOTE: We use proj_mat_treeculler here because
|
||||
// calc_focused_light_volume_points makes the assumption that the
|
||||
// near plane lies before the far plane.
|
||||
let visible_occlusion_volume = math::calc_focused_light_volume_points(
|
||||
math::calc_focused_light_volume_points(
|
||||
inv_proj_view,
|
||||
ray_direction.as_::<f64>(),
|
||||
visible_bounds_fine,
|
||||
1e-6,
|
||||
)
|
||||
.map(|v| v.as_::<f32>())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
visible_occlusion_volume
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
@ -1512,9 +1503,6 @@ impl<V: RectRasterableVol> Terrain<V> {
|
||||
let focus_chunk = Vec2::from(focus_pos).map2(TerrainChunk::RECT_SIZE, |e: f32, sz| {
|
||||
(e as i32).div_euclid(sz as i32)
|
||||
});
|
||||
// For rain occlusion we only need to render the closest chunks.
|
||||
// TODO: Is this a good value?
|
||||
const RAIN_OCCLUSION_CHUNKS: usize = 16;
|
||||
let chunk_iter = Spiral2d::new()
|
||||
.filter_map(|rpos| {
|
||||
let pos = focus_chunk + rpos;
|
||||
|
@ -1617,7 +1617,7 @@ impl PlayState for SessionState {
|
||||
&outcome,
|
||||
&scene_data,
|
||||
&mut global_state.audio,
|
||||
&client.state(),
|
||||
client.state(),
|
||||
cam_pos,
|
||||
);
|
||||
self.hud
|
||||
|
Loading…
Reference in New Issue
Block a user