proof-engine 0.2.1

Real-time graphics from math: glyphs and particles moved by ODEs, strange attractors and force fields, drawn with HDR bloom on OpenGL.
Documentation

// ── Screen Space Reflections ──────────────────────────────────────────────────

#[derive(Clone, Debug)]
pub struct SsrConfig {
    pub enabled: bool,
    pub max_steps: u32,
    pub max_distance: f32,
    pub thickness: f32,
    pub stride: u32,
    pub jitter: f32,
    pub fade_start: f32,
    pub fade_end: f32,
    pub reflection_blend: f32,
    pub quality: SsrQuality,
}

#[derive(Clone, Debug, PartialEq)]
pub enum SsrQuality { Low, Medium, High }

impl SsrConfig {
    pub fn new() -> Self { Self { enabled: false, max_steps: 32, max_distance: 100.0, thickness: 0.5, stride: 2, jitter: 0.5, fade_start: 0.7, fade_end: 1.0, reflection_blend: 0.5, quality: SsrQuality::Medium } }
    pub fn high() -> Self { Self { enabled: true, max_steps: 64, stride: 1, quality: SsrQuality::High, ..Self::new() } }
    pub fn low() -> Self { Self { enabled: true, max_steps: 16, stride: 4, quality: SsrQuality::Low, ..Self::new() } }
}

impl Default for SsrConfig {
    fn default() -> Self { Self::new() }
}

// ── Temporal Anti-Aliasing ────────────────────────────────────────────────────

#[derive(Clone, Debug)]
pub struct TaaConfig {
    pub enabled: bool,
    pub blend_factor: f32,
    pub history_blend: f32,
    pub sharpness: f32,
    pub jitter_scale: f32,
    pub motion_rejection: f32,
    pub clip_aabb: bool,
    pub variance_clip_gamma: f32,
    pub sample_count: u32,
}

impl TaaConfig {
    pub fn new() -> Self { Self { enabled: true, blend_factor: 0.1, history_blend: 0.9, sharpness: 0.5, jitter_scale: 1.0, motion_rejection: 0.3, clip_aabb: true, variance_clip_gamma: 1.0, sample_count: 8 } }
    pub fn aggressive() -> Self { Self { blend_factor: 0.05, motion_rejection: 0.5, ..Self::new() } }
    pub fn gentle() -> Self { Self { blend_factor: 0.2, motion_rejection: 0.1, ..Self::new() } }
}

impl Default for TaaConfig {
    fn default() -> Self { Self::new() }
}

// ── Volumetric Fog ────────────────────────────────────────────────────────────

#[derive(Clone, Debug)]
pub struct VolumetricFogConfig {
    pub enabled: bool,
    pub density: f32,
    pub scattering: f32,
    pub absorption: f32,
    pub anisotropy: f32,
    pub height_falloff: f32,
    pub base_height: f32,
    pub fog_color: [f32; 3],
    pub ambient_fog_color: [f32; 3],
    pub light_intensity: f32,
    pub num_slices: u32,
    pub temporal_reprojection: bool,
}

impl VolumetricFogConfig {
    pub fn new() -> Self { Self { enabled: false, density: 0.1, scattering: 0.5, absorption: 0.1, anisotropy: 0.5, height_falloff: 0.1, base_height: 0.0, fog_color: [1.0, 0.95, 0.9], ambient_fog_color: [0.5, 0.6, 0.8], light_intensity: 1.0, num_slices: 128, temporal_reprojection: true } }
    pub fn light_fog() -> Self { Self { enabled: true, density: 0.02, ..Self::new() } }
    pub fn heavy_fog() -> Self { Self { enabled: true, density: 0.3, ..Self::new() } }
    pub fn night_fog() -> Self { Self { enabled: true, density: 0.15, fog_color: [0.3, 0.35, 0.5], ambient_fog_color: [0.1, 0.1, 0.2], ..Self::new() } }
}

impl Default for VolumetricFogConfig {
    fn default() -> Self { Self::new() }
}

// ── Lens Flare ────────────────────────────────────────────────────────────────

#[derive(Clone, Debug)]
pub struct LensFlareConfig {
    pub enabled: bool,
    pub intensity: f32,
    pub threshold: f32,
    pub ghosts: u32,
    pub ghost_dispersal: f32,
    pub halo_width: f32,
    pub chromatic_distortion: f32,
    pub starburst_intensity: f32,
    pub starburst_count: u32,
}

impl LensFlareConfig {
    pub fn new() -> Self { Self { enabled: false, intensity: 0.5, threshold: 0.8, ghosts: 4, ghost_dispersal: 0.4, halo_width: 0.4, chromatic_distortion: 5.0, starburst_intensity: 0.5, starburst_count: 8 } }
    pub fn subtle() -> Self { Self { enabled: true, intensity: 0.2, ..Self::new() } }
    pub fn dramatic() -> Self { Self { enabled: true, intensity: 1.5, ghosts: 8, ..Self::new() } }
}

impl Default for LensFlareConfig {
    fn default() -> Self { Self::new() }
}

// ── Full Post Process Configuration ──────────────────────────────────────────

#[derive(Clone, Debug)]
pub struct FullPostProcessConfig {
    pub bloom: BloomConfig,
    pub color_grading: ColorGradingSettings,
    pub ssao: SsaoConfig,
    pub ssr: SsrConfig,
    pub taa: TaaConfig,
    pub dof: DepthOfFieldConfig,
    pub volumetric_fog: VolumetricFogConfig,
    pub lens_flare: LensFlareConfig,
    pub enabled: bool,
}

impl FullPostProcessConfig {
    pub fn new() -> Self {
        Self { bloom: BloomConfig::new(), color_grading: ColorGradingSettings::new(), ssao: SsaoConfig::new(), ssr: SsrConfig::new(), taa: TaaConfig::new(), dof: DepthOfFieldConfig::new(), volumetric_fog: VolumetricFogConfig::new(), lens_flare: LensFlareConfig::new(), enabled: true }
    }
    pub fn high_quality() -> Self {
        Self { bloom: BloomConfig::new(), ssao: SsaoConfig::high(), taa: TaaConfig::new(), ..Self::new() }
    }
    pub fn low_quality() -> Self {
        Self { bloom: BloomConfig::disabled(), ssao: SsaoConfig::low(), taa: TaaConfig::new(), ..Self::new() }
    }
    pub fn active_effect_count(&self) -> usize {
        [self.bloom.enabled, self.ssao.enabled, self.ssr.enabled, self.taa.enabled, self.dof.enabled, self.volumetric_fog.enabled, self.lens_flare.enabled].iter().filter(|&&b| b).count()
    }
}

impl Default for FullPostProcessConfig {
    fn default() -> Self { Self::new() }
}

// ── Rendering Quality Preset ──────────────────────────────────────────────────

#[derive(Clone, Debug)]
pub struct RenderQualityPreset {
    pub name: String,
    pub features: RenderFeatureFlags,
    pub post_process: FullPostProcessConfig,
    pub shadow_map_resolution: u32,
    pub shadow_cascades: u32,
    pub max_lights: u32,
    pub reflection_quality: u32,
    pub target_fps: u32,
    pub render_scale: f32,
}

impl RenderQualityPreset {
    pub fn low() -> Self {
        Self { name: "Low".into(), features: RenderFeatureFlags::default_low_quality(), post_process: FullPostProcessConfig::low_quality(), shadow_map_resolution: 1024, shadow_cascades: 2, max_lights: 16, reflection_quality: 0, target_fps: 60, render_scale: 0.75 }
    }
    pub fn medium() -> Self {
        Self { name: "Medium".into(), features: RenderFeatureFlags::default_medium_quality(), post_process: FullPostProcessConfig::new(), shadow_map_resolution: 2048, shadow_cascades: 3, max_lights: 64, reflection_quality: 1, target_fps: 60, render_scale: 1.0 }
    }
    pub fn high() -> Self {
        Self { name: "High".into(), features: RenderFeatureFlags::default_high_quality(), post_process: FullPostProcessConfig::high_quality(), shadow_map_resolution: 4096, shadow_cascades: 4, max_lights: 256, reflection_quality: 2, target_fps: 60, render_scale: 1.0 }
    }
    pub fn ultra() -> Self {
        let mut h = Self::high(); h.name = "Ultra".into(); h.shadow_map_resolution = 8192; h.render_scale = 1.25; h.max_lights = 1024; h
    }
    pub fn is_mobile_friendly(&self) -> bool { self.shadow_map_resolution <= 1024 && !self.features.ssao && !self.features.ssr }
}

// ── All rendering presets ─────────────────────────────────────────────────────

pub fn build_quality_presets() -> Vec<RenderQualityPreset> {
    vec![RenderQualityPreset::low(), RenderQualityPreset::medium(), RenderQualityPreset::high(), RenderQualityPreset::ultra()]
}

// ── Final constants ───────────────────────────────────────────────────────────

pub const SSR_MAX_STEPS: u32 = 128;
pub const TAA_HISTORY_FRAMES: u32 = 8;
pub const VOLUMETRIC_FOG_MAX_SLICES: u32 = 256;
pub const LENS_FLARE_MAX_GHOSTS: u32 = 16;
pub const POST_PROCESS_FULL_EFFECT_COUNT: usize = 8;
pub const RENDER_QUALITY_PRESET_COUNT: usize = 4;
pub const SHADOW_MAP_MAX_RESOLUTION: u32 = 16384;
pub const SHADOW_CASCADE_MAX: u32 = 8;
pub const RENDER_MAX_LIGHTS: u32 = 4096;
pub const RENDER_SCALE_MIN: f32 = 0.25;
pub const RENDER_SCALE_MAX: f32 = 2.0;

pub fn render_quality_preset_names() -> &'static [&'static str] { &["Low", "Medium", "High", "Ultra"] }
pub fn supported_render_apis() -> &'static [&'static str] { &["OpenGL 4.5", "Vulkan 1.3", "Metal 2", "WebGPU", "D3D12"] }
pub fn shader_compiler_total_feature_count() -> usize { shader_module_count() + RENDER_FEATURE_COUNT + POST_PROCESS_FULL_EFFECT_COUNT + RENDER_QUALITY_PRESET_COUNT }
pub fn shader_compiler_final_info() -> String {
    format!("ShaderCompilerEditor: {} total features, {} render API targets, {} quality presets", shader_compiler_total_feature_count(), supported_render_apis().len(), RENDER_QUALITY_PRESET_COUNT)
}