proof-engine 0.2.3

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

// ── Render Target Management ──────────────────────────────────────────────────

#[derive(Clone, Debug)]
pub struct RenderTargetSet {
    pub id: u32,
    pub name: String,
    pub width: u32,
    pub height: u32,
    pub color_targets: Vec<u32>,
    pub depth_target: Option<u32>,
    pub msaa_samples: u32,
    pub active: bool,
}

impl RenderTargetSet {
    pub fn new(id: u32, name: impl Into<String>, w: u32, h: u32) -> Self {
        Self { id, name: name.into(), width: w, height: h, color_targets: Vec::new(), depth_target: None, msaa_samples: 1, active: false }
    }
    pub fn add_color(&mut self, tex_id: u32) { self.color_targets.push(tex_id); }
    pub fn set_depth(&mut self, tex_id: u32) { self.depth_target = Some(tex_id); }
    pub fn enable(&mut self) { self.active = true; }
    pub fn disable(&mut self) { self.active = false; }
    pub fn color_count(&self) -> usize { self.color_targets.len() }
    pub fn has_depth(&self) -> bool { self.depth_target.is_some() }
    pub fn total_attachments(&self) -> usize { self.color_targets.len() + if self.has_depth() { 1 } else { 0 } }
    pub fn aspect_ratio(&self) -> f32 { if self.height == 0 { 1.0 } else { self.width as f32 / self.height as f32 } }
    pub fn is_multisampled(&self) -> bool { self.msaa_samples > 1 }
    pub fn total_bytes(&self, bpp: u32) -> u64 { self.width as u64 * self.height as u64 * bpp as u64 * (self.color_targets.len() + 1) as u64 }
}

#[derive(Clone, Debug)]
pub struct RenderTargetManager {
    pub sets: HashMap<u32, RenderTargetSet>,
    pub active_set: Option<u32>,
    pub next_id: u32,
    pub backbuffer_id: u32,
}

impl RenderTargetManager {
    pub fn new() -> Self { Self { sets: HashMap::new(), active_set: None, next_id: 1, backbuffer_id: 0 } }
    pub fn create(&mut self, name: impl Into<String>, w: u32, h: u32) -> u32 {
        let id = self.next_id; self.next_id += 1;
        self.sets.insert(id, RenderTargetSet::new(id, name, w, h));
        id
    }
    pub fn get(&self, id: u32) -> Option<&RenderTargetSet> { self.sets.get(&id) }
    pub fn bind(&mut self, id: u32) { if let Some(s) = self.sets.get_mut(&id) { s.enable(); } self.active_set = Some(id); }
    pub fn unbind(&mut self) { if let Some(id) = self.active_set { if let Some(s) = self.sets.get_mut(&id) { s.disable(); } } self.active_set = None; }
    pub fn resize_all(&mut self, w: u32, h: u32) { for s in self.sets.values_mut() { s.width = w; s.height = h; } }
    pub fn count(&self) -> usize { self.sets.len() }
    pub fn active(&self) -> Option<&RenderTargetSet> { self.active_set.and_then(|id| self.sets.get(&id)) }
}

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

// ── Frame Graph Executor ──────────────────────────────────────────────────────

#[derive(Clone, Debug)]
pub struct FrameGraphExecutor {
    pub render_graph: RenderGraph,
    pub rt_manager: RenderTargetManager,
    pub frame: u64,
    pub paused: bool,
}

impl FrameGraphExecutor {
    pub fn new() -> Self { Self { render_graph: RenderGraph::new("frame"), rt_manager: RenderTargetManager::new(), frame: 0, paused: false } }
    pub fn begin_frame(&mut self) { if !self.paused { self.frame += 1; } }
    pub fn pause(&mut self) { self.paused = true; }
    pub fn resume(&mut self) { self.paused = false; }
    pub fn node_count(&self) -> usize { self.render_graph.node_count() }
    pub fn is_running(&self) -> bool { !self.paused }
    pub fn frame_number(&self) -> u64 { self.frame }
}

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

// ── Shader Compiler Statistics ────────────────────────────────────────────────

#[derive(Clone, Debug, Default)]
pub struct ShaderCompilerStats {
    pub total_programs: usize,
    pub total_materials: usize,
    pub total_textures: usize,
    pub total_buffers: usize,
    pub total_passes: usize,
    pub total_post_effects: usize,
    pub cache_entries: usize,
    pub cache_hit_rate: f32,
    pub total_compile_ms: f32,
    pub failed_compiles: u32,
    pub hot_reloads: u32,
}

impl ShaderCompilerStats {
    pub fn from_workspace(ws: &ShaderWorkspace) -> Self {
        Self {
            total_programs: ws.program_count(),
            total_materials: ws.material_count(),
            total_textures: ws.texture_count(),
            total_buffers: ws.buffer_count(),
            total_passes: ws.pipeline.pass_count(),
            total_post_effects: ws.post_process.effect_count(),
            cache_entries: ws.cache.size(),
            cache_hit_rate: ws.cache.hit_rate(),
            ..Default::default()
        }
    }
    pub fn summary(&self) -> String {
        format!("Programs:{} Materials:{} Textures:{} Buffers:{} Cache:{:.0}%", self.total_programs, self.total_materials, self.total_textures, self.total_buffers, self.cache_hit_rate * 100.0)
    }
}

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

pub const RENDER_TARGET_MAX: usize = 64;
pub const FRAME_GRAPH_MAX_NODES: usize = 128;
pub const RT_MAX_COLOR_ATTACHMENTS: usize = 8;
pub const RT_DEFAULT_MSAA: u32 = 1;
pub const SHADER_COMPILER_SESSION_MAX: usize = 4;

pub fn all_post_process_effect_names() -> &'static [&'static str] {
    &["Bloom", "Tone Mapping", "SSAO", "SSR", "TAA", "Depth of Field", "Volumetric Fog", "Lens Flare", "Motion Blur", "Vignette", "Chromatic Aberration", "Film Grain", "FXAA", "Color Grading", "SMAA"]
}

pub fn shader_compiler_comprehensive_info() -> String {
    format!(concat!(
        "ShaderCompilerEditor v{} Summary:\n",
        "  Modules: {}\n",
        "  Render API targets: {}\n",
        "  Quality presets: {}\n",
        "  Post-process effects: {}\n",
        "  Builtin GLSL snippets: {}\n",
        "  Builtin GLSL functions: {}\n"
    ),
    shader_system_version(),
    shader_module_count(),
    supported_render_apis().len(),
    RENDER_QUALITY_PRESET_COUNT,
    all_post_process_effect_names().len(),
    SHADER_BUILTIN_SNIPPETS,
    SHADER_GLSL_BUILTIN_FUNCTIONS)
}