use super::super::color::illuminant_white_balance;
use super::{DEFAULT_HEAD_SHADOW_DEG, LightingPreset, clamp_head_shadow_deg};
use crate::renderer::env_map::EnvironmentMap;
use glam::Vec3;
#[derive(Clone, Copy)]
pub enum EnvironmentSource<'a> {
Studio {
preset: LightingPreset,
exposure: f32,
light_yaw: f32,
light_pitch: f32,
backdrop: f32,
surface_glare: f32,
head_shadow_deg: f32,
},
HdrMap(&'a EnvironmentMap),
}
pub const BACKDROP_GREY: f32 = 0.23;
impl EnvironmentSource<'_> {
#[must_use]
pub const fn with_backdrop(self, backdrop: f32) -> Self {
match self {
Self::Studio {
preset,
exposure,
light_yaw,
light_pitch,
surface_glare,
head_shadow_deg,
..
} => Self::Studio {
preset,
exposure,
light_yaw,
light_pitch,
backdrop,
surface_glare,
head_shadow_deg,
},
hdr @ Self::HdrMap(_) => hdr,
}
}
#[must_use]
pub const fn with_head_shadow(self, head_shadow_deg: f32) -> Self {
match self {
Self::Studio {
preset,
exposure,
light_yaw,
light_pitch,
backdrop,
surface_glare,
..
} => Self::Studio {
preset,
exposure,
light_yaw,
light_pitch,
backdrop,
surface_glare,
head_shadow_deg: clamp_head_shadow_deg(head_shadow_deg),
},
hdr @ Self::HdrMap(_) => hdr,
}
}
#[must_use]
pub const fn head_shadow_deg(&self) -> f32 {
match *self {
Self::Studio {
head_shadow_deg, ..
} => head_shadow_deg,
Self::HdrMap(_) => DEFAULT_HEAD_SHADOW_DEG,
}
}
#[must_use]
pub const fn with_surface_glare(self, surface_glare: f32) -> Self {
match self {
Self::Studio {
preset,
exposure,
light_yaw,
light_pitch,
backdrop,
head_shadow_deg,
..
} => Self::Studio {
preset,
exposure,
light_yaw,
light_pitch,
backdrop,
surface_glare: clamp_surface_glare(surface_glare),
head_shadow_deg,
},
hdr @ Self::HdrMap(_) => hdr,
}
}
#[must_use]
pub const fn lighting_preset(&self) -> Option<LightingPreset> {
match *self {
Self::Studio { preset, .. } => Some(preset),
Self::HdrMap(_) => None,
}
}
#[must_use]
pub const fn surface_glare(&self) -> f32 {
match *self {
Self::Studio { surface_glare, .. } => surface_glare,
Self::HdrMap(_) => 1.0,
}
}
}
const fn clamp_surface_glare(value: f32) -> f32 {
if value >= 1.0 || value.is_nan() {
1.0
} else if value > 0.0 {
value
} else {
0.0
}
}
#[inline]
#[expect(
clippy::redundant_pub_crate,
reason = "re-exported as `pub(crate)` from `environment` for color::metrics, the transport code and the GPU estimator checks"
)]
pub(crate) fn environment_white_balance(environment: EnvironmentSource<'_>) -> Vec3 {
match environment {
EnvironmentSource::Studio { preset, .. } => illuminant_white_balance(preset),
EnvironmentSource::HdrMap(_) => Vec3::ONE,
}
}