#![allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum IblComponent {
Diffuse,
Specular,
Combined,
}
#[derive(Debug, Clone)]
pub struct IblContributionViewConfig {
pub component: IblComponent,
pub exposure: f32,
pub show_probe_coverage: bool,
}
impl Default for IblContributionViewConfig {
fn default() -> Self {
Self { component: IblComponent::Combined, exposure: 1.0, show_probe_coverage: false }
}
}
#[derive(Debug, Clone)]
pub struct IblContributionView {
pub config: IblContributionViewConfig,
pub enabled: bool,
}
impl Default for IblContributionView {
fn default() -> Self {
Self { config: IblContributionViewConfig::default(), enabled: false }
}
}
pub fn ibl_enable(view: &mut IblContributionView) {
view.enabled = true;
}
pub fn ibl_disable(view: &mut IblContributionView) {
view.enabled = false;
}
pub fn ibl_set_component(view: &mut IblContributionView, component: IblComponent) {
view.config.component = component;
}
pub fn ibl_set_exposure(view: &mut IblContributionView, ev: f32) {
view.config.exposure = ev.clamp(0.0, 32.0);
}
pub fn ibl_combine(diffuse: [f32; 3], specular: [f32; 3], config: &IblContributionViewConfig) -> [f32; 4] {
let e = config.exposure;
match config.component {
IblComponent::Diffuse => [diffuse[0] * e, diffuse[1] * e, diffuse[2] * e, 1.0],
IblComponent::Specular => [specular[0] * e, specular[1] * e, specular[2] * e, 1.0],
IblComponent::Combined => [
(diffuse[0] + specular[0]) * e,
(diffuse[1] + specular[1]) * e,
(diffuse[2] + specular[2]) * e,
1.0,
],
}
}
pub fn ibl_probe_coverage(u: f32, v: f32) -> f32 {
let u = u.clamp(0.0, 1.0);
let v = v.clamp(0.0, 1.0);
(u * v).sqrt()
}
pub fn ibl_to_json(view: &IblContributionView) -> String {
let comp = match view.config.component {
IblComponent::Diffuse => "diffuse",
IblComponent::Specular => "specular",
IblComponent::Combined => "combined",
};
format!(r#"{{"component":"{}","exposure":{:.2},"enabled":{}}}"#, comp, view.config.exposure, view.enabled)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_disabled() {
let v = IblContributionView::default();
assert!(!v.enabled);
}
#[test]
fn test_enable_disable() {
let mut v = IblContributionView::default();
ibl_enable(&mut v);
assert!(v.enabled);
ibl_disable(&mut v);
assert!(!v.enabled);
}
#[test]
fn test_set_component() {
let mut v = IblContributionView::default();
ibl_set_component(&mut v, IblComponent::Diffuse);
assert_eq!(v.config.component, IblComponent::Diffuse);
}
#[test]
fn test_set_exposure() {
let mut v = IblContributionView::default();
ibl_set_exposure(&mut v, 2.5);
assert!((v.config.exposure - 2.5).abs() < 1e-6);
}
#[test]
fn test_exposure_clamp() {
let mut v = IblContributionView::default();
ibl_set_exposure(&mut v, 9999.0);
assert!((v.config.exposure - 32.0).abs() < 1e-6);
}
#[test]
fn test_combine_diffuse_only() {
let cfg = IblContributionViewConfig { component: IblComponent::Diffuse, exposure: 1.0, show_probe_coverage: false };
let c = ibl_combine([0.5, 0.5, 0.5], [0.0, 0.0, 0.0], &cfg);
assert!((c[0] - 0.5).abs() < 1e-6);
}
#[test]
fn test_combine_alpha_one() {
let cfg = IblContributionViewConfig::default();
let c = ibl_combine([0.5; 3], [0.5; 3], &cfg);
assert!((c[3] - 1.0).abs() < 1e-6);
}
#[test]
fn test_probe_coverage_range() {
let cov = ibl_probe_coverage(0.5, 0.5);
assert!((0.0..=1.0).contains(&cov));
}
#[test]
fn test_to_json_component() {
let v = IblContributionView::default();
let json = ibl_to_json(&v);
assert!(json.contains("combined"));
}
}