diff --git a/assets/martian.tweak.toml b/assets/martian.tweak.toml index 40523d7..8dac82a 100644 --- a/assets/martian.tweak.toml +++ b/assets/martian.tweak.toml @@ -1,29 +1,56 @@ +######################################################################### +# Audio settings +######################################################################### +### +# Main music track +### +[audio.music] +main = "/Music/Main Track2" + +### +# Menu SFX +### +[audio.menu] +select = "/SFX/MenuSelect" + +### +# 2D Mode SFX +### [audio.display2d] pick_up = "/SFX/2D/2DPickUpPiece" put_down = "/SFX/2D/2DPutDownPiece" +### +# 3D Mode SFX +### [audio.display3d] pick_up = "/SFX/3D/3DPickUpPiece" put_down = "/SFX/3D/3DPutDownPiece" idle = "/SFX/3D/3DPickup-Idle-PutdownWhirr" invalid = "/sfx/3D/3DInvalidMove" -[audio.music] -main = "/Music/Main Track2" - -[audio.menu] -select = "/SFX/MenuSelect" +######################################################################### +# Display3d settings +######################################################################### +[display3d] +### +# Multi-sample Anti-Aliasing +# https://docs.rs/bevy/0.11.3/bevy/prelude/enum.Msaa.html +# Options: Off, Sample2, Sample4, Sample8 +# Requires: display3d.ssoa.quality_level = "Off" +### +msaa = "Off" ### # Fog # Only seems to affect objects and not skyboxes ### [display3d.fog] -exponent = 0.001 +exponent = 0.0 [display3d.fog.color] -Rgba = { red = 1.0, green = 1.0, blue = 1.0, alpha = 0.1 } +Rgba = { red = 1.0, green = 1.0, blue = 1.0, alpha = 0.0 } [display3d.fog.light_color] -Rgba = { red = 1.0, green = 1.0, blue = 1.0, alpha = 0.1 } +Rgba = { red = 1.0, green = 1.0, blue = 1.0, alpha = 0.0 } ### # Fog Faloff # https://docs.rs/bevy/0.11.3/bevy/pbr/enum.FogFalloff.html @@ -56,3 +83,12 @@ exposure = 1.0 gamma = 1.0 pre_saturation = 1.0 post_saturation = 1.0 + +### +# Screen Space Ambient Occlusion +# https://docs.rs/bevy/0.11.3/bevy/pbr/enum.ScreenSpaceAmbientOcclusionQualityLevel.html +# Requires: display3d.msaa = "Off" +### +[display3d.ssao] +# Options: Off, Low, Medium, High, Ultra +quality_level = "Off" diff --git a/src/display3d.rs b/src/display3d.rs index 8d6dc3a..78b9b20 100644 --- a/src/display3d.rs +++ b/src/display3d.rs @@ -5,23 +5,31 @@ use crate::{ }; use bevy::{ core_pipeline::{ + experimental::taa::{TemporalAntiAliasPlugin, TemporalAntiAliasSettings}, + prepass::MotionVectorPrepass, tonemapping::{DebandDither, Tonemapping}, Skybox, }, input::mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel}, + pbr::{ + ScreenSpaceAmbientOcclusionBundle, ScreenSpaceAmbientOcclusionQualityLevel, + ScreenSpaceAmbientOcclusionSettings, + }, render::{ render_resource::{TextureViewDescriptor, TextureViewDimension}, view::ColorGrading, }, window::PrimaryWindow, }; -use serde::{de, Deserialize, Deserializer}; +use serde::Deserialize; pub(crate) struct Display3dPlugin; impl Plugin for Display3dPlugin { fn build(&self, app: &mut App) { - app.add_systems(OnEnter(GameState::Loading), load_assets) + app.add_plugins(TemporalAntiAliasPlugin) + .add_systems(OnEnter(GameState::Loading), load_assets) + .insert_resource(Msaa::Off) .add_systems( OnExit(GameState::Loading), (initialize, fix_skybox.before(initialize)), @@ -72,6 +80,7 @@ impl Plugin for Display3dPlugin { opening_animation .run_if(run_once()) .run_if(in_state(GameState::Play)), + update_tweaks, ), ) .add_systems(OnExit(DisplayState::Display3d), deactivate::) @@ -213,11 +222,10 @@ fn hydrate_camera( specular_map: assets.skybox.clone(), }, UiCameraConfig { show_ui: true }, - FogSettings { - color: Color::WHITE, - falloff: FogFalloff::from_visibility_colors(100.0, Color::NONE, Color::NONE), - ..default() - }, + FogSettings { ..default() }, + ScreenSpaceAmbientOcclusionBundle { ..default() }, + TemporalAntiAliasSettings { ..default() }, + MotionVectorPrepass { ..default() }, Name::new("3D Camera"), )); @@ -237,28 +245,50 @@ fn hydrate_camera( }); } +/// Update display3d tweaks in the game +/// Triggered on entering 3d state and when the tweakfile is updated. fn update_tweaks( - mut events: EventReader>, mut camera_settings: Query< - (&mut FogSettings, &mut ColorGrading, &mut Tonemapping), + ( + Entity, + &mut FogSettings, + &mut ColorGrading, + &mut Tonemapping, + ), With, >, tweaks: Res>, + mut commands: Commands, + server: 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, 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"), - }); + let handle: Handle = server.load("martian.tweak.toml"); + if let Some(tweak) = tweaks.get(&handle) { + camera_settings.iter_mut().for_each( + |(entity, 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(); + + let quality_level: Option = + tweak.display3d.ssao.quality_level.clone().into(); + match quality_level { + Some(quality_level) => { + commands + .entity(entity) + .insert(ScreenSpaceAmbientOcclusionSettings { quality_level }); + commands.insert_resource(Msaa::Off); + } + None => { + commands + .entity(entity) + .remove::(); + let msaa: Msaa = tweak.display3d.msaa.clone().into(); + commands.insert_resource(msaa); + } + } + }, + ); + } } fn fix_skybox(mut images: ResMut>, assets: Res) { @@ -758,7 +788,9 @@ fn switch_sides( } pub(crate) mod tweaks { - use bevy::core_pipeline::tonemapping::Tonemapping; + use bevy::{ + core_pipeline::tonemapping::Tonemapping, pbr::ScreenSpaceAmbientOcclusionQualityLevel, + }; use super::*; @@ -768,6 +800,10 @@ pub(crate) mod tweaks { pub fog: FogTweaks, #[serde(default)] pub color: ColorTweaks, + #[serde(default)] + pub ssao: SsaoTweaks, + #[serde(default)] + pub msaa: MsaaTweaks, } #[derive(Debug, Deserialize, Default)] @@ -903,4 +939,67 @@ pub(crate) mod tweaks { } } } + + #[derive(Debug, Clone, Default, Deserialize)] + pub(crate) struct SsaoTweaks { + #[serde(default)] + pub quality_level: SsaoQualityLevelTweak, + } + + #[derive(Debug, Deserialize, Default, Clone)] + pub(crate) enum SsaoQualityLevelTweak { + #[default] + Off, + Low, + Medium, + High, + Ultra, + Custom { + slice_count: u32, + samples_per_slice_side: u32, + }, + } + + impl Into> for SsaoQualityLevelTweak { + fn into(self) -> Option { + match self { + SsaoQualityLevelTweak::Off => None, + SsaoQualityLevelTweak::Low => Some(ScreenSpaceAmbientOcclusionQualityLevel::Low), + SsaoQualityLevelTweak::Medium => { + Some(ScreenSpaceAmbientOcclusionQualityLevel::Medium) + } + SsaoQualityLevelTweak::High => Some(ScreenSpaceAmbientOcclusionQualityLevel::High), + SsaoQualityLevelTweak::Ultra => { + Some(ScreenSpaceAmbientOcclusionQualityLevel::Ultra) + } + SsaoQualityLevelTweak::Custom { + slice_count, + samples_per_slice_side, + } => Some(ScreenSpaceAmbientOcclusionQualityLevel::Custom { + slice_count, + samples_per_slice_side, + }), + } + } + } + + #[derive(Debug, Deserialize, Default, Clone)] + pub(crate) enum MsaaTweaks { + #[default] + Off, + Sample2, + Sample4, + Sample8, + } + + impl Into for MsaaTweaks { + fn into(self) -> Msaa { + match self { + MsaaTweaks::Off => Msaa::Off, + MsaaTweaks::Sample2 => Msaa::Sample2, + MsaaTweaks::Sample4 => Msaa::Sample4, + MsaaTweaks::Sample8 => Msaa::Sample4, + } + } + } }