use crate::{
anti_alias::AntiAliasing,
features::RendererFeatures,
optimization_policy::RendererOptimizationPolicy,
post_process::{PostProcessing, ToneMapping},
render_passes::material_opaque::edge_buffers::{
DEFAULT_MAX_EDGE_BUDGET_DESKTOP, DEFAULT_MAX_EDGE_BUDGET_MOBILE,
},
scene_spatial::SceneSpatialConfig,
shadows::{ShadowQualityTier, ShadowsConfig},
};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum RendererProfile {
Mobile,
#[default]
Desktop,
Cinema,
}
#[derive(Clone, Debug)]
pub struct RendererProfileDefaults {
pub anti_aliasing: AntiAliasing,
pub post_processing: PostProcessing,
pub features: RendererFeatures,
pub optimization_policy: RendererOptimizationPolicy,
pub shadows_config: ShadowsConfig,
pub shadow_quality_tier: ShadowQualityTier,
pub max_edge_budget: u32,
pub scene_spatial: SceneSpatialConfig,
pub render_texture_formats: RenderTextureFormatsOverride,
}
#[derive(Clone, Copy, Debug)]
pub struct RenderTextureFormatsOverride {
pub depth: awsm_renderer_core::texture::TextureFormat,
}
impl RendererProfile {
pub fn defaults(self) -> RendererProfileDefaults {
use awsm_renderer_core::texture::TextureFormat;
match self {
RendererProfile::Mobile => RendererProfileDefaults {
anti_aliasing: AntiAliasing {
msaa_sample_count: None,
smaa: false,
mipmap: true,
},
post_processing: PostProcessing {
tonemapping: ToneMapping::KhronosNeutralPbr,
bloom: false,
dof: false,
exposure: 0.0,
},
features: RendererFeatures::default(),
optimization_policy: RendererOptimizationPolicy {
gpu_culling_enable_threshold: 2000,
gpu_culling_disable_threshold: 1200,
..RendererOptimizationPolicy::default()
},
shadows_config: ShadowsConfig {
atlas_size: 1024,
evsm_atlas_size: 512,
cascade_resolution: 1024,
max_point_shadows: 2,
point_shadow_resolution: 256,
..ShadowsConfig::default()
},
shadow_quality_tier: ShadowQualityTier::Low,
max_edge_budget: DEFAULT_MAX_EDGE_BUDGET_MOBILE,
scene_spatial: SceneSpatialConfig {
rebuild_dirty_threshold: 400,
rebuild_period_frames: 1200,
},
render_texture_formats: RenderTextureFormatsOverride {
depth: TextureFormat::Depth24plus,
},
},
RendererProfile::Desktop => RendererProfileDefaults {
anti_aliasing: AntiAliasing::default(),
post_processing: PostProcessing::default(),
features: RendererFeatures::default(),
optimization_policy: RendererOptimizationPolicy::default(),
shadows_config: ShadowsConfig::default(),
shadow_quality_tier: ShadowQualityTier::High,
max_edge_budget: DEFAULT_MAX_EDGE_BUDGET_DESKTOP,
scene_spatial: SceneSpatialConfig::default(),
render_texture_formats: RenderTextureFormatsOverride {
depth: TextureFormat::Depth32float,
},
},
RendererProfile::Cinema => RendererProfileDefaults {
anti_aliasing: AntiAliasing {
msaa_sample_count: Some(4),
smaa: false,
mipmap: true,
},
post_processing: PostProcessing {
tonemapping: ToneMapping::KhronosNeutralPbr,
bloom: true,
dof: true,
exposure: 0.0,
},
features: RendererFeatures::default(),
optimization_policy: RendererOptimizationPolicy::default(),
shadows_config: ShadowsConfig {
atlas_size: 8192,
max_point_shadows: 16,
..ShadowsConfig::default()
},
shadow_quality_tier: ShadowQualityTier::Ultra,
max_edge_budget: DEFAULT_MAX_EDGE_BUDGET_DESKTOP,
scene_spatial: SceneSpatialConfig::default(),
render_texture_formats: RenderTextureFormatsOverride {
depth: TextureFormat::Depth32float,
},
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mobile_disables_msaa() {
assert!(RendererProfile::Mobile
.defaults()
.anti_aliasing
.msaa_sample_count
.is_none());
}
#[test]
fn desktop_keeps_msaa_4x() {
assert_eq!(
RendererProfile::Desktop
.defaults()
.anti_aliasing
.msaa_sample_count,
Some(4)
);
}
#[test]
fn mobile_lowers_shadow_atlas_and_cube_resolution() {
let d = RendererProfile::Mobile.defaults();
assert_eq!(d.shadows_config.atlas_size, 1024);
assert_eq!(d.shadows_config.point_shadow_resolution, 256);
assert_eq!(d.shadows_config.max_point_shadows, 2);
}
#[test]
fn mobile_picks_smaller_edge_budget() {
assert_eq!(
RendererProfile::Mobile.defaults().max_edge_budget,
DEFAULT_MAX_EDGE_BUDGET_MOBILE
);
assert_eq!(
RendererProfile::Desktop.defaults().max_edge_budget,
DEFAULT_MAX_EDGE_BUDGET_DESKTOP
);
}
#[test]
fn mobile_halves_bvh_rebuild_cadence() {
let m = RendererProfile::Mobile.defaults();
let d = RendererProfile::Desktop.defaults();
assert!(m.scene_spatial.rebuild_period_frames > d.scene_spatial.rebuild_period_frames);
assert!(m.scene_spatial.rebuild_dirty_threshold > d.scene_spatial.rebuild_dirty_threshold);
}
#[test]
fn cinema_enables_bloom_and_dof() {
let d = RendererProfile::Cinema.defaults();
assert!(d.post_processing.bloom);
assert!(d.post_processing.dof);
}
#[test]
fn mobile_picks_depth24() {
use awsm_renderer_core::texture::TextureFormat;
assert_eq!(
RendererProfile::Mobile
.defaults()
.render_texture_formats
.depth,
TextureFormat::Depth24plus
);
assert_eq!(
RendererProfile::Desktop
.defaults()
.render_texture_formats
.depth,
TextureFormat::Depth32float
);
}
}