From 4187e7cb81ea5b00c2c8cb138525d1ba116904ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=CC=81te=CC=81=20Homolya?= Date: Sat, 18 Jan 2025 00:53:40 -0800 Subject: [PATCH] Change atmospheric units to meters --- .../src/atmosphere/aerial_view_lut.wgsl | 2 +- crates/bevy_pbr/src/atmosphere/functions.wgsl | 4 +- crates/bevy_pbr/src/atmosphere/mod.rs | 56 +++++++++---------- crates/bevy_pbr/src/atmosphere/types.wgsl | 2 +- examples/3d/atmosphere.rs | 4 +- 5 files changed, 32 insertions(+), 36 deletions(-) diff --git a/crates/bevy_pbr/src/atmosphere/aerial_view_lut.wgsl b/crates/bevy_pbr/src/atmosphere/aerial_view_lut.wgsl index b12d555552d35..659c7672ae1ed 100644 --- a/crates/bevy_pbr/src/atmosphere/aerial_view_lut.wgsl +++ b/crates/bevy_pbr/src/atmosphere/aerial_view_lut.wgsl @@ -39,7 +39,7 @@ fn main(@builtin(global_invocation_id) idx: vec3) { for (var step_i: i32 = i32(settings.aerial_view_lut_samples - 1); step_i >= 0; step_i--) { let sample_depth = depth_at_sample(slice_i, step_i); //view_dir.w is the cosine of the angle between the view vector and the camera forward vector, used to correct the step length. - let t_i = -depth_ndc_to_view_z(sample_depth) / ray_dir.w * settings.scene_units_to_km; + let t_i = -depth_ndc_to_view_z(sample_depth) / ray_dir.w * settings.scene_units_to_m; let dt = (t_i - prev_t); prev_t = t_i; diff --git a/crates/bevy_pbr/src/atmosphere/functions.wgsl b/crates/bevy_pbr/src/atmosphere/functions.wgsl index a067c51f4ea2d..816526a060fe9 100644 --- a/crates/bevy_pbr/src/atmosphere/functions.wgsl +++ b/crates/bevy_pbr/src/atmosphere/functions.wgsl @@ -257,9 +257,9 @@ fn max_atmosphere_distance(r: f32, mu: f32) -> f32 { return mix(t_top, t_bottom, f32(hits)); } -/// Assuming y=0 is the planet ground, returns the view radius in kilometers +/// Assuming y=0 is the planet ground, returns the view radius in meters fn view_radius() -> f32 { - return view.world_position.y * settings.scene_units_to_km + atmosphere.bottom_radius; + return view.world_position.y * settings.scene_units_to_m + atmosphere.bottom_radius; } // We assume the `up` vector at the view position is the y axis, since the world is locally flat/level. diff --git a/crates/bevy_pbr/src/atmosphere/mod.rs b/crates/bevy_pbr/src/atmosphere/mod.rs index 859412c341fbb..0a40e72cef549 100644 --- a/crates/bevy_pbr/src/atmosphere/mod.rs +++ b/crates/bevy_pbr/src/atmosphere/mod.rs @@ -232,24 +232,18 @@ impl Plugin for AtmospherePlugin { /// participating in Rayleigh and Mie scattering falls off roughly exponentially /// from the planet's surface, ozone only exists in a band centered at a fairly /// high altitude. -/// -/// Note that all units are in kilometers. This is to combat precision issues, -/// since integrating very small atmospheric densities over long distances -/// might otherwise cause problems. [`AtmosphereSettings`] has a field to set -/// the conversion factor from scene units to km, which by default assumes that -/// the scene units are meters. #[derive(Clone, Component, Reflect, ShaderType)] #[require(AtmosphereSettings)] pub struct Atmosphere { /// Radius of the planet /// - /// units: km + /// units: m pub bottom_radius: f32, /// Radius at which we consider the atmosphere to 'end' for our /// calculations (from center of planet) /// - /// units: km + /// units: m pub top_radius: f32, /// An approximation of the average albedo (or color, roughly) of the @@ -259,7 +253,7 @@ pub struct Atmosphere { pub ground_albedo: Vec3, /// The rate of falloff of rayleigh particulate with respect to altitude: - /// optical density = exp(-rayleigh_density_exp_scale * altitude). + /// optical density = exp(-rayleigh_density_exp_scale * altitude in meters). /// /// THIS VALUE MUST BE POSITIVE /// @@ -267,13 +261,13 @@ pub struct Atmosphere { pub rayleigh_density_exp_scale: f32, /// The scattering optical density of rayleigh particulate, or how - /// much light it scatters per kilometer + /// much light it scatters per meter /// - /// units: km^-1 + /// units: m^-1 pub rayleigh_scattering: Vec3, /// The rate of falloff of mie particulate with respect to altitude: - /// optical density = exp(-mie_density_exp_scale * altitude) + /// optical density = exp(-mie_density_exp_scale * altitude in meters) /// /// THIS VALUE MUST BE POSITIVE /// @@ -283,13 +277,13 @@ pub struct Atmosphere { /// The scattering optical density of mie particulate, or how much light /// it scatters per kilometer. /// - /// units: km^-1 + /// units: m^-1 pub mie_scattering: f32, /// The absorbing optical density of mie particulate, or how much light - /// it absorbs per kilometer. + /// it absorbs per meter. /// - /// units: km^-1 + /// units: m^-1 pub mie_absorption: f32, /// The "asymmetry" of mie scattering, or how much light tends to scatter @@ -301,35 +295,35 @@ pub struct Atmosphere { /// The altitude at which the ozone layer is centered. /// - /// units: km + /// units: m pub ozone_layer_altitude: f32, /// The width of the ozone layer /// - /// units: km + /// units: m pub ozone_layer_width: f32, /// The optical density of ozone, or how much of each wavelength of /// light it absorbs per kilometer. /// - /// units: km^-1 + /// units: m^-1 pub ozone_absorption: Vec3, } impl Atmosphere { pub const EARTH: Atmosphere = Atmosphere { - bottom_radius: 6360.0, - top_radius: 6460.0, + bottom_radius: 6360_000.0, + top_radius: 6460_000.0, ground_albedo: Vec3::splat(0.3), - rayleigh_density_exp_scale: 1.0 / 8.0, - rayleigh_scattering: Vec3::new(0.005802, 0.013558, 0.033100), - mie_density_exp_scale: 1.0 / 1.2, - mie_scattering: 0.003996, - mie_absorption: 0.0004440, + rayleigh_density_exp_scale: 1.0 / 8000.0, + rayleigh_scattering: Vec3::new(5.802e-6, 13.558e-6, 33.100e-6), + mie_density_exp_scale: 1.0 / 1200.0, + mie_scattering: 3.996e-6, + mie_absorption: 0.444e-6, mie_asymmetry: 0.8, - ozone_layer_altitude: 25.0, - ozone_layer_width: 30.0, - ozone_absorption: Vec3::new(0.000650, 0.001881, 0.000085), + ozone_layer_altitude: 25000.0, + ozone_layer_width: 30000.0, + ozone_absorption: Vec3::new(0.650e-6, 1.881e-6, 0.085e-6), }; pub fn with_density_multiplier(&self, mult: f32) -> Self { @@ -412,9 +406,9 @@ pub struct AtmosphereSettings { /// of the aerial-view LUT. pub aerial_view_lut_samples: u32, - /// A conversion factor between scene units and kilometers, used to + /// A conversion factor between scene units and meters, used to /// combat floating-point precision issues. - pub scene_units_to_km: f32, + pub scene_units_to_m: f32, } impl Default for AtmosphereSettings { @@ -429,7 +423,7 @@ impl Default for AtmosphereSettings { sky_view_lut_samples: 16, aerial_view_lut_size: UVec3::new(32, 32, 32), aerial_view_lut_samples: 10, - scene_units_to_km: 1.0e-3, + scene_units_to_m: 1.0, } } } diff --git a/crates/bevy_pbr/src/atmosphere/types.wgsl b/crates/bevy_pbr/src/atmosphere/types.wgsl index 4cf5452483559..3f28704cb2e80 100644 --- a/crates/bevy_pbr/src/atmosphere/types.wgsl +++ b/crates/bevy_pbr/src/atmosphere/types.wgsl @@ -32,7 +32,7 @@ struct AtmosphereSettings { multiscattering_lut_samples: u32, sky_view_lut_samples: u32, aerial_view_lut_samples: u32, - scene_units_to_km: f32, + scene_units_to_m: f32, } diff --git a/examples/3d/atmosphere.rs b/examples/3d/atmosphere.rs index aadce1615af41..8f44633bd8c83 100644 --- a/examples/3d/atmosphere.rs +++ b/examples/3d/atmosphere.rs @@ -7,6 +7,7 @@ use bevy::{ pbr::{Atmosphere, AtmosphereSettings, CascadeShadowConfigBuilder}, prelude::*, }; +use bevy_render::camera::Exposure; use light_consts::lux; fn main() { @@ -20,6 +21,7 @@ fn main() { fn setup_camera_fog(mut commands: Commands) { commands.spawn(( Camera3d::default(), + Exposure { ev100: 11.0 }, Camera { hdr: true, ..default() @@ -29,7 +31,7 @@ fn setup_camera_fog(mut commands: Commands) { Atmosphere::EARTH, Bloom::NATURAL, AtmosphereSettings { - scene_units_to_km: 1.0, + scene_units_to_m: 1e+3, ..Default::default() }, ));