use crate::ecs::graphics::resources::{Atmosphere, ColorGrading, DepthOfField, Fog, Graphics};
use crate::ecs::primitives::CameraCullingMask;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
pub enum ShadingMode {
Wireframe,
Solid,
Flat,
#[default]
Rendered,
}
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct ViewportShading {
pub mode: ShadingMode,
pub show_overlays: bool,
}
impl Default for ViewportShading {
fn default() -> Self {
Self {
mode: ShadingMode::Rendered,
show_overlays: true,
}
}
}
pub const FLAT_SHADING_COLOR: nalgebra_glm::Vec4 = nalgebra_glm::Vec4::new(0.72, 0.72, 0.72, 1.0);
pub const WIREFRAME_SENTINEL_COLOR: nalgebra_glm::Vec4 =
nalgebra_glm::Vec4::new(0.0, 0.0, 0.0, 2.0);
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct EffectiveShading {
pub unlit_mode: bool,
pub bloom_enabled: bool,
pub ssao_enabled: bool,
pub ssgi_enabled: bool,
pub ssr_enabled: bool,
pub show_normals: bool,
pub show_bounding_volumes: bool,
pub show_wireframe: bool,
pub selection_outline_enabled: bool,
pub flat_shading_color: Option<nalgebra_glm::Vec4>,
pub shadow_depth_enabled: bool,
pub lines_enabled: bool,
pub color_grading: ColorGrading,
pub depth_of_field: DepthOfField,
pub bloom_intensity: f32,
pub bloom_threshold: f32,
pub bloom_knee: f32,
pub bloom_filter_radius: f32,
pub ssao_radius: f32,
pub ssao_bias: f32,
pub ssao_intensity: f32,
pub ssao_sample_count: u32,
pub ssao_visualization: bool,
pub ssao_blur_depth_threshold: f32,
pub ssao_blur_normal_power: f32,
pub ssgi_radius: f32,
pub ssgi_intensity: f32,
pub ssgi_max_steps: u32,
pub ssr_max_steps: u32,
pub ssr_thickness: f32,
pub ssr_max_distance: f32,
pub ssr_stride: f32,
pub ssr_fade_start: f32,
pub ssr_fade_end: f32,
pub ssr_intensity: f32,
pub ambient_light: [f32; 4],
pub culling_mask: u32,
pub fog: Option<Fog>,
pub atmosphere: Atmosphere,
}
impl EffectiveShading {
pub fn from_graphics(graphics: &Graphics) -> Self {
Self {
unlit_mode: graphics.unlit_mode,
bloom_enabled: graphics.bloom_enabled,
ssao_enabled: graphics.ssao_enabled,
ssgi_enabled: graphics.ssgi_enabled,
ssr_enabled: graphics.ssr_enabled,
show_normals: graphics.show_normals,
show_bounding_volumes: graphics.show_bounding_volumes,
show_wireframe: false,
selection_outline_enabled: graphics.selection_outline_enabled,
flat_shading_color: None,
shadow_depth_enabled: true,
lines_enabled: graphics.show_normals || graphics.show_bounding_volumes,
color_grading: graphics.color_grading,
depth_of_field: graphics.depth_of_field,
bloom_intensity: graphics.bloom_intensity,
bloom_threshold: graphics.bloom_threshold,
bloom_knee: graphics.bloom_knee,
bloom_filter_radius: graphics.bloom_filter_radius,
ssao_radius: graphics.ssao_radius,
ssao_bias: graphics.ssao_bias,
ssao_intensity: graphics.ssao_intensity,
ssao_sample_count: graphics.ssao_sample_count,
ssao_visualization: graphics.ssao_visualization,
ssao_blur_depth_threshold: graphics.ssao_blur_depth_threshold,
ssao_blur_normal_power: graphics.ssao_blur_normal_power,
ssgi_radius: graphics.ssgi_radius,
ssgi_intensity: graphics.ssgi_intensity,
ssgi_max_steps: graphics.ssgi_max_steps,
ssr_max_steps: graphics.ssr_max_steps,
ssr_thickness: graphics.ssr_thickness,
ssr_max_distance: graphics.ssr_max_distance,
ssr_stride: graphics.ssr_stride,
ssr_fade_start: graphics.ssr_fade_start,
ssr_fade_end: graphics.ssr_fade_end,
ssr_intensity: graphics.ssr_intensity,
ambient_light: graphics.ambient_light,
culling_mask: !0,
fog: graphics.fog,
atmosphere: graphics.atmosphere,
}
}
pub fn for_camera(
graphics: &Graphics,
shading: &ViewportShading,
post_process: Option<&CameraPostProcess>,
culling_mask: Option<&CameraCullingMask>,
environment: Option<&CameraEnvironment>,
) -> Self {
let mut effective = Self::from_graphics(graphics);
if let Some(mask) = culling_mask {
effective.culling_mask = mask.0;
}
if let Some(env) = environment {
if let Some(atmosphere) = env.atmosphere {
effective.atmosphere = atmosphere;
}
effective.fog = match env.fog {
FogOverride::Inherit => effective.fog,
FogOverride::Disabled => None,
FogOverride::Override(fog) => Some(fog),
};
}
if let Some(overrides) = post_process {
if let Some(cg) = overrides.color_grading {
effective.color_grading = cg;
}
if let Some(dof) = overrides.depth_of_field {
effective.depth_of_field = dof;
}
if let Some(value) = overrides.bloom_intensity {
effective.bloom_intensity = value;
}
if let Some(value) = overrides.bloom_threshold {
effective.bloom_threshold = value;
}
if let Some(value) = overrides.bloom_knee {
effective.bloom_knee = value;
}
if let Some(value) = overrides.bloom_filter_radius {
effective.bloom_filter_radius = value;
}
if let Some(value) = overrides.ssao_intensity {
effective.ssao_intensity = value;
}
if let Some(value) = overrides.ssao_radius {
effective.ssao_radius = value;
}
if let Some(value) = overrides.ssgi_intensity {
effective.ssgi_intensity = value;
}
if let Some(value) = overrides.ssr_intensity {
effective.ssr_intensity = value;
}
if let Some(value) = overrides.ambient_light {
effective.ambient_light = value;
}
}
match shading.mode {
ShadingMode::Rendered => {}
ShadingMode::Solid => {
effective.unlit_mode = true;
effective.bloom_enabled = false;
effective.ssao_enabled = false;
effective.ssgi_enabled = false;
effective.ssr_enabled = false;
effective.shadow_depth_enabled = false;
}
ShadingMode::Flat => {
effective.bloom_enabled = false;
effective.ssao_enabled = false;
effective.ssgi_enabled = false;
effective.ssr_enabled = false;
effective.flat_shading_color = Some(FLAT_SHADING_COLOR);
}
ShadingMode::Wireframe => {
effective.unlit_mode = true;
effective.bloom_enabled = false;
effective.ssao_enabled = false;
effective.ssgi_enabled = false;
effective.ssr_enabled = false;
effective.shadow_depth_enabled = false;
effective.flat_shading_color = Some(WIREFRAME_SENTINEL_COLOR);
effective.show_wireframe = true;
}
}
if !shading.show_overlays {
effective.show_normals = false;
effective.show_bounding_volumes = false;
effective.selection_outline_enabled = false;
}
effective.lines_enabled =
effective.show_normals || effective.show_bounding_volumes || effective.show_wireframe;
effective
}
}
impl Default for EffectiveShading {
fn default() -> Self {
Self {
unlit_mode: false,
bloom_enabled: true,
ssao_enabled: false,
ssgi_enabled: false,
ssr_enabled: false,
show_normals: false,
show_bounding_volumes: false,
show_wireframe: false,
selection_outline_enabled: false,
flat_shading_color: None,
shadow_depth_enabled: true,
lines_enabled: false,
color_grading: ColorGrading::default(),
depth_of_field: DepthOfField::default(),
bloom_intensity: 0.08,
bloom_threshold: 1.0,
bloom_knee: 0.5,
bloom_filter_radius: 0.005,
ssao_radius: 0.5,
ssao_bias: 0.025,
ssao_intensity: 1.0,
ssao_sample_count: 64,
ssao_visualization: false,
ssao_blur_depth_threshold: 0.005,
ssao_blur_normal_power: 8.0,
ssgi_radius: 2.0,
ssgi_intensity: 1.0,
ssgi_max_steps: 16,
ssr_max_steps: 64,
ssr_thickness: 0.3,
ssr_max_distance: 50.0,
ssr_stride: 1.0,
ssr_fade_start: 0.8,
ssr_fade_end: 1.0,
ssr_intensity: 1.0,
ambient_light: [0.1, 0.1, 0.1, 1.0],
culling_mask: !0,
fog: None,
atmosphere: Atmosphere::None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct ConstrainedAspect(pub f32);
impl Default for ConstrainedAspect {
fn default() -> Self {
Self(16.0 / 9.0)
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct CameraEnvironment {
pub atmosphere: Option<Atmosphere>,
pub fog: FogOverride,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum FogOverride {
#[default]
Inherit,
Disabled,
Override(Fog),
}
#[derive(Debug, Clone, Copy, Default, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct CameraPostProcess {
pub color_grading: Option<ColorGrading>,
pub depth_of_field: Option<DepthOfField>,
pub bloom_intensity: Option<f32>,
pub bloom_threshold: Option<f32>,
pub bloom_knee: Option<f32>,
pub bloom_filter_radius: Option<f32>,
pub ssao_intensity: Option<f32>,
pub ssao_radius: Option<f32>,
pub ssgi_intensity: Option<f32>,
pub ssr_intensity: Option<f32>,
pub ambient_light: Option<[f32; 4]>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
pub enum ViewportUpdateMode {
#[default]
Always,
WhenVisible,
WhenDirty,
Once,
Disabled,
}