diff --git a/assets/martian.tweak.toml b/assets/martian.tweak.toml index c64e0d3..40523d7 100644 --- a/assets/martian.tweak.toml +++ b/assets/martian.tweak.toml @@ -14,23 +14,45 @@ main = "/Music/Main Track2" [audio.menu] select = "/SFX/MenuSelect" +### +# Fog +# Only seems to affect objects and not skyboxes +### [display3d.fog] -exponent = 1.0 -# https://docs.rs/bevy/latest/bevy/pbr/enum.FogFalloff.html -falloff = "Exponential 0.1" -# Examples: -# "Linear start end" -# "Exponential density" -# "ExponentialSquared density" -# "Exponential (extinction 1.0 1.0 1.0) (inscattering 1.0 1.0 1.0)" +exponent = 0.001 [display3d.fog.color] -Rgba = { red = 1.0, green = 0.2, blue = 0.1, alpha = 0.1 } +Rgba = { red = 1.0, green = 1.0, blue = 1.0, alpha = 0.1 } [display3d.fog.light_color] Rgba = { red = 1.0, green = 1.0, blue = 1.0, alpha = 0.1 } +### +# Fog Faloff +# https://docs.rs/bevy/0.11.3/bevy/pbr/enum.FogFalloff.html +### +[display3d.fog.falloff] +Exponential = { density = 0.005 } +# Examples: +# * Linear = { start = 1.0, end = 10.0 } +# * Exponential = { density = 1.0 } +# * ExponentialSquared = { density = 1.0 } +# * Atmospheric = { extinction = [1.0, 1.0, 1.0], inscattering = [1.0, 1.0, 1.0] } + +### +# Display 3D Coloring +### +[display3d.color] +### +# Tonemapping +# https://docs.rs/bevy/0.11.3/bevy/core_pipeline/tonemapping/enum.Tonemapping.html +# Options: None, Reinhard, ReinhardLuminance, AcesFitted, AgX, SomewhatBoringDisplayTransform, TonyMcMapface, BlenderFilmic +### +tonemapping = "ReinhardLuminance" -# https://docs.rs/bevy/latest/bevy/render/view/struct.ColorGrading.html +### +# Color grading +# https://docs.rs/bevy/0.11.3/bevy/render/view/struct.ColorGrading.html +### [display3d.color.grading] -exposure = 0.0 +exposure = 1.0 gamma = 1.0 pre_saturation = 1.0 post_saturation = 1.0 diff --git a/src/display3d.rs b/src/display3d.rs index 2ab079f..8d6dc3a 100644 --- a/src/display3d.rs +++ b/src/display3d.rs @@ -4,7 +4,10 @@ use crate::{ tweak::Tweakfile, }; use bevy::{ - core_pipeline::{tonemapping::DebandDither, Skybox}, + core_pipeline::{ + tonemapping::{DebandDither, Tonemapping}, + Skybox, + }, input::mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel}, render::{ render_resource::{TextureViewDescriptor, TextureViewDimension}, @@ -236,18 +239,22 @@ fn hydrate_camera( fn update_tweaks( mut events: EventReader>, - mut camera_settings: Query<(&mut FogSettings, &mut ColorGrading), With>, + mut camera_settings: Query< + (&mut FogSettings, &mut ColorGrading, &mut Tonemapping), + With, + >, tweaks: Res>, ) { events.iter().for_each(|event| match event { AssetEvent::Created { handle } | AssetEvent::Modified { handle } => { if let Some(tweak) = tweaks.get(handle) { - camera_settings - .iter_mut() - .for_each(|(mut fog, mut color_grading)| { + camera_settings.iter_mut().for_each( + |(mut fog, mut color_grading, mut tonemapping)| { *fog = tweak.display3d.fog.clone().into(); *color_grading = tweak.display3d.color.grading.clone().into(); - }); + *tonemapping = tweak.display3d.color.tonemapping.clone().into(); + }, + ); } } AssetEvent::Removed { .. } => debug!("Tweakfile removal not handled"), @@ -639,7 +646,7 @@ fn set_valid_move_model( } } -fn play_valid_move_animation(players: Query<&AnimationPlayer>) { +fn _play_valid_move_animation(_players: Query<&AnimationPlayer>) { todo!(); } @@ -751,6 +758,8 @@ fn switch_sides( } pub(crate) mod tweaks { + use bevy::core_pipeline::tonemapping::Tonemapping; + use super::*; #[derive(Debug, Deserialize, Default)] @@ -762,13 +771,15 @@ pub(crate) mod tweaks { } #[derive(Debug, Deserialize, Default)] - pub(super) struct ColorTweaks { + pub(crate) struct ColorTweaks { #[serde(default)] pub grading: ColorGradingTweaks, + #[serde(default)] + pub tonemapping: TonemappingTweak, } #[derive(Debug, Deserialize, Default, Clone)] - pub(super) struct ColorGradingTweaks { + pub(crate) struct ColorGradingTweaks { pub exposure: f32, pub gamma: f32, pub pre_saturation: f32, @@ -786,19 +797,46 @@ pub(crate) mod tweaks { } } + #[derive(Debug, Deserialize, Default, Clone)] + pub(crate) enum TonemappingTweak { + None, + Reinhard, + ReinhardLuminance, + AcesFitted, + AgX, + SomewhatBoringDisplayTransform, + #[default] + TonyMcMapface, + BlenderFilmic, + } + + impl Into for TonemappingTweak { + fn into(self) -> Tonemapping { + match self { + TonemappingTweak::None => Tonemapping::None, + TonemappingTweak::Reinhard => Tonemapping::Reinhard, + TonemappingTweak::ReinhardLuminance => Tonemapping::ReinhardLuminance, + TonemappingTweak::AcesFitted => Tonemapping::AcesFitted, + TonemappingTweak::AgX => Tonemapping::AgX, + TonemappingTweak::SomewhatBoringDisplayTransform => { + Tonemapping::SomewhatBoringDisplayTransform + } + TonemappingTweak::TonyMcMapface => Tonemapping::TonyMcMapface, + TonemappingTweak::BlenderFilmic => Tonemapping::BlenderFilmic, + } + } + } + #[derive(Debug, Clone, Deserialize)] - pub(super) struct FogTweaks { + pub(crate) struct FogTweaks { #[serde(default)] color: Color, #[serde(default)] light_color: Color, #[serde(default)] exponent: f32, - #[serde( - default = "default_fog_falloff", - deserialize_with = "deserialize_fog_falloff" - )] - falloff: FogFalloff, + #[serde(default)] + falloff: FogFalloffTweak, } impl Default for FogTweaks { @@ -807,7 +845,7 @@ pub(crate) mod tweaks { color: Color::WHITE, light_color: Color::WHITE, exponent: 1.0, - falloff: FogFalloff::Exponential { density: 1.0 }, + falloff: FogFalloffTweak::Exponential { density: 1.0 }, } } } @@ -818,115 +856,51 @@ pub(crate) mod tweaks { color: self.color, directional_light_color: self.light_color, directional_light_exponent: self.exponent, - falloff: self.falloff.clone(), + falloff: self.falloff.clone().into(), } } } - fn default_fog_falloff() -> FogFalloff { - FogFalloff::Exponential { density: 1.0 } + #[derive(Debug, Deserialize, Clone)] + pub(crate) enum FogFalloffTweak { + Linear { + start: f32, + end: f32, + }, + Exponential { + density: f32, + }, + ExponentialSquared { + density: f32, + }, + Atmospheric { + extinction: Vec3, + inscattering: Vec3, + }, } - fn deserialize_fog_falloff<'de, D: Deserializer<'de>>( - deserializer: D, - ) -> Result { - if let Ok(s) = String::deserialize(deserializer) { - // Linear [start f32] [end f32] - if s.starts_with("Linear") { - let mut parts = s.split(' '); - let _ = parts.next(); - let start: f32 = parts - .next() - .expect("Fog Linear Start") - .parse() - .expect("Floating point number"); - let end: f32 = parts - .next() - .expect("Fog Linear End") - .parse() - .expect("Floating point number"); - Ok(FogFalloff::Linear { start, end }) - // Exponential [density f32] - } else if s.starts_with("Exponential") { - let mut parts = s.split(' '); - let _ = parts.next(); - let density: f32 = parts - .next() - .expect("Fog Exponential Density") - .parse() - .expect("Floating point number"); - Ok(FogFalloff::Exponential { density }) - // ExponentialSquared [density f32] - } else if s.starts_with("ExponentialSquared") { - let mut parts = s.split(' '); - let _ = parts.next(); - let density: f32 = parts - .next() - .expect("Fog Exponential Density Squared") - .parse() - .expect("Floating point number"); - Ok(FogFalloff::ExponentialSquared { density }) - // Atmospheric (extinction [r: f32] [g: f32] [b: f32]) (inscattering [r: f32] [g: f32] [b: f32]) - } else if s.starts_with("Atmospheric") { - let extinction = { - let start = s.find("extinction").expect("Extinction start"); - let end = s[start..] - .match_indices(')') - .find_map(|(i, _)| Some(i)) - .expect("Extinction end"); - let mut parts = s[start..start + end].split(' '); - let _ = parts.next(); - let r: f32 = parts - .next() - .expect("red value") - .parse() - .expect("Floating point number"); - let g: f32 = parts - .next() - .expect("green value") - .parse() - .expect("Floating point number"); - let b: f32 = parts - .next() - .expect("blue value") - .parse() - .expect("Floating point number"); - Vec3::new(r, g, b) - }; - let inscattering = { - let start = s.find("inscattering").expect("Inscattering start"); - let end = s[start..] - .match_indices(')') - .find_map(|(i, _)| Some(i)) - .expect("Inscattering end"); - let mut parts = s[start..start + end].split(' '); - let _ = parts.next(); - let r: f32 = parts - .next() - .expect("red value") - .parse() - .expect("Floating point number"); - let g: f32 = parts - .next() - .expect("green value") - .parse() - .expect("Floating point number"); - let b: f32 = parts - .next() - .expect("blue value") - .parse() - .expect("Floating point number"); - Vec3::new(r, g, b) - }; - Ok(FogFalloff::Atmospheric { + impl Default for FogFalloffTweak { + fn default() -> FogFalloffTweak { + FogFalloffTweak::Exponential { density: 1.0 } + } + } + + impl Into for FogFalloffTweak { + fn into(self) -> FogFalloff { + match self { + FogFalloffTweak::Linear { start, end } => FogFalloff::Linear { start, end }, + FogFalloffTweak::Exponential { density } => FogFalloff::Exponential { density }, + FogFalloffTweak::ExponentialSquared { density } => { + FogFalloff::ExponentialSquared { density } + } + FogFalloffTweak::Atmospheric { extinction, inscattering, - }) - } else { - Err(de::Error::custom("Failed to parse fog value")) + } => FogFalloff::Atmospheric { + extinction, + inscattering, + }, } - } else { - Err(de::Error::custom("Failed to parse fog value")) } } }