codecraft 0.1.2

A minimalist 3D game engine built on parts of Bevy (ECS, color) with wgpu and winit: OpenPBR materials, clustered lighting, a yakui-drawn UI, audio and gamepad haptics; its binary maps any folder, and the symbols of its Rust files, as a 3D wall of boxes
Documentation
//! The OpenPBR Surface material model (MaterialX nodedef `ND_open_pbr_surface_surfaceshader` 1.1.1).
//! `surface.rs` is generated by `openpbr-gen`; only its `use crate::types` line is changed to `use super::types`.

pub mod energy;
pub mod gpu;
pub mod surface;
pub mod types;

pub use energy::EnergyTables;
pub use gpu::{Material, material_of, material_of_scaled};
pub use surface::{INPUTS, OpenPbrSurface};
pub use types::{Color3, InputError, InputSpec, Value, ValueType, Vector3};

use bevy_color::LinearRgba;
use glam::Vec3;

impl From<Color3> for LinearRgba {
    fn from(c: Color3) -> Self {
        LinearRgba::rgb(c.r, c.g, c.b)
    }
}

impl From<LinearRgba> for Color3 {
    fn from(c: LinearRgba) -> Self {
        Color3::new(c.red, c.green, c.blue)
    }
}

impl From<Color3> for Vec3 {
    fn from(c: Color3) -> Self {
        Vec3::new(c.r, c.g, c.b)
    }
}

impl From<Vector3> for Vec3 {
    fn from(v: Vector3) -> Self {
        Vec3::new(v.x, v.y, v.z)
    }
}

impl From<Vec3> for Vector3 {
    fn from(v: Vec3) -> Self {
        Vector3::new(v.x, v.y, v.z)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn a_new_surface_is_the_spec_default_not_zeroes() {
        let surface = OpenPbrSurface::default();
        assert_eq!(surface.base_weight, 1.0);
        assert_eq!(surface.base_color, Color3::new(0.8, 0.8, 0.8));
        assert_eq!(surface.specular_roughness, 0.3);
        assert_eq!(surface.specular_ior, 1.5);
        assert_eq!(surface.transmission_weight, 0.0);
        assert_eq!(surface.subsurface_weight, 0.0);
        assert_eq!(surface.fuzz_weight, 0.0);
        assert_eq!(surface.coat_weight, 0.0);
        assert_eq!(surface.thin_film_weight, 0.0);
        assert_eq!(surface.emission_luminance, 0.0);
    }

    #[test]
    fn every_input_is_reachable_by_name() {
        let surface = OpenPbrSurface::default();
        assert_eq!(INPUTS.len(), 41);
        for name in OpenPbrSurface::INPUT_NAMES {
            assert!(
                OpenPbrSurface::input_spec(name).is_some(),
                "{name} has no spec",
            );
            assert!(surface.get(name).is_ok(), "{name} cannot be read");
        }
    }

    #[test]
    fn a_colour_crosses_into_the_renderer_unchanged() {
        let linear: LinearRgba = Color3::new(0.25, 0.5, 0.75).into();
        assert_eq!(linear, LinearRgba::rgb(0.25, 0.5, 0.75));
        assert_eq!(Color3::from(linear), Color3::new(0.25, 0.5, 0.75));
    }

    #[test]
    fn setting_an_input_by_name_reaches_the_field() {
        let mut surface = OpenPbrSurface::default();
        surface.set_from_str("base_metalness", "1.0").unwrap();
        assert_eq!(surface.base_metalness, 1.0);
        assert!(!surface.is_default("base_metalness").unwrap());

        surface.reset("base_metalness").unwrap();
        assert_eq!(surface.base_metalness, 0.0);
        assert!(surface.changed_inputs().is_empty());
    }
}

/// The OpenPBR shading library as one WGSL program, in dependency order (no entry point).
/// A pass appends its own code, sets [`mat`](self) and calls `openpbr_prepare` then `openpbr_bsdf_evaluate`.
pub const SHADER: &str = concat!(
    include_str!("wgsl/material.wgsl"),
    "\n",
    include_str!("wgsl/common.wgsl"),
    "\n",
    include_str!("wgsl/fuzz_brdf.wgsl"),
    "\n",
    include_str!("wgsl/coat_brdf.wgsl"),
    "\n",
    include_str!("wgsl/thin_film.wgsl"),
    "\n",
    include_str!("wgsl/specular_brdf.wgsl"),
    "\n",
    include_str!("wgsl/specular_btdf.wgsl"),
    "\n",
    include_str!("wgsl/metal_brdf.wgsl"),
    "\n",
    include_str!("wgsl/diffuse.wgsl"),
    "\n",
    include_str!("wgsl/openpbr_surface.wgsl"),
);