From 83b75122eba9b8f4f408580a7bd439d5f75d0ef8 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 2 Sep 2025 14:58:29 +1200 Subject: [PATCH 01/31] move geometry descriptors into geometry module --- crates/example/src/lib.rs | 3 +- crates/renderling/src/atlas/cpu.rs | 2 +- crates/renderling/src/bvol.rs | 2 +- crates/renderling/src/cubemap/cpu.rs | 2 +- crates/renderling/src/geometry.rs | 175 +++++++++++++++++++++++- crates/renderling/src/geometry/cpu.rs | 11 +- crates/renderling/src/lib.rs | 48 +++++-- crates/renderling/src/light.rs | 2 +- crates/renderling/src/light/cpu/test.rs | 3 +- crates/renderling/src/pbr.rs | 2 +- crates/renderling/src/stage.rs | 173 +---------------------- crates/renderling/src/stage/cpu.rs | 11 +- crates/renderling/src/tutorial.rs | 4 +- crates/renderling/src/ui/cpu/path.rs | 5 +- crates/renderling/src/ui/cpu/text.rs | 6 +- 15 files changed, 237 insertions(+), 212 deletions(-) diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index 46784893..29b1872b 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -11,10 +11,11 @@ use renderling::{ atlas::AtlasImage, bvol::{Aabb, BoundingSphere}, camera::Camera, + geometry::Vertex, light::{AnalyticalLight, DirectionalLightDescriptor}, prelude::*, skybox::Skybox, - stage::{Animator, GltfDocument, Renderlet, Stage, Vertex}, + stage::{Animator, GltfDocument, Renderlet, Stage}, ui::{FontArc, Section, Text, Ui, UiPath, UiText}, Context, }; diff --git a/crates/renderling/src/atlas/cpu.rs b/crates/renderling/src/atlas/cpu.rs index 23a14c82..3c997ea6 100644 --- a/crates/renderling/src/atlas/cpu.rs +++ b/crates/renderling/src/atlas/cpu.rs @@ -937,9 +937,9 @@ mod test { use crate::{ atlas::{AtlasTexture, TextureAddressMode}, camera::Camera, + geometry::Vertex, material::Materials, pbr::Material, - stage::Vertex, test::BlockOnFuture, transform::Transform, Context, diff --git a/crates/renderling/src/bvol.rs b/crates/renderling/src/bvol.rs index e76345fc..193e34c7 100644 --- a/crates/renderling/src/bvol.rs +++ b/crates/renderling/src/bvol.rs @@ -595,7 +595,7 @@ impl BVol for Aabb { mod test { use glam::{Mat4, Quat}; - use crate::{pbr::Material, stage::Vertex, test::BlockOnFuture, Context}; + use crate::{geometry::Vertex, pbr::Material, test::BlockOnFuture, Context}; use super::*; diff --git a/crates/renderling/src/cubemap/cpu.rs b/crates/renderling/src/cubemap/cpu.rs index 663314aa..3f614050 100644 --- a/crates/renderling/src/cubemap/cpu.rs +++ b/crates/renderling/src/cubemap/cpu.rs @@ -270,8 +270,8 @@ mod test { use image::GenericImageView; use crate::{ + geometry::Vertex, math::{UNIT_INDICES, UNIT_POINTS}, - stage::Vertex, test::BlockOnFuture, texture::CopiedTextureBuffer, }; diff --git a/crates/renderling/src/geometry.rs b/crates/renderling/src/geometry.rs index 722e5d13..e6b59206 100644 --- a/crates/renderling/src/geometry.rs +++ b/crates/renderling/src/geometry.rs @@ -1,12 +1,183 @@ //! Holds geometry on CPU and GPU. -use crabslab::{Id, SlabItem}; +use crabslab::{Array, Id, Slab, SlabItem}; #[cfg(cpu)] mod cpu; #[cfg(cpu)] pub use cpu::*; +use glam::{Mat4, Vec2, Vec3, Vec4}; -use crate::camera::Camera; +use crate::{ + bvol::BoundingSphere, camera::Camera, math::IsVector, pbr::Material, transform::Transform, +}; + +/// A vertex skin. +/// +/// For more info on vertex skinning, see +/// +#[derive(Clone, Copy, Default, SlabItem)] +#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] +pub struct Skin { + // Ids of the skeleton nodes' global transforms used as joints in this skin. + pub joints: Array>, + // Contains the 4x4 inverse-bind matrices. + // + // When is none, each matrix is assumed to be the 4x4 identity matrix + // which implies that the inverse-bind matrices were pre-applied. + pub inverse_bind_matrices: Array, +} + +impl Skin { + pub fn get_joint_matrix(&self, i: usize, vertex: Vertex, slab: &[u32]) -> Mat4 { + let joint_index = vertex.joints[i] as usize; + let joint_id = slab.read(self.joints.at(joint_index)); + let joint_transform = slab.read(joint_id); + // First apply the inverse bind matrix to bring the vertex into the joint's + // local space, then apply the joint's current transformation to move it + // into world space. + let inverse_bind_matrix = slab.read(self.inverse_bind_matrices.at(joint_index)); + Mat4::from(joint_transform) * inverse_bind_matrix + } + + pub fn get_skinning_matrix(&self, vertex: Vertex, slab: &[u32]) -> Mat4 { + let mut skinning_matrix = Mat4::ZERO; + for i in 0..vertex.joints.len() { + let joint_matrix = self.get_joint_matrix(i, vertex, slab); + // Ensure weights are applied correctly to the joint matrix + let weight = vertex.weights[i]; + skinning_matrix += weight * joint_matrix; + } + + if skinning_matrix == Mat4::ZERO { + Mat4::IDENTITY + } else { + skinning_matrix + } + } +} + +/// A displacement target. +/// +/// Use to displace vertices using weights defined on the mesh. +/// +/// For more info on morph targets, see +/// +#[derive(Clone, Copy, Default, PartialEq, SlabItem)] +#[cfg_attr(cpu, derive(Debug))] +pub struct MorphTarget { + pub position: Vec3, + pub normal: Vec3, + pub tangent: Vec3, + // TODO: Extend MorphTargets to include UV and Color. + // I think this would take a contribution to the `gltf` crate. +} + +/// A vertex in a mesh. +#[derive(Clone, Copy, core::fmt::Debug, PartialEq, SlabItem)] +pub struct Vertex { + pub position: Vec3, + pub color: Vec4, + pub uv0: Vec2, + pub uv1: Vec2, + pub normal: Vec3, + pub tangent: Vec4, + // Indices that point to this vertex's 'joint' transforms. + pub joints: [u32; 4], + // The weights of influence that each joint has over this vertex + pub weights: [f32; 4], +} + +impl Default for Vertex { + fn default() -> Self { + Self { + position: Default::default(), + color: Vec4::ONE, + uv0: Vec2::ZERO, + uv1: Vec2::ZERO, + normal: Vec3::Z, + tangent: Vec4::Y, + joints: [0; 4], + weights: [0.0; 4], + } + } +} + +impl Vertex { + pub fn with_position(mut self, p: impl Into) -> Self { + self.position = p.into(); + self + } + + pub fn with_color(mut self, c: impl Into) -> Self { + self.color = c.into(); + self + } + + pub fn with_uv0(mut self, uv: impl Into) -> Self { + self.uv0 = uv.into(); + self + } + + pub fn with_uv1(mut self, uv: impl Into) -> Self { + self.uv1 = uv.into(); + self + } + + pub fn with_normal(mut self, n: impl Into) -> Self { + self.normal = n.into(); + self + } + + pub fn with_tangent(mut self, t: impl Into) -> Self { + self.tangent = t.into(); + self + } + + pub fn generate_normal(a: Vec3, b: Vec3, c: Vec3) -> Vec3 { + let ab = a - b; + let ac = a - c; + ab.cross(ac).normalize() + } + + pub fn generate_tangent(a: Vec3, a_uv: Vec2, b: Vec3, b_uv: Vec2, c: Vec3, c_uv: Vec2) -> Vec4 { + let ab = b - a; + let ac = c - a; + let n = ab.cross(ac); + let d_uv1 = b_uv - a_uv; + let d_uv2 = c_uv - a_uv; + let denom = d_uv1.x * d_uv2.y - d_uv2.x * d_uv1.y; + let denom_sign = if denom >= 0.0 { 1.0 } else { -1.0 }; + let denom = denom.abs().max(f32::EPSILON) * denom_sign; + let f = 1.0 / denom; + let s = f * Vec3::new( + d_uv2.y * ab.x - d_uv1.y * ac.x, + d_uv2.y * ab.y - d_uv1.y * ac.y, + d_uv2.y * ab.z - d_uv1.y * ac.z, + ); + let t = f * Vec3::new( + d_uv1.x * ac.x - d_uv2.x * ab.x, + d_uv1.x * ac.y - d_uv2.x * ab.y, + d_uv1.x * ac.z - d_uv2.x * ab.z, + ); + let n_cross_t_dot_s_sign = if n.cross(t).dot(s) >= 0.0 { 1.0 } else { -1.0 }; + (s - s.dot(n) * n) + .alt_norm_or_zero() + .extend(n_cross_t_dot_s_sign) + } + + #[cfg(cpu)] + /// A triangle list mesh of points. + pub fn cube_mesh() -> [Vertex; 36] { + let mut mesh = [Vertex::default(); 36]; + let unit_cube = crate::math::unit_cube(); + debug_assert_eq!(36, unit_cube.len()); + for (i, (position, normal)) in unit_cube.into_iter().enumerate() { + mesh[i].position = position; + mesh[i].normal = normal; + } + mesh + } +} /// Holds configuration info for vertex and shading render passes of /// geometry. diff --git a/crates/renderling/src/geometry/cpu.rs b/crates/renderling/src/geometry/cpu.rs index 0402c4aa..2b20d96b 100644 --- a/crates/renderling/src/geometry/cpu.rs +++ b/crates/renderling/src/geometry/cpu.rs @@ -13,13 +13,11 @@ use glam::{Mat4, UVec2}; use crate::{ camera::Camera, - geometry::GeometryDescriptor, + geometry::{GeometryDescriptor, MorphTarget, Skin, Vertex}, prelude::Transform, - stage::{MorphTarget, Renderlet, Skin, Vertex}, + stage::Renderlet, }; -// TODO: Move `Renderlet` to geometry. - /// Wrapper around the geometry slab, which holds mesh data and more. #[derive(Clone)] pub struct Geometry { @@ -45,7 +43,6 @@ impl AsRef> for Geometry { } impl Geometry { - // TODO: move atlas size into materials. pub fn new(runtime: impl AsRef, resolution: UVec2, atlas_size: UVec2) -> Self { let runtime = runtime.as_ref(); let slab = SlabAllocator::new(runtime, "geometry", wgpu::BufferUsages::empty()); @@ -98,12 +95,12 @@ impl Geometry { self.descriptor.modify(|cfg| cfg.camera_id = c.id()); } + /// Stage a new transform. pub fn new_transform(&self, transform: Transform) -> Hybrid { self.slab.new_value(transform) } /// Create new geometry data. - // TODO: Move `Vertex` to geometry. pub fn new_vertices(&self, data: impl IntoIterator) -> HybridArray { self.slab.new_array(data) } @@ -114,7 +111,6 @@ impl Geometry { } /// Create new morph targets. - // TODO: Move `MorphTarget` to geometry. pub fn new_morph_targets( &self, data: impl IntoIterator, @@ -150,7 +146,6 @@ impl Geometry { } /// Create a new skin. - // TODO: move `Skin` to geometry. pub fn new_skin(&self, skin: Skin) -> Hybrid { self.slab.new_value(skin) } diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index 0c7a9b91..fafcc99e 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -1,9 +1,15 @@ -//! A "GPU driven" renderer with a focus on simplicity and ease of use. -//! Backed by WebGPU. +//!
+//! renderling mascot +//!
//! -//! Shaders are written in Rust using [`rust-gpu`](https://rust-gpu.github.io/). +//! `renderling` is a "GPU driven" renderer with a focus on simplicity and ease +//! of use, targeting WebGPU. //! -//! All data is staged on the GPU using a [slab allocator](https://crates.io/crates/craballoc). +//! Shaders are written in Rust using [`rust-gpu`](https://rust-gpu.github.io/). //! //! ## Hello triangle //! @@ -13,7 +19,8 @@ //! ### Context creation //! //! First you must create a [`Context`]. -//! The `Context` holds the render target - either a window or a texture. +//! The `Context` holds the render target - either a native window, an HTML +//! canvas or a texture. //! //! ``` //! use renderling::prelude::*; @@ -24,6 +31,15 @@ //! //! [`Context::headless`] creates a `Context` that renders to a texture. //! +//! [`Context::from_winit_window`] creates a `Context` that renders to a native +//! window. +//! +//! [`Context::try_new_with_surface`] creates a `Context` that renders to any +//! [`wgpu::SurfaceTarget`]. +//! +//! See the [`renderling::context`](context) module documentation for +//! more info. +//! //! ### Staging //! //! We then create a "stage" to place the camera, geometry, materials and lights. @@ -43,11 +59,15 @@ //! synchronization will happen during //! [`Stage::render`](crate::stage::Stage::render). //! -//! When "staging" some data, you receive [`Hybrid`](crate::prelude::Hybrid)s and -//! [`HybridArray`](crate::prelude::HybridArray)s in return. +//! Use one of the many `Stage::new_*` functions to stage data on the GPU: +//! * [`Stage::new_camera`] +//! * [`Stage::new_vertices`] +//! * [`Stage::new_material`] +//! * [`Stage::new_renderlet`] +//! * ...and more //! -//! These types come from the [`craballoc`] library, which is re-exported -//! from [the prelude](crate::prelude). +//! Many of these functions return [`Hybrid`](crate::prelude::Hybrid)s or +//! [`HybridArray`](crate::prelude::HybridArray)s in return. //! //! In order to render, we need to "stage" a //! [`Renderlet`](crate::stage::Renderlet), which is a bundle of rendering @@ -152,7 +172,7 @@ pub mod bvol; pub mod camera; pub mod color; #[cfg(cpu)] -mod context; +pub mod context; pub mod convolution; pub mod cubemap; pub mod cull; @@ -187,15 +207,15 @@ pub use context::*; pub mod prelude { //! A prelude, meant to be glob-imported. - #[cfg(cpu)] - pub extern crate craballoc; pub extern crate glam; #[cfg(cpu)] pub use craballoc::prelude::*; pub use crabslab::{Array, Id}; - pub use crate::{camera::*, light::*, pbr::Material, stage::*, transform::Transform}; + pub use crate::{ + camera::*, geometry::*, light::*, pbr::Material, stage::*, transform::Transform, + }; #[cfg(cpu)] pub use crate::context::*; @@ -216,7 +236,7 @@ macro_rules! println { mod test { use super::*; use crate::{ - atlas::AtlasImage, camera::Camera, pbr::Material, stage::Vertex, transform::Transform, + atlas::AtlasImage, camera::Camera, geometry::Vertex, pbr::Material, transform::Transform, }; use glam::{Mat3, Mat4, Quat, UVec2, Vec2, Vec3, Vec4}; diff --git a/crates/renderling/src/light.rs b/crates/renderling/src/light.rs index 694902e2..da33516e 100644 --- a/crates/renderling/src/light.rs +++ b/crates/renderling/src/light.rs @@ -92,7 +92,7 @@ impl Default for ShadowMapDescriptor { pub struct ShadowMappingVertexInfo { pub renderlet_id: Id, pub vertex_index: u32, - pub vertex: crate::stage::Vertex, + pub vertex: crate::geometry::Vertex, pub transform: Transform, pub model_matrix: Mat4, pub world_pos: Vec3, diff --git a/crates/renderling/src/light/cpu/test.rs b/crates/renderling/src/light/cpu/test.rs index 76a2fb44..9b56c173 100644 --- a/crates/renderling/src/light/cpu/test.rs +++ b/crates/renderling/src/light/cpu/test.rs @@ -13,7 +13,8 @@ use crate::{ math::GpuRng, pbr::Material, prelude::Transform, - stage::{Renderlet, RenderletPbrVertexInfo, Stage, Vertex}, test::BlockOnFuture, + geometry::Vertex, + stage::{Renderlet, RenderletPbrVertexInfo, Stage}, test::BlockOnFuture, }; use super::*; diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index 26d6d038..2664a42f 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -717,9 +717,9 @@ mod test { use crate::{ atlas::AtlasImage, camera::Camera, + geometry::Vertex, pbr::Material, prelude::glam::{Vec3, Vec4}, - stage::Vertex, test::BlockOnFuture, transform::Transform, }; diff --git a/crates/renderling/src/stage.rs b/crates/renderling/src/stage.rs index a47e897e..0145072b 100644 --- a/crates/renderling/src/stage.rs +++ b/crates/renderling/src/stage.rs @@ -12,7 +12,10 @@ use spirv_std::{ }; use crate::{ - bvol::BoundingSphere, geometry::GeometryDescriptor, math::IsVector, pbr::Material, + bvol::BoundingSphere, + geometry::{GeometryDescriptor, MorphTarget, Skin, Vertex}, + math::IsVector, + pbr::Material, transform::Transform, }; @@ -29,67 +32,6 @@ mod gltf_support; #[cfg(all(feature = "gltf", not(target_arch = "spirv")))] pub use gltf_support::*; -/// A vertex skin. -/// -/// For more info on vertex skinning, see -/// -#[derive(Clone, Copy, Default, SlabItem)] -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -pub struct Skin { - // Ids of the skeleton nodes' global transforms used as joints in this skin. - pub joints: Array>, - // Contains the 4x4 inverse-bind matrices. - // - // When is none, each matrix is assumed to be the 4x4 identity matrix - // which implies that the inverse-bind matrices were pre-applied. - pub inverse_bind_matrices: Array, -} - -impl Skin { - pub fn get_joint_matrix(&self, i: usize, vertex: Vertex, slab: &[u32]) -> Mat4 { - let joint_index = vertex.joints[i] as usize; - let joint_id = slab.read(self.joints.at(joint_index)); - let joint_transform = slab.read(joint_id); - // First apply the inverse bind matrix to bring the vertex into the joint's - // local space, then apply the joint's current transformation to move it - // into world space. - let inverse_bind_matrix = slab.read(self.inverse_bind_matrices.at(joint_index)); - Mat4::from(joint_transform) * inverse_bind_matrix - } - - pub fn get_skinning_matrix(&self, vertex: Vertex, slab: &[u32]) -> Mat4 { - let mut skinning_matrix = Mat4::ZERO; - for i in 0..vertex.joints.len() { - let joint_matrix = self.get_joint_matrix(i, vertex, slab); - // Ensure weights are applied correctly to the joint matrix - let weight = vertex.weights[i]; - skinning_matrix += weight * joint_matrix; - } - - if skinning_matrix == Mat4::ZERO { - Mat4::IDENTITY - } else { - skinning_matrix - } - } -} - -/// A displacement target. -/// -/// Use to displace vertices using weights defined on the mesh. -/// -/// For more info on morph targets, see -/// -#[derive(Clone, Copy, Default, PartialEq, SlabItem)] -#[cfg_attr(cpu, derive(Debug))] -pub struct MorphTarget { - pub position: Vec3, - pub normal: Vec3, - pub tangent: Vec3, - // TODO: Extend MorphTargets to include UV and Color. - // I think this would take a contribution to the `gltf` crate. -} - /// Returned by [`Renderlet::get_vertex_info`]. pub struct VertexInfo { pub vertex: Vertex, @@ -98,113 +40,6 @@ pub struct VertexInfo { pub world_pos: Vec3, } -/// A vertex in a mesh. -#[derive(Clone, Copy, core::fmt::Debug, PartialEq, SlabItem)] -pub struct Vertex { - pub position: Vec3, - pub color: Vec4, - pub uv0: Vec2, - pub uv1: Vec2, - pub normal: Vec3, - pub tangent: Vec4, - // Indices that point to this vertex's 'joint' transforms. - pub joints: [u32; 4], - // The weights of influence that each joint has over this vertex - pub weights: [f32; 4], -} - -impl Default for Vertex { - fn default() -> Self { - Self { - position: Default::default(), - color: Vec4::ONE, - uv0: Vec2::ZERO, - uv1: Vec2::ZERO, - normal: Vec3::Z, - tangent: Vec4::Y, - joints: [0; 4], - weights: [0.0; 4], - } - } -} - -impl Vertex { - pub fn with_position(mut self, p: impl Into) -> Self { - self.position = p.into(); - self - } - - pub fn with_color(mut self, c: impl Into) -> Self { - self.color = c.into(); - self - } - - pub fn with_uv0(mut self, uv: impl Into) -> Self { - self.uv0 = uv.into(); - self - } - - pub fn with_uv1(mut self, uv: impl Into) -> Self { - self.uv1 = uv.into(); - self - } - - pub fn with_normal(mut self, n: impl Into) -> Self { - self.normal = n.into(); - self - } - - pub fn with_tangent(mut self, t: impl Into) -> Self { - self.tangent = t.into(); - self - } - - pub fn generate_normal(a: Vec3, b: Vec3, c: Vec3) -> Vec3 { - let ab = a - b; - let ac = a - c; - ab.cross(ac).normalize() - } - - pub fn generate_tangent(a: Vec3, a_uv: Vec2, b: Vec3, b_uv: Vec2, c: Vec3, c_uv: Vec2) -> Vec4 { - let ab = b - a; - let ac = c - a; - let n = ab.cross(ac); - let d_uv1 = b_uv - a_uv; - let d_uv2 = c_uv - a_uv; - let denom = d_uv1.x * d_uv2.y - d_uv2.x * d_uv1.y; - let denom_sign = if denom >= 0.0 { 1.0 } else { -1.0 }; - let denom = denom.abs().max(f32::EPSILON) * denom_sign; - let f = 1.0 / denom; - let s = f * Vec3::new( - d_uv2.y * ab.x - d_uv1.y * ac.x, - d_uv2.y * ab.y - d_uv1.y * ac.y, - d_uv2.y * ab.z - d_uv1.y * ac.z, - ); - let t = f * Vec3::new( - d_uv1.x * ac.x - d_uv2.x * ab.x, - d_uv1.x * ac.y - d_uv2.x * ab.y, - d_uv1.x * ac.z - d_uv2.x * ab.z, - ); - let n_cross_t_dot_s_sign = if n.cross(t).dot(s) >= 0.0 { 1.0 } else { -1.0 }; - (s - s.dot(n) * n) - .alt_norm_or_zero() - .extend(n_cross_t_dot_s_sign) - } - - #[cfg(cpu)] - /// A triangle list mesh of points. - pub fn cube_mesh() -> [Vertex; 36] { - let mut mesh = [Vertex::default(); 36]; - let unit_cube = crate::math::unit_cube(); - debug_assert_eq!(36, unit_cube.len()); - for (i, (position, normal)) in unit_cube.into_iter().enumerate() { - mesh[i].position = position; - mesh[i].normal = normal; - } - mesh - } -} - /// A draw call used to render some geometry. /// /// ## Note diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index a0eadfa9..01f96ae3 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -1,6 +1,15 @@ //! GPU staging area. //! -//! The `Stage` object contains a slab buffer and a render pipeline. +//! The [`Stage`] object is used to "stage" objects on the GPU, including +//! mesh geometry, transforms, materials and lights. +//! +//! [`Stage`] also controls various effects: +//! * [`Skybox`] +//! - [`Stage::with_skybox`] +//! - [`Stage::set_skybox`] +//! * [`Bloom`] +//! * [`Tonemapping`]. +//! //! It is used to stage [`Renderlet`]s for rendering. use core::ops::Deref; use core::sync::atomic::{AtomicU32, AtomicUsize, Ordering}; diff --git a/crates/renderling/src/tutorial.rs b/crates/renderling/src/tutorial.rs index c8707b58..e7f7ac34 100644 --- a/crates/renderling/src/tutorial.rs +++ b/crates/renderling/src/tutorial.rs @@ -5,8 +5,8 @@ use glam::{Vec3, Vec3Swizzles, Vec4}; use spirv_std::spirv; use crate::{ - geometry::GeometryDescriptor, - stage::{Renderlet, Vertex, VertexInfo}, + geometry::{GeometryDescriptor, Vertex}, + stage::{Renderlet, VertexInfo}, }; /// Simple fragment shader that writes the input color to the output color. diff --git a/crates/renderling/src/ui/cpu/path.rs b/crates/renderling/src/ui/cpu/path.rs index 1d610b05..d14867d6 100644 --- a/crates/renderling/src/ui/cpu/path.rs +++ b/crates/renderling/src/ui/cpu/path.rs @@ -1,10 +1,7 @@ //! Path and builder. //! //! Path colors are sRGB. -use crate::{ - pbr::Material, - stage::{Renderlet, Vertex}, -}; +use crate::{geometry::Vertex, pbr::Material, stage::Renderlet}; use craballoc::prelude::{GpuArray, Hybrid}; use crabslab::Id; use glam::{Vec2, Vec3, Vec3Swizzles, Vec4}; diff --git a/crates/renderling/src/ui/cpu/text.rs b/crates/renderling/src/ui/cpu/text.rs index fa2325cd..8f6ac457 100644 --- a/crates/renderling/src/ui/cpu/text.rs +++ b/crates/renderling/src/ui/cpu/text.rs @@ -15,11 +15,7 @@ use glyph_brush::*; pub use ab_glyph::FontArc; pub use glyph_brush::{Section, Text}; -use crate::{ - atlas::AtlasTexture, - pbr::Material, - stage::{Renderlet, Vertex}, -}; +use crate::{atlas::AtlasTexture, geometry::Vertex, pbr::Material, stage::Renderlet}; use image::{DynamicImage, GenericImage, ImageBuffer, Luma, Rgba}; use super::{Ui, UiTransform}; From 5822d1da677303268af0ff8a5c2b2fdd71d3a285 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Wed, 3 Sep 2025 10:39:30 +1200 Subject: [PATCH 02/31] transform rework WIP, move Materials into materials mod --- crates/example-culling/src/main.rs | 6 +- crates/example/src/lib.rs | 4 +- crates/renderling/src/atlas/cpu.rs | 15 ++-- crates/renderling/src/bvol.rs | 10 +-- crates/renderling/src/cull.rs | 4 +- crates/renderling/src/cull/cpu.rs | 14 ++-- crates/renderling/src/debug.rs | 13 +-- crates/renderling/src/draw/cpu.rs | 18 ++-- crates/renderling/src/geometry.rs | 6 +- crates/renderling/src/geometry/cpu.rs | 12 +-- crates/renderling/src/lib.rs | 32 ++++---- crates/renderling/src/light.rs | 14 ++-- crates/renderling/src/light/cpu.rs | 10 +-- crates/renderling/src/light/cpu/test.rs | 14 ++-- crates/renderling/src/light/shadow_map.rs | 4 +- crates/renderling/src/material.rs | 54 ++++++++++++ crates/renderling/src/material/cpu.rs | 2 +- crates/renderling/src/pbr.rs | 62 ++------------ crates/renderling/src/stage.rs | 48 +++++------ crates/renderling/src/stage/cpu.rs | 91 +++++++++++++-------- crates/renderling/src/stage/gltf_support.rs | 26 +++--- crates/renderling/src/transform.rs | 34 ++++---- crates/renderling/src/transform/cpu.rs | 18 ++++ crates/renderling/src/tutorial.rs | 4 +- crates/renderling/src/ui/cpu.rs | 10 +-- crates/renderling/src/ui/cpu/path.rs | 4 +- crates/renderling/src/ui/cpu/text.rs | 6 +- 27 files changed, 293 insertions(+), 242 deletions(-) create mode 100644 crates/renderling/src/transform/cpu.rs diff --git a/crates/example-culling/src/main.rs b/crates/example-culling/src/main.rs index 42eaef78..2ed9d6ed 100644 --- a/crates/example-culling/src/main.rs +++ b/crates/example-culling/src/main.rs @@ -39,7 +39,7 @@ struct CullingExample { material_frustum: Hybrid, frustum_camera: FrustumCamera, frustum_vertices: HybridArray, - frustum_renderlet: Hybrid, + frustum_renderlet: Hybrid, resources: BagOfResources, next_k: u64, } @@ -80,7 +80,7 @@ impl CullingExample { let center = Vec3::new(x, y, z); let half_size = Vec3::new(w, h, l); let aabb = Self::make_aabb(Vec3::ZERO, half_size); - let aabb_transform = Transform { + let aabb_transform = TransformDescriptor { translation: center, rotation, ..Default::default() @@ -248,7 +248,7 @@ impl TestAppHandler for CullingExample { ..Default::default() }, )); - let frustum_renderlet = stage.new_renderlet(Renderlet { + let frustum_renderlet = stage.new_renderlet(RenderletDescriptor { vertices_array: frustum_vertices.array(), material_id: material_frustum.id(), ..Default::default() diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index 29b1872b..38ee987d 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -15,7 +15,7 @@ use renderling::{ light::{AnalyticalLight, DirectionalLightDescriptor}, prelude::*, skybox::Skybox, - stage::{Animator, GltfDocument, Renderlet, Stage}, + stage::{Animator, GltfDocument, RenderletDescriptor, Stage}, ui::{FontArc, Section, Text, Ui, UiPath, UiText}, Context, }; @@ -116,7 +116,7 @@ impl AppUi { #[allow(dead_code)] pub struct DefaultModel { vertices: GpuArray, - renderlet: Hybrid, + renderlet: Hybrid, } pub enum Model { diff --git a/crates/renderling/src/atlas/cpu.rs b/crates/renderling/src/atlas/cpu.rs index 3c997ea6..4c6b3145 100644 --- a/crates/renderling/src/atlas/cpu.rs +++ b/crates/renderling/src/atlas/cpu.rs @@ -938,10 +938,9 @@ mod test { atlas::{AtlasTexture, TextureAddressMode}, camera::Camera, geometry::Vertex, - material::Materials, - pbr::Material, + material::{Material, Materials}, test::BlockOnFuture, - transform::Transform, + transform::TransformDescriptor, Context, }; use glam::{UVec3, Vec2, Vec3, Vec4}; @@ -992,7 +991,7 @@ mod test { .with_uv0(Vec2::splat(1.0)); [tl, bl, br, tl, br, tr] }) - .with_transform(Transform { + .with_transform(TransformDescriptor { scale: Vec3::new(32.0, 32.0, 1.0), ..Default::default() }) @@ -1063,7 +1062,7 @@ mod test { let _repeat_rez = stage .builder() - .with_transform(Transform { + .with_transform(TransformDescriptor { translation: Vec3::new(sheet_w + 1.0, 0.0, 0.0), ..Default::default() }) @@ -1077,7 +1076,7 @@ mod test { let _mirror_rez = stage .builder() - .with_transform(Transform { + .with_transform(TransformDescriptor { translation: Vec3::new(sheet_w * 2.0 + 2.0, 0.0, 0.0), ..Default::default() }) @@ -1161,7 +1160,7 @@ mod test { has_lighting: false, ..Default::default() }) - .with_transform(Transform { + .with_transform(TransformDescriptor { translation: Vec3::new(sheet_w + 1.0, 0.0, 0.0), ..Default::default() }) @@ -1175,7 +1174,7 @@ mod test { has_lighting: false, ..Default::default() }) - .with_transform(Transform { + .with_transform(TransformDescriptor { translation: Vec3::new(sheet_w * 2.0 + 2.0, 0.0, 0.0), ..Default::default() }) diff --git a/crates/renderling/src/bvol.rs b/crates/renderling/src/bvol.rs index 193e34c7..c1fbf5f1 100644 --- a/crates/renderling/src/bvol.rs +++ b/crates/renderling/src/bvol.rs @@ -16,7 +16,7 @@ use glam::{Mat4, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles}; #[cfg(gpu)] use spirv_std::num_traits::Float; -use crate::{camera::Camera, transform::Transform}; +use crate::{camera::Camera, transform::TransformDescriptor}; /// Normalize a plane. pub fn normalize_plane(mut plane: Vec4) -> Vec4 { @@ -151,7 +151,7 @@ impl Aabb { /// Determines whether this `Aabb` can be seen by `camera` after being /// transformed by `transform`. - pub fn is_outside_camera_view(&self, camera: &Camera, transform: Transform) -> bool { + pub fn is_outside_camera_view(&self, camera: &Camera, transform: TransformDescriptor) -> bool { let transform = Mat4::from(transform); let min = transform.transform_point3(self.min); let max = transform.transform_point3(self.max); @@ -463,7 +463,7 @@ impl BoundingSphere { pub fn is_inside_camera_view( &self, camera: &Camera, - transform: Transform, + transform: TransformDescriptor, ) -> (bool, BoundingSphere) { let center = Mat4::from(transform).transform_point3(self.center); let scale = Vec3::splat(transform.scale.max_element()); @@ -595,7 +595,7 @@ impl BVol for Aabb { mod test { use glam::{Mat4, Quat}; - use crate::{geometry::Vertex, pbr::Material, test::BlockOnFuture, Context}; + use crate::{geometry::Vertex, material::Material, test::BlockOnFuture, Context}; use super::*; @@ -636,7 +636,7 @@ mod test { min: Vec3::new(-3.2869213, -3.0652206, -3.8715153), max: Vec3::new(3.2869213, 3.0652206, 3.8715153), }; - let transform = Transform { + let transform = TransformDescriptor { translation: Vec3::new(7.5131035, -9.947085, -5.001645), rotation: Quat::from_xyzw(0.4700742, 0.34307128, 0.6853008, -0.43783003), scale: Vec3::new(1.0, 1.0, 1.0), diff --git a/crates/renderling/src/cull.rs b/crates/renderling/src/cull.rs index 58868778..74fc0b61 100644 --- a/crates/renderling/src/cull.rs +++ b/crates/renderling/src/cull.rs @@ -12,7 +12,7 @@ use spirv_std::{ spirv, }; -use crate::{draw::DrawIndirectArgs, geometry::GeometryDescriptor, stage::Renderlet}; +use crate::{draw::DrawIndirectArgs, geometry::GeometryDescriptor, stage::RenderletDescriptor}; #[cfg(not(target_arch = "spirv"))] mod cpu; @@ -35,7 +35,7 @@ pub fn compute_culling( // Get the draw arg let arg = unsafe { args.index_unchecked_mut(gid) }; // Get the renderlet using the draw arg's renderlet id - let renderlet_id = Id::::new(arg.first_instance); + let renderlet_id = Id::::new(arg.first_instance); let renderlet = stage_slab.read_unchecked(renderlet_id); crate::println!("renderlet: {renderlet_id:?}"); diff --git a/crates/renderling/src/cull/cpu.rs b/crates/renderling/src/cull/cpu.rs index 5accb2bd..8a93be6f 100644 --- a/crates/renderling/src/cull/cpu.rs +++ b/crates/renderling/src/cull/cpu.rs @@ -691,7 +691,7 @@ mod test { let _rez = stage .builder() .with_vertices(crate::test::gpu_cube_vertices()) - .with_transform(Transform { + .with_transform(TransformDescriptor { scale: Vec3::new(6.0, 6.0, 6.0), rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), ..Default::default() @@ -802,7 +802,7 @@ mod test { }; // A hashmap to hold renderlet ids to their names. - let mut names = HashMap::, String>::default(); + let mut names = HashMap::, String>::default(); // Add four yellow cubes in each corner let _ycubes = [ @@ -815,7 +815,7 @@ mod test { let yellow = hex_to_vec4(0xFFE6A5FF); let (transform, vertices, renderlet) = stage .builder() - .with_transform(Transform { + .with_transform(TransformDescriptor { // move it back behind the purple cube translation: (offset * 10.0).extend(-20.0), // scale it up since it's a unit cube @@ -841,7 +841,7 @@ mod test { let golden = hex_to_vec4(0xFFBF61FF); let (transform, vertices, renderlet) = stage .builder() - .with_transform(Transform { + .with_transform(TransformDescriptor { // flip it so it's facing up, like a floor should be rotation: Quat::from_rotation_x(std::f32::consts::FRAC_PI_2), // move it down and back a bit @@ -866,7 +866,7 @@ mod test { let green = hex_to_vec4(0x8ABFA3FF); let (transform, vertices, renderlet) = stage .builder() - .with_transform(Transform { + .with_transform(TransformDescriptor { // move it back behind the purple cube translation: Vec3::new(0.0, 0.0, -10.0), // scale it up since it's a unit cube @@ -893,7 +893,7 @@ mod test { let purple = hex_to_vec4(0x605678FF); let (transform, vertices, renderlet) = stage .builder() - .with_transform(Transform { + .with_transform(TransformDescriptor { // move it back a bit translation: Vec3::new(0.0, 0.0, -3.0), // scale it up since it's a unit cube @@ -977,7 +977,7 @@ mod test { } for i in 0..num_draw_calls as u32 { - let renderlet_id = Id::::new(args[i as usize].first_instance); + let renderlet_id = Id::::new(args[i as usize].first_instance); let name = names.get(&renderlet_id).unwrap(); if name != "green_cube" { continue; diff --git a/crates/renderling/src/debug.rs b/crates/renderling/src/debug.rs index 7eb5ca90..bd7a1b9f 100644 --- a/crates/renderling/src/debug.rs +++ b/crates/renderling/src/debug.rs @@ -4,8 +4,8 @@ use glam::{Vec2, Vec3Swizzles, Vec4, Vec4Swizzles}; use spirv_std::{arch::IndexUnchecked, spirv}; use crate::{ - draw::DrawIndirectArgs, geometry::GeometryDescriptor, sdf, stage::Renderlet, - transform::Transform, + draw::DrawIndirectArgs, geometry::GeometryDescriptor, sdf, stage::RenderletDescriptor, + transform::TransformDescriptor, }; #[cfg(not(target_arch = "spirv"))] @@ -42,11 +42,12 @@ pub fn debug_overlay_fragment( for i in 0..draw_calls.len() { let draw_call = unsafe { draw_calls.index_unchecked(i) }; - let renderlet_id = Id::::new(draw_call.first_instance); - let transform_id = slab.read_unchecked(renderlet_id + Renderlet::OFFSET_OF_TRANSFORM_ID); - let mut model = Transform::IDENTITY; + let renderlet_id = Id::::new(draw_call.first_instance); + let transform_id = + slab.read_unchecked(renderlet_id + RenderletDescriptor::OFFSET_OF_TRANSFORM_ID); + let mut model = TransformDescriptor::IDENTITY; slab.read_into_if_some(transform_id, &mut model); - let bounds = slab.read_unchecked(renderlet_id + Renderlet::OFFSET_OF_BOUNDS); + let bounds = slab.read_unchecked(renderlet_id + RenderletDescriptor::OFFSET_OF_BOUNDS); let (_, sphere_in_world_coords) = bounds.is_inside_camera_view(&camera, model); let sphere_aabb = sphere_in_world_coords.project_onto_viewport( diff --git a/crates/renderling/src/draw/cpu.rs b/crates/renderling/src/draw/cpu.rs index 2ffafe0a..a5f6e608 100644 --- a/crates/renderling/src/draw/cpu.rs +++ b/crates/renderling/src/draw/cpu.rs @@ -9,7 +9,7 @@ use rustc_hash::FxHashMap; use crate::{ cull::{ComputeCulling, CullingError}, - stage::Renderlet, + stage::RenderletDescriptor, texture::Texture, Context, }; @@ -19,7 +19,7 @@ use super::DrawIndirectArgs; /// Used to track renderlets internally. #[repr(transparent)] struct InternalRenderlet { - inner: WeakHybrid, + inner: WeakHybrid, } impl InternalRenderlet { @@ -27,7 +27,7 @@ impl InternalRenderlet { self.inner.strong_count() > 0 } - fn from_hybrid_renderlet(hr: &Hybrid) -> Self { + fn from_hybrid_renderlet(hr: &Hybrid) -> Self { Self { inner: WeakHybrid::from_hybrid(hr), } @@ -113,8 +113,8 @@ impl IndirectDraws { } } -impl From> for DrawIndirectArgs { - fn from(id: Id) -> Self { +impl From> for DrawIndirectArgs { + fn from(id: Id) -> Self { // This is obviously incomplete, but that's ok because // the rest of this struct is filled out on the GPU during // culling. @@ -205,7 +205,7 @@ impl DrawCalls { /// Add a renderlet to the drawing queue. /// /// Returns the number of draw calls in the queue. - pub fn add_renderlet(&mut self, renderlet: &Hybrid) -> usize { + pub fn add_renderlet(&mut self, renderlet: &Hybrid) -> usize { log::trace!("adding renderlet {:?}", renderlet.id()); if let Some(indirect) = &mut self.drawing_strategy.indirect { indirect.invalidate(); @@ -219,7 +219,7 @@ impl DrawCalls { /// drawn each frame. /// /// Returns the number of draw calls remaining in the queue. - pub fn remove_renderlet(&mut self, renderlet: &Hybrid) -> usize { + pub fn remove_renderlet(&mut self, renderlet: &Hybrid) -> usize { let id = renderlet.id(); self.internal_renderlets.retain(|ir| ir.inner.id() != id); @@ -237,7 +237,7 @@ impl DrawCalls { /// If the `order` iterator is missing any renderlet ids, those missing /// renderlets will be drawn _before_ the ordered ones, in no particular /// order. - pub fn reorder_renderlets(&mut self, order: impl IntoIterator>) { + pub fn reorder_renderlets(&mut self, order: impl IntoIterator>) { let mut ordered = vec![]; let mut m = FxHashMap::from_iter( std::mem::take(&mut self.internal_renderlets) @@ -257,7 +257,7 @@ impl DrawCalls { } /// Iterator over all staged [`Renderlet`]s. - pub fn renderlets_iter(&self) -> impl Iterator> + '_ { + pub fn renderlets_iter(&self) -> impl Iterator> + '_ { self.internal_renderlets.iter().map(|ir| ir.inner.clone()) } /// diff --git a/crates/renderling/src/geometry.rs b/crates/renderling/src/geometry.rs index e6b59206..c2eb93af 100644 --- a/crates/renderling/src/geometry.rs +++ b/crates/renderling/src/geometry.rs @@ -7,9 +7,7 @@ mod cpu; pub use cpu::*; use glam::{Mat4, Vec2, Vec3, Vec4}; -use crate::{ - bvol::BoundingSphere, camera::Camera, math::IsVector, pbr::Material, transform::Transform, -}; +use crate::{camera::Camera, math::IsVector, transform::TransformDescriptor}; /// A vertex skin. /// @@ -19,7 +17,7 @@ use crate::{ #[cfg_attr(not(target_arch = "spirv"), derive(Debug))] pub struct Skin { // Ids of the skeleton nodes' global transforms used as joints in this skin. - pub joints: Array>, + pub joints: Array>, // Contains the 4x4 inverse-bind matrices. // // When is none, each matrix is assumed to be the 4x4 identity matrix diff --git a/crates/renderling/src/geometry/cpu.rs b/crates/renderling/src/geometry/cpu.rs index 2b20d96b..7cee5b09 100644 --- a/crates/renderling/src/geometry/cpu.rs +++ b/crates/renderling/src/geometry/cpu.rs @@ -14,8 +14,8 @@ use glam::{Mat4, UVec2}; use crate::{ camera::Camera, geometry::{GeometryDescriptor, MorphTarget, Skin, Vertex}, - prelude::Transform, - stage::Renderlet, + prelude::TransformDescriptor, + stage::RenderletDescriptor, }; /// Wrapper around the geometry slab, which holds mesh data and more. @@ -96,7 +96,7 @@ impl Geometry { } /// Stage a new transform. - pub fn new_transform(&self, transform: Transform) -> Hybrid { + pub fn new_transform(&self, transform: TransformDescriptor) -> Hybrid { self.slab.new_value(transform) } @@ -135,8 +135,8 @@ impl Geometry { /// Create a new array of joint transform ids that each point to a [`Transform`]. pub fn new_joint_transform_ids( &self, - data: impl IntoIterator>, - ) -> HybridArray> { + data: impl IntoIterator>, + ) -> HybridArray> { self.slab.new_array(data) } @@ -150,7 +150,7 @@ impl Geometry { self.slab.new_value(skin) } - pub fn new_renderlet(&self, renderlet: Renderlet) -> Hybrid { + pub fn new_renderlet(&self, renderlet: RenderletDescriptor) -> Hybrid { self.slab.new_value(renderlet) } } diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index fafcc99e..692ccf59 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -214,7 +214,8 @@ pub mod prelude { pub use crabslab::{Array, Id}; pub use crate::{ - camera::*, geometry::*, light::*, pbr::Material, stage::*, transform::Transform, + camera::*, geometry::*, light::*, material::Material, stage::*, + transform::TransformDescriptor, }; #[cfg(cpu)] @@ -236,7 +237,8 @@ macro_rules! println { mod test { use super::*; use crate::{ - atlas::AtlasImage, camera::Camera, geometry::Vertex, pbr::Material, transform::Transform, + atlas::AtlasImage, camera::Camera, geometry::Vertex, material::Material, + transform::TransformDescriptor, }; use glam::{Mat3, Mat4, Quat, UVec2, Vec2, Vec3, Vec4}; @@ -451,13 +453,13 @@ mod test { let (_vertices, transform, _renderlet) = stage .builder() .with_vertices(right_tri_vertices()) - .with_transform(Transform::default()) + .with_transform(TransformDescriptor::default()) .build(); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); - transform.set(Transform { + transform.set(TransformDescriptor { translation: Vec3::new(100.0, 0.0, 0.0), rotation: Quat::from_axis_angle(Vec3::Z, std::f32::consts::FRAC_PI_2), scale: Vec3::new(0.5, 0.5, 1.0), @@ -520,7 +522,7 @@ mod test { let _rez = stage .builder() .with_vertices(gpu_cube_vertices()) - .with_transform(Transform { + .with_transform(TransformDescriptor { scale: Vec3::new(6.0, 6.0, 6.0), rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), ..Default::default() @@ -547,7 +549,7 @@ mod test { .builder() .with_vertices(math::UNIT_POINTS.map(cmy_gpu_vertex)) .with_indices(math::UNIT_INDICES.map(|i| i as u32)) - .with_transform(Transform { + .with_transform(TransformDescriptor { scale: Vec3::new(6.0, 6.0, 6.0), rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), ..Default::default() @@ -578,7 +580,7 @@ mod test { let (geometry, _cube_one_transform, _cube_one) = stage .builder() .with_vertices(gpu_cube_vertices()) - .with_transform(Transform { + .with_transform(TransformDescriptor { translation: Vec3::new(-4.5, 0.0, 0.0), scale: Vec3::new(6.0, 6.0, 6.0), rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), @@ -588,7 +590,7 @@ mod test { let (_cube_two_transform, cube_two) = stage .builder() .with_vertices_array(geometry.array()) - .with_transform(Transform { + .with_transform(TransformDescriptor { translation: Vec3::new(4.5, 0.0, 0.0), scale: Vec3::new(6.0, 6.0, 6.0), rotation: Quat::from_axis_angle(Vec3::Y, std::f32::consts::FRAC_PI_4), @@ -637,7 +639,7 @@ mod test { let (_cube_geometry, _transform, cube) = stage .builder() .with_vertices(math::UNIT_INDICES.map(|i| cmy_gpu_vertex(math::UNIT_POINTS[i]))) - .with_transform(Transform { + .with_transform(TransformDescriptor { scale: Vec3::new(10.0, 10.0, 10.0), ..Default::default() }) @@ -731,7 +733,7 @@ mod test { ..Default::default() }) .with_vertices(gpu_uv_unit_cube()) - .with_transform(Transform { + .with_transform(TransformDescriptor { scale: Vec3::new(10.0, 10.0, 10.0), ..Default::default() }) @@ -815,7 +817,7 @@ mod test { has_lighting: false, ..Default::default() }) - .with_transform(Transform { + .with_transform(TransformDescriptor { translation: Vec3::new(15.0, 35.0, 0.5), scale: Vec3::new(0.5, 0.5, 1.0), ..Default::default() @@ -947,13 +949,13 @@ mod test { let _camera = stage.new_camera(Camera::new(projection, view)); let root_node = stage.new_nested_transform(); - root_node.set(Transform { + root_node.set(TransformDescriptor { scale: Vec3::new(25.0, 25.0, 1.0), ..Default::default() }); println!("root_node: {:#?}", root_node.get_global_transform()); - let offset = Transform { + let offset = TransformDescriptor { translation: Vec3::new(1.0, 1.0, 0.0), ..Default::default() }; @@ -1046,7 +1048,7 @@ mod test { let _rez = stage .builder() .with_vertices(gpu_cube_vertices()) - .with_transform(Transform { + .with_transform(TransformDescriptor { scale: Vec3::new(6.0, 6.0, 6.0), rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), ..Default::default() @@ -1089,7 +1091,7 @@ mod test { let _rez = stage .builder() .with_vertices(gpu_cube_vertices()) - .with_transform(Transform { + .with_transform(TransformDescriptor { scale: Vec3::new(6.0, 6.0, 6.0), rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), ..Default::default() diff --git a/crates/renderling/src/light.rs b/crates/renderling/src/light.rs index da33516e..4fda7d9c 100644 --- a/crates/renderling/src/light.rs +++ b/crates/renderling/src/light.rs @@ -16,8 +16,8 @@ use crate::{ cubemap::{CubemapDescriptor, CubemapFaceDirection}, geometry::GeometryDescriptor, math::{Fetch, IsSampler, IsVector, Sample2dArray}, - stage::{Renderlet, VertexInfo}, - transform::Transform, + stage::{RenderletDescriptor, VertexInfo}, + transform::TransformDescriptor, }; #[cfg(cpu)] @@ -90,10 +90,10 @@ impl Default for ShadowMapDescriptor { #[cfg(test)] #[derive(Default, Debug, Clone, Copy, PartialEq)] pub struct ShadowMappingVertexInfo { - pub renderlet_id: Id, + pub renderlet_id: Id, pub vertex_index: u32, pub vertex: crate::geometry::Vertex, - pub transform: Transform, + pub transform: TransformDescriptor, pub model_matrix: Mat4, pub world_pos: Vec3, pub view_projection: Mat4, @@ -117,7 +117,7 @@ pub struct ShadowMappingVertexInfo { #[allow(clippy::too_many_arguments)] pub fn shadow_mapping_vertex( // Points at a `Renderlet` - #[spirv(instance_index)] renderlet_id: Id, + #[spirv(instance_index)] renderlet_id: Id, // Which vertex within the renderlet are we rendering #[spirv(vertex_index)] vertex_index: u32, // The slab where the renderlet's geometry is staged @@ -498,7 +498,7 @@ pub struct Light { /// The id of a transform to apply to the position and direction of the light. /// /// This `Id` points to a transform on the geometry slab. - pub transform_id: Id, + pub transform_id: Id, /// The id of the shadow map in use by this light. pub shadow_map_desc_id: Id, } @@ -796,7 +796,7 @@ impl ShadowCalculation { #[spirv(vertex)] pub fn light_tiling_depth_pre_pass( // Points at a `Renderlet`. - #[spirv(instance_index)] renderlet_id: Id, + #[spirv(instance_index)] renderlet_id: Id, // Which vertex within the renderlet are we rendering? #[spirv(vertex_index)] vertex_index: u32, // The slab where the renderlet's geometry is staged diff --git a/crates/renderling/src/light/cpu.rs b/crates/renderling/src/light/cpu.rs index 4fdbfb09..c9ff1e67 100644 --- a/crates/renderling/src/light/cpu.rs +++ b/crates/renderling/src/light/cpu.rs @@ -13,7 +13,7 @@ use snafu::prelude::*; use crate::{ atlas::{Atlas, AtlasBlitter, AtlasError}, geometry::Geometry, - prelude::Transform, + prelude::TransformDescriptor, stage::NestedTransform, }; @@ -133,7 +133,7 @@ pub struct AnalyticalLight { /// The light's global transform. /// /// This value lives in the lighting slab. - transform: Ct::Container, + transform: Ct::Container, /// The light's nested transform. /// /// This value comes from the light's node, if it belongs to one. @@ -160,7 +160,7 @@ impl core::fmt::Display for AnalyticalLight { impl Clone for AnalyticalLight where Ct::Container: Clone, - Ct::Container: Clone, + Ct::Container: Clone, LightDetails: Clone, NestedTransform: Clone, { @@ -250,7 +250,7 @@ impl AnalyticalLight { /// If a `NestedTransform` has been linked to this light by using [`Self::link_node_transform`], /// the transform returned by this function may be overwritten at any point by the given /// `NestedTransform`. - pub fn transform(&self) -> &Ct::Container { + pub fn transform(&self) -> &Ct::Container { &self.transform } @@ -444,7 +444,7 @@ impl Lighting { Light: From>, LightDetails: From>, { - let transform = self.light_slab.new_value(Transform::default()); + let transform = self.light_slab.new_value(TransformDescriptor::default()); let light_inner = self.light_slab.new_value(light_descriptor); let light = self.light_slab.new_value({ let mut light = Light::from(light_inner.id()); diff --git a/crates/renderling/src/light/cpu/test.rs b/crates/renderling/src/light/cpu/test.rs index 9b56c173..8f80fe41 100644 --- a/crates/renderling/src/light/cpu/test.rs +++ b/crates/renderling/src/light/cpu/test.rs @@ -11,10 +11,10 @@ use crate::{ color::linear_xfer_vec4, light::{LightTiling, LightTilingConfig, SpotLightCalculation}, math::GpuRng, - pbr::Material, - prelude::Transform, + material::Material, + prelude::TransformDescriptor, geometry::Vertex, - stage::{Renderlet, RenderletPbrVertexInfo, Stage}, test::BlockOnFuture, + stage::{RenderletDescriptor, RenderletPbrVertexInfo, Stage}, test::BlockOnFuture, }; use super::*; @@ -42,7 +42,7 @@ fn spot_one_calc() { log::info!("spot: {spot:#?}"); let light_node = doc.nodes().find(|node| node.light().is_some()).unwrap(); - let parent_transform = Transform::from(light_node.transform()); + let parent_transform = TransformDescriptor::from(light_node.transform()); log::info!("parent_transform: {parent_transform:#?}"); let spot_descriptor = SpotLightDescriptor { @@ -233,11 +233,11 @@ fn gen_vec3(prng: &mut GpuRng) -> Vec3 { } struct GeneratedLight { - _unused_transform: Hybrid, + _unused_transform: Hybrid, _mesh_geometry: HybridArray, _mesh_material: Hybrid, _light: AnalyticalLight, - mesh_renderlet: Hybrid, + mesh_renderlet: Hybrid, } fn gen_light(stage: &Stage, prng: &mut GpuRng, bounding_boxes: &[BoundingBox]) -> GeneratedLight { @@ -273,7 +273,7 @@ fn gen_light(stage: &Stage, prng: &mut GpuRng, bounding_boxes: &[BoundingBox]) - // }); let (a, b, c, d, e) = stage .builder() - .with_transform(Transform { + .with_transform(TransformDescriptor { translation: position, ..Default::default() }) diff --git a/crates/renderling/src/light/shadow_map.rs b/crates/renderling/src/light/shadow_map.rs index 1e24e9c0..6b65d6c5 100644 --- a/crates/renderling/src/light/shadow_map.rs +++ b/crates/renderling/src/light/shadow_map.rs @@ -14,7 +14,7 @@ use snafu::{OptionExt, ResultExt}; use crate::{ atlas::{AtlasBlittingOperation, AtlasImage, AtlasTexture}, bindgroup::ManagedBindGroup, - stage::Renderlet, + stage::RenderletDescriptor, }; use super::{ @@ -248,7 +248,7 @@ impl ShadowMap { pub fn update<'a>( &self, lighting: impl AsRef, - renderlets: impl IntoIterator>, + renderlets: impl IntoIterator>, ) -> Result<(), LightingError> { let lighting = lighting.as_ref(); let light_bundle = self diff --git a/crates/renderling/src/material.rs b/crates/renderling/src/material.rs index d15e21e8..1e058a53 100644 --- a/crates/renderling/src/material.rs +++ b/crates/renderling/src/material.rs @@ -4,3 +4,57 @@ mod cpu; #[cfg(cpu)] pub use cpu::*; +use crabslab::{Id, SlabItem}; +use glam::{Vec3, Vec4}; + +use crate::atlas::AtlasTexture; + +/// Represents a material on the GPU. +#[repr(C)] +#[derive(Clone, Copy, PartialEq, SlabItem, core::fmt::Debug)] +pub struct Material { + pub emissive_factor: Vec3, + pub emissive_strength_multiplier: f32, + pub albedo_factor: Vec4, + pub metallic_factor: f32, + pub roughness_factor: f32, + + pub albedo_texture_id: Id, + pub metallic_roughness_texture_id: Id, + pub normal_texture_id: Id, + pub ao_texture_id: Id, + pub emissive_texture_id: Id, + + pub albedo_tex_coord: u32, + pub metallic_roughness_tex_coord: u32, + pub normal_tex_coord: u32, + pub ao_tex_coord: u32, + pub emissive_tex_coord: u32, + + pub has_lighting: bool, + pub ao_strength: f32, +} + +impl Default for Material { + fn default() -> Self { + Self { + emissive_factor: Vec3::ZERO, + emissive_strength_multiplier: 1.0, + albedo_factor: Vec4::ONE, + metallic_factor: 1.0, + roughness_factor: 1.0, + albedo_texture_id: Id::NONE, + metallic_roughness_texture_id: Id::NONE, + normal_texture_id: Id::NONE, + ao_texture_id: Id::NONE, + albedo_tex_coord: 0, + metallic_roughness_tex_coord: 0, + normal_tex_coord: 0, + ao_tex_coord: 0, + has_lighting: true, + ao_strength: 0.0, + emissive_texture_id: Id::NONE, + emissive_tex_coord: 0, + } + } +} diff --git a/crates/renderling/src/material/cpu.rs b/crates/renderling/src/material/cpu.rs index a8ef1a17..6ad03773 100644 --- a/crates/renderling/src/material/cpu.rs +++ b/crates/renderling/src/material/cpu.rs @@ -6,7 +6,7 @@ use craballoc::{ value::{Hybrid, HybridArray}, }; -use crate::{atlas::Atlas, pbr::Material}; +use crate::{atlas::Atlas, material::Material}; /// Wrapper around the materials slab, which holds material textures in an atlas. #[derive(Clone)] diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index 2664a42f..6bafa047 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -4,7 +4,7 @@ //! * //! * //! * -use crabslab::{Id, Slab, SlabItem}; +use crabslab::{Id, Slab}; use glam::{Mat4, Vec2, Vec3, Vec4, Vec4Swizzles}; #[allow(unused)] @@ -17,65 +17,15 @@ use crate::{ DirectionalLightDescriptor, LightStyle, LightingDescriptor, PointLightDescriptor, ShadowCalculation, SpotLightCalculation, }, + material::Material, math::{self, IsSampler, IsVector, Sample2d, Sample2dArray, SampleCube}, println as my_println, - stage::Renderlet, + stage::RenderletDescriptor, }; pub mod debug; use debug::DebugChannel; -/// Represents a material on the GPU. -#[repr(C)] -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Clone, Copy, PartialEq, SlabItem)] -pub struct Material { - pub emissive_factor: Vec3, - pub emissive_strength_multiplier: f32, - pub albedo_factor: Vec4, - pub metallic_factor: f32, - pub roughness_factor: f32, - - pub albedo_texture_id: Id, - pub metallic_roughness_texture_id: Id, - pub normal_texture_id: Id, - pub ao_texture_id: Id, - pub emissive_texture_id: Id, - - pub albedo_tex_coord: u32, - pub metallic_roughness_tex_coord: u32, - pub normal_tex_coord: u32, - pub ao_tex_coord: u32, - pub emissive_tex_coord: u32, - - pub has_lighting: bool, - pub ao_strength: f32, -} - -impl Default for Material { - fn default() -> Self { - Self { - emissive_factor: Vec3::ZERO, - emissive_strength_multiplier: 1.0, - albedo_factor: Vec4::ONE, - metallic_factor: 1.0, - roughness_factor: 1.0, - albedo_texture_id: Id::NONE, - metallic_roughness_texture_id: Id::NONE, - normal_texture_id: Id::NONE, - ao_texture_id: Id::NONE, - albedo_tex_coord: 0, - metallic_roughness_tex_coord: 0, - normal_tex_coord: 0, - ao_tex_coord: 0, - has_lighting: true, - ao_strength: 0.0, - emissive_texture_id: Id::NONE, - emissive_tex_coord: 0, - } - } -} - /// Trowbridge-Reitz GGX normal distribution function (NDF). /// /// The normal distribution function D statistically approximates the relative @@ -286,7 +236,7 @@ pub fn fragment_impl( material_slab: &[u32], lighting_slab: &[u32], - renderlet_id: Id, + renderlet_id: Id, frag_coord: Vec4, in_color: Vec4, @@ -721,7 +671,7 @@ mod test { pbr::Material, prelude::glam::{Vec3, Vec4}, test::BlockOnFuture, - transform::Transform, + transform::TransformDescriptor, }; #[test] @@ -791,7 +741,7 @@ mod test { roughness_factor: roughness, ..Default::default() }) - .with_transform(Transform { + .with_transform(TransformDescriptor { translation: Vec3::new(x, y, 0.0), ..Default::default() }) diff --git a/crates/renderling/src/stage.rs b/crates/renderling/src/stage.rs index 0145072b..eedc5d05 100644 --- a/crates/renderling/src/stage.rs +++ b/crates/renderling/src/stage.rs @@ -14,9 +14,9 @@ use spirv_std::{ use crate::{ bvol::BoundingSphere, geometry::{GeometryDescriptor, MorphTarget, Skin, Vertex}, + material::Material, math::IsVector, - pbr::Material, - transform::Transform, + transform::TransformDescriptor, }; #[allow(unused_imports)] @@ -35,7 +35,7 @@ pub use gltf_support::*; /// Returned by [`Renderlet::get_vertex_info`]. pub struct VertexInfo { pub vertex: Vertex, - pub transform: Transform, + pub transform: TransformDescriptor, pub model_matrix: Mat4, pub world_pos: Vec3, } @@ -49,13 +49,13 @@ pub struct VertexInfo { #[cfg_attr(not(target_arch = "spirv"), derive(Debug))] #[derive(Clone, Copy, PartialEq, SlabItem)] #[offsets] -pub struct Renderlet { +pub struct RenderletDescriptor { pub visible: bool, pub vertices_array: Array, /// Bounding sphere of the entire renderlet, in local space. pub bounds: BoundingSphere, pub indices_array: Array, - pub transform_id: Id, + pub transform_id: Id, pub material_id: Id, pub skin_id: Id, pub morph_targets: Array>, @@ -63,9 +63,9 @@ pub struct Renderlet { pub geometry_descriptor_id: Id, } -impl Default for Renderlet { +impl Default for RenderletDescriptor { fn default() -> Self { - Renderlet { + RenderletDescriptor { visible: true, vertices_array: Array::default(), bounds: BoundingSphere::default(), @@ -80,7 +80,7 @@ impl Default for Renderlet { } } -impl Renderlet { +impl RenderletDescriptor { /// Returns the vertex at the given index and its related values. /// /// These values are often used in shaders, so they are grouped together. @@ -99,11 +99,11 @@ impl Renderlet { /// Retrieve the transform of this `Renderlet`. /// /// This takes into consideration all skinning matrices. - pub fn get_transform(&self, vertex: Vertex, slab: &[u32]) -> Transform { + pub fn get_transform(&self, vertex: Vertex, slab: &[u32]) -> TransformDescriptor { let config = slab.read_unchecked(self.geometry_descriptor_id); if config.has_skinning && self.skin_id.is_some() { let skin = slab.read(self.skin_id); - Transform::from(skin.get_skinning_matrix(vertex, slab)) + TransformDescriptor::from(skin.get_skinning_matrix(vertex, slab)) } else { slab.read(self.transform_id) } @@ -143,11 +143,11 @@ impl Renderlet { /// A helper struct that contains all outputs of the Renderlet's PBR vertex shader. #[derive(Default, Debug, Clone, Copy, PartialEq)] pub struct RenderletPbrVertexInfo { - pub renderlet: Renderlet, - pub renderlet_id: Id, + pub renderlet: RenderletDescriptor, + pub renderlet_id: Id, pub vertex_index: u32, pub vertex: Vertex, - pub transform: Transform, + pub transform: TransformDescriptor, pub model_matrix: Mat4, pub view_projection: Mat4, pub out_color: Vec4, @@ -165,12 +165,12 @@ pub struct RenderletPbrVertexInfo { #[allow(clippy::too_many_arguments)] pub fn renderlet_vertex( // Points at a `Renderlet` - #[spirv(instance_index)] renderlet_id: Id, + #[spirv(instance_index)] renderlet_id: Id, // Which vertex within the renderlet are we rendering #[spirv(vertex_index)] vertex_index: u32, #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], - #[spirv(flat)] out_renderlet: &mut Id, + #[spirv(flat)] out_renderlet: &mut Id, // TODO: Think about placing all these out values in a G-Buffer // But do we have enough buffers + enough space on web? // ...and can we write to buffers from vertex shaders on web? @@ -269,7 +269,7 @@ pub fn renderlet_fragment( #[spirv(storage_buffer, descriptor_set = 0, binding = 13)] debug_slab: &mut [u32], - #[spirv(flat)] renderlet_id: Id, + #[spirv(flat)] renderlet_id: Id, #[spirv(frag_coord)] frag_coord: Vec4, in_color: Vec4, in_uv0: Vec2, @@ -332,16 +332,16 @@ mod test { use craballoc::{prelude::SlabAllocator, runtime::CpuRuntime}; use glam::{Mat4, Quat, Vec3}; - use crate::{math::IsMatrix, stage::NestedTransform, transform::Transform}; + use crate::{math::IsMatrix, stage::NestedTransform, transform::TransformDescriptor}; #[test] fn matrix_hierarchy_sanity() { - let a: Mat4 = Transform { + let a: Mat4 = TransformDescriptor { translation: Vec3::new(100.0, 100.0, 0.0), ..Default::default() } .into(); - let b: Mat4 = Transform { + let b: Mat4 = TransformDescriptor { scale: Vec3::splat(0.5), ..Default::default() } @@ -372,17 +372,17 @@ mod test { #[expect(clippy::needless_borrows_for_generic_args, reason = "riffraff")] let slab = SlabAllocator::::new(&CpuRuntime, "transform", ()); let a = NestedTransform::new(&slab); - a.set(Transform { + a.set(TransformDescriptor { translation: Vec3::splat(100.0), ..Default::default() }); let b = NestedTransform::new(&slab); - b.set(Transform { + b.set(TransformDescriptor { rotation: Quat::from_scaled_axis(Vec3::Z), ..Default::default() }); let c = NestedTransform::new(&slab); - c.set(Transform { + c.set(TransformDescriptor { scale: Vec3::splat(2.0), ..Default::default() }); @@ -390,7 +390,7 @@ mod test { a.add_child(&b); b.add_child(&c); - let Transform { + let TransformDescriptor { translation, rotation, scale, @@ -411,7 +411,7 @@ mod test { all_updates ); - let Transform { + let TransformDescriptor { translation, rotation, scale, diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index 01f96ae3..6c4cdcf9 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -33,10 +33,10 @@ use crate::{ material::Materials, pbr::debug::DebugChannel, skybox::{Skybox, SkyboxRenderPipeline}, - stage::Renderlet, + stage::RenderletDescriptor, texture::{DepthTexture, Texture}, tonemapping::Tonemapping, - transform::Transform, + transform::TransformDescriptor, tuple::Bundle, }; @@ -308,9 +308,32 @@ impl StageRendering<'_> { } } -/// A helper struct to build [`Renderlet`]s in the [`Geometry`] manager. +pub enum RenderletTransform { + /// A single root transform + Root(crate::transform::Transform), + /// A heirarchy of transforms. + /// + /// Each transform represents the transform of one node in a scene graph. + Hierarchy(NestedTransform), +} + +pub struct Renderlet< + RenderletDescriptorCt: IsContainer = HybridContainer, + TransformCt: IsContainer = HybridContainer, + VerticesCt: IsContainer = GpuArrayContainer, + IndicesCt: IsContainer = GpuArrayContainer, + MaterialCt: IsContainer = GpuArrayContainer, +> { + transform: Option>, + descriptor: RenderletDescriptorCt::Container, + vertices: VerticesCt::Container, + indices: Option>, + material: Option, +} + +/// A helper struct to build [`Renderlet`]s. pub struct RenderletBuilder<'a, T> { - data: Renderlet, + data: RenderletDescriptor, resources: T, stage: &'a Stage, } @@ -318,7 +341,7 @@ pub struct RenderletBuilder<'a, T> { impl<'a> RenderletBuilder<'a, ()> { pub fn new(stage: &'a Stage) -> Self { RenderletBuilder { - data: Renderlet::default(), + data: RenderletDescriptor::default(), resources: (), stage, } @@ -357,15 +380,15 @@ impl<'a, T: Bundle> RenderletBuilder<'a, T> { self.suffix(indices) } - pub fn with_transform_id(mut self, transform_id: Id) -> Self { + pub fn with_transform_id(mut self, transform_id: Id) -> Self { self.data.transform_id = transform_id; self } pub fn with_transform( mut self, - transform: Transform, - ) -> RenderletBuilder<'a, T::Suffixed>> { + transform: TransformDescriptor, + ) -> RenderletBuilder<'a, T::Suffixed>> { let transform = self.stage.geometry.new_transform(transform); self.data.transform_id = transform.id(); self.suffix(transform) @@ -428,9 +451,9 @@ impl<'a, T: Bundle> RenderletBuilder<'a, T> { /// /// The returned value will be a tuple with the [`Hybrid`] as the head, and /// all other resources added as the tail. - pub fn build(self) -> > as Bundle>::Reduced + pub fn build(self) -> > as Bundle>::Reduced where - T::Suffixed>: Bundle, + T::Suffixed>: Bundle, { let renderlet = self.stage.geometry.new_renderlet(self.data); self.stage.add_renderlet(&renderlet); @@ -535,7 +558,7 @@ impl Stage { } /// Stage a [`Transform`] on the GPU. - pub fn new_transform(&self, transform: Transform) -> Hybrid { + pub fn new_transform(&self, transform: TransformDescriptor) -> Hybrid { self.geometry.new_transform(transform) } @@ -575,8 +598,8 @@ impl Stage { /// Create a new array of joint transform ids that each point to a [`Transform`]. pub fn new_joint_transform_ids( &self, - data: impl IntoIterator>, - ) -> HybridArray> { + data: impl IntoIterator>, + ) -> HybridArray> { self.geometry.new_joint_transform_ids(data) } @@ -595,7 +618,7 @@ impl Stage { /// /// The `Renderlet` should still be added to the draw list with /// [`Stage::add_renderlet`]. - pub fn new_renderlet(&self, renderlet: Renderlet) -> Hybrid { + pub fn new_renderlet(&self, renderlet: RenderletDescriptor) -> Hybrid { self.geometry.new_renderlet(renderlet) } @@ -1388,7 +1411,7 @@ impl Stage { /// If you drop the renderlet and no other references are kept, it will be /// removed automatically from the internal list and will cease to be /// drawn each frame. - pub fn add_renderlet(&self, renderlet: &Hybrid) { + pub fn add_renderlet(&self, renderlet: &Hybrid) { // UNWRAP: if we can't acquire the lock we want to panic. let mut draws = self.draw_calls.write().unwrap(); draws.add_renderlet(renderlet); @@ -1396,7 +1419,7 @@ impl Stage { /// Erase the given renderlet from the internal list of renderlets to be /// drawn each frame. - pub fn remove_renderlet(&self, renderlet: &Hybrid) { + pub fn remove_renderlet(&self, renderlet: &Hybrid) { let mut draws = self.draw_calls.write().unwrap(); draws.remove_renderlet(renderlet); } @@ -1408,7 +1431,7 @@ impl Stage { /// If the `order` iterator is missing any renderlet ids, those missing /// renderlets will be drawn _before_ the ordered ones, in no particular /// order. - pub fn reorder_renderlets(&self, order: impl IntoIterator>) { + pub fn reorder_renderlets(&self, order: impl IntoIterator>) { log::trace!("reordering renderlets"); // UNWRAP: panic on purpose let mut guard = self.draw_calls.write().unwrap(); @@ -1422,7 +1445,7 @@ impl Stage { /// /// You should have references of your own, but this is here as a convenience /// method, and is used internally. - pub fn renderlets_iter(&self) -> impl Iterator> { + pub fn renderlets_iter(&self) -> impl Iterator> { // UNWRAP: panic on purpose let guard = self.draw_calls.read().unwrap(); guard.renderlets_iter().collect::>().into_iter() @@ -1568,8 +1591,8 @@ impl Stage { /// Only available on CPU. #[derive(Clone)] pub struct NestedTransform { - pub(crate) global_transform: Ct::Container, - local_transform: Arc>, + pub(crate) global_transform: Ct::Container, + local_transform: Arc>, children: Arc>>, parent: Arc>>, } @@ -1620,8 +1643,8 @@ impl NestedTransform { impl NestedTransform { pub fn new(slab: &SlabAllocator) -> Self { let nested = NestedTransform { - local_transform: Arc::new(RwLock::new(Transform::default())), - global_transform: slab.new_value(Transform::default()), + local_transform: Arc::new(RwLock::new(TransformDescriptor::default())), + global_transform: slab.new_value(TransformDescriptor::default()), children: Default::default(), parent: Default::default(), }; @@ -1643,7 +1666,7 @@ impl NestedTransform { /// Modify the local transform. /// /// This automatically applies the local transform to the global transform. - pub fn modify(&self, f: impl Fn(&mut Transform)) { + pub fn modify(&self, f: impl Fn(&mut TransformDescriptor)) { { // UNWRAP: panic on purpose let mut local_guard = self.local_transform.write().unwrap(); @@ -1655,30 +1678,30 @@ impl NestedTransform { /// Set the local transform. /// /// This automatically applies the local transform to the global transform. - pub fn set(&self, transform: Transform) { + pub fn set(&self, transform: TransformDescriptor) { self.modify(move |t| { *t = transform; }); } /// Returns the local transform. - pub fn get(&self) -> Transform { + pub fn get(&self) -> TransformDescriptor { *self.local_transform.read().unwrap() } /// Returns the global transform. - pub fn get_global_transform(&self) -> Transform { + pub fn get_global_transform(&self) -> TransformDescriptor { let maybe_parent_guard = self.parent.read().unwrap(); let transform = self.get(); let parent_transform = maybe_parent_guard .as_ref() .map(|parent| parent.get_global_transform()) .unwrap_or_default(); - Transform::from(Mat4::from(parent_transform) * Mat4::from(transform)) + TransformDescriptor::from(Mat4::from(parent_transform) * Mat4::from(transform)) } /// Get a vector containing all the transforms up to the root. - pub fn get_all_transforms(&self) -> Vec { + pub fn get_all_transforms(&self) -> Vec { let mut transforms = vec![]; if let Some(parent) = self.parent() { transforms.extend(parent.get_all_transforms()); @@ -1687,7 +1710,7 @@ impl NestedTransform { transforms } - pub fn global_transform_id(&self) -> Id { + pub fn global_transform_id(&self) -> Id { self.global_transform.id() } @@ -1723,9 +1746,9 @@ mod test { use crate::{ camera::Camera, geometry::{Geometry, GeometryDescriptor}, - stage::{cpu::SlabAllocator, NestedTransform, Renderlet, Vertex}, + stage::{cpu::SlabAllocator, NestedTransform, RenderletDescriptor, Vertex}, test::BlockOnFuture, - transform::Transform, + transform::TransformDescriptor, Context, }; @@ -1770,13 +1793,13 @@ mod test { let root = NestedTransform::new(&slab); let child = NestedTransform::new(&slab); log::info!("set"); - child.set(Transform { + child.set(TransformDescriptor { translation: Vec3::new(1.0, 0.0, 0.0), ..Default::default() }); log::info!("grandchild"); let grandchild = NestedTransform::new(&slab); - grandchild.set(Transform { + grandchild.set(TransformDescriptor { translation: Vec3::new(1.0, 0.0, 0.0), ..Default::default() }); @@ -1855,7 +1878,7 @@ mod test { fn has_consistent_stage_renderlet_strong_count() { let ctx = Context::headless(100, 100).block(); let stage = ctx.new_stage(); - let r = stage.new_renderlet(Renderlet::default()); + let r = stage.new_renderlet(RenderletDescriptor::default()); assert_eq!(1, r.ref_count()); stage.add_renderlet(&r); diff --git a/crates/renderling/src/stage/gltf_support.rs b/crates/renderling/src/stage/gltf_support.rs index c7a16f0a..928b5cf4 100644 --- a/crates/renderling/src/stage/gltf_support.rs +++ b/crates/renderling/src/stage/gltf_support.rs @@ -15,9 +15,9 @@ use crate::{ AnalyticalLight, DirectionalLightDescriptor, LightStyle, PointLightDescriptor, SpotLightDescriptor, }, - pbr::Material, - stage::{MorphTarget, NestedTransform, Renderlet, Skin, Stage, Vertex}, - transform::Transform, + material::Material, + stage::{MorphTarget, NestedTransform, RenderletDescriptor, Skin, Stage, Vertex}, + transform::TransformDescriptor, }; mod anime; @@ -98,10 +98,10 @@ impl From for StageGltfError { } } -impl From for Transform { +impl From for TransformDescriptor { fn from(transform: gltf::scene::Transform) -> Self { let (translation, rotation, scale) = transform.decomposed(); - Transform { + TransformDescriptor { translation: Vec3::from_array(translation), rotation: Quat::from_array(rotation), scale: Vec3::from_array(scale), @@ -686,7 +686,7 @@ pub struct GltfNode { } impl GltfNode { - pub fn global_transform(&self) -> Transform { + pub fn global_transform(&self) -> TransformDescriptor { self.transform.get_global_transform() } } @@ -697,7 +697,7 @@ pub struct GltfSkin { // Indices of the skeleton nodes used as joints in this skin, unused internally // but possibly useful. pub joint_nodes: Vec, - pub joint_transforms: HybridArray>, + pub joint_transforms: HybridArray>, // Containins the 4x4 inverse-bind matrices. // // When None, each matrix is assumed to be the 4x4 identity matrix which implies that the @@ -780,7 +780,7 @@ pub struct GltfDocument { pub nodes: Vec, pub materials: HybridArray, // map of node index to renderlets - pub renderlets: FxHashMap>>, + pub renderlets: FxHashMap>>, /// Vector of scenes - each being a list of nodes. pub scenes: Vec>, pub skins: Vec, @@ -1110,7 +1110,7 @@ impl GltfDocument { let num_prims = mesh.primitives.len(); log::trace!(" has {num_prims} primitives"); for (prim, i) in mesh.primitives.iter().zip(1..) { - let hybrid = stage.new_renderlet(Renderlet { + let hybrid = stage.new_renderlet(RenderletDescriptor { vertices_array: prim.vertices.array(), indices_array: prim.indices.array(), transform_id: gltf_node.transform.global_transform_id(), @@ -1155,7 +1155,7 @@ impl GltfDocument { }) } - pub fn renderlets_iter(&self) -> impl Iterator> { + pub fn renderlets_iter(&self) -> impl Iterator> { self.renderlets.iter().flat_map(|(_, rs)| rs.iter()) } @@ -1217,8 +1217,8 @@ impl Stage { #[cfg(test)] mod test { use crate::{ - camera::Camera, pbr::Material, stage::Vertex, test::BlockOnFuture, transform::Transform, - Context, + camera::Camera, material::Material, stage::Vertex, test::BlockOnFuture, + transform::TransformDescriptor, Context, }; use glam::{Vec3, Vec4}; @@ -1327,7 +1327,7 @@ mod test { .with_uv0([0.0, 1.0]), ]) .with_indices([0u32, 3, 2, 0, 2, 1]) - .with_transform(Transform { + .with_transform(TransformDescriptor { scale: Vec3::new(100.0, 100.0, 1.0), ..Default::default() }) diff --git a/crates/renderling/src/transform.rs b/crates/renderling/src/transform.rs index 5d328e1d..19959cb8 100644 --- a/crates/renderling/src/transform.rs +++ b/crates/renderling/src/transform.rs @@ -4,27 +4,31 @@ use glam::{Mat4, Quat, Vec3}; use crate::math::IsMatrix; -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Clone, Copy, PartialEq, SlabItem)] -/// A decomposed transformation. +#[cfg(cpu)] +mod cpu; +#[cfg(cpu)] +pub use cpu::*; + +#[derive(Clone, Copy, PartialEq, SlabItem, core::fmt::Debug)] +/// A GPU descriptor of a decomposed transformation. /// -/// `Transform` can be converted to/from [`Mat4`]. -pub struct Transform { +/// `TransformDescriptor` can be converted to/from [`Mat4`]. +pub struct TransformDescriptor { pub translation: Vec3, pub rotation: Quat, pub scale: Vec3, } -impl Default for Transform { +impl Default for TransformDescriptor { fn default() -> Self { Self::IDENTITY } } -impl From for Transform { +impl From for TransformDescriptor { fn from(value: Mat4) -> Self { let (scale, rotation, translation) = value.to_scale_rotation_translation_or_id(); - Transform { + TransformDescriptor { translation, rotation, scale, @@ -32,20 +36,20 @@ impl From for Transform { } } -impl From for Mat4 { +impl From for Mat4 { fn from( - Transform { + TransformDescriptor { translation, rotation, scale, - }: Transform, + }: TransformDescriptor, ) -> Self { Mat4::from_scale_rotation_translation(scale, rotation, translation) } } -impl Transform { - pub const IDENTITY: Self = Transform { +impl TransformDescriptor { + pub const IDENTITY: Self = TransformDescriptor { translation: Vec3::ZERO, rotation: Quat::IDENTITY, scale: Vec3::ONE, @@ -61,8 +65,8 @@ mod test { fn transform_roundtrip() { assert_eq!(3, Vec3::SLAB_SIZE, "unexpected Vec3 slab size"); assert_eq!(4, Quat::SLAB_SIZE, "unexpected Quat slab size"); - assert_eq!(10, Transform::SLAB_SIZE); - let t = Transform::default(); + assert_eq!(10, TransformDescriptor::SLAB_SIZE); + let t = TransformDescriptor::default(); let mut slab = CpuSlab::new(vec![]); let t_id = slab.append(&t); pretty_assertions::assert_eq!( diff --git a/crates/renderling/src/transform/cpu.rs b/crates/renderling/src/transform/cpu.rs new file mode 100644 index 00000000..2f91ab9d --- /dev/null +++ b/crates/renderling/src/transform/cpu.rs @@ -0,0 +1,18 @@ +//! CPU side of transform. + +use craballoc::value::{GpuContainer, HybridContainer, IsContainer}; + +/// A decomposed 3d transformation. +pub struct Transform { + descriptor: Ct::Container, +} + +pub type GpuOnlyTransform = Transform; + +impl Transform { + pub fn into_gpu_only(self) -> GpuOnlyTransform { + Transform { + descriptor: self.descriptor.into_gpu_only(), + } + } +} diff --git a/crates/renderling/src/tutorial.rs b/crates/renderling/src/tutorial.rs index e7f7ac34..d42d80fc 100644 --- a/crates/renderling/src/tutorial.rs +++ b/crates/renderling/src/tutorial.rs @@ -6,7 +6,7 @@ use spirv_std::spirv; use crate::{ geometry::{GeometryDescriptor, Vertex}, - stage::{Renderlet, VertexInfo}, + stage::{RenderletDescriptor, VertexInfo}, }; /// Simple fragment shader that writes the input color to the output color. @@ -91,7 +91,7 @@ pub fn slabbed_vertices( #[spirv(vertex)] pub fn slabbed_renderlet( // Id of the array of vertices we are rendering - #[spirv(instance_index)] renderlet_id: Id, + #[spirv(instance_index)] renderlet_id: Id, // Which vertex within the render unit are we rendering #[spirv(vertex_index)] vertex_index: u32, diff --git a/crates/renderling/src/ui/cpu.rs b/crates/renderling/src/ui/cpu.rs index 454ef0e3..e27b4d68 100644 --- a/crates/renderling/src/ui/cpu.rs +++ b/crates/renderling/src/ui/cpu.rs @@ -6,8 +6,8 @@ use crate::{ atlas::AtlasTexture, camera::Camera, geometry::Geometry, - stage::{NestedTransform, Renderlet, Stage}, - transform::Transform, + stage::{NestedTransform, RenderletDescriptor, Stage}, + transform::TransformDescriptor, Context, }; use craballoc::prelude::{Hybrid, SourceId}; @@ -74,11 +74,11 @@ pub struct ImageId(usize); #[derive(Clone, Debug)] pub struct UiTransform { transform: NestedTransform, - renderlet_ids: Arc>>, + renderlet_ids: Arc>>, } impl UiTransform { - pub(crate) fn id(&self) -> Id { + pub(crate) fn id(&self) -> Id { self.transform.global_transform_id() } @@ -225,7 +225,7 @@ impl Ui { self } - fn new_transform(&self, renderlet_ids: Vec>) -> UiTransform { + fn new_transform(&self, renderlet_ids: Vec>) -> UiTransform { let transform = self.stage.new_nested_transform(); let transform = UiTransform { transform, diff --git a/crates/renderling/src/ui/cpu/path.rs b/crates/renderling/src/ui/cpu/path.rs index d14867d6..ce4c6795 100644 --- a/crates/renderling/src/ui/cpu/path.rs +++ b/crates/renderling/src/ui/cpu/path.rs @@ -1,7 +1,7 @@ //! Path and builder. //! //! Path colors are sRGB. -use crate::{geometry::Vertex, pbr::Material, stage::Renderlet}; +use crate::{geometry::Vertex, material::Material, stage::RenderletDescriptor}; use craballoc::prelude::{GpuArray, Hybrid}; use crabslab::Id; use glam::{Vec2, Vec3, Vec3Swizzles, Vec4}; @@ -20,7 +20,7 @@ pub struct UiPath { pub indices: GpuArray, pub transform: UiTransform, pub material: Hybrid, - pub renderlet: Hybrid, + pub renderlet: Hybrid, } #[derive(Clone, Copy)] diff --git a/crates/renderling/src/ui/cpu/text.rs b/crates/renderling/src/ui/cpu/text.rs index 8f6ac457..c9fe233b 100644 --- a/crates/renderling/src/ui/cpu/text.rs +++ b/crates/renderling/src/ui/cpu/text.rs @@ -15,7 +15,9 @@ use glyph_brush::*; pub use ab_glyph::FontArc; pub use glyph_brush::{Section, Text}; -use crate::{atlas::AtlasTexture, geometry::Vertex, pbr::Material, stage::Renderlet}; +use crate::{ + atlas::AtlasTexture, geometry::Vertex, material::Material, stage::RenderletDescriptor, +}; use image::{DynamicImage, GenericImage, ImageBuffer, Luma, Rgba}; use super::{Ui, UiTransform}; @@ -28,7 +30,7 @@ pub struct UiText { pub transform: UiTransform, pub texture: Hybrid, pub material: Hybrid, - pub renderlet: Hybrid, + pub renderlet: Hybrid, pub bounds: (Vec2, Vec2), } From 4203c8647582e2aa040d9053aa29a0d727221904 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Wed, 3 Sep 2025 10:40:01 +1200 Subject: [PATCH 03/31] rename Materials to MaterialDescriptor --- crates/example-culling/src/main.rs | 16 +++++------ crates/renderling/src/atlas/cpu.rs | 16 +++++------ crates/renderling/src/bvol.rs | 6 ++--- crates/renderling/src/lib.rs | 16 +++++------ crates/renderling/src/light/cpu/test.rs | 12 ++++----- crates/renderling/src/material.rs | 4 +-- crates/renderling/src/material/cpu.rs | 6 ++--- crates/renderling/src/pbr.rs | 12 ++++----- crates/renderling/src/stage.rs | 4 +-- crates/renderling/src/stage/cpu.rs | 13 +++++---- crates/renderling/src/stage/gltf_support.rs | 30 ++++++++++----------- crates/renderling/src/ui/cpu/path.rs | 8 +++--- crates/renderling/src/ui/cpu/text.rs | 8 +++--- 13 files changed, 77 insertions(+), 74 deletions(-) diff --git a/crates/example-culling/src/main.rs b/crates/example-culling/src/main.rs index 2ed9d6ed..b9d1b0c1 100644 --- a/crates/example-culling/src/main.rs +++ b/crates/example-culling/src/main.rs @@ -34,9 +34,9 @@ struct CullingExample { controller: example::camera::TurntableCameraController, stage: Stage, dlights: [AnalyticalLight; 2], - material_aabb_overlapping: Hybrid, - material_aabb_outside: Hybrid, - material_frustum: Hybrid, + material_aabb_overlapping: Hybrid, + material_aabb_outside: Hybrid, + material_frustum: Hybrid, frustum_camera: FrustumCamera, frustum_vertices: HybridArray, frustum_renderlet: Hybrid, @@ -55,8 +55,8 @@ impl CullingExample { seed: u64, stage: &Stage, frustum_camera: &FrustumCamera, - material_outside: &Hybrid, - material_overlapping: &Hybrid, + material_outside: &Hybrid, + material_overlapping: &Hybrid, ) -> Box { log::info!("generating aabbs with seed {seed}"); fastrand::seed(seed); @@ -218,15 +218,15 @@ impl TestAppHandler for CullingExample { let red_color = srgba_to_linear(hex_to_vec4(0xC96868FF)); let yellow_color = srgba_to_linear(hex_to_vec4(0xFADFA1FF)); - let material_aabb_overlapping = stage.new_material(Material { + let material_aabb_overlapping = stage.new_material(MaterialDescriptor { albedo_factor: blue_color, ..Default::default() }); - let material_aabb_outside = stage.new_material(Material { + let material_aabb_outside = stage.new_material(MaterialDescriptor { albedo_factor: red_color, ..Default::default() }); - let material_frustum = stage.new_material(Material { + let material_frustum = stage.new_material(MaterialDescriptor { albedo_factor: yellow_color, ..Default::default() }); diff --git a/crates/renderling/src/atlas/cpu.rs b/crates/renderling/src/atlas/cpu.rs index 4c6b3145..a31586c4 100644 --- a/crates/renderling/src/atlas/cpu.rs +++ b/crates/renderling/src/atlas/cpu.rs @@ -938,7 +938,7 @@ mod test { atlas::{AtlasTexture, TextureAddressMode}, camera::Camera, geometry::Vertex, - material::{Material, Materials}, + material::{MaterialDescriptor, Materials}, test::BlockOnFuture, transform::TransformDescriptor, Context, @@ -971,7 +971,7 @@ mod test { let _rez = stage .builder() - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id: texels_entry.id(), has_lighting: false, ..Default::default() @@ -1053,7 +1053,7 @@ mod test { let _clamp_rez = stage .builder() .with_vertices_array(geometry.array()) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id: clamp_tex.id(), has_lighting: false, ..Default::default() @@ -1066,7 +1066,7 @@ mod test { translation: Vec3::new(sheet_w + 1.0, 0.0, 0.0), ..Default::default() }) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id: repeat_tex.id(), has_lighting: false, ..Default::default() @@ -1080,7 +1080,7 @@ mod test { translation: Vec3::new(sheet_w * 2.0 + 2.0, 0.0, 0.0), ..Default::default() }) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id: mirror_tex.id(), has_lighting: false, ..Default::default() @@ -1146,7 +1146,7 @@ mod test { .with_uv0(Vec2::splat(-3.0)); [tl, bl, br, tl, br, tr] }) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id: clamp_tex.id(), has_lighting: false, ..Default::default() @@ -1155,7 +1155,7 @@ mod test { let _repeat_rez = stage .builder() - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id: repeat_tex.id(), has_lighting: false, ..Default::default() @@ -1169,7 +1169,7 @@ mod test { let _mirror_rez = stage .builder() - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id: mirror_tex.id(), has_lighting: false, ..Default::default() diff --git a/crates/renderling/src/bvol.rs b/crates/renderling/src/bvol.rs index c1fbf5f1..347e9fe0 100644 --- a/crates/renderling/src/bvol.rs +++ b/crates/renderling/src/bvol.rs @@ -595,7 +595,7 @@ impl BVol for Aabb { mod test { use glam::{Mat4, Quat}; - use crate::{geometry::Vertex, material::Material, test::BlockOnFuture, Context}; + use crate::{geometry::Vertex, material::MaterialDescriptor, test::BlockOnFuture, Context}; use super::*; @@ -665,11 +665,11 @@ mod test { }); let _lights = crate::test::make_two_directional_light_setup(&stage); - let white = stage.new_material(Material { + let white = stage.new_material(MaterialDescriptor { albedo_factor: Vec4::ONE, ..Default::default() }); - let red = stage.new_material(Material { + let red = stage.new_material(MaterialDescriptor { albedo_factor: Vec4::new(1.0, 0.0, 0.0, 1.0), ..Default::default() }); diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index 692ccf59..44ea2e70 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -214,7 +214,7 @@ pub mod prelude { pub use crabslab::{Array, Id}; pub use crate::{ - camera::*, geometry::*, light::*, material::Material, stage::*, + camera::*, geometry::*, light::*, material::MaterialDescriptor, stage::*, transform::TransformDescriptor, }; @@ -237,7 +237,7 @@ macro_rules! println { mod test { use super::*; use crate::{ - atlas::AtlasImage, camera::Camera, geometry::Vertex, material::Material, + atlas::AtlasImage, camera::Camera, geometry::Vertex, material::MaterialDescriptor, transform::TransformDescriptor, }; @@ -727,7 +727,7 @@ mod test { let (material, _geometry, _transform, cube) = stage .builder() - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id: entries[0].id(), has_lighting: false, ..Default::default() @@ -812,7 +812,7 @@ mod test { let _rez = stage .builder() .with_vertices_array(geometry.array()) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id: entries[0].id(), has_lighting: false, ..Default::default() @@ -879,7 +879,7 @@ mod test { let _rez = stage .builder() - .with_material(Material::default()) + .with_material(MaterialDescriptor::default()) .with_vertices( math::unit_cube() .into_iter() @@ -989,7 +989,7 @@ mod test { Vertex::default().with_position([size, 0.0, 0.0]), ] }) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_factor: Vec4::new(0.0, 1.0, 1.0, 1.0), has_lighting: false, ..Default::default() @@ -999,7 +999,7 @@ mod test { let _yellow = stage .builder() .with_vertices_array(geometry.array()) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_factor: Vec4::new(1.0, 1.0, 0.0, 1.0), has_lighting: false, ..Default::default() @@ -1009,7 +1009,7 @@ mod test { let _red = stage .builder() .with_vertices_array(geometry.array()) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_factor: Vec4::new(1.0, 0.0, 0.0, 1.0), has_lighting: false, ..Default::default() diff --git a/crates/renderling/src/light/cpu/test.rs b/crates/renderling/src/light/cpu/test.rs index 8f80fe41..c6ac01c6 100644 --- a/crates/renderling/src/light/cpu/test.rs +++ b/crates/renderling/src/light/cpu/test.rs @@ -11,7 +11,7 @@ use crate::{ color::linear_xfer_vec4, light::{LightTiling, LightTilingConfig, SpotLightCalculation}, math::GpuRng, - material::Material, + material::MaterialDescriptor, prelude::TransformDescriptor, geometry::Vertex, stage::{RenderletDescriptor, RenderletPbrVertexInfo, Stage}, test::BlockOnFuture, @@ -176,7 +176,7 @@ fn light_tiling_light_bounds() { }); let colors = [0x6DE1D2FF, 0xFFD63AFF, 0x6DE1D2FF, 0xF75A5AFF].map(|albedo_factor| { - stage.new_material(Material { + stage.new_material(MaterialDescriptor { albedo_factor: { let mut color = crate::math::hex_to_vec4(albedo_factor); linear_xfer_vec4(&mut color); @@ -235,7 +235,7 @@ fn gen_vec3(prng: &mut GpuRng) -> Vec3 { struct GeneratedLight { _unused_transform: Hybrid, _mesh_geometry: HybridArray, - _mesh_material: Hybrid, + _mesh_material: Hybrid, _light: AnalyticalLight, mesh_renderlet: Hybrid, } @@ -282,7 +282,7 @@ fn gen_light(stage: &Stage, prng: &mut GpuRng, bounding_boxes: &[BoundingBox]) - .get_mesh() .map(|(p, n)| Vertex::default().with_position(p).with_normal(n)), ) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_factor: color, has_lighting: false, emissive_factor: color.xyz(), @@ -549,7 +549,7 @@ fn light_bins_point() { log::info!("materials: {materials:#?}"); doc.materials.set_item( 0, - Material { + MaterialDescriptor { albedo_factor: Vec4::ONE, roughness_factor: 1.0, metallic_factor: 0.0, @@ -961,7 +961,7 @@ fn pedestal() { log::info!("materials: {materials:#?}"); doc.materials.set_item( 0, - Material { + MaterialDescriptor { albedo_factor: Vec4::ONE, roughness_factor: 1.0, metallic_factor: 0.0, diff --git a/crates/renderling/src/material.rs b/crates/renderling/src/material.rs index 1e058a53..7c803e13 100644 --- a/crates/renderling/src/material.rs +++ b/crates/renderling/src/material.rs @@ -12,7 +12,7 @@ use crate::atlas::AtlasTexture; /// Represents a material on the GPU. #[repr(C)] #[derive(Clone, Copy, PartialEq, SlabItem, core::fmt::Debug)] -pub struct Material { +pub struct MaterialDescriptor { pub emissive_factor: Vec3, pub emissive_strength_multiplier: f32, pub albedo_factor: Vec4, @@ -35,7 +35,7 @@ pub struct Material { pub ao_strength: f32, } -impl Default for Material { +impl Default for MaterialDescriptor { fn default() -> Self { Self { emissive_factor: Vec3::ZERO, diff --git a/crates/renderling/src/material/cpu.rs b/crates/renderling/src/material/cpu.rs index 6ad03773..3a7c5f71 100644 --- a/crates/renderling/src/material/cpu.rs +++ b/crates/renderling/src/material/cpu.rs @@ -6,7 +6,7 @@ use craballoc::{ value::{Hybrid, HybridArray}, }; -use crate::{atlas::Atlas, material::Material}; +use crate::{atlas::Atlas, material::MaterialDescriptor}; /// Wrapper around the materials slab, which holds material textures in an atlas. #[derive(Clone)] @@ -51,12 +51,12 @@ impl Materials { /// Create a new material. // TODO: move `Material` to material - pub fn new_material(&self, material: Material) -> Hybrid { + pub fn new_material(&self, material: MaterialDescriptor) -> Hybrid { self.slab.new_value(material) } /// Create an array of materials, stored contiguously. - pub fn new_materials(&self, data: impl IntoIterator) -> HybridArray { + pub fn new_materials(&self, data: impl IntoIterator) -> HybridArray { self.slab.new_array(data) } } diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index 6bafa047..0599d47d 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -17,7 +17,7 @@ use crate::{ DirectionalLightDescriptor, LightStyle, LightingDescriptor, PointLightDescriptor, ShadowCalculation, SpotLightCalculation, }, - material::Material, + material::MaterialDescriptor, math::{self, IsSampler, IsVector, Sample2d, Sample2dArray, SampleCube}, println as my_println, stage::RenderletDescriptor, @@ -181,14 +181,14 @@ pub fn sample_brdf, S: IsSampler>( /// Returns the `Material` from the stage's slab. pub fn get_material( - material_id: Id, + material_id: Id, has_lighting: bool, material_slab: &[u32], -) -> Material { +) -> MaterialDescriptor { if material_id.is_none() { // without an explicit material (or if the entire render has no lighting) // the entity will not participate in any lighting calculations - Material { + MaterialDescriptor { has_lighting: false, ..Default::default() } @@ -668,7 +668,7 @@ mod test { atlas::AtlasImage, camera::Camera, geometry::Vertex, - pbr::Material, + pbr::MaterialDescriptor, prelude::glam::{Vec3, Vec4}, test::BlockOnFuture, transform::TransformDescriptor, @@ -735,7 +735,7 @@ mod test { let rez = stage .builder() - .with_material(Material { + .with_material(MaterialDescriptor { albedo_factor: Vec4::new(1.0, 1.0, 1.0, 1.0), metallic_factor: metallic, roughness_factor: roughness, diff --git a/crates/renderling/src/stage.rs b/crates/renderling/src/stage.rs index eedc5d05..b1c19141 100644 --- a/crates/renderling/src/stage.rs +++ b/crates/renderling/src/stage.rs @@ -14,7 +14,7 @@ use spirv_std::{ use crate::{ bvol::BoundingSphere, geometry::{GeometryDescriptor, MorphTarget, Skin, Vertex}, - material::Material, + material::MaterialDescriptor, math::IsVector, transform::TransformDescriptor, }; @@ -56,7 +56,7 @@ pub struct RenderletDescriptor { pub bounds: BoundingSphere, pub indices_array: Array, pub transform_id: Id, - pub material_id: Id, + pub material_id: Id, pub skin_id: Id, pub morph_targets: Array>, pub morph_weights: Array, diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index 6c4cdcf9..75ac79af 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -399,15 +399,15 @@ impl<'a, T: Bundle> RenderletBuilder<'a, T> { self } - pub fn with_material_id(mut self, material_id: Id) -> Self { + pub fn with_material_id(mut self, material_id: Id) -> Self { self.data.material_id = material_id; self } pub fn with_material( mut self, - material: Material, - ) -> RenderletBuilder<'a, T::Suffixed>> { + material: MaterialDescriptor, + ) -> RenderletBuilder<'a, T::Suffixed>> { let material = self.stage.materials.new_material(material); self.data.material_id = material.id(); self.suffix(material) @@ -632,12 +632,15 @@ impl Stage { /// Materials methods. impl Stage { /// Stage a new [`Material`] on the GPU. - pub fn new_material(&self, material: Material) -> Hybrid { + pub fn new_material(&self, material: MaterialDescriptor) -> Hybrid { self.materials.new_material(material) } /// Create an array of materials, stored contiguously. - pub fn new_materials(&self, data: impl IntoIterator) -> HybridArray { + pub fn new_materials( + &self, + data: impl IntoIterator, + ) -> HybridArray { self.materials.new_materials(data) } diff --git a/crates/renderling/src/stage/gltf_support.rs b/crates/renderling/src/stage/gltf_support.rs index 928b5cf4..bd6920f7 100644 --- a/crates/renderling/src/stage/gltf_support.rs +++ b/crates/renderling/src/stage/gltf_support.rs @@ -15,7 +15,7 @@ use crate::{ AnalyticalLight, DirectionalLightDescriptor, LightStyle, PointLightDescriptor, SpotLightDescriptor, }, - material::Material, + material::MaterialDescriptor, stage::{MorphTarget, NestedTransform, RenderletDescriptor, Skin, Stage, Vertex}, transform::TransformDescriptor, }; @@ -150,7 +150,7 @@ pub fn get_vertex_count(primitive: &gltf::Primitive<'_>) -> u32 { } } -impl Material { +impl MaterialDescriptor { pub fn preprocess_images( material: gltf::Material, images: &mut [AtlasImage], @@ -200,7 +200,7 @@ impl Material { pub fn from_gltf( material: gltf::Material, entries: &[Hybrid], - ) -> Result { + ) -> Result { let name = material.name().map(String::from); log::trace!("loading material {:?} {name:?}", material.index()); let pbr = material.pbr_metallic_roughness(); @@ -215,7 +215,7 @@ impl Material { (Id::NONE, 0) }; - Material { + MaterialDescriptor { albedo_texture_id: albedo_texture, albedo_tex_coord, albedo_factor: pbr.base_color_factor().into(), @@ -280,7 +280,7 @@ impl Material { let emissive_factor = Vec3::from(material.emissive_factor()); let emissive_strength_multiplier = material.emissive_strength().unwrap_or(1.0); - Material { + MaterialDescriptor { albedo_factor, metallic_factor, roughness_factor, @@ -309,7 +309,7 @@ pub struct GltfPrimitive { pub indices: HybridArray, pub vertices: HybridArray, pub bounding_box: (Vec3, Vec3), - pub material: Id, + pub material: Id, pub morph_targets: Vec>, pub morph_targets_array: HybridArray>, } @@ -319,7 +319,7 @@ impl GltfPrimitive { stage: &Stage, primitive: gltf::Primitive, buffer_data: &[gltf::buffer::Data], - materials: &HybridArray, + materials: &HybridArray, ) -> Self { let material = primitive .material() @@ -584,7 +584,7 @@ impl GltfMesh { fn from_gltf( stage: &Stage, buffer_data: &[gltf::buffer::Data], - materials: &HybridArray, + materials: &HybridArray, mesh: gltf::Mesh, ) -> Self { log::debug!("Loading primitives for mesh {}", mesh.index()); @@ -771,14 +771,14 @@ impl GltfSkin { pub struct GltfDocument { pub animations: Vec, pub cameras: Vec, - pub default_material: Hybrid, + pub default_material: Hybrid, pub default_scene: Option, pub extensions: Option, pub textures: Vec>, pub lights: Vec, pub meshes: Vec, pub nodes: Vec, - pub materials: HybridArray, + pub materials: HybridArray, // map of node index to renderlets pub renderlets: FxHashMap>>, /// Vector of scenes - each being a list of nodes. @@ -796,7 +796,7 @@ impl GltfDocument { let textures = { let mut images = images.into_iter().map(AtlasImage::from).collect::>(); for gltf_material in document.materials() { - Material::preprocess_images(gltf_material, &mut images)?; + MaterialDescriptor::preprocess_images(gltf_material, &mut images)?; } // Arc these images because they could be large and we don't want duplicates let images = images.into_iter().map(Arc::new).collect::>(); @@ -871,11 +871,11 @@ impl GltfDocument { }; log::debug!("Creating materials"); - let default_material = stage.new_material(Material::default()); + let default_material = stage.new_material(MaterialDescriptor::default()); let mut materials = vec![]; for gltf_material in document.materials() { let material_index = gltf_material.index(); - let material = Material::from_gltf(gltf_material, &textures)?; + let material = MaterialDescriptor::from_gltf(gltf_material, &textures)?; if let Some(index) = material_index { log::trace!(" created material {index}"); debug_assert_eq!(index, materials.len(), "unexpected material index"); @@ -1217,7 +1217,7 @@ impl Stage { #[cfg(test)] mod test { use crate::{ - camera::Camera, material::Material, stage::Vertex, test::BlockOnFuture, + camera::Camera, material::MaterialDescriptor, stage::Vertex, test::BlockOnFuture, transform::TransformDescriptor, Context, }; use glam::{Vec3, Vec4}; @@ -1307,7 +1307,7 @@ mod test { assert!(!doc.textures.is_empty()); let (material, _vertices, _indices, _transform, _renderlet) = stage .builder() - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id: doc.textures[0].id(), has_lighting: false, ..Default::default() diff --git a/crates/renderling/src/ui/cpu/path.rs b/crates/renderling/src/ui/cpu/path.rs index ce4c6795..687afd5d 100644 --- a/crates/renderling/src/ui/cpu/path.rs +++ b/crates/renderling/src/ui/cpu/path.rs @@ -1,7 +1,7 @@ //! Path and builder. //! //! Path colors are sRGB. -use crate::{geometry::Vertex, material::Material, stage::RenderletDescriptor}; +use crate::{geometry::Vertex, material::MaterialDescriptor, stage::RenderletDescriptor}; use craballoc::prelude::{GpuArray, Hybrid}; use crabslab::Id; use glam::{Vec2, Vec3, Vec3Swizzles, Vec4}; @@ -19,7 +19,7 @@ pub struct UiPath { pub vertices: GpuArray, pub indices: GpuArray, pub transform: UiTransform, - pub material: Hybrid, + pub material: Hybrid, pub renderlet: Hybrid, } @@ -393,7 +393,7 @@ impl UiPathBuilder { .into_iter() .map(|u| u as u32), ) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id, ..Default::default() }) @@ -477,7 +477,7 @@ impl UiPathBuilder { .into_iter() .map(|u| u as u32), ) - .with_material(Material { + .with_material(MaterialDescriptor { albedo_texture_id, ..Default::default() }) diff --git a/crates/renderling/src/ui/cpu/text.rs b/crates/renderling/src/ui/cpu/text.rs index c9fe233b..fd6a0203 100644 --- a/crates/renderling/src/ui/cpu/text.rs +++ b/crates/renderling/src/ui/cpu/text.rs @@ -16,7 +16,7 @@ pub use ab_glyph::FontArc; pub use glyph_brush::{Section, Text}; use crate::{ - atlas::AtlasTexture, geometry::Vertex, material::Material, stage::RenderletDescriptor, + atlas::AtlasTexture, geometry::Vertex, material::MaterialDescriptor, stage::RenderletDescriptor, }; use image::{DynamicImage, GenericImage, ImageBuffer, Luma, Rgba}; @@ -29,14 +29,14 @@ pub struct UiText { pub vertices: GpuArray, pub transform: UiTransform, pub texture: Hybrid, - pub material: Hybrid, + pub material: Hybrid, pub renderlet: Hybrid, pub bounds: (Vec2, Vec2), } pub struct UiTextBuilder { ui: Ui, - material: Material, + material: MaterialDescriptor, bounds: (Vec2, Vec2), brush: GlyphBrush>, } @@ -45,7 +45,7 @@ impl UiTextBuilder { pub fn new(ui: &Ui) -> Self { Self { ui: ui.clone(), - material: Material::default(), + material: MaterialDescriptor::default(), brush: GlyphBrushBuilder::using_fonts(ui.get_fonts()).build(), bounds: (Vec2::ZERO, Vec2::ZERO), } From 6ef3dac4e148bd1683efeaf2e74e389d7ebf6781 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 6 Sep 2025 10:27:16 +1200 Subject: [PATCH 04/31] API rework and documentation fixed some tests --- Cargo.lock | 22 +- Cargo.toml | 2 + crates/example-culling/src/main.rs | 149 ++--- crates/example-wasm/src/lib.rs | 8 +- crates/example/src/camera.rs | 26 +- crates/example/src/lib.rs | 37 +- crates/example/src/utils.rs | 15 +- .../light-light_tiling_depth_pre_pass.spv | Bin 35796 -> 35796 bytes .../shaders/light-shadow_mapping_vertex.spv | Bin 32520 -> 32520 bytes .../shaders/stage-renderlet_fragment.spv | Bin 108052 -> 108052 bytes .../shaders/stage-renderlet_vertex.spv | Bin 44144 -> 44144 bytes .../shaders/tutorial-slabbed_renderlet.spv | Bin 44200 -> 44200 bytes crates/renderling/src/atlas.rs | 8 +- crates/renderling/src/atlas/cpu.rs | 322 +++++---- crates/renderling/src/bloom/cpu.rs | 6 +- crates/renderling/src/bvol.rs | 68 +- crates/renderling/src/camera.rs | 23 +- crates/renderling/src/camera/cpu.rs | 123 ++++ crates/renderling/src/convolution.rs | 4 +- crates/renderling/src/cubemap.rs | 4 +- crates/renderling/src/cubemap/cpu.rs | 24 +- crates/renderling/src/cull/cpu.rs | 171 ++--- crates/renderling/src/draw/cpu.rs | 184 ++--- crates/renderling/src/geometry.rs | 18 +- crates/renderling/src/geometry/cpu.rs | 453 +++++++++++-- crates/renderling/src/lib.rs | 462 +++++++------ crates/renderling/src/light.rs | 6 +- crates/renderling/src/light/cpu.rs | 66 +- crates/renderling/src/light/cpu/test.rs | 169 ++--- crates/renderling/src/light/shadow_map.rs | 49 +- crates/renderling/src/material.rs | 18 +- crates/renderling/src/material/cpu.rs | 469 ++++++++++++- crates/renderling/src/pbr.rs | 35 +- crates/renderling/src/skybox.rs | 6 +- crates/renderling/src/skybox/cpu.rs | 14 +- crates/renderling/src/stage.rs | 35 +- crates/renderling/src/stage/cpu.rs | 632 ++++++------------ crates/renderling/src/stage/cpu/renderlet.rs | 359 ++++++++++ crates/renderling/src/stage/gltf_support.rs | 465 ++++++------- .../src/stage/gltf_support/anime.rs | 28 +- crates/renderling/src/transform/cpu.rs | 406 ++++++++++- crates/renderling/src/types.rs | 26 + crates/renderling/src/{ => types}/tuple.rs | 0 crates/renderling/src/ui/cpu.rs | 110 +-- crates/renderling/src/ui/cpu/path.rs | 124 ++-- crates/renderling/src/ui/cpu/text.rs | 41 +- crates/renderling/tests/wasm.rs | 5 +- 47 files changed, 3227 insertions(+), 1965 deletions(-) create mode 100644 crates/renderling/src/camera/cpu.rs create mode 100644 crates/renderling/src/stage/cpu/renderlet.rs create mode 100644 crates/renderling/src/types.rs rename crates/renderling/src/{ => types}/tuple.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 7c6122ad..ba924263 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -853,9 +853,7 @@ dependencies = [ [[package]] name = "craballoc" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a2da5589f6c4076db520b5e1a96cbfbc954f5ef50d7ade9fd219860a8d8467" +version = "0.2.4" dependencies = [ "async-channel 1.9.0", "bytemuck", @@ -870,8 +868,6 @@ dependencies = [ [[package]] name = "crabslab" version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe77aba0fb1ad6ddb4d30744bfc61e1420a9cc1fa981b3556cc423506df9450" dependencies = [ "crabslab-derive", "futures-lite 1.13.0", @@ -881,9 +877,7 @@ dependencies = [ [[package]] name = "crabslab-derive" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32554318ca91eb0c2c6a05659ec2cd1627fd44142d54547bb3d0aa7405a979b2" +version = "0.4.5" dependencies = [ "proc-macro2", "quote", @@ -2213,7 +2207,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi 0.5.2", "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2337,7 +2331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.53.2", + "windows-targets 0.48.5", ] [[package]] @@ -3906,7 +3900,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3919,7 +3913,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -4242,7 +4236,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1961e2ef424c1424204d3a5d6975f934f56b6d50ff5732382d84ebf460e147f7" dependencies = [ - "heck 0.5.0", + "heck 0.4.1", "proc-macro2", "quote", "syn 2.0.104", @@ -5299,7 +5293,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 65e707e9..93154da1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,3 +75,5 @@ opt-level = 3 [patch.crates-io] spirv-std = { git = "https://github.com/LegNeato/rust-gpu.git", rev = "425328a" } +crabslab = { path = "../crabslab/crates/crabslab" } +craballoc = { path = "../crabslab/crates/craballoc" } diff --git a/crates/example-culling/src/main.rs b/crates/example-culling/src/main.rs index b9d1b0c1..68cd19e5 100644 --- a/crates/example-culling/src/main.rs +++ b/crates/example-culling/src/main.rs @@ -1,11 +1,12 @@ //! An example app showing (and verifying) how frustum culling works in //! `renderling`. -use std::{any::Any, sync::Arc}; +use std::sync::Arc; use example::{camera::CameraController, utils::*}; use glam::*; use renderling::{ bvol::{Aabb, BoundingSphere}, + material::Material, math::hex_to_vec4, prelude::*, tonemapping::srgba_to_linear, @@ -25,8 +26,8 @@ const BOUNDS: Aabb = Aabb { max: Vec3::new(MAX_DIST, MAX_DIST, MAX_DIST), }; -struct AppCamera(Hybrid); -struct FrustumCamera(Camera); +struct AppCamera(Camera); +struct FrustumCamera(CameraDescriptor); #[allow(dead_code)] struct CullingExample { @@ -34,13 +35,11 @@ struct CullingExample { controller: example::camera::TurntableCameraController, stage: Stage, dlights: [AnalyticalLight; 2], - material_aabb_overlapping: Hybrid, - material_aabb_outside: Hybrid, - material_frustum: Hybrid, frustum_camera: FrustumCamera, - frustum_vertices: HybridArray, - frustum_renderlet: Hybrid, - resources: BagOfResources, + frustum_renderlet: Renderlet, + material_aabb_outside: Material, + material_aabb_overlapping: Material, + renderlets: Vec, next_k: u64, } @@ -55,65 +54,57 @@ impl CullingExample { seed: u64, stage: &Stage, frustum_camera: &FrustumCamera, - material_outside: &Hybrid, - material_overlapping: &Hybrid, - ) -> Box { + material_outside: &Material, + material_overlapping: &Material, + ) -> Vec { log::info!("generating aabbs with seed {seed}"); fastrand::seed(seed); - Box::new( - (0..25u32) - .map(|i| { - log::info!("aabb {i}"); - let x = fastrand::f32() * MAX_DIST - MAX_DIST / 2.0; - let y = fastrand::f32() * MAX_DIST - MAX_DIST / 2.0; - let z = fastrand::f32() * MAX_DIST - MAX_DIST / 2.0; - let w = fastrand::f32() * (MAX_SIZE - MIN_SIZE) + MIN_SIZE; - let h = fastrand::f32() * (MAX_SIZE - MIN_SIZE) + MIN_SIZE; - let l = fastrand::f32() * (MAX_SIZE - MIN_SIZE) + MIN_SIZE; + (0..25u32) + .map(|i| { + log::info!("aabb {i}"); + let x = fastrand::f32() * MAX_DIST - MAX_DIST / 2.0; + let y = fastrand::f32() * MAX_DIST - MAX_DIST / 2.0; + let z = fastrand::f32() * MAX_DIST - MAX_DIST / 2.0; + let w = fastrand::f32() * (MAX_SIZE - MIN_SIZE) + MIN_SIZE; + let h = fastrand::f32() * (MAX_SIZE - MIN_SIZE) + MIN_SIZE; + let l = fastrand::f32() * (MAX_SIZE - MIN_SIZE) + MIN_SIZE; - let rx = std::f32::consts::PI * fastrand::f32(); - let ry = std::f32::consts::PI * fastrand::f32(); - let rz = std::f32::consts::PI * fastrand::f32(); + let rx = std::f32::consts::PI * fastrand::f32(); + let ry = std::f32::consts::PI * fastrand::f32(); + let rz = std::f32::consts::PI * fastrand::f32(); - let rotation = Quat::from_euler(EulerRot::XYZ, rx, ry, rz); + let rotation = Quat::from_euler(EulerRot::XYZ, rx, ry, rz); - let center = Vec3::new(x, y, z); - let half_size = Vec3::new(w, h, l); - let aabb = Self::make_aabb(Vec3::ZERO, half_size); - let aabb_transform = TransformDescriptor { - translation: center, - rotation, - ..Default::default() - }; + let center = Vec3::new(x, y, z); + let half_size = Vec3::new(w, h, l); + let aabb = Self::make_aabb(Vec3::ZERO, half_size); - let transform = stage.new_transform(aabb_transform); - let (aabb_vertices, aabb_renderlet) = { - let material_id = if BoundingSphere::from(aabb) - .is_inside_camera_view(&frustum_camera.0, transform.get()) + let transform = stage + .new_transform() + .with_translation(center) + .with_rotation(rotation); + stage + .new_renderlet() + .with_vertices(stage.new_vertices(aabb.get_mesh().into_iter().map( + |(position, normal)| Vertex { + position, + normal, + ..Default::default() + }, + ))) + .with_material( + if BoundingSphere::from(aabb) + .is_inside_camera_view(&frustum_camera.0, transform.descriptor()) .0 { - material_overlapping.id() + material_overlapping } else { - material_outside.id() - }; - let (renderlet, vertices) = stage - .builder() - .with_vertices(aabb.get_mesh().into_iter().map(|(position, normal)| { - Vertex { - position, - normal, - ..Default::default() - } - })) - .with_transform_id(transform.id()) - .with_material_id(material_id) - .build(); - (renderlet, vertices.into_gpu_only()) - }; - (aabb_renderlet, aabb_vertices, transform) - }) - .collect::>(), - ) + material_outside + }, + ) + .with_transform(transform) + }) + .collect::>() } } @@ -139,9 +130,9 @@ impl ApplicationHandler for CullingExample { .. } => { if c.as_str() == "r" { - self.resources.drain(); + self.renderlets.drain(..); let _ = self.stage.commit(); - self.resources.push(Self::make_aabbs( + self.renderlets.extend(Self::make_aabbs( self.next_k, &self.stage, &self.frustum_camera, @@ -181,7 +172,7 @@ impl TestAppHandler for CullingExample { ctx: &Context, ) -> Self { let mut seed = 46; - let mut resources = BagOfResources::default(); + let mut renderlets = vec![]; let stage = ctx.new_stage().with_lighting(true); let sunlight_a = stage.new_analytical_light(DirectionalLightDescriptor { direction: Vec3::new(-0.8, -1.0, 0.5).normalize(), @@ -208,7 +199,7 @@ impl TestAppHandler for CullingExample { let view = Mat4::look_at_rh(eye, target, up); // let projection = Mat4::orthographic_rh(-10.0, 10.0, -10.0, 10.0, -10.0, // 10.0); let view = Mat4::IDENTITY; - Camera::new(projection, view) + CameraDescriptor::new(projection, view) }); let frustum = frustum_camera.0.frustum(); @@ -218,20 +209,11 @@ impl TestAppHandler for CullingExample { let red_color = srgba_to_linear(hex_to_vec4(0xC96868FF)); let yellow_color = srgba_to_linear(hex_to_vec4(0xFADFA1FF)); - let material_aabb_overlapping = stage.new_material(MaterialDescriptor { - albedo_factor: blue_color, - ..Default::default() - }); - let material_aabb_outside = stage.new_material(MaterialDescriptor { - albedo_factor: red_color, - ..Default::default() - }); - let material_frustum = stage.new_material(MaterialDescriptor { - albedo_factor: yellow_color, - ..Default::default() - }); - let app_camera = AppCamera(stage.new_camera(Camera::default())); - resources.push(Self::make_aabbs( + let material_aabb_overlapping = stage.new_material().with_albedo_factor(blue_color); + let material_aabb_outside = stage.new_material().with_albedo_factor(red_color); + let material_frustum = stage.new_material().with_albedo_factor(yellow_color); + let app_camera = AppCamera(stage.new_camera()); + renderlets.extend(Self::make_aabbs( seed, &stage, &frustum_camera, @@ -248,11 +230,10 @@ impl TestAppHandler for CullingExample { ..Default::default() }, )); - let frustum_renderlet = stage.new_renderlet(RenderletDescriptor { - vertices_array: frustum_vertices.array(), - material_id: material_frustum.id(), - ..Default::default() - }); + let frustum_renderlet = stage + .new_renderlet() + .with_vertices(&frustum_vertices) + .with_material(&material_frustum); stage.add_renderlet(&frustum_renderlet); Self { @@ -269,10 +250,8 @@ impl TestAppHandler for CullingExample { stage, material_aabb_overlapping, material_aabb_outside, - material_frustum, - frustum_vertices, frustum_renderlet, - resources, + renderlets, } } diff --git a/crates/example-wasm/src/lib.rs b/crates/example-wasm/src/lib.rs index 30ba1cbf..4fca3d2b 100644 --- a/crates/example-wasm/src/lib.rs +++ b/crates/example-wasm/src/lib.rs @@ -1,5 +1,4 @@ -use futures_lite::StreamExt; -use glam::{Vec2, Vec3, Vec4}; +use glam::{Vec2, Vec4}; use renderling::{prelude::*, ui::prelude::*}; use wasm_bindgen::prelude::*; use web_sys::HtmlCanvasElement; @@ -27,7 +26,7 @@ pub struct App { path: UiPath, stage: Stage, doc: GltfDocument, - camera: Hybrid, + camera: Camera, text: UiText, } @@ -105,7 +104,8 @@ pub async fn main() { let fox = stage.load_gltf_document_from_bytes(GLTF_FOX_BYTES).unwrap(); log::info!("fox aabb: {:?}", fox.bounding_volume()); - let camera = stage.new_camera(Camera::default_perspective(800.0, 600.0)); + let (p, v) = renderling::camera::default_perspective(800.0, 600.0); + let camera = stage.new_camera().with_projection_and_view(p, v); let app = App { ctx, diff --git a/crates/example/src/camera.rs b/crates/example/src/camera.rs index 785b365e..beead2e5 100644 --- a/crates/example/src/camera.rs +++ b/crates/example/src/camera.rs @@ -1,9 +1,9 @@ //! Camera control. use std::str::FromStr; -use craballoc::prelude::Hybrid; +use renderling::bvol::Aabb; +use renderling::camera::Camera; use renderling::prelude::glam::{Mat4, Quat, UVec2, Vec2, Vec3}; -use renderling::{bvol::Aabb, camera::Camera}; use winit::{event::KeyEvent, keyboard::Key}; const RADIUS_SCROLL_DAMPENING: f32 = 0.001; @@ -68,10 +68,10 @@ impl CameraController for TurntableCameraController { self.left_mb_down = false; } - fn update_camera(&self, UVec2 { x: w, y: h }: UVec2, current_camera: &Hybrid) { + fn update_camera(&self, UVec2 { x: w, y: h }: UVec2, current_camera: &Camera) { let camera_position = Self::camera_position(self.radius, self.phi, self.theta); let znear = self.depth / 1000.0; - let camera = Camera::new( + current_camera.set_projection_and_view( Mat4::perspective_rh( std::f32::consts::FRAC_PI_4, w as f32 / h as f32, @@ -80,18 +80,6 @@ impl CameraController for TurntableCameraController { ), Mat4::look_at_rh(camera_position, self.center, Vec3::Y), ); - debug_assert!( - camera.view().is_finite(), - "camera view is borked w:{w} h:{h} camera_position: {camera_position} center: {} \ - radius: {} phi: {} theta: {}", - self.center, - self.radius, - self.phi, - self.theta - ); - if current_camera.get() != camera { - current_camera.set(camera); - } } fn mouse_scroll(&mut self, delta: f32) { @@ -194,7 +182,7 @@ impl CameraController for WasdMouseCameraController { } } - fn update_camera(&self, UVec2 { x: w, y: h }: UVec2, camera: &Hybrid) { + fn update_camera(&self, UVec2 { x: w, y: h }: UVec2, camera: &Camera) { let camera_rotation = Quat::from_euler( renderling::prelude::glam::EulerRot::XYZ, self.phi, @@ -204,7 +192,7 @@ impl CameraController for WasdMouseCameraController { let projection = Mat4::perspective_infinite_rh(std::f32::consts::FRAC_PI_4, w as f32 / h as f32, 0.01); let view = Mat4::from_quat(camera_rotation) * Mat4::from_translation(-self.position); - camera.modify(|c| c.set_projection_and_view(projection, view)); + camera.set_projection_and_view(projection, view); } fn reset(&mut self, _bounds: Aabb) { @@ -258,7 +246,7 @@ impl CameraController for WasdMouseCameraController { pub trait CameraController { fn reset(&mut self, bounds: Aabb); fn tick(&mut self); - fn update_camera(&self, size: UVec2, camera: &Hybrid); + fn update_camera(&self, size: UVec2, camera: &Camera); fn mouse_scroll(&mut self, delta: f32); fn mouse_moved(&mut self, position: Vec2); fn mouse_motion(&mut self, delta: Vec2); diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index 38ee987d..d753e265 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -5,17 +5,15 @@ use std::{ sync::{Arc, Mutex}, }; -use craballoc::prelude::{GpuArray, Hybrid}; use glam::{Mat4, UVec2, Vec2, Vec3, Vec4}; use renderling::{ atlas::AtlasImage, bvol::{Aabb, BoundingSphere}, - camera::Camera, geometry::Vertex, light::{AnalyticalLight, DirectionalLightDescriptor}, prelude::*, skybox::Skybox, - stage::{Animator, GltfDocument, RenderletDescriptor, Stage}, + stage::{Animator, GltfDocument, Stage}, ui::{FontArc, Section, Text, Ui, UiPath, UiText}, Context, }; @@ -113,15 +111,9 @@ impl AppUi { } } -#[allow(dead_code)] -pub struct DefaultModel { - vertices: GpuArray, - renderlet: Hybrid, -} - pub enum Model { Gltf(Box), - Default(DefaultModel), + Default(Renderlet), None, } @@ -130,7 +122,7 @@ pub struct App { skybox_image_bytes: Option>, loads: Arc>>>, pub stage: Stage, - camera: Hybrid, + camera: Camera, _lighting: AnalyticalLight, model: Model, animators: Option>, @@ -147,7 +139,9 @@ impl App { .with_bloom_mix_strength(0.5) .with_bloom_filter_radius(4.0) .with_msaa_sample_count(4); - let camera = stage.new_camera(Camera::default()); + let size = ctx.get_size(); + let (proj, view) = renderling::camera::default_perspective(size.x as f32, size.y as f32); + let camera = stage.new_camera().with_projection_and_view(proj, view); let directional_light = DirectionalLightDescriptor { direction: Vec3::NEG_Y, color: renderling::math::hex_to_vec4(0xFDFBD3FF), @@ -230,10 +224,9 @@ impl App { let mut max = Vec3::splat(f32::NEG_INFINITY); self.last_frame_instant = now(); - let (vertices, renderlet) = self + let vertices = self .stage - .builder() - .with_vertices(renderling::math::unit_cube().into_iter().map(|(p, n)| { + .new_vertices(renderling::math::unit_cube().into_iter().map(|(p, n)| { let p = p * 2.0; min = min.min(p); max = max.max(p); @@ -241,17 +234,17 @@ impl App { .with_position(p) .with_normal(n) .with_color(Vec4::new(1.0, 0.0, 0.0, 1.0)) - })) + })); + let renderlet = self + .stage + .new_renderlet() + .with_vertices(vertices) .with_bounds({ log::info!("default model bounds: {min} {max}"); BoundingSphere::from((min, max)) - }) - .build(); + }); - self.model = Model::Default(DefaultModel { - vertices: vertices.into_gpu_only(), - renderlet, - }); + self.model = Model::Default(renderlet); self.camera_controller.reset(Aabb::new(min, max)); self.camera_controller .update_camera(self.stage.get_size(), &self.camera); diff --git a/crates/example/src/utils.rs b/crates/example/src/utils.rs index 46ce02b7..b51e00f4 100644 --- a/crates/example/src/utils.rs +++ b/crates/example/src/utils.rs @@ -1,23 +1,10 @@ //! Example app utilities. -use std::{any::Any, sync::Arc}; +use std::sync::Arc; use renderling::Context; use winit::monitor::MonitorHandle; -#[derive(Default)] -pub struct BagOfResources(Vec>); - -impl BagOfResources { - pub fn push(&mut self, rez: impl Any) { - self.0.push(Box::new(rez)); - } - - pub fn drain(&mut self) { - let _ = self.0.drain(..); - } -} - pub trait TestAppHandler: winit::application::ApplicationHandler { fn new( event_loop: &winit::event_loop::ActiveEventLoop, diff --git a/crates/renderling/shaders/light-light_tiling_depth_pre_pass.spv b/crates/renderling/shaders/light-light_tiling_depth_pre_pass.spv index cde999c78808a1a4bd260902ab5714fe4b5a4f4a..e2bda6eafd6f2321c8a7c13f5e01ab4cd57e389e 100644 GIT binary patch literal 35796 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 TD>`fY_jt6O|HG%0l^FjIH4MnO diff --git a/crates/renderling/shaders/light-shadow_mapping_vertex.spv b/crates/renderling/shaders/light-shadow_mapping_vertex.spv index 43da3b39877d09d6c4e91872e122d1a25ff40eab..7d93a99a0b355b070c81cb5d8d00568a08defe7c 100644 GIT binary patch literal 32520 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 KJ)iK_ru`qdt8gp; literal 32520 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 literal 44144 zcmZvl1=v>A*0o<06T1rp)MIydcY&?vsK>yLqaun4hy^0pO^Ar12qr3acXxLlyY=(< z-S@*D|Ct}xzb}?+%rWO0bFQ`5+E2VMIOP-zP1812ySBErncMD}nT~7Lwkg_V?BAcG zt*t}b)Gd3{t+wB4nWK8{yUa=}FK66LZByE{{yTHqTrE5W|2?YbUiTGnB+$3r*@;@kfD;cf2u6H@?J#bB=P8blbOjYgmG2UTe_y((XxLb(d**{+nA} zx#%Xpob{TkGc9pbHk^wow=BI^ty3;~eZYx}-g^zFhF2Xcm$B=C9V?fyeF~Rah7`_q zQLhgo8SA~18`5wqg1u^9x#XP%>{z+v?F@E3kEZ|ceQn>?tJscN3EQh`%T2B=SG6;C z%4V!{4wpHtSGdfnTj8wBy#Fkm`&I4$n)R#i{#deQPf5jXZS%Bn`xfp3_A*vq*OoP@ zmX#ZO+Gid$>+9;1Gwr~xs3Hpc}|>zd)WNqPBbrV=c4TxZO3SvOWQN4?Hsi| zliH5c_PlE6?6?lv&QrhVSlhgFVjn}_nda3Q`&fE&%XcJ;XI$I~?3va!t~b3}a&zH3 zuEn>t&5iGPu(mZDdjh@n%IiOoUcWW!KZ#zy{OpW6nZ655AA0eU#8^XLnsqOL?X$#q zIW_vxy9V-!?+^CUHs7f&>%aDCExXUUbCC0NusUbZJ1_G^X8^ceu?K>kTPNauh8df9 z^PEL%YwL4w@(ya*ZR@IkHrP6?eF^4h-odoR8|*nx-gCfzaXIc>uxn(VHL<-diTl^O_SU&kK2D{%}-=6gP@uH= z#&{nb-w8#}x$!nRW9)5eUq-LCb~`F`O)saVuA$(66nhxhdBi^)>{`Sg0rnoMWzH*$ zZzOmY+EQe+_E9wVMQxsotKmA++O^uG`!pJy9M^#7p)JK)SoauO)rkJ}@b0t!pKol# zSAWLcP{za`-?-vaSHC{zI-X`uwbd{-HBSKh{BX^0r+3ZW6Y<{xp7i{f^t#}@T%+6< zUn?fkGUvO&=1!A0<{p~sVQypGPrjzO7l$`?FM4xpcOvUb^fjM(9b=r&4V!g8LT}yj z+K)E2u{js+4ey(_ ?s?uX3tG4Ome_lJ3(q`7x}rdvar=X(`w_oFRq{4{vfWX)Qh zg`1k@eOMDcZTFg-V~lyOv7Nj1d9L+abI!5zi|w=1Gg)o#VQkOwjFZ{k!|L}npxUm5 zw(DUXFVd)P{p_zpXP(5#+fJkDbBzzf=X15TrI@Shb9mz$4mRF*Jc3)N}&8HTfLP{yPb7s$!pv?LCjb54QI#c3*7oaqNEB zGZp(3Z2tT||Ct!G7JC5pY{edkJy)?Wz@EL>7h=y*?2EAHEcV6Na~Jy(?0JiQDfaxu zz6^VTVqcEkvDjB&cPjQ!>;;QG47+o&hhujs_6Y2*#l8}Ip<<83UbEO&VQ*jTQP?{a z`)ceRi#-~9r($1&y>qdz#ondZW3YEE_I23175jSZzhk>ce7=mu_AJ;|f%83&?=QUi z(0;|5wf&^$!z0)W6X$;MdExV~Q?W0>o{iY}`(e*sY{$=4Y{$>t*uU^p=;X%Z`UBjb zenD*W+pkSNpWz*e_xTaK6E=U^HllX@oiW_sUh8wV&Y{!od@~(%S zvHCN1eXzca-2m)Z&wa*jh@G+eGj=1ezKq=r?AQrq?B>`Rt3PA60PD-xZeYjy3`ySZ z*cq!oW48nA%h(;jjvZ0*?uebS`ZIPXu)d7l8SGe}Rmr;xcE;+@*j>T;GIn>cV|}h= z>>k(|t3PA+1nbM#e}WzBGcaTK!p>Oz8M`-FU&ihScI?P9-~F*OR)5AG0M_Rj=}qtT zdt3X~emxHRc$(+LejQ?bKKnZQ8=Ud_jML}qy?L|ePXxPvd@WS}B(RtI`c9_xp{Zei z0~LB!`hh)r?jOgULht1`ef?>t(i~@>d7l9`pJT1hamE;5ZTX*gl6a;EfLpKC^p00A zb*#g)p)gZB_OcFr>(SPwnZw>3#%Sy7$9&AOAviiWHFMku&fNOyILBL?>#zyf zIJE|2o5MQJVw{(C7&8d_Y?^uP)iXw0U-r*naQ1+?vj>KN_0@5X&l;TrHb$-fF$WUa0MXRVCOS`7v3JAoQ~k2wr1mpX=njjzx25!lhv zAFV6F`l2-wEElb-z-kR7PwEa(Rv)LFIrE4Zmi}mc3f32`&%kmypPz%BxAmGw zfAV|*HjkeheZMj{*w6jGK70lC^}^oQ2S4|J4feDD1@zz0zNP)#*1qk#1{2a6`#rW} z?YmR8ulYZK9q$$H$A)VMH=a0O<9~uPR-dndKht~p8mR9V+OIbB?YHB3Zf#SsIQ{AU zKGDlLIMz7FWX@9%r@pU889ODMeCqS;so5URIOD6Hx>*y~!SUvByfwu)HM|=7tWRI& zJ`J{huW-{goa^EJyqbPGIAdLl>6`dJxF7Nz8hZwM$IM9YeC;#enZe#?wX>II0rRJ| zUi!0_W(Dh8AMg42X9LgOjCFr#8{=A7i@D5QZELEwaX<0>iuZPQ@MwBt2Gcus2)*?> z#{HzGz4zOA_n-Sq-ridMergVU)|PqBiS1tYI}dA}3+#7N>du4D@%Fhl^Mc*WYR(6q zpXOd(puwbQjqQl-So_?kPGHA-gR#>)XRJQ&Ul)2W=ccbKZ6TWa_Suiif%_9z z_p)P+b4=#EG+6z*mzTkoPkq_T%QkVwyC%`I&ziUnjyH$nttr0c!D{HUK7E<{3Sj+S z;Z|(8x|dgiGuE|Oxrui#%dgVdtI|7WHG1c3pZTr<_CBkfy}TxvKdtrBpS`>mSYMut zYlG$7+qVZ8`%6uG@4xZx zNB5h&y|wpZ%z9vJ>&CZ(D`BsXeGRtnwO*t7On3hq=X)97Bji4B2-lx6yTX}wBW(5U zb1ydr8)wctsGghB_ zVOx4H*F|49T6dcI_Bj`OfSp@C7mhW~G1(`72diJt#Xqp+Q(x9=_a@GG*DHGVSufYf z@#b*6HO03lSPgyFr!RB=Cs@B%xV;*#o{PQVjCC#cY2rN>^7}S+4|>P!NAG;?^SSW= zu)5xJH4X%Oxt{tCq8&_goP9nw9t!relw-4Yhkzer`0z z@#aWv|KRg@XY|a|njf~8wdvb~wmZ!n_U729vGwIUgT27f$#({O!5XKI*d6AyC=;$?A0?yTVI|xM}zs(+K1-O^QISAU)J#$uzvSo#vY5! zpVnCY8QUAIFMIMtuzK>f4(rLj>jyT@+WbD*nzP4F0qge)*T3Q1L%BCcGw*Y`H~L(Y z6S2Kq6MZMpdeK}1`|O+EU_U20HuF6W&b<1pSuMw@QEmC`o0Guq8)F=Aj?{K0xHJ0Z zv9=-DUe=~>AZ-B69QNigMq6L@&Dr4SWZw*iGq=7v&hgnd=YWk<%Y9=G>o~JnSL-ll z0QNvyD=)oz#=H+fO=c6Tn`cHGQ|!?x1@&Z+zZoU3ez*Gw*ci1>#Wts}FMgl;DA;@JC1?C&*z#VdHr(Ub>gY?{6JXs>$8r;zEonZA+ayR z>$8@ele5^{=2J(%?_qs^{R&uLa%TNrg?Ig|A@h9=Tiz@4eI48R>Py@kVB_lgy@_p{ zzQnx+HmxT#hAr=vHTb;Y>N`x`OuHVn_`m80fzm{0*$oGL~ zvv$^@zT=F`+WrpK?;1PC=fFP3(D$IP_P&$Z#`#&;J-#{kNqS@K9jo?zw0vIv1MKHz zV+J=deqJ`lJe$&+*WTxy@f*>$Xn6ZP|7Ya~tq1VDuCJA|!4cAW=IPHfZ+5W0{7iNZ zuw0(?^Mk$2sc!*VN1Cj z%l+85i8J2yik^Me%QbSmIUH|I@$CmzL!b5O%iQ+|>-P$GK*PBnzSp{%{y;cmU5kV0 zz5LEc{@}(wgx)cS(mP*!HU0j(OLPC(rmg$$?}o``y$>hWyuq>#a}wNSeC# zu7memTi*ucIiL8hXsWGN_IyvUystIxfuphAt6tWd=TGuhU+m znZw>3#%SxybM-B7bn;w%8_wMN>Nv++n`h!(uyJY)#x{rR)Q53i)?rLv?0z)!+N)=b zw!S>yP66i`W$xUs{$PD|oa3`br-O}A%e68`*617ZJ2!upZEZheds&;l?`YrBti|3O z#%Sxy8vO{4PS)rrICJZ(;~bwg`bA7r%QZ5Gb)3mKFY7R70QNwddF|CRMq6Lj=qzy7 z$lO_@L12CPEOa(lE_-h<*!cQdGz2?Z`lEFYSYNcx1>8eZzX0y|pzqcs$) zFIvOEa?u(NR_p(K4}%>o{n5G-Jc1Ujkzl!KT?JOFZ>eh(cC_?I>uRvRXpIKT<$dur zVCQYU=Fy)#*MiMc-(QZwP9FWqa~)V;@>~y=i`H1MTL0&}80={2kJdQw4YX*D2g^n4 zMzC6bN1AP2M&?mnly0?MdW3G=e^;~(rJg3Ip4mQ@a z=HCnP4CZ-$2Y7RuuMPF};ZC@oH2t3GiS%BcX?=Im?xuN$?W1=OIC{qCd+B@O{rw9y zvqtxUjn`-G=1@=VYRl(&_yE}FpfQd&cb8WmI*fT3`w^OX?bS0zTVM9e zqu}fpb7#Li2G*DT@;F#7>-q%P`1(A25<6P@qxBS6U$mYE%SG!Muv+zb_$+p`^hfJC zu)b(L50;D83t+YCbMHm$Xz7pEOJIG`dKoO2XTmFB=WV^_(Vsl8g3U9WHP2eUhMhe6 zljn7?zT|lWEElae!D`iK;#=6!(jTq2!TO^04p=T)?}F8;&&2nzqoqGu?}PP4>jSV{ zv_1r@RiAqwVMj}Uv_1ywi`FM#xvb@`EElbB!D`jt6~egMlw>qoF!^>_Au z!j6{yX#EV<7p-5wa#_n?!Oq)y&7(hgegm6lMA?_WV<(UPoFR;F7@v_h+7p->KYSrJ{n*uIc`lB@^SYNc-gXN+%6oWZdtH%Q6q87ft`!FvR{@5JKlKxr=pYi6|kcb z-4)?nx0-(?Z1d|&+{$3r!?`BcDquB@*Ke-GuZo@8l7BV0Xe4fRIP<#(iCY6~etpTc zCRj~1^qVXDZ7po~rq|ic{#_f}wa}Nib->2CFB7*ew)4=Jxb?usxmOdnKDIUJOWX!v z&yH8P4I8fR{f!zfd*AalBWKYw>6NiFW6M`=7HsF@mAyJEoV@WFJ6jWH-o(ugCtu^{ zXyU9TadX1S*SNWwIL~I{=7y86ar0tZbDi&e*siNr#?B8XZ+vQApoyzBcZ8F#ah;mD zTJwT%@-?n=6IW~Q0w-@=_FPx6YiLd3_*ZV)Trcy7TNv!xm@C{OVAnz2%wtioYmocv z^KLP0_l#H8U~xEk<1==NCa$i*l5p}hZmA}&uEEl9@-=RmCa$i*vT*XoWgg3cT?cCl zw>;Q&Fn_oez^;S2!mS8)9n{S{RtCEUHSem}o)LXngVn*Fk;<(J=NXYpj&;D+s7APT z!Pcloxb?u+s7AQ;!Pcl=o*x^4)l|bV##p;&aYL|YvF_oGvE{u|`=;2QJAL6c2YbdU zw!~Gp>-Rh?1-NDve_u-z{?rVLic`vYgxN`eoyI(8U1KYhRm%RIdty|r2 z`-81p-Eaqhty|r22ZF6z-PC+A*qZC!JQUl#sV_AjZro(t5peEJjG!I|gix>Sb>p3szGN#~72n*&Ez}R-Y}$W6RgQc_OxZQ(xwDGT6OYxxU!$ z&B~pE?cS8jnw<(ZN8OvJW4kx?CC8ay_h#h=V!JmhHwfFkDVMc48*JU`h8qmFZgs;A z5!2KScMjOP)lJRkfvvgj%?q&IoBC4oMPT=4+ z!wm&nx4PkmfvsEJ)I0)g&2?{%#CC7$OU=%ig>Jtfm@{F(!L+9Jm9`+B2UUvE}RDycyfQsW0=n73|)u+yrd*X65d{ zc5lih$3(C>>fXE?+r6nTIqn6!H!F8PwtKU34`RDF<+2tJfvsEJa1Vp6TitMvfUR5I zaF2qmTiw+BIM|x&-h2|sB}1i(usB}1%V6tPH#NTsw&uDwU&nTD>PyXUg58^ydmGNZDVH4Yfvr)EaPNbyQH^jPfUQxD za36xLQN8TVkHBiG;TU85uJKcPFTZO%oX@q|pV9no(caI<-Ql(M`Ljg-&c)yOnV~$P&V81+AK~P!DRDnFao*d+{R}5>ovyLp8~g&c9&@QvUwmQ&x}@AKUQzcViP$oLK5pQHZ+eir)v zP0OD7A9#JYa6eDS_a|5ldGr2<-pjoD{?g_jS2C}?^E5_VU+QRwFLk&NQpXhVsl)HP zQ^%C>`cg-Gup08#F%`X+b?BR#HVw_Z_SRvHw!YLcEjV?!&r-*9@Tp@UeCn7UUSI0y z09HfZI%c5vvJQPS(q^KW*WNme(bktbW(KDY_i^f&1wM87J$veyRi2hQW&^7sUvro% zKhKyQY@B&Vqh&qUa{o^U-@u-+UiZ`xT3s*KEgExz)lpXs*EYVn!0PBzBkP{~Z=cw? ziBU^!b=)iQ%>!0TpE~+d=Q#BBTc;YXc}IFL*Ia)m>;-AAvAuIKMq6LjybIVhcmH{1 z&AY<8=I%ewL)LsDczs#(g~4jbTgM{wUe=-SZ?r{e=C!vDW3=_9j>W*Kqn?Gu;ZsLF z3roQ3OC3vs)sVN2rRY%F)tuJ+K3r-#NEOdiU9rY}9hu4=nwsSm9-a59Y zPaXPppzTOAuf25`qpdG>>;z67^(^cRpE~MU*aco+>ev;mhP-v`MxQ$L{hjs?ntAQ5 z!x(LSsbhC=>ZoU75BStk&%&PY`clU~!D`6Y9OlX%+Y4-*dEI~3lRb75d&qj-V?$_l zy;qOuT{T?W`1S>>qfd>jd+xt|VtatqQd=GON__i))zYVqzSMa$`ueR?4cGi& zdN22&{zI@2rMbrT&czsQeOdFv!LGUM?Ul3eFL>A7^{!{(2zY&2^CQ7($Xmxz^j_AX zuP5zjntAQ5!x(LSsiPM-b=0$P41DUSXW>|QeW{~2SPgmWIF3Gb=sTWv0?oYk)?tjc zzSMCdICa#sa1wm#sAu71czvm(4_FO(>*!0LI`s9UokBCOy>%F)tuJ--2d9pD7EXmv z9rY}n2Cpx5oDNn)zUDAj_ShL<mD0ItLx>uMPmS19d*@kZQ~mV zR!5&2S@+z3`^26FR!ePl+$-@70;{D@9et_uR`m5-ryACoeQqC(bHT=%Q+>}wG;V|U z%&3vMZiL@^Vjqq3!Rn~1#wNvg0azVAgH}`mewqN;9XuH5j9IX{=pH6!n9;l0Am-Eh$}Zk~pVp4_|*SM?TvvmUSLb!@n**Qw#E z-hvHR^}512m#Vi=!&SY78?Ndt(r{I8F*w(u>Mh=IRd0!gt9nZ|oO=1*W+^yx>kGFu z*xYL5=dsIxjn$X9Wx>v+j$IDhvDTEa%Y%*8m$55=9czwoD}t@1j$H}cSbd3G8SJ{& zysKcF*Y!!>Rl&yU%h=Vxj;(oD$2M;ry9Tzg`Z9J+uw$(++*)AgQOB;0ZLGe;tpj!+ zxsKu11-p-2pVYh_*jRmuTOaJ+axMIx#=W}%*jRmu+Ysz|&=+nauzR}Z-5A@vu21rA z0yb7(#%>BWuWOOKn}Lnhm$=Qro;iKd+X8Go`VzM#*jk)#xUImhORZ&VY-9B$ZX2+* zxVEWfTd=YE64wpvS=X1i?qKWDm$>b~*5aCm+a7E!&NuVe0c@M2 zaXW*3#^{UQE@11?m)F-V`HocH-)HbSJT=&>^%($Pd+e>~eeT-d(|o72bs6V#-F~p~u?j$&$3$|#U3}>vq#PtLF?6D>86gXq`CGIq^&o^7* zPKPsAUurx9oEr7#cc;$;yS~oBmNq?xXKM~#$}IQi0$PbRpT7m5Sn|` z-uDK^XzR=Sjyt%w>JMgY-XA5-KJRNT0vp@XHMVHn39nxb>+;OB{!#L#9{oe%FQ=K` z-g=DD)^|qp932MsthhGehBsWV!i{J+*Dm*D6xj2mM!3;n&r{{Dh4buGZY-R8+FThs z4(y(;+>LPV-^$$z=U%g>jGX{>uT}02IQNy@UCj4%=6NSrKKJn#u$T8y-|MuAG}p;K zd+jc;^*QHocY|F!^`d`|m=^t4!Cva?dy;l9O?~@l-3M0BvDwS_gR__Q=l(nZ9)za; zJXaqCyH>74*5o0uyzz;980`9aPZIYCSiZ(RitWAhJ|*rku)J~M9tT^STz)3?1lZi_ zI>s3HpKIZ~U4zu~6nOG^KMj|8>(9KO0XuK~S+{4w&c!*Ursu%&#wYH1@Z{_B0-U^Y z8T%sGoN}r0CGg~H@iLseahdlkU~{XhjxlxK&foLx&$nI!8}C}UUhV~Bf1!7c+=t2k z1~_{!+?#Nd@4dI+jLqKr3GC(G)Au>;ZJPS_S(|sj>Nz%h?_F^2f&Scs_rTr*{Tcs0 zc=Gl608ZZctnG(jwd6APBk<(+<)c8Gk z^7Z)vPTsi8`$w?#m`fdF>b#wQ_TJB6<6R5a%e_$do_jE{zk-c-ynEI?oY&O1%D>ZvBs#K*B*Pd{rgDmz{Z+yBKGC<@lAnGPM`lj4}EzJorvvg++h59 z4fQ>v_qRR0`C{8ga~iN(#;9LwnHJl8`m8HHUo)n|Hjh4Y>+>~t2IIIqU&eHxO;589 zd+RVpTVJ*1Q`d}OYcs|=9P4Lqe=mI|uzoK&pB*zdoclC!voxHacXJLAwOki-SjQM@^s)|PuEV~*so!2bW2{48{!Y?Z@KlWR zyJ2(tb3^}L^bPR(^7kUff#v!Tt$#e&c)!by){St{(jTpx!1|(fGgvNKw}931``BpR z3KuQ?(Yg(+FIp48a(OP?4z^Zv=u3_}z~=C~*5tSoE;;lk$3(EcxmjgQv>pbl)wk632wb%EN9$3r zzGyuLmdi8!aj^5YUi0Wro+rTOsekY5Nx0v^zTv|a$KRsU|+i*V7>AFY?b`l9tRST6hM6|l9MLtmb2uY%oUu8%SGTzS6o zOnMz`tY^)?@0v51XNrAd-vAr$c%NlHfAVZShO?~SE6?C#8?HWsdpBJD&ha=nV>8z8 zD2{KqjFmf~;p*5E8_w@5^Zw!_I5lnIP6n%K3)cs%rY-MR`hp#&M!0?rr$)F_8cvOH z{lV(jxKkUh#+?Rd&dQyR?ObZ!Ga9byo!M}X%{&Hx&8=?U6Ajd6P4p%1EUR9aIRa;e~vceT0VBR_wQUd*TcCc*Lh$yjc@shi|+Yw zsV(_0fQv@rE`&3`Ymm5$z~a<5w3CD`swul&B=rP!{8zQkPyHqL#S zxXZDfhrYyJ0XELPnz*6Z)}SwO!@!;$uW-W~uI~L24VS&|`<}NrZ~ogkUK#rioP6cp z#da=U*{kot$s3=s?>BMgP22}?@-^&Uz1LgOm5l*g3G} zZMlbYf{m;9aBggQTh?tJu;cY*?7U#d*84g?w!AH47XUk6U%p@H2sWqRf$PuD0y=^9 z`TX)d^@3n8-&5=BOzT4PJ+ys3pDzpcndn%bNv_LsVC&Q8djz!{r$)8qeIMYM<-ud< zjd8p=oUi*~1+eQ}e;&CaoV-`oWu=C5e&JSbIM*usZWTDk8?Qh2>00iuye-`IaK_oP zu4Cbh)t9*OV6|+CyAjSxsF-Z2T?gPWH|SzT=e>Y&82! z5w0KD+-hWx4gx#gc>T%!4QnrN3->*oajnMdfbWlffHPKK;(i9JWlQc~;EdImJ^Cv+ zdsKh+=x<%J zVE3pojyH#Uv;&;J?8m|Ax@YTt90F%d-H+$M8LKa2&u!xB*z@4jt7FfHGge_u*nV$LUMlrC@W^xXa+IOhn~zuR^XzR;&uARWq$#<>`!kJHB9p`xWr}?{pjZ@3-T+Lw}H#5%5I*hpm`&OEH?bS0z zTVLjV8#wbecji3-tS{e5-42%PL$u$y-T^j#061EAVn<7Vv?hY}Me8oGT(s^6t5v^q zy$3s5`lEF(SYNd61ItD0ez02gyVVDmjgQzDsx*?7XelJo=O85wLlN zm-#=6ojm%J=P|IpecC_?I>wU1kXng>d zi`Iu=wd%jA^$~Wo^hfJsu)b)00+!2KehPNp)@vU9$@3Z5JR{2e{~SAc^e4|3V13E+ zC0H(6{|2j7|4ps0u%o3vT3>_pMe7@|T(rIgt5yF^t?#g-r9WEVgY`x02e4eUegvyk z|4pr*u%o3vT0evJMe7%^T-Neeu=BQF^XS*N4D0tB*k^!y*EKgbHT({?hLL5R|G-WS z`cuRIfc2$@Kf!X*`VUyG`v1`U3p-l+qve}rebH*?n`c_IrU0wu|0grg#6<97>Q-jsIplD447cKqKnii}tTGN5$vd+_kowxOxM}P8k0GsE+l4l0vm|B0D z{^XevtS@|Z=*4$vVE-qU0z(q@cwB`lti`IN#xvb^5o=du)b(51eS}|!eF%?D|Iab7cKqK`WskZv=#-+MQbsz zT9=l(7Ke+L{%9=$))%cM!E#y4rNGYHdd;Ihd6ov7=dzM#8Mx%ppFGQg^(D`8V7X{5 z4_52)qO}5CwDd=7MXX{S_3Xx z`lGcbSYNc(0?TDB*9JRp>ot#leLhRq0s9Pa@4Dv3riOLF)-bHpupV4$(4QLC2kT1> z8-V4awINuo;YDjBxM=B**2Z9c(b@zo7p+afYKx?mx-YeWr4d-Xk{CoU6!x^j3&lbDTd->Ty->$UXXzJVN|6#B{xIc0A z|9{|E;~bMY?+aFc0I?a{16w}z<^O-MUlV7%YZ5*CtcmO3cyl=3n&LYEtcE`8)0ep) z2-fcv?x2QqJ-nA!(;p0HtZQ*d6Yu~3K>pCiK8)TmhtoS>`}|wa{{pK!9Dml}2yE}Y zzPz>^3C`ZqpS^VySYP&5Pq19Hjs_b)0R3q7!j6{yXdMIA7p-H#a?$DyR;zv%I}STq z`lEF`SYNbG0Lw+|M6g=*v)D=4(b6BSlfn9;)dwt>XG>qO^R`~|=wBbDvzc>0u;<1# z_6%to?|$)qc|W{A)%Lzs+qnE&A*X;xqif7yddK?vTHaH~c;?i!_e>b?8TAax+dHqL z7}FnYZCR63u|4l2oAW*!zGIs6envCiKKu7f@Co?U96%dL^SqzcU{bVd8iZ|b`|Rbj z!H)L|H@M;Ic^?92tUmYnIrLu6P2ah+^JwbZ=gbZV_b0BNcgGs%n9TVKu=)dt&Df#X z@~JQ9eOMD`ylWjj`>cuU;COR5-kRbY0ainw_36vpuLSG&3OBOh>UqBk&RExCR1@!c zm%qBPN7Fmz8hYnzpYwh#SY7vh)?f^__g-Jl=yl+n1^qb-*Ms%tEQ|%qMe7Ez@dMD0 z);R2F>5tZUu)b*B2$qZ1O<=X^dA}JuTKc1P3s_&YZUxKbHSRXBwVFep=kqdZoB(#8 zyC$AbZDYN^uCMFodRE(YuC{SGpSOcOpT>AT9qak@9yrD`qNcrj*m%#BXGY%MIrU`B z9bjwAdfbWa`MioVm$jV;m-Wz}^|%YHFY9qPST0)kfYlmRwC;tAmi}nn2i6y@`@wS2 zdH}4})kW(;xM=B*)o8L+-+JqwnL)^lLBt}R;6!$nJfv|a$~i`I)^ zxva@cU~4spzT|irY>qJ{$18Bjp+7lZ1?x+W*T8bodL69Rbw%q9xM=B*)|+5`(RvFk z7p=F!YF%Hn-hqpj{%E}m))%e!z;c=U`(SG|hrVuY)3q(fe)s_FcOdJ~Z%K21xK74< z&Thu%d9wHU>zGgRInFcIo7!&0=d;$&083%(_X@Xk!}%w-b+C=~%FhYb#g;c-J;$yGHqN|>TOV7##%<8V)t}332q$0THfrMh`9}0M zhLca6bK3;ld1SuUvMHSNsN81Q#(G6>b8LCzGmkC6#?^Uji7j8_wrb+)Jhq0DuW{Qn zadjTs!pR$#pXqf2yROz0t~=N@G=I45z^<3M!fg+BZPd;E-2v>nSYPJ0Bb@6}xt*|$ z^~$>Jj4f|`#_j?(uCB|j*zz@Qw$76eb<+6S!g3VFa?__MxrM~3o3-%0F?i6g# zTjfs0_H4;zzNdk$TitM{gRNWLaA$z6TitMHf~{NK)I1Pu&GlXm!uHJQOU;A9o{!3% zgY8+U+sB}1D6n;_n>{%i?4GR8t83xp>z=$0 z+dZi-^B4 zzITDGTitMXgRNWLaQA?%TitN?f~{NK)OsB}1Q()^>H{8=;>sB{4KMS_zx+kB@G|*t*pX_d3|R)eZLs*t*pX_a@l7)y4 z*gaXfkFnj8mHQOiJt>#9`W$SIx+lNHc2DX{j<3M($;y3$?VhaMci8Spxy<)_uyv~& z?gy}Ss~he|uyv~&?kBKytDBmC0b6t3lfPlRC-tS~KfvzE%KeG$o~+zo*zQTWZazY;Hi`z*(cZ;r;?!qq^bzr7&w$H(Wb7Yg9M2 zw1@Ltx8t)=xT)bh*Oi+V&U0P4>ES%ra>>yF&KlJXHv`xj)eScz*c#OhHxt+z)eScf zSWWM9xOuVF^gf514_i&|bGZ4j)$~5+yV?b?)l|bV#`wJt(`eJ@XUE>{Cw+Fb*Y@9A O_Oqn@pFA~Iqx~-e$3Cn8 diff --git a/crates/renderling/shaders/tutorial-slabbed_renderlet.spv b/crates/renderling/shaders/tutorial-slabbed_renderlet.spv index f54c68e3516baa5a6dc5ffc9deadc254df81ec2c..0050555940615424146bfd6836aa03ed51150b00 100644 GIT binary patch literal 44200 zcmZvl2e?($6|Jw*1;O6ME*8YZ7EA0VYAnItdsl3LvFk;OA|e{QqN0G!7?zzPdb1v7Vt)F=9srBDpZS%D7ocwq234@Ov zc*Fq%)?a_nfCCOZ@Q{P|8+gbu2OlzUz#)TMu^ox&#OTcE!sy1>vaMs=@eQYcOCkp{ ztG5-=Vvpr!O|AGrU^UEayqb%&aK{#22JE4>zGYk1EWJJrj-EN>Ja4&KHFRvv-LY3; zs56*3IbE|7wnx>Gi;lG=&T}zt>B4nrI5*U|m6<)No?P_W!HJ9Bn+<1;9(Ao;)@}lJ ztz6c&7cRA2P&oHNy>>*h*1eRwpy5^pd(^yg$(uds+lu;sOI+&Pq;Os{>)WDm_MY5Uh3ndI+ZN9LG_HTct;Xyj=V5(vIggyLT+U-@u>E6B z`^iK51ZHbXzx}4z>h{C-sJY~3&m~uLWo?IMZT8H#?Aa#Z#AVNNj>cur_AhbSv%}%6 zUwzNV>#f%6%pSE~x!LQLo4sCZ^r&m)ves*3PV4H;@K_N0MCPS6IF`mfiP<&sOH!fF z6>;z8nWAmn$;>?%K3f*TcS?(IYg-uKsbFnu)IP1T-8$t+%# z7<0BWtak})pI64WGt?Nu?0(8`fNecq2W!guplxOv{;xf}Ww&p<05yyNt9v%H z8s?AANbnrRJ{Rn{^(MX#v$2Uc&nQM)Tl>SwdtS?K+gSb4VC(i=R^gn@dp=|329E(J z?*-r=IXpkFi~DCC>im{j9rL=!7c-mNea-qyz+QLv&u6bOa<0FW+4b_h+2xg(t*MUQ z?5NLAW87!g_eRlYpz#hlW1JmoU(T$y_8e5yhxrOd>beTNcd^HUYu#64d#;JU2JAIa z%beF1-#G9*jJ{;F_Ujp5=Q`~3@o-Bs=4g#s`#u4j923EdF#56=);)<)HKKnLynXZk z^WEI=)t_~@lr{0kcWd#ft6!hzI+`q^1IrqAb^k!!JE$2K1 z+>PNiyPLTSL%sN?g6AssH1NC(`@-k5`Q3A8uZ`TjjO^k4V9zB(-k1j%?yu)!jQ#C1 z!Tk1t{pz#bn(YN`pY7JB-J7a>#@77S;Tq$7{y03Z8O-X+Yd_xD#^$~+-@*Aj^SW+;p0@ih=Ne<4Yi!Ro`=Z|( z`?AJdLwoW5!MWkQ?!(|FIk&hjt-TlyXG|T@7}5CLPwRGnM#9y;o~6~fb>8PT`sQ%- zrE;GMqu}d#R-9btHM!bb>$!a*&%OS)+hIc zaGw7qjP&0{aQ2=3XMC>v74V&keI<66Vqb;bz1U;1=Pvfu*gcDV4L1M&r#}H>zG6?r zUZ~i&W6xjgJFpih_MO-Z7W*#jg^N7}d(mRwjlFoWr(!Qr?0c}6EcP_)-o?Hbd#PgI zhrM*M@5f%I*biVYTkHq1mn-&k>Rei(b_Vn2etOR*ot-nH0|VeeM#8Q8lQ z`*G|&iais1&tgA;y%%<0u3}&2C$YVcyua%3UdynT#fE?WAdwE$ROv=#)*_2;_ynz|6!TFs#^ITi++ zqrKF-2wZaLPmV>w`jTTYuv~wlS7rU;VDrdFe+jVqKJRl5OTtB8fAo8U^=0i+VAuNk zlC?|2Wv%|KT?VW#YgYif*7spqyCPiH>d)FfV0~G;GT60K%i2}ovQ~fAt_s$dwX1<$ z>+4za_Jhk>{aL#@SYOuu6zp2xlV|N3a9OKAYu5zp%i6WTuJv^@YuAR$TK!qO4p?8- zt`Bytud!LX0bJJV&)T1Z^=0jb;8x9L?M84}t3PWu2J6e(&B3l6SI&0}xUAKmwZ8!C zv)B3%e=YfZ26!)r8wY0(*$d&WgLAJu=Wy4a^yl>}&%xc{^!Xa-b9WE0htFModouQ7 z_?&f)-rnHo%|U!#PxgWLbw|H?`!ai|r*A*T{tWe;b1e=6TZd~sKi3&!e6{60U(e|f zuyq^bdi7Gr1H5MVdgQa*Iv&IJunv9G84ohd;cO0LwDsk6?Gb&APF~j@g)?`{SJt^c zuWK{F#;N7&nmMfFFxGikhcSm^AHguMvvnAwtuOb(k>K>Dxzm?Nf%VmOuFoC~02`y$ zQ1T{+*V!CiU)RQV&f25FUJql`Q8(BB7_ishYhSPbv2d=_@A)3b?BV(9JDxF+VQ%N> z4FX5c_+gx_*LX1eOlCFHD<^=B*JthKP*3e@%jaB91luddxZd2^+mpcATjR2~Cxi9n z_2v|?TzoduT5Ywb|5 zwVFd;ats5TqrT4=j-4F(lVb!}UviucmW$RoV72P|jFH&U(jTpJ!TO>#3M?0`^T2A= z_Zg$HqoqGu=Y#b{YYbQ}S{H!TYUf(#`d)|~E&b8@Em&W)E&|K-=lSAi4i|$xZ|gOW z{^Yp?Y@YhQ;!^D7(Vsk*f%PTN)0BzR$Q4J6igqbro1&w8nzvd~NY_k*mS# z%SZnju=@4A$hFwf*B||HV13cQ4lEa~>%nT(_a@`9qoqGu6TteSH4!YAT5kZWFCYC$ zVD;t1l{+<706``|vf zXz7pE{a}63dH^gJtp~wsjVt%mbnIy9kJdwAebIUtEElauz-syRX6kwrJ6igq^%z)R zv}SM&{Tr-rQ@nnEO1-up zfhRB<LI(xm1xBu)fd1q@qfi)k4tu5#IA8dQs&lIiI&x!mzSKZIx zUGJQ0^Ix#Ntmfy8FC1up*N zED5(OHp^T4nCstL4LJSQvlO#=opX(s1{-HB%P=q7_^e?$uyyELzVUg#tk7UWTDmJ@ ztLvOz=mS>UBiu?2SMQgV;f&R1kF3J%;eP2`mC=`>zH{!E^}wE6ywwj- z_sh?)b$o1xMy*0(RK3ENX)~7G$z5!UjN4TFiT)kg5gfrH? z*r-yE#2*IbP)m_6K2eZOG*lHoe%^w5^z^pNrSI&&*{ zzxGlyd%88)czy1ZIn-0T+Vbv=?*+C2`*o%kGtBF3 z9mZ(u%k!x}n18MQGPtPCv5(;*6PpNox%FjtGk2MldpAHPx^5m zuyNMr_jar~y|*t|zel+J8qVIzwfU6uKAQVqpL_BRwugJ7?`y_q4EMk}ee(s_ud7^} z^ZgRey!xzJE!U}0ZTa-gw_y9m7}uL4wRP?R&-FHswaty~VQu=lGP*F#;cO0LwDqNL zy6bCn(lo~aCSL-n55bQ%4=5@9XW3=_<+8+kyU+dbN zJJV13a#8Y~yBW58x{^U3TtS>o!1D1={iD0$r=Pf6}@vo(& zKUyb)^+oFxuw1lG1*=s*Z#fN)e=RNj(K;QhFIs1S<#O(4g00mY`jVp^Y>sv`bKQr) z@voIbe{!4!)|VVZ!E(_W23D(n)-oK9e=RNj(Ha5P7p=3wa?v^mtXBQ3Wh5N`T3Y&} zbuL(6v_^sDa_;AWt<@a*oqcztSGr+Thcr`qy)R$T%1 zS!Imt&6E0;;5pzk#(UKImc#b2K7G9zOES#iYz||z_2pT$jJ`%E&#GnN%-!;pb*|5| zYI(46YWb`(hjm=VIuGkGW-RvA4D&i$hcVjv(zDlq`Pb?VbEh}11?x+1j04M69rdis z@6%ofHb(7X*yi;0$nT9_54IOPB+vF1pUe|N#Vf7X!moq{dzk@LM9+w;|zxT#>{>i*q>ZJfTuO#>TO z_wQb8yaANEJO^4TK9f^Io#Mb?L1YV!DWdA0yN9I#U zfA;TDus-)ujqKlJ*zR9A`(OsPyhrxn@rJAWJhS0kn|*!)&V5lM+>;HbM!2UMPK})B zGhp|GTfcQ=|DJ`@r*>kW11Glb-}CVL%$e91N^IS~7vc3;OJZLxvDT5#8*gOqtV4a* z8JE3%1+3pac8$-0jle!nHes&z#S^b*VM09UIY8O&=s85gb(55>+9`D*!*if2leMU_%T>t zzMuRbuw0)1UxGcXL*G}7ubrvS*?Nu9)|a}z0b5rW)<*j~IC)=tCQ^-G(|nID@A>y7WP)L9SPLmhou35J zoxEn+yl$-zHclzbg?zyvCeons<*w0>Yh;GS*_WdX_n#F>MOAPwHn(t~Jgz zxn>)I)wfr&c4KV$)R*hANfT$h`xQOs?3a7wdULqm+Tz;`tcE`8)0cDK9IW3X+!hVz ze)yhjJo7K$jCC)5*~I%9ll+#Ay%n=-wr2Kxoz?Vn__dqs-x2Kf_vbm~vftYfYu-FF zwgY>(-}NOq`sYbX61dn z_3ef2VSV~`W$eOe)yHfOW3=_s)VbBZ%GG7=~ItSIuP| zd$Z2NI*i!|dtZimovp(dZGCyJ?g!2@%G|kL`-An>b*|4I9RxN;E%(YC*`opE_uTxR zy0s0$_OLd6$1sj&Sc|hcjM3JYJvv@rqmw-v2xsn=udH)@_GmEJIJMj(b6CeAtn;uA zV-CeWjA349>o7)JU-sy5aQ4XD*`p)C`tmi?kzl#>-cexV>ub>f>}cta*3n>n(K-e! z7p-H#YSq`K>CJoP>22<+t1pFC%S^(D_aV7X|G1glj) z<2e^QTKc0k3al?$=Yi#-H5#l|{n?rGv7@CwT4TWaqICgSE`4+%*jmk@PkuG_^|xSq z%>6N@-dEmV-lxW03^vw#?E!4>!933|0k6RDwV}Q~Tng8pq2GJ@GG-6&X?>S7u3&f% zJ4f$IaP*AN=iOJqkHc0odo&hoygq9;hk9yPTRzXjYrsASjd8uX^E@2Rv&QF`d93+7 zY!7SJcQ#`L!yL}$Fh*Nno`>h^YjpBF90h0YmanXHeV&J-!N#fO^UxgDF^+W})?v(b z*w-`6>uepyXzR=UG9H|MF?af90$5-AWg=KE`+5V|`1(AYgdHvY(Yg_=FIqQ&<)U>n zxOLvtpSo^=itV23^||*5cC_?I>rt@2Xgvm&%U;d^d*0S-9{tJlIM_V(nK%MeA9xT(o`%R?GK3>C5M^qoqGu&x7?v z>-S)}XuSYdtN!fZi`dc9AFY?b`l9tRST1|{2e9XDz2?!MJg1wd&6gzK$I&{n2^@tS?$`g5{$1 z7FaER&oS5K@7U4OAFY3Y^+oG#uw3@?9kAzZz2?!c&##N$1^W!JcinSi>vMD*w$Ei_ z-vb+e9mC%Xy`I^x)%*j5V|&P*#(a6h`FfbRD;lnT)_EnIu^z_x`R7#)m$hYbb^yNK5IKSadi*6z{%IRu1#FsgKlv0HEymZ zuI@p1ICf?)5F z$}J4%JtCJJi-E0Cjc|*Dtx=6|OMtCWjc`kXtx>%^KYD}JRKqpKSiAS)Qef}J+QZAh z$$O;s<*>c)^o3gi>^)YwK5*Vom0KCkdq*yNwkp^h_1dq7?R}yzIaUXIPgL%waQ1)Y z)`YXy<+2xRfvsEJaBG9DTitN$fUR5Ia6bcEx4Nl$J+L*`KHLD?zSftTHw4?mmD?EG zey!Z5*!HGe@@@vUZgs zJ2-n&E;;&xtx=6|JAkcGjc_}Htx=6|JAtiHz4YeJVul*7F($pa3)tSQ&z9ZbIhk)(P${hx0Z&vOIID1nr zdvPS#y44ML6xh1e4L1O6-Rg!r8f@L_rsiY8)?9n@cx-!9Uuqr%wl^zx0=B(bxf8MN zO}XSf32fc!hC3N--Rg!r1#I2whC3B(-Rh?1)4|qUd-F_edsAO(9s;&ED>oF*-jqv@ z5nyXnBiz|wYg8lLIbds4Biu-^HL921JQu8{8m=)Wy*UbOZ(4iKXEdCA?aeXR_NKm^ z&xK%nvvL=~*_)NS1kT=+OODIH=BT}S1-8AZFFCFP+nbfU8qVIV+_iA_rd;-79N4GVRr_&}e7L8;KEo^bG`9Cn<(|Q|W;yrR_a4uJ zS0$f^=PLI*IC*m=?ztw;o=@EKaPsC)-0zz>`z&!Uz{y)v;$CdxytavZ2~OTR-D5vD zco}Rx=2FKP_wSd@{%yrv?JZ}sjq~So)ancNZ`2v%>{|7`2KjxNKY%ARF@An*%ot{4 z%(Du%*Uj1MYkVJYuBUUf_U5{|c6&Hyuf3YCwNLitXIVYeF?LUEIrW|WJl`I8m36sB z#%~7y9P?}N-I#|qBR%s+czt(sJxAdC6Icy-^ZuFH!@TUbAkU+Q=dtcJXG{FB+kI`qBI_!q;x&ema!w!YNy0XTKo$EoAr@Tp@geCqfR zUSI0?2&{&D&0(&5KjUMtaptuzt>-4Lzt{C?dd7O~Df_GLm-`ltPr&M^tA=|U-=|=8 z^r?}3&-Hgs>}O!L)KaKUg!j$I;khhMm%pTUEuNz}7hIyT>!x(LSsiQkMb<}&I2Yl+N z_rl!p`cg+vup08#(Th2C=$nTzFT=df)?tjczSJ=vICa!}VSf13QSXHX;Ps`B1;J{_ z*Bs_bk1Yf?&b;=Y^`yt1rH8Dy-V50;=V&YfR!3bm+}rpT1*@ZPOyjH9-#$p}Vqmq@ zR>xk6Z*j0%`qa^vI)8`0e(O}jJztvH!)vd98SG^l?y<8q7^AH(d%ir_J@>kMj(IP=UJR@hrJ++$~JFh*Nn_Iw+#d+vUF%FiYyuR%D z_Fy&St>f3s9@e3+KVt`md7Z7p810s?d9Su3T&t%Z0ZtwDUf2^pb<}%dFL-^aV{fn;^475rbL!ByFJnK3 zd7Z7p7;Sy2V}Ee!sQ1DF@TsHT3kSmMOC1M+)sU|_%#|KH7;Kz*?LX^DkNut=vfg?x zWWSuFaVS_Fb=7ch<2wwjj=nLCuU>!qAhCyo)lyp>dnLXjz-sAJM_=lE0e$_}sfPOL zbLVIr12)#2>U&Q_<3)JynR>2EoKI_j#iZ1EirR!85M#%C>gFXkMbfyAh# zwmQCVi*FE|TKd${mpWfUU%z##VSk;(>|vklKNqXbE$gc8m{VH*Kk$u`i84|6XD#4s&_-fRlP|K zSM_deIQ8=sIw}L&Fx^^{{y! zcOTgEsB7=XHdbHa9st`%?qj$I!S<2+lbWZ4jn$X9hrsrhd*SCa_U^-AWA!EO5wQ1z zzHpC%?dh8LF>Ld?Kgl}-Y^=VleH?6F_ab>`f{oRexF^8gbNZt9B-ncNCGIJ(wRpba zo(8)wwU%eFjn$X9XTjFu-lmq{fsNIdxaYv$>-rM+JlJ~lCGPiNYjID*y#Tfr&o}4s zBG_1ciF*m`{?%Gu#x_=8;{E{k8KWPXyQ z;EdImxYxm+uOo49z!|HrM^odQV4qd~{dE0V{}x!E=Me5)Y_F3e-1~4|Cr9%93(i=5 ziTe=jb#f%`BRFIACGHcjz2!*Ur*OvVOWmJ=Q@8%C{|fAL!4d9TIG+oSXnqH0tiHtk z2=>|INL(A(Sbd4>0O#|~k+_avWA&xRPTXoI9-SZTVUMcOlQB2L9(DG;fic?p^1kB_TwC?)`=i7;=e^4UU}If7hCFIU;}v-Q zYFL-|%<0S?)}w!M>_r*oceWm5wDq0C`Fp=C0rp;TZ^A9vaPC34-VNs-s5PXJGkU$H8C^_f6lfjCC3AlXH4)J+Sq8&f(SvyLakEe*>_w(cc;Dp}xMY7(ZvI z?;NcS!Rom-y}S`Py{tdiVq@@mXzI^%brZ0A%BY;JX3V~qXhUU=T_LF(BWJo|b73NGiZKj*y-*z?w( zecKl7xp+>gX*;mI@rm0WJp2Cq8cyE0tnCjrr(9~>0X+L&>d8~ z&r#sn_hJB?e2qIAd-lFP22S3%)Oaj-_Wd~yPTshj_wiusF_${V)bsZI(|d!!#=95p zm%UJX&mK(d31H)0Z_nDpc}+bPJdtq&V^YJf#vYvp?#ytlF>0UA?EX8ey&7?6fQ>bu z|8J;8nd3XN;q>|cbE?U=t)oL&2cs+Ks^hawvSYNazfaUU>p9uE6t=ByIljjDodFtX9WDLQx)rQ1T9d(Y(Yg(+R{edi+p(jiKU#Ny z^+oGWuw44+F0i$lLtmbCQ^59^`(sSKue`tVoSF(Y)_cw0fz3Ub=Zte=?*SX{dY^AT zlk&X%FZZ&3k35$@Z@Btg{-WXP=a65*8Jo3!9rjhjWv$%T4OiEG({O%JL@|9PEpYJ{5uPW>7;XT#OF4shnITt_(1rRMF_ za8<8!!?`x+(FM-j>gIh?SMYH5L|@{%fjt*B5;qsvb1_%$sqSFc8?S#DA&KvS9gXPD z4d=eq{5|2!uP<@E!0w0Vnq2dM)ihqexe`Awc4|xh`QW0FxcTAC?;a#>0kHY?CD(#r zHPz5>E_>D9S_s?T^vKWfEez*g=u6xpO`Lt1xJBVS4}FPStckN%6Sp{=HRwy+5@7Eg zk8n#iT}cta)_=hI zqV)+_E?S?0)vE7vKEsZd{%HLdtS?%hgXN<21z4^6e&$Q;Xz7pES73e7`Wh^k`}Z5L z=WV^_(Vslug3VLk>wJfuJo=O8d$7Lb`2j2!tslW^)%QAnV?0{=qcw-$FlR(-POx0G zI)K$`CoI>vBV4rfN2?Q9U$ikt^XN~WCBf#Y zzuVp$E_w7P&r)E0$+I+AE?Ucg)vCYSzARj{^hawsu)b(550;D83ShPB@3yZ97cKqK z>I2pnt(CxX(OMbYI!C^yO^>ev7cKqKS{1A>T7AKC*~`_yp11XyN58(6=dP`cuPC!TM6e8eq9-tqE3ZTG3hyE?WAdwKiB^wAKO3MeAo^ zwI-CkSr;x^`lGcTSYNc(2g^lk1F%}R7pr0-^!E({s0<4z*Kjvut0xnwmqxDO$zG!U;mW$R_V72`J zwnS@dxM=B*)~~?&qO}cJE?V1y)w-)_Z3h=E{n6SUtS?%>2FqnH`-44i>ot%5r0-U!E({s1+3PTQuD5G(b6BS-N5>ywL4fYT6=)inpx`F6E0f% zqqP@UU$piH%SCG+uv-2x#La@os)V9(on&7)u6N?h|nV4nf@u6u55 zY8VW*hWknlC%~l!{i)$MV123KM6g`6P6DfSf6+P_E?WAdbqZKtv`z)fMe8)MS`QSh z)8V3}KU!yi^+oGUuv|VjX$M=YIrJsR5U@EOB!_>a(*LLUD6sF>hvD=6y0h>9`>>D0 z!RO)kJ^Tpp*$n><={XH1q_uV=wridJII;YKx_Ukl~$Vx9+gE<>MRTa0G* z@M{Zw=QGAI)OXI`5*-WnePR7Oq^>p2H96-i!0L}AHfyiMmQQ{8JET`NamKqR(R0q8 zxDT#3hwH5=zN^7%=(9e3IrnS8`aQy3+i>oO*K$1bI5=b7i|d+r{|>4A^^HBA*)t?X=Bhio6E!ff0AFW%# z`l2-%EElcYz-ra6#cs!rmi}nn0oE6-JHc|%x(lpU{aS1acC_?I>u#{VXiWvn<=Ju% z*z>kt^XT6crO}-8G_d!Ld+a@=ZM^;B_40aneX8wstG03ZoxOX(6VNrrud!V_hS_WC z8t*wZoxLZFAI9(=ly~;L2C?Qou(f4R?#K3ipWfW>AK@F_-0#zy_0H+vhrk!&SMy=U zBMk5NM;lCvR!xs#o7*|PJOk`{k8qDST)p3C!Wpa29)E(_!*kR3B;zTD`p&s$UjYv# zuHNsiHO@6T=a<0hk0ds0U&fYCeYxNN(8L+O^yS=N z1MBw)_s52-_xqpVjCC*m+{Amo%m1aZ|H|x|zcG8h&bi-T2dit}XAj=M_S);qJ^Cg% z_k#Z13vYq-zV5!l+YA0K0Te?G)Lm%aTDT=qkM_Tv+5tYtV13b=7c3X8`M_#DQMBfViUkUhCtu?ZY~t#990VtCT)qc(FxY*yrf`RV-9z(-I~44G znJe63VE0DdT;IdN?n}OR&$N6^&Ev7XKPop7+k2sMld$c3x#YbOY~AXHy9sRF z>V~@+Y~AXHy9I3B>Zaz&U~8^@bvw5G-10Rw--&JSR&ENmeOkGx*!HAc^4B$Gc_GEotO^1`OJ^3)UJ*hAE>Z4$LvT`%9?a9i`#I`5p zvR6-n%~5;uX>5B^UvfMPwkIq19JW1Kx!+^klX5xV7r@r7Znzi0)~#;1m%!GoZn&4h z)~#-8eg$mJwI^T0wkP$a=0Ab$$;$l&+n%i4->~gTx#WEvY~AXHdjo9U>V|t0Y~AXH zdkbvc>Zay@fUUXq>sB{4cL!T@ z?a8^}>`8s8xfj@;tlYeC_GIPehqEW;l6L{Hb*me0L9lhJ8*U-6b*me0VX$?po0=B| zTXXHn#o_EpeW`g#usvD1rQqzz$}IzDPs%0lvS900H{5by>sB}1@?h&$H{1$f>sB|l zEX&sb?d0(1iNY-pH)J+$ML6FN)VP)4hR(+Ih4WeN&mu*yAKbLrxSzn?I~%tK+rj1-3?Y!>tXrMs>rj1GYwWQ_K2b?`wZ9D%{WEyss;_5uEpRW1qNwr+L9?EtoJb;Iolwr+J(%kE%%$e$|RJpU@?4imHgR_U^l6N@Ry44Lg0&LythC3T<-Rg!r2W;Kyrk3-; z_K-hc814c%d#G~1g|mk$cQKqjRJqIH>>+&B3ule$ zh8qXAMs>qo2ew9a!(9)yMs-um4Pbl7pOXxCBb+@{xtrnap~~F~XAj9G$7DEbR5#ph zU~5!2-0fg%R5#omU~5!2J#-g%adOlix*N_O(wCa=0oy~ByBE$Ls@(l>_K;liJ^;3E zb;CUfwr+L9O$S@Iy5SxITerHY<#Dh*v;-sE6L9uW<(`7Ghbs3BoIO;z=i%(3B^l9s z0nQ$(+)HrwQ04vrXAjAx=2zgXQQdH_f~`^AaIb-_QQdHV1Y4uJspYR=d#E=f-0N`m zQ03l)vxh48cQ|`UE;;@IXN~HHdmC(x>V|sn!Mdlzht>W2FStfoB^?o(_v?U`_& zVXJA+g!?bHn)Xb3@(XN#hS($Amkn1xd-$s1>U+m;;C$UvBYX87xc_Y257@r$)wnkP z_UDeXadX1?3^afAI>L>Zjq42OGqA>Wg*&I=a=zW*tWn)?bAhc<-EiH()~If{9$;%! zH?{Nxdw;nX;pTyRa5io}IPb3-w*cHj4VN4X!daub;T8g0qq^Z123w=L;T8c~qq^ai z0jp_`gj*I{O?xEVa@cCxBjJ|ER?{BI_oP?AR#Oev7~}W1_%las`o#PyU+d@1{k+`2 Q?dtcRoWJKQqjeeo2P(Ig#{d8T literal 44200 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 Vec3 { @@ -202,7 +202,7 @@ impl TextureAddressMode { #[derive(Clone, Copy, Default, SlabItem, core::fmt::Debug)] pub struct AtlasBlittingDescriptor { - pub atlas_texture_id: Id, + pub atlas_texture_id: Id, pub atlas_desc_id: Id, } @@ -263,7 +263,7 @@ mod test { /// Tests that clip coordinates can be converted into texture coords within /// a specific `AtlasTexture`, and back again. fn constrain_clip_coords_sanity() { - let atlas_texture = AtlasTexture { + let atlas_texture = AtlasTextureDescriptor { offset_px: UVec2::splat(0), size_px: UVec2::splat(800), layer_index: 0, diff --git a/crates/renderling/src/atlas/cpu.rs b/crates/renderling/src/atlas/cpu.rs index a31586c4..f2bfa9b5 100644 --- a/crates/renderling/src/atlas/cpu.rs +++ b/crates/renderling/src/atlas/cpu.rs @@ -12,14 +12,14 @@ use image::RgbaImage; use snafu::{prelude::*, OptionExt}; use crate::{ - atlas::AtlasDescriptor, + atlas::{AtlasDescriptor, TextureModes}, bindgroup::ManagedBindGroup, texture::{CopiedTextureBuffer, Texture}, }; use super::{ atlas_image::{convert_pixels, AtlasImage}, - AtlasBlittingDescriptor, AtlasTexture, + AtlasBlittingDescriptor, AtlasTextureDescriptor, }; pub(crate) const ATLAS_SUGGESTED_SIZE: u32 = 2048; @@ -43,16 +43,75 @@ pub enum AtlasError { MissingBindgroup { layer: u32 }, } +/// A staged texture in the texture atlas. +/// +/// An [`AtlasTexture`] can be acquired through: +/// * [`Atlas::add_image`] +/// * [`Atlas::add_images`]. +/// * [`Atlas::set_images`] +/// +/// Clones of this type all point to the same underlying data. +/// +/// Dropping all clones of this type will cause it to be unloaded from the GPU. +/// +/// If a value of this type has been given to another staged resource, +/// like [`Material`](crate::material::Material), this will prevent the `AtlasTexture` from +/// being dropped and unloaded. +/// +/// Internally an `AtlasTexture` holds a reference to its descriptor, +/// [`AtlasTextureDescriptor`]. +#[derive(Clone)] +pub struct AtlasTexture { + pub(crate) descriptor: Hybrid, +} + +impl AtlasTexture { + /// Get the GPU slab identifier of the underlying descriptor. + /// + /// This is for internal use. + pub fn id(&self) -> Id { + self.descriptor.id() + } + + /// Return a copy of the underlying descriptor. + pub fn descriptor(&self) -> AtlasTextureDescriptor { + self.descriptor.get() + } + + /// Return the texture modes of the underlying descriptor. + pub fn modes(&self) -> TextureModes { + self.descriptor.get().modes + } + + /// Sets the texture modes of the underlying descriptor. + /// + /// ## Warning + /// + /// This also sets the modes for all clones of this value. + pub fn set_modes(&self, modes: TextureModes) { + self.descriptor.modify(|d| d.modes = modes); + } +} + /// Used to track textures internally. +/// +/// We need a separate struct for tracking textures because the atlas +/// reorganizes the layout (the packing) of textures each time a new +/// texture is added. +/// +/// This means the textures must be updated on the GPU, but we don't +/// want these internal representations to keep unreferenced textures +/// from dropping, so we have to maintain a separate representation +/// here. #[derive(Clone, Debug)] struct InternalAtlasTexture { /// Cached value. - cache: AtlasTexture, - weak: WeakHybrid, + cache: AtlasTextureDescriptor, + weak: WeakHybrid, } impl InternalAtlasTexture { - fn from_hybrid(hat: &Hybrid) -> Self { + fn from_hybrid(hat: &Hybrid) -> Self { InternalAtlasTexture { cache: hat.get(), weak: WeakHybrid::from_hybrid(hat), @@ -63,7 +122,7 @@ impl InternalAtlasTexture { self.weak.has_external_references() } - fn set(&mut self, at: AtlasTexture) { + fn set(&mut self, at: AtlasTextureDescriptor) { self.cache = at; if let Some(hy) = self.weak.upgrade() { hy.set(at); @@ -265,10 +324,7 @@ impl Atlas { /// Reset this atlas with all new images. /// /// Any existing `Hybrid`s will be invalidated. - pub fn set_images( - &self, - images: &[AtlasImage], - ) -> Result>, AtlasError> { + pub fn set_images(&self, images: &[AtlasImage]) -> Result, AtlasError> { log::debug!("setting images"); { // UNWRAP: panic on purpose @@ -291,7 +347,7 @@ impl Atlas { pub fn add_images<'a>( &self, images: impl IntoIterator, - ) -> Result>, AtlasError> { + ) -> Result, AtlasError> { // UNWRAP: POP let mut layers = self.layers.write().unwrap(); let mut texture_array = self.texture_array.write().unwrap(); @@ -314,7 +370,11 @@ impl Atlas { *layers = staged.layers; staged.image_additions.sort_by_key(|a| a.0); - Ok(staged.image_additions.into_iter().map(|a| a.1).collect()) + Ok(staged + .image_additions + .into_iter() + .map(|a| AtlasTexture { descriptor: a.1 }) + .collect()) } /// Resize the atlas. @@ -513,7 +573,7 @@ fn pack_images<'a>( /// Internal atlas resources. struct StagedResources { texture: Texture, - image_additions: Vec<(usize, Hybrid)>, + image_additions: Vec<(usize, Hybrid)>, layers: Vec, } @@ -559,7 +619,7 @@ impl StagedResources { original_index, image, } => { - let atlas_texture = AtlasTexture { + let atlas_texture = AtlasTextureDescriptor { offset_px, size_px, frame_index: frame_index as u32, @@ -692,7 +752,7 @@ impl AtlasBlittingOperation { from_texture: &crate::texture::Texture, layer: u32, to_atlas: &Atlas, - atlas_texture: &Hybrid, + atlas_texture: &AtlasTexture, ) -> Result<(), AtlasError> { let runtime = runtime.as_ref(); @@ -752,7 +812,7 @@ impl AtlasBlittingOperation { }) }); - let atlas_texture = atlas_texture.get(); + let atlas_texture = atlas_texture.descriptor(); let atlas_view = to_atlas_texture .texture .create_view(&wgpu::TextureViewDescriptor { @@ -935,12 +995,10 @@ impl AtlasBlitter { #[cfg(test)] mod test { use crate::{ - atlas::{AtlasTexture, TextureAddressMode}, - camera::Camera, + atlas::{AtlasTextureDescriptor, TextureAddressMode}, geometry::Vertex, - material::{MaterialDescriptor, Materials}, + material::Materials, test::BlockOnFuture, - transform::TransformDescriptor, Context, }; use glam::{UVec3, Vec2, Vec3, Vec4}; @@ -959,7 +1017,9 @@ mod test { .with_background_color(Vec3::splat(0.0).extend(1.0)) .with_bloom(false); let (projection, view) = crate::camera::default_ortho2d(32.0, 32.0); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let dirt = AtlasImage::from_path("../../img/dirt.jpg").unwrap(); let sandstone = AtlasImage::from_path("../../img/sandstone.png").unwrap(); let texels = AtlasImage::from_path("../../test_img/atlas/uv_mapping.png").unwrap(); @@ -970,13 +1030,14 @@ mod test { let texels_entry = &atlas_entries[2]; let _rez = stage - .builder() - .with_material(MaterialDescriptor { - albedo_texture_id: texels_entry.id(), - has_lighting: false, - ..Default::default() - }) - .with_vertices({ + .new_renderlet() + .with_material( + stage + .new_material() + .with_albedo_texture(texels_entry) + .with_has_lighting(false), + ) + .with_vertices(stage.new_vertices({ let tl = Vertex::default() .with_position(Vec3::ZERO) .with_uv0(Vec2::ZERO); @@ -990,12 +1051,8 @@ mod test { .with_position(Vec3::new(1.0, 1.0, 0.0)) .with_uv0(Vec2::splat(1.0)); [tl, bl, br, tl, br, tr] - }) - .with_transform(TransformDescriptor { - scale: Vec3::new(32.0, 32.0, 1.0), - ..Default::default() - }) - .build(); + })) + .with_transform(stage.new_transform().with_scale(Vec3::new(32.0, 32.0, 1.0))); log::info!("rendering"); let frame = ctx.get_next_frame().unwrap(); @@ -1018,19 +1075,21 @@ mod test { .new_stage() .with_background_color(Vec4::new(1.0, 1.0, 0.0, 1.0)); let (projection, view) = crate::camera::default_ortho2d(w as f32, h as f32); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let texels = AtlasImage::from_path("../../img/happy_mac.png").unwrap(); let entries = stage.set_images(std::iter::repeat_n(texels, 3)).unwrap(); let clamp_tex = &entries[0]; let repeat_tex = &entries[1]; - repeat_tex.modify(|t| { - t.modes.s = TextureAddressMode::Repeat; - t.modes.t = TextureAddressMode::Repeat; + repeat_tex.set_modes(TextureModes { + s: TextureAddressMode::Repeat, + t: TextureAddressMode::Repeat, }); let mirror_tex = &entries[2]; - mirror_tex.modify(|t| { - t.modes.s = TextureAddressMode::MirroredRepeat; - t.modes.t = TextureAddressMode::MirroredRepeat; + mirror_tex.set_modes(TextureModes { + s: TextureAddressMode::MirroredRepeat, + t: TextureAddressMode::MirroredRepeat, }); let sheet_w = sheet_w as f32; @@ -1051,42 +1110,44 @@ mod test { [tl, bl, br, tl, br, tr] }); let _clamp_rez = stage - .builder() - .with_vertices_array(geometry.array()) - .with_material(MaterialDescriptor { - albedo_texture_id: clamp_tex.id(), - has_lighting: false, - ..Default::default() - }) - .build(); + .new_renderlet() + .with_vertices(&geometry) + .with_material( + stage + .new_material() + .with_albedo_texture(clamp_tex) + .with_has_lighting(false), + ); let _repeat_rez = stage - .builder() - .with_transform(TransformDescriptor { - translation: Vec3::new(sheet_w + 1.0, 0.0, 0.0), - ..Default::default() - }) - .with_material(MaterialDescriptor { - albedo_texture_id: repeat_tex.id(), - has_lighting: false, - ..Default::default() - }) - .with_vertices_array(geometry.array()) - .build(); + .new_renderlet() + .with_transform(stage.new_transform().with_translation(Vec3::new( + sheet_w + 1.0, + 0.0, + 0.0, + ))) + .with_material( + stage + .new_material() + .with_albedo_texture(repeat_tex) + .with_has_lighting(false), + ) + .with_vertices(&geometry); let _mirror_rez = stage - .builder() - .with_transform(TransformDescriptor { - translation: Vec3::new(sheet_w * 2.0 + 2.0, 0.0, 0.0), - ..Default::default() - }) - .with_material(MaterialDescriptor { - albedo_texture_id: mirror_tex.id(), - has_lighting: false, - ..Default::default() - }) - .with_vertices_array(geometry.array()) - .build(); + .new_renderlet() + .with_transform(stage.new_transform().with_translation(Vec3::new( + sheet_w * 2.0 + 2.0, + 0.0, + 0.0, + ))) + .with_material( + stage + .new_material() + .with_albedo_texture(mirror_tex) + .with_has_lighting(false), + ) + .with_vertices(geometry); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -1109,77 +1170,82 @@ mod test { .with_background_color(Vec4::new(1.0, 1.0, 0.0, 1.0)); let (projection, view) = crate::camera::default_ortho2d(w as f32, h as f32); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let texels = AtlasImage::from_path("../../img/happy_mac.png").unwrap(); let entries = stage.set_images(std::iter::repeat_n(texels, 3)).unwrap(); let clamp_tex = &entries[0]; let repeat_tex = &entries[1]; - repeat_tex.modify(|t| { - t.modes.s = TextureAddressMode::Repeat; - t.modes.t = TextureAddressMode::Repeat; + repeat_tex.set_modes(TextureModes { + s: TextureAddressMode::Repeat, + t: TextureAddressMode::Repeat, }); let mirror_tex = &entries[2]; - mirror_tex.modify(|t| { - t.modes.s = TextureAddressMode::MirroredRepeat; - t.modes.t = TextureAddressMode::MirroredRepeat; + mirror_tex.set_modes(TextureModes { + s: TextureAddressMode::MirroredRepeat, + t: TextureAddressMode::MirroredRepeat, }); let sheet_w = sheet_w as f32; let sheet_h = sheet_h as f32; - let (geometry, _clamp_material, _clamp_prim) = stage - .builder() - .with_vertices({ - let tl = Vertex::default() - .with_position(Vec3::ZERO) - .with_uv0(Vec2::ZERO); - let tr = Vertex::default() - .with_position(Vec3::new(sheet_w, 0.0, 0.0)) - .with_uv0(Vec2::new(-3.0, 0.0)); - let bl = Vertex::default() - .with_position(Vec3::new(0.0, sheet_h, 0.0)) - .with_uv0(Vec2::new(0.0, -3.0)); - let br = Vertex::default() - .with_position(Vec3::new(sheet_w, sheet_h, 0.0)) - .with_uv0(Vec2::splat(-3.0)); - [tl, bl, br, tl, br, tr] - }) - .with_material(MaterialDescriptor { - albedo_texture_id: clamp_tex.id(), - has_lighting: false, - ..Default::default() - }) - .build(); + let geometry = stage.new_vertices({ + let tl = Vertex::default() + .with_position(Vec3::ZERO) + .with_uv0(Vec2::ZERO); + let tr = Vertex::default() + .with_position(Vec3::new(sheet_w, 0.0, 0.0)) + .with_uv0(Vec2::new(-3.0, 0.0)); + let bl = Vertex::default() + .with_position(Vec3::new(0.0, sheet_h, 0.0)) + .with_uv0(Vec2::new(0.0, -3.0)); + let br = Vertex::default() + .with_position(Vec3::new(sheet_w, sheet_h, 0.0)) + .with_uv0(Vec2::splat(-3.0)); + [tl, bl, br, tl, br, tr] + }); + let _clamp_prim = stage + .new_renderlet() + .with_vertices(&geometry) + .with_material( + stage + .new_material() + .with_albedo_texture(clamp_tex) + .with_has_lighting(false), + ); let _repeat_rez = stage - .builder() - .with_material(MaterialDescriptor { - albedo_texture_id: repeat_tex.id(), - has_lighting: false, - ..Default::default() - }) - .with_transform(TransformDescriptor { - translation: Vec3::new(sheet_w + 1.0, 0.0, 0.0), - ..Default::default() - }) - .with_vertices_array(geometry.array()) - .build(); + .new_renderlet() + .with_material( + stage + .new_material() + .with_albedo_texture(repeat_tex) + .with_has_lighting(false), + ) + .with_transform(stage.new_transform().with_translation(Vec3::new( + sheet_w + 1.0, + 0.0, + 0.0, + ))) + .with_vertices(&geometry); let _mirror_rez = stage - .builder() - .with_material(MaterialDescriptor { - albedo_texture_id: mirror_tex.id(), - has_lighting: false, - ..Default::default() - }) - .with_transform(TransformDescriptor { - translation: Vec3::new(sheet_w * 2.0 + 2.0, 0.0, 0.0), - ..Default::default() - }) - .with_vertices_array(geometry.array()) - .build(); + .new_renderlet() + .with_material( + stage + .new_material() + .with_albedo_texture(mirror_tex) + .with_has_lighting(false), + ) + .with_transform(stage.new_transform().with_translation(Vec3::new( + sheet_w * 2.0 + 2.0, + 0.0, + 0.0, + ))) + .with_vertices(&geometry); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -1189,7 +1255,7 @@ mod test { #[test] fn transform_uvs_for_atlas() { - let mut tex = AtlasTexture { + let mut tex = AtlasTextureDescriptor { offset_px: UVec2::ZERO, size_px: UVec2::ONE, ..Default::default() diff --git a/crates/renderling/src/bloom/cpu.rs b/crates/renderling/src/bloom/cpu.rs index b8f1d355..9b43eb0a 100644 --- a/crates/renderling/src/bloom/cpu.rs +++ b/crates/renderling/src/bloom/cpu.rs @@ -701,7 +701,7 @@ impl Bloom { mod test { use glam::Vec3; - use crate::{camera::Camera, test::BlockOnFuture, Context}; + use crate::{camera::CameraDescriptor, test::BlockOnFuture, Context}; use super::*; @@ -754,7 +754,9 @@ mod test { let projection = crate::camera::perspective(width as f32, height as f32); let view = crate::camera::look_at(Vec3::new(0.0, 2.0, 18.0), Vec3::ZERO, Vec3::Y); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let skybox = stage .new_skybox_from_path("../../img/hdr/night.hdr") .unwrap(); diff --git a/crates/renderling/src/bvol.rs b/crates/renderling/src/bvol.rs index 347e9fe0..026d9de3 100644 --- a/crates/renderling/src/bvol.rs +++ b/crates/renderling/src/bvol.rs @@ -16,7 +16,7 @@ use glam::{Mat4, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles}; #[cfg(gpu)] use spirv_std::num_traits::Float; -use crate::{camera::Camera, transform::TransformDescriptor}; +use crate::{camera::CameraDescriptor, transform::TransformDescriptor}; /// Normalize a plane. pub fn normalize_plane(mut plane: Vec4) -> Vec4 { @@ -151,7 +151,11 @@ impl Aabb { /// Determines whether this `Aabb` can be seen by `camera` after being /// transformed by `transform`. - pub fn is_outside_camera_view(&self, camera: &Camera, transform: TransformDescriptor) -> bool { + pub fn is_outside_camera_view( + &self, + camera: &CameraDescriptor, + transform: TransformDescriptor, + ) -> bool { let transform = Mat4::from(transform); let min = transform.transform_point3(self.min); let max = transform.transform_point3(self.max); @@ -223,7 +227,7 @@ pub struct Frustum { impl Frustum { /// Compute a frustum in world space from the given [`Camera`]. - pub fn from_camera(camera: &Camera) -> Self { + pub fn from_camera(camera: &CameraDescriptor) -> Self { let viewprojection = camera.view_projection(); let mvp = viewprojection.to_cols_array_2d(); @@ -462,7 +466,7 @@ impl BoundingSphere { /// being transformed by `transform`. pub fn is_inside_camera_view( &self, - camera: &Camera, + camera: &CameraDescriptor, transform: TransformDescriptor, ) -> (bool, BoundingSphere) { let center = Mat4::from(transform).transform_point3(self.center); @@ -490,7 +494,7 @@ impl BoundingSphere { /// Returns an [`Aabb`] with x and y coordinates in viewport pixels and z coordinate /// in NDC depth. - pub fn project_onto_viewport(&self, camera: &Camera, viewport: Vec2) -> Aabb { + pub fn project_onto_viewport(&self, camera: &CameraDescriptor, viewport: Vec2) -> Aabb { fn ndc_to_pixel(viewport: Vec2, ndc: Vec3) -> Vec2 { let screen = Vec3::new((ndc.x + 1.0) * 0.5, 1.0 - (ndc.y + 1.0) * 0.5, ndc.z); (screen * viewport.extend(1.0)).xy() @@ -595,14 +599,14 @@ impl BVol for Aabb { mod test { use glam::{Mat4, Quat}; - use crate::{geometry::Vertex, material::MaterialDescriptor, test::BlockOnFuture, Context}; + use crate::{geometry::Vertex, test::BlockOnFuture, Context}; use super::*; #[test] fn bvol_frustum_is_in_world_space_sanity() { let (p, v) = crate::camera::default_perspective(800.0, 600.0); - let camera = Camera::new(p, v); + let camera = CameraDescriptor::new(p, v); let aabb_outside = Aabb { min: Vec3::new(-10.0, -12.0, 20.0), max: Vec3::new(10.0, 12.0, 40.0), @@ -630,7 +634,7 @@ mod test { let target = Vec3::ZERO; let up = Vec3::Y; let view = Mat4::look_at_rh(eye, target, up); - Camera::new(projection, view) + CameraDescriptor::new(projection, view) }; let aabb = Aabb { min: Vec3::new(-3.2869213, -3.0652206, -3.8715153), @@ -655,34 +659,26 @@ mod test { .with_background_color(Vec4::ZERO) .with_msaa_sample_count(4) .with_lighting(true); - let _camera = stage.new_camera({ - Camera::new( - // BUG: using orthographic here renderes nothing - // Mat4::orthographic_rh(-10.0, 10.0, -10.0, 10.0, 10.0, -10.0), - crate::camera::perspective(256.0, 256.0), - Mat4::look_at_rh(Vec3::new(-3.0, 3.0, 5.0) * 0.5, Vec3::ZERO, Vec3::Y), - ) - }); + let _camera = stage.new_camera().with_projection_and_view( + // TODO: BUG - using orthographic here renderes nothing + // Mat4::orthographic_rh(-10.0, 10.0, -10.0, 10.0, 10.0, -10.0), + crate::camera::perspective(256.0, 256.0), + Mat4::look_at_rh(Vec3::new(-3.0, 3.0, 5.0) * 0.5, Vec3::ZERO, Vec3::Y), + ); let _lights = crate::test::make_two_directional_light_setup(&stage); - let white = stage.new_material(MaterialDescriptor { - albedo_factor: Vec4::ONE, - ..Default::default() - }); - let red = stage.new_material(MaterialDescriptor { - albedo_factor: Vec4::new(1.0, 0.0, 0.0, 1.0), - ..Default::default() - }); - - let _w = stage - .builder() - .with_material_id(white.id()) - .with_vertices( + let white = stage.new_material(); + let red = stage + .new_material() + .with_albedo_factor(Vec4::new(1.0, 0.0, 0.0, 1.0)); + + let _w = stage.new_renderlet().with_material(&white).with_vertices( + stage.new_vertices( crate::math::unit_cube() .into_iter() .map(|(p, n)| Vertex::default().with_position(p).with_normal(n)), - ) - .build(); + ), + ); let mut corners = vec![]; for x in [-1.0, 1.0] { @@ -704,14 +700,12 @@ mod test { ); rs.push( - stage - .builder() - .with_material_id(red.id()) - .with_vertices( + stage.new_renderlet().with_material(&red).with_vertices( + stage.new_vertices( bb.get_mesh() .map(|(p, n)| Vertex::default().with_position(p).with_normal(n)), - ) - .build(), + ), + ), ); } diff --git a/crates/renderling/src/camera.rs b/crates/renderling/src/camera.rs index 793ac04f..84ac88f7 100644 --- a/crates/renderling/src/camera.rs +++ b/crates/renderling/src/camera.rs @@ -4,12 +4,19 @@ use glam::{Mat4, Vec2, Vec3, Vec4}; use crate::{bvol::Frustum, math::IsVector}; -/// A camera used for transforming the stage during rendering. +#[cfg(cpu)] +mod cpu; +#[cfg(cpu)] +pub use cpu::*; + +/// GPU descriptor of a camera. +/// +/// Used for transforming the stage during rendering. /// -/// Use [`Camera::new`] to create a new camera. +/// Use [`CameraDescriptor::new`] to create a new camera. #[cfg_attr(not(target_arch = "spirv"), derive(Debug))] #[derive(Default, Clone, Copy, PartialEq, SlabItem)] -pub struct Camera { +pub struct CameraDescriptor { projection: Mat4, view: Mat4, position: Vec3, @@ -20,19 +27,19 @@ pub struct Camera { z_far_point: Vec3, } -impl Camera { +impl CameraDescriptor { pub fn new(projection: Mat4, view: Mat4) -> Self { - Camera::default().with_projection_and_view(projection, view) + CameraDescriptor::default().with_projection_and_view(projection, view) } pub fn default_perspective(width: f32, height: f32) -> Self { let (projection, view) = default_perspective(width, height); - Camera::new(projection, view) + CameraDescriptor::new(projection, view) } pub fn default_ortho2d(width: f32, height: f32) -> Self { let (projection, view) = default_ortho2d(width, height); - Camera::new(projection, view) + CameraDescriptor::new(projection, view) } pub fn projection(&self) -> Mat4 { @@ -207,7 +214,7 @@ mod tests { for (eye, expected_forward) in eyes.into_iter().zip(expected_forwards) { let projection = Mat4::perspective_rh(45.0_f32.to_radians(), 800.0 / 600.0, 0.1, 100.0); let view = Mat4::look_at_rh(eye, Vec3::ZERO, Vec3::Y); - let camera = Camera::new(projection, view); + let camera = CameraDescriptor::new(projection, view); let forward = camera.forward(); let distance = forward.distance(expected_forward); diff --git a/crates/renderling/src/camera/cpu.rs b/crates/renderling/src/camera/cpu.rs new file mode 100644 index 00000000..afc9f642 --- /dev/null +++ b/crates/renderling/src/camera/cpu.rs @@ -0,0 +1,123 @@ +//! CPU side of [crate::camera]. + +use craballoc::{runtime::IsRuntime, slab::SlabAllocator, value::Hybrid}; +use crabslab::Id; + +use super::*; + +/// A camera used for transforming the stage during rendering. +/// +/// * Use [`Stage::new_camera`](crate::stage::Stage::new_camera) to create a new camera. +/// * Use [`Stage::use_camera`](crate::stage::Stage::use_camera) to set a camera on the stage. +/// +/// ## Note +/// +/// Clones of this type all point to the same underlying data. +#[derive(Clone, Debug)] +pub struct Camera { + inner: Hybrid, +} + +impl AsRef for Camera { + fn as_ref(&self) -> &Camera { + self + } +} + +impl Camera { + /// Stage a new camera on the given slab. + pub fn new(slab: &SlabAllocator) -> Self { + Self { + inner: slab.new_value(CameraDescriptor::default()), + } + } + + /// Returns a pointer to the underlying descriptor on the GPU. + pub fn id(&self) -> Id { + self.inner.id() + } + + /// Returns a copy of the underlying descriptor. + pub fn descriptor(&self) -> CameraDescriptor { + self.inner.get() + } + + /// Set the projection and view matrices of this camera. + pub fn set_projection_and_view( + &self, + projection: impl Into, + view: impl Into, + ) -> &Self { + self.inner + .modify(|d| d.set_projection_and_view(projection.into(), view.into())); + self + } + + /// Set the projection and view matrices and return this camera. + pub fn with_projection_and_view( + self, + projection: impl Into, + view: impl Into, + ) -> Self { + self.set_projection_and_view(projection, view); + self + } + + /// Returns the projection and view matrices. + pub fn projection_and_view(&self) -> (Mat4, Mat4) { + let d = self.inner.get(); + (d.projection, d.view()) + } + + /// Set the projection matrix of this camera. + pub fn set_projection(&self, projection: impl Into) -> &Self { + self.inner.modify(|d| d.set_projection(projection.into())); + self + } + + /// Set the projection matrix and return this camera. + pub fn with_projection(self, projection: impl Into) -> Self { + self.set_projection(projection); + self + } + + /// Returns the projection matrix. + pub fn projection(&self) -> Mat4 { + self.inner.get().projection + } + + /// Set the view matrix of this camera. + pub fn set_view(&self, view: impl Into) -> &Self { + self.inner.modify(|d| d.set_view(view.into())); + self + } + + /// Set the view matrix and return this camera. + pub fn with_view(self, view: impl Into) -> Self { + self.set_view(view); + self + } + + /// Returns the view matrix. + pub fn view(&self) -> Mat4 { + self.inner.get().view() + } +} + +#[cfg(test)] +mod test { + use craballoc::{runtime::CpuRuntime, slab::SlabAllocator}; + + use super::*; + + #[test] + fn camera_position_sanity() { + let slab = SlabAllocator::new(CpuRuntime, "camera test", ()); + let camera = Camera::new(&slab); + let projection = Mat4::perspective_rh(std::f32::consts::FRAC_PI_4, 1.0, 0.01, 10.0); + let view = Mat4::look_at_rh(Vec3::ONE, Vec3::ZERO, Vec3::Y); + camera.set_projection_and_view(projection, view); + let position = camera.descriptor().position(); + assert_eq!(Vec3::ONE, position); + } +} diff --git a/crates/renderling/src/convolution.rs b/crates/renderling/src/convolution.rs index 310114fa..1753bfa8 100644 --- a/crates/renderling/src/convolution.rs +++ b/crates/renderling/src/convolution.rs @@ -12,7 +12,7 @@ use spirv_std::{ #[allow(unused_imports)] use spirv_std::num_traits::Float; -use crate::{camera::Camera, math::IsVector}; +use crate::{camera::CameraDescriptor, math::IsVector}; // Allow manual bit rotation because this code is `no_std`. #[allow(clippy::manual_rotate)] @@ -155,7 +155,7 @@ pub fn integrate_brdf_doesnt_work(mut n_dot_v: f32, roughness: f32) -> Vec2 { /// roughness values from the slab. #[derive(Clone, Copy, Default, SlabItem)] pub struct VertexPrefilterEnvironmentCubemapIds { - pub camera: Id, + pub camera: Id, // TODO: does this have to be an Id? Pretty sure it can be inline pub roughness: Id, } diff --git a/crates/renderling/src/cubemap.rs b/crates/renderling/src/cubemap.rs index c986fda3..c9c7197c 100644 --- a/crates/renderling/src/cubemap.rs +++ b/crates/renderling/src/cubemap.rs @@ -14,7 +14,7 @@ mod cpu; pub use cpu::*; use crate::{ - atlas::{AtlasDescriptor, AtlasTexture}, + atlas::{AtlasDescriptor, AtlasTextureDescriptor}, math::{IsSampler, Sample2dArray}, }; @@ -111,7 +111,7 @@ impl CubemapFaceDirection { pub struct CubemapDescriptor { atlas_descriptor_id: Id, - faces: Array, + faces: Array, } impl CubemapDescriptor { diff --git a/crates/renderling/src/cubemap/cpu.rs b/crates/renderling/src/cubemap/cpu.rs index 3f614050..6c93a62f 100644 --- a/crates/renderling/src/cubemap/cpu.rs +++ b/crates/renderling/src/cubemap/cpu.rs @@ -5,7 +5,6 @@ use glam::{Mat4, UVec2, Vec3, Vec4}; use image::GenericImageView; use crate::{ - camera::Camera, stage::{Stage, StageRendering}, texture::Texture, }; @@ -90,7 +89,7 @@ impl SceneCubemap { let previous_camera_id = stage.used_camera_id(); // create a new camera for our cube, and use it to render with - let camera = stage.geometry.new_camera(Camera::default()); + let camera = stage.geometry.new_camera(); stage.use_camera(&camera); // By setting this to 90 degrees (PI/2 radians) we make sure the viewing field @@ -103,7 +102,7 @@ impl SceneCubemap { for (i, face) in CubemapFaceDirection::FACES.iter().enumerate() { // Update the camera angle, no need to sync as calling `Stage::render` does this // implicitly - camera.modify(|c| c.set_projection_and_view(projection, face.view())); + camera.set_projection_and_view(projection, face.view()); let label_s = format!("scene-to-cubemap-{i}"); let view = self .cubemap_texture @@ -288,23 +287,22 @@ mod test { .with_background_color(Vec4::ZERO) .with_lighting(false) .with_msaa_sample_count(4); - let _camera = - stage.new_camera( - Camera::default_perspective(width as f32, height as f32) - .with_view(Mat4::look_at_rh(Vec3::splat(3.0), Vec3::ZERO, Vec3::Y)), - ); + let projection = crate::camera::perspective(width as f32, height as f32); + let view = Mat4::look_at_rh(Vec3::splat(3.0), Vec3::ZERO, Vec3::Y); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); // geometry is the "clip cube" where colors are normalized 3d space coords let _rez = stage - .builder() - .with_vertices(UNIT_POINTS.map(|unit_cube_point| { + .new_renderlet() + .with_vertices(stage.new_vertices(UNIT_POINTS.map(|unit_cube_point| { Vertex::default() // multiply by 2.0 because the unit cube's AABB bounds are at 0.5, and we want 1.0 .with_position(unit_cube_point * 2.0) // "normalize" (really "shift") the space coord from [-0.5, 0.5] to [0.0, 1.0] .with_color((unit_cube_point + 0.5).extend(1.0)) - })) - .with_indices(UNIT_INDICES.map(|u| u as u32)) - .build(); + }))) + .with_indices(stage.new_indices(UNIT_INDICES.map(|u| u as u32))); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); diff --git a/crates/renderling/src/cull/cpu.rs b/crates/renderling/src/cull/cpu.rs index 8a93be6f..9815039c 100644 --- a/crates/renderling/src/cull/cpu.rs +++ b/crates/renderling/src/cull/cpu.rs @@ -684,19 +684,19 @@ mod test { let ctx = Context::headless(100, 100).block(); let stage = ctx.new_stage().with_background_color(Vec4::splat(1.0)); let camera_position = Vec3::new(0.0, 9.0, 9.0); - let _camera = stage.new_camera(Camera::new( + let _camera = stage.new_camera().with_projection_and_view( Mat4::perspective_rh(std::f32::consts::PI / 4.0, 1.0, 1.0, 24.0), Mat4::look_at_rh(camera_position, Vec3::ZERO, Vec3::Y), - )); + ); let _rez = stage - .builder() - .with_vertices(crate::test::gpu_cube_vertices()) - .with_transform(TransformDescriptor { - scale: Vec3::new(6.0, 6.0, 6.0), - rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), - ..Default::default() - }) - .build(); + .new_renderlet() + .with_vertices(stage.new_vertices(crate::test::gpu_cube_vertices())) + .with_transform( + stage + .new_transform() + .with_scale(Vec3::new(6.0, 6.0, 6.0)) + .with_rotation(Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4)), + ); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -790,7 +790,9 @@ mod test { let projection = Mat4::perspective_rh(fovy, aspect, znear, zfar); // Camera is looking straight down Z, towards the origin with Y up let view = Mat4::look_at_rh(Vec3::new(0.0, 0.0, 10.0), Vec3::ZERO, Vec3::Y); - stage.new_camera(Camera::new(projection, view)) + stage + .new_camera() + .with_projection_and_view(projection, view) }; let save_render = |s: &str| { @@ -813,25 +815,27 @@ mod test { ] .map(|(offset, suffix)| { let yellow = hex_to_vec4(0xFFE6A5FF); - let (transform, vertices, renderlet) = stage - .builder() - .with_transform(TransformDescriptor { - // move it back behind the purple cube - translation: (offset * 10.0).extend(-20.0), - // scale it up since it's a unit cube - scale: Vec3::splat(2.0), - ..Default::default() - }) - .with_vertices(crate::math::unit_cube().into_iter().map(|(p, n)| { - Vertex::default() - .with_position(p) - .with_normal(n) - .with_color(yellow) - })) - .with_bounds(BoundingSphere::new(Vec3::ZERO, Vec3::splat(0.5).length())) - .build(); + let renderlet = stage + .new_renderlet() + .with_transform( + stage + .new_transform() + // move it back behind the purple cube + .with_translation((offset * 10.0).extend(-20.0)) + // scale it up since it's a unit cube + .with_scale(Vec3::splat(2.0)), + ) + .with_vertices(stage.new_vertices(crate::math::unit_cube().into_iter().map( + |(p, n)| { + Vertex::default() + .with_position(p) + .with_normal(n) + .with_color(yellow) + }, + ))) + .with_bounds(BoundingSphere::new(Vec3::ZERO, Vec3::splat(0.5).length())); names.insert(renderlet.id(), format!("yellow_cube_{suffix}")); - (renderlet, transform, vertices) + renderlet }); save_render("0_yellow_cubes"); @@ -839,24 +843,27 @@ mod test { // We'll add a golden floor let _floor = { let golden = hex_to_vec4(0xFFBF61FF); - let (transform, vertices, renderlet) = stage - .builder() - .with_transform(TransformDescriptor { - // flip it so it's facing up, like a floor should be - rotation: Quat::from_rotation_x(std::f32::consts::FRAC_PI_2), - // move it down and back a bit - translation: Vec3::new(0.0, -5.0, -10.0), - // scale it up, since it's a unit quad - scale: Vec3::new(100.0, 100.0, 1.0), - }) + let renderlet = stage + .new_renderlet() + .with_transform( + stage + .new_transform() + // flip it so it's facing up, like a floor should be + .with_rotation(Quat::from_rotation_x(std::f32::consts::FRAC_PI_2)) + // move it down and back a bit + .with_translation(Vec3::new(0.0, -5.0, -10.0)) + // scale it up, since it's a unit quad + .with_scale(Vec3::new(100.0, 100.0, 1.0)), + ) .with_vertices( - crate::math::UNIT_QUAD_CCW - .map(|p| Vertex::default().with_position(p).with_color(golden)), + stage.new_vertices( + crate::math::UNIT_QUAD_CCW + .map(|p| Vertex::default().with_position(p).with_color(golden)), + ), ) - .with_bounds(BoundingSphere::new(Vec3::ZERO, Vec2::splat(0.5).length())) - .build(); + .with_bounds(BoundingSphere::new(Vec3::ZERO, Vec2::splat(0.5).length())); names.insert(renderlet.id(), "floor".into()); - (renderlet, transform, vertices) + renderlet }; save_render("1_floor"); @@ -864,26 +871,28 @@ mod test { // Add a green cube let _gcube = { let green = hex_to_vec4(0x8ABFA3FF); - let (transform, vertices, renderlet) = stage - .builder() - .with_transform(TransformDescriptor { - // move it back behind the purple cube - translation: Vec3::new(0.0, 0.0, -10.0), - // scale it up since it's a unit cube - scale: Vec3::splat(5.0), - ..Default::default() - }) - .with_vertices(crate::math::unit_cube().into_iter().map(|(p, n)| { - Vertex::default() - .with_position(p) - .with_normal(n) - .with_color(green) - })) - .with_bounds(BoundingSphere::new(Vec3::ZERO, Vec3::splat(0.5).length())) - .build(); + let renderlet = stage + .new_renderlet() + .with_transform( + stage + .new_transform() + // move it back behind the purple cube + .with_translation(Vec3::new(0.0, 0.0, -10.0)) + // scale it up since it's a unit cube + .with_scale(Vec3::splat(5.0)), + ) + .with_vertices(stage.new_vertices(crate::math::unit_cube().into_iter().map( + |(p, n)| { + Vertex::default() + .with_position(p) + .with_normal(n) + .with_color(green) + }, + ))) + .with_bounds(BoundingSphere::new(Vec3::ZERO, Vec3::splat(0.5).length())); stage.add_renderlet(&renderlet); names.insert(renderlet.id(), "green_cube".into()); - (renderlet, transform, vertices) + renderlet }; save_render("2_green_cube"); @@ -891,25 +900,27 @@ mod test { // And a purple cube let _pcube = { let purple = hex_to_vec4(0x605678FF); - let (transform, vertices, renderlet) = stage - .builder() - .with_transform(TransformDescriptor { - // move it back a bit - translation: Vec3::new(0.0, 0.0, -3.0), - // scale it up since it's a unit cube - scale: Vec3::splat(5.0), - ..Default::default() - }) - .with_vertices(crate::math::unit_cube().into_iter().map(|(p, n)| { - Vertex::default() - .with_position(p) - .with_normal(n) - .with_color(purple) - })) - .with_bounds(BoundingSphere::new(Vec3::ZERO, Vec3::splat(0.5).length())) - .build(); + let renderlet = stage + .new_renderlet() + .with_transform( + stage + .new_transform() + // move it back a bit + .with_translation(Vec3::new(0.0, 0.0, -3.0)) + // scale it up since it's a unit cube + .with_scale(Vec3::splat(5.0)), + ) + .with_vertices(stage.new_vertices(crate::math::unit_cube().into_iter().map( + |(p, n)| { + Vertex::default() + .with_position(p) + .with_normal(n) + .with_color(purple) + }, + ))) + .with_bounds(BoundingSphere::new(Vec3::ZERO, Vec3::splat(0.5).length())); names.insert(renderlet.id(), "purple_cube".into()); - (renderlet, transform, vertices) + renderlet }; // Do two renders, because depth pyramid operates on depth data one frame diff --git a/crates/renderling/src/draw/cpu.rs b/crates/renderling/src/draw/cpu.rs index a5f6e608..448ae6d2 100644 --- a/crates/renderling/src/draw/cpu.rs +++ b/crates/renderling/src/draw/cpu.rs @@ -1,39 +1,20 @@ //! CPU-only side of renderling/draw.rs use craballoc::{ - prelude::{Gpu, Hybrid, SlabAllocator, WeakHybrid, WgpuRuntime}, + prelude::{Gpu, SlabAllocator, WgpuRuntime}, slab::SlabBuffer, }; use crabslab::Id; -use rustc_hash::FxHashMap; use crate::{ cull::{ComputeCulling, CullingError}, - stage::RenderletDescriptor, + stage::{Renderlet, RenderletDescriptor, RenderletSortItem}, texture::Texture, Context, }; use super::DrawIndirectArgs; -/// Used to track renderlets internally. -#[repr(transparent)] -struct InternalRenderlet { - inner: WeakHybrid, -} - -impl InternalRenderlet { - fn has_external_references(&self) -> bool { - self.inner.strong_count() > 0 - } - - fn from_hybrid_renderlet(hr: &Hybrid) -> Self { - Self { - inner: WeakHybrid::from_hybrid(hr), - } - } -} - /// Issues indirect draw calls. /// /// Issues draw calls and performs culling. @@ -71,35 +52,6 @@ impl IndirectDraws { } } - fn get_indirect_buffer(&self) -> SlabBuffer { - self.slab.commit() - } - - fn sync_with_internal_renderlets( - &mut self, - internal_renderlets: &[InternalRenderlet], - redraw_args: bool, - ) -> SlabBuffer { - if redraw_args || self.draws.len() != internal_renderlets.len() { - self.invalidate(); - // Pre-upkeep to reclaim resources - this is necessary because - // the draw buffer has to be contiguous (it can't start with a bunch of trash) - let indirect_buffer = self.slab.commit(); - if indirect_buffer.is_new_this_commit() { - log::warn!("new indirect buffer"); - } - self.draws = internal_renderlets - .iter() - .map(|ir: &InternalRenderlet| { - self.slab - .new_value(DrawIndirectArgs::from(ir.inner.id())) - .into_gpu_only() - }) - .collect(); - } - self.get_indirect_buffer() - } - /// Read the images from the hierarchical z-buffer used for occlusion /// culling. /// @@ -149,7 +101,7 @@ impl DrawingStrategy { /// list of all [`Renderlet`]s. pub struct DrawCalls { /// Internal representation of all staged renderlets. - internal_renderlets: Vec, + renderlets: Vec, pub(crate) drawing_strategy: DrawingStrategy, } @@ -181,7 +133,7 @@ impl DrawCalls { } let can_use_compute_culling = use_compute_culling && can_use_multi_draw_indirect; Self { - internal_renderlets: vec![], + renderlets: vec![], drawing_strategy: DrawingStrategy { indirect: if can_use_compute_culling { log::debug!("Using indirect drawing method and compute culling"); @@ -205,93 +157,58 @@ impl DrawCalls { /// Add a renderlet to the drawing queue. /// /// Returns the number of draw calls in the queue. - pub fn add_renderlet(&mut self, renderlet: &Hybrid) -> usize { + pub fn add_renderlet(&mut self, renderlet: &Renderlet) -> usize { log::trace!("adding renderlet {:?}", renderlet.id()); if let Some(indirect) = &mut self.drawing_strategy.indirect { indirect.invalidate(); } - self.internal_renderlets - .push(InternalRenderlet::from_hybrid_renderlet(renderlet)); - self.internal_renderlets.len() + self.renderlets.push(renderlet.clone()); + self.renderlets.len() } /// Erase the given renderlet from the internal list of renderlets to be /// drawn each frame. /// /// Returns the number of draw calls remaining in the queue. - pub fn remove_renderlet(&mut self, renderlet: &Hybrid) -> usize { + pub fn remove_renderlet(&mut self, renderlet: &Renderlet) -> usize { let id = renderlet.id(); - self.internal_renderlets.retain(|ir| ir.inner.id() != id); + self.renderlets.retain(|ir| ir.descriptor.id() != id); if let Some(indirect) = &mut self.drawing_strategy.indirect { indirect.invalidate(); } - self.internal_renderlets.len() + self.renderlets.len() } - /// Re-order the renderlets to that of the given list of identifiers. - /// - /// This determines the order in which they are drawn each frame. - /// - /// If the `order` iterator is missing any renderlet ids, those missing - /// renderlets will be drawn _before_ the ordered ones, in no particular - /// order. - pub fn reorder_renderlets(&mut self, order: impl IntoIterator>) { - let mut ordered = vec![]; - let mut m = FxHashMap::from_iter( - std::mem::take(&mut self.internal_renderlets) - .into_iter() - .map(|r| (r.inner.id(), r)), - ); - for id in order.into_iter() { - if let Some(renderlet) = m.remove(&id) { - ordered.push(renderlet); - } - } - self.internal_renderlets.extend(m.into_values()); - self.internal_renderlets.extend(ordered); + /// Sort draw calls using a function compairing [`RenderletSortItem`]s. + pub fn sort_renderlets( + &mut self, + f: impl Fn(&RenderletSortItem, &RenderletSortItem) -> std::cmp::Ordering, + ) { + self.renderlets.sort_by(|a, b| { + let a = a.sort_item(); + let b = b.sort_item(); + f(&a, &b) + }); if let Some(indirect) = &mut self.drawing_strategy.indirect { indirect.invalidate(); } } - /// Iterator over all staged [`Renderlet`]s. - pub fn renderlets_iter(&self) -> impl Iterator> + '_ { - self.internal_renderlets.iter().map(|ir| ir.inner.clone()) - } - /// - /// Perform upkeep on queued draw calls and synchronize internal buffers. - pub fn upkeep(&mut self) { - let mut redraw_args = false; - - // Drop any renderlets that have no external references. - self.internal_renderlets.retain_mut(|ir| { - if ir.has_external_references() { - true - } else { - redraw_args = true; - log::trace!("dropping '{:?}' from drawing", ir.inner.id()); - false - } - }); - - if let Some(indirect) = &mut self.drawing_strategy.indirect { - indirect.sync_with_internal_renderlets(&self.internal_renderlets, redraw_args); - } + /// Return an iterator over all sort items. + pub fn sort_items(&self) -> impl Iterator + '_ { + self.renderlets.iter().map(Renderlet::sort_item) } /// Returns the number of draw calls (direct or indirect) that will be /// made during pre-rendering (compute culling) and rendering. pub fn draw_count(&self) -> usize { - self.internal_renderlets.len() + self.renderlets.len() } /// Perform pre-draw steps like frustum and occlusion culling, if available. /// - /// This does not do upkeep, please call [`DrawCalls::upkeep`] before - /// calling this function. - /// /// Returns the indirect draw buffer. pub fn pre_draw( &mut self, @@ -308,20 +225,31 @@ impl DrawCalls { // We can do this without multidraw by running GPU culling and then // copying `indirect_buffer` back to the CPU. if let Some(indirect) = &mut self.drawing_strategy.indirect { - let maybe_buffer = indirect.slab.get_buffer(); - if let Some(indirect_buffer) = maybe_buffer { - log::trace!("performing culling on {num_draw_calls} renderlets"); - indirect - .compute_culling - .run(num_draw_calls as u32, depth_texture); - Ok(Some(indirect_buffer)) - } else { - log::warn!( - "DrawCalls::pre_render called without first calling `upkeep` - no culling \ - was performed" - ); - Ok(None) + if indirect.draws.len() != self.renderlets.len() { + indirect.invalidate(); + // Pre-upkeep to reclaim resources - this is necessary because + // the draw buffer has to be contiguous (it can't start with a bunch of trash) + let indirect_buffer = indirect.slab.commit(); + if indirect_buffer.is_new_this_commit() { + log::warn!("new indirect buffer"); + } + indirect.draws = self + .renderlets + .iter() + .map(|r| { + indirect + .slab + .new_value(DrawIndirectArgs::from(r.descriptor.id())) + .into_gpu_only() + }) + .collect(); } + let indirect_buffer = indirect.slab.commit(); + log::trace!("performing culling on {num_draw_calls} renderlets"); + indirect + .compute_culling + .run(num_draw_calls as u32, depth_texture); + Ok(Some(indirect_buffer)) } else { Ok(None) } @@ -332,18 +260,16 @@ impl DrawCalls { /// Draw into the given `RenderPass` by directly calling each draw. pub fn draw_direct(&self, render_pass: &mut wgpu::RenderPass) { - if self.internal_renderlets.is_empty() { + if self.renderlets.is_empty() { log::warn!("no internal renderlets, nothing to draw"); } - for ir in self.internal_renderlets.iter() { + for ir in self.renderlets.iter() { // UNWRAP: panic on purpose - if let Some(hr) = ir.inner.upgrade() { - let ir = hr.get(); - let vertex_range = 0..ir.get_vertex_count(); - let id = hr.id(); - let instance_range = id.inner()..id.inner() + 1; - render_pass.draw(vertex_range, instance_range); - } + let desc = ir.descriptor.get(); + let vertex_range = 0..desc.get_vertex_count(); + let id = ir.descriptor.id(); + let instance_range = id.inner()..id.inner() + 1; + render_pass.draw(vertex_range, instance_range); } } diff --git a/crates/renderling/src/geometry.rs b/crates/renderling/src/geometry.rs index c2eb93af..96d1634d 100644 --- a/crates/renderling/src/geometry.rs +++ b/crates/renderling/src/geometry.rs @@ -7,33 +7,33 @@ mod cpu; pub use cpu::*; use glam::{Mat4, Vec2, Vec3, Vec4}; -use crate::{camera::Camera, math::IsVector, transform::TransformDescriptor}; +use crate::{camera::CameraDescriptor, math::IsVector, transform::TransformDescriptor}; -/// A vertex skin. +/// A vertex skin descriptor. /// /// For more info on vertex skinning, see /// #[derive(Clone, Copy, Default, SlabItem)] #[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -pub struct Skin { +pub struct SkinDescriptor { // Ids of the skeleton nodes' global transforms used as joints in this skin. - pub joints: Array>, + pub joints_array: Array>, // Contains the 4x4 inverse-bind matrices. // // When is none, each matrix is assumed to be the 4x4 identity matrix // which implies that the inverse-bind matrices were pre-applied. - pub inverse_bind_matrices: Array, + pub inverse_bind_matrices_array: Array, } -impl Skin { +impl SkinDescriptor { pub fn get_joint_matrix(&self, i: usize, vertex: Vertex, slab: &[u32]) -> Mat4 { let joint_index = vertex.joints[i] as usize; - let joint_id = slab.read(self.joints.at(joint_index)); + let joint_id = slab.read(self.joints_array.at(joint_index)); let joint_transform = slab.read(joint_id); // First apply the inverse bind matrix to bring the vertex into the joint's // local space, then apply the joint's current transformation to move it // into world space. - let inverse_bind_matrix = slab.read(self.inverse_bind_matrices.at(joint_index)); + let inverse_bind_matrix = slab.read(self.inverse_bind_matrices_array.at(joint_index)); Mat4::from(joint_transform) * inverse_bind_matrix } @@ -185,7 +185,7 @@ impl Vertex { #[derive(Clone, Copy, PartialEq, SlabItem)] #[offsets] pub struct GeometryDescriptor { - pub camera_id: Id, + pub camera_id: Id, pub atlas_size: glam::UVec2, pub resolution: glam::UVec2, pub debug_channel: crate::pbr::debug::DebugChannel, diff --git a/crates/renderling/src/geometry/cpu.rs b/crates/renderling/src/geometry/cpu.rs index 7cee5b09..3ea55abe 100644 --- a/crates/renderling/src/geometry/cpu.rs +++ b/crates/renderling/src/geometry/cpu.rs @@ -1,33 +1,280 @@ //! CPU side of the [super::geometry](geometry) module. -//! - use std::sync::{Arc, Mutex}; use craballoc::{ - runtime::WgpuRuntime, + runtime::{IsRuntime, WgpuRuntime}, slab::{SlabAllocator, SlabBuffer}, - value::{Hybrid, HybridArray}, + value::{GpuArray, Hybrid, HybridArray, IsContainer}, }; use crabslab::{Array, Id}; -use glam::{Mat4, UVec2}; +use glam::{Mat4, UVec2, Vec4}; use crate::{ camera::Camera, - geometry::{GeometryDescriptor, MorphTarget, Skin, Vertex}, + geometry::{GeometryDescriptor, MorphTarget, SkinDescriptor, Vertex}, prelude::TransformDescriptor, - stage::RenderletDescriptor, + transform::{NestedTransform, Transform}, + types::{GpuCpuArray, GpuOnlyArray}, }; +/// A contiguous array of vertices, staged on the GPU. +/// +/// The type variable `Ct` denotes whether the dta lives on the GPU only, or on +/// the CPU and the GPU. +pub struct Vertices { + inner: Ct::Container, +} + +impl Clone for Vertices +where + Ct: IsContainer, + Ct::Container: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } +} + +impl std::fmt::Debug for Vertices +where + Ct: IsContainer = Array>, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Vertices") + .field("array", &Ct::get_pointer(&self.inner)) + .finish() + } +} + +impl From for Vertices { + fn from(value: Vertices) -> Self { + value.into_gpu_only() + } +} + +impl From<&Vertices> for Vertices { + fn from(value: &Vertices) -> Self { + value.clone().into_gpu_only() + } +} + +impl From<&Vertices> for Vertices { + fn from(value: &Vertices) -> Self { + value.clone() + } +} + +impl Vertices { + /// Stage a new array of vertex data on the GPU. + /// + /// The resulting `Vertices` will live on the GPU and CPU, allowing for modification. + /// If you would like to unload the CPU side, use [`Vertices::into_gpu_only`]. + pub(crate) fn new( + slab: &SlabAllocator, + vertices: impl IntoIterator, + ) -> Self { + Vertices { + inner: slab.new_array(vertices), + } + } + + /// Unload the CPU side of vertex data. + /// + /// After this operation the data can still be updated using [`Vertices::set_item`], + /// but it cannot be modified in-place. + pub fn into_gpu_only(self) -> Vertices { + Vertices { + inner: self.inner.into_gpu_only(), + } + } +} + +impl Vertices +where + T: IsContainer = Array>, +{ + /// Returns a pointer to the underlying data on the GPU. + pub fn array(&self) -> Array { + T::get_pointer(&self.inner) + } +} + +/// A contiguous array of indices, staged on the GPU. +/// The type variable `Ct` denotes whether the data lives on the GPU only, or on +/// the CPU and the GPU. +pub struct Indices { + inner: Ct::Container, +} + +impl std::fmt::Debug for Indices +where + Ct: IsContainer = Array>, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Indices") + .field("array", &Ct::get_pointer(&self.inner)) + .finish() + } +} + +impl Clone for Indices +where + Ct: IsContainer, + Ct::Container: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } +} + +impl From for Indices { + fn from(value: Indices) -> Self { + value.into_gpu_only() + } +} + +impl From<&Indices> for Indices { + fn from(value: &Indices) -> Self { + value.clone().into_gpu_only() + } +} + +impl From<&Indices> for Indices { + fn from(value: &Indices) -> Self { + value.clone() + } +} + +impl Indices +where + T: IsContainer = Array>, +{ + /// Returns a pointer to the underlying data on the GPU. + pub fn array(&self) -> Array { + T::get_pointer(&self.inner) + } +} + +impl Indices { + /// Stage a new array of index data on the GPU. + /// + /// The resulting `Indices` will live on the GPU and CPU, allowing for modification. + /// If you would like to unload the CPU side, use [`Indices::into_gpu_only`]. + pub fn new(geometry: &Geometry, indices: impl IntoIterator) -> Self { + Indices { + inner: geometry.slab.new_array(indices), + } + } + + /// Unload the CPU side of this index data. + /// + /// After this operation the data can still be updated using [`Indices::set_item`], + /// but it cannot be modified in-place. + pub fn into_gpu_only(self) -> Indices { + Indices { + inner: self.inner.into_gpu_only(), + } + } +} + +/// Holds morph targets for animated nodes. +#[derive(Clone)] +pub struct MorphTargets { + // Held onto so the values don't drop from under us + _targets: Arc>>, + arrays: HybridArray>, +} + +impl From<&MorphTargets> for MorphTargets { + fn from(value: &MorphTargets) -> Self { + value.clone() + } +} + +impl std::fmt::Debug for MorphTargets { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("MorphTargets") + .field("arrays", &self.arrays) + .field("targets", &"...") + .finish() + } +} + +impl MorphTargets { + pub(crate) fn new( + slab: &SlabAllocator, + morph_targets: impl IntoIterator>, + ) -> Self { + let targets = morph_targets + .into_iter() + .map(|verts| slab.new_array(verts).into_gpu_only()) + .collect::>(); + let arrays = slab.new_array(targets.iter().map(|ts| ts.array())); + Self { + _targets: targets.into(), + arrays, + } + } + /// Returns a pointer to the underlying morph targets data on the GPU. + pub fn array(&self) -> Array> { + self.arrays.array() + } +} + +/// Holds morph targets weights for animated nodes. +#[derive(Clone, Debug)] +pub struct MorphTargetWeights { + inner: HybridArray, +} + +impl From<&MorphTargetWeights> for MorphTargetWeights { + fn from(value: &MorphTargetWeights) -> Self { + value.clone() + } +} + +impl MorphTargetWeights { + pub(crate) fn new( + slab: &SlabAllocator, + data: impl IntoIterator, + ) -> Self { + Self { + inner: slab.new_array(data), + } + } + + /// Returns a pointer to the underlying morph targets weights data on the GPU. + pub fn array(&self) -> Array { + self.inner.array() + } + + /// Return the weight at the given index, if any. + pub fn get_item(&self, index: usize) -> Option { + self.inner.get(index) + } + + /// Update the weight at the given index. + pub fn set_item(&self, index: usize, weight: f32) { + self.inner.set_item(index, weight); + } +} + /// Wrapper around the geometry slab, which holds mesh data and more. #[derive(Clone)] pub struct Geometry { slab: SlabAllocator, descriptor: Hybrid, + /// A plain white cube to use as default geometry. + default_vertices: Vertices, /// Holds the current camera just in case the user drops it, /// this way we never lose a camera that is in use. Dropping /// the camera would cause a blank screen, which is very confusing /// =( - _camera: Arc>>>, + camera: Arc>>, } impl AsRef for Geometry { @@ -51,10 +298,20 @@ impl Geometry { resolution, ..Default::default() }); + let default_vertices = Vertices::new( + &slab, + crate::math::unit_cube().into_iter().map(|(p, n)| { + Vertex::default() + .with_position(p) + .with_normal(n) + .with_color(Vec4::ONE) + }), + ); Self { slab, descriptor, - _camera: Default::default(), + default_vertices, + camera: Default::default(), } } @@ -70,6 +327,11 @@ impl Geometry { &self.descriptor } + /// Returns the vertices of a white unit cube. + pub fn default_vertices(&self) -> &Vertices { + &self.default_vertices + } + #[must_use] pub fn commit(&self) -> SlabBuffer { self.slab.commit() @@ -78,8 +340,8 @@ impl Geometry { /// Create a new camera. /// /// If this is the first camera created, it will be automatically used. - pub fn new_camera(&self, camera: Camera) -> Hybrid { - let c = self.slab.new_value(camera); + pub fn new_camera(&self) -> Camera { + let c = Camera::new(&self.slab); if self.descriptor.get().camera_id.is_none() { self.use_camera(&c); } @@ -87,70 +349,163 @@ impl Geometry { } /// Set all geometry to use the given camera. - pub fn use_camera(&self, camera: impl AsRef>) { - let c = camera.as_ref(); - log::info!("using camera: {:?}", c.id()); + pub fn use_camera(&self, camera: &Camera) { + let id = camera.id(); + log::info!("using camera: {id:?}"); // Save a clone so we never lose the active camera, even if the user drops it - *self._camera.lock().unwrap() = Some(c.clone()); - self.descriptor.modify(|cfg| cfg.camera_id = c.id()); + self.descriptor.modify(|cfg| cfg.camera_id = id); + *self.camera.lock().unwrap() = Some(camera.clone()); } /// Stage a new transform. - pub fn new_transform(&self, transform: TransformDescriptor) -> Hybrid { - self.slab.new_value(transform) + pub fn new_transform(&self) -> Transform { + Transform::new(&self.slab) } - /// Create new geometry data. - pub fn new_vertices(&self, data: impl IntoIterator) -> HybridArray { - self.slab.new_array(data) + /// Stage vertex geometry data on the GPU. + pub fn new_vertices(&self, vertices: impl IntoIterator) -> Vertices { + Vertices::new(self.slab_allocator(), vertices) } - /// Create new indices that point to offsets of an array of vertices. - pub fn new_indices(&self, data: impl IntoIterator) -> HybridArray { - self.slab.new_array(data) + /// Stage indices that point to offsets of an array of vertices. + pub fn new_indices(&self, indices: impl IntoIterator) -> Indices { + Indices::new(self, indices) } - /// Create new morph targets. + /// Stage new morph targets on the GPU. pub fn new_morph_targets( &self, - data: impl IntoIterator, - ) -> HybridArray { - self.slab.new_array(data) + data: impl IntoIterator>, + ) -> MorphTargets { + MorphTargets::new(&self.slab, data) } - /// Create an array of morph target arrays. - pub fn new_morph_targets_array( + /// Create new morph target weights. + pub fn new_morph_target_weights( &self, - data: impl IntoIterator>, - ) -> HybridArray> { - let morph_targets = data.into_iter(); - self.slab.new_array(morph_targets) + data: impl IntoIterator, + ) -> MorphTargetWeights { + MorphTargetWeights::new(&self.slab, data) } - /// Create new morph target weights. - pub fn new_weights(&self, data: impl IntoIterator) -> HybridArray { + /// Create a new array of matrices. + pub fn new_matrices(&self, data: impl IntoIterator) -> HybridArray { self.slab.new_array(data) } - /// Create a new array of joint transform ids that each point to a [`Transform`]. - pub fn new_joint_transform_ids( + pub fn new_skin( &self, - data: impl IntoIterator>, - ) -> HybridArray> { - self.slab.new_array(data) + joints: impl IntoIterator>, + inverse_bind_matrices: impl IntoIterator>, + ) -> Skin { + Skin::new(self.slab_allocator(), joints, inverse_bind_matrices) } +} - /// Create a new array of matrices. - pub fn new_matrices(&self, data: impl IntoIterator) -> HybridArray { - self.slab.new_array(data) +/// A vertex skin. +/// +/// For more info on vertex skinning, see +/// +#[derive(Clone)] +pub struct Skin { + descriptor: Hybrid, + joints: HybridArray>, + // Held onto so the transforms don't drop from under us + _skin_joints: Arc>>, + // Contains the 4x4 inverse-bind matrices. + // + // When None, each matrix is assumed to be the 4x4 identity matrix which implies that the + // inverse-bind matrices were pre-applied. + _inverse_bind_matrices: Arc>>>, +} + +impl From<&Skin> for Skin { + fn from(value: &Skin) -> Self { + value.clone() } +} - /// Create a new skin. - pub fn new_skin(&self, skin: Skin) -> Hybrid { - self.slab.new_value(skin) +impl core::fmt::Debug for Skin { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("Skin") + .field("descriptor", &self.descriptor) + .field("joints", &self.joints) + .field("joint_transforms", &"...") + .field("inverse_bind_matrices", &"...") + .finish() } +} + +impl Skin { + /// Stage a new skin on the GPU. + pub fn new( + slab: &SlabAllocator, + joints: impl IntoIterator>, + inverse_bind_matrices: impl IntoIterator>, + ) -> Self { + let descriptor = slab.new_value(SkinDescriptor::default()); + let skin_joints = joints.into_iter().map(|t| t.into()).collect::>(); + let joints = skin_joints.iter().map(|sj| sj.0.id()).collect::>(); + let inverse_bind_matrices = inverse_bind_matrices + .into_iter() + .map(|m| m.into()) + .collect::>(); + let inverse_bind_matrices = if inverse_bind_matrices.is_empty() { + None + } else { + Some(slab.new_array(inverse_bind_matrices).into_gpu_only()) + }; + + Skin { + descriptor, + joints: slab.new_array(joints), + // We hold on to the transforms so they don't get dropped if the user drops them. + _skin_joints: Arc::new(Mutex::new(skin_joints)), + _inverse_bind_matrices: Arc::new(Mutex::new(inverse_bind_matrices)), + } + } + + /// Return a pointer to the underlying descriptor data on the GPU. + pub fn id(&self) -> Id { + self.descriptor.id() + } + + /// Return a copy of the underlying descriptor. + pub fn descriptor(&self) -> SkinDescriptor { + self.descriptor.get() + } +} + +/// A joint in a skinned rigging. +/// +/// This is a thin wrapper over [`Transform`] and +/// [`NestedTransform`]. You can create a [`SkinJoint`] +/// from either of those types using the [`From`] trait. +/// +/// You can also pass an iterator of either [`Transform`] or [`NestedTransform`] +/// to [`Stage::new_skin`]. +pub struct SkinJoint(pub(crate) Transform); + +impl From for SkinJoint { + fn from(transform: Transform) -> Self { + SkinJoint(transform) + } +} + +impl From<&Transform> for SkinJoint { + fn from(transform: &Transform) -> Self { + transform.clone().into() + } +} + +impl From for SkinJoint { + fn from(value: NestedTransform) -> Self { + SkinJoint(value.global_transform) + } +} - pub fn new_renderlet(&self, renderlet: RenderletDescriptor) -> Hybrid { - self.slab.new_value(renderlet) +impl From<&NestedTransform> for SkinJoint { + fn from(value: &NestedTransform) -> Self { + value.clone().into() } } diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index 44ea2e70..ba57b150 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -196,8 +196,9 @@ pub mod sync; pub mod texture; pub mod tonemapping; pub mod transform; -pub mod tuple; pub mod tutorial; +#[cfg(cpu)] +pub mod types; #[cfg(feature = "ui")] pub mod ui; @@ -236,10 +237,7 @@ macro_rules! println { #[cfg(test)] mod test { use super::*; - use crate::{ - atlas::AtlasImage, camera::Camera, geometry::Vertex, material::MaterialDescriptor, - transform::TransformDescriptor, - }; + use crate::{atlas::AtlasImage, geometry::Vertex}; use glam::{Mat3, Mat4, Quat, UVec2, Vec2, Vec3, Vec4}; use img_diff::DiffCfg; @@ -382,8 +380,12 @@ mod test { fn cmy_triangle_sanity() { let ctx = Context::headless(100, 100).block(); let stage = ctx.new_stage().with_background_color(Vec4::splat(1.0)); - let _camera = stage.new_camera(Camera::default_ortho2d(100.0, 100.0)); - let _rez = stage.builder().with_vertices(right_tri_vertices()).build(); + let (p, v) = crate::camera::default_ortho2d(100.0, 100.0); + let _camera = stage.new_camera().with_projection_and_view(p, v); + + let _prim = stage + .new_renderlet() + .with_vertices(stage.new_vertices(right_tri_vertices())); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -419,15 +421,13 @@ mod test { let ctx = Context::headless(100, 100).block(); let stage = ctx.new_stage().with_background_color(Vec4::splat(1.0)); - let _camera = stage.new_camera(Camera::default_ortho2d(100.0, 100.0)); - let _rez = stage - .builder() - .with_vertices({ - let mut vs = right_tri_vertices(); - vs.reverse(); - vs - }) - .build(); + let (p, v) = crate::camera::default_ortho2d(100.0, 100.0); + let _camera = stage.new_camera().with_projection_and_view(p, v); + let _rez = stage.new_renderlet().with_vertices(stage.new_vertices({ + let mut vs = right_tri_vertices(); + vs.reverse(); + vs + })); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -449,21 +449,21 @@ mod test { fn cmy_triangle_update_transform() { let ctx = Context::headless(100, 100).block(); let stage = ctx.new_stage().with_background_color(Vec4::splat(1.0)); - let _camera = stage.new_camera(Camera::default_ortho2d(100.0, 100.0)); - let (_vertices, transform, _renderlet) = stage - .builder() - .with_vertices(right_tri_vertices()) - .with_transform(TransformDescriptor::default()) - .build(); + let (p, v) = crate::camera::default_ortho2d(100.0, 100.0); + let _camera = stage.new_camera().with_projection_and_view(p, v); + let transform = stage.new_transform(); + let _renderlet = stage + .new_renderlet() + .with_vertices(stage.new_vertices(right_tri_vertices())) + .with_transform(&transform); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); - transform.set(TransformDescriptor { - translation: Vec3::new(100.0, 0.0, 0.0), - rotation: Quat::from_axis_angle(Vec3::Z, std::f32::consts::FRAC_PI_2), - scale: Vec3::new(0.5, 0.5, 1.0), - }); + transform + .set_translation(Vec3::new(100.0, 0.0, 0.0)) + .set_rotation(Quat::from_axis_angle(Vec3::Z, std::f32::consts::FRAC_PI_2)) + .set_scale(Vec3::new(0.5, 0.5, 1.0)); stage.render(&frame.view()); let img = frame.read_linear_image().block().unwrap(); @@ -515,19 +515,19 @@ mod test { let ctx = Context::headless(100, 100).block(); let stage = ctx.new_stage().with_background_color(Vec4::splat(1.0)); let camera_position = Vec3::new(0.0, 12.0, 20.0); - let _camera = stage.new_camera(Camera::new( + let _camera = stage.new_camera().with_projection_and_view( Mat4::perspective_rh(std::f32::consts::PI / 4.0, 1.0, 0.1, 100.0), Mat4::look_at_rh(camera_position, Vec3::ZERO, Vec3::Y), - )); + ); let _rez = stage - .builder() - .with_vertices(gpu_cube_vertices()) - .with_transform(TransformDescriptor { - scale: Vec3::new(6.0, 6.0, 6.0), - rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), - ..Default::default() - }) - .build(); + .new_renderlet() + .with_vertices(stage.new_vertices(gpu_cube_vertices())) + .with_transform( + stage + .new_transform() + .with_scale(Vec3::new(6.0, 6.0, 6.0)) + .with_rotation(Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4)), + ); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -541,20 +541,21 @@ mod test { let ctx = Context::headless(100, 100).block(); let stage = ctx.new_stage().with_background_color(Vec4::splat(1.0)); let camera_position = Vec3::new(0.0, 12.0, 20.0); - let _camera = stage.new_camera(Camera::new( + let _camera = stage.new_camera().with_projection_and_view( Mat4::perspective_rh(std::f32::consts::PI / 4.0, 1.0, 0.1, 100.0), Mat4::look_at_rh(camera_position, Vec3::ZERO, Vec3::Y), - )); + ); + let _rez = stage - .builder() - .with_vertices(math::UNIT_POINTS.map(cmy_gpu_vertex)) - .with_indices(math::UNIT_INDICES.map(|i| i as u32)) - .with_transform(TransformDescriptor { - scale: Vec3::new(6.0, 6.0, 6.0), - rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), - ..Default::default() - }) - .build(); + .new_renderlet() + .with_vertices(stage.new_vertices(math::UNIT_POINTS.map(cmy_gpu_vertex))) + .with_indices(stage.new_indices(math::UNIT_INDICES.map(|i| i as u32))) + .with_transform( + stage + .new_transform() + .with_scale(Vec3::new(6.0, 6.0, 6.0)) + .with_rotation(Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4)), + ); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -576,26 +577,31 @@ mod test { let ctx = Context::headless(100, 100).block(); let stage = ctx.new_stage().with_background_color(Vec4::splat(1.0)); let (projection, view) = camera::default_perspective(100.0, 100.0); - let _camera = stage.new_camera(Camera::new(projection, view)); - let (geometry, _cube_one_transform, _cube_one) = stage - .builder() - .with_vertices(gpu_cube_vertices()) - .with_transform(TransformDescriptor { - translation: Vec3::new(-4.5, 0.0, 0.0), - scale: Vec3::new(6.0, 6.0, 6.0), - rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), - }) - .build(); - - let (_cube_two_transform, cube_two) = stage - .builder() - .with_vertices_array(geometry.array()) - .with_transform(TransformDescriptor { - translation: Vec3::new(4.5, 0.0, 0.0), - scale: Vec3::new(6.0, 6.0, 6.0), - rotation: Quat::from_axis_angle(Vec3::Y, std::f32::consts::FRAC_PI_4), - }) - .build(); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); + let geometry = stage.new_vertices(gpu_cube_vertices()); + let _cube_one = stage + .new_renderlet() + .with_vertices(&geometry) + .with_transform( + stage + .new_transform() + .with_translation(Vec3::new(-4.5, 0.0, 0.0)) + .with_scale(Vec3::new(6.0, 6.0, 6.0)) + .with_rotation(Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4)), + ); + + let cube_two = stage + .new_renderlet() + .with_vertices(&geometry) + .with_transform( + stage + .new_transform() + .with_translation(Vec3::new(4.5, 0.0, 0.0)) + .with_scale(Vec3::new(6.0, 6.0, 6.0)) + .with_rotation(Quat::from_axis_angle(Vec3::Y, std::f32::consts::FRAC_PI_4)), + ); // we should see two colored cubes let frame = ctx.get_next_frame().unwrap(); @@ -606,7 +612,7 @@ mod test { frame.present(); // update cube two making it invisible - cube_two.modify(|r| r.visible = false); + cube_two.set_visible(false); // we should see only one colored cube let frame = ctx.get_next_frame().unwrap(); @@ -616,7 +622,7 @@ mod test { frame.present(); // update cube two making in visible again - cube_two.modify(|r| r.visible = true); + cube_two.set_visible(true); // we should see two colored cubes again let frame = ctx.get_next_frame().unwrap(); @@ -635,15 +641,20 @@ mod test { .with_lighting(false) .with_background_color(Vec4::splat(1.0)); let (projection, view) = camera::default_perspective(100.0, 100.0); - let _camera = stage.new_camera(Camera::new(projection, view)); - let (_cube_geometry, _transform, cube) = stage - .builder() - .with_vertices(math::UNIT_INDICES.map(|i| cmy_gpu_vertex(math::UNIT_POINTS[i]))) - .with_transform(TransformDescriptor { - scale: Vec3::new(10.0, 10.0, 10.0), - ..Default::default() - }) - .build(); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); + let cube = stage + .new_renderlet() + .with_vertices( + stage + .new_vertices(math::UNIT_INDICES.map(|i| cmy_gpu_vertex(math::UNIT_POINTS[i]))), + ) + .with_transform( + stage + .new_transform() + .with_scale(Vec3::new(10.0, 10.0, 10.0)), + ); // we should see a cube (in sRGB color space) let frame = ctx.get_next_frame().unwrap(); @@ -657,7 +668,7 @@ mod test { let pyramid_points = pyramid_points(); let pyramid_geometry = stage .new_vertices(pyramid_indices().map(|i| cmy_gpu_vertex(pyramid_points[i as usize]))); - cube.modify(|r| r.vertices_array = pyramid_geometry.array()); + cube.set_vertices(pyramid_geometry); // we should see a pyramid (in sRGB color space) let frame = ctx.get_next_frame().unwrap(); @@ -719,26 +730,27 @@ mod test { let ctx = Context::headless(100, 100).block(); let stage = ctx.new_stage().with_background_color(Vec4::splat(0.0)); let (projection, view) = camera::default_perspective(100.0, 100.0); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let sandstone = AtlasImage::from(image::open("../../img/sandstone.png").unwrap()); let dirt = AtlasImage::from(image::open("../../img/dirt.jpg").unwrap()); let entries = stage.set_images([sandstone, dirt]).unwrap(); - let (material, _geometry, _transform, cube) = stage - .builder() - .with_material(MaterialDescriptor { - albedo_texture_id: entries[0].id(), - has_lighting: false, - ..Default::default() - }) - .with_vertices(gpu_uv_unit_cube()) - .with_transform(TransformDescriptor { - scale: Vec3::new(10.0, 10.0, 10.0), - ..Default::default() - }) - .build(); - println!("cube: {cube:?}"); + let material = stage + .new_material() + .with_albedo_texture(&entries[0]) + .with_has_lighting(false); + let cube = stage + .new_renderlet() + .with_vertices(stage.new_vertices(gpu_uv_unit_cube())) + .with_transform( + stage + .new_transform() + .with_scale(Vec3::new(10.0, 10.0, 10.0)), + ); + println!("cube: {:?}", cube.descriptor()); // we should see a cube with a stoney texture let frame = ctx.get_next_frame().unwrap(); @@ -748,7 +760,7 @@ mod test { frame.present(); // update the material's texture on the GPU - material.modify(|m| m.albedo_texture_id = entries[1].id()); + material.set_albedo_texture(&entries[1]); // we should see a cube with a dirty texture let frame = ctx.get_next_frame().unwrap(); @@ -776,53 +788,50 @@ mod test { .with_background_color(Vec3::splat(0.0).extend(1.0)); let (projection, view) = camera::default_ortho2d(100.0, 100.0); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); // now test the textures functionality let img = AtlasImage::from_path("../../img/cheetah.jpg").unwrap(); let entries = stage.set_images([img]).unwrap(); - let (geometry, _color_prim) = stage - .builder() - .with_vertices([ - Vertex { - position: Vec3::new(0.0, 0.0, 0.0), - color: Vec4::new(1.0, 1.0, 0.0, 1.0), - uv0: Vec2::new(0.0, 0.0), - uv1: Vec2::new(0.0, 0.0), - ..Default::default() - }, - Vertex { - position: Vec3::new(100.0, 100.0, 0.0), - color: Vec4::new(0.0, 1.0, 1.0, 1.0), - uv0: Vec2::new(1.0, 1.0), - uv1: Vec2::new(1.0, 1.0), - ..Default::default() - }, - Vertex { - position: Vec3::new(100.0, 0.0, 0.0), - color: Vec4::new(1.0, 0.0, 1.0, 1.0), - uv0: Vec2::new(1.0, 0.0), - uv1: Vec2::new(1.0, 0.0), - ..Default::default() - }, - ]) - .build(); - - let _rez = stage - .builder() - .with_vertices_array(geometry.array()) - .with_material(MaterialDescriptor { - albedo_texture_id: entries[0].id(), - has_lighting: false, + let geometry = stage.new_vertices([ + Vertex { + position: Vec3::new(0.0, 0.0, 0.0), + color: Vec4::new(1.0, 1.0, 0.0, 1.0), + uv0: Vec2::new(0.0, 0.0), + uv1: Vec2::new(0.0, 0.0), + ..Default::default() + }, + Vertex { + position: Vec3::new(100.0, 100.0, 0.0), + color: Vec4::new(0.0, 1.0, 1.0, 1.0), + uv0: Vec2::new(1.0, 1.0), + uv1: Vec2::new(1.0, 1.0), ..Default::default() - }) - .with_transform(TransformDescriptor { - translation: Vec3::new(15.0, 35.0, 0.5), - scale: Vec3::new(0.5, 0.5, 1.0), + }, + Vertex { + position: Vec3::new(100.0, 0.0, 0.0), + color: Vec4::new(1.0, 0.0, 1.0, 1.0), + uv0: Vec2::new(1.0, 0.0), + uv1: Vec2::new(1.0, 0.0), ..Default::default() - }) - .build(); + }, + ]); + let material = stage + .new_material() + .with_albedo_texture(&entries[0]) + .with_has_lighting(false); + let transform = stage + .new_transform() + .with_translation(Vec3::new(15.0, 35.0, 0.5)) + .with_scale(Vec3::new(0.5, 0.5, 1.0)); + let _rez = stage + .new_renderlet() + .with_vertices(&geometry) + .with_material(material) + .with_transform(transform); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -843,7 +852,9 @@ mod test { let (projection, _) = camera::default_perspective(100.0, 100.0); let view = Mat4::look_at_rh(Vec3::new(1.8, 1.8, 1.8), Vec3::ZERO, Vec3::Y); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let red = Vec3::X.extend(1.0); let green = Vec3::Y.extend(1.0); @@ -878,23 +889,15 @@ mod test { ); let _rez = stage - .builder() - .with_material(MaterialDescriptor::default()) - .with_vertices( - math::unit_cube() - .into_iter() - .map(|(p, n)| Vertex { - position: p, - normal: n, - color: Vec4::ONE, - ..Default::default() - }) - .collect::>(), - ) - .build(); + .new_renderlet() + .with_material(stage.default_material()); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); + println!( + "lighting_descriptor: {:#?}", + stage.lighting.lighting_descriptor.get() + ); let img = frame.read_image().block().unwrap(); let depth_texture = stage.get_depth_texture(); let depth_img = depth_texture.read_image().block().unwrap().unwrap(); @@ -946,76 +949,71 @@ mod test { let ctx = Context::headless(100, 100).block(); let stage = ctx.new_stage().with_background_color(Vec4::splat(0.0)); let (projection, view) = camera::default_ortho2d(100.0, 100.0); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); - let root_node = stage.new_nested_transform(); - root_node.set(TransformDescriptor { - scale: Vec3::new(25.0, 25.0, 1.0), - ..Default::default() - }); - println!("root_node: {:#?}", root_node.get_global_transform()); + let root_node = stage + .new_nested_transform() + .with_scale(Vec3::new(25.0, 25.0, 1.0)); + println!("root_node: {:#?}", root_node.global_descriptor()); - let offset = TransformDescriptor { - translation: Vec3::new(1.0, 1.0, 0.0), - ..Default::default() - }; + let offset = Vec3::new(1.0, 1.0, 0.0); - let cyan_node = stage.new_nested_transform(); - cyan_node.set(offset); - println!("cyan_node: {:#?}", cyan_node.get_global_transform()); + let cyan_node = stage.new_nested_transform().with_translation(offset); + println!("cyan_node: {:#?}", cyan_node.global_descriptor()); - let yellow_node = stage.new_nested_transform(); - yellow_node.set(offset); - println!("yellow_node: {:#?}", yellow_node.get_global_transform()); + let yellow_node = stage.new_nested_transform().with_translation(offset); + println!("yellow_node: {:#?}", yellow_node.global_descriptor()); - let red_node = stage.new_nested_transform(); - red_node.set(offset); - println!("red_node: {:#?}", red_node.get_global_transform()); + let red_node = stage.new_nested_transform().with_translation(offset); + println!("red_node: {:#?}", red_node.global_descriptor()); root_node.add_child(&cyan_node); - println!("cyan_node: {:#?}", cyan_node.get_global_transform()); + println!("cyan_node: {:#?}", cyan_node.global_descriptor()); cyan_node.add_child(&yellow_node); - println!("yellow_node: {:#?}", yellow_node.get_global_transform()); + println!("yellow_node: {:#?}", yellow_node.global_descriptor()); yellow_node.add_child(&red_node); - println!("red_node: {:#?}", red_node.get_global_transform()); - - let (geometry, _cyan_material, _cyan_primitive) = stage - .builder() - .with_vertices({ - let size = 1.0; - [ - Vertex::default().with_position([0.0, 0.0, 0.0]), - Vertex::default().with_position([size, size, 0.0]), - Vertex::default().with_position([size, 0.0, 0.0]), - ] - }) - .with_material(MaterialDescriptor { - albedo_factor: Vec4::new(0.0, 1.0, 1.0, 1.0), - has_lighting: false, - ..Default::default() - }) - .with_nested_transform(&cyan_node) - .build(); - let _yellow = stage - .builder() - .with_vertices_array(geometry.array()) - .with_material(MaterialDescriptor { - albedo_factor: Vec4::new(1.0, 1.0, 0.0, 1.0), - has_lighting: false, - ..Default::default() - }) - .with_nested_transform(&yellow_node) - .build(); - let _red = stage - .builder() - .with_vertices_array(geometry.array()) - .with_material(MaterialDescriptor { - albedo_factor: Vec4::new(1.0, 0.0, 0.0, 1.0), - has_lighting: false, - ..Default::default() - }) - .with_nested_transform(&red_node) - .build(); + println!("red_node: {:#?}", red_node.global_descriptor()); + + let geometry = stage.new_vertices({ + let size = 1.0; + [ + Vertex::default().with_position([0.0, 0.0, 0.0]), + Vertex::default().with_position([size, size, 0.0]), + Vertex::default().with_position([size, 0.0, 0.0]), + ] + }); + let _cyan_primitive = stage + .new_renderlet() + .with_vertices(&geometry) + .with_material( + stage + .new_material() + .with_albedo_factor(Vec4::new(0.0, 1.0, 1.0, 1.0)) + .with_has_lighting(false), + ) + .with_transform(&cyan_node); + let _yellow_primitive = stage + .new_renderlet() + .with_vertices(&geometry) + .with_material( + stage + .new_material() + .with_albedo_factor(Vec4::new(1.0, 1.0, 0.0, 1.0)) + .with_has_lighting(false), + ) + .with_transform(&yellow_node); + let _red_primitive = stage + .new_renderlet() + .with_vertices(&geometry) + .with_material( + stage + .new_material() + .with_albedo_factor(Vec4::new(1.0, 0.0, 0.0, 1.0)) + .with_has_lighting(false), + ) + .with_transform(&red_node); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -1041,19 +1039,19 @@ mod test { // create the CMY cube let camera_position = Vec3::new(0.0, 12.0, 20.0); - let _camera = stage.new_camera(Camera::new( + let _camera = stage.new_camera().with_projection_and_view( Mat4::perspective_rh(std::f32::consts::PI / 4.0, 1.0, 0.1, 100.0), Mat4::look_at_rh(camera_position, Vec3::ZERO, Vec3::Y), - )); + ); let _rez = stage - .builder() - .with_vertices(gpu_cube_vertices()) - .with_transform(TransformDescriptor { - scale: Vec3::new(6.0, 6.0, 6.0), - rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), - ..Default::default() - }) - .build(); + .new_renderlet() + .with_vertices(stage.new_vertices(gpu_cube_vertices())) + .with_transform( + stage + .new_transform() + .with_scale(Vec3::new(6.0, 6.0, 6.0)) + .with_rotation(Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4)), + ); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -1084,19 +1082,19 @@ mod test { // create the CMY cube let camera_position = Vec3::new(0.0, 12.0, 20.0); - let _camera = stage.new_camera(Camera::new( + let _camera = stage.new_camera().with_projection_and_view( Mat4::perspective_rh(std::f32::consts::PI / 4.0, 1.0, 0.1, 100.0), Mat4::look_at_rh(camera_position, Vec3::ZERO, Vec3::Y), - )); + ); let _rez = stage - .builder() - .with_vertices(gpu_cube_vertices()) - .with_transform(TransformDescriptor { - scale: Vec3::new(6.0, 6.0, 6.0), - rotation: Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4), - ..Default::default() - }) - .build(); + .new_renderlet() + .with_vertices(stage.new_vertices(gpu_cube_vertices())) + .with_transform( + stage + .new_transform() + .with_scale(Vec3::new(6.0, 6.0, 6.0)) + .with_rotation(Quat::from_axis_angle(Vec3::Y, -std::f32::consts::FRAC_PI_4)), + ); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); diff --git a/crates/renderling/src/light.rs b/crates/renderling/src/light.rs index 4fda7d9c..4d219972 100644 --- a/crates/renderling/src/light.rs +++ b/crates/renderling/src/light.rs @@ -12,7 +12,7 @@ use spirv_std::num_traits::Float; use spirv_std::{spirv, Image}; use crate::{ - atlas::{AtlasDescriptor, AtlasTexture}, + atlas::{AtlasDescriptor, AtlasTextureDescriptor}, cubemap::{CubemapDescriptor, CubemapFaceDirection}, geometry::GeometryDescriptor, math::{Fetch, IsSampler, IsVector, Sample2dArray}, @@ -67,7 +67,7 @@ pub struct ShadowMapDescriptor { /// /// This will be an array of one `Id` for directional and spot lights, /// and an array of four `Id`s for a point light. - pub atlas_textures_array: Array>, + pub atlas_textures_array: Array>, pub bias_min: f32, pub bias_max: f32, pub pcf_samples: u32, @@ -606,7 +606,7 @@ impl ShadowCalculation { } } - fn get_atlas_texture_at(&self, light_slab: &[u32], index: usize) -> AtlasTexture { + fn get_atlas_texture_at(&self, light_slab: &[u32], index: usize) -> AtlasTextureDescriptor { let atlas_texture_id = light_slab.read_unchecked(self.shadow_map_desc.atlas_textures_array.at(index)); light_slab.read_unchecked(atlas_texture_id) diff --git a/crates/renderling/src/light/cpu.rs b/crates/renderling/src/light/cpu.rs index c9ff1e67..bf1c72a7 100644 --- a/crates/renderling/src/light/cpu.rs +++ b/crates/renderling/src/light/cpu.rs @@ -14,7 +14,7 @@ use crate::{ atlas::{Atlas, AtlasBlitter, AtlasError}, geometry::Geometry, prelude::TransformDescriptor, - stage::NestedTransform, + transform::{NestedTransform, Transform}, }; use super::{ @@ -125,6 +125,9 @@ impl LightDetails { /// /// Create an `AnalyticalLightBundle` with the `Lighting::new_analytical_light`, /// or from `Stage::new_analytical_light`. +// TODO: rework the light API. +// * to not be based on descriptors +// * to match the rest of the builder style APIs pub struct AnalyticalLight { /// The generic light descriptor. light: Ct::Container, @@ -133,14 +136,14 @@ pub struct AnalyticalLight { /// The light's global transform. /// /// This value lives in the lighting slab. - transform: Ct::Container, + transform: Transform, /// The light's nested transform. /// /// This value comes from the light's node, if it belongs to one. /// This may have been set if this light originated from a GLTF file. /// This value lives on the geometry slab and must be referenced here /// to keep the two in sync, which is required to animate lights. - node_transform: Arc>>>, + node_transform: Arc>>, } impl core::fmt::Display for AnalyticalLight { @@ -149,10 +152,11 @@ impl core::fmt::Display for AnalyticalLight { "AnalyticalLightBundle type={} light-id={:?} node-nested-transform-global-id:{:?}", self.light_details.style(), self.light.id(), - self.node_transform.read().unwrap().as_ref().and_then(|wh| { - let h: NestedTransform = wh.upgrade()?; - Some(h.global_transform_id()) - }) + self.node_transform + .read() + .unwrap() + .as_ref() + .and_then(|h| { Some(h.global_id()) }) )) } } @@ -162,7 +166,6 @@ where Ct::Container: Clone, Ct::Container: Clone, LightDetails: Clone, - NestedTransform: Clone, { fn clone(&self) -> Self { Self { @@ -179,7 +182,7 @@ impl AnalyticalLight { AnalyticalLight { light: WeakHybrid::from_hybrid(&light.light), light_details: LightDetails::from_hybrid(&light.light_details), - transform: WeakHybrid::from_hybrid(&light.transform), + transform: light.transform.clone(), node_transform: light.node_transform.clone(), } } @@ -188,7 +191,7 @@ impl AnalyticalLight { Some(AnalyticalLight { light: self.light.upgrade()?, light_details: self.light_details.upgrade()?, - transform: self.transform.upgrade()?, + transform: self.transform.clone(), node_transform: self.node_transform.clone(), }) } @@ -200,7 +203,7 @@ impl AnalyticalLight { } pub fn light_space_transforms(&self, z_near: f32, z_far: f32) -> Vec { - let t = self.transform.get(); + let t = self.transform.descriptor(); let m = Mat4::from(t); match &self.light_details { LightDetails::Directional(d) => vec![{ @@ -228,8 +231,7 @@ impl AnalyticalLight { impl AnalyticalLight { /// Link this light to a node's `NestedTransform`. pub fn link_node_transform(&self, transform: &NestedTransform) { - *self.node_transform.write().unwrap() = - Some(NestedTransform::::from_hybrid(transform)); + *self.node_transform.write().unwrap() = Some(transform.clone()); } /// Get a reference to the generic light descriptor. @@ -250,7 +252,7 @@ impl AnalyticalLight { /// If a `NestedTransform` has been linked to this light by using [`Self::link_node_transform`], /// the transform returned by this function may be overwritten at any point by the given /// `NestedTransform`. - pub fn transform(&self) -> &Ct::Container { + pub fn transform(&self) -> &Transform { &self.transform } @@ -261,9 +263,11 @@ impl AnalyticalLight { /// To change this value, you should do so through the `NestedTransform`, which is likely /// held in the pub fn linked_node_transform(&self) -> Option { - let guard = self.node_transform.read().unwrap(); - let weak = guard.as_ref()?; - weak.upgrade() + self.node_transform + .read() + .unwrap() + .as_ref() + .map(|t| t.clone()) } } @@ -444,7 +448,7 @@ impl Lighting { Light: From>, LightDetails: From>, { - let transform = self.light_slab.new_value(TransformDescriptor::default()); + let transform = Transform::new(&self.light_slab); let light_inner = self.light_slab.new_value(light_descriptor); let light = self.light_slab.new_value({ let mut light = Light::from(light_inner.id()); @@ -499,24 +503,18 @@ impl Lighting { lights_guard.retain_mut(|light_bundle| { let has_refs = light_bundle.light.has_external_references(); if has_refs { - let mut node_transform_guard = light_bundle.node_transform.write().unwrap(); // References to this light still exist, so we'll check to see // if we need to update the values of linked node transforms. - if let Some(weak_node_transform) = node_transform_guard.take() { - if let Some(node_transform) = weak_node_transform.upgrade() { - // If we can upgrade the node transform, something is holding onto - // it and may updated it in the future, so put it back. - *node_transform_guard = Some(weak_node_transform); - // Get on with checking the update. - let node_global_transform_value = node_transform.get_global_transform(); - // UNWRAP: Safe because we checked that the light has external references - let light_global_transform = light_bundle.transform.upgrade().unwrap(); - let global_transform_value = light_global_transform.get(); - if global_transform_value != node_global_transform_value { - // TODO: write a test that animates a light using GLTF to ensure - // that this is working correctly - light_global_transform.set(node_global_transform_value); - } + if let Some(node_transform) = + light_bundle.node_transform.read().unwrap().as_ref() + { + let node_global_transform = node_transform.global_descriptor(); + // UNWRAP: Safe because we checked that the light has external references + let light_global_transform = light_bundle.transform.descriptor(); + if light_global_transform != node_global_transform { + // TODO: write a test that animates a light using GLTF to ensure + // that this is working correctly + light_bundle.transform.set_descriptor(node_global_transform); } } } diff --git a/crates/renderling/src/light/cpu/test.rs b/crates/renderling/src/light/cpu/test.rs index c6ac01c6..d5ed48ce 100644 --- a/crates/renderling/src/light/cpu/test.rs +++ b/crates/renderling/src/light/cpu/test.rs @@ -6,15 +6,7 @@ use glam::{Vec3, Vec4, Vec4Swizzles}; use spirv_std::num_traits::Zero; use crate::{ - bvol::BoundingBox, - camera::Camera, - color::linear_xfer_vec4, - light::{LightTiling, LightTilingConfig, SpotLightCalculation}, - math::GpuRng, - material::MaterialDescriptor, - prelude::TransformDescriptor, - geometry::Vertex, - stage::{RenderletDescriptor, RenderletPbrVertexInfo, Stage}, test::BlockOnFuture, + bvol::BoundingBox, camera::{Camera}, color::linear_xfer_vec4, geometry::Vertex, light::{LightTiling, LightTilingConfig, SpotLightCalculation}, math::GpuRng, prelude::TransformDescriptor, stage::{Renderlet, RenderletPbrVertexInfo, Stage}, test::BlockOnFuture }; use super::*; @@ -97,7 +89,7 @@ fn spot_one_frame() { let camera = doc.cameras.first().unwrap(); camera .as_ref() - .modify(|cam| cam.set_projection(crate::camera::perspective(w, h))); + .set_projection(crate::camera::perspective(w, h)); stage.use_camera(camera); let frame = ctx.get_next_frame().unwrap(); @@ -131,7 +123,7 @@ fn spot_lights() { let camera = doc.cameras.first().unwrap(); camera .as_ref() - .modify(|cam| cam.set_projection(crate::camera::perspective(w, h))); + .set_projection(crate::camera::perspective(w, h)); stage.use_camera(camera); let down_light = doc.lights.first().unwrap(); @@ -169,28 +161,23 @@ fn light_tiling_light_bounds() { // Here we only want to render the bounding boxes of the renderlets, // so mark the renderlets themeselves invisible - doc.renderlets_iter().for_each(|hy_rend| { - hy_rend.modify(|r| { - r.visible = false; - }); + doc.renderlets_iter().for_each(|r| { + r.set_visible(false); }); let colors = [0x6DE1D2FF, 0xFFD63AFF, 0x6DE1D2FF, 0xF75A5AFF].map(|albedo_factor| { - stage.new_material(MaterialDescriptor { - albedo_factor: { + stage.new_material().with_albedo_factor ({ let mut color = crate::math::hex_to_vec4(albedo_factor); linear_xfer_vec4(&mut color); color - }, - ..Default::default() - }) + }) }); let mut resources = vec![]; for (i, node) in doc.nodes.iter().enumerate() { if node.mesh.is_none() { continue; } - let transform = Mat4::from(node.transform.get_global_transform()); + let transform = Mat4::from(node.transform.global_descriptor()); if let Some(mesh_index) = node.mesh { log::info!("mesh: {}", node.name.as_deref().unwrap_or("unknown")); let mesh = &doc.meshes[mesh_index]; @@ -206,13 +193,12 @@ fn light_tiling_light_bounds() { log::info!("min: {min}, max: {max}"); resources.push( stage - .builder() - .with_vertices({ + .new_renderlet() + .with_vertices(stage.new_vertices( bb.get_mesh() .map(|(p, n)| Vertex::default().with_position(p).with_normal(n)) - }) - .with_material_id(colors[i % colors.len()].id()) - .build(), + )) + .with_material(&colors[i % colors.len()]) ); } } @@ -233,11 +219,9 @@ fn gen_vec3(prng: &mut GpuRng) -> Vec3 { } struct GeneratedLight { - _unused_transform: Hybrid, - _mesh_geometry: HybridArray, - _mesh_material: Hybrid, + _unused_transform: Transform, _light: AnalyticalLight, - mesh_renderlet: Hybrid, + mesh_renderlet: Renderlet, } fn gen_light(stage: &Stage, prng: &mut GpuRng, bounding_boxes: &[BoundingBox]) -> GeneratedLight { @@ -263,33 +247,19 @@ fn gen_light(stage: &Stage, prng: &mut GpuRng, bounding_boxes: &[BoundingBox]) - half_extent: Vec3::new(scale, scale, scale) * 0.5, }; - // Also make a renderlet for the light, so we can see where it is. - // let transform = stage.new_nested_transform(); - // transform.modify(|t| { - // if transform.global_transform_id().inner() == 5676 { - // println!("generated position: {position}"); - // } - // t.translation = position; - // }); - let (a, b, c, d, e) = stage - .builder() - .with_transform(TransformDescriptor { - translation: position, - ..Default::default() - }) - .with_vertices( + let _unused_transform = stage.new_transform().with_translation(position); + let vertices = stage.new_vertices( light_bb .get_mesh() .map(|(p, n)| Vertex::default().with_position(p).with_normal(n)), - ) - .with_material(MaterialDescriptor { - albedo_factor: color, - has_lighting: false, - emissive_factor: color.xyz(), - emissive_strength_multiplier: 100.0, - ..Default::default() - }) - .suffix({ + ); + let material = stage.new_material() + .with_albedo_factor(color) + .with_has_lighting(false) + .with_emissive_factor(color.xyz()) + .with_emissive_strength_multiplier(100.0); + let mesh_renderlet = stage.new_renderlet().with_vertices(vertices).with_material(material); + let _light = { // suffix the actual analytical light let intensity = scale * 100.0; @@ -300,14 +270,12 @@ fn gen_light(stage: &Stage, prng: &mut GpuRng, bounding_boxes: &[BoundingBox]) - }; stage.new_analytical_light(light_descriptor) - }) - .build(); + }; + GeneratedLight { - _unused_transform: a, - _mesh_geometry: b, - _mesh_material: c, - _light: d, - mesh_renderlet: e, + _unused_transform, + _light, + mesh_renderlet, } } @@ -318,12 +286,12 @@ fn size() -> UVec2 { ) } -fn make_camera() -> Camera { +fn make_camera(stage: &Stage) -> Camera { let size = size(); let eye = Vec3::new(250.0, 200.0, 250.0); let target = Vec3::ZERO; log::info!("make_camera: forward {}", (target - eye).normalize()); - Camera::new( + stage.new_camera().with_projection_and_view( Mat4::perspective_rh( std::f32::consts::FRAC_PI_4, size.x as f32 / size.y as f32, @@ -420,7 +388,7 @@ fn min_max_depth_sanity() { .join("light_tiling_test.glb"), ) .unwrap(); - let camera = stage.new_camera(make_camera()); + let camera = make_camera(&stage); stage.use_camera(camera); snapshot( &ctx, @@ -472,7 +440,7 @@ fn light_bins_sanity() { .join("light_tiling_test.glb"), ) .unwrap(); - let camera = stage.new_camera(make_camera()); + let camera = make_camera(&stage); stage.use_camera(camera); snapshot(&ctx, &stage, "light/tiling/bins/1-scene.png", false); @@ -538,30 +506,21 @@ fn light_bins_point() { .new_stage() .with_msaa_sample_count(1) .with_bloom_mix_strength(0.08); - let doc = stage + let mut doc = stage .load_gltf_document_from_path( crate::test::workspace_dir() .join("gltf") .join("pedestal.glb"), ) .unwrap(); - let materials = doc.materials.get_vec(); - log::info!("materials: {materials:#?}"); - doc.materials.set_item( - 0, - MaterialDescriptor { - albedo_factor: Vec4::ONE, - roughness_factor: 1.0, - metallic_factor: 0.0, - ..Default::default() - }, - ); + + doc.materials.get_mut(0).unwrap() + .set_albedo_factor(Vec4::ONE).set_roughness_factor(1.0).set_metallic_factor(0.0); + let camera = doc.cameras.first().unwrap(); - camera.camera.modify(|cam| { let view = Mat4::look_at_rh(Vec3::new(-7.0, 5.0, 7.0), Vec3::ZERO, Vec3::Y); let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_6, 1.0, 0.1, 15.0); - cam.set_projection_and_view(proj, view); - }); + camera.camera.set_projection_and_view(proj, view); let _point_light = stage.new_analytical_light(PointLightDescriptor { position: Vec3::new(1.1, 1.0, 1.1), @@ -621,7 +580,7 @@ fn tiling_e2e_sanity_with( ) .unwrap(); - let camera = stage.new_camera(make_camera()); + let camera = make_camera(&stage); stage.use_camera(camera); let _ = stage.lighting.commit(); @@ -645,7 +604,7 @@ fn tiling_e2e_sanity_with( if node.mesh.is_none() { continue; } - let transform = Mat4::from(node.transform.get_global_transform()); + let transform = Mat4::from(node.transform.global_descriptor()); if let Some(mesh_index) = node.mesh { let mesh = &doc.meshes[mesh_index]; for prim in mesh.primitives.iter() { @@ -950,30 +909,27 @@ fn pedestal() { .with_lighting(false) .with_msaa_sample_count(4) .with_bloom_mix_strength(0.08); - let doc = stage + let mut doc = stage .load_gltf_document_from_path( crate::test::workspace_dir() .join("gltf") .join("pedestal.glb"), ) .unwrap(); - let materials = doc.materials.get_vec(); - log::info!("materials: {materials:#?}"); - doc.materials.set_item( - 0, - MaterialDescriptor { - albedo_factor: Vec4::ONE, - roughness_factor: 1.0, - metallic_factor: 0.0, - ..Default::default() - }, - ); + + doc + .materials + .get_mut(0) + .unwrap() + .set_albedo_factor(Vec4::ONE) + .set_roughness_factor(1.0) + .set_metallic_factor(0.0); + let camera = doc.cameras.first().unwrap(); - camera.camera.modify(|cam| { - let view = Mat4::look_at_rh(Vec3::new(-7.0, 5.0, 7.0), Vec3::ZERO, Vec3::Y); - let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_6, 1.0, 0.1, 15.0); - cam.set_projection_and_view(proj, view); - }); + camera.camera.set_projection_and_view( + Mat4::perspective_rh(std::f32::consts::FRAC_PI_6, 1.0, 0.1, 15.0), + Mat4::look_at_rh(Vec3::new(-7.0, 5.0, 7.0), Vec3::ZERO, Vec3::Y) + ); let color = { // let mut c = hex_to_vec4(0xEEDF7AFF); @@ -982,9 +938,6 @@ fn pedestal() { Vec4::ONE }; let position = Vec3::new(1.1, 1.0, 1.1); - let transform = stage.new_nested_transform(); - transform.modify(|t| t.translation = position); - stage.set_has_lighting(true); let mut dir_infos = vec![]; @@ -1001,9 +954,9 @@ fn pedestal() { futures_lite::future::block_on(stage.geometry.slab_allocator().read(..)).unwrap(); let renderlet = doc.renderlets_iter().next().unwrap(); - log::info!("renderlet: {renderlet:#?}"); + log::info!("renderlet: {:#?}", renderlet.descriptor()); - for vertex_index in 0..renderlet.get().vertices_array.len() { + for vertex_index in 0..renderlet.descriptor().vertices_array.len() { let mut info = RenderletPbrVertexInfo::default(); crate::stage::renderlet_vertex( renderlet.id(), @@ -1042,7 +995,7 @@ fn pedestal() { { log::info!("adding point light with nested transform"); let transform = stage.new_nested_transform(); - transform.modify(|t| t.translation = position); + transform.set_translation(position); let point_light = stage.new_analytical_light(PointLightDescriptor { position: Vec3::ZERO, @@ -1073,10 +1026,10 @@ fn pedestal() { futures_lite::future::block_on(stage.geometry.slab_allocator().read(..)).unwrap(); let renderlet = doc.renderlets_iter().next().unwrap(); - log::info!("renderlet: {renderlet:#?}"); + log::info!("renderlet: {:#?}", renderlet.descriptor()); let mut spot_infos = vec![]; - for vertex_index in 0..renderlet.get().vertices_array.len() { + for vertex_index in 0..renderlet.descriptor().vertices_array.len() { let mut info = RenderletPbrVertexInfo::default(); crate::stage::renderlet_vertex( renderlet.id(), @@ -1105,7 +1058,7 @@ fn pedestal() { log::info!("adding spot light with node position"); let node_transform = stage.new_nested_transform(); - node_transform.modify(|t| t.translation = position); + node_transform.set_translation(position); let spot_desc = SpotLightDescriptor { position: Vec3::ZERO, diff --git a/crates/renderling/src/light/shadow_map.rs b/crates/renderling/src/light/shadow_map.rs index 6b65d6c5..d22b461f 100644 --- a/crates/renderling/src/light/shadow_map.rs +++ b/crates/renderling/src/light/shadow_map.rs @@ -12,9 +12,9 @@ use glam::{Mat4, UVec2}; use snafu::{OptionExt, ResultExt}; use crate::{ - atlas::{AtlasBlittingOperation, AtlasImage, AtlasTexture}, + atlas::{AtlasBlittingOperation, AtlasImage, AtlasTexture, AtlasTextureDescriptor}, bindgroup::ManagedBindGroup, - stage::RenderletDescriptor, + stage::Renderlet, }; use super::{ @@ -40,8 +40,8 @@ pub struct ShadowMap { pub(crate) light_space_transforms: HybridArray, /// Bindgroup for the shadow map update shader pub(crate) update_bindgroup: ManagedBindGroup, - pub(crate) atlas_textures: Vec>, - pub(crate) _atlas_textures_array: HybridArray>, + pub(crate) atlas_textures: Vec, + pub(crate) _atlas_textures_array: HybridArray>, pub(crate) update_texture: crate::texture::Texture, pub(crate) blitting_op: AtlasBlittingOperation, pub(crate) light_bundle: AnalyticalLight, @@ -248,7 +248,7 @@ impl ShadowMap { pub fn update<'a>( &self, lighting: impl AsRef, - renderlets: impl IntoIterator>, + renderlets: impl IntoIterator, ) -> Result<(), LightingError> { let lighting = lighting.as_ref(); let light_bundle = self @@ -339,7 +339,7 @@ impl ShadowMap { let mut count = 0; for rlet in renderlets.iter() { let id = rlet.id(); - let rlet = rlet.get(); + let rlet = rlet.descriptor(); let vertex_range = 0..rlet.get_vertex_count(); let instance_range = id.inner()..id.inner() + 1; render_pass.draw(vertex_range, instance_range); @@ -368,7 +368,7 @@ impl ShadowMap { #[cfg(test)] #[allow(clippy::unused_enumerate_index)] mod test { - use crate::{camera::Camera, test::BlockOnFuture}; + use crate::test::BlockOnFuture; use super::super::*; @@ -398,7 +398,7 @@ mod test { let camera = doc.cameras.first().unwrap(); camera .as_ref() - .modify(|cam| cam.set_projection(crate::camera::perspective(w, h))); + .set_projection(crate::camera::perspective(w, h)); stage.use_camera(camera); let frame = ctx.get_next_frame().unwrap(); @@ -446,7 +446,7 @@ mod test { let camera = doc.cameras.first().unwrap(); camera .as_ref() - .modify(|cam| cam.set_projection(crate::camera::perspective(w, h))); + .set_projection(crate::camera::perspective(w, h)); stage.use_camera(camera); let gltf_light_a = doc.lights.first().unwrap(); @@ -498,7 +498,7 @@ mod test { let camera = doc.cameras.first().unwrap(); camera .as_ref() - .modify(|cam| cam.set_projection(crate::camera::perspective(w, h))); + .set_projection(crate::camera::perspective(w, h)); stage.use_camera(camera); let frame = ctx.get_next_frame().unwrap(); @@ -584,10 +584,9 @@ mod test { ) .unwrap(); let camera = doc.cameras.first().unwrap(); - let original_camera = camera.as_ref().modify(|cam| { - cam.set_projection(crate::camera::perspective(w, h)); - *cam - }); + camera + .as_ref() + .set_projection(crate::camera::perspective(w, h)); stage.use_camera(camera); let mut shadow_maps = vec![]; @@ -597,11 +596,12 @@ mod test { { let desc = light_bundle.light_details().as_spot().unwrap().get(); let (p, v) = desc.shadow_mapping_projection_and_view( - &light_bundle.transform().get().into(), + &light_bundle.transform().as_mat4(), z_near, z_far, ); - camera.as_ref().set(Camera::new(p, v)); + let temp_camera = stage.new_camera().with_projection_and_view(p, v); + stage.use_camera(temp_camera); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); let _img = frame.read_image().block().unwrap(); @@ -622,7 +622,8 @@ mod test { shadow.update(&stage, doc.renderlets_iter()).unwrap(); shadow_maps.push(shadow); } - camera.as_ref().set(original_camera); + + stage.use_camera(camera); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -649,10 +650,9 @@ mod test { ) .unwrap(); let camera = doc.cameras.first().unwrap(); - let c = camera.as_ref().modify(|cam| { - cam.set_projection(crate::camera::perspective(w, h)); - *cam - }); + camera + .as_ref() + .set_projection(crate::camera::perspective(w, h)); stage.use_camera(camera); let mut shadows = vec![]; @@ -663,12 +663,12 @@ mod test { let desc = light_bundle.light_details().as_point().unwrap().get(); println!("point light {i}: {desc:?}"); let (p, vs) = desc.shadow_mapping_projection_and_view_matrices( - &light_bundle.transform().get().into(), + &light_bundle.transform().as_mat4(), z_near, z_far, ); for (_j, v) in vs.into_iter().enumerate() { - camera.as_ref().set(Camera::new(p, v)); + stage.use_camera(stage.new_camera().with_projection_and_view(p, v)); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); let _img = frame.read_image().block().unwrap(); @@ -690,7 +690,8 @@ mod test { shadow.update(&stage, doc.renderlets_iter()).unwrap(); shadows.push(shadow); } - camera.as_ref().set(c); + + stage.use_camera(&camera); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); diff --git a/crates/renderling/src/material.rs b/crates/renderling/src/material.rs index 7c803e13..ba5c9643 100644 --- a/crates/renderling/src/material.rs +++ b/crates/renderling/src/material.rs @@ -1,13 +1,13 @@ //! Atlas images, used for materials. CPU and GPU. +use crabslab::{Id, SlabItem}; +use glam::{Vec3, Vec4}; + +use crate::atlas::AtlasTextureDescriptor; #[cfg(cpu)] mod cpu; #[cfg(cpu)] pub use cpu::*; -use crabslab::{Id, SlabItem}; -use glam::{Vec3, Vec4}; - -use crate::atlas::AtlasTexture; /// Represents a material on the GPU. #[repr(C)] @@ -19,11 +19,11 @@ pub struct MaterialDescriptor { pub metallic_factor: f32, pub roughness_factor: f32, - pub albedo_texture_id: Id, - pub metallic_roughness_texture_id: Id, - pub normal_texture_id: Id, - pub ao_texture_id: Id, - pub emissive_texture_id: Id, + pub albedo_texture_id: Id, + pub metallic_roughness_texture_id: Id, + pub normal_texture_id: Id, + pub ao_texture_id: Id, + pub emissive_texture_id: Id, pub albedo_tex_coord: u32, pub metallic_roughness_tex_coord: u32, diff --git a/crates/renderling/src/material/cpu.rs b/crates/renderling/src/material/cpu.rs index 3a7c5f71..280fe2ba 100644 --- a/crates/renderling/src/material/cpu.rs +++ b/crates/renderling/src/material/cpu.rs @@ -1,18 +1,27 @@ //! CPU side of materials. +use std::sync::{Arc, Mutex}; + use craballoc::{ + // Craballoc is used for memory allocation and management. runtime::WgpuRuntime, slab::{SlabAllocator, SlabBuffer}, - value::{Hybrid, HybridArray}, + value::Hybrid, }; +use crabslab::Id; +use glam::{Vec3, Vec4}; -use crate::{atlas::Atlas, material::MaterialDescriptor}; +use crate::{ + atlas::{Atlas, AtlasTexture}, + material::MaterialDescriptor, +}; /// Wrapper around the materials slab, which holds material textures in an atlas. #[derive(Clone)] pub struct Materials { slab: SlabAllocator, atlas: Atlas, + default_material: Material, } impl AsRef for Materials { @@ -22,24 +31,50 @@ impl AsRef for Materials { } impl Materials { + /// Creates a new `Materials` instance with the specified runtime and atlas size. + /// + /// # Arguments + /// + /// * `runtime` - A reference to the WgpuRuntime. + /// * `atlas_size` - The size of the atlas texture. pub fn new(runtime: impl AsRef, atlas_size: wgpu::Extent3d) -> Self { let slab = SlabAllocator::new(runtime, "materials", wgpu::BufferUsages::empty()); let atlas = Atlas::new(&slab, atlas_size, None, Some("materials-atlas"), None); - Self { slab, atlas } + let default_material = Material { + descriptor: slab.new_value(Default::default()), + albedo_texture: Default::default(), + metallic_roughness_texture: Default::default(), + normal_mapping_texture: Default::default(), + ao_texture: Default::default(), + emissive_texture: Default::default(), + }; + Self { + slab, + atlas, + default_material, + } } + /// Returns a reference to the WgpuRuntime. pub fn runtime(&self) -> &WgpuRuntime { self.as_ref() } + /// Returns a reference to the slab allocator. pub fn slab_allocator(&self) -> &SlabAllocator { &self.slab } + /// Returns a reference to the atlas. pub fn atlas(&self) -> &Atlas { &self.atlas } + /// Returns the default material. + pub fn default_material(&self) -> &Material { + &self.default_material + } + /// Runs atlas upkeep and commits all changes to the GPU. /// /// Returns `true` if the atlas texture was recreated. @@ -49,14 +84,428 @@ impl Materials { (self.atlas.upkeep(self.runtime()), self.slab.commit()) } - /// Create a new material. - // TODO: move `Material` to material - pub fn new_material(&self, material: MaterialDescriptor) -> Hybrid { - self.slab.new_value(material) + /// Returns a [`MaterialBuilder`] for building a new [`Material`]. + pub fn new_material(&self) -> Material { + let descriptor = self.slab.new_value(MaterialDescriptor::default()); + Material { + descriptor, + albedo_texture: Default::default(), + metallic_roughness_texture: Default::default(), + normal_mapping_texture: Default::default(), + ao_texture: Default::default(), + emissive_texture: Default::default(), + } + } +} + +/// A material staged on the GPU. +/// +/// Internally a `Material` holds references to: +/// * its descriptor, [`MaterialDescriptor`], which lives on the GPU +/// * [`AtlasTexture`]s that determine how the material presents: +/// * albedo color +/// * metallic roughness +/// * normal mapping +/// * ambient occlusion +/// * emissive +/// +/// ## Note +/// +/// Clones of `Material` all point to the same underlying data. +/// Changing a value on one `Material` will change that value for all clones as well. +#[derive(Clone)] +pub struct Material { + descriptor: Hybrid, + + albedo_texture: Arc>>, + metallic_roughness_texture: Arc>>, + normal_mapping_texture: Arc>>, + ao_texture: Arc>>, + emissive_texture: Arc>>, +} + +impl From<&Material> for Material { + fn from(value: &Material) -> Self { + value.clone() + } +} + +impl Material { + /// Returns the unique identifier of the material descriptor. + pub fn id(&self) -> Id { + self.descriptor.id() + } + + /// Returns a copy of the underlying descriptor. + pub fn descriptor(&self) -> MaterialDescriptor { + self.descriptor.get() + } + + /// Sets the emissive factor of the material. + /// + /// # Arguments + /// + /// * `param` - The emissive factor as a `Vec3`. + pub fn set_emissive_factor(&self, param: Vec3) -> &Self { + self.descriptor.modify(|d| d.emissive_factor = param); + self + } + /// Sets the emissive factor. + /// + /// # Arguments + /// + /// * `param` - The emissive factor as a `Vec3`. + pub fn with_emissive_factor(self, param: Vec3) -> Self { + self.set_emissive_factor(param); + self + } + /// Sets the emissive strength multiplier of the material. + /// + /// # Arguments + /// + /// * `param` - The emissive strength multiplier as a `f32`. + pub fn set_emissive_strength_multiplier(&self, param: f32) -> &Self { + self.descriptor + .modify(|d| d.emissive_strength_multiplier = param); + self + } + /// Sets the emissive strength multiplier. + /// + /// # Arguments + /// + /// * `param` - The emissive strength multiplier as a `f32`. + pub fn with_emissive_strength_multiplier(self, param: f32) -> Self { + self.set_emissive_strength_multiplier(param); + self + } + /// Sets the albedo factor of the material. + /// + /// # Arguments + /// + /// * `param` - The albedo factor as a `Vec4`. + pub fn set_albedo_factor(&self, param: Vec4) -> &Self { + self.descriptor.modify(|d| d.albedo_factor = param); + self + } + /// Sets the albedo factor. + /// + /// # Arguments + /// + /// * `param` - The albedo factor as a `Vec4`. + pub fn with_albedo_factor(self, param: Vec4) -> Self { + self.set_albedo_factor(param); + self + } + /// Sets the metallic factor of the material. + /// + /// # Arguments + /// + /// * `param` - The metallic factor as a `f32`. + pub fn set_metallic_factor(&self, param: f32) -> &Self { + self.descriptor.modify(|d| d.metallic_factor = param); + self + } + /// Sets the metallic factor. + /// + /// # Arguments + /// + /// * `param` - The metallic factor as a `f32`. + pub fn with_metallic_factor(self, param: f32) -> Self { + self.set_metallic_factor(param); + self + } + /// Sets the roughness factor of the material. + /// + /// # Arguments + /// + /// * `param` - The roughness factor as a `f32`. + pub fn set_roughness_factor(&self, param: f32) -> &Self { + self.descriptor.modify(|d| d.roughness_factor = param); + self + } + /// Sets the roughness factor. + /// + /// # Arguments + /// + /// * `param` - The roughness factor as a `f32`. + pub fn with_roughness_factor(self, param: f32) -> Self { + self.set_roughness_factor(param); + self + } + /// Sets the albedo texture coordinate of the material. + /// + /// # Arguments + /// + /// * `param` - The texture coordinate as a `u32`. + pub fn set_albedo_tex_coord(&self, param: u32) -> &Self { + self.descriptor.modify(|d| d.albedo_tex_coord = param); + self + } + /// Sets the albedo texture coordinate. + /// + /// # Arguments + /// + /// * `param` - The texture coordinate as a `u32`. + pub fn with_albedo_tex_coord(self, param: u32) -> Self { + self.set_albedo_tex_coord(param); + self + } + /// Sets the metallic roughness texture coordinate of the material. + /// + /// # Arguments + /// + /// * `param` - The texture coordinate as a `u32`. + pub fn set_metallic_roughness_tex_coord(&self, param: u32) -> &Self { + self.descriptor + .modify(|d| d.metallic_roughness_tex_coord = param); + self + } + /// Sets the metallic roughness texture coordinate. + /// + /// # Arguments + /// + /// * `param` - The texture coordinate as a `u32`. + pub fn with_metallic_roughness_tex_coord(self, param: u32) -> Self { + self.set_metallic_roughness_tex_coord(param); + self + } + /// Sets the normal texture coordinate of the material. + /// + /// # Arguments + /// + /// * `param` - The texture coordinate as a `u32`. + pub fn set_normal_tex_coord(&self, param: u32) -> &Self { + self.descriptor.modify(|d| d.normal_tex_coord = param); + self + } + /// Sets the normal texture coordinate. + /// + /// # Arguments + /// + /// * `param` - The texture coordinate as a `u32`. + pub fn with_normal_tex_coord(self, param: u32) -> Self { + self.set_normal_tex_coord(param); + self + } + /// Sets the ambient occlusion texture coordinate of the material. + /// + /// # Arguments + /// + /// * `param` - The texture coordinate as a `u32`. + pub fn set_ambient_occlusion_tex_coord(&self, param: u32) -> &Self { + self.descriptor.modify(|d| d.ao_tex_coord = param); + self + } + /// Sets the ambient occlusion texture coordinate. + /// + /// # Arguments + /// + /// * `param` - The texture coordinate as a `u32`. + pub fn with_ambient_occlusion_tex_coord(self, param: u32) -> Self { + self.set_ambient_occlusion_tex_coord(param); + self + } + /// Sets the emissive texture coordinate of the material. + /// + /// # Arguments + /// + /// * `param` - The texture coordinate as a `u32`. + pub fn set_emissive_tex_coord(&self, param: u32) -> &Self { + self.descriptor.modify(|d| d.emissive_tex_coord = param); + self + } + /// Sets the emissive texture coordinate. + /// + /// # Arguments + /// + /// * `param` - The texture coordinate as a `u32`. + pub fn with_emissive_tex_coord(self, param: u32) -> Self { + self.set_emissive_tex_coord(param); + self + } + /// Sets whether the material has lighting. + /// + /// # Arguments + /// + /// * `param` - A boolean indicating if the material has lighting. + pub fn set_has_lighting(&self, param: bool) -> &Self { + self.descriptor.modify(|d| d.has_lighting = param); + self + } + /// Sets whether the material has lighting. + /// + /// # Arguments + /// + /// * `param` - A boolean indicating if the material has lighting. + pub fn with_has_lighting(self, param: bool) -> Self { + self.set_has_lighting(param); + self + } + /// Sets the ambient occlusion strength of the material. + /// + /// # Arguments + /// + /// * `param` - The ambient occlusion strength as a `f32`. + pub fn set_ambient_occlusion_strength(&self, param: f32) -> &Self { + self.descriptor.modify(|d| d.ao_strength = param); + self + } + /// Sets the ambient occlusion strength. + /// + /// # Arguments + /// + /// * `param` - The ambient occlusion strength as a `f32`. + pub fn with_ambient_occlusion_strength(self, param: f32) -> Self { + self.set_ambient_occlusion_strength(param); + self + } + + /// Remove the albedo texture. + /// + /// This causes any `[Renderlet]` that references this material to fall back to + /// using the albedo factor for color. + pub fn remove_albedo_texture(&self) { + self.descriptor.modify(|d| d.albedo_texture_id = Id::NONE); + self.albedo_texture.lock().unwrap().take(); + } + + /// Sets the albedo color texture. + pub fn set_albedo_texture(&self, texture: &AtlasTexture) -> &Self { + self.descriptor + .modify(|d| d.albedo_texture_id = texture.id()); + *self.albedo_texture.lock().unwrap() = Some(texture.clone()); + self + } + + /// Replace the albedo texture. + pub fn with_albedo_texture(self, texture: &AtlasTexture) -> Self { + self.descriptor + .modify(|d| d.albedo_texture_id = texture.id()); + *self.albedo_texture.lock().unwrap() = Some(texture.clone()); + self + } + + /// Remove the metallic roughness texture. + /// + /// This causes any `[Renderlet]` that references this material to fall back to + /// using the metallic and roughness factors for appearance. + pub fn remove_metallic_roughness_texture(&self) { + self.descriptor + .modify(|d| d.metallic_roughness_texture_id = Id::NONE); + self.metallic_roughness_texture.lock().unwrap().take(); + } + + /// Sets the metallic roughness texture of the material. + /// + /// # Arguments + /// + /// * `texture` - A reference to the metallic roughness `AtlasTexture`. + pub fn set_metallic_roughness_texture(&self, texture: &AtlasTexture) -> &Self { + self.descriptor + .modify(|d| d.metallic_roughness_texture_id = texture.id()); + *self.metallic_roughness_texture.lock().unwrap() = Some(texture.clone()); + self + } + + /// Sets the metallic roughness texture and returns the material. + /// + /// # Arguments + /// + /// * `texture` - A reference to the metallic roughness `AtlasTexture`. + pub fn with_metallic_roughness_texture(self, texture: &AtlasTexture) -> Self { + self.set_metallic_roughness_texture(texture); + self + } + + /// Remove the normal texture. + /// + /// This causes any `[Renderlet]` that references this material to fall back to + /// using the default normal mapping. + pub fn remove_normal_texture(&self) { + self.descriptor.modify(|d| d.normal_texture_id = Id::NONE); + self.normal_mapping_texture.lock().unwrap().take(); + } + + /// Sets the normal texture of the material. + /// + /// # Arguments + /// + /// * `texture` - A reference to the normal `AtlasTexture`. + pub fn set_normal_texture(&self, texture: &AtlasTexture) -> &Self { + self.descriptor + .modify(|d| d.normal_texture_id = texture.id()); + *self.normal_mapping_texture.lock().unwrap() = Some(texture.clone()); + self + } + + /// Sets the normal texture and returns the material. + /// + /// # Arguments + /// + /// * `texture` - A reference to the normal `AtlasTexture`. + pub fn with_normal_texture(self, texture: &AtlasTexture) -> Self { + self.set_normal_texture(texture); + self + } + + /// Remove the ambient occlusion texture. + /// + /// This causes any `[Renderlet]` that references this material to fall back to + /// using the default ambient occlusion. + pub fn remove_ambient_occlusion_texture(&self) { + self.descriptor.modify(|d| d.ao_texture_id = Id::NONE); + self.ao_texture.lock().unwrap().take(); } - /// Create an array of materials, stored contiguously. - pub fn new_materials(&self, data: impl IntoIterator) -> HybridArray { - self.slab.new_array(data) + /// Sets the ambient occlusion texture of the material. + /// + /// # Arguments + /// + /// * `texture` - A reference to the ambient occlusion `AtlasTexture`. + pub fn set_ambient_occlusion_texture(&self, texture: &AtlasTexture) -> &Self { + self.descriptor.modify(|d| d.ao_texture_id = texture.id()); + *self.ao_texture.lock().unwrap() = Some(texture.clone()); + self + } + + /// Sets the ambient occlusion texture and returns the material. + /// + /// # Arguments + /// + /// * `texture` - A reference to the ambient occlusion `AtlasTexture`. + pub fn with_ambient_occlusion_texture(self, texture: &AtlasTexture) -> Self { + self.set_ambient_occlusion_texture(texture); + self + } + + /// Remove the emissive texture. + /// + /// This causes any `[Renderlet]` that references this material to fall back to + /// using the emissive factor for appearance. + pub fn remove_emissive_texture(&self) { + self.descriptor.modify(|d| d.emissive_texture_id = Id::NONE); + self.emissive_texture.lock().unwrap().take(); + } + + /// Sets the emissive texture of the material. + /// + /// # Arguments + /// + /// * `texture` - A reference to the emissive `AtlasTexture`. + pub fn set_emissive_texture(&self, texture: &AtlasTexture) -> &Self { + self.descriptor + .modify(|d| d.emissive_texture_id = texture.id()); + *self.emissive_texture.lock().unwrap() = Some(texture.clone()); + self + } + + /// Sets the emissive texture and returns the material. + /// + /// # Arguments + /// + /// * `texture` - A reference to the emissive `AtlasTexture`. + pub fn with_emissive_texture(self, texture: &AtlasTexture) -> Self { + self.set_emissive_texture(texture); + self } } diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index 0599d47d..019727cf 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -11,7 +11,7 @@ use glam::{Mat4, Vec2, Vec3, Vec4, Vec4Swizzles}; use spirv_std::num_traits::{Float, Zero}; use crate::{ - atlas::AtlasTexture, + atlas::AtlasTextureDescriptor, geometry::GeometryDescriptor, light::{ DirectionalLightDescriptor, LightStyle, LightingDescriptor, PointLightDescriptor, @@ -200,7 +200,7 @@ pub fn get_material( } pub fn texture_color, S: IsSampler>( - texture_id: Id, + texture_id: Id, uv: Vec2, atlas: &A, sampler: &S, @@ -666,12 +666,9 @@ where mod test { use crate::{ atlas::AtlasImage, - camera::Camera, geometry::Vertex, - pbr::MaterialDescriptor, prelude::glam::{Vec3, Vec4}, test::BlockOnFuture, - transform::TransformDescriptor, }; #[test] @@ -697,7 +694,9 @@ mod test { Vec3::new(half, half, 0.0), Vec3::Y, ); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let geometry = stage.new_vertices({ let mut icosphere = icosahedron::Polyhedron::new_isocahedron(radius, 5); @@ -734,20 +733,16 @@ mod test { let y = (diameter + spacing) * j as f32; let rez = stage - .builder() - .with_material(MaterialDescriptor { - albedo_factor: Vec4::new(1.0, 1.0, 1.0, 1.0), - metallic_factor: metallic, - roughness_factor: roughness, - ..Default::default() - }) - .with_transform(TransformDescriptor { - translation: Vec3::new(x, y, 0.0), - ..Default::default() - }) - .with_vertices_array(geometry.array()) - .build(); - + .new_renderlet() + .with_material( + stage + .new_material() + .with_albedo_factor(Vec4::new(1.0, 1.0, 1.0, 1.0)) + .with_metallic_factor(metallic) + .with_roughness_factor(roughness), + ) + .with_transform(stage.new_transform().with_translation(Vec3::new(x, y, 0.0))) + .with_vertices(&geometry); spheres.push(rez); } } diff --git a/crates/renderling/src/skybox.rs b/crates/renderling/src/skybox.rs index d3797f3c..040d4707 100644 --- a/crates/renderling/src/skybox.rs +++ b/crates/renderling/src/skybox.rs @@ -10,7 +10,7 @@ use spirv_std::{ use spirv_std::num_traits::Float; use crate::{ - camera::Camera, + camera::CameraDescriptor, math::{self, IsVector}, }; @@ -39,7 +39,7 @@ pub fn skybox_vertex( local_pos: &mut Vec3, #[spirv(position)] clip_pos: &mut Vec4, ) { - let camera_id = Id::::from(camera_index); + let camera_id = Id::::from(camera_index); let camera = slab.read(camera_id); let point = math::CUBE[vertex_index as usize]; *local_pos = point; @@ -69,7 +69,7 @@ pub fn skybox_cubemap_fragment( /// convolutions. #[spirv(vertex)] pub fn skybox_cubemap_vertex( - #[spirv(instance_index)] camera_id: Id, + #[spirv(instance_index)] camera_id: Id, #[spirv(vertex_index)] vertex_index: u32, #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], local_pos: &mut Vec3, diff --git a/crates/renderling/src/skybox/cpu.rs b/crates/renderling/src/skybox/cpu.rs index f3d929e6..75a73d91 100644 --- a/crates/renderling/src/skybox/cpu.rs +++ b/crates/renderling/src/skybox/cpu.rs @@ -7,7 +7,7 @@ use crabslab::Id; use glam::{Mat4, UVec2, Vec3}; use crate::{ - atlas::AtlasImage, camera::Camera, convolution::VertexPrefilterEnvironmentCubemapIds, + atlas::AtlasImage, camera::CameraDescriptor, convolution::VertexPrefilterEnvironmentCubemapIds, cubemap::EquirectangularImageToCubemapBlitter, texture::Texture, }; @@ -190,7 +190,7 @@ impl Skybox { let slab = SlabAllocator::new(runtime, "skybox-slab", wgpu::BufferUsages::VERTEX); let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1, 10.0); - let camera = slab.new_value(Camera::default().with_projection(proj)); + let camera = slab.new_value(CameraDescriptor::default().with_projection(proj)); let roughness = slab.new_value(0.0f32); let prefilter_ids = slab.new_value(VertexPrefilterEnvironmentCubemapIds { camera: camera.id(), @@ -317,7 +317,7 @@ impl Skybox { buffer: &wgpu::Buffer, buffer_upkeep: impl FnMut(), hdr_texture: &Texture, - camera: &Hybrid, + camera: &Hybrid, views: [Mat4; 6], ) -> Texture { let runtime = runtime.as_ref(); @@ -357,7 +357,7 @@ impl Skybox { runtime: impl AsRef, pipeline: &wgpu::RenderPipeline, mut buffer_upkeep: impl FnMut(), - camera: &Hybrid, + camera: &Hybrid, bindgroup: &wgpu::BindGroup, views: [Mat4; 6], texture_size: u32, @@ -440,7 +440,7 @@ impl Skybox { buffer: &wgpu::Buffer, buffer_upkeep: impl FnMut(), environment_texture: &Texture, - camera: &Hybrid, + camera: &Hybrid, views: [Mat4; 6], ) -> Texture { let runtime = runtime.as_ref(); @@ -475,7 +475,7 @@ impl Skybox { runtime: impl AsRef, buffer: &wgpu::Buffer, mut buffer_upkeep: impl FnMut(), - camera: &Hybrid, + camera: &Hybrid, roughness: &Hybrid, prefilter_id: Id, environment_texture: &Texture, @@ -661,7 +661,7 @@ mod test { let stage = ctx.new_stage(); - let _camera = stage.new_camera(Camera::new(proj, view)); + let _camera = stage.new_camera().with_projection_and_view(proj, view); let skybox = stage .new_skybox_from_path("../../img/hdr/resting_place.hdr") .unwrap(); diff --git a/crates/renderling/src/stage.rs b/crates/renderling/src/stage.rs index b1c19141..6f00fb70 100644 --- a/crates/renderling/src/stage.rs +++ b/crates/renderling/src/stage.rs @@ -13,7 +13,7 @@ use spirv_std::{ use crate::{ bvol::BoundingSphere, - geometry::{GeometryDescriptor, MorphTarget, Skin, Vertex}, + geometry::{GeometryDescriptor, MorphTarget, SkinDescriptor, Vertex}, material::MaterialDescriptor, math::IsVector, transform::TransformDescriptor, @@ -57,7 +57,7 @@ pub struct RenderletDescriptor { pub indices_array: Array, pub transform_id: Id, pub material_id: Id, - pub skin_id: Id, + pub skin_id: Id, pub morph_targets: Array>, pub morph_weights: Array, pub geometry_descriptor_id: Id, @@ -332,7 +332,10 @@ mod test { use craballoc::{prelude::SlabAllocator, runtime::CpuRuntime}; use glam::{Mat4, Quat, Vec3}; - use crate::{math::IsMatrix, stage::NestedTransform, transform::TransformDescriptor}; + use crate::{ + math::IsMatrix, + transform::{NestedTransform, TransformDescriptor}, + }; #[test] fn matrix_hierarchy_sanity() { @@ -357,7 +360,7 @@ mod test { let mut mat = Mat4::IDENTITY; let mut local = Some(tfrm.clone()); while let Some(t) = local.take() { - let transform = t.get(); + let transform = t.local_descriptor(); mat = Mat4::from_scale_rotation_translation( transform.scale, transform.rotation, @@ -369,23 +372,13 @@ mod test { (t, r, s) } - #[expect(clippy::needless_borrows_for_generic_args, reason = "riffraff")] - let slab = SlabAllocator::::new(&CpuRuntime, "transform", ()); + let slab = SlabAllocator::new(CpuRuntime, "transform", ()); let a = NestedTransform::new(&slab); - a.set(TransformDescriptor { - translation: Vec3::splat(100.0), - ..Default::default() - }); + a.set_translation(Vec3::splat(100.0)); let b = NestedTransform::new(&slab); - b.set(TransformDescriptor { - rotation: Quat::from_scaled_axis(Vec3::Z), - ..Default::default() - }); + b.set_rotation(Quat::from_scaled_axis(Vec3::Z)); let c = NestedTransform::new(&slab); - c.set(TransformDescriptor { - scale: Vec3::splat(2.0), - ..Default::default() - }); + c.set_scale(Vec3::splat(2.0)); a.add_child(&b); b.add_child(&c); @@ -394,12 +387,12 @@ mod test { translation, rotation, scale, - } = c.get_global_transform(); + } = c.global_descriptor(); let global_transform = (translation, rotation, scale); let legacy_transform = legacy_get_world_transform(&c); assert_eq!(legacy_transform, global_transform); - c.modify(|t| t.translation = Vec3::ONE); + c.set_translation(Vec3::ONE); let all_updates = slab.get_updated_source_ids(); assert_eq!( @@ -415,7 +408,7 @@ mod test { translation, rotation, scale, - } = c.get_global_transform(); + } = c.global_descriptor(); let global_transform = (translation, rotation, scale); let legacy_transform = legacy_get_world_transform(&c); assert_eq!(legacy_transform, global_transform); diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index 75ac79af..57083d06 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -18,14 +18,17 @@ use crabslab::Id; use snafu::Snafu; use std::sync::{atomic::AtomicBool, Arc, Mutex, RwLock}; +use crate::atlas::AtlasTexture; +use crate::camera::Camera; +use crate::material::Material; use crate::{ - atlas::{AtlasError, AtlasImage, AtlasImageError, AtlasTexture}, + atlas::{AtlasError, AtlasImage, AtlasImageError}, bindgroup::ManagedBindGroup, bloom::Bloom, - camera::Camera, + camera::CameraDescriptor, debug::DebugOverlay, draw::DrawCalls, - geometry::Geometry, + geometry::{Geometry, Indices, MorphTargetWeights, MorphTargets, Skin, SkinJoint, Vertices}, light::{ AnalyticalLight, Light, LightDetails, LightTiling, LightTilingConfig, Lighting, LightingBindGroupLayoutEntries, LightingError, ShadowMap, @@ -33,13 +36,16 @@ use crate::{ material::Materials, pbr::debug::DebugChannel, skybox::{Skybox, SkyboxRenderPipeline}, - stage::RenderletDescriptor, texture::{DepthTexture, Texture}, tonemapping::Tonemapping, - transform::TransformDescriptor, - tuple::Bundle, + transform::{NestedTransform, Transform}, }; +#[cfg(cpu)] +pub mod renderlet; +#[cfg(cpu)] +pub use renderlet::*; + use super::*; #[derive(Debug, Snafu)] @@ -266,198 +272,43 @@ impl StageRendering<'_> { .create() }); - self.stage.draw_calls.write().unwrap().upkeep(); let mut draw_calls = self.stage.draw_calls.write().unwrap(); let depth_texture = self.stage.depth_texture.read().unwrap(); // UNWRAP: safe because we know the depth texture format will always match let maybe_indirect_buffer = draw_calls.pre_draw(&depth_texture).unwrap(); - { - log::trace!("rendering"); - let label = Some("stage render"); - - let mut encoder = self - .stage - .device() - .create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label, - color_attachments: &[Some(self.color_attachment)], - depth_stencil_attachment: Some(self.depth_stencil_attachment), - ..Default::default() - }); - - render_pass.set_pipeline(self.pipeline); - render_pass.set_bind_group(0, Some(renderlet_bind_group.as_ref()), &[]); - draw_calls.draw(&mut render_pass); - - let has_skybox = self.stage.has_skybox.load(Ordering::Relaxed); - if has_skybox { - let (pipeline, bindgroup) = self - .stage - .get_skybox_pipeline_and_bindgroup(&commit_result.geometry_buffer); - render_pass.set_pipeline(&pipeline.pipeline); - render_pass.set_bind_group(0, Some(bindgroup.as_ref()), &[]); - let camera_id = self.stage.geometry.descriptor().get().camera_id.inner(); - render_pass.draw(0..36, camera_id..camera_id + 1); - } - } - let sindex = self.stage.queue().submit(std::iter::once(encoder.finish())); - (sindex, maybe_indirect_buffer) - } - } -} - -pub enum RenderletTransform { - /// A single root transform - Root(crate::transform::Transform), - /// A heirarchy of transforms. - /// - /// Each transform represents the transform of one node in a scene graph. - Hierarchy(NestedTransform), -} - -pub struct Renderlet< - RenderletDescriptorCt: IsContainer = HybridContainer, - TransformCt: IsContainer = HybridContainer, - VerticesCt: IsContainer = GpuArrayContainer, - IndicesCt: IsContainer = GpuArrayContainer, - MaterialCt: IsContainer = GpuArrayContainer, -> { - transform: Option>, - descriptor: RenderletDescriptorCt::Container, - vertices: VerticesCt::Container, - indices: Option>, - material: Option, -} -/// A helper struct to build [`Renderlet`]s. -pub struct RenderletBuilder<'a, T> { - data: RenderletDescriptor, - resources: T, - stage: &'a Stage, -} + log::trace!("rendering"); + let label = Some("stage render"); -impl<'a> RenderletBuilder<'a, ()> { - pub fn new(stage: &'a Stage) -> Self { - RenderletBuilder { - data: RenderletDescriptor::default(), - resources: (), - stage, - } - } -} + let mut encoder = self + .stage + .device() + .create_command_encoder(&wgpu::CommandEncoderDescriptor { label }); + { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label, + color_attachments: &[Some(self.color_attachment)], + depth_stencil_attachment: Some(self.depth_stencil_attachment), + ..Default::default() + }); -impl<'a, T: Bundle> RenderletBuilder<'a, T> { - pub fn suffix(self, element: S) -> RenderletBuilder<'a, T::Suffixed> { - RenderletBuilder { - data: self.data, - resources: self.resources.suffix(element), - stage: self.stage, + render_pass.set_pipeline(self.pipeline); + render_pass.set_bind_group(0, Some(renderlet_bind_group.as_ref()), &[]); + draw_calls.draw(&mut render_pass); + + let has_skybox = self.stage.has_skybox.load(Ordering::Relaxed); + if has_skybox { + let (pipeline, bindgroup) = self + .stage + .get_skybox_pipeline_and_bindgroup(&commit_result.geometry_buffer); + render_pass.set_pipeline(&pipeline.pipeline); + render_pass.set_bind_group(0, Some(bindgroup.as_ref()), &[]); + let camera_id = self.stage.geometry.descriptor().get().camera_id.inner(); + render_pass.draw(0..36, camera_id..camera_id + 1); + } } - } - - pub fn with_vertices_array(mut self, array: Array) -> Self { - self.data.vertices_array = array; - self - } - - pub fn with_vertices( - mut self, - vertices: impl IntoIterator, - ) -> RenderletBuilder<'a, T::Suffixed>> { - let vertices = self.stage.geometry.new_vertices(vertices); - self.data.vertices_array = vertices.array(); - self.suffix(vertices) - } - - pub fn with_indices( - mut self, - indices: impl IntoIterator, - ) -> RenderletBuilder<'a, T::Suffixed>> { - let indices = self.stage.geometry.new_indices(indices); - self.data.indices_array = indices.array(); - self.suffix(indices) - } - - pub fn with_transform_id(mut self, transform_id: Id) -> Self { - self.data.transform_id = transform_id; - self - } - - pub fn with_transform( - mut self, - transform: TransformDescriptor, - ) -> RenderletBuilder<'a, T::Suffixed>> { - let transform = self.stage.geometry.new_transform(transform); - self.data.transform_id = transform.id(); - self.suffix(transform) - } - - pub fn with_nested_transform(mut self, transform: &NestedTransform) -> Self { - self.data.transform_id = transform.global_transform_id(); - self - } - - pub fn with_material_id(mut self, material_id: Id) -> Self { - self.data.material_id = material_id; - self - } - - pub fn with_material( - mut self, - material: MaterialDescriptor, - ) -> RenderletBuilder<'a, T::Suffixed>> { - let material = self.stage.materials.new_material(material); - self.data.material_id = material.id(); - self.suffix(material) - } - - pub fn with_skin_id(mut self, skin_id: Id) -> Self { - self.data.skin_id = skin_id; - self - } - - pub fn with_morph_targets( - mut self, - morph_targets: impl IntoIterator>, - ) -> (Self, HybridArray>) { - let morph_targets = self.stage.geometry.new_morph_targets_array(morph_targets); - self.data.morph_targets = morph_targets.array(); - (self, morph_targets) - } - - pub fn with_morph_weights( - mut self, - morph_weights: impl IntoIterator, - ) -> (Self, HybridArray) { - let morph_weights = self.stage.geometry.new_weights(morph_weights); - self.data.morph_weights = morph_weights.array(); - (self, morph_weights) - } - - pub fn with_geometry_descriptor_id(mut self, pbr_config_id: Id) -> Self { - self.data.geometry_descriptor_id = pbr_config_id; - self - } - - pub fn with_bounds(mut self, bounds: impl Into) -> Self { - self.data.bounds = bounds.into(); - self - } - - /// Build the [`Renderlet`], add it to the [`Stage`] with [`Stage::add_renderlet`] and - /// return the [`Hybrid`] along with any resources that were staged. - /// - /// The returned value will be a tuple with the [`Hybrid`] as the head, and - /// all other resources added as the tail. - pub fn build(self) -> > as Bundle>::Reduced - where - T::Suffixed>: Bundle, - { - let renderlet = self.stage.geometry.new_renderlet(self.data); - self.stage.add_renderlet(&renderlet); - self.resources.suffix(renderlet).reduce() + let sindex = self.stage.queue().submit(std::iter::once(encoder.finish())); + (sindex, maybe_indirect_buffer) } } @@ -532,94 +383,87 @@ impl AsRef for Stage { /// Geometry methods. impl Stage { + /// Returns the vertices of a white unit cube. + /// + /// This is the mesh of every [`Renderlet`] that has not had its vertices set. + pub fn default_vertices(&self) -> &Vertices { + self.geometry.default_vertices() + } /// Stage a [`Camera`] on the GPU. /// /// If the camera has not been set, this camera will be used /// automatically. - pub fn new_camera(&self, camera: Camera) -> Hybrid { - self.geometry.new_camera(camera) + pub fn new_camera(&self) -> Camera { + self.geometry.new_camera() } /// Use the given camera when rendering. - pub fn use_camera(&self, camera: impl AsRef>) { - self.geometry.use_camera(camera); + pub fn use_camera(&self, camera: impl AsRef) { + self.geometry.use_camera(camera.as_ref()); } /// Return the `Id` of the camera currently in use. - pub fn used_camera_id(&self) -> Id { + pub fn used_camera_id(&self) -> Id { self.geometry.descriptor().get().camera_id } /// Set the default camera `Id`. - pub fn use_camera_id(&self, camera_id: Id) { + pub fn use_camera_id(&self, camera_id: Id) { self.geometry .descriptor() .modify(|desc| desc.camera_id = camera_id); } /// Stage a [`Transform`] on the GPU. - pub fn new_transform(&self, transform: TransformDescriptor) -> Hybrid { - self.geometry.new_transform(transform) + pub fn new_transform(&self) -> Transform { + self.geometry.new_transform() } /// Stage some vertex geometry data. - pub fn new_vertices(&self, data: impl IntoIterator) -> HybridArray { + pub fn new_vertices(&self, data: impl IntoIterator) -> Vertices { self.geometry.new_vertices(data) } /// Stage some vertex index data. - pub fn new_indices(&self, data: impl IntoIterator) -> HybridArray { + pub fn new_indices(&self, data: impl IntoIterator) -> Indices { self.geometry.new_indices(data) } /// Create new morph targets. - // TODO: Move `MorphTarget` to geometry. pub fn new_morph_targets( &self, - data: impl IntoIterator, - ) -> HybridArray { + data: impl IntoIterator>, + ) -> MorphTargets { self.geometry.new_morph_targets(data) } - /// Create an array of morph target arrays. - pub fn new_morph_targets_array( - &self, - data: impl IntoIterator>, - ) -> HybridArray> { - let morph_targets = data.into_iter(); - self.geometry.new_morph_targets_array(morph_targets) - } - /// Create new morph target weights. - pub fn new_weights(&self, data: impl IntoIterator) -> HybridArray { - self.geometry.new_weights(data) - } - - /// Create a new array of joint transform ids that each point to a [`Transform`]. - pub fn new_joint_transform_ids( + pub fn new_morph_target_weights( &self, - data: impl IntoIterator>, - ) -> HybridArray> { - self.geometry.new_joint_transform_ids(data) - } - - /// Create a new array of matrices. - pub fn new_matrices(&self, data: impl IntoIterator) -> HybridArray { - self.geometry.new_matrices(data) + data: impl IntoIterator, + ) -> MorphTargetWeights { + self.geometry.new_morph_target_weights(data) } - /// Create a new skin. - // TODO: move `Skin` to geometry. - pub fn new_skin(&self, skin: Skin) -> Hybrid { - self.geometry.new_skin(skin) + pub fn new_skin( + &self, + joints: impl IntoIterator>, + inverse_bind_matrices: impl IntoIterator>, + ) -> Skin { + self.geometry.new_skin(joints, inverse_bind_matrices) } - /// Stage a new [`Renderlet`]. + /// Stage a new [`Renderlet`] on the GPU. + /// + /// The returned [`Renderlet`] will automatically be added to this [`Stage`]. /// - /// The `Renderlet` should still be added to the draw list with - /// [`Stage::add_renderlet`]. - pub fn new_renderlet(&self, renderlet: RenderletDescriptor) -> Hybrid { - self.geometry.new_renderlet(renderlet) + /// The returned [`Renderlet`] will have the stage's default [`Vertices`], which is an all-white + /// unit cube. + /// + /// The returned [`Renderlet`] uses the stage's default [`Material`], which is white and + /// **does not** participate in lighting. + pub fn new_renderlet(&self) -> Renderlet { + Renderlet::new(self) } /// Returns a reference to the descriptor stored at the root of the @@ -631,17 +475,18 @@ impl Stage { /// Materials methods. impl Stage { - /// Stage a new [`Material`] on the GPU. - pub fn new_material(&self, material: MaterialDescriptor) -> Hybrid { - self.materials.new_material(material) + /// Returns the default [`Material`]. + /// + /// The default is an all-white matte material. + pub fn default_material(&self) -> &Material { + self.materials.default_material() } - /// Create an array of materials, stored contiguously. - pub fn new_materials( - &self, - data: impl IntoIterator, - ) -> HybridArray { - self.materials.new_materials(data) + /// Stage a new [`Material`] on the GPU. + /// + /// The returned [`Material`] can be customized using the builder pattern. + pub fn new_material(&self) -> Material { + self.materials.new_material() } /// Set the size of the atlas. @@ -666,7 +511,7 @@ impl Stage { pub fn add_images( &self, images: impl IntoIterator>, - ) -> Result>, StageError> { + ) -> Result, StageError> { let images = images.into_iter().map(|i| i.into()).collect::>(); let frames = self.materials.atlas().add_images(&images)?; @@ -696,7 +541,7 @@ impl Stage { pub fn set_images( &self, images: impl IntoIterator>, - ) -> Result>, StageError> { + ) -> Result, StageError> { let images = images.into_iter().map(|i| i.into()).collect::>(); let frames = self.materials.atlas().set_images(&images)?; @@ -804,12 +649,13 @@ impl Stage { &self.runtime().queue } - pub fn hdr_texture(&self) -> impl Deref + '_ { - self.hdr_texture.read().unwrap() + /// Create a new [`SceneBuilder`] to help bundle staged resources. + pub fn builder(&self) -> SceneBuilder<'_, ()> { + SceneBuilder::new(self) } - pub fn builder(&self) -> RenderletBuilder<'_, ()> { - RenderletBuilder::new(self) + pub fn hdr_texture(&self) -> impl Deref + '_ { + self.hdr_texture.read().unwrap() } /// Run all upkeep and commit all staged changes to the GPU. @@ -1414,7 +1260,7 @@ impl Stage { /// If you drop the renderlet and no other references are kept, it will be /// removed automatically from the internal list and will cease to be /// drawn each frame. - pub fn add_renderlet(&self, renderlet: &Hybrid) { + pub fn add_renderlet(&self, renderlet: &Renderlet) { // UNWRAP: if we can't acquire the lock we want to panic. let mut draws = self.draw_calls.write().unwrap(); draws.add_renderlet(renderlet); @@ -1422,36 +1268,27 @@ impl Stage { /// Erase the given renderlet from the internal list of renderlets to be /// drawn each frame. - pub fn remove_renderlet(&self, renderlet: &Hybrid) { + pub fn remove_renderlet(&self, renderlet: &Renderlet) { let mut draws = self.draw_calls.write().unwrap(); draws.remove_renderlet(renderlet); } - /// Re-order the renderlets. + /// Sort the drawing order of renderlets. /// - /// This determines the order in which they are drawn each frame. - /// - /// If the `order` iterator is missing any renderlet ids, those missing - /// renderlets will be drawn _before_ the ordered ones, in no particular - /// order. - pub fn reorder_renderlets(&self, order: impl IntoIterator>) { - log::trace!("reordering renderlets"); + /// This determines the order in which [`Renderlet`]s are drawn each frame. + pub fn sort_renderlets( + &self, + f: impl Fn(&RenderletSortItem, &RenderletSortItem) -> std::cmp::Ordering, + ) { // UNWRAP: panic on purpose let mut guard = self.draw_calls.write().unwrap(); - guard.reorder_renderlets(order); + guard.sort_renderlets(f); } - /// Iterator over all staged [`Renderlet`]s. - /// - /// This iterator returns `Renderlets` wrapped in `WeakHybrid`, because they - /// are stored by weak references internally. - /// - /// You should have references of your own, but this is here as a convenience - /// method, and is used internally. - pub fn renderlets_iter(&self) -> impl Iterator> { + /// Returns the sort items of all staged [`Renderlet`]s. + pub fn renderlet_sort_items(&self) -> Vec { // UNWRAP: panic on purpose - let guard = self.draw_calls.read().unwrap(); - guard.renderlets_iter().collect::>().into_iter() + self.draw_calls.read().unwrap().sort_items().collect() } /// Returns a clone of the current depth texture. @@ -1587,156 +1424,114 @@ impl Stage { } } -/// Manages scene heirarchy on the [`Stage`]. -/// -/// Clones all reference the same nested transform. +/// A wrapper around [`Stage`] that builds up tuples of staged resources. /// -/// Only available on CPU. -#[derive(Clone)] -pub struct NestedTransform { - pub(crate) global_transform: Ct::Container, - local_transform: Arc>, - children: Arc>>, - parent: Arc>>, -} - -impl core::fmt::Debug for NestedTransform { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let children = self - .children - .read() - .unwrap() - .iter() - .map(|nt| nt.global_transform.id()) - .collect::>(); - let parent = self - .parent - .read() - .unwrap() - .as_ref() - .map(|nt| nt.global_transform.id()); - f.debug_struct("NestedTransform") - .field("local_transform", &self.local_transform) - .field("children", &children) - .field("parent", &parent) - .finish() - } +/// [`SceneBuilder`] implements a builder pattern that allows you to +/// build up tuples of resources like [`Vertices`], [`Indices`], +/// [`MorphTargets`] and [`MorphTargetWeights`]. +// TODO: documentation example +pub struct SceneBuilder<'a, T> { + stage: &'a Stage, + resources: T, } -impl NestedTransform { - pub fn from_hybrid(hybrid: &NestedTransform) -> Self { - Self { - global_transform: WeakHybrid::from_hybrid(&hybrid.global_transform), - local_transform: hybrid.local_transform.clone(), - children: hybrid.children.clone(), - parent: hybrid.parent.clone(), +impl<'a> SceneBuilder<'a, ()> { + pub fn new(stage: &'a Stage) -> Self { + SceneBuilder { + resources: (), + stage, } } - - pub(crate) fn upgrade(&self) -> Option { - Some(NestedTransform { - global_transform: self.global_transform.upgrade()?, - local_transform: self.local_transform.clone(), - children: self.children.clone(), - parent: self.parent.clone(), - }) - } } -impl NestedTransform { - pub fn new(slab: &SlabAllocator) -> Self { - let nested = NestedTransform { - local_transform: Arc::new(RwLock::new(TransformDescriptor::default())), - global_transform: slab.new_value(TransformDescriptor::default()), - children: Default::default(), - parent: Default::default(), - }; - nested.mark_dirty(); - nested - } - - pub fn get_notifier_index(&self) -> SourceId { - self.global_transform.notifier_index() - } - - fn mark_dirty(&self) { - self.global_transform.set(self.get_global_transform()); - for child in self.children.read().unwrap().iter() { - child.mark_dirty(); - } - } - - /// Modify the local transform. - /// - /// This automatically applies the local transform to the global transform. - pub fn modify(&self, f: impl Fn(&mut TransformDescriptor)) { - { - // UNWRAP: panic on purpose - let mut local_guard = self.local_transform.write().unwrap(); - f(&mut local_guard); +impl<'a, T: crate::types::tuple::Bundle> SceneBuilder<'a, T> { + pub fn suffix(self, element: S) -> SceneBuilder<'a, T::Suffixed> { + SceneBuilder { + resources: self.resources.suffix(element), + stage: self.stage, } - self.mark_dirty() - } - - /// Set the local transform. - /// - /// This automatically applies the local transform to the global transform. - pub fn set(&self, transform: TransformDescriptor) { - self.modify(move |t| { - *t = transform; - }); } - /// Returns the local transform. - pub fn get(&self) -> TransformDescriptor { - *self.local_transform.read().unwrap() + /// Stage vertex data and add it to the resource bundle. + pub fn with_vertices( + self, + vertices: impl IntoIterator, + ) -> SceneBuilder<'a, T::Suffixed> { + let vertices = self.stage.geometry.new_vertices(vertices); + self.suffix(vertices) } - /// Returns the global transform. - pub fn get_global_transform(&self) -> TransformDescriptor { - let maybe_parent_guard = self.parent.read().unwrap(); - let transform = self.get(); - let parent_transform = maybe_parent_guard - .as_ref() - .map(|parent| parent.get_global_transform()) - .unwrap_or_default(); - TransformDescriptor::from(Mat4::from(parent_transform) * Mat4::from(transform)) + /// Stage vertex index data and add it to the resource bundle. + pub fn with_indices( + self, + indices: impl IntoIterator, + ) -> SceneBuilder<'a, T::Suffixed> { + let indices = self.stage.geometry.new_indices(indices); + self.suffix(indices) } - /// Get a vector containing all the transforms up to the root. - pub fn get_all_transforms(&self) -> Vec { - let mut transforms = vec![]; - if let Some(parent) = self.parent() { - transforms.extend(parent.get_all_transforms()); - } - transforms.push(self.get()); - transforms + /// Stage morph target weights and add them to the resource bundle. + pub fn with_morph_targets( + self, + morph_targets: impl IntoIterator>, + ) -> SceneBuilder<'a, T::Suffixed> { + let ts = self.stage.geometry.new_morph_targets(morph_targets); + self.suffix(ts) } - pub fn global_transform_id(&self) -> Id { - self.global_transform.id() + /// Stage morph target weights and add them to the resource bundle. + pub fn with_morph_target_weights( + self, + morph_weights: impl IntoIterator, + ) -> SceneBuilder<'a, T::Suffixed> { + let ws = self.stage.new_morph_target_weights(morph_weights); + self.suffix(ws) } - pub fn add_child(&self, node: &NestedTransform) { - *node.parent.write().unwrap() = Some(self.clone()); - node.mark_dirty(); - self.children.write().unwrap().push(node.clone()); + /// Stage morph target weights and add them to the resource bundle. + pub fn with_skin( + self, + joints: impl IntoIterator>, + inverse_bind_matrices: impl IntoIterator>, + ) -> SceneBuilder<'a, T::Suffixed> { + let s = self.stage.new_skin(joints, inverse_bind_matrices); + self.suffix(s) } - pub fn remove_child(&self, node: &NestedTransform) { - self.children.write().unwrap().retain_mut(|child| { - if child.global_transform.id() == node.global_transform.id() { - node.mark_dirty(); - let _ = node.parent.write().unwrap().take(); - false - } else { - true - } - }); + /// Stage images and add them to the resource bundle, if possible. + /// + /// # Errors + /// Returns an error if the images could not be packed into the [`Atlas`]. + pub fn with_images( + self, + images: impl IntoIterator>, + ) -> Result>>, StageError> { + let i = self.stage.add_images(images)?; + Ok(self.suffix(i)) } - pub fn parent(&self) -> Option { - self.parent.read().unwrap().clone() + /// Stage one image and add it to the resource bundle, if possible. + /// + /// # Note + /// Each time the set of staged images changes, the [`Atlas`] must be repacked. + /// For this reason it is runtime-quicker to batch add as many images at once + /// as is possible. Consider using [`SceneBuilder::with_images`] instead. + /// + /// # Errors + /// Returns an error if the images could not be packed into the [`Atlas`]. + pub fn with_image( + self, + image: impl Into, + ) -> Result>, StageError> { + let mut i = self.stage.add_images(Some(image))?; + // UNWRAP: safe because we know there is _exactly_ one in there + Ok(self.suffix(i.pop().unwrap())) + } + + /// Consume the [`SceneBuilder`] and return the bundled resources as a tuple, + /// in the order they were accumulated. + pub fn build(self) -> T::Reduced { + self.resources.reduce() } } @@ -1747,11 +1542,10 @@ mod test { use glam::{Mat4, Vec2, Vec3, Vec4}; use crate::{ - camera::Camera, geometry::{Geometry, GeometryDescriptor}, - stage::{cpu::SlabAllocator, NestedTransform, RenderletDescriptor, Vertex}, + stage::{cpu::SlabAllocator, Vertex}, test::BlockOnFuture, - transform::TransformDescriptor, + transform::NestedTransform, Context, }; @@ -1792,21 +1586,9 @@ mod test { )] let slab = SlabAllocator::::new(&CpuRuntime, "transform", ()); // Setup a hierarchy of transforms - log::info!("new"); let root = NestedTransform::new(&slab); - let child = NestedTransform::new(&slab); - log::info!("set"); - child.set(TransformDescriptor { - translation: Vec3::new(1.0, 0.0, 0.0), - ..Default::default() - }); - log::info!("grandchild"); - let grandchild = NestedTransform::new(&slab); - grandchild.set(TransformDescriptor { - translation: Vec3::new(1.0, 0.0, 0.0), - ..Default::default() - }); - + let child = NestedTransform::new(&slab).with_translation(Vec3::new(1.0, 0.0, 0.0)); + let grandchild = NestedTransform::new(&slab).with_translation(Vec3::new(1.0, 0.0, 0.0)); log::info!("hierarchy"); // Build the hierarchy root.add_child(&child); @@ -1814,7 +1596,7 @@ mod test { log::info!("get_global_transform"); // Calculate global transforms - let grandchild_global_transform = grandchild.get_global_transform(); + let grandchild_global_transform = grandchild.global_descriptor(); // Assert that the global transform is as expected assert_eq!( @@ -1830,7 +1612,10 @@ mod test { .new_stage() .with_background_color([1.0, 1.0, 1.0, 1.0]) .with_lighting(false); - let _camera = stage.new_camera(Camera::default_ortho2d(100.0, 100.0)); + let (projection, view) = crate::camera::default_ortho2d(100.0, 100.0); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let _triangle_rez = stage .builder() .with_vertices([ @@ -1877,17 +1662,6 @@ mod test { frame.present(); } - #[test] - fn has_consistent_stage_renderlet_strong_count() { - let ctx = Context::headless(100, 100).block(); - let stage = ctx.new_stage(); - let r = stage.new_renderlet(RenderletDescriptor::default()); - assert_eq!(1, r.ref_count()); - - stage.add_renderlet(&r); - assert_eq!(1, r.ref_count()); - } - #[test] /// Tests that the PBR descriptor is written to slot 0 of the geometry buffer, /// and that it contains what we think it contains. diff --git a/crates/renderling/src/stage/cpu/renderlet.rs b/crates/renderling/src/stage/cpu/renderlet.rs new file mode 100644 index 00000000..09579d33 --- /dev/null +++ b/crates/renderling/src/stage/cpu/renderlet.rs @@ -0,0 +1,359 @@ +//! `Renderlet` builder. + +use core::ops::Deref; +use std::sync::{Arc, Mutex}; + +use craballoc::value::Hybrid; +use crabslab::{Array, Id}; + +use crate::{ + bvol::BoundingSphere, + geometry::{Indices, MorphTargetWeights, MorphTargets, Skin, Vertices}, + material::{Material, MaterialDescriptor}, + stage::RenderletDescriptor, + transform::{Transform, TransformDescriptor}, + types::GpuOnlyArray, +}; + +/// Used to sort renderlet draw calls. +pub struct RenderletSortItem { + pub descriptor: RenderletDescriptor, + pub transform: Option, + pub material: Option, +} + +/// A unit of rendering. +/// +/// A `Renderlet` represents one draw call, or one mesh primitive. +pub struct Renderlet { + pub(crate) descriptor: Hybrid, + + vertices: Arc>>>, + indices: Arc>>>, + + pub(crate) transform: Arc>>, + pub(crate) material: Arc>>, + skin: Arc>>, + morph_targets: Arc>>, +} + +impl Renderlet { + /// Create a new [`Renderlet`], automatically adding it to the [`Stage`] to be drawn. + /// + /// The returned [`Renderlet`] will have the stage's default [`Vertices`], which is an all-white + /// unit cube. + pub fn new(stage: &super::Stage) -> Self { + let descriptor = stage + .geometry + .slab_allocator() + .new_value(RenderletDescriptor::default()); + let renderlet = Renderlet { + descriptor, + vertices: Default::default(), + indices: Default::default(), + transform: Default::default(), + material: Default::default(), + skin: Default::default(), + morph_targets: Default::default(), + } + .with_vertices(stage.default_vertices()); + stage.add_renderlet(&renderlet); + renderlet + } + + /// Return a struct that can be used to order a [`Renderlet`] relative to others. + pub fn sort_item(&self) -> RenderletSortItem { + let transform = self + .transform + .lock() + .unwrap() + .as_ref() + .map(|t| t.descriptor()); + let material = self + .material + .lock() + .unwrap() + .as_ref() + .map(|m| m.descriptor()); + RenderletSortItem { + descriptor: self.descriptor.get(), + transform, + material, + } + } +} + +impl Clone for Renderlet { + fn clone(&self) -> Self { + Self { + descriptor: self.descriptor.clone(), + vertices: self.vertices.clone(), + indices: self.indices.clone(), + transform: self.transform.clone(), + material: self.material.clone(), + skin: self.skin.clone(), + morph_targets: self.morph_targets.clone(), + } + } +} + +// Vertices impls +impl Renderlet { + /// Set the vertex data of this renderlet. + pub fn set_vertices(&self, vertices: impl Into>) -> &Self { + let vertices = vertices.into(); + let array = vertices.array(); + self.descriptor.modify(|d| d.vertices_array = array); + *self.vertices.lock().unwrap() = Some(vertices.clone()); + self + } + + /// Set the vertex data of this renderlet and return the renderlet. + pub fn with_vertices(self, vertices: impl Into>) -> Self { + self.set_vertices(vertices); + self + } +} + +// Indices impls +impl Renderlet { + /// Set the index data of this renderlet. + pub fn set_indices(&self, indices: impl Into>) -> &Self { + let indices = indices.into(); + let array = indices.array(); + self.descriptor.modify(|d| d.indices_array = array); + *self.indices.lock().unwrap() = Some(indices.clone()); + self + } + + /// Set the index data of this renderlet and return the renderlet. + pub fn with_indices(self, indices: impl Into>) -> Self { + self.set_indices(indices); + self + } + + /// Remove the indices from this renderlet. + pub fn remove_indices(&self) -> &Self { + *self.indices.lock().unwrap() = None; + self.descriptor.modify(|d| d.indices_array = Array::NONE); + self + } +} + +// RenderletDescriptor impls +impl Renderlet { + /// Return a pointer to the underlying descriptor on the GPU. + pub fn id(&self) -> Id { + self.descriptor.id() + } + + /// Return the underlying descriptor. + pub fn descriptor(&self) -> RenderletDescriptor { + self.descriptor.get() + } + + /// Set the bounds of this renderlet. + pub fn set_bounds(&self, bounds: BoundingSphere) -> &Self { + self.descriptor.modify(|d| d.bounds = bounds); + self + } + + /// Set the bounds and return the renderlet. + pub fn with_bounds(self, bounds: BoundingSphere) -> Self { + self.set_bounds(bounds); + self + } + + /// Get the bounds. + /// + /// Returns the current `BoundingSphere`. + pub fn bounds(&self) -> BoundingSphere { + self.descriptor.get().bounds + } + + /// Modify the bounds of the renderlet. + /// + /// # Arguments + /// + /// * `f` - A closure that takes a mutable reference to the `BoundingSphere` and returns a value of type `T`. + pub fn modify_bounds(&self, f: impl FnOnce(&mut BoundingSphere) -> T) -> T { + self.descriptor.modify(|d| f(&mut d.bounds)) + } + + /// Set the visibility of this renderlet. + pub fn set_visible(&self, visible: bool) -> &Self { + self.descriptor.modify(|d| d.visible = visible); + self + } + + /// Set the visibility and return the renderlet. + pub fn with_visible(self, visible: bool) -> Self { + self.set_visible(visible); + self + } + + /// Return the renderlet's visibility. + pub fn visible(&self) -> bool { + self.descriptor.get().visible + } + + /// Modify the visible of the renderlet. + /// + /// # Arguments + /// + /// * `f` - A closure that takes a mutable reference to the visibility and returns a value of type `T`. + pub fn modify_visible(&self, f: impl FnOnce(&mut bool) -> T) -> T { + self.descriptor.modify(|d| f(&mut d.visible)) + } +} + +// Transform functions +impl Renderlet { + /// Set the transform. + /// + /// # Note + /// This can be set with [`Transform`] or [`NestedTransform`]. + pub fn set_transform(&self, transform: impl Into) -> &Self { + let transform = transform.into(); + self.descriptor.modify(|d| d.transform_id = transform.id()); + *self.transform.lock().unwrap() = Some(transform.clone()); + self + } + + /// Set the transform and return the `Renderlet`. + /// + /// # Note + /// This can be set with [`Transform`] or [`NestedTransform`]. + pub fn with_transform(self, transform: impl Into) -> Self { + self.set_transform(transform); + self + } + + /// Get the transform. + /// + /// Returns a reference to the current `Transform`, if any. + // TODO: see if we really need to provide this. + pub fn transform(&self) -> impl Deref> + '_ { + self.transform.lock().unwrap() + } + + /// Remove the transform from this renderlet. + /// + /// This effectively makes the transform the identity. + pub fn remove_transform(&self) -> &Self { + self.descriptor.modify(|d| d.transform_id = Id::NONE); + *self.transform.lock().unwrap() = None; + self + } +} + +// Material impls +impl Renderlet { + /// Set the material of this renderlet. + pub fn set_material(&self, material: impl Into) -> &Self { + let material = material.into(); + self.descriptor.modify(|d| d.material_id = material.id()); + *self.material.lock().unwrap() = Some(material); + self + } + + /// Set the material and return the renderlet. + pub fn with_material(self, material: impl Into) -> Self { + self.set_material(material); + self + } + + /// Get the material. + /// + /// Returns a reference to the current `Material`, if any. + // TODO: see if we really need to provide this. + pub fn material(&self) -> impl Deref> + '_ { + self.material.lock().unwrap() + } + + /// Remove the material from this renderlet. + pub fn remove_material(&self) -> &Self { + self.descriptor.modify(|d| d.material_id = Id::NONE); + *self.material.lock().unwrap() = None; + self + } +} + +// Skin impls +impl Renderlet { + /// Set the skin of this renderlet. + pub fn set_skin(&self, skin: impl Into) -> &Self { + let skin = skin.into(); + self.descriptor.modify(|d| d.skin_id = skin.id()); + *self.skin.lock().unwrap() = Some(skin.clone()); + self + } + + /// Set the skin and return the renderlet. + pub fn with_skin(self, skin: impl Into) -> Self { + self.set_skin(skin); + self + } + + /// Get the skin. + /// + /// Returns a reference to the current `Skin`, if any. + pub fn skin(&self) -> impl Deref> + '_ { + self.skin.lock().unwrap() + } + + /// Remove the skin from this renderlet. + pub fn remove_skin(&self) -> &Self { + self.descriptor.modify(|d| d.skin_id = Id::NONE); + *self.skin.lock().unwrap() = None; + self + } +} + +// (MorphTargets, MorphTargetsWeights) impls +impl Renderlet { + /// Set the morph targets and weights of this renderlet. + pub fn set_morph_targets( + &self, + morph_targets: impl Into, + weights: impl Into, + ) -> &Self { + let morph_targets = morph_targets.into(); + let weights = weights.into(); + self.descriptor.modify(|d| { + d.morph_targets = morph_targets.array(); + d.morph_weights = weights.array(); + }); + *self.morph_targets.lock().unwrap() = Some((morph_targets.clone(), weights.clone())); + self + } + + /// Set the morph targets and weights and return the renderlet. + pub fn with_morph_targets( + self, + morph_targets: impl Into, + weights: impl Into, + ) -> Self { + self.set_morph_targets(morph_targets, weights); + self + } + + /// Get the morph targets and weights. + /// + /// Returns a reference to the current `MorphTargets` and `MorphTargetsWeights`, if any. + pub fn morph_targets( + &self, + ) -> impl Deref> + '_ { + self.morph_targets.lock().unwrap() + } + + /// Remove the morph targets and weights from this renderlet. + pub fn remove_morph_targets(&self) -> &Self { + self.descriptor.modify(|d| { + d.morph_targets = Array::NONE; + d.morph_weights = Array::NONE; + }); + *self.morph_targets.lock().unwrap() = None; + self + } +} diff --git a/crates/renderling/src/stage/gltf_support.rs b/crates/renderling/src/stage/gltf_support.rs index bd6920f7..f496fbd7 100644 --- a/crates/renderling/src/stage/gltf_support.rs +++ b/crates/renderling/src/stage/gltf_support.rs @@ -2,22 +2,26 @@ use std::{collections::HashMap, sync::Arc}; use craballoc::prelude::*; -use crabslab::{Array, Id}; +use crabslab::Id; use glam::{Mat4, Quat, Vec2, Vec3, Vec4}; use rustc_hash::{FxHashMap, FxHashSet}; use snafu::{OptionExt, ResultExt, Snafu}; use crate::{ - atlas::{AtlasError, AtlasImage, AtlasTexture, TextureAddressMode, TextureModes}, + atlas::{ + AtlasError, AtlasImage, AtlasTexture, AtlasTextureDescriptor, TextureAddressMode, + TextureModes, + }, bvol::Aabb, - camera::Camera, + camera::{Camera, CameraDescriptor}, + geometry::{Indices, MorphTargetWeights, MorphTargets, Skin, Vertices}, light::{ AnalyticalLight, DirectionalLightDescriptor, LightStyle, PointLightDescriptor, SpotLightDescriptor, }, - material::MaterialDescriptor, - stage::{MorphTarget, NestedTransform, RenderletDescriptor, Skin, Stage, Vertex}, - transform::TransformDescriptor, + material::Material, + stage::{MorphTarget, Renderlet, Stage, Vertex}, + transform::{NestedTransform, TransformDescriptor}, }; mod anime; @@ -43,7 +47,7 @@ pub enum StageGltfError { #[snafu(display("Missing texture at gltf index {index} slab index {tex_id:?}"))] MissingTexture { index: usize, - tex_id: Id, + tex_id: Id, }, #[snafu(display("Missing material with index {index}"))] @@ -150,7 +154,7 @@ pub fn get_vertex_count(primitive: &gltf::Primitive<'_>) -> u32 { } } -impl MaterialDescriptor { +impl Material { pub fn preprocess_images( material: gltf::Material, images: &mut [AtlasImage], @@ -198,120 +202,87 @@ impl MaterialDescriptor { } pub fn from_gltf( + stage: &Stage, material: gltf::Material, - entries: &[Hybrid], - ) -> Result { + entries: &[AtlasTexture], + ) -> Result { let name = material.name().map(String::from); log::trace!("loading material {:?} {name:?}", material.index()); let pbr = material.pbr_metallic_roughness(); - let material = if material.unlit() { + let builder = stage.new_material(); + if material.unlit() { log::trace!(" is unlit"); - let (albedo_texture, albedo_tex_coord) = if let Some(info) = pbr.base_color_texture() { + if let Some(info) = pbr.base_color_texture() { let texture = info.texture(); let index = texture.index(); - let tex_id = entries.get(index).map(|e| e.id()).unwrap_or_default(); - (tex_id, info.tex_coord()) - } else { - (Id::NONE, 0) - }; - - MaterialDescriptor { - albedo_texture_id: albedo_texture, - albedo_tex_coord, - albedo_factor: pbr.base_color_factor().into(), - ..Default::default() + if let Some(tex) = entries.get(index) { + builder.set_albedo_texture(tex); + builder.set_albedo_tex_coord(info.tex_coord()); + } } + builder.set_albedo_factor(pbr.base_color_factor().into()); } else { log::trace!(" is pbr"); - let albedo_factor: Vec4 = pbr.base_color_factor().into(); - let (albedo_texture, albedo_tex_coord) = if let Some(info) = pbr.base_color_texture() { + + builder.set_albedo_factor(pbr.base_color_factor().into()); + if let Some(info) = pbr.base_color_texture() { let texture = info.texture(); let index = texture.index(); - let tex_id = entries.get(index).map(|e| e.id()).unwrap_or_default(); - (tex_id, info.tex_coord()) - } else { - (Id::NONE, 0) - }; + if let Some(tex) = entries.get(index) { + builder.set_albedo_texture(tex); + builder.set_albedo_tex_coord(info.tex_coord()); + } + } - let ( - metallic_factor, - roughness_factor, - metallic_roughness_texture, - metallic_roughness_tex_coord, - ) = if let Some(info) = pbr.metallic_roughness_texture() { + if let Some(info) = pbr.metallic_roughness_texture() { let index = info.texture().index(); - let tex_id = entries.get(index).map(|e| e.id()).unwrap_or_default(); - (1.0, 1.0, tex_id, info.tex_coord()) + if let Some(tex) = entries.get(index) { + builder.set_metallic_roughness_texture(tex); + builder.set_metallic_roughness_tex_coord(info.tex_coord()); + } } else { - (pbr.metallic_factor(), pbr.roughness_factor(), Id::NONE, 0) - }; + builder.set_metallic_factor(pbr.metallic_factor()); + builder.set_roughness_factor(pbr.roughness_factor()); + } - let (normal_texture, normal_tex_coord) = - if let Some(norm_tex) = material.normal_texture() { - let tex_id = entries - .get(norm_tex.texture().index()) - .map(|e| e.id()) - .unwrap_or_default(); - (tex_id, norm_tex.tex_coord()) - } else { - (Id::NONE, 0) - }; + if let Some(norm_tex) = material.normal_texture() { + if let Some(tex) = entries.get(norm_tex.texture().index()) { + builder.set_normal_texture(tex); + builder.set_normal_tex_coord(norm_tex.tex_coord()); + } + } - let (ao_strength, ao_texture, ao_tex_coord) = - if let Some(occlusion_tex) = material.occlusion_texture() { - let tex_id = entries - .get(occlusion_tex.texture().index()) - .map(|e| e.id()) - .unwrap_or_default(); - (occlusion_tex.strength(), tex_id, occlusion_tex.tex_coord()) - } else { - (0.0, Id::NONE, 0) - }; + if let Some(occlusion_tex) = material.occlusion_texture() { + if let Some(tex) = entries.get(occlusion_tex.texture().index()) { + builder.set_ambient_occlusion_texture(tex); + builder.set_ambient_occlusion_tex_coord(occlusion_tex.tex_coord()); + builder.set_ambient_occlusion_strength(occlusion_tex.strength()); + } + } - let (emissive_texture, emissive_tex_coord) = - if let Some(emissive_tex) = material.emissive_texture() { - let texture = emissive_tex.texture(); - let index = texture.index(); - let tex_id = entries.get(index).map(|e| e.id()).unwrap_or_default(); - (tex_id, emissive_tex.tex_coord()) - } else { - (Id::NONE, 0) - }; - let emissive_factor = Vec3::from(material.emissive_factor()); - let emissive_strength_multiplier = material.emissive_strength().unwrap_or(1.0); - - MaterialDescriptor { - albedo_factor, - metallic_factor, - roughness_factor, - albedo_texture_id: albedo_texture, - metallic_roughness_texture_id: metallic_roughness_texture, - normal_texture_id: normal_texture, - ao_texture_id: ao_texture, - albedo_tex_coord, - metallic_roughness_tex_coord, - normal_tex_coord, - ao_tex_coord, - ao_strength, - emissive_factor, - emissive_strength_multiplier, - emissive_texture_id: emissive_texture, - emissive_tex_coord, - has_lighting: true, + if let Some(emissive_tex) = material.emissive_texture() { + let texture = emissive_tex.texture(); + let index = texture.index(); + if let Some(tex) = entries.get(index) { + builder.set_emissive_texture(tex); + builder.set_emissive_tex_coord(emissive_tex.tex_coord()); + } } + + builder.set_emissive_factor(Vec3::from(material.emissive_factor())); + builder.set_emissive_strength_multiplier(material.emissive_strength().unwrap_or(1.0)); }; - Ok(material) + Ok(builder) } } #[derive(Debug)] pub struct GltfPrimitive { - pub indices: HybridArray, - pub vertices: HybridArray, + pub indices: Indices, + pub vertices: Vertices, pub bounding_box: (Vec3, Vec3), - pub material: Id, - pub morph_targets: Vec>, - pub morph_targets_array: HybridArray>, + pub material_index: Option, + pub morph_targets: MorphTargets, } impl GltfPrimitive { @@ -319,13 +290,8 @@ impl GltfPrimitive { stage: &Stage, primitive: gltf::Primitive, buffer_data: &[gltf::buffer::Data], - materials: &HybridArray, ) -> Self { - let material = primitive - .material() - .index() - .map(|index| materials.array().at(index)) - .unwrap_or_default(); + let material_index = primitive.material().index(); let reader = primitive.reader(|buffer| { let data = buffer_data.get(buffer.index())?; @@ -508,13 +474,7 @@ impl GltfPrimitive { morph_targets.len(), morph_targets.iter().map(|mt| mt.len()).collect::>() ); - let morph_targets = morph_targets - .into_iter() - .map(|verts| stage.new_morph_targets(verts)) - .collect::>(); - let morph_targets_array = - stage.new_morph_targets_array(morph_targets.iter().map(HybridArray::array)); - + let morph_targets = stage.new_morph_targets(morph_targets); let vs = joints.into_iter().zip(weights); let vs = colors.zip(vs); let vs = tangents.into_iter().zip(vs); @@ -544,9 +504,13 @@ impl GltfPrimitive { ) .collect::>(); let vertices = stage.new_vertices(vertices); - log::debug!("{} vertices, {:?}", vertices.len(), vertices.array()); + log::debug!( + "{} vertices, {:?}", + vertices.array().len(), + vertices.array() + ); let indices = stage.new_indices(indices); - log::debug!("{} indices, {:?}", indices.len(), indices.array()); + log::debug!("{} indices, {:?}", indices.array().len(), indices.array()); let (bbmin, bbmax) = { let gltf::mesh::Bounds { min, max } = primitive.bounding_box(); (Vec3::from_array(min), Vec3::from_array(max)) @@ -564,9 +528,8 @@ impl GltfPrimitive { Self { vertices, indices, - material, + material_index, morph_targets, - morph_targets_array, bounding_box, } } @@ -577,26 +540,21 @@ pub struct GltfMesh { /// Mesh primitives, aka meshlets pub primitives: Vec, /// Morph target weights - pub weights: HybridArray, + pub weights: MorphTargetWeights, } impl GltfMesh { - fn from_gltf( - stage: &Stage, - buffer_data: &[gltf::buffer::Data], - materials: &HybridArray, - mesh: gltf::Mesh, - ) -> Self { + fn from_gltf(stage: &Stage, buffer_data: &[gltf::buffer::Data], mesh: gltf::Mesh) -> Self { log::debug!("Loading primitives for mesh {}", mesh.index()); let primitives = mesh .primitives() - .map(|prim| GltfPrimitive::from_gltf(stage, prim, buffer_data, materials)) + .map(|prim| GltfPrimitive::from_gltf(stage, prim, buffer_data)) .collect::>(); log::debug!(" loaded {} primitives\n", primitives.len()); let weights = mesh.weights().unwrap_or(&[]).iter().copied(); GltfMesh { primitives, - weights: stage.new_weights(weights), + weights: stage.new_morph_target_weights(weights), } } } @@ -607,11 +565,11 @@ pub struct GltfCamera { pub name: Option, pub node_transform: NestedTransform, projection: Mat4, - pub camera: Hybrid, + pub camera: Camera, } -impl AsRef> for GltfCamera { - fn as_ref(&self) -> &Hybrid { +impl AsRef for GltfCamera { + fn as_ref(&self) -> &Camera { &self.camera } } @@ -619,7 +577,7 @@ impl AsRef> for GltfCamera { impl GltfCamera { fn new(stage: &Stage, gltf_camera: gltf::Camera<'_>, transform: &NestedTransform) -> Self { log::debug!("camera: {}", gltf_camera.name().unwrap_or("unknown")); - log::debug!(" transform: {:#?}", transform.get_global_transform()); + log::debug!(" transform: {:#?}", transform.global_descriptor()); let projection = match gltf_camera.projection() { gltf::camera::Projection::Orthographic(o) => glam::Mat4::orthographic_rh( -o.xmag(), @@ -643,8 +601,10 @@ impl GltfCamera { } } }; - let view = Mat4::from(transform.get_global_transform()).inverse(); - let camera = stage.new_camera(Camera::new(projection, view)); + let view = Mat4::from(transform.global_descriptor()).inverse(); + let camera = stage + .new_camera() + .with_projection_and_view(projection, view); GltfCamera { index: gltf_camera.index(), name: gltf_camera.name().map(String::from), @@ -654,9 +614,9 @@ impl GltfCamera { } } - pub fn get_camera(&self) -> Camera { - let view = Mat4::from(self.node_transform.get_global_transform()).inverse(); - Camera::new(self.projection, view) + pub fn camera_descriptor(&self) -> CameraDescriptor { + let view = Mat4::from(self.node_transform.global_descriptor()).inverse(); + CameraDescriptor::new(self.projection, view) } } @@ -679,15 +639,15 @@ pub struct GltfNode { /// /// Each element indexes into the `GltfDocument`'s `nodes` field. pub children: Vec, - /// Array of morph target weights - pub weights: HybridArray, + /// Morph target weights + pub weights: MorphTargetWeights, /// This node's transform. pub transform: NestedTransform, } impl GltfNode { pub fn global_transform(&self) -> TransformDescriptor { - self.transform.get_global_transform() + self.transform.global_descriptor() } } @@ -697,17 +657,11 @@ pub struct GltfSkin { // Indices of the skeleton nodes used as joints in this skin, unused internally // but possibly useful. pub joint_nodes: Vec, - pub joint_transforms: HybridArray>, - // Containins the 4x4 inverse-bind matrices. - // - // When None, each matrix is assumed to be the 4x4 identity matrix which implies that the - // inverse-bind matrices were pre-applied. - pub inverse_bind_matrices: Option>, // Index of the node used as the skeleton root. // When None, joints transforms resolve to scene root. pub skeleton: Option, - // Skin as seen by shaders, on the GPU - pub skin: Hybrid, + // Skin as seen by renderling + pub skin: Skin, } impl GltfSkin { @@ -715,34 +669,33 @@ impl GltfSkin { stage: &Stage, buffer_data: &[gltf::buffer::Data], nodes: &[GltfNode], - skin: gltf::Skin, + gltf_skin: gltf::Skin, ) -> Result { - log::debug!("reading skin {} {:?}", skin.index(), skin.name()); - let joint_nodes = skin.joints().map(|n| n.index()).collect::>(); + log::debug!("reading skin {} {:?}", gltf_skin.index(), gltf_skin.name()); + let joint_nodes = gltf_skin.joints().map(|n| n.index()).collect::>(); log::debug!(" has {} joints", joint_nodes.len()); let mut joint_transforms = vec![]; for node_index in joint_nodes.iter() { let gltf_node: &GltfNode = nodes .get(*node_index) .context(MissingNodeSnafu { index: *node_index })?; - let transform_id = gltf_node.transform.global_transform_id(); + let transform_id = gltf_node.transform.global_descriptor(); log::debug!(" joint node {node_index} is {transform_id:?}"); - joint_transforms.push(transform_id); + joint_transforms.push(gltf_node.transform.clone()); } - let joint_transforms = stage.new_joint_transform_ids(joint_transforms); - let reader = skin.reader(|b| buffer_data.get(b.index()).map(|d| d.0.as_slice())); - let inverse_bind_matrices = if let Some(mats) = reader.read_inverse_bind_matrices() { + let reader = gltf_skin.reader(|b| buffer_data.get(b.index()).map(|d| d.0.as_slice())); + let mut inverse_bind_matrices = vec![]; + if let Some(mats) = reader.read_inverse_bind_matrices() { let invs = mats .into_iter() .map(|m| Mat4::from_cols_array_2d(&m)) .collect::>(); log::debug!(" has {} inverse bind matrices", invs.len()); - Some(stage.new_matrices(invs)) + inverse_bind_matrices = invs; } else { log::debug!(" no inverse bind matrices"); - None - }; - let skeleton = if let Some(n) = skin.skeleton() { + } + let skeleton = if let Some(n) = gltf_skin.skeleton() { let index = n.index(); log::debug!(" skeleton is node {index}, {:?}", n.name()); Some(index) @@ -751,17 +704,9 @@ impl GltfSkin { None }; Ok(GltfSkin { - index: skin.index(), - skin: stage.new_skin(Skin { - joints: joint_transforms.array(), - inverse_bind_matrices: inverse_bind_matrices - .as_ref() - .map(|a| a.array()) - .unwrap_or_default(), - }), + index: gltf_skin.index(), + skin: stage.new_skin(joint_transforms, inverse_bind_matrices), joint_nodes, - joint_transforms, - inverse_bind_matrices, skeleton, }) } @@ -771,16 +716,16 @@ impl GltfSkin { pub struct GltfDocument { pub animations: Vec, pub cameras: Vec, - pub default_material: Hybrid, pub default_scene: Option, pub extensions: Option, - pub textures: Vec>, + pub textures: Vec, pub lights: Vec, pub meshes: Vec, pub nodes: Vec, - pub materials: HybridArray, + pub default_material: Material, + pub materials: Vec, // map of node index to renderlets - pub renderlets: FxHashMap>>, + pub renderlets: FxHashMap>, /// Vector of scenes - each being a list of nodes. pub scenes: Vec>, pub skins: Vec, @@ -796,7 +741,7 @@ impl GltfDocument { let textures = { let mut images = images.into_iter().map(AtlasImage::from).collect::>(); for gltf_material in document.materials() { - MaterialDescriptor::preprocess_images(gltf_material, &mut images)?; + Material::preprocess_images(gltf_material, &mut images)?; } // Arc these images because they could be large and we don't want duplicates let images = images.into_iter().map(Arc::new).collect::>(); @@ -855,9 +800,9 @@ impl GltfDocument { }) .collect(); let hybrid_textures = stage.add_images(prepared_images).context(StageSnafu)?; - let mut texture_lookup = FxHashMap::>::default(); + let mut texture_lookup = FxHashMap::::default(); for (hybrid, (tex, refs)) in hybrid_textures.into_iter().zip(deduped_textures) { - hybrid.modify(|t| t.modes = tex.modes); + hybrid.set_modes(tex.modes); for tex_index in refs.into_iter() { texture_lookup.insert(tex_index, hybrid.clone()); } @@ -871,27 +816,26 @@ impl GltfDocument { }; log::debug!("Creating materials"); - let default_material = stage.new_material(MaterialDescriptor::default()); + let mut default_material = stage.default_material().clone(); let mut materials = vec![]; for gltf_material in document.materials() { let material_index = gltf_material.index(); - let material = MaterialDescriptor::from_gltf(gltf_material, &textures)?; + let material = Material::from_gltf(stage, gltf_material, &textures)?; if let Some(index) = material_index { log::trace!(" created material {index}"); debug_assert_eq!(index, materials.len(), "unexpected material index"); materials.push(material); } else { log::trace!(" created default material"); - default_material.set(material); + default_material = material; } } - let materials = stage.new_materials(materials); log::trace!(" created {} materials", materials.len()); log::debug!("Loading meshes"); let mut meshes = vec![]; for mesh in document.meshes() { - let mesh = GltfMesh::from_gltf(stage, &buffer_data, &materials, mesh); + let mesh = GltfMesh::from_gltf(stage, &buffer_data, mesh); meshes.push(mesh); } log::trace!(" loaded {} meshes", meshes.len()); @@ -912,8 +856,16 @@ impl GltfDocument { let nt = if let Some(nt) = cache.get(&node.index()) { nt.clone() } else { - let transform = stage.new_nested_transform(); - transform.set(node.transform().into()); + let TransformDescriptor { + translation, + rotation, + scale, + } = node.transform().into(); + let transform = stage + .new_nested_transform() + .with_translation(translation) + .with_rotation(rotation) + .with_scale(scale); for node in node.children() { let child_transform = transform_for_node(nesting_level + 1, stage, cache, &node); @@ -922,7 +874,7 @@ impl GltfDocument { cache.insert(node.index(), transform.clone()); transform }; - let t = nt.get(); + let t = nt.local_descriptor(); log::trace!( "{padding}{} {:?} {:?} {:?} {:?}", node.index(), @@ -961,10 +913,10 @@ impl GltfDocument { if let Some(mesh) = node.mesh() { meshes[mesh.index()].weights.clone() } else { - stage.new_weights(weights) + stage.new_morph_target_weights(weights) } } else { - stage.new_weights(weights) + stage.new_morph_target_weights(weights) }; let transform = transform_for_node(0, stage, &mut node_transforms, &node); nodes.push(GltfNode { @@ -1058,8 +1010,8 @@ impl GltfDocument { log::trace!( " linking light {:?} with node transform {:?}: {:#?}", light_bundle.light().id(), - node_transform.global_transform_id(), - node_transform.get_global_transform() + node_transform.global_id(), + node_transform.global_descriptor() ); light_bundle.link_node_transform(&node_transform); lights.push(light_bundle); @@ -1088,14 +1040,14 @@ impl GltfDocument { let mut renderlets = FxHashMap::default(); for gltf_node in nodes.iter() { let mut node_renderlets = vec![]; - let skin_id = if let Some(skin_index) = gltf_node.skin { + let maybe_skin = if let Some(skin_index) = gltf_node.skin { log::debug!(" node {} {:?} has skin", gltf_node.index, gltf_node.name); let gltf_skin = skins .get(skin_index) .context(MissingSkinSnafu { index: skin_index })?; - gltf_skin.skin.id() + Some(gltf_skin.skin.clone()) } else { - Id::NONE + None }; if let Some(mesh_index) = gltf_node.mesh { @@ -1110,20 +1062,26 @@ impl GltfDocument { let num_prims = mesh.primitives.len(); log::trace!(" has {num_prims} primitives"); for (prim, i) in mesh.primitives.iter().zip(1..) { - let hybrid = stage.new_renderlet(RenderletDescriptor { - vertices_array: prim.vertices.array(), - indices_array: prim.indices.array(), - transform_id: gltf_node.transform.global_transform_id(), - material_id: prim.material, - skin_id, - morph_targets: prim.morph_targets_array.array(), - morph_weights: gltf_node.weights.array(), - bounds: prim.bounding_box.into(), - ..Default::default() - }); - log::trace!(" created renderlet {i}/{num_prims}: {:#?}", hybrid.get()); - stage.add_renderlet(&hybrid); - node_renderlets.push(hybrid); + let material = prim + .material_index + .and_then(|index| materials.get(index)) + .unwrap_or(&default_material); + let renderlet = stage + .new_renderlet() + .with_vertices(&prim.vertices) + .with_indices(&prim.indices) + .with_transform(&gltf_node.transform) + .with_material(material) + .with_bounds(prim.bounding_box.into()) + .with_morph_targets(&prim.morph_targets, &gltf_node.weights); + if let Some(skin) = maybe_skin.as_ref() { + renderlet.set_skin(skin); + } + log::trace!( + " created renderlet {i}/{num_prims}: {:#?}", + renderlet.id() + ); + node_renderlets.push(renderlet); } } if !node_renderlets.is_empty() { @@ -1155,7 +1113,7 @@ impl GltfDocument { }) } - pub fn renderlets_iter(&self) -> impl Iterator> { + pub fn renderlets_iter(&self) -> impl Iterator { self.renderlets.iter().flat_map(|(_, rs)| rs.iter()) } @@ -1216,10 +1174,7 @@ impl Stage { #[cfg(test)] mod test { - use crate::{ - camera::Camera, material::MaterialDescriptor, stage::Vertex, test::BlockOnFuture, - transform::TransformDescriptor, Context, - }; + use crate::{stage::Vertex, test::BlockOnFuture, Context}; use glam::{Vec3, Vec4}; #[test] @@ -1253,7 +1208,9 @@ mod test { .with_lighting(false) .with_bloom(false) .with_background_color(Vec3::splat(0.0).extend(1.0)); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let _doc = stage .load_gltf_document_from_path("../../gltf/gltfTutorial_008_SimpleMeshes.gltf") .unwrap(); @@ -1277,7 +1234,9 @@ mod test { let projection = crate::camera::perspective(20.0, 20.0); let eye = Vec3::new(0.5, 0.5, 2.0); let view = crate::camera::look_at(eye, Vec3::new(0.5, 0.5, 0.0), Vec3::Y); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let _doc = stage .load_gltf_document_from_path("../../gltf/gltfTutorial_003_MinimalGltfFile.gltf") @@ -1300,38 +1259,42 @@ mod test { .with_lighting(false) .with_background_color(Vec4::splat(1.0)); let (projection, view) = crate::camera::default_ortho2d(100.0, 100.0); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let doc = stage .load_gltf_document_from_path("../../gltf/cheetah_cone.glb") .unwrap(); assert!(!doc.textures.is_empty()); - let (material, _vertices, _indices, _transform, _renderlet) = stage - .builder() - .with_material(MaterialDescriptor { - albedo_texture_id: doc.textures[0].id(), - has_lighting: false, - ..Default::default() - }) - .with_vertices([ - Vertex::default() - .with_position([0.0, 0.0, 0.0]) - .with_uv0([0.0, 0.0]), - Vertex::default() - .with_position([1.0, 0.0, 0.0]) - .with_uv0([1.0, 0.0]), - Vertex::default() - .with_position([1.0, 1.0, 0.0]) - .with_uv0([1.0, 1.0]), - Vertex::default() - .with_position([0.0, 1.0, 0.0]) - .with_uv0([0.0, 1.0]), - ]) - .with_indices([0u32, 3, 2, 0, 2, 1]) - .with_transform(TransformDescriptor { - scale: Vec3::new(100.0, 100.0, 1.0), - ..Default::default() - }) - .build(); + let material = stage + .new_material() + .with_albedo_texture(&doc.textures[0]) + .with_has_lighting(false); + let _rez = stage + .new_renderlet() + .with_material(&material) + .with_vertices( + stage.new_vertices([ + Vertex::default() + .with_position([0.0, 0.0, 0.0]) + .with_uv0([0.0, 0.0]), + Vertex::default() + .with_position([1.0, 0.0, 0.0]) + .with_uv0([1.0, 0.0]), + Vertex::default() + .with_position([1.0, 1.0, 0.0]) + .with_uv0([1.0, 1.0]), + Vertex::default() + .with_position([0.0, 1.0, 0.0]) + .with_uv0([0.0, 1.0]), + ]), + ) + .with_indices(stage.new_indices([0u32, 3, 2, 0, 2, 1])) + .with_transform( + stage + .new_transform() + .with_scale(Vec3::new(100.0, 100.0, 1.0)), + ); println!("material_id: {:#?}", material.id()); let frame = ctx.get_next_frame().unwrap(); @@ -1354,7 +1317,9 @@ mod test { let projection = crate::camera::perspective(size as f32, size as f32); let view = crate::camera::look_at(Vec3::new(0.5, 0.5, 1.25), Vec3::new(0.5, 0.5, 0.0), Vec3::Y); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let _doc = stage .load_gltf_document_from_path("../../gltf/gltfTutorial_013_SimpleTexture.gltf") @@ -1407,11 +1372,12 @@ mod test { let up = Vec3::Y; let view = glam::Mat4::look_at_rh(eye, target, up); - let _camera = stage.new_camera(Camera::new(projection, view)); - let doc = stage + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); + let _doc = stage .load_gltf_document_from_path("../../gltf/Fox.glb") .unwrap(); - log::info!("renderlets: {:#?}", doc.renderlets); // render a frame without vertex skinning as a baseline let frame = ctx.get_next_frame().unwrap(); @@ -1483,10 +1449,19 @@ mod test { .unwrap(); let camera_a = doc.cameras.first().unwrap(); - let eq = |p: Vec3| p.distance(camera_a.get_camera().position()) <= 10e-6; - let either_y_up_or_z_up = eq(Vec3::new(14.699949, 4.958309, 12.676651)) - || eq(Vec3::new(14.699949, -12.676651, 4.958309)); - assert!(either_y_up_or_z_up); + let desc = camera_a.camera_descriptor(); + const THRESHOLD: f32 = 10e-6; + let a = Vec3::new(14.699949, 4.958309, 12.676651); + let b = Vec3::new(14.699949, -12.676651, 4.958309); + let distance_a = a.distance(desc.position()); + let distance_b = b.distance(desc.position()); + if distance_a > THRESHOLD && distance_b > THRESHOLD { + println!("desc: {desc:#?}"); + println!("distance_a: {distance_a}"); + println!("distance_b: {distance_b}"); + println!("threshold: {THRESHOLD}"); + panic!("distance greater than threshold"); + } let doc = stage .load_gltf_document_from_path( @@ -1505,8 +1480,8 @@ mod test { a.distance(b) <= 10e-6 || c.distance(c) <= 10e-6 }; assert!(eq( - camera_a.get_camera().position(), - camera_b.get_camera().position() + camera_a.camera_descriptor().position(), + camera_b.camera_descriptor().position() )); } } diff --git a/crates/renderling/src/stage/gltf_support/anime.rs b/crates/renderling/src/stage/gltf_support/anime.rs index 72958a41..65cf42f2 100644 --- a/crates/renderling/src/stage/gltf_support/anime.rs +++ b/crates/renderling/src/stage/gltf_support/anime.rs @@ -3,7 +3,9 @@ use craballoc::prelude::HybridArray; use glam::{Quat, Vec3}; use snafu::prelude::*; -use crate::stage::{gltf_support::GltfNode, NestedTransform}; +use crate::{ + geometry::MorphTargetWeights, stage::gltf_support::GltfNode, transform::NestedTransform, +}; #[derive(Debug, Snafu)] pub enum InterpolationError { @@ -546,7 +548,7 @@ impl Tween { #[derive(Clone, Debug)] pub struct AnimationNode { pub transform: NestedTransform, - pub morph_weights: HybridArray, + pub morph_weights: MorphTargetWeights, } impl From<&GltfNode> for (usize, AnimationNode) { @@ -737,26 +739,20 @@ impl Animator { if let Some(node) = self.nodes.get(&node_index) { match property { TweenProperty::Translation(translation) => { - node.transform.modify(|t| { - t.translation = translation; - }); + node.transform.set_translation(translation); } TweenProperty::Rotation(rotation) => { - node.transform.modify(|t| { - t.rotation = rotation; - }); + node.transform.set_rotation(rotation); } TweenProperty::Scale(scale) => { - node.transform.modify(|t| { - t.scale = scale; - }); + node.transform.set_scale(scale); } TweenProperty::MorphTargetWeights(new_weights) => { - if node.morph_weights.is_empty() { + if node.morph_weights.array().is_empty() { log::error!("animation is applied to morph targets but node {node_index} is missing weights"); } else { for (i, w) in new_weights.into_iter().enumerate() { - let _ = node.morph_weights.set_item(i, w); + node.morph_weights.set_item(i, w); } } } @@ -771,7 +767,7 @@ impl Animator { #[cfg(test)] mod test { - use crate::{camera::Camera, stage::Animator, test::BlockOnFuture, Context}; + use crate::{camera::CameraDescriptor, stage::Animator, test::BlockOnFuture, Context}; use glam::Vec3; #[test] @@ -783,7 +779,9 @@ mod test { .with_background_color(Vec3::ZERO.extend(1.0)); let projection = crate::camera::perspective(50.0, 50.0); let view = crate::camera::look_at(Vec3::Z * 3.0, Vec3::ZERO, Vec3::Y); - let _camera = stage.new_camera(Camera::new(projection, view)); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let doc = stage .load_gltf_document_from_path("../../gltf/animated_triangle.gltf") diff --git a/crates/renderling/src/transform/cpu.rs b/crates/renderling/src/transform/cpu.rs index 2f91ab9d..d2155451 100644 --- a/crates/renderling/src/transform/cpu.rs +++ b/crates/renderling/src/transform/cpu.rs @@ -1,18 +1,410 @@ //! CPU side of transform. -use craballoc::value::{GpuContainer, HybridContainer, IsContainer}; +use std::sync::{Arc, RwLock}; + +use craballoc::{ + runtime::IsRuntime, + slab::{SlabAllocator, SourceId}, + value::Hybrid, +}; +use crabslab::Id; +use glam::{Mat4, Quat, Vec3}; + +use super::TransformDescriptor; /// A decomposed 3d transformation. -pub struct Transform { - descriptor: Ct::Container, +#[derive(Clone)] +pub struct Transform { + descriptor: Hybrid, } -pub type GpuOnlyTransform = Transform; +impl From<&Transform> for Transform { + fn from(value: &Transform) -> Self { + value.clone() + } +} impl Transform { - pub fn into_gpu_only(self) -> GpuOnlyTransform { - Transform { - descriptor: self.descriptor.into_gpu_only(), + /// Stage a new transform on the GPU. + pub(crate) fn new(slab: &SlabAllocator) -> Self { + let descriptor = slab.new_value(TransformDescriptor::default()); + Self { descriptor } + } + + /// Return a pointer to the underlying descriptor data on the GPU. + pub fn id(&self) -> Id { + self.descriptor.id() + } + + /// Return the a copy of the underlying descriptor. + pub fn descriptor(&self) -> TransformDescriptor { + self.descriptor.get() + } + + /// Set the descriptor. + pub fn set_descriptor(&self, descriptor: TransformDescriptor) -> &Self { + self.descriptor.set(descriptor); + self + } + + /// Set the descriptor and return the `Transform`. + pub fn with_descriptor(self, descriptor: TransformDescriptor) -> Self { + self.set_descriptor(descriptor); + self + } + + /// Return the transform in combined matrix format; + pub fn as_mat4(&self) -> Mat4 { + self.descriptor().into() + } + + /// Get the translation of the transform. + pub fn translation(&self) -> Vec3 { + self.descriptor.get().translation + } + + /// Modify the translation of the transform. + /// + /// # Arguments + /// + /// - `f`: A closure that takes a mutable reference to the translation vector and returns a value of type `T`. + pub fn modify_translation(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { + self.descriptor.modify(|t| f(&mut t.translation)) + } + + /// Set the translation of the transform. + /// + /// # Arguments + /// + /// - `translation`: A 3d translation vector `Vec3`. + pub fn set_translation(&self, translation: impl Into) -> &Self { + self.descriptor + .modify(|t| t.translation = translation.into()); + self + } + + /// Set the translation of the transform. + /// + /// # Arguments + /// + /// - `translation`: A 3d translation vector `Vec3`. + pub fn with_translation(self, translation: impl Into) -> Self { + self.set_translation(translation); + self + } + + /// Get the rotation of the transform. + pub fn rotation(&self) -> Quat { + self.descriptor.get().rotation + } + + /// Modify the rotation of the transform. + /// + /// # Arguments + /// + /// - `f`: A closure that takes a mutable reference to the rotation quaternion and returns a value of type `T`. + pub fn modify_rotation(&self, f: impl FnOnce(&mut Quat) -> T) -> T { + self.descriptor.modify(|t| f(&mut t.rotation)) + } + + /// Set the rotation of the transform. + /// + /// # Arguments + /// + /// - `rotation`: A quaternion representing the rotation. + pub fn set_rotation(&self, rotation: impl Into) -> &Self { + self.descriptor.modify(|t| t.rotation = rotation.into()); + self + } + + /// Set the rotation of the transform. + /// + /// # Arguments + /// + /// - `rotation`: A quaternion representing the rotation. + pub fn with_rotation(self, rotation: impl Into) -> Self { + self.set_rotation(rotation); + self + } + + /// Get the scale of the transform. + pub fn scale(&self) -> Vec3 { + self.descriptor.get().scale + } + + /// Modify the scale of the transform. + /// + /// # Arguments + /// + /// - `f`: A closure that takes a mutable reference to the scale vector and returns a value of type `T`. + pub fn modify_scale(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { + self.descriptor.modify(|t| f(&mut t.scale)) + } + + /// Set the scale of the transform. + /// + /// # Arguments + /// + /// - `scale`: A 3d scale vector `Vec3`. + pub fn set_scale(&self, scale: impl Into) -> &Self { + self.descriptor.modify(|t| t.scale = scale.into()); + self + } + + /// Set the scale of the transform. + /// + /// # Arguments + /// + /// - `scale`: A 3d scale vector `Vec3`. + pub fn with_scale(self, scale: impl Into) -> Self { + self.set_scale(scale); + self + } +} + +/// Manages scene heirarchy on the [`Stage`]. +/// +/// Clones all reference the same nested transform. +#[derive(Clone)] +pub struct NestedTransform { + pub(crate) global_transform: Transform, + local_transform: Arc>, + children: Arc>>, + parent: Arc>>, +} + +impl core::fmt::Debug for NestedTransform { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let children = self + .children + .read() + .unwrap() + .iter() + .map(|nt| nt.global_transform.id()) + .collect::>(); + let parent = self + .parent + .read() + .unwrap() + .as_ref() + .map(|nt| nt.global_transform.id()); + f.debug_struct("NestedTransform") + .field("local_transform", &self.local_transform) + .field("children", &children) + .field("parent", &parent) + .finish() + } +} + +impl From<&NestedTransform> for Transform { + fn from(value: &NestedTransform) -> Self { + value.global_transform.clone() + } +} + +impl From for Transform { + fn from(value: NestedTransform) -> Self { + value.global_transform + } +} + +// Make the API mirror Transform + +impl NestedTransform { + /// Stage a new hierarchical transform on the GPU. + pub(crate) fn new(slab: &SlabAllocator) -> Self { + let nested = NestedTransform { + local_transform: Arc::new(RwLock::new(TransformDescriptor::default())), + global_transform: Transform::new(slab), + children: Default::default(), + parent: Default::default(), + }; + nested.mark_dirty(); + nested + } + + /// Return the _local_ transform in combined matrix format; + pub fn as_mat4(&self) -> Mat4 { + (*self.local_transform.read().unwrap()).into() + } + + /// Get the _local_ translation of the transform. + pub fn translation(&self) -> Vec3 { + self.local_transform.read().unwrap().translation + } + + /// Modify the _local_ translation of the transform. + /// + /// # Arguments + /// + /// - `f`: A closure that takes a mutable reference to the translation vector and returns a value of type `T`. + pub fn modify_translation(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { + let mut local_transform = self.local_transform.write().unwrap(); + f(&mut local_transform.translation) + } + + /// Set the _local_ translation of the transform. + /// + /// # Arguments + /// + /// - `translation`: A 3d translation vector `Vec3`. + pub fn set_translation(&self, translation: impl Into) -> &Self { + self.local_transform.write().unwrap().translation = translation.into(); + self + } + + /// Set the _local_ translation of the transform. + /// + /// # Arguments + /// + /// - `translation`: A 3d translation vector `Vec3`. + pub fn with_translation(self, translation: impl Into) -> Self { + self.set_translation(translation); + self + } + + /// Get the _local_ rotation of the transform. + pub fn rotation(&self) -> Quat { + self.local_transform.read().unwrap().rotation + } + + /// Modify the _local_ rotation of the transform. + /// + /// # Arguments + /// + /// - `f`: A closure that takes a mutable reference to the rotation quaternion and returns a value of type `T`. + pub fn modify_rotation(&self, f: impl FnOnce(&mut Quat) -> T) -> T { + let mut local_transform = self.local_transform.write().unwrap(); + f(&mut local_transform.rotation) + } + + /// Set the _local_ rotation of the transform. + /// + /// # Arguments + /// + /// - `rotation`: A quaternion representing the rotation. + pub fn set_rotation(&self, rotation: impl Into) -> &Self { + self.local_transform.write().unwrap().rotation = rotation.into(); + self + } + + /// Set the _local_ rotation of the transform. + /// + /// # Arguments + /// + /// - `rotation`: A quaternion representing the rotation. + pub fn with_rotation(self, rotation: impl Into) -> Self { + self.set_rotation(rotation); + self + } + + /// Get the _local_ scale of the transform. + pub fn scale(&self) -> Vec3 { + self.local_transform.read().unwrap().scale + } + + /// Modify the _local_ scale of the transform. + /// + /// # Arguments + /// + /// - `f`: A closure that takes a mutable reference to the scale vector and returns a value of type `T`. + pub fn modify_scale(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { + let mut local_transform = self.local_transform.write().unwrap(); + f(&mut local_transform.scale) + } + + /// Set the _local_ scale of the transform. + /// + /// # Arguments + /// + /// - `scale`: A 3d scale vector `Vec3`. + pub fn set_scale(&self, scale: impl Into) -> &Self { + self.local_transform.write().unwrap().scale = scale.into(); + self + } + + /// Set the _local_ scale of the transform. + /// + /// # Arguments + /// + /// - `scale`: A 3d scale vector `Vec3`. + pub fn with_scale(self, scale: impl Into) -> Self { + self.set_scale(scale); + self + } +} + +impl NestedTransform { + /// Return a pointer to the underlying descriptor data on the GPU. + /// + /// The descriptor is the descriptor that describes the _global_ transform. + pub fn global_id(&self) -> Id { + self.global_transform.id() + } + + /// Return the descriptor of the _global_ transform. + /// + /// This traverses the heirarchy and computes the result. + pub fn global_descriptor(&self) -> TransformDescriptor { + let maybe_parent_guard = self.parent.read().unwrap(); + let transform = self.local_descriptor(); + let parent_transform = maybe_parent_guard + .as_ref() + .map(|parent| parent.global_descriptor()) + .unwrap_or_default(); + TransformDescriptor::from(Mat4::from(parent_transform) * Mat4::from(transform)) + } + + /// Return the descriptor of the _local_ tarnsform. + pub fn local_descriptor(&self) -> TransformDescriptor { + *self.local_transform.read().unwrap() + } + + pub(crate) fn get_notifier_index(&self) -> SourceId { + self.global_transform.descriptor.notifier_index() + } + + fn mark_dirty(&self) { + self.global_transform + .descriptor + .set(self.global_descriptor()); + for child in self.children.read().unwrap().iter() { + child.mark_dirty(); + } + } + + /// Get a vector containing all the hierarchy's transforms. + /// + /// Starts with the root transform and ends with the local transform. + pub fn hierarchy(&self) -> Vec { + let mut transforms = vec![]; + if let Some(parent) = self.parent() { + transforms.extend(parent.hierarchy()); } + transforms.push(self.local_descriptor()); + transforms + } + + pub fn add_child(&self, node: &NestedTransform) { + *node.parent.write().unwrap() = Some(self.clone()); + node.mark_dirty(); + self.children.write().unwrap().push(node.clone()); + } + + pub fn remove_child(&self, node: &NestedTransform) { + self.children.write().unwrap().retain_mut(|child| { + if child.global_transform.id() == node.global_transform.id() { + node.mark_dirty(); + let _ = node.parent.write().unwrap().take(); + false + } else { + true + } + }); + } + + /// Return a clone of the parent `NestedTransform`, if any. + pub fn parent(&self) -> Option { + self.parent.read().unwrap().clone() } } diff --git a/crates/renderling/src/types.rs b/crates/renderling/src/types.rs new file mode 100644 index 00000000..f7489b33 --- /dev/null +++ b/crates/renderling/src/types.rs @@ -0,0 +1,26 @@ +//! Type level machinery. + +use craballoc::value::{GpuArrayContainer, GpuContainer, HybridArrayContainer, HybridContainer}; + +pub mod tuple; + +/// Specifies that a staged value has been unloaded from the CPU +/// and now lives solely on the GPU. +pub type GpuOnly = GpuContainer; + +/// Specifies that a contiguous array of staged values has been +/// unloaded from the CPU and now lives solely on the GPU. +pub type GpuOnlyArray = GpuArrayContainer; + +/// Specifies that a staged value lives on both the CPU and GPU, +/// with the CPU value being a synchronized copy of the GPU value. +/// +/// Currently updates flow from the CPU to the GPU, but not back. +pub type GpuCpu = HybridContainer; + +/// Specifies that a contiguous array of staged values lives on both +/// the CPU and GPU, with the CPU values being synchronized copies +/// of the GPU values. +/// +/// Currently updates flow from the CPU to the GPU, but not back. +pub type GpuCpuArray = HybridArrayContainer; diff --git a/crates/renderling/src/tuple.rs b/crates/renderling/src/types/tuple.rs similarity index 100% rename from crates/renderling/src/tuple.rs rename to crates/renderling/src/types/tuple.rs diff --git a/crates/renderling/src/ui/cpu.rs b/crates/renderling/src/ui/cpu.rs index e27b4d68..48ed0781 100644 --- a/crates/renderling/src/ui/cpu.rs +++ b/crates/renderling/src/ui/cpu.rs @@ -3,14 +3,14 @@ use std::sync::{Arc, RwLock}; use crate::{ - atlas::AtlasTexture, + atlas::{AtlasTexture, TextureAddressMode, TextureModes}, camera::Camera, geometry::Geometry, - stage::{NestedTransform, RenderletDescriptor, Stage}, - transform::TransformDescriptor, + stage::{RenderletDescriptor, Stage}, + transform::{NestedTransform, TransformDescriptor}, Context, }; -use craballoc::prelude::{Hybrid, SourceId}; +use craballoc::prelude::SourceId; use crabslab::Id; use glam::{Quat, UVec2, Vec2, Vec3Swizzles, Vec4}; use glyph_brush::ab_glyph; @@ -74,72 +74,60 @@ pub struct ImageId(usize); #[derive(Clone, Debug)] pub struct UiTransform { transform: NestedTransform, - renderlet_ids: Arc>>, } impl UiTransform { pub(crate) fn id(&self) -> Id { - self.transform.global_transform_id() + self.transform.global_id() } pub fn set_translation(&self, t: Vec2) { - self.transform.modify(|a| { - a.translation.x = t.x; - a.translation.y = t.y; + self.transform.modify_translation(|a| { + a.x = t.x; + a.y = t.y; }); } pub fn get_translation(&self) -> Vec2 { - let t = self.transform.get(); - t.translation.xy() + self.transform.translation().xy() } pub fn set_rotation(&self, radians: f32) { let rotation = Quat::from_rotation_z(radians); - self.transform.modify(|t| { - t.rotation *= rotation; + // TODO: check to see if *= rotation makes sense here + self.transform.modify_rotation(|t| { + *t = *t * rotation; }); } pub fn get_rotation(&self) -> f32 { - self.transform - .get() - .rotation - .to_euler(glam::EulerRot::XYZ) - .2 + self.transform.rotation().to_euler(glam::EulerRot::XYZ).2 } pub fn set_z(&self, z: f32) { - self.transform.modify(|t| { - t.translation.z = z; + self.transform.modify_translation(|t| { + t.z = z; }); } pub fn get_z(&self) -> f32 { - self.transform.get().translation.z + self.transform.translation().z } } #[derive(Clone)] #[repr(transparent)] -pub struct UiImage(Hybrid); +pub struct UiImage(AtlasTexture); /// A 2d user interface renderer. /// /// Clones of `Ui` all point to the same data. #[derive(Clone)] pub struct Ui { - camera: Hybrid, + camera: Camera, stage: Stage, images: Arc>>, fonts: Arc>>, - // We keep a list of transforms that we use to "manually" order renderlets. - // - // This is required because interface elements have transparency. - // - // The `usize` key here is the update source notifier index, which is needed - // to re-order after any transform performs an update. - transforms: Arc>>, default_stroke_options: Arc>, default_fill_options: Arc>, } @@ -154,13 +142,13 @@ impl Ui { .with_bloom(false) .with_msaa_sample_count(4) .with_frustum_culling(false); - let camera = stage.new_camera(Camera::default_ortho2d(x as f32, y as f32)); + let (proj, view) = crate::camera::default_ortho2d(x as f32, y as f32); + let camera = stage.new_camera().with_projection_and_view(proj, view); Ui { camera, stage, images: Default::default(), fonts: Default::default(), - transforms: Default::default(), default_stroke_options: Default::default(), default_fill_options: Default::default(), } @@ -225,17 +213,9 @@ impl Ui { self } - fn new_transform(&self, renderlet_ids: Vec>) -> UiTransform { + fn new_transform(&self) -> UiTransform { let transform = self.stage.new_nested_transform(); - let transform = UiTransform { - transform, - renderlet_ids: Arc::new(renderlet_ids), - }; - self.transforms - .write() - .unwrap() - .insert(transform.transform.get_notifier_index(), transform.clone()); - transform + UiTransform { transform } } pub fn new_path(&self) -> UiPathBuilder { @@ -266,7 +246,7 @@ impl Ui { self.fonts.read().unwrap().clone() } - pub fn get_camera(&self) -> &Hybrid { + pub fn get_camera(&self) -> &Camera { &self.camera } @@ -284,9 +264,9 @@ impl Ui { .context(StageSnafu)? .pop() .unwrap(); - entry.modify(|t| { - t.modes.s = crate::atlas::TextureAddressMode::Repeat; - t.modes.t = crate::atlas::TextureAddressMode::Repeat; + entry.set_modes(TextureModes { + s: TextureAddressMode::Repeat, + t: TextureAddressMode::Repeat, }); let mut guard = self.images.write().unwrap(); let id = guard.len(); @@ -299,44 +279,14 @@ impl Ui { } fn reorder_renderlets(&self) { - // UNWRAP: panic on purpose - let guard = self.transforms.read().unwrap(); - let mut transforms = guard.values().collect::>(); - transforms.sort_by(|a, b| { - let ta = a.transform.get_global_transform(); - let tb = b.transform.get_global_transform(); - ta.translation.z.total_cmp(&tb.translation.z) + self.stage.sort_renderlets(|a, b| { + let za = a.transform.map(|t| t.translation.z).unwrap_or_default(); + let zb = b.transform.map(|t| t.translation.z).unwrap_or_default(); + za.total_cmp(&zb) }); - self.stage.reorder_renderlets( - transforms - .iter() - .flat_map(|t| t.renderlet_ids.as_ref().clone()), - ); } pub fn render(&self, view: &wgpu::TextureView) { - let mut should_reorder = false; - // UNWRAP: panic on purpose - let mut transforms = self.transforms.write().unwrap(); - let geometry: &Geometry = self.stage.as_ref(); - for update_id in geometry - .slab_allocator() - .get_updated_source_ids() - .into_iter() - { - if let Some(ui_transform) = transforms.get(&update_id) { - if Arc::strong_count(&ui_transform.renderlet_ids) == 1 { - let _ = transforms.remove(&update_id); - } else { - should_reorder = true; - } - } - } - drop(transforms); - if should_reorder { - log::trace!("a ui transform changed, sorting the renderlets"); - self.reorder_renderlets(); - } self.stage.render(view); } } diff --git a/crates/renderling/src/ui/cpu/path.rs b/crates/renderling/src/ui/cpu/path.rs index 687afd5d..95394bca 100644 --- a/crates/renderling/src/ui/cpu/path.rs +++ b/crates/renderling/src/ui/cpu/path.rs @@ -1,9 +1,7 @@ //! Path and builder. //! //! Path colors are sRGB. -use crate::{geometry::Vertex, material::MaterialDescriptor, stage::RenderletDescriptor}; -use craballoc::prelude::{GpuArray, Hybrid}; -use crabslab::Id; +use crate::{geometry::Vertex, material::Material, stage::Renderlet}; use glam::{Vec2, Vec3, Vec3Swizzles, Vec4}; use lyon::{ path::traits::PathBuilder, @@ -16,11 +14,9 @@ use super::{ImageId, Ui, UiTransform}; pub use lyon::tessellation::{LineCap, LineJoin}; pub struct UiPath { - pub vertices: GpuArray, - pub indices: GpuArray, pub transform: UiTransform, - pub material: Hybrid, - pub renderlet: Hybrid, + pub material: Material, + pub renderlet: Renderlet, } #[derive(Clone, Copy)] @@ -346,23 +342,18 @@ impl UiPathBuilder { let l_path = self.inner.build(); let mut geometry = VertexBuffers::::new(); let mut tesselator = FillTessellator::new(); - + let material = self.ui.stage.new_material(); let mut size = Vec2::ONE; - let albedo_texture_id = if let Some(ImageId(index)) = options.image_id { + // If we have an image use it in the material + if let Some(ImageId(index)) = options.image_id { if let Some(image) = self.ui.get_image(index) { - let tex = image.0.get(); - log::debug!("size: {}", tex.size_px); - size.x = tex.size_px.x as f32; - size.y = tex.size_px.y as f32; - image.0.id() - } else { - Id::NONE + let size_px = image.0.descriptor().size_px; + log::debug!("size: {}", size_px); + size.x = size_px.x as f32; + size.y = size_px.y as f32; + material.set_albedo_texture(&image.0); } - } else { - log::debug!("no image"); - Id::NONE - }; - + } tesselator .tessellate_path( l_path.as_slice(), @@ -383,28 +374,27 @@ impl UiPathBuilder { }), ) .unwrap(); - let (vertices, indices, material, renderlet) = self + let vertices = self .ui .stage - .builder() - .with_vertices(std::mem::take(&mut geometry.vertices)) - .with_indices( - std::mem::take(&mut geometry.indices) - .into_iter() - .map(|u| u as u32), - ) - .with_material(MaterialDescriptor { - albedo_texture_id, - ..Default::default() - }) - .build(); + .new_vertices(std::mem::take(&mut geometry.vertices)); + let indices = self.ui.stage.new_indices( + std::mem::take(&mut geometry.indices) + .into_iter() + .map(|u| u as u32), + ); - let transform = self.ui.new_transform(vec![renderlet.id()]); - renderlet.modify(|r| r.transform_id = transform.id()); + let transform = self.ui.new_transform(); + let renderlet = self + .ui + .stage + .new_renderlet() + .with_vertices(&vertices) + .with_indices(&indices) + .with_material(&material) + .with_transform(&transform.transform); UiPath { - vertices: vertices.into_gpu_only(), - indices: indices.into_gpu_only(), transform, material, renderlet, @@ -430,23 +420,18 @@ impl UiPathBuilder { .with_line_cap(line_cap) .with_line_join(line_join) .with_line_width(line_width); - + let material = self.ui.stage.new_material(); let mut size = Vec2::ONE; - let albedo_texture_id = if let Some(ImageId(index)) = image_id { + // If we have an image, use it in the material + if let Some(ImageId(index)) = image_id { if let Some(image) = self.ui.get_image(index) { - let tex = image.0.get(); - log::debug!("size: {}", tex.size_px); - size.x = tex.size_px.x as f32; - size.y = tex.size_px.y as f32; - image.0.id() - } else { - Id::NONE + let size_px = image.0.descriptor.get().size_px; + log::debug!("size: {}", size_px); + size.x = size_px.x as f32; + size.y = size_px.y as f32; + material.set_albedo_texture(&image.0); } - } else { - log::debug!("no image"); - Id::NONE - }; - + } tesselator .tessellate_path( l_path.as_slice(), @@ -467,28 +452,25 @@ impl UiPathBuilder { }), ) .unwrap(); - let (vertices, indices, material, renderlet) = self + let vertices = self .ui .stage - .builder() - .with_vertices(std::mem::take(&mut geometry.vertices)) - .with_indices( - std::mem::take(&mut geometry.indices) - .into_iter() - .map(|u| u as u32), - ) - .with_material(MaterialDescriptor { - albedo_texture_id, - ..Default::default() - }) - .build(); - - let transform = self.ui.new_transform(vec![renderlet.id()]); - renderlet.modify(|r| r.transform_id = transform.id()); - + .new_vertices(std::mem::take(&mut geometry.vertices)); + let indices = self.ui.stage.new_indices( + std::mem::take(&mut geometry.indices) + .into_iter() + .map(|u| u as u32), + ); + let transform = self.ui.new_transform(); + let renderlet = self + .ui + .stage + .new_renderlet() + .with_vertices(vertices) + .with_indices(indices) + .with_transform(&transform.transform) + .with_material(&material); UiPath { - vertices: vertices.into_gpu_only(), - indices: indices.into_gpu_only(), transform, material, renderlet, diff --git a/crates/renderling/src/ui/cpu/text.rs b/crates/renderling/src/ui/cpu/text.rs index fd6a0203..37a67af8 100644 --- a/crates/renderling/src/ui/cpu/text.rs +++ b/crates/renderling/src/ui/cpu/text.rs @@ -8,35 +8,30 @@ use std::{ }; use ab_glyph::Rect; -use craballoc::prelude::{GpuArray, Hybrid}; use glam::{Vec2, Vec4}; use glyph_brush::*; pub use ab_glyph::FontArc; pub use glyph_brush::{Section, Text}; -use crate::{ - atlas::AtlasTexture, geometry::Vertex, material::MaterialDescriptor, stage::RenderletDescriptor, -}; +use crate::{atlas::AtlasTexture, geometry::Vertex, material::Material, stage::Renderlet}; use image::{DynamicImage, GenericImage, ImageBuffer, Luma, Rgba}; use super::{Ui, UiTransform}; // TODO: make UiText able to be updated without fully destroying it -#[derive(Debug)] pub struct UiText { pub cache: GlyphCache, - pub vertices: GpuArray, pub transform: UiTransform, - pub texture: Hybrid, - pub material: Hybrid, - pub renderlet: Hybrid, + pub texture: AtlasTexture, + pub material: Material, + pub renderlet: Renderlet, pub bounds: (Vec2, Vec2), } pub struct UiTextBuilder { ui: Ui, - material: MaterialDescriptor, + material: Material, bounds: (Vec2, Vec2), brush: GlyphBrush>, } @@ -45,14 +40,14 @@ impl UiTextBuilder { pub fn new(ui: &Ui) -> Self { Self { ui: ui.clone(), - material: MaterialDescriptor::default(), + material: ui.stage.new_material(), brush: GlyphBrushBuilder::using_fonts(ui.get_fonts()).build(), bounds: (Vec2::ZERO, Vec2::ZERO), } } pub fn set_color(&mut self, color: impl Into) -> &mut Self { - self.material.albedo_factor = color.into(); + self.material.set_albedo_factor(color.into()); self } @@ -84,7 +79,7 @@ impl UiTextBuilder { pub fn build(self) -> UiText { let UiTextBuilder { ui, - mut material, + material, bounds, brush, } = self; @@ -104,22 +99,18 @@ impl UiTextBuilder { // UNWRAP: panic on purpose let entry = ui.stage.add_images(Some(img)).unwrap().pop().unwrap(); - log::trace!("ui text texture: {entry:#?}"); - material.albedo_texture_id = entry.id(); - - let (vertices, material, renderlet) = ui + material.set_albedo_texture(&entry); + let vertices = ui.stage.new_vertices(mesh); + let transform = ui.new_transform(); + let renderlet = ui .stage - .builder() - .with_vertices(mesh) - .with_material(material) - .build(); - let transform = ui.new_transform(vec![renderlet.id()]); - renderlet.modify(|r| r.transform_id = transform.id()); - + .new_renderlet() + .with_vertices(vertices) + .with_transform(&transform.transform) + .with_material(&material); UiText { cache, bounds, - vertices: vertices.into_gpu_only(), transform, texture: entry, material, diff --git a/crates/renderling/tests/wasm.rs b/crates/renderling/tests/wasm.rs index 838f7e93..e16d5cd0 100644 --- a/crates/renderling/tests/wasm.rs +++ b/crates/renderling/tests/wasm.rs @@ -1008,7 +1008,10 @@ async fn can_render_hello_triangle() { // This is a wasm version of cmy_triangle_sanity let ctx = Context::try_new_headless(100, 100, None).await.unwrap(); let stage = ctx.new_stage().with_background_color(Vec4::splat(1.0)); - let _camera = stage.new_camera(Camera::default_ortho2d(100.0, 100.0)); + let (projection, view) = renderling::camera::default_ortho2d(100.0, 100.0); + let _camera = stage + .new_camera() + .with_projection_and_view(projection, view); let _rez = stage.builder().with_vertices(right_tri_vertices()).build(); let frame = ctx.get_next_frame().unwrap(); From 425203440acba09d1d310c5355a4ae35e83ef324 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 8 Sep 2025 13:17:30 +1200 Subject: [PATCH 05/31] remove SceneBuilder --- crates/renderling/src/bloom/cpu.rs | 5 +- crates/renderling/src/stage/cpu.rs | 125 +-------------------------- crates/renderling/src/types.rs | 2 - crates/renderling/src/types/tuple.rs | 107 ----------------------- crates/renderling/tests/wasm.rs | 4 +- 5 files changed, 8 insertions(+), 235 deletions(-) delete mode 100644 crates/renderling/src/types/tuple.rs diff --git a/crates/renderling/src/bloom/cpu.rs b/crates/renderling/src/bloom/cpu.rs index 9b43eb0a..8c43ba9e 100644 --- a/crates/renderling/src/bloom/cpu.rs +++ b/crates/renderling/src/bloom/cpu.rs @@ -701,7 +701,7 @@ impl Bloom { mod test { use glam::Vec3; - use crate::{camera::CameraDescriptor, test::BlockOnFuture, Context}; + use crate::{test::BlockOnFuture, Context}; use super::*; @@ -749,9 +749,6 @@ mod test { let height = 128; let ctx = Context::headless(width, height).block(); let stage = ctx.new_stage().with_bloom(false); - // .with_frustum_culling(false) - // .with_occlusion_culling(false); - let projection = crate::camera::perspective(width as f32, height as f32); let view = crate::camera::look_at(Vec3::new(0.0, 2.0, 18.0), Vec3::ZERO, Vec3::Y); let _camera = stage diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index 57083d06..f0ebd754 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -649,11 +649,6 @@ impl Stage { &self.runtime().queue } - /// Create a new [`SceneBuilder`] to help bundle staged resources. - pub fn builder(&self) -> SceneBuilder<'_, ()> { - SceneBuilder::new(self) - } - pub fn hdr_texture(&self) -> impl Deref + '_ { self.hdr_texture.read().unwrap() } @@ -1424,117 +1419,6 @@ impl Stage { } } -/// A wrapper around [`Stage`] that builds up tuples of staged resources. -/// -/// [`SceneBuilder`] implements a builder pattern that allows you to -/// build up tuples of resources like [`Vertices`], [`Indices`], -/// [`MorphTargets`] and [`MorphTargetWeights`]. -// TODO: documentation example -pub struct SceneBuilder<'a, T> { - stage: &'a Stage, - resources: T, -} - -impl<'a> SceneBuilder<'a, ()> { - pub fn new(stage: &'a Stage) -> Self { - SceneBuilder { - resources: (), - stage, - } - } -} - -impl<'a, T: crate::types::tuple::Bundle> SceneBuilder<'a, T> { - pub fn suffix(self, element: S) -> SceneBuilder<'a, T::Suffixed> { - SceneBuilder { - resources: self.resources.suffix(element), - stage: self.stage, - } - } - - /// Stage vertex data and add it to the resource bundle. - pub fn with_vertices( - self, - vertices: impl IntoIterator, - ) -> SceneBuilder<'a, T::Suffixed> { - let vertices = self.stage.geometry.new_vertices(vertices); - self.suffix(vertices) - } - - /// Stage vertex index data and add it to the resource bundle. - pub fn with_indices( - self, - indices: impl IntoIterator, - ) -> SceneBuilder<'a, T::Suffixed> { - let indices = self.stage.geometry.new_indices(indices); - self.suffix(indices) - } - - /// Stage morph target weights and add them to the resource bundle. - pub fn with_morph_targets( - self, - morph_targets: impl IntoIterator>, - ) -> SceneBuilder<'a, T::Suffixed> { - let ts = self.stage.geometry.new_morph_targets(morph_targets); - self.suffix(ts) - } - - /// Stage morph target weights and add them to the resource bundle. - pub fn with_morph_target_weights( - self, - morph_weights: impl IntoIterator, - ) -> SceneBuilder<'a, T::Suffixed> { - let ws = self.stage.new_morph_target_weights(morph_weights); - self.suffix(ws) - } - - /// Stage morph target weights and add them to the resource bundle. - pub fn with_skin( - self, - joints: impl IntoIterator>, - inverse_bind_matrices: impl IntoIterator>, - ) -> SceneBuilder<'a, T::Suffixed> { - let s = self.stage.new_skin(joints, inverse_bind_matrices); - self.suffix(s) - } - - /// Stage images and add them to the resource bundle, if possible. - /// - /// # Errors - /// Returns an error if the images could not be packed into the [`Atlas`]. - pub fn with_images( - self, - images: impl IntoIterator>, - ) -> Result>>, StageError> { - let i = self.stage.add_images(images)?; - Ok(self.suffix(i)) - } - - /// Stage one image and add it to the resource bundle, if possible. - /// - /// # Note - /// Each time the set of staged images changes, the [`Atlas`] must be repacked. - /// For this reason it is runtime-quicker to batch add as many images at once - /// as is possible. Consider using [`SceneBuilder::with_images`] instead. - /// - /// # Errors - /// Returns an error if the images could not be packed into the [`Atlas`]. - pub fn with_image( - self, - image: impl Into, - ) -> Result>, StageError> { - let mut i = self.stage.add_images(Some(image))?; - // UNWRAP: safe because we know there is _exactly_ one in there - Ok(self.suffix(i.pop().unwrap())) - } - - /// Consume the [`SceneBuilder`] and return the bundled resources as a tuple, - /// in the order they were accumulated. - pub fn build(self) -> T::Reduced { - self.resources.reduce() - } -} - #[cfg(test)] mod test { use craballoc::runtime::CpuRuntime; @@ -1616,9 +1500,8 @@ mod test { let _camera = stage .new_camera() .with_projection_and_view(projection, view); - let _triangle_rez = stage - .builder() - .with_vertices([ + let _triangle_rez = stage.new_renderlet().with_vertices( + stage.new_vertices([ Vertex::default() .with_position([10.0, 10.0, 0.0]) .with_color([0.0, 1.0, 1.0, 1.0]), @@ -1628,8 +1511,8 @@ mod test { Vertex::default() .with_position([90.0, 10.0, 0.0]) .with_color([1.0, 0.0, 1.0, 1.0]), - ]) - .build(); + ]), + ); log::debug!("rendering without msaa"); let frame = ctx.get_next_frame().unwrap(); diff --git a/crates/renderling/src/types.rs b/crates/renderling/src/types.rs index f7489b33..41799c57 100644 --- a/crates/renderling/src/types.rs +++ b/crates/renderling/src/types.rs @@ -2,8 +2,6 @@ use craballoc::value::{GpuArrayContainer, GpuContainer, HybridArrayContainer, HybridContainer}; -pub mod tuple; - /// Specifies that a staged value has been unloaded from the CPU /// and now lives solely on the GPU. pub type GpuOnly = GpuContainer; diff --git a/crates/renderling/src/types/tuple.rs b/crates/renderling/src/types/tuple.rs deleted file mode 100644 index c4316b35..00000000 --- a/crates/renderling/src/types/tuple.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! Traits for preforming type-level operations on tuples. -//! -//! The traits are used for "smart" builders to organize return types. - -pub trait Bundle { - type Prefixed; - type Suffixed; - type Reduced; - - fn prefix(self, element: T) -> Self::Prefixed; - fn suffix(self, element: T) -> Self::Suffixed; - fn reduce(self) -> Self::Reduced; -} - -impl Bundle for () { - type Prefixed = (T,); - type Suffixed = (T,); - type Reduced = (); - - fn prefix(self, element: B) -> Self::Prefixed { - (element,) - } - - fn suffix(self, element: B) -> Self::Suffixed { - (element,) - } - - fn reduce(self) -> Self::Reduced { - self - } -} - -impl Bundle for (A,) { - type Prefixed = (B, A); - type Suffixed = (A, B); - type Reduced = A; - - fn prefix(self, element: B) -> Self::Prefixed { - (element, self.0) - } - - fn suffix(self, element: B) -> Self::Suffixed { - (self.0, element) - } - - fn reduce(self) -> Self::Reduced { - self.0 - } -} - -macro_rules! suffix { - ($($i:ident),*) => { - #[allow(non_snake_case)] - impl<$($i),*> Bundle for ($($i),*) { - type Prefixed = (T, $($i),*); - type Suffixed = ($($i),*, T); - type Reduced = Self; - - fn prefix(self, element: T) -> Self::Prefixed { - let ($($i),*) = self; - (element, $($i),*) - } - - fn suffix(self, element: T) -> Self::Suffixed { - let ($($i),*) = self; - ($($i),*, element) - } - - fn reduce(self) -> Self::Reduced { - self - } - } - }; -} - -suffix!(A, B); -suffix!(A, B, C); -suffix!(A, B, C, D); -suffix!(A, B, C, D, E); -suffix!(A, B, C, D, E, F); -suffix!(A, B, C, D, E, F, G); -suffix!(A, B, C, D, E, F, G, H); -suffix!(A, B, C, D, E, F, G, H, I); -suffix!(A, B, C, D, E, F, G, H, I, J); -suffix!(A, B, C, D, E, F, G, H, I, J, K); -suffix!(A, B, C, D, E, F, G, H, I, J, K, L); -suffix!(A, B, C, D, E, F, G, H, I, J, K, L, M); -suffix!(A, B, C, D, E, F, G, H, I, J, K, L, M, N); -suffix!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); -suffix!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P); - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn sanity() { - let bundle = (); - let bundle: (f32,) = bundle.suffix(0.0); - let bundle: (f32, u32) = bundle.suffix(0u32); - let bundle: (f32, u32, char) = bundle.suffix('c'); - let _bundle: (&str, f32, u32, char) = bundle.prefix("blah"); - - let bundle: (&str,) = ("hello",); - let _bundle: &str = bundle.reduce(); - } -} diff --git a/crates/renderling/tests/wasm.rs b/crates/renderling/tests/wasm.rs index e16d5cd0..d53d096e 100644 --- a/crates/renderling/tests/wasm.rs +++ b/crates/renderling/tests/wasm.rs @@ -1012,7 +1012,9 @@ async fn can_render_hello_triangle() { let _camera = stage .new_camera() .with_projection_and_view(projection, view); - let _rez = stage.builder().with_vertices(right_tri_vertices()).build(); + let _rez = stage + .new_renderlet() + .with_vertices(stage.new_vertices(right_tri_vertices())); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); From ebc0f1e9ca0378bfe7e6f39025d8cc734a273043 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 8 Sep 2025 14:03:05 +1200 Subject: [PATCH 06/31] NestedTransform needs to be marked dirty after update --- crates/renderling/src/draw/cpu.rs | 18 +----- crates/renderling/src/lib.rs | 8 +-- crates/renderling/src/light/cpu/test.rs | 4 +- crates/renderling/src/stage.rs | 14 ++--- crates/renderling/src/stage/cpu.rs | 16 ++--- crates/renderling/src/stage/cpu/renderlet.rs | 32 +--------- crates/renderling/src/stage/gltf_support.rs | 13 ++-- .../src/stage/gltf_support/anime.rs | 6 +- crates/renderling/src/transform/cpu.rs | 62 +++++++++---------- crates/renderling/src/ui/cpu.rs | 29 +++++---- 10 files changed, 78 insertions(+), 124 deletions(-) diff --git a/crates/renderling/src/draw/cpu.rs b/crates/renderling/src/draw/cpu.rs index 448ae6d2..4d85d4e1 100644 --- a/crates/renderling/src/draw/cpu.rs +++ b/crates/renderling/src/draw/cpu.rs @@ -8,7 +8,7 @@ use crabslab::Id; use crate::{ cull::{ComputeCulling, CullingError}, - stage::{Renderlet, RenderletDescriptor, RenderletSortItem}, + stage::{Renderlet, RenderletDescriptor}, texture::Texture, Context, }; @@ -182,25 +182,13 @@ impl DrawCalls { } /// Sort draw calls using a function compairing [`RenderletSortItem`]s. - pub fn sort_renderlets( - &mut self, - f: impl Fn(&RenderletSortItem, &RenderletSortItem) -> std::cmp::Ordering, - ) { - self.renderlets.sort_by(|a, b| { - let a = a.sort_item(); - let b = b.sort_item(); - f(&a, &b) - }); + pub fn sort_renderlets(&mut self, f: impl Fn(&Renderlet, &Renderlet) -> std::cmp::Ordering) { + self.renderlets.sort_by(f); if let Some(indirect) = &mut self.drawing_strategy.indirect { indirect.invalidate(); } } - /// Return an iterator over all sort items. - pub fn sort_items(&self) -> impl Iterator + '_ { - self.renderlets.iter().map(Renderlet::sort_item) - } - /// Returns the number of draw calls (direct or indirect) that will be /// made during pre-rendering (compute culling) and rendering. pub fn draw_count(&self) -> usize { diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index ba57b150..5b444521 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -955,18 +955,18 @@ mod test { let root_node = stage .new_nested_transform() - .with_scale(Vec3::new(25.0, 25.0, 1.0)); + .with_local_scale(Vec3::new(25.0, 25.0, 1.0)); println!("root_node: {:#?}", root_node.global_descriptor()); let offset = Vec3::new(1.0, 1.0, 0.0); - let cyan_node = stage.new_nested_transform().with_translation(offset); + let cyan_node = stage.new_nested_transform().with_local_translation(offset); println!("cyan_node: {:#?}", cyan_node.global_descriptor()); - let yellow_node = stage.new_nested_transform().with_translation(offset); + let yellow_node = stage.new_nested_transform().with_local_translation(offset); println!("yellow_node: {:#?}", yellow_node.global_descriptor()); - let red_node = stage.new_nested_transform().with_translation(offset); + let red_node = stage.new_nested_transform().with_local_translation(offset); println!("red_node: {:#?}", red_node.global_descriptor()); root_node.add_child(&cyan_node); diff --git a/crates/renderling/src/light/cpu/test.rs b/crates/renderling/src/light/cpu/test.rs index d5ed48ce..cdaff6cd 100644 --- a/crates/renderling/src/light/cpu/test.rs +++ b/crates/renderling/src/light/cpu/test.rs @@ -995,7 +995,7 @@ fn pedestal() { { log::info!("adding point light with nested transform"); let transform = stage.new_nested_transform(); - transform.set_translation(position); + transform.set_local_translation(position); let point_light = stage.new_analytical_light(PointLightDescriptor { position: Vec3::ZERO, @@ -1058,7 +1058,7 @@ fn pedestal() { log::info!("adding spot light with node position"); let node_transform = stage.new_nested_transform(); - node_transform.set_translation(position); + node_transform.set_local_translation(position); let spot_desc = SpotLightDescriptor { position: Vec3::ZERO, diff --git a/crates/renderling/src/stage.rs b/crates/renderling/src/stage.rs index 6f00fb70..de457058 100644 --- a/crates/renderling/src/stage.rs +++ b/crates/renderling/src/stage.rs @@ -374,11 +374,11 @@ mod test { let slab = SlabAllocator::new(CpuRuntime, "transform", ()); let a = NestedTransform::new(&slab); - a.set_translation(Vec3::splat(100.0)); + a.set_local_translation(Vec3::splat(100.0)); let b = NestedTransform::new(&slab); - b.set_rotation(Quat::from_scaled_axis(Vec3::Z)); + b.set_local_rotation(Quat::from_scaled_axis(Vec3::Z)); let c = NestedTransform::new(&slab); - c.set_scale(Vec3::splat(2.0)); + c.set_local_scale(Vec3::splat(2.0)); a.add_child(&b); b.add_child(&c); @@ -392,14 +392,14 @@ mod test { let legacy_transform = legacy_get_world_transform(&c); assert_eq!(legacy_transform, global_transform); - c.set_translation(Vec3::ONE); + c.set_local_translation(Vec3::ONE); let all_updates = slab.get_updated_source_ids(); assert_eq!( std::collections::HashSet::from_iter([ - a.get_notifier_index(), - b.get_notifier_index(), - c.get_notifier_index() + a.global_transform.descriptor.notifier_index(), + b.global_transform.descriptor.notifier_index(), + c.global_transform.descriptor.notifier_index() ]), all_updates ); diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index f0ebd754..c7628f71 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -1271,21 +1271,12 @@ impl Stage { /// Sort the drawing order of renderlets. /// /// This determines the order in which [`Renderlet`]s are drawn each frame. - pub fn sort_renderlets( - &self, - f: impl Fn(&RenderletSortItem, &RenderletSortItem) -> std::cmp::Ordering, - ) { + pub fn sort_renderlets(&self, f: impl Fn(&Renderlet, &Renderlet) -> std::cmp::Ordering) { // UNWRAP: panic on purpose let mut guard = self.draw_calls.write().unwrap(); guard.sort_renderlets(f); } - /// Returns the sort items of all staged [`Renderlet`]s. - pub fn renderlet_sort_items(&self) -> Vec { - // UNWRAP: panic on purpose - self.draw_calls.read().unwrap().sort_items().collect() - } - /// Returns a clone of the current depth texture. pub fn get_depth_texture(&self) -> DepthTexture { DepthTexture { @@ -1471,8 +1462,9 @@ mod test { let slab = SlabAllocator::::new(&CpuRuntime, "transform", ()); // Setup a hierarchy of transforms let root = NestedTransform::new(&slab); - let child = NestedTransform::new(&slab).with_translation(Vec3::new(1.0, 0.0, 0.0)); - let grandchild = NestedTransform::new(&slab).with_translation(Vec3::new(1.0, 0.0, 0.0)); + let child = NestedTransform::new(&slab).with_local_translation(Vec3::new(1.0, 0.0, 0.0)); + let grandchild = + NestedTransform::new(&slab).with_local_translation(Vec3::new(1.0, 0.0, 0.0)); log::info!("hierarchy"); // Build the hierarchy root.add_child(&child); diff --git a/crates/renderling/src/stage/cpu/renderlet.rs b/crates/renderling/src/stage/cpu/renderlet.rs index 09579d33..0e55539c 100644 --- a/crates/renderling/src/stage/cpu/renderlet.rs +++ b/crates/renderling/src/stage/cpu/renderlet.rs @@ -9,19 +9,12 @@ use crabslab::{Array, Id}; use crate::{ bvol::BoundingSphere, geometry::{Indices, MorphTargetWeights, MorphTargets, Skin, Vertices}, - material::{Material, MaterialDescriptor}, + material::Material, stage::RenderletDescriptor, - transform::{Transform, TransformDescriptor}, + transform::Transform, types::GpuOnlyArray, }; -/// Used to sort renderlet draw calls. -pub struct RenderletSortItem { - pub descriptor: RenderletDescriptor, - pub transform: Option, - pub material: Option, -} - /// A unit of rendering. /// /// A `Renderlet` represents one draw call, or one mesh primitive. @@ -60,27 +53,6 @@ impl Renderlet { stage.add_renderlet(&renderlet); renderlet } - - /// Return a struct that can be used to order a [`Renderlet`] relative to others. - pub fn sort_item(&self) -> RenderletSortItem { - let transform = self - .transform - .lock() - .unwrap() - .as_ref() - .map(|t| t.descriptor()); - let material = self - .material - .lock() - .unwrap() - .as_ref() - .map(|m| m.descriptor()); - RenderletSortItem { - descriptor: self.descriptor.get(), - transform, - material, - } - } } impl Clone for Renderlet { diff --git a/crates/renderling/src/stage/gltf_support.rs b/crates/renderling/src/stage/gltf_support.rs index f496fbd7..432e6e8b 100644 --- a/crates/renderling/src/stage/gltf_support.rs +++ b/crates/renderling/src/stage/gltf_support.rs @@ -212,6 +212,8 @@ impl Material { let builder = stage.new_material(); if material.unlit() { log::trace!(" is unlit"); + builder.set_has_lighting(false); + if let Some(info) = pbr.base_color_texture() { let texture = info.texture(); let index = texture.index(); @@ -223,8 +225,8 @@ impl Material { builder.set_albedo_factor(pbr.base_color_factor().into()); } else { log::trace!(" is pbr"); + builder.set_has_lighting(true); - builder.set_albedo_factor(pbr.base_color_factor().into()); if let Some(info) = pbr.base_color_texture() { let texture = info.texture(); let index = texture.index(); @@ -233,6 +235,7 @@ impl Material { builder.set_albedo_tex_coord(info.tex_coord()); } } + builder.set_albedo_factor(pbr.base_color_factor().into()); if let Some(info) = pbr.metallic_roughness_texture() { let index = info.texture().index(); @@ -268,8 +271,6 @@ impl Material { builder.set_emissive_tex_coord(emissive_tex.tex_coord()); } } - - builder.set_emissive_factor(Vec3::from(material.emissive_factor())); builder.set_emissive_strength_multiplier(material.emissive_strength().unwrap_or(1.0)); }; Ok(builder) @@ -863,9 +864,9 @@ impl GltfDocument { } = node.transform().into(); let transform = stage .new_nested_transform() - .with_translation(translation) - .with_rotation(rotation) - .with_scale(scale); + .with_local_translation(translation) + .with_local_rotation(rotation) + .with_local_scale(scale); for node in node.children() { let child_transform = transform_for_node(nesting_level + 1, stage, cache, &node); diff --git a/crates/renderling/src/stage/gltf_support/anime.rs b/crates/renderling/src/stage/gltf_support/anime.rs index 65cf42f2..d17c58d7 100644 --- a/crates/renderling/src/stage/gltf_support/anime.rs +++ b/crates/renderling/src/stage/gltf_support/anime.rs @@ -739,13 +739,13 @@ impl Animator { if let Some(node) = self.nodes.get(&node_index) { match property { TweenProperty::Translation(translation) => { - node.transform.set_translation(translation); + node.transform.set_local_translation(translation); } TweenProperty::Rotation(rotation) => { - node.transform.set_rotation(rotation); + node.transform.set_local_rotation(rotation); } TweenProperty::Scale(scale) => { - node.transform.set_scale(scale); + node.transform.set_local_scale(scale); } TweenProperty::MorphTargetWeights(new_weights) => { if node.morph_weights.array().is_empty() { diff --git a/crates/renderling/src/transform/cpu.rs b/crates/renderling/src/transform/cpu.rs index d2155451..00225f71 100644 --- a/crates/renderling/src/transform/cpu.rs +++ b/crates/renderling/src/transform/cpu.rs @@ -2,11 +2,7 @@ use std::sync::{Arc, RwLock}; -use craballoc::{ - runtime::IsRuntime, - slab::{SlabAllocator, SourceId}, - value::Hybrid, -}; +use craballoc::{runtime::IsRuntime, slab::SlabAllocator, value::Hybrid}; use crabslab::Id; use glam::{Mat4, Quat, Vec3}; @@ -15,7 +11,7 @@ use super::TransformDescriptor; /// A decomposed 3d transformation. #[derive(Clone)] pub struct Transform { - descriptor: Hybrid, + pub(crate) descriptor: Hybrid, } impl From<&Transform> for Transform { @@ -223,13 +219,8 @@ impl NestedTransform { nested } - /// Return the _local_ transform in combined matrix format; - pub fn as_mat4(&self) -> Mat4 { - (*self.local_transform.read().unwrap()).into() - } - /// Get the _local_ translation of the transform. - pub fn translation(&self) -> Vec3 { + pub fn local_translation(&self) -> Vec3 { self.local_transform.read().unwrap().translation } @@ -238,9 +229,11 @@ impl NestedTransform { /// # Arguments /// /// - `f`: A closure that takes a mutable reference to the translation vector and returns a value of type `T`. - pub fn modify_translation(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { + pub fn modify_local_translation(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { let mut local_transform = self.local_transform.write().unwrap(); - f(&mut local_transform.translation) + let t = f(&mut local_transform.translation); + self.mark_dirty(); + t } /// Set the _local_ translation of the transform. @@ -248,8 +241,9 @@ impl NestedTransform { /// # Arguments /// /// - `translation`: A 3d translation vector `Vec3`. - pub fn set_translation(&self, translation: impl Into) -> &Self { + pub fn set_local_translation(&self, translation: impl Into) -> &Self { self.local_transform.write().unwrap().translation = translation.into(); + self.mark_dirty(); self } @@ -258,13 +252,13 @@ impl NestedTransform { /// # Arguments /// /// - `translation`: A 3d translation vector `Vec3`. - pub fn with_translation(self, translation: impl Into) -> Self { - self.set_translation(translation); + pub fn with_local_translation(self, translation: impl Into) -> Self { + self.set_local_translation(translation); self } /// Get the _local_ rotation of the transform. - pub fn rotation(&self) -> Quat { + pub fn local_rotation(&self) -> Quat { self.local_transform.read().unwrap().rotation } @@ -273,9 +267,11 @@ impl NestedTransform { /// # Arguments /// /// - `f`: A closure that takes a mutable reference to the rotation quaternion and returns a value of type `T`. - pub fn modify_rotation(&self, f: impl FnOnce(&mut Quat) -> T) -> T { + pub fn modify_local_rotation(&self, f: impl FnOnce(&mut Quat) -> T) -> T { let mut local_transform = self.local_transform.write().unwrap(); - f(&mut local_transform.rotation) + let t = f(&mut local_transform.rotation); + self.mark_dirty(); + t } /// Set the _local_ rotation of the transform. @@ -283,8 +279,9 @@ impl NestedTransform { /// # Arguments /// /// - `rotation`: A quaternion representing the rotation. - pub fn set_rotation(&self, rotation: impl Into) -> &Self { + pub fn set_local_rotation(&self, rotation: impl Into) -> &Self { self.local_transform.write().unwrap().rotation = rotation.into(); + self.mark_dirty(); self } @@ -293,13 +290,13 @@ impl NestedTransform { /// # Arguments /// /// - `rotation`: A quaternion representing the rotation. - pub fn with_rotation(self, rotation: impl Into) -> Self { - self.set_rotation(rotation); + pub fn with_local_rotation(self, rotation: impl Into) -> Self { + self.set_local_rotation(rotation); self } /// Get the _local_ scale of the transform. - pub fn scale(&self) -> Vec3 { + pub fn local_scale(&self) -> Vec3 { self.local_transform.read().unwrap().scale } @@ -308,9 +305,11 @@ impl NestedTransform { /// # Arguments /// /// - `f`: A closure that takes a mutable reference to the scale vector and returns a value of type `T`. - pub fn modify_scale(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { + pub fn modify_local_scale(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { let mut local_transform = self.local_transform.write().unwrap(); - f(&mut local_transform.scale) + let t = f(&mut local_transform.scale); + self.mark_dirty(); + t } /// Set the _local_ scale of the transform. @@ -318,8 +317,9 @@ impl NestedTransform { /// # Arguments /// /// - `scale`: A 3d scale vector `Vec3`. - pub fn set_scale(&self, scale: impl Into) -> &Self { + pub fn set_local_scale(&self, scale: impl Into) -> &Self { self.local_transform.write().unwrap().scale = scale.into(); + self.mark_dirty(); self } @@ -328,8 +328,8 @@ impl NestedTransform { /// # Arguments /// /// - `scale`: A 3d scale vector `Vec3`. - pub fn with_scale(self, scale: impl Into) -> Self { - self.set_scale(scale); + pub fn with_local_scale(self, scale: impl Into) -> Self { + self.set_local_scale(scale); self } } @@ -360,10 +360,6 @@ impl NestedTransform { *self.local_transform.read().unwrap() } - pub(crate) fn get_notifier_index(&self) -> SourceId { - self.global_transform.descriptor.notifier_index() - } - fn mark_dirty(&self) { self.global_transform .descriptor diff --git a/crates/renderling/src/ui/cpu.rs b/crates/renderling/src/ui/cpu.rs index 48ed0781..67b85a8c 100644 --- a/crates/renderling/src/ui/cpu.rs +++ b/crates/renderling/src/ui/cpu.rs @@ -5,16 +5,13 @@ use std::sync::{Arc, RwLock}; use crate::{ atlas::{AtlasTexture, TextureAddressMode, TextureModes}, camera::Camera, - geometry::Geometry, - stage::{RenderletDescriptor, Stage}, + stage::Stage, transform::{NestedTransform, TransformDescriptor}, Context, }; -use craballoc::prelude::SourceId; use crabslab::Id; use glam::{Quat, UVec2, Vec2, Vec3Swizzles, Vec4}; use glyph_brush::ab_glyph; -use rustc_hash::FxHashMap; use snafu::{prelude::*, ResultExt}; pub use glyph_brush::FontId; @@ -82,36 +79,36 @@ impl UiTransform { } pub fn set_translation(&self, t: Vec2) { - self.transform.modify_translation(|a| { + self.transform.modify_local_translation(|a| { a.x = t.x; a.y = t.y; }); } pub fn get_translation(&self) -> Vec2 { - self.transform.translation().xy() + self.transform.local_translation().xy() } pub fn set_rotation(&self, radians: f32) { let rotation = Quat::from_rotation_z(radians); // TODO: check to see if *= rotation makes sense here - self.transform.modify_rotation(|t| { + self.transform.modify_local_rotation(|t| { *t = *t * rotation; }); } pub fn get_rotation(&self) -> f32 { - self.transform.rotation().to_euler(glam::EulerRot::XYZ).2 + self.transform.local_rotation().to_euler(glam::EulerRot::XYZ).2 } pub fn set_z(&self, z: f32) { - self.transform.modify_translation(|t| { + self.transform.modify_local_translation(|t| { t.z = z; }); } pub fn get_z(&self) -> f32 { - self.transform.translation().z + self.transform.local_translation().z } } @@ -280,8 +277,16 @@ impl Ui { fn reorder_renderlets(&self) { self.stage.sort_renderlets(|a, b| { - let za = a.transform.map(|t| t.translation.z).unwrap_or_default(); - let zb = b.transform.map(|t| t.translation.z).unwrap_or_default(); + let za = a + .transform() + .as_ref() + .map(|t| t.translation().z) + .unwrap_or_default(); + let zb = b + .transform() + .as_ref() + .map(|t| t.translation().z) + .unwrap_or_default(); za.total_cmp(&zb) }); } From 7b656b6e15ee80f48672c33a8e214d404a8cf7be Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Mon, 8 Sep 2025 14:26:06 +1200 Subject: [PATCH 07/31] fixed some more tests --- crates/renderling/src/lib.rs | 5 ++++- crates/renderling/src/transform/cpu.rs | 4 ---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index 5b444521..e7647079 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -749,7 +749,8 @@ mod test { stage .new_transform() .with_scale(Vec3::new(10.0, 10.0, 10.0)), - ); + ) + .with_material(&material); println!("cube: {:?}", cube.descriptor()); // we should see a cube with a stoney texture @@ -819,6 +820,8 @@ mod test { ..Default::default() }, ]); + let _color_prim = stage.new_renderlet().with_vertices(&geometry); + let material = stage .new_material() .with_albedo_texture(&entries[0]) diff --git a/crates/renderling/src/transform/cpu.rs b/crates/renderling/src/transform/cpu.rs index 00225f71..47af1fbe 100644 --- a/crates/renderling/src/transform/cpu.rs +++ b/crates/renderling/src/transform/cpu.rs @@ -204,8 +204,6 @@ impl From for Transform { } } -// Make the API mirror Transform - impl NestedTransform { /// Stage a new hierarchical transform on the GPU. pub(crate) fn new(slab: &SlabAllocator) -> Self { @@ -332,9 +330,7 @@ impl NestedTransform { self.set_local_scale(scale); self } -} -impl NestedTransform { /// Return a pointer to the underlying descriptor data on the GPU. /// /// The descriptor is the descriptor that describes the _global_ transform. From 8a7d52de9972aca8fed4fc1650d3285ef068fe4d Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 9 Sep 2025 08:38:08 +1200 Subject: [PATCH 08/31] fixed NestedTransform bug where modification didn't update children --- crates/renderling/src/transform/cpu.rs | 18 +++++++---- crates/renderling/src/ui/cpu.rs | 7 +++-- crates/renderling/src/ui/cpu/text.rs | 42 +++++++++++++++++++------- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/crates/renderling/src/transform/cpu.rs b/crates/renderling/src/transform/cpu.rs index 47af1fbe..55710547 100644 --- a/crates/renderling/src/transform/cpu.rs +++ b/crates/renderling/src/transform/cpu.rs @@ -228,8 +228,10 @@ impl NestedTransform { /// /// - `f`: A closure that takes a mutable reference to the translation vector and returns a value of type `T`. pub fn modify_local_translation(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { - let mut local_transform = self.local_transform.write().unwrap(); - let t = f(&mut local_transform.translation); + let t = { + let mut local_transform = self.local_transform.write().unwrap(); + f(&mut local_transform.translation) + }; self.mark_dirty(); t } @@ -266,8 +268,10 @@ impl NestedTransform { /// /// - `f`: A closure that takes a mutable reference to the rotation quaternion and returns a value of type `T`. pub fn modify_local_rotation(&self, f: impl FnOnce(&mut Quat) -> T) -> T { - let mut local_transform = self.local_transform.write().unwrap(); - let t = f(&mut local_transform.rotation); + let t = { + let mut local_transform = self.local_transform.write().unwrap(); + f(&mut local_transform.rotation) + }; self.mark_dirty(); t } @@ -304,8 +308,10 @@ impl NestedTransform { /// /// - `f`: A closure that takes a mutable reference to the scale vector and returns a value of type `T`. pub fn modify_local_scale(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { - let mut local_transform = self.local_transform.write().unwrap(); - let t = f(&mut local_transform.scale); + let t = { + let mut local_transform = self.local_transform.write().unwrap(); + f(&mut local_transform.scale) + }; self.mark_dirty(); t } diff --git a/crates/renderling/src/ui/cpu.rs b/crates/renderling/src/ui/cpu.rs index 67b85a8c..09e61177 100644 --- a/crates/renderling/src/ui/cpu.rs +++ b/crates/renderling/src/ui/cpu.rs @@ -93,12 +93,15 @@ impl UiTransform { let rotation = Quat::from_rotation_z(radians); // TODO: check to see if *= rotation makes sense here self.transform.modify_local_rotation(|t| { - *t = *t * rotation; + *t *= rotation; }); } pub fn get_rotation(&self) -> f32 { - self.transform.local_rotation().to_euler(glam::EulerRot::XYZ).2 + self.transform + .local_rotation() + .to_euler(glam::EulerRot::XYZ) + .2 } pub fn set_z(&self, z: f32) { diff --git a/crates/renderling/src/ui/cpu/text.rs b/crates/renderling/src/ui/cpu/text.rs index 37a67af8..170729df 100644 --- a/crates/renderling/src/ui/cpu/text.rs +++ b/crates/renderling/src/ui/cpu/text.rs @@ -379,6 +379,8 @@ mod test { ui.load_font("../../fonts/Recursive Mn Lnr St Med Nerd Font Complete.ttf"), ) .unwrap(); + log::info!("loaded font"); + let text1 = "Voluptas magnam sint et incidunt. Aliquam praesentium voluptas ut nemo \ laboriosam. Dicta qui et dicta."; let text2 = "Inventore impedit quo ratione ullam blanditiis soluta aliquid. Enim \ @@ -404,6 +406,7 @@ mod test { .with_bounds((400.0, f32::INFINITY)), ) .build(); + log::info!("created text"); let (fill, stroke) = ui .new_path() @@ -411,26 +414,42 @@ mod test { .with_stroke_color([1.0, 0.0, 1.0, 1.0]) .with_rectangle(text.bounds.0, text.bounds.1) .fill_and_stroke(); + log::info!("filled and stroked"); - for path in [&fill, &stroke] { + for (i, path) in [&fill, &stroke].into_iter().enumerate() { + log::info!("for {i}"); // move the path to (50, 50) path.transform.set_translation(Vec2::new(51.0, 53.0)); + log::info!("translated"); // move it to the back - path.transform.set_z(-0.1); + path.transform.set_z(0.1); + log::info!("z'd"); } + log::info!("transformed"); let frame = ctx.get_next_frame().unwrap(); ui.render(&frame.view()); + log::info!("rendered"); let img = frame.read_image().block().unwrap(); - img_diff::assert_img_eq("ui/text/overlay.png", img); - let depth_img = ui - .stage - .get_depth_texture() - .read_image() - .block() - .unwrap() - .unwrap(); - img_diff::assert_img_eq("ui/text/overlay_depth.png", depth_img); + if let Err(e) = + img_diff::assert_img_eq_cfg_result("ui/text/overlay.png", img, Default::default()) + { + let depth_img = ui + .stage + .get_depth_texture() + .read_image() + .block() + .unwrap() + .unwrap(); + let e2 = img_diff::assert_img_eq_cfg_result( + "ui/text/overlay_depth.png", + depth_img, + Default::default(), + ) + .err() + .unwrap_or_default(); + panic!("{e}\n{e2}"); + } } #[test] @@ -441,6 +460,7 @@ mod test { ui.load_font("../../fonts/Recursive Mn Lnr St Med Nerd Font Complete.ttf"), ) .unwrap(); + log::info!("loaded font"); let mut _text = ui .new_text() .with_section( From ef10942174ee11b5f59850e88b816e60ae93769f Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 9 Sep 2025 10:58:55 +1200 Subject: [PATCH 09/31] fixed ui tests, ui builder API changes --- crates/example-wasm/src/lib.rs | 5 +- crates/example/src/lib.rs | 8 +-- crates/renderling/src/light/cpu.rs | 2 +- crates/renderling/src/light/shadow_map.rs | 2 +- .../src/stage/gltf_support/anime.rs | 3 +- crates/renderling/src/ui/cpu.rs | 69 +++++++++++++++---- crates/renderling/src/ui/cpu/path.rs | 26 +++---- crates/renderling/src/ui/cpu/text.rs | 54 +++++++++------ 8 files changed, 114 insertions(+), 55 deletions(-) diff --git a/crates/example-wasm/src/lib.rs b/crates/example-wasm/src/lib.rs index 4fca3d2b..a43ea4cc 100644 --- a/crates/example-wasm/src/lib.rs +++ b/crates/example-wasm/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use glam::{Vec2, Vec4}; use renderling::{prelude::*, ui::prelude::*}; use wasm_bindgen::prelude::*; @@ -72,7 +73,7 @@ pub async fn main() { let ui = ctx.new_ui(); let path = ui - .new_path() + .path_builder() .with_circle(Vec2::splat(100.0), 20.0) .with_fill_color(Vec4::new(1.0, 1.0, 0.0, 1.0)) .fill(); @@ -81,7 +82,7 @@ pub async fn main() { .await .expect_throw("Could not load font"); let text = ui - .new_text() + .text_builder() .with_color( // white Vec4::ONE, diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index d753e265..ad6e7afa 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -84,15 +84,15 @@ impl AppUi { let translation = Vec2::new(2.0, 2.0); let text = format!("{}fps", fps_counter.current_fps_string()); let fps_text = ui - .new_text() + .text_builder() .with_color(Vec3::ZERO.extend(1.0)) .with_section(Section::new().add_text(Text::new(&text).with_scale(32.0))) .build(); - fps_text.transform.set_translation(translation); + fps_text.transform().set_translation(translation); let background = ui - .new_path() + .path_builder() .with_fill_color(Vec4::ONE) - .with_rectangle(fps_text.bounds.0, fps_text.bounds.1) + .with_rectangle(fps_text.bounds().0, fps_text.bounds().1) .fill(); background.transform.set_translation(translation); background.transform.set_z(-0.9); diff --git a/crates/renderling/src/light/cpu.rs b/crates/renderling/src/light/cpu.rs index bf1c72a7..d3446137 100644 --- a/crates/renderling/src/light/cpu.rs +++ b/crates/renderling/src/light/cpu.rs @@ -156,7 +156,7 @@ impl core::fmt::Display for AnalyticalLight { .read() .unwrap() .as_ref() - .and_then(|h| { Some(h.global_id()) }) + .map(|h| h.global_id()) )) } } diff --git a/crates/renderling/src/light/shadow_map.rs b/crates/renderling/src/light/shadow_map.rs index d22b461f..3202f7fe 100644 --- a/crates/renderling/src/light/shadow_map.rs +++ b/crates/renderling/src/light/shadow_map.rs @@ -691,7 +691,7 @@ mod test { shadows.push(shadow); } - stage.use_camera(&camera); + stage.use_camera(camera); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); diff --git a/crates/renderling/src/stage/gltf_support/anime.rs b/crates/renderling/src/stage/gltf_support/anime.rs index d17c58d7..dbde92ab 100644 --- a/crates/renderling/src/stage/gltf_support/anime.rs +++ b/crates/renderling/src/stage/gltf_support/anime.rs @@ -1,5 +1,4 @@ //! Animation helpers for gltf. -use craballoc::prelude::HybridArray; use glam::{Quat, Vec3}; use snafu::prelude::*; @@ -767,7 +766,7 @@ impl Animator { #[cfg(test)] mod test { - use crate::{camera::CameraDescriptor, stage::Animator, test::BlockOnFuture, Context}; + use crate::{stage::Animator, test::BlockOnFuture, Context}; use glam::Vec3; #[test] diff --git a/crates/renderling/src/ui/cpu.rs b/crates/renderling/src/ui/cpu.rs index 09e61177..7d5a49f3 100644 --- a/crates/renderling/src/ui/cpu.rs +++ b/crates/renderling/src/ui/cpu.rs @@ -1,17 +1,19 @@ //! CPU part of ui. +use core::sync::atomic::AtomicBool; use std::sync::{Arc, RwLock}; use crate::{ - atlas::{AtlasTexture, TextureAddressMode, TextureModes}, + atlas::{AtlasTexture, AtlasTextureDescriptor, TextureAddressMode, TextureModes}, camera::Camera, stage::Stage, - transform::{NestedTransform, TransformDescriptor}, + transform::NestedTransform, Context, }; use crabslab::Id; use glam::{Quat, UVec2, Vec2, Vec3Swizzles, Vec4}; use glyph_brush::ab_glyph; +use rustc_hash::FxHashMap; use snafu::{prelude::*, ResultExt}; pub use glyph_brush::FontId; @@ -63,22 +65,25 @@ pub enum UiError { /// `ImageId` can be created with [`Ui::load_image`]. #[repr(transparent)] #[derive(Clone, Copy, Debug)] -pub struct ImageId(usize); +pub struct ImageId(Id); /// A two dimensional transformation. /// /// Clones of `UiTransform` all point to the same data. #[derive(Clone, Debug)] pub struct UiTransform { + should_reorder: Arc, transform: NestedTransform, } impl UiTransform { - pub(crate) fn id(&self) -> Id { - self.transform.global_id() + fn mark_should_reorder(&self) { + self.should_reorder + .store(true, std::sync::atomic::Ordering::Relaxed); } pub fn set_translation(&self, t: Vec2) { + self.mark_should_reorder(); self.transform.modify_local_translation(|a| { a.x = t.x; a.y = t.y; @@ -90,6 +95,7 @@ impl UiTransform { } pub fn set_rotation(&self, radians: f32) { + self.mark_should_reorder(); let rotation = Quat::from_rotation_z(radians); // TODO: check to see if *= rotation makes sense here self.transform.modify_local_rotation(|t| { @@ -105,6 +111,7 @@ impl UiTransform { } pub fn set_z(&self, z: f32) { + self.mark_should_reorder(); self.transform.modify_local_translation(|t| { t.z = z; }); @@ -126,7 +133,8 @@ pub struct UiImage(AtlasTexture); pub struct Ui { camera: Camera, stage: Stage, - images: Arc>>, + should_reorder: Arc, + images: Arc, UiImage>>>, fonts: Arc>>, default_stroke_options: Arc>, default_fill_options: Arc>, @@ -147,6 +155,7 @@ impl Ui { Ui { camera, stage, + should_reorder: AtomicBool::new(true).into(), images: Default::default(), fonts: Default::default(), default_stroke_options: Default::default(), @@ -214,18 +223,45 @@ impl Ui { } fn new_transform(&self) -> UiTransform { + self.mark_should_reorder(); let transform = self.stage.new_nested_transform(); - UiTransform { transform } + UiTransform { + transform, + should_reorder: self.should_reorder.clone(), + } + } + + fn mark_should_reorder(&self) { + self.should_reorder + .store(true, std::sync::atomic::Ordering::Relaxed) } - pub fn new_path(&self) -> UiPathBuilder { + pub fn path_builder(&self) -> UiPathBuilder { + self.mark_should_reorder(); UiPathBuilder::new(self) } - pub fn new_text(&self) -> UiTextBuilder { + /// Remove the `path` from the [`Ui`]. + /// + /// The given `path` must have been created with this [`Ui`], otherwise this function is + /// a noop. + pub fn remove_path(&self, path: &UiPath) { + self.stage.remove_renderlet(&path.renderlet); + } + + pub fn text_builder(&self) -> UiTextBuilder { + self.mark_should_reorder(); UiTextBuilder::new(self) } + /// Remove the text from the [`Ui`]. + /// + /// The given `text` must have been created with this [`Ui`], otherwise this function is + /// a noop. + pub fn remove_text(&self, text: &UiText) { + self.stage.remove_renderlet(&text.renderlet); + } + pub async fn load_font(&self, path: impl AsRef) -> Result { let path_s = path.as_ref(); let bytes = loading_bytes::load(path_s).await.context(LoadingSnafu)?; @@ -269,13 +305,14 @@ impl Ui { t: TextureAddressMode::Repeat, }); let mut guard = self.images.write().unwrap(); - let id = guard.len(); - guard.push(UiImage(entry)); + let id = entry.id(); + guard.insert(id, UiImage(entry)); Ok(ImageId(id)) } - pub(crate) fn get_image(&self, index: usize) -> Option { - self.images.read().unwrap().get(index).cloned() + /// Remove an image previously loaded with [`Ui::load_image`]. + pub fn remove_image(&self, image_id: &ImageId) -> Option { + self.images.write().unwrap().remove(&image_id.0) } fn reorder_renderlets(&self) { @@ -295,6 +332,12 @@ impl Ui { } pub fn render(&self, view: &wgpu::TextureView) { + if self + .should_reorder + .swap(false, std::sync::atomic::Ordering::Relaxed) + { + self.reorder_renderlets(); + } self.stage.render(view); } } diff --git a/crates/renderling/src/ui/cpu/path.rs b/crates/renderling/src/ui/cpu/path.rs index 95394bca..3dfb1643 100644 --- a/crates/renderling/src/ui/cpu/path.rs +++ b/crates/renderling/src/ui/cpu/path.rs @@ -345,8 +345,9 @@ impl UiPathBuilder { let material = self.ui.stage.new_material(); let mut size = Vec2::ONE; // If we have an image use it in the material - if let Some(ImageId(index)) = options.image_id { - if let Some(image) = self.ui.get_image(index) { + if let Some(ImageId(id)) = &options.image_id { + let guard = self.ui.images.read().unwrap(); + if let Some(image) = guard.get(id) { let size_px = image.0.descriptor().size_px; log::debug!("size: {}", size_px); size.x = size_px.x as f32; @@ -423,8 +424,9 @@ impl UiPathBuilder { let material = self.ui.stage.new_material(); let mut size = Vec2::ONE; // If we have an image, use it in the material - if let Some(ImageId(index)) = image_id { - if let Some(image) = self.ui.get_image(index) { + if let Some(ImageId(id)) = &image_id { + let guard = self.ui.images.read().unwrap(); + if let Some(image) = guard.get(id) { let size_px = image.0.descriptor.get().size_px; log::debug!("size: {}", size_px); size.x = size_px.x as f32; @@ -539,7 +541,7 @@ mod test { let ctx = Context::headless(100, 100).block(); let ui = Ui::new(&ctx).with_antialiasing(false); let builder = ui - .new_path() + .path_builder() .with_fill_color([1.0, 1.0, 0.0, 1.0]) .with_stroke_color([0.0, 1.0, 1.0, 1.0]) .with_rectangle(Vec2::splat(10.0), Vec2::splat(60.0)) @@ -586,7 +588,7 @@ mod test { // rectangle let fill = colors.next_color(); let _rect = ui - .new_path() + .path_builder() .with_fill_color(fill) .with_stroke_color(hex_to_vec4(0x333333FF)) .with_rectangle(Vec2::splat(2.0), Vec2::splat(42.0)) @@ -595,7 +597,7 @@ mod test { // circle let fill = colors.next_color(); let _circ = ui - .new_path() + .path_builder() .with_fill_color(fill) .with_stroke_color(hex_to_vec4(0x333333FF)) .with_circle([64.0, 22.0], 20.0) @@ -604,7 +606,7 @@ mod test { // ellipse let fill = colors.next_color(); let _elli = ui - .new_path() + .path_builder() .with_fill_color(fill) .with_stroke_color(hex_to_vec4(0x333333FF)) .with_ellipse([104.0, 22.0], [20.0, 15.0], std::f32::consts::FRAC_PI_4) @@ -623,7 +625,7 @@ mod test { let fill = colors.next_color(); let center = Vec2::new(144.0, 22.0); let _penta = ui - .new_path() + .path_builder() .with_fill_color(fill) .with_stroke_color(hex_to_vec4(0x333333FF)) .with_polygon(true, circle_points(5, 20.0).into_iter().map(|p| p + center)) @@ -632,7 +634,7 @@ mod test { let fill = colors.next_color(); let center = Vec2::new(184.0, 22.0); let _star = ui - .new_path() + .path_builder() .with_fill_color(fill) .with_stroke_color(hex_to_vec4(0x333333FF)) .with_polygon( @@ -644,7 +646,7 @@ mod test { let fill = colors.next_color(); let tl = Vec2::new(210.0, 4.0); let _rrect = ui - .new_path() + .path_builder() .with_fill_color(fill) .with_stroke_color(hex_to_vec4(0x333333FF)) .with_rounded_rectangle(tl, tl + Vec2::new(40.0, 40.0), 5.0, 0.0, 0.0, 10.0) @@ -664,7 +666,7 @@ mod test { let image_id = futures_lite::future::block_on(ui.load_image("../../img/dirt.jpg")).unwrap(); let center = Vec2::splat(w / 2.0); let _path = ui - .new_path() + .path_builder() .with_polygon( true, star_points(7, w / 2.0, w / 3.0) diff --git a/crates/renderling/src/ui/cpu/text.rs b/crates/renderling/src/ui/cpu/text.rs index 170729df..37092388 100644 --- a/crates/renderling/src/ui/cpu/text.rs +++ b/crates/renderling/src/ui/cpu/text.rs @@ -19,16 +19,6 @@ use image::{DynamicImage, GenericImage, ImageBuffer, Luma, Rgba}; use super::{Ui, UiTransform}; -// TODO: make UiText able to be updated without fully destroying it -pub struct UiText { - pub cache: GlyphCache, - pub transform: UiTransform, - pub texture: AtlasTexture, - pub material: Material, - pub renderlet: Renderlet, - pub bounds: (Vec2, Vec2), -} - pub struct UiTextBuilder { ui: Ui, material: Material, @@ -109,16 +99,38 @@ impl UiTextBuilder { .with_transform(&transform.transform) .with_material(&material); UiText { - cache, + _cache: cache, bounds, transform, - texture: entry, - material, + _texture: entry, + _material: material, renderlet, } } } +pub struct UiText { + pub(crate) transform: UiTransform, + pub(crate) renderlet: Renderlet, + pub(crate) bounds: (Vec2, Vec2), + + pub(crate) _cache: GlyphCache, + pub(crate) _texture: AtlasTexture, + pub(crate) _material: Material, +} + +impl UiText { + /// Returns the bounds of this text. + pub fn bounds(&self) -> (Vec2, Vec2) { + self.bounds + } + + /// Returns the transform of this text. + pub fn transform(&self) -> &UiTransform { + &self.transform + } +} + /// A text cache maintained mostly by ab_glyph. pub struct Cache { img: image::ImageBuffer, Vec>, @@ -335,7 +347,7 @@ mod test { let ui = Ui::new(&ctx); let _font_id = ui.add_font(font); let _text = ui - .new_text() + .text_builder() .with_section( Section::default() .add_text( @@ -387,7 +399,7 @@ mod test { molestiae eaque ab commodi et.\nQuidem ex tempore ipsam. Incidunt suscipit \ aut commodi cum atque voluptate est."; let text = ui - .new_text() + .text_builder() .with_section( Section::default().add_text( Text::new(text1) @@ -409,7 +421,7 @@ mod test { log::info!("created text"); let (fill, stroke) = ui - .new_path() + .path_builder() .with_fill_color([1.0, 1.0, 0.0, 1.0]) .with_stroke_color([1.0, 0.0, 1.0, 1.0]) .with_rectangle(text.bounds.0, text.bounds.1) @@ -461,8 +473,8 @@ mod test { ) .unwrap(); log::info!("loaded font"); - let mut _text = ui - .new_text() + let text = ui + .text_builder() .with_section( Section::default() .add_text( @@ -481,8 +493,10 @@ mod test { img_diff::assert_img_eq("ui/text/can_recreate_0.png", img); log::info!("replacing text"); - _text = ui - .new_text() + ui.remove_text(&text); + + let _ = ui + .text_builder() .with_section( Section::default() .add_text( From 53420ccd7de52964164ba427c8707f5f09f126e2 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 9 Sep 2025 13:13:24 +1200 Subject: [PATCH 10/31] update lighting API --- crates/example/src/lib.rs | 16 +- crates/renderling/src/lib.rs | 6 +- crates/renderling/src/light.rs | 31 +- crates/renderling/src/light/cpu.rs | 822 ++++++++++++++------ crates/renderling/src/light/shadow_map.rs | 55 +- crates/renderling/src/stage/cpu.rs | 29 +- crates/renderling/src/stage/gltf_support.rs | 48 +- crates/renderling/src/transform/cpu.rs | 2 +- 8 files changed, 696 insertions(+), 313 deletions(-) diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index ad6e7afa..6cf8371d 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -10,7 +10,7 @@ use renderling::{ atlas::AtlasImage, bvol::{Aabb, BoundingSphere}, geometry::Vertex, - light::{AnalyticalLight, DirectionalLightDescriptor}, + light::AnalyticalLight, prelude::*, skybox::Skybox, stage::{Animator, GltfDocument, Stage}, @@ -142,12 +142,12 @@ impl App { let size = ctx.get_size(); let (proj, view) = renderling::camera::default_perspective(size.x as f32, size.y as f32); let camera = stage.new_camera().with_projection_and_view(proj, view); - let directional_light = DirectionalLightDescriptor { - direction: Vec3::NEG_Y, - color: renderling::math::hex_to_vec4(0xFDFBD3FF), - intensity: 10.0, - }; - let sunlight_bundle = stage.new_analytical_light(directional_light); + + let sunlight = stage + .new_directional_light() + .with_direction(Vec3::NEG_Y) + .with_color(renderling::math::hex_to_vec4(0xFDFBD3FF)) + .with_intensity(10.0); stage .set_atlas_size(wgpu::Extent3d { @@ -172,7 +172,7 @@ impl App { }, stage, camera, - _lighting: sunlight_bundle, + _lighting: sunlight.into_generic(), model: Model::None, animators: None, animations_conflict: false, diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index e7647079..b43b2169 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -845,7 +845,7 @@ mod test { #[test] /// Tests shading with directional light. fn scene_cube_directional() { - use crate::light::{DirectionalLightDescriptor, Light, LightStyle}; + use crate::light::{DirectionalLightDescriptor, LightDescriptor, LightStyle}; let ctx = Context::headless(100, 100).block(); let stage = ctx @@ -878,7 +878,7 @@ mod test { intensity: 10.0, }); assert_eq!( - Light { + LightDescriptor { light_type: LightStyle::Directional, index: dir_red .light_details() @@ -888,7 +888,7 @@ mod test { .inner(), ..Default::default() }, - Light::from(dir_red.light_details().as_directional().unwrap().id()) + LightDescriptor::from(dir_red.light_details().as_directional().unwrap().id()) ); let _rez = stage diff --git a/crates/renderling/src/light.rs b/crates/renderling/src/light.rs index 4d219972..268d7a99 100644 --- a/crates/renderling/src/light.rs +++ b/crates/renderling/src/light.rs @@ -40,7 +40,7 @@ pub use tiling::*; #[offsets] pub struct LightingDescriptor { /// List of all analytical lights in the scene. - pub analytical_lights_array: Array>, + pub analytical_lights_array: Array>, /// Shadow mapping atlas info. pub shadow_map_atlas_descriptor_id: Id, /// `Id` of the [`ShadowMapDescriptor`] to use when updating @@ -486,24 +486,27 @@ impl SlabItem for LightStyle { /// A generic light that is used as a slab pointer to a /// specific light type. -// TODO: rename to `LightDescriptor` #[repr(C)] #[cfg_attr(not(target_arch = "spirv"), derive(Debug))] #[derive(Copy, Clone, PartialEq, SlabItem)] -pub struct Light { +pub struct LightDescriptor { /// The type of the light pub light_type: LightStyle, /// The index of the light in the lighting slab pub index: u32, /// The id of a transform to apply to the position and direction of the light. /// - /// This `Id` points to a transform on the geometry slab. + /// This `Id` points to a transform on the lighting slab. + /// + /// The value of this descriptor can be synchronized with that of a node + /// transform on the geometry slab from + /// [`crate::light::AnalyticalLight::link_node_transform`]. pub transform_id: Id, /// The id of the shadow map in use by this light. pub shadow_map_desc_id: Id, } -impl Default for Light { +impl Default for LightDescriptor { fn default() -> Self { Self { light_type: LightStyle::Directional, @@ -514,7 +517,7 @@ impl Default for Light { } } -impl From> for Light { +impl From> for LightDescriptor { fn from(id: Id) -> Self { Self { light_type: LightStyle::Directional, @@ -525,7 +528,7 @@ impl From> for Light { } } -impl From> for Light { +impl From> for LightDescriptor { fn from(id: Id) -> Self { Self { light_type: LightStyle::Spot, @@ -536,7 +539,7 @@ impl From> for Light { } } -impl From> for Light { +impl From> for LightDescriptor { fn from(id: Id) -> Self { Self { light_type: LightStyle::Point, @@ -547,7 +550,7 @@ impl From> for Light { } } -impl Light { +impl LightDescriptor { pub fn into_directional_id(self) -> Id { Id::from(self.index) } @@ -579,7 +582,7 @@ impl ShadowCalculation { /// Reads various required parameters from the slab and creates a `ShadowCalculation`. pub fn new( light_slab: &[u32], - light: crate::prelude::Light, + light: crate::prelude::LightDescriptor, in_pos: Vec3, surface_normal: Vec3, light_direction: Vec3, @@ -837,7 +840,7 @@ pub struct LightTile { /// Also, the next available light index. pub next_light_index: u32, /// List of light ids that intersect this tile's frustum. - pub lights_array: Array>, + pub lights_array: Array>, } impl core::fmt::Debug for LightTile { @@ -912,12 +915,12 @@ pub fn dequantize_depth_u32_to_f32(depth: u32) -> f32 { struct NextLightIndex { current_step: usize, tile_size: u32, - lights: Array>, + lights: Array>, global_id: UVec3, } impl Iterator for NextLightIndex { - type Item = Id>; + type Item = Id>; fn next(&mut self) -> Option { let next_index = self.next_index(); @@ -934,7 +937,7 @@ impl NextLightIndex { pub fn new( global_id: UVec3, tile_size: u32, - analytical_lights_array: Array>, + analytical_lights_array: Array>, ) -> Self { Self { current_step: 0, diff --git a/crates/renderling/src/light/cpu.rs b/crates/renderling/src/light/cpu.rs index d3446137..331a909c 100644 --- a/crates/renderling/src/light/cpu.rs +++ b/crates/renderling/src/light/cpu.rs @@ -1,13 +1,13 @@ //! CPU-only lighting and shadows. -use std::sync::{Arc, RwLock, RwLockReadGuard}; +use std::sync::{Arc, RwLock}; use craballoc::{ prelude::{Hybrid, SlabAllocator, WgpuRuntime}, slab::SlabBuffer, - value::{HybridArray, HybridContainer, IsContainer, WeakContainer, WeakHybrid}, + value::HybridArray, }; -use crabslab::{Id, SlabItem}; -use glam::{Mat4, UVec2}; +use crabslab::Id; +use glam::{Mat4, UVec2, Vec3, Vec4}; use snafu::prelude::*; use crate::{ @@ -18,8 +18,8 @@ use crate::{ }; use super::{ - DirectionalLightDescriptor, Light, LightStyle, LightingDescriptor, PointLightDescriptor, - SpotLightDescriptor, + DirectionalLightDescriptor, LightDescriptor, LightStyle, LightingDescriptor, + PointLightDescriptor, SpotLightDescriptor, }; pub use super::shadow_map::ShadowMap; @@ -30,9 +30,6 @@ pub enum LightingError { #[snafu(display("{source}"))] Atlas { source: AtlasError }, - #[snafu(display("AnalyticalLightBundle attached to this ShadowMap was dropped"))] - DroppedAnalyticalLightBundle, - #[snafu(display("Driver poll error: {source}"))] Poll { source: wgpu::PollError }, } @@ -43,81 +40,481 @@ impl From for LightingError { } } -/// A wrapper around all types of analytical lighting. +/// Describes shared behaviour between all analytical lights. +pub trait IsLight: Clone { + /// Return the style of this light. + fn style(&self) -> LightStyle; + + fn light_space_transforms( + &self, + // Another transform applied to the light. + parent_transform: &TransformDescriptor, + // Near limits of the light's reach + // + // The maximum should be the `Camera`'s `Frustum::depth()`. + // TODO: in `DirectionalLightDescriptor::shadow_mapping_projection_and_view`, take Frustum + // as a parameter and then figure out the minimal view projection that includes that frustum + z_near: f32, + // Far limits of the light's reach + z_far: f32, + ) -> Vec; +} + +/// A directional light. +/// +/// An analitical light that casts light in parallel, infinitely. #[derive(Clone, Debug)] -pub enum LightDetails { - Directional(C::Container), - Point(C::Container), - Spot(C::Container), +pub struct DirectionalLight { + descriptor: Hybrid, } -impl From> for LightDetails { - fn from(value: Hybrid) -> Self { - LightDetails::Directional(value) +impl IsLight for DirectionalLight { + fn style(&self) -> LightStyle { + LightStyle::Directional + } + + fn light_space_transforms( + &self, + parent_transform: &TransformDescriptor, + z_near: f32, + z_far: f32, + ) -> Vec { + let m = Mat4::from(*parent_transform); + vec![{ + let (p, v) = self + .descriptor() + .shadow_mapping_projection_and_view(&m, z_near, z_far); + p * v + }] } } -impl From> for LightDetails { - fn from(value: Hybrid) -> Self { - LightDetails::Spot(value) +impl DirectionalLight { + /// Returns a pointer to the descriptor data on the GPU slab. + pub fn id(&self) -> Id { + self.descriptor.id() + } + + /// Returns the a copy of the descriptor. + pub fn descriptor(&self) -> DirectionalLightDescriptor { + self.descriptor.get() + } +} + +impl AnalyticalLight { + /// Set the direction of the directional light. + pub fn set_direction(&self, direction: Vec3) -> &Self { + self.inner.descriptor.modify(|d| d.direction = direction); + self + } + + /// Set the direction and return the directional light. + pub fn with_direction(self, direction: Vec3) -> Self { + self.set_direction(direction); + self + } + + /// Modify the direction of the directional light. + pub fn modify_direction(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.direction)) + } + + /// Get the direction of the directional light. + pub fn direction(&self) -> Vec3 { + self.inner.descriptor.get().direction + } + + /// Set the color of the directional light. + pub fn set_color(&self, color: Vec4) -> &Self { + self.inner.descriptor.modify(|d| d.color = color); + self + } + + /// Set the color and return the directional light. + pub fn with_color(self, color: Vec4) -> Self { + self.set_color(color); + self + } + + /// Modify the color of the directional light. + pub fn modify_color(&self, f: impl FnOnce(&mut Vec4) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.color)) + } + + /// Get the color of the directional light. + pub fn color(&self) -> Vec4 { + self.inner.descriptor.get().color + } + + /// Set the intensity of the directional light. + pub fn set_intensity(&self, intensity: f32) -> &Self { + self.inner.descriptor.modify(|d| d.intensity = intensity); + self + } + + /// Set the intensity and return the directional light. + pub fn with_intensity(self, intensity: f32) -> Self { + self.set_intensity(intensity); + self + } + + /// Modify the intensity of the directional light. + pub fn modify_intensity(&self, f: impl FnOnce(&mut f32) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.intensity)) + } + + /// Get the intensity of the directional light. + pub fn intensity(&self) -> f32 { + self.inner.descriptor.get().intensity } } -impl From> for LightDetails { - fn from(value: Hybrid) -> Self { - LightDetails::Point(value) +/// A point light. +/// +/// An analytical light that emits light in all directions from a single point. +#[derive(Clone, Debug)] +pub struct PointLight { + descriptor: Hybrid, +} + +impl IsLight for PointLight { + fn style(&self) -> LightStyle { + LightStyle::Point + } + + fn light_space_transforms( + &self, + t: &TransformDescriptor, + // Near limits of the light's reach + // + // The maximum should be the `Camera`'s `Frustum::depth()`. + z_near: f32, + // Far limits of the light's reach + z_far: f32, + ) -> Vec { + let m = Mat4::from(*t); + let (p, vs) = self + .descriptor() + .shadow_mapping_projection_and_view_matrices(&m, z_near, z_far); + vs.into_iter().map(|v| p * v).collect() } } -impl LightDetails { - pub fn as_directional(&self) -> Option<&C::Container> { - if let LightDetails::Directional(d) = self { - Some(d) - } else { - None - } +impl PointLight { + /// Returns a pointer to the descriptor data on the GPU slab. + pub fn id(&self) -> Id { + self.descriptor.id() } - pub fn as_spot(&self) -> Option<&C::Container> { - if let LightDetails::Spot(s) = self { - Some(s) - } else { - None - } + /// Returns a copy of the descriptor. + pub fn descriptor(&self) -> PointLightDescriptor { + self.descriptor.get() } +} - pub fn as_point(&self) -> Option<&C::Container> { - if let LightDetails::Point(p) = self { - Some(p) - } else { - None - } +impl AnalyticalLight { + /// Set the position of the point light. + pub fn set_position(&self, position: Vec3) -> &Self { + self.inner.descriptor.modify(|d| d.position = position); + self } - pub fn style(&self) -> LightStyle { - match self { - LightDetails::Directional(_) => LightStyle::Directional, - LightDetails::Point(_) => LightStyle::Point, - LightDetails::Spot(_) => LightStyle::Spot, - } + /// Set the position and return the point light. + pub fn with_position(self, position: Vec3) -> Self { + self.set_position(position); + self + } + + /// Modify the position of the point light. + pub fn modify_position(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.position)) + } + + /// Get the position of the point light. + pub fn position(&self) -> Vec3 { + self.inner.descriptor.get().position + } + + /// Set the color of the point light. + pub fn set_color(&self, color: Vec4) -> &Self { + self.inner.descriptor.modify(|d| d.color = color); + self + } + + /// Set the color and return the point light. + pub fn with_color(self, color: Vec4) -> Self { + self.set_color(color); + self + } + + /// Modify the color of the point light. + pub fn modify_color(&self, f: impl FnOnce(&mut Vec4) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.color)) + } + + /// Get the color of the point light. + pub fn color(&self) -> Vec4 { + self.inner.descriptor.get().color + } + + /// Set the intensity of the point light. + pub fn set_intensity(&self, intensity: f32) -> &Self { + self.inner.descriptor.modify(|d| d.intensity = intensity); + self + } + + /// Set the intensity and return the point light. + pub fn with_intensity(self, intensity: f32) -> Self { + self.set_intensity(intensity); + self + } + + /// Modify the intensity of the point light. + pub fn modify_intensity(&self, f: impl FnOnce(&mut f32) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.intensity)) + } + + /// Get the intensity of the point light. + pub fn intensity(&self) -> f32 { + self.inner.descriptor.get().intensity + } +} + +/// A spot light. +/// +/// An analytical light that emits light in a cone shape. +#[derive(Clone, Debug)] +pub struct SpotLight { + descriptor: Hybrid, +} + +impl IsLight for SpotLight { + fn style(&self) -> LightStyle { + LightStyle::Spot + } + + fn light_space_transforms( + &self, + t: &TransformDescriptor, + // Near limits of the light's reach + // + // The maximum should be the `Camera`'s `Frustum::depth()`. + z_near: f32, + // Far limits of the light's reach + z_far: f32, + ) -> Vec { + let m = Mat4::from(*t); + vec![{ + let (p, v) = self + .descriptor() + .shadow_mapping_projection_and_view(&m, z_near, z_far); + p * v + }] + } +} + +impl SpotLight { + /// Returns a pointer to the descriptor data on the GPU slab. + pub fn id(&self) -> Id { + self.descriptor.id() + } + + /// Returns a copy of the descriptor. + pub fn descriptor(&self) -> SpotLightDescriptor { + self.descriptor.get() } } -impl LightDetails { - pub(crate) fn from_hybrid(hybrid: &LightDetails) -> Self { - match hybrid { - LightDetails::Directional(d) => LightDetails::Directional(WeakHybrid::from_hybrid(d)), - LightDetails::Point(p) => LightDetails::Point(WeakHybrid::from_hybrid(p)), - LightDetails::Spot(s) => LightDetails::Spot(WeakHybrid::from_hybrid(s)), +impl AnalyticalLight { + /// Set the position of the spot light. + pub fn set_position(&self, position: Vec3) -> &Self { + self.inner.descriptor.modify(|d| d.position = position); + self + } + + /// Set the position and return the spot light. + pub fn with_position(self, position: Vec3) -> Self { + self.set_position(position); + self + } + + /// Modify the position of the spot light. + pub fn modify_position(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.position)) + } + + /// Get the position of the spot light. + pub fn position(&self) -> Vec3 { + self.inner.descriptor.get().position + } + + /// Set the direction of the spot light. + pub fn set_direction(&self, direction: Vec3) -> &Self { + self.inner.descriptor.modify(|d| d.direction = direction); + self + } + + /// Set the direction and return the spot light. + pub fn with_direction(self, direction: Vec3) -> Self { + self.set_direction(direction); + self + } + + /// Modify the direction of the spot light. + pub fn modify_direction(&self, f: impl FnOnce(&mut Vec3) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.direction)) + } + + /// Get the direction of the spot light. + pub fn direction(&self) -> Vec3 { + self.inner.descriptor.get().direction + } + + /// Set the inner cutoff of the spot light. + pub fn set_inner_cutoff(&self, inner_cutoff: f32) -> &Self { + self.inner + .descriptor + .modify(|d| d.inner_cutoff = inner_cutoff); + self + } + + /// Set the inner cutoff and return the spot light. + pub fn with_inner_cutoff(self, inner_cutoff: f32) -> Self { + self.set_inner_cutoff(inner_cutoff); + self + } + + /// Modify the inner cutoff of the spot light. + pub fn modify_inner_cutoff(&self, f: impl FnOnce(&mut f32) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.inner_cutoff)) + } + + /// Get the inner cutoff of the spot light. + pub fn inner_cutoff(&self) -> f32 { + self.inner.descriptor.get().inner_cutoff + } + + /// Set the outer cutoff of the spot light. + pub fn set_outer_cutoff(&self, outer_cutoff: f32) -> &Self { + self.inner + .descriptor + .modify(|d| d.outer_cutoff = outer_cutoff); + self + } + + /// Set the outer cutoff and return the spot light. + pub fn with_outer_cutoff(self, outer_cutoff: f32) -> Self { + self.set_outer_cutoff(outer_cutoff); + self + } + + /// Modify the outer cutoff of the spot light. + pub fn modify_outer_cutoff(&self, f: impl FnOnce(&mut f32) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.outer_cutoff)) + } + + /// Get the outer cutoff of the spot light. + pub fn outer_cutoff(&self) -> f32 { + self.inner.descriptor.get().outer_cutoff + } + + /// Set the color of the spot light. + pub fn set_color(&self, color: Vec4) -> &Self { + self.inner.descriptor.modify(|d| d.color = color); + self + } + + /// Set the color and return the spot light. + pub fn with_color(self, color: Vec4) -> Self { + self.set_color(color); + self + } + + /// Modify the color of the spot light. + pub fn modify_color(&self, f: impl FnOnce(&mut Vec4) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.color)) + } + + /// Get the color of the spot light. + pub fn color(&self) -> Vec4 { + self.inner.descriptor.get().color + } + + /// Set the intensity of the spot light. + pub fn set_intensity(&self, intensity: f32) -> &Self { + self.inner.descriptor.modify(|d| d.intensity = intensity); + self + } + + /// Set the intensity and return the spot light. + pub fn with_intensity(self, intensity: f32) -> Self { + self.set_intensity(intensity); + self + } + + /// Modify the intensity of the spot light. + pub fn modify_intensity(&self, f: impl FnOnce(&mut f32) -> T) -> T { + self.inner.descriptor.modify(|d| f(&mut d.intensity)) + } + + /// Get the intensity of the spot light. + pub fn intensity(&self) -> f32 { + self.inner.descriptor.get().intensity + } +} + +#[derive(Clone)] +pub enum Light { + Directional(DirectionalLight), + Point(PointLight), + Spot(SpotLight), +} + +impl From for Light { + fn from(light: DirectionalLight) -> Self { + Light::Directional(light) + } +} + +impl From for Light { + fn from(light: PointLight) -> Self { + Light::Point(light) + } +} + +impl From for Light { + fn from(light: SpotLight) -> Self { + Light::Spot(light) + } +} + +impl IsLight for Light { + fn style(&self) -> LightStyle { + match self { + Light::Directional(light) => light.style(), + Light::Point(light) => light.style(), + Light::Spot(light) => light.style(), } } - pub(crate) fn upgrade(&self) -> Option { - Some(match self { - LightDetails::Directional(d) => LightDetails::Directional(d.upgrade()?), - LightDetails::Point(p) => LightDetails::Point(p.upgrade()?), - LightDetails::Spot(s) => LightDetails::Spot(s.upgrade()?), - }) + fn light_space_transforms( + &self, + // Another transform applied to the light. + parent_transform: &TransformDescriptor, + // Near limits of the light's reach + // + // The maximum should be the `Camera`'s `Frustum::depth()`. + z_near: f32, + // Far limits of the light's reach + z_far: f32, + ) -> Vec { + match self { + Light::Directional(light) => { + light.light_space_transforms(parent_transform, z_near, z_far) + } + Light::Point(light) => light.light_space_transforms(parent_transform, z_near, z_far), + Light::Spot(light) => light.light_space_transforms(parent_transform, z_near, z_far), + } } } @@ -125,14 +522,12 @@ impl LightDetails { /// /// Create an `AnalyticalLightBundle` with the `Lighting::new_analytical_light`, /// or from `Stage::new_analytical_light`. -// TODO: rework the light API. -// * to not be based on descriptors -// * to match the rest of the builder style APIs -pub struct AnalyticalLight { +#[derive(Clone)] +pub struct AnalyticalLight { /// The generic light descriptor. - light: Ct::Container, - /// The specific light descriptor. - light_details: LightDetails, + pub(crate) light_descriptor: Hybrid, + /// The specific light. + inner: T, /// The light's global transform. /// /// This value lives in the lighting slab. @@ -146,12 +541,12 @@ pub struct AnalyticalLight { node_transform: Arc>>, } -impl core::fmt::Display for AnalyticalLight { +impl core::fmt::Display for AnalyticalLight { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.write_fmt(format_args!( "AnalyticalLightBundle type={} light-id={:?} node-nested-transform-global-id:{:?}", - self.light_details.style(), - self.light.id(), + self.inner.style(), + self.light_descriptor.id(), self.node_transform .read() .unwrap() @@ -161,87 +556,48 @@ impl core::fmt::Display for AnalyticalLight { } } -impl Clone for AnalyticalLight -where - Ct::Container: Clone, - Ct::Container: Clone, - LightDetails: Clone, -{ - fn clone(&self) -> Self { - Self { - light: self.light.clone(), - light_details: self.light_details.clone(), - transform: self.transform.clone(), - node_transform: self.node_transform.clone(), - } +impl IsLight for AnalyticalLight { + fn style(&self) -> LightStyle { + self.inner.style() } -} -impl AnalyticalLight { - pub(crate) fn from_hybrid(light: &AnalyticalLight) -> Self { - AnalyticalLight { - light: WeakHybrid::from_hybrid(&light.light), - light_details: LightDetails::from_hybrid(&light.light_details), - transform: light.transform.clone(), - node_transform: light.node_transform.clone(), - } + fn light_space_transforms( + &self, + // Another transform applied to the light. + parent_transform: &TransformDescriptor, + // Near limits of the light's reach + // + // The maximum should be the `Camera`'s `Frustum::depth()`. + // TODO: in `DirectionalLightDescriptor::shadow_mapping_projection_and_view`, take Frustum + // as a parameter and then figure out the minimal view projection that includes that frustum + z_near: f32, + // Far limits of the light's reach + z_far: f32, + ) -> Vec { + self.inner + .light_space_transforms(parent_transform, z_near, z_far) } +} - pub(crate) fn upgrade(&self) -> Option { - Some(AnalyticalLight { - light: self.light.upgrade()?, - light_details: self.light_details.upgrade()?, - transform: self.transform.clone(), - node_transform: self.node_transform.clone(), - }) +impl AnalyticalLight { + /// Returns a pointer to this light on the GPU + pub fn id(&self) -> Id { + self.light_descriptor.id() } -} -impl AnalyticalLight { - pub fn weak(&self) -> AnalyticalLight { - AnalyticalLight::from_hybrid(self) - } - - pub fn light_space_transforms(&self, z_near: f32, z_far: f32) -> Vec { - let t = self.transform.descriptor(); - let m = Mat4::from(t); - match &self.light_details { - LightDetails::Directional(d) => vec![{ - let (p, v) = d - .get() - .shadow_mapping_projection_and_view(&m, z_near, z_far); - p * v - }], - LightDetails::Point(point) => { - let (p, vs) = point - .get() - .shadow_mapping_projection_and_view_matrices(&m, z_near, z_far); - vs.into_iter().map(|v| p * v).collect() - } - LightDetails::Spot(spot) => vec![{ - let (p, v) = spot - .get() - .shadow_mapping_projection_and_view(&m, z_near, z_far); - p * v - }], - } + /// Returns a copy of the descriptor on the GPU. + pub fn descriptor(&self) -> LightDescriptor { + self.light_descriptor.get() } -} -impl AnalyticalLight { /// Link this light to a node's `NestedTransform`. pub fn link_node_transform(&self, transform: &NestedTransform) { *self.node_transform.write().unwrap() = Some(transform.clone()); } - /// Get a reference to the generic light descriptor. - pub fn light(&self) -> &Ct::Container { - &self.light - } - - /// Get a reference to the specific light descriptor. - pub fn light_details(&self) -> &LightDetails { - &self.light_details + /// Get a reference to the inner light. + pub fn inner(&self) -> &T { + &self.inner } /// Get a reference to the light's global transform. @@ -249,9 +605,9 @@ impl AnalyticalLight { /// This value lives in the lighting slab. /// /// ## Note - /// If a `NestedTransform` has been linked to this light by using [`Self::link_node_transform`], + /// If a [`NestedTransform`] has been linked to this light by using [`Self::link_node_transform`], /// the transform returned by this function may be overwritten at any point by the given - /// `NestedTransform`. + /// [`NestedTransform`]. pub fn transform(&self) -> &Transform { &self.transform } @@ -269,19 +625,27 @@ impl AnalyticalLight { .as_ref() .map(|t| t.clone()) } -} -struct AnalyticalLightIterator<'a> { - inner: RwLockReadGuard<'a, Vec>>, - index: usize, -} - -impl Iterator for AnalyticalLightIterator<'_> { - type Item = AnalyticalLight; - - fn next(&mut self) -> Option { - let item = self.inner.get(self.index)?; - item.upgrade() + /// Convert this light into a generic light, hiding the specific light type that it is. + /// + /// This is useful if you want to store your lights together. + pub fn into_generic(self) -> AnalyticalLight + where + Light: From, + { + let AnalyticalLight { + light_descriptor, + inner, + transform, + node_transform, + } = self; + let inner = Light::from(inner); + AnalyticalLight { + light_descriptor, + inner, + transform, + node_transform, + } } } @@ -293,8 +657,8 @@ pub struct Lighting { pub(crate) light_slab_buffer: Arc>>, pub(crate) geometry_slab_buffer: Arc>>, pub(crate) lighting_descriptor: Hybrid, - pub(crate) analytical_lights: Arc>>>, - pub(crate) analytical_lights_array: Arc>>>>, + pub(crate) analytical_lights: Arc>>, + pub(crate) analytical_lights_array: Arc>>>>, pub(crate) shadow_map_update_pipeline: Arc, pub(crate) shadow_map_update_bindgroup_layout: Arc, pub(crate) shadow_map_update_blitter: AtlasBlitter, @@ -394,21 +758,29 @@ impl Lighting { /// Add an [`AnalyticalLightBundle`] to the internal list of lights. /// - /// This is called implicitly by [`Lighting::new_analytical_light`]. + /// This is called implicitly by: + /// + /// * [`Lighting::new_directional_light`]. + /// * [`Lighting::new_point_light`]. + /// * [`Lighting::new_spot_light`]. /// /// This can be used to add the light back to the scene after using /// [`Lighting::remove_light`]. - pub fn add_light(&self, bundle: &AnalyticalLight) { + pub fn add_light(&self, bundle: &AnalyticalLight) + where + T: IsLight, + Light: From, + { log::trace!( "adding light {:?} ({})", - bundle.light.id(), - bundle.light_details.style() + bundle.light_descriptor.id(), + bundle.inner.style() ); // Update our list of weakly ref'd light bundles self.analytical_lights .write() .unwrap() - .push(AnalyticalLight::::from_hybrid(bundle)); + .push(bundle.clone().into_generic()); // Invalidate the array of lights *self.analytical_lights_array.write().unwrap() = None; } @@ -418,56 +790,91 @@ impl Lighting { /// Use this to exclude a light from rendering, without dropping the light. /// /// After calling this function you can include the light again using [`Lighting::add_light`]. - pub fn remove_light(&self, bundle: &AnalyticalLight) { + pub fn remove_light(&self, bundle: &AnalyticalLight) { log::trace!( "removing light {:?} ({})", - bundle.light.id(), - bundle.light_details.style() + bundle.light_descriptor.id(), + bundle.inner.style() ); // Remove the light from the list of weakly ref'd light bundles let mut guard = self.analytical_lights.write().unwrap(); - guard.retain(|stored_light| stored_light.light.id() != bundle.light.id()); + guard.retain(|stored_light| { + stored_light.light_descriptor.id() != bundle.light_descriptor.id() + }); *self.analytical_lights_array.write().unwrap() = None; } /// Return an iterator over all lights. - pub fn lights(&self) -> impl Iterator + '_ { - let inner = self.analytical_lights.read().unwrap(); - AnalyticalLightIterator { inner, index: 0 } + pub fn lights(&self) -> Vec { + self.analytical_lights.read().unwrap().clone() } - /// Create a new [`AnalyticalLightBundle`] for the given descriptor `T`. + /// Create a new [`AnalyticalLight`]. /// - /// `T` must be one of: - /// - [`DirectionalLightDescriptor`] - /// - [`SpotLightDescriptor`] - /// - [`PointLightDescriptor`] - pub fn new_analytical_light(&self, light_descriptor: T) -> AnalyticalLight - where - T: Clone + Copy + SlabItem + Send + Sync, - Light: From>, - LightDetails: From>, - { + /// The light is automatically added with [`Lighting::add_light`]. + pub fn new_directional_light(&self) -> AnalyticalLight { + let descriptor = self + .light_slab + .new_value(DirectionalLightDescriptor::default()); let transform = Transform::new(&self.light_slab); - let light_inner = self.light_slab.new_value(light_descriptor); - let light = self.light_slab.new_value({ - let mut light = Light::from(light_inner.id()); + let light_descriptor = self.light_slab.new_value({ + let mut light = LightDescriptor::from(descriptor.id()); light.transform_id = transform.id(); light }); - let light_details = LightDetails::from(light_inner); + let bundle = AnalyticalLight { - light, - light_details, + light_descriptor, + inner: DirectionalLight { descriptor }, transform, node_transform: Default::default(), }; - log::trace!( - "created light {:?} ({})", - bundle.light.id(), - bundle.light_details.style() - ); + self.add_light(&bundle); + bundle + } + + /// Create a new [`AnalyticalLight`]. + /// + /// The light is automatically added with [`Lighting::add_light`]. + pub fn new_point_light(&self) -> AnalyticalLight { + let descriptor = self.light_slab.new_value(PointLightDescriptor::default()); + let transform = Transform::new(&self.light_slab); + let light_descriptor = self.light_slab.new_value({ + let mut light = LightDescriptor::from(descriptor.id()); + light.transform_id = transform.id(); + light + }); + + let bundle = AnalyticalLight { + light_descriptor, + inner: PointLight { descriptor }, + transform, + node_transform: Default::default(), + }; + self.add_light(&bundle); + + bundle + } + + /// Create a new [`AnalyticalLight`]. + /// + /// The light is automatically added with [`Lighting::add_light`]. + pub fn new_spot_light(&self) -> AnalyticalLight { + let descriptor = self.light_slab.new_value(SpotLightDescriptor::default()); + let transform = Transform::new(&self.light_slab); + let light_descriptor = self.light_slab.new_value({ + let mut light = LightDescriptor::from(descriptor.id()); + light.transform_id = transform.id(); + light + }); + + let bundle = AnalyticalLight { + light_descriptor, + inner: SpotLight { descriptor }, + transform, + node_transform: Default::default(), + }; self.add_light(&bundle); bundle @@ -496,48 +903,17 @@ impl Lighting { pub fn commit(&self) -> SlabBuffer { log::trace!("committing lights"); let lights_array = { - let mut lights_guard = self.analytical_lights.write().unwrap(); - // Update the list of analytical lights to only reference lights that are still - // held somewhere in the outside program. - let mut analytical_lights_dropped = false; - lights_guard.retain_mut(|light_bundle| { - let has_refs = light_bundle.light.has_external_references(); - if has_refs { - // References to this light still exist, so we'll check to see - // if we need to update the values of linked node transforms. - if let Some(node_transform) = - light_bundle.node_transform.read().unwrap().as_ref() - { - let node_global_transform = node_transform.global_descriptor(); - // UNWRAP: Safe because we checked that the light has external references - let light_global_transform = light_bundle.transform.descriptor(); - if light_global_transform != node_global_transform { - // TODO: write a test that animates a light using GLTF to ensure - // that this is working correctly - light_bundle.transform.set_descriptor(node_global_transform); - } - } - } - analytical_lights_dropped = analytical_lights_dropped || !has_refs; - has_refs - }); - - // If lights have been dropped, invalidate the array let mut array_guard = self.analytical_lights_array.write().unwrap(); - if analytical_lights_dropped { - array_guard.take(); - } - // If lights have been invalidated (either by some being dropped or if - // it was previously invalidated by `Lighting::add_light` or `Lighting::remove_light`), - // create a new array + // Create a new array if lights have been invalidated by + // `Lighting::add_light` or `Lighting::remove_light` array_guard .get_or_insert_with(|| { log::trace!(" analytical lights array was invalidated"); + let lights_guard = self.analytical_lights.read().unwrap(); let new_lights = lights_guard .iter() - .map(|bundle| bundle.light.id()) - .collect::>(); + .map(|bundle| bundle.light_descriptor.id()); let array = self.light_slab.new_array(new_lights); log::trace!(" lights array is now: {:?}", array.array()); array diff --git a/crates/renderling/src/light/shadow_map.rs b/crates/renderling/src/light/shadow_map.rs index 3202f7fe..e1e754ed 100644 --- a/crates/renderling/src/light/shadow_map.rs +++ b/crates/renderling/src/light/shadow_map.rs @@ -5,22 +5,20 @@ use std::sync::Arc; use craballoc::{ prelude::Hybrid, - value::{HybridArray, HybridWriteGuard, WeakContainer}, + value::{HybridArray, HybridWriteGuard}, }; use crabslab::Id; use glam::{Mat4, UVec2}; -use snafu::{OptionExt, ResultExt}; +use snafu::ResultExt; use crate::{ atlas::{AtlasBlittingOperation, AtlasImage, AtlasTexture, AtlasTextureDescriptor}, bindgroup::ManagedBindGroup, + light::{IsLight, Light}, stage::Renderlet, }; -use super::{ - AnalyticalLight, DroppedAnalyticalLightBundleSnafu, Lighting, LightingError, PollSnafu, - ShadowMapDescriptor, -}; +use super::{AnalyticalLight, Lighting, LightingError, PollSnafu, ShadowMapDescriptor}; /// A depth map rendering of the scene from a light's point of view. /// @@ -44,7 +42,7 @@ pub struct ShadowMap { pub(crate) _atlas_textures_array: HybridArray>, pub(crate) update_texture: crate::texture::Texture, pub(crate) blitting_op: AtlasBlittingOperation, - pub(crate) light_bundle: AnalyticalLight, + pub(crate) light_bundle: AnalyticalLight, } impl ShadowMap { @@ -162,19 +160,22 @@ impl ShadowMap { /// Enable shadow mapping for the given [`AnalyticalLightBundle`], creating /// a new [`ShadowMap`]. - pub fn new( + pub fn new( lighting: &Lighting, - analytical_light_bundle: &AnalyticalLight, + analytical_light_bundle: &AnalyticalLight, // Size of the shadow map size: UVec2, // Distance to the shadow map frustum's near plane z_near: f32, // Distance to the shadow map frustum's far plane z_far: f32, - ) -> Result { + ) -> Result + where + T: IsLight, + Light: From, + { let stage_slab_buffer = lighting.geometry_slab_buffer.read().unwrap(); - let is_point_light = - analytical_light_bundle.light_details().style() == super::LightStyle::Point; + let is_point_light = analytical_light_bundle.style() == super::LightStyle::Point; let count = if is_point_light { 6 } else { 1 }; let atlas = &lighting.shadow_map_atlas; let image = AtlasImage::new(size, crate::atlas::AtlasImageFormat::R32FLOAT); @@ -198,9 +199,14 @@ impl ShadowMap { let blitting_op = lighting .shadow_map_update_blitter .new_blitting_operation(atlas, if is_point_light { 6 } else { 1 }); - let light_space_transforms = lighting - .light_slab - .new_array(analytical_light_bundle.light_space_transforms(z_near, z_far)); + let light_space_transforms = + lighting + .light_slab + .new_array(analytical_light_bundle.light_space_transforms( + &analytical_light_bundle.transform().descriptor(), + z_near, + z_far, + )); let shadowmap_descriptor = lighting.light_slab.new_value(ShadowMapDescriptor { light_space_transforms_array: light_space_transforms.array(), z_near, @@ -211,7 +217,7 @@ impl ShadowMap { pcf_samples: 4, }); // Set the descriptor in the light, so the shader knows to use it - analytical_light_bundle.light().modify(|light| { + analytical_light_bundle.light_descriptor.modify(|light| { light.shadow_map_desc_id = shadowmap_descriptor.id(); }); let light_slab_buffer = lighting.commit(); @@ -232,7 +238,7 @@ impl ShadowMap { _atlas_textures_array: atlas_textures_array, update_texture, blitting_op, - light_bundle: analytical_light_bundle.weak(), + light_bundle: analytical_light_bundle.clone().into_generic(), }) } @@ -251,13 +257,12 @@ impl ShadowMap { renderlets: impl IntoIterator, ) -> Result<(), LightingError> { let lighting = lighting.as_ref(); - let light_bundle = self - .light_bundle - .upgrade() - .context(DroppedAnalyticalLightBundleSnafu)?; let shadow_desc = self.shadowmap_descriptor.get(); - let new_transforms = - light_bundle.light_space_transforms(shadow_desc.z_near, shadow_desc.z_far); + let new_transforms = self.light_bundle.light_space_transforms( + &self.light_bundle.transform().descriptor(), + shadow_desc.z_near, + shadow_desc.z_far, + ); for (i, t) in (0..self.light_space_transforms.len()).zip(new_transforms) { self.light_space_transforms.set_item(i, t); } @@ -594,7 +599,7 @@ mod test { let z_far = 100.0; for (_i, light_bundle) in doc.lights.iter().enumerate() { { - let desc = light_bundle.light_details().as_spot().unwrap().get(); + let desc = light_bundle.inner().as_spot().unwrap().get(); let (p, v) = desc.shadow_mapping_projection_and_view( &light_bundle.transform().as_mat4(), z_near, @@ -660,7 +665,7 @@ mod test { let z_far = 100.0; for (i, light_bundle) in doc.lights.iter().enumerate() { { - let desc = light_bundle.light_details().as_point().unwrap().get(); + let desc = light_bundle.inner().as_point().unwrap().get(); println!("point light {i}: {desc:?}"); let (p, vs) = desc.shadow_mapping_projection_and_view_matrices( &light_bundle.transform().as_mat4(), diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index c7628f71..d6cf47c4 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -20,6 +20,7 @@ use std::sync::{atomic::AtomicBool, Arc, Mutex, RwLock}; use crate::atlas::AtlasTexture; use crate::camera::Camera; +use crate::light::{DirectionalLight, PointLight, SpotLight}; use crate::material::Material; use crate::{ atlas::{AtlasError, AtlasImage, AtlasImageError}, @@ -30,7 +31,7 @@ use crate::{ draw::DrawCalls, geometry::{Geometry, Indices, MorphTargetWeights, MorphTargets, Skin, SkinJoint, Vertices}, light::{ - AnalyticalLight, Light, LightDetails, LightTiling, LightTilingConfig, Lighting, + AnalyticalLight, LightDescriptor, LightTiling, LightTilingConfig, Lighting, LightingBindGroupLayoutEntries, LightingError, ShadowMap, }, material::Materials, @@ -554,19 +555,19 @@ impl Stage { /// Lighting methods. impl Stage { - /// Stage a new analytical light. - /// - /// `T` must be one of: - /// - [`DirectionalLightDescriptor`](crate::light::DirectionalLightDescriptor) - /// - [`SpotLightDescriptor`](crate::light::SpotLightDescriptor) - /// - [`PointLightDescriptor`](crate::light::PointLightDescriptor) - pub fn new_analytical_light(&self, light_descriptor: T) -> AnalyticalLight - where - T: Clone + Copy + SlabItem + Send + Sync, - Light: From>, - LightDetails: From>, - { - self.lighting.new_analytical_light(light_descriptor) + /// Stage a new directional light. + pub fn new_directional_light(&self) -> AnalyticalLight { + self.lighting.new_directional_light() + } + + /// Stage a new point light. + pub fn new_point_light(&self) -> AnalyticalLight { + self.lighting.new_point_light() + } + + /// Stage a new spot light. + pub fn new_spot_light(&self) -> AnalyticalLight { + self.lighting.new_spot_light() } /// Add an [`AnalyticalLightBundle`] to the internal list of lights. diff --git a/crates/renderling/src/stage/gltf_support.rs b/crates/renderling/src/stage/gltf_support.rs index 432e6e8b..c60bb095 100644 --- a/crates/renderling/src/stage/gltf_support.rs +++ b/crates/renderling/src/stage/gltf_support.rs @@ -15,10 +15,7 @@ use crate::{ bvol::Aabb, camera::{Camera, CameraDescriptor}, geometry::{Indices, MorphTargetWeights, MorphTargets, Skin, Vertices}, - light::{ - AnalyticalLight, DirectionalLightDescriptor, LightStyle, PointLightDescriptor, - SpotLightDescriptor, - }, + light::{AnalyticalLight, LightStyle}, material::Material, stage::{MorphTarget, Renderlet, Stage, Vertex}, transform::{NestedTransform, TransformDescriptor}, @@ -969,9 +966,10 @@ impl GltfDocument { let intensity = gltf_light.intensity(); let light_bundle = match gltf_light.kind() { gltf::khr_lights_punctual::Kind::Directional => { - stage.new_analytical_light(DirectionalLightDescriptor { - direction: Vec3::NEG_Z, - color, + stage + .new_directional_light() + .with_direction(Vec3::NEG_Z) + .with_color(color) // TODO: Set a unit for lighting. // We don't yet use a unit for our lighting, and we should. // https://www.realtimerendering.com/blog/physical-units-for-lights/ @@ -983,34 +981,34 @@ impl GltfDocument { // 1. https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_lights_punctual/README.md // 2. https://depts.washington.edu/mictech/optics/me557/Radiometry.pdf // 3. https://projects.blender.org/blender/blender-addons/commit/9d903a93f03b - intensity: intensity / 683.0, - }) + .with_intensity(intensity / 683.0) + .into_generic() } - gltf::khr_lights_punctual::Kind::Point => { - stage.new_analytical_light(PointLightDescriptor { - position: Vec3::ZERO, - color, - intensity: intensity / 683.0, - }) - } + gltf::khr_lights_punctual::Kind::Point => stage + .new_point_light() + .with_position(Vec3::ZERO) + .with_color(color) + .with_intensity(intensity / 683.0) + .into_generic(), gltf::khr_lights_punctual::Kind::Spot { inner_cone_angle, outer_cone_angle, - } => stage.new_analytical_light(SpotLightDescriptor { - position: Vec3::ZERO, - direction: Vec3::NEG_Z, - inner_cutoff: inner_cone_angle, - outer_cutoff: outer_cone_angle, - color, - intensity: intensity / (683.0 * 4.0 * std::f32::consts::PI), - }), + } => stage + .new_spot_light() + .with_position(Vec3::ZERO) + .with_direction(Vec3::NEG_Z) + .with_inner_cutoff(inner_cone_angle) + .with_outer_cutoff(outer_cone_angle) + .with_color(color) + .with_intensity(intensity / (683.0 * 4.0 * std::f32::consts::PI)) + .into_generic(), }; log::trace!( " linking light {:?} with node transform {:?}: {:#?}", - light_bundle.light().id(), + light_bundle.id(), node_transform.global_id(), node_transform.global_descriptor() ); diff --git a/crates/renderling/src/transform/cpu.rs b/crates/renderling/src/transform/cpu.rs index 55710547..17a402df 100644 --- a/crates/renderling/src/transform/cpu.rs +++ b/crates/renderling/src/transform/cpu.rs @@ -9,7 +9,7 @@ use glam::{Mat4, Quat, Vec3}; use super::TransformDescriptor; /// A decomposed 3d transformation. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Transform { pub(crate) descriptor: Hybrid, } From 2d73282163d23296d7f4ca2709bc8570f09b3c6d Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Tue, 9 Sep 2025 13:39:36 +1200 Subject: [PATCH 11/31] sync light's node transforms --- crates/example-culling/src/main.rs | 22 ++--- crates/renderling/src/lib.rs | 69 ++++++--------- crates/renderling/src/light/cpu.rs | 37 ++++++++ crates/renderling/src/light/cpu/test.rs | 100 +++++++++------------- crates/renderling/src/light/shadow_map.rs | 6 +- crates/renderling/src/stage/cpu.rs | 14 +-- 6 files changed, 129 insertions(+), 119 deletions(-) diff --git a/crates/example-culling/src/main.rs b/crates/example-culling/src/main.rs index 68cd19e5..dd75e46e 100644 --- a/crates/example-culling/src/main.rs +++ b/crates/example-culling/src/main.rs @@ -34,7 +34,7 @@ struct CullingExample { app_camera: AppCamera, controller: example::camera::TurntableCameraController, stage: Stage, - dlights: [AnalyticalLight; 2], + dlights: [AnalyticalLight; 2], frustum_camera: FrustumCamera, frustum_renderlet: Renderlet, material_aabb_outside: Material, @@ -174,16 +174,16 @@ impl TestAppHandler for CullingExample { let mut seed = 46; let mut renderlets = vec![]; let stage = ctx.new_stage().with_lighting(true); - let sunlight_a = stage.new_analytical_light(DirectionalLightDescriptor { - direction: Vec3::new(-0.8, -1.0, 0.5).normalize(), - color: Vec4::ONE, - intensity: 10.0, - }); - let sunlight_b = stage.new_analytical_light(DirectionalLightDescriptor { - direction: Vec3::new(1.0, 1.0, -0.1).normalize(), - color: Vec4::ONE, - intensity: 1.0, - }); + let sunlight_a = stage + .new_directional_light() + .with_direction(Vec3::new(-0.8, -1.0, 0.5).normalize()) + .with_color(Vec4::ONE) + .with_intensity(10.0); + let sunlight_b = stage + .new_directional_light() + .with_direction(Vec3::new(1.0, 1.0, -0.1).normalize()) + .with_color(Vec4::ONE) + .with_intensity(1.0); let dlights = [sunlight_a, sunlight_b]; diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index b43b2169..b2d64f35 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -241,7 +241,7 @@ mod test { use glam::{Mat3, Mat4, Quat, UVec2, Vec2, Vec3, Vec4}; use img_diff::DiffCfg; - use light::{AnalyticalLight, DirectionalLightDescriptor}; + use light::AnalyticalLight; use pretty_assertions::assert_eq; use stage::Stage; @@ -283,17 +283,17 @@ mod test { } pub fn make_two_directional_light_setup(stage: &Stage) -> (AnalyticalLight, AnalyticalLight) { - let sunlight_a = stage.new_analytical_light(DirectionalLightDescriptor { - direction: Vec3::new(-0.8, -1.0, 0.5).normalize(), - color: Vec4::ONE, - intensity: 100.0, - }); - let sunlight_b = stage.new_analytical_light(DirectionalLightDescriptor { - direction: Vec3::new(1.0, 1.0, -0.1).normalize(), - color: Vec4::ONE, - intensity: 10.0, - }); - (sunlight_a, sunlight_b) + let sunlight_a = stage + .new_directional_light() + .with_direction(Vec3::new(-0.8, -1.0, 0.5).normalize()) + .with_color(Vec4::ONE) + .with_intensity(100.0); + let sunlight_b = stage + .new_directional_light() + .with_direction(Vec3::new(1.0, 1.0, -0.1).normalize()) + .with_color(Vec4::ONE) + .with_intensity(10.0); + (sunlight_a.into_generic(), sunlight_b.into_generic()) } #[allow(unused, reason = "Used in debugging on macos")] @@ -845,8 +845,6 @@ mod test { #[test] /// Tests shading with directional light. fn scene_cube_directional() { - use crate::light::{DirectionalLightDescriptor, LightDescriptor, LightStyle}; - let ctx = Context::headless(100, 100).block(); let stage = ctx .new_stage() @@ -862,34 +860,21 @@ mod test { let red = Vec3::X.extend(1.0); let green = Vec3::Y.extend(1.0); let blue = Vec3::Z.extend(1.0); - let dir_red = stage.new_analytical_light(DirectionalLightDescriptor { - direction: Vec3::NEG_Y, - color: red, - intensity: 10.0, - }); - let _dir_green = stage.new_analytical_light(DirectionalLightDescriptor { - direction: Vec3::NEG_X, - color: green, - intensity: 10.0, - }); - let _dir_blue = stage.new_analytical_light(DirectionalLightDescriptor { - direction: Vec3::NEG_Z, - color: blue, - intensity: 10.0, - }); - assert_eq!( - LightDescriptor { - light_type: LightStyle::Directional, - index: dir_red - .light_details() - .as_directional() - .unwrap() - .id() - .inner(), - ..Default::default() - }, - LightDescriptor::from(dir_red.light_details().as_directional().unwrap().id()) - ); + let _dir_red = stage + .new_directional_light() + .with_direction(Vec3::NEG_Y) + .with_color(red) + .with_intensity(10.0); + let _dir_green = stage + .new_directional_light() + .with_direction(Vec3::NEG_X) + .with_color(green) + .with_intensity(10.0); + let _dir_blue = stage + .new_directional_light() + .with_direction(Vec3::NEG_Z) + .with_color(blue) + .with_intensity(10.0); let _rez = stage .new_renderlet() diff --git a/crates/renderling/src/light/cpu.rs b/crates/renderling/src/light/cpu.rs index 331a909c..03d8c26c 100644 --- a/crates/renderling/src/light/cpu.rs +++ b/crates/renderling/src/light/cpu.rs @@ -579,6 +579,32 @@ impl IsLight for AnalyticalLight { } } +impl AnalyticalLight { + /// Returns a reference to the inner `DirectionalLight`, if this light is directional. + pub fn as_directional(&self) -> Option<&DirectionalLight> { + match &self.inner { + Light::Directional(light) => Some(light), + _ => None, + } + } + + /// Returns a reference to the inner `PointLight`, if this light is a point light. + pub fn as_point(&self) -> Option<&PointLight> { + match &self.inner { + Light::Point(light) => Some(light), + _ => None, + } + } + + /// Returns a reference to the inner `SpotLight`, if this light is a spot light. + pub fn as_spot(&self) -> Option<&SpotLight> { + match &self.inner { + Light::Spot(light) => Some(light), + _ => None, + } + } +} + impl AnalyticalLight { /// Returns a pointer to this light on the GPU pub fn id(&self) -> Id { @@ -902,6 +928,17 @@ impl Lighting { #[must_use] pub fn commit(&self) -> SlabBuffer { log::trace!("committing lights"); + + // Sync any lights whose node transforms have changed + for light in self.analytical_lights.read().unwrap().iter() { + if let Some(node_transform) = light.node_transform.read().unwrap().as_ref() { + let global_node_transform = node_transform.global_descriptor(); + if node_transform.global_descriptor() != light.transform.descriptor() { + light.transform.set_descriptor(global_node_transform); + } + } + } + let lights_array = { let mut array_guard = self.analytical_lights_array.write().unwrap(); diff --git a/crates/renderling/src/light/cpu/test.rs b/crates/renderling/src/light/cpu/test.rs index cdaff6cd..0bb9a25e 100644 --- a/crates/renderling/src/light/cpu/test.rs +++ b/crates/renderling/src/light/cpu/test.rs @@ -129,7 +129,7 @@ fn spot_lights() { let down_light = doc.lights.first().unwrap(); log::info!( "down_light: {:#?}", - down_light.light_details.as_spot().unwrap().get() + down_light.as_spot().unwrap() ); let frame = ctx.get_next_frame().unwrap(); @@ -220,7 +220,7 @@ fn gen_vec3(prng: &mut GpuRng) -> Vec3 { struct GeneratedLight { _unused_transform: Transform, - _light: AnalyticalLight, + _light: AnalyticalLight, mesh_renderlet: Renderlet, } @@ -260,17 +260,10 @@ fn gen_light(stage: &Stage, prng: &mut GpuRng, bounding_boxes: &[BoundingBox]) - .with_emissive_strength_multiplier(100.0); let mesh_renderlet = stage.new_renderlet().with_vertices(vertices).with_material(material); let _light = { - // suffix the actual analytical light - let intensity = scale * 100.0; - - let light_descriptor = PointLightDescriptor { - position, - color, - intensity, - }; - - stage.new_analytical_light(light_descriptor) - }; + // suffix the actual analytical light + let intensity = scale * 100.0; + stage.new_point_light().with_position(position).with_color(color).with_intensity(intensity) + }; GeneratedLight { _unused_transform, @@ -489,7 +482,7 @@ fn light_bins_sanity() { // Assert either the light is the correct one, or we're using the zero frustum optimization // discussed in if tile.depth_min != tile.depth_max { - assert_eq!(light_bin[0], directional_light.light.id()); + assert_eq!(light_bin[0], directional_light.id()); assert_eq!(light_bin[1], Id::NONE); } else { assert_eq!(0, tile.next_light_index); @@ -522,11 +515,10 @@ fn light_bins_point() { let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_6, 1.0, 0.1, 15.0); camera.camera.set_projection_and_view(proj, view); - let _point_light = stage.new_analytical_light(PointLightDescriptor { - position: Vec3::new(1.1, 1.0, 1.1), - color: Vec4::ONE, - intensity: 5.0, - }); + let _point_light = stage.new_point_light() + .with_position(Vec3::new(1.1, 1.0, 1.1)) + .with_color(Vec4::ONE) + .with_intensity(5.0); snapshot( &ctx, &stage, @@ -943,11 +935,10 @@ fn pedestal() { let mut dir_infos = vec![]; { log::info!("adding dir light"); - let _dir_light = stage.new_analytical_light(DirectionalLightDescriptor { - direction: -position, - color, - intensity: 5.0, - }); + let dir_light = stage.new_directional_light() + .with_direction(-position) + .with_color(color) + .with_intensity(5.0); snapshot(&ctx, &stage, "light/pedestal/directional.png", false); let geometry_slab = @@ -976,20 +967,19 @@ fn pedestal() { dir_infos.push(info); } - log::info!("dropping dir light"); + stage.remove_light(&dir_light); } - assert_eq!(0, stage.lighting.lights().count()); + assert_eq!(0, stage.lighting.lights().len()); // Point lights { log::info!("adding point light with pre-applied position"); - let _point_light = stage.new_analytical_light(PointLightDescriptor { - position, - color, - intensity: 5.0, - }); + let point_light = stage.new_point_light() + .with_position(position) + .with_color(color) + .with_intensity(5.0); snapshot(&ctx, &stage, "light/pedestal/point.png", false); - log::info!("dropping point light"); + stage.remove_light(&point_light); } { @@ -997,29 +987,25 @@ fn pedestal() { let transform = stage.new_nested_transform(); transform.set_local_translation(position); - let point_light = stage.new_analytical_light(PointLightDescriptor { - position: Vec3::ZERO, - color, - intensity: 5.0, - }); + let point_light = stage.new_point_light() + .with_position(Vec3::ZERO) + .with_color(color) + .with_intensity(5.0); point_light.link_node_transform(&transform); snapshot(&ctx, &stage, "light/pedestal/point.png", false); - log::info!("dropping point light"); + stage.remove_light(&point_light); } { log::info!("adding spot light with pre-applied position"); - let spot_desc = SpotLightDescriptor { - position, - direction: -position, - color, - intensity: 5.0, - inner_cutoff: core::f32::consts::PI / 5.0, - outer_cutoff: core::f32::consts::PI / 4.0, - // ..Default::default() - }; - let _spot = stage.new_analytical_light(spot_desc); + let spot = stage.new_spot_light() + .with_position(position) + .with_direction(-position) + .with_color(color) + .with_intensity(5.0) + .with_inner_cutoff(core::f32::consts::PI / 5.0) + .with_outer_cutoff(core::f32::consts::PI / 4.0); snapshot(&ctx, &stage, "light/pedestal/spot.png", false); let geometry_slab = @@ -1052,6 +1038,7 @@ fn pedestal() { // assert that the output of the vertex shader is the same for the first renderlet, // regardless of the lighting pretty_assertions::assert_eq!(dir_infos, spot_infos); + stage.remove_light(&spot); } { @@ -1060,16 +1047,13 @@ fn pedestal() { let node_transform = stage.new_nested_transform(); node_transform.set_local_translation(position); - let spot_desc = SpotLightDescriptor { - position: Vec3::ZERO, - direction: -position, - color, - intensity: 5.0, - inner_cutoff: core::f32::consts::PI / 5.0, - outer_cutoff: core::f32::consts::PI / 4.0, - // ..Default::default() - }; - let spot = stage.new_analytical_light(spot_desc); + let spot = stage.new_spot_light() + .with_position(Vec3::ZERO) + .with_direction(-position) + .with_color(color) + .with_intensity(5.0) + .with_inner_cutoff(core::f32::consts::PI / 5.0) + .with_outer_cutoff(core::f32::consts::PI / 4.0); spot.link_node_transform(&node_transform); snapshot(&ctx, &stage, "light/pedestal/spot.png", false); } diff --git a/crates/renderling/src/light/shadow_map.rs b/crates/renderling/src/light/shadow_map.rs index e1e754ed..6c95ea44 100644 --- a/crates/renderling/src/light/shadow_map.rs +++ b/crates/renderling/src/light/shadow_map.rs @@ -516,7 +516,7 @@ mod test { let gltf_light = doc.lights.first().unwrap(); assert_eq!( - gltf_light.light().get().transform_id, + gltf_light.descriptor().transform_id, gltf_light.transform().id(), "light's global transform id is different from its transform_id" ); @@ -599,7 +599,7 @@ mod test { let z_far = 100.0; for (_i, light_bundle) in doc.lights.iter().enumerate() { { - let desc = light_bundle.inner().as_spot().unwrap().get(); + let desc = light_bundle.as_spot().unwrap().descriptor(); let (p, v) = desc.shadow_mapping_projection_and_view( &light_bundle.transform().as_mat4(), z_near, @@ -665,7 +665,7 @@ mod test { let z_far = 100.0; for (i, light_bundle) in doc.lights.iter().enumerate() { { - let desc = light_bundle.inner().as_point().unwrap().get(); + let desc = light_bundle.as_point().unwrap().descriptor(); println!("point light {i}: {desc:?}"); let (p, vs) = desc.shadow_mapping_projection_and_view_matrices( &light_bundle.transform().as_mat4(), diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index d6cf47c4..54c70184 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -20,7 +20,7 @@ use std::sync::{atomic::AtomicBool, Arc, Mutex, RwLock}; use crate::atlas::AtlasTexture; use crate::camera::Camera; -use crate::light::{DirectionalLight, PointLight, SpotLight}; +use crate::light::{DirectionalLight, IsLight, Light, PointLight, SpotLight}; use crate::material::Material; use crate::{ atlas::{AtlasError, AtlasImage, AtlasImageError}, @@ -31,8 +31,8 @@ use crate::{ draw::DrawCalls, geometry::{Geometry, Indices, MorphTargetWeights, MorphTargets, Skin, SkinJoint, Vertices}, light::{ - AnalyticalLight, LightDescriptor, LightTiling, LightTilingConfig, Lighting, - LightingBindGroupLayoutEntries, LightingError, ShadowMap, + AnalyticalLight, LightTiling, LightTilingConfig, Lighting, LightingBindGroupLayoutEntries, + LightingError, ShadowMap, }, material::Materials, pbr::debug::DebugChannel, @@ -576,7 +576,11 @@ impl Stage { /// /// This can be used to add the light back to the scene after using /// [`Stage::remove_light`]. - pub fn add_light(&self, bundle: &AnalyticalLight) { + pub fn add_light(&self, bundle: &AnalyticalLight) + where + T: IsLight, + Light: From, + { self.lighting.add_light(bundle) } @@ -585,7 +589,7 @@ impl Stage { /// Use this to exclude a light from rendering, without dropping the light. /// /// After calling this function you can include the light again using [`Stage::add_light`]. - pub fn remove_light(&self, bundle: &AnalyticalLight) { + pub fn remove_light(&self, bundle: &AnalyticalLight) { self.lighting.remove_light(bundle); } From 76f39a35e5b9e515881a7bcbfa26219a97340d24 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Wed, 10 Sep 2025 09:15:32 +1200 Subject: [PATCH 12/31] rename Renderlet* to Primitive*, fix doc examples, fix doc links --- crates/example-culling/src/main.rs | 26 +- crates/example/src/lib.rs | 10 +- crates/renderling/src/atlas/cpu.rs | 24 +- crates/renderling/src/bits.rs | 343 ------------------ crates/renderling/src/bvol.rs | 8 +- crates/renderling/src/cubemap/cpu.rs | 4 +- crates/renderling/src/cull.rs | 36 +- crates/renderling/src/cull/cpu.rs | 16 +- crates/renderling/src/debug.rs | 8 +- crates/renderling/src/draw.rs | 2 +- crates/renderling/src/draw/cpu.rs | 18 +- crates/renderling/src/geometry/cpu.rs | 23 +- crates/renderling/src/lib.rs | 155 ++++---- crates/renderling/src/light.rs | 17 +- crates/renderling/src/light/cpu.rs | 20 +- crates/renderling/src/light/cpu/test.rs | 18 +- crates/renderling/src/light/shadow_map.rs | 15 +- crates/renderling/src/light/tiling.rs | 6 +- crates/renderling/src/material/cpu.rs | 5 +- crates/renderling/src/math.rs | 4 +- crates/renderling/src/pbr.rs | 6 +- crates/renderling/src/skybox.rs | 2 +- crates/renderling/src/stage.rs | 68 ++-- crates/renderling/src/stage/cpu.rs | 82 +++-- .../stage/cpu/{renderlet.rs => primitive.rs} | 109 +++--- crates/renderling/src/stage/gltf_support.rs | 10 +- crates/renderling/src/transform/cpu.rs | 5 +- crates/renderling/src/tutorial.rs | 25 +- crates/renderling/src/ui.rs | 2 +- crates/renderling/src/ui/cpu.rs | 4 +- crates/renderling/src/ui/cpu/path.rs | 14 +- crates/renderling/src/ui/cpu/text.rs | 6 +- crates/renderling/tests/wasm.rs | 2 +- 33 files changed, 409 insertions(+), 684 deletions(-) delete mode 100644 crates/renderling/src/bits.rs rename crates/renderling/src/stage/cpu/{renderlet.rs => primitive.rs} (75%) diff --git a/crates/example-culling/src/main.rs b/crates/example-culling/src/main.rs index dd75e46e..96ad7490 100644 --- a/crates/example-culling/src/main.rs +++ b/crates/example-culling/src/main.rs @@ -36,10 +36,10 @@ struct CullingExample { stage: Stage, dlights: [AnalyticalLight; 2], frustum_camera: FrustumCamera, - frustum_renderlet: Renderlet, + frustum_primitive: Primitive, material_aabb_outside: Material, material_aabb_overlapping: Material, - renderlets: Vec, + primitives: Vec, next_k: u64, } @@ -56,7 +56,7 @@ impl CullingExample { frustum_camera: &FrustumCamera, material_outside: &Material, material_overlapping: &Material, - ) -> Vec { + ) -> Vec { log::info!("generating aabbs with seed {seed}"); fastrand::seed(seed); (0..25u32) @@ -84,7 +84,7 @@ impl CullingExample { .with_translation(center) .with_rotation(rotation); stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(aabb.get_mesh().into_iter().map( |(position, normal)| Vertex { position, @@ -130,9 +130,9 @@ impl ApplicationHandler for CullingExample { .. } => { if c.as_str() == "r" { - self.renderlets.drain(..); + self.primitives.drain(..); let _ = self.stage.commit(); - self.renderlets.extend(Self::make_aabbs( + self.primitives.extend(Self::make_aabbs( self.next_k, &self.stage, &self.frustum_camera, @@ -172,7 +172,7 @@ impl TestAppHandler for CullingExample { ctx: &Context, ) -> Self { let mut seed = 46; - let mut renderlets = vec![]; + let mut prims = vec![]; let stage = ctx.new_stage().with_lighting(true); let sunlight_a = stage .new_directional_light() @@ -213,7 +213,7 @@ impl TestAppHandler for CullingExample { let material_aabb_outside = stage.new_material().with_albedo_factor(red_color); let material_frustum = stage.new_material().with_albedo_factor(yellow_color); let app_camera = AppCamera(stage.new_camera()); - renderlets.extend(Self::make_aabbs( + prims.extend(Self::make_aabbs( seed, &stage, &frustum_camera, @@ -230,11 +230,11 @@ impl TestAppHandler for CullingExample { ..Default::default() }, )); - let frustum_renderlet = stage - .new_renderlet() + let frustum_prim = stage + .new_primitive() .with_vertices(&frustum_vertices) .with_material(&material_frustum); - stage.add_renderlet(&frustum_renderlet); + stage.add_primitive(&frustum_prim); Self { next_k: seed, @@ -250,8 +250,8 @@ impl TestAppHandler for CullingExample { stage, material_aabb_overlapping, material_aabb_outside, - frustum_renderlet, - renderlets, + frustum_primitive: frustum_prim, + primitives: prims, } } diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index 6cf8371d..b7e1f9bc 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -113,7 +113,7 @@ impl AppUi { pub enum Model { Gltf(Box), - Default(Renderlet), + Default(Primitive), None, } @@ -235,16 +235,16 @@ impl App { .with_normal(n) .with_color(Vec4::new(1.0, 0.0, 0.0, 1.0)) })); - let renderlet = self + let primitive = self .stage - .new_renderlet() + .new_primitive() .with_vertices(vertices) .with_bounds({ log::info!("default model bounds: {min} {max}"); BoundingSphere::from((min, max)) }); - self.model = Model::Default(renderlet); + self.model = Model::Default(primitive); self.camera_controller.reset(Aabb::new(min, max)); self.camera_controller .update_camera(self.stage.get_size(), &self.camera); @@ -375,7 +375,7 @@ impl App { // self.lighting // .shadow_map - // .update(&self.lighting.lighting, doc.renderlets.values().flatten()); + // .update(&self.lighting.lighting, doc.primitives.values().flatten()); // self.lighting.light = light.light.clone(); // self.lighting.light_details = dir.clone(); // } diff --git a/crates/renderling/src/atlas/cpu.rs b/crates/renderling/src/atlas/cpu.rs index f2bfa9b5..2ad0a53f 100644 --- a/crates/renderling/src/atlas/cpu.rs +++ b/crates/renderling/src/atlas/cpu.rs @@ -46,6 +46,7 @@ pub enum AtlasError { /// A staged texture in the texture atlas. /// /// An [`AtlasTexture`] can be acquired through: +/// /// * [`Atlas::add_image`] /// * [`Atlas::add_images`]. /// * [`Atlas::set_images`] @@ -377,6 +378,15 @@ impl Atlas { .collect()) } + /// Add one image. + /// + /// If you have more than one image, you should use [`Atlas::add_images`], as every + /// change in images causes a repacking, which might be expensive. + pub fn add_image(&self, image: &AtlasImage) -> Result { + // UNWRAP: safe because we know there's at least one image + Ok(self.add_images(Some(image))?.pop().unwrap()) + } + /// Resize the atlas. /// /// This also distributes the images by size among all layers in an effort to reduce @@ -1030,7 +1040,7 @@ mod test { let texels_entry = &atlas_entries[2]; let _rez = stage - .new_renderlet() + .new_primitive() .with_material( stage .new_material() @@ -1110,7 +1120,7 @@ mod test { [tl, bl, br, tl, br, tr] }); let _clamp_rez = stage - .new_renderlet() + .new_primitive() .with_vertices(&geometry) .with_material( stage @@ -1120,7 +1130,7 @@ mod test { ); let _repeat_rez = stage - .new_renderlet() + .new_primitive() .with_transform(stage.new_transform().with_translation(Vec3::new( sheet_w + 1.0, 0.0, @@ -1135,7 +1145,7 @@ mod test { .with_vertices(&geometry); let _mirror_rez = stage - .new_renderlet() + .new_primitive() .with_transform(stage.new_transform().with_translation(Vec3::new( sheet_w * 2.0 + 2.0, 0.0, @@ -1208,7 +1218,7 @@ mod test { [tl, bl, br, tl, br, tr] }); let _clamp_prim = stage - .new_renderlet() + .new_primitive() .with_vertices(&geometry) .with_material( stage @@ -1218,7 +1228,7 @@ mod test { ); let _repeat_rez = stage - .new_renderlet() + .new_primitive() .with_material( stage .new_material() @@ -1233,7 +1243,7 @@ mod test { .with_vertices(&geometry); let _mirror_rez = stage - .new_renderlet() + .new_primitive() .with_material( stage .new_material() diff --git a/crates/renderling/src/bits.rs b/crates/renderling/src/bits.rs deleted file mode 100644 index dafed727..00000000 --- a/crates/renderling/src/bits.rs +++ /dev/null @@ -1,343 +0,0 @@ -//! Helpers for bitwise operations. - -use core::ops::RangeInclusive; - -use crabslab::{Id, Slab}; - -/// Statically define a shift/mask range as a literal range of bits. -pub const fn bits(range: RangeInclusive) -> (u32, u32) { - let mut start = *range.start(); - let end = *range.end(); - let mut mask = 0; - while start <= end { - mask = (mask << 1) | 1; - start += 1; - } - (*range.start(), mask) -} - -/// Insert the value of the bits defined by the shift/mask range. -pub fn insert(bits: &mut u32, (shift, mask): (u32, u32), value: u32) { - // rotate right - if shift >= 1 { - *bits = (*bits >> shift) | (*bits << (32 - shift)); - } - // unset - *bits &= !mask; - // set - *bits |= value & mask; - // unrotate (rotate left) - if shift >= 1 { - *bits = (*bits << shift) | (*bits >> (32 - shift)); - } -} - -/// Extract the value of the bits defined by the shift/mask range. -pub fn extract(bits: u32, (shift, mask): (u32, u32)) -> u32 { - (bits >> shift) & mask -} - -/// The shift/mask range for the first 8 bits of a u32. -pub const U8_0_BITS: (u32, u32) = bits(0..=7); -/// The shift/mask range for the second 8 bits of a u32. -pub const U8_1_BITS: (u32, u32) = bits(8..=15); -/// The shift/mask range for the third 8 bits of a u32. -pub const U8_2_BITS: (u32, u32) = bits(16..=23); -/// The shift/mask range for the fourth 8 bits of a u32. -pub const U8_3_BITS: (u32, u32) = bits(24..=31); - -/// The shift/mask range for the first 16 bits of a u32. -pub const U16_0_BITS: (u32, u32) = bits(0..=15); -/// The shift/mask range for the second 16 bits of a u32. -pub const U16_1_BITS: (u32, u32) = bits(16..=31); - -/// Extract 8 bits of the u32 at the given index in the slab. -/// -/// Returns the extracted value, the index of the next component and the index -/// of the next u32 in the slab. -pub fn extract_u8( - // index of the u32 in the slab - u32_index: usize, - // eg 0 for the first 8 bits, 1 for the second 8 bits, etc - byte_offset: usize, - // slab of u32s - slab: &[u32], -) -> (u32, usize, usize) { - const SHIFT_MASKS: [((u32, u32), usize); 4] = [ - (U8_0_BITS, 0), - (U8_1_BITS, 0), - (U8_2_BITS, 0), - (U8_3_BITS, 1), - ]; - let byte_mod = byte_offset % 4; - let (shift_mask, index_inc) = SHIFT_MASKS[byte_mod]; - let u32_value = slab.read(Id::from(u32_index)); - let value = extract(u32_value, shift_mask); - (value, u32_index + index_inc, byte_mod + 1) -} - -/// Extract 8 bits of the u32 at the given index in the slab. -/// -/// Returns the extracted value, the index of the next component and the index -/// of the next u32 in the slab. -pub fn extract_i8( - // index of the u32 in the slab - u32_index: usize, - // eg 0 for the first 8 bits, 1 for the second 8 bits, etc - byte_offset: usize, - // slab of u32s - slab: &[u32], -) -> (i32, usize, usize) { - let (value, u32_index, n) = extract_u8(u32_index, byte_offset, slab); - let value: i32 = (value as i32 & 0xFF) - ((value as i32 & 0x80) << 1); - (value, u32_index, n) -} - -/// Extract 16 bits of the u32 at the given index in the slab. -pub fn extract_u16( - // index of the u32 in the slab - u32_index: usize, - // eg 0 for the first 16 bits, 2 for the second 16 bits, etc - byte_offset: usize, - // slab of u32s - slab: &[u32], -) -> (u32, usize, usize) { - // NOTE: This should only have two entries, but we'll still handle the case - // where the extraction is not aligned to a u32 boundary by reading as if it - // were, and then re-aligning. - const SHIFT_MASKS: [((u32, u32), usize, usize); 4] = [ - (U16_0_BITS, 2, 0), - (U16_0_BITS, 2, 0), - (U16_1_BITS, 0, 1), - (U16_1_BITS, 0, 1), - ]; - let byte_mod = byte_offset % 4; - crate::println!("byte_mod: {byte_mod}"); - let (shift_mask, next_byte_offset, index_inc) = SHIFT_MASKS[byte_mod]; - let u32_value = slab.read(Id::from(u32_index)); - crate::println!("u32: {:032b}", u32_value); - let value = extract(u32_value, shift_mask); - crate::println!("u16: {:016b}", value); - crate::println!("u32: {:?}", u32_value); - (value, u32_index + index_inc, next_byte_offset) -} - -/// Extract 16 bits of the u32 at the given index in the slab. -pub fn extract_i16( - // index of the u32 in the slab - u32_index: usize, - // eg 0 for the first 16 bits, 1 for the second 16 bits, etc - byte_offset: usize, - // slab of u32s - slab: &[u32], -) -> (i32, usize, usize) { - let (value, u32_index, n) = extract_u16(u32_index, byte_offset, slab); - let value: i32 = (value as i32 & 0xFFFF) - ((value as i32 & 0x8000) << 1); - (value, u32_index, n) -} - -/// Extract 32 bits of the u32 at the given index in the slab. -pub fn extract_u32( - // index of the u32 in the slab - u32_index: usize, - // ignored and always passed back as `0` - _byte_offset: usize, - // slab of u32s - slab: &[u32], -) -> (u32, usize, usize) { - (slab.read(Id::from(u32_index)), u32_index + 1, 0) -} - -/// Extract 32 bits of the u32 at the given index in the slab. -pub fn extract_i32( - // index of the u32 in the slab - u32_index: usize, - // ignored and always passed back as `0` - _byte_offset: usize, - // slab of u32s - slab: &[u32], -) -> (i32, usize, usize) { - let (value, _, _) = extract_u32(u32_index, 0, slab); - (value as i32, u32_index + 1, 0) -} - -/// Extract 32 bits of the u32 at the given index in the slab. -pub fn extract_f32( - // index of the u32 in the slab - u32_index: usize, - // ignored and always passed back as `0` - _byte_offset: usize, - // slab of u32s - slab: &[u32], -) -> (f32, usize, usize) { - let (value, _, _) = extract_u32(u32_index, 0, slab); - (f32::from_bits(value), u32_index + 1, 0) -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn bits_sanity() { - let mut store = 0; - assert_eq!( - "00000000000000000000000000000000", - &format!("{:032b}", store) - ); - insert(&mut store, bits(0..=7), u8::MAX as u32); - assert_eq!( - "00000000000000000000000011111111", - &format!("{:032b}", store) - ); - store = 0; - insert(&mut store, bits(8..=15), u8::MAX as u32); - assert_eq!( - "00000000000000001111111100000000", - &format!("{:032b}", store) - ); - } - - #[test] - fn bits_u8_sanity() { - let mut bits = 0; - println!("bits: {:032b}", bits); - super::insert(&mut bits, super::U8_0_BITS, 6u8 as u32); - println!("bits: {:032b}", bits); - assert_eq!(super::extract(bits, super::U8_0_BITS), 6); - super::insert(&mut bits, super::U8_1_BITS, 5u8 as u32); - println!("bits: {:032b}", bits); - assert_eq!(super::extract(bits, super::U8_0_BITS), 6); - assert_eq!(super::extract(bits, super::U8_1_BITS), 5); - super::insert(&mut bits, super::U8_2_BITS, 4u8 as u32); - println!("bits: {:032b}", bits); - assert_eq!(super::extract(bits, super::U8_0_BITS), 6); - assert_eq!(super::extract(bits, super::U8_1_BITS), 5); - assert_eq!(super::extract(bits, super::U8_2_BITS), 4); - super::insert(&mut bits, super::U8_3_BITS, 3u8 as u32); - println!("bits: {:032b}", bits); - assert_eq!(super::extract(bits, super::U8_0_BITS), 6); - assert_eq!(super::extract(bits, super::U8_1_BITS), 5); - assert_eq!(super::extract(bits, super::U8_2_BITS), 4); - assert_eq!(super::extract(bits, super::U8_3_BITS), 3); - } - - #[test] - fn extract_u8_sanity() { - let u8_slab = [0u8, 1u8, 2u8, 3u8, 4u8, 5u8, 0u8, 0u8]; - let u32_slab: &[u32] = bytemuck::cast_slice(&u8_slab); - let index = 0; - let n = 0; - let (a, index, n) = extract_u8(index, n, u32_slab); - let (b, index, n) = extract_u8(index, n, u32_slab); - let (c, index, n) = extract_u8(index, n, u32_slab); - let (d, index, n) = extract_u8(index, n, u32_slab); - let (e, index, n) = extract_u8(index, n, u32_slab); - let (f, _, _) = extract_u8(index, n, u32_slab); - assert_eq!([0, 1, 2, 3, 4, 5], [a, b, c, d, e, f]); - } - - #[test] - fn extract_i8_sanity() { - let i8_slab = [0i8, -1i8, -2i8, -3i8, 4i8, 5i8, 0i8, 0i8]; - let u32_slab: &[u32] = bytemuck::cast_slice(&i8_slab); - let index = 0; - let n = 0; - let (a, index, n) = extract_i8(index, n, u32_slab); - let (b, index, n) = extract_i8(index, n, u32_slab); - let (c, index, n) = extract_i8(index, n, u32_slab); - let (d, index, n) = extract_i8(index, n, u32_slab); - let (e, index, n) = extract_i8(index, n, u32_slab); - let (f, _, _) = extract_i8(index, n, u32_slab); - assert_eq!([0, -1, -2, -3, 4, 5], [a, b, c, d, e, f]); - } - - #[test] - fn extract_u16_sanity() { - let u16_slab = [0u16, 1u16, 2u16, 3u16, 4u16, 5u16]; - let u32_slab: &[u32] = bytemuck::cast_slice(&u16_slab); - let index = 0; - let n = 0; - let (a, index, n) = extract_u16(index, n, u32_slab); - let (b, index, n) = extract_u16(index, n, u32_slab); - let (c, index, n) = extract_u16(index, n, u32_slab); - let (d, index, n) = extract_u16(index, n, u32_slab); - let (e, index, n) = extract_u16(index, n, u32_slab); - let (f, _, _) = extract_u16(index, n, u32_slab); - assert_eq!([0, 1, 2, 3, 4, 5], [a, b, c, d, e, f]); - } - - #[test] - fn extract_i16_sanity() { - let i16_slab = [0i16, -1i16, -2i16, -3i16, 4i16, 5i16, -12345i16, 0i16]; - let u32_slab: &[u32] = bytemuck::cast_slice(&i16_slab); - let index = 0; - let n = 0; - let (a, index, n) = extract_i16(index, n, u32_slab); - let (b, index, n) = extract_i16(index, n, u32_slab); - let (c, index, n) = extract_i16(index, n, u32_slab); - let (d, index, n) = extract_i16(index, n, u32_slab); - let (e, index, n) = extract_i16(index, n, u32_slab); - let (f, index, n) = extract_i16(index, n, u32_slab); - let (g, _, _) = extract_i16(index, n, u32_slab); - assert_eq!([0, -1, -2, -3, 4, 5, -12345], [a, b, c, d, e, f, g]); - } - - #[test] - fn extract_u32_sanity() { - let u32_slab = [0u32, 1u32, 2u32, 3u32, 4u32, 5u32]; - let u32_slab: &[u32] = bytemuck::cast_slice(&u32_slab); - let index = 0; - let n = 0; - let (a, index, n) = extract_u32(index, n, u32_slab); - let (b, index, n) = extract_u32(index, n, u32_slab); - let (c, index, n) = extract_u32(index, n, u32_slab); - let (d, index, n) = extract_u32(index, n, u32_slab); - let (e, index, n) = extract_u32(index, n, u32_slab); - let (f, _, _) = extract_u32(index, n, u32_slab); - assert_eq!([0, 1, 2, 3, 4, 5], [a, b, c, d, e, f]); - } - - #[test] - fn extract_i32_sanity() { - let i32_slab = [0i32, -1i32, -2i32, -3i32, 4i32, 5i32, -12345i32]; - let u32_slab: &[u32] = bytemuck::cast_slice(&i32_slab); - let index = 0; - let n = 0; - let (a, index, n) = extract_i32(index, n, u32_slab); - let (b, index, n) = extract_i32(index, n, u32_slab); - let (c, index, n) = extract_i32(index, n, u32_slab); - let (d, index, n) = extract_i32(index, n, u32_slab); - let (e, index, n) = extract_i32(index, n, u32_slab); - let (f, index, n) = extract_i32(index, n, u32_slab); - let (g, _, _) = extract_i32(index, n, u32_slab); - assert_eq!([0, -1, -2, -3, 4, 5, -12345], [a, b, c, d, e, f, g]); - } - - #[test] - fn extract_f32_sanity() { - let f32_slab = [ - 0.0f32, - -1.0f32, - -2.0f32, - -3.0f32, - 4.0f32, - 5.0f32, - -12345.0f32, - ]; - let u32_slab: &[u32] = bytemuck::cast_slice(&f32_slab); - let index = 0; - let n = 0; - let (a, index, n) = extract_f32(index, n, u32_slab); - let (b, index, n) = extract_f32(index, n, u32_slab); - let (c, index, n) = extract_f32(index, n, u32_slab); - let (d, index, n) = extract_f32(index, n, u32_slab); - let (e, index, n) = extract_f32(index, n, u32_slab); - let (f, index, n) = extract_f32(index, n, u32_slab); - let (g, _, _) = extract_f32(index, n, u32_slab); - assert_eq!( - [0f32, -1f32, -2f32, -3f32, 4f32, 5f32, -12345f32], - [a, b, c, d, e, f, g] - ); - } -} diff --git a/crates/renderling/src/bvol.rs b/crates/renderling/src/bvol.rs index 026d9de3..7106eb81 100644 --- a/crates/renderling/src/bvol.rs +++ b/crates/renderling/src/bvol.rs @@ -141,7 +141,7 @@ impl Aabb { self.min == self.max } - /// Returns the union of the two [`Aabbs`]. + /// Returns the union of the two [`Aabb`]s. pub fn union(a: Self, b: Self) -> Self { Aabb { min: a.min.min(a.max).min(b.min).min(b.max), @@ -226,7 +226,7 @@ pub struct Frustum { } impl Frustum { - /// Compute a frustum in world space from the given [`Camera`]. + /// Compute a frustum in world space from the given [`CameraDescriptor`]. pub fn from_camera(camera: &CameraDescriptor) -> Self { let viewprojection = camera.view_projection(); let mvp = viewprojection.to_cols_array_2d(); @@ -672,7 +672,7 @@ mod test { .new_material() .with_albedo_factor(Vec4::new(1.0, 0.0, 0.0, 1.0)); - let _w = stage.new_renderlet().with_material(&white).with_vertices( + let _w = stage.new_primitive().with_material(&white).with_vertices( stage.new_vertices( crate::math::unit_cube() .into_iter() @@ -700,7 +700,7 @@ mod test { ); rs.push( - stage.new_renderlet().with_material(&red).with_vertices( + stage.new_primitive().with_material(&red).with_vertices( stage.new_vertices( bb.get_mesh() .map(|(p, n)| Vertex::default().with_position(p).with_normal(n)), diff --git a/crates/renderling/src/cubemap/cpu.rs b/crates/renderling/src/cubemap/cpu.rs index 6c93a62f..10542b4b 100644 --- a/crates/renderling/src/cubemap/cpu.rs +++ b/crates/renderling/src/cubemap/cpu.rs @@ -71,7 +71,7 @@ impl SceneCubemap { view_formats: &[], }); let depth_texture = Texture::create_depth_texture(device, size.x, size.y, 1, label); - let pipeline = Arc::new(Stage::create_renderlet_pipeline(device, format, 1)); + let pipeline = Arc::new(Stage::create_primitive_pipeline(device, format, 1)); Self { pipeline, cubemap_texture, @@ -294,7 +294,7 @@ mod test { .with_projection_and_view(projection, view); // geometry is the "clip cube" where colors are normalized 3d space coords let _rez = stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(UNIT_POINTS.map(|unit_cube_point| { Vertex::default() // multiply by 2.0 because the unit cube's AABB bounds are at 0.5, and we want 1.0 diff --git a/crates/renderling/src/cull.rs b/crates/renderling/src/cull.rs index 74fc0b61..832e4117 100644 --- a/crates/renderling/src/cull.rs +++ b/crates/renderling/src/cull.rs @@ -12,7 +12,7 @@ use spirv_std::{ spirv, }; -use crate::{draw::DrawIndirectArgs, geometry::GeometryDescriptor, stage::RenderletDescriptor}; +use crate::{draw::DrawIndirectArgs, geometry::GeometryDescriptor, stage::PrimitiveDescriptor}; #[cfg(not(target_arch = "spirv"))] mod cpu; @@ -34,16 +34,16 @@ pub fn compute_culling( crate::println!("gid: {gid}"); // Get the draw arg let arg = unsafe { args.index_unchecked_mut(gid) }; - // Get the renderlet using the draw arg's renderlet id - let renderlet_id = Id::::new(arg.first_instance); - let renderlet = stage_slab.read_unchecked(renderlet_id); - crate::println!("renderlet: {renderlet_id:?}"); + // Get the primitive using the draw arg's primitive id + let primitive_id = Id::::new(arg.first_instance); + let primitive = stage_slab.read_unchecked(primitive_id); + crate::println!("primitive: {primitive_id:?}"); - arg.vertex_count = renderlet.get_vertex_count(); - arg.instance_count = if renderlet.visible { 1 } else { 0 }; + arg.vertex_count = primitive.get_vertex_count(); + arg.instance_count = if primitive.visible { 1 } else { 0 }; - if renderlet.bounds.radius == 0.0 { - crate::println!("renderlet bounding radius is zero, cannot cull"); + if primitive.bounds.radius == 0.0 { + crate::println!("primitive bounding radius is zero, cannot cull"); return; } @@ -53,14 +53,14 @@ pub fn compute_culling( } let camera = stage_slab.read(config.camera_id); - let model = stage_slab.read(renderlet.transform_id); + let model = stage_slab.read(primitive.transform_id); // Compute frustum culling, and then occlusion culling, if need be - let (renderlet_is_inside_frustum, sphere_in_world_coords) = - renderlet.bounds.is_inside_camera_view(&camera, model); + let (primitive_is_inside_frustum, sphere_in_world_coords) = + primitive.bounds.is_inside_camera_view(&camera, model); - if renderlet_is_inside_frustum { + if primitive_is_inside_frustum { arg.instance_count = 1; - crate::println!("renderlet is inside frustum"); + crate::println!("primitive is inside frustum"); crate::println!("znear: {}", camera.frustum().planes[0]); crate::println!(" zfar: {}", camera.frustum().planes[5]); if !config.perform_occlusion_culling { @@ -79,7 +79,7 @@ pub fn compute_culling( } else { size_in_pixels.y }; - crate::println!("renderlet size in pixels: {size_in_pixels}"); + crate::println!("primitive size in pixels: {size_in_pixels}"); let mip_level = size_in_pixels.log2().floor() as u32; let max_mip_level = hzb_desc.mip.len() as u32 - 1; @@ -109,10 +109,10 @@ pub fn compute_culling( let depth_of_sphere = sphere_aabb.min.z; crate::println!("depth_of_sphere: {depth_of_sphere}"); - let renderlet_is_behind_something = depth_of_sphere > depth_in_hzb; - let renderlet_surrounds_camera = depth_of_sphere > 1.0; + let primitive_is_behind_something = depth_of_sphere > depth_in_hzb; + let primitive_surrounds_camera = depth_of_sphere > 1.0; - if renderlet_is_behind_something || renderlet_surrounds_camera { + if primitive_is_behind_something || primitive_surrounds_camera { crate::println!("CULLED"); arg.instance_count = 0; } diff --git a/crates/renderling/src/cull/cpu.rs b/crates/renderling/src/cull/cpu.rs index 9815039c..d2abb113 100644 --- a/crates/renderling/src/cull/cpu.rs +++ b/crates/renderling/src/cull/cpu.rs @@ -689,7 +689,7 @@ mod test { Mat4::look_at_rh(camera_position, Vec3::ZERO, Vec3::Y), ); let _rez = stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(crate::test::gpu_cube_vertices())) .with_transform( stage @@ -804,7 +804,7 @@ mod test { }; // A hashmap to hold renderlet ids to their names. - let mut names = HashMap::, String>::default(); + let mut names = HashMap::, String>::default(); // Add four yellow cubes in each corner let _ycubes = [ @@ -816,7 +816,7 @@ mod test { .map(|(offset, suffix)| { let yellow = hex_to_vec4(0xFFE6A5FF); let renderlet = stage - .new_renderlet() + .new_primitive() .with_transform( stage .new_transform() @@ -844,7 +844,7 @@ mod test { let _floor = { let golden = hex_to_vec4(0xFFBF61FF); let renderlet = stage - .new_renderlet() + .new_primitive() .with_transform( stage .new_transform() @@ -872,7 +872,7 @@ mod test { let _gcube = { let green = hex_to_vec4(0x8ABFA3FF); let renderlet = stage - .new_renderlet() + .new_primitive() .with_transform( stage .new_transform() @@ -890,7 +890,7 @@ mod test { }, ))) .with_bounds(BoundingSphere::new(Vec3::ZERO, Vec3::splat(0.5).length())); - stage.add_renderlet(&renderlet); + stage.add_primitive(&renderlet); names.insert(renderlet.id(), "green_cube".into()); renderlet }; @@ -901,7 +901,7 @@ mod test { let _pcube = { let purple = hex_to_vec4(0x605678FF); let renderlet = stage - .new_renderlet() + .new_primitive() .with_transform( stage .new_transform() @@ -988,7 +988,7 @@ mod test { } for i in 0..num_draw_calls as u32 { - let renderlet_id = Id::::new(args[i as usize].first_instance); + let renderlet_id = Id::::new(args[i as usize].first_instance); let name = names.get(&renderlet_id).unwrap(); if name != "green_cube" { continue; diff --git a/crates/renderling/src/debug.rs b/crates/renderling/src/debug.rs index bd7a1b9f..cb52719a 100644 --- a/crates/renderling/src/debug.rs +++ b/crates/renderling/src/debug.rs @@ -4,7 +4,7 @@ use glam::{Vec2, Vec3Swizzles, Vec4, Vec4Swizzles}; use spirv_std::{arch::IndexUnchecked, spirv}; use crate::{ - draw::DrawIndirectArgs, geometry::GeometryDescriptor, sdf, stage::RenderletDescriptor, + draw::DrawIndirectArgs, geometry::GeometryDescriptor, sdf, stage::PrimitiveDescriptor, transform::TransformDescriptor, }; @@ -42,12 +42,12 @@ pub fn debug_overlay_fragment( for i in 0..draw_calls.len() { let draw_call = unsafe { draw_calls.index_unchecked(i) }; - let renderlet_id = Id::::new(draw_call.first_instance); + let renderlet_id = Id::::new(draw_call.first_instance); let transform_id = - slab.read_unchecked(renderlet_id + RenderletDescriptor::OFFSET_OF_TRANSFORM_ID); + slab.read_unchecked(renderlet_id + PrimitiveDescriptor::OFFSET_OF_TRANSFORM_ID); let mut model = TransformDescriptor::IDENTITY; slab.read_into_if_some(transform_id, &mut model); - let bounds = slab.read_unchecked(renderlet_id + RenderletDescriptor::OFFSET_OF_BOUNDS); + let bounds = slab.read_unchecked(renderlet_id + PrimitiveDescriptor::OFFSET_OF_BOUNDS); let (_, sphere_in_world_coords) = bounds.is_inside_camera_view(&camera, model); let sphere_aabb = sphere_in_world_coords.project_onto_viewport( diff --git a/crates/renderling/src/draw.rs b/crates/renderling/src/draw.rs index d2990b7a..09ccf3b4 100644 --- a/crates/renderling/src/draw.rs +++ b/crates/renderling/src/draw.rs @@ -1,7 +1,7 @@ //! Handles queueing draw calls. //! //! [`DrawCalls`] is used to maintain the list of all staged -//! [`Renderlet`](crate::prelude::Renderlet)s. +//! [`PrimitiveDescriptor`](crate::stage::PrimitiveDescriptor)s. //! It also performs frustum culling and issues draw calls during //! [`Stage::render`](crate::prelude::Stage::render). use crabslab::SlabItem; diff --git a/crates/renderling/src/draw/cpu.rs b/crates/renderling/src/draw/cpu.rs index 4d85d4e1..f4d781f8 100644 --- a/crates/renderling/src/draw/cpu.rs +++ b/crates/renderling/src/draw/cpu.rs @@ -8,7 +8,7 @@ use crabslab::Id; use crate::{ cull::{ComputeCulling, CullingError}, - stage::{Renderlet, RenderletDescriptor}, + stage::{Primitive, PrimitiveDescriptor}, texture::Texture, Context, }; @@ -65,8 +65,8 @@ impl IndirectDraws { } } -impl From> for DrawIndirectArgs { - fn from(id: Id) -> Self { +impl From> for DrawIndirectArgs { + fn from(id: Id) -> Self { // This is obviously incomplete, but that's ok because // the rest of this struct is filled out on the GPU during // culling. @@ -98,10 +98,10 @@ impl DrawingStrategy { } /// Used to determine which objects are drawn and maintains the -/// list of all [`Renderlet`]s. +/// list of all [`Primitive`]s. pub struct DrawCalls { /// Internal representation of all staged renderlets. - renderlets: Vec, + renderlets: Vec, pub(crate) drawing_strategy: DrawingStrategy, } @@ -157,7 +157,7 @@ impl DrawCalls { /// Add a renderlet to the drawing queue. /// /// Returns the number of draw calls in the queue. - pub fn add_renderlet(&mut self, renderlet: &Renderlet) -> usize { + pub fn add_primitive(&mut self, renderlet: &Primitive) -> usize { log::trace!("adding renderlet {:?}", renderlet.id()); if let Some(indirect) = &mut self.drawing_strategy.indirect { indirect.invalidate(); @@ -170,7 +170,7 @@ impl DrawCalls { /// drawn each frame. /// /// Returns the number of draw calls remaining in the queue. - pub fn remove_renderlet(&mut self, renderlet: &Renderlet) -> usize { + pub fn remove_primitive(&mut self, renderlet: &Primitive) -> usize { let id = renderlet.id(); self.renderlets.retain(|ir| ir.descriptor.id() != id); @@ -181,8 +181,8 @@ impl DrawCalls { self.renderlets.len() } - /// Sort draw calls using a function compairing [`RenderletSortItem`]s. - pub fn sort_renderlets(&mut self, f: impl Fn(&Renderlet, &Renderlet) -> std::cmp::Ordering) { + /// Sort draw calls using a function compairing [`Primitive`]s. + pub fn sort_primitives(&mut self, f: impl Fn(&Primitive, &Primitive) -> std::cmp::Ordering) { self.renderlets.sort_by(f); if let Some(indirect) = &mut self.drawing_strategy.indirect { indirect.invalidate(); diff --git a/crates/renderling/src/geometry/cpu.rs b/crates/renderling/src/geometry/cpu.rs index 3ea55abe..267e6347 100644 --- a/crates/renderling/src/geometry/cpu.rs +++ b/crates/renderling/src/geometry/cpu.rs @@ -89,6 +89,24 @@ impl Vertices { inner: self.inner.into_gpu_only(), } } + + /// Returns a [`Vertex`] at a specific index, if any. + pub fn get(&self, index: usize) -> Option { + self.inner.get(index) + } + + /// Return all vertices as a vector. + pub fn get_vec(&self) -> Vec { + self.inner.get_vec() + } + + /// Set the [`Vertex`] at the given index to the given value, if the item at + /// the index exists. + /// + /// Returns the previous value, if any. + pub fn set_item(&self, index: usize, value: Vertex) -> Option { + self.inner.set_item(index, value) + } } impl Vertices @@ -171,9 +189,6 @@ impl Indices { } /// Unload the CPU side of this index data. - /// - /// After this operation the data can still be updated using [`Indices::set_item`], - /// but it cannot be modified in-place. pub fn into_gpu_only(self) -> Indices { Indices { inner: self.inner.into_gpu_only(), @@ -483,7 +498,7 @@ impl Skin { /// from either of those types using the [`From`] trait. /// /// You can also pass an iterator of either [`Transform`] or [`NestedTransform`] -/// to [`Stage::new_skin`]. +/// to [`Stage::new_skin`](crate::stage::Stage::new_skin). pub struct SkinJoint(pub(crate) Transform); impl From for SkinJoint { diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index b2d64f35..549d0806 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -60,59 +60,53 @@ //! [`Stage::render`](crate::stage::Stage::render). //! //! Use one of the many `Stage::new_*` functions to stage data on the GPU: -//! * [`Stage::new_camera`] -//! * [`Stage::new_vertices`] -//! * [`Stage::new_material`] -//! * [`Stage::new_renderlet`] +//! * [`Stage::new_camera`](crate::stage::Stage::new_camera) +//! * [`Stage::new_vertices`](crate::stage::Stage::new_vertices) +//! * [`Stage::new_indices`](crate::stage::Stage::new_indices) +//! * [`Stage::new_material`](crate::stage::Stage::new_material) +//! * [`Stage::new_primitive`](crate::stage::Stage::new_primitive) //! * ...and more //! -//! Many of these functions return [`Hybrid`](crate::prelude::Hybrid)s or -//! [`HybridArray`](crate::prelude::HybridArray)s in return. -//! //! In order to render, we need to "stage" a -//! [`Renderlet`](crate::stage::Renderlet), which is a bundle of rendering +//! [`Primitive`](crate::stage::Primitive), which is a bundle of rendering //! resources, roughly representing a singular mesh. //! -//! But first we'll need a [`Camera`](crate::camera::Camera) so we can see -//! what's on the stage, and then we'll need a list -//! of [`Vertex`](crate::stage::Vertex) organized as triangles with -//! counter-clockwise winding. Here we'll use the builder pattern to create a -//! staged [`Renderlet`](crate::stage::Renderlet) using our vertices. +//! But first we'll need a list of [`Vertex`](crate::geometry::Vertex) organized +//! as triangles with counter-clockwise winding. Here we'll use the builder +//! pattern to create a staged [`Primitive`](crate::stage::Primitive) using our +//! vertices. +//! +//! We'll also create a [`Camera`](crate::camera::Camera) so we can see the +//! stage. //! //! ``` //! # use renderling::prelude::*; //! # let ctx = futures_lite::future::block_on(Context::headless(100, 100)); //! # let stage: Stage = ctx.new_stage(); +//! let vertices = stage.new_vertices([ +//! Vertex::default() +//! .with_position([0.0, 0.0, 0.0]) +//! .with_color([0.0, 1.0, 1.0, 1.0]), +//! Vertex::default() +//! .with_position([0.0, 100.0, 0.0]) +//! .with_color([1.0, 1.0, 0.0, 1.0]), +//! Vertex::default() +//! .with_position([100.0, 0.0, 0.0]) +//! .with_color([1.0, 0.0, 1.0, 1.0]), +//! ]); +//! let triangle_prim = stage +//! .new_primitive() +//! .with_vertices(vertices); //! -//! let camera = stage.new_camera(Camera::default_ortho2d(100.0, 100.0)); -//! let (vertices, triangle_renderlet) = stage -//! .builder() -//! .with_vertices([ -//! Vertex::default() -//! .with_position([0.0, 0.0, 0.0]) -//! .with_color([0.0, 1.0, 1.0, 1.0]), -//! Vertex::default() -//! .with_position([0.0, 100.0, 0.0]) -//! .with_color([1.0, 1.0, 0.0, 1.0]), -//! Vertex::default() -//! .with_position([100.0, 0.0, 0.0]) -//! .with_color([1.0, 0.0, 1.0, 1.0]), -//! ]) -//! .build(); +//! let (projection, view) = renderling::camera::default_ortho2d(100.0, 100.0); +//! let camera = stage.new_camera() +//! .with_projection_and_view(projection, view); //! ``` //! -//! The builder is of the type [`RenderletBuilder`](crate::stage::RenderletBuilder) -//! and after building, it leaves you with all the resources that have been staged, -//! including the `Renderlet`. -//! The return type of [`RenderletBuilder::build`](crate::stage::RenderletBuilder::build) -//! is special in that it depends on the new resources that have been staged. -//! The type will be a tuple of all the newly staged resources that have been added. -//! In this case it's our mesh data and the `Renderlet`. -//! //! ### Rendering //! //! Finally, we get the next frame from the context with -//! [`Context::get_next_frame`], render to it using +//! [`Context::get_next_frame`]. Then we render to it using //! [`Stage::render`](crate::stage::Stage::render) and then present the //! frame with [`Frame::present`]. //! @@ -120,8 +114,10 @@ //! # use renderling::prelude::*; //! # let ctx = futures_lite::future::block_on(Context::headless(100, 100)); //! # let stage = ctx.new_stage(); -//! # let _camera = stage.new_camera(Camera::default_ortho2d(100.0, 100.0)); -//! # let _rez = stage.builder().with_vertices([ +//! # let (projection, view) = renderling::camera::default_ortho2d(100.0, 100.0); +//! # let camera = stage.new_camera() +//! # .with_projection_and_view(projection, view); +//! # let vertices = stage.new_vertices([ //! # Vertex::default() //! # .with_position([0.0, 0.0, 0.0]) //! # .with_color([0.0, 1.0, 1.0, 1.0]), @@ -131,25 +127,57 @@ //! # Vertex::default() //! # .with_position([100.0, 0.0, 0.0]) //! # .with_color([1.0, 0.0, 1.0, 1.0]), -//! # ]).build(); -//! +//! # ]); +//! # let triangle_prim = stage +//! # .new_primitive() +//! # .with_vertices(vertices); //! let frame = ctx.get_next_frame().unwrap(); //! stage.render(&frame.view()); //! let img = futures_lite::future::block_on(frame.read_image()).unwrap(); //! frame.present(); //! ``` //! +//! Here for our purposes we also read the rendered frame as an image. //! Saving `img` should give us this: //! -//! ![renderling hello triangle](https://github.com/schell/renderling/blob/main/test_img/cmy_triangle.png?raw=true) +//! ![renderling hello triangle](https://github.com/schell/renderling/blob/main/test_img/cmy_triangle/hdr.png?raw=true) //! //! ### Modifying //! -//! Later, if we want to modify any of the staged values, we can do so through -//! [`Hybrid`](crate::prelude::Hybrid) and [`HybridArray`](crate::prelude::HybridArray). -//! The changes made will be synchronized to the GPU at the beginning of the +//! Later, if we want to modify any of the staged values, we can do so through each resource's +//! struct, using `set_*`, `modify_*` and `with_*` functions. +//! +//! The changes made will be synchronized to the GPU at the beginning of the next //! [`Stage::render`](crate::prelude::Stage::render) function. //! +//! ### Removing primitives +//! +//! To remove primitives from the stage, use +//! [`Stage::remove_primitive`](crate::stage::Stage::remove_primitive). This +//! will remove the primitive from rendering entirely. +//! +//! If you just want to mark a [`Primitive`](crate::stage::Primitive) invisible, use +//! [`Primitive::set_visible`](crate::stage::Primitive::set_visible). +//! +//! ### Releasing resources +//! +//! GPU resources are automatically released when dropped. The data they +//! occupy on the GPU is reclaimed during calls to +//! [`Stage::render`](crate::stage::Stage::render). If you would like to +//! manually reclaim resources without rendering, you can do so with +//! [`Stage::commit`](crate::stage::Stage::commit). +//! +//! [`Primitive`](crate::stage::Primitive) and +//! [`AnalyticalLight`](crate::light::AnalyticalLight) are special in that you +//! must remove them from the [`Stage`](crate::stage::Stage) explicitly, because +//! clones are made internally. +//! +//! Other resources like [`Vertices`](crate::geometry::Vertices), +//! [`Indices`](crate::geometry::Indices), +//! [`Transform`](crate::transform::Transform), +//! [`NestedTransform`](crate::transform::NestedTransform) and others can simply +//! be dropped. +//! //! # WARNING //! //! This is very much a work in progress. @@ -165,8 +193,7 @@ pub mod atlas; #[cfg(cpu)] -pub mod bindgroup; -pub mod bits; +pub(crate) mod bindgroup; pub mod bloom; pub mod bvol; pub mod camera; @@ -384,7 +411,7 @@ mod test { let _camera = stage.new_camera().with_projection_and_view(p, v); let _prim = stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(right_tri_vertices())); let frame = ctx.get_next_frame().unwrap(); @@ -423,7 +450,7 @@ mod test { let stage = ctx.new_stage().with_background_color(Vec4::splat(1.0)); let (p, v) = crate::camera::default_ortho2d(100.0, 100.0); let _camera = stage.new_camera().with_projection_and_view(p, v); - let _rez = stage.new_renderlet().with_vertices(stage.new_vertices({ + let _rez = stage.new_primitive().with_vertices(stage.new_vertices({ let mut vs = right_tri_vertices(); vs.reverse(); vs @@ -453,7 +480,7 @@ mod test { let _camera = stage.new_camera().with_projection_and_view(p, v); let transform = stage.new_transform(); let _renderlet = stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(right_tri_vertices())) .with_transform(&transform); @@ -520,7 +547,7 @@ mod test { Mat4::look_at_rh(camera_position, Vec3::ZERO, Vec3::Y), ); let _rez = stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(gpu_cube_vertices())) .with_transform( stage @@ -547,7 +574,7 @@ mod test { ); let _rez = stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(math::UNIT_POINTS.map(cmy_gpu_vertex))) .with_indices(stage.new_indices(math::UNIT_INDICES.map(|i| i as u32))) .with_transform( @@ -582,7 +609,7 @@ mod test { .with_projection_and_view(projection, view); let geometry = stage.new_vertices(gpu_cube_vertices()); let _cube_one = stage - .new_renderlet() + .new_primitive() .with_vertices(&geometry) .with_transform( stage @@ -593,7 +620,7 @@ mod test { ); let cube_two = stage - .new_renderlet() + .new_primitive() .with_vertices(&geometry) .with_transform( stage @@ -645,7 +672,7 @@ mod test { .new_camera() .with_projection_and_view(projection, view); let cube = stage - .new_renderlet() + .new_primitive() .with_vertices( stage .new_vertices(math::UNIT_INDICES.map(|i| cmy_gpu_vertex(math::UNIT_POINTS[i]))), @@ -743,7 +770,7 @@ mod test { .with_albedo_texture(&entries[0]) .with_has_lighting(false); let cube = stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(gpu_uv_unit_cube())) .with_transform( stage @@ -820,7 +847,7 @@ mod test { ..Default::default() }, ]); - let _color_prim = stage.new_renderlet().with_vertices(&geometry); + let _color_prim = stage.new_primitive().with_vertices(&geometry); let material = stage .new_material() @@ -831,7 +858,7 @@ mod test { .with_translation(Vec3::new(15.0, 35.0, 0.5)) .with_scale(Vec3::new(0.5, 0.5, 1.0)); let _rez = stage - .new_renderlet() + .new_primitive() .with_vertices(&geometry) .with_material(material) .with_transform(transform); @@ -877,7 +904,7 @@ mod test { .with_intensity(10.0); let _rez = stage - .new_renderlet() + .new_primitive() .with_material(stage.default_material()); let frame = ctx.get_next_frame().unwrap(); @@ -973,7 +1000,7 @@ mod test { ] }); let _cyan_primitive = stage - .new_renderlet() + .new_primitive() .with_vertices(&geometry) .with_material( stage @@ -983,7 +1010,7 @@ mod test { ) .with_transform(&cyan_node); let _yellow_primitive = stage - .new_renderlet() + .new_primitive() .with_vertices(&geometry) .with_material( stage @@ -993,7 +1020,7 @@ mod test { ) .with_transform(&yellow_node); let _red_primitive = stage - .new_renderlet() + .new_primitive() .with_vertices(&geometry) .with_material( stage @@ -1032,7 +1059,7 @@ mod test { Mat4::look_at_rh(camera_position, Vec3::ZERO, Vec3::Y), ); let _rez = stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(gpu_cube_vertices())) .with_transform( stage @@ -1075,7 +1102,7 @@ mod test { Mat4::look_at_rh(camera_position, Vec3::ZERO, Vec3::Y), ); let _rez = stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(gpu_cube_vertices())) .with_transform( stage diff --git a/crates/renderling/src/light.rs b/crates/renderling/src/light.rs index 268d7a99..b553c453 100644 --- a/crates/renderling/src/light.rs +++ b/crates/renderling/src/light.rs @@ -16,7 +16,7 @@ use crate::{ cubemap::{CubemapDescriptor, CubemapFaceDirection}, geometry::GeometryDescriptor, math::{Fetch, IsSampler, IsVector, Sample2dArray}, - stage::{RenderletDescriptor, VertexInfo}, + stage::{PrimitiveDescriptor, VertexInfo}, transform::TransformDescriptor, }; @@ -90,7 +90,7 @@ impl Default for ShadowMapDescriptor { #[cfg(test)] #[derive(Default, Debug, Clone, Copy, PartialEq)] pub struct ShadowMappingVertexInfo { - pub renderlet_id: Id, + pub renderlet_id: Id, pub vertex_index: u32, pub vertex: crate::geometry::Vertex, pub transform: TransformDescriptor, @@ -117,7 +117,7 @@ pub struct ShadowMappingVertexInfo { #[allow(clippy::too_many_arguments)] pub fn shadow_mapping_vertex( // Points at a `Renderlet` - #[spirv(instance_index)] renderlet_id: Id, + #[spirv(instance_index)] renderlet_id: Id, // Which vertex within the renderlet are we rendering #[spirv(vertex_index)] vertex_index: u32, // The slab where the renderlet's geometry is staged @@ -784,22 +784,21 @@ impl ShadowCalculation { /// Depth pre-pass for the light tiling feature. /// -/// This shader writes all staged [`Renderlet`]'s depth into a buffer. +/// This shader writes all staged [`PrimitiveDescriptor`]'s depth into a buffer. /// /// This shader is very much like [`shadow_mapping_vertex`], except that /// shader gets its projection+view matrix from the light stored in a /// `ShadowMapDescriptor`. /// -/// Here we want to render as normal forward pass would, with the `Renderlet`'s view -/// and the [`Camera`]'s projection. -/// +/// Here we want to render as normal forward pass would, with the `PrimitiveDescriptor` +/// and the `Camera`'s view projection matrix. /// ## Note /// This shader will likely be expanded to include parts of occlusion culling and order /// independent transparency. #[spirv(vertex)] pub fn light_tiling_depth_pre_pass( // Points at a `Renderlet`. - #[spirv(instance_index)] renderlet_id: Id, + #[spirv(instance_index)] renderlet_id: Id, // Which vertex within the renderlet are we rendering? #[spirv(vertex_index)] vertex_index: u32, // The slab where the renderlet's geometry is staged @@ -858,7 +857,7 @@ impl core::fmt::Debug for LightTile { /// them into lists that illuminate tiles of the screen. #[derive(Clone, Copy, SlabItem, core::fmt::Debug)] pub struct LightTilingDescriptor { - /// Size of the [`Stage`]'s depth texture. + /// Size of the [`Stage`](crate::stage::Stage)'s depth texture. pub depth_texture_size: UVec2, /// Configurable tile size. pub tile_size: u32, diff --git a/crates/renderling/src/light/cpu.rs b/crates/renderling/src/light/cpu.rs index 03d8c26c..844beef0 100644 --- a/crates/renderling/src/light/cpu.rs +++ b/crates/renderling/src/light/cpu.rs @@ -520,7 +520,7 @@ impl IsLight for Light { /// A bundle of lighting resources representing one analytical light in a scene. /// -/// Create an `AnalyticalLightBundle` with the `Lighting::new_analytical_light`, +/// Create an `AnalyticalLight` with the `Lighting::new_analytical_light`, /// or from `Stage::new_analytical_light`. #[derive(Clone)] pub struct AnalyticalLight { @@ -544,7 +544,7 @@ pub struct AnalyticalLight { impl core::fmt::Display for AnalyticalLight { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.write_fmt(format_args!( - "AnalyticalLightBundle type={} light-id={:?} node-nested-transform-global-id:{:?}", + "AnalyticalLight type={} light-id={:?} node-nested-transform-global-id:{:?}", self.inner.style(), self.light_descriptor.id(), self.node_transform @@ -782,7 +782,7 @@ impl Lighting { &self.light_slab } - /// Add an [`AnalyticalLightBundle`] to the internal list of lights. + /// Add an [`AnalyticalLight`] to the internal list of lights. /// /// This is called implicitly by: /// @@ -811,7 +811,7 @@ impl Lighting { *self.analytical_lights_array.write().unwrap() = None; } - /// Remove an [`AnalyticalLightBundle`] from the internal list of lights. + /// Remove an [`AnalyticalLight`] from the internal list of lights. /// /// Use this to exclude a light from rendering, without dropping the light. /// @@ -906,11 +906,11 @@ impl Lighting { bundle } - /// Enable shadow mapping for the given [`AnalyticalLightBundle`], creating + /// Enable shadow mapping for the given [`AnalyticalLight`], creating /// a new [`ShadowMap`]. - pub fn new_shadow_map( + pub fn new_shadow_map( &self, - analytical_light_bundle: &AnalyticalLight, + analytical_light_bundle: &AnalyticalLight, // Size of the shadow map size: UVec2, // Distance to the near plane of the shadow map's frustum. @@ -921,7 +921,11 @@ impl Lighting { // // Only objects within the shadow map's frustum will cast shadows. z_far: f32, - ) -> Result { + ) -> Result + where + T: IsLight, + Light: From, + { ShadowMap::new(self, analytical_light_bundle, size, z_near, z_far) } diff --git a/crates/renderling/src/light/cpu/test.rs b/crates/renderling/src/light/cpu/test.rs index 0bb9a25e..8ac2c686 100644 --- a/crates/renderling/src/light/cpu/test.rs +++ b/crates/renderling/src/light/cpu/test.rs @@ -6,7 +6,7 @@ use glam::{Vec3, Vec4, Vec4Swizzles}; use spirv_std::num_traits::Zero; use crate::{ - bvol::BoundingBox, camera::{Camera}, color::linear_xfer_vec4, geometry::Vertex, light::{LightTiling, LightTilingConfig, SpotLightCalculation}, math::GpuRng, prelude::TransformDescriptor, stage::{Renderlet, RenderletPbrVertexInfo, Stage}, test::BlockOnFuture + bvol::BoundingBox, camera::Camera, color::linear_xfer_vec4, geometry::Vertex, light::{LightTiling, LightTilingConfig, SpotLightCalculation}, math::GpuRng, prelude::TransformDescriptor, stage::{Primitive, PrimitivePbrVertexInfo, Stage}, test::BlockOnFuture }; use super::*; @@ -193,7 +193,7 @@ fn light_tiling_light_bounds() { log::info!("min: {min}, max: {max}"); resources.push( stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices( bb.get_mesh() .map(|(p, n)| Vertex::default().with_position(p).with_normal(n)) @@ -221,7 +221,7 @@ fn gen_vec3(prng: &mut GpuRng) -> Vec3 { struct GeneratedLight { _unused_transform: Transform, _light: AnalyticalLight, - mesh_renderlet: Renderlet, + mesh_renderlet: Primitive, } fn gen_light(stage: &Stage, prng: &mut GpuRng, bounding_boxes: &[BoundingBox]) -> GeneratedLight { @@ -258,7 +258,7 @@ fn gen_light(stage: &Stage, prng: &mut GpuRng, bounding_boxes: &[BoundingBox]) - .with_has_lighting(false) .with_emissive_factor(color.xyz()) .with_emissive_strength_multiplier(100.0); - let mesh_renderlet = stage.new_renderlet().with_vertices(vertices).with_material(material); + let mesh_renderlet = stage.new_primitive().with_vertices(vertices).with_material(material); let _light = { // suffix the actual analytical light let intensity = scale * 100.0; @@ -622,7 +622,7 @@ fn tiling_e2e_sanity_with( // Remove the light meshes for generated_light in lights.iter() { - stage.remove_renderlet(&generated_light.mesh_renderlet); + stage.remove_primitive(&generated_light.mesh_renderlet); } snapshot( &ctx, @@ -948,8 +948,8 @@ fn pedestal() { log::info!("renderlet: {:#?}", renderlet.descriptor()); for vertex_index in 0..renderlet.descriptor().vertices_array.len() { - let mut info = RenderletPbrVertexInfo::default(); - crate::stage::renderlet_vertex( + let mut info = PrimitivePbrVertexInfo::default(); + crate::stage::primitive_vertex( renderlet.id(), vertex_index as u32, &geometry_slab, @@ -1016,8 +1016,8 @@ fn pedestal() { let mut spot_infos = vec![]; for vertex_index in 0..renderlet.descriptor().vertices_array.len() { - let mut info = RenderletPbrVertexInfo::default(); - crate::stage::renderlet_vertex( + let mut info = PrimitivePbrVertexInfo::default(); + crate::stage::primitive_vertex( renderlet.id(), vertex_index as u32, &geometry_slab, diff --git a/crates/renderling/src/light/shadow_map.rs b/crates/renderling/src/light/shadow_map.rs index 6c95ea44..421e9f16 100644 --- a/crates/renderling/src/light/shadow_map.rs +++ b/crates/renderling/src/light/shadow_map.rs @@ -15,7 +15,7 @@ use crate::{ atlas::{AtlasBlittingOperation, AtlasImage, AtlasTexture, AtlasTextureDescriptor}, bindgroup::ManagedBindGroup, light::{IsLight, Light}, - stage::Renderlet, + stage::Primitive, }; use super::{AnalyticalLight, Lighting, LightingError, PollSnafu, ShadowMapDescriptor}; @@ -158,7 +158,7 @@ impl ShadowMap { self.shadowmap_descriptor.lock() } - /// Enable shadow mapping for the given [`AnalyticalLightBundle`], creating + /// Enable shadow mapping for the given [`AnalyticalLight`], creating /// a new [`ShadowMap`]. pub fn new( lighting: &Lighting, @@ -242,19 +242,20 @@ impl ShadowMap { }) } - /// Update the `ShadowMap`, rendering the given [`Renderlet`]s to the map as shadow casters. + /// Update the `ShadowMap`, rendering the given [`Primitive`]s to the map as + /// shadow casters. /// - /// The `ShadowMap` contains a weak reference to the [`AnalyticalLightBundle`] used to create - /// it. Updates made to this `AnalyticalLightBundle` will automatically propogate to this + /// The `ShadowMap` contains a weak reference to the [`AnalyticalLight`] used to create + /// it. Updates made to this `AnalyticalLight` will automatically propogate to this /// `ShadowMap`. /// /// ## Errors - /// If the `AnalyticalLightBundle` used to create this `ShadowMap` has been + /// If the `AnalyticalLight` used to create this `ShadowMap` has been /// dropped, calling this function will err. pub fn update<'a>( &self, lighting: impl AsRef, - renderlets: impl IntoIterator, + renderlets: impl IntoIterator, ) -> Result<(), LightingError> { let lighting = lighting.as_ref(); let shadow_desc = self.shadowmap_descriptor.get(); diff --git a/crates/renderling/src/light/tiling.rs b/crates/renderling/src/light/tiling.rs index 0a1f20c5..6e0bee1b 100644 --- a/crates/renderling/src/light/tiling.rs +++ b/crates/renderling/src/light/tiling.rs @@ -28,6 +28,8 @@ use crate::{ /// . pub struct LightTiling { pub(crate) tiling_descriptor: Hybrid, + /// Container is a type variable for testing, as we have to load + /// the tiles with known values from the CPU. tiles: Ct::Container, /// Cache of the id of the Stage's depth texture. /// @@ -422,8 +424,8 @@ impl Default for LightTilingConfig { } impl LightTiling { - /// Creates a new [`LightTiling`] struct with a [`HybridArray`] of tiles. - pub fn new_hybrid( + /// Creates a new [`LightTiling`] struct with a `HybridArray` of tiles. + pub(crate) fn new_hybrid( lighting: &Lighting, multisampled: bool, depth_texture_size: UVec2, diff --git a/crates/renderling/src/material/cpu.rs b/crates/renderling/src/material/cpu.rs index 280fe2ba..8280ab68 100644 --- a/crates/renderling/src/material/cpu.rs +++ b/crates/renderling/src/material/cpu.rs @@ -1,5 +1,4 @@ //! CPU side of materials. - use std::sync::{Arc, Mutex}; use craballoc::{ @@ -84,7 +83,7 @@ impl Materials { (self.atlas.upkeep(self.runtime()), self.slab.commit()) } - /// Returns a [`MaterialBuilder`] for building a new [`Material`]. + /// Stage a new [`Material`] on the materials slab. pub fn new_material(&self) -> Material { let descriptor = self.slab.new_value(MaterialDescriptor::default()); Material { @@ -362,7 +361,7 @@ impl Material { /// Remove the albedo texture. /// - /// This causes any `[Renderlet]` that references this material to fall back to + /// This causes any `[Primitive]` that references this material to fall back to /// using the albedo factor for color. pub fn remove_albedo_texture(&self) { self.descriptor.modify(|d| d.albedo_texture_id = Id::NONE); diff --git a/crates/renderling/src/math.rs b/crates/renderling/src/math.rs index 25029b75..27b6e32a 100644 --- a/crates/renderling/src/math.rs +++ b/crates/renderling/src/math.rs @@ -690,8 +690,8 @@ pub const fn convex_mesh([p0, p1, p2, p3, p4, p5, p6, p7]: [Vec3; 8]) -> [Vec3; /// An PCG PRNG that is optimized for GPUs, in that it is fast to evaluate and accepts /// sequential ids as it's initial state without sacrificing on RNG quality. /// -/// https://www.reedbeta.com/blog/hash-functions-for-gpu-rendering/ -/// https://jcgt.org/published/0009/03/02/ +/// * +/// * /// /// Thanks to Firestar99 at /// diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index 019727cf..ecb14a80 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -20,7 +20,7 @@ use crate::{ material::MaterialDescriptor, math::{self, IsSampler, IsVector, Sample2d, Sample2dArray, SampleCube}, println as my_println, - stage::RenderletDescriptor, + stage::PrimitiveDescriptor, }; pub mod debug; @@ -236,7 +236,7 @@ pub fn fragment_impl( material_slab: &[u32], lighting_slab: &[u32], - renderlet_id: Id, + renderlet_id: Id, frag_coord: Vec4, in_color: Vec4, @@ -733,7 +733,7 @@ mod test { let y = (diameter + spacing) * j as f32; let rez = stage - .new_renderlet() + .new_primitive() .with_material( stage .new_material() diff --git a/crates/renderling/src/skybox.rs b/crates/renderling/src/skybox.rs index 040d4707..a061d8f6 100644 --- a/crates/renderling/src/skybox.rs +++ b/crates/renderling/src/skybox.rs @@ -63,7 +63,7 @@ pub fn skybox_cubemap_fragment( /// Vertex shader that draws a cubemap. /// -/// Uses the `instance_index` as the [`Id`] for a [`Camera`]. +/// Uses the `instance_index` as the [`Id`] for a [`CameraDescriptor`]. /// /// Used to create a cubemap from an equirectangular image as well as cubemap /// convolutions. diff --git a/crates/renderling/src/stage.rs b/crates/renderling/src/stage.rs index de457058..4ab6797a 100644 --- a/crates/renderling/src/stage.rs +++ b/crates/renderling/src/stage.rs @@ -32,7 +32,7 @@ mod gltf_support; #[cfg(all(feature = "gltf", not(target_arch = "spirv")))] pub use gltf_support::*; -/// Returned by [`Renderlet::get_vertex_info`]. +/// Returned by [`PrimitiveDescriptor::get_vertex_info`]. pub struct VertexInfo { pub vertex: Vertex, pub transform: TransformDescriptor, @@ -41,18 +41,12 @@ pub struct VertexInfo { } /// A draw call used to render some geometry. -/// -/// ## Note -/// The default implentation returns a `Renderlet` with `pbr_config` set to -/// `Id::new(0)`. This corresponds to the `PbrConfig` that is maintained by -/// the [`Stage`]. -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Clone, Copy, PartialEq, SlabItem)] +#[derive(Clone, Copy, PartialEq, SlabItem, Debug)] #[offsets] -pub struct RenderletDescriptor { +pub struct PrimitiveDescriptor { pub visible: bool, pub vertices_array: Array, - /// Bounding sphere of the entire renderlet, in local space. + /// Bounding sphere of the entire primitive, in local space. pub bounds: BoundingSphere, pub indices_array: Array, pub transform_id: Id, @@ -63,9 +57,9 @@ pub struct RenderletDescriptor { pub geometry_descriptor_id: Id, } -impl Default for RenderletDescriptor { +impl Default for PrimitiveDescriptor { fn default() -> Self { - RenderletDescriptor { + PrimitiveDescriptor { visible: true, vertices_array: Array::default(), bounds: BoundingSphere::default(), @@ -80,7 +74,7 @@ impl Default for RenderletDescriptor { } } -impl RenderletDescriptor { +impl PrimitiveDescriptor { /// Returns the vertex at the given index and its related values. /// /// These values are often used in shaders, so they are grouped together. @@ -96,7 +90,7 @@ impl RenderletDescriptor { world_pos, } } - /// Retrieve the transform of this `Renderlet`. + /// Retrieve the transform of this `primitive`. /// /// This takes into consideration all skinning matrices. pub fn get_transform(&self, vertex: Vertex, slab: &[u32]) -> TransformDescriptor { @@ -140,11 +134,11 @@ impl RenderletDescriptor { } #[cfg(test)] -/// A helper struct that contains all outputs of the Renderlet's PBR vertex shader. +/// A helper struct that contains all outputs of the primitive's PBR vertex shader. #[derive(Default, Debug, Clone, Copy, PartialEq)] -pub struct RenderletPbrVertexInfo { - pub renderlet: RenderletDescriptor, - pub renderlet_id: Id, +pub struct PrimitivePbrVertexInfo { + pub primitive: PrimitiveDescriptor, + pub primitive_id: Id, pub vertex_index: u32, pub vertex: Vertex, pub transform: TransformDescriptor, @@ -160,17 +154,17 @@ pub struct RenderletPbrVertexInfo { pub out_clip_pos: Vec4, } -/// Renderlet vertex shader. +/// primitive vertex shader. #[spirv(vertex)] #[allow(clippy::too_many_arguments)] -pub fn renderlet_vertex( - // Points at a `Renderlet` - #[spirv(instance_index)] renderlet_id: Id, - // Which vertex within the renderlet are we rendering +pub fn primitive_vertex( + // Points at a `primitive` + #[spirv(instance_index)] primitive_id: Id, + // Which vertex within the primitive are we rendering #[spirv(vertex_index)] vertex_index: u32, #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], - #[spirv(flat)] out_renderlet: &mut Id, + #[spirv(flat)] out_primitive: &mut Id, // TODO: Think about placing all these out values in a G-Buffer // But do we have enough buffers + enough space on web? // ...and can we write to buffers from vertex shaders on web? @@ -183,23 +177,23 @@ pub fn renderlet_vertex( out_world_pos: &mut Vec3, #[spirv(position)] out_clip_pos: &mut Vec4, // test-only info struct - #[cfg(test)] out_info: &mut RenderletPbrVertexInfo, + #[cfg(test)] out_info: &mut PrimitivePbrVertexInfo, ) { - let renderlet = geometry_slab.read_unchecked(renderlet_id); - if !renderlet.visible { + let primitive = geometry_slab.read_unchecked(primitive_id); + if !primitive.visible { // put it outside the clipping frustum *out_clip_pos = Vec4::new(10.0, 10.0, 10.0, 1.0); return; } - *out_renderlet = renderlet_id; + *out_primitive = primitive_id; let VertexInfo { vertex, transform, model_matrix, world_pos, - } = renderlet.get_vertex_info(vertex_index, geometry_slab); + } = primitive.get_vertex_info(vertex_index, geometry_slab); *out_color = vertex.color; *out_uv0 = vertex.uv0; *out_uv1 = vertex.uv1; @@ -222,21 +216,21 @@ pub fn renderlet_vertex( *out_bitangent = bitangent_w; let camera_id = geometry_slab - .read_unchecked(renderlet.geometry_descriptor_id + GeometryDescriptor::OFFSET_OF_CAMERA_ID); + .read_unchecked(primitive.geometry_descriptor_id + GeometryDescriptor::OFFSET_OF_CAMERA_ID); let camera = geometry_slab.read(camera_id); let clip_pos = camera.view_projection() * world_pos.extend(1.0); *out_clip_pos = clip_pos; #[cfg(test)] { - *out_info = RenderletPbrVertexInfo { - renderlet_id, + *out_info = PrimitivePbrVertexInfo { + primitive_id, vertex_index, vertex, transform, model_matrix, view_projection: camera.view_projection(), out_clip_pos: clip_pos, - renderlet, + primitive, out_color: *out_color, out_uv0: *out_uv0, out_uv1: *out_uv1, @@ -248,10 +242,10 @@ pub fn renderlet_vertex( } } -/// Renderlet fragment shader +/// primitive fragment shader #[allow(clippy::too_many_arguments, dead_code)] #[spirv(fragment)] -pub fn renderlet_fragment( +pub fn primitive_fragment( #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] material_slab: &[u32], #[spirv(descriptor_set = 0, binding = 2)] atlas: &Image2dArray, @@ -269,7 +263,7 @@ pub fn renderlet_fragment( #[spirv(storage_buffer, descriptor_set = 0, binding = 13)] debug_slab: &mut [u32], - #[spirv(flat)] renderlet_id: Id, + #[spirv(flat)] primitive_id: Id, #[spirv(frag_coord)] frag_coord: Vec4, in_color: Vec4, in_uv0: Vec2, @@ -295,7 +289,7 @@ pub fn renderlet_fragment( geometry_slab, material_slab, light_slab, - renderlet_id, + primitive_id, frag_coord, in_color, in_uv0, diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index 54c70184..126b801f 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -43,9 +43,9 @@ use crate::{ }; #[cfg(cpu)] -pub mod renderlet; +pub mod primitive; #[cfg(cpu)] -pub use renderlet::*; +pub use primitive::*; use super::*; @@ -386,14 +386,15 @@ impl AsRef for Stage { impl Stage { /// Returns the vertices of a white unit cube. /// - /// This is the mesh of every [`Renderlet`] that has not had its vertices set. + /// This is the mesh of every [`Primitive`] that has not had its vertices set. pub fn default_vertices(&self) -> &Vertices { self.geometry.default_vertices() } - /// Stage a [`Camera`] on the GPU. + + /// Stage a new [`Camera`] on the GPU. /// - /// If the camera has not been set, this camera will be used - /// automatically. + /// If no camera is currently in use on the [`Stage`] through + /// [`Stage::use_camera`], this new camera will be used automatically. pub fn new_camera(&self) -> Camera { self.geometry.new_camera() } @@ -430,7 +431,7 @@ impl Stage { self.geometry.new_indices(data) } - /// Create new morph targets. + /// Stage new morph targets. pub fn new_morph_targets( &self, data: impl IntoIterator>, @@ -438,7 +439,7 @@ impl Stage { self.geometry.new_morph_targets(data) } - /// Create new morph target weights. + /// Stage new morph target weights. pub fn new_morph_target_weights( &self, data: impl IntoIterator, @@ -446,6 +447,7 @@ impl Stage { self.geometry.new_morph_target_weights(data) } + /// Stage a new skin. pub fn new_skin( &self, joints: impl IntoIterator>, @@ -454,17 +456,18 @@ impl Stage { self.geometry.new_skin(joints, inverse_bind_matrices) } - /// Stage a new [`Renderlet`] on the GPU. + /// Stage a new [`Primitive`] on the GPU. /// - /// The returned [`Renderlet`] will automatically be added to this [`Stage`]. + /// The returned [`Primitive`] will automatically be added to this [`Stage`]. /// - /// The returned [`Renderlet`] will have the stage's default [`Vertices`], which is an all-white + /// The returned [`Primitive`] will have the stage's default [`Vertices`], which is an all-white /// unit cube. /// - /// The returned [`Renderlet`] uses the stage's default [`Material`], which is white and - /// **does not** participate in lighting. - pub fn new_renderlet(&self) -> Renderlet { - Renderlet::new(self) + /// The returned [`Primitive`] uses the stage's default [`Material`], which is white and + /// **does not** participate in lighting. To change this, first create a [`Material`] with + /// [`Stage::new_material`] and then call [`Primitive::set_material`] with the new material. + pub fn new_primitive(&self) -> Primitive { + Primitive::new(self) } /// Returns a reference to the descriptor stored at the root of the @@ -570,9 +573,9 @@ impl Stage { self.lighting.new_spot_light() } - /// Add an [`AnalyticalLightBundle`] to the internal list of lights. + /// Add an [`AnalyticalLight`] to the internal list of lights. /// - /// This is called implicitly by [`Stage::new_analytical_light`]. + /// This is called implicitly by `Stage::new_*_light`. /// /// This can be used to add the light back to the scene after using /// [`Stage::remove_light`]. @@ -584,7 +587,7 @@ impl Stage { self.lighting.add_light(bundle) } - /// Remove an [`AnalyticalLightBundle`] from the internal list of lights. + /// Remove an [`AnalyticalLight`] from the internal list of lights. /// /// Use this to exclude a light from rendering, without dropping the light. /// @@ -593,23 +596,25 @@ impl Stage { self.lighting.remove_light(bundle); } - /// Enable shadow mapping for the given [`AnalyticalLightBundle`], creating + /// Enable shadow mapping for the given [`AnalyticalLight`], creating /// a new [`ShadowMap`]. /// /// ## Tips for making a good shadow map /// /// 1. Make sure the map is big enough. /// Using a big map can fix some peter panning issues, even before - /// messing with bias in the [`ShadowMapDescriptor`]. + /// playing with bias in the returned [`ShadowMap`]. /// The bigger the map, the cleaner the shadows will be. This can /// also solve PCF problems. - /// 2. Don't set PCF samples too high in the [`ShadowMapDescriptor`], as + /// 2. Don't set PCF samples too high in the returned [`ShadowMap`], as /// this can _cause_ peter panning. /// 3. Ensure the **znear** and **zfar** parameters make sense, as the /// shadow map uses these to determine how much of the scene to cover. - pub fn new_shadow_map( + /// If you find that shadows are cut off in a straight line, it's likely + /// `znear` or `zfar` needs adjustment. + pub fn new_shadow_map( &self, - analytical_light_bundle: &AnalyticalLight, + analytical_light_bundle: &AnalyticalLight, // Size of the shadow map size: UVec2, // Distance to the near plane of the shadow map's frustum. @@ -620,7 +625,11 @@ impl Stage { // // Only objects within the shadow map's frustum will cast shadows. z_far: f32, - ) -> Result { + ) -> Result + where + T: IsLight, + Light: From, + { Ok(self .lighting .new_shadow_map(analytical_light_bundle, size, z_near, z_far)?) @@ -662,8 +671,7 @@ impl Stage { /// /// This is done implicitly in [`Stage::render`] and [`StageRendering::run`]. /// - /// This can be used after dropping [`Hybrid`] or [`Gpu`] resources to reclaim - /// those resources on the GPU. + /// This can be used after dropping resources to reclaim those resources on the GPU. #[must_use] pub fn commit(&self) -> StageCommitResult { let (materials_atlas_texture_was_recreated, materials_buffer) = self.materials.commit(); @@ -787,7 +795,7 @@ impl Stage { }) } - pub fn create_renderlet_pipeline( + pub fn create_primitive_pipeline( device: &wgpu::Device, fragment_color_format: wgpu::TextureFormat, multisample_count: u32, @@ -881,7 +889,7 @@ impl Stage { ctx.get_render_target().format().add_srgb_suffix(), &bloom.get_mix_texture(), ); - let stage_pipeline = Self::create_renderlet_pipeline( + let stage_pipeline = Self::create_primitive_pipeline( device, wgpu::TextureFormat::Rgba16Float, multisample_count, @@ -962,7 +970,7 @@ impl Stage { log::debug!("setting multisample count to {multisample_count}"); // UNWRAP: POP - *self.renderlet_pipeline.write().unwrap() = Self::create_renderlet_pipeline( + *self.renderlet_pipeline.write().unwrap() = Self::create_primitive_pipeline( self.device(), wgpu::TextureFormat::Rgba16Float, multisample_count, @@ -1260,26 +1268,26 @@ impl Stage { /// If you drop the renderlet and no other references are kept, it will be /// removed automatically from the internal list and will cease to be /// drawn each frame. - pub fn add_renderlet(&self, renderlet: &Renderlet) { + pub fn add_primitive(&self, renderlet: &Primitive) { // UNWRAP: if we can't acquire the lock we want to panic. let mut draws = self.draw_calls.write().unwrap(); - draws.add_renderlet(renderlet); + draws.add_primitive(renderlet); } /// Erase the given renderlet from the internal list of renderlets to be /// drawn each frame. - pub fn remove_renderlet(&self, renderlet: &Renderlet) { + pub fn remove_primitive(&self, renderlet: &Primitive) { let mut draws = self.draw_calls.write().unwrap(); - draws.remove_renderlet(renderlet); + draws.remove_primitive(renderlet); } /// Sort the drawing order of renderlets. /// - /// This determines the order in which [`Renderlet`]s are drawn each frame. - pub fn sort_renderlets(&self, f: impl Fn(&Renderlet, &Renderlet) -> std::cmp::Ordering) { + /// This determines the order in which [`Primitive`]s are drawn each frame. + pub fn sort_renderlets(&self, f: impl Fn(&Primitive, &Primitive) -> std::cmp::Ordering) { // UNWRAP: panic on purpose let mut guard = self.draw_calls.write().unwrap(); - guard.sort_renderlets(f); + guard.sort_primitives(f); } /// Returns a clone of the current depth texture. @@ -1497,7 +1505,7 @@ mod test { let _camera = stage .new_camera() .with_projection_and_view(projection, view); - let _triangle_rez = stage.new_renderlet().with_vertices( + let _triangle_rez = stage.new_primitive().with_vertices( stage.new_vertices([ Vertex::default() .with_position([10.0, 10.0, 0.0]) diff --git a/crates/renderling/src/stage/cpu/renderlet.rs b/crates/renderling/src/stage/cpu/primitive.rs similarity index 75% rename from crates/renderling/src/stage/cpu/renderlet.rs rename to crates/renderling/src/stage/cpu/primitive.rs index 0e55539c..62e08c93 100644 --- a/crates/renderling/src/stage/cpu/renderlet.rs +++ b/crates/renderling/src/stage/cpu/primitive.rs @@ -1,4 +1,4 @@ -//! `Renderlet` builder. +//! Mesh primitives. use core::ops::Deref; use std::sync::{Arc, Mutex}; @@ -10,16 +10,16 @@ use crate::{ bvol::BoundingSphere, geometry::{Indices, MorphTargetWeights, MorphTargets, Skin, Vertices}, material::Material, - stage::RenderletDescriptor, + stage::PrimitiveDescriptor, transform::Transform, types::GpuOnlyArray, }; /// A unit of rendering. /// -/// A `Renderlet` represents one draw call, or one mesh primitive. -pub struct Renderlet { - pub(crate) descriptor: Hybrid, +/// A `Primitive` represents one draw call, or one mesh primitive. +pub struct Primitive { + pub(crate) descriptor: Hybrid, vertices: Arc>>>, indices: Arc>>>, @@ -30,17 +30,18 @@ pub struct Renderlet { morph_targets: Arc>>, } -impl Renderlet { - /// Create a new [`Renderlet`], automatically adding it to the [`Stage`] to be drawn. +impl Primitive { + /// Create a new [`Primitive`], automatically adding it to the + /// [`Stage`](crate::stage::Stage) to be drawn. /// - /// The returned [`Renderlet`] will have the stage's default [`Vertices`], which is an all-white - /// unit cube. + /// The returned [`Primitive`] will have the stage's default [`Vertices`], + /// which is an all-white unit cube. pub fn new(stage: &super::Stage) -> Self { let descriptor = stage .geometry .slab_allocator() - .new_value(RenderletDescriptor::default()); - let renderlet = Renderlet { + .new_value(PrimitiveDescriptor::default()); + let primitive = Primitive { descriptor, vertices: Default::default(), indices: Default::default(), @@ -50,12 +51,12 @@ impl Renderlet { morph_targets: Default::default(), } .with_vertices(stage.default_vertices()); - stage.add_renderlet(&renderlet); - renderlet + stage.add_primitive(&primitive); + primitive } } -impl Clone for Renderlet { +impl Clone for Primitive { fn clone(&self) -> Self { Self { descriptor: self.descriptor.clone(), @@ -70,8 +71,8 @@ impl Clone for Renderlet { } // Vertices impls -impl Renderlet { - /// Set the vertex data of this renderlet. +impl Primitive { + /// Set the vertex data of this primitive. pub fn set_vertices(&self, vertices: impl Into>) -> &Self { let vertices = vertices.into(); let array = vertices.array(); @@ -80,7 +81,7 @@ impl Renderlet { self } - /// Set the vertex data of this renderlet and return the renderlet. + /// Set the vertex data of this primitive and return the primitive. pub fn with_vertices(self, vertices: impl Into>) -> Self { self.set_vertices(vertices); self @@ -88,8 +89,8 @@ impl Renderlet { } // Indices impls -impl Renderlet { - /// Set the index data of this renderlet. +impl Primitive { + /// Set the index data of this primitive. pub fn set_indices(&self, indices: impl Into>) -> &Self { let indices = indices.into(); let array = indices.array(); @@ -98,13 +99,13 @@ impl Renderlet { self } - /// Set the index data of this renderlet and return the renderlet. + /// Set the index data of this primitive and return the primitive. pub fn with_indices(self, indices: impl Into>) -> Self { self.set_indices(indices); self } - /// Remove the indices from this renderlet. + /// Remove the indices from this primitive. pub fn remove_indices(&self) -> &Self { *self.indices.lock().unwrap() = None; self.descriptor.modify(|d| d.indices_array = Array::NONE); @@ -112,25 +113,25 @@ impl Renderlet { } } -// RenderletDescriptor impls -impl Renderlet { +// PrimitiveDescriptor impls +impl Primitive { /// Return a pointer to the underlying descriptor on the GPU. - pub fn id(&self) -> Id { + pub fn id(&self) -> Id { self.descriptor.id() } /// Return the underlying descriptor. - pub fn descriptor(&self) -> RenderletDescriptor { + pub fn descriptor(&self) -> PrimitiveDescriptor { self.descriptor.get() } - /// Set the bounds of this renderlet. + /// Set the bounds of this primitive. pub fn set_bounds(&self, bounds: BoundingSphere) -> &Self { self.descriptor.modify(|d| d.bounds = bounds); self } - /// Set the bounds and return the renderlet. + /// Set the bounds and return the primitive. pub fn with_bounds(self, bounds: BoundingSphere) -> Self { self.set_bounds(bounds); self @@ -138,53 +139,56 @@ impl Renderlet { /// Get the bounds. /// - /// Returns the current `BoundingSphere`. + /// Returns the current [`BoundingSphere`]. pub fn bounds(&self) -> BoundingSphere { self.descriptor.get().bounds } - /// Modify the bounds of the renderlet. + /// Modify the bounds of the primitive. /// /// # Arguments /// - /// * `f` - A closure that takes a mutable reference to the `BoundingSphere` and returns a value of type `T`. + /// * `f` - A closure that takes a mutable reference to the + /// [`BoundingSphere`] and returns a value of type `T`. pub fn modify_bounds(&self, f: impl FnOnce(&mut BoundingSphere) -> T) -> T { self.descriptor.modify(|d| f(&mut d.bounds)) } - /// Set the visibility of this renderlet. + /// Set the visibility of this primitive. pub fn set_visible(&self, visible: bool) -> &Self { self.descriptor.modify(|d| d.visible = visible); self } - /// Set the visibility and return the renderlet. + /// Set the visibility and return the primitive. pub fn with_visible(self, visible: bool) -> Self { self.set_visible(visible); self } - /// Return the renderlet's visibility. + /// Return the primitive's visibility. pub fn visible(&self) -> bool { self.descriptor.get().visible } - /// Modify the visible of the renderlet. + /// Modify the visible of the primitive. /// /// # Arguments /// - /// * `f` - A closure that takes a mutable reference to the visibility and returns a value of type `T`. + /// * `f` - A closure that takes a mutable reference to the visibility and + /// returns a value of type `T`. pub fn modify_visible(&self, f: impl FnOnce(&mut bool) -> T) -> T { self.descriptor.modify(|d| f(&mut d.visible)) } } // Transform functions -impl Renderlet { +impl Primitive { /// Set the transform. /// /// # Note - /// This can be set with [`Transform`] or [`NestedTransform`]. + /// This can be set with [`Transform`] or + /// [`NestedTransform`](crate::transform::NestedTransform). pub fn set_transform(&self, transform: impl Into) -> &Self { let transform = transform.into(); self.descriptor.modify(|d| d.transform_id = transform.id()); @@ -192,10 +196,11 @@ impl Renderlet { self } - /// Set the transform and return the `Renderlet`. + /// Set the transform and return the `Primitive`. /// /// # Note - /// This can be set with [`Transform`] or [`NestedTransform`]. + /// This can be set with [`Transform`] or + /// [`NestedTransform`](crate::transform::NestedTransform). pub fn with_transform(self, transform: impl Into) -> Self { self.set_transform(transform); self @@ -209,7 +214,7 @@ impl Renderlet { self.transform.lock().unwrap() } - /// Remove the transform from this renderlet. + /// Remove the transform from this primitive. /// /// This effectively makes the transform the identity. pub fn remove_transform(&self) -> &Self { @@ -220,8 +225,8 @@ impl Renderlet { } // Material impls -impl Renderlet { - /// Set the material of this renderlet. +impl Primitive { + /// Set the material of this primitive. pub fn set_material(&self, material: impl Into) -> &Self { let material = material.into(); self.descriptor.modify(|d| d.material_id = material.id()); @@ -229,7 +234,7 @@ impl Renderlet { self } - /// Set the material and return the renderlet. + /// Set the material and return the primitive. pub fn with_material(self, material: impl Into) -> Self { self.set_material(material); self @@ -243,7 +248,7 @@ impl Renderlet { self.material.lock().unwrap() } - /// Remove the material from this renderlet. + /// Remove the material from this primitive. pub fn remove_material(&self) -> &Self { self.descriptor.modify(|d| d.material_id = Id::NONE); *self.material.lock().unwrap() = None; @@ -252,8 +257,8 @@ impl Renderlet { } // Skin impls -impl Renderlet { - /// Set the skin of this renderlet. +impl Primitive { + /// Set the skin of this primitive. pub fn set_skin(&self, skin: impl Into) -> &Self { let skin = skin.into(); self.descriptor.modify(|d| d.skin_id = skin.id()); @@ -261,7 +266,7 @@ impl Renderlet { self } - /// Set the skin and return the renderlet. + /// Set the skin and return the primitive. pub fn with_skin(self, skin: impl Into) -> Self { self.set_skin(skin); self @@ -274,7 +279,7 @@ impl Renderlet { self.skin.lock().unwrap() } - /// Remove the skin from this renderlet. + /// Remove the skin from this primitive. pub fn remove_skin(&self) -> &Self { self.descriptor.modify(|d| d.skin_id = Id::NONE); *self.skin.lock().unwrap() = None; @@ -283,8 +288,8 @@ impl Renderlet { } // (MorphTargets, MorphTargetsWeights) impls -impl Renderlet { - /// Set the morph targets and weights of this renderlet. +impl Primitive { + /// Set the morph targets and weights of this primitive. pub fn set_morph_targets( &self, morph_targets: impl Into, @@ -300,7 +305,7 @@ impl Renderlet { self } - /// Set the morph targets and weights and return the renderlet. + /// Set the morph targets and weights and return the primitive. pub fn with_morph_targets( self, morph_targets: impl Into, @@ -319,7 +324,7 @@ impl Renderlet { self.morph_targets.lock().unwrap() } - /// Remove the morph targets and weights from this renderlet. + /// Remove the morph targets and weights from this primitive. pub fn remove_morph_targets(&self) -> &Self { self.descriptor.modify(|d| { d.morph_targets = Array::NONE; diff --git a/crates/renderling/src/stage/gltf_support.rs b/crates/renderling/src/stage/gltf_support.rs index c60bb095..d2009f4d 100644 --- a/crates/renderling/src/stage/gltf_support.rs +++ b/crates/renderling/src/stage/gltf_support.rs @@ -17,7 +17,7 @@ use crate::{ geometry::{Indices, MorphTargetWeights, MorphTargets, Skin, Vertices}, light::{AnalyticalLight, LightStyle}, material::Material, - stage::{MorphTarget, Renderlet, Stage, Vertex}, + stage::{MorphTarget, Primitive, Stage, Vertex}, transform::{NestedTransform, TransformDescriptor}, }; @@ -723,7 +723,7 @@ pub struct GltfDocument { pub default_material: Material, pub materials: Vec, // map of node index to renderlets - pub renderlets: FxHashMap>, + pub renderlets: FxHashMap>, /// Vector of scenes - each being a list of nodes. pub scenes: Vec>, pub skins: Vec, @@ -1066,7 +1066,7 @@ impl GltfDocument { .and_then(|index| materials.get(index)) .unwrap_or(&default_material); let renderlet = stage - .new_renderlet() + .new_primitive() .with_vertices(&prim.vertices) .with_indices(&prim.indices) .with_transform(&gltf_node.transform) @@ -1112,7 +1112,7 @@ impl GltfDocument { }) } - pub fn renderlets_iter(&self) -> impl Iterator { + pub fn renderlets_iter(&self) -> impl Iterator { self.renderlets.iter().flat_map(|(_, rs)| rs.iter()) } @@ -1270,7 +1270,7 @@ mod test { .with_albedo_texture(&doc.textures[0]) .with_has_lighting(false); let _rez = stage - .new_renderlet() + .new_primitive() .with_material(&material) .with_vertices( stage.new_vertices([ diff --git a/crates/renderling/src/transform/cpu.rs b/crates/renderling/src/transform/cpu.rs index 17a402df..09fac7a9 100644 --- a/crates/renderling/src/transform/cpu.rs +++ b/crates/renderling/src/transform/cpu.rs @@ -158,7 +158,10 @@ impl Transform { } } -/// Manages scene heirarchy on the [`Stage`]. +/// Manages scene heirarchy on the [`Stage`](crate::stage::Stage). +/// +/// Can be created with +/// [`Stage::new_nested_transform`](crate::stage::Stage::new_nested_transform). /// /// Clones all reference the same nested transform. #[derive(Clone)] diff --git a/crates/renderling/src/tutorial.rs b/crates/renderling/src/tutorial.rs index d42d80fc..0e9253cf 100644 --- a/crates/renderling/src/tutorial.rs +++ b/crates/renderling/src/tutorial.rs @@ -6,7 +6,7 @@ use spirv_std::spirv; use crate::{ geometry::{GeometryDescriptor, Vertex}, - stage::{RenderletDescriptor, VertexInfo}, + stage::{PrimitiveDescriptor, VertexInfo}, }; /// Simple fragment shader that writes the input color to the output color. @@ -80,18 +80,19 @@ pub fn slabbed_vertices( *out_color = color; } -// TODO: fix all this documentation -/// This shader uses the `instance_index` as a slab [`Id`]. -/// The `instance_index` is the [`Id`] of a [`RenderUnit`]. -/// The [`RenderUnit`] contains an [`Array`] of [`Vertex`]s -/// as its mesh, the [`Id`]s of a [`Material`] and [`Camera`], +/// This shader uses the `instance_index` as a slab id. +/// The `instance_index` is the `id` of a [`PrimitiveDescriptor`]. +/// The [`PrimitiveDescriptor`] contains an [`Array`] of [`Vertex`]s +/// as its mesh, the [`Id`]s of a +/// [`MaterialDescriptor`](crate::material::MaterialDescriptor) and +///[`CameraDescriptor`](crate::camera::CameraDescriptor), /// and TRS transforms. /// The `vertex_index` is the index of a [`Vertex`] within the -/// [`RenderUnit`]'s `vertices` [`Array`]. +/// [`PrimitiveDescriptor`]'s `vertices` [`Array`]. #[spirv(vertex)] pub fn slabbed_renderlet( // Id of the array of vertices we are rendering - #[spirv(instance_index)] renderlet_id: Id, + #[spirv(instance_index)] primitive_id: Id, // Which vertex within the render unit are we rendering #[spirv(vertex_index)] vertex_index: u32, @@ -100,14 +101,14 @@ pub fn slabbed_renderlet( out_color: &mut Vec4, #[spirv(position)] clip_pos: &mut Vec4, ) { - let renderlet = slab.read(renderlet_id); + let prim = slab.read(primitive_id); let VertexInfo { vertex, model_matrix, .. - } = renderlet.get_vertex_info(vertex_index, slab); - let camera_id = slab - .read_unchecked(renderlet.geometry_descriptor_id + GeometryDescriptor::OFFSET_OF_CAMERA_ID); + } = prim.get_vertex_info(vertex_index, slab); + let camera_id = + slab.read_unchecked(prim.geometry_descriptor_id + GeometryDescriptor::OFFSET_OF_CAMERA_ID); let camera = slab.read(camera_id); *clip_pos = camera.view_projection() * model_matrix * vertex.position.xyz().extend(1.0); *out_color = vertex.color; diff --git a/crates/renderling/src/ui.rs b/crates/renderling/src/ui.rs index bffe3ef7..a654450c 100644 --- a/crates/renderling/src/ui.rs +++ b/crates/renderling/src/ui.rs @@ -12,7 +12,7 @@ //! let mut ui = Ui::new(&ctx); //! //! let _path = ui -//! .new_path() +//! .path_builder() //! .with_stroke_color([1.0, 1.0, 0.0, 1.0]) //! .with_rectangle(Vec2::splat(10.0), Vec2::splat(60.0)) //! .stroke(); diff --git a/crates/renderling/src/ui/cpu.rs b/crates/renderling/src/ui/cpu.rs index 7d5a49f3..6c0e1426 100644 --- a/crates/renderling/src/ui/cpu.rs +++ b/crates/renderling/src/ui/cpu.rs @@ -246,7 +246,7 @@ impl Ui { /// The given `path` must have been created with this [`Ui`], otherwise this function is /// a noop. pub fn remove_path(&self, path: &UiPath) { - self.stage.remove_renderlet(&path.renderlet); + self.stage.remove_primitive(&path.primitive); } pub fn text_builder(&self) -> UiTextBuilder { @@ -259,7 +259,7 @@ impl Ui { /// The given `text` must have been created with this [`Ui`], otherwise this function is /// a noop. pub fn remove_text(&self, text: &UiText) { - self.stage.remove_renderlet(&text.renderlet); + self.stage.remove_primitive(&text.renderlet); } pub async fn load_font(&self, path: impl AsRef) -> Result { diff --git a/crates/renderling/src/ui/cpu/path.rs b/crates/renderling/src/ui/cpu/path.rs index 3dfb1643..b65929d5 100644 --- a/crates/renderling/src/ui/cpu/path.rs +++ b/crates/renderling/src/ui/cpu/path.rs @@ -1,7 +1,7 @@ //! Path and builder. //! //! Path colors are sRGB. -use crate::{geometry::Vertex, material::Material, stage::Renderlet}; +use crate::{geometry::Vertex, material::Material, stage::Primitive}; use glam::{Vec2, Vec3, Vec3Swizzles, Vec4}; use lyon::{ path::traits::PathBuilder, @@ -16,7 +16,7 @@ pub use lyon::tessellation::{LineCap, LineJoin}; pub struct UiPath { pub transform: UiTransform, pub material: Material, - pub renderlet: Renderlet, + pub primitive: Primitive, } #[derive(Clone, Copy)] @@ -386,10 +386,10 @@ impl UiPathBuilder { ); let transform = self.ui.new_transform(); - let renderlet = self + let primitive = self .ui .stage - .new_renderlet() + .new_primitive() .with_vertices(&vertices) .with_indices(&indices) .with_material(&material) @@ -398,7 +398,7 @@ impl UiPathBuilder { UiPath { transform, material, - renderlet, + primitive, } } @@ -467,7 +467,7 @@ impl UiPathBuilder { let renderlet = self .ui .stage - .new_renderlet() + .new_primitive() .with_vertices(vertices) .with_indices(indices) .with_transform(&transform.transform) @@ -475,7 +475,7 @@ impl UiPathBuilder { UiPath { transform, material, - renderlet, + primitive: renderlet, } } diff --git a/crates/renderling/src/ui/cpu/text.rs b/crates/renderling/src/ui/cpu/text.rs index 37092388..19b2eb1c 100644 --- a/crates/renderling/src/ui/cpu/text.rs +++ b/crates/renderling/src/ui/cpu/text.rs @@ -14,7 +14,7 @@ use glyph_brush::*; pub use ab_glyph::FontArc; pub use glyph_brush::{Section, Text}; -use crate::{atlas::AtlasTexture, geometry::Vertex, material::Material, stage::Renderlet}; +use crate::{atlas::AtlasTexture, geometry::Vertex, material::Material, stage::Primitive}; use image::{DynamicImage, GenericImage, ImageBuffer, Luma, Rgba}; use super::{Ui, UiTransform}; @@ -94,7 +94,7 @@ impl UiTextBuilder { let transform = ui.new_transform(); let renderlet = ui .stage - .new_renderlet() + .new_primitive() .with_vertices(vertices) .with_transform(&transform.transform) .with_material(&material); @@ -111,7 +111,7 @@ impl UiTextBuilder { pub struct UiText { pub(crate) transform: UiTransform, - pub(crate) renderlet: Renderlet, + pub(crate) renderlet: Primitive, pub(crate) bounds: (Vec2, Vec2), pub(crate) _cache: GlyphCache, diff --git a/crates/renderling/tests/wasm.rs b/crates/renderling/tests/wasm.rs index d53d096e..20b1fcd7 100644 --- a/crates/renderling/tests/wasm.rs +++ b/crates/renderling/tests/wasm.rs @@ -1013,7 +1013,7 @@ async fn can_render_hello_triangle() { .new_camera() .with_projection_and_view(projection, view); let _rez = stage - .new_renderlet() + .new_primitive() .with_vertices(stage.new_vertices(right_tri_vertices())); let frame = ctx.get_next_frame().unwrap(); From 347db47c1e0486bb3fa414564355ff3c1fab1292 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Wed, 10 Sep 2025 09:32:56 +1200 Subject: [PATCH 13/31] regen shaders, move bloom shaders --- .../bloom-bloom_downsample_fragment.spv | Bin 4956 -> 0 bytes .../shaders/bloom-bloom_mix_fragment.spv | Bin 1796 -> 0 bytes .../shaders/bloom-bloom_upsample_fragment.spv | Bin 3324 -> 0 bytes ...loom-shaders-bloom_downsample_fragment.spv | Bin 0 -> 4964 bytes .../bloom-shaders-bloom_mix_fragment.spv | Bin 0 -> 1804 bytes .../bloom-shaders-bloom_upsample_fragment.spv | Bin 0 -> 3332 bytes ...tex.spv => bloom-shaders-bloom_vertex.spv} | Bin 1336 -> 1348 bytes crates/renderling/shaders/manifest.json | 36 ++-- ...gment.spv => stage-primitive_fragment.spv} | Bin 108052 -> 108052 bytes ..._vertex.spv => stage-primitive_vertex.spv} | Bin 44144 -> 44144 bytes .../shaders/tutorial-slabbed_renderlet.spv | Bin 44200 -> 44200 bytes crates/renderling/src/bloom.rs | 186 +----------------- crates/renderling/src/bloom/shaders.rs | 182 +++++++++++++++++ crates/renderling/src/context.rs | 3 +- crates/renderling/src/cull/cpu.rs | 2 +- crates/renderling/src/geometry/cpu.rs | 3 +- crates/renderling/src/lib.rs | 9 +- crates/renderling/src/light/cpu.rs | 3 +- crates/renderling/src/light/cpu/test.rs | 122 +++++++----- crates/renderling/src/linkage.rs | 4 +- .../src/linkage/bloom_downsample_fragment.rs | 8 +- .../src/linkage/bloom_mix_fragment.rs | 8 +- .../src/linkage/bloom_upsample_fragment.rs | 8 +- crates/renderling/src/linkage/bloom_vertex.rs | 8 +- ...rlet_fragment.rs => primitive_fragment.rs} | 12 +- ...enderlet_vertex.rs => primitive_vertex.rs} | 12 +- crates/renderling/src/stage/cpu.rs | 4 +- crates/renderling/tests/wasm.rs | 4 + 28 files changed, 319 insertions(+), 295 deletions(-) delete mode 100644 crates/renderling/shaders/bloom-bloom_downsample_fragment.spv delete mode 100644 crates/renderling/shaders/bloom-bloom_mix_fragment.spv delete mode 100644 crates/renderling/shaders/bloom-bloom_upsample_fragment.spv create mode 100644 crates/renderling/shaders/bloom-shaders-bloom_downsample_fragment.spv create mode 100644 crates/renderling/shaders/bloom-shaders-bloom_mix_fragment.spv create mode 100644 crates/renderling/shaders/bloom-shaders-bloom_upsample_fragment.spv rename crates/renderling/shaders/{bloom-bloom_vertex.spv => bloom-shaders-bloom_vertex.spv} (82%) rename crates/renderling/shaders/{stage-renderlet_fragment.spv => stage-primitive_fragment.spv} (99%) rename crates/renderling/shaders/{stage-renderlet_vertex.spv => stage-primitive_vertex.spv} (98%) create mode 100644 crates/renderling/src/bloom/shaders.rs rename crates/renderling/src/linkage/{renderlet_fragment.rs => primitive_fragment.rs} (71%) rename crates/renderling/src/linkage/{renderlet_vertex.rs => primitive_vertex.rs} (71%) diff --git a/crates/renderling/shaders/bloom-bloom_downsample_fragment.spv b/crates/renderling/shaders/bloom-bloom_downsample_fragment.spv deleted file mode 100644 index d6660d641769ad1968f572f2de21c114becdad29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4956 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 diff --git a/crates/renderling/shaders/bloom-shaders-bloom_downsample_fragment.spv b/crates/renderling/shaders/bloom-shaders-bloom_downsample_fragment.spv new file mode 100644 index 0000000000000000000000000000000000000000..432592f2d755c5bd70948d97f2291ffeebdb6dbd GIT binary patch literal 4964 zcmZvfSB#Za6or2n5V3&hfYN8gf+AR>1{_Ob0#T!&6gxA*s4J9w+z2d)~X**^JgtsxUgsP^)a%#0{>&Tymv3qK98~A@Z0~5DCua?%b_8)7 z+to%qlBZhv(R6kO@tAsMV|Al=ZpU`^VdO?P_^R5Ooc)dUZ#=e+ox|ETo_dzw2~|7K zb{J<6PpSJ`?->(_^{^Y;Wo-Z58_|F99*ubM5&Q6&=wZ)Vqpp>6#`E<2y?EN!p6NXS z+^2~50ek-5__A(do%7sDY}P^XvG3;i$l=w%YCo_Vds&}l?DG8mH^YW@1gZmS{=k|~ zd=Rm9&f=XI`>x0ttM^V_Bk_4KPtP~!8Q!tW*w58>!P@wq0%jea_^?K}xFc~#Bd$8E zZv*@8*z;gqwDYu=%g^ms=9tFwXmZ}`G3?CWLA^5^%htcKn&a4dx(C)fo=!vSy!%a@ zG^ak`cl73FuxGP9OMH2K)=Y5f?yq~zg0sK5-_YC3I_t|=ej}54{>fnL?Cs~RRv*WM zUHVXS0(d&xe&VB;!gp#0+nIe&Jv(!r2sU>q^}ZV?vE>%WKUlr*V0z60r`Jqydd&u# zORqU#x#{%sj!$OWU*0+Ou221zvAlCza|+u!XYo6ub_V_QdMewzE8J;dIj*AN%lGwk zw(nvzXMp{@U02n;&IJ2ivF8;vHy5ndTxvVP*4jU{U0`cHdr4h;7PymbF7wX=+tZwP z=J#P9jeKusQ|EVNKCzsh=fL?p)J@#r!Rd7#Sa0@9?Sdw?J#g~sQ@arCOkHgKde0ZI zoy%PMUDTxC#c=ZK)9(_nb9J&)dufx}%i!eIM|Wit-Bob%`pJDR0q3*GxmPsu|3CMd zCjG93lUMI&>%3R9d(V4AliC~M9-V4UVUnB0x#)R zdwY}GWpMK9<7Fw>bA4}fSGRyW*}jiC<5sX*bMd#l$r*RU$*a%1aU0mX@_Uuq2b?kp09PKzZc;2XfC=J!G7+pocj`3kLIF#8LY1K_X?aI%|*Aa z)|LL&!|BmnbQ@}2>F-rIJ(`Q|HE>VuFWl>Jm-X`e2Ao=R(Y*<_R%y7mz}CuT-nYSO z%|-VP*jncZ_b%Ala<=#2)S8R#eXzC87VZPEwdK4Y!oANn7u`qTrRZGo_c7S{%tiMJ zSe?@7J_S3Ax#&Ivt1CT!4ySK((S1?tN`GI%>Cs$tUxBaf4hmT*2RC$J2Kl*q)QXck*w&(L7%!F8OH3 z!+Tb#eTBH>qn!w^hf=$axa6Zf0A6o<6du+Sm;7}8JvWy8A@KV1T>GgzoVRX3o%@S7 H`cU@2TFbUs literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/bloom-shaders-bloom_mix_fragment.spv b/crates/renderling/shaders/bloom-shaders-bloom_mix_fragment.spv new file mode 100644 index 0000000000000000000000000000000000000000..8083476800f4f10c3569ec9ed65df0905f222172 GIT binary patch literal 1804 zcmYk5TT9eI7{+H^&4kb*J89Z(Mw*=?A~q_5LZg#LDIIl9tsoP$i!Lfs^S-+3@EyA7 z8}%Wg0|fnk|DDkpcy`|Bd5<&y*>Y1~YiKEj5IVwFeqCEaQ&4gL(HTN}C>OfF9icNc zv+JLFHa|aCt1UjMPtPnY)@lWxn0xwiVs@eacy8wTi$H}?WSi3hHh@;J5wwBLc&(*2 zMCC4aV~iid*UfH?VY0PdeT}W~>)Q#;)vm7j8hmfY?a`ZY`>*qIF;hF5wVY3%v&o&u z+V)61ukGFFPx12H@0s*B&edF;G532n`pvVxJo&f5cf%{dRe|@gmwBs=Z@e?P zah_ol@b0$b+f(Qv?7&ySmNx-;HF9S(*Z%2TTZ!s}S5fw{YoCer&9}!vxHIerF1hvl z3%1S&3jX$dCp8aX+iQ^B8s?`uhp=Y9BQyc4Q~^yzU3g*?$$7XKlZqvCeUY-Q^s{Tm{#F^|UYW z5AjW02cFqCW$$#(8`%0@k?&g=0cy@+ZR=Ps=jzU7{3tNTUj4vWYx^#4g67Em_U}O% zjByXXhYwLRZXB)3{xRx)k5M#x+=@Eensz&CrA!-(n&(V2jAQ#&fw&%*V3ApFVwMn@1 z5T6Rue-ppls6qD^V*V)CD1xDkLU&#ETw?Hbn}kEv+r02MvED#S2kS zXkv^I0~|DHJP;LBaNqYWE(fED+gU*qqR;bn-a7dvc{{&(=G|t#Y1=Y&QEQq$C8gAs zdYu^Oq^U{i{NwDDW~7#i`?D?0O4FF#-!M2lJk--OwxxgL!01>{Pqps5dt|JCXk>7p zZ_{Z1=AnVD+sKlt48~2z&cIr+nNahn*OGM}vwQljWp6&Su{RKc0KC@B07!ma5MgdC#8B9lo9?YMo2$0@e-8(O`W( zv%d0$WcJ+Z_Izg7`YmKW8}sbvv1iT(Hix|qX4m%bx{=qO!`Mz{dv0K}@Ur(#i1(+y zCg(Ta8ke%RhYK->Yx7@Jtx{UTH?U?`X7btOy@c6%ixqHJ*8M*hPGbhUW#U1 zx0t@nvkZ&9Zg)~zJujV=E=Smlxr~qD+F|`GCS>J1AFnGjzbf-sFK2C>XYmeP`!-~* z_4f`P3+QVFv-RDxhIi_4?RWIs8ykJELZ{SR?S3c9w_wcVzRs!Hdo@-44%L#`?{bR1 z*E3(wp7(eQ7U%6HpFQ7-*{^GT`Y?Mq4D}9w!i@8-Pg41JX2(DHyZ1Bp8)hx_1G&~O z=!knh=lT_9e)s;y-(1ESU#{hUa#HL6ff;9Rzo)+T(a-F#4}CUZw_)Z}ui+HFp^cbl z_8nR~&N+Z~?>^#v3!5-mGxxt4t-o(Ba&19JF83qX?P&KR*BxltI&yU|--(%D?m6w< zKJB+$%RRR-gP3uir3=&dM)KL~5azxk*jBX6?{8ne&tYsD7Cs|rzqeyo&UF`BZqD!< zMeAp-o!M^;Ew@gbYa7~l_pIr={tIitZX(XNeljzAxf#}AK84ARkDA*vXPRX9WM&`X zcW-8Xhv?&ev}dr7sQWM4Udp;2NUne6+kuW>nqbY$%DOu{+x-9PGKw>?Q902-r@T0$T0} z_99v)4)#)J)*a{Wy@R9JUd;c0!H%JQM?^cqHb=0p(Vp2H!M;IzW^=?n ve~UJL6%R1jcdU&s+4roCm#yP}as&MXX1xCHFU79qzg;V{d#8ETE3y9o0yiZT literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/bloom-bloom_vertex.spv b/crates/renderling/shaders/bloom-shaders-bloom_vertex.spv similarity index 82% rename from crates/renderling/shaders/bloom-bloom_vertex.spv rename to crates/renderling/shaders/bloom-shaders-bloom_vertex.spv index be801ad55739343a3d53a101080606aa77e3a34b..0b4ff7f454503fcf0222b96608c0a6772b8ea696 100644 GIT binary patch delta 52 zcmdnNb%bkzk){9x2rvS1Qciw;u9a1BMq)~8QL&X3m>*x3T2zu+0hHe8|B?j&Y@QE$ delta 40 ocmX@YwS#Mdkt{C*2rvS1Qciw;u9X#-iZ4qoDoL%_82yq30L)4Z8UO$Q diff --git a/crates/renderling/shaders/manifest.json b/crates/renderling/shaders/manifest.json index b38af795..6e975137 100644 --- a/crates/renderling/shaders/manifest.json +++ b/crates/renderling/shaders/manifest.json @@ -10,24 +10,24 @@ "wgsl_entry_point": "atlasatlas_blit_vertex" }, { - "source_path": "shaders/bloom-bloom_downsample_fragment.spv", - "entry_point": "bloom::bloom_downsample_fragment", - "wgsl_entry_point": "bloombloom_downsample_fragment" + "source_path": "shaders/bloom-shaders-bloom_downsample_fragment.spv", + "entry_point": "bloom::shaders::bloom_downsample_fragment", + "wgsl_entry_point": "bloomshadersbloom_downsample_fragment" }, { - "source_path": "shaders/bloom-bloom_mix_fragment.spv", - "entry_point": "bloom::bloom_mix_fragment", - "wgsl_entry_point": "bloombloom_mix_fragment" + "source_path": "shaders/bloom-shaders-bloom_mix_fragment.spv", + "entry_point": "bloom::shaders::bloom_mix_fragment", + "wgsl_entry_point": "bloomshadersbloom_mix_fragment" }, { - "source_path": "shaders/bloom-bloom_upsample_fragment.spv", - "entry_point": "bloom::bloom_upsample_fragment", - "wgsl_entry_point": "bloombloom_upsample_fragment" + "source_path": "shaders/bloom-shaders-bloom_upsample_fragment.spv", + "entry_point": "bloom::shaders::bloom_upsample_fragment", + "wgsl_entry_point": "bloomshadersbloom_upsample_fragment" }, { - "source_path": "shaders/bloom-bloom_vertex.spv", - "entry_point": "bloom::bloom_vertex", - "wgsl_entry_point": "bloombloom_vertex" + "source_path": "shaders/bloom-shaders-bloom_vertex.spv", + "entry_point": "bloom::shaders::bloom_vertex", + "wgsl_entry_point": "bloomshadersbloom_vertex" }, { "source_path": "shaders/convolution-brdf_lut_convolution_fragment.spv", @@ -160,14 +160,14 @@ "wgsl_entry_point": "skyboxskybox_vertex" }, { - "source_path": "shaders/stage-renderlet_fragment.spv", - "entry_point": "stage::renderlet_fragment", - "wgsl_entry_point": "stagerenderlet_fragment" + "source_path": "shaders/stage-primitive_fragment.spv", + "entry_point": "stage::primitive_fragment", + "wgsl_entry_point": "stageprimitive_fragment" }, { - "source_path": "shaders/stage-renderlet_vertex.spv", - "entry_point": "stage::renderlet_vertex", - "wgsl_entry_point": "stagerenderlet_vertex" + "source_path": "shaders/stage-primitive_vertex.spv", + "entry_point": "stage::primitive_vertex", + "wgsl_entry_point": "stageprimitive_vertex" }, { "source_path": "shaders/tonemapping-tonemapping_fragment.spv", diff --git a/crates/renderling/shaders/stage-renderlet_fragment.spv b/crates/renderling/shaders/stage-primitive_fragment.spv similarity index 99% rename from crates/renderling/shaders/stage-renderlet_fragment.spv rename to crates/renderling/shaders/stage-primitive_fragment.spv index 3d6a278e72b528e97b89190f93e830a2944dec7c..4d3f6441254eeef68c69d4c7555d4d60575d6545 100644 GIT binary patch delta 25 hcmbPohHc6jwh7Uk1x1;;nI)NJsf{UHQy4ca1pti~3hn>^ delta 25 hcmbPohHc6jwh7UkMX7lysYN-dC5$jnFf%YPa09XSWK-s;n{P44u};3hDKOcB LbHU~poE?h*MH3U8 diff --git a/crates/renderling/shaders/tutorial-slabbed_renderlet.spv b/crates/renderling/shaders/tutorial-slabbed_renderlet.spv index 0050555940615424146bfd6836aa03ed51150b00..a453ac6d3a0579494f9bdb0a76bd528f88da2eb7 100644 GIT binary patch delta 55 zcmZ2+lWE0GrVTbMlYLl9c-Ft7`TC0d-GlvX4c6UI2Z6*1BEMqLLe!|&AD9G FivWf@3^o7& delta 54 zcmZ2+lWE0GrVTbMyzUGv49pA+4BSAhJ=v0_eDMJmR$gnMXa!INB*Qp)FX!UT1zZ-3 E08q~i1^@s6 diff --git a/crates/renderling/src/bloom.rs b/crates/renderling/src/bloom.rs index b3bdddee..f753c29b 100644 --- a/crates/renderling/src/bloom.rs +++ b/crates/renderling/src/bloom.rs @@ -1,190 +1,10 @@ //! Physically based bloom. //! -//! As described in [learnopengl.com's Physically Based Bloom article](https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom). -use crabslab::{Id, Slab}; -use glam::{Vec2, Vec4, Vec4Swizzles}; -use spirv_std::{image::Image2d, spirv, Sampler}; - +//! As described in [learnopengl.com's Physically Based Bloom +//! article](https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom). #[cfg(not(target_arch = "spirv"))] mod cpu; #[cfg(not(target_arch = "spirv"))] pub use cpu::*; -/// Bloom vertex shader. -/// -/// This is a pass-through vertex shader to facilitate a bloom effect. -#[spirv(vertex)] -pub fn bloom_vertex( - #[spirv(vertex_index)] vertex_index: u32, - #[spirv(instance_index)] in_id: u32, - out_uv: &mut Vec2, - #[spirv(flat)] out_id: &mut u32, - #[spirv(position)] out_clip_pos: &mut Vec4, -) { - let i = (vertex_index % 6) as usize; - *out_uv = crate::math::UV_COORD_QUAD_CCW[i]; - *out_clip_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i]; - *out_id = in_id; -} - -/// Bloom downsampling shader. -/// -/// Performs successive downsampling from a source texture. -/// -/// As taken from Call Of Duty method - presented at ACM Siggraph 2014. -/// -/// This particular method was designed to eliminate -/// "pulsating artifacts and temporal stability issues". -#[spirv(fragment)] -pub fn bloom_downsample_fragment( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - // Remember to add bilinear minification filter for this texture! - // Remember to use a floating-point texture format (for HDR)! - // Remember to use edge clamping for this texture! - #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, - in_uv: Vec2, - #[spirv(flat)] in_pixel_size_id: Id, - // frag_color - downsample: &mut Vec4, -) { - use glam::Vec3; - - let Vec2 { x, y } = slab.read(in_pixel_size_id); - - // Take 13 samples around current texel: - // a - b - c - // - j - k - - // d - e - f - // - l - m - - // g - h - i - // === ('e' is the current texel) === - let a = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y + 2.0 * y)); - let b = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y + 2.0 * y)); - let c = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y + 2.0 * y)); - - let d = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y)); - let e = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y)); - let f = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y)); - - let g = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y - 2.0 * y)); - let h = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y - 2.0 * y)); - let i = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y - 2.0 * y)); - - let j = texture.sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y + y)); - let k = texture.sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y + y)); - let l = texture.sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y - y)); - let m = texture.sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y - y)); - - // Apply weighted distribution: - // 0.5 + 0.125 + 0.125 + 0.125 + 0.125 = 1 - // a,b,d,e * 0.125 - // b,c,e,f * 0.125 - // d,e,g,h * 0.125 - // e,f,h,i * 0.125 - // j,k,l,m * 0.5 - // This shows 5 square areas that are being sampled. But some of them overlap, - // so to have an energy preserving downsample we need to make some adjustments. - // The weights are the distributed so that the sum of j,k,l,m (e.g.) - // contribute 0.5 to the final color output. The code below is written - // to effectively yield this sum. We get: - // 0.125*5 + 0.03125*4 + 0.0625*4 = 1 - let f1 = 0.125; - let f2 = 0.0625; - let f3 = 0.03125; - let center = e * f1; - let inner = (j + k + l + m) * f1; - let outer = (b + d + h + f) * f2; - let furthest = (a + c + g + i) * f3; - let min = Vec3::splat(f32::EPSILON).extend(1.0); - *downsample = (center + inner + outer + furthest).max(min); -} - -/// Bloom upsampling shader. -/// -/// This shader performs successive upsampling on a source texture. -/// -/// Taken from Call Of Duty method, presented at ACM Siggraph 2014. -#[spirv(fragment)] -pub fn bloom_upsample_fragment( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - // Remember to add bilinear minification filter for this texture! - // Remember to use a floating-point texture format (for HDR)! - // Remember to use edge clamping for this texture! - #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, - in_uv: Vec2, - #[spirv(flat)] filter_radius_id: Id, - // frag_color - upsample: &mut Vec4, -) { - // The filter kernel is applied with a radius, specified in texture - // coordinates, so that the radius will vary across mip resolutions. - let Vec2 { x, y } = slab.read(filter_radius_id); - - // Take 9 samples around current texel: - // a - b - c - // d - e - f - // g - h - i - // === ('e' is the current texel) === - let a = texture - .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y + y)) - .xyz(); - let b = texture - .sample(*sampler, Vec2::new(in_uv.x, in_uv.y + y)) - .xyz(); - let c = texture - .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y + y)) - .xyz(); - - let d = texture - .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y)) - .xyz(); - let e = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y)).xyz(); - let f = texture - .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y)) - .xyz(); - - let g = texture - .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y - y)) - .xyz(); - let h = texture - .sample(*sampler, Vec2::new(in_uv.x, in_uv.y - y)) - .xyz(); - let i = texture - .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y - y)) - .xyz(); - - // Apply weighted distribution, by using a 3x3 tent filter: - // 1 | 1 2 1 | - // -- * | 2 4 2 | - // 16 | 1 2 1 | - let mut sample = e * 4.0; - sample += (b + d + f + h) * 2.0; - sample += a + c + g + i; - sample *= 1.0 / 16.0; - *upsample = sample.extend(0.5); -} - -#[spirv(fragment)] -#[allow(clippy::too_many_arguments)] -/// Bloom "mix" shader. -/// -/// This is the final step in applying bloom in which the computed bloom is -/// mixed with the source texture according to a strength factor. -pub fn bloom_mix_fragment( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - #[spirv(descriptor_set = 0, binding = 1)] hdr_texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 2)] hdr_sampler: &Sampler, - #[spirv(descriptor_set = 0, binding = 3)] bloom_texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 4)] bloom_sampler: &Sampler, - in_uv: Vec2, - #[spirv(flat)] in_bloom_strength_id: Id, - frag_color: &mut Vec4, -) { - let bloom_strength = slab.read(in_bloom_strength_id); - let hdr = hdr_texture.sample(*hdr_sampler, in_uv).xyz(); - let bloom = bloom_texture.sample(*bloom_sampler, in_uv).xyz(); - let color = hdr.lerp(bloom, bloom_strength); - *frag_color = color.extend(1.0) -} +pub mod shaders; diff --git a/crates/renderling/src/bloom/shaders.rs b/crates/renderling/src/bloom/shaders.rs new file mode 100644 index 00000000..c8185c74 --- /dev/null +++ b/crates/renderling/src/bloom/shaders.rs @@ -0,0 +1,182 @@ +use crabslab::{Id, Slab}; +use glam::{Vec2, Vec4, Vec4Swizzles}; +use spirv_std::{image::Image2d, spirv, Sampler}; + +/// Bloom vertex shader. +/// +/// This is a pass-through vertex shader to facilitate a bloom effect. +#[spirv(vertex)] +pub fn bloom_vertex( + #[spirv(vertex_index)] vertex_index: u32, + #[spirv(instance_index)] in_id: u32, + out_uv: &mut Vec2, + #[spirv(flat)] out_id: &mut u32, + #[spirv(position)] out_clip_pos: &mut Vec4, +) { + let i = (vertex_index % 6) as usize; + *out_uv = crate::math::UV_COORD_QUAD_CCW[i]; + *out_clip_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i]; + *out_id = in_id; +} + +/// Bloom downsampling shader. +/// +/// Performs successive downsampling from a source texture. +/// +/// As taken from Call Of Duty method - presented at ACM Siggraph 2014. +/// +/// This particular method was designed to eliminate +/// "pulsating artifacts and temporal stability issues". +#[spirv(fragment)] +pub fn bloom_downsample_fragment( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], + // Remember to add bilinear minification filter for this texture! + // Remember to use a floating-point texture format (for HDR)! + // Remember to use edge clamping for this texture! + #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, + #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, + in_uv: Vec2, + #[spirv(flat)] in_pixel_size_id: Id, + // frag_color + downsample: &mut Vec4, +) { + use glam::Vec3; + + let Vec2 { x, y } = slab.read(in_pixel_size_id); + + // Take 13 samples around current texel: + // a - b - c + // - j - k - + // d - e - f + // - l - m - + // g - h - i + // === ('e' is the current texel) === + let a = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y + 2.0 * y)); + let b = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y + 2.0 * y)); + let c = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y + 2.0 * y)); + + let d = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y)); + let e = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y)); + let f = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y)); + + let g = texture.sample(*sampler, Vec2::new(in_uv.x - 2.0 * x, in_uv.y - 2.0 * y)); + let h = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y - 2.0 * y)); + let i = texture.sample(*sampler, Vec2::new(in_uv.x + 2.0 * x, in_uv.y - 2.0 * y)); + + let j = texture.sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y + y)); + let k = texture.sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y + y)); + let l = texture.sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y - y)); + let m = texture.sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y - y)); + + // Apply weighted distribution: + // 0.5 + 0.125 + 0.125 + 0.125 + 0.125 = 1 + // a,b,d,e * 0.125 + // b,c,e,f * 0.125 + // d,e,g,h * 0.125 + // e,f,h,i * 0.125 + // j,k,l,m * 0.5 + // This shows 5 square areas that are being sampled. But some of them overlap, + // so to have an energy preserving downsample we need to make some adjustments. + // The weights are the distributed so that the sum of j,k,l,m (e.g.) + // contribute 0.5 to the final color output. The code below is written + // to effectively yield this sum. We get: + // 0.125*5 + 0.03125*4 + 0.0625*4 = 1 + let f1 = 0.125; + let f2 = 0.0625; + let f3 = 0.03125; + let center = e * f1; + let inner = (j + k + l + m) * f1; + let outer = (b + d + h + f) * f2; + let furthest = (a + c + g + i) * f3; + let min = Vec3::splat(f32::EPSILON).extend(1.0); + *downsample = (center + inner + outer + furthest).max(min); +} + +/// Bloom upsampling shader. +/// +/// This shader performs successive upsampling on a source texture. +/// +/// Taken from Call Of Duty method, presented at ACM Siggraph 2014. +#[spirv(fragment)] +pub fn bloom_upsample_fragment( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], + // Remember to add bilinear minification filter for this texture! + // Remember to use a floating-point texture format (for HDR)! + // Remember to use edge clamping for this texture! + #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, + #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, + in_uv: Vec2, + #[spirv(flat)] filter_radius_id: Id, + // frag_color + upsample: &mut Vec4, +) { + // The filter kernel is applied with a radius, specified in texture + // coordinates, so that the radius will vary across mip resolutions. + let Vec2 { x, y } = slab.read(filter_radius_id); + + // Take 9 samples around current texel: + // a - b - c + // d - e - f + // g - h - i + // === ('e' is the current texel) === + let a = texture + .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y + y)) + .xyz(); + let b = texture + .sample(*sampler, Vec2::new(in_uv.x, in_uv.y + y)) + .xyz(); + let c = texture + .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y + y)) + .xyz(); + + let d = texture + .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y)) + .xyz(); + let e = texture.sample(*sampler, Vec2::new(in_uv.x, in_uv.y)).xyz(); + let f = texture + .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y)) + .xyz(); + + let g = texture + .sample(*sampler, Vec2::new(in_uv.x - x, in_uv.y - y)) + .xyz(); + let h = texture + .sample(*sampler, Vec2::new(in_uv.x, in_uv.y - y)) + .xyz(); + let i = texture + .sample(*sampler, Vec2::new(in_uv.x + x, in_uv.y - y)) + .xyz(); + + // Apply weighted distribution, by using a 3x3 tent filter: + // 1 | 1 2 1 | + // -- * | 2 4 2 | + // 16 | 1 2 1 | + let mut sample = e * 4.0; + sample += (b + d + f + h) * 2.0; + sample += a + c + g + i; + sample *= 1.0 / 16.0; + *upsample = sample.extend(0.5); +} + +#[spirv(fragment)] +#[allow(clippy::too_many_arguments)] +/// Bloom "mix" shader. +/// +/// This is the final step in applying bloom in which the computed bloom is +/// mixed with the source texture according to a strength factor. +pub fn bloom_mix_fragment( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], + #[spirv(descriptor_set = 0, binding = 1)] hdr_texture: &Image2d, + #[spirv(descriptor_set = 0, binding = 2)] hdr_sampler: &Sampler, + #[spirv(descriptor_set = 0, binding = 3)] bloom_texture: &Image2d, + #[spirv(descriptor_set = 0, binding = 4)] bloom_sampler: &Sampler, + in_uv: Vec2, + #[spirv(flat)] in_bloom_strength_id: Id, + frag_color: &mut Vec4, +) { + let bloom_strength = slab.read(in_bloom_strength_id); + let hdr = hdr_texture.sample(*hdr_sampler, in_uv).xyz(); + let bloom = bloom_texture.sample(*bloom_sampler, in_uv).xyz(); + let color = hdr.lerp(bloom, bloom_strength); + *frag_color = color.extend(1.0) +} diff --git a/crates/renderling/src/context.rs b/crates/renderling/src/context.rs index 2b4adfa2..1d175329 100644 --- a/crates/renderling/src/context.rs +++ b/crates/renderling/src/context.rs @@ -5,7 +5,6 @@ use std::{ sync::{Arc, RwLock}, }; -use craballoc::runtime::WgpuRuntime; use glam::{UVec2, UVec3}; use snafu::prelude::*; @@ -15,6 +14,8 @@ use crate::{ ui::Ui, }; +pub use craballoc::runtime::WgpuRuntime; + pub(crate) enum RenderTargetInner { Surface { surface: wgpu::Surface<'static>, diff --git a/crates/renderling/src/cull/cpu.rs b/crates/renderling/src/cull/cpu.rs index d2abb113..ec279a7e 100644 --- a/crates/renderling/src/cull/cpu.rs +++ b/crates/renderling/src/cull/cpu.rs @@ -676,7 +676,7 @@ mod test { bvol::BoundingSphere, cull::DepthPyramidDescriptor, draw::DrawIndirectArgs, geometry::Geometry, math::hex_to_vec4, prelude::*, test::BlockOnFuture, }; - use crabslab::{GrowableSlab, Slab}; + use crabslab::{Array, GrowableSlab, Id, Slab}; use glam::{Mat4, Quat, UVec2, UVec3, Vec2, Vec3, Vec4}; #[test] diff --git a/crates/renderling/src/geometry/cpu.rs b/crates/renderling/src/geometry/cpu.rs index 267e6347..36badcff 100644 --- a/crates/renderling/src/geometry/cpu.rs +++ b/crates/renderling/src/geometry/cpu.rs @@ -12,8 +12,7 @@ use glam::{Mat4, UVec2, Vec4}; use crate::{ camera::Camera, geometry::{GeometryDescriptor, MorphTarget, SkinDescriptor, Vertex}, - prelude::TransformDescriptor, - transform::{NestedTransform, Transform}, + transform::{NestedTransform, Transform, TransformDescriptor}, types::{GpuCpuArray, GpuOnlyArray}, }; diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index 549d0806..d8b982d4 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -237,14 +237,7 @@ pub mod prelude { pub extern crate glam; - #[cfg(cpu)] - pub use craballoc::prelude::*; - pub use crabslab::{Array, Id}; - - pub use crate::{ - camera::*, geometry::*, light::*, material::MaterialDescriptor, stage::*, - transform::TransformDescriptor, - }; + pub use crate::{camera::*, geometry::*, light::*, stage::*}; #[cfg(cpu)] pub use crate::context::*; diff --git a/crates/renderling/src/light/cpu.rs b/crates/renderling/src/light/cpu.rs index 844beef0..f99eb820 100644 --- a/crates/renderling/src/light/cpu.rs +++ b/crates/renderling/src/light/cpu.rs @@ -13,8 +13,7 @@ use snafu::prelude::*; use crate::{ atlas::{Atlas, AtlasBlitter, AtlasError}, geometry::Geometry, - prelude::TransformDescriptor, - transform::{NestedTransform, Transform}, + transform::{NestedTransform, Transform, TransformDescriptor}, }; use super::{ diff --git a/crates/renderling/src/light/cpu/test.rs b/crates/renderling/src/light/cpu/test.rs index 8ac2c686..80bbf9af 100644 --- a/crates/renderling/src/light/cpu/test.rs +++ b/crates/renderling/src/light/cpu/test.rs @@ -2,11 +2,18 @@ use glam::{Vec3, Vec4, Vec4Swizzles}; - use spirv_std::num_traits::Zero; use crate::{ - bvol::BoundingBox, camera::Camera, color::linear_xfer_vec4, geometry::Vertex, light::{LightTiling, LightTilingConfig, SpotLightCalculation}, math::GpuRng, prelude::TransformDescriptor, stage::{Primitive, PrimitivePbrVertexInfo, Stage}, test::BlockOnFuture + bvol::BoundingBox, + camera::Camera, + color::linear_xfer_vec4, + geometry::Vertex, + light::{LightTiling, LightTilingConfig, SpotLightCalculation}, + math::GpuRng, + stage::{Primitive, PrimitivePbrVertexInfo, Stage}, + test::BlockOnFuture, + transform::TransformDescriptor, }; use super::*; @@ -127,10 +134,7 @@ fn spot_lights() { stage.use_camera(camera); let down_light = doc.lights.first().unwrap(); - log::info!( - "down_light: {:#?}", - down_light.as_spot().unwrap() - ); + log::info!("down_light: {:#?}", down_light.as_spot().unwrap()); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -166,11 +170,11 @@ fn light_tiling_light_bounds() { }); let colors = [0x6DE1D2FF, 0xFFD63AFF, 0x6DE1D2FF, 0xF75A5AFF].map(|albedo_factor| { - stage.new_material().with_albedo_factor ({ - let mut color = crate::math::hex_to_vec4(albedo_factor); - linear_xfer_vec4(&mut color); - color - }) + stage.new_material().with_albedo_factor({ + let mut color = crate::math::hex_to_vec4(albedo_factor); + linear_xfer_vec4(&mut color); + color + }) }); let mut resources = vec![]; for (i, node) in doc.nodes.iter().enumerate() { @@ -194,11 +198,14 @@ fn light_tiling_light_bounds() { resources.push( stage .new_primitive() - .with_vertices(stage.new_vertices( - bb.get_mesh() - .map(|(p, n)| Vertex::default().with_position(p).with_normal(n)) - )) - .with_material(&colors[i % colors.len()]) + .with_vertices( + stage.new_vertices( + bb.get_mesh().map(|(p, n)| { + Vertex::default().with_position(p).with_normal(n) + }), + ), + ) + .with_material(&colors[i % colors.len()]), ); } } @@ -249,20 +256,28 @@ fn gen_light(stage: &Stage, prng: &mut GpuRng, bounding_boxes: &[BoundingBox]) - let _unused_transform = stage.new_transform().with_translation(position); let vertices = stage.new_vertices( - light_bb - .get_mesh() - .map(|(p, n)| Vertex::default().with_position(p).with_normal(n)), - ); - let material = stage.new_material() - .with_albedo_factor(color) - .with_has_lighting(false) - .with_emissive_factor(color.xyz()) - .with_emissive_strength_multiplier(100.0); - let mesh_renderlet = stage.new_primitive().with_vertices(vertices).with_material(material); + light_bb + .get_mesh() + .map(|(p, n)| Vertex::default().with_position(p).with_normal(n)), + ); + let material = stage + .new_material() + .with_albedo_factor(color) + .with_has_lighting(false) + .with_emissive_factor(color.xyz()) + .with_emissive_strength_multiplier(100.0); + let mesh_renderlet = stage + .new_primitive() + .with_vertices(vertices) + .with_material(material); let _light = { // suffix the actual analytical light let intensity = scale * 100.0; - stage.new_point_light().with_position(position).with_color(color).with_intensity(intensity) + stage + .new_point_light() + .with_position(position) + .with_color(color) + .with_intensity(intensity) }; GeneratedLight { @@ -507,15 +522,20 @@ fn light_bins_point() { ) .unwrap(); - doc.materials.get_mut(0).unwrap() - .set_albedo_factor(Vec4::ONE).set_roughness_factor(1.0).set_metallic_factor(0.0); - + doc.materials + .get_mut(0) + .unwrap() + .set_albedo_factor(Vec4::ONE) + .set_roughness_factor(1.0) + .set_metallic_factor(0.0); + let camera = doc.cameras.first().unwrap(); - let view = Mat4::look_at_rh(Vec3::new(-7.0, 5.0, 7.0), Vec3::ZERO, Vec3::Y); - let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_6, 1.0, 0.1, 15.0); + let view = Mat4::look_at_rh(Vec3::new(-7.0, 5.0, 7.0), Vec3::ZERO, Vec3::Y); + let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_6, 1.0, 0.1, 15.0); camera.camera.set_projection_and_view(proj, view); - let _point_light = stage.new_point_light() + let _point_light = stage + .new_point_light() .with_position(Vec3::new(1.1, 1.0, 1.1)) .with_color(Vec4::ONE) .with_intensity(5.0); @@ -643,7 +663,7 @@ fn tiling_e2e_sanity_with( &ctx, &stage, &format!("light/tiling/e2e/6-scene-{tile_size}-{max_lights_per_tile}-lights-{i}-{minimum_illuminance}-min-lux.png"), - save_images + save_images ); #[cfg(feature = "light-tiling-stats")] @@ -721,7 +741,7 @@ fn tiling_e2e_sanity() { max_lights_per_tile, i as u32, *minimum_illuminance, - true + true, ) } } @@ -733,7 +753,7 @@ fn snapshot(ctx: &crate::Context, stage: &Stage, path: &str, save: bool) { let frame = ctx.get_next_frame().unwrap(); let start = std::time::Instant::now(); stage.render(&frame.view()); - let elapsed = start.elapsed(); + let elapsed = start.elapsed(); log::info!("shapshot: {}s '{path}'", elapsed.as_secs_f32()); let img = frame.read_image().block().unwrap(); if save { @@ -786,8 +806,8 @@ mod stats { } pub fn plot(stats: LightTilingStats, filename: &str) { - let path = - crate::test::workspace_dir().join(format!("test_output/light/tiling/e2e/{filename}.png")); + let path = crate::test::workspace_dir() + .join(format!("test_output/light/tiling/e2e/{filename}.png")); let root_drawing_area = BitMapBackend::new(&path, (800, 600)).into_drawing_area(); root_drawing_area.fill(&plotters::style::WHITE).unwrap(); @@ -856,7 +876,8 @@ mod stats { 5, ShapeStyle::from(&plotters::style::RED).filled(), &|(num_lights, seconds_per_frame), size, style| { - EmptyElement::at((num_lights, seconds_per_frame)) + Circle::new((0, 0), size, style) + EmptyElement::at((num_lights, seconds_per_frame)) + + Circle::new((0, 0), size, style) }, )) .unwrap(); @@ -869,7 +890,8 @@ mod stats { 5, ShapeStyle::from(&plotters::style::BLUE).filled(), &|(num_lights, seconds_per_frame), size, style| { - EmptyElement::at((num_lights, seconds_per_frame)) + Circle::new((0, 0), size, style) + EmptyElement::at((num_lights, seconds_per_frame)) + + Circle::new((0, 0), size, style) }, )) .unwrap(); @@ -909,8 +931,7 @@ fn pedestal() { ) .unwrap(); - doc - .materials + doc.materials .get_mut(0) .unwrap() .set_albedo_factor(Vec4::ONE) @@ -920,7 +941,7 @@ fn pedestal() { let camera = doc.cameras.first().unwrap(); camera.camera.set_projection_and_view( Mat4::perspective_rh(std::f32::consts::FRAC_PI_6, 1.0, 0.1, 15.0), - Mat4::look_at_rh(Vec3::new(-7.0, 5.0, 7.0), Vec3::ZERO, Vec3::Y) + Mat4::look_at_rh(Vec3::new(-7.0, 5.0, 7.0), Vec3::ZERO, Vec3::Y), ); let color = { @@ -935,7 +956,8 @@ fn pedestal() { let mut dir_infos = vec![]; { log::info!("adding dir light"); - let dir_light = stage.new_directional_light() + let dir_light = stage + .new_directional_light() .with_direction(-position) .with_color(color) .with_intensity(5.0); @@ -974,7 +996,8 @@ fn pedestal() { // Point lights { log::info!("adding point light with pre-applied position"); - let point_light = stage.new_point_light() + let point_light = stage + .new_point_light() .with_position(position) .with_color(color) .with_intensity(5.0); @@ -987,7 +1010,8 @@ fn pedestal() { let transform = stage.new_nested_transform(); transform.set_local_translation(position); - let point_light = stage.new_point_light() + let point_light = stage + .new_point_light() .with_position(Vec3::ZERO) .with_color(color) .with_intensity(5.0); @@ -999,7 +1023,8 @@ fn pedestal() { { log::info!("adding spot light with pre-applied position"); - let spot = stage.new_spot_light() + let spot = stage + .new_spot_light() .with_position(position) .with_direction(-position) .with_color(color) @@ -1047,7 +1072,8 @@ fn pedestal() { let node_transform = stage.new_nested_transform(); node_transform.set_local_translation(position); - let spot = stage.new_spot_light() + let spot = stage + .new_spot_light() .with_position(Vec3::ZERO) .with_direction(-position) .with_color(color) diff --git a/crates/renderling/src/linkage.rs b/crates/renderling/src/linkage.rs index 55941dd6..f12c7a3e 100644 --- a/crates/renderling/src/linkage.rs +++ b/crates/renderling/src/linkage.rs @@ -33,8 +33,8 @@ pub mod light_tiling_compute_tile_min_and_max_depth_multisampled; pub mod light_tiling_depth_pre_pass; pub mod prefilter_environment_cubemap_fragment; pub mod prefilter_environment_cubemap_vertex; -pub mod renderlet_fragment; -pub mod renderlet_vertex; +pub mod primitive_fragment; +pub mod primitive_vertex; pub mod shadow_mapping_fragment; pub mod shadow_mapping_vertex; pub mod skybox_cubemap_fragment; diff --git a/crates/renderling/src/linkage/bloom_downsample_fragment.rs b/crates/renderling/src/linkage/bloom_downsample_fragment.rs index 124add10..8e4435b0 100644 --- a/crates/renderling/src/linkage/bloom_downsample_fragment.rs +++ b/crates/renderling/src/linkage/bloom_downsample_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "bloom::bloom_downsample_fragment"; + pub const ENTRY_POINT: &str = "bloom::shaders::bloom_downsample_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-bloom_downsample_fragment.spv") + wgpu::include_spirv!("../../shaders/bloom-shaders-bloom_downsample_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +20,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "bloombloom_downsample_fragment"; + pub const ENTRY_POINT: &str = "bloomshadersbloom_downsample_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-bloom_downsample_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/bloom-shaders-bloom_downsample_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "bloom_downsample_fragment"); diff --git a/crates/renderling/src/linkage/bloom_mix_fragment.rs b/crates/renderling/src/linkage/bloom_mix_fragment.rs index 9bcd9325..dbef37a2 100644 --- a/crates/renderling/src/linkage/bloom_mix_fragment.rs +++ b/crates/renderling/src/linkage/bloom_mix_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "bloom::bloom_mix_fragment"; + pub const ENTRY_POINT: &str = "bloom::shaders::bloom_mix_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-bloom_mix_fragment.spv") + wgpu::include_spirv!("../../shaders/bloom-shaders-bloom_mix_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "bloom_mix_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "bloombloom_mix_fragment"; + pub const ENTRY_POINT: &str = "bloomshadersbloom_mix_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-bloom_mix_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/bloom-shaders-bloom_mix_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "bloom_mix_fragment"); diff --git a/crates/renderling/src/linkage/bloom_upsample_fragment.rs b/crates/renderling/src/linkage/bloom_upsample_fragment.rs index 5884452b..05139518 100644 --- a/crates/renderling/src/linkage/bloom_upsample_fragment.rs +++ b/crates/renderling/src/linkage/bloom_upsample_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "bloom::bloom_upsample_fragment"; + pub const ENTRY_POINT: &str = "bloom::shaders::bloom_upsample_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-bloom_upsample_fragment.spv") + wgpu::include_spirv!("../../shaders/bloom-shaders-bloom_upsample_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "bloom_upsample_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "bloombloom_upsample_fragment"; + pub const ENTRY_POINT: &str = "bloomshadersbloom_upsample_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-bloom_upsample_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/bloom-shaders-bloom_upsample_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "bloom_upsample_fragment"); diff --git a/crates/renderling/src/linkage/bloom_vertex.rs b/crates/renderling/src/linkage/bloom_vertex.rs index 20417c46..3153b8c0 100644 --- a/crates/renderling/src/linkage/bloom_vertex.rs +++ b/crates/renderling/src/linkage/bloom_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "bloom::bloom_vertex"; + pub const ENTRY_POINT: &str = "bloom::shaders::bloom_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-bloom_vertex.spv") + wgpu::include_spirv!("../../shaders/bloom-shaders-bloom_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "bloom_vertex"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "bloombloom_vertex"; + pub const ENTRY_POINT: &str = "bloomshadersbloom_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-bloom_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/bloom-shaders-bloom_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "bloom_vertex"); diff --git a/crates/renderling/src/linkage/renderlet_fragment.rs b/crates/renderling/src/linkage/primitive_fragment.rs similarity index 71% rename from crates/renderling/src/linkage/renderlet_fragment.rs rename to crates/renderling/src/linkage/primitive_fragment.rs index 5984c350..a5cbc0fa 100644 --- a/crates/renderling/src/linkage/renderlet_fragment.rs +++ b/crates/renderling/src/linkage/primitive_fragment.rs @@ -3,12 +3,12 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "stage::renderlet_fragment"; + pub const ENTRY_POINT: &str = "stage::primitive_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/stage-renderlet_fragment.spv") + wgpu::include_spirv!("../../shaders/stage-primitive_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating native linkage for {}", "renderlet_fragment"); + log::debug!("creating native linkage for {}", "primitive_fragment"); super::ShaderLinkage { entry_point: ENTRY_POINT, module: device.create_shader_module(descriptor()).into(), @@ -17,12 +17,12 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "stagerenderlet_fragment"; + pub const ENTRY_POINT: &str = "stageprimitive_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/stage-renderlet_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/stage-primitive_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating web linkage for {}", "renderlet_fragment"); + log::debug!("creating web linkage for {}", "primitive_fragment"); super::ShaderLinkage { entry_point: ENTRY_POINT, module: device.create_shader_module(descriptor()).into(), diff --git a/crates/renderling/src/linkage/renderlet_vertex.rs b/crates/renderling/src/linkage/primitive_vertex.rs similarity index 71% rename from crates/renderling/src/linkage/renderlet_vertex.rs rename to crates/renderling/src/linkage/primitive_vertex.rs index 11af60ab..fae3130e 100644 --- a/crates/renderling/src/linkage/renderlet_vertex.rs +++ b/crates/renderling/src/linkage/primitive_vertex.rs @@ -3,12 +3,12 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "stage::renderlet_vertex"; + pub const ENTRY_POINT: &str = "stage::primitive_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/stage-renderlet_vertex.spv") + wgpu::include_spirv!("../../shaders/stage-primitive_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating native linkage for {}", "renderlet_vertex"); + log::debug!("creating native linkage for {}", "primitive_vertex"); super::ShaderLinkage { entry_point: ENTRY_POINT, module: device.create_shader_module(descriptor()).into(), @@ -17,12 +17,12 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "stagerenderlet_vertex"; + pub const ENTRY_POINT: &str = "stageprimitive_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/stage-renderlet_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/stage-primitive_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { - log::debug!("creating web linkage for {}", "renderlet_vertex"); + log::debug!("creating web linkage for {}", "primitive_vertex"); super::ShaderLinkage { entry_point: ENTRY_POINT, module: device.create_shader_module(descriptor()).into(), diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index 126b801f..fbc6f711 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -802,8 +802,8 @@ impl Stage { ) -> wgpu::RenderPipeline { log::trace!("creating stage render pipeline"); let label = Some("renderlet"); - let vertex_linkage = crate::linkage::renderlet_vertex::linkage(device); - let fragment_linkage = crate::linkage::renderlet_fragment::linkage(device); + let vertex_linkage = crate::linkage::primitive_vertex::linkage(device); + let fragment_linkage = crate::linkage::primitive_fragment::linkage(device); let bind_group_layout = Self::renderlet_pipeline_bindgroup_layout(device); let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { diff --git a/crates/renderling/tests/wasm.rs b/crates/renderling/tests/wasm.rs index 20b1fcd7..6dbd296e 100644 --- a/crates/renderling/tests/wasm.rs +++ b/crates/renderling/tests/wasm.rs @@ -1,6 +1,10 @@ //! WASM tests. #![allow(dead_code)] +use craballoc::{ + runtime::WgpuRuntime, + slab::{SlabAllocator, SlabBuffer}, +}; use glam::{Vec3, Vec4}; use image::DynamicImage; use renderling::{prelude::*, texture::CopiedTextureBuffer}; From 603cdb529bc226a1508101ec78209cbfbd83c84b Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Thu, 11 Sep 2025 08:35:46 +1200 Subject: [PATCH 14/31] doc updates, manual stub --- Cargo.lock | 18 +- Cargo.toml | 4 +- crates/example-culling/src/main.rs | 9 +- crates/example-wasm/src/lib.rs | 2 +- crates/example/src/lib.rs | 5 +- .../shaders/atlas-atlas_blit_vertex.spv | Bin 6212 -> 0 bytes ...v => atlas-shader-atlas_blit_fragment.spv} | Bin 596 -> 604 bytes .../atlas-shader-atlas_blit_vertex.spv | Bin 0 -> 6220 bytes ...loom-shader-bloom_downsample_fragment.spv} | Bin 4964 -> 4964 bytes ...pv => bloom-shader-bloom_mix_fragment.spv} | Bin 1804 -> 1804 bytes ... bloom-shader-bloom_upsample_fragment.spv} | Bin 3332 -> 3332 bytes ...rtex.spv => bloom-shader-bloom_vertex.spv} | Bin 1348 -> 1344 bytes ...shader-cubemap_sampling_test_fragment.spv} | Bin 608 -> 616 bytes ...p-shader-cubemap_sampling_test_vertex.spv} | Bin 1092 -> 1100 bytes .../cull-compute_copy_depth_to_pyramid.spv | Bin 2184 -> 0 bytes ...ute_copy_depth_to_pyramid_multisampled.spv | Bin 2200 -> 0 bytes .../cull-compute_downsample_depth_pyramid.spv | Bin 6260 -> 0 bytes ...l-shader-compute_copy_depth_to_pyramid.spv | Bin 0 -> 2192 bytes ...ute_copy_depth_to_pyramid_multisampled.spv | Bin 0 -> 2208 bytes ...ng.spv => cull-shader-compute_culling.spv} | Bin 27836 -> 27844 bytes ...hader-compute_downsample_depth_pyramid.spv | Bin 0 -> 6268 bytes ...> debug-shader-debug_overlay_fragment.spv} | Bin 21276 -> 21284 bytes ... => debug-shader-debug_overlay_vertex.spv} | Bin 824 -> 832 bytes .../light-light_tiling_depth_pre_pass.spv | Bin 35796 -> 35796 bytes .../shaders/light-shadow_mapping_vertex.spv | Bin 32520 -> 32520 bytes crates/renderling/shaders/manifest.json | 104 +- .../primitive-shader-primitive_fragment.spv | Bin 0 -> 108064 bytes .../primitive-shader-primitive_vertex.spv | Bin 0 -> 44156 bytes .../shaders/stage-primitive_fragment.spv | Bin 108052 -> 0 bytes .../shaders/stage-primitive_vertex.spv | Bin 44144 -> 0 bytes .../shaders/tutorial-slabbed_renderlet.spv | Bin 44200 -> 44200 bytes .../tutorial-slabbed_vertices_no_instance.spv | Bin 5084 -> 5084 bytes crates/renderling/src/atlas.rs | 158 +- crates/renderling/src/atlas/cpu.rs | 12 +- crates/renderling/src/atlas/shader.rs | 140 ++ crates/renderling/src/bloom.rs | 2 +- .../src/bloom/{shaders.rs => shader.rs} | 0 crates/renderling/src/build.rs | 1 + crates/renderling/src/bvol.rs | 2 +- crates/renderling/src/camera.rs | 131 +- crates/renderling/src/camera/cpu.rs | 36 +- crates/renderling/src/camera/shader.rs | 127 ++ crates/renderling/src/context.rs | 81 +- crates/renderling/src/convolution.rs | 2 +- crates/renderling/src/cubemap.rs | 156 +- crates/renderling/src/cubemap/cpu.rs | 2 +- crates/renderling/src/cubemap/shader.rs | 191 +++ crates/renderling/src/cull.rs | 236 +-- crates/renderling/src/cull/cpu.rs | 14 +- crates/renderling/src/cull/shader.rs | 239 +++ crates/renderling/src/debug.rs | 128 +- crates/renderling/src/draw.rs | 4 +- crates/renderling/src/draw/cpu.rs | 2 +- crates/renderling/src/geometry.rs | 89 +- crates/renderling/src/geometry/cpu.rs | 7 +- crates/renderling/src/geometry/shader.rs | 84 ++ .../src/{stage/gltf_support.rs => gltf.rs} | 206 ++- .../src/{stage/gltf_support => gltf}/anime.rs | 6 +- crates/renderling/src/ibl/mod.rs | 2 +- crates/renderling/src/internal.rs | 181 +-- crates/renderling/src/internal/cpu.rs | 178 +++ crates/renderling/src/lib.rs | 121 +- crates/renderling/src/light.rs | 1305 +---------------- crates/renderling/src/light/cpu.rs | 28 +- crates/renderling/src/light/cpu/test.rs | 15 +- crates/renderling/src/light/shader.rs | 1222 +++++++++++++++ crates/renderling/src/light/shadow_map.rs | 24 +- crates/renderling/src/light/tiling.rs | 16 +- .../src/linkage/atlas_blit_fragment.rs | 8 +- .../src/linkage/atlas_blit_vertex.rs | 8 +- .../src/linkage/bloom_downsample_fragment.rs | 8 +- .../src/linkage/bloom_mix_fragment.rs | 8 +- .../src/linkage/bloom_upsample_fragment.rs | 8 +- crates/renderling/src/linkage/bloom_vertex.rs | 8 +- .../linkage/compute_copy_depth_to_pyramid.rs | 8 +- ...pute_copy_depth_to_pyramid_multisampled.rs | 12 +- .../renderling/src/linkage/compute_culling.rs | 8 +- .../compute_downsample_depth_pyramid.rs | 8 +- .../linkage/cubemap_sampling_test_fragment.rs | 8 +- .../linkage/cubemap_sampling_test_vertex.rs | 8 +- .../src/linkage/debug_overlay_fragment.rs | 8 +- .../src/linkage/debug_overlay_vertex.rs | 8 +- .../src/linkage/primitive_fragment.rs | 8 +- .../src/linkage/primitive_vertex.rs | 8 +- crates/renderling/src/material.rs | 103 +- crates/renderling/src/material/cpu.rs | 2 +- crates/renderling/src/pbr.rs | 12 +- crates/renderling/src/primitive.rs | 8 + .../cpu/primitive.rs => primitive/cpu.rs} | 5 +- crates/renderling/src/primitive/shader.rs | 317 ++++ crates/renderling/src/skybox.rs | 2 +- crates/renderling/src/skybox/cpu.rs | 3 +- crates/renderling/src/stage.rs | 325 +--- crates/renderling/src/stage/cpu.rs | 145 +- crates/renderling/src/transform.rs | 91 +- crates/renderling/src/transform/cpu.rs | 2 +- crates/renderling/src/tutorial.rs | 10 +- crates/renderling/src/ui/cpu.rs | 2 +- crates/renderling/src/ui/cpu/path.rs | 2 +- crates/renderling/src/ui/cpu/text.rs | 2 +- crates/renderling/tests/wasm.rs | 2 +- crates/xtask/src/deps.rs | 26 + crates/xtask/src/main.rs | 9 + manual/.gitignore | 1 + manual/book.toml | 5 + manual/src/SUMMARY.md | 3 + manual/src/chapter_1.md | 1 + 107 files changed, 3504 insertions(+), 2996 deletions(-) delete mode 100644 crates/renderling/shaders/atlas-atlas_blit_vertex.spv rename crates/renderling/shaders/{atlas-atlas_blit_fragment.spv => atlas-shader-atlas_blit_fragment.spv} (62%) create mode 100644 crates/renderling/shaders/atlas-shader-atlas_blit_vertex.spv rename crates/renderling/shaders/{bloom-shaders-bloom_downsample_fragment.spv => bloom-shader-bloom_downsample_fragment.spv} (98%) rename crates/renderling/shaders/{bloom-shaders-bloom_mix_fragment.spv => bloom-shader-bloom_mix_fragment.spv} (96%) rename crates/renderling/shaders/{bloom-shaders-bloom_upsample_fragment.spv => bloom-shader-bloom_upsample_fragment.spv} (98%) rename crates/renderling/shaders/{bloom-shaders-bloom_vertex.spv => bloom-shader-bloom_vertex.spv} (82%) rename crates/renderling/shaders/{cubemap-cubemap_sampling_test_fragment.spv => cubemap-shader-cubemap_sampling_test_fragment.spv} (61%) rename crates/renderling/shaders/{cubemap-cubemap_sampling_test_vertex.spv => cubemap-shader-cubemap_sampling_test_vertex.spv} (74%) delete mode 100644 crates/renderling/shaders/cull-compute_copy_depth_to_pyramid.spv delete mode 100644 crates/renderling/shaders/cull-compute_copy_depth_to_pyramid_multisampled.spv delete mode 100644 crates/renderling/shaders/cull-compute_downsample_depth_pyramid.spv create mode 100644 crates/renderling/shaders/cull-shader-compute_copy_depth_to_pyramid.spv create mode 100644 crates/renderling/shaders/cull-shader-compute_copy_depth_to_pyramid_multisampled.spv rename crates/renderling/shaders/{cull-compute_culling.spv => cull-shader-compute_culling.spv} (92%) create mode 100644 crates/renderling/shaders/cull-shader-compute_downsample_depth_pyramid.spv rename crates/renderling/shaders/{debug-debug_overlay_fragment.spv => debug-shader-debug_overlay_fragment.spv} (91%) rename crates/renderling/shaders/{debug-debug_overlay_vertex.spv => debug-shader-debug_overlay_vertex.spv} (73%) create mode 100644 crates/renderling/shaders/primitive-shader-primitive_fragment.spv create mode 100644 crates/renderling/shaders/primitive-shader-primitive_vertex.spv delete mode 100644 crates/renderling/shaders/stage-primitive_fragment.spv delete mode 100644 crates/renderling/shaders/stage-primitive_vertex.spv create mode 100644 crates/renderling/src/atlas/shader.rs rename crates/renderling/src/bloom/{shaders.rs => shader.rs} (100%) create mode 100644 crates/renderling/src/camera/shader.rs create mode 100644 crates/renderling/src/cubemap/shader.rs create mode 100644 crates/renderling/src/cull/shader.rs create mode 100644 crates/renderling/src/geometry/shader.rs rename crates/renderling/src/{stage/gltf_support.rs => gltf.rs} (91%) rename crates/renderling/src/{stage/gltf_support => gltf}/anime.rs (99%) create mode 100644 crates/renderling/src/internal/cpu.rs create mode 100644 crates/renderling/src/light/shader.rs create mode 100644 crates/renderling/src/primitive.rs rename crates/renderling/src/{stage/cpu/primitive.rs => primitive/cpu.rs} (99%) create mode 100644 crates/renderling/src/primitive/shader.rs create mode 100644 crates/xtask/src/deps.rs create mode 100644 manual/.gitignore create mode 100644 manual/book.toml create mode 100644 manual/src/SUMMARY.md create mode 100644 manual/src/chapter_1.md diff --git a/Cargo.lock b/Cargo.lock index ba924263..926c7573 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "craballoc" -version = "0.2.4" +version = "0.3.0" dependencies = [ "async-channel 1.9.0", "bytemuck", @@ -867,7 +867,7 @@ dependencies = [ [[package]] name = "crabslab" -version = "0.6.5" +version = "0.6.6" dependencies = [ "crabslab-derive", "futures-lite 1.13.0", @@ -877,7 +877,7 @@ dependencies = [ [[package]] name = "crabslab-derive" -version = "0.4.5" +version = "0.4.6" dependencies = [ "proc-macro2", "quote", @@ -2207,7 +2207,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi 0.5.2", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2331,7 +2331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.53.2", ] [[package]] @@ -3900,7 +3900,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3913,7 +3913,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4236,7 +4236,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1961e2ef424c1424204d3a5d6975f934f56b6d50ff5732382d84ebf460e147f7" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.104", @@ -5293,7 +5293,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 93154da1..aa67a84b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,8 +23,8 @@ bytemuck = { version = "1.19.0", features = ["derive"] } cfg_aliases = "0.2" clap = { version = "4.5.23", features = ["derive"] } console_log = "1.0.0" -craballoc = { version = "0.2.3" } -crabslab = { version = "0.6.5", default-features = false } +craballoc = { version = "0.3.0" } +crabslab = { version = "0.6.6", default-features = false } plotters = "0.3.7" ctor = "0.2.2" dagga = "0.2.1" diff --git a/crates/example-culling/src/main.rs b/crates/example-culling/src/main.rs index 96ad7490..1121eb2b 100644 --- a/crates/example-culling/src/main.rs +++ b/crates/example-culling/src/main.rs @@ -6,9 +6,14 @@ use example::{camera::CameraController, utils::*}; use glam::*; use renderling::{ bvol::{Aabb, BoundingSphere}, + camera::{shader::CameraDescriptor, Camera}, + geometry::Vertex, + light::{AnalyticalLight, DirectionalLight}, material::Material, math::hex_to_vec4, prelude::*, + primitive::Primitive, + stage::Stage, tonemapping::srgba_to_linear, }; use winit::{ @@ -29,6 +34,8 @@ const BOUNDS: Aabb = Aabb { struct AppCamera(Camera); struct FrustumCamera(CameraDescriptor); +type Type = Primitive; + #[allow(dead_code)] struct CullingExample { app_camera: AppCamera, @@ -39,7 +46,7 @@ struct CullingExample { frustum_primitive: Primitive, material_aabb_outside: Material, material_aabb_overlapping: Material, - primitives: Vec, + primitives: Vec, next_k: u64, } diff --git a/crates/example-wasm/src/lib.rs b/crates/example-wasm/src/lib.rs index a43ea4cc..d67e0696 100644 --- a/crates/example-wasm/src/lib.rs +++ b/crates/example-wasm/src/lib.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] use glam::{Vec2, Vec4}; -use renderling::{prelude::*, ui::prelude::*}; +use renderling::{camera::Camera, gltf::GltfDocument, stage::Stage, ui::prelude::*}; use wasm_bindgen::prelude::*; use web_sys::HtmlCanvasElement; diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index b7e1f9bc..716fec43 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -9,11 +9,14 @@ use glam::{Mat4, UVec2, Vec2, Vec3, Vec4}; use renderling::{ atlas::AtlasImage, bvol::{Aabb, BoundingSphere}, + camera::Camera, geometry::Vertex, + gltf::{Animator, GltfDocument}, light::AnalyticalLight, prelude::*, + primitive::Primitive, skybox::Skybox, - stage::{Animator, GltfDocument, Stage}, + stage::Stage, ui::{FontArc, Section, Text, Ui, UiPath, UiText}, Context, }; diff --git a/crates/renderling/shaders/atlas-atlas_blit_vertex.spv b/crates/renderling/shaders/atlas-atlas_blit_vertex.spv deleted file mode 100644 index 9cb3260a439965c1f1c39c1bba0bc7874b31ef59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6212 zcmZwKd+gU`6$kJS*Pn=mP1H0lKOjW`F_D~ul*@ErQCW7gmPAQu(WXFVUgAgACdq26 zu&J~_`^Q^Zxt5o7t4a6!T3P+$x@c>&ypReZy+;g)5A<<^{p~4MEwe&a>9a@Gfo`7}jjm?7tRoXY zEqs`gH5`3QRk6&N> zX2Z{ZM510EJ}Z{v!pZZ4QN!^e{Y;B)hQlE?Ip&7zjh)|2y$*-;IxF1VM$ce;w>YxC%(QwtE%KN~KRvSZtKODG?z)i& zOJ6$ByYxCVnDeWm!yvxVo=1IW^!oqvo%sUxf8&_t#6IYHxjR2&JXdsw-x*L z$Q8?9vG0h?SGadJIC%?qL1ez#V{K&qc8_;OuRZuHc3ot?ihWOHvEEVbdtu~?<*(TF zk@+h2y^+PbI~DuB=oQOfu@^<=tJq5-i*;@lduil~<*(R{k@=kOrf_S2H>qRaJkYxC zL*Xf-yDa2xemLZeac3@$&fn_dT3xURM9%W^kn@JY#hSUC=4Y?!?<0}*=N(ml zS46M=_^ZDwBlGF+s&Gqx>{k!8uKQ@X{hiU^xax0fWPQQl zV)ZAd{zgL8%e9fK7x%V$*%q0v=J3hL{PI-nb&)HUzhbvX=JVcsGnR+Ur4BEz!j@r&V>b9c{nh3vmO!DV&!Rd_PzPi59S!zZwibY z_JP%xSoJ^9@B7t0cf0T3gJ;)+86Vcy^Nq-HrIXQmJ{W0QgkH?p&s>b56(=kY;4Zu z8jWN*7x=3}9}AfeZeB2SzPtPVu8u5M&C8iT5uN?4$Y+PzSUH>v+{Yus$_HnkI_oDR z^UJO7n%hH>ornF@y(ipKH{W+d-wUY|hxtjk1!F!x4gD+xgR2jQ&UZ~eqn}5%w^~{Z zY~8J2M1~UwSNYT>pL*2r{cx*l_(9|!hG6j8^GA`}J;lMmtD$tfYWQ(vd&7vA54LK+ z3;WB+@Z#037ub3WyQ9~=`BLPaA+xS?c`Ey`tFe6xw?>aE6CRDJ92dvP2VZyZ{f*6R zHVVu#8~6`|E)D4$S04cbNB31J?@RnFSoku z?%f_)|MpY&9pRR``R)vTIiya!&h#sh<&jq};$YxgoxRTKt{x8~UcUC6cKw&`{QOpW z+rJ8}4DAZZBd>FJ53WxQzK!btb#%*jeQWq{LUDBuhsK6}8?t^EQZHV!xGzAz6Z(?t zA%R(D!FPY?fsi=7zUvQ07FTDc-haf#?z_&XPx-{k)9UOsqdk#**J0$a53Ih#s=w~x zU;5nbzRv{Du7~z6KOQ}-!?}wcqvq(b?swo^DH#>QR5at=k)$bNRYPvYZS29igv<%m+6w7&>3Qtve&j zRrB(;o{i4lzO9PI>uuc~8CE`T%RcqCo{P*cx4LU?2O>KU`>Ff+a7*2M2PyHZ6Ni}? zZo!z(Q1nB346ZjAF?{tNCq=fmT3QTj-K|3-!-<2deCm=3G#JfiDCjUOw2W0Wa+2_~6B>T`#cp7QE@YH@}bUUf0=rgZqMKS7ZAY z9*G{;3vZ!v+z=xleBHep8=KkOEHKM#;BN};4(S_L9}JzZ?%vMGa#elq-u~$9?cJ+b zyzbsDkzwU?_v}-5@1K$R9(na54hFu} z+3TDh>+vw+z)&yJ1^?|TMQwHy=qqS&gIW25VZy=s{r znZ0V6(d%t3GkaTG%W!P4YLTOAnH3pcEim;r-<-(mydd_n9Ty#bU2IkJ@zJ+6`rPQ- z8~udna$Vd1U-87qY~m`%yvTAFW`1NgxoQ>*B8xpIxyyD^bXc~!YYU^px^HDWIXWy` z#hwzK-5ajI85c$05#4Wk*-q_k<6=8E{~w~GMpaz E7iti+Z~y=R diff --git a/crates/renderling/shaders/atlas-atlas_blit_fragment.spv b/crates/renderling/shaders/atlas-shader-atlas_blit_fragment.spv similarity index 62% rename from crates/renderling/shaders/atlas-atlas_blit_fragment.spv rename to crates/renderling/shaders/atlas-shader-atlas_blit_fragment.spv index c844340166803d171d3eff65a6c48da395acd11f..5990bacc27e1784c11dc3f4cd0e030726cbc0d3d 100644 GIT binary patch delta 34 ocmcb@a))Jtk+=W@3j+fKBM>K+K+b2`OE?P8DSFPEweq_}p>o$(8yA)330ikiB@u3N!6|uam)A?2e zbyT>VX9Y>NrjN1#{^-c!4-APvrqd7Ubo)#S&FXY{>9Ys=*unlsc0RQXhb+11#|^Ym z-9FPAUCnY?hXp@1yidvMM~5{>_NnPbZ{%rRUv#)*!zYLIcX)jLaCAg`!<}pfuF1c}W+)$<94ChBjh)|2hZ=+*qqO~3pL!}VpR)!VBg4>kI0B0In8 zZE@sYZ_7iapE}Tc>2<nE&-n9Gu~@*zGB| z9B65XO^?gN&A=TPO6UFXGeWZ>o70)0nVtOF$Tf$vBJazpKF^MxwV?EKM)jrU>fYMJ zT+9DRhPZd%<|UQy(dgwj?|()YQ~1ZC@7uTe+*jt#xa($ax%S1f1xTQb#D+gMyw>eyYTSEG~Dx@D=z2fLw_S40+e)(Em zT=jQ#WPQQlV)eHrq(6IAFV{t`UfkR2<@(5cHHVK!=9i~pw??j5{)*iena}s;%~%#P zlTU?P^-a@19nvqZpZccxeACOrKNFItzUk?aw|DmQg6T)Tp|geMy%@E9wzCa|U)$Mk zjLg0`bX8}&DYE#vjqT>huxu5(BQor%jqP)hVcGP!Gu(3S?%6FN``;RJ-nWIU+e7-s z?@Jx?!?y-#4|~eBU0{}Z@ofuzA|wv~Mi=+V$l~UNzL0mVAO5e{*w2p4XSVW*m8aF& zcju)ScSB^qDKK)_2X<$CV%7g(x9?XX@4xTAgJ;)+8Bgx&`FiBI(#dGd#gV2)zAwc0 z%`WG+I$bX{m-{=L-!A=$dmsese#=qz2P4D#U4^+WdEvhk;&cD+==S<xW<7*qqBpqg&1e{)*5wA@jk_3x>{jZ@1r-k>#p$a^{amXFoHtzYE$}Ih+gJ zwUJ@vgR@Va^%If#h1U?|Y%|ht!F~{50HxF`u7>ejb9s)dxf8 zyQZ7bFCyDpEiDGN?$$3O!-<2deCm=h55Df+`x=|sY!aAdHt-ul8$;^B)dxf8tGjn`WVxz7cWQTZ_V(^oEM9kSgdCF3 z-Lp^i_*7(mxz$~F@6O2jx1YN23b)kFcX#MZA$8()ruRgaM_#>%gMn{#_By98cX$}_ z^0nu5%YORK=zc5v;lB=@5rUCNUgz!}cniIa>iEKfPN?RCD+3Ov&@3;fzU%Cad^G!-;OM<&a5B#>Dbu4>wNl@Ppmwx&R#Rx71_HE zBZqxp^(9vQbr1j1^f@z3WeOx|}taCp%mFuJ4Ww z)|)Ixz3Wd!hWD<+)VsbXGGF_yKOdc4j_T=)DN;S^uW#$l#^zk^)kv0efxj#C)sXq% z<^@CNt8eS>$a2-Zd|S^(XK%l)ipA^O`dVaI`FvaUsc-AK$oz7vyXLkxvh%Q?y7z@! z>gIDGLm_qIFcZQp81p$W`os={>kUQ>Uww}+iEMARv>4dBTazNgiG!XJ`AY8Vr4 zRSjdK9}t4UYtM0!+daj>z^kEjylNO9+1@bX<%6vn@WM`x4_>_5^#WVpf^WL+%^xGX z*LAl2$a{ikS7ZAv{5g7DFMbP^hA4` zELYX%?mZu!y}f%Ci`U(|Ju<9(?w)<>?!6G1Uv72R-TO;q{ny?5YjjK9e18l5J)};& z&h(MU^2n`&PD-qr?zUNeZ%#C#`)2=N6)MEqHRHE8ynjj^Y{4l@P)D2M-DMC{=Yk+ R^SPJxe_8y6ybP}n{RjShxlI57 literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/bloom-shaders-bloom_downsample_fragment.spv b/crates/renderling/shaders/bloom-shader-bloom_downsample_fragment.spv similarity index 98% rename from crates/renderling/shaders/bloom-shaders-bloom_downsample_fragment.spv rename to crates/renderling/shaders/bloom-shader-bloom_downsample_fragment.spv index 432592f2d755c5bd70948d97f2291ffeebdb6dbd..9ffcf8d35ea650f21d28942f028742789f5b0acc 100644 GIT binary patch delta 13 UcmaE&_C#%h=R_~Ljp=`d04!Gq4gdfE delta 15 WcmaE&_C#%hCu8wMPq~d5e}n)v&jx`2 diff --git a/crates/renderling/shaders/bloom-shaders-bloom_mix_fragment.spv b/crates/renderling/shaders/bloom-shader-bloom_mix_fragment.spv similarity index 96% rename from crates/renderling/shaders/bloom-shaders-bloom_mix_fragment.spv rename to crates/renderling/shaders/bloom-shader-bloom_mix_fragment.spv index 8083476800f4f10c3569ec9ed65df0905f222172..4601da7c2aeef6251fc22b5e110740e5b575fdf9 100644 GIT binary patch delta 32 ncmeC->*1T=DQabvl#`#I8=sq55ua9+n4X)OSHiF{ZXFu{yH*R+ delta 32 ncmeC->*1T=DOzl0m6Vg8pBtZ>SrMOBl$f5Inpd(hZXFu{zN8FB diff --git a/crates/renderling/shaders/bloom-shaders-bloom_upsample_fragment.spv b/crates/renderling/shaders/bloom-shader-bloom_upsample_fragment.spv similarity index 98% rename from crates/renderling/shaders/bloom-shaders-bloom_upsample_fragment.spv rename to crates/renderling/shaders/bloom-shader-bloom_upsample_fragment.spv index 701bfb834bb23168516e7376876a57c645b7f069..3b19809c2b276444fa542749798a97a0a950612a 100644 GIT binary patch delta 13 UcmZpXYLS}YInhgMWAZ{C03mS%%m4rY delta 37 scmZpXYLS}YDOGG`m6Vg8pBrCVP@I@skdqppR+N~Yo0?a$F?k^m00bWnY5)KL diff --git a/crates/renderling/shaders/bloom-shaders-bloom_vertex.spv b/crates/renderling/shaders/bloom-shader-bloom_vertex.spv similarity index 82% rename from crates/renderling/shaders/bloom-shaders-bloom_vertex.spv rename to crates/renderling/shaders/bloom-shader-bloom_vertex.spv index 0b4ff7f454503fcf0222b96608c0a6772b8ea696..2e8d7dc129026644de513e5edab329acf908da2c 100644 GIT binary patch delta 48 wcmX@Yb%1Mvkt#m}2rvS1Qciw;u9a1BMq)~8k(Cvg8()@MRFYb;G5RG705r7^7XSbN delta 52 zcmX@Wb%bkzk){9x2rvS1Qciw;u9a1BMq)~8QL&X3m>*x3T2zu+0hHbt{*na%ZdMPA diff --git a/crates/renderling/shaders/cubemap-cubemap_sampling_test_fragment.spv b/crates/renderling/shaders/cubemap-shader-cubemap_sampling_test_fragment.spv similarity index 61% rename from crates/renderling/shaders/cubemap-cubemap_sampling_test_fragment.spv rename to crates/renderling/shaders/cubemap-shader-cubemap_sampling_test_fragment.spv index 6ece10521149d2b7ae75ed5bc41d10254aa6ddab..26105c8e62afa115c2a5ea1116c159755a68b72d 100644 GIT binary patch delta 36 qcmaFB@`7c8k)$vK3j+fKBM>K-CZ*;k7FbyoXC$Vi7HxEvWdZ=EaS5LQ delta 28 icmaFC@_=Q6k)R+03j+fKBM>K-CZ*;k7HssEWdZADz8X>5m=4wd|ZDVY!sVN#s4GZcE+(;`iw7EA@3yFn@oed!*gy_P; zkP<6vGYcE6knkbIkOwCMe`{-2Hl+F~DWzGdQxvxI)GmNOh@=dn%;e03NHj_1!}@v1euFD$C|%{J+e2$|`Z{%J+2mrI2}y*$R1r zUr}MpygjOqy5vJYAOF?xEs$p!by~Nw=3KLU3wCR`XF%58gl=tFp3(wz?O=IpoJ&O= z+^yJja*I21o^@c)JZ#o;8+QY@am^Wao50p?dc8q*oum-CQUZ+=hIc$@&rfR#nu8_}7=cYc~>bCB7Gx{%EWTeGskY}W*KE}loo+_MG9 zlpEs*ud+IoVhq+Edm>hYckei80F^vg}t%#)4!Tm{yjC6^DhJIXKZ&~ z+dH|oX0Uqq-`ehRd#p{}eeeUw9Aa~5BdfZeTe=q`KbeigA%?mqkGVY>mjd+YAl+m;;5-qdY` zdLVldpCgCyy1?Q0IOpv~W*&9Uz*zd}U(G9zx%YzgGq!Wr);gYnJ=USkbMOnuc;eXC zm*DtL%pLps3c0$ox!%`c^?pm?`vx4o>cjUfSebxy5(^Pu!~!9RDQv4D ztnAGsHdrCXM0lQi-_zW9lhgA%^YA~nV+)HWq`EOFrKzbb<4sS6B$U5vOle9QThaS> zYHCPzaP2)qrP8KNJp=vap~1dl&p`QfvA3^0c(gb;P%NK5+1-Dvx7a^a8a#HYyT4rO z>orLMGS4_@S{k40h^u7Y-B=gH$3yz~Hg!m3!2?Nxj9r5yGd#4kl|g?!EQY2WHva?i@G_$`A^hU~owTU$k+(oAg2 z!OHg7Ku7KH1^9Hp#qGJy3b3ycpOtX)u7aD_n&GzwY`^ASn{Cb+_H|(87VPfLSZO&m z&AT3I%eWI9aT~yYdCt8B+zMGI>|Nmbkaf4h&FQ}Ea~oV=^_#Qoyb*7{osdtv`?5!8 zo1G@6{cv}rzvQdM);LgASA5N(Y<*w!c$^@0A)i3Dj}Gq2U6hcW(_MF>bN|-ybwEGq z>H>ThHs`wp*{83IOwM;1GUpC1*za=%(#M>Ve#Tyfw1wX_aQOKR!|ys+Tln3q@$*}T z-z~7V@Visv=iK3U7rnOdyI14qKEm%ldTo#Mtkbbs!|yzjb@k|+LtE%(fbCh`;q2E0 zb}zo0=)AL;=+v9z2VZ3#-1nRPXqyGih1|I~a?J*t3pSc-4uX1X|H9u~#u;BLtN)fJ zRO&Z_jWf45ukXd&TMJmb_it~*aG$+tdjKARtRc3>aF*3auMfe|>mhRcdwc{rw>Ed} zZ7)XlE{pW$|AQsS>h#?X?S#zfZ{P`}-FGAR`xNYL`OU6yciz_kKI*+^zj^qsLhs#r zJI=Nt=W;e}tD#QF*~I6lVZL?Xh`XKZu19AbZSKHa#u;BLtB<{J1RG~=_pYyfJOlge zL!am17m)eHaj!4I1;}}=9ryYQS=-s%@9S*$w-m8&z!9rGV&8(b`HlQP@E$VXTgW-= z%|7g>R#xv^#(aQ`vseF*=o@$N5v<)8x=&zrxQ_mIK7;)|IotU>#}}}-qAh0o3RdqO z#dqBcR&QSSdDz4}_o;0kv>$Q~v2*C7tUhud1lzBGo7j<)ZR cHyS(t0gjy;x0T-1>1Y07xIM`Ku#Jt-KNSScVE_OC diff --git a/crates/renderling/shaders/cull-compute_downsample_depth_pyramid.spv b/crates/renderling/shaders/cull-compute_downsample_depth_pyramid.spv deleted file mode 100644 index 1fa75571fdeccc29ac33a0d1559e4a093fb668f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6260 zcmZYDd(4+*83*tOgqJq)0FvfeG(iL2sema?Hx~`eLz+!(OPL8B4CE~#JGkkbr?m1P z>rc%R4{bS9nkduC+OPv^Tj{22d8#$bC6xju+V}JOJ(s)p>(-0sd!4@5_1yP$KkxS2 zZSoP*x~Y@8uG_2o)NXlX&FCg~ES@jU>bl*#v4OtqjC0QzzkJ=w@kNV|5w~YIOz`hs z`EP2TlOva`U%h(Cl1tXEnOMJW)rysCuej{;i`Pu74qP>{?(-`qzV_vd*L-1RH^`on z_`Sm~Z^i)AyJ5X+Fsadx3${0hB;G!VB_B#nJPRX7_jplo@hlF0 zH>>m$qaPaCFFZ@~#9@E*aZ;XYvY*uJ_LPn8{l)6F_|A)gt@QJw$eG`t*9Fn_U>}Z; z&E9wq%Uc4wYThFLfxXq*34SjDrgZa&--nQgv>5cD+;9p17fYlH~XRls=8(h6! z+waBiV)Ne4u54R_#j;(~$2}cvzsQi_Nw<> zuv)mT?(01tY&Q7XJo)y_%>F6je&805vwBO3!F|B1w`u*w(Hq~S$XG-#aJ}c0VE0Jg z1O0nWjZG~+z2K53zt!36Jl_{A54ZCatB*eiTlx_5Lhy?bd~n@^mxAk_s$KWs44HnsTlf=izKR%fr7TO2HJP$zZ8>f`M}7sEcp?27(Q1Rq>;^KNj>joLLg4v+83 zyvN);CppZBK5*l~*Xr#05_dqm$eq6Vyn7&?2+ z%8X!l)?5|$%-DQG_}V=Ab)K_=ohNSbIPKZT^8S`SQmR`TIW3|tTxYi|c=UU*JT|<1 z>f(|ozt!36>`o7shuil;tUmS)kEIVW`$hji1Rq>yw|{V*o!WJF2L$ugo*Wp=Z@(+| zpy-v$U%3Yd^VRoab}&A6@1Zw+=%>}$y_fIBoM3r+^}P^V--fxt{8rhH>TS%`^D$A} zd9zY??bF!{cJcOUWpv9v@m(0XD55`De`4tD#r>IJec)o>x$XA2q;Wi^;^|3I$Tlx^QDEi_EKDf^L z_~1HcwdzE)?~m-~HUupG7AZ?Uz%rvz_}t?u_nqFZ`(zn4b; zXhaQI4KZ}~y5Gx#NALG(vAN%TZJzu(yVHZ69d7YB?b)~U{+2#cs=Fcbt%$mCo!w2r zqxbvf*zoeHi%XvTR%frX`%bVt+|Ev{KF$n}r4KP@MgMpNA6#d5c5t1Y+I4p41oPE? ze}S^7F&1uqF{cjY%6*j zbDiyHqnMNS@BHVYv$uceZ_oa)h z2{t!)#LHLnkvuIm-T94?ha+mhH8&3hkKXxBvEk)Y7neNwt@Cb-UC?K=C*V&|(nzc!dnAGq=0Yjt*gx$_gja@2C?#p>(pd0P5% zzrPXv$_PFfpBOrO&A?T`qxbvj*xYZvHcx(?(>1})3AcEh`gl6;YUv}Ty5B^eil__M zIc*Idz28srhlfvHT=L|%I(wbd?}O#xc1~jTacy`keTca(`t=cfaGlc)!F5h**E!u7 z%vZDf&0zlae%};=1c`}Asb%RceF9C;<8KUjZa=4T57t>+aqsB)PQS7-U=SQ%m0lHFQ2-&C*XGHudDt9m9&n4t=^Xa4xmo&1scw(xGb8H4H4l3SkA5>|#Do>x!>nL=xXpuDeLNZ-OCMq$i~h3+KDg%L=fQCgejil3=HVB?e6=T!2lKbzj9*5t zT>i@aRWM(DGoA>>$L>A!rVstJI=lDs&Da_&Pp`fiV(a_xWH7%~wx@abc~Z`8u2DgX12Yjl5H$v5CXKB|bfP?#c~2A@V;Q3ihi2 diff --git a/crates/renderling/shaders/cull-shader-compute_copy_depth_to_pyramid.spv b/crates/renderling/shaders/cull-shader-compute_copy_depth_to_pyramid.spv new file mode 100644 index 0000000000000000000000000000000000000000..15c9a616f7cdc8212e4341f1c91b62f78fbe20ee GIT binary patch literal 2192 zcmZ9MNpHAE)H9`zkLk-nxT4RjWN=+e>8Wz+SxM|uZMWr{?LSi9eXF~`HA-b?I zq{PbFR4i<;LQ)?>42keO_nx=8agz6*-#ZWI{okooEw!m;N=j*VDtd9|rm7_L{#KvT ztTeSG_jfkZ8gBJ{XNHElx=s)F_79xu>gpRlSv)f`Q0N;jo-Onb6h{UNBg2K_*;BnI zkM$ENm7-L0&q>pAd~unK*PW_UEB7==yKX$%xb@vnRe4*} zeko)gV>Uyc;8&E{5^t~Sqb~W-&&Piyd=unZMxEBJtTERt--O*N?wOFaFF?1tBu{A} zx;0>VYn(?#Yq^`TS;sA2oAay(d+M>-z-`=(+{QI$*lh+|ud%meoqdMB9W397-nr>3 zts$pzw?eBk?f{2hC-^VNzIT9|AoGNNCwMtz-d)_rbY9lEn_FAu+cR&!;cvXXkf$L{ zXZGcpsF&gdHs<~;)Yh2J*uI>Hyn6F{qQ>I{P!{|Nc8qL9mt%2R-^<=vR zVCUj_g3LWzh)lULe()+wxjny`kGe(B63Cg0BUS_0SX`5_7Q-kv_b=>?rJw$lyz=j< zwv>MvSU+RC^V;6awKam(yZ_eqfZJnj>K=k0LFN#fLmPSJQR^5uYCS@1zsJXreXDcU z?r$r+ds(11{}0;Wm1*lv?1hZ!|HM;By=N@f`wZ-EjY9X?JNIiC8|Ch^ZyvTAk-N9< zj=go}SoWrF6Vw6Oi}(ULjMokhzo$9xR%GT;=M0RcpZ=A+@|gQJuztpN?%G<%3$VvJ zw0Q}B1sP8q`}!Ij--)?nU&oQFJD=-)16J?16uxi4;j2D;-+|TnM*a`Hhm5D(KCI0; ztf!J!ZeRL*fb_Fg|3|cqJ@^P#?+Mu_urf?1zn#xuzbD`FV(#M$cnne(y?q5MFYi(L zdpbZM<;HcMJqG4DPjv^OLy&!l?L!-Rnw9=Y)*r{{O(;eT#xYnDt(6UL>Krl*pOSC?v%Q2w?drD>_QtoQHq z)R-o~wfBt_i#eYG<8E-otq1?%Irk=T3uK+JZw4=fth)tnPWNS>TjBbu-}w8X>-(a|V+5%S`8cwDba7YiqKNFA?z$VD z`?rp-3;ID<=ixiCIp0OdK7E_XqBt#dXU`y z9v?x@t<7C~+pWmnWr5!Of6#`kPTy_N4#=GT2A)9Leb;lpPr=@n-|RAX=Y0*~quzV= zn}_d8^xmzv<8145E@#uW3hIWOO?;Lb=35JnxLdjII&{|2<_^qdoblDN`q=vhuyN*g z@A}%uGqBG-^mz_`0hv!6_xciC139m?<6d7OYde$seVy(8mLm2IIAXO&>=;;^-^l+1 z?;!JyLC#@s_F+HOvU=w-<~?Mbz50Jd-?)PhVC}xpeFUq+_1|yj6WHIAvz^OxdLd37u>G2=+DBh!^%f3;y({zR kZ~STMX!{0vqp|bv;MlowTj))le&!#A+k^Z!+t>j81*#0tP5=M^ literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/cull-compute_culling.spv b/crates/renderling/shaders/cull-shader-compute_culling.spv similarity index 92% rename from crates/renderling/shaders/cull-compute_culling.spv rename to crates/renderling/shaders/cull-shader-compute_culling.spv index 95c9f82d4b04bd7a82c12a729375fb9adb7d205b..fbac1c1881f1adb47a86c6256ae8678fb9de3c65 100644 GIT binary patch delta 35 pcmdmUlkvz+#tB|x{0yuN3=B*_oLridV`WvGk(iQNv@s$j2LQXa3a_jJ$8-}gFwuj{_=>wehY z{idHVtD8Bk>$-!w5AT;x)|_s7$Kw0+ysq278yn~=&%Nl}@r|1%$CoWXMcjeiFv0&1 zO7zTpr$;W^yl&mZ#Kz0lOs>6hV&bw5>!&tvTDy93!&O&oT(f>^UEtcOO_#5p`rMUk z)_-EM8?eks-odFOf6f5YyJ6jKMt4H+SVY{)WV|(Bv8z%Qw!~O$bBFN%Z1yE?$TMT` z-9P$Kk(JTxWq!me{rI8Uy*d69gOBU=qZ5sb?U=qN`f-U{knik>-VTj#;lSQ?hotM1 zg6GF}a=!4Qo_A5OMHjz#pmp86?}IV0mHwe9au)aZ zb#Zh(IET|>b2j#2IjcRwd{vGY~j{Y{+nsJI7W=iAZm^&dG{HQdRA zz3qkA?1QgtF9z$G?ZQ58SFm%j?u^Y0{3|wg9J_NuyYsbP$@%d8JMwbGnZw2PpI}`1 zyutNS6n3@uCLWhO`K`|WQa5W*e-9kNZ63vL>3iE7%x^aJwj*ClZ+s60|2m=utcDmm zd-eL;;Oh0d{w#hMn|-^xvh55O%XV!a_h_*5HVb$3ef=Sr-QDQxkNH~q;(ILectjtt zzQoYktKJjAYT>%3ulHoI+2CvQMbP(?*XsgX7vw8Z+z1tV-dZ; zwa*#B-jTe!`hCufO)WmX;F2f5)!FMl-xMqlxBC>Uk3R=n`VjL}@Y4}|aJ_?Pg6o~C zUGL!8V7@x1=Ysj&OXdD0xN`X`_piZx7i3>^^L;*okKI1>rVstJI=g+z`DaAlQxU&U zVr#x$4Cc4Wwkwz|BlgDIeL2`&w{LfMbZ?ih=3-B&tz?hR%)w{_Qt=N#G9a>nzc zTh5s8h{%xoxSevoM3sl{a%RG$D!e|^daW3=x>SOgX``N53ajYyYB9YV7@w& zBZK*!cjX=xy>j_0_vm20`n{MRjE~(u^rjE}v^u+e`Mp>WEKjd~FT~bw!@^*Gt86Fr zHsp)c;_@3-EvNRmqad&=nvMP7&?1#e>7MhxY`)8H6v?-%?KXx z^3}X5UrSBz`_qxnMAU$5Mm7bHzVFSk;pI~ompu8c&R#R}*EC_x~(kF2$qN2-HFx5`@&=CL(F;6&yV1P>+UWHuDesa z?(V{1zB=#s2lKb@`=aQT%U`)42^&S`|tesaz5-hoZT(aEoaB~{m4xbJ;QnyLuaou+7hfc zTy2clnwwjL%?%#$^3}XAUrSAIerx33h#GLs%{{@RZ+=^Bc=^=DB~N~6yLzAl0fuDMwsTz9W_-Tf7@^VOT*5X`0z+<5S{I=jBS`Ke$zYI*Zw z_4WCDEq!_4Ux2ATdGcGGz3%Dv!SZmsC$ajtEz>rEd-_T+U(N1UgZbO{eM9uh<*(cugZb)xe=`^#yM5?QANpx^cKh%c9f4`r}S+I+DPR~cToD<)(k>?`%gY_qd&R*Pq3)Tm& zHb!jC$lrs_2p;kB)!dh_rKY#MJMwBo4Y+3HmEh60{NLE{@~MkUp8Qs4uNiqQSRQUO zB32(arFTmoVtx?)hY@^m&B)EcbZ|Sdeet~TAkg#{ATP7mZw+08Di`A;o)F@t89<- zHs-q9$D;Tf)C>96J{}Kd-xaA@Ix+n0IGo)Qo62%_d3(shO3Pc vTXQoWY;N#~m+#H_ThtTDGxK#fPX@<5xEpzAMPn0(e@A?J@ZFaec6#K0@0j_R literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/debug-debug_overlay_fragment.spv b/crates/renderling/shaders/debug-shader-debug_overlay_fragment.spv similarity index 91% rename from crates/renderling/shaders/debug-debug_overlay_fragment.spv rename to crates/renderling/shaders/debug-shader-debug_overlay_fragment.spv index 5d0205f235577df721f5a474bdb6792de477234d..2f81ffd21d4bc3f128d089ed882244c683d6c522 100644 GIT binary patch delta 36 qcmbQUjB&{_#tB~Hf($GS3=B*_oRXSUnr>xPoROH4TC_3pa1a2nyb7oQ delta 28 icmZ3ojB(B~#tB~h{0uA%3=B*_oRXSUn!Yjda1a1%eh0e% diff --git a/crates/renderling/shaders/debug-debug_overlay_vertex.spv b/crates/renderling/shaders/debug-shader-debug_overlay_vertex.spv similarity index 73% rename from crates/renderling/shaders/debug-debug_overlay_vertex.spv rename to crates/renderling/shaders/debug-shader-debug_overlay_vertex.spv index dd32e9148ab5a7ed5d3146cd672824d02fbea3a6..6f2d0c623e13eecb97adb6f6abe1ad60a205fea4 100644 GIT binary patch delta 34 lcmdnNc7SbykvJa%2rvS1N@`MRx|LONMq)~8(MHGbOaO>62}%F} delta 26 dcmX@Wwu5bg5kC(D2rvS1N@`MR`bN+1OaM$f23-IE diff --git a/crates/renderling/shaders/light-light_tiling_depth_pre_pass.spv b/crates/renderling/shaders/light-light_tiling_depth_pre_pass.spv index e2bda6eafd6f2321c8a7c13f5e01ab4cd57e389e..913f6a4e28d9bc06281c7fbe97cbb72bc7413862 100644 GIT binary patch literal 35796 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 Iw>s_r0JHLWTmS$7 literal 32520 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 KJ)iK_ru`qdt8gp; diff --git a/crates/renderling/shaders/manifest.json b/crates/renderling/shaders/manifest.json index 6e975137..e45e9e21 100644 --- a/crates/renderling/shaders/manifest.json +++ b/crates/renderling/shaders/manifest.json @@ -1,33 +1,33 @@ [ { - "source_path": "shaders/atlas-atlas_blit_fragment.spv", - "entry_point": "atlas::atlas_blit_fragment", - "wgsl_entry_point": "atlasatlas_blit_fragment" + "source_path": "shaders/atlas-shader-atlas_blit_fragment.spv", + "entry_point": "atlas::shader::atlas_blit_fragment", + "wgsl_entry_point": "atlasshaderatlas_blit_fragment" }, { - "source_path": "shaders/atlas-atlas_blit_vertex.spv", - "entry_point": "atlas::atlas_blit_vertex", - "wgsl_entry_point": "atlasatlas_blit_vertex" + "source_path": "shaders/atlas-shader-atlas_blit_vertex.spv", + "entry_point": "atlas::shader::atlas_blit_vertex", + "wgsl_entry_point": "atlasshaderatlas_blit_vertex" }, { - "source_path": "shaders/bloom-shaders-bloom_downsample_fragment.spv", - "entry_point": "bloom::shaders::bloom_downsample_fragment", - "wgsl_entry_point": "bloomshadersbloom_downsample_fragment" + "source_path": "shaders/bloom-shader-bloom_downsample_fragment.spv", + "entry_point": "bloom::shader::bloom_downsample_fragment", + "wgsl_entry_point": "bloomshaderbloom_downsample_fragment" }, { - "source_path": "shaders/bloom-shaders-bloom_mix_fragment.spv", - "entry_point": "bloom::shaders::bloom_mix_fragment", - "wgsl_entry_point": "bloomshadersbloom_mix_fragment" + "source_path": "shaders/bloom-shader-bloom_mix_fragment.spv", + "entry_point": "bloom::shader::bloom_mix_fragment", + "wgsl_entry_point": "bloomshaderbloom_mix_fragment" }, { - "source_path": "shaders/bloom-shaders-bloom_upsample_fragment.spv", - "entry_point": "bloom::shaders::bloom_upsample_fragment", - "wgsl_entry_point": "bloomshadersbloom_upsample_fragment" + "source_path": "shaders/bloom-shader-bloom_upsample_fragment.spv", + "entry_point": "bloom::shader::bloom_upsample_fragment", + "wgsl_entry_point": "bloomshaderbloom_upsample_fragment" }, { - "source_path": "shaders/bloom-shaders-bloom_vertex.spv", - "entry_point": "bloom::shaders::bloom_vertex", - "wgsl_entry_point": "bloomshadersbloom_vertex" + "source_path": "shaders/bloom-shader-bloom_vertex.spv", + "entry_point": "bloom::shader::bloom_vertex", + "wgsl_entry_point": "bloomshaderbloom_vertex" }, { "source_path": "shaders/convolution-brdf_lut_convolution_fragment.spv", @@ -60,44 +60,44 @@ "wgsl_entry_point": "convolutionprefilter_environment_cubemap_vertex" }, { - "source_path": "shaders/cubemap-cubemap_sampling_test_fragment.spv", - "entry_point": "cubemap::cubemap_sampling_test_fragment", - "wgsl_entry_point": "cubemapcubemap_sampling_test_fragment" + "source_path": "shaders/cubemap-shader-cubemap_sampling_test_fragment.spv", + "entry_point": "cubemap::shader::cubemap_sampling_test_fragment", + "wgsl_entry_point": "cubemapshadercubemap_sampling_test_fragment" }, { - "source_path": "shaders/cubemap-cubemap_sampling_test_vertex.spv", - "entry_point": "cubemap::cubemap_sampling_test_vertex", - "wgsl_entry_point": "cubemapcubemap_sampling_test_vertex" + "source_path": "shaders/cubemap-shader-cubemap_sampling_test_vertex.spv", + "entry_point": "cubemap::shader::cubemap_sampling_test_vertex", + "wgsl_entry_point": "cubemapshadercubemap_sampling_test_vertex" }, { - "source_path": "shaders/cull-compute_copy_depth_to_pyramid.spv", - "entry_point": "cull::compute_copy_depth_to_pyramid", - "wgsl_entry_point": "cullcompute_copy_depth_to_pyramid" + "source_path": "shaders/cull-shader-compute_copy_depth_to_pyramid.spv", + "entry_point": "cull::shader::compute_copy_depth_to_pyramid", + "wgsl_entry_point": "cullshadercompute_copy_depth_to_pyramid" }, { - "source_path": "shaders/cull-compute_copy_depth_to_pyramid_multisampled.spv", - "entry_point": "cull::compute_copy_depth_to_pyramid_multisampled", - "wgsl_entry_point": "cullcompute_copy_depth_to_pyramid_multisampled" + "source_path": "shaders/cull-shader-compute_copy_depth_to_pyramid_multisampled.spv", + "entry_point": "cull::shader::compute_copy_depth_to_pyramid_multisampled", + "wgsl_entry_point": "cullshadercompute_copy_depth_to_pyramid_multisampled" }, { - "source_path": "shaders/cull-compute_culling.spv", - "entry_point": "cull::compute_culling", - "wgsl_entry_point": "cullcompute_culling" + "source_path": "shaders/cull-shader-compute_culling.spv", + "entry_point": "cull::shader::compute_culling", + "wgsl_entry_point": "cullshadercompute_culling" }, { - "source_path": "shaders/cull-compute_downsample_depth_pyramid.spv", - "entry_point": "cull::compute_downsample_depth_pyramid", - "wgsl_entry_point": "cullcompute_downsample_depth_pyramid" + "source_path": "shaders/cull-shader-compute_downsample_depth_pyramid.spv", + "entry_point": "cull::shader::compute_downsample_depth_pyramid", + "wgsl_entry_point": "cullshadercompute_downsample_depth_pyramid" }, { - "source_path": "shaders/debug-debug_overlay_fragment.spv", - "entry_point": "debug::debug_overlay_fragment", - "wgsl_entry_point": "debugdebug_overlay_fragment" + "source_path": "shaders/debug-shader-debug_overlay_fragment.spv", + "entry_point": "debug::shader::debug_overlay_fragment", + "wgsl_entry_point": "debugshaderdebug_overlay_fragment" }, { - "source_path": "shaders/debug-debug_overlay_vertex.spv", - "entry_point": "debug::debug_overlay_vertex", - "wgsl_entry_point": "debugdebug_overlay_vertex" + "source_path": "shaders/debug-shader-debug_overlay_vertex.spv", + "entry_point": "debug::shader::debug_overlay_vertex", + "wgsl_entry_point": "debugshaderdebug_overlay_vertex" }, { "source_path": "shaders/ibl-diffuse_irradiance-di_convolution_fragment.spv", @@ -139,6 +139,16 @@ "entry_point": "light::shadow_mapping_vertex", "wgsl_entry_point": "lightshadow_mapping_vertex" }, + { + "source_path": "shaders/primitive-shader-primitive_fragment.spv", + "entry_point": "primitive::shader::primitive_fragment", + "wgsl_entry_point": "primitiveshaderprimitive_fragment" + }, + { + "source_path": "shaders/primitive-shader-primitive_vertex.spv", + "entry_point": "primitive::shader::primitive_vertex", + "wgsl_entry_point": "primitiveshaderprimitive_vertex" + }, { "source_path": "shaders/skybox-skybox_cubemap_fragment.spv", "entry_point": "skybox::skybox_cubemap_fragment", @@ -159,16 +169,6 @@ "entry_point": "skybox::skybox_vertex", "wgsl_entry_point": "skyboxskybox_vertex" }, - { - "source_path": "shaders/stage-primitive_fragment.spv", - "entry_point": "stage::primitive_fragment", - "wgsl_entry_point": "stageprimitive_fragment" - }, - { - "source_path": "shaders/stage-primitive_vertex.spv", - "entry_point": "stage::primitive_vertex", - "wgsl_entry_point": "stageprimitive_vertex" - }, { "source_path": "shaders/tonemapping-tonemapping_fragment.spv", "entry_point": "tonemapping::tonemapping_fragment", diff --git a/crates/renderling/shaders/primitive-shader-primitive_fragment.spv b/crates/renderling/shaders/primitive-shader-primitive_fragment.spv new file mode 100644 index 0000000000000000000000000000000000000000..2f61dfb220034593b937adb473da33ed2b612b83 GIT binary patch literal 108064 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 literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/primitive-shader-primitive_vertex.spv b/crates/renderling/shaders/primitive-shader-primitive_vertex.spv new file mode 100644 index 0000000000000000000000000000000000000000..609b6ebb6fe460c14db5caf3d4b52edde102332d GIT binary patch literal 44156 zcmZvl1-w?(_O%a!jbgW?aZT(l>=rxkRj*=qAc}#CV1U?NfQT5_-QC^Y-QCykd0zIo zcmB`s+dr0T%rWO0bFQ`5+Haf#cATi!q-_&-XlrZh(spkbI<9HkCTf$he{Y7iwkg{t zY1wP7zv=o5A9&Et3oo(cBF0VK*3qu@-!5&lw(vy!cfSL6-+T9icJJSBx#bSrZO5Ja z9kAST|E0F?-|v8f`VDA}=|t?rv`J`_(k7!#PMd-@C9N}UD%#YvX=rP;b!t11-gw8Z zg~~zn=3E;ku~)ANT`T@zu2M(mQxDn zx~Mk@k&N};$(_=0OM<;>Ub*C*2JBe5mfTGE z4sY>oZ8PIL0<3M##vVy;z4H2xqStSY`UlbLm!F0JZ)#18>`X`63o%le;ve9IoR@(koW0j$o6^v=tC(HRErQ0(Dg=hl^YpJB!( z-aIGM+S&%)le{BZcH7G8dycKs+UIAE<~@}*UxQBrC-3RtzquTD2G}(+&+^#bC)dxq zvyuOOe0ufdyK)yiyUwAuuIw_O zi^g~#9N!g1pKZq5-i_77<(>k=;g!?oOoE%qxXQ3^~T3Gj0w5k*R@$l}m|DW%g zhOhpNyS9vpKfddVPhI``oa^;8bE>U|v8nksu+Ia9*xa z?u)M#chNHEd%)&SlQ-sGn(JY1W86=^rnncqSK0&U&8^*)tV_|?eCBnGaXvR}*8M2G zb<1l%*4V~+4ty^8tn>b7UXO!kqq!f<^Ayd!>NDM(X`bh0u-$*Qtm!l0vF)0(VH;~+TqXzZi0CoT3d*c09_G_QNu z-s8j%#`aks`#5a={MSASW7=X5!=A3#!?9;7_Sx9e7yBIS8H#-__Kd|o4}0cfpN~Cj zu`j@$z1SCG&r$4)u;(oH#n@eoeF=8AVvoe`UhGlWJ&HXVyJxX4#qL$?G1$u&`!eiJ zi#-;5vtnP4y?L?6VQ*3FE3mgL_LbOM75gget&4p%_BO>HkG(Cn`_|{pHQ1g7+fr~x z!%alV0{@oAK0*cq!oW7h=h%h+|nj=imnT@O2B^=It*V0{_83D~hd zLy~t>?2Of)v73SQW$YGU$Br&}x5Um^{TaIzSYO6&4R-9YCGR%a8LK~Iw*~9V*zLiN z^|_XscfihA{TaI>SYO8e8|+x0ff>6KcE;+@*qy=pGIlqxW5<;F?v9*3f(&^#yhD-q-K+1JtE;EdO2oW4o$nKyg>D6sp-*FyCNfxXn%cQox7 zni}@wsnD}B7~Gxa{&C!K^j?nBH-t8n<~aMz`$Vw$9BX}!GsgI8%m2ia#4|k%+##Q1IJHj2Hivbb%s4OWFlGeyDKzuit7nY1zU-epHN$Xk8DMi`ETbwR}$*tsAkU zr9WCXf%Qe}X0TkeZUL+1`{!ugiXAQe(Yg(+FIu;Q<@$0a{p@xJ*m+y8dGsgGonZ6S z*VVhQlShB@+zr;3JokX*qIEA=t@=89A9l3#N9%sDzGyuFmg`HjpD!N-t1ln@hrsIB z*W!n|5319v>pSibw^p>$FZZOKUzou@k&gbi3Yc+?yjSV_W6C}M5Ib7>qxBJ3U$j03%SG!Guv&h;%lZ5iJ6igq^%+=Sv_1#R<$Qht zcHY)&9{tJlCD=TEZuI@itYAO)`}*(=*w+htUmtoiuW!MA_CK5cJKFcOpW8aM{m@`S zT4R62cC7uzRPAg2PhiJ;h5NbTI>22^oUie}z!|I0*T7%ty?hPS_Z#hZn)>#e@I1G+ zNm(3Ui~T;)%Q-mKILBnporqK4*Q1P`7*0O*dG^$t1kO0)tDd@96W77<=5V|<#Wxwe z8v3kHU*ShAKJ#a7S>`eb64A%s%_j)e81wooe?~a-WcD% zIrcPq>vfF#Nlkn2xAE>j_m{lAwfg$H zkBfoZ?`6jt=a|g7H(33;mlwg7Pkq_Ti#Bn_yC%`I&ziUnjyH$nttr06!D{HUK7E<{ z5@7va;g)Q;x|f%NGuE|Ox`}r$%P-T|%hEe$IeO=7pZTr;_CBkfy}TlrKdtrBpS`@2 zn3m__%3wM7_U**40(Ot6<$lpN#F$5yd@tjBgxu#f;M_ag!kKqX zZ1wGPFV_MaXU?^0>(KO>YhAGU^sPtJ=ebzF!GyGQH^5fcKKFb>u-abXHfp$fF8ab5 ztIxf#F};`TqHh!0rZn~Kb1rrOw?7w-HO?{FC;tSiU(dzAu;o)<)@%DF&Un`=diGf_ z*U0haaJ)6ew>-mJ~!?Q_Op~@vv&J|w?aps>!Ft8)Tp++Yv6190boBj z8sm6#q_%(YdAuij=4s6j+soSY?Lga}W)6FE^lNN=`OaV`aCGvW!On2z)>p?l-r9W4 z*#&HzTAoXDSjRz(^Rf7Cnm?pQt$b2{AuOT zpBxu}^(DuJV7X{rBu1-#e{wM#e_C4lqjd>bU$jPo<)Sr8j8^^rWHcOqT3Y&}btzb1 zw8nttGWW~C)@lxY$uU+;j{3dI<#7CI<^hfJDu)b(r50=Z^Zvb1XIrPc<^V}Q3?g`h%n0gL8 z51uRIZU!6cx$$Sfo}HZeTfx2-?c8a?S-TDFnmO#vVT`uEJbNw!M<>sov2fy*795^}}F&xz~?? z<*JT)*5!A*kAjU+dnmR!eSPu!)W^WyTQ51|AIFyWI=WA2qp29Xx zU*ety8|TkV6ZZ_Zar!o9FPisR@Vc~IM>n~jgVSdXiG2Z_So0_LMRr2k8-)r!$pEYE@uVc%5Wxj7S2(QmN68mw9t?Ty*ygqBm z`i)?X%%_h2tly_#eXgS#S-;P)UB7VdgU_+$y|M;hG+bThFB{IWS?90dTo*OMecf*KMT9Z*8@LAZ;ZWT)t>MynebiE zU)X+LHpXY1F@9b)#ysoLo7djwo$+hZ)^B+GJpZSkq^)fap4auYat1g;TF*TFdFIUs z)|a2j&IFdrvwlvnmpS!yrFElOi@miOqpdGGJ;9q%gRd!L$n0m2UU2fx%jfr8U@x`x z%}tw!rk1_h#%Sxy>(MPd>wO&=#aMOj#`aQ2-)*#8X^yj3#~5vWc|E!l9G$!#-34de z`sz5x=k@3wuyJa6ugqZ`^HHOhbr>^0_5w})_Uaj99s2Tmv>-V5#@x9#3&HEleO(x= zzrOeFUB>Fq*hRqlGIj~DW9xg}CE=1+f5t8a)|atMgB?4Pxuxc1;4)T!#x4uim(Olz zaDJSJ^@KYU&K$}C;ul!vh zIkh$*&Na7Jt2Z$lg8jZz{f%gS8=t?^xH0${dVQNTKELzXw86Mqx|?CEYi}KX_TL<= zwpX|<8qVk0wZwTAwuCcQpL=I3dN22mzO8B7(A2ljcRss$dS8LYm0 zC1d+x%cs8Fk6oHL<6W=l*=N06BgdP=@zxaIZeTU^S)ableRr^auW)-boa^CxEx*^_ z6V6!IVy`CN?|kIcf;he-un}4-aIo71beyO z`m_(CscY{#c)zvvtxBG=h@T5hwbja=?+=#uwZ=Vg2)29G%X;(N8USake&=~;6Jrhf z4x@(RI$D1ehy~Z;u@6WC8U2HGw z)At7Lb(%Ts&0&nTzC2go21h5))py{`t*?%AytR2I-UAz_md{mlSjRDp^RfR5K zGq1gR#%SxyGwL{So>At`{Tc$+SI0R%YjgtG7`0q0b7YOaBfoR=XW7>FE4G)l>HC59 zJ;#;N5RnZr6xVw{(C7&8oeIL*BF>KUW0 zFKcu%IBR6?tkDRtzI+xs1uU1ncPiNU`dV}vcC_?I>vXWbXq^F;i`JQ7wd!lrS=iCi zAFZ>&`l59XST66A&jnknIrJsRd0=ylWQ{WS^Rbgde{x&^)|VU?g5{!h5m+ssCDFPV zJ6igqbqQEsv_^vEqBRPv*8lk)20L2%qjf2GG%Z?Vz;e;L46IiDzGWoapbA61d=gRZt zIW_Kfu(6)Cd$B!(d7j?^UXSK$Lw$X?6Rtl^zi0X`dN0qkzPoAn&^*KT(YqHMJ>&De z^nLJSu+_{O-48ZipS7DqJ+-SXpXcF&V4s7=INscO9!}AD!gI_#);uk?mo@9_Oq-Hs z4tsMLqpdH`!!BT-hw9{cI1QY+_0@5X&+~9PuyJbnJT!-OJj^&R>oDdK>_=(lwO7v= zZGG78;73{pN*F5@@=QXf->ND|m z?Bvm(Ja2&YCC{5+xoEuwR;xY}-^PxX{%E}e))%dJ!E(`h53E*wCccjyE&b8@0IV-s zAA;qg^$}RD`rP{%J6igq^$A#Cv_1vPWi3AgJ8$bXkN)KO9BiKYO#A{ndGsgGmtcL# z^A%VwT3>_Js?Wr4u%o3vTHk{8Me94TT(rIit5tuG?+5H?>5tZrV13d02`m?_pTTO? z-`V>GJ6igq^($Ckw0;B2Wi5XPJ8$bXkN)KO18knr#iE*@OO$t`4{@&hX z#!$i#%K%4fat&o=_lC<@xgHHy$M$SE zzst*axV_-iw1t}stfnp8++a0r`L1&wu;bJSH*dqK5$+!ir$)H>!0Oky`5UgrEdXcE z$}NcPTx#Bh8m{Us+;EP~JbHu8t?seS`Yi%Jo;A^zxJALvMUBKQ26isy%6?fK?0Dn# z4@D>OOJGMMx=X^jZZ-c>*yh)lxTV3ahjUG?Wx#40uispWUlu#HCI518(Ma6#aOQUn z61M`_{Q8n>MX;J`=r>pP+e+B(O|O%i{kt-@YoRZ3tALGjUnZ^(w)4=JxK+W%xmOdn z8n!j)OWf*U&yH8PH5#t&{WTjdd*Acbg|q0H^vc+2vE?f_9kz4v%3hrwPTu&8ouP>{ zZ{lWzldo|zHF4IGxS8SPYuqeNoM$s}v%<;OxY@C-xz2YEY}eH*W9NjEH$F9YZQ^Rp z-QeVFT=yof*4zV5zQ*-z;%d$OOEzut#%0gV1$GUsDcsy(*US9j<^j7l<_b42*mY1h z^Oz6p8sz@^yqh1}J>!)%SO8Am_>5h!iK}a{5S)CCTeyjtIdc76-cy<`1_7*mW>hxFx}^gSwf=(qPx1=3N%sGomkRusql^Qn?l3JR@?+ zu?pB4)d<%IY>jG!TNP}LYJ^)2Y>n#W`LQ}!O*I^2jJ10f*8qDK>mFVUTiz?RuY>Km z(-&?%uxG4t8(@2$Dz_1~XGbn;wlUZo_1a*ntZ27u3kHU6u>dSnN z2D>*acPzGhvvS8_yEo;sW<$Z|sC)ASZ1<+VV`WFY~AXHI~{D@>Zay1!PZ>&=GoZpO?|2PT(Enya_3{aH!F7`wtG`9c`pK6 zx4Pjj23xnf;VuDNx4Pj*f~{NK)I1t&&2?{%!FF%zOU+}!?#;@LgL7}nCC61@Yg8lL z)nIE>BiwkfHL4Nr8n890m%Vu{SWPt?V@&qub>OLJ)}Hy?fGuD5=1th{O?{cqEnxR% zWx#WEjY~AXH zdkJja>V|t6Y~AXHdj)LW>Zaz`z}8&%<{Q}VO?|2PEwFpDa__*oH|3J!eXupE5$*%9 zHL4NrL$Ecf5$+?fHL91r`7u~cH5_A%-!*dbb=1<&DO`Q8IaX-V!TT|kGY2v)MiTf2!-a1`lzc=^| zY(3^u#~9aduV(%Bp|AGd?QG-xy&JVQ0bfdQjD2e?dftQlJ(b_V{@#r-et&F?zn@}^ zdHP~|-|W4=#%}=5{j`tPy4*L%9t3Cay;sw*?vuIrxty0e#&*Y+Q{Ue2^W6h~GA{SX z_*LPbr~eCn8u}qk%bxiUyuKT`pZ*;6Z?GEj=575$O7P~@*I_cA3pDfEJ5OV@^`(xE zVruttAEb^>@Tp@MeCn7OUSH~%1gwUOd)RSaG#}) zDdAIx-<7A1&hYwD$5dc7&Aj&3VT`uE)G@8Nsl$DoI;Mk99V6jW z$Mo>}QpXHnHRNj!bLHn5GlGpXulv$^#&Q3>uh+6?tk*r|{;KQcxX={L)KSmE0`RG$o`nVB^`(x5z-q`_$HMffLtk&&A~f^bTZb{)`clWD;--#z78Zj~ z9rY|M4zDkDECE(S-a3|~PaXP}qAg7`uf25`qpdG>EF*5}sApkW_|#F)!gBEXQpfUO zHRNj!b7haM05;CN?mz3v9=o1BWWDt)WWDU8u@YDvb=7cf<69Z5jz0Hr);;&%KC!ES z)lyp>_ey+yz-sAJM_=l^0e$_}sfKI5CcT$?Q2$!kYtvj~d)LDlZGBnub;Yc?_uVUJ zVLf=)-1|O+mb0)vyuPgY24FShtz$!aFYC~^5v?!Hy!O^%jJCeiv9Y+Rqn?FL;8RCE z3!B30OC6gzo+fV{o71NbeOu7Bq?y;=I*ifQmpZl*H+9srur++@sApjtczvm3Td*4P z*0CLZ>d^O3+P`S#wYLsqwDqNq?Zr(U^(^cFpE~MU*b!b|>i9QU4f&eGT-jqgfsHe- z`_Fo^$8KZ~S#LcHSugu&^aHD-t{Sdwe7k_v(dQn{y667eCw5n`T57A~UWsovuv+@m z(U&@JLSMgis^OaNP4DF%)V~k*zBJd^-t{m>TVK|Ee=%$BdVA$8902c{yWT@+ISU8E z>&u!S1Xe@dIu54yvJQRyX@}6vYi}LKXzNQI1H?@o^(-6;pE~MUI1FB2>KF)CL*6ZoU75Pa&WXW?jgeW~LZup08#aV&l6&^MTN9L>D; z)?tjczSJ>9+|*Ie!ch3sQP0Bh@cL5631BtkYYuZ|kDUlM&b;nF>&YIwnLT8^^(BxVG^P2dkscJ)CvV{kKo-$zZkAR>!>(-w3c;`qa^vI&VQ=zjdnNT(i&Z zqj3hevOE-FT?4xrISS_{H z=}~;=g4NQej=t1+8~XaKQw{gmMf6^tH~kl5UqUmdy)_u4t*_eh*0c!YM}n`XH^zPE z*nH-k4PE_S;bw0*&uX|i8qRYQZq9~t56k(vY?i5bUkmRQZq|m2o^i7^T=e8-Z@8-0 z70!CRqSvkAs$Tbot9m^euIkMN=Ul4Z+znUt=4rU9H*dpLz4_r>hpM+g!&SWn8?Ndt z)NtzMdz*#f%&jk6Z?L)5$j@UJ0UN6?af^bTOC7rywqva+V;2V-t1n}h06W$k;g$qj zOC7ruwz2vWw=~#wt$CNhHm~cGyvu@()t9l$fgM}(E{|>AI(7wYWA$b1ieSfDU$~XP z&ZCZ98QWNWiCYEiK5`wy^#Qw&T%XjuD%e!C9W^nT3p-IvN70LeTmxy>{-{BxJ|*vIm__Qdu+*~0Au=Y6sz&%SWR>Py@K zVDFPHaR|4U*8`k&OYyJ&IKFW(j||Y(YO;{zZ%x% znVE=n@v{RX=IQO)vPWG?g9IpQ7`)Uf{l&-YvAbXdx~}+O?~@l-49mJvDwQH zfU}qN=l(nh9)YO-JXaqAyH>74*5qNZyzz;91nl~GPZIYiSiZ(RhV8xdJ|*sPu)J~M zo&Z~$Tz)3?B-q^QI>s3HpKIZ~U4zu~G`Rh|pMlG~^=IDCf}OYitlM*7=i;1F)AL|? z;}iD+xc&OP2q$k`#=ZnLr(9}$8Qgv?UV)Q0F7tjBY;JYcF{aMj`Fps@ zpg;HEeX#dHf5v|RZofVs!pR$-wfzXJmR!bu3~qm4K7o@rF7y2q>^=5gNAEMRym7e) zpM%Y9E_IA?U0n<3?HWY$OK|&ne+8F$>(9Ku20L&4$^Q-57=4+~x8U|`@g1Cejr$(E z{l5JHPTsiG_#?Re`uqeZZ(Qd6GuV2}rH(Om-p)UJ?^m$#u7&I6UZ{J|J($?v!Nxn@ zJ?kFMYib+MR^RvgdBD#T`TIy6z$X#sSYy=AYmdF!{(Yp5U}Md97xqQ;@pXci)93%s zLtkG1?!xvpuD*u)p3(d3dqwlbwvXoIV6}`N^pRc)7 z(|dWojG2nonPwgK)?tjczG};-t}b9}GsZd`>t}C&FMS%YelIzn9n&_P`!sRWHJqP! zb04OMlQ&)+^UuZi5!Pd${G<6k!dPo^4d%g@wZ5DA_QI}fJ!hj~AB{0+sH3hL-5Q_k zcNx4o`dmkSuHRUAFW1kQ%W30i)@N_M#%Svs-@JzRqt5(2Rdx2lj*h-vX}i!IXRnSi z+WPYMyY>J_Cx5?dPq_6v@%s<-b)4g!tMl0#Y@AxIi#e?0Dr)p{KE_;a%}xFG>KS7l z`tonXV8(Vsj|gY_lPGhn%BJquQ={@t$U z;G(5JTF-;^Me7ByT(n*Ut5yGQ*Gq8G(jTpt!TO^03Ro`t=vA<_nnPcnYp;RbW3G=e z^;~(r@=SUIY^-PPUhYTEV4f-ViG34nyyJbA`TWVV^-#{Tey==(4{Nyk3?A5U^*hJI z;f&2#zoR&!;WAe4$cC$9k7_u-ugv?4L2zo?!W|7((-!U+u$s2KUpW@+I5olzZa6i< z9oKMbgc|~G=@)Kj!_~Os;mldN6R@32&3j_Q)x0M)oMSVOVPJEsoA*S+wOJE=i8~qW zT+~S12(WW8SI*QaV8e0+)xAHu;j;IA-}5%-&3`+^D`Ve< zlds%+*v`c(d-Z)ddE+zogC@?riTe;vzQ%pj#92$?K8BO8ai3yaOP$AO*shmX#(oYb zZ+vR`qKT`ud2iJ*SKGsxH^yD;N*=chc;^%D zZ?OAKjc^?%=lubk8sR#^x!=^t>r5v&#~ZKT`T0J3Qm}i_`T6fRP1GM5;T8>kr+VZ{+aLnT1 ztLTk!yg8h&`(X*N>s)^xxg?ytSJq{zhI4-5mToxLD*J93IL8~WKlkZM?ytNp+;}+S zY+2W9;EdImxa+}c*%EgHoU!_{{x^cN{`#~2H;HLk|3|=HuD`yAX*bhcNBgY*gDpH^ zY}WrFIOnL(^;XMqYE)Z3>;EX&^*6@x=Exc@hnDxpD|wg4miPQ5ZUwM$&M$E*V#|A` z61NiAIPXc~R>qe1oMlZ{1^aqpu5hb^eeI~+nsB~ORBjzOpa161*!93Z>npbboX>T+ z+_w$E=2j!zMqqQR5w0)T+-fApreL4f&L`aFV4uyE+Y-*_uw3-E0-IZna9e}Ttwy+Q zz~)vXd%7Rk@y6>Py^9V6|+Cdl}AHec98mfU~FdXHUNh z)|Wl~IoQiRt?x71Yc%(!efGj9Ej(dt_VlN4&QYIxSS`n?QEmC`=`XiKd$e-RFxWj> zxkKRGqjI?q1Hk51Bix~2bE^^VFtEARNRA`G?osCx?kKQ(v~owoxku%qcMRCvYJ@u$ zY;HBe4F;QAjqK48V8dzki1FSE5bSnR+m0a#oeVwuYq<62`XOB(+f4p&U*`rg!IY)i&NwplOMz!U$N2dn6 zM~!j3IozZE^$>m8kEf#Ro~`@wG&p1Gemot{SbZ6LMiW=Zo(ZR39eWm>vHJ3v=WMW= z`l5F(*t}l359h%-PG90K0Gp%6T?l7w`jX=!u;cYbZzR|l>j`%$SbgW0v17o->dWsP zUIxzl1>ZB|_ZG&&>+@dwJ*)4z@8SDVdGF=PwB))9&bjLkcQv-PR&G4DHOOV3UxV#< z&3~Ua-_2YPuWvlw6Y$N>I{RJeC1Br|^=#JN{i$zG+8i|Z znZ5hW7;Sy|&b2!@I{D7E2b}rz)p3q@f11A+*f_QP&ea^&aTDXbtiza_v2UT7*Iqqi zwDo1)w}LZob7$VSf%WA(soTMF`F`sTu<^sl8Ld09qoqGucY*aq>u#`IwC(|`HN0ru ziybZf(Yg<;FIxA5<)ZZfSgnyo>p|>j>5tY!V13bg7%Z3X5*`6NZ|gOW{^WTSY@Sgi z&turhqd$2b2kT3oC%|&idJ?Qw{oeH{>}cta*3)2p(Rv0f7p-T(YSr&upTmxp{%Ac9 z))%c8z;e-g5v*4IZuKSXXz7pE%V2%cdIc<(wR{!qysg(f`jh81uzBkDuCHS!kN)I& z1FSE3-UQ1<>n*Ta^?TR1v7@CwTJM1MMeAL#T(sT;t5yF^t@p8`r9WC9fb~V|L$F-5 zJ_4&%|4prrv7@CwTAzURMe9?rT-Ne4u=BQF^XN~W&%x#yUH0V{*vX?mdAF8UU1RUAFa8-`l2;AST0)gfYo}u)HN?$wDd>oA7Fjanhz`&t@*)fT~O*; z04`ekqqQJdU$hni%VjMW20L%-HIM$}=?yl|g(c4-aLJ=Tc@_ohOP5tZuV13bA3M?0`rNL@lT(p*fiwUS(OMp?)+I%21-NMGkJgG{ zebHJ;A1!OSGT3=ruX*(A^I5tI*k^!y*EKgbHS_^n!^l#@s&J`6e`;6_tS>dJ4wj47 z8ep|X6|FVlqNP7tYk~DeYi+PxwAKNuHM(f63l}Z@(OM6zFIww^*? zpa1+liY>v8_X@XF!}(b>{~rI=aK`HMv&A;_UVgUFw=Hcun)>$ne;Diz_VZKy{~tKk zILBnpyMWdAvqQ%2iY=e|^8Y{Bt%)<C4>r1nc(- zw^zft9^T8#>Gy^+*0tEDiTD41Air;8??>;L{pp>reg3WI1HkI~Ss`n1Ah!2jUtU`d z0%vdO&)zy1tS@`3KUgkWhk%W*pT!1XM@xUS4h8Fr)?r||Xbl9bRX>XzjvX!i(K-UG zFIq=}<)U>ISgrb5Y!G&|^hfJxu)b&=1D4CPJKfFKH_P$lyxcplo$AQP8YmA?<9qaFFc~2eVnN!o=Ghw`E)H5h=@4OCX%n-1( zWle@+d)~)1=Y0lzhc@T^#AdvG_U}pHBk`*_j5eI+c|WcuU;COR5-kRbY4OT;+_36vpF9qxO3OAUqBm&RExCY!mN!m%qHR$I(0H z3VP>jpYwhtSY7vh*5E2^@4dd9_p8A<3;J^w#)I|cEL;PYi`KPZ)SoeTfUPa-aVNIt z^D@p{?$cdxSr7eLkGsM8vL5$<<)U>jSgo-|>pr+>>5ta^V13bg04x`+2f=DxUbG&9 ziJr7pv%A)lGT(tB@>qW4>XuSlM%bL6lwpMfK zOO98-=D4clcoi-=^e4w_V13E)I#@1RZ-CXhx@f%#7cKqKdJC*CT5p5pqV*0~t?@twv=>?VAkCwrg2 zj`<9q<2+*nsqGegK5P99urRiMuW-E^&S$BdzhAH--(SmngE@!|Yg!OC#PR&Et+ zW4-cof^$` z*IL$ra~_pj7u#5`=&gq>Z+zylKG?WAj}5TpYutuST%E^8aPl>-ZxdJNu`!&yarv3v zCScdqn!;@gb`8xRZZoj!Wv+0WgIybSbAPu0yDrw3xorvOx>Rl}Y-7E$E?Z;E8=tY; zfQ_r`vMsiJjoYq?tLySlIQbg)uO_ap%l2^c#$|3hfL$AF3b!NJwK0FVe}i2cbA{Up z?AoZCb=ev0x|la}>j&q$RBjh+W4*F2yJE{5pRv1vjjQXjJGOj{+oOrA>#`@De2v?y ziL2|fH=Mk2ncF^K*T$N{?F)8o%pYz)uxn$kaQlN@8+EfT2ZDV@)H8E1oP1q_L$E#j z`m!#Ef<5Pz8;I?huG|sWo?p4F-%((5)b%?W+jFTeIgSN;1}k?Qw&$&KL$N(ua+&Y( zVCz;l+zDXoRyW*d2U~N!mm{z}Gx}2VsbJ4Xt!@IFqwdLDu-%jTlH)e8d$MwOV7n(PcNeyMQZDno8*JU`hPwxB z-Rg$B7i`_?hPw}J-Rh?12f)@`_vAy^?n!;A`4O;tvT~1MyC*C61h#upE_t5>TerI5 zo&sC9y5XJ%TerI5o&j68x~cg&ur=2``2x0kQeSF*3GAM%+$-4b$;!Qk?VglN-q*p_ zt!}tCz}Bs9xHrMpt!}utz}Bs9_T)QY_hfyocn?m#?#U0Z-IMw19neV?mKMvWaWOqc2CM>zCVJkTitL!fvsEJa6f~s zTitNKfUR5I)chORn(LnY1KT~RFE#%Kc28FBZ*2EuoOP?4nkNNYbKR4Z!?`E*rRFKY?#aqc1?QfuTo*X^q+Ie&1Ga8;!%Yje zZgs;=2exi?!%YviZgo@3w|oZJhaCQ{dART4_HD=g2q=0b8TG;idswqq^Z{1FPwM4mUftn%?Jd zb6~6KeGWG#wwm7Od{^5QTTL|_V~pSXFpV~Ses&z#X~Jhmdu{){Wj{;W|HV^d8QT8? DQbJ+7 literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/stage-primitive_fragment.spv b/crates/renderling/shaders/stage-primitive_fragment.spv deleted file mode 100644 index 4d3f6441254eeef68c69d4c7555d4d60575d6545..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108052 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 z 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 diff --git a/crates/renderling/shaders/stage-primitive_vertex.spv b/crates/renderling/shaders/stage-primitive_vertex.spv deleted file mode 100644 index 7d66f9a70ac70b9500a8d61e61c7639215dc1b1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44144 zcmZ{t1-zG4*0zs=31YXB>e$#iHg=$5*Ni$UwvM9+iiIeOf{5LEK*VDqc42pScjwsc z%=li{;koBsFTd}5er)%>?zQ&4*51$F&p*xqJ51ecx|V6CYH4Yix#gaj>9}TXnYu;B z{=GR`S~|5%+iq{zck8}OA39*qrB_&S8RNRNbg*mx@60W8wd1Mz@1XeymAp`m!-X7Nx|1`8|Y17fBr_Df{k=BXUnKl!x3vCwKhAkai4xu;R zu^XatD7|?$LP_k^YjW2fKLBjJ-wFYf3?ZfD+Ztr%_ z|K?U#F1pDtXT9d?PD@;ehI29H?7eE8a?u+CPF(cfZMbFWz3N!Gj9nY-Sh{av1CGRX?$I2ydcd+X@kp6$~YsZ#B#dge!*j`mzZc1&r zs-3YNnz627xXfwo!evhV3TIvB-K}u$SGj#??nB4T(~di~;~roy=ccb`yEQrYN)2|r zm-Wa^ITyJp=d!W`xawHBjP(qevje^Rb%}PnL;KpghxIw1t~4)g=c28Kwi?>z*7i(l ztEugo)OMV<=T$pr$GqCkTfgU6+q`pPA5Pz$=G7hh2zqnNFGv>8xVS6WGp%jhV0yLW z=E8SmJKxeWH@>65+SY9B(e&0Uum2c&{nn`eSbF{PvomT4eGi!9=*3GAV+})T*1Z6> z&l2P1)Ht5rHIPsIFtC@l`A%%N{?|UK-5#>m9ON7hR_A1T=ViX=i~vtn?2%yS)|Ggl zVa6ujJg3rHT87+{yrbIfmbKJB4Q!p(zBqFX2-ZQ{|a5?Twuxn(V)v&!! zuAg;jyN2#5V~jtW-aN*;=I7E|Tm0uWSU&mA2fN=~-^1wj$*Fe%y?XLpxeGo!okMM1 z*=3$-W4sTJ?~0<&Hsft_#@O4`zKC9J?Ww5HHNBXYx-JF(rP!@t=Mn!Huxk-}EZBRf zmN_pgzH#7LXiJjO+Q-w}7qxjVu7K-Ko2tD{zE5r7}XJlV2B{ zmur;!;%mhuTIPH=*xYII#@s`5J=Z4L? zAECEydF@9V+gQ(m&n2IA-v7+&G4Ome_k($!q`6mprkgX(^Sm;)`_Gm&eHuJ|ie~O- z;ijdz?yI4vJxjwm#+c_C+qvf4x_75)Y|phCayiG&FSgH4&t$c|hp|1!z6Mm=dsuB> z1FG%XXuCev^&*XG`(%F|H1lLm-sb()=NkVVpU>6WmSpa(*TIc%OcU=tIuy=5T3g}= z;PV-$mV3whaTuI?Cv8b~>;UY6@Z;(KUoCorh*8Vege7^!^*MC-6nfFEy}6em_6TB) zH?AeQbF7_P7J`a1&VxNyacd;+Pp10T+ zV$Wafi?A0c_Qlu>7W)$HuEo9-yIZkavAY+040exVkHzj;?8~rw6?+`^YQ?@Bd+TD4 z$KIycS72{j>^AJ}ihU*a_Qk#mdxv6QjlE;Bufg7_*wHFiIQNUT&%bWPz5si6V&gv^dyZl|e(qvBexAnunWsWGHy+pT zVE1izZ1dZ%K|Y`1U5WSk5xW~Ue_Ga~cKtmt+}~b(I9n&v_iQ*d9iOqi!1}IY#Bh8I zf#pVkhctQ%V>?DJdW&G2Lp}Y``x97S#x4qW?8q{9G3<=hpRtRB^=0hZV8?nsleZ6c z#_G@5b-?;Ec3rSzJ@*;A9(Km+&)D_B`Z9K7uw!p4V>iLhSp6BhDOg{|ZV7g*&yeKZ z3Oi%$56jcf`(E{TaIxSYO8O0(Pv= zwT#^rJ7e`{>~3Iv8T&V|V|@l@?C#hZt3PA+0PD-xy}^zhSLVA9cE;+@*nPqJJR^hY zy?$%y*uGzn#6F7VIk8`p7@yC+j{XW~yguXfO^eUG+4IMM-9Nq-s(&olOMQJqXvfji zu%AGMo|WUlo;~-E<4&OWa-64t;%SYtzhOZw_O$^$le{=2#CLog11tt`BE!eRZ7Ut<81V z5Nw=Uqp{6l9j7wR%Q}o1g?$>$y!PrDqpdIdXEZo_z}(pbr-Sv?agNU#odGsRtzqO% z4)3QqhR{1UwtdE)3HE*%qmH^+-?PE`eLgv_bLhRCm%ejp=h4hze?qgK7l3{5>)71; z3&B1k^;wHrj#H!B@~Q1&u=m~=$D1Q-bqP3YWn9+kQn0?GsL}VBtzfy-F$Qe>2z=2R ziybZf(Yg$*FIwZka?!dRtX6%-kH?Od{%BnR))%cduv|Y*<+;>yCD>Zcp)WbE0-K|? z)O$5{a_CQvYry)F<65v>v?hSn@_lmVejRqS^hawVSYNcR2g^n42C!Pbr;OH(*wNA- zt((C5qIEM^E?T#M)$;vwv~Iv`t`N= zA?)bukN(48ebIjeEElau!D`)6*7q^&Xz7pE<6wQ!dIBt$TAu`~FCYDhKlgtP_Ot&v^xx3FrTx^>vE{o46Vg8R zdu+$rZ%Ng@=Klb8yjQp%8*VDNiNyID{}Y_C`g{%incmCSKz+Z^eziy6ek-2m);2AR zGmPHv6TO^+V~ul6=G=ie^?g0c*p6`Wsn4^g<}`4|8DI6(&6>CljyH$nttr0g;MLG) zefl!@>9O^Dg`1(_To3Q(74$R08S7efYT|$Ae#m!j?3w5t(}mvo+GoDAfW6OZXD`hP z=1=>2>Cax84Xm#Z-m~$~4xXnO>;BL-#Lide&qWV@9iAmHhN=x|K`}! z>8;l>?k6?vz2C;W|J+~l_SWk6Q*+|8w#;)bZ1=L?d06Y*V84@6cV2vsx6i$q5A0r6 zbAIpwH23m?4JJkV*sj=)wa0KZ!Rpt&+#6dy^<^(F)5IC?nnce&YvMXM-W-m%rudcvtD(>O^kweL zgY|obTcP3VUS1K-Sl42uCf>a)zj9-*LhqPA(>q`L%y%`g_gU@i<<-IbX*~@Ey z_2s#^raqc``*z~j0=q}la=&OBv)hvbWa;ySI&TZ#&k#ZT*gMf2nEj z{WsqI=zf#8xAsAd=>xX5el4BazsFt&`$}xzYrRJEneP5K&i69DN639%4{jJ5JHeTE zeQfpZb1ydl8)wc9X&ce>t;o2I!RFJq2~D5pV$%i_(yrSVTV4Cy^Uc6&dxhJ);p(~A z0?t@{?uCBzUapJ2EoocP)VI&M*cCjCxOy%eYn)@UPyPZ{zn+V~V#}w#tk*70obj$# z^z5@}M&*X6^nC-X0x&u7_HVQ={7Qu7R)Z z{{Z{B(HO^@Bengt)8xCiIFxZ-)?v&5?89i*VXvMs+WPXm83^W2`#v;xo;QQQ`m&CP zgY}OfHe-*#=1==r{TVwLtS@`=7_fTswGQjazB?XloVEFVvNdOqodDMF6>eC=xrcIZ z1~Tt6SyO$k$uZbou8F>*X@h94fqnMPV6dN)9Gm$bsUIDE)~uG})Tp+6_RXGckF}kS?PYEHM$$&m%wca1W3=^U-<$@HPWH`cICJZ(;~bxTa|YNrwcI!6 zu#Qujb+ry-MqrPmwdbW*&zSbQ=yUH+1@ou<-kUr3eiWp>yiT14mdm=11{*(uvC%pm zjz8^M`lEFQSYNcx1j|M1EU;Sj`;)Wb_|vYXKU(L2^+oGkuv|W$od>p7bLdNs^TFn5 zE%jai$Dj5b`jg{Au)gHD2rL(^i@|D*DO#7n@uyu&f3z+I>x)(^ST0&)z-ra+PsYOW zr(H{bv@Qedi`F=>T;_f`*jmk@FFD48%~8KsxdM(q?K$)(M;lmQa$E_Pi`G?Owd!{# zSHtnAT}ywot^w@mji>ZOiW*2-tb2>hP;E3mz+L*H217@9fk&0&nTzC3#_ z2S+E*p7C(z)>p?lKF^*uuyJbn>@kOR+{ZXC>oDei><4J(wO7v=ZGCxOJP77b`@J@I z?)5`peYw{UgXOA@de-H4yN`g4QQM#Mo72}9zfXM>?7j7pGyXAbd9Ps&_c*pX`V#j9 z*f?LC689vwarzSX6xg__OWf1g#_8LVy=dNNz#G$Y9oOW37EYfvB=&i5V$Gk}7vS|- zM`B+pvDT2-m*MqUOU}uu>}~U@qu=+izQ2A2tS>pUey_s2e%6rrzJ@LDm34U?+xhBC z+#6uy>iWHjZJfTuy#+R|uHW0(#_7vE-vL{nabB6{yKwrfA+hg+6I<8s19*Mbk=Tz) zY+b*P;q_Td)^8MRWIlEDXZ=0_>vJ8|$ohSX?fQjtAAE)_@0B(9yy5CPf6;J`%{qSx z=enp7?w<{(M!2sUPL0g-8?bBQ&(6KFe&53BQ#-NWgA-fV?+18&=1lBQCAO~L&+z)J zC9%JjSnJ65fv2%{)}g-RjLX{o4%Y7)JI3e0o?xFRd(l_B{}i@yein9*ZvuXj-WYqw zsy+ExGWolpe_{K1*%+U3#`t;J81rmIZ(e(!cgC+z+qB{B^ZcKUAGGev^SZuP&JITi z_lfVUz0@jz$ZfA0SoQL&)A-Kxe}ltFNw;>*cx|vkBNZ*UsM^a!q}X`5n-P$` zZ^OABzSr`5{r%vKbuIR9;{DD?{(#0lklrx|(K}yzHU0j(C->6(&o*tp|Nd^6T-N(w zV$GXp#vx!Y*IS?Vp)_^vT?g;Cw!U@9w5>=%lh=aPJ4}J4tsMLqpdH`)wjUW$#eB>ICJZ(;~Z~oo{4wC#;N6V)g0Dw z9OJyK!ccY1U$I4r8?SWsQCWM<;9a6P&sA)p3r`8vOz`PA%8S9M*9P<+IRfV7ctQ(O~08kTY7RV@FGWw9WwQi`JQ7 zxoDjQR;#`?osAtW{n0uHtS?&Ug5~l)`8=?-nnPc5oDVifYpM4F?Bvj&92bK1CC5cz zxoBMsR?BBe=6(rwwDd>oQn0>gwSwiMH3qEK|M?yUJ6igqbs2apEn4Hia?!dRtk%#{ z*Ldt`>5tYGV13bQ1Iy)o@s(ibZN28vpFCHA%~RiBUX7hR`jh7xu)gHE7AzO731GGU z&v!A{(b6BSiQwyK(YhWi7p)t>YWW>$?#qqX(b6BSo51>_bu(Bl`{)+1wVFep{0iva z3U-gVKE~8@<@xfQ8h1O`SkIb&FT^vL=lLDrO=!M0)YpeQ;SQte_e@Ws_wr2ZyNh-= z%`9pUus4S>+WPW5>;m?As7{`TGsBr%UmfT8JP&6D8>g1fLvvWiLyYsX z4r3n1euQRTd-aUb)|dVAC^-AY+}SUWf%Rp-JPwx2x;_CmzCI71#EzE!Xgvki7psoh#f8c(RvB2FIq2y8;1?;@7 z*F5@@=T)$I>ND{*?Bvm(JgdGsgG7hrwK^Ceg=TK@#ARiBApVMj}Uw7v%Gi`F+_xoCY0R;&IV-*?#2(jTqw z!TO^016VFvKZ4b&zq9ufcC_?I>u0dOX#E0~%Ub>lcHY)&9{tJl8`wN!%l`izJ9+dc z&%eO>lIP!GxoG_dtXBPfzCW;|r9WD{47BKr)>PPX(V7~pR{g!b4sg-ZAFYmHebJf* zEElb5!D`jt+nWw9TKc0kJy>6~W&q1&EoTHfZ|gOWeto?uzZ2MJfP2?9H?}@UeV+PU zHnuZ9<9)VXkL@$p&uV@*K0nXn+p)dm{Jq%)8qU|l#4Xrxezzy*cbHw_jP(lFt>H4( zxb6*C$M$GAzst*akUinlw1w*hR?`-4A+VaZeAl@!*l}uvTcqLC2=}LkQzP7>VD)R< zVhva07Kbxu<(9y9E;a9x4OjJ+YBR>h1&~L8nw>7Zcn_i=u{ktZ%YoRZ3Yk`e(UnXvCZ0Dgb zaectXxmOdn4z@MuOWe9(&yH8P^%}13{q-9zd*Acbg|q0H^vc*-u;nW^E4Fj-%3hrf zPTu&8oxO=OZ{p^Fldo}eHgVRHxVhluYuwyToM$s}^T5g1xcRWHxz2ZfY}eH*V;6vv zH$F8l*u>SEyTZxWxNc2ct+_j#e2weT#MPR6!pR$#J;%Rj)8ZOhQ@Dk|u9x}4Eev*T z%oT1CuosdhfTw_MGTTj%~o6iOOwxva&GVCz;l+)iNYRyW+vVCz;l++V=ft!`@G1#HcAAMS?jzSftTcL%$NE4L@M z`?Yd=VY@fwl6P;gb*me0AFy?+8*X2)b*me0Kd^PHo0<;*TXWr;2VuK6^`+*6jhliy z1kSx_Tyh)+wnjC=4Fp@G8sP?ktx=6|hl8zAz3j~+z-p@D7-Oa*o2Z27u3 zkHL0t>dSnFfZdyw8;b4TtlSCM?oGL@*@<9t)V(Yd-Rg$B1Z>^vhPxDO-Rg#G1zWeesd+5en(N*ihwa|fmzu|e-J6wbgL7}n zCCAlZYg8lLHDGI0BiyxMYg8lL1h6%#m%Vu%SWPt?V@&quL~v)CwP!vzV9VFNc@wsK zQ(xwD3)sC`x!bVao0Yo*+r2559FxH2sC)BnZ1<+Vz}psV_CZ33hK*?rk{trd)Eo z2ew8v!o3f+Mm55H0JcUo!hHy~M)k5cKLV?%hGUHJyT(uHz5K56U_RGse@64WMSDLZ zZw0Td&z~jwcP{?K&kX%J^}hK0eD3?WFYwFfbHJC_zL$^>_fN3T@XCFK?b)f^*Vxu9 z=NkLo;~Q{4@_9K|xo_d*&6T+CnmG4-;=YHIH-F-OXyV*wiTe>w-kK8kQxoUCP2A6L z^494Z`@O+0VCylLI>xwu`#0-%AbqtDn8G&B-@8$3OYmj%#@IVneeXg3p31LafA7W^ zzdts{-%l~dJX<)X>AkIK^7D*2z{Z)k4K3@rlKVd#d>wnndPjrZXLY??w`j}-R!7}7 z;#}MK<_4>yPmQd5?!SFv=OIQdwcChwuf#VmSS@|(=u4dw(bsRCYPjZI>AhTY{oSy; z(_CYF=VFYuzN~pquxsxA^U9j{f_Kf`f1Zb|`9kpevgQke)sVN2Md-b(L*Jihi_*+% zZym;H>q{Mrfm2643yZ_2j(QfBfY+BgmISLIZyig~rw)Bf(|Xg)Yi}LKXzNQI%Yaiy zJqydir;d6SmV?)qI+h2kA#WWk(5DW4E7De?nb+PrjM3JYI#vd!j(QeWflnQ+2e9d95?6K9r#+kPbE$hi1yPiE{y`$lC7P4OU(O3hlj=F8cy0-DH306m+ z8d>+;fBVF)1y)P#He%f?@vRM3OP@OWQs)im>$grdT=Vtmz1)NPH^API<{I0(9>!?v z%bITtcFn!-UO5Y!z`N$&_j(pKh1Zug?+aE#-a0m;_p%Oso71+Snb+PrjM3JYI{JZA zM?DK$!l#aU7PfLMEp=?|c$&O*Y(t+q^leMqj%Hqa>o7)JU+UN%oI2`R*a1Fu)U&W7 zyuQ@26Icy->)4q-b?EyG?XNWR+FOS)+WJz*F5uKr&%&>r}%vKY-rLJ*fXc?1N~ovAyeIjJCe4`N3e<-1YX# zS@;LMYu-w$XW(F-?Z6M9O_SRvHw!YLc2%I|VSvVX%b=0$P z1iZe~F&M0dymcH&pE~p%MLU{iUVG~>Mq6L%I0l?L>RC7zK6TWyFa%y->NpOphP-tQ zrB5CDj;EbKGq1gM7^AH(bqoWij(QeOgijr<2V;V71h4Bi6kV-zczJ z`qa^vI&VQ=zjdnNT(i&Zqj4tKSaY@!>zRngt?-_iI@k5_dr$16aW+^Tb=%O`kUqY1 z!0PC;Mt#=Om0lhD#GVUQOYJsdyVJ*a9#}1X>gY?Ix1q1!I@NH0T}dV;W!HzXYxD~+GQpc`{ZLGe;tps*mYu=Ty&FlIk?Py@v zV9%Vs=xqwN9({@H3$_;L8*VeO>r!jk9NSoZiQ58fEv{{9=?6AeU*fg|d)D z#Xgby>T`HHuvhzM0DRM6Z$|HP*Zywyz;OJVmvKJV-50m>Y>+<*d@3!qY!Bz&u!Y+R z&iiJ|TI~#HtiHtU0(MPpiQ5&TjB=78LKaK4+5ud{TY80 z*yn;R+_7*z7i`fS0%xqg#2pXz*<(xG32?^hOWa9dpKrFr4Tm#UUurxVoEr7#cc)JQ zyS~oBm|L4YG_v8{d*Mbkag`h0jLRN97u(A{s>T_#(`oKed*2%vqpdIRJMQ4#s$bt9 zCC>i8?_I#gw(F8d&1l>Se_o?uU7ne#SQjtr(SIrY#WeHVTaPi?`i3{p(N?f$#kC1H zrr`z^ZfwK3cDX0x!Ja2I!nJ`tPnEk0&a+dw32^Rdb7kyAuzR|4H^8}nD|ZW=d(E0M z_BOD4t#Wt3xv%6VF<+ktvt3b{E+CoO8Il!LFTp(Z2_5 zZ1i6Rd#SJQN!q zW!|rV&8@CF#?*N`f6uo+-+B#fyldflxfhK6h2AxCA141B;OxC{Z^BKv_uhgtHhb?U zu$OyJ-{-WqY3kc&ZQcQ^=h*DMcfq*_`g0H71A7njXZ-u%Dc9!%IC(fbrEZ(Q!dXJB)iOC4ieSJ%RMy9Uwx0zBoszl6)Y^=IDy z1Uqm2$^RAD7=4+~*WfAF;u|>m8uu;sl>7EOICE!Nxn@J?kFMYw90h-}n1@z|Rx;`$#R|Q}8*~7`5}- zW3RSu{`} zz5TuPnZf$K+ecy-L*Yud^6*eCy3zK<~0np}g0@nx;= zV!l1G>sl|+XxK+%92)AVt47zx=lWd^uZ}*~QJ?EK9^T9KGv*3f8_o5yw_ank^-XAA z!}p}l{5@55_Q#HnzP)JuX^yj3#~5vW`TJe_f}@ka-?bmyrXBhH2l_hB@y>NPi4Fi8 zrt?W8Ba7B8aM98qty{tRqIDZsF3*MA!PaUH zeaUeL*c`1T$DMG=p+7k$f%PTFU0}Ir-3?Z2OwqarE?WAdbuU<7wC)4TMeBaBTJ`UC zJpdOi{n2_5tS?#*f#st0Fj%djrLITdqNP7tkAn3@>oKrgp6QQ+owxOxM}P7>0X9$l zdtXn&C6E5(c?zsAd7cK#Me7-`TJ`UCJqs5t{n2_3tS?&6gXN<20$8p3ce`GMi>hJ{jH&0!^Oa}P>tJI&YyN%LoWVR(>=XM2*m%eL zEc5x3XY1jdW&K`x1|QLI^%*?4;p%seN5UDKv3^H!RKsPg+|dnJ#~#ygeqWjQ7stY> zX$v<5tfnp8abPuVdA~9g>^L>T9p7+jggc?()Ce~WtbUCV=hI4G@F#>FEb@QHRq&91!FL9^pr>T*+QDEm{uAHgUz>YUw|B2`%el&J8qI)`= z>sIrhq0Kmbi8~YQdN|kQIt#3(@$LR{AJ2wMZOMNQTr{G4E}Z#YgT$Q&Hov~)Iv=d2 z8v31=d)2*l0k(V7E5EOIA+~FwFL4)vjdNcn?qY1`p)YZlfQ@snChk&fYtWatRMR(}LZD&d-0pX}X5fe-wDS#?RZ?cE1vG@lW6Q9p`w=7CEuYYu>DHC$MMH7Oo4N z=gt;xRyfaC&Y5RrHaP37_i%PNd9RF}6I5USGz}2X<_| zuM1$y+cI`Ru;caR`-QGxbNU^){`@SU8(5#uFW*yl2YdORT3-)ZPnz$c?eqD38L-bp z$NEfiU6ut~pFZCssO2~{sx9yP0LLr`zM9?`$D70Xx*wJYyUz9Jkt@K-du3f#Y&ho^ zZl#8Et+MY{hI72}`g5PI;{M9p!d(kzoGt4*0nS)`iMt-GmMw8Nz!|GA>whCS>#slS ze-l_=*8gF!m+P)f{{YzacWl=GL9lbw=X$HC!M=7> zZhg29r{Fe%^Z9T7jNJt6v%YeD;e4*k<-TnOHn$q#HV2zqjc{9l&8&* z1NPZmx$WS54$DPvd$76H2)6^++-ii|5o~TXvZwb1JKlKx$^8`fQQj8rSvcct(R>ch zSbd3m5v-OiaWBCct1o-{WpMVi{_N>j!1}VMKLdNYr}ceGdzI$iw9j7n80?;QZ1(gg zVCSgMJ*<}F)Tp+6_Vnjq_p~vNH;1nQ{=b3sWk2qPuKV9B+};gWpC$V=Tz&5D59c0L zBkOh`*gaagzr(plD|ZN-d(>PRI{@q+t=vF3_o!U%!yvG^)d+Vu*xYJ_I|6KOHIm~f zuzS?`ggXZ89r+2T}XOGSR z?;dq*_UMdo&QYIxQZ2`+QEmC`(V4*RQDYo$4)W=KJsZwgefi9D4p>cn(K`=pUa#DT^Whw)FL4)w%~9hng0nV#$#F5* z@%p0I3O2@i!d(Vd-}zHh4JwEyw`ru>U-|H`F>R1dwD7? zxvqwD?)t-BgKe#qyB6CTzjag zIKKHg1vxthZ|ZepC5br^Fq_ANB?+N)=bw!X~!R&eHR?#%l(u)cgJbvsxt-*4RkHhu&- zqje{CwDd=75?Eif?gGn2>u#`G^*h&lu%o3vTK9tWMe9DWT(s^7tJPZSdH_3G`lIzA zSYNar0?XyQgonY-+j`BTKY1Pjn`cbP^C))m=ue)xwDd>oC9u9|y$qJi zTD}5y-qvd#{mJtx*gW-n*VnL{|h@c=uZv*2J1@={{hQI>kqJ6_5Y#io8oBckJePa zS*As6YOq|iI)K&k|C5=0))6jR`lB@sSYNcJHI5do>A-58Q?#Zxh7yL+^haw3u)b)` z2$st_cLFot%5xxsSLng^`b`9*79xM=B*)_h=n(V8DDm$h5~ z?7XelJo=MoL9ltQEc>!6T=M8oo^D`$$xxjOr9WCLfb~UdMX+47RsySaNzqyv zE?WAdwF+2YwEhg1i`J@OwJt4MtHDJ}f3#Ky>xy`TU5J&EnaG_P>mH=LhE^Y8KR0B5W| zKU?fb@8xF;eLK;1rm1hA|A)ao;9_3&O^L4N?8v985|O}zjA1Nnm* z`|tFQIhfx0+UMVT{s&lHKPzMn4#D=`>&t7)q2TN-{n=Xs!1}Vc4gu|8XXdMBTi`HPUTJ^Kok=W7FAFZRn`l5BTm=>*Lz-qNJ@67R7>}cta))271 zXdMTZ%d=%D*m+y8dGz-|=`^&D2YYT@W6zMb@$MJzm-oZ_Q*G~CwT;Wa6>@Vt~u|s<2$@L?w2)hXx#voi`I=`wd#4l2|HT)qjfV_ zU$kxk%jGrhR0IK@qB6<>-}|oT|d{e+OBi8jm!DG9qjou#`Eb| z&!_jmF`f}M?cKx1d!{@y^7hW@Fvi>gwzjOto!Fkw%Qy>QXeAFcbq`l59|ST0%*fYrL9XgvrQE&b7Y2&^w!4};}$pB@2Qt2y+^ zFT+|q3U)n)(Tqv%$H3-pE4d$sOK$zi{RCKFaz6={i`G+MwXQ5$Ps2q^f3%(f>xo1+czoy$F`en!E(IR&(e}j+epaxVq$c1ui-CC&#N`eaZ0} zST0(xgVnmGXuSa!E&b7Y6Ra;H1~(=WW49>CVZYJd!N6K`4peyJY$2Y?G}7KYkT8c3R}Nd zxTPD;XQ`aOU$8pgU(0)iTLaGV;rv;_nsCNeZY^wMz4CK{wXx-mSI@D1z{Z(3aqD2q z*SK|?xcYOM_2A@d-1<#i{X5kgz{w}hxowE;JThNv*$B>gRBmHzW4%(}CfM@EXC9k^ zjjQwMi!EQ{Hf!SQJT`}uuW?&6adjU3;N*?V&-AtgyROz0ZY!{BX#Q|pgIzCkh1&+~ z+NhiRyDivtvA)c0J2=;+a@%7Y>y>rc0bAbqjNK7zTwRx)u;pvq&P`lhm%qTt*SNnn zadlmGfs;2bbK4c{+E`P#-N3Gm`NRDU?An+s-0oo4M%}E-9$?qSyqVjcaIQ<``ePgG zm37$*Ti*DL-5YFNU6*~ZlzHi_U!A+x*QJnoL6ozwr9F>M`3$@<+6Uq zfXz|YZwR*MQeScm1$zc7cLKKOt#T(~d$!~<-;==Bt!}vCVCz;l+{s|;RyW)!VCz;l zHID>abG?_Nust*SQuAoA=c96GV0#uScNVt$UM_jh23xnf;m!eDx4PlZ1zWee;m!kF zx4NnM0y4jO& zgWZ$$wc=ek`MM|H$97NZ%RD{=yC*C6F}8cMa-U+mC*`tMpM%X&_vDw@?n!;g@fFxT zS-Eep-IJC34%%U~8^>@;7Yvq`uVr zFR**Ea{s}0Pgbslb$3t7CGS*l)~#;1so|_!-EbY?tXti19pS87-PAlS*qZB}oF2|S zsV_Cp2zF0at}~o_vT|ME+>>(2J2Tk2)eScb*t*pXH!Ik>)eScr*t*qCEno8);6QTt zyXN7(g*#{p?t3`j57f9H;SQdH`vuNtIUig8tM?n+xGA`Q!CgKD_aC_N4VRk#fU`z* z!}$wf)~If{so<V>#0k9)4_SJD>nn2=ely8;5^rI$UB0_us$sc8-e;fv_T97ZeuwY7U*ALb>(`2HPs|LA4vdbBPK-_3+PC#>IQ^Rtc{HZ{dZ(9%}1bq-FiCw`7B(XAU{fTkiK7+PCJ;*h@3i zIfgkoU9%LnN7a#wjdRgk zm-<#Kaj9?J!gyn>?sMDAihUw2NUWOQR z4q#aC0@yyUjF(g6bY}Nceobua@j6&j)(-@GXj{*qmi2%3nJv5jI^C#YFj(Co%xaiF zI%k916?-VybL&q0lFY^?-aNw?ZEgJ@NZ#QsyKNoyM}V!{b6J{mHt$HrQVl)_oV@3P zf8+4{ye{sab*OVbvpVK=k1u34xBHs)7lG{q_s?gqF>${_9FB$KUGsfAW_NB~fYqz5!_vkW4>be5FTd_xhYu#63d#;JU3hXse%bZs; z;u{T~mC=ig)_yI+>s*I@J_fD_qg`wKzVBnf(YX#h52F`*Vcj<{sz&s0g12w}f4-X= zzWTH7ma-=P_--veb@l7>T*ooYskR!%+IPK}t1Q~zvY}KfIBg~ zW_K}r&D4v3B6y}^PXf=zurGW*o8LWm_S(qZ!^j@q2liYt{p-d)@(0m`)s#1?e0|NGq&cp4%Zmx^T*+NO=VVBUi;C;Ha6$^7+<~0gfpg&Xbf(A?x*qY&)IObuYcF-(AtNgjlMY?y*Lw} z3B%y)c~_iV!<$?KTI)Kuo+l%w(Ti@K?H8XdBZ)QMT*u%QWqop=2j}@; z#7O^L0B7IXf5xW|E`y(;*q3A5JMmwE-MQGKuxBpzmDsZs`zma{{=0rG#_Ywu4tuU* zkH?;)*tcVMEA}1Oa~Atf?753Q0ejwJ--SJYu_t0LQ0%+07cBN9?C!tUS^Ap(KN8Vp`c&}yHOTI?iUp@<-EU~M=`ToWC1|Izx-(!8o z&Fj5A6?=8!?J4a?nO7|K#n_({8^7;yz9_cqzbdxtzi#aBctY%Ib8`Fyw$9zK&F{Px z`Fx&!M?7EuwZF$`kG&za>;Dnkd%$BHXfX4Bte2kzHqW6=o*!AM?*PXB40AdEz-)}R zzSA4+gTc|cqtQMD&YJYqb*}%0oiP7lVB^#piER$+_?dMc)?v&q*uOH&>#UwJ+WOYx zc`}6f-@u-udt~nHjT@owrlz)bZVcmWrvA-2Oo#0nx#&#~7d`#aYY*0!wKITSJG89r z0GGA;v$i8xU)FX8yLMDr+XXIb^=IwOV0|Z3{7J;m0+x$bSFl<>`*RMn!bMAev}ObA zi`ML5xoFJ+R?BB+w7S7XOMkTH1nY~|Twu9ATo+$s=LTD=IrJsRJYaM9`jH&-!X=0P zd)Fm z!1}Uwajd)FvvysuzO3C4?Ap=gd^dv2TK!qOF<76ywj}Xalh0>> z_j0(=aQ2YB5bhc{_sVk)cP*UfVLg4C*QYUX_OH6?xXw6x!)xrdvId`9_1Wh$&}XTy zaXaEu$LFE1cRnY#=Kk~9zY{+FdHu?BaA!Duz6Sc--39F7b64N4jNKSMXPu+BJ2-mn zh|lZE9>$Vazj}Kzd#I;xFUH;s^_+7p_61vqYdt^L8Do64NQQpaRo zGkiVrS#BMVV0&1HzA23R8Rl>{hcVjv^1AjAI68Sg&rmnqh9|==B3f&-j6yt=IS% zc)y2JGre*w*m!-`ZVvU-uC{#6<#@2YVvOs}oxME)oV_(JdwU{SUtVuc0?Vb2lflN< z_Y0?BM@xUSP6g|W)@fk5X!QrHHIy1t*8uEj>5tawV13a#11y)<+JRteHHW_B7z8#) zeV=hAc5>)Xj=^Ak$uR^h7p=3vYSs4{XJbc8f3${z^+jtKST0(_!D`j_86&Wxr9WCD z!TO?g4p=T)=YrK5Q1}cta*7;z4(YgRE*N5kepE+Cz_PnjvJo=O8BCvVt`-+RP zlShB@TmsgYJePvyqIDTqt@=LWa_ng7kJc4nebE{Pmh-j6&qb~Tt1ln@tHA2l_aawg zM_+&RM}zf6{~EAdw5|oKRo|P8!H$;xXpIHyi`I2uxzu_+Sbh2E-vCy>zJIw9JNo*g ze-l_=^lt{sMe7!@TJ`)Xj=RD7l4BBBE?W11Tj$REfILs`g^QN{Xx#_a7p=)) zxoF)FR%>**r>0;>OMkQ;0PBm^gJ8L6Jp@+E?>AG|!`RW%AFW5g`l2-zESLN9QLyK2 zz2?!MJdc6R%)`qzFs){`r!Myr@(%0b`C3sl3)b%u?!AU{KfIn}nBRvp*1hAM1I_G@<4fZ;#onHC` zoLgpWL)#el!dlE_?rK|8wT=6R&q}?vpM%FT8#9vGwSJal zy{@sJ)O7ZG8*l&FU-Hh@dMssm&Ea}$if?9kHS}4ZzMT6k z*!n%fb#1uX%d^56>t4*(#M{gAvp4n}%&zIi?D;z9eCGmtoz+e+&kg3QwO{(v%kzNs z<+(U7SkB(Qi}?A#_J~^ci?%WDjkTHETB>c0)iy4@JwJFXy2jYsuC=$V-!=A^n$BK- z<6C{%@b;ax`*Vl|@L5|QK5g%fy&(2L{1-ANFnp%l|HfU(?0bZKkI)@%M{Jh2_A%Fg zAvNIiTTc&W>v7ICUKnhgwJgHiv+-HOqG0RLw^-xzep$T1gtT;*Fa}-c^um&0wLQWu z)o}HGSsKn*efG#Q%pUHSzFv%F8R|Rdepv(Txz+o{wZ^$7{j(}q{d&KwhAp4^vR|t= zamKq}(R0pzxks)yhwH5=zBR#W=(9e3Irl$;^?QU{tKsVXvNoKt?!`Jyy!VUzx{bXa zvuoC8_I#c5{r!eub-m_lY{cy0e(Kwpu?fR<&gr2|!RaC6^L^%K@P6;5X7+S*u<`ob zCv&K$cD3c*8{Z3T0rvY$V_a|U)ciNT-}kcw^H}rS*dErb?+wP^8Rl>{hcVjv@|nb& z;OOKtiMQa)t*@?gy|wuo^$yrLwY-nbVI5nt&ciy4*$TT4!@SPw8KbQ)&!?@ye6{-1 z+<8821J;*)+!n0g-ptzVu=#4O)t|N7gY~6XcLu8`U+b`*^y402*9`Z-IeqgT*zc=coAdo1&b<1pSuNM8 zQEmD3&Cg)_#u(R|Beiwx0#DzV$J%DW_OLd6oftDR%;9VfW3=_9Z@Pe^lfIc5&fNOy zI@hOfx`K^U%f2y(b?n#dt92N&KlT9(^E#_%jJCd9`vbvzwXVInbL|g;)R)(_gTZpy z*F(U@*FHKFj<1%M{%9Qr))%eA!E(_$0<6|h)~2o_;rME4>5tY?V13c*3zp0Gb4P=% z)g1bgqaWBD_4Afv;P`6g(4QQ~g7qcGabUS<9S>Hke%^8d9A7Oh{n0uRtS?$8f#srg zGFYwpdCMtqe6_UnN9$CuzG$5Wmdm;K2V1K-^d-jtusH^xnf*N-j;~e@{mF3#SYL7s z1j|Kh5Lm7HS<9Jle6_UnM{6)xU$lmR<)U>KSgrb5%h_;zwY2m{YbaP>w1$D@a_+;y z)@lxY^8Q}Q2(Ufj-WXHw1Mdg#E91@q8|%H{?_hY($id(Js}7lET^eD>oKcztSGr+Thcr`qy)R$T`6S!Imt&6D~TCo z#(UKI7RC0kK79)@x--n-Yz||z_2pT$2sk=;2n#9aqA&eyWUU5{;?zQo-CHqM{_B<@CR$8^JSJ!hdm`@%3z8CJznmfSy zk~8~vC%pS-4LRQl*zz7Z-@C9qUww(22sW$R0e}aCM&_YdF_tpC5;FU(^WqM8l~O?#YHzBj@=vcu|Jm<9THNo`KV+ zc4D6eC${e2bMX4inb;RfY~8;X;q_TdVqY$?){)N}Z)ESRLw(m7m%V)ztlvF$jn9E~ zz&=mbW3KkP)7ZxOy>@TbEe7^?6pe9qt=hjoOMd^X={4-JP0Yw9#_z|CF;7os^E&&y zGrk97@rHNyn)?09>tJ6OW(4Oo;WIe-`g;30Heaphp#D4uzX0pY&y)WHmdo@1d$5Of z==*{3Bg6Wft=AZBeW~jwuyu80ZM1)ZllQe}EYy7WP)L8@DLmho9Gge}_&RHE}wDsk6Yc+6m^18J;oOSD~>s+7L ztu?{MspT~_hjp~4Mi1*SW(MpI4D&jxXNjj~XP$@k zgc}EE4rAq3pr+g4jMZ27$^CNQjaeLQoO|c*`?;s~pr2K(f$j6fn*1Ei-|v%CYf0kV zb7!^uoPH^=pS!BRG-H{@=kEyj0zb{HZ`sD@XH3gA7*|WTH@3RYxfhlPtL+hPg@*IF zH=YW;7ybZetUh~ZMP?6sN8d_}l^Nw zJ=SaDjCa4H=bZg=k6dpK*IQG38-Uf&XMOr|?i+&jdxYDl;oJ}3lZ|2C7|vMtVv{D` z&zR&lZS2jMU9&l}=j*JdpTn=xT>ti9ufM;~DVP1;f>`tBnXx6Z!O zf}^KquJO+B`qZ>u^<1k?wdK85*0w9yXRaK9+)>qfL-rBq;b~lEh)<|q~S;y|I^RNzM_Q2kgVP0qTjM3JY z=i6T3JfqB=>$NvnUtQ<=?9skpW7Kl5%#l4hjQpOPKU251e%Kz?rtb*G;S6hWHit3V z`m#rT!O_Vc9Svu0eRZAdvq#5(jZ@1#GKY2S&pHq5Fy;X40~zLZR?ir1ec7Xfz}X{n zXO9jB>&y2{hk)hMdxwIJudhXiVMj}UvxVjzH=&ewDd>oG_byC^#{vEYXDfS0rWwx@9Egl(jToe!1|&!5G3P z2lG6?2)sDM*M|D~aIrBA{od1;Fnf4U>${Y38N++nIeM3aqi1|R@4f~4(k}rIuGkG<{Ip48Rm6X&lqiexnIVB(=X;uzl;Uz zOTSzPmdn0g4>rC&4{yMZmi}nn2-X*^o4|6>x*6O$Z|YB7x4=b9f3$7|>xoUa-Ds-3OM7)?~0+1Ik|Bj~y-j(V7C*7p(`ta?yGatX6&QJ%k-C z{n2_DtS?%RfaS86Q^B6M^_oY2@;nMQPkkmnhMhe6ljm`;zT|lVEElaO!D`iK;#1hs z(jTp-!TO^03|KB&e*vrId!O{>v)IwnAFb!W`l9tbST0&GfYqwMJNP1YwDd>oC9u9| zy$qJiUcLhMysg(f`jh8XuzBk56~2a@Jo=O8b+EqV`72m1T7LtpRe!JW@7U4OAFVgQ z`l9s@uw1nM30ABA{@|O~(b6BSx4`^6wmTUEalxmi}nH2i6y@_rY@6 z%MZYwxAmGwzdpY&{t)alz}|Jwjjhko(bzthjr|C0{51^!F7#SvzgP1!^hYmZ;-!0%X*%N(6hEUt~Xx)AaoKx9y=P*y&cYdtNHK1 zHov~a-3fL-JlEu!09Mm@{pL#iUD&BD`6t3fBXM`bncqD~+$6C1^(EImU^UgyZ?5#) zz1a4q$B3qX@56R4^d)XG*f{$#ara|;9{LhD1#FzXnz#qBtwCSn9t3;uc!YbX;cD+c z+;HiA@2`)!-@GS1vi1{f`O1BY?YVfQS3iT3H$H1WZ{p0GxG&)3YutaDIBQAVmvHhm z?yDxwdoyug!^zjUZ?Ubpp6_?q?yE=Eeh(*ad}{uoiK{jL2q$0Tern=s%|FA**SKGr zxLWhCaPr2b=Y9jbht?F1$7GxPW&UvO;M^N?g_{n}eNZ>&(H_n{$o2JkHv^nKh+ z04HyJ)^=>->K@DpCtu?_HF0$hW`dKiah;pEx(8k0>kv--Qc`O^kom`0(*~CZXP)A5xL};A8d_kgj)b?jcSBj5NwTV zgzFBrM)mUiSO~198m=+M+PxQhfV~%M4=(~I?~&RU#rD3_7jAK|_gLkYg!6u?+|qE~ zJ962xUSM<7Yrh<}_ldsbSRU*>QMo_B+5eSW3C>=Z%U-Muwr+L9tpc`gb;GR+wr+L9 ztp>JkbyM>iU~8^@_(yE}T3>2j8*C3(Ze48qwQ}oY+naL9y8+m`)eW~H*t*pXw-MO7 z)eW~X*t*qC&6|R)x%TGf*!HHr)Vu}Q-mKh~aQ3ELa%>H@Mm5511GYvr!fgw-Mm551 z2ewA_(wp0Z)l|bZ#-ulQ0Nb1O*|HOyeC^F$ut!krDaM)lI0 zL&0jQ;TmJoo5R5NrnTpMM!?C}-aH4}-qe@#IS*`aR_+2gd$V#E!P%Q~$#DtT9JMzu z!?ri|CC3$Dd$V#^!r7aZyBf~kl*?X>23xnf;jRH&x4Pl31zWee;l_ZiTiw)r9oU*{ zZ{C1yZ|Y0UH-YWV%H4u(Z&q#`w!JBrytjd^TitNu!Pc#AxZACK10YO3KH zWBjafDzk^5HEzLm)qa%WXN%5$kGvebwmyHB=-+;<$@lC2oO&aCet+)!xX1C!=lg&s zuzfEfAMQ!8&+y7Uh3&mlxu>zMSIFt@>Vr{JqR8;IU22$R@_$Pcg!Gb zy_&AIPxj<@Sv}M-c2{gU^_~4Z-yV34b-6~yuMht$^Xu@Pmv*&4yw!YNyPjKq64^qdQ@TtSkyHm$o@cL56+h8^1t>YbL z59`qPF5^9hd7Z7p7;Sy2<9%@Iu+LJ*2k@z5D17Sp5ME#E_z0|qymkDG*~2>Yea!eb z!@SPcVT`uE)bR;8b=b$L<5T$5F$z9)dZq%RdmG|H$m&p6mY!`)7uG?CiN1qpdG{{wvr$xBon{=fA|q`Hrf0NgnAh1ljM3JYI%WW;j(RV2fKMIuUg!v~FLlfaRzu!8Ix(jX zeKRpSGtBF39mZ(uOC4RnsiWQtGsCBjdN0fZuP=3U1*;)%9kVj04t=vRW@nh!**c8T z)|Wcw0H=<6FLZ-X9ra$A6JB5Hm_~rwvqfd?Od#=B8V&?~|rM5cuN_-1|)zYVqzSQ{_^z~b(8t(bR%pUfj z{zb5RGTdWl_rn-%ecAKH!0x%%-6QwH;_&Xd*S+2gOTg>Po-YYjL*6=;V)n2OeM>Wz zVVKw1I*ifQmpXcZQ%AiQmW59p^F$Xmy%%&9})YK+wx=5@9XW3=_9jy1rkquvW^!l#aU zFZ>Z+U+P#3tcHBeVXpMp+F;|%YyVkKdhA(x$a?Lu+zZ(+=V+`8R!3bm+}rrp1FNG? zjqH1_zjI>O2dkyFI`&F@8-Uf)r;fhV`5gNCty2y6d{br*dr<#o*qbxlV`uln7;Syo z^DV&cx%=&rd*M&;?z#J2?}aVl^<~eu0;?f!9etQRtV7?{jBOa^b+!&;wDqNqZNaId z-V58or;d6rY!9z5b?g9EL*6=eWKJFWc4F+zFt4+97^AH(b?gF89ra$=6+U&;dtod%IP=8;_C;emOgd#rOubo*KeI_*k30wdw9R;KN0&R zhP69egE89rsx5EcrC5J5*q<*OW8b+p-*YaDu6~bj%Qc+$YPjAF=Y11y`G&KH<@~Rk=zxm3N;4OjK9 zX}GF)ZNpW)>)_mns&{?ERlOS;uIk;`aO&lAo15UwtuNfoU~{XHpU2(;HdbHaZUuWT zb?rE8*IHB7-Uc>SU)GKXyVe}xZU{{y!cQ4rUsB7=THdbHaCWGxG_c7f4VEf4ZNzGHh#_CJl z17Lg0z3_7yd-p-GvHBAC5ZL=cU$}?C_H@nr2)23MpX8kiHdbHOJ_-rM+ z9N2pFCGL5!wYaC@UI1H*=bQ6*5p1l!#JvP||7tBSV;ie4aj$@V#^{UQt6=NVm)F-P z`HWP45ZBe`@IbJK&tZM1V?V|0bJuwaJun#m(`B8{b^GFFo(=M6f`>6u%gb=~h9lf- za9%e@_Ud&wWA!EO?_l@Tk+?VDjMbO8H^H8-BXMuR8LO{LQ{&rUpH&Mn^k@A$V11rL zxDT`XOAOs?ZC$BOI&-f&o@WnW&j(jFEw_MYxY)ues{Vf z*!}e!jJdn%p-v5N?}h6OXI$lGhI3tdv>VvN9#x|&V-|)z>g;<1W3=_ zHt&xT=bZO0bApX^t#N8b<5hV5YFL-|%&E*C)}wy`?D-hxceWm5wDk?){Jmcm1beTz zH{rTBoO=*%p@#c?4}M?U6Yc_r8o5r3fxVw9w*B{xSwtp+P zBDTF|O_;lAnHk+C|%eR58(tpT<^&pF(hVE0bF z=>HLHZ1lGWd#JB(GsapB^_`=&HdsB^rkB?Nrqqp3gZ_XJP7KYPK+8=t-1 z8?2UG*6stI_PYETPTshj@4jHKvDZ3!`+?<+%Qe^^Y;JR@V~qRiUU=T_K{O8pPkY`6 z!R5U5=e!RF59hq~C;uT}WAx>G4h2uU7l*;g*SN#6r|sJ#;N*=loKFZfJP_&gc|y zM}}*SQTtS8_upA<<4yw`Yd-(qQ1caE|Ay1&|C2{wUjJUh_BC!KYw{X85Wo7TGn+5A zbMg%Wt7VM(wU#rntwEo4#pnCX!Pw@}XKsDI=AO;$;r(UIS&ShJ>u|OXW3=^ETRwFS z1zVdj*5O*e_xAVFhk^Bb$ocFT-f;G5;zl%_-|yz{!bZZ$8?TP}^KTb8C;zE@9$~CC zxd-h!{NG-`&iVT9Ak@9izqjBVjs9q;qplkM+YI{LzX9;-=yMwDsk0zCHj) zCx7$xA)Gn&)pf4VIsOZ5oLcUcIjmza>pZN(m?79_G0f|%o-x|`^0yLagFQb#FE+P7 zOZ41_g7xKZC5D0J`Zs$s9BjOw??!6`cC_?IYb01-w9Wy`MeAI!T7E_wt@E&>r9WEd zgY`x00n(Yg|>R{eXgtFWV`KU!CV^+jtmST0)EfYlmM&hc98Xz7pE7_h!*jRni) zIe#74^R`~|=ue*O!RD!d3w8r`^5{>V8^QXL=O(aRv~C8gRsY`W7VK#0kJhbVebE{R zmW$SHV72PsdyU7Ami}nn4%Qc~JHT@3qdURYY7TvQ)=dE0WA2YJ^}h1{%5!QW*jVp1 z{{}YqV4gG1iM<nn2=Th@_Xt=7^vEf{s^OzCN-0J3iQYWzQhxH|HCa~wCM&deyJr{H3 zp6UX2z47`7u`Ka3V@D&pv%tA;HGfw)^Xp68tYG)Ub4{+1B&qH70 z=5ONc)x<3TXASxiw;-)F2;TH8l$Km<<{_UNHb8TMp-iI@6AmepFo`)a6 z>l=sH_fpGIhwo3W0Q>%8<)$v*U+7z&(VOA>31^>!#%Sxy`$udZ`_ z-sh|WHcl3^E>oDeH?0+-N>#UwJ+WK-(H9u%o3vTK@s-i`JK5xoCX_R;#|x`5HS~`lIy?SYNch1W4 z9bB~ZM{7E;zGzJkmWx(5tYN zV13c*29}G~oM5%;-?q;M7cKqKnj5SyTJwPAqBSpAt@^j^^T9<+f3)TY>xfg360T(U((OMF$FIr21<)XDTxOI+vPn#ZJ1}<9qqty$nFIvlj<+7K{fjw{Q zHIIIMOL7172Kx-KcinSiQ^WFLYZzVbvlZY{gZ|X;2e7`>up(G4S}TFonpCt_hKrW| zXsrU)7p+yna?x51td{@Zob1i&aM98qtu?^3vmsb6S{s4Y^8d#it&QQLr9WDm zfb~UdQ?OjLHUq2W|FdOs}EQ% zd$~2(^R`~|=ue()z^$4~FKr8#Jo=MoJFvdw*&ZwxtsTH>O(-?*2p28=(b@^DFIqc; z<)XC1M7>{?qIoS?EzNH|A%(2%bsx2(jTq8!1|)KH&`xvxewU$ zwqEn-Po6)6%`>s&*%vN(^e4}LV13E6KUgkW2Y}VOyJ#H<7cKqKItZ*US_gyWqIC#Z zE&re3IsZf9qNP7thk^A)>u|7Kw2lC)<^NAST1Ub~OMkSE0_%%bU$9*E@@TNJOI7=OzQd)@lxY$#FW^9QTvMf1}d>r}!|i z@7D+6^ZmNB@Bf!%AI}62$M1Xi!Qdeb{~gk^8caxQ?b+C_b@uz7)@PSs*L#E;)^L6= zlz$g@+I8TTF8=Jn^>AK$eYx*$0H?R~r?+kd>q~Fl1eS}| z&0yo}_hPqTM@xUSZUyU$);O?Sv~B~dRlgS-j~y-j(YhV1FIsni<)U>bSgrcK*aYlo z>5tZ3V13b=2$svU*waa1?;H2ndq~@O`^D?!_3-*s+v`?sRi=hSreo-p2f)O%3g+4JhhntQ?4mOZ%-+xvY=bH9I%Z$xvy zPifXWr+*&+pNC(~2N@4Byx$*gFezF!J%Vj+=k)Saufet!(kSbg^RizyVIAh(5zc=yT@A7Xn_CJ_i^G{~a*E#q5n_zYA z`|QD6*j{^mx!>Og=U&jCd*L0hzT6A%g5{$19@zMLzrT+iE&b8@0IV-sAA;qg^$}RD zdcXe*J6igq^)XmqwEhj2%WK>xU~4spKJU*<*@I8P_PKlF{i$uN*Vp}Z|J=`NyU*1& zF8AkWVDC?3ygyy*{pmGujrWL}&i1hJ-c#N)^3I;qF|7F5tZoV13c*1eVL5%mlVpbLdNs&R}yq zT5@zTj?)^*(4QPLgY_lHEMU24bp@;SSkamlE?WAdH5*u8v}Om(MQaYQT8|g4ZgA1k zAFVmT`l2-#ST5&2H`rRup|4L{r?zD{w|T(5xt9GH0~q#)`((WLSw2s8_WA3Y1@XDg zd+Z!)^Rs84wM*e!4_m)Sxb+*(XQ`Z@&-dZ;Yk7}wTf@0NoIgX^2F}>ZZHsNJM}AJW z9k#sj>bZ7%F~hux+W}j?#_ia|`7?#Y?F1)Z<92T1c$EA%ZWlQD#CdMJVtXDrUu)S7 z&hx0;?%2k9B<~*B^2X;p_5>SO&tora`5L!(6Iah;A2|6M_va?Ap2xm$^2X(7VEcjH zS8EElKiEAqf4Bp{?w7g39SC-B)Xnuh2<*P(XE*N4!Eo+N z#?^f}99zD|9nr+qeK`_NzQ!HZ#MOQ23ny<}&h2Qhdt*)E`hndW^M^YI?B19w+_7Ny zM&0boabWkwyg9ey;oO(Xoq%nuNA~4JY@%X?Geh9y>mHnq?Y*xr z`!WpdeO|c{*xu8XI|tkQS1$W^9@rdp|1QAxzSNf-7lFM8D|ZRD_gm#I!}i{i%lTdo zwr+L9T>-Xkb;FGUTerI5t^`}Rx~chUur=3fc@4JrjK0)72JHP&x$CgK7bJ^2B)J*h7>e+0HCEB7(BJz2R=u z3~b%%hWi|B-Rg$>0&LytrYFAy+mrRR;%hkh+LPa6+mrfo9^ZrQ$;$nRZBJJ2XKZ^? zE_?MW*c`Pd+o;2y)R!F7!P%3QYY%5nR;~k_Jt>#-?FeVx>V}&UY~AXH>jbuLb;HdB zwr+J(a~H5R*PfgO&Ysklnr8*ula-qt&YrAXH#mDzE_vq!TerI5<^o%{y5Z&qTerI5 z<^fx`x~X|Sur=47Tma6V)R&sOgYC)6^?#GJ;BzkZn#Ck)~#;1#lY6B zZn(w4)~#-8>B;v11IXd;6NOt0?(}K6CE$ENP~(<@8#oQOES%4Be-|lwz2PQJ!>s^! z&otbMaQ8M`YF-J>8r2QAGT0i`4Yvx|8r2QAD%cv;O)YDJy|4YfsBmk+d0$s<9XRjn z%B=_IeJz(9>%&>2y5TkeTcf(+HUwLvy5TkgTcf(^p-sT^kfZj{W^i72eX03>z+U&t z{Rz(NUb(H{yzX+z+Xrmj>W14IY~AXH+Xigi>W14EY~AXnmYwxev%gmsZdW*asB*i* z*+Z4v6V4v0+@Im>p~s5eesK0sp-0=7nV!yO8?Ms>p- z2DV0Zb8bh0?IC|ZF5J;@_E6=HfwPAycO0BOB$ph=!&#%c;Z6Wsqq^Zv1Y4uJ;Z6cu zqq^y#Q^50)qxR5gaQ2YC)I0!e4^{3AID4pagW&8Tx#T?)Y~AXH8w|E?b;At-TerI5 z&H`Jvx~XNPeropj3&WiYXAf2Gd^mfkau>qcLzTM}&K~l26Qg%IoIO;zQE>K9<*tIW zhvZW8)o|9RZn)84Yg9MfHDGI0H{7*gYg9M2To1N~{5{EVH^SLNmAe_v9;)1}aQ2W~ za*TtsMs>s82DV0Z!;J@9qq^a42V0}M>7hHp3y`Ds&|Pr$kiOJ>H`pGk+&ysiQ04A} zvxnr8cQV+z)eUz)*t*pXHwA3n>V|s&Y~AXnmPhqd^MZ_UkHgtRm3tD-9;)2aaQ0B; zo`bW8x-+8p0-QZmxtHMVp~}4iXAjAx=2zjYQQdH_fvr*9aIb@{QQdHV1zV%KspTJF zduSm>xHsYKp~}4tXAf2GT{wG4E;-(Vvqp8py$`lVb;ErCwnlZseF(Njb;ErLR@0sd z_Z7C9_Ds01vDLI^!hM6SrahCM{0`gSA@&IOeZ$qy9)4)J`rh#;IA8bF$X@*d-g+AD zH*8<`YFxX{ydR&2n;y<*p!uUW1Ki+gxQ=i>18ZC-xU(8A=Q|UeHL4q~GuRr{4c7&1 zjp~M*8ElQ}rk1W??=SZv+-z|7Ps7at=lxaV=7f8o;gVx6IBQfl+}vPmR5#o_U~5!2 z+`M3GR5#orU^VTLa6Pfrv`4}%imj$S5^gbUHSLl7OnPx_HPvv9G5&n3BfX+e+yU(G VoBMgW|F)|?e{%kX?~GPs{4Zb!q9_0W literal 44200 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 N$@x3JGFq4Me*l-amd5}9 diff --git a/crates/renderling/shaders/tutorial-slabbed_vertices_no_instance.spv b/crates/renderling/shaders/tutorial-slabbed_vertices_no_instance.spv index 1e6d7ea45abd9133fe58d710671c38d7033721a1..c8aed39b6da33158bb2fadbf1375ac16ecd281cc 100644 GIT binary patch delta 20 ccmcbken)-71eVDQSY#$oU=i7TfJKHM09z~vdjJ3c delta 30 kcmcbken)-71QuRv1{MY_1_mI>z`#7YmqmW_9u@_D0Cm^~tpET3 diff --git a/crates/renderling/src/atlas.rs b/crates/renderling/src/atlas.rs index b8e2ec68..2b2a73d0 100644 --- a/crates/renderling/src/atlas.rs +++ b/crates/renderling/src/atlas.rs @@ -1,33 +1,27 @@ //! Texture atlas. //! //! All images are packed into an atlas at staging time. -//! Texture descriptors describing where in the atlas an image is, -//! and how callsites should sample pixels is packed into a buffer -//! on the GPU. This keeps the number of texture binds to a minimum. +//! Texture descriptors describe where in the atlas an image is, +//! and how it should sample pixels. These descriptors are packed into a buffer +//! on the GPU. This keeps the number of texture binds to a minimum (one, in most cases). //! //! ## NOTE: //! `Atlas` is a temporary work around until we can use bindless techniques //! on web. //! //! `Atlas` is only available on CPU. Not available in shaders. -use crabslab::{Id, Slab, SlabItem}; -use glam::{UVec2, UVec3, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles}; +use crabslab::SlabItem; -#[cfg(not(target_arch = "spirv"))] +#[cfg(cpu)] mod atlas_image; -#[cfg(not(target_arch = "spirv"))] +#[cfg(cpu)] pub use atlas_image::*; -#[cfg(not(target_arch = "spirv"))] +#[cfg(cpu)] mod cpu; -#[cfg(not(target_arch = "spirv"))] +#[cfg(cpu)] pub use cpu::*; -use spirv_std::{image::Image2d, spirv, Sampler}; -/// Describes various qualities of the atlas, to be used on the GPU. -#[derive(Clone, Copy, core::fmt::Debug, Default, PartialEq, SlabItem)] -pub struct AtlasDescriptor { - pub size: UVec3, -} +pub mod shader; /// Method of addressing the edges of a texture. #[cfg_attr(not(target_arch = "spirv"), derive(Debug))] @@ -37,88 +31,6 @@ pub struct TextureModes { pub t: TextureAddressMode, } -/// A texture inside the atlas. -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Clone, Copy, Default, PartialEq, SlabItem)] -pub struct AtlasTextureDescriptor { - /// The top left offset of texture in the atlas. - pub offset_px: UVec2, - /// The size of the texture in the atlas. - pub size_px: UVec2, - /// The index of the layer within the atlas that this `AtlasTexture `belongs to. - pub layer_index: u32, - /// The index of this frame within the layer. - pub frame_index: u32, - /// Various toggles of texture modes. - pub modes: TextureModes, -} - -impl AtlasTextureDescriptor { - /// Transform the given `uv` coordinates for this texture's address mode - /// and placement in the atlas of the given size. - pub fn uv(&self, mut uv: Vec2, atlas_size: UVec2) -> Vec3 { - uv.x = self.modes.s.wrap(uv.x); - uv.y = self.modes.t.wrap(uv.y); - - // get the pixel index of the uv coordinate in terms of the original image - let mut px_index_s = (uv.x * self.size_px.x as f32) as u32; - let mut px_index_t = (uv.y * self.size_px.y as f32) as u32; - - // convert the pixel index from image to atlas space - px_index_s += self.offset_px.x; - px_index_t += self.offset_px.y; - - let sx = atlas_size.x as f32; - let sy = atlas_size.y as f32; - // normalize the pixels by dividing by the atlas size - let uv_s = px_index_s as f32 / sx; - let uv_t = px_index_t as f32 / sy; - - Vec2::new(uv_s, uv_t).extend(self.layer_index as f32) - } - - /// Constrain the input `clip_pos` to be within the bounds of this texture - /// within its atlas, in texture space. - pub fn constrain_clip_coords_to_texture_space( - &self, - clip_pos: Vec2, - atlas_size: UVec2, - ) -> Vec2 { - // Convert `clip_pos` into uv coords to figure out where in the texture - // this point lives - let input_uv = (clip_pos * Vec2::new(1.0, -1.0) + Vec2::splat(1.0)) * Vec2::splat(0.5); - self.uv(input_uv, atlas_size).xy() - } - - /// Constrain the input `clip_pos` to be within the bounds of this texture - /// within its atlas. - pub fn constrain_clip_coords(&self, clip_pos: Vec2, atlas_size: UVec2) -> Vec2 { - let uv = self.constrain_clip_coords_to_texture_space(clip_pos, atlas_size); - // Convert `uv` back into clip space - (uv * Vec2::new(2.0, 2.0) - Vec2::splat(1.0)) * Vec2::new(1.0, -1.0) - } - - #[cfg(cpu)] - /// Returns the frame of this texture as a [`wgpu::Origin3d`]. - pub fn origin(&self) -> wgpu::Origin3d { - wgpu::Origin3d { - x: self.offset_px.x, - y: self.offset_px.y, - z: self.layer_index, - } - } - - #[cfg(cpu)] - /// Returns the frame of this texture as a [`wgpu::Extent3d`]. - pub fn size_as_extent(&self) -> wgpu::Extent3d { - wgpu::Extent3d { - width: self.size_px.x, - height: self.size_px.y, - depth_or_array_layers: 1, - } - } -} - /// Infinitely wrap the input between 0.0 and 1.0. /// /// Only handles `input` >= 0.0. @@ -200,56 +112,12 @@ impl TextureAddressMode { } } -#[derive(Clone, Copy, Default, SlabItem, core::fmt::Debug)] -pub struct AtlasBlittingDescriptor { - pub atlas_texture_id: Id, - pub atlas_desc_id: Id, -} - -/// Vertex shader for blitting a texture into a the frame of an [`AtlasTexture`]. -/// -/// This is useful for copying textures of unsupported formats, or -/// textures of different sizes. -#[spirv(vertex)] -pub fn atlas_blit_vertex( - #[spirv(vertex_index)] vertex_id: u32, - #[spirv(instance_index)] atlas_blitting_desc_id: Id, - #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] slab: &[u32], - out_uv: &mut Vec2, - #[spirv(position)] out_pos: &mut Vec4, -) { - let i = vertex_id as usize; - *out_uv = crate::math::UV_COORD_QUAD_CCW[i]; - - crate::println!("atlas_blitting_desc_id: {atlas_blitting_desc_id:?}"); - let atlas_blitting_desc = slab.read_unchecked(atlas_blitting_desc_id); - crate::println!("atlas_blitting_desc: {atlas_blitting_desc:?}"); - let atlas_texture = slab.read_unchecked(atlas_blitting_desc.atlas_texture_id); - crate::println!("atlas_texture: {atlas_texture:?}"); - let atlas_desc = slab.read_unchecked(atlas_blitting_desc.atlas_desc_id); - crate::println!("atlas_desc: {atlas_desc:?}"); - let clip_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i]; - crate::println!("clip_pos: {clip_pos:?}"); - *out_pos = atlas_texture - .constrain_clip_coords(clip_pos.xy(), atlas_desc.size.xy()) - .extend(clip_pos.z) - .extend(clip_pos.w); - crate::println!("out_pos: {out_pos}"); -} - -/// Fragment shader for blitting a texture into a frame of an atlas. -#[spirv(fragment)] -pub fn atlas_blit_fragment( - #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, - in_uv: Vec2, - frag_color: &mut Vec4, -) { - *frag_color = texture.sample(*sampler, in_uv); -} - #[cfg(test)] mod test { + use glam::{UVec2, UVec3, Vec2, Vec3Swizzles, Vec4Swizzles}; + + use crate::atlas::shader::AtlasTextureDescriptor; + use super::*; #[test] diff --git a/crates/renderling/src/atlas/cpu.rs b/crates/renderling/src/atlas/cpu.rs index 2ad0a53f..910f8e6e 100644 --- a/crates/renderling/src/atlas/cpu.rs +++ b/crates/renderling/src/atlas/cpu.rs @@ -12,15 +12,15 @@ use image::RgbaImage; use snafu::{prelude::*, OptionExt}; use crate::{ - atlas::{AtlasDescriptor, TextureModes}, + atlas::{ + shader::{AtlasBlittingDescriptor, AtlasDescriptor, AtlasTextureDescriptor}, + TextureModes, + }, bindgroup::ManagedBindGroup, texture::{CopiedTextureBuffer, Texture}, }; -use super::{ - atlas_image::{convert_pixels, AtlasImage}, - AtlasBlittingDescriptor, AtlasTextureDescriptor, -}; +use super::atlas_image::{convert_pixels, AtlasImage}; pub(crate) const ATLAS_SUGGESTED_SIZE: u32 = 2048; pub(crate) const ATLAS_SUGGESTED_LAYERS: u32 = 8; @@ -1005,7 +1005,7 @@ impl AtlasBlitter { #[cfg(test)] mod test { use crate::{ - atlas::{AtlasTextureDescriptor, TextureAddressMode}, + atlas::{shader::AtlasTextureDescriptor, TextureAddressMode}, geometry::Vertex, material::Materials, test::BlockOnFuture, diff --git a/crates/renderling/src/atlas/shader.rs b/crates/renderling/src/atlas/shader.rs new file mode 100644 index 00000000..7ea18ffd --- /dev/null +++ b/crates/renderling/src/atlas/shader.rs @@ -0,0 +1,140 @@ +use crabslab::{Id, Slab, SlabItem}; +use glam::{UVec2, UVec3, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles}; +use spirv_std::{image::Image2d, spirv, Sampler}; + +/// Describes various qualities of the atlas, to be used on the GPU. +#[derive(Clone, Copy, core::fmt::Debug, Default, PartialEq, SlabItem)] +pub struct AtlasDescriptor { + pub size: UVec3, +} + +/// A texture inside the atlas. +#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] +#[derive(Clone, Copy, Default, PartialEq, SlabItem)] +pub struct AtlasTextureDescriptor { + /// The top left offset of texture in the atlas. + pub offset_px: UVec2, + /// The size of the texture in the atlas. + pub size_px: UVec2, + /// The index of the layer within the atlas that this `AtlasTexture `belongs to. + pub layer_index: u32, + /// The index of this frame within the layer. + pub frame_index: u32, + /// Various toggles of texture modes. + pub modes: super::TextureModes, +} + +impl AtlasTextureDescriptor { + /// Transform the given `uv` coordinates for this texture's address mode + /// and placement in the atlas of the given size. + pub fn uv(&self, mut uv: Vec2, atlas_size: UVec2) -> Vec3 { + uv.x = self.modes.s.wrap(uv.x); + uv.y = self.modes.t.wrap(uv.y); + + // get the pixel index of the uv coordinate in terms of the original image + let mut px_index_s = (uv.x * self.size_px.x as f32) as u32; + let mut px_index_t = (uv.y * self.size_px.y as f32) as u32; + + // convert the pixel index from image to atlas space + px_index_s += self.offset_px.x; + px_index_t += self.offset_px.y; + + let sx = atlas_size.x as f32; + let sy = atlas_size.y as f32; + // normalize the pixels by dividing by the atlas size + let uv_s = px_index_s as f32 / sx; + let uv_t = px_index_t as f32 / sy; + + Vec2::new(uv_s, uv_t).extend(self.layer_index as f32) + } + + /// Constrain the input `clip_pos` to be within the bounds of this texture + /// within its atlas, in texture space. + pub fn constrain_clip_coords_to_texture_space( + &self, + clip_pos: Vec2, + atlas_size: UVec2, + ) -> Vec2 { + // Convert `clip_pos` into uv coords to figure out where in the texture + // this point lives + let input_uv = (clip_pos * Vec2::new(1.0, -1.0) + Vec2::splat(1.0)) * Vec2::splat(0.5); + self.uv(input_uv, atlas_size).xy() + } + + /// Constrain the input `clip_pos` to be within the bounds of this texture + /// within its atlas. + pub fn constrain_clip_coords(&self, clip_pos: Vec2, atlas_size: UVec2) -> Vec2 { + let uv = self.constrain_clip_coords_to_texture_space(clip_pos, atlas_size); + // Convert `uv` back into clip space + (uv * Vec2::new(2.0, 2.0) - Vec2::splat(1.0)) * Vec2::new(1.0, -1.0) + } + + #[cfg(cpu)] + /// Returns the frame of this texture as a [`wgpu::Origin3d`]. + pub fn origin(&self) -> wgpu::Origin3d { + wgpu::Origin3d { + x: self.offset_px.x, + y: self.offset_px.y, + z: self.layer_index, + } + } + + #[cfg(cpu)] + /// Returns the frame of this texture as a [`wgpu::Extent3d`]. + pub fn size_as_extent(&self) -> wgpu::Extent3d { + wgpu::Extent3d { + width: self.size_px.x, + height: self.size_px.y, + depth_or_array_layers: 1, + } + } +} + +#[derive(Clone, Copy, Default, SlabItem, core::fmt::Debug)] +pub struct AtlasBlittingDescriptor { + pub atlas_texture_id: Id, + pub atlas_desc_id: Id, +} + +/// Vertex shader for blitting a texture into a the frame of an +/// [`AtlasTextureDescriptor`]. +/// +/// This is useful for copying textures of unsupported formats, or +/// textures of different sizes. +#[spirv(vertex)] +pub fn atlas_blit_vertex( + #[spirv(vertex_index)] vertex_id: u32, + #[spirv(instance_index)] atlas_blitting_desc_id: Id, + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] slab: &[u32], + out_uv: &mut Vec2, + #[spirv(position)] out_pos: &mut Vec4, +) { + let i = vertex_id as usize; + *out_uv = crate::math::UV_COORD_QUAD_CCW[i]; + + crate::println!("atlas_blitting_desc_id: {atlas_blitting_desc_id:?}"); + let atlas_blitting_desc = slab.read_unchecked(atlas_blitting_desc_id); + crate::println!("atlas_blitting_desc: {atlas_blitting_desc:?}"); + let atlas_texture = slab.read_unchecked(atlas_blitting_desc.atlas_texture_id); + crate::println!("atlas_texture: {atlas_texture:?}"); + let atlas_desc = slab.read_unchecked(atlas_blitting_desc.atlas_desc_id); + crate::println!("atlas_desc: {atlas_desc:?}"); + let clip_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i]; + crate::println!("clip_pos: {clip_pos:?}"); + *out_pos = atlas_texture + .constrain_clip_coords(clip_pos.xy(), atlas_desc.size.xy()) + .extend(clip_pos.z) + .extend(clip_pos.w); + crate::println!("out_pos: {out_pos}"); +} + +/// Fragment shader for blitting a texture into a frame of an atlas. +#[spirv(fragment)] +pub fn atlas_blit_fragment( + #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, + #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, + in_uv: Vec2, + frag_color: &mut Vec4, +) { + *frag_color = texture.sample(*sampler, in_uv); +} diff --git a/crates/renderling/src/bloom.rs b/crates/renderling/src/bloom.rs index f753c29b..011ad9f4 100644 --- a/crates/renderling/src/bloom.rs +++ b/crates/renderling/src/bloom.rs @@ -7,4 +7,4 @@ mod cpu; #[cfg(not(target_arch = "spirv"))] pub use cpu::*; -pub mod shaders; +pub mod shader; diff --git a/crates/renderling/src/bloom/shaders.rs b/crates/renderling/src/bloom/shader.rs similarity index 100% rename from crates/renderling/src/bloom/shaders.rs rename to crates/renderling/src/bloom/shader.rs diff --git a/crates/renderling/src/build.rs b/crates/renderling/src/build.rs index 138e0627..0967910b 100644 --- a/crates/renderling/src/build.rs +++ b/crates/renderling/src/build.rs @@ -11,5 +11,6 @@ fn main() { cfg_aliases::cfg_aliases! { cpu: { not(target_arch = "spirv") }, gpu: { target_arch = "spirv" }, + gltf: { feature = "gltf" } } } diff --git a/crates/renderling/src/bvol.rs b/crates/renderling/src/bvol.rs index 7106eb81..734fde4e 100644 --- a/crates/renderling/src/bvol.rs +++ b/crates/renderling/src/bvol.rs @@ -16,7 +16,7 @@ use glam::{Mat4, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles}; #[cfg(gpu)] use spirv_std::num_traits::Float; -use crate::{camera::CameraDescriptor, transform::TransformDescriptor}; +use crate::{camera::shader::CameraDescriptor, transform::shader::TransformDescriptor}; /// Normalize a plane. pub fn normalize_plane(mut plane: Vec4) -> Vec4 { diff --git a/crates/renderling/src/camera.rs b/crates/renderling/src/camera.rs index 84ac88f7..b1c1beb3 100644 --- a/crates/renderling/src/camera.rs +++ b/crates/renderling/src/camera.rs @@ -1,134 +1,12 @@ //! Camera projection, view and utilities. -use crabslab::SlabItem; -use glam::{Mat4, Vec2, Vec3, Vec4}; - -use crate::{bvol::Frustum, math::IsVector}; +use glam::{Mat4, Vec3}; #[cfg(cpu)] mod cpu; #[cfg(cpu)] pub use cpu::*; -/// GPU descriptor of a camera. -/// -/// Used for transforming the stage during rendering. -/// -/// Use [`CameraDescriptor::new`] to create a new camera. -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Default, Clone, Copy, PartialEq, SlabItem)] -pub struct CameraDescriptor { - projection: Mat4, - view: Mat4, - position: Vec3, - frustum: Frustum, - /// Nearest center point on the frustum - z_near_point: Vec3, - /// Furthest center point on the frustum - z_far_point: Vec3, -} - -impl CameraDescriptor { - pub fn new(projection: Mat4, view: Mat4) -> Self { - CameraDescriptor::default().with_projection_and_view(projection, view) - } - - pub fn default_perspective(width: f32, height: f32) -> Self { - let (projection, view) = default_perspective(width, height); - CameraDescriptor::new(projection, view) - } - - pub fn default_ortho2d(width: f32, height: f32) -> Self { - let (projection, view) = default_ortho2d(width, height); - CameraDescriptor::new(projection, view) - } - - pub fn projection(&self) -> Mat4 { - self.projection - } - - pub fn set_projection_and_view(&mut self, projection: Mat4, view: Mat4) { - self.projection = projection; - self.view = view; - self.position = view.inverse().transform_point3(Vec3::ZERO); - let inverse = (projection * view).inverse(); - self.z_near_point = inverse.project_point3(Vec3::ZERO); - self.z_far_point = inverse.project_point3(Vec2::ZERO.extend(1.0)); - self.frustum = Frustum::from_camera(self); - } - - pub fn with_projection_and_view(mut self, projection: Mat4, view: Mat4) -> Self { - self.set_projection_and_view(projection, view); - self - } - - pub fn set_projection(&mut self, projection: Mat4) { - self.set_projection_and_view(projection, self.view); - } - - pub fn with_projection(mut self, projection: Mat4) -> Self { - self.set_projection(projection); - self - } - - pub fn view(&self) -> Mat4 { - self.view - } - - pub fn set_view(&mut self, view: Mat4) { - self.set_projection_and_view(self.projection, view); - } - - pub fn with_view(mut self, view: Mat4) -> Self { - self.set_view(view); - self - } - - pub fn position(&self) -> Vec3 { - self.position - } - - pub fn frustum(&self) -> Frustum { - self.frustum - } - - pub fn view_projection(&self) -> Mat4 { - self.projection * self.view - } - - pub fn near_plane(&self) -> Vec4 { - self.frustum.planes[0] - } - - pub fn far_plane(&self) -> Vec4 { - self.frustum.planes[5] - } - - /// Returns **roughly** the location of the znear plane. - pub fn z_near(&self) -> f32 { - self.z_near_point.distance(self.position) - } - - pub fn z_far(&self) -> f32 { - self.z_far_point.distance(self.position) - } - - pub fn depth(&self) -> f32 { - (self.z_far() - self.z_near()).abs() - } - - /// Returns the normalized forward vector which points in the direction the camera is looking. - pub fn forward(&self) -> Vec3 { - (self.z_far_point - self.z_near_point).alt_norm_or_zero() - } - - pub fn frustum_near_point(&self) -> Vec3 { - self.forward() * self.z_near() - } - - pub fn frustum_far_point(&self) -> Vec3 { - self.forward() * self.z_far() - } -} +pub mod shader; /// Returns the projection and view matrices for a camera with default /// perspective. @@ -137,7 +15,6 @@ impl CameraDescriptor { /// /// ```rust /// use glam::*; -/// use renderling::prelude::*; /// /// let width = 800.0; /// let height = 600.0; @@ -150,7 +27,7 @@ impl CameraDescriptor { /// let target = Vec3::ZERO; /// let up = Vec3::Y; /// let view = Mat4::look_at_rh(eye, target, up); -/// assert_eq!(default_perspective(width, height), (projection, view)); +/// assert_eq!(renderling::camera::default_perspective(width, height), (projection, view)); /// ``` pub fn default_perspective(width: f32, height: f32) -> (Mat4, Mat4) { let projection = perspective(width, height); @@ -199,6 +76,8 @@ pub fn default_ortho2d(width: f32, height: f32) -> (Mat4, Mat4) { #[cfg(test)] mod tests { + use crate::camera::shader::CameraDescriptor; + use super::*; use glam::Vec3; diff --git a/crates/renderling/src/camera/cpu.rs b/crates/renderling/src/camera/cpu.rs index afc9f642..eeecb6a2 100644 --- a/crates/renderling/src/camera/cpu.rs +++ b/crates/renderling/src/camera/cpu.rs @@ -3,6 +3,8 @@ use craballoc::{runtime::IsRuntime, slab::SlabAllocator, value::Hybrid}; use crabslab::Id; +use crate::camera::shader::CameraDescriptor; + use super::*; /// A camera used for transforming the stage during rendering. @@ -42,6 +44,36 @@ impl Camera { self.inner.get() } + /// Set the camera to a default perspective projection and view based + /// on the width and height of the viewport. + pub fn set_default_perspective(&self, width: f32, height: f32) -> &Self { + self.inner + .modify(|d| *d = CameraDescriptor::default_perspective(width, height)); + self + } + + /// Set the camera to a default perspective projection and view based + /// on the width and height of the viewport. + pub fn with_default_perspective(self, width: f32, height: f32) -> Self { + self.set_default_perspective(width, height); + self + } + + /// Set the camera to a default orthographic 2d projection and view based + /// on the width and height of the viewport. + pub fn set_default_ortho2d(&self, width: f32, height: f32) -> &Self { + self.inner + .modify(|d| *d = CameraDescriptor::default_ortho2d(width, height)); + self + } + + /// Set the camera to a default orthographic 2d projection and view based + /// on the width and height of the viewport. + pub fn with_default_ortho2d(self, width: f32, height: f32) -> Self { + self.set_default_ortho2d(width, height); + self + } + /// Set the projection and view matrices of this camera. pub fn set_projection_and_view( &self, @@ -66,7 +98,7 @@ impl Camera { /// Returns the projection and view matrices. pub fn projection_and_view(&self) -> (Mat4, Mat4) { let d = self.inner.get(); - (d.projection, d.view()) + (d.projection(), d.view()) } /// Set the projection matrix of this camera. @@ -83,7 +115,7 @@ impl Camera { /// Returns the projection matrix. pub fn projection(&self) -> Mat4 { - self.inner.get().projection + self.inner.get().projection() } /// Set the view matrix of this camera. diff --git a/crates/renderling/src/camera/shader.rs b/crates/renderling/src/camera/shader.rs new file mode 100644 index 00000000..96f10874 --- /dev/null +++ b/crates/renderling/src/camera/shader.rs @@ -0,0 +1,127 @@ +//! [`CameraDescriptor`] and camera shader utilities. + +use crabslab::SlabItem; +use glam::{Mat4, Vec2, Vec3, Vec4}; + +use crate::{bvol::Frustum, math::IsVector}; + +/// GPU descriptor of a camera. +/// +/// Used for transforming the stage during rendering. +/// +/// Use [`CameraDescriptor::new`] to create a new camera. +#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] +#[derive(Default, Clone, Copy, PartialEq, SlabItem)] +pub struct CameraDescriptor { + projection: Mat4, + view: Mat4, + position: Vec3, + frustum: Frustum, + /// Nearest center point on the frustum + z_near_point: Vec3, + /// Furthest center point on the frustum + z_far_point: Vec3, +} + +impl CameraDescriptor { + pub fn new(projection: Mat4, view: Mat4) -> Self { + CameraDescriptor::default().with_projection_and_view(projection, view) + } + + pub fn default_perspective(width: f32, height: f32) -> Self { + let (projection, view) = super::default_perspective(width, height); + CameraDescriptor::new(projection, view) + } + + pub fn default_ortho2d(width: f32, height: f32) -> Self { + let (projection, view) = super::default_ortho2d(width, height); + CameraDescriptor::new(projection, view) + } + + pub fn projection(&self) -> Mat4 { + self.projection + } + + pub fn set_projection_and_view(&mut self, projection: Mat4, view: Mat4) { + self.projection = projection; + self.view = view; + self.position = view.inverse().transform_point3(Vec3::ZERO); + let inverse = (projection * view).inverse(); + self.z_near_point = inverse.project_point3(Vec3::ZERO); + self.z_far_point = inverse.project_point3(Vec2::ZERO.extend(1.0)); + self.frustum = Frustum::from_camera(self); + } + + pub fn with_projection_and_view(mut self, projection: Mat4, view: Mat4) -> Self { + self.set_projection_and_view(projection, view); + self + } + + pub fn set_projection(&mut self, projection: Mat4) { + self.set_projection_and_view(projection, self.view); + } + + pub fn with_projection(mut self, projection: Mat4) -> Self { + self.set_projection(projection); + self + } + + pub fn view(&self) -> Mat4 { + self.view + } + + pub fn set_view(&mut self, view: Mat4) { + self.set_projection_and_view(self.projection, view); + } + + pub fn with_view(mut self, view: Mat4) -> Self { + self.set_view(view); + self + } + + pub fn position(&self) -> Vec3 { + self.position + } + + pub fn frustum(&self) -> Frustum { + self.frustum + } + + pub fn view_projection(&self) -> Mat4 { + self.projection * self.view + } + + pub fn near_plane(&self) -> Vec4 { + self.frustum.planes[0] + } + + pub fn far_plane(&self) -> Vec4 { + self.frustum.planes[5] + } + + /// Returns **roughly** the location of the znear plane. + pub fn z_near(&self) -> f32 { + self.z_near_point.distance(self.position) + } + + pub fn z_far(&self) -> f32 { + self.z_far_point.distance(self.position) + } + + pub fn depth(&self) -> f32 { + (self.z_far() - self.z_near()).abs() + } + + /// Returns the normalized forward vector which points in the direction the camera is looking. + pub fn forward(&self) -> Vec3 { + (self.z_far_point - self.z_near_point).alt_norm_or_zero() + } + + pub fn frustum_near_point(&self) -> Vec3 { + self.forward() * self.z_near() + } + + pub fn frustum_far_point(&self) -> Vec3 { + self.forward() * self.z_far() + } +} diff --git a/crates/renderling/src/context.rs b/crates/renderling/src/context.rs index 1d175329..ad63b663 100644 --- a/crates/renderling/src/context.rs +++ b/crates/renderling/src/context.rs @@ -1,4 +1,8 @@ -//! Rendering context initialization and frame management. +//! Rendering context initialization +//! +//! This module contains [`Context`] initialization and frame management. +//! This module provides the setup and management of rendering targets, +//! frames, and surface configurations. use core::fmt::Debug; use std::{ ops::Deref, @@ -16,6 +20,7 @@ use crate::{ pub use craballoc::runtime::WgpuRuntime; +/// Represents the internal structure of a render target, which can either be a surface or a texture. pub(crate) enum RenderTargetInner { Surface { surface: wgpu::Surface<'static>, @@ -27,13 +32,12 @@ pub(crate) enum RenderTargetInner { } #[repr(transparent)] -/// Either a surface or a texture. -/// -/// Will be a surface if the context was created with a window or canvas. -/// -/// Will be a texture if the context is headless. +/// Represents a render target that can either be a surface or a texture. +/// It will be a surface if the context was created with a window or canvas, +/// and a texture if the context is headless. pub struct RenderTarget(pub(crate) RenderTargetInner); +/// Converts a `wgpu::Texture` into a `RenderTarget`. impl From for RenderTarget { fn from(value: wgpu::Texture) -> Self { RenderTarget(RenderTargetInner::Texture { @@ -43,6 +47,7 @@ impl From for RenderTarget { } impl RenderTarget { + /// Resizes the render target to the specified width and height using the provided device. pub fn resize(&mut self, width: u32, height: u32, device: &wgpu::Device) { match &mut self.0 { RenderTargetInner::Surface { @@ -75,6 +80,7 @@ impl RenderTarget { } } + /// Returns the format of the render target. pub fn format(&self) -> wgpu::TextureFormat { match &self.0 { RenderTargetInner::Surface { surface_config, .. } => surface_config.format, @@ -82,6 +88,7 @@ impl RenderTarget { } } + /// Checks if the render target is headless (i.e., a texture). pub fn is_headless(&self) -> bool { match &self.0 { RenderTargetInner::Surface { .. } => false, @@ -89,7 +96,7 @@ impl RenderTarget { } } - /// Return the underlying target as a texture, if possible. + /// Returns the underlying target as a texture, if possible. pub fn as_texture(&self) -> Option<&wgpu::Texture> { match &self.0 { RenderTargetInner::Surface { .. } => None, @@ -97,6 +104,7 @@ impl RenderTarget { } } + /// Returns the size of the render target as a `UVec2`. pub fn get_size(&self) -> UVec2 { match &self.0 { RenderTargetInner::Surface { @@ -113,6 +121,7 @@ impl RenderTarget { #[derive(Debug, Snafu)] #[snafu(visibility(pub(crate)))] +/// Represents errors that can occur within the rendering context. pub enum ContextError { #[snafu(display("missing surface texture: {}", source))] Surface { source: wgpu::SurfaceError }, @@ -144,6 +153,7 @@ impl Deref for FrameTextureView { } } +/// Represents the surface of a frame, which can either be a surface texture or a texture. pub(crate) enum FrameSurface { Surface(wgpu::SurfaceTexture), Texture(Arc), @@ -166,6 +176,7 @@ impl Frame { } } + /// Returns a view of the current frame's texture. pub fn view(&self) -> wgpu::TextureView { let texture = self.texture(); let format = texture.format().add_srgb_suffix(); @@ -176,6 +187,7 @@ impl Frame { }) } + /// Copies the current frame to a buffer for further processing. pub fn copy_to_buffer(&self, width: u32, height: u32) -> CopiedTextureBuffer { let dimensions = BufferDimensions::new(4, 1, width as usize, height as usize); // The output buffer lets us retrieve the self as an array @@ -224,7 +236,7 @@ impl Frame { UVec2::new(s.width, s.height) } - /// Read the current frame buffer into an image. + /// Reads the current frame buffer into an image. /// /// This should be called after rendering, before presentation. /// Good for getting headless screen grabs. @@ -245,13 +257,11 @@ impl Frame { Ok(img) } - /// Read the frame into an image. + /// Reads the frame into an image in a sRGB color space. /// /// This should be called after rendering, before presentation. /// Good for getting headless screen grabs. /// - /// The resulting image will be in a sRGB color space. - /// /// ## Note /// This operation can take a long time, depending on how big the screen is. pub async fn read_srgb_image(&self) -> Result { @@ -260,13 +270,11 @@ impl Frame { log::trace!("read image has the format: {:?}", buffer.format); buffer.into_srgba(&self.runtime.device).await } - /// Read the frame into an image. + /// Reads the frame into an image in a linear color space. /// /// This should be called after rendering, before presentation. /// Good for getting headless screen grabs. /// - /// The resulting image will be in a linear color space. - /// /// ## Note /// This operation can take a long time, depending on how big the screen is. pub async fn read_linear_image(&self) -> Result { @@ -275,9 +283,8 @@ impl Frame { buffer.into_linear_rgba(&self.runtime.device).await } - /// If self is `TargetFrame::Surface` this presents the surface frame. - /// - /// If self is a `TargetFrame::Texture` this is a noop. + /// Presents the surface frame if the frame is a `TargetFrame::Surface`. + /// If the frame is a `TargetFrame::Texture`, this is a no-op. pub fn present(self) { match self.surface { FrameSurface::Surface(s) => s.present(), @@ -318,6 +325,7 @@ impl AsRef for Context { } impl Context { + /// Creates a new `Context` with the specified target, adapter, device, and queue. pub fn new( target: RenderTarget, adapter: impl Into>, @@ -356,6 +364,7 @@ impl Context { } } + /// Attempts to create a new headless `Context` with the specified width, height, and backends. pub async fn try_new_headless( width: u32, height: u32, @@ -368,6 +377,7 @@ impl Context { Ok(Self::new(target, adapter, device, queue)) } + /// Attempts to create a new `Context` with a surface, using the specified width, height, backends, and window. pub async fn try_new_with_surface( width: u32, height: u32, @@ -396,12 +406,12 @@ impl Context { .unwrap() } - /// Create a new headless renderer. + /// Creates a new headless renderer. /// - /// Immediately proxies to [`Context::try_new_headless`] and unwraps. + /// Immediately proxies to `Context::try_new_headless` and unwraps. /// /// ## Panics - /// This function will panic if an adapter cannot be found. For example this + /// This function will panic if an adapter cannot be found. For example, this /// would happen on machines without a GPU. pub async fn headless(width: u32, height: u32) -> Self { let result = Self::try_new_headless(width, height, None).await; @@ -420,12 +430,13 @@ impl Context { self.render_target.get_size() } + /// Sets the size of the render target. pub fn set_size(&mut self, size: UVec2) { self.render_target .resize(size.x, size.y, &self.runtime.device); } - /// Convenience method for creating textures from an image buffer. + /// Creates a texture from an image buffer. pub fn create_texture

( &self, label: Option<&str>, @@ -445,6 +456,7 @@ impl Context { ) } + /// Creates a `Texture` from a `wgpu::Texture` and an optional sampler. pub fn texture_from_wgpu_tex( &self, texture: impl Into>, @@ -453,38 +465,44 @@ impl Context { Texture::from_wgpu_tex(self.get_device(), texture, sampler, None) } + /// Returns a reference to the `WgpuRuntime`. pub fn runtime(&self) -> &WgpuRuntime { &self.runtime } + /// Returns a reference to the `wgpu::Device`. pub fn get_device(&self) -> &wgpu::Device { &self.runtime.device } + /// Returns a reference to the `wgpu::Queue`. pub fn get_queue(&self) -> &wgpu::Queue { &self.runtime.queue } + /// Returns a reference to the `wgpu::Adapter`. pub fn get_adapter(&self) -> &wgpu::Adapter { &self.adapter } - /// Returns a the adapter in an owned wrapper. + /// Returns the adapter in an owned wrapper. pub fn get_adapter_owned(&self) -> Arc { self.adapter.clone() } + /// Returns a reference to the `RenderTarget`. pub fn get_render_target(&self) -> &RenderTarget { &self.render_target } - /// Get the next frame from the render target. + /// Gets the next frame from the render target. /// /// A surface context (window or canvas) will return the next swapchain /// texture. /// /// A headless context will return the underlying headless texture. /// + /// ## Errors /// Errs if the render target is a surface and there was an error getting /// the next swapchain texture. This can happen if the frame has already /// been acquired. @@ -503,7 +521,7 @@ impl Context { }) } - /// Set the default texture size for the material atlas. + /// Sets the default texture size for the material atlas. /// /// * Width is `size.x` and must be a power of two. /// * Height is `size.y`, must match `size.x` and must be a power of two. @@ -520,7 +538,7 @@ impl Context { self } - /// Set the default texture size for the material atlas. + /// Sets the default texture size for the material atlas. /// /// * Width is `size.x` and must be a power of two. /// * Height is `size.y`, must match `size.x` and must be a power of two. @@ -533,7 +551,7 @@ impl Context { self } - /// Set the default texture size for the shadow mapping atlas. + /// Sets the default texture size for the shadow mapping atlas. /// /// * Width is `size.x` and must be a power of two. /// * Height is `size.y`, must match `size.x` and must be a power of two. @@ -550,7 +568,7 @@ impl Context { self } - /// Set the default texture size for the shadow mapping atlas. + /// Sets the default texture size for the shadow mapping atlas. /// /// * Width is `size.x` and must be a power of two. /// * Height is `size.y`, must match `size.x` and must be a power of two. @@ -563,7 +581,7 @@ impl Context { self } - /// Set the use of direct drawing. + /// Sets the use of direct drawing. /// /// Default is **false**. /// @@ -573,7 +591,7 @@ impl Context { self.stage_config.write().unwrap().use_compute_culling = !use_direct_drawing; } - /// Set the use of direct drawing. + /// Sets the use of direct drawing. /// /// Default is **false**. /// @@ -584,16 +602,17 @@ impl Context { self } + /// Returns whether direct drawing is used. pub fn get_use_direct_draw(&self) -> bool { !self.stage_config.read().unwrap().use_compute_culling } - /// Create and return a new [`Stage`] renderer. + /// Creates and returns a new [`Stage`] renderer. pub fn new_stage(&self) -> Stage { Stage::new(self) } - /// Create and return a new [`Ui`] renderer. + /// Creates and returns a new [`Ui`] renderer. pub fn new_ui(&self) -> Ui { Ui::new(self) } diff --git a/crates/renderling/src/convolution.rs b/crates/renderling/src/convolution.rs index 1753bfa8..a38f313a 100644 --- a/crates/renderling/src/convolution.rs +++ b/crates/renderling/src/convolution.rs @@ -12,7 +12,7 @@ use spirv_std::{ #[allow(unused_imports)] use spirv_std::num_traits::Float; -use crate::{camera::CameraDescriptor, math::IsVector}; +use crate::{camera::shader::CameraDescriptor, math::IsVector}; // Allow manual bit rotation because this code is `no_std`. #[allow(clippy::manual_rotate)] diff --git a/crates/renderling/src/cubemap.rs b/crates/renderling/src/cubemap.rs index c9c7197c..c58d6ad5 100644 --- a/crates/renderling/src/cubemap.rs +++ b/crates/renderling/src/cubemap.rs @@ -4,167 +4,19 @@ //! //! For more info see: //! * -use crabslab::{Array, Id, Slab}; -use glam::{Mat4, Vec2, Vec3, Vec3Swizzles, Vec4}; -use spirv_std::{num_traits::Zero, spirv}; #[cfg(cpu)] mod cpu; #[cfg(cpu)] pub use cpu::*; -use crate::{ - atlas::{AtlasDescriptor, AtlasTextureDescriptor}, - math::{IsSampler, Sample2dArray}, -}; - -/// Vertex shader for testing cubemap sampling. -#[spirv(vertex)] -pub fn cubemap_sampling_test_vertex( - #[spirv(vertex_index)] vertex_index: u32, - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] uv: &Vec3, - out_uv: &mut Vec3, - #[spirv(position)] out_clip_coords: &mut Vec4, -) { - let vertex_index = vertex_index as usize % 6; - *out_clip_coords = crate::math::CLIP_SPACE_COORD_QUAD_CCW[vertex_index]; - *out_uv = *uv; -} - -/// Vertex shader for testing cubemap sampling. -#[spirv(fragment)] -pub fn cubemap_sampling_test_fragment( - #[spirv(descriptor_set = 0, binding = 1)] cubemap: &spirv_std::image::Cubemap, - #[spirv(descriptor_set = 0, binding = 2)] sampler: &spirv_std::Sampler, - in_uv: Vec3, - frag_color: &mut Vec4, -) { - *frag_color = cubemap.sample(*sampler, in_uv); -} - -/// Represents one side of a cubemap. -/// -/// Assumes the camera is at the origin, inside the cube, with -/// a left-handed coordinate system (+Z going into the screen). -#[derive(Clone, Copy)] -pub struct CubemapFaceDirection { - /// Where is the camera - pub eye: Vec3, - /// Where is the camera looking - pub dir: Vec3, - /// Which direction is up - pub up: Vec3, -} - -impl CubemapFaceDirection { - pub const X: Self = Self { - eye: Vec3::ZERO, - dir: Vec3::X, - up: Vec3::Y, - }; - pub const NEG_X: Self = Self { - eye: Vec3::ZERO, - dir: Vec3::NEG_X, - up: Vec3::Y, - }; - - pub const Y: Self = Self { - eye: Vec3::ZERO, - dir: Vec3::Y, - up: Vec3::NEG_Z, - }; - pub const NEG_Y: Self = Self { - eye: Vec3::ZERO, - dir: Vec3::NEG_Y, - up: Vec3::Z, - }; - - pub const Z: Self = Self { - eye: Vec3::ZERO, - dir: Vec3::Z, - up: Vec3::Y, - }; - pub const NEG_Z: Self = Self { - eye: Vec3::ZERO, - dir: Vec3::NEG_Z, - up: Vec3::Y, - }; - - pub const FACES: [Self; 6] = [ - CubemapFaceDirection::X, - CubemapFaceDirection::NEG_X, - CubemapFaceDirection::Y, - CubemapFaceDirection::NEG_Y, - CubemapFaceDirection::Z, - CubemapFaceDirection::NEG_Z, - ]; - - pub fn right(&self) -> Vec3 { - -self.dir.cross(self.up) - } - - /// The view from _inside_ the cube. - pub fn view(&self) -> Mat4 { - Mat4::look_at_lh(self.eye, self.eye + self.dir, self.up) - } -} - -pub struct CubemapDescriptor { - atlas_descriptor_id: Id, - faces: Array, -} - -impl CubemapDescriptor { - /// Return the face index and UV coordinates that can be used to sample - /// a cubemap from the given directional coordinate. - pub fn get_face_index_and_uv(coord: Vec3) -> (usize, Vec2) { - let abs_x = coord.x.abs(); - let abs_y = coord.y.abs(); - let abs_z = coord.z.abs(); - - let (face_index, uv) = if abs_x >= abs_y && abs_x >= abs_z { - if coord.x > 0.0 { - (0, Vec2::new(-coord.z, -coord.y) / abs_x) - } else { - (1, Vec2::new(coord.z, -coord.y) / abs_x) - } - } else if abs_y >= abs_x && abs_y >= abs_z { - if coord.y > 0.0 { - (2, Vec2::new(coord.x, coord.z) / abs_y) - } else { - (3, Vec2::new(coord.x, -coord.z) / abs_y) - } - } else if coord.z > 0.0 { - (4, Vec2::new(coord.x, -coord.y) / abs_z) - } else { - (5, Vec2::new(-coord.x, -coord.y) / abs_z) - }; - - (face_index, (uv + Vec2::ONE) / 2.0) - } - - /// Sample the cubemap with a directional coordinate. - pub fn sample(&self, coord: Vec3, slab: &[u32], atlas: &A, sampler: &S) -> Vec4 - where - A: Sample2dArray, - S: IsSampler, - { - let coord = if coord.length().is_zero() { - Vec3::X - } else { - coord.normalize() - }; - let (face_index, uv) = Self::get_face_index_and_uv(coord); - let atlas_image = slab.read_unchecked(self.faces.at(face_index)); - let atlas_desc = slab.read_unchecked(self.atlas_descriptor_id); - let uv = atlas_image.uv(uv, atlas_desc.size.xy()); - atlas.sample_by_lod(*sampler, uv, 0.0) - } -} +pub mod shader; #[cfg(test)] mod test { - use super::*; + use glam::{Vec2, Vec3}; + + use crate::cubemap::shader::{CubemapDescriptor, CubemapFaceDirection}; #[test] fn cubemap_right() { diff --git a/crates/renderling/src/cubemap/cpu.rs b/crates/renderling/src/cubemap/cpu.rs index 10542b4b..1b7af066 100644 --- a/crates/renderling/src/cubemap/cpu.rs +++ b/crates/renderling/src/cubemap/cpu.rs @@ -9,7 +9,7 @@ use crate::{ texture::Texture, }; -use super::{CubemapDescriptor, CubemapFaceDirection}; +use super::shader::{CubemapDescriptor, CubemapFaceDirection}; pub fn cpu_sample_cubemap(cubemap: &[image::DynamicImage; 6], coord: Vec3) -> Vec4 { let coord = coord.normalize_or(Vec3::X); diff --git a/crates/renderling/src/cubemap/shader.rs b/crates/renderling/src/cubemap/shader.rs new file mode 100644 index 00000000..c77a1bff --- /dev/null +++ b/crates/renderling/src/cubemap/shader.rs @@ -0,0 +1,191 @@ +use crabslab::{Array, Id, Slab}; +use glam::{Mat4, Vec2, Vec3, Vec3Swizzles, Vec4}; +use spirv_std::{num_traits::Zero, spirv}; + +use crate::{ + atlas::shader::{AtlasDescriptor, AtlasTextureDescriptor}, + math::{IsSampler, Sample2dArray}, +}; + +/// Vertex shader for testing cubemap sampling. +#[spirv(vertex)] +pub fn cubemap_sampling_test_vertex( + #[spirv(vertex_index)] vertex_index: u32, + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] uv: &Vec3, + out_uv: &mut Vec3, + #[spirv(position)] out_clip_coords: &mut Vec4, +) { + let vertex_index = vertex_index as usize % 6; + *out_clip_coords = crate::math::CLIP_SPACE_COORD_QUAD_CCW[vertex_index]; + *out_uv = *uv; +} + +/// Vertex shader for testing cubemap sampling. +#[spirv(fragment)] +pub fn cubemap_sampling_test_fragment( + #[spirv(descriptor_set = 0, binding = 1)] cubemap: &spirv_std::image::Cubemap, + #[spirv(descriptor_set = 0, binding = 2)] sampler: &spirv_std::Sampler, + in_uv: Vec3, + frag_color: &mut Vec4, +) { + *frag_color = cubemap.sample(*sampler, in_uv); +} + +/// Represents one side of a cubemap. +/// +/// Assumes the camera is at the origin, inside the cube, with +/// a left-handed coordinate system (+Z going into the screen). +#[derive(Clone, Copy)] +pub struct CubemapFaceDirection { + /// Where is the camera + pub eye: Vec3, + /// Where is the camera looking + pub dir: Vec3, + /// Which direction is up + pub up: Vec3, +} + +impl CubemapFaceDirection { + pub const X: Self = Self { + eye: Vec3::ZERO, + dir: Vec3::X, + up: Vec3::Y, + }; + pub const NEG_X: Self = Self { + eye: Vec3::ZERO, + dir: Vec3::NEG_X, + up: Vec3::Y, + }; + + pub const Y: Self = Self { + eye: Vec3::ZERO, + dir: Vec3::Y, + up: Vec3::NEG_Z, + }; + pub const NEG_Y: Self = Self { + eye: Vec3::ZERO, + dir: Vec3::NEG_Y, + up: Vec3::Z, + }; + + pub const Z: Self = Self { + eye: Vec3::ZERO, + dir: Vec3::Z, + up: Vec3::Y, + }; + pub const NEG_Z: Self = Self { + eye: Vec3::ZERO, + dir: Vec3::NEG_Z, + up: Vec3::Y, + }; + + pub const FACES: [Self; 6] = [ + CubemapFaceDirection::X, + CubemapFaceDirection::NEG_X, + CubemapFaceDirection::Y, + CubemapFaceDirection::NEG_Y, + CubemapFaceDirection::Z, + CubemapFaceDirection::NEG_Z, + ]; + + pub fn right(&self) -> Vec3 { + -self.dir.cross(self.up) + } + + /// The view from _inside_ the cube. + pub fn view(&self) -> Mat4 { + Mat4::look_at_lh(self.eye, self.eye + self.dir, self.up) + } +} + +pub struct CubemapDescriptor { + atlas_descriptor_id: Id, + faces: Array, +} + +impl CubemapDescriptor { + /// Return the face index and UV coordinates that can be used to sample + /// a cubemap from the given directional coordinate. + pub fn get_face_index_and_uv(coord: Vec3) -> (usize, Vec2) { + let abs_x = coord.x.abs(); + let abs_y = coord.y.abs(); + let abs_z = coord.z.abs(); + + let (face_index, uv) = if abs_x >= abs_y && abs_x >= abs_z { + if coord.x > 0.0 { + (0, Vec2::new(-coord.z, -coord.y) / abs_x) + } else { + (1, Vec2::new(coord.z, -coord.y) / abs_x) + } + } else if abs_y >= abs_x && abs_y >= abs_z { + if coord.y > 0.0 { + (2, Vec2::new(coord.x, coord.z) / abs_y) + } else { + (3, Vec2::new(coord.x, -coord.z) / abs_y) + } + } else if coord.z > 0.0 { + (4, Vec2::new(coord.x, -coord.y) / abs_z) + } else { + (5, Vec2::new(-coord.x, -coord.y) / abs_z) + }; + + (face_index, (uv + Vec2::ONE) / 2.0) + } + + /// Sample the cubemap with a directional coordinate. + pub fn sample(&self, coord: Vec3, slab: &[u32], atlas: &A, sampler: &S) -> Vec4 + where + A: Sample2dArray, + S: IsSampler, + { + let coord = if coord.length().is_zero() { + Vec3::X + } else { + coord.normalize() + }; + let (face_index, uv) = Self::get_face_index_and_uv(coord); + let atlas_image = slab.read_unchecked(self.faces.at(face_index)); + let atlas_desc = slab.read_unchecked(self.atlas_descriptor_id); + let uv = atlas_image.uv(uv, atlas_desc.size.xy()); + atlas.sample_by_lod(*sampler, uv, 0.0) + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn cubemap_right() { + assert_eq!(Vec3::NEG_Z, CubemapFaceDirection::X.right()); + assert_eq!(Vec3::Z, CubemapFaceDirection::NEG_X.right()); + assert_eq!(Vec3::X, CubemapFaceDirection::Y.right()); + assert_eq!(Vec3::X, CubemapFaceDirection::NEG_Y.right()); + assert_eq!(Vec3::X, CubemapFaceDirection::Z.right()); + assert_eq!(Vec3::NEG_X, CubemapFaceDirection::NEG_Z.right()); + + assert_eq!( + (1, Vec2::new(0.0, 1.0)), + CubemapDescriptor::get_face_index_and_uv(Vec3::NEG_ONE) + ); + } + + #[test] + fn cubemap_face_index() { + let center = Vec2::splat(0.5); + let data = [ + (Vec3::X, 0, center), + (Vec3::NEG_X, 1, center), + (Vec3::Y, 2, center), + (Vec3::NEG_Y, 3, center), + (Vec3::Z, 4, center), + (Vec3::NEG_Z, 5, center), + ]; + for (coord, expected_face_index, expected_uv) in data { + let (seen_face_index, seen_uv) = CubemapDescriptor::get_face_index_and_uv(coord); + dbg!((coord, seen_face_index, seen_uv)); + assert_eq!(expected_face_index, seen_face_index); + assert_eq!(expected_uv, seen_uv); + } + } +} diff --git a/crates/renderling/src/cull.rs b/crates/renderling/src/cull.rs index 832e4117..84f921af 100644 --- a/crates/renderling/src/cull.rs +++ b/crates/renderling/src/cull.rs @@ -2,244 +2,10 @@ //! //! Frustum culling as explained in //! [the vulkan guide](https://vkguide.dev/docs/gpudriven/compute_culling/). -use crabslab::{Array, Id, Slab, SlabItem}; -use glam::{UVec2, UVec3, Vec2, Vec3Swizzles}; -#[allow(unused_imports)] -use spirv_std::num_traits::Float; -use spirv_std::{ - arch::IndexUnchecked, - image::{sample_with, Image, ImageWithMethods}, - spirv, -}; - -use crate::{draw::DrawIndirectArgs, geometry::GeometryDescriptor, stage::PrimitiveDescriptor}; #[cfg(not(target_arch = "spirv"))] mod cpu; #[cfg(not(target_arch = "spirv"))] pub use cpu::*; -#[spirv(compute(threads(16)))] -pub fn compute_culling( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] stage_slab: &[u32], - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] depth_pyramid_slab: &[u32], - #[spirv(storage_buffer, descriptor_set = 0, binding = 2)] args: &mut [DrawIndirectArgs], - #[spirv(global_invocation_id)] global_id: UVec3, -) { - let gid = global_id.x as usize; - if gid >= args.len() { - return; - } - - crate::println!("gid: {gid}"); - // Get the draw arg - let arg = unsafe { args.index_unchecked_mut(gid) }; - // Get the primitive using the draw arg's primitive id - let primitive_id = Id::::new(arg.first_instance); - let primitive = stage_slab.read_unchecked(primitive_id); - crate::println!("primitive: {primitive_id:?}"); - - arg.vertex_count = primitive.get_vertex_count(); - arg.instance_count = if primitive.visible { 1 } else { 0 }; - - if primitive.bounds.radius == 0.0 { - crate::println!("primitive bounding radius is zero, cannot cull"); - return; - } - - let config: GeometryDescriptor = stage_slab.read(Id::new(0)); - if !config.perform_frustum_culling { - return; - } - - let camera = stage_slab.read(config.camera_id); - let model = stage_slab.read(primitive.transform_id); - // Compute frustum culling, and then occlusion culling, if need be - let (primitive_is_inside_frustum, sphere_in_world_coords) = - primitive.bounds.is_inside_camera_view(&camera, model); - - if primitive_is_inside_frustum { - arg.instance_count = 1; - crate::println!("primitive is inside frustum"); - crate::println!("znear: {}", camera.frustum().planes[0]); - crate::println!(" zfar: {}", camera.frustum().planes[5]); - if !config.perform_occlusion_culling { - return; - } - - // Compute occlusion culling using the hierachical z-buffer. - let hzb_desc = depth_pyramid_slab.read_unchecked::(0u32.into()); - let viewport_size = Vec2::new(hzb_desc.size.x as f32, hzb_desc.size.y as f32); - let sphere_aabb = sphere_in_world_coords.project_onto_viewport(&camera, viewport_size); - crate::println!("sphere_aabb: {sphere_aabb:#?}"); - - let size_in_pixels = sphere_aabb.max.xy() - sphere_aabb.min.xy(); - let size_in_pixels = if size_in_pixels.x > size_in_pixels.y { - size_in_pixels.x - } else { - size_in_pixels.y - }; - crate::println!("primitive size in pixels: {size_in_pixels}"); - - let mip_level = size_in_pixels.log2().floor() as u32; - let max_mip_level = hzb_desc.mip.len() as u32 - 1; - let mip_level = if mip_level > max_mip_level { - crate::println!("mip_level maxed out at {mip_level}, setting to {max_mip_level}"); - max_mip_level - } else { - mip_level - }; - crate::println!( - "selected mip level: {mip_level} {}x{}", - viewport_size.x as u32 >> mip_level, - viewport_size.y as u32 >> mip_level - ); - - let center = sphere_aabb.center().xy(); - crate::println!("center: {center}"); - - let x = center.x.round() as u32 >> mip_level; - let y = center.y.round() as u32 >> mip_level; - crate::println!("mip (x, y): ({x}, {y})"); - - let depth_id = hzb_desc.id_of_depth(mip_level, UVec2::new(x, y), depth_pyramid_slab); - let depth_in_hzb = depth_pyramid_slab.read_unchecked(depth_id); - crate::println!("depth_in_hzb: {depth_in_hzb}"); - - let depth_of_sphere = sphere_aabb.min.z; - crate::println!("depth_of_sphere: {depth_of_sphere}"); - - let primitive_is_behind_something = depth_of_sphere > depth_in_hzb; - let primitive_surrounds_camera = depth_of_sphere > 1.0; - - if primitive_is_behind_something || primitive_surrounds_camera { - crate::println!("CULLED"); - arg.instance_count = 0; - } - } else { - arg.instance_count = 0; - } -} - -/// A hierarchichal depth buffer. -/// -/// AKA HZB -#[derive(Clone, Copy, Default, SlabItem)] -pub struct DepthPyramidDescriptor { - /// Size of the top layer mip. - size: UVec2, - /// Current mip level. - /// - /// This will be updated for each run of the downsample compute shader. - mip_level: u32, - /// Pointer to the mip data. - /// - /// This points to the depth data at each mip level. - /// - /// The depth data itself is somewhere else in the slab. - mip: Array>, -} - -impl DepthPyramidDescriptor { - fn should_skip_invocation(&self, global_invocation: UVec3) -> bool { - let current_size = self.size >> self.mip_level; - !(global_invocation.x < current_size.x && global_invocation.y < current_size.y) - } - - #[cfg(test)] - fn size_at(&self, mip_level: u32) -> UVec2 { - UVec2::new(self.size.x >> mip_level, self.size.y >> mip_level) - } - - /// Return the [`Id`] of the depth at the given `mip_level` and coordinate. - fn id_of_depth(&self, mip_level: u32, coord: UVec2, slab: &[u32]) -> Id { - let mip_array = slab.read(self.mip.at(mip_level as usize)); - let width_at_mip = self.size.x >> mip_level; - let index = coord.y * width_at_mip + coord.x; - mip_array.at(index as usize) - } -} - -pub type DepthImage2d = Image!(2D, type=f32, sampled, depth); -pub type DepthImage2dMultisampled = Image!(2D, type=f32, sampled, depth, multisampled); - -/// Copies a depth texture to the top mip of a pyramid of mips. -/// -/// It is assumed that a [`DepthPyramidDescriptor`] is stored at index `0` in -/// the given slab. -#[spirv(compute(threads(16, 16, 1)))] -pub fn compute_copy_depth_to_pyramid( - #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] slab: &mut [u32], - #[spirv(descriptor_set = 0, binding = 1)] depth_texture: &DepthImage2d, - #[spirv(global_invocation_id)] global_id: UVec3, -) { - let desc = slab.read_unchecked::(0u32.into()); - if desc.should_skip_invocation(global_id) { - return; - } - - let depth = depth_texture - .fetch_with(global_id.xy(), sample_with::lod(0)) - .x; - let dest_id = desc.id_of_depth(0, global_id.xy(), slab); - slab.write(dest_id, &depth); -} - -/// Copies a depth texture to the top mip of a pyramid of mips. -/// -/// It is assumed that a [`DepthPyramidDescriptor`] is stored at index `0` in -/// the given slab. -#[spirv(compute(threads(16, 16, 1)))] -pub fn compute_copy_depth_to_pyramid_multisampled( - #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] slab: &mut [u32], - #[spirv(descriptor_set = 0, binding = 1)] depth_texture: &DepthImage2dMultisampled, - #[spirv(global_invocation_id)] global_id: UVec3, -) { - let desc = slab.read_unchecked::(0u32.into()); - if desc.should_skip_invocation(global_id) { - return; - } - - let depth = depth_texture - .fetch_with(global_id.xy(), sample_with::sample_index(0)) - .x; - let dest_id = desc.id_of_depth(0, global_id.xy(), slab); - slab.write(dest_id, &depth); -} - -/// Downsample from `DepthPyramidDescriptor::mip_level-1` into -/// `DepthPyramidDescriptor::mip_level`. -/// -/// It is assumed that a [`DepthPyramidDescriptor`] is stored at index `0` in -/// the given slab. -/// -/// The `DepthPyramidDescriptor`'s `mip_level` field will point to that of the -/// mip level being downsampled to (the mip level being written into). -/// -/// This shader should be called in a loop from from `1..mip_count`. -#[spirv(compute(threads(16, 16, 1)))] -pub fn compute_downsample_depth_pyramid( - #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] slab: &mut [u32], - #[spirv(global_invocation_id)] global_id: UVec3, -) { - let desc = slab.read_unchecked::(0u32.into()); - if desc.should_skip_invocation(global_id) { - return; - } - // Sample the texel. - // - // The texel will look like this: - // - // a b - // c d - let a_coord = global_id.xy() * 2; - let a = slab.read(desc.id_of_depth(desc.mip_level - 1, a_coord, slab)); - let b = slab.read(desc.id_of_depth(desc.mip_level - 1, a_coord + UVec2::new(1, 0), slab)); - let c = slab.read(desc.id_of_depth(desc.mip_level - 1, a_coord + UVec2::new(0, 1), slab)); - let d = slab.read(desc.id_of_depth(desc.mip_level - 1, a_coord + UVec2::new(1, 1), slab)); - // Take the maximum depth of the region (max depth means furthest away) - let depth_value = a.max(b).max(c).max(d); - // Write the texel in the next mip - let depth_id = desc.id_of_depth(desc.mip_level, global_id.xy(), slab); - slab.write(depth_id, &depth_value); -} +pub mod shader; diff --git a/crates/renderling/src/cull/cpu.rs b/crates/renderling/src/cull/cpu.rs index ec279a7e..da33337a 100644 --- a/crates/renderling/src/cull/cpu.rs +++ b/crates/renderling/src/cull/cpu.rs @@ -11,7 +11,7 @@ use snafu::{OptionExt, Snafu}; use crate::{bindgroup::ManagedBindGroup, texture::Texture}; -use super::DepthPyramidDescriptor; +use super::shader::DepthPyramidDescriptor; #[derive(Debug, Snafu)] pub enum CullingError { @@ -673,8 +673,14 @@ mod test { use std::collections::HashMap; use crate::{ - bvol::BoundingSphere, cull::DepthPyramidDescriptor, draw::DrawIndirectArgs, - geometry::Geometry, math::hex_to_vec4, prelude::*, test::BlockOnFuture, + bvol::BoundingSphere, + cull::shader::DepthPyramidDescriptor, + draw::DrawIndirectArgs, + geometry::{Geometry, Vertex}, + math::hex_to_vec4, + prelude::*, + primitive::shader::PrimitiveDescriptor, + test::BlockOnFuture, }; use crabslab::{Array, GrowableSlab, Id, Slab}; use glam::{Mat4, Quat, UVec2, UVec3, Vec2, Vec3, Vec4}; @@ -995,7 +1001,7 @@ mod test { } log::info!(""); log::info!("name: {name}"); - crate::cull::compute_culling( + crate::cull::shader::compute_culling( &stage_slab, &depth_pyramid_slab, args, diff --git a/crates/renderling/src/cull/shader.rs b/crates/renderling/src/cull/shader.rs new file mode 100644 index 00000000..1eb9af16 --- /dev/null +++ b/crates/renderling/src/cull/shader.rs @@ -0,0 +1,239 @@ +use crabslab::{Array, Id, Slab, SlabItem}; +use glam::{UVec2, UVec3, Vec2, Vec3Swizzles}; +#[allow(unused_imports)] +use spirv_std::num_traits::Float; +use spirv_std::{ + arch::IndexUnchecked, + image::{sample_with, Image, ImageWithMethods}, + spirv, +}; + +use crate::{ + draw::DrawIndirectArgs, geometry::shader::GeometryDescriptor, + primitive::shader::PrimitiveDescriptor, +}; + +#[spirv(compute(threads(16)))] +pub fn compute_culling( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] stage_slab: &[u32], + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] depth_pyramid_slab: &[u32], + #[spirv(storage_buffer, descriptor_set = 0, binding = 2)] args: &mut [DrawIndirectArgs], + #[spirv(global_invocation_id)] global_id: UVec3, +) { + let gid = global_id.x as usize; + if gid >= args.len() { + return; + } + + crate::println!("gid: {gid}"); + // Get the draw arg + let arg = unsafe { args.index_unchecked_mut(gid) }; + // Get the primitive using the draw arg's primitive id + let primitive_id = Id::::new(arg.first_instance); + let primitive = stage_slab.read_unchecked(primitive_id); + crate::println!("primitive: {primitive_id:?}"); + + arg.vertex_count = primitive.get_vertex_count(); + arg.instance_count = if primitive.visible { 1 } else { 0 }; + + if primitive.bounds.radius == 0.0 { + crate::println!("primitive bounding radius is zero, cannot cull"); + return; + } + + let config: GeometryDescriptor = stage_slab.read(Id::new(0)); + if !config.perform_frustum_culling { + return; + } + + let camera = stage_slab.read(config.camera_id); + let model = stage_slab.read(primitive.transform_id); + // Compute frustum culling, and then occlusion culling, if need be + let (primitive_is_inside_frustum, sphere_in_world_coords) = + primitive.bounds.is_inside_camera_view(&camera, model); + + if primitive_is_inside_frustum { + arg.instance_count = 1; + crate::println!("primitive is inside frustum"); + crate::println!("znear: {}", camera.frustum().planes[0]); + crate::println!(" zfar: {}", camera.frustum().planes[5]); + if !config.perform_occlusion_culling { + return; + } + + // Compute occlusion culling using the hierachical z-buffer. + let hzb_desc = depth_pyramid_slab.read_unchecked::(0u32.into()); + let viewport_size = Vec2::new(hzb_desc.size.x as f32, hzb_desc.size.y as f32); + let sphere_aabb = sphere_in_world_coords.project_onto_viewport(&camera, viewport_size); + crate::println!("sphere_aabb: {sphere_aabb:#?}"); + + let size_in_pixels = sphere_aabb.max.xy() - sphere_aabb.min.xy(); + let size_in_pixels = if size_in_pixels.x > size_in_pixels.y { + size_in_pixels.x + } else { + size_in_pixels.y + }; + crate::println!("primitive size in pixels: {size_in_pixels}"); + + let mip_level = size_in_pixels.log2().floor() as u32; + let max_mip_level = hzb_desc.mip.len() as u32 - 1; + let mip_level = if mip_level > max_mip_level { + crate::println!("mip_level maxed out at {mip_level}, setting to {max_mip_level}"); + max_mip_level + } else { + mip_level + }; + crate::println!( + "selected mip level: {mip_level} {}x{}", + viewport_size.x as u32 >> mip_level, + viewport_size.y as u32 >> mip_level + ); + + let center = sphere_aabb.center().xy(); + crate::println!("center: {center}"); + + let x = center.x.round() as u32 >> mip_level; + let y = center.y.round() as u32 >> mip_level; + crate::println!("mip (x, y): ({x}, {y})"); + + let depth_id = hzb_desc.id_of_depth(mip_level, UVec2::new(x, y), depth_pyramid_slab); + let depth_in_hzb = depth_pyramid_slab.read_unchecked(depth_id); + crate::println!("depth_in_hzb: {depth_in_hzb}"); + + let depth_of_sphere = sphere_aabb.min.z; + crate::println!("depth_of_sphere: {depth_of_sphere}"); + + let primitive_is_behind_something = depth_of_sphere > depth_in_hzb; + let primitive_surrounds_camera = depth_of_sphere > 1.0; + + if primitive_is_behind_something || primitive_surrounds_camera { + crate::println!("CULLED"); + arg.instance_count = 0; + } + } else { + arg.instance_count = 0; + } +} + +/// A hierarchichal depth buffer. +/// +/// AKA HZB +#[derive(Clone, Copy, Default, SlabItem)] +pub struct DepthPyramidDescriptor { + /// Size of the top layer mip. + pub size: UVec2, + /// Current mip level. + /// + /// This will be updated for each run of the downsample compute shader. + pub mip_level: u32, + /// Pointer to the mip data. + /// + /// This points to the depth data at each mip level. + /// + /// The depth data itself is somewhere else in the slab. + pub mip: Array>, +} + +impl DepthPyramidDescriptor { + fn should_skip_invocation(&self, global_invocation: UVec3) -> bool { + let current_size = self.size >> self.mip_level; + !(global_invocation.x < current_size.x && global_invocation.y < current_size.y) + } + + #[cfg(test)] + pub fn size_at(&self, mip_level: u32) -> UVec2 { + UVec2::new(self.size.x >> mip_level, self.size.y >> mip_level) + } + + /// Return the [`Id`] of the depth at the given `mip_level` and coordinate. + pub fn id_of_depth(&self, mip_level: u32, coord: UVec2, slab: &[u32]) -> Id { + let mip_array = slab.read(self.mip.at(mip_level as usize)); + let width_at_mip = self.size.x >> mip_level; + let index = coord.y * width_at_mip + coord.x; + mip_array.at(index as usize) + } +} + +pub type DepthImage2d = Image!(2D, type=f32, sampled, depth); +pub type DepthImage2dMultisampled = Image!(2D, type=f32, sampled, depth, multisampled); + +/// Copies a depth texture to the top mip of a pyramid of mips. +/// +/// It is assumed that a [`DepthPyramidDescriptor`] is stored at index `0` in +/// the given slab. +#[spirv(compute(threads(16, 16, 1)))] +pub fn compute_copy_depth_to_pyramid( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] slab: &mut [u32], + #[spirv(descriptor_set = 0, binding = 1)] depth_texture: &DepthImage2d, + #[spirv(global_invocation_id)] global_id: UVec3, +) { + let desc = slab.read_unchecked::(0u32.into()); + if desc.should_skip_invocation(global_id) { + return; + } + + let depth = depth_texture + .fetch_with(global_id.xy(), sample_with::lod(0)) + .x; + let dest_id = desc.id_of_depth(0, global_id.xy(), slab); + slab.write(dest_id, &depth); +} + +/// Copies a depth texture to the top mip of a pyramid of mips. +/// +/// It is assumed that a [`DepthPyramidDescriptor`] is stored at index `0` in +/// the given slab. +#[spirv(compute(threads(16, 16, 1)))] +pub fn compute_copy_depth_to_pyramid_multisampled( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] slab: &mut [u32], + #[spirv(descriptor_set = 0, binding = 1)] depth_texture: &DepthImage2dMultisampled, + #[spirv(global_invocation_id)] global_id: UVec3, +) { + let desc = slab.read_unchecked::(0u32.into()); + if desc.should_skip_invocation(global_id) { + return; + } + + let depth = depth_texture + .fetch_with(global_id.xy(), sample_with::sample_index(0)) + .x; + let dest_id = desc.id_of_depth(0, global_id.xy(), slab); + slab.write(dest_id, &depth); +} + +/// Downsample from `DepthPyramidDescriptor::mip_level-1` into +/// `DepthPyramidDescriptor::mip_level`. +/// +/// It is assumed that a [`DepthPyramidDescriptor`] is stored at index `0` in +/// the given slab. +/// +/// The `DepthPyramidDescriptor`'s `mip_level` field will point to that of the +/// mip level being downsampled to (the mip level being written into). +/// +/// This shader should be called in a loop from from `1..mip_count`. +#[spirv(compute(threads(16, 16, 1)))] +pub fn compute_downsample_depth_pyramid( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] slab: &mut [u32], + #[spirv(global_invocation_id)] global_id: UVec3, +) { + let desc = slab.read_unchecked::(0u32.into()); + if desc.should_skip_invocation(global_id) { + return; + } + // Sample the texel. + // + // The texel will look like this: + // + // a b + // c d + let a_coord = global_id.xy() * 2; + let a = slab.read(desc.id_of_depth(desc.mip_level - 1, a_coord, slab)); + let b = slab.read(desc.id_of_depth(desc.mip_level - 1, a_coord + UVec2::new(1, 0), slab)); + let c = slab.read(desc.id_of_depth(desc.mip_level - 1, a_coord + UVec2::new(0, 1), slab)); + let d = slab.read(desc.id_of_depth(desc.mip_level - 1, a_coord + UVec2::new(1, 1), slab)); + // Take the maximum depth of the region (max depth means furthest away) + let depth_value = a.max(b).max(c).max(d); + // Write the texel in the next mip + let depth_id = desc.id_of_depth(desc.mip_level, global_id.xy(), slab); + slab.write(depth_id, &depth_value); +} diff --git a/crates/renderling/src/debug.rs b/crates/renderling/src/debug.rs index cb52719a..03861e8c 100644 --- a/crates/renderling/src/debug.rs +++ b/crates/renderling/src/debug.rs @@ -1,77 +1,79 @@ //! Debug overlay. -use crabslab::{Id, Slab}; -use glam::{Vec2, Vec3Swizzles, Vec4, Vec4Swizzles}; -use spirv_std::{arch::IndexUnchecked, spirv}; - -use crate::{ - draw::DrawIndirectArgs, geometry::GeometryDescriptor, sdf, stage::PrimitiveDescriptor, - transform::TransformDescriptor, -}; - -#[cfg(not(target_arch = "spirv"))] +#[cfg(cpu)] mod cpu; -#[cfg(not(target_arch = "spirv"))] +#[cfg(cpu)] pub use cpu::*; -/// Renders an implicit quad. -#[spirv(vertex)] -pub fn debug_overlay_vertex( - #[spirv(vertex_index)] vertex_id: u32, - #[spirv(position)] clip_pos: &mut Vec4, -) { - *clip_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[vertex_id as usize % 6]; -} +pub mod shader { + use crabslab::{Id, Slab}; + use glam::{Vec2, Vec3Swizzles, Vec4, Vec4Swizzles}; + use spirv_std::{arch::IndexUnchecked, spirv}; + + use crate::{ + draw::DrawIndirectArgs, geometry::shader::GeometryDescriptor, + primitive::shader::PrimitiveDescriptor, sdf, transform::shader::TransformDescriptor, + }; + /// Renders an implicit quad. + #[spirv(vertex)] + pub fn debug_overlay_vertex( + #[spirv(vertex_index)] vertex_id: u32, + #[spirv(position)] clip_pos: &mut Vec4, + ) { + *clip_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[vertex_id as usize % 6]; + } -/// Renders a debug overlay on top of the current framebuffer. -/// -/// Displays useful information in real time. -#[spirv(fragment)] -pub fn debug_overlay_fragment( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] draw_calls: &[DrawIndirectArgs], - #[spirv(frag_coord)] frag_coord: Vec4, - frag_color: &mut Vec4, -) { - let camera_id_id = Id::from(GeometryDescriptor::OFFSET_OF_CAMERA_ID); - let camera_id = slab.read_unchecked(camera_id_id); - let camera = slab.read_unchecked(camera_id); - let resolution_id = Id::from(GeometryDescriptor::OFFSET_OF_RESOLUTION); - let viewport_size = slab.read_unchecked(resolution_id); + /// Renders a debug overlay on top of the current framebuffer. + /// + /// Displays useful information in real time. + #[spirv(fragment)] + pub fn debug_overlay_fragment( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] draw_calls: &[DrawIndirectArgs], + #[spirv(frag_coord)] frag_coord: Vec4, + frag_color: &mut Vec4, + ) { + let camera_id_id = Id::from(GeometryDescriptor::OFFSET_OF_CAMERA_ID); + let camera_id = slab.read_unchecked(camera_id_id); + let camera = slab.read_unchecked(camera_id); + let resolution_id = Id::from(GeometryDescriptor::OFFSET_OF_RESOLUTION); + let viewport_size = slab.read_unchecked(resolution_id); - *frag_color = Vec4::ZERO; + *frag_color = Vec4::ZERO; - for i in 0..draw_calls.len() { - let draw_call = unsafe { draw_calls.index_unchecked(i) }; - let renderlet_id = Id::::new(draw_call.first_instance); - let transform_id = - slab.read_unchecked(renderlet_id + PrimitiveDescriptor::OFFSET_OF_TRANSFORM_ID); - let mut model = TransformDescriptor::IDENTITY; - slab.read_into_if_some(transform_id, &mut model); - let bounds = slab.read_unchecked(renderlet_id + PrimitiveDescriptor::OFFSET_OF_BOUNDS); + for i in 0..draw_calls.len() { + let draw_call = unsafe { draw_calls.index_unchecked(i) }; + let primitive_id: Id = + Id::::new(draw_call.first_instance); + let transform_id = + slab.read_unchecked(primitive_id + PrimitiveDescriptor::OFFSET_OF_TRANSFORM_ID); + let mut model = TransformDescriptor::IDENTITY; + slab.read_into_if_some::(transform_id, &mut model); + let bounds = slab.read_unchecked(primitive_id + PrimitiveDescriptor::OFFSET_OF_BOUNDS); - let (_, sphere_in_world_coords) = bounds.is_inside_camera_view(&camera, model); - let sphere_aabb = sphere_in_world_coords.project_onto_viewport( - &camera, - Vec2::new(viewport_size.x as f32, viewport_size.y as f32), - ); + let (_, sphere_in_world_coords) = bounds.is_inside_camera_view(&camera, model); + let sphere_aabb = sphere_in_world_coords.project_onto_viewport( + &camera, + Vec2::new(viewport_size.x as f32, viewport_size.y as f32), + ); - let sdf_circle = sdf::Box { - center: sphere_aabb.center().xy(), - half_extent: (sphere_aabb.max.xy() - sphere_aabb.min.xy()) * 0.5, - }; + let sdf_circle = sdf::Box { + center: sphere_aabb.center().xy(), + half_extent: (sphere_aabb.max.xy() - sphere_aabb.min.xy()) * 0.5, + }; - let distance = sdf_circle.distance(frag_coord.xy() + 0.5); + let distance = sdf_circle.distance(frag_coord.xy() + 0.5); - // Here we use `step_le`, which I have annotated with `#inline(always)`. - // I did this because without it, it seems to do the opposite of expected. - // I found this by inlining by hand. - let alpha = crate::math::step_le(sphere_aabb.max.z, 1.0); - if distance.abs() < 0.5 { - *frag_color = Vec4::new(0.0, 0.0, 0.0, 1.0 * alpha); - } else if distance.abs() <= 2.0 { - *frag_color = Vec4::new(1.0, 1.0, 1.0, 0.5 * alpha); - } else if distance.abs() <= 3.0 { - *frag_color = Vec4::new(0.5, 0.5, 0.5, 1.0 * alpha); + // Here we use `step_le`, which I have annotated with `#inline(always)`. + // I did this because without it, it seems to do the opposite of expected. + // I found this by inlining by hand. + let alpha = crate::math::step_le(sphere_aabb.max.z, 1.0); + if distance.abs() < 0.5 { + *frag_color = Vec4::new(0.0, 0.0, 0.0, 1.0 * alpha); + } else if distance.abs() <= 2.0 { + *frag_color = Vec4::new(1.0, 1.0, 1.0, 0.5 * alpha); + } else if distance.abs() <= 3.0 { + *frag_color = Vec4::new(0.5, 0.5, 0.5, 1.0 * alpha); + } } } } diff --git a/crates/renderling/src/draw.rs b/crates/renderling/src/draw.rs index 09ccf3b4..781cc0a9 100644 --- a/crates/renderling/src/draw.rs +++ b/crates/renderling/src/draw.rs @@ -1,9 +1,9 @@ //! Handles queueing draw calls. //! //! [`DrawCalls`] is used to maintain the list of all staged -//! [`PrimitiveDescriptor`](crate::stage::PrimitiveDescriptor)s. +//! [`PrimitiveDescriptor`](crate::primitive::shader::PrimitiveDescriptor)s. //! It also performs frustum culling and issues draw calls during -//! [`Stage::render`](crate::prelude::Stage::render). +//! [`Stage::render`](crate::stage::Stage::render). use crabslab::SlabItem; #[cfg(cpu)] diff --git a/crates/renderling/src/draw/cpu.rs b/crates/renderling/src/draw/cpu.rs index f4d781f8..f1fb1a1a 100644 --- a/crates/renderling/src/draw/cpu.rs +++ b/crates/renderling/src/draw/cpu.rs @@ -8,7 +8,7 @@ use crabslab::Id; use crate::{ cull::{ComputeCulling, CullingError}, - stage::{Primitive, PrimitiveDescriptor}, + primitive::{shader::PrimitiveDescriptor, Primitive}, texture::Texture, Context, }; diff --git a/crates/renderling/src/geometry.rs b/crates/renderling/src/geometry.rs index 96d1634d..585b229b 100644 --- a/crates/renderling/src/geometry.rs +++ b/crates/renderling/src/geometry.rs @@ -1,64 +1,20 @@ -//! Holds geometry on CPU and GPU. -use crabslab::{Array, Id, Slab, SlabItem}; +//! Types and functions for staging geometry. +use crate::math::IsVector; +use crabslab::SlabItem; #[cfg(cpu)] mod cpu; #[cfg(cpu)] pub use cpu::*; -use glam::{Mat4, Vec2, Vec3, Vec4}; +use glam::{Vec2, Vec3, Vec4}; -use crate::{camera::CameraDescriptor, math::IsVector, transform::TransformDescriptor}; - -/// A vertex skin descriptor. -/// -/// For more info on vertex skinning, see -/// -#[derive(Clone, Copy, Default, SlabItem)] -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -pub struct SkinDescriptor { - // Ids of the skeleton nodes' global transforms used as joints in this skin. - pub joints_array: Array>, - // Contains the 4x4 inverse-bind matrices. - // - // When is none, each matrix is assumed to be the 4x4 identity matrix - // which implies that the inverse-bind matrices were pre-applied. - pub inverse_bind_matrices_array: Array, -} - -impl SkinDescriptor { - pub fn get_joint_matrix(&self, i: usize, vertex: Vertex, slab: &[u32]) -> Mat4 { - let joint_index = vertex.joints[i] as usize; - let joint_id = slab.read(self.joints_array.at(joint_index)); - let joint_transform = slab.read(joint_id); - // First apply the inverse bind matrix to bring the vertex into the joint's - // local space, then apply the joint's current transformation to move it - // into world space. - let inverse_bind_matrix = slab.read(self.inverse_bind_matrices_array.at(joint_index)); - Mat4::from(joint_transform) * inverse_bind_matrix - } - - pub fn get_skinning_matrix(&self, vertex: Vertex, slab: &[u32]) -> Mat4 { - let mut skinning_matrix = Mat4::ZERO; - for i in 0..vertex.joints.len() { - let joint_matrix = self.get_joint_matrix(i, vertex, slab); - // Ensure weights are applied correctly to the joint matrix - let weight = vertex.weights[i]; - skinning_matrix += weight * joint_matrix; - } - - if skinning_matrix == Mat4::ZERO { - Mat4::IDENTITY - } else { - skinning_matrix - } - } -} +pub mod shader; /// A displacement target. /// /// Use to displace vertices using weights defined on the mesh. /// -/// For more info on morph targets, see +/// For more info on morph targets in general, see /// #[derive(Clone, Copy, Default, PartialEq, SlabItem)] #[cfg_attr(cpu, derive(Debug))] @@ -176,36 +132,3 @@ impl Vertex { mesh } } - -/// Holds configuration info for vertex and shading render passes of -/// geometry. -/// -/// This descriptor lives at the root (index 0) of the geometry slab. -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Clone, Copy, PartialEq, SlabItem)] -#[offsets] -pub struct GeometryDescriptor { - pub camera_id: Id, - pub atlas_size: glam::UVec2, - pub resolution: glam::UVec2, - pub debug_channel: crate::pbr::debug::DebugChannel, - pub has_lighting: bool, - pub has_skinning: bool, - pub perform_frustum_culling: bool, - pub perform_occlusion_culling: bool, -} - -impl Default for GeometryDescriptor { - fn default() -> Self { - Self { - camera_id: Id::NONE, - atlas_size: Default::default(), - resolution: glam::UVec2::ONE, - debug_channel: Default::default(), - has_lighting: true, - has_skinning: true, - perform_frustum_culling: true, - perform_occlusion_culling: false, - } - } -} diff --git a/crates/renderling/src/geometry/cpu.rs b/crates/renderling/src/geometry/cpu.rs index 36badcff..ad87e26f 100644 --- a/crates/renderling/src/geometry/cpu.rs +++ b/crates/renderling/src/geometry/cpu.rs @@ -11,8 +11,11 @@ use glam::{Mat4, UVec2, Vec4}; use crate::{ camera::Camera, - geometry::{GeometryDescriptor, MorphTarget, SkinDescriptor, Vertex}, - transform::{NestedTransform, Transform, TransformDescriptor}, + geometry::{ + shader::{GeometryDescriptor, SkinDescriptor}, + MorphTarget, Vertex, + }, + transform::{shader::TransformDescriptor, NestedTransform, Transform}, types::{GpuCpuArray, GpuOnlyArray}, }; diff --git a/crates/renderling/src/geometry/shader.rs b/crates/renderling/src/geometry/shader.rs new file mode 100644 index 00000000..93a11ec3 --- /dev/null +++ b/crates/renderling/src/geometry/shader.rs @@ -0,0 +1,84 @@ +use crabslab::{Array, Id, Slab, SlabItem}; +use glam::Mat4; + +use crate::{ + camera::shader::CameraDescriptor, geometry::Vertex, transform::shader::TransformDescriptor, +}; + +/// A vertex skin descriptor. +/// +/// For more info on vertex skinning, see +/// +#[derive(Clone, Copy, Default, SlabItem)] +#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] +pub struct SkinDescriptor { + // Ids of the skeleton nodes' global transforms used as joints in this skin. + pub joints_array: Array>, + // Contains the 4x4 inverse-bind matrices. + // + // When is none, each matrix is assumed to be the 4x4 identity matrix + // which implies that the inverse-bind matrices were pre-applied. + pub inverse_bind_matrices_array: Array, +} + +impl SkinDescriptor { + pub fn get_joint_matrix(&self, i: usize, vertex: Vertex, slab: &[u32]) -> Mat4 { + let joint_index = vertex.joints[i] as usize; + let joint_id = slab.read(self.joints_array.at(joint_index)); + let joint_transform = slab.read(joint_id); + // First apply the inverse bind matrix to bring the vertex into the joint's + // local space, then apply the joint's current transformation to move it + // into world space. + let inverse_bind_matrix = slab.read(self.inverse_bind_matrices_array.at(joint_index)); + Mat4::from(joint_transform) * inverse_bind_matrix + } + + pub fn get_skinning_matrix(&self, vertex: Vertex, slab: &[u32]) -> Mat4 { + let mut skinning_matrix = Mat4::ZERO; + for i in 0..vertex.joints.len() { + let joint_matrix = self.get_joint_matrix(i, vertex, slab); + // Ensure weights are applied correctly to the joint matrix + let weight = vertex.weights[i]; + skinning_matrix += weight * joint_matrix; + } + + if skinning_matrix == Mat4::ZERO { + Mat4::IDENTITY + } else { + skinning_matrix + } + } +} + +/// Holds configuration info for vertex and shading render passes of +/// geometry. +/// +/// This descriptor lives at the root (index 0) of the geometry slab. +#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] +#[derive(Clone, Copy, PartialEq, SlabItem)] +#[offsets] +pub struct GeometryDescriptor { + pub camera_id: Id, + pub atlas_size: glam::UVec2, + pub resolution: glam::UVec2, + pub debug_channel: crate::pbr::debug::DebugChannel, + pub has_lighting: bool, + pub has_skinning: bool, + pub perform_frustum_culling: bool, + pub perform_occlusion_culling: bool, +} + +impl Default for GeometryDescriptor { + fn default() -> Self { + Self { + camera_id: Id::NONE, + atlas_size: Default::default(), + resolution: glam::UVec2::ONE, + debug_channel: Default::default(), + has_lighting: true, + has_skinning: true, + perform_frustum_culling: true, + perform_occlusion_culling: false, + } + } +} diff --git a/crates/renderling/src/stage/gltf_support.rs b/crates/renderling/src/gltf.rs similarity index 91% rename from crates/renderling/src/stage/gltf_support.rs rename to crates/renderling/src/gltf.rs index d2009f4d..8a2e3855 100644 --- a/crates/renderling/src/stage/gltf_support.rs +++ b/crates/renderling/src/gltf.rs @@ -1,24 +1,31 @@ -//! Gltf support for the [`Stage`](crate::Stage). +//! GLTF support. +//! +//! # Loading GLTF files +//! +//! Loading GLTF files is accomplished through [`Stage::load_gltf_document_from_path`] +//! and [`Stage::load_gltf_document_from_bytes`]. use std::{collections::HashMap, sync::Arc}; use craballoc::prelude::*; -use crabslab::Id; +use crabslab::{Array, Id}; use glam::{Mat4, Quat, Vec2, Vec3, Vec4}; use rustc_hash::{FxHashMap, FxHashSet}; use snafu::{OptionExt, ResultExt, Snafu}; use crate::{ atlas::{ - AtlasError, AtlasImage, AtlasTexture, AtlasTextureDescriptor, TextureAddressMode, + shader::AtlasTextureDescriptor, AtlasError, AtlasImage, AtlasTexture, TextureAddressMode, TextureModes, }, bvol::Aabb, - camera::{Camera, CameraDescriptor}, - geometry::{Indices, MorphTargetWeights, MorphTargets, Skin, Vertices}, - light::{AnalyticalLight, LightStyle}, + camera::Camera, + geometry::{Indices, MorphTarget, MorphTargetWeights, MorphTargets, Skin, Vertex, Vertices}, + light::{shader::LightStyle, AnalyticalLight}, material::Material, - stage::{MorphTarget, Primitive, Stage, Vertex}, - transform::{NestedTransform, TransformDescriptor}, + primitive::Primitive, + stage::{Stage, StageError}, + transform::{shader::TransformDescriptor, NestedTransform}, + types::{GpuCpuArray, GpuOnlyArray}, }; mod anime; @@ -26,9 +33,6 @@ pub use anime::*; #[derive(Debug, Snafu)] pub enum StageGltfError { - #[snafu(display("{source}"))] - Stage { source: crate::stage::StageError }, - #[snafu(display("{source}"))] Gltf { source: gltf::Error }, @@ -274,15 +278,30 @@ impl Material { } } -#[derive(Debug)] -pub struct GltfPrimitive { - pub indices: Indices, - pub vertices: Vertices, +pub struct GltfPrimitive { + pub indices: Indices, + pub vertices: Vertices, pub bounding_box: (Vec3, Vec3), pub material_index: Option, pub morph_targets: MorphTargets, } +impl core::fmt::Debug for GltfPrimitive +where + Ct: IsContainer = Array>, + Ct: IsContainer = Array>, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("GltfPrimitive") + .field("indices", &self.indices) + .field("vertices", &self.vertices) + .field("bounding_box", &self.bounding_box) + .field("material_index", &self.material_index) + .field("morph_targets", &self.morph_targets) + .finish() + } +} + impl GltfPrimitive { pub fn from_gltf( stage: &Stage, @@ -531,16 +550,45 @@ impl GltfPrimitive { bounding_box, } } + + pub fn into_gpu_only(self) -> GltfPrimitive { + let Self { + indices, + vertices, + bounding_box, + material_index, + morph_targets, + } = self; + GltfPrimitive { + indices: indices.into_gpu_only(), + vertices: vertices.into_gpu_only(), + bounding_box, + material_index, + morph_targets, + } + } } -#[derive(Debug)] -pub struct GltfMesh { +pub struct GltfMesh { /// Mesh primitives, aka meshlets - pub primitives: Vec, + pub primitives: Vec>, /// Morph target weights pub weights: MorphTargetWeights, } +impl core::fmt::Debug for GltfMesh +where + Ct: IsContainer = Array>, + Ct: IsContainer = Array>, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("GltfMesh") + .field("primitives", &self.primitives) + .field("weights", &self.weights) + .finish() + } +} + impl GltfMesh { fn from_gltf(stage: &Stage, buffer_data: &[gltf::buffer::Data], mesh: gltf::Mesh) -> Self { log::debug!("Loading primitives for mesh {}", mesh.index()); @@ -555,6 +603,21 @@ impl GltfMesh { weights: stage.new_morph_target_weights(weights), } } + + pub fn into_gpu_only(self) -> GltfMesh { + let Self { + primitives, + weights, + } = self; + let primitives = primitives + .into_iter() + .map(GltfPrimitive::into_gpu_only) + .collect::>(); + GltfMesh { + primitives, + weights, + } + } } #[derive(Debug)] @@ -562,7 +625,6 @@ pub struct GltfCamera { pub index: usize, pub name: Option, pub node_transform: NestedTransform, - projection: Mat4, pub camera: Camera, } @@ -606,16 +668,10 @@ impl GltfCamera { GltfCamera { index: gltf_camera.index(), name: gltf_camera.name().map(String::from), - projection, node_transform: transform.clone(), camera, } } - - pub fn camera_descriptor(&self) -> CameraDescriptor { - let view = Mat4::from(self.node_transform.global_descriptor()).inverse(); - CameraDescriptor::new(self.projection, view) - } } /// A node in a GLTF document, ready to be 'drawn'. @@ -711,19 +767,31 @@ impl GltfSkin { } /// A loaded GLTF document. -pub struct GltfDocument { +/// +/// After being loaded, a [`GltfDocument`] is a collection of staged resources. +/// +/// All primitives are automatically added to the [`Stage`] they were loaded +/// from. +/// +/// ## Note +/// +/// After being loaded, the `meshes` field contains [`Vertices`] and [`Indices`] +/// that can be inspected from the CPU. This has memory implications, so if your +/// document contains lots of geometric data it is advised that you unload that +/// data from the CPU using [`GltfDocument::into_gpu_only`]. +pub struct GltfDocument { pub animations: Vec, pub cameras: Vec, pub default_scene: Option, pub extensions: Option, pub textures: Vec, pub lights: Vec, - pub meshes: Vec, + pub meshes: Vec>, pub nodes: Vec, pub default_material: Material, pub materials: Vec, - // map of node index to renderlets - pub renderlets: FxHashMap>, + // map of node index to primitives + pub primitives: FxHashMap>, /// Vector of scenes - each being a list of nodes. pub scenes: Vec>, pub skins: Vec, @@ -735,7 +803,7 @@ impl GltfDocument { document: &gltf::Document, buffer_data: Vec, images: Vec, - ) -> Result { + ) -> Result { let textures = { let mut images = images.into_iter().map(AtlasImage::from).collect::>(); for gltf_material in document.materials() { @@ -797,7 +865,7 @@ impl GltfDocument { Err(aimg) => aimg.as_ref().clone(), }) .collect(); - let hybrid_textures = stage.add_images(prepared_images).context(StageSnafu)?; + let hybrid_textures = stage.add_images(prepared_images)?; let mut texture_lookup = FxHashMap::::default(); for (hybrid, (tex, refs)) in hybrid_textures.into_iter().zip(deduped_textures) { hybrid.set_modes(tex.modes); @@ -1104,7 +1172,7 @@ impl GltfDocument { scenes, skins, default_scene: document.default_scene().map(|scene| scene.index()), - renderlets, + primitives: renderlets, extensions: document .extensions() .cloned() @@ -1112,8 +1180,54 @@ impl GltfDocument { }) } + /// Unload vertex and index data from the CPU. + /// + /// The data can still be updated from the CPU, but will not be inspectable. + pub fn into_gpu_only(self) -> GltfDocument { + let Self { + animations, + cameras, + default_scene, + extensions, + textures, + lights, + meshes, + nodes, + default_material, + materials, + primitives, + scenes, + skins, + } = self; + let meshes = meshes + .into_iter() + .map(GltfMesh::into_gpu_only) + .collect::>(); + GltfDocument { + animations, + cameras, + default_scene, + extensions, + textures, + lights, + meshes, + nodes, + default_material, + materials, + primitives, + scenes, + skins, + } + } +} + +impl GltfDocument +where + Ct: IsContainer = Array>, + Ct: IsContainer = Array>, +{ pub fn renderlets_iter(&self) -> impl Iterator { - self.renderlets.iter().flat_map(|(_, rs)| rs.iter()) + self.primitives.iter().flat_map(|(_, rs)| rs.iter()) } pub fn nodes_in_scene(&self, scene_index: usize) -> impl Iterator { @@ -1153,27 +1267,9 @@ impl GltfDocument { } } -impl Stage { - pub fn load_gltf_document_from_path( - &self, - path: impl AsRef, - ) -> Result { - let (document, buffers, images) = gltf::import(path)?; - GltfDocument::from_gltf(self, &document, buffers, images) - } - - pub fn load_gltf_document_from_bytes( - &self, - bytes: impl AsRef<[u8]>, - ) -> Result { - let (document, buffers, images) = gltf::import_slice(bytes)?; - GltfDocument::from_gltf(self, &document, buffers, images) - } -} - #[cfg(test)] mod test { - use crate::{stage::Vertex, test::BlockOnFuture, Context}; + use crate::{geometry::Vertex, test::BlockOnFuture, Context}; use glam::{Vec3, Vec4}; #[test] @@ -1448,7 +1544,7 @@ mod test { .unwrap(); let camera_a = doc.cameras.first().unwrap(); - let desc = camera_a.camera_descriptor(); + let desc = camera_a.camera.descriptor(); const THRESHOLD: f32 = 10e-6; let a = Vec3::new(14.699949, 4.958309, 12.676651); let b = Vec3::new(14.699949, -12.676651, 4.958309); @@ -1479,8 +1575,8 @@ mod test { a.distance(b) <= 10e-6 || c.distance(c) <= 10e-6 }; assert!(eq( - camera_a.camera_descriptor().position(), - camera_b.camera_descriptor().position() + camera_a.camera.descriptor().position(), + camera_b.camera.descriptor().position() )); } } diff --git a/crates/renderling/src/stage/gltf_support/anime.rs b/crates/renderling/src/gltf/anime.rs similarity index 99% rename from crates/renderling/src/stage/gltf_support/anime.rs rename to crates/renderling/src/gltf/anime.rs index dbde92ab..830492ad 100644 --- a/crates/renderling/src/stage/gltf_support/anime.rs +++ b/crates/renderling/src/gltf/anime.rs @@ -2,9 +2,7 @@ use glam::{Quat, Vec3}; use snafu::prelude::*; -use crate::{ - geometry::MorphTargetWeights, stage::gltf_support::GltfNode, transform::NestedTransform, -}; +use crate::{geometry::MorphTargetWeights, gltf::GltfNode, transform::NestedTransform}; #[derive(Debug, Snafu)] pub enum InterpolationError { @@ -766,7 +764,7 @@ impl Animator { #[cfg(test)] mod test { - use crate::{stage::Animator, test::BlockOnFuture, Context}; + use crate::{gltf::Animator, test::BlockOnFuture, Context}; use glam::Vec3; #[test] diff --git a/crates/renderling/src/ibl/mod.rs b/crates/renderling/src/ibl/mod.rs index fe2a39a6..98ba804e 100644 --- a/crates/renderling/src/ibl/mod.rs +++ b/crates/renderling/src/ibl/mod.rs @@ -1,4 +1,4 @@ -//! Resources for image based lighting. +//! Shader resources for image based lighting. pub mod diffuse_irradiance; #[cfg(not(target_arch = "spirv"))] diff --git a/crates/renderling/src/internal.rs b/crates/renderling/src/internal.rs index 512ecbf2..8cbf38b1 100644 --- a/crates/renderling/src/internal.rs +++ b/crates/renderling/src/internal.rs @@ -7,180 +7,7 @@ //! They are public here because they are needed for integration tests, and //! on the off-chance that somebody wants to build something with them. -use std::sync::Arc; - -use snafu::{OptionExt, ResultExt}; - -use crate::{ - CannotCreateAdaptorSnafu, CannotRequestDeviceSnafu, ContextError, IncompatibleSurfaceSnafu, - RenderTarget, RenderTargetInner, -}; - -/// Create a new [`wgpu::Adapter`]. -pub async fn adapter( - instance: &wgpu::Instance, - compatible_surface: Option<&wgpu::Surface<'_>>, -) -> Result { - log::trace!( - "creating adapter for a {} context", - if compatible_surface.is_none() { - "headless" - } else { - "surface-based" - } - ); - let adapter = instance - .request_adapter(&wgpu::RequestAdapterOptions { - power_preference: wgpu::PowerPreference::default(), - compatible_surface, - force_fallback_adapter: false, - }) - .await - .context(CannotCreateAdaptorSnafu)?; - - log::info!("Adapter selected: {:?}", adapter.get_info()); - let info = adapter.get_info(); - log::info!( - "using adapter: '{}' backend:{:?} driver:'{}'", - info.name, - info.backend, - info.driver - ); - Ok(adapter) -} - -/// Create a new [`wgpu::Device`]. -pub async fn device( - adapter: &wgpu::Adapter, -) -> Result<(wgpu::Device, wgpu::Queue), wgpu::RequestDeviceError> { - let wanted_features = wgpu::Features::INDIRECT_FIRST_INSTANCE - | wgpu::Features::MULTI_DRAW_INDIRECT - //// when debugging rust-gpu shader miscompilation it's nice to have this - //| wgpu::Features::SPIRV_SHADER_PASSTHROUGH - // this one is a funny requirement, it seems it is needed if using storage buffers in - // vertex shaders, even if those shaders are read-only - | wgpu::Features::VERTEX_WRITABLE_STORAGE - | wgpu::Features::CLEAR_TEXTURE; - let supported_features = adapter.features(); - let required_features = wanted_features.intersection(supported_features); - let unsupported_features = wanted_features.difference(supported_features); - if !unsupported_features.is_empty() { - log::error!("requested but unsupported features: {unsupported_features:#?}"); - log::warn!("requested and supported features: {supported_features:#?}"); - } - let limits = adapter.limits(); - log::info!("adapter limits: {limits:#?}"); - adapter - .request_device(&wgpu::DeviceDescriptor { - required_features, - required_limits: adapter.limits(), - label: None, - memory_hints: wgpu::MemoryHints::default(), - trace: wgpu::Trace::Off, - }) - .await -} - -/// Create a new instance. -/// -/// This is for internal use. It is not necessary to create your own `wgpu` -/// instance to use this library. -pub fn new_instance(backends: Option) -> wgpu::Instance { - log::info!( - "creating instance - available backends: {:#?}", - wgpu::Instance::enabled_backend_features() - ); - // BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU - let backends = backends.unwrap_or(wgpu::Backends::PRIMARY); - let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor { - backends, - ..Default::default() - }); - - #[cfg(not(target_arch = "wasm32"))] - { - let adapters = instance.enumerate_adapters(backends); - log::trace!("available adapters: {adapters:#?}"); - } - - instance -} - -/// Create a new suite of `wgpu` machinery using a window or canvas. -/// -/// ## Note -/// This function is used internally. -pub async fn new_windowed_adapter_device_queue( - width: u32, - height: u32, - instance: &wgpu::Instance, - window: impl Into>, -) -> Result<(wgpu::Adapter, wgpu::Device, wgpu::Queue, RenderTarget), ContextError> { - let surface = instance - .create_surface(window) - .map_err(|e| ContextError::CreateSurface { source: e })?; - let adapter = adapter(instance, Some(&surface)).await?; - let surface_caps = surface.get_capabilities(&adapter); - let fmt = if surface_caps - .formats - .contains(&wgpu::TextureFormat::Rgba8UnormSrgb) - { - wgpu::TextureFormat::Rgba8UnormSrgb - } else { - surface_caps - .formats - .iter() - .copied() - .find(|f| f.is_srgb()) - .unwrap_or(surface_caps.formats[0]) - }; - let view_fmts = if fmt.is_srgb() { - vec![] - } else { - vec![fmt.add_srgb_suffix()] - }; - log::info!("surface capabilities: {surface_caps:#?}"); - let mut surface_config = surface - .get_default_config(&adapter, width, height) - .context(IncompatibleSurfaceSnafu)?; - surface_config.view_formats = view_fmts; - let (device, queue) = device(&adapter).await.context(CannotRequestDeviceSnafu)?; - surface.configure(&device, &surface_config); - let target = RenderTarget(RenderTargetInner::Surface { - surface, - surface_config, - }); - Ok((adapter, device, queue, target)) -} - -/// Create a new suite of `wgpu` machinery that renders to a texture. -/// -/// ## Note -/// This function is used internally. -pub async fn new_headless_device_queue_and_target( - width: u32, - height: u32, - instance: &wgpu::Instance, -) -> Result<(wgpu::Adapter, wgpu::Device, wgpu::Queue, RenderTarget), ContextError> { - let adapter = adapter(instance, None).await?; - let texture_desc = wgpu::TextureDescriptor { - size: wgpu::Extent3d { - width, - height, - depth_or_array_layers: 1, - }, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsages::COPY_SRC - | wgpu::TextureUsages::RENDER_ATTACHMENT - | wgpu::TextureUsages::TEXTURE_BINDING, - label: None, - view_formats: &[], - }; - let (device, queue) = device(&adapter).await.context(CannotRequestDeviceSnafu)?; - let texture = Arc::new(device.create_texture(&texture_desc)); - let target = RenderTarget(RenderTargetInner::Texture { texture }); - Ok((adapter, device, queue, target)) -} +#[cfg(cpu)] +mod cpu; +#[cfg(cpu)] +pub use cpu::*; diff --git a/crates/renderling/src/internal/cpu.rs b/crates/renderling/src/internal/cpu.rs new file mode 100644 index 00000000..309e5ded --- /dev/null +++ b/crates/renderling/src/internal/cpu.rs @@ -0,0 +1,178 @@ +//! Internal CPU stuff. +use std::sync::Arc; + +use snafu::{OptionExt, ResultExt}; + +use crate::{ + CannotCreateAdaptorSnafu, CannotRequestDeviceSnafu, ContextError, IncompatibleSurfaceSnafu, + RenderTarget, RenderTargetInner, +}; + +/// Create a new [`wgpu::Adapter`]. +pub async fn adapter( + instance: &wgpu::Instance, + compatible_surface: Option<&wgpu::Surface<'_>>, +) -> Result { + log::trace!( + "creating adapter for a {} context", + if compatible_surface.is_none() { + "headless" + } else { + "surface-based" + } + ); + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::default(), + compatible_surface, + force_fallback_adapter: false, + }) + .await + .context(CannotCreateAdaptorSnafu)?; + + log::info!("Adapter selected: {:?}", adapter.get_info()); + let info = adapter.get_info(); + log::info!( + "using adapter: '{}' backend:{:?} driver:'{}'", + info.name, + info.backend, + info.driver + ); + Ok(adapter) +} + +/// Create a new [`wgpu::Device`]. +pub async fn device( + adapter: &wgpu::Adapter, +) -> Result<(wgpu::Device, wgpu::Queue), wgpu::RequestDeviceError> { + let wanted_features = wgpu::Features::INDIRECT_FIRST_INSTANCE + | wgpu::Features::MULTI_DRAW_INDIRECT + //// when debugging rust-gpu shader miscompilation it's nice to have this + //| wgpu::Features::SPIRV_SHADER_PASSTHROUGH + // this one is a funny requirement, it seems it is needed if using storage buffers in + // vertex shaders, even if those shaders are read-only + | wgpu::Features::VERTEX_WRITABLE_STORAGE + | wgpu::Features::CLEAR_TEXTURE; + let supported_features = adapter.features(); + let required_features = wanted_features.intersection(supported_features); + let unsupported_features = wanted_features.difference(supported_features); + if !unsupported_features.is_empty() { + log::error!("requested but unsupported features: {unsupported_features:#?}"); + log::warn!("requested and supported features: {supported_features:#?}"); + } + let limits = adapter.limits(); + log::info!("adapter limits: {limits:#?}"); + adapter + .request_device(&wgpu::DeviceDescriptor { + required_features, + required_limits: adapter.limits(), + label: None, + memory_hints: wgpu::MemoryHints::default(), + trace: wgpu::Trace::Off, + }) + .await +} + +/// Create a new instance. +/// +/// This is for internal use. It is not necessary to create your own `wgpu` +/// instance to use this library. +pub fn new_instance(backends: Option) -> wgpu::Instance { + log::info!( + "creating instance - available backends: {:#?}", + wgpu::Instance::enabled_backend_features() + ); + // BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU + let backends = backends.unwrap_or(wgpu::Backends::PRIMARY); + let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor { + backends, + ..Default::default() + }); + + #[cfg(not(target_arch = "wasm32"))] + { + let adapters = instance.enumerate_adapters(backends); + log::trace!("available adapters: {adapters:#?}"); + } + + instance +} + +/// Create a new suite of `wgpu` machinery using a window or canvas. +/// +/// ## Note +/// This function is used internally. +pub async fn new_windowed_adapter_device_queue( + width: u32, + height: u32, + instance: &wgpu::Instance, + window: impl Into>, +) -> Result<(wgpu::Adapter, wgpu::Device, wgpu::Queue, RenderTarget), ContextError> { + let surface = instance + .create_surface(window) + .map_err(|e| ContextError::CreateSurface { source: e })?; + let adapter = adapter(instance, Some(&surface)).await?; + let surface_caps = surface.get_capabilities(&adapter); + let fmt = if surface_caps + .formats + .contains(&wgpu::TextureFormat::Rgba8UnormSrgb) + { + wgpu::TextureFormat::Rgba8UnormSrgb + } else { + surface_caps + .formats + .iter() + .copied() + .find(|f| f.is_srgb()) + .unwrap_or(surface_caps.formats[0]) + }; + let view_fmts = if fmt.is_srgb() { + vec![] + } else { + vec![fmt.add_srgb_suffix()] + }; + log::info!("surface capabilities: {surface_caps:#?}"); + let mut surface_config = surface + .get_default_config(&adapter, width, height) + .context(IncompatibleSurfaceSnafu)?; + surface_config.view_formats = view_fmts; + let (device, queue) = device(&adapter).await.context(CannotRequestDeviceSnafu)?; + surface.configure(&device, &surface_config); + let target = RenderTarget(RenderTargetInner::Surface { + surface, + surface_config, + }); + Ok((adapter, device, queue, target)) +} + +/// Create a new suite of `wgpu` machinery that renders to a texture. +/// +/// ## Note +/// This function is used internally. +pub async fn new_headless_device_queue_and_target( + width: u32, + height: u32, + instance: &wgpu::Instance, +) -> Result<(wgpu::Adapter, wgpu::Device, wgpu::Queue, RenderTarget), ContextError> { + let adapter = adapter(instance, None).await?; + let texture_desc = wgpu::TextureDescriptor { + size: wgpu::Extent3d { + width, + height, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Rgba8UnormSrgb, + usage: wgpu::TextureUsages::COPY_SRC + | wgpu::TextureUsages::RENDER_ATTACHMENT + | wgpu::TextureUsages::TEXTURE_BINDING, + label: None, + view_formats: &[], + }; + let (device, queue) = device(&adapter).await.context(CannotRequestDeviceSnafu)?; + let texture = Arc::new(device.create_texture(&texture_desc)); + let target = RenderTarget(RenderTargetInner::Texture { texture }); + Ok((adapter, device, queue, target)) +} diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index d8b982d4..887bb447 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -23,7 +23,7 @@ //! canvas or a texture. //! //! ``` -//! use renderling::prelude::*; +//! use renderling::{context::Context, stage::Stage, geometry::Vertex}; //! //! // create a headless context with dimensions 100, 100. //! let ctx = futures_lite::future::block_on(Context::headless(100, 100)); @@ -40,12 +40,12 @@ //! See the [`renderling::context`](context) module documentation for //! more info. //! -//! ### Staging +//! ### Staging resources //! //! We then create a "stage" to place the camera, geometry, materials and lights. //! //! ``` -//! # use renderling::prelude::*; +//! # use renderling::{context::Context, stage::Stage}; //! # let ctx = futures_lite::future::block_on(Context::headless(100, 100)); //! let stage: Stage = ctx //! .new_stage() @@ -54,33 +54,30 @@ //! .with_lighting(false); //! ``` //! -//! The [`Stage`](crate::stage::Stage) is neat in that it allows you to "stage" data +//! The [`Stage`] is neat in that it allows you to "stage" data //! directly onto the GPU. Those values can be modified on the CPU and -//! synchronization will happen during -//! [`Stage::render`](crate::stage::Stage::render). +//! synchronization will happen during [`Stage::render`]. //! //! Use one of the many `Stage::new_*` functions to stage data on the GPU: -//! * [`Stage::new_camera`](crate::stage::Stage::new_camera) -//! * [`Stage::new_vertices`](crate::stage::Stage::new_vertices) -//! * [`Stage::new_indices`](crate::stage::Stage::new_indices) -//! * [`Stage::new_material`](crate::stage::Stage::new_material) -//! * [`Stage::new_primitive`](crate::stage::Stage::new_primitive) +//! * [`Stage::new_camera`] +//! * [`Stage::new_vertices`] +//! * [`Stage::new_indices`] +//! * [`Stage::new_material`] +//! * [`Stage::new_primitive`] //! * ...and more //! //! In order to render, we need to "stage" a -//! [`Primitive`](crate::stage::Primitive), which is a bundle of rendering +//! [`Primitive`], which is a bundle of rendering //! resources, roughly representing a singular mesh. //! -//! But first we'll need a list of [`Vertex`](crate::geometry::Vertex) organized +//! But first we'll need a list of [`Vertex`] organized //! as triangles with counter-clockwise winding. Here we'll use the builder -//! pattern to create a staged [`Primitive`](crate::stage::Primitive) using our -//! vertices. +//! pattern to create a staged [`Primitive`] using our vertices. //! -//! We'll also create a [`Camera`](crate::camera::Camera) so we can see the -//! stage. +//! We'll also create a [`Camera`] so we can see the stage. //! //! ``` -//! # use renderling::prelude::*; +//! # use renderling::{context::Context, geometry::Vertex, stage::Stage}; //! # let ctx = futures_lite::future::block_on(Context::headless(100, 100)); //! # let stage: Stage = ctx.new_stage(); //! let vertices = stage.new_vertices([ @@ -98,25 +95,20 @@ //! .new_primitive() //! .with_vertices(vertices); //! -//! let (projection, view) = renderling::camera::default_ortho2d(100.0, 100.0); -//! let camera = stage.new_camera() -//! .with_projection_and_view(projection, view); +//! let camera = stage.new_camera().with_default_ortho2d(100.0, 100.0); //! ``` //! //! ### Rendering //! //! Finally, we get the next frame from the context with -//! [`Context::get_next_frame`]. Then we render to it using -//! [`Stage::render`](crate::stage::Stage::render) and then present the -//! frame with [`Frame::present`]. +//! [`Context::get_next_frame`]. Then we render to it using [`Stage::render`] +//! and then present the frame with [`Frame::present`]. //! //! ``` -//! # use renderling::prelude::*; +//! # use renderling::{context::Context, geometry::Vertex, stage::Stage}; //! # let ctx = futures_lite::future::block_on(Context::headless(100, 100)); //! # let stage = ctx.new_stage(); -//! # let (projection, view) = renderling::camera::default_ortho2d(100.0, 100.0); -//! # let camera = stage.new_camera() -//! # .with_projection_and_view(projection, view); +//! # let camera = stage.new_camera().with_default_ortho2d(100.0, 100.0); //! # let vertices = stage.new_vertices([ //! # Vertex::default() //! # .with_position([0.0, 0.0, 0.0]) @@ -142,41 +134,53 @@ //! //! ![renderling hello triangle](https://github.com/schell/renderling/blob/main/test_img/cmy_triangle/hdr.png?raw=true) //! -//! ### Modifying +//! ### Modifying resources //! -//! Later, if we want to modify any of the staged values, we can do so through each resource's -//! struct, using `set_*`, `modify_*` and `with_*` functions. +//! Later, if we want to modify any of the staged values, we can do so through +//! each resource's struct, using `set_*`, `modify_*` and `with_*` functions. //! -//! The changes made will be synchronized to the GPU at the beginning of the next -//! [`Stage::render`](crate::prelude::Stage::render) function. +//! The changes made will be synchronized to the GPU at the beginning of the +//! next [`Stage::render`] function. //! -//! ### Removing primitives +//! ### Removing and hiding primitives //! -//! To remove primitives from the stage, use -//! [`Stage::remove_primitive`](crate::stage::Stage::remove_primitive). This -//! will remove the primitive from rendering entirely. +//! To remove primitives from the stage, use [`Stage::remove_primitive`]. +//! This will remove the primitive from rendering entirely, but the GPU +//! resources will not be released until all clones have been dropped. //! -//! If you just want to mark a [`Primitive`](crate::stage::Primitive) invisible, use -//! [`Primitive::set_visible`](crate::stage::Primitive::set_visible). +//! If you just want to mark a [`Primitive`] invisible, use +//! [`Primitive::set_visible`]. //! //! ### Releasing resources //! -//! GPU resources are automatically released when dropped. The data they -//! occupy on the GPU is reclaimed during calls to -//! [`Stage::render`](crate::stage::Stage::render). If you would like to -//! manually reclaim resources without rendering, you can do so with -//! [`Stage::commit`](crate::stage::Stage::commit). +//! GPU resources are automatically released when all clones are dropped. +//! The data they occupy on the GPU is reclaimed during calls to +//! [`Stage::render`]. +//! If you would like to manually reclaim the resources of fully dropped +//! resources without rendering, you can do so with +//! [`Stage::commit`]. //! -//! [`Primitive`](crate::stage::Primitive) and -//! [`AnalyticalLight`](crate::light::AnalyticalLight) are special in that you -//! must remove them from the [`Stage`](crate::stage::Stage) explicitly, because -//! clones are made internally. +//! #### Ensuring resources are released //! -//! Other resources like [`Vertices`](crate::geometry::Vertices), -//! [`Indices`](crate::geometry::Indices), -//! [`Transform`](crate::transform::Transform), -//! [`NestedTransform`](crate::transform::NestedTransform) and others can simply -//! be dropped. +//! Keep in mind that many resource functions (like [`Primitive::set_material`] +//! for example) take another resource as a parameter. In these functions the +//! parameter resource is cloned and held internally. This is done to keep +//! resources that are in use from being released. Therefore if you want a +//! resource to be released, you must ensure that all references to it are +//! removed. You can use the `remove_*` functions on many resources for this +//! purpose, like [`Primitive::remove_material`], for example, which would +//! remove the material from the primitive. After that call, if no other +//! primitives are using that material and the material is dropped from +//! user code, the next call to [`Stage::render`] or [`Stage::commit`] will +//! reclaim the GPU resources of the material to be re-used. +//! +//! Other resources like [`Vertices`], [`Indices`], [`Transform`], +//! [`NestedTransform`] and others can simply be dropped. +//! +//! # Next steps +//! +//! For further introduction to what renderling can do, take a tour of the +//! [`Stage`] type, or get started with [the manual](#todo). //! //! # WARNING //! @@ -184,13 +188,17 @@ //! //! Your mileage may vary, but I hope you get good use out of this library. //! -//! PRs, criticisms and ideas are all very much welcomed [at the repo](https://github.com/schell/renderling). +//! PRs, criticisms and ideas are all very much welcomed [at the +//! repo](https://github.com/schell/renderling). //! //! 😀☕ #![allow(unexpected_cfgs)] #![cfg_attr(target_arch = "spirv", no_std)] #![deny(clippy::disallowed_methods)] +#[cfg(doc)] +use crate::{camera::Camera, geometry::*, primitive::Primitive, stage::Stage, transform::*}; + pub mod atlas; #[cfg(cpu)] pub(crate) mod bindgroup; @@ -206,6 +214,8 @@ pub mod cull; pub mod debug; pub mod draw; pub mod geometry; +#[cfg(all(cpu, gltf))] +pub mod gltf; pub mod ibl; #[cfg(cpu)] pub mod internal; @@ -215,6 +225,7 @@ pub mod linkage; pub mod material; pub mod math; pub mod pbr; +pub mod primitive; pub mod sdf; pub mod skybox; pub mod stage; @@ -237,8 +248,6 @@ pub mod prelude { pub extern crate glam; - pub use crate::{camera::*, geometry::*, light::*, stage::*}; - #[cfg(cpu)] pub use crate::context::*; } diff --git a/crates/renderling/src/light.rs b/crates/renderling/src/light.rs index b553c453..e1b2f1ad 100644 --- a/crates/renderling/src/light.rs +++ b/crates/renderling/src/light.rs @@ -1,23 +1,81 @@ -//! Lighting. +//! Lighting effects. //! -//! Directional, point and spot lights. +//! This module includes support for various types of lights such as +//! directional, point, and spot lights. //! -//! Shadow mapping. +//! Additionally, the module provides shadow mapping to create realistic shadows. //! -//! Tiling. -use crabslab::{Array, Id, Slab, SlabItem}; -use glam::{Mat4, UVec2, UVec3, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles}; -#[cfg(gpu)] -use spirv_std::num_traits::Float; -use spirv_std::{spirv, Image}; +//! Also provided is an implementation of light tiling, a technique that optimizes +//! the rendering of thousands of analytical lights. If you find your scene performing +//! poorly under the load of very many lights, [`LightTiling`] can speed things up. +//! +//! ## Analytical lights +//! +//! Analytical lights are a fundamental lighting effect in a scene. +//! These lights can be created directly from the [`Stage`] using the methods +//! * [`Stage::new_directional_light`] +//! * [`Stage::new_point_light`] +//! * [`Stage::new_spot_light`] +//! +//! Each of these methods returns an [`AnalyticalLight`] instance that can be +//! manipulated to simulate different lighting conditions. +//! +//! Once created, these lights can be positioned and oriented using +//! [`Transform`] or [`NestedTransform`] objects. The [`Transform`] allows you +//! to set the position, rotation, and scale of the light, while +//! [`NestedTransform`] enables hierarchical transformations, which is useful +//! for complex scenes where lights need to follow specific objects or structures. +//! +//! By adjusting the properties of these lights, such as intensity, color, and +//! direction, you can achieve a wide range of lighting effects, from simulating +//! sunlight with directional lights to creating focused spotlights or ambient +//! point lights. These lights can also be combined with shadow mapping +//! techniques to enhance the realism of shadows in the scene. +//! +//! ## Shadow mapping +//! +//! Shadow mapping is a technique used to add realistic shadows to a scene by +//! simulating the way light interacts with objects. +//! +//! To create a [`ShadowMap`], use the [`Stage::new_shadow_map`] method, passing in +//! the light source and desired parameters such as the size of the shadow map +//! and the near and far planes of the light's frustum. Once created, the +//! shadow map needs to be updated each frame (or as needed) using the +//! [`ShadowMap::update`] method, which renders the scene from the light's +//! perspective to determine which areas are in shadow. +//! +//! This technique allows for dynamic shadows that change with the movement of +//! lights and objects, enhancing the realism of the scene. Proper +//! configuration of shadow map parameters, such as bias and resolution, is +//! crucial to achieving high-quality shadows without artifacts, and varies +//! with each scene. +//! +//! ## Light tiling +//! +//! Light tiling is a technique used to optimize the rendering of scenes with a +//! large number of lights. +//! +//! It divides the rendering surface into a grid of tiles, allowing for +//! efficient computation of lighting effects by processing each tile +//! independently and cutting down on the overall lighting calculations. +//! +//! To create a [`LightTiling`], use the [`Stage::new_light_tiling`] method, +//! providing a [`LightTilingConfig`] to specify parameters such as tile size +//! and maximum lights per tile. +//! +//! Once created, the [`LightTiling`] instance should be kept in sync with the +//! scene by calling the [`LightTiling::run`] method each frame, or however you +//! see fit. This method updates the lighting calculations for each tile based +//! on the current scene configuration, ensuring optimal performance even with +//! many lights. +//! +//! By using light tiling, you can significantly improve the performance of your +//! rendering pipeline, especially in complex scenes with numerous light sources. +#[cfg(doc)] use crate::{ - atlas::{AtlasDescriptor, AtlasTextureDescriptor}, - cubemap::{CubemapDescriptor, CubemapFaceDirection}, - geometry::GeometryDescriptor, - math::{Fetch, IsSampler, IsVector, Sample2dArray}, - stage::{PrimitiveDescriptor, VertexInfo}, - transform::TransformDescriptor, + stage::Stage, + transform::{NestedTransform, Transform}, }; #[cfg(cpu)] @@ -35,1219 +93,16 @@ mod tiling; #[cfg(cpu)] pub use tiling::*; -/// Root descriptor of the lighting system. -#[derive(Clone, Copy, Default, SlabItem, core::fmt::Debug)] -#[offsets] -pub struct LightingDescriptor { - /// List of all analytical lights in the scene. - pub analytical_lights_array: Array>, - /// Shadow mapping atlas info. - pub shadow_map_atlas_descriptor_id: Id, - /// `Id` of the [`ShadowMapDescriptor`] to use when updating - /// a shadow map. - /// - /// This changes from each run of the `shadow_mapping_vertex`. - pub update_shadow_map_id: Id, - /// The index of the shadow map atlas texture to update. - pub update_shadow_map_texture_index: u32, - /// `Id` of the [`LightTilingDescriptor`] to use when performing - /// light tiling. - pub light_tiling_descriptor_id: Id, -} - -#[derive(Clone, Copy, SlabItem, core::fmt::Debug)] -pub struct ShadowMapDescriptor { - pub light_space_transforms_array: Array, - /// Near plane of the projection matrix - pub z_near: f32, - /// Far plane of the projection matrix - pub z_far: f32, - /// Pointers to the atlas textures where the shadow map depth - /// data is stored. - /// - /// This will be an array of one `Id` for directional and spot lights, - /// and an array of four `Id`s for a point light. - pub atlas_textures_array: Array>, - pub bias_min: f32, - pub bias_max: f32, - pub pcf_samples: u32, -} - -impl Default for ShadowMapDescriptor { - fn default() -> Self { - Self { - light_space_transforms_array: Default::default(), - z_near: Default::default(), - z_far: Default::default(), - atlas_textures_array: Default::default(), - bias_min: 0.0005, - bias_max: 0.005, - pcf_samples: 4, - } - } -} - -#[cfg(test)] -#[derive(Default, Debug, Clone, Copy, PartialEq)] -pub struct ShadowMappingVertexInfo { - pub renderlet_id: Id, - pub vertex_index: u32, - pub vertex: crate::geometry::Vertex, - pub transform: TransformDescriptor, - pub model_matrix: Mat4, - pub world_pos: Vec3, - pub view_projection: Mat4, - pub clip_pos: Vec4, -} - -/// Shadow mapping vertex shader. -/// -/// It is assumed that a [`LightingDescriptor`] is stored at `Id(0)` of the -/// `light_slab`. -/// -/// This shader reads the [`LightingDescriptor`] to find the shadow map to -/// be updated, then determines the clip positions to emit based on the -/// shadow map's atlas texture. -/// -/// It then renders the renderlet into the designated atlas frame. -// Note: -// If this is taking too long to render for each renderlet, think about -// a frustum and occlusion culling pass to generate the list of renderlets. -#[spirv(vertex)] -#[allow(clippy::too_many_arguments)] -pub fn shadow_mapping_vertex( - // Points at a `Renderlet` - #[spirv(instance_index)] renderlet_id: Id, - // Which vertex within the renderlet are we rendering - #[spirv(vertex_index)] vertex_index: u32, - // The slab where the renderlet's geometry is staged - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], - // The slab where the scene's lighting data is staged - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] light_slab: &[u32], - - #[spirv(position)] out_clip_pos: &mut Vec4, - #[cfg(test)] out_comparison_info: &mut ShadowMappingVertexInfo, -) { - let renderlet = geometry_slab.read_unchecked(renderlet_id); - if !renderlet.visible { - // put it outside the clipping frustum - *out_clip_pos = Vec4::new(100.0, 100.0, 100.0, 1.0); - return; - } - - let VertexInfo { - world_pos, - vertex: _vertex, - transform: _transform, - model_matrix: _model_matrix, - } = renderlet.get_vertex_info(vertex_index, geometry_slab); - - let lighting_desc = light_slab.read_unchecked(Id::::new(0)); - let shadow_desc = light_slab.read_unchecked(lighting_desc.update_shadow_map_id); - let light_space_transform_id = shadow_desc - .light_space_transforms_array - .at(lighting_desc.update_shadow_map_texture_index as usize); - let light_space_transform = light_slab.read_unchecked(light_space_transform_id); - let clip_pos = light_space_transform * world_pos.extend(1.0); - #[cfg(test)] - { - *out_comparison_info = ShadowMappingVertexInfo { - renderlet_id, - vertex_index, - vertex: _vertex, - transform: _transform, - model_matrix: _model_matrix, - world_pos, - view_projection: light_space_transform, - clip_pos, - }; - } - *out_clip_pos = clip_pos; -} - -#[spirv(fragment)] -pub fn shadow_mapping_fragment(clip_pos: Vec4, frag_color: &mut Vec4) { - *frag_color = (clip_pos.xyz() / clip_pos.w).extend(1.0); -} - -/// Contains values needed to determine the outgoing radiance of a fragment. -/// -/// For more info, see the **Spotlight** section of the -/// [learnopengl](https://learnopengl.com/Lighting/Light-casters) -/// article. -#[derive(Clone, Copy, Default, core::fmt::Debug)] -pub struct SpotLightCalculation { - /// Position of the light in world space - pub light_position: Vec3, - /// Position of the fragment in world space - pub frag_position: Vec3, - /// Unit vector (LightDir) pointing from the fragment to the light - pub frag_to_light: Vec3, - /// Distance from the fragment to the light - pub frag_to_light_distance: f32, - /// Unit vector (SpotDir) direction that the light is pointing in - pub light_direction: Vec3, - /// The cosine of the cutoff angle (Phi Ï•) that specifies the spotlight's radius. - /// - /// Everything inside this angle is lit by the spotlight. - pub cos_inner_cutoff: f32, - /// The cosine of the cutoff angle (Gamma γ) that specifies the spotlight's outer radius. - /// - /// Everything outside this angle is not lit by the spotlight. - /// - /// Fragments between `inner_cutoff` and `outer_cutoff` have an intensity - /// between `1.0` and `0.0`. - pub cos_outer_cutoff: f32, - /// Whether the fragment is inside the `inner_cutoff` cone. - pub fragment_is_inside_inner_cone: bool, - /// Whether the fragment is inside the `outer_cutoff` cone. - pub fragment_is_inside_outer_cone: bool, - /// `outer_cutoff` - `inner_cutoff` - pub epsilon: f32, - /// Cosine of the angle (Theta θ) between `frag_to_light` (LightDir) vector and the - /// `light_direction` (SpotDir) vector. - /// - /// θ should be smaller than `outer_cutoff` (Gamma γ) to be - /// inside the spotlight, but since these are all cosines of angles, we actually - /// compare using `>`. - pub cos_theta: f32, - pub contribution_unclamped: f32, - /// The intensity level between `0.0` and `1.0` that should be used to determine - /// outgoing radiance. - pub contribution: f32, -} - -impl SpotLightCalculation { - /// Calculate the values required to determine outgoing radiance of a spot light. - pub fn new( - spot_light_descriptor: SpotLightDescriptor, - node_transform: Mat4, - fragment_world_position: Vec3, - ) -> Self { - let light_position = node_transform.transform_point3(spot_light_descriptor.position); - let frag_position = fragment_world_position; - let frag_to_light = light_position - frag_position; - let frag_to_light_distance = frag_to_light.length(); - if frag_to_light_distance == 0.0 { - crate::println!("frag_to_light_distance: {frag_to_light_distance}"); - return Self::default(); - } - let frag_to_light = frag_to_light.alt_norm_or_zero(); - let light_direction = node_transform - .transform_vector3(spot_light_descriptor.direction) - .alt_norm_or_zero(); - let cos_inner_cutoff = spot_light_descriptor.inner_cutoff.cos(); - let cos_outer_cutoff = spot_light_descriptor.outer_cutoff.cos(); - let epsilon = cos_inner_cutoff - cos_outer_cutoff; - let cos_theta = frag_to_light.dot(-light_direction); - let fragment_is_inside_inner_cone = cos_theta > cos_inner_cutoff; - let fragment_is_inside_outer_cone = cos_theta > cos_outer_cutoff; - let contribution_unclamped = (cos_theta - cos_outer_cutoff) / epsilon; - let contribution = contribution_unclamped.clamp(0.0, 1.0); - Self { - light_position, - frag_position, - frag_to_light, - frag_to_light_distance, - light_direction, - cos_inner_cutoff, - cos_outer_cutoff, - fragment_is_inside_inner_cone, - fragment_is_inside_outer_cone, - epsilon, - cos_theta, - contribution_unclamped, - contribution, - } - } -} - -/// Description of a spot light. -/// -/// ## Tips -/// -/// If your spotlight is not illuminating your scenery, ensure that the -/// `inner_cutoff` and `outer_cutoff` values are "correct". `outer_cutoff` -/// should be _greater than_ `inner_cutoff` and the values should be a large -/// enough to cover at least one pixel at the distance between the light and -/// the scenery. -#[repr(C)] -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Copy, Clone, SlabItem)] -pub struct SpotLightDescriptor { - pub position: Vec3, - pub direction: Vec3, - pub inner_cutoff: f32, - pub outer_cutoff: f32, - pub color: Vec4, - pub intensity: f32, -} - -impl Default for SpotLightDescriptor { - fn default() -> Self { - let white = Vec4::splat(1.0); - let inner_cutoff = 0.077143565; - let outer_cutoff = 0.09075713; - let direction = Vec3::new(0.0, -1.0, 0.0); - let color = white; - let intensity = 1.0; - - Self { - position: Default::default(), - direction, - inner_cutoff, - outer_cutoff, - color, - intensity, - } - } -} - -impl SpotLightDescriptor { - pub fn shadow_mapping_projection_and_view( - &self, - parent_light_transform: &Mat4, - z_near: f32, - z_far: f32, - ) -> (Mat4, Mat4) { - let fovy = 2.0 * self.outer_cutoff; - let aspect = 1.0; - let projection = Mat4::perspective_rh(fovy, aspect, z_near, z_far); - let direction = parent_light_transform - .transform_vector3(self.direction) - .alt_norm_or_zero(); - let position = parent_light_transform.transform_point3(self.position); - let up = direction.orthonormal_vectors()[0]; - let view = Mat4::look_to_rh(position, direction, up); - (projection, view) - } -} - -#[repr(C)] -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Copy, Clone, SlabItem)] -pub struct DirectionalLightDescriptor { - pub direction: Vec3, - pub color: Vec4, - pub intensity: f32, -} - -impl Default for DirectionalLightDescriptor { - fn default() -> Self { - let direction = Vec3::new(0.0, -1.0, 0.0); - let color = Vec4::splat(1.0); - let intensity = 1.0; - - Self { - direction, - color, - intensity, - } - } -} - -impl DirectionalLightDescriptor { - pub fn shadow_mapping_projection_and_view( - &self, - parent_light_transform: &Mat4, - // Near limits of the light's reach - // - // The maximum should be the `Camera`'s `Frustum::depth()`. - // TODO: in `DirectionalLightDescriptor::shadow_mapping_projection_and_view`, take Frustum - // as a parameter and then figure out the minimal view projection that includes that frustum - z_near: f32, - // Far limits of the light's reach - z_far: f32, - ) -> (Mat4, Mat4) { - crate::println!("descriptor: {self:#?}"); - let depth = (z_far - z_near).abs(); - let hd = depth * 0.5; - let projection = Mat4::orthographic_rh(-hd, hd, -hd, hd, z_near, z_far); - let direction = parent_light_transform - .transform_vector3(self.direction) - .alt_norm_or_zero(); - let position = -direction * depth * 0.5; - crate::println!("direction: {direction}"); - crate::println!("position: {position}"); - let up = direction.orthonormal_vectors()[0]; - let view = Mat4::look_to_rh(position, direction, up); - (projection, view) - } -} - -#[repr(C)] -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Copy, Clone, SlabItem)] -pub struct PointLightDescriptor { - pub position: Vec3, - pub color: Vec4, - /// Expressed as candelas. - pub intensity: f32, -} - -impl Default for PointLightDescriptor { - fn default() -> Self { - let color = Vec4::splat(1.0); - let intensity = 1.0; - - Self { - position: Default::default(), - color, - intensity, - } - } -} - -impl PointLightDescriptor { - pub fn shadow_mapping_view_matrix( - &self, - face_index: usize, - parent_light_transform: &Mat4, - ) -> Mat4 { - let eye = parent_light_transform.transform_point3(self.position); - let mut face = CubemapFaceDirection::FACES[face_index]; - face.eye = eye; - face.view() - } - - pub fn shadow_mapping_projection_matrix(z_near: f32, z_far: f32) -> Mat4 { - Mat4::perspective_lh(core::f32::consts::FRAC_PI_2, 1.0, z_near, z_far) - } - - pub fn shadow_mapping_projection_and_view_matrices( - &self, - parent_light_transform: &Mat4, - z_near: f32, - z_far: f32, - ) -> (Mat4, [Mat4; 6]) { - let p = Self::shadow_mapping_projection_matrix(z_near, z_far); - let eye = parent_light_transform.transform_point3(self.position); - ( - p, - CubemapFaceDirection::FACES.map(|mut face| { - face.eye = eye; - face.view() - }), - ) - } -} - -/// Returns the radius of illumination in meters. -/// -/// * Moonlight: < 1 lux. -/// - Full moon on a clear night: 0.25 lux. -/// - Quarter moon: 0.01 lux -/// - Starlight overcast moonless night sky: 0.0001 lux. -/// * General indoor lighting: Around 100 to 300 lux. -/// * Office lighting: Typically around 300 to 500 lux. -/// * Reading or task lighting: Around 500 to 750 lux. -/// * Detailed work (e.g., drafting, surgery): 1000 lux or more. -pub fn radius_of_illumination(intensity_candelas: f32, minimum_illuminance_lux: f32) -> f32 { - (intensity_candelas / minimum_illuminance_lux).sqrt() -} - -#[repr(u32)] -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Copy, Clone, PartialEq)] -pub enum LightStyle { - Directional = 0, - Point = 1, - Spot = 2, -} - -impl core::fmt::Display for LightStyle { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - LightStyle::Directional => f.write_str("directional"), - LightStyle::Point => f.write_str("point"), - LightStyle::Spot => f.write_str("spot"), - } - } -} - -impl SlabItem for LightStyle { - const SLAB_SIZE: usize = { 1 }; - - fn read_slab(index: usize, slab: &[u32]) -> Self { - let proxy = u32::read_slab(index, slab); - match proxy { - 0 => LightStyle::Directional, - 1 => LightStyle::Point, - 2 => LightStyle::Spot, - _ => LightStyle::Directional, - } - } - - fn write_slab(&self, index: usize, slab: &mut [u32]) -> usize { - let proxy = *self as u32; - proxy.write_slab(index, slab) - } -} - -/// A generic light that is used as a slab pointer to a -/// specific light type. -#[repr(C)] -#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] -#[derive(Copy, Clone, PartialEq, SlabItem)] -pub struct LightDescriptor { - /// The type of the light - pub light_type: LightStyle, - /// The index of the light in the lighting slab - pub index: u32, - /// The id of a transform to apply to the position and direction of the light. - /// - /// This `Id` points to a transform on the lighting slab. - /// - /// The value of this descriptor can be synchronized with that of a node - /// transform on the geometry slab from - /// [`crate::light::AnalyticalLight::link_node_transform`]. - pub transform_id: Id, - /// The id of the shadow map in use by this light. - pub shadow_map_desc_id: Id, -} - -impl Default for LightDescriptor { - fn default() -> Self { - Self { - light_type: LightStyle::Directional, - index: Id::<()>::NONE.inner(), - transform_id: Id::NONE, - shadow_map_desc_id: Id::NONE, - } - } -} - -impl From> for LightDescriptor { - fn from(id: Id) -> Self { - Self { - light_type: LightStyle::Directional, - index: id.inner(), - transform_id: Id::NONE, - shadow_map_desc_id: Id::NONE, - } - } -} - -impl From> for LightDescriptor { - fn from(id: Id) -> Self { - Self { - light_type: LightStyle::Spot, - index: id.inner(), - transform_id: Id::NONE, - shadow_map_desc_id: Id::NONE, - } - } -} - -impl From> for LightDescriptor { - fn from(id: Id) -> Self { - Self { - light_type: LightStyle::Point, - index: id.inner(), - transform_id: Id::NONE, - shadow_map_desc_id: Id::NONE, - } - } -} - -impl LightDescriptor { - pub fn into_directional_id(self) -> Id { - Id::from(self.index) - } - - pub fn into_spot_id(self) -> Id { - Id::from(self.index) - } - - pub fn into_point_id(self) -> Id { - Id::from(self.index) - } -} - -/// Parameters to the shadow mapping calculation function. -/// -/// This is mostly just to appease clippy. -pub struct ShadowCalculation { - pub shadow_map_desc: ShadowMapDescriptor, - pub shadow_map_atlas_size: UVec2, - pub surface_normal_in_world_space: Vec3, - pub frag_pos_in_world_space: Vec3, - pub frag_to_light_in_world_space: Vec3, - pub bias_min: f32, - pub bias_max: f32, - pub pcf_samples: u32, -} - -impl ShadowCalculation { - /// Reads various required parameters from the slab and creates a `ShadowCalculation`. - pub fn new( - light_slab: &[u32], - light: crate::prelude::LightDescriptor, - in_pos: Vec3, - surface_normal: Vec3, - light_direction: Vec3, - ) -> Self { - let shadow_map_desc = light_slab.read_unchecked(light.shadow_map_desc_id); - let atlas_size = { - let lighting_desc_id = Id::::new(0); - let atlas_desc_id = light_slab.read_unchecked( - lighting_desc_id + LightingDescriptor::OFFSET_OF_SHADOW_MAP_ATLAS_DESCRIPTOR_ID, - ); - let atlas_desc = light_slab.read_unchecked(atlas_desc_id); - atlas_desc.size - }; - - ShadowCalculation { - shadow_map_desc, - shadow_map_atlas_size: atlas_size.xy(), - surface_normal_in_world_space: surface_normal, - frag_pos_in_world_space: in_pos, - frag_to_light_in_world_space: light_direction, - bias_min: shadow_map_desc.bias_min, - bias_max: shadow_map_desc.bias_max, - pcf_samples: shadow_map_desc.pcf_samples, - } - } - - fn get_atlas_texture_at(&self, light_slab: &[u32], index: usize) -> AtlasTextureDescriptor { - let atlas_texture_id = - light_slab.read_unchecked(self.shadow_map_desc.atlas_textures_array.at(index)); - light_slab.read_unchecked(atlas_texture_id) - } - - fn get_frag_pos_in_light_space(&self, light_slab: &[u32], index: usize) -> Vec3 { - let light_space_transform_id = self.shadow_map_desc.light_space_transforms_array.at(index); - let light_space_transform = light_slab.read_unchecked(light_space_transform_id); - light_space_transform.project_point3(self.frag_pos_in_world_space) - } - - /// Returns shadow _intensity_ for directional and spot lights. - /// - /// Returns `0.0` when the fragment is in full light. - /// Returns `1.0` when the fragment is in full shadow. - pub fn run_directional_or_spot( - &self, - light_slab: &[u32], - shadow_map: &T, - shadow_map_sampler: &S, - ) -> f32 - where - S: IsSampler, - T: Sample2dArray, - { - let ShadowCalculation { - shadow_map_desc: _, - shadow_map_atlas_size, - frag_pos_in_world_space: _, - surface_normal_in_world_space: surface_normal, - frag_to_light_in_world_space: light_direction, - bias_min, - bias_max, - pcf_samples, - } = self; - let frag_pos_in_light_space = self.get_frag_pos_in_light_space(light_slab, 0); - crate::println!("frag_pos_in_light_space: {frag_pos_in_light_space}"); - if !crate::math::is_inside_clip_space(frag_pos_in_light_space.xyz()) { - return 0.0; - } - // The range of coordinates in the light's clip space is -1.0 to 1.0 for x and y, - // but the texture space is [0, 1], and Y increases downward, so we do this - // conversion to flip Y and also normalize to the range [0.0, 1.0]. - // Z should already be 0.0 to 1.0. - let proj_coords_uv = (frag_pos_in_light_space.xy() * Vec2::new(1.0, -1.0) - + Vec2::splat(1.0)) - * Vec2::splat(0.5); - crate::println!("proj_coords_uv: {proj_coords_uv}"); - - let shadow_map_atlas_texture = self.get_atlas_texture_at(light_slab, 0); - // With these projected coordinates we can sample the depth map as the - // resulting [0,1] coordinates from proj_coords directly correspond to - // the transformed NDC coordinates from the `ShadowMap::update` render pass. - // This gives us the closest depth from the light's point of view: - let pcf_samples_2 = *pcf_samples as i32 / 2; - let texel_size = 1.0 - / Vec2::new( - shadow_map_atlas_texture.size_px.x as f32, - shadow_map_atlas_texture.size_px.y as f32, - ); - let mut shadow = 0.0f32; - let mut total = 0.0f32; - for x in -pcf_samples_2..=pcf_samples_2 { - for y in -pcf_samples_2..=pcf_samples_2 { - let proj_coords = shadow_map_atlas_texture.uv( - proj_coords_uv + Vec2::new(x as f32, y as f32) * texel_size, - *shadow_map_atlas_size, - ); - let shadow_map_depth = shadow_map - .sample_by_lod(*shadow_map_sampler, proj_coords, 0.0) - .x; - // To get the current depth at this fragment we simply retrieve the projected vector's z - // coordinate which equals the depth of this fragment from the light's perspective. - let fragment_depth = frag_pos_in_light_space.z; - - // If the `current_depth`, which is the depth of the fragment from the lights POV, is - // greater than the `closest_depth` of the shadow map at that fragment, the fragment - // is in shadow - crate::println!("current_depth: {fragment_depth}"); - crate::println!("closest_depth: {shadow_map_depth}"); - let bias = (bias_max * (1.0 - surface_normal.dot(*light_direction))).max(*bias_min); - - if (fragment_depth - bias) >= shadow_map_depth { - shadow += 1.0 - } - total += 1.0; - } - } - shadow / total.max(1.0) - } - - pub const POINT_SAMPLE_OFFSET_DIRECTIONS: [Vec3; 21] = [ - Vec3::ZERO, - Vec3::new(1.0, 1.0, 1.0), - Vec3::new(1.0, -1.0, 1.0), - Vec3::new(-1.0, -1.0, 1.0), - Vec3::new(-1.0, 1.0, 1.0), - Vec3::new(1.0, 1.0, -1.0), - Vec3::new(1.0, -1.0, -1.0), - Vec3::new(-1.0, -1.0, -1.0), - Vec3::new(-1.0, 1.0, -1.0), - Vec3::new(1.0, 1.0, 0.0), - Vec3::new(1.0, -1.0, 0.0), - Vec3::new(-1.0, -1.0, 0.0), - Vec3::new(-1.0, 1.0, 0.0), - Vec3::new(1.0, 0.0, 1.0), - Vec3::new(-1.0, 0.0, 1.0), - Vec3::new(1.0, 0.0, -1.0), - Vec3::new(-1.0, 0.0, -1.0), - Vec3::new(0.0, 1.0, 1.0), - Vec3::new(0.0, -1.0, 1.0), - Vec3::new(0.0, -1.0, -1.0), - Vec3::new(0.0, 1.0, -1.0), - ]; - /// Returns shadow _intensity_ for point lights. - /// - /// Returns `0.0` when the fragment is in full light. - /// Returns `1.0` when the fragment is in full shadow. - pub fn run_point( - &self, - light_slab: &[u32], - shadow_map: &T, - shadow_map_sampler: &S, - light_pos_in_world_space: Vec3, - ) -> f32 - where - S: IsSampler, - T: Sample2dArray, - { - let ShadowCalculation { - shadow_map_desc, - shadow_map_atlas_size, - frag_pos_in_world_space, - surface_normal_in_world_space: surface_normal, - frag_to_light_in_world_space: frag_to_light, - bias_min, - bias_max, - pcf_samples, - } = self; - - let light_to_frag_dir = frag_pos_in_world_space - light_pos_in_world_space; - crate::println!("light_to_frag_dir: {light_to_frag_dir}"); - - let pcf_samplesf = (*pcf_samples as f32) - .max(1.0) - .min(Self::POINT_SAMPLE_OFFSET_DIRECTIONS.len() as f32); - let pcf_samples = pcf_samplesf as usize; - let view_distance = light_to_frag_dir.length(); - let disk_radius = (1.0 + view_distance / shadow_map_desc.z_far) / 25.0; - let mut shadow = 0.0f32; - for i in 0..pcf_samples { - let sample_offset = Self::POINT_SAMPLE_OFFSET_DIRECTIONS[i] * disk_radius; - crate::println!("sample_offset: {sample_offset}"); - let sample_dir = (light_to_frag_dir + sample_offset).alt_norm_or_zero(); - let (face_index, uv) = CubemapDescriptor::get_face_index_and_uv(sample_dir); - crate::println!("face_index: {face_index}",); - crate::println!("uv: {uv}"); - let frag_pos_in_light_space = self.get_frag_pos_in_light_space(light_slab, face_index); - let face_texture = self.get_atlas_texture_at(light_slab, face_index); - let uv_tex = face_texture.uv(uv, *shadow_map_atlas_size); - let shadow_map_depth = shadow_map.sample_by_lod(*shadow_map_sampler, uv_tex, 0.0).x; - let fragment_depth = frag_pos_in_light_space.z; - let bias = (bias_max * (1.0 - surface_normal.dot(*frag_to_light))).max(*bias_min); - if (fragment_depth - bias) > shadow_map_depth { - shadow += 1.0 - } - } - - shadow / pcf_samplesf - } -} - -/// Depth pre-pass for the light tiling feature. -/// -/// This shader writes all staged [`PrimitiveDescriptor`]'s depth into a buffer. -/// -/// This shader is very much like [`shadow_mapping_vertex`], except that -/// shader gets its projection+view matrix from the light stored in a -/// `ShadowMapDescriptor`. -/// -/// Here we want to render as normal forward pass would, with the `PrimitiveDescriptor` -/// and the `Camera`'s view projection matrix. -/// ## Note -/// This shader will likely be expanded to include parts of occlusion culling and order -/// independent transparency. -#[spirv(vertex)] -pub fn light_tiling_depth_pre_pass( - // Points at a `Renderlet`. - #[spirv(instance_index)] renderlet_id: Id, - // Which vertex within the renderlet are we rendering? - #[spirv(vertex_index)] vertex_index: u32, - // The slab where the renderlet's geometry is staged - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], - // Output clip coords - #[spirv(position)] out_clip_pos: &mut Vec4, -) { - let renderlet = geometry_slab.read_unchecked(renderlet_id); - if !renderlet.visible { - // put it outside the clipping frustum - *out_clip_pos = Vec3::splat(100.0).extend(1.0); - return; - } - - let camera_id = geometry_slab - .read_unchecked(Id::::new(0) + GeometryDescriptor::OFFSET_OF_CAMERA_ID); - let camera = geometry_slab.read_unchecked(camera_id); - - let VertexInfo { world_pos, .. } = renderlet.get_vertex_info(vertex_index, geometry_slab); - - *out_clip_pos = camera.view_projection() * world_pos.extend(1.0); -} - -pub type DepthImage2d = Image!(2D, type=f32, sampled, depth); - -pub type DepthImage2dMultisampled = Image!(2D, type=f32, sampled, depth, multisampled=true); - -/// A tile of screen space used to cull lights. -#[derive(Clone, Copy, Default, SlabItem)] -#[offsets] -pub struct LightTile { - /// Minimum depth of objects found within the frustum of the tile. - pub depth_min: u32, - /// Maximum depth of objects foudn within the frustum of the tile. - pub depth_max: u32, - /// The count of lights in this tile. - /// - /// Also, the next available light index. - pub next_light_index: u32, - /// List of light ids that intersect this tile's frustum. - pub lights_array: Array>, -} - -impl core::fmt::Debug for LightTile { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_struct("LightTile") - .field("depth_min", &dequantize_depth_u32_to_f32(self.depth_min)) - .field("depth_max", &dequantize_depth_u32_to_f32(self.depth_max)) - .field("next_light_index", &self.next_light_index) - .field("lights_array", &self.lights_array) - .finish() - } -} - -/// Descriptor of the light tiling operation, which culls lights by accumulating -/// them into lists that illuminate tiles of the screen. -#[derive(Clone, Copy, SlabItem, core::fmt::Debug)] -pub struct LightTilingDescriptor { - /// Size of the [`Stage`](crate::stage::Stage)'s depth texture. - pub depth_texture_size: UVec2, - /// Configurable tile size. - pub tile_size: u32, - /// Array pointing to the lighting "tiles". - pub tiles_array: Array, - /// Minimum illuminance. - /// - /// Used to determine whether a light illuminates a tile. - pub minimum_illuminance_lux: f32, -} - -impl Default for LightTilingDescriptor { - fn default() -> Self { - Self { - depth_texture_size: Default::default(), - tile_size: 16, - tiles_array: Default::default(), - minimum_illuminance_lux: 0.1, - } - } -} - -impl LightTilingDescriptor { - /// Returns the dimensions of the grid of tiles. - pub fn tile_grid_size(&self) -> UVec2 { - let dims_f32 = self.depth_texture_size.as_vec2() / self.tile_size as f32; - dims_f32.ceil().as_uvec2() - } - - pub fn tile_coord_for_fragment(&self, frag_coord: Vec2) -> UVec2 { - let frag_coord = frag_coord.as_uvec2(); - frag_coord / self.tile_size - } - - pub fn tile_index_for_fragment(&self, frag_coord: Vec2) -> usize { - let tile_coord = self.tile_coord_for_fragment(frag_coord); - let tile_dimensions = self.tile_grid_size(); - (tile_coord.y * tile_dimensions.x + tile_coord.x) as usize - } -} - -/// Quantizes a fragment depth from `f32` to `u32`. -pub fn quantize_depth_f32_to_u32(depth: f32) -> u32 { - (u32::MAX as f32 * depth).round() as u32 -} - -/// Reconstructs a previously quantized depth from a `u32`. -pub fn dequantize_depth_u32_to_f32(depth: u32) -> f32 { - depth as f32 / u32::MAX as f32 -} - -/// Helper for determining the next light to check during an -/// invocation of the light list computation. -struct NextLightIndex { - current_step: usize, - tile_size: u32, - lights: Array>, - global_id: UVec3, -} - -impl Iterator for NextLightIndex { - type Item = Id>; - - fn next(&mut self) -> Option { - let next_index = self.next_index(); - self.current_step += 1; - if next_index < self.lights.len() { - Some(self.lights.at(next_index)) - } else { - None - } - } -} - -impl NextLightIndex { - pub fn new( - global_id: UVec3, - tile_size: u32, - analytical_lights_array: Array>, - ) -> Self { - Self { - current_step: 0, - tile_size, - lights: analytical_lights_array, - global_id, - } - } - - pub fn next_index(&self) -> usize { - // Determine the xy coord of this invocation within the _tile_ - let frag_tile_xy = self.global_id.xy() % self.tile_size; - // Determine the index of this invocation within the _tile_ - let offset = frag_tile_xy.y * self.tile_size + frag_tile_xy.x; - let stride = (self.tile_size * self.tile_size) as usize; - self.current_step * stride + offset as usize - } -} - -struct LightTilingInvocation { - global_id: UVec3, - descriptor: LightTilingDescriptor, -} - -impl LightTilingInvocation { - fn new(global_id: UVec3, descriptor: LightTilingDescriptor) -> Self { - Self { - global_id, - descriptor, - } - } - - /// The fragment's position. - /// - /// X range is 0 to (width - 1), Y range is 0 to (height - 1). - fn frag_pos(&self) -> UVec2 { - self.global_id.xy() - } - - /// The number of tiles in X and Y within the depth texture. - fn tile_grid_size(&self) -> UVec2 { - self.descriptor.tile_grid_size() - } - - /// The tile's coordinate among all tiles in the tile grid. - /// - /// The units are in tile x y. - fn tile_coord(&self) -> UVec2 { - self.global_id.xy() / self.descriptor.tile_size - } - - /// The tile's index in all the [`LightTilingDescriptor`]'s `tile_array`. - fn tile_index(&self) -> usize { - let tile_pos = self.tile_coord(); - let tile_dimensions = self.tile_grid_size(); - (tile_pos.y * tile_dimensions.x + tile_pos.x) as usize - } - - /// The tile's normalized midpoint. - fn tile_ndc_midpoint(&self) -> Vec2 { - let min_coord = self.tile_coord().as_vec2(); - let mid_coord = min_coord + 0.5; - crate::math::convert_pixel_to_ndc(mid_coord, self.tile_grid_size()) - } - - /// Compute the min and max depth of one fragment/invocation for light tiling. - /// - /// The min and max is stored in a tile on lighting slab. - fn compute_min_and_max_depth( - &self, - depth_texture: &impl Fetch, - lighting_slab: &mut [u32], - ) { - let frag_pos = self.frag_pos(); - let depth_texture_size = self.descriptor.depth_texture_size; - if frag_pos.x >= depth_texture_size.x || frag_pos.y >= depth_texture_size.y { - return; - } - // Depth frag value at the fragment position - let frag_depth: f32 = depth_texture.fetch(frag_pos).x; - // Fragment depth scaled to min/max of u32 values - // - // This is so we can compare with normal atomic ops instead of using the float extension - let frag_depth_u32 = quantize_depth_f32_to_u32(frag_depth); - - // The tile's index in all the tiles - let tile_index = self.tile_index(); - let lighting_desc = lighting_slab.read_unchecked(Id::::new(0)); - let tiling_desc = lighting_slab.read_unchecked(lighting_desc.light_tiling_descriptor_id); - // index of the tile's min depth atomic value in the lighting slab - let tile_id = tiling_desc.tiles_array.at(tile_index); - let min_depth_index = tile_id + LightTile::OFFSET_OF_DEPTH_MIN; - // index of the tile's max depth atomic value in the lighting slab - let max_depth_index = tile_id + LightTile::OFFSET_OF_DEPTH_MAX; - - let _prev_min_depth = crate::sync::atomic_u_min::< - { spirv_std::memory::Scope::Workgroup as u32 }, - { spirv_std::memory::Semantics::WORKGROUP_MEMORY.bits() }, - >(lighting_slab, min_depth_index, frag_depth_u32); - let _prev_max_depth = crate::sync::atomic_u_max::< - { spirv_std::memory::Scope::Workgroup as u32 }, - { spirv_std::memory::Semantics::WORKGROUP_MEMORY.bits() }, - >(lighting_slab, max_depth_index, frag_depth_u32); - } - - /// Determine whether this invocation should run. - fn should_invoke(&self) -> bool { - self.global_id.x < self.descriptor.depth_texture_size.x - && self.global_id.y < self.descriptor.depth_texture_size.y - } - - /// Clears one tile. - /// - /// ## Note - /// This is only valid to call from the [`light_tiling_clear_tiles`] shader. - fn clear_tile(&self, lighting_slab: &mut [u32]) { - let dimensions = self.tile_grid_size(); - let index = (self.global_id.y * dimensions.x + self.global_id.x) as usize; - if index < self.descriptor.tiles_array.len() { - let tile_id = self.descriptor.tiles_array.at(index); - let mut tile = lighting_slab.read(tile_id); - tile.depth_min = u32::MAX; - tile.depth_max = 0; - tile.next_light_index = 0; - lighting_slab.write(tile_id, &tile); - // Zero out the light list and the ratings - for id in tile.lights_array.iter() { - lighting_slab.write(id, &Id::NONE); - } - } - } - - // The difficulty here is that in SPIRV we can access `lighting_slab` atomically without wrapping it - // in a type, but on CPU we must pass an array of (something like) `AtomicU32`. I'm not sure how to - // model this interaction to test it on the CPU. - fn compute_light_lists(&self, geometry_slab: &[u32], lighting_slab: &mut [u32]) { - let index = self.tile_index(); - let tile_id = self.descriptor.tiles_array.at(index); - // Construct the tile's frustum in clip space. - let depth_min_u32 = lighting_slab.read_unchecked(tile_id + LightTile::OFFSET_OF_DEPTH_MIN); - let depth_max_u32 = lighting_slab.read_unchecked(tile_id + LightTile::OFFSET_OF_DEPTH_MAX); - let depth_min = dequantize_depth_u32_to_f32(depth_min_u32); - let depth_max = dequantize_depth_u32_to_f32(depth_max_u32); - - if depth_min == depth_max { - // If we would construct a frustum with zero volume, abort. - // - // See - // for more info. - return; - } - - let camera_id = geometry_slab.read_unchecked( - Id::::new(0) + GeometryDescriptor::OFFSET_OF_CAMERA_ID, - ); - let camera = geometry_slab.read_unchecked(camera_id); - - // let (ndc_tile_min, ndc_tile_max) = self.tile_ndc_min_max(); - // // This is the AABB frustum, in NDC coords - // let ndc_tile_aabb = Aabb::new( - // ndc_tile_min.extend(depth_min), - // ndc_tile_max.extend(depth_max), - // ); - - // Get the frustum (here simplified to a line) in world coords, since we'll be - // using it to compare against the radius of illumination of each light - let tile_ndc_midpoint = self.tile_ndc_midpoint(); - let tile_line_ndc = ( - tile_ndc_midpoint.extend(depth_min), - tile_ndc_midpoint.extend(depth_max), - ); - let inverse_viewproj = camera.view_projection().inverse(); - let tile_line = ( - inverse_viewproj.project_point3(tile_line_ndc.0), - inverse_viewproj.project_point3(tile_line_ndc.1), - ); - - let tile_index = self.tile_index(); - let tile_id = self.descriptor.tiles_array.at(tile_index); - let tile_lights_array = lighting_slab.read(tile_id + LightTile::OFFSET_OF_LIGHTS_ARRAY); - let next_light_id = tile_id + LightTile::OFFSET_OF_NEXT_LIGHT_INDEX; - - // List of all analytical lights in the scene - let analytical_lights_array = lighting_slab.read_unchecked( - Id::::new(0) - + LightingDescriptor::OFFSET_OF_ANALYTICAL_LIGHTS_ARRAY, - ); - - // Each invocation will calculate a few lights' contribution to the tile, until all lights - // have been visited - let next_light = NextLightIndex::new( - self.global_id, - self.descriptor.tile_size, - analytical_lights_array, - ); - for id_of_light_id in next_light { - let light_id = lighting_slab.read_unchecked(id_of_light_id); - let light = lighting_slab.read_unchecked(light_id); - let transform = lighting_slab.read(light.transform_id); - // Get the distance to the light in world coords, and the - // intensity of the light. - let (distance, intensity_candelas) = match light.light_type { - LightStyle::Directional => { - let directional_light = lighting_slab.read(light.into_directional_id()); - (0.0, directional_light.intensity) - } - LightStyle::Point => { - let point_light = lighting_slab.read(light.into_point_id()); - let center = Mat4::from(transform).transform_point3(point_light.position); - let distance = crate::math::distance_to_line(center, tile_line.0, tile_line.1); - (distance, point_light.intensity) - } - LightStyle::Spot => { - // TODO: take into consideration the direction the spot light is pointing - let spot_light = lighting_slab.read(light.into_spot_id()); - let center = Mat4::from(transform).transform_point3(spot_light.position); - let distance = crate::math::distance_to_line(center, tile_line.0, tile_line.1); - (distance, spot_light.intensity) - } - }; - - let radius = - radius_of_illumination(intensity_candelas, self.descriptor.minimum_illuminance_lux); - let should_add = radius >= distance; - if should_add { - // If the light should be added to the bin, get the next available index in the bin, - // then write the id of the light into that index. - let next_index = crate::sync::atomic_i_increment::< - { spirv_std::memory::Scope::Workgroup as u32 }, - { spirv_std::memory::Semantics::WORKGROUP_MEMORY.bits() }, - >(lighting_slab, next_light_id); - if next_index as usize >= tile_lights_array.len() { - // We've already filled the bin, so abort. - // - // TODO: Figure out a better way to handle light tile list overrun. - break; - } else { - // Get the id that corresponds to the next available index in the ratings bin - let binned_light_id = tile_lights_array.at(next_index as usize); - // Write to that location - lighting_slab.write(binned_light_id, &light_id); - } - } - } - } -} - -#[spirv(compute(threads(16, 16, 1)))] -pub fn light_tiling_clear_tiles( - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] lighting_slab: &mut [u32], - #[spirv(global_invocation_id)] global_id: UVec3, -) { - let lighting_descriptor = lighting_slab.read(Id::::new(0)); - let light_tiling_descriptor = - lighting_slab.read(lighting_descriptor.light_tiling_descriptor_id); - let invocation = LightTilingInvocation::new(global_id, light_tiling_descriptor); - invocation.clear_tile(lighting_slab); -} - -/// Compute the min and max depth value for a tile. -/// -/// This shader must be called **once for each fragment in the depth texture**. -#[spirv(compute(threads(16, 16, 1)))] -pub fn light_tiling_compute_tile_min_and_max_depth( - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] lighting_slab: &mut [u32], - #[spirv(descriptor_set = 0, binding = 2)] depth_texture: &DepthImage2d, - #[spirv(global_invocation_id)] global_id: UVec3, -) { - let lighting_descriptor = lighting_slab.read(Id::::new(0)); - let light_tiling_descriptor = - lighting_slab.read(lighting_descriptor.light_tiling_descriptor_id); - let invocation = LightTilingInvocation::new(global_id, light_tiling_descriptor); - invocation.compute_min_and_max_depth(depth_texture, lighting_slab); -} - -/// Compute the min and max depth value for a tile, multisampled. -/// -/// This shader must be called **once for each fragment in the depth texture**. -#[spirv(compute(threads(16, 16, 1)))] -pub fn light_tiling_compute_tile_min_and_max_depth_multisampled( - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] lighting_slab: &mut [u32], - #[spirv(descriptor_set = 0, binding = 2)] depth_texture: &DepthImage2dMultisampled, - #[spirv(global_invocation_id)] global_id: UVec3, -) { - let lighting_descriptor = lighting_slab.read(Id::::new(0)); - let light_tiling_descriptor = - lighting_slab.read(lighting_descriptor.light_tiling_descriptor_id); - let invocation = LightTilingInvocation::new(global_id, light_tiling_descriptor); - invocation.compute_min_and_max_depth(depth_texture, lighting_slab); -} - -#[spirv(compute(threads(16, 16, 1)))] -pub fn light_tiling_bin_lights( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] lighting_slab: &mut [u32], - #[spirv(global_invocation_id)] global_id: UVec3, -) { - let lighting_descriptor = lighting_slab.read(Id::::new(0)); - let light_tiling_descriptor = - lighting_slab.read(lighting_descriptor.light_tiling_descriptor_id); - let invocation = LightTilingInvocation::new(global_id, light_tiling_descriptor); - if invocation.should_invoke() { - invocation.compute_light_lists(geometry_slab, lighting_slab); - } -} +pub mod shader; #[cfg(test)] mod test { - use crate::math::GpuRng; + use crabslab::Array; + use glam::{UVec2, UVec3, Vec2, Vec3}; + + use crate::math::{GpuRng, IsVector}; - use super::*; + use super::shader::*; #[cfg(feature = "gltf")] #[test] @@ -1260,6 +115,8 @@ mod test { println!("{:#?}", std::env::current_dir()); let (document, _buffers, _images) = gltf::import("../../gltf/four_spotlights.glb").unwrap(); for node in document.nodes() { + use glam::Vec3; + println!("node: {} {:?}", node.index(), node.name()); let gltf_transform = node.transform(); diff --git a/crates/renderling/src/light/cpu.rs b/crates/renderling/src/light/cpu.rs index f99eb820..0dca1ca3 100644 --- a/crates/renderling/src/light/cpu.rs +++ b/crates/renderling/src/light/cpu.rs @@ -1,6 +1,8 @@ //! CPU-only lighting and shadows. use std::sync::{Arc, RwLock}; +#[cfg(doc)] +use crate::stage::Stage; use craballoc::{ prelude::{Hybrid, SlabAllocator, WgpuRuntime}, slab::SlabBuffer, @@ -13,10 +15,10 @@ use snafu::prelude::*; use crate::{ atlas::{Atlas, AtlasBlitter, AtlasError}, geometry::Geometry, - transform::{NestedTransform, Transform, TransformDescriptor}, + transform::{shader::TransformDescriptor, NestedTransform, Transform}, }; -use super::{ +use super::shader::{ DirectionalLightDescriptor, LightDescriptor, LightStyle, LightingDescriptor, PointLightDescriptor, SpotLightDescriptor, }; @@ -100,6 +102,9 @@ impl DirectionalLight { } } +/// A [`DirectionalLight`] comes wrapped in [`AnalyticalLight`], giving the +/// [`AnalyticalLight`] the ability to simulate sunlight or other lights that +/// are "infinitely" far away. impl AnalyticalLight { /// Set the direction of the directional light. pub fn set_direction(&self, direction: Vec3) -> &Self { @@ -211,6 +216,10 @@ impl PointLight { } } +/// A [`PointLight`] comes wrapped in [`AnalyticalLight`], giving the +/// [`AnalyticalLight`] the ability to simulate lights that +/// emit from a single point in space and attenuate exponentially with +/// distance. impl AnalyticalLight { /// Set the position of the point light. pub fn set_position(&self, position: Vec3) -> &Self { @@ -324,6 +333,10 @@ impl SpotLight { } } +/// A [`SpotLight`] comes wrapped in [`AnalyticalLight`], giving the +/// [`AnalyticalLight`] the ability to simulate lights that +/// emit from a single point in space in a specific direction, with +/// a specific spread. impl AnalyticalLight { /// Set the position of the spot light. pub fn set_position(&self, position: Vec3) -> &Self { @@ -519,8 +532,15 @@ impl IsLight for Light { /// A bundle of lighting resources representing one analytical light in a scene. /// -/// Create an `AnalyticalLight` with the `Lighting::new_analytical_light`, -/// or from `Stage::new_analytical_light`. +/// Create an [`AnalyticalLight`] with: +/// * [`Stage::new_directional_light`] +/// * [`Stage::new_point_light`] +/// * [`Stage::new_spot_light`]. +/// +/// Lights may be added and removed from rendering with [`Stage::add_light`] and +/// [`Stage::remove_light`]. +/// The GPU resources a light uses will not be released until [`Stage::remove_light`] +/// is called _and_ the light is dropped. #[derive(Clone)] pub struct AnalyticalLight { /// The generic light descriptor. diff --git a/crates/renderling/src/light/cpu/test.rs b/crates/renderling/src/light/cpu/test.rs index 80bbf9af..92168f3f 100644 --- a/crates/renderling/src/light/cpu/test.rs +++ b/crates/renderling/src/light/cpu/test.rs @@ -9,11 +9,12 @@ use crate::{ camera::Camera, color::linear_xfer_vec4, geometry::Vertex, - light::{LightTiling, LightTilingConfig, SpotLightCalculation}, + light::{shader::SpotLightCalculation, LightTiling, LightTilingConfig}, math::GpuRng, - stage::{Primitive, PrimitivePbrVertexInfo, Stage}, + primitive::{shader::PrimitivePbrVertexInfo, Primitive}, + stage::Stage, test::BlockOnFuture, - transform::TransformDescriptor, + transform::shader::TransformDescriptor, }; use super::*; @@ -340,8 +341,8 @@ fn clear_tiles_sanity() { // This should produce an image where pixels get darker towards the upper left corner. let max = 1.0 - distance / max_distance; - item.depth_min = crate::light::quantize_depth_f32_to_u32(min); - item.depth_max = crate::light::quantize_depth_f32_to_u32(max); + item.depth_min = crate::light::shader::quantize_depth_f32_to_u32(min); + item.depth_max = crate::light::shader::quantize_depth_f32_to_u32(max); // This should produce an image that looks like noise item.next_light_index = rng.gen_u32(0, 32); @@ -971,7 +972,7 @@ fn pedestal() { for vertex_index in 0..renderlet.descriptor().vertices_array.len() { let mut info = PrimitivePbrVertexInfo::default(); - crate::stage::primitive_vertex( + crate::primitive::shader::primitive_vertex( renderlet.id(), vertex_index as u32, &geometry_slab, @@ -1042,7 +1043,7 @@ fn pedestal() { for vertex_index in 0..renderlet.descriptor().vertices_array.len() { let mut info = PrimitivePbrVertexInfo::default(); - crate::stage::primitive_vertex( + crate::primitive::shader::primitive_vertex( renderlet.id(), vertex_index as u32, &geometry_slab, diff --git a/crates/renderling/src/light/shader.rs b/crates/renderling/src/light/shader.rs new file mode 100644 index 00000000..afbae486 --- /dev/null +++ b/crates/renderling/src/light/shader.rs @@ -0,0 +1,1222 @@ +/// Root descriptor of the lighting system. +use crabslab::{Array, Id, Slab, SlabItem}; +use glam::{Mat4, UVec2, UVec3, Vec2, Vec3, Vec3Swizzles, Vec4, Vec4Swizzles}; +#[cfg(gpu)] +use spirv_std::num_traits::Float; +use spirv_std::{spirv, Image}; + +use crate::{ + atlas::shader::{AtlasDescriptor, AtlasTextureDescriptor}, + cubemap::shader::{CubemapDescriptor, CubemapFaceDirection}, + geometry::shader::GeometryDescriptor, + math::{Fetch, IsSampler, IsVector, Sample2dArray}, + primitive::shader::{PrimitiveDescriptor, VertexInfo}, + transform::shader::TransformDescriptor, +}; + +#[derive(Clone, Copy, Default, SlabItem, core::fmt::Debug)] +#[offsets] +pub struct LightingDescriptor { + /// List of all analytical lights in the scene. + pub analytical_lights_array: Array>, + /// Shadow mapping atlas info. + pub shadow_map_atlas_descriptor_id: Id, + /// `Id` of the [`ShadowMapDescriptor`] to use when updating + /// a shadow map. + /// + /// This changes from each run of the `shadow_mapping_vertex`. + pub update_shadow_map_id: Id, + /// The index of the shadow map atlas texture to update. + pub update_shadow_map_texture_index: u32, + /// `Id` of the [`LightTilingDescriptor`] to use when performing + /// light tiling. + pub light_tiling_descriptor_id: Id, +} + +#[derive(Clone, Copy, SlabItem, core::fmt::Debug)] +pub struct ShadowMapDescriptor { + pub light_space_transforms_array: Array, + /// Near plane of the projection matrix + pub z_near: f32, + /// Far plane of the projection matrix + pub z_far: f32, + /// Pointers to the atlas textures where the shadow map depth + /// data is stored. + /// + /// This will be an array of one `Id` for directional and spot lights, + /// and an array of four `Id`s for a point light. + pub atlas_textures_array: Array>, + pub bias_min: f32, + pub bias_max: f32, + pub pcf_samples: u32, +} + +impl Default for ShadowMapDescriptor { + fn default() -> Self { + Self { + light_space_transforms_array: Default::default(), + z_near: Default::default(), + z_far: Default::default(), + atlas_textures_array: Default::default(), + bias_min: 0.0005, + bias_max: 0.005, + pcf_samples: 4, + } + } +} + +#[cfg(test)] +#[derive(Default, Debug, Clone, Copy, PartialEq)] +pub struct ShadowMappingVertexInfo { + pub renderlet_id: Id, + pub vertex_index: u32, + pub vertex: crate::geometry::Vertex, + pub transform: TransformDescriptor, + pub model_matrix: Mat4, + pub world_pos: Vec3, + pub view_projection: Mat4, + pub clip_pos: Vec4, +} + +/// Shadow mapping vertex shader. +/// +/// It is assumed that a [`LightingDescriptor`] is stored at `Id(0)` of the +/// `light_slab`. +/// +/// This shader reads the [`LightingDescriptor`] to find the shadow map to +/// be updated, then determines the clip positions to emit based on the +/// shadow map's atlas texture. +/// +/// It then renders the renderlet into the designated atlas frame. +// Note: +// If this is taking too long to render for each renderlet, think about +// a frustum and occlusion culling pass to generate the list of renderlets. +#[spirv(vertex)] +#[allow(clippy::too_many_arguments)] +pub fn shadow_mapping_vertex( + // Points at a `Renderlet` + #[spirv(instance_index)] renderlet_id: Id, + // Which vertex within the renderlet are we rendering + #[spirv(vertex_index)] vertex_index: u32, + // The slab where the renderlet's geometry is staged + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], + // The slab where the scene's lighting data is staged + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] light_slab: &[u32], + + #[spirv(position)] out_clip_pos: &mut Vec4, + #[cfg(test)] out_comparison_info: &mut ShadowMappingVertexInfo, +) { + let renderlet = geometry_slab.read_unchecked(renderlet_id); + if !renderlet.visible { + // put it outside the clipping frustum + *out_clip_pos = Vec4::new(100.0, 100.0, 100.0, 1.0); + return; + } + + let VertexInfo { + world_pos, + vertex: _vertex, + transform: _transform, + model_matrix: _model_matrix, + } = renderlet.get_vertex_info(vertex_index, geometry_slab); + + let lighting_desc = light_slab.read_unchecked(Id::::new(0)); + let shadow_desc = light_slab.read_unchecked(lighting_desc.update_shadow_map_id); + let light_space_transform_id = shadow_desc + .light_space_transforms_array + .at(lighting_desc.update_shadow_map_texture_index as usize); + let light_space_transform = light_slab.read_unchecked(light_space_transform_id); + let clip_pos = light_space_transform * world_pos.extend(1.0); + #[cfg(test)] + { + *out_comparison_info = ShadowMappingVertexInfo { + renderlet_id, + vertex_index, + vertex: _vertex, + transform: _transform, + model_matrix: _model_matrix, + world_pos, + view_projection: light_space_transform, + clip_pos, + }; + } + *out_clip_pos = clip_pos; +} + +#[spirv(fragment)] +pub fn shadow_mapping_fragment(clip_pos: Vec4, frag_color: &mut Vec4) { + *frag_color = (clip_pos.xyz() / clip_pos.w).extend(1.0); +} + +/// Contains values needed to determine the outgoing radiance of a fragment. +/// +/// For more info, see the **Spotlight** section of the +/// [learnopengl](https://learnopengl.com/Lighting/Light-casters) +/// article. +#[derive(Clone, Copy, Default, core::fmt::Debug)] +pub struct SpotLightCalculation { + /// Position of the light in world space + pub light_position: Vec3, + /// Position of the fragment in world space + pub frag_position: Vec3, + /// Unit vector (LightDir) pointing from the fragment to the light + pub frag_to_light: Vec3, + /// Distance from the fragment to the light + pub frag_to_light_distance: f32, + /// Unit vector (SpotDir) direction that the light is pointing in + pub light_direction: Vec3, + /// The cosine of the cutoff angle (Phi Ï•) that specifies the spotlight's radius. + /// + /// Everything inside this angle is lit by the spotlight. + pub cos_inner_cutoff: f32, + /// The cosine of the cutoff angle (Gamma γ) that specifies the spotlight's outer radius. + /// + /// Everything outside this angle is not lit by the spotlight. + /// + /// Fragments between `inner_cutoff` and `outer_cutoff` have an intensity + /// between `1.0` and `0.0`. + pub cos_outer_cutoff: f32, + /// Whether the fragment is inside the `inner_cutoff` cone. + pub fragment_is_inside_inner_cone: bool, + /// Whether the fragment is inside the `outer_cutoff` cone. + pub fragment_is_inside_outer_cone: bool, + /// `outer_cutoff` - `inner_cutoff` + pub epsilon: f32, + /// Cosine of the angle (Theta θ) between `frag_to_light` (LightDir) vector and the + /// `light_direction` (SpotDir) vector. + /// + /// θ should be smaller than `outer_cutoff` (Gamma γ) to be + /// inside the spotlight, but since these are all cosines of angles, we actually + /// compare using `>`. + pub cos_theta: f32, + pub contribution_unclamped: f32, + /// The intensity level between `0.0` and `1.0` that should be used to determine + /// outgoing radiance. + pub contribution: f32, +} + +impl SpotLightCalculation { + /// Calculate the values required to determine outgoing radiance of a spot light. + pub fn new( + spot_light_descriptor: SpotLightDescriptor, + node_transform: Mat4, + fragment_world_position: Vec3, + ) -> Self { + let light_position = node_transform.transform_point3(spot_light_descriptor.position); + let frag_position = fragment_world_position; + let frag_to_light = light_position - frag_position; + let frag_to_light_distance = frag_to_light.length(); + if frag_to_light_distance == 0.0 { + crate::println!("frag_to_light_distance: {frag_to_light_distance}"); + return Self::default(); + } + let frag_to_light = frag_to_light.alt_norm_or_zero(); + let light_direction = node_transform + .transform_vector3(spot_light_descriptor.direction) + .alt_norm_or_zero(); + let cos_inner_cutoff = spot_light_descriptor.inner_cutoff.cos(); + let cos_outer_cutoff = spot_light_descriptor.outer_cutoff.cos(); + let epsilon = cos_inner_cutoff - cos_outer_cutoff; + let cos_theta = frag_to_light.dot(-light_direction); + let fragment_is_inside_inner_cone = cos_theta > cos_inner_cutoff; + let fragment_is_inside_outer_cone = cos_theta > cos_outer_cutoff; + let contribution_unclamped = (cos_theta - cos_outer_cutoff) / epsilon; + let contribution = contribution_unclamped.clamp(0.0, 1.0); + Self { + light_position, + frag_position, + frag_to_light, + frag_to_light_distance, + light_direction, + cos_inner_cutoff, + cos_outer_cutoff, + fragment_is_inside_inner_cone, + fragment_is_inside_outer_cone, + epsilon, + cos_theta, + contribution_unclamped, + contribution, + } + } +} + +/// Description of a spot light. +/// +/// ## Tips +/// +/// If your spotlight is not illuminating your scenery, ensure that the +/// `inner_cutoff` and `outer_cutoff` values are "correct". `outer_cutoff` +/// should be _greater than_ `inner_cutoff` and the values should be a large +/// enough to cover at least one pixel at the distance between the light and +/// the scenery. +#[repr(C)] +#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] +#[derive(Copy, Clone, SlabItem)] +pub struct SpotLightDescriptor { + pub position: Vec3, + pub direction: Vec3, + pub inner_cutoff: f32, + pub outer_cutoff: f32, + pub color: Vec4, + pub intensity: f32, +} + +impl Default for SpotLightDescriptor { + fn default() -> Self { + let white = Vec4::splat(1.0); + let inner_cutoff = 0.077143565; + let outer_cutoff = 0.09075713; + let direction = Vec3::new(0.0, -1.0, 0.0); + let color = white; + let intensity = 1.0; + + Self { + position: Default::default(), + direction, + inner_cutoff, + outer_cutoff, + color, + intensity, + } + } +} + +impl SpotLightDescriptor { + pub fn shadow_mapping_projection_and_view( + &self, + parent_light_transform: &Mat4, + z_near: f32, + z_far: f32, + ) -> (Mat4, Mat4) { + let fovy = 2.0 * self.outer_cutoff; + let aspect = 1.0; + let projection = Mat4::perspective_rh(fovy, aspect, z_near, z_far); + let direction = parent_light_transform + .transform_vector3(self.direction) + .alt_norm_or_zero(); + let position = parent_light_transform.transform_point3(self.position); + let up = direction.orthonormal_vectors()[0]; + let view = Mat4::look_to_rh(position, direction, up); + (projection, view) + } +} + +#[repr(C)] +#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] +#[derive(Copy, Clone, SlabItem)] +pub struct DirectionalLightDescriptor { + pub direction: Vec3, + pub color: Vec4, + pub intensity: f32, +} + +impl Default for DirectionalLightDescriptor { + fn default() -> Self { + let direction = Vec3::new(0.0, -1.0, 0.0); + let color = Vec4::splat(1.0); + let intensity = 1.0; + + Self { + direction, + color, + intensity, + } + } +} + +impl DirectionalLightDescriptor { + pub fn shadow_mapping_projection_and_view( + &self, + parent_light_transform: &Mat4, + // Near limits of the light's reach + // + // The maximum should be the `Camera`'s `Frustum::depth()`. + // TODO: in `DirectionalLightDescriptor::shadow_mapping_projection_and_view`, take Frustum + // as a parameter and then figure out the minimal view projection that includes that frustum + z_near: f32, + // Far limits of the light's reach + z_far: f32, + ) -> (Mat4, Mat4) { + crate::println!("descriptor: {self:#?}"); + let depth = (z_far - z_near).abs(); + let hd = depth * 0.5; + let projection = Mat4::orthographic_rh(-hd, hd, -hd, hd, z_near, z_far); + let direction = parent_light_transform + .transform_vector3(self.direction) + .alt_norm_or_zero(); + let position = -direction * depth * 0.5; + crate::println!("direction: {direction}"); + crate::println!("position: {position}"); + let up = direction.orthonormal_vectors()[0]; + let view = Mat4::look_to_rh(position, direction, up); + (projection, view) + } +} + +#[repr(C)] +#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] +#[derive(Copy, Clone, SlabItem)] +pub struct PointLightDescriptor { + pub position: Vec3, + pub color: Vec4, + /// Expressed as candelas. + pub intensity: f32, +} + +impl Default for PointLightDescriptor { + fn default() -> Self { + let color = Vec4::splat(1.0); + let intensity = 1.0; + + Self { + position: Default::default(), + color, + intensity, + } + } +} + +impl PointLightDescriptor { + pub fn shadow_mapping_view_matrix( + &self, + face_index: usize, + parent_light_transform: &Mat4, + ) -> Mat4 { + let eye = parent_light_transform.transform_point3(self.position); + let mut face = CubemapFaceDirection::FACES[face_index]; + face.eye = eye; + face.view() + } + + pub fn shadow_mapping_projection_matrix(z_near: f32, z_far: f32) -> Mat4 { + Mat4::perspective_lh(core::f32::consts::FRAC_PI_2, 1.0, z_near, z_far) + } + + pub fn shadow_mapping_projection_and_view_matrices( + &self, + parent_light_transform: &Mat4, + z_near: f32, + z_far: f32, + ) -> (Mat4, [Mat4; 6]) { + let p = Self::shadow_mapping_projection_matrix(z_near, z_far); + let eye = parent_light_transform.transform_point3(self.position); + ( + p, + CubemapFaceDirection::FACES.map(|mut face| { + face.eye = eye; + face.view() + }), + ) + } +} + +/// Returns the radius of illumination in meters. +/// +/// * Moonlight: < 1 lux. +/// - Full moon on a clear night: 0.25 lux. +/// - Quarter moon: 0.01 lux +/// - Starlight overcast moonless night sky: 0.0001 lux. +/// * General indoor lighting: Around 100 to 300 lux. +/// * Office lighting: Typically around 300 to 500 lux. +/// * Reading or task lighting: Around 500 to 750 lux. +/// * Detailed work (e.g., drafting, surgery): 1000 lux or more. +pub fn radius_of_illumination(intensity_candelas: f32, minimum_illuminance_lux: f32) -> f32 { + (intensity_candelas / minimum_illuminance_lux).sqrt() +} + +#[repr(u32)] +#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] +#[derive(Copy, Clone, PartialEq)] +pub enum LightStyle { + Directional = 0, + Point = 1, + Spot = 2, +} + +impl core::fmt::Display for LightStyle { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + LightStyle::Directional => f.write_str("directional"), + LightStyle::Point => f.write_str("point"), + LightStyle::Spot => f.write_str("spot"), + } + } +} + +impl SlabItem for LightStyle { + const SLAB_SIZE: usize = { 1 }; + + fn read_slab(index: usize, slab: &[u32]) -> Self { + let proxy = u32::read_slab(index, slab); + match proxy { + 0 => LightStyle::Directional, + 1 => LightStyle::Point, + 2 => LightStyle::Spot, + _ => LightStyle::Directional, + } + } + + fn write_slab(&self, index: usize, slab: &mut [u32]) -> usize { + let proxy = *self as u32; + proxy.write_slab(index, slab) + } +} + +/// A generic light that is used as a slab pointer to a +/// specific light type. +#[repr(C)] +#[cfg_attr(not(target_arch = "spirv"), derive(Debug))] +#[derive(Copy, Clone, PartialEq, SlabItem)] +pub struct LightDescriptor { + /// The type of the light + pub light_type: LightStyle, + /// The index of the light in the lighting slab + pub index: u32, + /// The id of a transform to apply to the position and direction of the light. + /// + /// This `Id` points to a transform on the lighting slab. + /// + /// The value of this descriptor can be synchronized with that of a node + /// transform on the geometry slab from + /// [`crate::light::AnalyticalLight::link_node_transform`]. + pub transform_id: Id, + /// The id of the shadow map in use by this light. + pub shadow_map_desc_id: Id, +} + +impl Default for LightDescriptor { + fn default() -> Self { + Self { + light_type: LightStyle::Directional, + index: Id::<()>::NONE.inner(), + transform_id: Id::NONE, + shadow_map_desc_id: Id::NONE, + } + } +} + +impl From> for LightDescriptor { + fn from(id: Id) -> Self { + Self { + light_type: LightStyle::Directional, + index: id.inner(), + transform_id: Id::NONE, + shadow_map_desc_id: Id::NONE, + } + } +} + +impl From> for LightDescriptor { + fn from(id: Id) -> Self { + Self { + light_type: LightStyle::Spot, + index: id.inner(), + transform_id: Id::NONE, + shadow_map_desc_id: Id::NONE, + } + } +} + +impl From> for LightDescriptor { + fn from(id: Id) -> Self { + Self { + light_type: LightStyle::Point, + index: id.inner(), + transform_id: Id::NONE, + shadow_map_desc_id: Id::NONE, + } + } +} + +impl LightDescriptor { + pub fn into_directional_id(self) -> Id { + Id::from(self.index) + } + + pub fn into_spot_id(self) -> Id { + Id::from(self.index) + } + + pub fn into_point_id(self) -> Id { + Id::from(self.index) + } +} + +/// Parameters to the shadow mapping calculation function. +/// +/// This is mostly just to appease clippy. +pub struct ShadowCalculation { + pub shadow_map_desc: ShadowMapDescriptor, + pub shadow_map_atlas_size: UVec2, + pub surface_normal_in_world_space: Vec3, + pub frag_pos_in_world_space: Vec3, + pub frag_to_light_in_world_space: Vec3, + pub bias_min: f32, + pub bias_max: f32, + pub pcf_samples: u32, +} + +impl ShadowCalculation { + /// Reads various required parameters from the slab and creates a `ShadowCalculation`. + pub fn new( + light_slab: &[u32], + light: LightDescriptor, + in_pos: Vec3, + surface_normal: Vec3, + light_direction: Vec3, + ) -> Self { + let shadow_map_desc = light_slab.read_unchecked(light.shadow_map_desc_id); + let atlas_size = { + let lighting_desc_id = Id::::new(0); + let atlas_desc_id = light_slab.read_unchecked( + lighting_desc_id + LightingDescriptor::OFFSET_OF_SHADOW_MAP_ATLAS_DESCRIPTOR_ID, + ); + let atlas_desc = light_slab.read_unchecked(atlas_desc_id); + atlas_desc.size + }; + + ShadowCalculation { + shadow_map_desc, + shadow_map_atlas_size: atlas_size.xy(), + surface_normal_in_world_space: surface_normal, + frag_pos_in_world_space: in_pos, + frag_to_light_in_world_space: light_direction, + bias_min: shadow_map_desc.bias_min, + bias_max: shadow_map_desc.bias_max, + pcf_samples: shadow_map_desc.pcf_samples, + } + } + + fn get_atlas_texture_at(&self, light_slab: &[u32], index: usize) -> AtlasTextureDescriptor { + let atlas_texture_id = + light_slab.read_unchecked(self.shadow_map_desc.atlas_textures_array.at(index)); + light_slab.read_unchecked(atlas_texture_id) + } + + fn get_frag_pos_in_light_space(&self, light_slab: &[u32], index: usize) -> Vec3 { + let light_space_transform_id = self.shadow_map_desc.light_space_transforms_array.at(index); + let light_space_transform = light_slab.read_unchecked(light_space_transform_id); + light_space_transform.project_point3(self.frag_pos_in_world_space) + } + + /// Returns shadow _intensity_ for directional and spot lights. + /// + /// Returns `0.0` when the fragment is in full light. + /// Returns `1.0` when the fragment is in full shadow. + pub fn run_directional_or_spot( + &self, + light_slab: &[u32], + shadow_map: &T, + shadow_map_sampler: &S, + ) -> f32 + where + S: IsSampler, + T: Sample2dArray, + { + let ShadowCalculation { + shadow_map_desc: _, + shadow_map_atlas_size, + frag_pos_in_world_space: _, + surface_normal_in_world_space: surface_normal, + frag_to_light_in_world_space: light_direction, + bias_min, + bias_max, + pcf_samples, + } = self; + let frag_pos_in_light_space = self.get_frag_pos_in_light_space(light_slab, 0); + crate::println!("frag_pos_in_light_space: {frag_pos_in_light_space}"); + if !crate::math::is_inside_clip_space(frag_pos_in_light_space.xyz()) { + return 0.0; + } + // The range of coordinates in the light's clip space is -1.0 to 1.0 for x and y, + // but the texture space is [0, 1], and Y increases downward, so we do this + // conversion to flip Y and also normalize to the range [0.0, 1.0]. + // Z should already be 0.0 to 1.0. + let proj_coords_uv = (frag_pos_in_light_space.xy() * Vec2::new(1.0, -1.0) + + Vec2::splat(1.0)) + * Vec2::splat(0.5); + crate::println!("proj_coords_uv: {proj_coords_uv}"); + + let shadow_map_atlas_texture = self.get_atlas_texture_at(light_slab, 0); + // With these projected coordinates we can sample the depth map as the + // resulting [0,1] coordinates from proj_coords directly correspond to + // the transformed NDC coordinates from the `ShadowMap::update` render pass. + // This gives us the closest depth from the light's point of view: + let pcf_samples_2 = *pcf_samples as i32 / 2; + let texel_size = 1.0 + / Vec2::new( + shadow_map_atlas_texture.size_px.x as f32, + shadow_map_atlas_texture.size_px.y as f32, + ); + let mut shadow = 0.0f32; + let mut total = 0.0f32; + for x in -pcf_samples_2..=pcf_samples_2 { + for y in -pcf_samples_2..=pcf_samples_2 { + let proj_coords = shadow_map_atlas_texture.uv( + proj_coords_uv + Vec2::new(x as f32, y as f32) * texel_size, + *shadow_map_atlas_size, + ); + let shadow_map_depth = shadow_map + .sample_by_lod(*shadow_map_sampler, proj_coords, 0.0) + .x; + // To get the current depth at this fragment we simply retrieve the projected vector's z + // coordinate which equals the depth of this fragment from the light's perspective. + let fragment_depth = frag_pos_in_light_space.z; + + // If the `current_depth`, which is the depth of the fragment from the lights POV, is + // greater than the `closest_depth` of the shadow map at that fragment, the fragment + // is in shadow + crate::println!("current_depth: {fragment_depth}"); + crate::println!("closest_depth: {shadow_map_depth}"); + let bias = (bias_max * (1.0 - surface_normal.dot(*light_direction))).max(*bias_min); + + if (fragment_depth - bias) >= shadow_map_depth { + shadow += 1.0 + } + total += 1.0; + } + } + shadow / total.max(1.0) + } + + pub const POINT_SAMPLE_OFFSET_DIRECTIONS: [Vec3; 21] = [ + Vec3::ZERO, + Vec3::new(1.0, 1.0, 1.0), + Vec3::new(1.0, -1.0, 1.0), + Vec3::new(-1.0, -1.0, 1.0), + Vec3::new(-1.0, 1.0, 1.0), + Vec3::new(1.0, 1.0, -1.0), + Vec3::new(1.0, -1.0, -1.0), + Vec3::new(-1.0, -1.0, -1.0), + Vec3::new(-1.0, 1.0, -1.0), + Vec3::new(1.0, 1.0, 0.0), + Vec3::new(1.0, -1.0, 0.0), + Vec3::new(-1.0, -1.0, 0.0), + Vec3::new(-1.0, 1.0, 0.0), + Vec3::new(1.0, 0.0, 1.0), + Vec3::new(-1.0, 0.0, 1.0), + Vec3::new(1.0, 0.0, -1.0), + Vec3::new(-1.0, 0.0, -1.0), + Vec3::new(0.0, 1.0, 1.0), + Vec3::new(0.0, -1.0, 1.0), + Vec3::new(0.0, -1.0, -1.0), + Vec3::new(0.0, 1.0, -1.0), + ]; + /// Returns shadow _intensity_ for point lights. + /// + /// Returns `0.0` when the fragment is in full light. + /// Returns `1.0` when the fragment is in full shadow. + pub fn run_point( + &self, + light_slab: &[u32], + shadow_map: &T, + shadow_map_sampler: &S, + light_pos_in_world_space: Vec3, + ) -> f32 + where + S: IsSampler, + T: Sample2dArray, + { + let ShadowCalculation { + shadow_map_desc, + shadow_map_atlas_size, + frag_pos_in_world_space, + surface_normal_in_world_space: surface_normal, + frag_to_light_in_world_space: frag_to_light, + bias_min, + bias_max, + pcf_samples, + } = self; + + let light_to_frag_dir = frag_pos_in_world_space - light_pos_in_world_space; + crate::println!("light_to_frag_dir: {light_to_frag_dir}"); + + let pcf_samplesf = (*pcf_samples as f32) + .max(1.0) + .min(Self::POINT_SAMPLE_OFFSET_DIRECTIONS.len() as f32); + let pcf_samples = pcf_samplesf as usize; + let view_distance = light_to_frag_dir.length(); + let disk_radius = (1.0 + view_distance / shadow_map_desc.z_far) / 25.0; + let mut shadow = 0.0f32; + for i in 0..pcf_samples { + let sample_offset = Self::POINT_SAMPLE_OFFSET_DIRECTIONS[i] * disk_radius; + crate::println!("sample_offset: {sample_offset}"); + let sample_dir = (light_to_frag_dir + sample_offset).alt_norm_or_zero(); + let (face_index, uv) = CubemapDescriptor::get_face_index_and_uv(sample_dir); + crate::println!("face_index: {face_index}",); + crate::println!("uv: {uv}"); + let frag_pos_in_light_space = self.get_frag_pos_in_light_space(light_slab, face_index); + let face_texture = self.get_atlas_texture_at(light_slab, face_index); + let uv_tex = face_texture.uv(uv, *shadow_map_atlas_size); + let shadow_map_depth = shadow_map.sample_by_lod(*shadow_map_sampler, uv_tex, 0.0).x; + let fragment_depth = frag_pos_in_light_space.z; + let bias = (bias_max * (1.0 - surface_normal.dot(*frag_to_light))).max(*bias_min); + if (fragment_depth - bias) > shadow_map_depth { + shadow += 1.0 + } + } + + shadow / pcf_samplesf + } +} + +/// Depth pre-pass for the light tiling feature. +/// +/// This shader writes all staged [`PrimitiveDescriptor`]'s depth into a buffer. +/// +/// This shader is very much like [`shadow_mapping_vertex`], except that +/// shader gets its projection+view matrix from the light stored in a +/// `ShadowMapDescriptor`. +/// +/// Here we want to render as normal forward pass would, with the `PrimitiveDescriptor` +/// and the `Camera`'s view projection matrix. +/// ## Note +/// This shader will likely be expanded to include parts of occlusion culling and order +/// independent transparency. +#[spirv(vertex)] +pub fn light_tiling_depth_pre_pass( + // Points at a `Renderlet`. + #[spirv(instance_index)] renderlet_id: Id, + // Which vertex within the renderlet are we rendering? + #[spirv(vertex_index)] vertex_index: u32, + // The slab where the renderlet's geometry is staged + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], + // Output clip coords + #[spirv(position)] out_clip_pos: &mut Vec4, +) { + let renderlet = geometry_slab.read_unchecked(renderlet_id); + if !renderlet.visible { + // put it outside the clipping frustum + *out_clip_pos = Vec3::splat(100.0).extend(1.0); + return; + } + + let camera_id = geometry_slab + .read_unchecked(Id::::new(0) + GeometryDescriptor::OFFSET_OF_CAMERA_ID); + let camera = geometry_slab.read_unchecked(camera_id); + + let VertexInfo { world_pos, .. } = renderlet.get_vertex_info(vertex_index, geometry_slab); + + *out_clip_pos = camera.view_projection() * world_pos.extend(1.0); +} + +pub type DepthImage2d = Image!(2D, type=f32, sampled, depth); + +pub type DepthImage2dMultisampled = Image!(2D, type=f32, sampled, depth, multisampled=true); + +/// A tile of screen space used to cull lights. +#[derive(Clone, Copy, Default, SlabItem)] +#[offsets] +pub struct LightTile { + /// Minimum depth of objects found within the frustum of the tile. + pub depth_min: u32, + /// Maximum depth of objects foudn within the frustum of the tile. + pub depth_max: u32, + /// The count of lights in this tile. + /// + /// Also, the next available light index. + pub next_light_index: u32, + /// List of light ids that intersect this tile's frustum. + pub lights_array: Array>, +} + +impl core::fmt::Debug for LightTile { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("LightTile") + .field("depth_min", &dequantize_depth_u32_to_f32(self.depth_min)) + .field("depth_max", &dequantize_depth_u32_to_f32(self.depth_max)) + .field("next_light_index", &self.next_light_index) + .field("lights_array", &self.lights_array) + .finish() + } +} + +/// Descriptor of the light tiling operation, which culls lights by accumulating +/// them into lists that illuminate tiles of the screen. +#[derive(Clone, Copy, SlabItem, core::fmt::Debug)] +pub struct LightTilingDescriptor { + /// Size of the [`Stage`](crate::stage::Stage)'s depth texture. + pub depth_texture_size: UVec2, + /// Configurable tile size. + pub tile_size: u32, + /// Array pointing to the lighting "tiles". + pub tiles_array: Array, + /// Minimum illuminance. + /// + /// Used to determine whether a light illuminates a tile. + pub minimum_illuminance_lux: f32, +} + +impl Default for LightTilingDescriptor { + fn default() -> Self { + Self { + depth_texture_size: Default::default(), + tile_size: 16, + tiles_array: Default::default(), + minimum_illuminance_lux: 0.1, + } + } +} + +impl LightTilingDescriptor { + /// Returns the dimensions of the grid of tiles. + pub fn tile_grid_size(&self) -> UVec2 { + let dims_f32 = self.depth_texture_size.as_vec2() / self.tile_size as f32; + dims_f32.ceil().as_uvec2() + } + + pub fn tile_coord_for_fragment(&self, frag_coord: Vec2) -> UVec2 { + let frag_coord = frag_coord.as_uvec2(); + frag_coord / self.tile_size + } + + pub fn tile_index_for_fragment(&self, frag_coord: Vec2) -> usize { + let tile_coord = self.tile_coord_for_fragment(frag_coord); + let tile_dimensions = self.tile_grid_size(); + (tile_coord.y * tile_dimensions.x + tile_coord.x) as usize + } +} + +/// Quantizes a fragment depth from `f32` to `u32`. +pub fn quantize_depth_f32_to_u32(depth: f32) -> u32 { + (u32::MAX as f32 * depth).round() as u32 +} + +/// Reconstructs a previously quantized depth from a `u32`. +pub fn dequantize_depth_u32_to_f32(depth: u32) -> f32 { + depth as f32 / u32::MAX as f32 +} + +/// Helper for determining the next light to check during an +/// invocation of the light list computation. +pub(crate) struct NextLightIndex { + current_step: usize, + tile_size: u32, + lights: Array>, + global_id: UVec3, +} + +impl Iterator for NextLightIndex { + type Item = Id>; + + fn next(&mut self) -> Option { + let next_index = self.next_index(); + self.current_step += 1; + if next_index < self.lights.len() { + Some(self.lights.at(next_index)) + } else { + None + } + } +} + +impl NextLightIndex { + pub fn new( + global_id: UVec3, + tile_size: u32, + analytical_lights_array: Array>, + ) -> Self { + Self { + current_step: 0, + tile_size, + lights: analytical_lights_array, + global_id, + } + } + + pub fn next_index(&self) -> usize { + // Determine the xy coord of this invocation within the _tile_ + let frag_tile_xy = self.global_id.xy() % self.tile_size; + // Determine the index of this invocation within the _tile_ + let offset = frag_tile_xy.y * self.tile_size + frag_tile_xy.x; + let stride = (self.tile_size * self.tile_size) as usize; + self.current_step * stride + offset as usize + } +} + +struct LightTilingInvocation { + global_id: UVec3, + descriptor: LightTilingDescriptor, +} + +impl LightTilingInvocation { + fn new(global_id: UVec3, descriptor: LightTilingDescriptor) -> Self { + Self { + global_id, + descriptor, + } + } + + /// The fragment's position. + /// + /// X range is 0 to (width - 1), Y range is 0 to (height - 1). + fn frag_pos(&self) -> UVec2 { + self.global_id.xy() + } + + /// The number of tiles in X and Y within the depth texture. + fn tile_grid_size(&self) -> UVec2 { + self.descriptor.tile_grid_size() + } + + /// The tile's coordinate among all tiles in the tile grid. + /// + /// The units are in tile x y. + fn tile_coord(&self) -> UVec2 { + self.global_id.xy() / self.descriptor.tile_size + } + + /// The tile's index in all the [`LightTilingDescriptor`]'s `tile_array`. + fn tile_index(&self) -> usize { + let tile_pos = self.tile_coord(); + let tile_dimensions = self.tile_grid_size(); + (tile_pos.y * tile_dimensions.x + tile_pos.x) as usize + } + + /// The tile's normalized midpoint. + fn tile_ndc_midpoint(&self) -> Vec2 { + let min_coord = self.tile_coord().as_vec2(); + let mid_coord = min_coord + 0.5; + crate::math::convert_pixel_to_ndc(mid_coord, self.tile_grid_size()) + } + + /// Compute the min and max depth of one fragment/invocation for light tiling. + /// + /// The min and max is stored in a tile on lighting slab. + fn compute_min_and_max_depth( + &self, + depth_texture: &impl Fetch, + lighting_slab: &mut [u32], + ) { + let frag_pos = self.frag_pos(); + let depth_texture_size = self.descriptor.depth_texture_size; + if frag_pos.x >= depth_texture_size.x || frag_pos.y >= depth_texture_size.y { + return; + } + // Depth frag value at the fragment position + let frag_depth: f32 = depth_texture.fetch(frag_pos).x; + // Fragment depth scaled to min/max of u32 values + // + // This is so we can compare with normal atomic ops instead of using the float extension + let frag_depth_u32 = quantize_depth_f32_to_u32(frag_depth); + + // The tile's index in all the tiles + let tile_index = self.tile_index(); + let lighting_desc = lighting_slab.read_unchecked(Id::::new(0)); + let tiling_desc = lighting_slab.read_unchecked(lighting_desc.light_tiling_descriptor_id); + // index of the tile's min depth atomic value in the lighting slab + let tile_id = tiling_desc.tiles_array.at(tile_index); + let min_depth_index = tile_id + LightTile::OFFSET_OF_DEPTH_MIN; + // index of the tile's max depth atomic value in the lighting slab + let max_depth_index = tile_id + LightTile::OFFSET_OF_DEPTH_MAX; + + let _prev_min_depth = crate::sync::atomic_u_min::< + { spirv_std::memory::Scope::Workgroup as u32 }, + { spirv_std::memory::Semantics::WORKGROUP_MEMORY.bits() }, + >(lighting_slab, min_depth_index, frag_depth_u32); + let _prev_max_depth = crate::sync::atomic_u_max::< + { spirv_std::memory::Scope::Workgroup as u32 }, + { spirv_std::memory::Semantics::WORKGROUP_MEMORY.bits() }, + >(lighting_slab, max_depth_index, frag_depth_u32); + } + + /// Determine whether this invocation should run. + fn should_invoke(&self) -> bool { + self.global_id.x < self.descriptor.depth_texture_size.x + && self.global_id.y < self.descriptor.depth_texture_size.y + } + + /// Clears one tile. + /// + /// ## Note + /// This is only valid to call from the [`light_tiling_clear_tiles`] shader. + fn clear_tile(&self, lighting_slab: &mut [u32]) { + let dimensions = self.tile_grid_size(); + let index = (self.global_id.y * dimensions.x + self.global_id.x) as usize; + if index < self.descriptor.tiles_array.len() { + let tile_id = self.descriptor.tiles_array.at(index); + let mut tile = lighting_slab.read(tile_id); + tile.depth_min = u32::MAX; + tile.depth_max = 0; + tile.next_light_index = 0; + lighting_slab.write(tile_id, &tile); + // Zero out the light list and the ratings + for id in tile.lights_array.iter() { + lighting_slab.write(id, &Id::NONE); + } + } + } + + // The difficulty here is that in SPIRV we can access `lighting_slab` atomically without wrapping it + // in a type, but on CPU we must pass an array of (something like) `AtomicU32`. I'm not sure how to + // model this interaction to test it on the CPU. + fn compute_light_lists(&self, geometry_slab: &[u32], lighting_slab: &mut [u32]) { + let index = self.tile_index(); + let tile_id = self.descriptor.tiles_array.at(index); + // Construct the tile's frustum in clip space. + let depth_min_u32 = lighting_slab.read_unchecked(tile_id + LightTile::OFFSET_OF_DEPTH_MIN); + let depth_max_u32 = lighting_slab.read_unchecked(tile_id + LightTile::OFFSET_OF_DEPTH_MAX); + let depth_min = dequantize_depth_u32_to_f32(depth_min_u32); + let depth_max = dequantize_depth_u32_to_f32(depth_max_u32); + + if depth_min == depth_max { + // If we would construct a frustum with zero volume, abort. + // + // See + // for more info. + return; + } + + let camera_id = geometry_slab.read_unchecked( + Id::::new(0) + GeometryDescriptor::OFFSET_OF_CAMERA_ID, + ); + let camera = geometry_slab.read_unchecked(camera_id); + + // let (ndc_tile_min, ndc_tile_max) = self.tile_ndc_min_max(); + // // This is the AABB frustum, in NDC coords + // let ndc_tile_aabb = Aabb::new( + // ndc_tile_min.extend(depth_min), + // ndc_tile_max.extend(depth_max), + // ); + + // Get the frustum (here simplified to a line) in world coords, since we'll be + // using it to compare against the radius of illumination of each light + let tile_ndc_midpoint = self.tile_ndc_midpoint(); + let tile_line_ndc = ( + tile_ndc_midpoint.extend(depth_min), + tile_ndc_midpoint.extend(depth_max), + ); + let inverse_viewproj = camera.view_projection().inverse(); + let tile_line = ( + inverse_viewproj.project_point3(tile_line_ndc.0), + inverse_viewproj.project_point3(tile_line_ndc.1), + ); + + let tile_index = self.tile_index(); + let tile_id = self.descriptor.tiles_array.at(tile_index); + let tile_lights_array = lighting_slab.read(tile_id + LightTile::OFFSET_OF_LIGHTS_ARRAY); + let next_light_id = tile_id + LightTile::OFFSET_OF_NEXT_LIGHT_INDEX; + + // List of all analytical lights in the scene + let analytical_lights_array = lighting_slab.read_unchecked( + Id::::new(0) + + LightingDescriptor::OFFSET_OF_ANALYTICAL_LIGHTS_ARRAY, + ); + + // Each invocation will calculate a few lights' contribution to the tile, until all lights + // have been visited + let next_light = NextLightIndex::new( + self.global_id, + self.descriptor.tile_size, + analytical_lights_array, + ); + for id_of_light_id in next_light { + let light_id = lighting_slab.read_unchecked(id_of_light_id); + let light = lighting_slab.read_unchecked(light_id); + let transform = lighting_slab.read(light.transform_id); + // Get the distance to the light in world coords, and the + // intensity of the light. + let (distance, intensity_candelas) = match light.light_type { + LightStyle::Directional => { + let directional_light = lighting_slab.read(light.into_directional_id()); + (0.0, directional_light.intensity) + } + LightStyle::Point => { + let point_light = lighting_slab.read(light.into_point_id()); + let center = Mat4::from(transform).transform_point3(point_light.position); + let distance = crate::math::distance_to_line(center, tile_line.0, tile_line.1); + (distance, point_light.intensity) + } + LightStyle::Spot => { + // TODO: take into consideration the direction the spot light is pointing + let spot_light = lighting_slab.read(light.into_spot_id()); + let center = Mat4::from(transform).transform_point3(spot_light.position); + let distance = crate::math::distance_to_line(center, tile_line.0, tile_line.1); + (distance, spot_light.intensity) + } + }; + + let radius = + radius_of_illumination(intensity_candelas, self.descriptor.minimum_illuminance_lux); + let should_add = radius >= distance; + if should_add { + // If the light should be added to the bin, get the next available index in the bin, + // then write the id of the light into that index. + let next_index = crate::sync::atomic_i_increment::< + { spirv_std::memory::Scope::Workgroup as u32 }, + { spirv_std::memory::Semantics::WORKGROUP_MEMORY.bits() }, + >(lighting_slab, next_light_id); + if next_index as usize >= tile_lights_array.len() { + // We've already filled the bin, so abort. + // + // TODO: Figure out a better way to handle light tile list overrun. + break; + } else { + // Get the id that corresponds to the next available index in the ratings bin + let binned_light_id = tile_lights_array.at(next_index as usize); + // Write to that location + lighting_slab.write(binned_light_id, &light_id); + } + } + } + } +} + +#[spirv(compute(threads(16, 16, 1)))] +pub fn light_tiling_clear_tiles( + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] lighting_slab: &mut [u32], + #[spirv(global_invocation_id)] global_id: UVec3, +) { + let lighting_descriptor = lighting_slab.read(Id::::new(0)); + let light_tiling_descriptor = + lighting_slab.read(lighting_descriptor.light_tiling_descriptor_id); + let invocation = LightTilingInvocation::new(global_id, light_tiling_descriptor); + invocation.clear_tile(lighting_slab); +} + +/// Compute the min and max depth value for a tile. +/// +/// This shader must be called **once for each fragment in the depth texture**. +#[spirv(compute(threads(16, 16, 1)))] +pub fn light_tiling_compute_tile_min_and_max_depth( + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] lighting_slab: &mut [u32], + #[spirv(descriptor_set = 0, binding = 2)] depth_texture: &DepthImage2d, + #[spirv(global_invocation_id)] global_id: UVec3, +) { + let lighting_descriptor = lighting_slab.read(Id::::new(0)); + let light_tiling_descriptor = + lighting_slab.read(lighting_descriptor.light_tiling_descriptor_id); + let invocation = LightTilingInvocation::new(global_id, light_tiling_descriptor); + invocation.compute_min_and_max_depth(depth_texture, lighting_slab); +} + +/// Compute the min and max depth value for a tile, multisampled. +/// +/// This shader must be called **once for each fragment in the depth texture**. +#[spirv(compute(threads(16, 16, 1)))] +pub fn light_tiling_compute_tile_min_and_max_depth_multisampled( + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] lighting_slab: &mut [u32], + #[spirv(descriptor_set = 0, binding = 2)] depth_texture: &DepthImage2dMultisampled, + #[spirv(global_invocation_id)] global_id: UVec3, +) { + let lighting_descriptor = lighting_slab.read(Id::::new(0)); + let light_tiling_descriptor = + lighting_slab.read(lighting_descriptor.light_tiling_descriptor_id); + let invocation = LightTilingInvocation::new(global_id, light_tiling_descriptor); + invocation.compute_min_and_max_depth(depth_texture, lighting_slab); +} + +#[spirv(compute(threads(16, 16, 1)))] +pub fn light_tiling_bin_lights( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] lighting_slab: &mut [u32], + #[spirv(global_invocation_id)] global_id: UVec3, +) { + let lighting_descriptor = lighting_slab.read(Id::::new(0)); + let light_tiling_descriptor = + lighting_slab.read(lighting_descriptor.light_tiling_descriptor_id); + let invocation = LightTilingInvocation::new(global_id, light_tiling_descriptor); + if invocation.should_invoke() { + invocation.compute_light_lists(geometry_slab, lighting_slab); + } +} diff --git a/crates/renderling/src/light/shadow_map.rs b/crates/renderling/src/light/shadow_map.rs index 421e9f16..20271657 100644 --- a/crates/renderling/src/light/shadow_map.rs +++ b/crates/renderling/src/light/shadow_map.rs @@ -12,17 +12,25 @@ use glam::{Mat4, UVec2}; use snafu::ResultExt; use crate::{ - atlas::{AtlasBlittingOperation, AtlasImage, AtlasTexture, AtlasTextureDescriptor}, + atlas::{shader::AtlasTextureDescriptor, AtlasBlittingOperation, AtlasImage, AtlasTexture}, bindgroup::ManagedBindGroup, light::{IsLight, Light}, - stage::Primitive, + primitive::Primitive, }; -use super::{AnalyticalLight, Lighting, LightingError, PollSnafu, ShadowMapDescriptor}; +use super::{ + shader::{LightStyle, ShadowMapDescriptor}, + AnalyticalLight, Lighting, LightingError, PollSnafu, +}; -/// A depth map rendering of the scene from a light's point of view. +/// Projects shadows from a single light source for specific objects. +/// +/// A `ShadowMap` is essentially a depth map rendering of the scene from one +/// light's point of view. We use this rendering of the scene to determine if +/// an object lies in shadow. /// -/// Used to project shadows from one light source for specific objects. +/// To create a new [`ShadowMap`], use +/// [`Stage::new_shadow_map`](crate::stage::Stage::new_shadow_map). #[derive(Clone)] pub struct ShadowMap { /// Last time the stage slab was bound. @@ -175,7 +183,7 @@ impl ShadowMap { Light: From, { let stage_slab_buffer = lighting.geometry_slab_buffer.read().unwrap(); - let is_point_light = analytical_light_bundle.style() == super::LightStyle::Point; + let is_point_light = analytical_light_bundle.style() == LightStyle::Point; let count = if is_point_light { 6 } else { 1 }; let atlas = &lighting.shadow_map_atlas; let image = AtlasImage::new(size, crate::atlas::AtlasImageFormat::R32FLOAT); @@ -374,9 +382,9 @@ impl ShadowMap { #[cfg(test)] #[allow(clippy::unused_enumerate_index)] mod test { - use crate::test::BlockOnFuture; + use glam::{UVec2, Vec3}; - use super::super::*; + use crate::test::BlockOnFuture; #[test] fn shadow_mapping_just_cuboid() { diff --git a/crates/renderling/src/light/tiling.rs b/crates/renderling/src/light/tiling.rs index 6e0bee1b..3834933e 100644 --- a/crates/renderling/src/light/tiling.rs +++ b/crates/renderling/src/light/tiling.rs @@ -1,7 +1,10 @@ -//! Implementation of light tiling. +//! This module implements light tiling, a technique used in rendering to efficiently manage and apply lighting effects across a scene. //! -//! For more info on what light tiling is, see -//! [this blog post](https://renderling.xyz/articles/live/light_tiling.html). +//! Light tiling divides the rendering surface into a grid of tiles, allowing for the efficient computation of lighting effects by processing each tile independently. This approach helps in optimizing the rendering pipeline by reducing the number of lighting calculations needed, especially in complex scenes with multiple light sources. +//! +//! The `LightTiling` struct and its associated methods provide the necessary functionality to set up and execute light tiling operations. It includes the creation of compute pipelines for clearing tiles, computing minimum and maximum depths, and binning lights into tiles. +//! +//! For more detailed information on light tiling and its implementation, refer to [this blog post](https://renderling.xyz/articles/live/light_tiling.html). use core::sync::atomic::AtomicUsize; use std::sync::Arc; @@ -15,7 +18,10 @@ use glam::{UVec2, UVec3}; use crate::{ bindgroup::ManagedBindGroup, - light::{LightTile, LightTilingDescriptor, Lighting}, + light::{ + shader::{LightTile, LightTilingDescriptor}, + Lighting, + }, stage::Stage, }; @@ -336,7 +342,7 @@ impl LightTiling { ) -> (image::GrayImage, image::GrayImage, image::GrayImage) { use crabslab::Slab; - use crate::light::dequantize_depth_u32_to_f32; + use crate::light::shader::dequantize_depth_u32_to_f32; let tile_dimensions = self.tiling_descriptor.get().tile_grid_size(); let slab = lighting.light_slab.read(..).await.unwrap(); diff --git a/crates/renderling/src/linkage/atlas_blit_fragment.rs b/crates/renderling/src/linkage/atlas_blit_fragment.rs index f4ce010d..43d02289 100644 --- a/crates/renderling/src/linkage/atlas_blit_fragment.rs +++ b/crates/renderling/src/linkage/atlas_blit_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "atlas::atlas_blit_fragment"; + pub const ENTRY_POINT: &str = "atlas::shader::atlas_blit_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/atlas-atlas_blit_fragment.spv") + wgpu::include_spirv!("../../shaders/atlas-shader-atlas_blit_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "atlas_blit_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "atlasatlas_blit_fragment"; + pub const ENTRY_POINT: &str = "atlasshaderatlas_blit_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/atlas-atlas_blit_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/atlas-shader-atlas_blit_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "atlas_blit_fragment"); diff --git a/crates/renderling/src/linkage/atlas_blit_vertex.rs b/crates/renderling/src/linkage/atlas_blit_vertex.rs index e3cfab71..d78fd25b 100644 --- a/crates/renderling/src/linkage/atlas_blit_vertex.rs +++ b/crates/renderling/src/linkage/atlas_blit_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "atlas::atlas_blit_vertex"; + pub const ENTRY_POINT: &str = "atlas::shader::atlas_blit_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/atlas-atlas_blit_vertex.spv") + wgpu::include_spirv!("../../shaders/atlas-shader-atlas_blit_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "atlas_blit_vertex"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "atlasatlas_blit_vertex"; + pub const ENTRY_POINT: &str = "atlasshaderatlas_blit_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/atlas-atlas_blit_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/atlas-shader-atlas_blit_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "atlas_blit_vertex"); diff --git a/crates/renderling/src/linkage/bloom_downsample_fragment.rs b/crates/renderling/src/linkage/bloom_downsample_fragment.rs index 8e4435b0..6960adc6 100644 --- a/crates/renderling/src/linkage/bloom_downsample_fragment.rs +++ b/crates/renderling/src/linkage/bloom_downsample_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "bloom::shaders::bloom_downsample_fragment"; + pub const ENTRY_POINT: &str = "bloom::shader::bloom_downsample_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-shaders-bloom_downsample_fragment.spv") + wgpu::include_spirv!("../../shaders/bloom-shader-bloom_downsample_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +20,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "bloomshadersbloom_downsample_fragment"; + pub const ENTRY_POINT: &str = "bloomshaderbloom_downsample_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-shaders-bloom_downsample_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/bloom-shader-bloom_downsample_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "bloom_downsample_fragment"); diff --git a/crates/renderling/src/linkage/bloom_mix_fragment.rs b/crates/renderling/src/linkage/bloom_mix_fragment.rs index dbef37a2..fe362a45 100644 --- a/crates/renderling/src/linkage/bloom_mix_fragment.rs +++ b/crates/renderling/src/linkage/bloom_mix_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "bloom::shaders::bloom_mix_fragment"; + pub const ENTRY_POINT: &str = "bloom::shader::bloom_mix_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-shaders-bloom_mix_fragment.spv") + wgpu::include_spirv!("../../shaders/bloom-shader-bloom_mix_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "bloom_mix_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "bloomshadersbloom_mix_fragment"; + pub const ENTRY_POINT: &str = "bloomshaderbloom_mix_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-shaders-bloom_mix_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/bloom-shader-bloom_mix_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "bloom_mix_fragment"); diff --git a/crates/renderling/src/linkage/bloom_upsample_fragment.rs b/crates/renderling/src/linkage/bloom_upsample_fragment.rs index 05139518..74fcc4b8 100644 --- a/crates/renderling/src/linkage/bloom_upsample_fragment.rs +++ b/crates/renderling/src/linkage/bloom_upsample_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "bloom::shaders::bloom_upsample_fragment"; + pub const ENTRY_POINT: &str = "bloom::shader::bloom_upsample_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-shaders-bloom_upsample_fragment.spv") + wgpu::include_spirv!("../../shaders/bloom-shader-bloom_upsample_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "bloom_upsample_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "bloomshadersbloom_upsample_fragment"; + pub const ENTRY_POINT: &str = "bloomshaderbloom_upsample_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-shaders-bloom_upsample_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/bloom-shader-bloom_upsample_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "bloom_upsample_fragment"); diff --git a/crates/renderling/src/linkage/bloom_vertex.rs b/crates/renderling/src/linkage/bloom_vertex.rs index 3153b8c0..532f4dcd 100644 --- a/crates/renderling/src/linkage/bloom_vertex.rs +++ b/crates/renderling/src/linkage/bloom_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "bloom::shaders::bloom_vertex"; + pub const ENTRY_POINT: &str = "bloom::shader::bloom_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/bloom-shaders-bloom_vertex.spv") + wgpu::include_spirv!("../../shaders/bloom-shader-bloom_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "bloom_vertex"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "bloomshadersbloom_vertex"; + pub const ENTRY_POINT: &str = "bloomshaderbloom_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/bloom-shaders-bloom_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/bloom-shader-bloom_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "bloom_vertex"); diff --git a/crates/renderling/src/linkage/compute_copy_depth_to_pyramid.rs b/crates/renderling/src/linkage/compute_copy_depth_to_pyramid.rs index fa419158..471ed73a 100644 --- a/crates/renderling/src/linkage/compute_copy_depth_to_pyramid.rs +++ b/crates/renderling/src/linkage/compute_copy_depth_to_pyramid.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "cull::compute_copy_depth_to_pyramid"; + pub const ENTRY_POINT: &str = "cull::shader::compute_copy_depth_to_pyramid"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/cull-compute_copy_depth_to_pyramid.spv") + wgpu::include_spirv!("../../shaders/cull-shader-compute_copy_depth_to_pyramid.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +20,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "cullcompute_copy_depth_to_pyramid"; + pub const ENTRY_POINT: &str = "cullshadercompute_copy_depth_to_pyramid"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/cull-compute_copy_depth_to_pyramid.wgsl") + wgpu::include_wgsl!("../../shaders/cull-shader-compute_copy_depth_to_pyramid.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/linkage/compute_copy_depth_to_pyramid_multisampled.rs b/crates/renderling/src/linkage/compute_copy_depth_to_pyramid_multisampled.rs index 707b4fc0..4eb2118f 100644 --- a/crates/renderling/src/linkage/compute_copy_depth_to_pyramid_multisampled.rs +++ b/crates/renderling/src/linkage/compute_copy_depth_to_pyramid_multisampled.rs @@ -3,9 +3,11 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "cull::compute_copy_depth_to_pyramid_multisampled"; + pub const ENTRY_POINT: &str = "cull::shader::compute_copy_depth_to_pyramid_multisampled"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/cull-compute_copy_depth_to_pyramid_multisampled.spv") + wgpu::include_spirv!( + "../../shaders/cull-shader-compute_copy_depth_to_pyramid_multisampled.spv" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +22,11 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "cullcompute_copy_depth_to_pyramid_multisampled"; + pub const ENTRY_POINT: &str = "cullshadercompute_copy_depth_to_pyramid_multisampled"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/cull-compute_copy_depth_to_pyramid_multisampled.wgsl") + wgpu::include_wgsl!( + "../../shaders/cull-shader-compute_copy_depth_to_pyramid_multisampled.wgsl" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/linkage/compute_culling.rs b/crates/renderling/src/linkage/compute_culling.rs index 09a45604..d70aed56 100644 --- a/crates/renderling/src/linkage/compute_culling.rs +++ b/crates/renderling/src/linkage/compute_culling.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "cull::compute_culling"; + pub const ENTRY_POINT: &str = "cull::shader::compute_culling"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/cull-compute_culling.spv") + wgpu::include_spirv!("../../shaders/cull-shader-compute_culling.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "compute_culling"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "cullcompute_culling"; + pub const ENTRY_POINT: &str = "cullshadercompute_culling"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/cull-compute_culling.wgsl") + wgpu::include_wgsl!("../../shaders/cull-shader-compute_culling.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "compute_culling"); diff --git a/crates/renderling/src/linkage/compute_downsample_depth_pyramid.rs b/crates/renderling/src/linkage/compute_downsample_depth_pyramid.rs index 4c65701f..af7a2f06 100644 --- a/crates/renderling/src/linkage/compute_downsample_depth_pyramid.rs +++ b/crates/renderling/src/linkage/compute_downsample_depth_pyramid.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "cull::compute_downsample_depth_pyramid"; + pub const ENTRY_POINT: &str = "cull::shader::compute_downsample_depth_pyramid"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/cull-compute_downsample_depth_pyramid.spv") + wgpu::include_spirv!("../../shaders/cull-shader-compute_downsample_depth_pyramid.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +20,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "cullcompute_downsample_depth_pyramid"; + pub const ENTRY_POINT: &str = "cullshadercompute_downsample_depth_pyramid"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/cull-compute_downsample_depth_pyramid.wgsl") + wgpu::include_wgsl!("../../shaders/cull-shader-compute_downsample_depth_pyramid.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/linkage/cubemap_sampling_test_fragment.rs b/crates/renderling/src/linkage/cubemap_sampling_test_fragment.rs index 8783ec44..6a015c8f 100644 --- a/crates/renderling/src/linkage/cubemap_sampling_test_fragment.rs +++ b/crates/renderling/src/linkage/cubemap_sampling_test_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "cubemap::cubemap_sampling_test_fragment"; + pub const ENTRY_POINT: &str = "cubemap::shader::cubemap_sampling_test_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/cubemap-cubemap_sampling_test_fragment.spv") + wgpu::include_spirv!("../../shaders/cubemap-shader-cubemap_sampling_test_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +20,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "cubemapcubemap_sampling_test_fragment"; + pub const ENTRY_POINT: &str = "cubemapshadercubemap_sampling_test_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/cubemap-cubemap_sampling_test_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/cubemap-shader-cubemap_sampling_test_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/linkage/cubemap_sampling_test_vertex.rs b/crates/renderling/src/linkage/cubemap_sampling_test_vertex.rs index 40c8ba5f..bb5528ad 100644 --- a/crates/renderling/src/linkage/cubemap_sampling_test_vertex.rs +++ b/crates/renderling/src/linkage/cubemap_sampling_test_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "cubemap::cubemap_sampling_test_vertex"; + pub const ENTRY_POINT: &str = "cubemap::shader::cubemap_sampling_test_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/cubemap-cubemap_sampling_test_vertex.spv") + wgpu::include_spirv!("../../shaders/cubemap-shader-cubemap_sampling_test_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +20,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "cubemapcubemap_sampling_test_vertex"; + pub const ENTRY_POINT: &str = "cubemapshadercubemap_sampling_test_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/cubemap-cubemap_sampling_test_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/cubemap-shader-cubemap_sampling_test_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/linkage/debug_overlay_fragment.rs b/crates/renderling/src/linkage/debug_overlay_fragment.rs index f365ed3d..3612aa13 100644 --- a/crates/renderling/src/linkage/debug_overlay_fragment.rs +++ b/crates/renderling/src/linkage/debug_overlay_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "debug::debug_overlay_fragment"; + pub const ENTRY_POINT: &str = "debug::shader::debug_overlay_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/debug-debug_overlay_fragment.spv") + wgpu::include_spirv!("../../shaders/debug-shader-debug_overlay_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "debug_overlay_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "debugdebug_overlay_fragment"; + pub const ENTRY_POINT: &str = "debugshaderdebug_overlay_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/debug-debug_overlay_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/debug-shader-debug_overlay_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "debug_overlay_fragment"); diff --git a/crates/renderling/src/linkage/debug_overlay_vertex.rs b/crates/renderling/src/linkage/debug_overlay_vertex.rs index b6e66b69..c3614af8 100644 --- a/crates/renderling/src/linkage/debug_overlay_vertex.rs +++ b/crates/renderling/src/linkage/debug_overlay_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "debug::debug_overlay_vertex"; + pub const ENTRY_POINT: &str = "debug::shader::debug_overlay_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/debug-debug_overlay_vertex.spv") + wgpu::include_spirv!("../../shaders/debug-shader-debug_overlay_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "debug_overlay_vertex"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "debugdebug_overlay_vertex"; + pub const ENTRY_POINT: &str = "debugshaderdebug_overlay_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/debug-debug_overlay_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/debug-shader-debug_overlay_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "debug_overlay_vertex"); diff --git a/crates/renderling/src/linkage/primitive_fragment.rs b/crates/renderling/src/linkage/primitive_fragment.rs index a5cbc0fa..3975086d 100644 --- a/crates/renderling/src/linkage/primitive_fragment.rs +++ b/crates/renderling/src/linkage/primitive_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "stage::primitive_fragment"; + pub const ENTRY_POINT: &str = "primitive::shader::primitive_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/stage-primitive_fragment.spv") + wgpu::include_spirv!("../../shaders/primitive-shader-primitive_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "primitive_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "stageprimitive_fragment"; + pub const ENTRY_POINT: &str = "primitiveshaderprimitive_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/stage-primitive_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/primitive-shader-primitive_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "primitive_fragment"); diff --git a/crates/renderling/src/linkage/primitive_vertex.rs b/crates/renderling/src/linkage/primitive_vertex.rs index fae3130e..40c032a3 100644 --- a/crates/renderling/src/linkage/primitive_vertex.rs +++ b/crates/renderling/src/linkage/primitive_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "stage::primitive_vertex"; + pub const ENTRY_POINT: &str = "primitive::shader::primitive_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/stage-primitive_vertex.spv") + wgpu::include_spirv!("../../shaders/primitive-shader-primitive_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "primitive_vertex"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "stageprimitive_vertex"; + pub const ENTRY_POINT: &str = "primitiveshaderprimitive_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/stage-primitive_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/primitive-shader-primitive_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "primitive_vertex"); diff --git a/crates/renderling/src/material.rs b/crates/renderling/src/material.rs index ba5c9643..92117897 100644 --- a/crates/renderling/src/material.rs +++ b/crates/renderling/src/material.rs @@ -1,60 +1,65 @@ //! Atlas images, used for materials. CPU and GPU. -use crabslab::{Id, SlabItem}; -use glam::{Vec3, Vec4}; - -use crate::atlas::AtlasTextureDescriptor; #[cfg(cpu)] mod cpu; #[cfg(cpu)] pub use cpu::*; -/// Represents a material on the GPU. -#[repr(C)] -#[derive(Clone, Copy, PartialEq, SlabItem, core::fmt::Debug)] -pub struct MaterialDescriptor { - pub emissive_factor: Vec3, - pub emissive_strength_multiplier: f32, - pub albedo_factor: Vec4, - pub metallic_factor: f32, - pub roughness_factor: f32, - - pub albedo_texture_id: Id, - pub metallic_roughness_texture_id: Id, - pub normal_texture_id: Id, - pub ao_texture_id: Id, - pub emissive_texture_id: Id, - - pub albedo_tex_coord: u32, - pub metallic_roughness_tex_coord: u32, - pub normal_tex_coord: u32, - pub ao_tex_coord: u32, - pub emissive_tex_coord: u32, - - pub has_lighting: bool, - pub ao_strength: f32, -} +pub mod shader { + //! Material shader types. + + use crabslab::{Id, SlabItem}; + use glam::{Vec3, Vec4}; + + use crate::atlas::shader::AtlasTextureDescriptor; + + /// Represents a material on the GPU. + #[repr(C)] + #[derive(Clone, Copy, PartialEq, SlabItem, core::fmt::Debug)] + pub struct MaterialDescriptor { + pub emissive_factor: Vec3, + pub emissive_strength_multiplier: f32, + pub albedo_factor: Vec4, + pub metallic_factor: f32, + pub roughness_factor: f32, + + pub albedo_texture_id: Id, + pub metallic_roughness_texture_id: Id, + pub normal_texture_id: Id, + pub ao_texture_id: Id, + pub emissive_texture_id: Id, + + pub albedo_tex_coord: u32, + pub metallic_roughness_tex_coord: u32, + pub normal_tex_coord: u32, + pub ao_tex_coord: u32, + pub emissive_tex_coord: u32, + + pub has_lighting: bool, + pub ao_strength: f32, + } -impl Default for MaterialDescriptor { - fn default() -> Self { - Self { - emissive_factor: Vec3::ZERO, - emissive_strength_multiplier: 1.0, - albedo_factor: Vec4::ONE, - metallic_factor: 1.0, - roughness_factor: 1.0, - albedo_texture_id: Id::NONE, - metallic_roughness_texture_id: Id::NONE, - normal_texture_id: Id::NONE, - ao_texture_id: Id::NONE, - albedo_tex_coord: 0, - metallic_roughness_tex_coord: 0, - normal_tex_coord: 0, - ao_tex_coord: 0, - has_lighting: true, - ao_strength: 0.0, - emissive_texture_id: Id::NONE, - emissive_tex_coord: 0, + impl Default for MaterialDescriptor { + fn default() -> Self { + Self { + emissive_factor: Vec3::ZERO, + emissive_strength_multiplier: 1.0, + albedo_factor: Vec4::ONE, + metallic_factor: 1.0, + roughness_factor: 1.0, + albedo_texture_id: Id::NONE, + metallic_roughness_texture_id: Id::NONE, + normal_texture_id: Id::NONE, + ao_texture_id: Id::NONE, + albedo_tex_coord: 0, + metallic_roughness_tex_coord: 0, + normal_tex_coord: 0, + ao_tex_coord: 0, + has_lighting: true, + ao_strength: 0.0, + emissive_texture_id: Id::NONE, + emissive_tex_coord: 0, + } } } } diff --git a/crates/renderling/src/material/cpu.rs b/crates/renderling/src/material/cpu.rs index 8280ab68..818304a7 100644 --- a/crates/renderling/src/material/cpu.rs +++ b/crates/renderling/src/material/cpu.rs @@ -12,7 +12,7 @@ use glam::{Vec3, Vec4}; use crate::{ atlas::{Atlas, AtlasTexture}, - material::MaterialDescriptor, + material::shader::MaterialDescriptor, }; /// Wrapper around the materials slab, which holds material textures in an atlas. diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index ecb14a80..c3f5c94a 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -1,4 +1,4 @@ -//! "Physically based" types and functions. +//! "Physically based" shader types and functions. //! //! ## References //! * @@ -11,16 +11,16 @@ use glam::{Mat4, Vec2, Vec3, Vec4, Vec4Swizzles}; use spirv_std::num_traits::{Float, Zero}; use crate::{ - atlas::AtlasTextureDescriptor, - geometry::GeometryDescriptor, - light::{ + atlas::shader::AtlasTextureDescriptor, + geometry::shader::GeometryDescriptor, + light::shader::{ DirectionalLightDescriptor, LightStyle, LightingDescriptor, PointLightDescriptor, ShadowCalculation, SpotLightCalculation, }, - material::MaterialDescriptor, + material::shader::MaterialDescriptor, math::{self, IsSampler, IsVector, Sample2d, Sample2dArray, SampleCube}, + primitive::shader::PrimitiveDescriptor, println as my_println, - stage::PrimitiveDescriptor, }; pub mod debug; diff --git a/crates/renderling/src/primitive.rs b/crates/renderling/src/primitive.rs new file mode 100644 index 00000000..128b4044 --- /dev/null +++ b/crates/renderling/src/primitive.rs @@ -0,0 +1,8 @@ +//! Mesh primitives + +#[cfg(cpu)] +mod cpu; +#[cfg(cpu)] +pub use cpu::*; + +pub mod shader; diff --git a/crates/renderling/src/stage/cpu/primitive.rs b/crates/renderling/src/primitive/cpu.rs similarity index 99% rename from crates/renderling/src/stage/cpu/primitive.rs rename to crates/renderling/src/primitive/cpu.rs index 62e08c93..15b03dbb 100644 --- a/crates/renderling/src/stage/cpu/primitive.rs +++ b/crates/renderling/src/primitive/cpu.rs @@ -10,7 +10,8 @@ use crate::{ bvol::BoundingSphere, geometry::{Indices, MorphTargetWeights, MorphTargets, Skin, Vertices}, material::Material, - stage::PrimitiveDescriptor, + primitive::shader::PrimitiveDescriptor, + stage::Stage, transform::Transform, types::GpuOnlyArray, }; @@ -36,7 +37,7 @@ impl Primitive { /// /// The returned [`Primitive`] will have the stage's default [`Vertices`], /// which is an all-white unit cube. - pub fn new(stage: &super::Stage) -> Self { + pub fn new(stage: &Stage) -> Self { let descriptor = stage .geometry .slab_allocator() diff --git a/crates/renderling/src/primitive/shader.rs b/crates/renderling/src/primitive/shader.rs new file mode 100644 index 00000000..9aac4ae5 --- /dev/null +++ b/crates/renderling/src/primitive/shader.rs @@ -0,0 +1,317 @@ +//! Shader support for rendering primitives. +use crabslab::{Array, Id, Slab, SlabItem}; +use glam::{Mat4, Vec2, Vec3, Vec4, Vec4Swizzles}; +use spirv_std::{ + image::{Cubemap, Image2d, Image2dArray}, + spirv, Image, Sampler, +}; + +// use glam::Mat4; +// #[cfg(not(target_arch = "spirv"))] +// use glam::UVec2; + +// #[allow(unused_imports)] +// use spirv_std::num_traits::Float; + +use crate::{ + bvol::BoundingSphere, + geometry::{ + shader::{GeometryDescriptor, SkinDescriptor}, + MorphTarget, Vertex, + }, + material::shader::MaterialDescriptor, + math::IsVector, + transform::shader::TransformDescriptor, +}; + +#[allow(unused_imports)] +use spirv_std::num_traits::Float; + +/// Returned by [`PrimitiveDescriptor::get_vertex_info`]. +pub struct VertexInfo { + pub vertex: Vertex, + pub transform: TransformDescriptor, + pub model_matrix: Mat4, + pub world_pos: Vec3, +} + +/// A draw call used to render some geometry. +#[derive(Clone, Copy, PartialEq, SlabItem, Debug)] +#[offsets] +pub struct PrimitiveDescriptor { + pub visible: bool, + pub vertices_array: Array, + /// Bounding sphere of the entire primitive, in local space. + pub bounds: BoundingSphere, + pub indices_array: Array, + pub transform_id: Id, + pub material_id: Id, + pub skin_id: Id, + pub morph_targets: Array>, + pub morph_weights: Array, + pub geometry_descriptor_id: Id, +} + +impl Default for PrimitiveDescriptor { + fn default() -> Self { + PrimitiveDescriptor { + visible: true, + vertices_array: Array::default(), + bounds: BoundingSphere::default(), + indices_array: Array::default(), + transform_id: Id::NONE, + material_id: Id::NONE, + skin_id: Id::NONE, + morph_targets: Array::default(), + morph_weights: Array::default(), + geometry_descriptor_id: Id::new(0), + } + } +} + +impl PrimitiveDescriptor { + /// Returns the vertex at the given index and its related values. + /// + /// These values are often used in shaders, so they are grouped together. + pub fn get_vertex_info(&self, vertex_index: u32, geometry_slab: &[u32]) -> VertexInfo { + let vertex = self.get_vertex(vertex_index, geometry_slab); + let transform = self.get_transform(vertex, geometry_slab); + let model_matrix = Mat4::from(transform); + let world_pos = model_matrix.transform_point3(vertex.position); + VertexInfo { + vertex, + transform, + model_matrix, + world_pos, + } + } + /// Retrieve the transform of this `primitive`. + /// + /// This takes into consideration all skinning matrices. + pub fn get_transform(&self, vertex: Vertex, slab: &[u32]) -> TransformDescriptor { + let config = slab.read_unchecked(self.geometry_descriptor_id); + if config.has_skinning && self.skin_id.is_some() { + let skin = slab.read(self.skin_id); + TransformDescriptor::from(skin.get_skinning_matrix(vertex, slab)) + } else { + slab.read(self.transform_id) + } + } + + /// Retrieve the vertex from the slab, calculating any displacement due to + /// morph targets. + pub fn get_vertex(&self, vertex_index: u32, slab: &[u32]) -> Vertex { + let index = if self.indices_array.is_null() { + vertex_index as usize + } else { + slab.read(self.indices_array.at(vertex_index as usize)) as usize + }; + let vertex_id = self.vertices_array.at(index); + let mut vertex = slab.read_unchecked(vertex_id); + for i in 0..self.morph_targets.len() { + let morph_target_array = slab.read(self.morph_targets.at(i)); + let morph_target = slab.read(morph_target_array.at(index)); + let weight = slab.read(self.morph_weights.at(i)); + vertex.position += weight * morph_target.position; + vertex.normal += weight * morph_target.normal; + vertex.tangent += weight * morph_target.tangent.extend(0.0); + } + vertex + } + + pub fn get_vertex_count(&self) -> u32 { + if self.indices_array.is_null() { + self.vertices_array.len() as u32 + } else { + self.indices_array.len() as u32 + } + } +} + +#[cfg(test)] +/// A helper struct that contains all outputs of the primitive's PBR vertex shader. +#[derive(Default, Debug, Clone, Copy, PartialEq)] +pub struct PrimitivePbrVertexInfo { + pub primitive: PrimitiveDescriptor, + pub primitive_id: Id, + pub vertex_index: u32, + pub vertex: Vertex, + pub transform: TransformDescriptor, + pub model_matrix: Mat4, + pub view_projection: Mat4, + pub out_color: Vec4, + pub out_uv0: Vec2, + pub out_uv1: Vec2, + pub out_norm: Vec3, + pub out_tangent: Vec3, + pub out_bitangent: Vec3, + pub out_pos: Vec3, + pub out_clip_pos: Vec4, +} + +/// primitive vertex shader. +#[spirv(vertex)] +#[allow(clippy::too_many_arguments)] +pub fn primitive_vertex( + // Points at a `primitive` + #[spirv(instance_index)] primitive_id: Id, + // Which vertex within the primitive are we rendering + #[spirv(vertex_index)] vertex_index: u32, + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], + + #[spirv(flat)] out_primitive: &mut Id, + // TODO: Think about placing all these out values in a G-Buffer + // But do we have enough buffers + enough space on web? + // ...and can we write to buffers from vertex shaders on web? + out_color: &mut Vec4, + out_uv0: &mut Vec2, + out_uv1: &mut Vec2, + out_norm: &mut Vec3, + out_tangent: &mut Vec3, + out_bitangent: &mut Vec3, + out_world_pos: &mut Vec3, + #[spirv(position)] out_clip_pos: &mut Vec4, + // test-only info struct + #[cfg(test)] out_info: &mut PrimitivePbrVertexInfo, +) { + let primitive = geometry_slab.read_unchecked(primitive_id); + if !primitive.visible { + // put it outside the clipping frustum + *out_clip_pos = Vec4::new(10.0, 10.0, 10.0, 1.0); + return; + } + + *out_primitive = primitive_id; + + let VertexInfo { + vertex, + transform, + model_matrix, + world_pos, + } = primitive.get_vertex_info(vertex_index, geometry_slab); + *out_color = vertex.color; + *out_uv0 = vertex.uv0; + *out_uv1 = vertex.uv1; + *out_world_pos = world_pos; + + let scale2 = transform.scale * transform.scale; + let normal = vertex.normal.alt_norm_or_zero(); + let tangent = vertex.tangent.xyz().alt_norm_or_zero(); + let normal_w: Vec3 = (model_matrix * (normal / scale2).extend(0.0)) + .xyz() + .alt_norm_or_zero(); + *out_norm = normal_w; + + let tangent_w: Vec3 = (model_matrix * tangent.extend(0.0)) + .xyz() + .alt_norm_or_zero(); + *out_tangent = tangent_w; + + let bitangent_w = normal_w.cross(tangent_w) * if vertex.tangent.w >= 0.0 { 1.0 } else { -1.0 }; + *out_bitangent = bitangent_w; + + let camera_id = geometry_slab + .read_unchecked(primitive.geometry_descriptor_id + GeometryDescriptor::OFFSET_OF_CAMERA_ID); + let camera = geometry_slab.read(camera_id); + let clip_pos = camera.view_projection() * world_pos.extend(1.0); + *out_clip_pos = clip_pos; + #[cfg(test)] + { + *out_info = PrimitivePbrVertexInfo { + primitive_id, + vertex_index, + vertex, + transform, + model_matrix, + view_projection: camera.view_projection(), + out_clip_pos: clip_pos, + primitive, + out_color: *out_color, + out_uv0: *out_uv0, + out_uv1: *out_uv1, + out_norm: *out_norm, + out_tangent: *out_tangent, + out_bitangent: *out_bitangent, + out_pos: *out_world_pos, + }; + } +} + +/// primitive fragment shader +#[allow(clippy::too_many_arguments, dead_code)] +#[spirv(fragment)] +pub fn primitive_fragment( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] material_slab: &[u32], + #[spirv(descriptor_set = 0, binding = 2)] atlas: &Image2dArray, + #[spirv(descriptor_set = 0, binding = 3)] atlas_sampler: &Sampler, + #[spirv(descriptor_set = 0, binding = 4)] irradiance: &Cubemap, + #[spirv(descriptor_set = 0, binding = 5)] irradiance_sampler: &Sampler, + #[spirv(descriptor_set = 0, binding = 6)] prefiltered: &Cubemap, + #[spirv(descriptor_set = 0, binding = 7)] prefiltered_sampler: &Sampler, + #[spirv(descriptor_set = 0, binding = 8)] brdf: &Image2d, + #[spirv(descriptor_set = 0, binding = 9)] brdf_sampler: &Sampler, + #[spirv(storage_buffer, descriptor_set = 0, binding = 10)] light_slab: &[u32], + #[spirv(descriptor_set = 0, binding = 11)] shadow_map: &Image!(2D, type=f32, sampled, arrayed), + #[spirv(descriptor_set = 0, binding = 12)] shadow_map_sampler: &Sampler, + #[cfg(feature = "debug-slab")] + #[spirv(storage_buffer, descriptor_set = 0, binding = 13)] + debug_slab: &mut [u32], + + #[spirv(flat)] primitive_id: Id, + #[spirv(frag_coord)] frag_coord: Vec4, + in_color: Vec4, + in_uv0: Vec2, + in_uv1: Vec2, + in_norm: Vec3, + in_tangent: Vec3, + in_bitangent: Vec3, + world_pos: Vec3, + output: &mut Vec4, +) { + // proxy to a separate impl that allows us to test on CPU + crate::pbr::fragment_impl( + atlas, + atlas_sampler, + irradiance, + irradiance_sampler, + prefiltered, + prefiltered_sampler, + brdf, + brdf_sampler, + shadow_map, + shadow_map_sampler, + geometry_slab, + material_slab, + light_slab, + primitive_id, + frag_coord, + in_color, + in_uv0, + in_uv1, + in_norm, + in_tangent, + in_bitangent, + world_pos, + output, + ); +} + +#[cfg(feature = "test_i8_16_extraction")] +#[spirv(compute(threads(32)))] +/// A shader to ensure that we can extract i8 and i16 values from a storage +/// buffer. +pub fn test_i8_i16_extraction( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &mut [u32], + #[spirv(global_invocation_id)] global_id: UVec3, +) { + let index = global_id.x as usize; + let (value, _, _) = crate::bits::extract_i8(index, 2, slab); + if value > 0 { + slab[index] = value as u32; + } + let (value, _, _) = crate::bits::extract_i16(index, 2, slab); + if value > 0 { + slab[index] = value as u32; + } +} diff --git a/crates/renderling/src/skybox.rs b/crates/renderling/src/skybox.rs index a061d8f6..570d8e58 100644 --- a/crates/renderling/src/skybox.rs +++ b/crates/renderling/src/skybox.rs @@ -10,7 +10,7 @@ use spirv_std::{ use spirv_std::num_traits::Float; use crate::{ - camera::CameraDescriptor, + camera::shader::CameraDescriptor, math::{self, IsVector}, }; diff --git a/crates/renderling/src/skybox/cpu.rs b/crates/renderling/src/skybox/cpu.rs index 75a73d91..c4f5bbfe 100644 --- a/crates/renderling/src/skybox/cpu.rs +++ b/crates/renderling/src/skybox/cpu.rs @@ -7,7 +7,8 @@ use crabslab::Id; use glam::{Mat4, UVec2, Vec3}; use crate::{ - atlas::AtlasImage, camera::CameraDescriptor, convolution::VertexPrefilterEnvironmentCubemapIds, + atlas::AtlasImage, camera::shader::CameraDescriptor, + convolution::VertexPrefilterEnvironmentCubemapIds, cubemap::EquirectangularImageToCubemapBlitter, texture::Texture, }; diff --git a/crates/renderling/src/stage.rs b/crates/renderling/src/stage.rs index 4ab6797a..69016fbc 100644 --- a/crates/renderling/src/stage.rs +++ b/crates/renderling/src/stage.rs @@ -1,326 +1,13 @@ -//! GPU staging area. +//! Scene staging. //! -//! The `Stage` object contains a slab buffer and a render pipeline. -//! It is used to stage objects for rendering. -use crabslab::{Array, Id, Slab, SlabItem}; -#[cfg(not(target_arch = "spirv"))] -use glam::UVec2; -use glam::{Mat4, Vec2, Vec3, Vec4, Vec4Swizzles}; -use spirv_std::{ - image::{Cubemap, Image2d, Image2dArray}, - spirv, Image, Sampler, -}; +//! The [`Stage`] is the entrypoint for staging data on the GPU and +//! interacting with lighting. -use crate::{ - bvol::BoundingSphere, - geometry::{GeometryDescriptor, MorphTarget, SkinDescriptor, Vertex}, - material::MaterialDescriptor, - math::IsVector, - transform::TransformDescriptor, -}; - -#[allow(unused_imports)] -use spirv_std::num_traits::Float; - -#[cfg(not(target_arch = "spirv"))] +#[cfg(cpu)] mod cpu; -#[cfg(not(target_arch = "spirv"))] +#[cfg(cpu)] pub use cpu::*; -#[cfg(all(feature = "gltf", not(target_arch = "spirv")))] -mod gltf_support; -#[cfg(all(feature = "gltf", not(target_arch = "spirv")))] -pub use gltf_support::*; - -/// Returned by [`PrimitiveDescriptor::get_vertex_info`]. -pub struct VertexInfo { - pub vertex: Vertex, - pub transform: TransformDescriptor, - pub model_matrix: Mat4, - pub world_pos: Vec3, -} - -/// A draw call used to render some geometry. -#[derive(Clone, Copy, PartialEq, SlabItem, Debug)] -#[offsets] -pub struct PrimitiveDescriptor { - pub visible: bool, - pub vertices_array: Array, - /// Bounding sphere of the entire primitive, in local space. - pub bounds: BoundingSphere, - pub indices_array: Array, - pub transform_id: Id, - pub material_id: Id, - pub skin_id: Id, - pub morph_targets: Array>, - pub morph_weights: Array, - pub geometry_descriptor_id: Id, -} - -impl Default for PrimitiveDescriptor { - fn default() -> Self { - PrimitiveDescriptor { - visible: true, - vertices_array: Array::default(), - bounds: BoundingSphere::default(), - indices_array: Array::default(), - transform_id: Id::NONE, - material_id: Id::NONE, - skin_id: Id::NONE, - morph_targets: Array::default(), - morph_weights: Array::default(), - geometry_descriptor_id: Id::new(0), - } - } -} - -impl PrimitiveDescriptor { - /// Returns the vertex at the given index and its related values. - /// - /// These values are often used in shaders, so they are grouped together. - pub fn get_vertex_info(&self, vertex_index: u32, geometry_slab: &[u32]) -> VertexInfo { - let vertex = self.get_vertex(vertex_index, geometry_slab); - let transform = self.get_transform(vertex, geometry_slab); - let model_matrix = Mat4::from(transform); - let world_pos = model_matrix.transform_point3(vertex.position); - VertexInfo { - vertex, - transform, - model_matrix, - world_pos, - } - } - /// Retrieve the transform of this `primitive`. - /// - /// This takes into consideration all skinning matrices. - pub fn get_transform(&self, vertex: Vertex, slab: &[u32]) -> TransformDescriptor { - let config = slab.read_unchecked(self.geometry_descriptor_id); - if config.has_skinning && self.skin_id.is_some() { - let skin = slab.read(self.skin_id); - TransformDescriptor::from(skin.get_skinning_matrix(vertex, slab)) - } else { - slab.read(self.transform_id) - } - } - - /// Retrieve the vertex from the slab, calculating any displacement due to - /// morph targets. - pub fn get_vertex(&self, vertex_index: u32, slab: &[u32]) -> Vertex { - let index = if self.indices_array.is_null() { - vertex_index as usize - } else { - slab.read(self.indices_array.at(vertex_index as usize)) as usize - }; - let vertex_id = self.vertices_array.at(index); - let mut vertex = slab.read_unchecked(vertex_id); - for i in 0..self.morph_targets.len() { - let morph_target_array = slab.read(self.morph_targets.at(i)); - let morph_target = slab.read(morph_target_array.at(index)); - let weight = slab.read(self.morph_weights.at(i)); - vertex.position += weight * morph_target.position; - vertex.normal += weight * morph_target.normal; - vertex.tangent += weight * morph_target.tangent.extend(0.0); - } - vertex - } - - pub fn get_vertex_count(&self) -> u32 { - if self.indices_array.is_null() { - self.vertices_array.len() as u32 - } else { - self.indices_array.len() as u32 - } - } -} - -#[cfg(test)] -/// A helper struct that contains all outputs of the primitive's PBR vertex shader. -#[derive(Default, Debug, Clone, Copy, PartialEq)] -pub struct PrimitivePbrVertexInfo { - pub primitive: PrimitiveDescriptor, - pub primitive_id: Id, - pub vertex_index: u32, - pub vertex: Vertex, - pub transform: TransformDescriptor, - pub model_matrix: Mat4, - pub view_projection: Mat4, - pub out_color: Vec4, - pub out_uv0: Vec2, - pub out_uv1: Vec2, - pub out_norm: Vec3, - pub out_tangent: Vec3, - pub out_bitangent: Vec3, - pub out_pos: Vec3, - pub out_clip_pos: Vec4, -} - -/// primitive vertex shader. -#[spirv(vertex)] -#[allow(clippy::too_many_arguments)] -pub fn primitive_vertex( - // Points at a `primitive` - #[spirv(instance_index)] primitive_id: Id, - // Which vertex within the primitive are we rendering - #[spirv(vertex_index)] vertex_index: u32, - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], - - #[spirv(flat)] out_primitive: &mut Id, - // TODO: Think about placing all these out values in a G-Buffer - // But do we have enough buffers + enough space on web? - // ...and can we write to buffers from vertex shaders on web? - out_color: &mut Vec4, - out_uv0: &mut Vec2, - out_uv1: &mut Vec2, - out_norm: &mut Vec3, - out_tangent: &mut Vec3, - out_bitangent: &mut Vec3, - out_world_pos: &mut Vec3, - #[spirv(position)] out_clip_pos: &mut Vec4, - // test-only info struct - #[cfg(test)] out_info: &mut PrimitivePbrVertexInfo, -) { - let primitive = geometry_slab.read_unchecked(primitive_id); - if !primitive.visible { - // put it outside the clipping frustum - *out_clip_pos = Vec4::new(10.0, 10.0, 10.0, 1.0); - return; - } - - *out_primitive = primitive_id; - - let VertexInfo { - vertex, - transform, - model_matrix, - world_pos, - } = primitive.get_vertex_info(vertex_index, geometry_slab); - *out_color = vertex.color; - *out_uv0 = vertex.uv0; - *out_uv1 = vertex.uv1; - *out_world_pos = world_pos; - - let scale2 = transform.scale * transform.scale; - let normal = vertex.normal.alt_norm_or_zero(); - let tangent = vertex.tangent.xyz().alt_norm_or_zero(); - let normal_w: Vec3 = (model_matrix * (normal / scale2).extend(0.0)) - .xyz() - .alt_norm_or_zero(); - *out_norm = normal_w; - - let tangent_w: Vec3 = (model_matrix * tangent.extend(0.0)) - .xyz() - .alt_norm_or_zero(); - *out_tangent = tangent_w; - - let bitangent_w = normal_w.cross(tangent_w) * if vertex.tangent.w >= 0.0 { 1.0 } else { -1.0 }; - *out_bitangent = bitangent_w; - - let camera_id = geometry_slab - .read_unchecked(primitive.geometry_descriptor_id + GeometryDescriptor::OFFSET_OF_CAMERA_ID); - let camera = geometry_slab.read(camera_id); - let clip_pos = camera.view_projection() * world_pos.extend(1.0); - *out_clip_pos = clip_pos; - #[cfg(test)] - { - *out_info = PrimitivePbrVertexInfo { - primitive_id, - vertex_index, - vertex, - transform, - model_matrix, - view_projection: camera.view_projection(), - out_clip_pos: clip_pos, - primitive, - out_color: *out_color, - out_uv0: *out_uv0, - out_uv1: *out_uv1, - out_norm: *out_norm, - out_tangent: *out_tangent, - out_bitangent: *out_bitangent, - out_pos: *out_world_pos, - }; - } -} - -/// primitive fragment shader -#[allow(clippy::too_many_arguments, dead_code)] -#[spirv(fragment)] -pub fn primitive_fragment( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] geometry_slab: &[u32], - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] material_slab: &[u32], - #[spirv(descriptor_set = 0, binding = 2)] atlas: &Image2dArray, - #[spirv(descriptor_set = 0, binding = 3)] atlas_sampler: &Sampler, - #[spirv(descriptor_set = 0, binding = 4)] irradiance: &Cubemap, - #[spirv(descriptor_set = 0, binding = 5)] irradiance_sampler: &Sampler, - #[spirv(descriptor_set = 0, binding = 6)] prefiltered: &Cubemap, - #[spirv(descriptor_set = 0, binding = 7)] prefiltered_sampler: &Sampler, - #[spirv(descriptor_set = 0, binding = 8)] brdf: &Image2d, - #[spirv(descriptor_set = 0, binding = 9)] brdf_sampler: &Sampler, - #[spirv(storage_buffer, descriptor_set = 0, binding = 10)] light_slab: &[u32], - #[spirv(descriptor_set = 0, binding = 11)] shadow_map: &Image!(2D, type=f32, sampled, arrayed), - #[spirv(descriptor_set = 0, binding = 12)] shadow_map_sampler: &Sampler, - #[cfg(feature = "debug-slab")] - #[spirv(storage_buffer, descriptor_set = 0, binding = 13)] - debug_slab: &mut [u32], - - #[spirv(flat)] primitive_id: Id, - #[spirv(frag_coord)] frag_coord: Vec4, - in_color: Vec4, - in_uv0: Vec2, - in_uv1: Vec2, - in_norm: Vec3, - in_tangent: Vec3, - in_bitangent: Vec3, - world_pos: Vec3, - output: &mut Vec4, -) { - // proxy to a separate impl that allows us to test on CPU - crate::pbr::fragment_impl( - atlas, - atlas_sampler, - irradiance, - irradiance_sampler, - prefiltered, - prefiltered_sampler, - brdf, - brdf_sampler, - shadow_map, - shadow_map_sampler, - geometry_slab, - material_slab, - light_slab, - primitive_id, - frag_coord, - in_color, - in_uv0, - in_uv1, - in_norm, - in_tangent, - in_bitangent, - world_pos, - output, - ); -} - -#[cfg(feature = "test_i8_16_extraction")] -#[spirv(compute(threads(32)))] -/// A shader to ensure that we can extract i8 and i16 values from a storage -/// buffer. -pub fn test_i8_i16_extraction( - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &mut [u32], - #[spirv(global_invocation_id)] global_id: UVec3, -) { - let index = global_id.x as usize; - let (value, _, _) = crate::bits::extract_i8(index, 2, slab); - if value > 0 { - slab[index] = value as u32; - } - let (value, _, _) = crate::bits::extract_i16(index, 2, slab); - if value > 0 { - slab[index] = value as u32; - } -} - #[cfg(test)] mod test { use craballoc::{prelude::SlabAllocator, runtime::CpuRuntime}; @@ -328,7 +15,7 @@ mod test { use crate::{ math::IsMatrix, - transform::{NestedTransform, TransformDescriptor}, + transform::{shader::TransformDescriptor, NestedTransform}, }; #[test] diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index fbc6f711..e6185f26 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -1,32 +1,26 @@ //! GPU staging area. -//! -//! The [`Stage`] object is used to "stage" objects on the GPU, including -//! mesh geometry, transforms, materials and lights. -//! -//! [`Stage`] also controls various effects: -//! * [`Skybox`] -//! - [`Stage::with_skybox`] -//! - [`Stage::set_skybox`] -//! * [`Bloom`] -//! * [`Tonemapping`]. -//! -//! It is used to stage [`Renderlet`]s for rendering. use core::ops::Deref; use core::sync::atomic::{AtomicU32, AtomicUsize, Ordering}; use craballoc::prelude::*; use crabslab::Id; +use glam::{Mat4, UVec2, Vec4}; use snafu::Snafu; use std::sync::{atomic::AtomicBool, Arc, Mutex, RwLock}; use crate::atlas::AtlasTexture; use crate::camera::Camera; +use crate::geometry::{shader::GeometryDescriptor, MorphTarget, Vertex}; +use crate::gltf::GltfDocument; +#[cfg(gltf)] +use crate::gltf::StageGltfError; use crate::light::{DirectionalLight, IsLight, Light, PointLight, SpotLight}; use crate::material::Material; +use crate::primitive::Primitive; use crate::{ atlas::{AtlasError, AtlasImage, AtlasImageError}, bindgroup::ManagedBindGroup, bloom::Bloom, - camera::CameraDescriptor, + camera::shader::CameraDescriptor, debug::DebugOverlay, draw::DrawCalls, geometry::{Geometry, Indices, MorphTargetWeights, MorphTargets, Skin, SkinJoint, Vertices}, @@ -42,13 +36,7 @@ use crate::{ transform::{NestedTransform, Transform}, }; -#[cfg(cpu)] -pub mod primitive; -#[cfg(cpu)] -pub use primitive::*; - -use super::*; - +/// Enumeration of errors that may be the result of [`Stage`] functions. #[derive(Debug, Snafu)] pub enum StageError { #[snafu(display("{source}"))] @@ -56,6 +44,10 @@ pub enum StageError { #[snafu(display("{source}"))] Lighting { source: LightingError }, + + #[cfg(gltf)] + #[snafu(display("{source}"))] + Gltf { source: crate::gltf::StageGltfError }, } impl From for StageError { @@ -70,6 +62,13 @@ impl From for StageError { } } +#[cfg(gltf)] +impl From for StageError { + fn from(source: crate::gltf::StageGltfError) -> Self { + Self::Gltf { source } + } +} + fn create_msaa_textureview( device: &wgpu::Device, width: u32, @@ -95,14 +94,16 @@ fn create_msaa_textureview( .create_view(&wgpu::TextureViewDescriptor::default()) } +/// Result of calling [`Stage::commit`]. pub struct StageCommitResult { - pub geometry_buffer: SlabBuffer, - pub lighting_buffer: SlabBuffer, - pub materials_buffer: SlabBuffer, + pub(crate) geometry_buffer: SlabBuffer, + pub(crate) lighting_buffer: SlabBuffer, + pub(crate) materials_buffer: SlabBuffer, } impl StageCommitResult { - pub fn latest_creation_time(&self) -> usize { + /// Timestamp of the most recently created buffer used by the stage. + pub(crate) fn latest_creation_time(&self) -> usize { [ &self.geometry_buffer, &self.materials_buffer, @@ -114,7 +115,9 @@ impl StageCommitResult { .unwrap_or_default() } - pub fn should_invalidate(&self, previous_creation_time: usize) -> bool { + /// Whether or not the stage's bindgroups need to be invalidated as a result + /// of the call to [`Stage::commit`] that produced this `StageCommitResult`. + pub(crate) fn should_invalidate(&self, previous_creation_time: usize) -> bool { let mut should = false; if self.geometry_buffer.is_new_this_commit() { log::trace!("geometry buffer is new this frame"); @@ -221,7 +224,7 @@ impl RenderletBindGroup<'_> { } /// Performs a rendering of an entire scene, given the resources at hand. -pub struct StageRendering<'a> { +pub(crate) struct StageRendering<'a> { // TODO: include the rest of the needed paramaters from `stage`, and then remove `stage` pub stage: &'a Stage, pub pipeline: &'a wgpu::RenderPipeline, @@ -313,12 +316,60 @@ impl StageRendering<'_> { } } -/// Represents an entire scene worth of rendering data. +/// Entrypoint for staging data on the GPU and interacting with lighting. +/// +/// # Design +/// +/// The `Stage` struct serves as the central hub for managing and staging data on the GPU. +/// It provides a consistent API for creating resources, applying effects, and customizing parameters. +/// +/// The `Stage` uses a combination of `new_*`, `with_*`, `set_*`, and getter functions to facilitate +/// resource management and customization. +/// +/// Resources are managed internally, requiring no additional lifecycle work from the user. +/// This design simplifies the process of resource management, allowing developers to focus on creating and rendering +/// their scenes without worrying about the underlying GPU resource management. +/// +/// # Resources +/// +/// The `Stage` is responsible for creating various resources and staging them on the GPU. +/// It handles the setup and management of the following resources: /// -/// A clone of a stage is a reference to the same stage. +/// * [`Camera`]: Manages the view and projection matrices for rendering scenes. +/// - [`Stage::new_camera`] creates a new [`Camera`]. +/// - [`Stage::use_camera`] tells the `Stage` to use a camera. +/// * [`Transform`]: Represents the position, rotation, and scale of objects. +/// - [`Stage::new_transform`] creates a new [`Transform`]. +/// * [`NestedTransform`]: Allows for hierarchical transformations, useful for complex object hierarchies. +/// - [`Stage::new_nested_transform`] creates a new [`NestedTransform`] +/// * [`Vertices`]: Manages vertex data for rendering meshes. +/// - [`Stage::new_vertices`] +/// * [`Indices`]: Manages index data for rendering meshes with indexed drawing. +/// - [`Stage::new_indices`] +/// * [`Primitive`]: Represents a drawable object in the scene. +/// - [`Stage::new_primitive`] +/// * [`GltfDocument`]: Handles loading and managing GLTF assets. +/// - [`Stage::load_gltf_document_from_path`] loads a new GLTF document from the local filesystem. +/// - [`Stage::load_gltf_document_from_bytes`] parses a new GLTF document from pre-loaded bytes. +/// * [`Skin`]: Animation and rigging information. +/// - [`Stage::new_skin`] /// -/// ## Note -/// Only available on the CPU. Not available in shaders. +/// # Lighting effects +/// +/// The `Stage` also manages various lighting effects, which enhance the visual quality of the scene: +/// +/// * [`AnalyticalLight`]: Simulates a single light source, with three flavors: +/// - [`DirectionalLight`]: Represents sunlight or other distant light sources. +/// - [`PointLight`]: Represents a light source that emits light in all directions from a single point. +/// - [`SpotLight`]: Represents a light source that emits light in a cone shape. +/// * [`Skybox`]: Provides image-based lighting (IBL) for realistic environmental reflections and ambient lighting. +/// * [`Bloom`]: Adds a glow effect to bright areas of the scene, enhancing visual appeal. +/// * [`ShadowMap`]: Manages shadow mapping for realistic shadow rendering. +/// * [`LightTiling`]: Optimizes lighting calculations by dividing the scene into tiles for efficient processing. +/// +/// # Note +/// +/// Clones of [`Stage`] all point to the same underlying data. #[derive(Clone)] pub struct Stage { pub(crate) geometry: Geometry, @@ -382,7 +433,28 @@ impl AsRef for Stage { } } -/// Geometry methods. +#[cfg(gltf)] +/// GLTF functions +impl Stage { + pub fn load_gltf_document_from_path( + &self, + path: impl AsRef, + ) -> Result { + let (document, buffers, images) = gltf::import(path).map_err(StageGltfError::from)?; + GltfDocument::from_gltf(self, &document, buffers, images) + } + + pub fn load_gltf_document_from_bytes( + &self, + bytes: impl AsRef<[u8]>, + ) -> Result { + let (document, buffers, images) = + gltf::import_slice(bytes).map_err(StageGltfError::from)?; + GltfDocument::from_gltf(self, &document, buffers, images) + } +} + +/// Geometry functions impl Stage { /// Returns the vertices of a white unit cube. /// @@ -614,7 +686,7 @@ impl Stage { /// `znear` or `zfar` needs adjustment. pub fn new_shadow_map( &self, - analytical_light_bundle: &AnalyticalLight, + analytical_light: &AnalyticalLight, // Size of the shadow map size: UVec2, // Distance to the near plane of the shadow map's frustum. @@ -632,7 +704,7 @@ impl Stage { { Ok(self .lighting - .new_shadow_map(analytical_light_bundle, size, z_near, z_far)?) + .new_shadow_map(analytical_light, size, z_near, z_far)?) } /// Enable light tiling, creating a new [`LightTiling`]. @@ -669,7 +741,7 @@ impl Stage { /// Run all upkeep and commit all staged changes to the GPU. /// - /// This is done implicitly in [`Stage::render`] and [`StageRendering::run`]. + /// This is done implicitly in [`Stage::render`]. /// /// This can be used after dropping resources to reclaim those resources on the GPU. #[must_use] @@ -1425,13 +1497,12 @@ impl Stage { #[cfg(test)] mod test { - use craballoc::runtime::CpuRuntime; + use craballoc::{runtime::CpuRuntime, slab::SlabAllocator}; use crabslab::{Array, Id, Slab}; use glam::{Mat4, Vec2, Vec3, Vec4}; use crate::{ - geometry::{Geometry, GeometryDescriptor}, - stage::{cpu::SlabAllocator, Vertex}, + geometry::{shader::GeometryDescriptor, Geometry, Vertex}, test::BlockOnFuture, transform::NestedTransform, Context, diff --git a/crates/renderling/src/transform.rs b/crates/renderling/src/transform.rs index 19959cb8..1c4e12dc 100644 --- a/crates/renderling/src/transform.rs +++ b/crates/renderling/src/transform.rs @@ -1,65 +1,70 @@ -//! Decomposed 3d transform. -use crabslab::SlabItem; -use glam::{Mat4, Quat, Vec3}; - -use crate::math::IsMatrix; +//! Decomposed 3d transforms and hierarchies. #[cfg(cpu)] mod cpu; #[cfg(cpu)] pub use cpu::*; -#[derive(Clone, Copy, PartialEq, SlabItem, core::fmt::Debug)] -/// A GPU descriptor of a decomposed transformation. -/// -/// `TransformDescriptor` can be converted to/from [`Mat4`]. -pub struct TransformDescriptor { - pub translation: Vec3, - pub rotation: Quat, - pub scale: Vec3, -} +pub mod shader { + use crabslab::SlabItem; + use glam::{Mat4, Quat, Vec3}; + + use crate::math::IsMatrix; -impl Default for TransformDescriptor { - fn default() -> Self { - Self::IDENTITY + #[derive(Clone, Copy, PartialEq, SlabItem, core::fmt::Debug)] + /// A GPU descriptor of a decomposed transformation. + /// + /// `TransformDescriptor` can be converted to/from [`Mat4`]. + pub struct TransformDescriptor { + pub translation: Vec3, + pub rotation: Quat, + pub scale: Vec3, } -} -impl From for TransformDescriptor { - fn from(value: Mat4) -> Self { - let (scale, rotation, translation) = value.to_scale_rotation_translation_or_id(); - TransformDescriptor { - translation, - rotation, - scale, + impl Default for TransformDescriptor { + fn default() -> Self { + Self::IDENTITY + } + } + + impl From for TransformDescriptor { + fn from(value: Mat4) -> Self { + let (scale, rotation, translation) = value.to_scale_rotation_translation_or_id(); + TransformDescriptor { + translation, + rotation, + scale, + } } } -} -impl From for Mat4 { - fn from( - TransformDescriptor { - translation, - rotation, - scale, - }: TransformDescriptor, - ) -> Self { - Mat4::from_scale_rotation_translation(scale, rotation, translation) + impl From for Mat4 { + fn from( + TransformDescriptor { + translation, + rotation, + scale, + }: TransformDescriptor, + ) -> Self { + Mat4::from_scale_rotation_translation(scale, rotation, translation) + } } -} -impl TransformDescriptor { - pub const IDENTITY: Self = TransformDescriptor { - translation: Vec3::ZERO, - rotation: Quat::IDENTITY, - scale: Vec3::ONE, - }; + impl TransformDescriptor { + pub const IDENTITY: Self = TransformDescriptor { + translation: Vec3::ZERO, + rotation: Quat::IDENTITY, + scale: Vec3::ONE, + }; + } } #[cfg(test)] mod test { - use super::*; use crabslab::*; + use glam::{Quat, Vec3}; + + use crate::transform::shader::TransformDescriptor; #[test] fn transform_roundtrip() { diff --git a/crates/renderling/src/transform/cpu.rs b/crates/renderling/src/transform/cpu.rs index 09fac7a9..5e0c8343 100644 --- a/crates/renderling/src/transform/cpu.rs +++ b/crates/renderling/src/transform/cpu.rs @@ -6,7 +6,7 @@ use craballoc::{runtime::IsRuntime, slab::SlabAllocator, value::Hybrid}; use crabslab::Id; use glam::{Mat4, Quat, Vec3}; -use super::TransformDescriptor; +use super::shader::TransformDescriptor; /// A decomposed 3d transformation. #[derive(Clone, Debug)] diff --git a/crates/renderling/src/tutorial.rs b/crates/renderling/src/tutorial.rs index 0e9253cf..979930de 100644 --- a/crates/renderling/src/tutorial.rs +++ b/crates/renderling/src/tutorial.rs @@ -1,12 +1,12 @@ -//! Shaders used in the intro tutorial and in WASM tests. +//! Shaders used in the contributor intro tutorial and in WASM tests. use crabslab::{Array, Id, Slab, SlabItem}; use glam::{Vec3, Vec3Swizzles, Vec4}; use spirv_std::spirv; use crate::{ - geometry::{GeometryDescriptor, Vertex}, - stage::{PrimitiveDescriptor, VertexInfo}, + geometry::{shader::GeometryDescriptor, Vertex}, + primitive::shader::{PrimitiveDescriptor, VertexInfo}, }; /// Simple fragment shader that writes the input color to the output color. @@ -84,8 +84,8 @@ pub fn slabbed_vertices( /// The `instance_index` is the `id` of a [`PrimitiveDescriptor`]. /// The [`PrimitiveDescriptor`] contains an [`Array`] of [`Vertex`]s /// as its mesh, the [`Id`]s of a -/// [`MaterialDescriptor`](crate::material::MaterialDescriptor) and -///[`CameraDescriptor`](crate::camera::CameraDescriptor), +/// [`MaterialDescriptor`](crate::material::shader::MaterialDescriptor) and +///[`CameraDescriptor`](crate::camera::shader::CameraDescriptor), /// and TRS transforms. /// The `vertex_index` is the index of a [`Vertex`] within the /// [`PrimitiveDescriptor`]'s `vertices` [`Array`]. diff --git a/crates/renderling/src/ui/cpu.rs b/crates/renderling/src/ui/cpu.rs index 6c0e1426..72e6457c 100644 --- a/crates/renderling/src/ui/cpu.rs +++ b/crates/renderling/src/ui/cpu.rs @@ -4,7 +4,7 @@ use core::sync::atomic::AtomicBool; use std::sync::{Arc, RwLock}; use crate::{ - atlas::{AtlasTexture, AtlasTextureDescriptor, TextureAddressMode, TextureModes}, + atlas::{shader::AtlasTextureDescriptor, AtlasTexture, TextureAddressMode, TextureModes}, camera::Camera, stage::Stage, transform::NestedTransform, diff --git a/crates/renderling/src/ui/cpu/path.rs b/crates/renderling/src/ui/cpu/path.rs index b65929d5..5ea0da6c 100644 --- a/crates/renderling/src/ui/cpu/path.rs +++ b/crates/renderling/src/ui/cpu/path.rs @@ -1,7 +1,7 @@ //! Path and builder. //! //! Path colors are sRGB. -use crate::{geometry::Vertex, material::Material, stage::Primitive}; +use crate::{geometry::Vertex, material::Material, primitive::Primitive}; use glam::{Vec2, Vec3, Vec3Swizzles, Vec4}; use lyon::{ path::traits::PathBuilder, diff --git a/crates/renderling/src/ui/cpu/text.rs b/crates/renderling/src/ui/cpu/text.rs index 19b2eb1c..8a88fafc 100644 --- a/crates/renderling/src/ui/cpu/text.rs +++ b/crates/renderling/src/ui/cpu/text.rs @@ -14,7 +14,7 @@ use glyph_brush::*; pub use ab_glyph::FontArc; pub use glyph_brush::{Section, Text}; -use crate::{atlas::AtlasTexture, geometry::Vertex, material::Material, stage::Primitive}; +use crate::{atlas::AtlasTexture, geometry::Vertex, material::Material, primitive::Primitive}; use image::{DynamicImage, GenericImage, ImageBuffer, Luma, Rgba}; use super::{Ui, UiTransform}; diff --git a/crates/renderling/tests/wasm.rs b/crates/renderling/tests/wasm.rs index 6dbd296e..8d6de648 100644 --- a/crates/renderling/tests/wasm.rs +++ b/crates/renderling/tests/wasm.rs @@ -7,7 +7,7 @@ use craballoc::{ }; use glam::{Vec3, Vec4}; use image::DynamicImage; -use renderling::{prelude::*, texture::CopiedTextureBuffer}; +use renderling::{geometry::Vertex, prelude::*, texture::CopiedTextureBuffer}; use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure}; use web_sys::wasm_bindgen::prelude::*; use wire_types::{Error, PixelType}; diff --git a/crates/xtask/src/deps.rs b/crates/xtask/src/deps.rs new file mode 100644 index 00000000..43952b52 --- /dev/null +++ b/crates/xtask/src/deps.rs @@ -0,0 +1,26 @@ +//! Xtask dependency helpers. +//! +//! This module helps installing xtask's required dependencies. + +pub async fn has_binary(name: impl AsRef) -> bool { + let output = tokio::process::Command::new("hash") + .arg(name.as_ref()) + .output() + .await + .expect("Failed to execute process"); + + output.status.success() +} + +pub async fn cargo_install(name: impl AsRef) { + log::warn!("installing mdbook"); + + let mut process = tokio::process::Command::new("cargo") + .args(["install", name.as_ref()]) + .spawn() + .unwrap(); + let status = process.wait().await.unwrap(); + if !status.success() { + panic!("Failed installing {}", name.as_ref()); + } +} diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 514c82bd..b5f4e334 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -1,6 +1,7 @@ //! A build helper for the `renderling` project. use clap::{Parser, Subcommand}; +mod deps; mod server; #[derive(Subcommand)] @@ -32,6 +33,8 @@ enum Command { #[clap(long)] chrome: bool, }, + /// Build the manual + BuildManual, } #[derive(Parser)] @@ -99,5 +102,11 @@ async fn main() { Command::WasmServer => { server::serve().await; } + Command::BuildManual => { + log::info!("building manual"); + if !deps::has_binary("mdbook").await { + deps::cargo_install("mdbook").await; + } + } } } diff --git a/manual/.gitignore b/manual/.gitignore new file mode 100644 index 00000000..7585238e --- /dev/null +++ b/manual/.gitignore @@ -0,0 +1 @@ +book diff --git a/manual/book.toml b/manual/book.toml new file mode 100644 index 00000000..ea0a1a6d --- /dev/null +++ b/manual/book.toml @@ -0,0 +1,5 @@ +[book] +authors = ["Schell Carl Scivally"] +language = "en" +src = "src" +title = "The Renderling Manual" diff --git a/manual/src/SUMMARY.md b/manual/src/SUMMARY.md new file mode 100644 index 00000000..7390c828 --- /dev/null +++ b/manual/src/SUMMARY.md @@ -0,0 +1,3 @@ +# Summary + +- [Chapter 1](./chapter_1.md) diff --git a/manual/src/chapter_1.md b/manual/src/chapter_1.md new file mode 100644 index 00000000..b743fda3 --- /dev/null +++ b/manual/src/chapter_1.md @@ -0,0 +1 @@ +# Chapter 1 From 2ef6300424a3069d5f361ce2dda0893e43189e60 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Wed, 17 Sep 2025 17:27:16 +1200 Subject: [PATCH 15/31] work on docs and the manual --- Cargo.lock | 71 ++------ Cargo.toml | 15 +- crates/example/src/camera.rs | 16 +- crates/example/src/lib.rs | 4 +- crates/example/src/main.rs | 4 +- crates/example/src/utils.rs | 2 +- crates/examples/Cargo.toml | 10 ++ crates/examples/src/context.rs | 19 ++ crates/examples/src/gltf.rs | 66 +++++++ crates/examples/src/lib.rs | 44 +++++ crates/examples/src/skybox.rs | 75 ++++++++ crates/examples/src/stage.rs | 86 +++++++++ crates/examples/stage-example.png | Bin 0 -> 33422 bytes crates/renderling/src/atlas/cpu.rs | 2 +- crates/renderling/src/bloom/cpu.rs | 2 +- crates/renderling/src/bvol.rs | 2 +- crates/renderling/src/camera/cpu.rs | 38 ++++ crates/renderling/src/context.rs | 2 +- crates/renderling/src/cubemap/cpu.rs | 3 +- crates/renderling/src/cull/cpu.rs | 2 +- crates/renderling/src/draw/cpu.rs | 2 +- crates/renderling/src/geometry/cpu.rs | 39 +++- crates/renderling/src/gltf.rs | 23 ++- crates/renderling/src/gltf/anime.rs | 2 +- crates/renderling/src/internal/cpu.rs | 2 +- crates/renderling/src/lib.rs | 14 +- crates/renderling/src/light/cpu/test.rs | 21 +-- crates/renderling/src/light/shadow_map.rs | 12 +- crates/renderling/src/math.rs | 9 +- crates/renderling/src/pbr.rs | 5 +- crates/renderling/src/skybox/cpu.rs | 2 +- crates/renderling/src/stage/cpu.rs | 18 +- crates/renderling/src/texture.rs | 2 +- crates/renderling/src/ui/cpu.rs | 4 +- crates/renderling/src/ui/cpu/path.rs | 2 +- crates/renderling/src/ui/cpu/text.rs | 2 +- crates/renderling/tests/wasm.rs | 13 +- crates/xtask/src/main.rs | 105 ++++++++++- crates/xtask/src/server.rs | 51 ++++-- manual/book.toml | 16 ++ manual/src/SUMMARY.md | 7 +- manual/src/assets/gltf-example-shadow.png | Bin 0 -> 12924 bytes manual/src/assets/gltf-example-unlit.png | Bin 0 -> 12067 bytes manual/src/assets/gltf-example.png | Bin 0 -> 12924 bytes .../src/assets/qwantani_dusk_2_puresky.webp | Bin 0 -> 2804 bytes .../src/assets/qwantani_dusk_2_puresky_1k.hdr | Bin 0 -> 1166018 bytes manual/src/assets/skybox.png | Bin 0 -> 28323 bytes manual/src/assets/stage-example.png | Bin 0 -> 33422 bytes manual/src/chapter_1.md | 1 - manual/src/context.md | 57 ++++++ manual/src/gltf.md | 79 ++++++++ manual/src/reflinks.md | 43 +++++ manual/src/setup.md | 40 +++++ manual/src/skybox.md | 55 ++++++ manual/src/stage.md | 169 ++++++++++++++++++ manual/src/welcome.md | 41 +++++ 56 files changed, 1122 insertions(+), 177 deletions(-) create mode 100644 crates/examples/Cargo.toml create mode 100644 crates/examples/src/context.rs create mode 100644 crates/examples/src/gltf.rs create mode 100644 crates/examples/src/lib.rs create mode 100644 crates/examples/src/skybox.rs create mode 100644 crates/examples/src/stage.rs create mode 100644 crates/examples/stage-example.png create mode 100644 manual/src/assets/gltf-example-shadow.png create mode 100644 manual/src/assets/gltf-example-unlit.png create mode 100644 manual/src/assets/gltf-example.png create mode 100644 manual/src/assets/qwantani_dusk_2_puresky.webp create mode 100644 manual/src/assets/qwantani_dusk_2_puresky_1k.hdr create mode 100644 manual/src/assets/skybox.png create mode 100644 manual/src/assets/stage-example.png delete mode 100644 manual/src/chapter_1.md create mode 100644 manual/src/context.md create mode 100644 manual/src/gltf.md create mode 100644 manual/src/reflinks.md create mode 100644 manual/src/setup.md create mode 100644 manual/src/skybox.md create mode 100644 manual/src/stage.md create mode 100644 manual/src/welcome.md diff --git a/Cargo.lock b/Cargo.lock index 926c7573..372a3ec8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -748,26 +748,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "console_log" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" -dependencies = [ - "log", - "web-sys", -] - [[package]] name = "console_log" version = "1.0.0" @@ -854,6 +834,8 @@ dependencies = [ [[package]] name = "craballoc" version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9d96bb4eed7f67b467d045c9563040dd5101b359bc60c9d355d3bb9ea858d1" dependencies = [ "async-channel 1.9.0", "bytemuck", @@ -868,6 +850,8 @@ dependencies = [ [[package]] name = "crabslab" version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9866f967260166a968eb2c7382c62f97bbf0a9896fa5c444730e49b3ca3f08" dependencies = [ "crabslab-derive", "futures-lite 1.13.0", @@ -878,6 +862,8 @@ dependencies = [ [[package]] name = "crabslab-derive" version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc3fdfc4f885d410742aad05c6cc3d2867627be16f79f6f3859c2d0484ce778" dependencies = [ "proc-macro2", "quote", @@ -1189,35 +1175,13 @@ dependencies = [ ] [[package]] -name = "example-culling" -version = "0.1.0" -dependencies = [ - "env_logger", - "example", - "fastrand 2.3.0", - "log", - "renderling", - "winit", -] - -[[package]] -name = "example-wasm" +name = "examples" version = "0.1.0" dependencies = [ - "console_error_panic_hook", - "console_log 0.2.2", - "example", - "fern", + "doc-comment", "futures-lite 1.13.0", - "gltf", - "log", "renderling", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-bindgen-test", - "web-sys", - "wgpu", - "winit", + "tokio", ] [[package]] @@ -1259,15 +1223,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "fern" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" -dependencies = [ - "log", -] - [[package]] name = "fixedbitset" version = "0.5.7" @@ -3731,7 +3686,7 @@ dependencies = [ "async-channel 1.9.0", "bytemuck", "cfg_aliases", - "console_log 1.0.0", + "console_log", "craballoc", "crabslab", "crunch", @@ -4264,7 +4219,7 @@ dependencies = [ [[package]] name = "spirv-std" version = "0.9.0" -source = "git+https://github.com/LegNeato/rust-gpu.git?rev=425328a#425328a3ac7f1f18db914d24b3d4754bf13bb7ac" +source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=425328a#425328a3ac7f1f18db914d24b3d4754bf13bb7ac" dependencies = [ "bitflags 1.3.2", "glam", @@ -4277,7 +4232,7 @@ dependencies = [ [[package]] name = "spirv-std-macros" version = "0.9.0" -source = "git+https://github.com/LegNeato/rust-gpu.git?rev=425328a#425328a3ac7f1f18db914d24b3d4754bf13bb7ac" +source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=425328a#425328a3ac7f1f18db914d24b3d4754bf13bb7ac" dependencies = [ "proc-macro2", "quote", @@ -4288,7 +4243,7 @@ dependencies = [ [[package]] name = "spirv-std-types" version = "0.9.0" -source = "git+https://github.com/LegNeato/rust-gpu.git?rev=425328a#425328a3ac7f1f18db914d24b3d4754bf13bb7ac" +source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=425328a#425328a3ac7f1f18db914d24b3d4754bf13bb7ac" [[package]] name = "stable_deref_trait" diff --git a/Cargo.toml b/Cargo.toml index aa67a84b..eb7e3684 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,9 @@ [workspace] members = [ - "crates/example", - "crates/example-culling", - "crates/example-wasm", + # "crates/example", + "crates/examples", + #"crates/example-culling", + #"crates/example-wasm", "crates/loading-bytes", "crates/renderling", "crates/renderling-build", @@ -50,8 +51,8 @@ serde_json = "1.0.117" send_wrapper = "0.6.0" similarity = "0.2.0" snafu = "0.8" -spirv-std = { git = "https://github.com/LegNeato/rust-gpu.git", rev = "425328a" } -spirv-std-macros = { git = "https://github.com/LegNeato/rust-gpu.git", rev = "425328a" } +spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "425328a" } +spirv-std-macros = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "425328a" } syn = { version = "2.0.49", features = ["full", "extra-traits", "parsing"] } tokio = "1.47.1" tracing = "0.1.41" @@ -74,6 +75,4 @@ opt-level = 3 opt-level = 3 [patch.crates-io] -spirv-std = { git = "https://github.com/LegNeato/rust-gpu.git", rev = "425328a" } -crabslab = { path = "../crabslab/crates/crabslab" } -craballoc = { path = "../crabslab/crates/craballoc" } +spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "425328a" } diff --git a/crates/example/src/camera.rs b/crates/example/src/camera.rs index beead2e5..cec4b35d 100644 --- a/crates/example/src/camera.rs +++ b/crates/example/src/camera.rs @@ -1,9 +1,11 @@ //! Camera control. use std::str::FromStr; -use renderling::bvol::Aabb; -use renderling::camera::Camera; -use renderling::prelude::glam::{Mat4, Quat, UVec2, Vec2, Vec3}; +use renderling::{ + bvol::Aabb, + camera::Camera, + glam::{Mat4, Quat, UVec2, Vec2, Vec3}, +}; use winit::{event::KeyEvent, keyboard::Key}; const RADIUS_SCROLL_DAMPENING: f32 = 0.001; @@ -183,12 +185,8 @@ impl CameraController for WasdMouseCameraController { } fn update_camera(&self, UVec2 { x: w, y: h }: UVec2, camera: &Camera) { - let camera_rotation = Quat::from_euler( - renderling::prelude::glam::EulerRot::XYZ, - self.phi, - self.theta, - 0.0, - ); + let camera_rotation = + Quat::from_euler(renderling::glam::EulerRot::XYZ, self.phi, self.theta, 0.0); let projection = Mat4::perspective_infinite_rh(std::f32::consts::FRAC_PI_4, w as f32 / h as f32, 0.01); let view = Mat4::from_quat(camera_rotation) * Mat4::from_translation(-self.position); diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index 716fec43..a097f0b7 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -10,15 +10,15 @@ use renderling::{ atlas::AtlasImage, bvol::{Aabb, BoundingSphere}, camera::Camera, + context::Context, geometry::Vertex, + glam, gltf::{Animator, GltfDocument}, light::AnalyticalLight, - prelude::*, primitive::Primitive, skybox::Skybox, stage::Stage, ui::{FontArc, Section, Text, Ui, UiPath, UiText}, - Context, }; pub mod camera; diff --git a/crates/example/src/main.rs b/crates/example/src/main.rs index af18313e..0b1e9063 100644 --- a/crates/example/src/main.rs +++ b/crates/example/src/main.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use clap::Parser; use example::{camera::CameraControl, App}; use renderling::{ - prelude::glam::{UVec2, Vec2}, - Context, + context::Context, + glam::{UVec2, Vec2}, }; use winit::{application::ApplicationHandler, event::WindowEvent, window::WindowAttributes}; diff --git a/crates/example/src/utils.rs b/crates/example/src/utils.rs index b51e00f4..c2d3e949 100644 --- a/crates/example/src/utils.rs +++ b/crates/example/src/utils.rs @@ -2,7 +2,7 @@ use std::sync::Arc; -use renderling::Context; +use renderling::context::Context; use winit::monitor::MonitorHandle; pub trait TestAppHandler: winit::application::ApplicationHandler { diff --git a/crates/examples/Cargo.toml b/crates/examples/Cargo.toml new file mode 100644 index 00000000..800b8bc0 --- /dev/null +++ b/crates/examples/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "examples" +version = "0.1.0" +edition = "2024" + +[dependencies] +doc-comment = "0.3" +futures-lite.workspace = true +renderling = { path = "../renderling" } +tokio = { workspace = true, features = ["full"] } diff --git a/crates/examples/src/context.rs b/crates/examples/src/context.rs new file mode 100644 index 00000000..2f033ea8 --- /dev/null +++ b/crates/examples/src/context.rs @@ -0,0 +1,19 @@ +//! Context manual page. + +#[tokio::test] +async fn context_page() { + // ANCHOR: create + use renderling::context::Context; + + let ctx = Context::headless(256, 256).await; + // ANCHOR_END: create + + // ANCHOR: frame + let frame = ctx.get_next_frame().unwrap(); + // ...do some rendering + // + // Then capture the frame into an image, if you like + let _image_capture = frame.read_image().await.unwrap(); + frame.present(); + // ANCHOR_END: frame +} diff --git a/crates/examples/src/gltf.rs b/crates/examples/src/gltf.rs new file mode 100644 index 00000000..d8c93429 --- /dev/null +++ b/crates/examples/src/gltf.rs @@ -0,0 +1,66 @@ +//! GLTF manual page. + +use crate::workspace_dir; + +#[tokio::test] +async fn manual_gltf() { + // ANCHOR: setup + use renderling::{ + camera::Camera, + context::Context, + glam::Vec4, + glam::{Mat4, Vec3}, + stage::Stage, + }; + + let ctx = Context::headless(256, 256).await; + let stage: Stage = ctx + .new_stage() + .with_background_color(Vec4::new(0.5, 0.5, 0.5, 1.0)); + + let _camera: Camera = { + let aspect = 1.0; + let fovy = core::f32::consts::PI / 4.0; + let znear = 0.1; + let zfar = 1000.0; + let projection = Mat4::perspective_rh(fovy, aspect, znear, zfar); + let y = 50.0; + let eye = Vec3::new(120.0, y, 120.0); + let target = Vec3::new(0.0, y, 0.0); + let up = Vec3::Y; + let view = Mat4::look_at_rh(eye, target, up); + + stage + .new_camera() + .with_projection_and_view(projection, view) + }; + // ANCHOR_END: setup + + // ANCHOR: load + use renderling::{gltf::GltfDocument, types::GpuOnlyArray}; + let _model: GltfDocument = stage + .load_gltf_document_from_path(workspace_dir().join("gltf/Fox.glb")) + .unwrap() + .into_gpu_only(); + // ANCHOR_END: load + + super::cwd_to_manual_assets_dir(); + + // ANCHOR: render_1 + let frame = ctx.get_next_frame().unwrap(); + stage.render(&frame.view()); + let img = frame.read_image().await.unwrap(); + img.save("gltf-example-shadow.png").unwrap(); + frame.present(); + // ANCHOR_END: render_1 + + // ANCHOR: no_lights + stage.set_has_lighting(false); + // ANCHOR_END: no_lights + + let frame = ctx.get_next_frame().unwrap(); + stage.render(&frame.view()); + let img = frame.read_image().await.unwrap(); + img.save("gltf-example-unlit.png").unwrap(); + frame.present(); +} diff --git a/crates/examples/src/lib.rs b/crates/examples/src/lib.rs new file mode 100644 index 00000000..a0ca8ea0 --- /dev/null +++ b/crates/examples/src/lib.rs @@ -0,0 +1,44 @@ +//! # Examples for the manual +//! +//! This crate contains examples and snippets that get pulled into the manual +//! via mdbook links. It also contains tests. + +#[cfg(test)] +mod context; + +#[cfg(test)] +mod stage; + +#[cfg(test)] +mod gltf; + +#[cfg(test)] +mod skybox; + +pub fn cwd_to_manual_assets_dir() -> std::path::PathBuf { + let current_dir = + std::path::PathBuf::from(std::env!("CARGO_WORKSPACE_DIR")).join("manual/src/assets"); + let current_dir = current_dir.canonicalize().unwrap(); + std::env::set_current_dir(¤t_dir).unwrap(); + println!("current dir: {:?}", std::env::current_dir()); + current_dir +} + +pub fn workspace_dir() -> std::path::PathBuf { + let current_dir = std::path::PathBuf::from(std::env!("CARGO_WORKSPACE_DIR")); + current_dir.canonicalize().unwrap() +} + +pub fn cwd_to_cargo_workspace() -> std::path::PathBuf { + let current_dir = workspace_dir(); + std::env::set_current_dir(¤t_dir).unwrap(); + println!("current dir: {:?}", std::env::current_dir()); + current_dir +} + +doc_comment::doctest!("../../../manual/src/stage.md", stage_md); + +#[test] +fn can_test() { + assert_eq!(1, 1); +} diff --git a/crates/examples/src/skybox.rs b/crates/examples/src/skybox.rs new file mode 100644 index 00000000..086aa907 --- /dev/null +++ b/crates/examples/src/skybox.rs @@ -0,0 +1,75 @@ +//! Skybox manual page. + +#[tokio::test] +async fn manual_stage() { + // ANCHOR: setup + use renderling::{ + camera::Camera, + context::Context, + geometry::Vertex, + glam::Vec4, + glam::{Mat4, Vec3}, + stage::Stage, + }; + + let ctx = Context::headless(256, 256).await; + let stage: Stage = ctx + .new_stage() + .with_background_color(Vec4::new(0.5, 0.5, 0.5, 1.0)); + + let _camera: Camera = stage + .new_camera() + .with_default_perspective(256.0, 256.0) + .with_view(Mat4::look_at_rh(Vec3::splat(1.5), Vec3::ZERO, Vec3::Y)); + + let vertices = stage.new_vertices(renderling::math::unit_cube().into_iter().map( + |(position, normal)| { + Vertex::default() + .with_position(position) + .with_normal(normal) + .with_color({ + // The color can vary from vertex to vertex + // + // X axis is green + let g: f32 = position.x + 0.5; + // Y axis is blue + let b: f32 = position.y + 0.5; + // Z is red + let r: f32 = position.z + 0.5; + Vec4::new(r, g, b, 1.0) + }) + }, + )); + + let material = stage.new_material().with_albedo_factor(Vec4::ONE); + + let _prim = stage + .new_primitive() + .with_vertices(&vertices) + .with_material(&material); + // ANCHOR_END: setup + + // ANCHOR: render_cube + let frame = ctx.get_next_frame().unwrap(); + stage.render(&frame.view()); + frame.present(); + // ANCHOR_END: render_cube + + // Excluded from the manual because it's off-topic + super::cwd_to_manual_assets_dir(); + + // ANCHOR: skybox + let skybox = stage + .new_skybox_from_path("qwantani_dusk_2_puresky_1k.hdr") + .unwrap(); + stage.set_skybox(skybox); + // ANCHOR_END: skybox + + // ANCHOR: render_skybox + let frame = ctx.get_next_frame().unwrap(); + stage.render(&frame.view()); + let image = frame.read_image().await.unwrap(); + image.save("skybox.png").unwrap(); + frame.present(); + // ANCHOR_END: render_skybox +} diff --git a/crates/examples/src/stage.rs b/crates/examples/src/stage.rs new file mode 100644 index 00000000..e9358108 --- /dev/null +++ b/crates/examples/src/stage.rs @@ -0,0 +1,86 @@ +//! Stage manual page. + +#[tokio::test] +async fn manual_stage() { + // ANCHOR: creation + use renderling::{context::Context, glam::Vec4, stage::Stage}; + + let ctx = Context::headless(256, 256).await; + let stage: Stage = ctx + .new_stage() + .with_background_color(Vec4::new(0.5, 0.5, 0.5, 1.0)); + // ANCHOR_END: creation + + // ANCHOR: camera + use renderling::{ + camera::Camera, + glam::{Mat4, Vec3}, + }; + + let camera: Camera = stage + .new_camera() + .with_default_perspective(256.0, 256.0) + .with_view(Mat4::look_at_rh(Vec3::splat(1.5), Vec3::ZERO, Vec3::Y)); + // This is technically not necessary because Stage always "uses" the first + // camera created, but we do it here for demonstration. + stage.use_camera(&camera); + // ANCHOR_END: camera + + // ANCHOR: unit_cube_vertices + use renderling::geometry::{Vertex, Vertices}; + + let vertices: Vertices = stage.new_vertices(renderling::math::unit_cube().into_iter().map( + |(position, normal)| { + Vertex::default() + .with_position(position) + .with_normal(normal) + .with_color({ + // The color can vary from vertex to vertex + // + // X axis is green + let g: f32 = position.x + 0.5; + // Y axis is blue + let b: f32 = position.y + 0.5; + // Z is red + let r: f32 = position.z + 0.5; + Vec4::new(r, g, b, 1.0) + }) + }, + )); + // ANCHOR_END: unit_cube_vertices + + // ANCHOR: unload_vertices + use renderling::types::GpuOnlyArray; + + let vertices: Vertices = vertices.into_gpu_only(); + // ANCHOR_END: unload_vertices + + // ANCHOR: material + let material = stage + .new_material() + .with_albedo_factor(Vec4::ONE) + .with_has_lighting(false); + // ANCHOR_END: material + + // ANCHOR: prim + let _prim = stage + .new_primitive() + .with_vertices(&vertices) + .with_material(&material); + // ANCHOR_END: prim + + // Excluded from the manual because it's off-topic + let current_dir = + std::path::PathBuf::from(std::env!("CARGO_WORKSPACE_DIR")).join("manual/src/assets"); + let current_dir = current_dir.canonicalize().unwrap(); + std::env::set_current_dir(current_dir).unwrap(); + + // ANCHOR: render + let frame = ctx.get_next_frame().unwrap(); + stage.render(&frame.view()); + + let img = frame.read_image().await.unwrap(); + img.save("stage-example.png").unwrap(); + frame.present(); + // ANCHOR_END: render +} diff --git a/crates/examples/stage-example.png b/crates/examples/stage-example.png new file mode 100644 index 0000000000000000000000000000000000000000..98ef0adfd94616dda2e8705da52979c02dcbcf3e GIT binary patch literal 33422 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 literal 0 HcmV?d00001 diff --git a/crates/renderling/src/atlas/cpu.rs b/crates/renderling/src/atlas/cpu.rs index 910f8e6e..f978ee02 100644 --- a/crates/renderling/src/atlas/cpu.rs +++ b/crates/renderling/src/atlas/cpu.rs @@ -1006,10 +1006,10 @@ impl AtlasBlitter { mod test { use crate::{ atlas::{shader::AtlasTextureDescriptor, TextureAddressMode}, + context::Context, geometry::Vertex, material::Materials, test::BlockOnFuture, - Context, }; use glam::{UVec3, Vec2, Vec3, Vec4}; diff --git a/crates/renderling/src/bloom/cpu.rs b/crates/renderling/src/bloom/cpu.rs index 8c43ba9e..f059cd13 100644 --- a/crates/renderling/src/bloom/cpu.rs +++ b/crates/renderling/src/bloom/cpu.rs @@ -701,7 +701,7 @@ impl Bloom { mod test { use glam::Vec3; - use crate::{test::BlockOnFuture, Context}; + use crate::{context::Context, test::BlockOnFuture}; use super::*; diff --git a/crates/renderling/src/bvol.rs b/crates/renderling/src/bvol.rs index 734fde4e..43bdf02d 100644 --- a/crates/renderling/src/bvol.rs +++ b/crates/renderling/src/bvol.rs @@ -599,7 +599,7 @@ impl BVol for Aabb { mod test { use glam::{Mat4, Quat}; - use crate::{geometry::Vertex, test::BlockOnFuture, Context}; + use crate::{context::Context, geometry::Vertex, test::BlockOnFuture}; use super::*; diff --git a/crates/renderling/src/camera/cpu.rs b/crates/renderling/src/camera/cpu.rs index eeecb6a2..f4220161 100644 --- a/crates/renderling/src/camera/cpu.rs +++ b/crates/renderling/src/camera/cpu.rs @@ -46,6 +46,25 @@ impl Camera { /// Set the camera to a default perspective projection and view based /// on the width and height of the viewport. + /// + /// The default projection and view matrices are defined as: + /// + /// ```rust + /// use glam::*; + /// + /// let width = 800.0; + /// let height = 600.0; + /// let aspect = width / height; + /// let fovy = core::f32::consts::PI / 4.0; + /// let znear = 0.1; + /// let zfar = 100.0; + /// let projection = Mat4::perspective_rh(fovy, aspect, znear, zfar); + /// let eye = Vec3::new(0.0, 12.0, 20.0); + /// let target = Vec3::ZERO; + /// let up = Vec3::Y; + /// let view = Mat4::look_at_rh(eye, target, up); + /// assert_eq!(renderling::camera::default_perspective(width, height), (projection, view)); + /// ``` pub fn set_default_perspective(&self, width: f32, height: f32) -> &Self { self.inner .modify(|d| *d = CameraDescriptor::default_perspective(width, height)); @@ -54,6 +73,25 @@ impl Camera { /// Set the camera to a default perspective projection and view based /// on the width and height of the viewport. + /// + /// The default projection and view matrices are defined as: + /// + /// ```rust + /// use glam::*; + /// + /// let width = 800.0; + /// let height = 600.0; + /// let aspect = width / height; + /// let fovy = core::f32::consts::PI / 4.0; + /// let znear = 0.1; + /// let zfar = 100.0; + /// let projection = Mat4::perspective_rh(fovy, aspect, znear, zfar); + /// let eye = Vec3::new(0.0, 12.0, 20.0); + /// let target = Vec3::ZERO; + /// let up = Vec3::Y; + /// let view = Mat4::look_at_rh(eye, target, up); + /// assert_eq!(renderling::camera::default_perspective(width, height), (projection, view)); + /// ``` pub fn with_default_perspective(self, width: f32, height: f32) -> Self { self.set_default_perspective(width, height); self diff --git a/crates/renderling/src/context.rs b/crates/renderling/src/context.rs index ad63b663..87183a95 100644 --- a/crates/renderling/src/context.rs +++ b/crates/renderling/src/context.rs @@ -307,7 +307,7 @@ pub(crate) struct GlobalStageConfig { /// texture. /// /// ``` -/// use renderling::Context; +/// use renderling::context::Context; /// /// let ctx = futures_lite::future::block_on(Context::headless(100, 100)); /// ``` diff --git a/crates/renderling/src/cubemap/cpu.rs b/crates/renderling/src/cubemap/cpu.rs index 1b7af066..0ffa57d2 100644 --- a/crates/renderling/src/cubemap/cpu.rs +++ b/crates/renderling/src/cubemap/cpu.rs @@ -269,6 +269,7 @@ mod test { use image::GenericImageView; use crate::{ + context::Context, geometry::Vertex, math::{UNIT_INDICES, UNIT_POINTS}, test::BlockOnFuture, @@ -281,7 +282,7 @@ mod test { fn hand_rolled_cubemap_sampling() { let width = 256; let height = 256; - let ctx = crate::Context::headless(width, height).block(); + let ctx = Context::headless(width, height).block(); let stage = ctx .new_stage() .with_background_color(Vec4::ZERO) diff --git a/crates/renderling/src/cull/cpu.rs b/crates/renderling/src/cull/cpu.rs index da33337a..8969f4f8 100644 --- a/crates/renderling/src/cull/cpu.rs +++ b/crates/renderling/src/cull/cpu.rs @@ -674,11 +674,11 @@ mod test { use crate::{ bvol::BoundingSphere, + context::Context, cull::shader::DepthPyramidDescriptor, draw::DrawIndirectArgs, geometry::{Geometry, Vertex}, math::hex_to_vec4, - prelude::*, primitive::shader::PrimitiveDescriptor, test::BlockOnFuture, }; diff --git a/crates/renderling/src/draw/cpu.rs b/crates/renderling/src/draw/cpu.rs index f1fb1a1a..88276c95 100644 --- a/crates/renderling/src/draw/cpu.rs +++ b/crates/renderling/src/draw/cpu.rs @@ -7,10 +7,10 @@ use craballoc::{ use crabslab::Id; use crate::{ + context::Context, cull::{ComputeCulling, CullingError}, primitive::{shader::PrimitiveDescriptor, Primitive}, texture::Texture, - Context, }; use super::DrawIndirectArgs; diff --git a/crates/renderling/src/geometry/cpu.rs b/crates/renderling/src/geometry/cpu.rs index ad87e26f..f7ad58a3 100644 --- a/crates/renderling/src/geometry/cpu.rs +++ b/crates/renderling/src/geometry/cpu.rs @@ -21,8 +21,20 @@ use crate::{ /// A contiguous array of vertices, staged on the GPU. /// -/// The type variable `Ct` denotes whether the dta lives on the GPU only, or on -/// the CPU and the GPU. +/// The type variable `Ct` denotes whether the staged data lives on the GPU +/// only, or on the CPU and the GPU. +/// +/// # Note +/// The amount of data staged in `Vertices` can potentially be very large, and +/// it is common to unload the data from the CPU with +/// [`Vertices::into_gpu_only`]. +/// +/// The only reason to keep data on the CPU is if it needs to be inspected and +/// modified _in place_. This type of modification can be done with +/// [`Vertices::modify_vertex`]. +/// +/// After unloading it is still possible to _replace_ a [`Vertex`] at a +/// specific index using [`Vertices::set_vertex`]. pub struct Vertices { inner: Ct::Container, } @@ -93,7 +105,7 @@ impl Vertices { } /// Returns a [`Vertex`] at a specific index, if any. - pub fn get(&self, index: usize) -> Option { + pub fn get_vertex(&self, index: usize) -> Option { self.inner.get(index) } @@ -102,12 +114,13 @@ impl Vertices { self.inner.get_vec() } - /// Set the [`Vertex`] at the given index to the given value, if the item at - /// the index exists. - /// - /// Returns the previous value, if any. - pub fn set_item(&self, index: usize, value: Vertex) -> Option { - self.inner.set_item(index, value) + /// Modify a vertex at a specific index, if it exists. + pub fn modify_vertex( + &self, + index: usize, + f: impl FnOnce(&mut Vertex) -> T, + ) -> Option { + self.inner.modify(index, f) } } @@ -121,6 +134,14 @@ where } } +impl Vertices { + /// Set the [`Vertex`] at the given index to the given value, if the item at + /// the index exists. + pub fn set_vertex(&self, index: usize, value: &Vertex) { + self.inner.set_item(index, value) + } +} + /// A contiguous array of indices, staged on the GPU. /// The type variable `Ct` denotes whether the data lives on the GPU only, or on /// the CPU and the GPU. diff --git a/crates/renderling/src/gltf.rs b/crates/renderling/src/gltf.rs index 8a2e3855..b11bdce9 100644 --- a/crates/renderling/src/gltf.rs +++ b/crates/renderling/src/gltf.rs @@ -33,8 +33,19 @@ pub use anime::*; #[derive(Debug, Snafu)] pub enum StageGltfError { - #[snafu(display("{source}"))] - Gltf { source: gltf::Error }, + #[snafu( + display( + "GLTF error with '{}': {source}", + path + .as_ref() + .map(|p| p.display().to_string()) + .unwrap_or("".to_string())), + visibility(pub(crate)) + )] + Gltf { + source: gltf::Error, + path: Option, + }, #[snafu(display("{source}"))] Atlas { source: crate::atlas::AtlasError }, @@ -91,12 +102,6 @@ pub enum StageGltfError { Animation { source: anime::AnimationError }, } -impl From for StageGltfError { - fn from(source: gltf::Error) -> Self { - Self::Gltf { source } - } -} - impl From for StageGltfError { fn from(source: AtlasError) -> Self { Self::Atlas { source } @@ -1269,7 +1274,7 @@ where #[cfg(test)] mod test { - use crate::{geometry::Vertex, test::BlockOnFuture, Context}; + use crate::{context::Context, geometry::Vertex, test::BlockOnFuture}; use glam::{Vec3, Vec4}; #[test] diff --git a/crates/renderling/src/gltf/anime.rs b/crates/renderling/src/gltf/anime.rs index 830492ad..3d750e80 100644 --- a/crates/renderling/src/gltf/anime.rs +++ b/crates/renderling/src/gltf/anime.rs @@ -764,7 +764,7 @@ impl Animator { #[cfg(test)] mod test { - use crate::{gltf::Animator, test::BlockOnFuture, Context}; + use crate::{context::Context, gltf::Animator, test::BlockOnFuture}; use glam::Vec3; #[test] diff --git a/crates/renderling/src/internal/cpu.rs b/crates/renderling/src/internal/cpu.rs index 309e5ded..2e7b1704 100644 --- a/crates/renderling/src/internal/cpu.rs +++ b/crates/renderling/src/internal/cpu.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use snafu::{OptionExt, ResultExt}; -use crate::{ +use crate::context::{ CannotCreateAdaptorSnafu, CannotRequestDeviceSnafu, ContextError, IncompatibleSurfaceSnafu, RenderTarget, RenderTargetInner, }; diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index 887bb447..db85adf2 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -240,17 +240,7 @@ pub mod types; #[cfg(feature = "ui")] pub mod ui; -#[cfg(cpu)] -pub use context::*; - -pub mod prelude { - //! A prelude, meant to be glob-imported. - - pub extern crate glam; - - #[cfg(cpu)] - pub use crate::context::*; -} +pub extern crate glam; #[macro_export] /// A wrapper around `std::println` that is a noop on the GPU. @@ -266,7 +256,7 @@ macro_rules! println { #[cfg(test)] mod test { use super::*; - use crate::{atlas::AtlasImage, geometry::Vertex}; + use crate::{atlas::AtlasImage, context::Context, geometry::Vertex}; use glam::{Mat3, Mat4, Quat, UVec2, Vec2, Vec3, Vec4}; use img_diff::DiffCfg; diff --git a/crates/renderling/src/light/cpu/test.rs b/crates/renderling/src/light/cpu/test.rs index 92168f3f..0ac1668d 100644 --- a/crates/renderling/src/light/cpu/test.rs +++ b/crates/renderling/src/light/cpu/test.rs @@ -8,6 +8,7 @@ use crate::{ bvol::BoundingBox, camera::Camera, color::linear_xfer_vec4, + context::Context, geometry::Vertex, light::{shader::SpotLightCalculation, LightTiling, LightTilingConfig}, math::GpuRng, @@ -85,7 +86,7 @@ fn spot_one_calc() { fn spot_one_frame() { let m = 32.0; let (w, h) = (16.0f32 * m, 9.0 * m); - let ctx = crate::Context::headless(w as u32, h as u32).block(); + let ctx = Context::headless(w as u32, h as u32).block(); let stage = ctx.new_stage().with_msaa_sample_count(4); let doc = stage .load_gltf_document_from_path( @@ -115,7 +116,7 @@ fn spot_one_frame() { fn spot_lights() { let w = 800.0; let h = 800.0; - let ctx = crate::Context::headless(w as u32, h as u32).block(); + let ctx = Context::headless(w as u32, h as u32).block(); let stage = ctx .new_stage() .with_lighting(true) @@ -149,7 +150,7 @@ fn light_tiling_light_bounds() { let magnification = 8; let w = 16.0 * 2.0f32.powi(magnification); let h = 9.0 * 2.0f32.powi(magnification); - let ctx = crate::Context::headless(w as u32, h as u32).block(); + let ctx = Context::headless(w as u32, h as u32).block(); let stage = ctx.new_stage().with_msaa_sample_count(4); let doc = stage .load_gltf_document_from_path( @@ -317,7 +318,7 @@ fn clear_tiles_sanity() { let _ = env_logger::builder().is_test(true).try_init(); let s = 256; let depth_texture_size = UVec2::splat(s); - let ctx = crate::Context::headless(s, s).block(); + let ctx = Context::headless(s, s).block(); let stage = ctx.new_stage(); let lighting: &Lighting = stage.as_ref(); let tiling_config = LightTilingConfig::default(); @@ -388,7 +389,7 @@ fn min_max_depth_sanity() { let _ = env_logger::builder().is_test(true).try_init(); let s = 256; let depth_texture_size = UVec2::splat(s); - let ctx = crate::Context::headless(s, s).block(); + let ctx = Context::headless(s, s).block(); let stage = ctx.new_stage(); let _doc = stage .load_gltf_document_from_path( @@ -440,7 +441,7 @@ fn light_bins_sanity() { let _ = env_logger::builder().is_test(true).try_init(); let s = 256; let depth_texture_size = UVec2::splat(s); - let ctx = crate::Context::headless(s, s).block(); + let ctx = Context::headless(s, s).block(); let stage = ctx.new_stage(); let doc = stage .load_gltf_document_from_path( @@ -510,7 +511,7 @@ fn light_bins_sanity() { // Ensures point lights are being binned properly. #[test] fn light_bins_point() { - let ctx = crate::Context::headless(256, 256).block(); + let ctx = Context::headless(256, 256).block(); let stage = ctx .new_stage() .with_msaa_sample_count(1) @@ -578,7 +579,7 @@ fn tiling_e2e_sanity_with( minimum_illuminance: {minimum_illuminance}" ); let size = size(); - let ctx = crate::Context::headless(size.x, size.y).block(); + let ctx = Context::headless(size.x, size.y).block(); let stage = ctx .new_stage() .with_bloom(true) @@ -750,7 +751,7 @@ fn tiling_e2e_sanity() { } } -fn snapshot(ctx: &crate::Context, stage: &Stage, path: &str, save: bool) { +fn snapshot(ctx: &crate::context::Context, stage: &Stage, path: &str, save: bool) { let frame = ctx.get_next_frame().unwrap(); let start = std::time::Instant::now(); stage.render(&frame.view()); @@ -918,7 +919,7 @@ mod stats { /// In other words, light w/ nested transform is the same as light with /// that same transform pre-applied. fn pedestal() { - let ctx = crate::Context::headless(256, 256).block(); + let ctx = crate::context::Context::headless(256, 256).block(); let stage = ctx .new_stage() .with_lighting(false) diff --git a/crates/renderling/src/light/shadow_map.rs b/crates/renderling/src/light/shadow_map.rs index 20271657..e0649887 100644 --- a/crates/renderling/src/light/shadow_map.rs +++ b/crates/renderling/src/light/shadow_map.rs @@ -384,13 +384,13 @@ impl ShadowMap { mod test { use glam::{UVec2, Vec3}; - use crate::test::BlockOnFuture; + use crate::{context::Context, test::BlockOnFuture}; #[test] fn shadow_mapping_just_cuboid() { let w = 800.0; let h = 800.0; - let ctx = crate::Context::headless(w as u32, h as u32).block(); + let ctx = Context::headless(w as u32, h as u32).block(); let stage = ctx .new_stage() .with_lighting(true) @@ -444,7 +444,7 @@ mod test { fn shadow_mapping_just_cuboid_red_and_blue() { let w = 800.0; let h = 800.0; - let ctx = crate::Context::headless(w as u32, h as u32).block(); + let ctx = Context::headless(w as u32, h as u32).block(); let stage = ctx .new_stage() .with_lighting(true) @@ -497,7 +497,7 @@ mod test { fn shadow_mapping_sanity() { let w = 800.0; let h = 800.0; - let ctx = crate::Context::headless(w as u32, h as u32) + let ctx = Context::headless(w as u32, h as u32) .block() .with_shadow_mapping_atlas_texture_size([1024, 1024, 2]); let stage = ctx.new_stage().with_lighting(true); @@ -584,7 +584,7 @@ mod test { fn shadow_mapping_spot_lights() { let w = 800.0; let h = 800.0; - let ctx = crate::Context::headless(w as u32, h as u32).block(); + let ctx = Context::headless(w as u32, h as u32).block(); let stage = ctx .new_stage() .with_lighting(true) @@ -650,7 +650,7 @@ mod test { fn shadow_mapping_point_lights() { let w = 800.0; let h = 800.0; - let ctx = crate::Context::headless(w as u32, h as u32).block(); + let ctx = Context::headless(w as u32, h as u32).block(); let stage = ctx .new_stage() .with_lighting(true) diff --git a/crates/renderling/src/math.rs b/crates/renderling/src/math.rs index 27b6e32a..c6ad4246 100644 --- a/crates/renderling/src/math.rs +++ b/crates/renderling/src/math.rs @@ -1,11 +1,10 @@ //! Mathematical helper types and functions. //! -//! Primarily this module re-exports types from `glam`. It also adds -//! some traits to help using `glam` types on the GPU without panicking, -//! as well as a few traits to aid in writing generic shader code that can be -//! run on the CPU. +//! Primarily this module adds some traits to help using `glam` types on the GPU +//! without panicking, as well as a few traits to aid in writing generic shader +//! code that can be run on the CPU. //! -//! Lastly, it provides some constant geometry used in many shaders. +//! Lastly, it provides some common geometry and constants used in many shaders. use core::ops::Mul; use spirv_std::{ image::{sample_with, Cubemap, Image2d, Image2dArray, ImageWithMethods}, diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index c3f5c94a..69fde69b 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -667,18 +667,19 @@ mod test { use crate::{ atlas::AtlasImage, geometry::Vertex, - prelude::glam::{Vec3, Vec4}, + glam::{Vec3, Vec4}, test::BlockOnFuture, }; #[test] + // TODO: Move this over to a manual example // Tests the initial implementation of pbr metallic roughness on an array of // spheres with different metallic roughnesses lit by an environment map. // // see https://learnopengl.com/PBR/Lighting fn pbr_metallic_roughness_spheres() { let ss = 600; - let ctx = crate::Context::headless(ss, ss).block(); + let ctx = crate::context::Context::headless(ss, ss).block(); let stage = ctx.new_stage(); let radius = 0.5; diff --git a/crates/renderling/src/skybox/cpu.rs b/crates/renderling/src/skybox/cpu.rs index c4f5bbfe..a81d22a1 100644 --- a/crates/renderling/src/skybox/cpu.rs +++ b/crates/renderling/src/skybox/cpu.rs @@ -651,7 +651,7 @@ mod test { use glam::Vec3; use super::*; - use crate::{test::BlockOnFuture, texture::CopiedTextureBuffer, Context}; + use crate::{context::Context, test::BlockOnFuture, texture::CopiedTextureBuffer}; #[test] fn hdr_skybox_scene() { diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index e6185f26..091d97c7 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -4,15 +4,14 @@ use core::sync::atomic::{AtomicU32, AtomicUsize, Ordering}; use craballoc::prelude::*; use crabslab::Id; use glam::{Mat4, UVec2, Vec4}; -use snafu::Snafu; +use snafu::{ResultExt, Snafu}; use std::sync::{atomic::AtomicBool, Arc, Mutex, RwLock}; use crate::atlas::AtlasTexture; use crate::camera::Camera; use crate::geometry::{shader::GeometryDescriptor, MorphTarget, Vertex}; -use crate::gltf::GltfDocument; #[cfg(gltf)] -use crate::gltf::StageGltfError; +use crate::gltf::GltfDocument; use crate::light::{DirectionalLight, IsLight, Light, PointLight, SpotLight}; use crate::material::Material; use crate::primitive::Primitive; @@ -440,7 +439,12 @@ impl Stage { &self, path: impl AsRef, ) -> Result { - let (document, buffers, images) = gltf::import(path).map_err(StageGltfError::from)?; + use snafu::ResultExt; + + let (document, buffers, images) = + gltf::import(&path).with_context(|_| crate::gltf::GltfSnafu { + path: Some(path.as_ref().to_path_buf()), + })?; GltfDocument::from_gltf(self, &document, buffers, images) } @@ -449,7 +453,7 @@ impl Stage { bytes: impl AsRef<[u8]>, ) -> Result { let (document, buffers, images) = - gltf::import_slice(bytes).map_err(StageGltfError::from)?; + gltf::import_slice(bytes).context(crate::gltf::GltfSnafu { path: None })?; GltfDocument::from_gltf(self, &document, buffers, images) } } @@ -930,7 +934,7 @@ impl Stage { } /// Create a new stage. - pub fn new(ctx: &crate::Context) -> Self { + pub fn new(ctx: &crate::context::Context) -> Self { let runtime = ctx.runtime(); let device = &runtime.device; let resolution @ UVec2 { x: w, y: h } = ctx.get_size(); @@ -1502,10 +1506,10 @@ mod test { use glam::{Mat4, Vec2, Vec3, Vec4}; use crate::{ + context::Context, geometry::{shader::GeometryDescriptor, Geometry, Vertex}, test::BlockOnFuture, transform::NestedTransform, - Context, }; #[test] diff --git a/crates/renderling/src/texture.rs b/crates/renderling/src/texture.rs index dbc3e655..fd9205df 100644 --- a/crates/renderling/src/texture.rs +++ b/crates/renderling/src/texture.rs @@ -1159,7 +1159,7 @@ impl CopiedTextureBuffer { #[cfg(test)] mod test { - use crate::{test::BlockOnFuture, texture::CopiedTextureBuffer, Context}; + use crate::{context::Context, test::BlockOnFuture, texture::CopiedTextureBuffer}; use super::Texture; diff --git a/crates/renderling/src/ui/cpu.rs b/crates/renderling/src/ui/cpu.rs index 72e6457c..d3455a44 100644 --- a/crates/renderling/src/ui/cpu.rs +++ b/crates/renderling/src/ui/cpu.rs @@ -6,9 +6,9 @@ use std::sync::{Arc, RwLock}; use crate::{ atlas::{shader::AtlasTextureDescriptor, AtlasTexture, TextureAddressMode, TextureModes}, camera::Camera, + context::Context, stage::Stage, transform::NestedTransform, - Context, }; use crabslab::Id; use glam::{Quat, UVec2, Vec2, Vec3Swizzles, Vec4}; @@ -344,7 +344,7 @@ impl Ui { #[cfg(test)] pub(crate) mod test { - use crate::{color::rgb_hex_color, prelude::glam::Vec4}; + use crate::{color::rgb_hex_color, glam::Vec4}; pub struct Colors(std::iter::Cycle>); diff --git a/crates/renderling/src/ui/cpu/path.rs b/crates/renderling/src/ui/cpu/path.rs index 5ea0da6c..94e07aa7 100644 --- a/crates/renderling/src/ui/cpu/path.rs +++ b/crates/renderling/src/ui/cpu/path.rs @@ -505,13 +505,13 @@ impl UiPathBuilder { #[cfg(test)] mod test { use crate::{ + context::Context, math::hex_to_vec4, test::BlockOnFuture, ui::{ test::{cute_beach_palette, Colors}, Ui, }, - Context, }; use glam::Vec2; diff --git a/crates/renderling/src/ui/cpu/text.rs b/crates/renderling/src/ui/cpu/text.rs index 8a88fafc..b1820149 100644 --- a/crates/renderling/src/ui/cpu/text.rs +++ b/crates/renderling/src/ui/cpu/text.rs @@ -331,7 +331,7 @@ impl GlyphCache { #[cfg(test)] mod test { - use crate::{test::BlockOnFuture, ui::Ui, Context}; + use crate::{context::Context, test::BlockOnFuture, ui::Ui}; use glyph_brush::Section; use super::*; diff --git a/crates/renderling/tests/wasm.rs b/crates/renderling/tests/wasm.rs index 8d6de648..18c7163f 100644 --- a/crates/renderling/tests/wasm.rs +++ b/crates/renderling/tests/wasm.rs @@ -7,7 +7,11 @@ use craballoc::{ }; use glam::{Vec3, Vec4}; use image::DynamicImage; -use renderling::{geometry::Vertex, prelude::*, texture::CopiedTextureBuffer}; +use renderling::{ + context::{Context, Frame}, + geometry::Vertex, + texture::CopiedTextureBuffer, +}; use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure}; use web_sys::wasm_bindgen::prelude::*; use wire_types::{Error, PixelType}; @@ -44,14 +48,14 @@ async fn can_write_system_info_artifact() { #[wasm_bindgen_test] async fn can_create_headless_ctx() { - let _ctx = renderling::Context::try_new_headless(256, 256, None) + let _ctx = Context::try_new_headless(256, 256, None) .await .unwrap_throw(); } #[wasm_bindgen_test] async fn stage_creation() { - let ctx = renderling::Context::try_new_headless(256, 256, None) + let ctx = Context::try_new_headless(256, 256, None) .await .unwrap_throw(); let _stage = ctx.new_stage(); @@ -980,10 +984,13 @@ async fn can_clear_background() { let stage = ctx .new_stage() .with_background_color(Vec4::new(1.0, 0.0, 0.0, 1.0)); + // ANCHOR: manual_context_frame let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); let seen = frame.read_image().await.unwrap(); assert_img_eq("clear.png", seen).await; + frame.present(); + // ANCHOR_END: manual_context_frame } // #[wasm_bindgen_test] diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index b5f4e334..157cfd4c 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -33,8 +33,58 @@ enum Command { #[clap(long)] chrome: bool, }, - /// Build the manual - BuildManual, + /// Perform actions regarding the manual + Manual(Manual), +} + +#[derive(Parser)] +pub struct Manual { + /// Whether to skip building the docs + #[clap(long)] + no_build_docs: bool, + + /// Whether to skip testing the manual + #[clap(long)] + no_test: bool, + + /// Serve the manual instead of simply building it + #[clap(long)] + serve: bool, +} + +impl Manual { + async fn install_deps() { + const DEPS: &[&str] = &["mdbook", "mdbook-environment"]; + for dep in DEPS { + if !deps::has_binary(dep).await { + deps::cargo_install(dep).await; + } + } + } + + async fn build_docs() { + log::info!("building docs"); + let mut process = tokio::process::Command::new("cargo") + .args(["doc", "-p", "renderling", "--all-features"]) + .spawn() + .unwrap(); + let status = process.wait().await.unwrap(); + if !status.success() { + panic!("Failed building docs"); + } + } + + async fn test() { + log::info!("testing the manual snippets"); + let mut process = tokio::process::Command::new("cargo") + .args(["test", "-p", "test-manual"]) + .spawn() + .unwrap(); + let status = process.wait().await.unwrap(); + if !status.success() { + panic!("Failed testing manual"); + } + } } #[derive(Parser)] @@ -102,10 +152,53 @@ async fn main() { Command::WasmServer => { server::serve().await; } - Command::BuildManual => { - log::info!("building manual"); - if !deps::has_binary("mdbook").await { - deps::cargo_install("mdbook").await; + Command::Manual(Manual { + no_build_docs, + no_test, + serve, + }) => { + log::info!("checking dependencies for the manual"); + Manual::install_deps().await; + if !no_test { + Manual::test().await; + } + if !no_build_docs { + Manual::build_docs().await; + } + + if serve { + log::info!("serving manual"); + + // serve the docs in the meantime + let _docs_handle = tokio::spawn(server::serve_docs()); + + let mut build = tokio::process::Command::new("mdbook") + .arg("serve") + .current_dir( + std::path::PathBuf::from(env!("CARGO_WORKSPACE_DIR")).join("manual"), + ) + .env("DOCS_URL", "http://localhost:4000") + .spawn() + .unwrap(); + let build_status = build.wait().await.unwrap(); + if !build_status.success() { + log::error!("could not build the manual"); + } + } else { + log::info!("building manual"); + + let mut build = tokio::process::Command::new("mdbook") + .arg("build") + .env("DOCS_URL", "http://docs.rs/renderling/latest") + .current_dir( + std::path::PathBuf::from(env!("CARGO_WORKSPACE_DIR")).join("manual"), + ) + .spawn() + .unwrap(); + let build_status = build.wait().await.unwrap(); + if !build_status.success() { + log::error!("could not build the manual"); + } } } } diff --git a/crates/xtask/src/server.rs b/crates/xtask/src/server.rs index 1dfd8f61..f1b54c27 100644 --- a/crates/xtask/src/server.rs +++ b/crates/xtask/src/server.rs @@ -17,7 +17,7 @@ use tokio::io::AsyncWriteExt; use wire_types::Error; pub async fn serve() { - log::info!("starting the webdriver proxy"); + log::info!("starting the xtask server"); let app = Router::new() .route("/test_img/{*path}", get(static_file)) .route("/assert_img_eq/{*filename}", options(accept)) @@ -35,7 +35,7 @@ pub async fn serve() { /// Responds with access control headers to allow anything from anywhere. async fn accept(request: Request) -> Response { - log::info!("accept: {request:#?}"); + log::debug!("accept: {request:#?}"); Response::builder() .status(StatusCode::OK) .header("accept", "*/*") @@ -46,16 +46,25 @@ async fn accept(request: Request) -> Response { .unwrap() } -async fn static_file(Path(path): Path) -> Result { - log::info!("requested static '{path}'"); - let test_img = std::path::PathBuf::from(std::env!("CARGO_WORKSPACE_DIR")).join("test_img"); - let path = test_img.join(path); - if path.exists() { - let bytes = tokio::fs::read(&path).await.map_err(|e| { - log::error!("could not read path '{path:?}': {e}"); +async fn static_file_inner( + path: impl AsRef, + prefix: impl AsRef, +) -> Result { + log::info!( + "requested '{}' '{}'", + prefix.as_ref().display(), + path.as_ref().display() + ); + let mut full_path = prefix.as_ref().join(path); + if full_path.is_dir() { + full_path = full_path.join("index.html"); + } + if full_path.exists() { + let bytes = tokio::fs::read(&full_path).await.map_err(|e| { + log::error!("could not read path '{full_path:?}': {e}"); StatusCode::BAD_REQUEST })?; - let mime = new_mime_guess::from_path(path); + let mime = new_mime_guess::from_path(full_path); let mimetype = if let Some(mt) = mime.first() { mt.to_string() } else { @@ -72,11 +81,16 @@ async fn static_file(Path(path): Path) -> Result { })?; Ok(resp) } else { - log::error!("{path:?} not found"); + log::error!("{full_path:?} not found"); Err(StatusCode::NOT_FOUND) } } +async fn static_file(Path(path): Path) -> Result { + let test_img_dir = std::path::PathBuf::from(std::env!("CARGO_WORKSPACE_DIR")).join("test_img"); + static_file_inner(path, test_img_dir).await +} + fn image_from_wire(img: wire_types::Image) -> Result { match img.pixel { wire_types::PixelType::Rgb8 => { @@ -195,3 +209,18 @@ async fn artifact(Path(parts): Path>, body: Body) -> Response { .body(Json(result).into_response().into_body()) .unwrap() } + +pub async fn serve_docs() { + log::info!("starting the xtask docs server"); + let app = Router::new().route("/{*rest}", get(docs)); + let listener = tokio::net::TcpListener::bind("127.0.0.1:4000") + .await + .unwrap(); + log::info!("serving docs"); + axum::serve(listener, app).await.unwrap(); +} + +async fn docs(Path(path): Path) -> impl IntoResponse { + log::info!("path: {path:#?}"); + static_file_inner(path, "target/doc").await +} diff --git a/manual/book.toml b/manual/book.toml index ea0a1a6d..2379f046 100644 --- a/manual/book.toml +++ b/manual/book.toml @@ -3,3 +3,19 @@ authors = ["Schell Carl Scivally"] language = "en" src = "src" title = "The Renderling Manual" +description = "Operations manual for the Renderling real-time renderer" + +# The "environment" preprocessor, provided by `mdbook-environment`, +# references variables from here and the environment that can then be +# interpolated in the book with `{{VARIABLE}}`. +# +# Setting variables here overrides any set in the environment, so for +# variables that must change based on environment we add them here +# commented out. +[preprocessor.environment] +# when deploying the manual +# DOCS_URL = "https://docs.rs/renderling/latest" + +# when running locally +# DOCS_URL = "http://localhost:4000" + diff --git a/manual/src/SUMMARY.md b/manual/src/SUMMARY.md index 7390c828..dab7eaa7 100644 --- a/manual/src/SUMMARY.md +++ b/manual/src/SUMMARY.md @@ -1,3 +1,8 @@ # Summary -- [Chapter 1](./chapter_1.md) +- [Welcome](./welcome.md) +- [Project setup](./setup.md) +- [Context creation](./context.md) +- [Staging resources](./stage.md) +- [Loading GLTF files](./gltf.md) +- [Skybox](./skybox.md) diff --git a/manual/src/assets/gltf-example-shadow.png b/manual/src/assets/gltf-example-shadow.png new file mode 100644 index 0000000000000000000000000000000000000000..a3aa105ba929a4b8d8b13c8e6862e40fef33f270 GIT binary patch literal 12924 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 Vugf$7|Eol^Bt4h7E8*qB{{}}oLdyUE literal 0 HcmV?d00001 diff --git a/manual/src/assets/gltf-example-unlit.png b/manual/src/assets/gltf-example-unlit.png new file mode 100644 index 0000000000000000000000000000000000000000..db65b791290fa44976d8807af425c598a614136e GIT binary patch literal 12067 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 Vugf$7|Eol^Bt4h7E8*qB{{}}oLdyUE literal 0 HcmV?d00001 diff --git a/manual/src/assets/qwantani_dusk_2_puresky.webp b/manual/src/assets/qwantani_dusk_2_puresky.webp new file mode 100644 index 0000000000000000000000000000000000000000..1970a7561fe275de60237088876a7b2bf058c712 GIT binary patch literal 2804 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 literal 0 HcmV?d00001 diff --git a/manual/src/assets/qwantani_dusk_2_puresky_1k.hdr b/manual/src/assets/qwantani_dusk_2_puresky_1k.hdr new file mode 100644 index 0000000000000000000000000000000000000000..62d1e3b0e2abc27872237587a4b189a394e29992 GIT binary patch literal 1166018 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

XidE*Zqc&#Ptb9r-gPtX>=V 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 |5y*KHu!y`>YPrDh)i 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

  • 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�o$ajZcJOoecSm|z_mBX=T(1K#P`ZbZ(T#cZ5Q57E7|4!}9)nlF z@BrxEs~dqUKnL&@1mg;Z#eqN-)CO}k->A+%8pMHcfsMb$ zg02t%{%>6BE!~Km?P2r5GZus8S%-EI8wE=qexuq+5=c#Qk^qm^qyRiy3{N!>5J07^ z&6uu~`U6nMRE}-Q;3C^H2v@6KdHH4T7(9pL0QKttCI(dYfUo)I8)69rR15^rKnAR0 zAM~TkKmeWuF2I8%IQ2^O4y;@%O$kU6hcuaoz_jv$2k3J;T-%NYKGk>ze8DlHfhUCq z+8|hGr}l5!Kl!PRr$v7C;~P&wIpvTw#{sJ|SweGdW5DXp^tN<0V3j&)MFnvf0C2zp z(Q4K~@T}kAc<5pF|3)NM)ACu# z1E|%goW>4ZA=?0KgSsj~-@qO28`SFJx4+A%rKg{LUe1AGejq%3qlBxyn?Fi}a|i+G z_(~a7)ASATr%s>Zt&vBs^8(L8 z5MboNx9ke{efJn?4>pVgQ{V+G--s76+4?VUh!}{ye~1{U5}d=9!LFU!GDr?*IkLdZ zw8|Tp*gyf>VotONhLRs@{{JjjSdd{kgC)EGFr%;5n-y5awgqYcIm|o8ImyEL$9=D@ zVq&{9r=YE|x6R@PChaX(OfGGFb3@RC@YD zl84@^83wKK1N@nsWq7q>0yvwa@e{KOv{tIU+o)}ACe1YR#*cc3Z_T+Os@xwgHX86P z2}=dTh*M0!FhIUhaPyX1*BBQdG9a{m2m{M|KM#WPSb67+1#Et{fUWR<Z^esO%?D?A5;O>6Kknq@aLjo zbOCTEVprvujkap5(rENh1-LJu7z0xUo_&rN^q^_6B&U6nagR#fmMrY5+{uhc;Y^0!!!L4HdNuNd))tbBVS_u^SdR$Tp z%{@MzFx;!VCsT`&MtC>Ghj_=Kxnnp2wxFdN>TNO`g$jxKNYN_J_Q+5~D1jYeV2C1{ zJBNEfg$EvFijs!=r=NZ9#dNw4)z$@Aw*U~2@WKC~Rd*A7eb{1T8FJIJk1gDseGE5Q z^ozrqMuIYC z(d({r@%$OEtTZ5edQb0~=U?&3mtJxSSk5@lD-{t?89hBsTZDz+pWD-^RhX3^d`lb! z|N9s=Kwg#OylSess>1w~c+WF59Y{+%P*}Oa-P_tFvzm)pUD(`3FNbb5kTkV4Ifia_ zWaGkytJmY*ZdiZIhLQF8hKcnX@UQiA81mZ!rfl|YJl|5jmC}hR*xLdxMe%XS)0)ir zu&xN3YR*sEeQnMs6~9sn!HwR7Z{v}%&wQ3+KIeQh0Bpz1P2!(Cl|5yBd4j*SYWI;~ z3Lcai^Pf`xavrWx!(WenZ?k^3>1~u6tl!UMTTY9^KJRq4cP+tHL6#qPJGbRqTj=uH z=4`r=^mzW$RgYf_ebOB(22}mIq0!od3zru38pKc4YNm$zm?yxv3*tIr$}rV4$v`Uy zGv`E|KXiE~6sj(duN1ye^)A0`sxOH!^&Df6cfHHY>L(v+cJ8SGW|{+nZ61eA^%}cy z{fp;s!zYC{-=7|tLYr@EwC|(M&-cdA7dzdXIM-vaKhz!T^}2Jt5&YHZ7e3Xuuo=iC z#2lM}IW_|kkB^4mK3W_rktuNManzIJsO*~SucZZGg|VIsCsG+dg^p2K{wTMn&E7rt zTn_x^x76(GV?9`Y)Vr$LGeX%CivVt0NV=<)YczYG>K)fA0+H6}s@VtEU)W4Yq7DKA zku4$V_J+H25dBQ#&3T2eIJbM=;`wcbrQ(ts&dwHS_GJ4gM-J<;=?^h<2ylqVfL~Gb2cv(1yZvjFK2Hh&`K0H&Q!~^}*Zbw0;yk~S-!Bo04unHDS5heooTw%vwfxU2jmTR*U@QE7 ztdk9I`J@m+nN-Wq{5}E-q{MzC2w}(2>3pmKQtihcfVF(=0VwJaaRN_b69BxxaR##7M(oKAGjKXB&oj@9v_zOh58*D#~3^NtMME-Cf##?C(bAv%_bb zPoptHbUriB+dG!9JITJD;WS&WzTTS3HZ^FG1btU)>lIfYruWcW<8M7~cO>RL5m0pR zrEGoh@UPg|(bpTK>%rG=T*1X}d@CBeX;NW)4@g<&L5=Tf>^{BY-QhFfL-11wX|8N1 zHL`y1-f`N*$=5^hL3c0k{<@mryPM~xu~UlU(0xk?TI?S{7a#3(2c0nt0t@ZM&f74< zqrt1m@9Uo0!~Z)PKmOMk{wkcoFXmcW`eUzW3P6tGp1rviBi8$d``qCRL8=h?!oye#YL%q5k_r`9U_+Q_ZK*&%=Xes+r!OeV{N?bBR6p z*ylku5P#5Q5H}E&OhEJzKb3u~hjxGpZn>-mC$HLk`<$h7$Id(Vye{~9H2t&M=j zfZK=gKX!PC;?XwuRSxvD##6L+L0odU%v79y+|(EOdV9VW!JSO>HmZPvvPV>bLrADT z(w~Pe&qaSE$a<51`st^V!w12>?~H@C4XbrSeZ*Ri_dWkx$k^Y^Ed!tE=|NP#;6$HY zJp#g>@x_$w5n>6hzQE-J&hsT)eH~a!N9Jv!|6JpF^!Q%$=jidzsK=L6^IVCZh2A-` zA%n(w)A~~Y+W9{j{*yI(PDgC|>r3>1{y*CPkM$c)tnY7VW8!ab>Y??IZbtWSgCAw< zht`K*ptb(M<#XCk2~zN**7?op@58=?aVq0gX^WnvSlc-4+w~1b3E@GJBnrd+*Y9Nn z0Bh(OWb);ZPKkWG5Y38hvp)C#@F!zMN_UZTw9z{Mo!}0b0KgE!Z!v`s833g6rRAH~ zkFCF%QC1bZO8!9e7CssPg%za z6i;{EY3tXKZ^mDbuAkk|aTvf0jcwRadeEO}K`|Jxg8#(yr#h?e=MaLNziiBBUyeY4 zWR<_)00hkXX`7)o=1X6P00G*Z#(S!mKINZ9j*QDH2r3e(??6Cb7b8|_AmFoeRslcE zjW5^MhOIR=>EjHB~_?2ELLdmr6jTD?C)eH0*1+a^K5%Fb#=XCs6TI2n*Cg~s1S zE>#z|J_l1HoAUW`u7_Rze*Z9Z`flfXTsOF>TWW&OkqStYUZ!lHQrSMmA(ZLEZC}{S zu58AxuIZiQF)Cc}?^{<-EPBICePG3-0B%Cb2{SY?M_4iw@ALT zv113ub&~T84MsZ;CO4VjYq7yL3yWXUV{rK$@4?3@R#)&$#?VtwqNbDdbG%D{LewQn zI@CoO+;gc-?Ht;d`S22o9{bdO$tGFQXL5_S@v52K8T#8!lH0>}4zgDtnGF4L`1D(@ zzFS8pL*GV6&z8neREovX1vK{D8~fiiUO;2do4-I~f6l0SRKSIeM>j02A4AP+uUnc+ z<5v~O8*JP@s{5*^RlKPGBw&$G3w#g~B*_M$d;cVKZ*$yf50594A-kt`e5dGTj=qXP zDSA8zUp3%(+x$Y~>uRk>gk_pj$dbHPU z7$@8u=%wDa4%m}#x4nL3-NE&<>&Dr}=hpWCJdLPlie(!Pk`7QOPZLm#&S2pPTkDm? zRB24aopO+nazZ2Z2M`*#flt6V8*1Vkhz%TqY9cpT1OF^}^NOaQL<0{reOS|@fkl|t zRC&GQ%8)0#8^}_3t_JI>{WuZ_Xa%>dUb7}!yNa*|E&R0D!qK8J%QMdN=+**!d=5T7 zo60w3wYI%>jkx&eRie(sy5o&o0uV81keD2~u|isbOjP&Kxkb~EkeAIadhd;quR8a| z8*Os`q>QBAx%K1u)781-kH^oa1Z7rf4$Vo84ojdb5c19$MbgNP9~#^F26HGDCH6qE zjtubF-Q0uev)t63E0x2u0MgY&kfUe#JFKcaBP3!chF#OPnx?WFv85`&!C+^wQ(_JzQWasarVZ}fhebR%>|U(jI<6fD z@Fjqd4&;o2Q3^4YFPQ9QunXgQ5D?O**3Pf%v&ole^0M1;B@f1XPCRy!s1=%gAn2pxp8Py|JlC15U}5B_==m`1h9SL@ zcn(Ity-D(-endY?$+RIIeoglH`!H6MotN7#w)k`x5ARhoI?Q&u5UVQzJRd|4AKms` z#&dd}e;h6we)HR5N+&_j{7R%({`?olTd~WhUjkPa7Jo-GTIlo8=keujA8TGwDmJlU zz>!3}pd%V$C`&076o4aP<4^wqED$mrUNAx)YxeG_4-!1UAvAKlZMH~Eily+J}4OYj?mw|(%$60y-?--js}ao0xaoe zjwO~(f^^IN-(fJ)ezgo%VJwn=Ic@Le`eJ*}w`kK2b2S<~EF(R5L9@vb&`fh14{x|) z{hRCN*LSgMN9@_2DsjewYocug{`24_dB5cid?hL#Z;~ERZ{YUJ1uT@$$aolY8li!c z92frdj=HRYQ)id0E->+XsIxC);w>&h6SyQKJ}Cj-`UuV$JRHt2!IK@FUk7X9A4dz1 zj65lM4A#gnW(O~!ppA25F2gaV3@tqO7M^cttVuLg5WR32ZrI>=HHlM z<2_Wr-x_=q?`_j}*qslTfV_!wgWtw)F7UZjeF1bPN0Va)ESV>!My|SA<(>oNU{N5*enl9-~dn$xjBR0m1x)f z_5}JJXt@Pwo#S}j?L(cBZi&ADn7eI^=FHN`LAd8g*|R2&Wv7ESnj;3~=)^Gq{wo0a zPdQHRj?`Tv(bj!BmyM1Rc50(T2M>Au$rLOf9piMOw*DP6()o5h7wCetu6R9A?w;4r z2F`~zjpvW-x1U+u~Yp!ZqXa^(;7YK6wMu|e{ROG z{{0bp=zgxe98}tBJ|A+(TU<`q@^`-dt6vEYI!OZT-_ZTdA3rpn6K#-90Nt+f9CW+- zcLx8Q^=>RyKvA~@eop5~e=Z@a!{X7I&%AekvGK}fZ#I98-uNU8fXO*2Y$H3jybi zW$QOS_ZZi%E{>stR^(J<_enhkgdz`9_Anqq6fW{mv5ON10t4RpWjvmH?rmVUrWwiP z%GwGtok%K=7^+c?{WS4mTmgi}j$1#Wi}Oa|7ZkROr8%kWI8a=T>i9mejlV(t=~o!m z>z}>*oaG)B9gp-H*z*vN$V%;AQp1^FJDK{BrSH>MibY){%K&i`l>r>B!t_V{E_->uCT^k4|UIKYEm z-ocpEpYFp0qK(dl$)lV)QIqDX{4K)+R2^vWemGnLaPQZ zC!Ks9;d^37QWW3gWmlxAvFx?Fi>YokTYR?mH2f36oURt1qs8Y_-Dz49bMWc-zu}+F z*0=Cau7UsG!MiJ=uUaDFlp}@6P+RrORtl5Qp=NVFT`@pGQ?Ie=m8kAF{$ezqEx}z7 z`#Sb8X@AmVHciL40V31L>N~J7VyGI=_OkF_U#zQ zLAHZ!|Hggd+u=deMj0h^)6mnMH~QqHOxLDzaqgPR1L-asNHUgVfftX)+q%>4cr}-T z93}6L`3ZIRWVHMDz7w4BA-qSlJB{)7DV3Jy-u>9t%_;ZsN=5gvTz%bH_v|W2FjtbX z;oCqwP76IFlQEug`2~b@07-;1jLh0V{-wr`FMGB58#MKo)zmxk91Z9>TEGmx3hjIC zy8UZUUjw*K%)WNb{cA^15Z-S8h5q-N#kJjaqwCjoFs08adW_=`csodNNX|%?YttD$ zP?{^#@L)3oSPXP_RHQZJipq9rP&6hV6W%!<5}G@JD;^LQ;u{RivF6SI&^V%-0BQ20 zvGDlgxekX@fvCPR&;`%DJLnuN(2z&l{Nr4TdkQ8xtc}1$_o~7o^o;-)Z=W6|xBSDT z(36Wr;bn(s6!y{q7-3;rQzN&5JU**Xj9TjDw8ZNQ1BP*n)%~gc1wA2 z%*~j~t=F;u8tooBt*hqV%~5z8>0FLtCvUvEd1a1AHz%zh!}iS_k27bgu{YX}@VWfx z;lt^Qv;LMemmB=G0xyo=C$~S9a>~6Yjpbon3S+r7a|N-r(9K(@tnjp>`}8Q3_f04t zVDuaSiGp=skKvqf6#qJ~?(1vc#%>PR7@_E~wF`Kr9r))8CFFH9wbSfDtq5o#OzrZ= z^M$V9jz>!mJsmi18S9=vIoHk80*D&TAsV6fsLTjVl57-6_bG4bm1^!!R;qbm-L(wo z01^+(-WO>gSL%f#4y&o7H7KwjKayH!SixNFZ5=IpeQQIGe;DPaLsQ7KKr7Ed#AWO9 zwb`1+YW#A|v11bi1_%(A=I*psE^KIJ(P(Zti(DYb(OGiO@*4?2zDBMg@4gejSsqCEj5uml4is^(SKM))qU?=yA90r@Vy| zXYxI@IxD}DJ1{Ex$6I$YmAi(+shlr3el{ZvV(+e+H`(?39}qRhjZ>ay!*$nvd%Bp% znH#{Jm&P{h-1o6_YaYLc+hXjBYTnisJrYK%f6Kvf?^6y3;$A3^SS3h5~roZ+S{x|sVKDq|e`F1fR-BOKps@i-@aFaAqSU1H}c2% z%npOxGtWK`?i~WVP3=Fo?GUT>q~B3?f7d5ChFyYqU~k8_eROHDCwD^*V;X37@9W{k zNyi}(RQWXY;y?r0A|*_h5OJ)x>%?w|wv8@$Xx^4$6F7Itp2u*9Mstnm@VPnS)B33X zkxOdLz1n6^jPPcPgJ#81T}FEjP(fS8ppbgbQZLWRYuWDtCF&P)ZGdlz#0rl~IKEoi2Nji+Mv+{pjwpveQB?puEy-}e5s zqifdYYfg7~idX!dwR39mZ6MJSj*u=a@*N=2T$B5RMZ#lo7F6Y+kJswv-p!C3o*+c4w+?Rd6JcNGX``sS20V^!J=16A(>P)-c zDcfUs3v=Z{FnQqH zk(u}To!WY|%}H8kWDK5=&BzoWSCG~T0?=Z03>+8nFuq&vZ8g6G1n`zF1x0tw{qk2I zG&0hxLmY%m0;*=Mr~%=Tg&WhT%tDh4SqOnP%Td6ccN#>wOEWyLgJFml4%h}90RJKO zFMGS+bq2nOyZOKDKb+BvcmTnRevq`n0|Eqw2sqD&C3l(P2?@fICMBIzW|v8sjTMY0 zYgicQokfL3!j+kW$4dpH8@?7Gm){~t^cg?6{m z0qFh*)X)8Q5h1mBv3@_9Os720-u=0fIK% zNb~CsXnxPujI2Gd=AB^o^gkL1R%dIPtG~8p48y_V>ajJeSMOWXA$8vc6WYZ}ac8nX z>RkZ@(1NTN5I}Wf!^^2J!&hT{%GrAZr3S=$W&og)-Va^AEZy72`cH&IyWC?VWsiQn zowr0zLfPv$ZdinmYjN0wPXPe!@v!TOC$L;yC|YFgu^flN{@LeVph=#SJw2vc91(LL zzAWWC`EAD+rq>5<9^lKK&yCH`;ZSBin++QHFU1g{CZIe7YbNQT&&Tn#zt`W2T7CtX8UI-^mUZCj1>d${jTtsT(yo|upm z*WaQQ9_|#tHhAnHll+N=-r{MGV-VzRD{*4%Xu9{2!KEAAo2gh6` zwr_Q{9b2~zwfPM)Y6?@Pth}{(6lI^}1D8OlNxCVaWyPbdV2A^(Ly9=={4ym2 zY3^d?Nj^w-r!d9~l*e%x07(;AE*Rgs^&8*F?i=SYpWV{{56@}dn|HLAbEVDJ)-iMN zflxql+9^C(bID0S!c*~)9BcYw+(eO-9yy4$50%?57_$^D?_n7+k1Rl!a!)W0g>bc<7(F!}Z zE5XaRXIBmI^1X-O)p+Bw$I-(}^zc{J!v`=A&#M$(tw#Ou>Q!jetJi#T_2`<_y*0hH zeN;uP4P&RR#BxvprLLH6Vr2J*t>kM>>}Z^3F4jJqJLRCUt0scrtPa=M*fU(2Y(;0N zUxQ*)Da6wb+ibDB!iLm{i$G~`jo%9gBw*zO7{DJ5x7Z4ybCmKFw?dlyGH`f16>~fOMmn9Wo8kLBGQc^iUfylcAnQ#! z4CVp%`9&jNpm@P%bGY55qN`8Sk*<9;?5N*?g*An6MngJ;bQ2!wCt{7|)&{{Q>uYJ5 zH=3c?JcqbZ9qM-;}D7@(Yp@{QLQ}kY1mR=SIlZ#SXw!Q8MHd*qu z1$*-cK468esvK50G_82Kvmw0JpXtNU`-!v*#uNcCG)8IFT4PB2vuDgiH=H%-MqEeR zxI%-jo7%~v3M8yFhgTG8s+yDi!3!hy4C2mEe;(h1DnvINb#u1oj7bO?Iy6`t@$Iwl z7>(g~mThQ4Ht)b0H|UJ>JA6fZ6ys`nTQOR~?Dj5vm-s*U8slI1PYdln09?D5V+!XP zTI{whtfKaYNxa-ws&k_PBV?Wh8J#;jhGAS{y3gW4O6TuTQhG9q$7%QToW<#K2j}hi zGaf6;v^l!ulFjtmC?4WxI9$NpOIy$d4MI?sD!DOhgb(YjH*O17tVuiggg%TXdVwvd zgEjRJ7+N>{az@ODk^CEl&Yd1XU;>u{v#k?G!Dl?>eb3jDzD3vnwHQW< zTb_&I(VH!hl(x5SJR@0{$SI*n(ZFQyxz@YEB%&<-<`S3FL+_SNj#c=XYW5E2W>P{P zAG_L0x89A9THPVB4@-fI-@u!Ij?uaU+=#u~LuB#Mp{Cp5&92SC+t$+C=-OSx8<*a( z?{573vIo$yyXe@jt7F5&z8>=U+I6#Q_pd2dkE}Vqdfx}eR)1i1@qyb{PkaFXVfE^z z4~(qN^w;9*t}197ja-sC`#7TKWvV6h-q-@mk8A20y?0>*Mk^=x9y&R6R9W8RbW@p+ z_^|M;;baq6BbU5v;#;5rgJ=-^4ke!dkFxg+lJh#(#N0gr07>25>%Hr}yX&&cuB~#p zT;+1vWtYpLcK3&OZ4nqu1{fug)RittkrYXZne6F4-`9Ea41k$I4on~^F-MUismvf= zNeqgVsCbpG0*Q?A^E~f4=li-bl)2JVm~#zr(Qd zS`}X)!19R=0nHPama8d7R9&r7b!mx`jqS7K!LfY?F^A#T8SvZ~%YMuHJ<{y2DF(-h zGCAi_T}MO55@^Uu`1ZQDQk^Zdno6|$k+s`yEwS`QqAhuyL_3Dsy?`I1a2#5@@7^<` zaICVXx7ys0H40W?`I_)@E1HEUuCvl#ckREDb1n}v$FtGxVGRXXb_FrG%B2ZdcJ;$4 zUGwI}(~Q8i6oH$)ppOx+^D98~;`tDY805V3yk1D^IJkS+Up}<8uw@tQqJ{+ax}qL- zX)>c8M0N&nf*@q)QU^0)JD?Q`cP`4=p|G<{LzCuDD2`Ajcju~~r@{Mj+?zHeDl+nE zH)zWosrMzI-r4Y4SVN-+;De<6+8yNEtDj~{X}hP@TnoV?ZpD{}C*TJ>0|&aZ@;ab< z4RRUc1wi(6OEO+U6%2LdPK9rMMn}~U<&gGuUWtrEM%eDjH)I@*Ty{R^wj-7e8_73$ zF2qxvG`lB`;C{*N#CDrCUklu6=BsJ!m^BY{Dpq75Y0j*QZa$7Wk6*Svj_1#>II={X z`$RvW-BWMNVM3b$uvY=>4Jtj=(c|VvH;M}d0z_q-#o`ds4j6sBsOp*7f ztmlW;5I>`Kjp78T^m}F^oJ(5A^4Pa>$v6-XNQJ-h7s!fv+=g-mI7hJ}oU`akO$vTz zIM6md2HzAlwjp6 z?#q=gxi6N#;9e}f@B%1p9>)Wan}!}l^uWSRljdnr^aCt|XP3@2MRaw9#=-^VI5+^6<4L)*_U9Z#~y_m|{T5fQ^TG>Bz#BixUms=V`bZ>pT1K z%3DD;u8%f=SU7@}SR2blau`VGyjlZ9ywNVVOiKS!>G;Hp0QELN{SN~5b<7muZTh@P z)I_&+*OnUK`}gDJvE}jBme$sWWr&;SH!n!xSXyMZ0_D7PDI~!&5d88rxi|$%8}aoV zBny?9N=Q+M=6QBaOwc6{V7`nkVRs_#`4>y(b!XnW2k=kdcq7S9SK8eYalAhcH^h*O zYibQ$LFUJ!>E*0D*3M(U3|uF?GT7!)oq~nVXk6UAgeLdI$qx|40plX&cy072DESHW zv@|IRzo8~u>j#zGM=90(dE>=;KWrot1qXy|nPxw9P^E6y z&Q25;2{#nSR~58M!R|zHv2dbzM)WPvZazG(n!};XEe?~K8Mso&Mfr9?1)ait-ZTxa z>Gl7ORZ((qm36Wslu)jWA&PskyaFQbF6rYg@{gp5ZB;Ms<@K)|qMQVZ6UL`-@}|#U zLh|D)XgM9;61=T!S%5@D;he<00pYy4*Iiao1g=kus55(<>k@njPKFMk+oR{r zw*>4iS()>+Mct*aJIBjou-yo=tzE>BX$M7tRB8-+TskqbX%qnqjxjbnxgY`UE!R zABJBDLhQx^u}7lLF-yR8Lbun=EdyuJ9n_y1pqr|B%NoaCjRag!0WW7NV7|6f*xgF+ zggdzookNPZz1aBPs8^++2QHq%5wD7er?~7b*+`ud-;AOmG2mvc&5jiWAIMB=6Y&hW zP2vY~$Hz!6ZfXIbTSB^f@hoCDcs3kz_m%2LC%I_6`LQ-|yXUgYJaSin+#3RNf8IUU z^X#*qbI+7S!Si>en*koMn^;Ir3sFg0v}kx&-x)W_=-{9t@`7O`Sv>vGz6A!-0sKh<-+_J?7%>_eqp{I(T@8hVH>z*v$?P0(u1=xPyS6 z=vFsDcN5DC8;WZfbbqCEYT^k%_Y9!>T|xI0%)_ZI8%VoBzQ?!h9q%0*A0OX4_JQ&7 zF}|m_u{y9ElzeOozoz3o_?^9Dg>g4l93Pt=Z^#~RASu@b71GsOsX*R+m>}OLke5O3 z^>*dnLDH?9n#u_x)G4>4nst;j-!RIzVUpOZKVl(~{TN60?s(42*47Seo>^mc9KJ}! zZir!F&-&6=!OiJVbB2t| z;1o&q=cO}jaKm*UZ4Vpg?2CAL9etz~+wf(A z3LtqMFBfwtO?l{4VL7_wW9?S(ulW~->p57@Jn+h84zNyr9XX4O8#bLbeZefIFc@G@ z&#M5|XV1G|#?Sng58w#v6yp$&kEdJ8m$KMQs&Rq%E zNtL@+O457Gxd(`+GcNTzK)eEQtcX%3RTJ|NuhZ#|CvcX^WR9Ktsf-Ie#NQTX(?kA^ z-LIC*uocY`aDe!XpGz3<$`xdRthEqB_aHA@o*FJVy3$m6QkdE@7TdBulKur!Ju5SGt;6yO8U+d(5U&PX~vm90Hu}W*q>rGwB7&qkZoOU{qntSQu^!n2&k38VGx}>9lBuK{#aPWSkcl;GJ_X zYz3ShyD0#rW}au>c|HyIz6yL?0563b(C??&JoLZR5r^Z2FH+!tKyKm_@gyguoWkf! zaHhapL@5XTwu1rCpNnJAW(xLs)}EMuZrIQLwE+K!{(yh5a3DGi@h=p<;J$dabpT)a z@@1D@b`VcNAKHO0eJS}Ok>9;ge%^h)B;_5EH)!wR?6RY!ziY#c^6+6s%-iPy{4?fG z_%zX}o4Nb8F^B$nF;zsYB>1SzV5fWrrJ=tVWCrohv1;B9v-!Ecaz~g`fL2o zQ+E>^P;q6T>jla6I3W`c=8nhjFx6(@pFoFCFx8gM_J9Rfaq}>*9j>>VtwPiA|Es0d ziOR%%=l~Yb0US{W(7P3B_sOl(TZ-dbc8wRu#*?ugp#Ja2`bS4mAx3u-1%I}Az43G7&8fydL<~^@32SZ)8GiRu4xJ9+BV>C)OKIE<}1?1eZL}o4u{` z%775amSvPmve5~>^t8P|YJs<}V`fZhk%CjstQmvH|1^9X3Rpe*fxvXpM^+rotA zo-Lmp{{XvHLcKsg*|I+1e`+?;IL_;O{Wku{@|HH3ejO@6P03AO10VVTGW{sjhl$Ki zojz*>{K|!_5rA}Kjet0}geYGksYIzw%^l*dM!;lxTJX1NhCMgJjx1-s5ip_NkGw?} z-V`tZ4OyAkzU7+qm2<6ts2K`0NP`#bMfpJ^QKwO;)4Sb03uDPW72I1;xzimgA9M#w zgn!HHh-kvd{C-LH0k&6*$31Mx=w-|-fs&%^&wo947)3;gJlU`SrIr7jNk8jV0`d3Izu&(Y1^s9W1^o7M1ok_4 z@aP^r_SZe`H;@lWJ?_5*+;2}T0QYwT_m2tp>xi{aj;EmU`^Nf4#{l+sj`ol7ozd#p z+4=-NhyQA0h0zAy!1hPS?inqPjZTeCk~eH^pO>DWLefvv2y8&Ql{0adKtP2re?~Jv za;08?ye4Y~w6)XXb)@2+RMj{*%1WB$G*w5*%RQf>qOZNM^v~H0FbXHs_F;GwP>r~U zWNkEr@zn6>X?owt?PQMX;OV}yK!UkHhzGg}A%JITJm3@qpnza9i zKmHLfpZ+69jvPC7%pI?sXr3&dIO$H5j-v@+7x3PD=mY-vd*28k?;i4(@BHv>%&=z% zNUeZQ4=2ry^dn=!%`u!t^Q_;i`8(H8^BacH0_Zz#FOdYvrz8uvwcIFp-jr9|6{0=^U7BhSwp zT-F(9!)_V8tFge!1m;x29%E{+8Ni3xsRQm{^T$*go?ZzPFV|Y=kJmgAQaI+KIF~8}d9g=Lv zYHuK}RpszVVj3VqJC9o!wNM}*%g)OF*7|;VN4m=v84dKF2JG0Fees7Hz;GANIF~y2iaEn|whSgvdtT)lCf&aNnx*3D#!J+Hn`DK|{_kZw zUd!QK6ZONLFL@y;>sujU`R>un`abGG5yJWp%K)nVz{C8Ew%9Yh&jy46c_6!>-96L$ zIfMb-bN$lypLZ{$FD758eX;PRD&Cqv^#pX@Jzw#V?hMlLf1^8ioNL^G>0y(bf%*e6 z4v&Z$xbeX*H9tSk#*^$(-FJp;4NcGQfb|Y*wUp;)@BHXTD9X92oWG$xgLM>Vco57E z;GyS&b$&N|Fyq;Yz=E)cos-ydFGj$6FJF(w=_|r@OiOwr9)eT5w}lq0-fCd6vC;Zh z0Pm|4&j8v_2-@3Q`b3K+N#|$AK0qAj54??y?HcVJ866!-N6RB_v@r6;(Z9rpqa*wr z-}uWef_#g-e{y_kOC1tw6{9rRY9*X6MVv>s?#=ti`bk<$*q28s-qJ1X)29T|v!yiZ zk^_1lS|;ny1N~u(yjxJNWWqkj-d+Oj4`Jn)z0+kHnia-ZpkJjJePsOtdJVpzf57Qw znO6V6oC|qBBY4cWV6P45Mk$ni7tBA?$^PXpeu+LAXpeFD-~Imge-Pro3siqEJyOG9 zh4B3ke*o409eTvy{`%Ly`qeLg`3r4Mz@8eP)Z_+PwTUq71LK!BByHcXa`&eFy>ZoR zSOpqXcW9o9K7)Kn-6!eyI4^gVRgl+jFcgJ?{I_Aa9XS6y0{WabiS0ywJ6JwFkJcEC zu~%1Fec2M9iSt4M&9(oP#hPREPKv7g+kax>KGqu|vI$*}w7>EZu0l;PiVg4v=V#2W zrHPK|t?M|9iD?eErFGs6Wd5yN_tUB3(Z<`3@!ewyEU9lIVls&apsAILTxG+#Oos*l zfB$7&8<)b>2kb@FjB24x#_u`q(XmFJCsju^F&L3B*R5tdZ7~Ur?#^rb8J{-u+{fP3;E_rD1Rk2oZe}0W z&0+w~Cg6zwoKUt#*1TCMPDbrP&kX-L1GmQ7_?+-W{J$+H?_0YW@LwYwd1haT`TB~+ zIIIJ}C@<7~?o7fug=uC!C$YiLHEO81&FV_J4q%USpH3&!u7KLLzJj0lW0$)-DW+IY zhv5BW6|auy?c>9#8t#ap$Zxm2_Vc;g9!37F5zzA`cqP7q;CF}YI|kmv#Jf+~cM$xS zwN2hq_EF+zA3%xU=G{5L`)M=+N0qW?h?um?_qf*L(%$!drrJzn_$I~1)QI$>?1B0* zK0Z=w1s?TUzi7Ux{qA!h?$5c;C(l>G@e41^zL>m_0R2-D`U=p$-w3^XqLhPwsre6e zPnhMic=W1xu$d$M6Ow+r6^4+}Lb8k*vxhg^nXY07@Hg?ww|BB|eKr{P>MM#_QKX*#KWR&Dv^5cT z7N7&D`VQdh>HwZV2XIOqK(b|u*grM46A)j=n;U&#q%c~;TVtdjC=aY}kCaF6$0yv# z?C1GFUgL~eB5o}Yyy|*hhD|CjBpN}Q|S-6+R zuOJkQCp7*N7t?Zg9Z?y)-r$}}LLTl-+U1>T!pK)mPpyr})x zUVi!29N@>oFGpRK}h zGIn42PX%|*a?-_z3S`rq7MJtjZuV28_o#j1K*076a3{7?bs{&z`Ml+VuArXg+YQ_y zKKa)LN9eMJ&9?;k9%>iAxCyIXz?Zbj(rfS@@tp#z@ZFdrm3+4+*<0IJ+`q4}zXn`S z_V7mNG6r)H9JBHvOkd2_BZEbU`6ARok$O>SwR2fN=b=*X2;J_FY&ys|t4*Ll>!Y&+(iDB0U-vo_XQmYtiMDo)LpfnrV@_3 zpJ}h;Zn%ZRgE(jnvzgOa-#LZ8QX_D1-FpCbdqL`xr0w?NwvIj^LE?5BjyD0~fy>vh zbry@orlr$!YYlO{gzu>Vc?Y9M`Sy)h4#)wIxoJ5udZ8n*Q8YO+dYJV#Movbr#qBmO zmu;R6DZL;6w6xaZ+102Rp;g5{!17YT5bCD%Y!vZmq198Ym#5$#swef4)eFmgW-n;= zy+m_x_0J_h^V;Woke{D?zV`X#IrnS=Sw78Byz;nvY`v%O54(p-#Bc@F8F4dlKB)5t z!H4NMMHI&|rnwWk(j1YGC~itnfblS-%zd*R6LQgL{lOKU$@_wgo8G{^vb$wv&Z{hE zFs?QgeX2d|Jd^iCo)0|AYPsIpEtkdOsm{BFzIlid^T`~-Apmmb^052ZP`uG7*Nw@) zCLDhRIKEmc2+5n{(_=kg?sKE}j`R+Xj0`6uJ;NizK=R=)kDN6;jQ8<2GLj4fbXOPr7LRnA%xU5 z3h%3zC_K*^S&?P)@)Ukg-nS19yQKQ(o-YNh-fqO?7c?c5Hm8N}sS>a<Xb0)_e1zACgLGq;S``ZY z6cqY}Ev@lM*h}{zDLOvBI@YF?)P|H)!?+yNcs1nhliV0*B`?&Yd5Gx|&(ga$$%m~B z#*@9CWE{p?%n0Pf(QqKK^Dq;YG9ah^Lma=(7RlS58roNEHu-W0c0tVCcdUiLR=V(7 z;ETcA1URsa<>3{v2A0#`T~@>^!OHS<_xzp&cRf2`cie_i>H=>sV`@6shKe#JQ&iZi z@?1M)R5-(L0yt+VLWAb_(%6RC$jeE~Gspd*PiYglj#OwAbHrS|BF+_?MXwCy09@jb z+Ebn`p9zUm9oLyqV7h$XaYy*V?kKPoNXexb#Q=n-fba%*`4ny>m_4tuHN~pAHulc| zwDAq!o)la)nQ;$Q`p`>NDtlqLPo@n$4^^zSzycfS@sRPgIlekq(G~1x3BLv3Zn+fo zc&R2r@5sW5-g%vS4fICELCMj09FprOJE}VxcF*?CeHQ|vZgkTWknN}mYW!vXMmP1M zriljh4m@0T4~n0hcJXk?qdE9SW145;+;I<8-g9y4@{hX5%8$Dz`X$Ui<(^KSNk7*D zdLugjT>aT9;`7PVm8X&?-4lfD%A@X)zK0>tJmelM39k+v=wl%hQv$_@<_rjW9FhRlI)%S#tDo5U_`Mu`6HAO2_^;Q7Y@X!q0V&k8?p z{H*d*_mdJ3n4B7;ZUKb-fiOen)t6uX8gmvp4;izTx*bJENG~|F2lnmDvS-3xO3jW}m<3s86g@^}s79Sh^@FtNc& zj=PoPcyzRv$L^C^eDxtOBu}5F3j9CH<0u0NQ1X z(Eno~o5FhF-qM8D6xQ=`4;?6r6|30`kSz&^kge(V4}JJ=Y`)z?HvJ$*=zRm5dzpj> zfWa@1*`VLR5MYIQ`!-_FSBpTK0y}yKFR^PmN(DEFZQof%=#~>V2GXFirkeu}QSdB8 z1Ximkn&ie{Ihx>Dj{Z4YuOO$e_lnOrQ86-YG+jou)o|tV@fSXR1vPY@ZiPYE{rQM| z2GxvesN0N3kIX;l`9RG4!%?=3_8sFpW?>f;^!v{EU$$^qBQKQ@(2=}D>8 z0pwU5O9V&CUW?{P!7B*MP`5YmzUy+LuGu&yRV&o=l!fpWXqsoj&D&+s@;51w6YS{|{i>eWsUra(7?pu-_s}xG?nGa4$bQHFS z4M^!#@NW)iCLaQI&t^Bm@CHcl83ddI9M|S;a#PYxN*4nrniEcaqyvqiIn_qMDceLL zJ)9d;(&dsra>3OR&b!gvGw>K4&1vbOp9l(oUJYG%E*frt&Jyeq9b?vT*Kl{(%yPQa zw}WmQS6R8m4YI%q<&HNNOxr>(QEt=@Uk5wqfj!fWXdVNP_@3p7xAqp$79pHdKY@G# z;XJpL=20*%8sb6A`CIsesMPc}*OJb|=pEzk@-uOYr30Xwj5@$taISp{S=7CYc)Lpz z#4i)vp`Kohy$G0fBk`WzTHcaieyyE05>Rd6^nTZar@US1!83oL+)E^1s;uKGH&13#)2u?Cou4^ z7}xSE-J@gGrrBXDx;;|fR|w)-WBB8NxX59FYvoM z*}`7p2KF5`xR*Hb;QfZc`!0cZP2fE}Iy+Jv9$5rLyWt)nv>WOZe!o0a7;fV2nW5tF z(EM-<7!4bI5@C06@f1Qi)L!~b3yMv5-nR64V`6RwrM#dH2h$^`z*!|xfB6RY; z1=8kPKKkh6ygUXVEvek2w29@fz6MHesug3TZ}khQzngxq{rwWO^Y49^Q2ZT&@mrd3 zeEnNI6GTQF3cu+8ixy-1{IedA={g%tc>o8QEG4SpVTe4lxFLtLn&FIAD&)n!j zo55|E+|OeE5me1Gs;1o=hAGMOYFlT3$J@u&kynFR*YMG{u?>V|eggerVXTU`-J|Om z%0T?GIdT>cCi+Kw{PyTHGMJ>{Ot^E_B5YQ0A3;W*a~7bzp?6#hxw%~-hur4k+zb<% zYEk6jA^sy9S|&6O>8!WFJr7ro!Ur_ss+y~`XU^8l`8{*w;mWxCh+A}$^cu-8%<)qn zlFyBbN9<-hD+xW*(8-{T`z70^wikA^fY%Aye1|eo67SBTwG3{9YZg8D%30b6lB445 zUMM$!1pN;Ddo88hHqijFjeqBsxEo@B0u5j|ZbWR_m|bQ!lmTkxVNxy*%d7G959my- zoIOORR1SYGEQrMhgO9>H0bZL>PQ2#57TA_~9w2)TD}3tQ-`+%oectsEm)*|F)8#{z zUP8dMn@$?QXncp1U9Vv>olF~_#!7cLSB6%;KA7E_OqXfF?7FP(4tS1E_n(I6m|5eN z7q69DWKC5E*X=H zM!#ERJDBq(@B^XIRhVoJjDE;H>>f!TO&+T~-UCg!{Y3HcCu)x;Lg)k>yYiqDLYIwS zcK|ers+cN4PPsH522j*Mve$&@KgqJq)W)?~XJGUX!I5qV82!4@Y#%hDAZm&zEc$0V z(rK2yq^-?%GwAvrqYv`Ycd=~!3o@1+aGEbbh%&%w>=d3#C!30<1FCUrZ=q@&`z^ur z0l{=bFrAF{px8~1%nlzO>Kg=;9!!VaV0ox9xPc$wzoEfrhWh!-&`>(KZfJ0jpLBx- zeAI)FmWQT>+aqwsM{1+>u_`uxq+2Vx+sR#6$tTxPmoJ5qZdEDd*18yWR++LDb3r5Y z=xru6H*HYLA$V_xi5LAuYLkiup(VAu*-E%ch3E|z`sG(6dNZ{K^tMT#TW`M|wGXv7 zdfePUvqoo-g^nJ=U(fD<`0cH3;&*r@>AE8!_&2}V^Q~{a?%vq&CSFo+z4h(4zU|)X z!_WNHy;*o8dA&qM<{JWUoR)kF!i;PSr$LqJAk>HNg@)9H--xI!vf(tEYepae9MU2I z+*D4nBGg#nx2(t#l49Xz7jBFXlV_&c`~1)uUyS@c>~lBKp6!DA1qtafm`o0ThN=qu zM*TDg^yB|LpHREh_!uF)0%o1~yTNMIF{@jf*o9WWyd+m2&2SKMc654tVeGSlZKCzB zl%!;uavLzaiCqa0Kd~qwxuAFZ zv2LUNvcA2J?y(yWMp8N?DU@Vor>YCZ#f2HHmvr;RIl#7?bu%SVY?I3)YD;Ytr}ePS zvy|a>KJ1+X?%;9r3C5^{nD&}fJC2p}kX_B5R88q2)V#Hj8zLoJdrhns49z5=jn|_Gi6^Q2v78j;K@5TjfK=&*ioT)8^@kHR=cD)r~_rA(p zxt9|O+b81KWnq)ZNYAhABb=22ai^21==7GMjcdo5IdC1`${pn=}^eLq5TW6lEiyJq~&6rGk( zHg0K#3{X8P=t@v9&v8a0VorE?)Q7>H#l4B_?z6z`hmwcWN2-q&AA7X@SpCuDk@Vr@ zq2$5JXOquV9&q4Qn+l}NZ=7n#NLnWIB=0^$h{GgtAofiX9F8ovJ}_XEH6Am7?5yxjfzl+8(uWqY<6(S6_ud4(<)|{f%!nzEya=`mOcf z1V9s^-QSgX1U$q3+E;y37nB!W`lr+bB4-a%b&-4sp6%5`Q4#f?Ui%hKw(l@)rZ%}(MZN@icfq+`(x-NL}Qv06(>X)ThR){376HYD(PV@H%KPzaVRUtb*^3^qa3&)gOh(qX z){wv8v_m3*P9TVvB0&FXW_^ucTqtPl2IxC@S*dB_<}e5KN9To2UObPnhYV-tQpm<_rdjgEoZ~E$#PBpRK{EbDlQ#8nOeF z3jSefoh-c;r+{e0ZsAO5&WYd^EPSb4>Mr5H0zGZa z9bAYNg63(@5Siz;RL4oGo0!sdWz2(>dw|2U=% zZ@g>u;5&+eFZsR&rqT6fu7=IWHvS#cBcxCQ!GWupJ3(@D*pHqlusV_SDpVMWYB&Y7IXXv$zLyn zUlF#tT6A2Jr#QAq6Qkoc1rEhP>u89|7SJ$~ZJS+Cne{KgHwRCvNdysJcu8g@s8VE7_4vZ!TWBom!EA97B=t0n;SffzmFgIlT(}f_`eJ$n|BRPQaqm= zZou14Aetu-&3U161qHO!h2S6*WE8%36sg+GVs-} zK|bFAAm=4VufCdmz42NJc>ZKp=Vao-ytoCxl-<2tG~{GCVe?(q1MZPp^Mw=YMt zoL`UB9!1}0)-3@l&u2b%aITLuczc0C(lOKdAE^oJnWH39jLi_8CmFZ%i*dJha}au znI4pGT-~X=c`L1?iQli6R2hR-9>85VYKF3u93HTL47^9?4O=9b+G}(+`kX?7QRR3T|sQkT^b-Bvj~9r8kWAaz`WqK&>N^D5Y+p%7hnZXVy zKVeAz?jItQ1Ie=?u;6I>A+Re^sNr5_d)flC;&iT+W~mjO$@%KTbYVNiKc<1Z{Mrat@Two@q5KDe@@<0h89{kdjRt9BDFf1$~)|GRn)+t{fwX=5@c@)jAeIehswqiOs~PgvZbj3U{i2t zF8Cq9RxzB=#F+mA?tDzgn)s$nR<@V>Ntq|gJ16?_-NcW*rQ!sxN+^_;Ce{;Z3AGMy zi{+V056V0mnFzObjS4R!cjD4rB6lFue%vmS=_qkWRvJLp9ALV?8k*8&-(6&ypo@Zn zhM&S+#-+V+{WhKJpZx4&5p`i*+wIF9bUnTCY7BLuT(-fz+R`sz)UemrZOkNXnH9BiUJ1V|$FFH1;VEG$1zp?lVbE8KM zJxHQF{~;c8Av9!|8`(1;*KO+$?78CEGiDK>Yhxcjj(StOeVS<@G4lLFA?~aYcV38F z92%Y*ng%%r75>cT!a#NNhJk_2n+G=IXEy+%JdkcK4?MnkJwF>hSsggb{sjMEGO)pZ z2OlhMo&|$$0HYHq;0frn14froCrgN&NdgZFxF8y3Iq>I!+6 zXlKz4vX|wH%D<$%e@&R?Ed5Z)hOua}RL}3f44CcUkYpyg?Ufv=`Ei;Mo3ZZfd4WWh0WlQT4HRH`s8AIoVk>`dhLy3L^djf`jF+2^VZh{Zj zFo9Urz8_8?a-BaT;b$t~f0ht;<218nQos$Tc@}eaOpKPXzVW#5I=vhrzPv*Lk8|09 z5yx~H)g2?}oDh#9c&Ay;^J-8H2M&-+s5Y!d4-00D2o#dZ?KZ|kY5?k_Q9-=ap$#ts zqx*!>4o606GGo=ZfdyxSQtzvC`;b8%rQ;Q(n6u6^;b_=+!G}~hz;s9~j(94Z9j-HA znhz~LFq7ZKg>x_+O=yWS?qdv)84+gSo6C7{zcO&T3Y>0J=$=Jh5mPJ}CrAO;txB<6 znJyoi=mAbYUg{SmF5Nv*EKkfy?VhaE(CpOdzM(b{of9bC4oWw?gqgF=f|k~;2`&<1 zboIcvjuC8%#zZ)TwBW!3-qv8m+%)<)6hDFU=b|3RcAw2Y_c!Lj8KE-Wr2L~F{TSeE z*gS5zGJ!J~@hM(V>bp4-95Ni9S)#Kg89XN@*Xbg~-iO}9#=`CI6Fg&&KG4}=x4yeK zJzTwS`Ti=nZ{NKPiY50X*tPGlYrk?Z;jVp?fd$9L9zA#Td1&-$-D-9hAX~=bpU(&5-=LfU8 zNHEhM*ro?SPCh3^^YSy>rK zR{o2f1CS1O;^%=C{E82D4&bLB5A+e60l&?`UWCX78$;FM;s}Jps;IIPRqj9k{PV$; z9ffR}Ze~U2fjHEi%eCY*=31@rL`4wUT5#o9{S1gXDa}(flaGEQykPX?F5PPah*Y}k z=CJeZMXfl+9#Y#vVOI2YNa7$qhS3+sfN)@QT$xK!VuH*Dy(N|V(rN=YsI3spBVi_E zei~tLropk9uMcqi!VBq(jV}~m)N*A}5+o)z{B6%kt zH%en)k=V}?ZfTt?A?7z^s6zUD7%3Js>p+kD#j<2On{16MAP@~p1;p*qDM`{J+lKov zbucvC7@C5H{m5`X<^u6yZK!Ae{-Jb#VJO+(Gqium?O#8Hm;DfadS$2we7{uUxcO;9gz#qz-JQaOEP@+{X&PP6dy}?rNlU!lIRhl9XELZqFq|4rnM9$xYjH- zn)OBsTu!Qqa2XG~jA~6>2D+o$$Z*-SX92UAYDQE)k&picWJaXGV%-|VvK1&f0&SCh zI%GWA8pZMqdJCrs!X7hQuw#v;hi05`HJdu*d1&?&I(uN*U;&jG_wjP>W*pA?rAj1{ zL01{=uIkpth4Fd2xnUFvbfs0^1z8iw1Lxfr3rEkbwJR%#i9`k|8qDEb<=`kfr%nZO-Gu(t|h5CoE4|DY|eU3oaUah z_c5exak-T1ONrA^uC=k$aGF4Eog6h6(hvZ(v};8UBT!S7^tN=q$p|qw`~y6f1`q?R zle?39>i2FxT)Ve;4@h%*cY^zHl0)vGJ5b)A>??^dqcw{HZ*Xceox0O<_8?8)OsNT+ zYE&T}3!L25)48RixELw~yX89L0?2o0J9GHermrwTebG0#aSGJLPuftnq-Ys=Gisx4 zKS5=dYKhj8zOzSZYL}?bUA!4EDU?B1|t2Rzu7k=*$e$Ngr2)REy(7&>b|5mEY=jiL(N7$`! zHku#%%*t|e<<5b^rgUK4rh$P?n>GzJHWdckrVRu9ke^u@C~h8@g^4}5xjtAQssYtW zuHCo;xpwE34An0Lz4q%OI$+)V(_xuu)ct}2$->zoffLrtfZUKU%K~P|gd+pymy>Y^ z%0XqqOWG9)T;~pyr?AS@-&gk1D_?)@8)zhQ_O!wJEo>gLSh!ZK7{Q*4nV}WD0@-V_ zBui-5bQgi0uR2T?(k)VR{M6HDJ^c&?alkva{S-g{T=MzC^L4E1E8!FPG=3A1{-h30 z+*==Q4$ZWn_T4E|_q4>1Hgk?TsNS7?7l%6&p)uIpA$xz~N?wYKQ|xgax;KO0uv$XW z+-vP|=Q%mO>FhSTowuXaNp#!MO5sAKlty{x=BtlGI3=zZFT2cLS_Z%71~YKqiz=R6 zJE-2Z@!D9^FnxGret6qZWv~j8joo`AJBQa1;DPIH%o9!l(C^>(4Vx-NS2;b>!hWB+ zU+x304iOyf!o{TUa9`dRz2Q%K59Um}`AqcY3(RVuQ5B-M@f45VX2&dnSIKSOhx4eD zf&ln=0ll@FJOs@CG<=5_gp_daeS7>yx65vVkI3P*;qc<9;6c@(vGvqzXy;R4HeN3d zFPm~@!l6QxZ+EwqZY7V#K2|I>prH)B=0TCN3^t!VZ8>E`&)a1luw^Ps@xF-61l{P` znou6G!}uR1?@{H(IyG-!n%Pn0$uvcxu2!NGvE#PeFpot#T|sn=V+7pEQ$4SVI5)0X zoYe@yEQK4yV8N&-%d->3(!`ym#%keovieu2PXn#-b{g=2pYhA;>8aI2rC#w}yaE{Q^{YyKrYwI`qM6T}u;%e)A;rn)U)$#Ue#yjGk{j;L z#7(Q7UUQ^G{5q^Xp^*pdri!Og1e6&OY*GkdHzaS*u(KR@(7b(+yA!?>i= z2H5>Ui*m0K8jHLtf;Uy~0N(p@k+F!~xHEox*@w9M@!aDC7;-xyH#9E%OIldRqj|t$ z!fx7qr}U6e+6J^LLg^KubPKt!;=tzlfwKX+1YY9p?53XOS|9oi~|DmIzc4O~< zX1Ta&IoVWLetuIg|NNZcat)ZAVrMCtc141B|9QOD5u~OJ#SyDeya~s9!!Csl=N0d8 zhiHb#CPHV5H%#eUMS*dWc#v2JMPgV6yAxdqB6|8_126jA$+U~S)vSJ~;}o7}B8)VVcY>KQh|uuRL)$rCU#CJ||fSYU8f(jxM`Os{rLS;TIMc7`b|?_+)xW&P|hf<>GJB4YzR5ZU1#2JFd0;ufAE7xOfL!kjcHW5R!qvBnfr zf%U;zlfH)!4fX8XH#EJkmttINZ(-l;-m__S`M2qP#i4!4P+@Ots4!UbZ+8yO0k|8` z#H(7?!+p87tOt(*V_T&Dl;SyXt)5XaY))V>PG24MyPWloCDjcpMm?XcQu75HSki!Kb#8%-loHr_OB~4Uf(HEP8CRsW<58u@iJ?1Z_V(t!iR6 z?l%@@x3^3qfjB=}8EIFV<>`q-V%Lq;>C=T%b-XQ}?g2(muNF(INvW{9hu-z#L<{(g z6abus6cR=i1l#Z#ez$CDjH~C+`3#rZz>UY3{8Zo^65mF!9{@blPGeP(5YEK6Icmti z0-bZou$&J5`kQZhllqdkO;o=0RYzRhx9%%SEX zIVXDi=vUy={(8lqc^{gDIxKJ&CVM_T(j|L)Og>ZVd_O{MkQ{tyvDb`GZ!i}c?HFes zF%bYl?Vx%mEnEtVD`pzCNsReT>YBNlD^y+)r+(#*V(AW?Dk1a>(7{g$pLZFH7Kff5 zC~g{<+O%P5)6yn_@umYyXK|U)5?z%YdzT7$TaVw{v9xK^j$~8s#*Ldcr5n%MgkLt| z{f!&lruF(2AFphhAE-kjuRo4G56uffX#eeO`v^-?fqqchJ zE-!V|o@=cTO7O$<)Gay0hI+%31;mEI;sKi>S%e0*kcGPxJOEgD)@Q&T-$c1g#!Vc=IP;>qwBPiW^S?B#mwEX$CPG> zVrH_qM{F=z8q_SWSE84M48$z=*9@>deZJZAXCM3V!Z;O6GzuWl`l<^HY;nna*xV}4 z9i{ld*)2gXG2VaKt2+?eZ?Ga_TUE~tYA!x0qjaX{kwYVeI94BRjZ6(M3_+k7S{Ur- zM8W3GbR-kv>s_sr{OhmTkGt{>bxxOea1 z;NE>2DI6Ny2HAXQXlA%B!fhJ>xWT7OE{}Wet+@>I2p!lh#_eaWBUxA3<$j(1F zi!8d2^_zI(E~{MXG&oJyIzhV3#t74T?wAjT#F^**uhIm+gsd5~$BN*L?Hqn(;)lpB?{OOq-u`vL;h z5k zfv+ja-@L{qXI9W_!>ky$?K_W7I)sM+3~42^xg}+N3>lvo+uv$$gMdEtDH$ zWuQ79w7IJcEL&{M^X!UZWe%ua9joE0IBdBcX%1toU~p(@u()}!y;-A#v%~X4edH$l zb_16idw;p-pvL+keK$s$Sf@t@&0TtM$1i}Qj(!pQRI=-4A`Ax#Ezncj=wUCXHJk8l ztHTwm@GuM%w)T-~Oz>brs!T9!w)GyK3xnZd?B|ge!xZ9~$~PX?nmFu@bO0t$*V0c$uw7Kr#W zAe=osi=G>Au3VY`ge~H2S~o5a#4LUtV*|b1I6pnMpjA(^n9^&Od(c8PCuT~m)pb(0 zS68d23#%m3?sOl4_;mf0J6Slj^JLGdQzxfR^#h#&%rmF^f!EMnXIB>?gyT`SCW_?= z46Pvz4h0+xH3b%@!eSsa(%|a>#nQpu+=d8ax`f-}W^De0jSVEGfQ;%v;Vy{aq5-HM zk!HhDi!}SW=M0H$iCL$O{ra14b!5SR`m>+?;upLzm}|^7{r->dzW3e{j$q+m1~~{l zrCHe;AAp!2GH24kJrrkHEI(WQ1mxFcw^G3kGESGlCHrdoR}R$or~48hZ~|Uk*_o_V zu;GI@j|;C1fC*UAhl#+RSj(seAutH`0}51DRM|>+4hX?P?KZ3W*A^%vyo@HE+eHenUtYc_Bz z+i`g-zlqK5g>8qhe(=!to^9K?M0lIqSUz_ju(tvFOyEu6LAz0hfH#w64gqfyyL$<| zs)RY>3=K-Mo%jBzB1%If4N+=Gu!}0=DTqHS%xy@AoK!VF!< zb)woP`jx-oZ1ih?_s!Seh*~!h-tQy}Ovk7*>#GUs9SS8VI)T@l&_v!iyGYerD|fKH z7GwR%L%oDw_h1juHZ`!t(`*EpdzZ){tbDQ8@+8@|m1OCf9OR-!%%LAOKPcON;l%ZZ zxyF;B!;3?`P_Bn2 z_pXCdfggLDd;0L}p1t#XdPyW6-d)&J#ap_&cMrsj#_sZ-8a|xejV>_3DF5!kDGcnl zFcnzCz&^L+5t$Jpzp$*0Cna9ku{!s>2C#i89l(z{J7D~n6MY=B=bD_!@yW5d(FKJW5SZbB^W;Pm3>kE{x;lBfd8$vWxN&Og zWY38cCz~eUIU7+$T`RVs)wCpiYq=qx6y=i(2|{S&kn^RAy!I)^y;<5tYG@P5XW^ zOhqeP7Wwg;LHvIE?H^rCf{elFe-uIP(7$QdC}YN?t*Q9>cSNF38GC0w6z@qQ~I6*=Y;%aGWw))ceG+dk;caz9lo=fqv=tjVn+#R}IDc*{F5VVu~lLt0{RXm`#^nt$n z3DgNMkI?}TIi}u6vf+;aAc(36MZX>58Hhm?MjIWDY8VvB;nE5s{I%k208VVm*EZP0d zUmHh8icD3KgW+;4wSQ;eI9fojz3}h`?M40xqySOu z^L*sN!ets{xG?8a`*>L-+0x&c4`%|>y53-&8_$kVexti7xw&#na%+0qp4-#g(p!^T z@bOLVMt4Kf0o-dLw^Z%?Do{~sJheglxaguMwBT0hF*StViVmEbN{n&p%(yX9joxsw z{U3SAb;`}X3E1reWU)!?!tO3J`r{vWAKPHUHlW+Vj5g%Pm1}TR5+QdLq`EQQ#yT8q zycwMvnHg?@Nhhm~)4jmq)9q8eK;=^lCwotvJb7~RL~{I`699-4$B!S!FUNPB=mCDW z!L4g2r%xei22xGjuC2}>G~PfWJVl@k#1Eid5tAlpyUCKN+96Vgq8{K56%49mgl#sX z43vpXONz@p>j>MF;vmF9);>lQ_YEKQJEP14g*>*o-6Er*09@4 z+LnauTQ=qfQ9YjB#2fbPY0+ZL%tY-`}7 zWxP${t-aW%&sFjM?#04FW3i9nKWq%%c5ZRwxicG^;Ml2<+lgaWz_H8SId4Q`Y>}vF zO$TzvqSHM!>PJ$TDf99+=c*_?R}HvX{Q}RCNMEpn>>Ar63XA$_?B$L_)J%Ef z&MP2y=282cw^{_BU855&La!k)d?ix)g#{=Mc!{YomRQAFORb78FL&p9YE@9HFke_a zj1j}ieT~Bvj26Z%dD+vAqwJq;&p_~9<#WuAQxrGMt&m!ae?(zfm}$Z?Z@?7C{Wg!J zEEXCpU)J*O=Xu`;8c0;rM;^ZFPmt>v9Me`YD%$LDh1EDrW(pFkbEH16q<64uFKD|< z&hm0Lo_kA;RgfA3MgpnHtrM;+sS2nUH!lrTHcb!p!b%>j?k(;Cqb}~=Gq<}R$P6sT zZ8W><0PDqFg`Ew&CA-Qyr||2WyQVO{KaCYT^^p{0+JQ{l_B#uTxr@td%G@0o?9&kz z70a#J@#oJ+Bs>N~7sL^y`Jr4RV-h@to=bDsz;|^lyTV}bq<_!YAu(9f_8nw8t~%)i zVeo0s@TEOn<34#7`&mQb)mx5 zzUUkV&44r=e&=y9T}%PoA1QxeoLhKTa;5=pz)Lc<}h_iFG8>o=Kk+ zlZMRA|D0rQSku+jDS&bh{wcL`jTd8L9v#?>;Wwz<4k|Zt@nyn}7I+-)mwkm-p_# zX3wdk){Uc0oya76qt&301PDWCx0Ea=E7hItUB%tI>br}(cDHs_g~tgDQK_(4tra;Z zBkL2O+Z7a%UcMr@)Q+=S^m^X|Cq>H*Ju#AUrk@ zA=&1!EH|N*6+X&qwoMl4mdl*6X)!7&&w^z9(=trPPCCWM=rgAfxl^?nSYm(}LQ|Kq zO_r+@v!xWW*}KaohIRwqAat=N4PISam&B8TNRs zg`UNQ#o2{|KHa;358MJT+&P=SkB|6=(uFd9EzIx3A9HwLKs~jwzNrSFP9=s{P%it& zaBspm^zioPr8E!;CS@N^2HhmIQag@p^I?9WVXzk-< ztIm*g+qncOvv*@WcI%Ao|i@4UMqk^zCxQ)zRX!KLNiiD-B-ZEPB}mMV}U zuc&Yal~4yQCq~ctJKuiub(^2&ot0lzvik+x0mEA>MW;0_^T72s-b%7#d>V9~ErQH$ z`{LB1&TySAYm3qvBjvUa3U$>=zvt67YIPZ^eo#zdIopP@iuCVf>sed2Y#HBz(=j&g zM5?Q}r>!-JnLdp7&-=l@fq}_Q2qq3Dduv4NX~1)3=j^WH&Rvb2gqQ@y{UO~-Z7<4gcSQ+3fr z7v^D_#z`knmKehxlPB1xCD>vrZHTx8&XB|)onQ8t|2NPr;xu7ehqy!JwrM+F|H|FTLYIjjpSSAP0P_yADYo=>EKc-*FfkmV!kD_piv5qGu!kaIEw)Ke~SoBZ_>g*@SuGTtdlfH z!Fxgfu(B-ZiY#cNvujlAxcwCWB5u3ufj2e@%G{nPmnH$uZws7T0O#)soF6c7-dKPf zQQuA#+ife7A}2uCCb}C~1q-~BP4D1?bm44#f0pA%8Y<)D*9?!X*T@zS zTia2@uVowNd~9E&G!Fwh5q<1y#UqHK7R>Gx#ue;pS^%84ViH4HEm_rc z=nQA5KN@y?V`l3mAh!7Ro8SI!TvJ9TJA}X)RP#(;G>VQS+XJIf!fbv)k!)Go)+_Hp ztg+vic6x9MIGrA-U|ylb9?c6UUN=#P#(v0?=`d4jfSE~xz-k}V>Y%j>b$|CexJy&o zw*q2b`+k8V2soh@Q#3w(ZC?E5jn-Ce^AWKyibXm^CXX5$QntRpqD}C7x_$Wf3K^WT z54-KnPOQd2Jx5rZm=YXV#DoEc3aW!()h&3@J@|IEcJYui<=k%xk&(WE|JUR5fi-gX0;!_La{@w^YWlc z-h^^LewB$ucEY?}9Vj=EJZD$m^greNYEy4094QLfO}VAvK=bZ5%Y}w@Al-y=uAr@9 z|7;u6_uDizurO2}tOCcY0P)7jJ~Hf+?nLi#!FNHJ?T+^!LtN?D@#?X{@$^{Xs5{m^ zS~#|Jw0P|3wqx6myAy@uGXU=*eQfjttC+mT2v@UI7wfLV!%l(Xq!gHvt#jw7YxRRk z0>j|CCBVcZS6>|w?1Tg*r za6;6i>49e-TluMD;JcZN$#yt;hM`8arAiy)71uUB90xY9hj#_MpM2sm6x%iQa6gu{ z^f8isJ_O}-SzYl$@^WSfmNVrhAu~6?O?H$ORLgj?=7YUOvK=*6WU3%jLlY;4gAA|_H`!zWJ$pmPhUY~xd_UUam6hD1K?bGR}((9A!@ac&18{n9$VZ%L=B_9>HCq1XJ z#HT%qkHHS4ww?vXNop*ZrUXZXdL@x0oto+tj$=%w`N;VH%0p?(TNt3bF3YA7>h(x7 zbvY156^qPs!cDKfyM42fe)?=mxa33>)q%1$Pxxs-~}j{;WHU#(FcHiaU5rmMj;6 z$8n(<4)nK0ra*r>hsdyTA@UajfqzMg`)inV{U&@w68KG6W$LHAq8pA|yTT>e2$vsK zy4=IR%`D1DLJJ!>e8hh@*(XuL?jghdkAVK#wsiYG;C%}8s(?uHdS^zfIpM|zsC_oR z8v*e>VHe^sOm zSi3_9SS$ni+Y?iz0+9c>U_Sxuzb4p!#9)7WZQCT_zPiwZwy-hZPpqDszh|z1TVOuG z-pV>GyqC_d!$ezYY#x2l6Ml!7D`$y#fwjRt~)+*K4+5i`rjCD^DLecBj}Nersah4 zCON(9EZr7N^1STM8L+DZ`a^cNP2=7q?*RYreE0iEzuT8H;oUk74&TP=Y+p`OKjsi^rY64p7yN;mAJDsS_q*`W^^F-uOd*A;5i?B^qDah}FZRqchbGbo`j)X@SS_)VL zcxAZD&jI)X*o50xIdJp@96hQ&?>vsXIi`N0LQvi1AX}Pe2B*pk=4gg*rK$>HUp_F#(OV*x1LgGgEmb-j23$?@9p`mvs)$Bykd z+DmwzInw(c(7F0v`AGe}UcC3-(vfvQiKD=3AoP(cP}&_`e+(ak!XKSEwjR`;s{FC^ zcppXhB$#E#$;EGI|YtoDW`NtJC zuqaBDZVa#|XvD0ZMl3CIbOLs8!K28o#o?Z$Ybj|?We;0PQ3N^PiaLlwNC`9Cp%oC@ zR-2(F{?C!6ckVWm5iZ0=jWn7Dmadu&hZ*hxFL^-==9DTAB;8@u3*RP;0XAHNXx+fD zVHv}Q1?)Czm#`1_^y(d}cT|Mj!0?H$3b`LFRqx=ybr~uZp_D-ovn$&L5 zaBo?I)>sCeU7wO{`7Px1B|D^cX3*h{Uxs1Fr|muv3!zhM|K_*ec=Oxe!9g~T&ap9@ z8@uIJZAlYJ_hzW+r5>kQktvxHsI!)Nhg&Kyrz=GYy;X3@3c?&EJk^W=vOmMOjNf7# zQe@L<8j}(nRJSE>3nfEfOygJqCb2x15KV0zi^S1UBBp`EX~FVmY?HW_P<{5ZeiH2N zI}aVa=HPzbwk3?_))YJxlJgns63&RUdn>$4T~|mMY7uOX(8$H`nr| zz~}}x=vH_33~U}~aWOzm;A|JrFu{f|sc|q4YBNTTTRA`SPdk7ahYfmibe}z&CN4)d zjU$)gvUc+MT`6E4><*(Vp2KDNJdsT+zjjctY;-ycuo*7@n+VL-H{{5^Av1c`%iR_I z2F>oO1jw9zGQGBV-L;MDddW=d*SD^#1DA`}fJ@`Ip_nIE;{OmqHOYKUbha6JgJ&u^ z4_i>pJK(?unS=)!p9pN4y&Z*f`ZAfc1gVs)$%{LtkY)$?wp;(*t#rW=sGxLCeC8?k z-Cj=U$%WPO_^jzdTVrdNw*@*~(+Zwx?An{X(8rQ&hLnF!JjE@a9{7WcvpM=pX-t01bTp<*$Ejyqep`@oy%v zHeH>C4!XMjQ8?s=(5~Jmzdz>{5TTRVbS|B5EzB+Up!U__!Bzn;RUsIMm67IyQ(OWx zD=?1ghSL$z+0*G&pBmQ;c7W&Kl22pg>lZ(hh8_s@_q>Sy21}n`JZd63gKA&;5^Zpg z&$*o1zvuDR`8FS%_$;|-4SddmYLro>qA&7t%k`|;WU1y4!0z@UIyU8ae6BJ%-oQ4! zDX{4p(inwPMCJyN`6O`pMd9*&r77VuBWR6<)_i-emn^S7yAF5@Oqe}1Q<(no%sD(Z zKo*^z=Ja~J=RfE{!EVkbbA5a~UKp)PC4k-p&`X#5FGfdkv*8%hN8{tbU$?b% zUU0i(B1fK`M_^9~$ObZ=tksX=trik81DauSvk-HcF^Se8owf~G^86GS(%gsd`xx?= zerlUxa-3YmIV6%ZO^)M=ZjzVTr~vcpS@8t|n@-*lNK)-328$I5gzVaf9F-O}?HsWPo5)Qqko3IW_{UqM?T74DQ=OZ~Ov_@a4n8H1Qh5(TvroW>O#T zgkVpTO&@1w9Lw*-k*kBP&25Cw7B=>ryK!TBZem%<8eYna3+b*l4C|@o^`gWK+%EO( zSlW?b?_R>O2Yh3f7I*YuaIuMHJv(-kF*^cC-mwm!;eT`ZD8cV9?U-GHEWWhVT&`gR z#c_9T0}^<3s172{B|h9GkYEpAg3)bab@}~9zB<(JKvd1bSqramWVFu5_iffEM!fcM zbNSpFX5)y_o*;m0$&g*J8Hqj~AR3B(y?TJy?n>Y=;5xmg z_Q@Wg-NLo?Pu8wUuTF%|$rTmo+}VwiEwsL7y8(r;qdim}~D9-UT+lo4mLC z-NGMty}L{T{oZ?XM+#8ADRH-swgU>g6C0FLLv-q7g5_q(Y8_OWtKuBI?ezpL!WPE9 z>gNcyBC*8KR}PPT%f2RGW=?J2pT*;cz0B?T^5;zE4tPwy%$%Ct*Cm~MvnAC!bna+# zbB&6H%LT}O@=JgmobHIoW_H8Aw`n%s5?Y+WRbYFaj9}-$ z_%SVjeu(n6soVcH2gV>NVUR0Y+L0`Ku512d-I+dOT9W3WQZ69A4evJY{a z(}Xq1HieS}!{T2{N$Q`do2#t~FbnnQhHr*N&mCn=Z^eg10@> zWqiHDOcQSl(}gK6Myuo3`t*7pEWAxE@Oh}tRAEgK`OgZY6!ocR;ngr>J z_L$*9Ljbhf@~>0*6bar?IF_WCyVLX2N4k}@+VH9@g!3AhD=8&(VRLu{9-GB$ zuD7pmgJg!yz=AV0Y*fvhgw5!oC&(sXCmx)u0B4N!Z`?F5d`^JRNKDoiH*h?GT@0rZ z<|+R}o!;44=>b)qUY=X(1(+=z!WO+HyfyIF!dnxAifCo|q1#bL`lYZv-Ej_Z4=*YH zv}5~DU^@QIEu!`EQVr5YFLiG>&<3-vLCPUo^Y)npn}2N4NSG$--K)gEA>iJ z9)zZ~y9CSFBgw`^ksk*Pd$_J%RlB-)&DAT{^q{Y(U7cQ)e!^XudZc##=Bf&ix{U23 zrQk#WsUIW30Do3dV@k&(bvEkd=M*7l@Y^iSk8LQR8b_U3qYeqkj=4q8vK?lA7ZCU} zotkU^JFaudjeD&L)o2GPaO3(@2;3Eg$cfVokz=79wunw)5gz97ksm^=v5naS2;0et zI`U<;qdg#owIfsS%>$8>cWZwvynD|d%kNhISpEMQdk-+V&htw1sp_smHvkf%WJw-t zJR^J8W3N5?*xt3r-d)=}GrRNbSj?g=2PKjql_=S}mb~+fMF54W|K3}vtGkgC2?j9d z9A!}wDUu?oL}f7{=NyC@=aXW0C3X+Fw~hOS$FpF%lKND(&26y+>zwmR9? zH2V^JI~u^a#7*tumKbkgKkK(c#HQVk<6V?IWO(f)VaK*j#%sPVWL^O>zX~$nYsh>} z<8ni0+-4PaJypufpfvsIiK%xRk(=Zn@HhJ~l}%R2?$zzzomxLRu7BTdcBdYhO`Zly z3#auUhwO|qT=kPv+}2N4INQEDHJO3%VQPe5BAu=-1J0pUVR`ohDzy_JoI)lTipz|4 zl{@^^Tg+(lqK8Gc?K}Cb6(Ag$Te4$0h-Q+bg1T&ni}ML60#u34hT*dZqj?a`1LYUp zeDf`q*HN{?DIgG1dcaufFi~_NjTKiE4L2G&$Uxl9@1pUCe^L^sN6Vu>Gwh5YBf&Eo zrfLS{0qv)@64e_8sH%LvtQi^(5i`8k*0A^74@|@n!$Q=6Wr9v zSO(?Nr0uIPEJSX{a2@v`iQ5Y7aQ-`nE;JAhX$ybDM7)?F7lx9Ie6=-MrCn#_23Gi#(s+X=?Ajyy{;8nwxbjpfp|TeMv3Uf;<25-$@@i+{o)9j48A zW<5|yvm!*&WQELtX&Yml!?bK?4~suS_2F@`uRnoAD43pYJpc5kfBf9@78vs;?H%Sk zo3ee9N?OywZD(_Fd%g_yAyBLLTqk-nQFF4d3U2vyb!xgZ)n@Ls&{@Z)3!M@9)4FTe zhR!8;jcCi>>mZ7Ag2FwF5XY9zRdE6K)7AvW*>f1v2uAX6ylUc~ zjNLp=61zylF+rsSQ|IXgRRLhU&oRNLG`BvLe;Z!NcV+!Ahs)r|1t zo4qxo4A-UbPS<6Mm|d2f)dsQs_!;8qrg_VsR&SRy?|0@j(Noo0c;TW(8L!QdDFe1D z=$R!nE07vG50A;hqZrW!my6yJuvJ2rGT#=G&;~s$p%wdPQT}V2wBki{jF7n=75|rE zVe2AJg#@vaPl3pvX@l4sKiBzec1iM?6ogJdXq_6F*wC-K=^mh6bA5P$$wrmOZ6yfW@)`V-$BS$VVuVjtu2m7|je+H(MH@cr1t@lnd`;{k0P z%zwH1%FBtGy)sa{No6hlyY*(;$k4xomDQ~X*Xr$RsFmcctx#518(^CNQ~9@bFgg1qC?9nc=Vixgs>3g4f(F%*@X0*G} zKM##2YQcC*Ygv`G4ubIr9C+MsPqYVDOjZX#blb*w38Hn9IuEltqs5^yfWGFEIXHWp zHM;iEVQ72r9vg*X=uG*Xw^}Q>%rOS`6cZ<&c>M9N&+?hAe$InnE(3{k-h#CK zAIkOfCe8hkZ&S2uX>m&ta(ISD@!I4vXsn>suqAYEbtP`ofzLMW=-gg90;R!Vr;5(r z=#YHK43#ejm5+nU*BdHtXxwI~Tr+!=?Q0aWtQkxRIGm9d5j(cm^HGLI$Fb2ObgF(neAM-T#m0=v{w0;8Mw^8m^XBR z%f2UCQ42r{9+le3wQ$oD(ZcO?YjtMZw5jWFSZJ-;5tkvQ59ez5<4->6xU55Al^Ani zCRd?3*MG~%8kAbnF*{iH#xrD|lI&4!LDuEOn z%0|4Xf*CL7hnj`^9l8v1Kl{Z+eJapd;^z0LFjG}_Ig@##&24dUiZMi^TjRlt6k-eRmDBw|p_?AM`<+CQPM9zq=lM6d> zokCN5*dD0_E6P(V%CqyjnheloDsDJC)A(CWyzMgygwumJWb0e6X6WVZ6J4NxaCE-# z-cTN_UwNc{_%NVzBpe>&gMFGDuJGjuLTE4yau@NT+e;F=OmNfKy>|EF9eB52kcK8mP8X6hs-=+)suP2$iH!Lq zn#QeaJwZsmVRKr9jdu|7meF$;)-;jY;-H{GjzI5PWNj4 zWLCG0&d>Gq+u#GLg8o!}iVB{w_d3xn@d2%SXS;912ZGHk&1-dpbfdl*Zb7xl$nh?< zdS+b;8U&Qtko)xY>T9nDH4|!HfQt4jy}w%wVWTmG^^LoYA#^dedxQlllYLZ=%HZ;e zN`D!*oB4b_r_H4k<5Y~g2Kx}MCLgK2xh0Gc;I2N(e02al=uYBmOpjoHC(BcyJ~PQY ziP1FakFa(zh6M88{MP?q&525ECj?o9;J6;;&}JWi8H#V z+a!VZ%HE2B^(Lgt>TFN!QI+)_;$_t}YkQnXvwF>>jSbR?vmiF8J;5;DA23X}&n;V} zK!FD9HdkH&#%oM|drb{my%x8-y-qD&YSj;ivPk&+#02ZmAJAO zz7(wzC)jLhagAAlbgB}!h@{qqSK=a`Fi$hHV;`5PrY@P9oh@WmDIUdhhvr+~>GFBr zQwtxp6HZi8BYP)YDpc8EbMndTQ{7Kr_L=sltDpLG@~HxllZ(Q_fDf#SR@47KsuDb} zR^(cnnyB4LW}kIY+vaq&YL&cFaX^-cm{;NDklE~%S&qn;Y5_%++()4OUS5ai=C!*l zKBukJo&_heEF=Hxag%b?^ye*FEigHlP@YnYcd5nu2FTsZdzV!ehUl*+ddNU)>}YE8 z&WQ}E985`$b-W6nJW@Fvj&#A^!$;D?l|#wlu|st6g3E`(;X2bs_>&!;qmPFV9a?vI zj<6Zb?(lP~j?{qlBUJ2zW4+^@6K(48IW%$UExaa3ZX%+G2**;;K_IJJ>kh}EH)fkC zTS7pwBos3|H^dfqtjWdJ%y(j(*m3Fcso5{1Wz) zV9@KGSg)IlU4q`&KD}3YZxhP3)#XmMC%)C}QbfMJiP{df_RM$L%g)=VXKCfE?pyw3 z*7}|?J4H%Ul$vA(iS)-}9InJ}6sE=zmsKWDSkz3_I0-|3NAwn6;7+qcB`!ZZVG@1! z_0$npeSgB-Yok!U+5mS=;~@jw%5)cX+|BEBvO5?ROPijUV_-Tl@g&%~oZF`UoE{rT zuMd%%$7lXUzn3Xr&us--2*BGxP){tDpHN{ZGhnw>G-Ktk+xT0?rFhS@!LDa`tiDz; zlH1guo?Ts2UYqLeQE*qFSq;T5_qGRLTh*bRjcrYnoX@_)Q?(|0e_6=;n5Ds=CNODE zbrim3Rd3tQp*FF=9uBe+^df#M7j89n%{-kXYqA#8?i7Rfdc7Vq-8-5yT#NcPfk!IY zSTuMNc34$MiTMj0zY6_B3^E_OfLrw%kf4yx{nobd*Shb-_N&g0}Z z)b0$mJ3F&~#^~v%OYaT{-92IzUQW}wKdQ2zH{G17fV=%QQ>)i1431Gf&ZVHsVdbhf zS1w;U$1aUkE2k*2du!UXx}`v?S`Yl_nUtuQ#`1WuJFj``zR1G)#GI8%TG*I1I%J5f zN<>6t{XDXYUUqN90!d~dE45CpaTmvBTG2~w;&~@Td?N4T(NG?tdS`&j-Y1o77&ie(eEDjgAhsCb-CMZL}USq|s^#r&99hsS9>!L-Aie;NC zF<GA3b;@>H@bRg-Syx#m-c%v1OG~h*3$64K1H-BrU9sPdxW=V`Q z3R_5G#8Qn-Xw0r_Z7t;EOJZFc2ZsA{@b!?7FDVS^VQ$O{TdQkhZVWk4b*-Ru8(Wro zt<-GgQ2Hx}Jl<^wdq5XTwQX1mM4H(yG-0r2XR2Glj;-`2yVXv&jmJTzomw^lO~VjP zUDqbBP3{htK*Bb$FvnBi6lFU%o{L&`HlBVb#|F@oyAKy`KFD+a0o*S>;(+*S>Xr#}LkPW7w3{<2;T=h6fR2Kw{15caKH9;kK2GsHJ?`pWrJHeE-J9rlQ5X_RTSmqpW2a=nQrfNp z&T@KA3ujq{Z7~r1-KJq%X$#20U2XphoEJO;Vhd+kQLthxi7VLNfoxlza4xSTl;$=C znhv`6}%C~`UnV%f-!>Uk*})Z>VI=@8I0B0TOJ3~qTRBE6)Qu= zW$XfFz3;eX4aS=Y-tV6hO)RUcD5z$0}okQ8>`wP@pZi|I#!$~zSPvL0>y*1+Ce`K zYjOo!Ow^>pyucpTwV$_LlX~PAP92K}EAdL^3O03ZlH)9=qT(tih}g+FoWX{O-9Dpt z`dk60mc6FtOfcMLgdJ)C>1$5PBeu$xTs8^#)lAq~&Aj<8x3IFtTw4vq&6snmYsPL$ z&3BoHU|Bm&`B}+01g6^CxA|0KaVde7$>Xjo_^5AbE^b&+UAbbga*Uk4;kZlTZRPLN zH5n~kG^hjM@Pl}ETv`CQx~LT@o1d>>(Zp~;BQ9c}OlC&Ruy4>pjj=dp;GIEu^hQiH z!KQZNrWG9_+*T0Ros^Os!ohHMaOu`s+jR36(Xwl=dw)>@;Z-X^F&th&{qx{MRv`<- zRUT)6c=r>ReX{$B?BeQ0fOfJlxlo{;SUt?zD#LcnahogcC9%tOaf5S>+RFvE?rdu- zL~3dTfZKv&)-b@1&dTF*D9P0Mr2ugMTg4tBdNDc{6WyOhU9s#Tq@z?6hlTSZFd(Kr(=Mzl~0@ibdMd+ zj`|sxW^!05FOSVTLtv+v&3)?-kv##~Q;@v_tk?NX`9p7jrs=e)n7d>sGFWBx z_zA(g&dpRDycKKauN%CNvKS^iW<`&%TV#gs?S2Iy2jf@t=5(RVTz+Y9gpcj+2wy6` zH?OCA`GOC!4b*m!-%hc6^&NdbBdpG7Jo{Vd=N>@AZnVFq->dd}9TeTVtQ6@tfmBs6 zl{X90W$Nw9XPQ*wG{%f1V#|n3?8!1R+U>C=`Q+nlb zGm0-u7{NwDW3G~J%@+R=+@_GMPDexw*z3@Qnl0%)2K}Ct^$kyTtyI80d$fG1u+>Ls zJ^d`)ypLIitNAqOVB?#kF(oAf68D( z|Mux4t4?R|PU4iNlXTEVuJhbs_6*z;P}cPS?^(mX}A?e-fD{O2sLaZFZfIJnt8X?nmC3Z|gDE;>uSV|{){V`#t zuB>h%;WD}A#WV?!bJKurn5~8tpn(1Z=@biFY9c;lS8QKuCW|= zI95Fhj*n1^XGq)KLvtOth1TtZ@4#6-c;Fx)#e02t@W7aT#k+8@d0_d$cNwx5aBo1L z9;zJf9hwH#P5d6Gyu{N6)!WDBA3uH^0s)0U2}tPBPF}6O#-MWa?JHdf>p zIo)u4u?jBL@XCnTNWo>Q(XE&_IjLq~9Tqi!_*kg}kU~gXnx2TT<^>m!;_$KW&|fW0 zT&Kh-6R8=YP)iD`eB|SuiuXzscN6-WO;PxSLwdr8Ds?#qi{d>ho6hxeeHb{)0Xrtn zsFq@_WIb8}Z12&sZPgQJg)B~&mQ2G_twjqCh9-k7jx=r6I#Y72T4$pCncXwmr!#nr z@>$Ib?degp#A#F@OG6|BHL0)SgjYuCbyv=ztXB0s&CI^miav|!AR}&j+^$+~C-toW zp}h)ES7a-zt5$aKq$#$;nighs3o+7BIur>pH=>!8MnY^HeZi}30?1UbO)6N#a$9qj zhR~vOniw^s!iJVuUaqvAu4(zH)Mg*{_5cBNj6j-XT8fA{LfdwG)zyyBRztmih|op! zr#MrQrk#&+N)@7cc0qb!cj2asIt$YavkQ{*Q!B7_9FbMn!`yd{%3f^P^6+U)G5sA? z#JDG+>nN^(l=Ajvw&y5jl-Y*Me{4+8%x8C0jO~?y*(Rl_%yxl1Cw<|9BD5}jTrFD6 zsiDr+A?d2Kb)H-IoSKU4jR{F`yl0yx3&}~>4=A%I)@Tq>Yjr>)uMq`1ax}$n?i{MC zjy`m#cW@L)KG-=>*`FO4rGng_9JqOZ9XvPyD(?>mM)n`rzvjS*VRY+2a&Ux)hl7;^ zlLxDZ4lX}bqxL?GdENDbJ3ETYtztVpF~=(HSE#f(CFJ$_9O(51jXPFs2ipR2R8~yv zv`!uqGgzjy33SP7{bL6~Jhj>xH?X>a6oa1E)w79RnZl@@!|G<7v)8!iLB zjD*Q(-dc|bhyw^jr8yw0$Tmb4B;#ecdVUo7!XVkkkC`8x7upDw)>>_t{L@%zyCsc+ zuEE~1dn?a}YY>@%GW+37Q~EDGb5VAN^2WpxD8qTo9hwmdQ~E;k-muno4ZSF})ubjr zI>RUMQafw3NQ8CXNOWea_v7mrIG(Qbl@4je#KRGR&I2LzT_E(&8v6~Q*EYUw@Z6mk zurqUvS-02e)@->lpt{TK z)a*gdbwF1SQ=`)?y1?*niXFuD#Oi5vSxa0G*0!Z|c$2_Rj?IOzKKt+?%}M!`S&Bty z%;#?p&1*~Pn6Mtr>v$%%fir7=M$6U}SFp-0mgCC$2ap`^y62wzH1Zq$NaggSl+&iI zQ%ofeGxw=WuCrQCJ+7q>a&~?9*XsuUTWeUTTXKiWHXc z-9^ny!xtM$(ikj@GqOC9fwphozKx}6WRYc=PX(pn-xj1#C41~qmLj4L>(DD{l||Ng zV|F!sP_5H+PMckALn;&mXQc_5-HMcs{#VvK9Sv(QrIqhdDXk4wrL@=5E~UF+{b}1+ zh0GUuwL{?IT=|LPM-9jGsJHiaDa~t|xeZA1NST?P|3)2$?9bleC9l)H z@4GR-;|7g%{!sF<hl)a_oN?_tjShEBI;l@-lgL&e-k>HlOoGGA#dH5-EB$!=S1#ss5ylb6`x zqMB9M;exSf-w^C3fghn7;wmhG<`=F@1 zLh3=Yr_s)b?)dlr6TLF3RNg9|Ye$TDt~&b=zqtdt5M94?%$zx-t0}$Rnuf?$r8HI; zD^hLY9Ru{#o;JYDfE{Fi9bg|8+wP1D+j-tqZV%0IJFX+D=sCET3T{HSc2JichHX0f z<6l>$6TzK5wWzr7{}Zl?do1v6o9k_MN!;X@gn}PAx6LhbKNmR$zQgKM9o%hef_(*s ziXk#g$un`);!1=lS_v&@q93v_EB>lfmu~UHW*D-y2^2r&x>+A zKMIMoQ1sFT_^f=3S32O^WR)j$&d2`>dF6<0`Wt9-)H3((1`B~W=I`T*KX}OZ^MA4( zo!SgBeNnQwkCKGe$-?b^b z`cATJuHDNw6nPuxBaA{9o&AU=;=?Vv%UaX@WdnrwwyOAqA}AqGo{)lSZqR8oshviH z@{eDxNv1Be&&K{=n0WiF^V3=2?^$wzKWnAv>Q)hN;BQ@wvt@P%e>2P#2Eh*1cr*)? z`+k1?Z(UDpI3D>x0Mp^$vu_q0MmLpr{?Nn8$I_3t&+lDOmo|Oj1=)p_3(^ZGF6f+} zU^>@XSWtoRU}MMxj0)U^&`vfecDld?O!Uc*8dm3PZ19?4o|oKni9o18vTfMxR7aRW z>Uule*aY`Q=ruX|LB|Uq5ps7tW4@cFRDcT(^jgm)jc z_QM}jA6aIuu+-_K_0*h5!EcHtd6{p%y2lt{6P=gnA?`@{VNS{gE+7x_PryukCKb z7wwUUkNnsF8vZHyVsdG9(WM=veg02&>n=(zO(Jpd_01jvcW|9RYkTV!McUm}qFMZh zvfQ7wL+Q}2zTr{sw z?L!?uFX5yW=I~g)D@8;}2!MfJrN7rWS2)5{6@jOHfN0pw2+v zsZm9Q84@&@989JIWk;+fZ-VFuDLMpwgw7s}L;K+*htUN(7^nHk3KJ75%eIq?58O8K zc~&9}lT2Hd%3oWB(lC_yog*j|ucL4{?Nft?@?88ZKR!R7Bntg-C(gKb0V@~!{aCJ< zsrX^P*$j^0PE#EHGP~oT9=&dm5Y>RLq~0@oj0ZzMq)0UP{qhleIeCb&-xMmbL) z8vU@c1RraEd~kl{g4O4DK0eCVUkVS`Oe#noXhKnmG9 z(Q z8Aa$dzHFMorpEI|5o!`6*x_rE3-AP{WUeqOuae%MH91_hhR>a)fH^VoO4{K*X%?se zggd9w1q2}Z12YvlP18w5$=mH}2bPLAkakD)x2vZdtk)?zbjV5IwcP!D7U>5*@PX4$ z=gk~~#0I;$Lr`c26)LeYV8T#8e54UA`~vigxKn=GNnsL12j62(R({1!UfWi42jAS& z@*vh>{62zyf%%MfyZ7ER)sy+KQg`0wW&>I68o(zg#tut1fCxvgAWxuZ@UTf^hm}E* zI+pxX`-`KLK$o_^Sh+M6;v1>;^{bqZBrXe-L`u7Divd5#Z+zB*_AVQIOa0^D_=aW} zSks5c?V?Ly!U5D(3l!-0)Rf9NK|f0psv4Dpi)UE)Y|AC+FJgM*UBs52)Ht9p_nO^{HvpQut+MsynT~NX_m@Y#MNa5CPd+$qZb5 z>|k2)=r+@WmrpgPubCR>D}7^XYV|a6f9wN#F$wJ}a*q?Sx<*TqB zT*xd0kywKOiNiyucjND)BiK||vk|-oya|e+8W4)$sl7XuzcMQU00{So2PzLH4L zbI;nnE!2b&_`np_Lb7jkKYl__sR1tb1MP#!p^S$1mWc!5M0mN0^Ut|uO5?!?3>D@3 z%PUYCFQhdqyEqJ_Ob0ahBTU&;*PIN%22Mf-ycGjwNo)Yph)4=+gbU;=!c>8LHCRV_ zv5G4V% zHknp7T=Cjzz($>1UeA$VQwFH0y)m8F8gB&G#7u%FPeK6nnfMFh%NkJUNAE~>I6Wk= z|7QdHm5ogX_O~@&GO*9c)KzGxrhw-!uBfEXPBmG{&|6skNZL%+fbU>@a&=lGWdtF& zgLwE%Z)1F^k0dchfPAR|nC;+wMhHJ617LxAjTYD7c)702mn)#B8F3z|7r^`AnDC)r zG`ZE9i=)pv3`<>-7xjPdXHR&JS!%pWCxw_B-d?AG6k>zziRKBYs?U#fR11<-_2KViJ6}`=*E??28gf*>aF60Hipd-{D z#k-lKE*iAIDrUod&RUuz$$B6_ zc>pW4!ujtl!@O1aZV-eIaeS=7y!-)<%{ePQvwcQ5y@jVg22icg=HFh%Q3?qKe%mJ~ z=yIsArbf9W7zTy86=>v4l`PG=71H=~SY47m`;cc2+T%A8iRRC3QzJ$+=c*`DT{Ou# z0Po-~``Yf{^MnI`I2wTabfSaJ@X*Tb*qlTA!7gVI7-wClQPMqp1m+;A2QOht4RJ6y zKmh;!pj?s;5&iS@0O@ZV6E`cTe_>qKv(*96-&;qE7@+6$y=Pty0xR6XUpYX8VQ4HD zuv9hBpC<|X%LdXE=%07pdF#Bn2)`{~n8M^*lYmwD*=Aoz1lED)B0;z}fd8!rk_W2~ zJs2Juq3~Ju@LY)nSPKXP>4WJ5&HKZB$-Q%p0o)~pG~CfBgaOMb=jG6K*T!uzw-1U~ z6eK_mNJjZs2&_$BM(u~HgH)opI-q^WOe|ZZ-T_ju0MEF358m(2k_U!~g2)2YabT;~ z^?{j_X~fuAx*U!}SBR(pllid{bPzz)2-3@1%=*vPWn}jItEX1ASJt(LSE4#qmIq{k zY=7OX01&>ymLO#y>>WWDnA&sw?#ixZ+@^QW1D(J?Zo9es6L`WE@Pxo4D|-fe>(UJN z?d@YH)RafqpF$5(LW1E)I2!N{TF`@cnQtI|pt{)!LSp=YSuMg0>NOn`29$J7F0lD= zRG4-lSd?G}LEu$bD@qGesSnR>16fa3&&m=wXS`Lal0{E!q>*i&?4D)0zz%4MY61Ev z`{{-)fXLtwRaj%wp$)!;-;P-cqV3m_N0tz_4f1TeS7a_dXdYw_`Z&ZK& z#>$^p->{4v1AM^8@JeII4{~Y1RGeb#wfbt8(F77$^fH+UQ;PrN~5zP_PExoQp;hWfDk~hS(%H2nh%0X3&L>HJF4W9UJrj?K~*r@MR+o zN*8QtY&X(i=0V!QJeWWi7-6@WmSo>UkqR0(VNHrF(4BU8skYIK4T37jgE^%iK`M>)`P)q>S|ZR*!g2pNb^ zxL^>@ZCZ<7lgt);0=UWL0yhb0*Eg3y{%6S~$XoPOaQOf*1cT4B-)clj&L@2I7qXLW zwCuCmWwpu5B*^*1`t@8WkxzV>O%*ZiCOK+Do8Unt1MAwCbcTs$TvA^WNykN{3?LOSOuOYRuV7hV#um_5aD+`#6>kr-a zat@)KfR3q(mI8uX%Q&{Zs9YI@bwo0AhL4V)rmrxmQ>Bq7c(5QmuT`FVip zvJMo0Q|?x!rU3*yY0akQpkEjTU^bo!0PYT`>AwC^6RyI?Yc}aET-aPV91L$u(fol} z{TC4eTaZ-$LjsU909dXv1gZhW;GOA~%m0D__>Laisx3$0yEz2lSDXUGB%w(FrU9^} zhdaYv&AY=rt$R}#K=pz9+YiiReLTpGcMtX-Nbb+>gC5+|qU;~LGuHj#wuVHU5*t1>-={4(?uQFGQO9K|auB>aANdINKXd#I^kobLy7goX2=wI&B+P|PKzzm+ zw%rrxt{RX<&9sb?1J(TpQmg-~d-itsjBwRX@16sI0W7;8+EurYyVBiteZ6Z}fB>x6 zJ=d_GD_r>BF`b~cSKh$@*v|m`lrkbPR91lBqAY$7ZTALv5%J9-_<6}8aKz^fh#}(J zCTe@AxUUsuIphxwf+!Kqfc#Q?&>ey(3dE>D6a{={Y@Q#C{QwIewSBIz2)rY}6jHX9c1s zaGxg!3uQpkz*!!rjq@01ApS5=8@` zNmnH`b{t4}ata^#$Mq?Jg6zC7+yjzCUCIgjoD&APd5P=n~NCY&v$B%@Wf8Kc-K98teN(^8g zfFgM-R*@L6DlBjRE9DKf`wq^5H$!adq9FBc|E> z9>{>y1$DGK8PE(LV*^hhooTkR22@z@zLEn(Y&}kcXvXD%i59lKW4pR$AjPm^Z5il^ zb6L-b2YTP$+hP+5yDB@wj)wEtNCIL^K&!e$1N@L8Xn^|t7%s0AEU6bUS2lT{BtbDJ zZR-~I49w4prh&^@aeOI?E=iTBdL*Bu zgXUz9TQaEocXYDWLp(I)7{VUMMW&<~u`^bVBE*s|kbRJdI&7f#K*tEDF<9W#K_{t) zp?5HA&OH4GG$2^Kz|yk$#GWW17=OsuaNb8~T`H!L4ebMJL|xUo(s>SGM^QmgVHiDR zo4jTfp*Q?{67gRfIBYWeScfb{jSz0H-=Vtj&g8Dv-RV8qy=(7l-<#eO?rz-$ zvyedG(E--h&?d-zg1AAtJr%`Mc~oVu0J7(F!Bi~M35;X zM&_{35JsB`wX$!6A|zJCx@!Oa{p!Wkz+ht;Cawg=0jIAFd`ex% zLU$RR?|})4M~Gw{4u=}%&z4yQ&pNLMf4iv&TiAYK6)$2pAS2As5iG1FT48DLlL-ki zYTzviwjq1N?cGDm;kG}S88(PC`)XY_MGR3ayDTNBNU{q@0jR*iY+@CmZ!rK`5*W8i zt6@UafP;648jwJJv&k4-ajYgY``}!p4^tWuT0{$aOqS{$l=meb@%4g7e7~{Rctna| z(6?bSebENCn%e>UZm6_2a$C)9k{it*c7qG>F|=S0Ef!geQ|soK$<^XvqoNHQHyafK zK1Cs*X9RKh-L?aZ+Zwsm#>L7D9|)%_OPHM1f*K6l4#S5|u`YyMBZ!fLLLo4Tpondi zSV584a>v0>ii?5noE2Ch=8nTmi9jiClL)Zc)Ou*7AeRXKOj)e^HOt4F5sVhZh5fXp zYm67Ls9h^l?~UaPoEn6!&27o{up`|$s>{B&tGP4XF?Tx@V5Bu)g^Gq4-YJX zKx^U+jI5eu!ZR1ofWwqB{}j)aPdRr<_iHosqnMOW)Wixq+i;>wb|LY@ne@1fhgBw4 z46q;u9geF^NE#4y)Vx3v20Gt;EEi)XcIEnlPNIPTS(Ab+hLXO}WXyn%^n)P8;TFSj zR30zLr&HS5?Xw+*Tww4~1Gd|XAeh473_;f$Pp7u{VZ^{hW82*6c0TnANyf2$yyn_) z-2xawt};LoZV9)xZVR^uREG4f?%h-ORPVkgy?ca;GTfEk*}8*o-PXJ{xupT2KxoFI zK!x%Q!H^p$yHZRsi-Kv{L~t=7FP&64!Sb{qQ4^$5nVz6gZFIk~DoZ|sMqB-(d0y`= z;sgafxI{U_@ag$+%7DcT!@{wA_)qwFlU{^6Y62yPa)$B{Tu#u*NE{u=3JnbXNj5as zr|Z(S!Hy#Aa++{Q^B@N+rWJHW!fH-u`}%vcJ-ywdLh{b8>dswjcAlaVK*FHC>+h)P zGbn#$XR>2~-@Ai5^xYj{XU!fMc2;(*gGbcFBKX+cxe~sR>>3qONOw26jmnDX?|~s? zYIR8HWyoL$qtxEuV$E)N@s)6eW-EDr$8jfYadg2@n) zsZ524#>1=ufFu(vn!wJ93?X@S=setQX;z}F1x3hb0OlOwk7tmCxSiS&@h(JIUduWc zAPF(BXzFX&J?zt@iT2~m1qoV>-P9{jOcf;Z4p>Qx9 zXuvI$KXlQ7XIn3fw&v(E#2BJYPD7?GW)ZmX@ExhO^n;bNh>w3=@h+@iF$9+$sMy31 zN^^Z}zqVAud7{_4f^-3y61S-=#M$-@M_`jF+=fUI;^kv5oNZ{XJy0@fFag6DB-BSNY-UC+GPM-5DXaPWDT2d?ARYgL*9Zk^Uhv(>z^Rk!cr zjv28?ldAlRd6`v05*~0M_*vr@E$TqLWg{21=Y>LbNY1XGbIv*Eo=fEx&ikc8cQAtC zE=2fnBkB&bWrvGnE}U%AC3&V{*ym`9uj>wl2f?pnr5c$A=(g{{+JR^24wh;#hH)cI zTK3%kF5!V(gRT#w7@BZkuAFfUPLfd1Lhi_sZpc}N5)M%3@Z#u8FKyYJYzbS_ZR1+I zylvZ_Y-?>zw~TH^Itwp0@<@%$vKUxUJELb7@<@#(X`^bUG>xy@`{_RytG(k6(;5__ z(OT6;50|y@j1r169Z1c1-6z+9MaibFEu9_xVikOmV^}mSO2cs{*ESBv7}^fQ!{9X; zaAD3dW=u0ESO%{rY7&}~SO!fg=Z2^@NNSkt>a_w4YEcl?P)Rz4O*Zg})oleA+Sm@g z&Zu-*lh&*whMq<&tpV5ARAdXu;LV91ZpAg6)0A>dW0%+h!2=z)II1X3ihw|5Vs)}+ z+_p=_y1ji-&VwdZ&SnPTqX5z`%pKYaEGq{RzubAS;Gx_w>gJimz^w;)5B4i*Ny?}b zF)(IeEi`IRur`|Y>wn$U1Mg!rYG8RYWe|K@haDt0)lEP!c97nl-O;^sTzLY$-POA@ zy(7E5bz5?4>y~hH>!xsH14^Mijk<@ma*c0mR{E4#K}jHDfY{40D@-_4FIIqVkCaCzTCYS>eKWmUD)=)4(j|7%$KStAuz#X5=+o-hvu1 z{t;@Ba6&QX5~d~^a5RXFhABm4NVraAdpmnZ_MJDb}#!5X?d_^BN`+E9emJIBNiRKrg0s_x#^-`ztmNYvg4 zjNx!-WYO;&ayj07cnj<0dOQjIC>kh;pvgUHLj(1KHe1O|GdY1uPKM7-G$fwo#al@= zD5n)sQLtEz5zHW#ZeQIvOe=a5BRo=+U^u8Kmkq3oF>-<@&4eY7@T(dP{B73_%EEzf zf8oV{Y3{^OIna~5TTi^igOqL#c@&5!iPNMb{iE5jQE4f?qnZ)bI+Q{L>O6xGfw1>q z$*7e+qi6lCR3JRxFsZ=BS~3TvaNU9oGzWilJIIn{+PDdF{1V z71Ru`v4|$Ms`+vl~BN zLGl>kfw$^?a~X{nDS|^yq=5EDYidZlwH{jrM-jY-Wy`{4qt6|+73yXP*2&PKp*%8! z#Ila>F+-xn3*3+hA8ix|abIZ4L#)`;%wW7A=E2Z%2`3cFLrj7#9)=xlA4b9TaKaQk zMd5D^By{OPBZMVAxb|?9vR)ofF!8}6J2pC7%9>esPjG!a_0%)5xkpzAEsZ&2*8C6b ziRYewF1*lwu`Y+=rOn}`QRwXE_Ddr#zVu>vVN|^}$xjq|+JbkcA!%HJzzG&O~K$dawfEPbQ?L>UhC%LcKCk1XRB`XfB*I__nV_C$Z>#0bv{O+1q$pkCX^ zgsg}b5r#m7vF=PFtXGd?LXTs5QX)a?jh}qs9k<2#&2B@?=yLo8IYy7x{FC_*tY23d zlw<@TY!R1?2wh)d6CPz)`71e{5a}5rf^_6?_1sOHAOWfpuM5{VZ%A&0BHSFH64l#o z?cTQP_7R{V+?L%sdJC&5xj8@}S~rC2E7yf<&o}m9J7G>ASY4$S?wK(x%P5FH_*zqZ zHtGr2{;3OIu+bu?0D;K)!*Hr_Y@L~PzE8MdK5ZiwiP0)V?XhKOvkqiF z1k8tE;({h`aG337#1)uKxxTuN!~$I^l10|&EJa>!I|wQxsHov=Bw5fJ+RG-?8AJRf zOl5oeySuvvkcgc-dpp8*l!NV+ZN2TyZ4-RFoUgO(6YV@SqRRt5?b zUFjMR_V|^Dv`Xw^ll-<)P#|z`b}@(P4}}1Uf;I+=EFERdwn@=TLGm zVP-@NrqI~4*QkQ21~bTl84J-_kf>|Qfy~{=7rgMAp&j^u1BnOPYuRj359IbD^P1lq z2Z6<;qSs<)+s0c`53D9D%LjImP@eZRBn@j7_5u*gd`_2ADX)<+K?h2v=6lRclT9gc{lfnH9TFghQ}JmjWsl> zy++X|m=#%*DiEex;|BC10*^H-44HW14t5bmUH=Q`OmXm@fKK?>eFCVGDo@JLeHI7qO)Q72&^FQeo#n3PJ~=*#Degb zwGVv=P7waOF&v4+7)149pJYU_rW(xP1WYvm!SWOQtpCBn;kg@8WEA=nBG{%~7$?YE z9MuAG^(JwG^KQ67s+vubq1cL70FFe-lF-_J;t8my9RzKPfzg8ReV?<3BpMJ}`0-Dm z2F?wBnmiYtue^{xU*l4E?)mUs`qS`}%8$d38d|1s39>b&56APMXr#167(2oKYVWt||mBCMJ5 zA~AwuAn}k95EXYf!ej!CK~guPR05|20hPd723NL_2ok0dgsBwkO)-HEXEAr<@fLl_ z12&@ry4ferJI9pjG^KkH>ml&?<<|Jf%&kWmbpY)5)^k;HDi%vmM_+NWl^tx6*lCiX zS66x4Cp%N=t>j?I-k>^3sxh6ai?eEUlDr0WG^&%KMJIz!KbM@~EI^%%nug>?gP$HW zUa)|0{(pNKQgQyDSq)!^1XhU}QCPWWI$Kw%8g(;B;EG{{avC90Y~TuMlHI-7+?@kZ z7LHTE$Z)vo>SWWHSb%6ia(&BaKz4KQmJy1d!L8L>Zq05&h> zAKM`RhKTw*!24;}46>bbsA44;bjdTOXazPTi77}{5~qiL1DrSK;F$9IInq-MzNYwM zt`g+!j7?trGSbg8q&HoOU6o{kX-g&BAdeQvHW*UEqNDLGNT0Vf799(oEl?s$#=)0x zUm11uh=&V?P%nY>>1V$AKYq&tTI%w4nZOzs*zMenEwG-D!Paeor%PauR={%;h-$S6 zT=Wi%GbQ>Uod*XGPJm)+3<(H0E!a|>$3v^aw$ZJmx1(vR>_7|;6m?XLCFYwayQc*R zo-$3qB-Y392WA@to*}sJzIz#KSn6BMRe`cY5T&#~)3&NB0s^Hg!aM>oNhQ8KMsRYE zfY&X`0`dsBsAH61uE_#F*VG2ii~{46SDN?(37$#7GpQcNHff`lFdG{ZRA792PiwbO z{+k8Lf2HxVq5QaAbVB1U=hToLq~Nc#CYp02ZiC)J@&UKr(h7)PGkgzAPvtv;_6Yc0 zzDkO3R+`I}j@XY@8vUh}M#e2!I?`AQBds)6FCF)v<1c78yYKV$ zrY;Py?MKJJj~0r33#JVGc`24~JLeVH)d3Io*i9S)<`npeTpd6jU_x><4|H8fBKSf0 z;XIK6=m2j&PJS{1FGzn}`APEQQ@P(+swlws!n42a6hI@6MFF02Ng(o6JT7m$g`+<7 zK)Ang->^9WZi=y$TLqBPt8BT#NVQazOEeb1o*e^XISVKz8EK=&`i;hK)OWQ*zr`$Y zS%9MK*YZe$ClY*HHbvJ9GMytdHZ%*G)MW5IqX8`<3Du!6;4Gj9k_=GPRN%LJZ3zP+ zDw?;+0Id|3Oywh!K=ttxhxCM4$N`ywRs{5I|hp;R|D! zO-QAj%fRzh_5=9r^4Dw%*VJ>&Pi{zW?A?^!JgTsIxT$$_c2gU)PeJ?Ewc(o9rU2SE z1ok=F+veuGTWmtK?G3!N8pbPqmz7Rh>T4abkY#8R}@N(>{BNVgxoQ z!+U7M#qSlp^mau05{8gpl>5pOG?{bkhJlW#%2--53<99f(T`*aI6sOZnq3Xd%9hul z{L8Gmr_q%G7d=>Hch?A@B)CznzBAiVqm4ZcF&|#;uiY z>DKDDt;x2qbqt0;if-%HYvBhy_(5gc02N@z_Q8&>O8&4bGcM4i-ft2izz9D)&sc!F z1q`pF+z+pw;vB$w7QNg@rgahsXi!+`kfA0SuZGE8aOJ$NvSMGW!`Pr(OqLvo3k1w^ zI+!y6w+V{mz^zv1SeNVFP652wHwvI>hoS)PkgDQ&;txGM00;1LKUO_#bzbyX#q(TV z@T(C(uCd4{YP(Rt(+>vZ=@vJuZ2{j>jRX+s%=mS{A zWCatBs`nob8xYY@A7{r@E}#VaU;2_FTpkRNoT{zUXM9`sR$(qSP|2#+qw}Axm9$#) z=ty7n*`7J>$B_k*2fwAbXa52BdBrS2Na+pib4(&l2}3u)QNKk$LKD=_$PgwNBq>P= zL4F#)864JQWH%^qm0o1I|ceb*m&L0zprC&($MCle^(f@^zX<>r;t3QnZ*N$<#3Eemw7A)2Parladp3Np&UFC|NPe*3hd*H1@@BX1{~&z7^}Y1jMh^Jj5^;Uz>1Tj^ zW3IV2_0LQNI1hXg=UA_A?y zhPd$xYrDn{up2>>*%Ol#Nx*<1313DBSTfgJ6wkLKu+QB%v!fQH&pKr$p2Fl1746LLvz zaauFP`L+7j0rh=uNw3Dstm7`5$WVkB`Pk{r<$~m1U6)BO>(19B>?`imf#f%E3pS#w zJFug&ArQg-jrO1oWv~GrFh&hNYQ@~axDy9zfv~<}jSIng9+f2>YvyEn|ek&EC4ZHPB^Zm3>=LmSS(_pWIgXJ}m+u9)lk zfa;;J{(Z3^@{Q3Yr<^i`$v<$-)1GrEoiZx60NEBzBM|p2QwB2#!hd;ht`XRHL!%6K z>R|Zn0+$HPpOQZiE}lCi4B`Cwg*{*rK^`yQ%t$P%6g?`lvD{6Z0Z9buy5`yxOCV)* zK}T$%V`pVe*f5OVyw1yZB|(goW_pa_Gll`WmEbGK}z z^0l|lmN}HL`a0QC*_v@nwv2Mm)^y95KVr+4+ej@Nr$~)$RJQiF&2jO;=)`uC3mLdM zW?uR3-B5}aa}=uk>4Khb@`6nal8^A~^4d*az)2{K1d7ZzltFk?jSGq<3M)95n7MVK z{a#mWMVx1li!j}gN@}sz8H-12XGlJ;6!px>g$>cr?wOC-yxoli&mh<)8h6p5li2UTW-Og zjygv&2wuu-1OtJ?C0ph}NsL<%(<%}Mxu9U&!UBiSmdS-q8&)+I*@cmdlBi$-@jP~D zssil7vIf3O-=gwthN_^=T23$Qk*YsoEM7-N@=&u7iIxcB zJ!??o1=lP{h^09PCtf~rLT#YoSa!5^Br#zjInYCL$(X~jcQ4TvdU3V72*QeBe6JuF z_cY!xg3%&kC~na+hhTDP&3Hi{UT_1qCmZiz(mz0=KYZjJp4Adq1h=qc+-d^dy<9A$ zfsBCq0QM+j&?1AN#6${#2oQ*tnFmZs6oUwpr}DeozN@9^nF0w1xqUG1_5tkSshM;K8LcrXtHf(B|s=0Rq9L0p*5p7yRLhE6&h`pq7T~xdv{= zLWmxMGiym}4@GGW2Juy+5KvXo>L<1GDE8k0=t$z2})0^x!~27)oA2`RESsT5!ey#ieR=#vqkM0}{_+S#z83@YlvCx6>01AuoD!(djh5Fh9-{z8n9qmm>RFedBF zUmJ;KY?<;c>>q#r7+3Re!!0B3?o zD?lJvW*v|0c|YgaO&!YFhpy`+F#2mpfl!Xg>FHGLHlw-uft196+7fg!c1pLcI6!U{ z)J$?!U_iDTl6Tj^8Q6z+o;R+C);6T`vUXxwhy{>Y7 z!mWSZ2xWR z0rs_uw2X{;!aZ#=Mm$M7<_b{?@?5~*|6TapZ-2HV6xgh-oQb|gDIn*GH88||g#u&^ zB*Y3^3^0^R5cvNq4j`Q)1N(K{hGYUIOFPWQR+kJZfR4`Qn3$Xxpr!7d07ok5*}ZL( zTi0%>Z0>AnZtiXQHLG!fl`WL5dgG&R`r1CbSCS$!@k}#vTRGy+uYqnn9D4y&s2s;$1nelPq^w|GDJ@EYc-{oW9%R0X*fl z7$U6u6huO{%jRi4M8P1eX%vn@kqsyyeUoKK*v%Z$RS_vfJ;Zckg^E%am@dzNosF%H z;>h9w+Sz21N-%Ix_rV8%dh|&b0P3xdr`q(&djjIC| zk=ZyW8f9VqZ?J_9FNopw;69n)Tf0f!Gk6izytT~BU7p2dFTbnUgmCOd)jK2fi0@n1!qc~F9P@P z7vO$-agLg{^wlNHnCIGz@G9im#p6LN52`ue4vL!WPJa}F)Y!6FD1@`(f%|8{| z>$@%P8Z$<~BYO4-%mY3q+`h47qCw68QKAj@TY3PAE3_BPSh6}0K@;h;WI5MPwt)hL z0)H;ybH?d3$i;((i3f@g%p7<$%xIB1o~0ke{6N0hnodidWg=~P#zDh&Sl?f{pz=_m zwS-HOwN&9*;=?vi?&_#;|}*BXZU zUuO8>mmV^eE7!Q3gK7mk0kzc|*Y1^wzMktU90Gu!qzY1jR%(nd``iuWHiW3E`d-4sBv3C+fGLUVI0+1bpi8gaou^N2htyZh z_0r!ps&6wEl*Y#jA4m8yL3aJF=66qb8JL8S(3R|<9>zd70_g>9r?#JJM-8i*bR#rl zcpzs48iXiCAn#HvjWUp(@Sc1Oa+Cxxyd?>QPhFxlTIK{c39&E~;vi&C54a>y&JY@< zcGk*orRvTYHKYJsv*nwEfI zoJ(-YZw)gFvgH&$w@6Vn_yM>BKWkR1z`ubhlu3#AI) zRM&!1|lP`e0aJiADUx(&@&i0!JyBeC?9T;_i}>#Y+|^OUB6} zYbT+IUz{$fE0nZ&@rEVuvrqK7zRNp4(HHtES=?MQxp*wUH{nzJ{^G?`OR9|}9m;-u z1f6rqrW|U(X~M0EV=$J3eyUTD27_es)KbAeqvCH7#||HSn~ERp*$e}laA-T~g+s)b zJ*x^!^_3C+XEJ^|_HndszLA0B(Z zdR>QkRhvuj0BhDK6rnk3nhfjpme?aO+ZfP%0t*BT>-=Tr3`D$V!W?j)+TKisW_Z8I z@!k$Oz{Acn0a1?q98aj++kF1<#TTD;@kPE3!@1<#>NvW07T$mc6&T_tf2q@~sPrLm zD)r%XXTj~xsH_RA$D;bhyaH@n&?-!k4nTzEh%77jlWxl3Zg01#v{UN*3L9UW4q2!Q zhlyf_wNR2qc_EvbO*$Ni0j%tfJLm)V58%#qm;kO}M_2ls15zverR^TVT7`>qo-R;b zquf#+xdxG7RJK9d>p%ih(t`_p0G9!(wpEQnR7c|c!WjTk)k)ySfYSgVC`Jlq3@iAh zx6lAkEqwCxdHahkUC$NB?TR!2-6hWzs4a1ZHUK6_=w&4r$pUzQ7_7{JTpchpfV<>q zfFl;xjhCoEfC^++rdN$Z1+H3m^$06oJRn?=ZcHw(dmxHaqp{q_^4PNpHF4()Q~&o& z7Lbbpt|-l<0c;w@^noD_nBfBq#}k#;UYtPSion~a1w{kuwgjzJK+T4^D&WnAnnOVN zleAz)+e(j&YMTy2#$isQ1oSPaI*Az2r89+n95puG-rd&SI<;kla(}Qnd8x8_CATZM zt$Ar4Xr+2puoX5h;1hjrU-IGV%}u8VJ=B4)WdwH6fgNn!+TK>(j-oxP2wZ|=o?1Jj!R$4`tK=R5@JeZXta4*)2tYK53(FDs85F?=2 zk}qpQ!4(^Svj`GMY<1S0?{)EVF`5|$b4@8Q?JVhxtH{yD3{?nRFcSMiV?nMJNbG<8 zH6}iKpFn^rC`H(WDkx77h!3Xw#xzfBFO8ZhLo_t6l$8|#7hQ6YU;T;bEok}kK07uOBpmuy;GS=8Yc7B{&qP>NX>F*p6;J4-THL}hVj z$q0-hAwJNy$Uve2$ywb744}HImyqc8@W_Nymzi}bruu=?btsa{{%<7#oSdVkfjlsn zhX!o6tW$s}`s--=yq>bqK-@&xLP=&RhRyz||G7^#G!7sV5UYO028;tJHeh8x*T&_S zUjbRZdea|nQr!g&IXOqJY4FBDA!gRVr?X57@n_cO*p72t| zPswjmKZ}og&82=T`6opIynic}{5C?MRP(Fx`~Qfi&V3>87c7ktIC+17rMEsdvtw{x zP6A}xkPlD_1UV-$5|Etvt7n`6eyW_*e-Kfk%%Z0x`g6`UL4l0(z&dRX+u*X8E9BSJ zkx={B1^*h`Rbi!dniKhW!@g+-8#TW>aJ;t>aKOE3M|=zP@8S0C_PG95gZ(LK0O$kc z5lI7NR`YYNlI#Z?Or&~$*eswUJu;eFeD;7R0D_G!oIUl};)6c7(AH)tKNvY`u1hJ` z@(;AOAWZ@EZURJk%9g4KtExZ!#u4eAwrbJFUA_$UB|CR@Iln+^?y_)sb>roL`W4kH zuULKM7z_IfE$(ndwvjSfBBwg(S|DVFJUwj^t43At2TqI;GRnO>5Cg)>b#hN-GP?r@RRW4x>xt% z2Mv+{nnDb6yE`v4^cj*4Wx3Z5c$2o&x)p#*z^&+V~zhC z#&#*8N;*G#lnhgr4;(R~_bEg4wu>NSb-SM{?1FSQ<%{QnPT=SML{x^o&cAsIlgSdUy0o}i!EPlT~#vbH9Y=49P7Cms$ z;;^W)I9)VipEVb6;;U@YglhsK4cU_U>;YybfG@}b35&QY{Yr-^s9Hf7XhI6!uX4qA zF{;0kex+^9SwV7U%fbNR+?v?|8u~ILDj3MqKyD6O?;WXQrD4X0U{@`xyQfb<{8(|%t@Yp`G^-N zZY%%nt6xhV%^vH19q@-47(Gb8K8L*Fqexfj*P34qUzuC1>o0|e8k$7UvL+pig4ZCZf31K|P2M3Jkske!2?Y%9m#Q-W;ZQLJ?-fF)~gEiYK?5166-%k-xh zofmlkCD|q6Grt`VmZ2KE=%R}}#vMc4QTx~A04SS=7S0X|Lhx*A;iyt>|;JN>1+4R88dM|{1{?$v|*P4{xM2PT~Ko$Blk#Jy&F zBVUDVl&|=^SFmpIBGjUoVQ;1E%(xo#A|xwxRpB|N35I#}kiMj|9 z!2#8?hYI9|fyNaoG$@%M&|*+K`)s2@^NGL#1NyUeZMLRKejtTMq_h>*=_W-kps~~} z17=?_C9}(AWyf@OH2ujxV+1jyswGD}=yqLbU{>25f&As3^KD_W^@Oyeh6y9HdlGjS%WmZmC4G8m|lt52o>}aaEM%1Q0Q< zi?I6tplvPXF|?3Vv5QQ z)MvssN9CM`@645;;LTWpUaZ!S0&+rz%}{;*x$g5TU+6raJ(vD8{Rs@@N8yLHAN&9Z zf!wxpj1U7?L>ELcau=bLxXOJ5^=CseN=CvAmN7#jD6tIbv$HhD`E@;MpH5GXVmnL#2`;2-FyxWIQHcb}YjrpVuP#Fxkq8(%fkeXbCus>nig3jhj=r)i{(A&{L;c9IayLh2s7ni{<`o=EC(DkJhlRg|Qnd2m5N!#c} zbQ~?e z%}2tQ8@3V|Dd-_UX9mW2xttIPG+WTPLE&g=5k{FRCkLg*L9IJ+TW!wD1>l1V2es5h zXZ7;?W=uh6?BGwe6Z<|~M7U;01E}Jh9#|@HC=;luyJlkqhT(vwH4!A|IyVSs*3U5Q zEUa4Kmqo$91HA-+4uJ{MBlP_zIQfaNnPa)SiUhQQ56ilwR6+N7#GE zNp@9vo*Nk^O<7sgAkk*p4n55FXJ==3%+5~lA3J|c145`Z2stDbG$24y`Km0F_1?Yj zg-KJD<&A`-s*?8}Aqj-=pz_|xmuN(zM)csO8`$sf-1}ZcmgrekzRbwT$W%nU`|j`j ze&=`2+0dLWEaxy3XT*2&XN>vwd0p`+6F3r%O137Srau^u)tu`Vr3RUGDB^l#DGJs7 znv@9#{Q^eLedt~sKt1{d8T?qf0z#cYXem(6Mq1v3=`6?q>P4C1X_W%K6B1*oKm>Js zb;5Kab4zSl2uomOTe!W{64rYzBhbrD4i+1@bwu!+WOGzzAlsU48@s7;^Y~2-NyFQ2 z%C>0~PzIa!C;}Q_8P3L}r;iRxhVya36gpG@x@}Ydx=TJ1R*rZkK$F%$O(1=AqB-86gEgl)jL{m!UXrv&Uv0h8K-@>?Zvw=Xm)kGxc(F#i z(371P&p7#_{&hc{eBwp_Qr#fjy*LDz+s8{UZg^=xvVr7;?B)KDHh4KVp*w%I@3mK( z_~CNY0>|V7k6Mu65FGf?kAhm@fBbt>5d3G+{2xt%zry=phy}#+Bm>^3H7xuNVO_zp z;zk-0TEz-*8%Bb2)S}Xu5wObBTi+=c{4-X;pcgz@VtB6*Y6;QUW1vSe=qd(#_SW_y z8o2$*0e{dP@`v3Ke>6MRcl_As@xBu@SLwI>!0{99<9){fbAEV)2T^6^D66jQb9>W0 zZubnKcnRa~+at12eFOEi*A8I9YJ~CN=%1<!H4AifC@pD++7SA++ky>iWpx{>&`KyS8ureGO} z4xg8~i7?;x(> ziD=|~h-)RFnJ*y3v=2%?Gjt~_Ab>aXEc4`RPZQO;XY((+uO!d;uk@n=kaK#j4Ve39 zXFl`HGf&6V6GY!?|AppL8(L~X-XlOSS0jKP%_;2DA@Ltn{}4z9K-bnRN{q}6%1NOz zh7}Q=^BE9b@@ynlY{LI3BwVrJ~9o_Ii`4N}?*rL5i_j_fxkU4CB}1l2J+G%Hpp;4d8n zrGlTupI`GC`Kjpux;mQuuP)z~x&M?9P$vi~O?>3?45=dN-=x*Vgepy&qeId^>=@1E zCmC&z0r>quwvan}X~1YZh(7*e<)nM@*^`wMx1FqGRDY4yUkyb8FP?1Lk18iUU)MwI z-HTNMfbo~wFZaFjatGhL6#}}~Gb-8y^*Q4RDA96%_nrdl%@x>7*SooY75e>}+<#~o zsFN$KSCyYN3nX$!HM1bqO^isu(GC`gdQhKu2TH1bQ)n>JGo5G$OdYCjn;J~L@B>09 z0#}E&#B^sYb|T?fbP@^~&##&DiEQV$zBTLHAvq9@fxF!929%wWeh1PI95`Tge+M&I zd+W&P(dx0I$5tP$Vie4dG{N?q3Tn6C?Q2*M0N{P5v2@D>D2*TST>y`48hCndHlW;3 z<(?|?0nj7T0aFpa*Y}C@dLWicd=5D{d;wP6B;$lD3k%X3mc&fK>O!RWA`PwcOR=zcSWOC zar;;T$nFpVfUY4hj2j4!KufenLsbX>Y`0{q>@5N)y9me+VA{Xc0ji0R0ss{P+;SVz z76AYk%lSs|3t0VYv;LU|;Q%3l`;vbu z0r1~t>3yq8K}wPk@#*W z0Na6u`AGbMcxmnnJ8#7N0QrAvn9mz)nb=6<4f8`g06;(Zt=uKk4fLbu4=bmY_YHjD z10VP+JxjN-ZvzslMi%?Yfq31Z^wUO?iW!H>kHL>Tn(zaazv;&Cv5pZMS62CvegT@| zNiq4!=0=;%t)1^toPl5D$Qaql?>RpW^w9^=93ORk;od>}UgDYK!JD$NypOU1z+9~? z8NM-=VoXiJ!oErHoOTwbZF+hI`b`5t+LT=1tpF_i{$X^X^8fCN!7JlZ{J6XN59CZK zdHp-YdKCe>>;EEX^%2P}{~wA|3#T7guFRA<0CX7v=I>RE0<|MXih}(VtCuPkz-X!$ z8DF}wxoLEBvSpnOz>-Ujlm!+Gf@CCIDUQo=Z*PpBM&~hEgIcn}b_sLq&;~Tb=!0_ZMe`Odh$Y7^SW#8ANOHbS= z)1JR@8fttYm-?*~Fi4` zd-;`&Zrv}vJoeHA+#SrGI9a74t$Cty@;Q$7iF&9v1Jvo|dBSsK@t8PS6Ub*L2ld5Z ze$9)cFLhq_R0z7)JZ3(Rk55Ah{hKvaXt^Jq^H#|6zm51V>7D)kr$1%f;Ot-gqMPK0 zwu9vw98h3+!%i-6P6-+57~&B(HUzqq`sb$$)*duR!MT`8+?q&DPBrqWSgFMGd!xO- zx5O{v`4_P~_DX zTiu@f>0rQaLN?|lp|%USC9|7hKcnP6H^8Q#BzwJz)1*aasPC0mGwMi$*{4d(9tX46 z8D?iIJ1c4eC+X_V-ca3#0HV~4iDI+%6H?2 z$6hvlPb$6#l10f$DHv^1Wt5{aO6e$>rPxtxO$sOeJk1vjnfMZt&$#&F(-e32v6;qe z%D%ofpH2Hh4X@7;H7~1LqqhZQc2Bq`Yb^UO=1*l`syyBLQU#taIL@AQPt?so;vOA&IXn>5xe&iF_P$8{X;Byr& z1+#YfwH4UhV0k5YkU$LF85TDI%_{V*T2~ zGULhR{)+QTs6_+@PD-qGpZqU!eRRw1ZK#9^K!vH^664WTuN4Px=2B7;OU$_hTjyr8 z0|c;*XiK{xH4P$EP+nhc0{lAcWgDuT?)JtiXFU^F9;Xwns?9SSi9nrsP{~7}^FDSN z0Eu@)u^9o$6sWaKOR1B);UTSw0JU!6pA)Oah4I@n-=$El%7RbKA`~v-HZ|FES1CZb zA}$j-<#|Uf|Bd&6HIgBd*OdR3gRU;hV_o(fP@AnEl3Zho4KE6(15KUV43-?F6*Jdm zZe5)xRA;FIj2iD(GkZCIsiti9*o#$Avvabh`tPkL`i`F%KVCVpi32(J#PR$@!_430 zY?I>;o=8a8lDmzN>qM`ORrkFF;^rW(Ja(!c$4MVaG`;11@GnH70bc5*dK~mUId2qm z_si*)^8S@^=+l5#DaQ-+^dsy}iK>i8n}Oa4N}SD5q`bumdU3b3*MUs73l%)N+=Z0? zGllR;DTH0%jo#rdmHxVUgRFsw>g?;WeAw+ucl$klZ?-Sn-#kz|NL%s^2kXYDvjctm z5BU9lUq6yM?eq3JxU<{kUPyr7G|*<##i#OSv%m)*oiS&F-=4%`z+dyyDY^RW8(>PdEFE@ycCYq{B+{Z=;P{q)61NHuD&X(XJY<>XN~eb4%Bsi2=Gl=oBg5qR$}7|o+k?uhc=I;>xTPPoWtRVD@!vDKU|OB57;Ak z(CBbYTTQkU8qL?{(#o(~nhdX9>W0&$t>J_t1KaauO{{vYl@6??WRSSf7oIt%lBIHi zI>z$AovqAADvvQ15)fq#edxdc&y>?e{jmgU9LraSU9>>z9{D^p;4}8D^dk@z&Gb?m z*)pNeKsB4CmDCwhk1Av}0bNk7I{HmqE`PE$O6X`#kwOcs1BDJ8+Q8a9SVN|H*gujy z>K@A;?dpeu`Gko6PR4t(ny)22`fMh0!Wol9xGd#>Gw?IFCe2uty+$PN|j`)LAI) zu9yu&@}E7ctA(R%@%nMLxjD0X(VZC3 zU71=EJo%WvG=WTOSdPjsM5gl#2bBN^s?^ReK@4}Lrmxpf*Ng;SM+f@c;&oIQ7~ScN zt4s3)=Qu<19y{50;$-JUO_f?6^xkrO&`P?ktovA<6z#ENW5+AFuj;!07>_xYaXffD z;qi?V`n}_uBh4N?Ie`=0Q|aY#u+`X}Uw5a{H{AEnR-dvT`~bnT1axdm8qWJ;`ro}P zy5)=fcQniY+WjWQK-4pnSIp**joFkN=4pr?q;XE6TmO04cZ$Wy7PT$p`HI%M(J&u& zs)*<%q$AatWj;c>Jo5(WPhrlnav;O>==y!$+-&X}Gfg0e2_s~G_q*S9bOdp`G9W$Q z+qVx&-M|6AfB(MC`}2LRy?##yfCv680G~xT@J)Qfga&Z)uYFDZL7>k8!Jm~!t&8Bq z7d)eoOw?A1wiv`kAvk0vLU^oZGpm{i4HUXJ#jPE)6u^NPC}GUrMg4oacyw0)XPR7d zpf|epP-s7L1`IkNI278%Z};=s&j4`u-)EtH!=K-N`)$s1seQX2Hs7Rh0xP@(@9g#b zHG;oDo|~4KF+YXj_nRetXW;in!|%HM>ageO5~YRUAU9d-pmGmGmW9)9X}>mgAUR*! z;4?SZ1I-!7W{x(;B**B|%97O_;~cr&uIblS!^2^2IUKvC8aidX6U%sOyG&Swxb|A- z0EyT8tH& zVU!j_XL5xfyaOgF2F2S&$TrDaPY%c?)|LEOVz#aaiQb{lG_E!Xc3{}k5ntfgTngw) z?*0LVw9`%n^S$D0+D{$@XvHa0K4Lq-F0Y2m&JOg>#qDWhVcazn2caD&N zi7T+X{@AWU+r)r{w(uw%RP#Djw3R|PyRF3CU{@1hN4YWrc8S+U*?%8iwM^-S%n zMw-f^BX{M{6{6Lb39;R!{VHx}KCX{l?EFO%L)7UQ$UYmTo2x`mG?un;kxY@gCA5lO zXC${BPq<$iwIOYvb+bt-h)r;8hBx54909azs-nm!?m#8rV+G}zRqS5k+v~GFp9#F% zfVTkL!QQL4{B3tmfIlbg@}+hRR5xo4f)V0|L%!^xs^&ZCwW$*dYUlhJgWvwFyD$ zvH@e*63;Q()D+6O6$4>280PB#oq}ImNLKrcgtR-^K6gq>?qT8@-_tqbV zJ~lsjJ37pR!TcA$EOl-&*0AkR%f?wH2Xm&LbqpPY%uVR{oj0+;5wbC@lH|yV`xb55i zJCNq@W!A5&wFj5l-aVW4w)gnm`L2u(9@7ACARHY3_P5=)8dl2t4fpkt9#y*})>ClV zn00~6Q>E?GfY}OsyTBa9?I}x$nA(gDhRnQWYuBE^+ZUlZ3fykAUn>Z4#y8FALZGkR zGL)JNnGKr%v5U+@LT0G7Wu+SdnWb%~B&8k2Y7(~n_cH_LzSqF!_N(nzS}*s#M0H>K zqB!*rOH59{@ve1qlJKXjW8(7m_wGk(^VnZa^tCF)$ zje!S5FDSTmu_uHZhJY@GFjJ=z79t8faw{RRUeEJ=;@PS-qbh-aJ)}l5+~7y>Z_%TAQ`Vr<*fK6v%^|vw8CDvD#+CF6-7OxY%c#JE+)ZOMV_kEuR%{8Nw30b{Sb#)~)1Uh+{L|cx6!J-jYFx=Mpdx=?YD+B`R za<^<|RCR*PzQ`?{ZA5%tTv#+ha@P+Ot~7VuG-Y98PTPGlg@@P89O15Rgyq!}129$S zQvcD4&9RZlt|GJS!h|aIA!Fhe0r<^B!I!pyu+gp0@z}|k=CKY_S(c-+Hx2!v;-h#U zYJ$#Io}j41$D1@rO@Qrzi0;SN9cwU{l4fgPKAIlOjuHhNJ(hFR9le)0AUlSY8t6ZE zY|Zhy`1tYc#3)7C9%(&vV@qDoPt{d;4AL{Z6`XfJOvq>diPG63;XT=GfSzo&aGpZ4 z->Rxl@5Oly46|%DvAZomH+gk0#>2q7<}}-xjCI)N1S<`^Bcgmv?uFc5na?&7US_mS zSa(mKDVXn8)~J-mea(HnuBIH{^xsOq?Y`6ZU2s09F;|nivfaCPt=~PmtNDWaUiRJW zJL$K1%r~=d(8;5Ob^lyV<+<+J8C|k%&fSGi0P1GlHBcAXffJQf=N{ZVmOQkKwOM-b z^hCOCUFL#9W9uTKx@qPG-!Ar@i0XvGcm$NTR&iKek|i4gdjJdEkDOOX=72hUn{fe_ zuomAQFuo0_`yVF==BhIwn8Ua5!<4$P6vpk|$mz=0#97vYY8$H8us^=kGH8D*Li;}f z?Ar|3X%K_2ti7x=+yK)d(qho7h1-JVrAzMtgl}C^S$rGElO-50T{5%66?|J1;i=!F-{OYWkr1&Z3iz}gKPm84Gpr_*Q7{%C;QDVQ6WG!$kI zkZS}c<`1s}bJ?|e%;VxMa@#HrdsU#)GTO37X@}C488Nr49oMt75Z2aq3|~o)80c;n z=bWu`4PjcQULZWJk%f-E8TfA7srcU|H} zjDpQ4^oWaj$IF87?LInaJo*wKHzcSvI*u^ugJ+6ED}#=!Ev|gGc3L-@#jaGytT{#9 z9v0oOMbFdDF^u_;o>m)T`W&sGHxYb!#rX0nIh+o5Fqy;FU}hc=st7_o*UB0Yb&}(s z%wgWp-6>mDUF#2e-G)F5b}}3iw41l=bz&u8ZtZymMF|RG(6<#>bu-xHR;@W~=n5Cg zz;HcL*L~(Yk<)$h%+R$Uq+deR=RQ9e>bmI_ITy)aetGLp`OkacWrbQVh3|qHHd-X&r_zr z6)9@Xb&;t%RB{2IZdhS6+vpt=ss06M`#%8NfBMG&w!u249HBV1Y~T$`#;{Hk)+u?Si5a{LkxjEw-THsa zKG`F6o3KAI7h|vLObA;{eTRal_+z2@9zS;ppBI& zAT7~2`;FRAkseg})*to~Xu!6F+UV=%G%~*D$Ad`QZ@u*vXq*2X^?h*Yx;nT2tpjcw zr%t_bicvtXL#7=G>b_TAZCb0l7KFNK<%Tcj7!t*-|31R+FM!`K82q}xs>jJY3!6rl zP8aZU82)Ynbe$djY#56HFt=nH22SxP9nB?!`p$0qB?H{DpJj`u*`xI+Np;P|4LxS@ zlFs58;UW5thqf1=XAjih(4UEaOt)9V*Le~#?M-sL3ZArf*qdNJ zfU+eJWf7lWVtu)aZM!wFmq%QZImV_B(^&i?@4fiq)7)rq>j3m@DeSftY`G(nD%o|q zNp3Zb70#E6`CN5}30ZDl9d9N(Yak>6=XsjKc|Au(BO?Cc5(DU`Abm883+cQ3x__sM z=Xba}`wi>wx!d34?{)XpB>SwszoDKk_uudD(@;;6Gyd)d592~~cg%>3Skqr`yVcz? zA|25x5Vw_x8B#M;bDR1@m@RZS@=y?Jc5{V?5#LphD@LsljdK=~kOAMRF$(>-wR!Uv zMbgt#1U6)p+IqmcE6@6^lzK{HTkYT62miRl_mF?@Mz%naxSNF}CY1LpDq%5XrdZ`@ zx#$`Ic0-&{g_F6!o)SZiA|P<&7+=v|UN0tOH z{2`zA6Tm5k%afY^vZt$zzU}a^JejF?OFy>zxZ_;@-*(&Xx1Z>HM>|@6c^w&G0tao# zL=2R$#lS(byE4i$nKy#E>DMWn%+;UkBe+-h;?>lnvFM`l_$5aWlVM>ZcFuuyHDe@f*luctrq;)u7uwLBOYgEh9_8 zKCYms5PVElClu&X?jjU0Y7*=@SubJ%D|dB|olmuEj0K*;M@~bF zBKb{63r8^EAl>QL{WttK-M3l<19gP+?|x_FcRSx{La=e70Q}JM=hLtH=LXe}^~>tF z;+{E!zhtNnzeY7Do$Ve!=ds7SwK7FM`+j%dh3uFG!{#~P9@2?cHB)31O@a)#UjV%t0wO7>6<#*>XrGvo)2r1mx&yuZB5>_L%aJ4kj&YD+l}N$rwk&*Pa@|31DJoSVZK?w zTf==zhsT%pEm^u5fcHykfbNnP7FQOHa(r)b-5}mA9$(V8bV+k*KHL=7rVGo8<$gs9 z_@1XkW4PwE=Yhh;WW^Z%Oc#YgalyNz$ZZj&;4bj)jT_xx^?%?4AN&A{VZh^Z?CU#b zz5~dYU#|S&l~)#fSb*f1J1nSo*uDzZV;h$;h6*eKBunjey{aB4EZ zxU+m>S#@~XaK}%YzU^*O&-Nr;msA1K=ab5+gUO@>Z@mF6cxns3L{3_zuS57JiPw*- zy`^6>P;6X&{kgpq#*!G(OD5RVbhbdZ-G2+US?;ow+N|kCc11=w&)HKejAz12`4wg{X|z{zBun|r20v923Tg;nl4p6{m{ zMO~HqMBPq2ugj{c&=#)XMVBe)(BsT~gmgXxdgjy=wA;cw8-q!W>{VSD9nKU#l3phP zZM}B#(RQcV?tqYMh{9AHPsO}4%*T(nkBuJfJ92dGkp`#;W%h?FNA?{~j0X>1G@w)-+I=}Sp!CnDU-JNE-#5RJ ze>4A<+C+bA^SASFRRB)GWd3#cwc7JkO*xQ~UqOXVpK(u5?*&Qs#O$a-2h$fiw0m&+ z1CV1_#=Y9k+}&pwujoZdcUuKs@xN*h<26b)WE0yG#JFf_DRuae!ZqPcNyhURg{yA z8orkq5ZCwOOPv?{RFj9iqT;>d_zRDV8~-%oM5DY&sh2)1>0HO@TT7$7d5rvb6T&cNJfM)gTZOvLGKp7sSLd2Uss zq1)W{A&WS7-cHcz@5t_~vPRuql{=evRqh_UYX}~E2bmK--0jKEY)7))-8Rgxc7c~w ztDcRvW&?=vzb%m0$YmhJbT~8UwS{W2T*O}4#+EHpQarokY+w^CA+y=S>)kSsH)H%vu5c6(@@hJC?@?YR$K6on(UU0MBG8yGaEFq^V;pUIdz^8IpYb63#G?-#dVuJ_ z9o_`;=f~QXg+2)}&ai_g*ufJ@yF`rL8}Bk*9A#X(cv0C!659Rv4@?#h71bt-3-OV~ zL40*W6XMHkRz_q}F$T3O8JP*g+-?0`mfsY%0NR%ZSlEKQ z>%6bXCdO&p}CwJWiIl1f(xCt@IjzE2T zxNp!4Bdqth#=@3E++(4B1olGrhNvjo*Mg7;mz2v}GLI_Qe|2tA6y2+PtD8yfZ5-YH z@9U;{yT79Yz8SjR_x&55<|R#rzU3;-Z>lt(*sqDJp+j9@dQ4FM^9bcX0LpI2$OZsH0=b&8E=;uV%K zT}vcHyIb9D>2|ln@9evMXLkGK9euao(Y!t1>2|p7>22=ThG8kYMoqhh+ghPgV|;yzg;rTLkqE%qRvkzIi&A14Oh;YCNrpbmC^XxV+}egkOen->o|dr# z5sQgqp*mW|EcF#r_e;<~y-1WvWzo5ht3Vvc0669-xch|rWWwmtbE8arnodmFk*tM5 zCw2?#x@yS#Bye80Ea8GlP>kq?U|b5Po3iP82`%QRv|E$(TlcCM>L7e;K)bUgA$1@O zKlBV6l(qrgb;RUR6CNzF(9L)AlDY22MxeXy^V173l+NKkUAGnDKIuP^ut1V)9BfxG zm|o!v81%9Cr`m`hpxYGC>Aj4m%ow|k4f06nevW*f$8ep{%A3SEx;7$kC}s9A-src& zwl{$WUK7J_x%61;Xk7{7qn#sb4%dW(YJM?xsB*AJC*89^&)4nt^eUoBCw8 z^obu-4(1%I4dENZQ zf845QO>jv>UnISH@zO-(ZpBEKACppck4$?s@M8(d?#a4Aru!1u_l$!ZyRYQWHE0v^ z{8zu~pYMF_=C5}E$>vwxa~TZSqZ2zo(gBiZnnql@u*84e!~gN2hmeUM=wf9MiUCVe ziXh~HmW5Ir_CQ{T(O|cAR@hL=!Vb4CK_;1D8Db^bq>H)H>9!X}q+~QeDH9V48&LlG z*S~WA^gCTI*3U$N&0zf#RX#bhV)dhJ5bOYy^&hTCI{ z-gxj!FXsSe>tq%!`*tCtr#TIONk3<+V)M`HK%qI?ZS02yGgG_ z&s{2m<%`2Wk)Tc+UMu_*P2fqIJgrKrnv^EDuCADZIa9OoWJf*IG^U&V7y4O>P-8$l z+ujDWD;(7wJ9g$f`nK=Lpucr^vqm`iFT6J{*R2MCh4>t{I5@DITol)o0z5-Oe}bWf3>fgyLr*_W5S!jPaN5q3QTLPN8#Kl&j1 zM@inz{YCMxtZnbLF$OO&8$5zeYwtY(p)+)3s=&-(3C)*+ZwxTeu=8VTm z**Y`c!DI9jee!fH%SZa{_QuES+#JCItOz+X+4%}EeHIa|wYIG}8-V_A`3TC_-rnd6!N}{$226IBH;9y4! zkj|Z%+d5ST1cif({h~oFs|8wEZe9xR50)~w`&^31J-x?jO~q9T15U4X*E9%ecv0>u zULFKkI=8xi7Q??&bZ!~N`avOG6K>l;L3mC}2a{BwmXNjOaf;>R{USUZIOGTbM#28J zb+u_43+{*o`w5q(UV`_8lx|v8PlDmCLk$7^!9%+bRt}AGxPxa2<8@a7`+&YbRJRCV z%c1p$M~^h{j*%R0QZJo>=nfC|ObOqwyz=TRud>U(2Cz>%6_Fj2ko&=3nD}i>c#8II zL^uNbRP9>^F`qQFTk0C2sa4RvX>$dqV>6=bhWG=E?LB6(3DS26JlQ&8;OVyfzo%jQ zt)|zB3-3UxBS8#~f~I#XLw4`II9Dx2+>;|N`XM$zcM#frvGJ5KV*j)U-~E?8Y`FT> z=bmeR^_J(WzHLrcmI}rLf_v;XQy$Nka2+n}&F|Gb z**eiOL~rBYuN)Dk|6|1Tm%;RV4Ac8bNFiAfqt^wSOI9yl1D^UtRiHIr)DXZfT+~`v zS@hV#%7V=tw~|&`0}AW@ocptd>lP6aNa5BsDU(=EfwM=9mPLz+;v-uyKnr zm)4Y#iD6?h*i}x>_!@*uE1t6>o-CpqaF>N%Fl9DXTjg<$2X8jJYK;hX8)-_gH-jwK zq@A>HtFdghkKUF8v;#!8ws!KH68Ld{09qxp*%ep2cK{WwW zEAGVf=66Sm969pFf+C|gyEQ{y3zn*Az4e5|0>tyqS?E5=0N2*a+6vz2=86VyIBafI zIbI-^dOVy6XeoO8lXL>M>yukGXO?RN08Li?W@M`-#gB}vSv3X^rm+|cN_r{{$BYB3 zriV8UIU{xlJKx%eOp)ajBXO1hzivCu0Dc3C<}?^iHA?EqNk5D$A&4KZ8wYmRrgPjU zXeCXpcK|=!Mz*lr=aSF6>qR@kJ~y`}2J9B33T=)4dWsbT;wk<_0Rz5Uz(kERnoX#r zYm8UXws(lq1q1_+AKLetWHvl^Pjs zExKU4BJUoUfRbbhxTeekL*;ED{XbLkxkd-NM*Whq-l9;OaM~#AjxwWb9%%d^HNl#@ ze|GG00OUX|AAOVtMJc@m(PqEso=U&upU$4~;8~4Xe~{Li%752BSNZDrbA4ZVt^<}; zpM4g-njz|DU-C~0%ls4kfyes!Q;)z_-NVx!3YI1byY9XO1IqcBPJTOAwb=hW#W{hi za_*!0B`k9r&NnP8Lg+GvHt7xxj3%Q2&Zac07M!_}a}CRWg|aKg8nNtW)DBILwL_dB z#CWR*uG4#sLNUmylD65Y^!4mD_iEoO09u{1{W3(g`r?cDnQ{u&I(P>9jvnjan-{44 zDuUWcK(P>^b3cGQWp?Q0&8x;GzFD> ztB-s^g?om&_v8!C(If2+`vpCeV`2ehcEN&tVU_Q1T3Cgj=B6GSHT8>IhKib8Rb$VK zMM~276alEw$50m)-6%t3gf(vUnM!?vHKKSSoHE%MC+vlTAw3Hyx{J@kk#jm5b+Spl z!zYD?7dJ5VSh!Bxmx;%=cS*cciq@)>#6|-hHUF~M2~Rh`qHxi*-VH8}mVC6QP(Zp) zzYv_u#BFg~-8Rqk;OR=$A|u<8-BP)A;+7_x4rBlPP3g9bMyoOL>Nftnl6QvWtNEUS zP@*KJB@}}7sTUE|4AZUnH$h(Q&A=9b*qegI2h-z9M%IKK%!=8uSmp~os0j|;#}fF# zbkKqKIC!7Bc=$&jRMNP(Y6|1iluL$liFp^+IT$V%QX#;hJ#)M~TrDDKz8e9vq9L( zv~w-oPzWS}+2gCHUbXE1k%Fq;P}N_yQ|Y{+_m*NQb^n<&nZ#W49JmEQvIX) zxv8YmE#QKd(B!6|Yskj*DcEch8%+30whq$es9kQMAZO5Yy*r3N6jFO!#VO#*pI8J? zFL3kId46tkqrahUc?AcsHn==YICh^(BY$ilgafOEa@^~a>Sj*^qRy}|&m=&0Rs7k; z5Y!Gc7^N7SL73-2Q_$bgG*fr-Hms3=pp{YMEk)nhmnM_dmApw}-V`PH@aUn@gS7)R zZ`^dCLJ#E%tsJK_%8(BZh8m9US0iPOL8xgc^4Nhv{nUQk;n8;-s4^{i-NAmNnFkM! z8uI3c`;OpDb|w`Ms3C~jZe}m0=*8}p#Pni!swTPE{p~CS#%|S-`fUAPX{SOf7N?}- z2u@jO#R6SVY84jDd0~mMx_oP9wBoIOgh628x4*S_N&1d_*{OmYC@PFgA8_ovZ~OXCi8G? zhvnXC1XbAmuz>~;Rbl@IS@PG(mSc@-Vu@;*6x=yJdaQkP)Swl39nrrdKGSuCn5oVuKu`cosiLNMtt-}yAn30? z@BtHV<3uQbQF0n&UK+El?()x0?PzJ$K2h89SONq)gCB8KdX7Rf)#)n;JxBWJFpwSAbCN0xYv_ zRVa+xI#Yld3FO92%%$m<@&NQOp05yVC*0V-2x2YRLx>SbBteHZ6Xhxe3hEPnK0s5D z$bv=k+Ja@+U0+48^`E_f4bfaBY}Q@5)_8`|3^w*FhPn)LYMrif-13usSiPjr3a}}c zv*{*czi!=oic6sIIqMqenAS{@y4!23 z=L4X`)?Otqpn{(yX_?J9LuB1HGR-hj@Q5M{2Cm`w%}T#=u*Ay_k8>kcIA?oRGwHBn z)xGf>wk~W`W$HC6$wDm7aqG@|$F8+Syz?f*MmdcGHqzfIcEu3m?8&^Q_>7Zl-JC{P zf9`LTzWns3-DjrT5+rOR=@0F!8#?;Ab;WMbPAX&!7*kXj5~XBa{mKl%xt;W-kmf3H z+$fDea`Mbo0y<`@!O6uq$&dhwVw`?)O0GqPHbGc*H&8%~aZPg>d@n54Z5{YeK#Z?- zpkmp=q7YV#u?$6-jfB-90i)rfwUYFkXGY;HNC_B=`lYL~5lUBe6kdz)K4OH#11ikK?AWNgrS2KWjQ58TA?zeo31 z4y@-`yT9M=I{=hc`SJP#^@CvRfibbt9Be#vsC76$k{cQI%y>v}9Ql{)=&i59MH9H_ zjF?0Ipwcn%Y)yXS_A?!$pg`x7eNVtb6M)e@n!-R+ zj72F8eNs>{xyRjoUO_%j%ar05sYwlUH`h&ga9jVppa6h^AP&S~`1vN(<+e(6i1 zQM`4DK=IEaD3&s+RMaUls!>l=0{5dDsZt7Q9X%`D_tQ6Ws3!wC;GNmaO=fQmoK*L4 zLZBu+QkWgt!mZxMxhCTIo0VzA$Ng*?4+T9H-U$pW9$(Y}6G>MZFt`PEL&RGboWm8m zKm?1=B3j{a3#P~K?1xP*;{N!s=7QPbp?YNa&1^wKcP*HoFGzS~CZ%b%I{p_Kq7Z_s>ccw%RqFLHsbU9t5s@+Kv)AAzv2D$Qewj&xs%2hO z1&6}bl8Fje;XzVp4Oa!LrA8|<8bblgj`DQ-#GRR+sTRV~2je$PixH$^$mW*j)+)4Z z^|qSSK#@Xa<81AjCJRo0rf&Ir08>NL z=v(4^aLNLlx*Ogf_fj!XtH9|tzWBtPIYE{UIVw|S-4zv*RI_?TS$HT`F%$2U`=l%2 zhjaxMG*r^fxiJf&h>~!+>oZ_C2@$1d)M1tl+Vi)KlZYS(Pct>X@Nz48ieXtMkfnaD z8a^DY$}ubP(Ox=cUVwaYC0V0F+R4)Gl#D#GGGQpU$-K(*&4kp7+48|x{f7yy@#pAeV9M@E)G$9D4zgJnYdgbIuYt<i8IO z74kVJjXg3q3E%5MBH&=fccy}nhBBWA!lTZ7SjXFS=FyZ6D%iAs4DN>m#*&))na8{R! z+8XhjH7$cJ){^AJT`3MG+L!>h^>N884#-t?ZVnxV{!^w~6S7LxWuHYIg^Y3mjv_$x z%ap{?Iamc+n?^%x0@tzqH8ml2`)BZFe?0c>e|{fi)s8c{cOO6CpB|_OeE}eL(AH%C z1n|q>JJ5;P%S=D~OF5;m>4}i-OyHvqJ}MP>2;_y4st<;Lvx*4pe)Pvd1Qzc8Bv_XM z9fgk;B5*PGIQY?&oJv?vYQJrSG%TnO@pgoaLRe8!<08B0QG!E4eG2YchkDC!b~!0x zu)BL!k>rff>mGzj!b#DC9i-GF2Mc_gPqn|)_w<*xJze_}^|0+P<+zio^oI6eZT5Kj zn19q82^H4*`x|gvGN)72)Ay>!1kE9bhjj+?aV0ihaHdo?%n@9+Pd)p zSh*Mk1v&{KxZGXEt_S3joIi)y#R_zouFw^G-Oq+dTt=wVhdUHd*GJUd4eCB(sM{wdicU+~a^a$} zg*EB3YXCy2IyLRQe!=Sbl?7jzUzzs^U)vlx$F})(!%=7CbpDtW+=YwZy|* zzA`PkRfLj-ZXvnWqEOfVBiKUIKo^$s}2br0TV107~=(nkF^QL^W%)1P8 z&A0UPDztTGoBK9x&Nk)1OG>kx6mWEF&hLUt;S1_gO{a}Rff>zzOn)^0WFY!RVI zU}{2Ym@?F1pi!~Hb40@&J+>9Pq~yc&B(a9y#3g)$)+nQk zS%+>>3(L+Bd{X)<7sf`Ai{aTI*!YSn2=|*6`HCUKI)lCSD?1}~GymWiPFA&&oDH@w z_+bQYGWV)$)SyXY6P6Q5>ARe)b?YkV1$2K<=cQ3Pu1zDX4TOZIs$6i+d@hAo%1u+?nxCJLB@wUmm;fCuPCeQE=E`x>v7FeA z)DCrchy3!sWy>{PEHh=*qpW(aK|fFK93?FM=Tl&e{|9c|l-egXX>fCR8m6eatGbn^ z{!-AGlPTg@G(J2-3Yrl|OH&c8g-|Uu1fwts!U*<57`^8AW!7FI$AL>Y>&%LiNmXr| zDBKJc#j9!4QRPZ$uWBF6$wp=e*6nxulKt!VRraN+DZBJZmz!>Q`%O(*SO}7oIR8}S4 z2Tzz=M}#<4Rt=$%yJ@KFz;(9`1(%LwRd+|-d^+y#^d5IF?OFja_W<|4 z=3l)1sZl1a@IvNguVb%XYGPPDq zB|H3wpO|Lq{{HN@)MZIV+8?Uh0*s#WVS$yyYU5#u#2!p^ri>KhmDP}X7^18;wIfH5 z9L?3_gBs=zR<3|r&4^mx1+^YE)XEl(!w*56g=-hojo#f1Kuydy_dq`HJy61Vq73$x z+k9i6`IOC1<~8Rx?E871-%|EMcj_49`-}sKo40m;6^NUFe?mkTv`I^n(gfbD3$jYp zG9)5ZvILA%Af!g{66U)AC#)zb;2J{;ML=wT-#s+*EVfzZ)!7F7U{HaJ&bQUuM2v+c2Yuo$j(gZ-*tABP;&|w zO4g@#HAZh78l>7$*OY#Ci~glJzfPWMsG*siNoWvV<9%Hr)qSGECV1AA`cK{}-Y|Dr zJtA9g$HN|Udmj_m!j>rZ3c#6i5_RC>(kMOVI2$M*@y*%YAkOHYwheI38FGbJLzWB% z$oxo2h|AjWJ*lbm0a?7HMKQ9p`b7(qRcowhbmPj$<>rx{Ctp!vmc;-!#csG+Sw4z$ z)AQ9KF;*lqn)4_AFyjYdDuHfI3M5yok!_6W1p-F53Y8LIl*GeaB35RK?#fhF>0-gB zA-Dt9bZ@4&E#9mOox+Nvi zJ`2?~y#Yj<3r8ckl;Y~SrsR8Lp2sqDR8?a4t>lH&Eeu$$aJ+zw z?(^O}t1cpAu&V}S^pW6UNFo_|rQ>jzlZ+9@ehQOZ%t zCGC_=BYBxA87;)@QQprru=y(Qdvb70qu|!;Un79qw|Cz?du{&uo;~^A%AR`xLIGpb zK(Swd$RWVow6AafzVZE|a`iN^wq}PLR_H=XvF{k@=Rm)dK1S}P)NDNNH5;xLDp1_t zR)6pVl+!;)IsFkG8qCKd3Ks|9BAr?n!(aZ=q*JgD@bmImOArd;X~-%{70^UDX##^K zh3kT!T4x~$*#@Rn5~C+PP?k~zfNs0ZZJ!1r?Tl6)cV`NDYXtHZx|+KO2b4}!LNR;9 zKRWOjV5blNc=L(AC!ZL9vP#RL?2EN0p=}dSwx4J{&Nwol&_7(~_Z~Djbikpz7eKw+ z-Ida(Eg@}~?r_^1x5d1n7~3qn#NqBGWg93cn_Jfir`D~h^kQJQ%?i2W(-hLb2z2dN zVrvls&1i}fxToh3Z-0S-NTh1!96AlwPMvxk%2p?Ac@>*ZisLi`2I;2YFr8+gU{elf zVc_8-P2+Ak(tG7VK*DxJ!mopbPZ|;?khVU-Ah5Myjo}(tmvL=9JFhbL_IVXkK}0zuu>2`W12hg^{Xof#-hvvKjop~aB< z@cU^-p~<2kom~SVXUNXR3lU_C$Q4YEZOxAkba*S;&`{NQ^rL7?rIk!8-Ac^`JXymg z=vG7D#AZ_^sPOdn7+o@oc5m)ya81_b4*bmo(akIR4bfHrV9AO}fb16>e)$kM#t(#j z>y7EP1YXUN9L$nTNygGJE4Q}uZgiSrsSr-lxFBlO=PRI6H2&LM4iYLgOUHjCy*Qg9 zR8qYkA}W~E$CWSa5<2OWu&nDEoCIar4}*h5UhA((uJ%?_0m&q6>Ee`!j{A=UoPxn& z0xLM2BzL#@48y7J$)sF`*h?*VMa?~Ij*-7mxq3_PDWrbcW5nW67GyNVs+rWZ{ddd= z)gH-lzEqJE$M+2eSlYL5-^AY99%x!?PqOzrOda=o#z3>Z{M)mAZv$`xy(R=)IRd2L z-#L&|hv^PmiRO`vl%Gd-%uc4D)}Y!8y`rR_duH>dY>8u+n$`|Lt{ z{F!K5?7!>&Y0z-%H^>9pgq-#uSR1=EVs=VcGaV_rh`G6p2ekjl3gg!Oj;)fI$RPBV zoW0G`%E)?#T)~8j3)SsN$oMso0U>P;=n`ooC1;c^gR%*-T90)euRTGzS$Ndwd zk9Xi|jN0;#WY9GaUCSaq`MZI?JN4(p1a~$9S97bA`)F)D-~Zo{m2 zk**DwDFFz+TDBV+3=@7#54i|)CV*1P;L7pD>GZ4KABDwV7s4WJjp|e0%dWCmr1C&2 z_jg0)BQ>t(zYm*!gOlT5XZX;o(>Y~wlD_mZ6NQ^lwj7|U9y@m2Q;FMDONtgb;*Pw@ zKH}6^#Hp`r;3OSxoL>cm900X_-gGinN?K{}=4t`4?AF{I2y4x& z&Yd@R%szMQ^G@z<0&0e89-c;~5cJ9x4Cw#Cfl1XZ>RU|WE< za}c)Xm9sPAQ|Q(TdEOgE>mK9^TZ`5VZZuMMiG{;T*%jS=2C%*xS96zL*yU=4Saj{R zb7Imi_8zd1*mjpfk)*%)Tu7@^)^;xst;yP%A)}r%myEb2fT=P~2JdTKA5o zZ8^ia{A86yGfoCiaXqV_Z`U=~HrXEPBqP!&Tm?mQb7v~mQn(z{B5kN_SqpNV7m>@XE6T{uon05b0;EOcZq4kj02y9}x7u+Wq6Wac6wPN5JM*ZJ){;I) zV{1V)nf7a>thHnYL4s1x=F3_gUin3)xTr0X>cwwHG&lirSm6^17&vH6ZdmLvO$fhitztJN*7uuv4nEzD6 zoGpNxpTjfiktbC!sJSdE7!2~H+Q-V*at0(UY=g?gDpGfw`%Q2b1shbLVtb%C*dUXa zwF!>l46d^3L$WQilrk=f3@)o3d8TD z(bpY;xVd{$`egh2GX%?wK~&90T94KsY>(ddSm)9Fk^JEtxEp-Hs{ARP$RK4dk}`jX zyM1uy&Yc1B{B47dG%oo^(I!k0pTa?elHC>04c5_9o&a@}#wb^=bltN>cJ`v_XQF zxtBap*E})6?A+s;+vAQ=RYSi-NAJWO$WvY|gPV;VNcRVJHW5+pX;ANJLp{uzAQK;K z>mq2K`Aq;%ptp8j!gbg;7q~-uoLdw2`MH&OV;rkF^10Ij9s+)Ic|c`ei^I*GZufGR z0Fxv)KjlWQ8(`<$HrVJnCXh16h*TRe46brdhdkTn{E~i6gu#c94Qp@H1|~~EsRKv@ zpJgkmi;J%FC*7DTFuGX7r=Z(pOaY^nM3Xb>PEn=$?UMJvNeXN%D4iKvWO}^%oTy`( zp(SGDr`fZ9*ZeF{x?mLLHO}wB#>J?w=k#cqpko9_8&?IU8yh7eENg8uE9Zj*ezr3@e5qv7ml~Q|o|6q_r zU=$XBiI`IJj5DQNoq%zmunhP$=ZDDs9mr_Cm7F}jgkl*B4h%6P3i-1K1*Kh^Zxqu1`oya^T;P~!NS~7`~Bj+CBahNUV7JX zXK51;cN1Qhk(ondf!AebFp>V~F_`cd$;?TA6!dvBm?$$>@H)ykfIj>(WabL!JFCzi z$+Vio#By_q<%uOw8AbP`=lX?u;2xcMIk`EzAj83FdzZoHbj8~2IzXT*cNc~khZ;G7 zBZ<-tf;i>Z*6i&Evjkj|0GZo!cz0#bdJebyEYL0ho_(=T9?)C8M;W?3d)Dl2@57n0 zZ(nBU<_~0+oAXGN_0W6Ph@Rw0CFfM{FwF|-1Iu%7%nmrmmTNfIGrKe>lt2BcW#>fm zBy*BNP^+n(%j zpq#s-VW~N2o(4js26Wkj`9tl8#~-Ou8JIniJi6|Y_QOpkKxOzvGIDSk_$E^4??_>E zZb!P^LFZx%FJGE6Q{tFpljCI4X@rGLqeUX{L7s3S8_Aw(0XX2@#6#2D&0mwd|Gcz^ zNNMvr(L}X-cojWl|zg94fLln+g z!mUZmz~Dp5upd?S1xQ;HA?-;Z?OB7g7E8afU}F9{P^Qf#P?^`^*vf{tiDSQzOdPHu zG@1(zRiSAeQfUkDSGH9BZV@M!l_Ti19y7g85tmG3@p7)MovF(!obK6nx_c1FtvOee zUi*RoC?XK2*?lm@O-VnpDS0$2O%^+IAN%8|DNb>VSfN5;sf<4H>UGzV%AXP4BC2`^ zZRh{4_$AL@?KlLY0fJ;k2>i^hIww~k`XBh|n+XwF4JDm^n>F#X9D5~`6YI7BR&zTR0C5N%k!fm_z67H%qB&tqMlM?s`X5w9s<)FGWA6UGpwahCPiFok#R_U31B23$`ax~+AyO3F@(Cy@#>TP68rMk zB-i>mgGC_oH#iNAeK|6+slkgB#2f`trRc~Mpom0@d~ru5JKGtROL|c7(j>i=Vf=7& zGlB>Yx$@>;^buY>@Zty_+%^8{^yB`j)ZoP<8^Q^J7oMaUKjdGWcHxEc0vNS&^6QFN zX+uh4B^|wAiF-7bgC2OmimC*FF%d?Rd%;`x!r@icJJP`OCO%^D!ZB-n|FKAXEKa*9s^jK z`};(gGP<;6hds%z>{x0(kCetNv?ND=a<3+@x!2E*l*!DBMfF^;E23q+ZAb!T3Qms# zN=ht|6HSU?Ntv`R&McH4t&5-=hCwlf(?bJHL`ycFQ|7yR0fo^v^r}e7cS+TQ=y+pI z?k-Q=y1zFAO!5bs5B5FuVDq6G*{+ASJX}-GtMgFn!5o2*2iyzlkihaJu-xtGPEP{M z-Im_!Zb`{rHA42vZ%ypP`Hh1-nV<^(|6oZ7`gpYj0&dmsi5-O&DY2})bZ>+^ywq^aD&7U+>j^jI6w;}Ou~ zxgZ0Y_O}M@Z~pu-D3F7?)Q!WepF4OXyB9myT-H4U0PMT$#ws^xOQ?-)E^0$PKH%Sn zJM2+B((ctm!iU|VyX{B%%p-KCek+^XA8)OjJ4@_JAA&1Bn&imbyf#?XrnZh|;Sxt| zt{3^~%=$308Br>233ir~&UVeFW{=1L=L2n~TORX24Gnhq?5#9A?2G1Fa zdYDZ&a6%{yKE>ab<@yt{T(-{@L3HqQ*tKF91xSe>xiCq?X#f#(E2KUVC3ec8_)0yXDH->$X0DBa}2?Qpl(?~rGz3~x5D8(-cu zp9h{nV^KM$Pyq*npo~SS*gQ0rQWle1#xnmgWILHHL$|r6b!Z&wX3t8@B8NhPMO_Tj zJ3M{Ne9_I6{M6OyHGx2-pM>LBj?7=@jXkB;=Qq^t@)Lu~(BhkP7X;l_FUI)-!cjxG zWZmL6J&&4TTV7&YhN;mb7zb?gP^Z&XLw|+Gy5S?X6{?}IZI;e?IO%5Ia9hugKAvFY znX*l)E;xreiQ5a~as(t%r#?CJM;W2gS%o1}f!w%iFIHgT>Fk}@Qw7*ogI$%~H|^?w zVb?Bww08~gg_|$D;C3}$cp==VFu=HO-#oOd4&d$D-P|>RbO-?M-Zi6=r z8CciC)|epz+bf>!=#&f5?D>Hb@ z@5}G+d*J@&168!YJ0EO6&;-!>?!7Mq)3Uq$UFn_K9sc$Pun0J2+kwej(_8!(lA9gU zUrJ$r93fg%_B&kBxRItN)m?iKknYWLY1`2i+T})=F(mlK1Xt;uf15TbVd|siE7t^R zYU_k(KB z2bphv-@N%y9S~$IU_~R}2rwX7W$rk~Yd0oyn>Qlx-3Z><4<+wYLpUH!~47gJjxwqN5NtR@9l1G(9c82U> z2_6tAL^sKZTY0uTbIM%wB9L2T<%4k6b0Pxa%q|cJWzJnUyE{@o2y<>uh0r>U(|l-S zr7RWL<1QTpoq2c6Vc{-LJ_0NF@V{pZ(jF9igoM`uo{gInqZ#fPHv)K!8x`3$&JZiw zsn@^NgM^o15q88Ke5H`17J^epT3lOvs0|;I6?GwC(=Uw*U}eZ3FB`3G#p>lZ3viqY z|3MQ6lKf_P%W&Va;f>42u@c%egq16DU?XSM$Sd!BRX836I7en`uqOzf3Lccl69!9D z8R8WRJcwf4O_iISc>_g|{KYnMOwDvi?~tG()ngP%20>>DDtE1$6KcT%ez5UdA(+1& z9gV;&!+F~z^jaSVyR60L+cLc1M(kHYW`g&h@lk4Xa3OD8i2sFgA!V6_7akGS zBefMn85qkF&K0}Q1(Mp7X0kY;#0xr}DbXZ5yu5z25CJg4sKpGxfDoZoLK|A7n8s9! z)*e|6TmT!RD{9i!I-o^OoBzgL*$e3|_d;dYkr!qOEkFrA*^%w46__y&vbbH-4KE^A zw8=r47}wgg>RP>_83ouF=FSxCP zwy8*H>+&MMBiWfDvUyO$-<{plytjGZ8jKXx`yaS}%;u@L?yus8Z{ODfHJZkRGMJEq z3Hj~GZCO`Ub2ouXphimZg4@{BLtKpmcuqaQK_4hZc*+$?|EB$>1+2DTsL=WURH3uX z5uxm=hYXpG@9noW7D?EFIYLhMk`B4=5AxoE9w?g*_;9c2tv7Fk?Ckjor($P!EIaB2 zBhAC|@3jszsf?h@4C%)JBAX+K+zE($!$3q%^qRKJ2}}2kkyQ_@CNiB3H&$*Ky)n5V zyOFL1#9EG9x~GC}UAduo<81EL{raIkZdl9Rw}CzUg8tBrlXG!g%pHZ@%x34Xtwcfu zBEQ;6D?j9MHTk89HK5dpLal_e5TCR?vtRHIis$6)&^7JPuJbQPBWI3WM<`?UTasVn zJ|UQ)#x}4W{}I)2CB&F27(Mf2!R1#VjHQJBx6<0)^|tpQj7@7OvqHicUWr>cOR`aq zEaxzqsqsl@pBa`i4(MiI%UUv3z?KSP8`X zevr~tb?cT77|=io$|i%3R%n6hz$o2~(+p`s;|J@9gy(}jYgUxuqA7x%s~%hG4qjPw zk#v_OWXWZUP`sOxD)^Tm^oKwE;R`P$d1`777n=63pu`oD08*S9Kg<-^0RL>}f#sk> znhwV~3}PZ#AT}>fZ*Z#TpiLIWd$csgQr4L^MhF$;wii@+hx7U4%i$k5DIX?h)RFvX zmQXZMZnQB}G{}VU4P=J*gd(PdzgOixdWiD~KRhV8RKLYN6~0fFZUCa%@FR!w00~dl z?-mLkjzKvnn)D12J(UnFZX<4u5JmJV$)DYM%?yiPLD}CT(8PU+b*G9hp_7~w!MPrs z6G6K}Ju_hHzxLW|=MdIppAfl8KjlB2eujh&+FeFOlW~dVXm_po?FDzyfv0c&0>U-9 zmq_3?IoCYk`kXRj|Jls4K%Oj+WV&olYS1KipRz!LCdqW!N6`^4$$+L%X8f)an!166 zpealYnjZ8XE-qfN91v=8Gvxk24BPb30&8cH@~5f+89Tj@%8E z8y`X=5IQ;gdc%#|xX*JieT!q79vzSi=u*{VT{P;(4i>-)a(F(!gMUyt+2)eLxcw|+ zL&BORzRs3Wv`U^)0+r_3yZ?``HxH8QyskXw6xCyQ+n#Pu2wMRK6aX#~MUmP`ai{i$ zl4a4H-?`t*tb!ad0VJwW1r$*E@|}C`Ip^Ll{}WKqh;4|Zx5cxnQTB7Y)ik5F|0>;HQh{wj&2<@ZF#MCL(oKSZj-S%Z- ze|mTxiU2wpkmHo0cw4TsnVXO0U+AX5i_j~>_k?BmNDu-j;qWSGQO7^ zt%&yc9e66c`V@z;oM@r0O(zr_1`@}?T5CiRu-1q})jO?GeUT@-Cuz+uLl0X~S&6h8 zlTC=N0Hy0n>#0Gd4eOgs=F|Qi*x1_8fGehJOKZ4)QfrQ4TH4r*B2NW!Gnyk$1#*R$ z<}HW7e+HvSNA)CgZwXr3j1ZphY+dY`b{uNdpE{jUooG2{1cO^TShpjkc^x~zOSIN} zvPt}Zq!?EFLjG9({Md7)>(7l}FH=L3Yti+mu0>Z<9{YIzi_{paEc>sQp1VHsT;uud zh5W^sM0t#(Af?Q|QeiaI#Io61toZG3<7R({`Vmgz>9Z+dNcmfDq3&pv1uJpik62~# zuT?x`4w+om_J)dMcx(!oc~)vi+Z+Oty?pvEt5dF9`RKe;kiXdJ;%T%c3i(LeOh-trC=6qoOk42L147 zXke{bQG|d5LD8%1qXZnJ2&h?64M64Lmen9`$Ma>Y?fsa(zt`5olq<3l&{o9U(pzV= zE4Fb$OIYP$nIz^}iEJSPwJQ!btm7%oo1tN;V_XaWbtHEdcS#?jX~B)96sYsc;vZp zpsPLY{Yk=$s(CNrl#h<_!pisC*}*sWlc2rYk!kTugA2Re&RK2oD|jvu!h4^Z5jrgs zzU&)QyuoXm9^XWa_AYOVWrQ(6ubgo&6;iE8kwoKkUu`GZ#I|VSB=miL{Rk_5%~#pJ zeOztFwr%G)W(Hv2I>ZBz-@1#(Ujy`+f&JLF;q5tbw1g2Omg(~}$Gk@PZ@`*e)~z5t zOhKo?@e;9&hFIcF#p@(wO%T97R_I>{V6?V+xgdeXgib;TZDy0TFn*{;JiBLM z@k)so(;ScxATCCi5f>nztx49VCxO-xHNWpwq1mQm4S7=~dv`!!(j1eh)Ta;-iY8c_Jn`Pp$ zOgue?Pv+>grw4bI-Cu_G7PQt8xU70q%zlJfC`HFbL2BlnWVk2Nyqr0OkjLA&LR=$NX`RC{{X! zE|#5cJXL!7sgqAvo}wgVPnAwTm7GpbB`5h4lmt&n&>2(wZAyaQ=L_|#MlL=y6I$KD zzi*uc9WtE+Avx>!RSvwe@apyd?EhErvLIREmHZH|IRXGq1tAVoK;5=2`KyeBWnXE%SbBk8qVhbs`m87phl}E{kK%C6ibK4< zB6!T!RpcG)UAvE6(qgB{nwyjXUM-?(zq&PLe(zUDfZ44kvG6H-Ykyv!a%*PW-?0zy zx9BbOE8aEUgKfA9^&k zXyQ96Q!zx1x*}B_0`Zq%HIx>xGfZi+PyshxQLm7nHcYY7quL`i9W)V`9P+jeuzdS% z6rULlh|b=`gSfXxduIdt%1KG_f2P_{JRe?A%mn!ds(fpTK)d-Wx412#zmNdt zZu`{Sxknl6o;G|~RaCY4s^yiyQpJwEm@%BUMkrWm^WO!q&KGcxVg; z>AW%>8e)+&j^Dv`$wK^jGa?w#MNI25I%9J~pfLINJ=>mov{&sLFNa5&_C(Oqsd>@@ z`4}G>NFo z)Jd)R#q}k$3)CZgl@$q=OtLED)=Q0i?N&`%w|*zhJ&i`PrnH(Ol&*?VyV&wBD&dzW zR*C!)zgUu&Ul5XM{(+c*R)4QY@@iKi{x@cv)jqESeTsg=?eEgnl;Gudk;5yjd+rhy zqR?>2yRSB+XyR1i0qUS^=n;Ml1-xF;Hr@tu*U;lFyf9K5`SzS*<7h9&u9c}YC$2_Q z?rP7})YR3hSEuYm%Zt`18Iqi5lfAb7d!vUjd$&t=b- zUU)vXHYG;qa$ifSL++K2z542_3PqXB6*`p=i0*sswRSafZ{7^ewrWHzGJnSX;NQ%U zxo(I=htZ#+RguhPIv3qB#b{=)f{0Xzqg@6vP?vD5duOFbeNVhs0vE#6L65-YkNBe$ znBz$}kT^TlINhsLIe9#FI({lb@rsy!9X#Ej8f8?Y_*i_@Q;poAxKOvKZ7emb?eaTm zh)miNZ}9YoVMJBcNd5~m}zy9?Hv?mTL?lWbUegtdj!Mng>e`x9yv=y*TK(}*jI73}r09`RO?J|^n1IEv+1k=N zYg^I{2^$sEvGfTUzy|LASh6<*sb1lHdX~8MfAZXfUFYztcJY8N7s^$O;J=hh)2^g8 zh+wpn&*sH)+p`VW!p}jw>J8eJP;_4Z{P{EXDb%?2E5Pmox3IPd-fu>}TRJ=Jk}c|n zU&Z&&b3thJCMz2%_CCQgau zvrU^$g&Z9)=(pCX8rbvXr!*xmlS*ZSVf$4z3%mw7iaps&9x)|j&caYI%rB7u2hr8M ze0$ALdxlii;(xJX(XJNz%`DLlyY}i2u=B>;a=Tt=@CQ;`_$8_nU^3+{EF4X(&BDmn}7LDo35Zj9wM zrgEZ8RZW?4d;3H+;2Km3r9Tofi2n8%uA#=Ieou^TAEQl$xl-2WJPevIbc?Fg>?Nj8 zdGx7xd5m?RvKt{^-CDD2ZJj%(qE}14CZ{$e12i=&5_G7<8Wc~164Rg%lcqt5AE@6S zbKN{9R~QAA6T*MuHif#ZKM8e#|EJ$qwz9xt#Tg?Menc3j1UES2SaBfh&W9|Ys=Vd8 zQi4xO@IsO&8&9nSokUPp~;IeRy~J@(3jM{9@CfjZ`921=r_Fz zrx?fzenlC-ps9aGZm{}wtEuPe ztaKFEkAeM|CWODmHIW7HJGzt~;~xR`>jWm+c82dXA-r6RxYnOe!~So6Q_QkRm6~}* zqmH%u{Q~vhdoLuAXUbBt+_g1_Nm|_YI&OPhXi_nd@9{5Qddb?3(u-^yY+!hKGI~_( z=L+;cQK0`Y=>HW%|9oAG<4<|*ssmWN({LY17w$KC99Uh)0*rW6R;^mi>pfbPtgdP_ z(LPK`Saoc5nJT~^f*4`WQ#aIPjI1g1B{OB01#L-a?Y&z2l$48|!=sgQJ+}576!0t* z5fRtU=H4RTMHIE(t2$5plv42@WocMbVU9*vhN603n4#)CRTr$QP+_p9;?UvGfBy4x z=g!4NcDHxkar+&2+{x{(VL4R%`TyeH>9H6Y8`E10xbGwG`M&m{ecEw(OXw>)!j>uo zLIs@#Te&E7^a3Vpd21_owYF4?c292y%f$B zQp6T4z2VTlI#00FE4OmiO!dk=QlmI@Eh@w-bQZkUE*d0y33p#@x|h)0oi+?e@BaAQ zW5rrX|3-2C%^h;`>Fy4vECRjB!4hi>L zdxHKY@8(uMAu&upc~=k4@ZCCV`nOxRRI!k<(n{kF)=PojTNK zdI}x;sH210OTOZkmOlcfeps8}`lj_R=GJ!iw53tEzuR6*QoB4WbvWynq7mCf3}Gu8 z3l$9=`Uu8b(WozqdGV;Rh-oYktSA_zRRh_o22`oOc2u22V|BJFA4sSc@$!@=BF42S zEw*wW(?^7Y5fm-;5usox)g?vC-4@TiIbx`wRohCwy-|F0u?X7Rh4UilSETZjh`Qd29kJiz%LiMQc_Iu=Xcp8WVhdic%NRFn* z(&Ob5$B$nnVZoT8AB1*k*Aa| zYZii)5gfpeNw=C_W1|U3_d$e}aVztWmecCUR(2jmPthpgfOo%1N(X6*>jUlH{0Sp5mB4dEAl)lce%(;oWOrB%qc-CFU*$CFi6doNj4(I1Op+=i-6 z`#pcUC;Z*jG~=~ZJ18#+MWrICDzRKwgZUZF`{xAiS>3h?^d&W{oo&GAHjZhdlwb~U zsa>tAo1ZEYAu4>lP^N6>8Fzzje>ePDQO2?HkQ1i6uvKjq^wfQiv32;!=jVQ&FpXAd z-f;&vzq{)bch8tv>68)ofLe@ChM{Xndm&G?r>^T%5e#P&r+V7rlm-W|`DY$a=lLc= znl)zVA$`30#7#&x(rolVylFg9dYrQWQtK%y@&XbhnEDn^?TBb9w4emv#d_{X*%$_F(HXcvCM#s8BdQd+gY;qZAJ9;sS3Vs1_pa z^c89==qsG~sVaxMU=COSWt8^~DXcQp+}9&~I*K5f6|^T-UQ+u~sDEO|ZYKEJ43?;F z#3nr@sFA9$>t}B;`yM@p*B{xVXl)-zFA0x|vg6T{8X`>9pfSe(b30g?cMoWUiAH0P z>24jBb49`RxpF%uB+fS9$~|hCG(UkHpqUBrCF&8AYL@7eAzH)gg!$w?k_cA6=Q! zMa0Wus|&I@{KAB6wz>!vg}4xxVlGllQD{efZ>1=xx)=JAE|ZQCtSBz$cHw7-D({h( zYN+QGE|s+s+Tm9sJx>qlr58&1q#2Ak`HE|m>gATo;AqiB3@c^O+7?}J1|wte>b|Mu zN`2~USE8xmE7F;$0#jF#sp!fm*zc!yUM=HlrtD*dF=TTkh?@Wc&ZS!Nf4om&I+zBn91wd{k%|q#PA3!-pRh ztFApzpgvufn-jsTVFIgJC3KvvZDz=p8)h#k{<^Scn*c(@9e4Xj%nL&1bejzSZqAU?PRX!@F|FttO^Zv ze0I7^u&E9kc~_ed<`mnI?|yWv+JyHz!CZ9-Z@=Zwry(We7wOYrk2$-KR){(sI zk%khaq4>oz>ku-Q{gjEsHJ%&1Ub`0H{+R;qJ#hbZgZl=lTWLFEYYef3TBC-~hVKIR zI&+(tu85cgN=VAL~)%+pt6(2 z!cFCH(W<4SIMfvhX*2@=I+zR70+AG=&OJ?&o5!6BS-$UI1b4x@fMV0V0XPPOTOz<*%1t}t5SKYt$@Fxn7&4)`zD6-B&KTt^ zG`1u<&?eS&HW_)b{gKDJ#rpZ-zEHz;Xp?^_@6JfA*}ljrWP8j}0P^_KZY?W1cn;@; zl`1RS7Irvcv?E&`^kUXkC5n*rTPbsA3W30Yir3_-<Wl_D_TqoI(1I9r4aj7foXr z?Py!upn5w$8_0fe5j+Z!W&??|8rct^j>rS3r??2o@&+!#;J}Ghg9AAb-arT{Ed|As zM`EabX%Q}ggWbor_A(|I>j83IBCSV>Y18=EOb#l2o(ptq0pnI~)vASPEGvlHK;B{a z%sdX(I1;wb(o5ls1-U`-HnmSUv9Ae+%ks&;pv3_!!U;>>2Mh4rt)@y)b`;=8xXYzXu3a`vbgzWd?7DZpNV zrp{t#D1I^RK7-+#P0*eIoCbTTLsALZsuf-ZYz!T%kHYTmpTRNQi zdqWLC7eV-S^U%@fE8#k8W({BxyB%peJM1LuR((>X@EZhMu))vIO# z_=l^-_L6XFsxY4azMoeEK_v7jqx5O?uH(mr@{+;fr+H@3-s>gK*8wq@jvGz*8#8F#Of0w~PS( zn!UhR$a#WU>xGw$(;_cfkri|C;R}j5`Sx}|0RTe;!&-mR+tz!adsPU7PQ)?Fz$?aF zf}#k-NQa0nW)lF@=!OU~Sjq5k@=a2F+`<^e2NU>_G86r7X=&NgWLdU6T~S)OqRIOI zmHM%JAi`fBUfEcYBKRa$5)vc!@dCccLoxP%VyZ#ynXU&?drEV02>OiLTMWP*=n2$b z>RperXQ~L|n{}{AGkiLfO?r=}_~a3&B8b(S(&OrMWKUMqNyemA8(%1s=g1)TW3*z~ z)rus42X)VZ^k{1QN{?YbF#n^=-2!`lxXV?&y}aj28M;3@Rk}LWysD82l1bt&IufL24R{lGMDso3j%dE;*yQA3=@3jmJ6z_r z89m~TR#@nN#2<}#*BvPzJwh2M!z8oA`Jv=sd>}z{EA2JLuWAtE1*;lp6?Lcv-m=1~ z1~eQ5+f@yuoYIUu@fU4*XU3T_#hT(`63@Kg8z%AGyR~=R+uflQ*c4ukSQ4iqSS*QC z624J=^&1%Ro&rFn{aO!a(c0neF{?>31fJyiF2-Q+guO(bj8L-XU%Hh)qxy$Z@PAt= z_zk7tTUH9{YeQKp%1gJ^GFQfE&O{ z7^v|FJ{>+}AJ%8=&+2cuRaN_oegMaz{o7Ro{41*)tI9}462hAtGS$vRHJMLRo|bMR zr;|vSlhCoHPNpKQ1PTG#y3|W7XHM2|?BPQ{VOl`jwj>L|k7O>)nHgEKq^v+;aGgPe7bH5FD-C@BmL024K4t!5qyS+iLyx2((7 zAv12(8=fP+FBTtB8f}W)SuIJdFUqMRvvCUehU|OVMueuK?@fy~av<5;ep6d6*6FmbBP8j(14^|7`K!=6s{AKvAnFjv$KfaBAp(rIc zWL`Tbqw%7@S(QWwqoJl#i?vSwCUXr!EkRLGF^Tc)w7|gRALb3z3sF;IB%qQ;=eTZ= z{+NP-JHC0-Mn_qxXwH$-ZEY0BqH>LOWooVFKkJX~-fH_jw{G1}>0p3wGX*u;@>3pc zaa84STe_`aY}vePOAjrDc?c~+N#Ynejiz!)p7Dp6=ArZ?MsppbnH$x5%`klzd_^~? zJ%msU0Hi1E6_8ZG#yxx|3nER&*@A3Xv=H8^NByqEbfHi^6!?0;+K5m=@Q4>t45%Qb zrH>>_^JUHD%@wm&G6QK9>2$n%C%RqEsra0vG&9__8rZBngAc6sNOiUg+SR7KWwgRE?sgpy|(@44%q zq^xIe;|quz2^FW#Mt)}%N83hfY#Z_4zFCe!n7xBWE7|!*jb@{_SVyesiGOc)LU9Cl zv0ST|pRnOONlRf-m1ua+d*hDiU|n!lUrmQ{BWk(?B400VK%$(-^`Qq8r$z_G5Cof$MLB}gW+EB z)Rq|gz%%)fQdBJA>e{|RiyU)wEiH=4f3afn3yR5it(Xuz1>&3?K)+g6GebUj0~ruM zvZ|MA5PoJ9ixD1w%VTh$D-;Z8@9@4~)uTG0Kf2qjgismeL#O6IhtqXogu%EHsjB zBX1@k*~l(TR7O_~Ce-dMW>Jmdp<0itDG1L%c9#mAaz?U(QG2&ij4BGo0mX@ zgWSX)U_HLI5RBfLK}Z4cUDj)IH_J4R*k$QiAtbdJfJ8me6s>08W}7Jx6ePI0dV*|K9JuP(>5e~GunpqK*)=fCY9oq+so^Vc0jlQ zObABtAYaNckD$msM~UB9hon$64I)wY&CusX1KF53U~J2XBR zylu@_4lnM&%=qa31IFbcMLN3e=xqXPJYFq?3MnC`4unR-owinLf*NW77 zQ~GNL*E%kVZ4662IUm2czrg9RBhWq6ZHDdrK!AdvTAi+;V~h2}r3JPL(`RcMTX$~h38IfqK#sPIgUy-Lu+6gz#1?96MGHr3 zZ9c@v^C%BzXS8{hgUx)Zw&^J;MpBc;*|s;tp*OMv*k4F!v~Ho%5H9Ya1yOtnBxh}e zthoesc|x1#9wsY!kt{Mh?0*^&bl;tiTA?8UFw;<#0PjJm!e6> zjvC%ry z&SL7?fm=fxa^Ib+32L|!pdFP#Xr4Cv62fF^F9~X-=Knv2`R{@GZy4qa@2k>Wg772cM)6-gB(XiQDZN6;Awqw=4mK+w<2-6FoGrE4G z8^~^VcOmz<1GjYKo@2*Cg;3H%?m@_rBAVPc+dBFOLW~qT&j}X`7E&R=?XdW*hJRe> zJ$_|HoSyyG6bMur3Pb{>SCR<@i%sC*-tgv{!J?qCMVVj+2q!O8E&k%e;)579OvK)= z(AQPv!7GTD)bR>xz)9T_p~z2&%57PPY|33)lHEs@J8_aKar~G&`bk?|5ln*p0u)jC z-87zMtYC~%5kxoKUno1oZ}Av=G+CxOBp2UoBU`+x<>66Ce1FH|@UL1c@ zPSwcUC16PIv9_)@kapy~r|qRmo=FqR7&kqHmKT5yNYQbRQ2H7T`po4xDCls!*+oxh zb$~{_f7%l`9H@PjNyXbK1%z+ziYW!6_c8`V?_=nF@^B2d&!_{9C5=Z~OZ(`&L=bok zFKaA~P;Ukw$>H>6A_noI(!xav&Tzs-D?NyglbDVZ6a5ssr`FJb#f*^QM$C0b{%~5x zxxpL`cVvKIxBZrd|He&hX6`RQ_XeDeoD>}y-#t5%Um_56D}WntfBIro3x|d zRT=$Q#IpAKmh8$Xr2%DT=VZSX1%3hjKe&XZb7?F{Ik5iLWns$Yp(~l(f%Iwu?n|PH z@dSD~Jn^e+_al7xQv9_#rtr;*f4+)(-5wwdr`@~n^}ZGgz#DHkgqn)b-@V%l7KY%b z`_cb6(;Co{q-l;nt<;dDB>D+~v6lfLY#cw%(B{n-mPjLxuY*rxu77E#!GF9v-IMMu z?c1BO79TdSZ`b}VI3q8H9s64_{nDPj85JPbdEgRi5}tCt#7K$lD4mW1x2ci0a?a#o9uJZ=EQpSduHV&fqGF^Y}D22P)+*}4wr&ukt&yV@kd6~O=R4g9|k z_`hS|AEEizV6wX*`U9(=^{euM9^tiM8%0L2Ep*4_(z}h7(ZDetnUEZ}OXe4!$$@h{ zR43AbGAd6Ds4Ey$CNGp|i~wL)xKn&tZm?sMatyF143lc)s)mFQtUS?=U=So4@&3Nx z1#2{*H~|dHYml=dA^mRTGj>=8w}Lo-I4y%~$i-8t^YCGJr0eLhW5qJ*x$)!e4Cx}}l0Y>r-qWI# z!CB61(DFBt`9%BbwN?=>-yj2w`JHNJogWeBSU}OY?9mBI+JUZ9xOnfc38gxX1Ms9M zpqlW=Hq|%o=k2jgwatl+M*+;k_S4NnAb8W5yrrj{t^L*%7=u4#jY718V$Llb+&wH# zbk|G=jvv&dA0>$HpN)J=Z zOA9c0lZEM`d~s{Z*dtx2XDDd#(i#c>osSGI$rk5}QYvl&ftQUNqszqi(izN4KyK~3 zLj?l46JziE%S@mhs9_$~kP0foY&78=5hAbViE5a)6`gma1O4RQme}CJRFTveE$t?> zN-Q&dBEh&#I8tOg2T_64&27WVQ4Py$_gl)ivqR|W(d8jP*-h@g^s$SVF6k!^ezD)A z7rVmm^NY1h`NfKUlh~V!?vlG$<_u5c`_#uRJ-g^Z;1M%-Xv2A z(N0I?$05GQmg=mN>DLrkpz~dA-9|y52+^ialK+PD+biPoVQtZ$DAH+DU^7G;NO4$P zRD?R+hZQ6naz4^*6y?`!hcnTgeH}D+9RJHA6I^icJVvweI}*5j4wyIhR!s?eW?xg_ zo$kqYr>4{-WpVv}onqc>zU0c`iZF5GXU?fnQ_;cTLBK;GLDyL+jmRT3VdhBOsN zE+)^Hv|hb=y?)JdTCJ%D39SI!XAHQ%18~1r%u1p)N6P9j;L4 zTFjAjt_r8S)0pJ1dCu+TE-FMM4nwO=U7N1G>LXH5GrWTk}-5?-{^lH~Ut z|I_WapFAm6E$u}L`OFx$(P||%q>-aE6nXjCg=ZSn7uWbiZfhF^)Rw~5v+1A=RWWN` zeV!0$I1Gt7YK+sEGlVd^kzR68I_zsm^gZQ-J18|PU0$Rgsqe7wzGRV+HDBb8__mn6lpi!A8NMFShQeX zw^eQFFa>Pu*oL@R@E{$=%}aS{poZTcKah~hi6P%PfL+Gt&KH-KEFOo0N2D~fCD9|T zC8fn+cA4pnd{IWOJ~iA<9!N}2k73-g;dWxU&A$ZW4(o#~G3)n(A^4_jxS2k@b5_Vx z1vy>$8&u;0za_oMrz@%Xa45?jy3L|j=5pB&N0c7(dyw#Jz9mL5ahFSzms^uvmrO|+ zx)g!MT>|Wjm;UNvH1W3=qf4HLvqu>$KXj=H=Qj5g&Rx24IYm-uns>@yjiKBmah#NO z5Ao&@b9_+;JUb}2d!>fjasxbfA-9mjgitDrqZp=pyYkMv@4V~Y`-@`I%5s>~SsZgl zrx~}b(YCBEgpOx0?$CG%p@S_N!?=ae9>yJuamPE;UCrHtd#WUcAbvGb?}?VuM|?x$ni~h1j+( zB+O7LUgI?-aTP<9Tx~v8x-ykvV+Y7SXOR60kp05~vOSy_u>+Po1XKfIBGm_1)=3qU zIaC~AC25g_DI(rsuCPKjfH&RPM9@(NN}?5~L3L+hOTp5|;M)RoQkXe-F8w~U{U({I z?1J?6>2!7GC>cfN-gRFf&kZqjPYQUDe(QapI!|wa^==6$^v|yO*$%23tcT@tV%&D~ z?g<)-?%Z42jwqD-#EBF1&a7ahch)d&olu>|C;?T*C^arqGfelzjs^|PIGizi3M3GD ztcMJ3y-BYSVF^YX#yO5pYr@#5PjBIvt0b(ye3@jCu#~t06aeFHVFg_Vrmb<=>BW%B zyojn9j0?o!+A~qSpxQwkkvhURs1`dIXl|qojBA`P;?)>I8zQ=EniG3H+Dnp!5CU+K z?F99__Lv5r7>6Z>vX${C%;hqDeOoM-EsVJlR=wq?tol)kM>>)tX3)<>XtI8qI9 zC_whRI!4137K9T+=v|w7g8jK^)1Ym0YT3awDFi#&#_86Ueu+s=syQwxIT@pk)`e8S zw6>koSTUgpzYfXCZWezkWIMfvr?U+*LMORJHN1$wV5@xo^Vp!%3|mkQxN@yigKA7n zbdqdA1D&L_c+v3UNGbUxi*qWjUs5$=WyF9wRs40)A~cfHf`#dV(!-GL_@NZCog#0g z6ygM#B;g9Ccj{cJ+Y2K!BDfc^x21=c&&JlYM!yDdYp;UVl|e#Oa^T&#xd7qE*(@j)(GjaN2kJvYli#sosCnqmuIHv;j#^oFVCBQlQd3-HF zM3GAxaxNCGbYG1vT&X=g63}}C;}%qXM`w~o0QxPKtTzo^5;_XHdpCk~_Z8E#ux|I0 z{-1LAc9E`kAAG{*sDg&l*$CHR-3~keZ+VrlfdUmpFOir+E)}ITYQ#GkPj}>CdTIBr z!QFb&TYGBwrePt+@a}w9V`sV}g?RhX)GSi|ek)-VO?a-u__Pu_F})n7|HQvDJhuS7 zOwx`=Y9mrbW^x9gyC3uwLsI%?-;Un$Z+3SEq?DShp_g-TtHtL1D=e)b)lzziebDs+ z$TMP+`Smz>qWM(?n_?k&<4O~MBw+YO!|)fu@Shll*MlxjelbD54hRmnKGcS47uMV6 zD{3o8S9F8f!gR&D(iL;;clt#i(-|!}c%JeY0nTGAxGY~7oQ2{s|r})Z#v!8Bjw3M>B9|>epnlIcmWJ9uAzCB@0e)SEZxHjkj<4|*x!r%YF`|?3&swW2Izto`t1OPP=3zEBk?7boK;vserW?r=d za?S`*SROu2&?y;g^YdgZ9d82UrCmFRcSR&ySf``T%r+r(=qM(mOhY+EN$w~1r!D5h^VNp`x7}O) zJOg6p?P*sX&B-_cqIY*-Px3e%YY?D$xG(AcYsuK0qWffKD_pT5#_bxNyCq-~x2R^Mhdejup}J z-F)2WxqZCO=a>rdfcmh3Ivy&2Z3wXfWY-{74ywB~-CB0QBf%ZywCN4KT6`{QXTd*3 z+#N@w5tGC4e2hVy=EWmqQG%KJx@Xpj! zyp$D~;^NC$vRLLh@+(UN)I`>0vDV=ehUmg{jndjA74K*hUACs86?3=)=vaPLX#lY2 zuj;9GoyCj9C6Q+Qf(qe9rf68g(vfCL^Jb_s?vDTC)E%czLF|u9p9vy5`b=jAwhbaY z5u)}X#HeT-&y)eaYu(ap5^864N?S??PIUXI;nV~-Yedn|yS8uNPBPyC`EotQ>o?7@8?fH!!cv2bl{jSzoQ9!od(T4JhcdzqSU`!FDb*4#p~ z7;1+bZ^Zom(8-y6UZB1}AJiAWPmp2|OUwuLNHLyBOniTe51Pa8D^krG3wA850Q(C^ z7j-RMxCkykwy=yp-h{~K5c%|h(*1>So|*s?7r-Cip4@ipTy~(&4cOl)(tiIetI|cP zDIBHP8~8j8N_$^_!2g)d28pRKNilVAdM-;KwA&!&!f6JoNv3H~a!hVjU{GfQZN=1( z37>54f{w%Qhc69Z^sxBxiOPkEi3<+=Pr|$LMD+q6n(!C8`NRb8rxz-E<1R!KiG7fd zPQ({-{?6fvZmSs+6FZUIVg7@cS`yfkV4G%FW)pNr#bFjpkK~#SRXNjf+>3QmGn%KB zb?RQ}GT-zY{+l%-?(AFB)|_H}0w+Db(FaKE>p zpANNxVo?Y=s3$n5ZLM9e8c`h2Zgw0^s}!-Z{$w~FNk&U!qbbEgxq*B~S+r?qv}>OU zH_aUlh<-krP#sc)o7jXKc20=vx1&jH z9XRa?DND$hdJ|HS?(P1Lc++0qTnRCDHcSwSbgw25e#tgQ_*p|lePAht^mX@KFQwUz z0m2`R!#G?j-k)Bnkc~pVDN`k~$ujL;s1#SNQcUQj^wHzLv|>SKU4u<-6;Y1?)EtzY zl>>X|0;mt7`{R@bng9mI32*Sh~ z1=>@}K^>M)0?$S=AC*<=9@F-lIt{%RCpg#76%)l*04|VxJVCl#HyFty8U43n_-)C? zq<9hh;F4@&j)ECk;nCz|--&wY0 zvb#bNAdguE^sI;oY(k2JA)-rP=7DLpETJxskqNy8#WqW5F)S4o9q^ z+teV4ybuBP8t~wu@SHZuFRIw(csb~o0WyzZJB)rDJ|7{nyA43OfjRr`H+~0jZvgb&0(3sQZ)1Pp^eP1#M@X@k znQHQg?S4yUV{REsRdcSnN5l!(-W|ktuDr6$rKGUNGzBS;pD_Z@tSH=G$81Tj69GVO z7o9F_QVTwE9(w`uvPsDz79vjRUSs#k{W+3*{?OpVGH^JJ@4d8_@1h*mVd9BUbzm2rOhW7xuPYAN)=<7p_MnnwB4U-sZTq?uQhb~sc+4lh6U~~*d z=R8I))Xq;{C8)7hxJ*<`c#rpaTfRW zda=n2xcRnx&ri>sIfA(cL2#tf#rnj><5#fcsL!&Mw?@U<6qoS8s9NEo^B6FEv+HMo+HArG?;}|de~j9bpVcW z6NrR`6zg>1wV6VU9Bkqkp{!O@ZMWgzXEAkiOx+NIgA7xI7zG-*Pj_;g3a0n4uHyIQ zn6`&eJ1BkX)M+%(0My}3bE)fXk`9(~dukb#GnBS*b4rVX*^?InoXwBf<&678WaaE;&WqTKRc+wKQ)vN9+>P zqDjTgy?LJvq!b+yrIQny)4MRR zn-66V=74H?Uq(I5h?)S*cO^(AAtV?b_3Z;>-N9bNR1$1}YA>%HD~BlHZikjcc21EE zuBCJ>=_P{HD*Hb9X8CSiUFX%58J}j$4ue2B5_n@9gS6B_$t7EvXCVFGLf%q|+q9{I z1`bsQNiU+2T+AoB1hW$pyDmiM2YI9yW}QEO{(}ABZG2vz=N-pqdh}6#b3Wq_9s-p; zL>eZ&e*)igBDvTt!i>U_UMfuj%!x!6r_s(FH_AZSA~ zI7G-?sPsKTDcY%yM6OXH_g0Pd0}-BQuMH9jmHm%D*TG~_WgO2LvWgv;(jFx;gzV+{~FgA}KO38XmXxz|qT*x=Z!!!$Ru zYH;j6EaPUn-*g4Z#C`duc3KiW(iLT% z7O&wEw#qX3Elk$rw>0i>&T7!OLNLG86Ux;k<7~R9CvlHzA7A8pf;KW9gKJXPZ%&+jU5@|}N z)HzOsU_KC?LvqU$L>JDw$;qVH?obafuU<2PV;ku)(Aucwm!dJ|Z~(aWu~3Q+@N#hMj)E`~ z_aj%BbO>`gKS34A?r%KMd~gJZJ9_B&!*-I*&_iWr%JK&@DIn?n$$b@8`k;S{DPx!3 zosu6+?nv0)?B=?owIlv;jrkvcpnJcC^@$L&=*Y0V%4>9taD^(3%MOM`Vchwf(ax;6IH~HixWA7`r^e5T|CT%#+Q>T=~P!+ z;t*gv27@#eSS3&}gJpFJsZ@ zp0P5ojG@scFrFE!PMZlZt|KCKukfPcMqvVh=X$o3?+&eYzxnrt_Wi36A#4xn&+su( zzi*H>diXAlSiA4nAl5twzonVm8$SK7OaXO1V3L0XOeIMi>Yz7y=s>}tYJ1|;wF z^5Ep)rFwzoFBz8q6O-}V;FVJEGP>RHSy<2 zgojzsn&CN`oqPOK#h8zBDgt$0-@1+Ih z`N)jcAvH62WiF|su{^Uq9{gd@+>s)VAFji&Lo_9f0S2kV-PwJ|Qyfuq3NY_BEI)QM zJ~GQfhBkyRa#uAd_d9DKd2cb>O%$F$vB?}9;rh=;@B^`SAa}C8PM$ChKBYI~5iE^2 zR@KP>vLG_lIyTWd$Ds_1|4A2_F=7UWru28iqZxMvj}HO)H5hphT-(|rt#KLQk%R5) zH;k|E6Rx*EB@~bC?7#KvPr%4G!p27#nyqL9SZ=wMWNS_^Jl>w*V`^gyeX8B7RdFrd zX0Y2%Y~$YA*Uf7;fD^FjiG^}-Wifc7MA~H*ps`;uv4l^{vg~Yh)K0HndiXHC!~Q87(+~5T9CNNMzOTJT{A3Q~vn_i_iFWPv zUQFt{AO5*8dS>if3>)Jz%V&tSYEb zDc$qP*l0yf^vK8%5Sl(beYM9?qQ@;bxN!nZcNo zS#%yGk--GrV+x0o7H9HuGFg)UP`OC&6Bn@kioy2N2HW0XJHjWch=Gro=7Ho)WDW}5 zT5+=g7!(GH?FXyqq7^%qN6Y?(w@uOU6|9{WQRnk}3d9;&sX5P;D;o+_3!k-#tH~*8 z32V39`mUgLq#Kh>6_ic1Nk@uMI&_50!PYJRco(TRh=!}Rcd>KbSV-!!|Fxjox>JSB zZBsIkEaTh4X6W|beL<6kV<~UIGT);&S&k68joNYg^iw4F$Py}b5VC|U$9O<%HWWEQ zxKO?fgoSYDKr;1;6-(_Ui!0`|pAdVye8u4M#m2!#`VC~1-(Xb3fAsfD{5#8(d7BZ#kFDq!C5-@)p?;eA1Lfal2G4sYl) zeHx73u%V@(xVf7fbHtO3%t_3Ct!)U?8Hp1S?6y?tT^9`0pt{Ynl{fjM+O1CL$mFh& zF+`o%QDfbP#l}oOar>nY8(KRixcuA%@dSE&XL1*!GGMLDNkr5qLp`bJN;Mz&dkN5k zqSs*feL2iJ$R#OZL4QYPGnKsot?7&qX87{_BgNr-A?RH*hRt+UxKv~Ki^`X1RAicB zw-W1zbXio0{s`5inO=PJPYId{GyX!qype5MPfjs1wI7 z2JqbvXU)WK_wyQ7;wOJsAPL~@J`#3Q%aBJ%!^@svGbJQD0lqUxb~e}=+M#p2Y|~l| zt)#+xBRetSb6`6~AW8C+Fpnx@%KbpUW|i@eW)SPnJms%!p3+Q1_w$~g{fvo9fZP3e zRtL9l(>7AYrP`Wh=&G*=D}w2EQNj%ebb*4n$vbYD0> z!*A`gg{q2`z_AFGw5RChH1xo&MXkANtZ?GMgaW;Zl(c8>xKN4)|Ai52>ySgH#E7*T zWE;GMSkLqnPjTwv>8JdiHSS=o<5fObYIR8)^6Er{>!eEJg{4IcW1+ZXSyKK;wzSMB zb-XNMvqrB{-g+XIk1xA9%vjrwE3LT##Slh_dkRDjXCr9!k<4UA3623YUP43D$ zb9&|}1FI>&G5Y+MOQ~nI4*GT`WnI&L^|W zF~UZb;Knr~e=(WuK%BMNNL?`k?SQeER6}G61}11vBFC zZGOqL@na?4n)cYTFUtnra~QOpkjY*TkuFw%ur-Ng7LweIMb~I`{bMy+-5OU>M=h9W zUE@MV=0Cao4|KnBw{oolgI1R_Ha5n+I?m1d=koO7&wC04766MswY z>PFaA2d%|`l5DMD2L~3&+=m7;PL~0{%s>lWpI(|XRwsY3w3t;ErA5Y-L0LHW!VC0LoLu&=mr6o<1;CO61iAl(^IP>C?}yAL2{o8<^XX`8WhPb6g(Ro5Y^n#+llNBx$%l1veaACrP@exZ0H5 zKJHtcjmuq2)QzIc-X|vL;HkUo2pe_G;jX}x-Jv>6Il*R3QKT~z>C)Y%Y~=H@`Gfa1 z?knAY-|qWoi!1Y!2k*HDcHbY7;Twc5=g{T+o)mQ>xl@si?6zKx5j<+@hCf_2bdC?y zNn+O#qd{h%S;*{d5tWcxJed{rL~6ti#FrCcb8J3>mgR5T zo*+u6W-+F=UtkD?ZfvYij9l1xzI5*ViE~|N&z?JX_N+fwIm>(5*=~NrPd?zzcIh+c z&bo7b`kX#`?rd@{I(rHV9i1CJzw<(Kq5(%v;m1tP8%LJnVKMEPJykOfvCs~4snIpm z=-M~pZ&n%G{x&9}hHR#n5$br;8VW}liX6Wmp>O;iI)UjM2H7(Z`vZWofb6yk9b{;s zHhwFp%`xBdrw}+aao23-t7elEV=gSNpLvRA=syxOar4Hd(X zmA!6GW@K_MT}p-56BiY%4+Q!9hS+0<*dvD6gQjYXujme%G74(6Y;bvxAu#w`IAjsH zEPU=ZOkM_bM?A{>Zgg1<>?U<5z;>MJW5B&^**+UEG=aoJop->&(WVym(5Q8Qh2PpQ7R?J+3%ZlXX6w`+Bhoa4@aP&hbrlGwoi`Qa zCgagYxzq!z__~o#d$F6^ zq`ZgLWBUe!4a)2GN9_XZr(%rhuSZiWkUJVo1*{8Gk4t1f; zVAfHSS~*nbO0%NL>NQ&`M6SDb?@_wvcM!a4euO*f=Q0MPu!!{O42qrML^S6&?=5o> z$d3EEB~0-cxqtS3_Ky8>|NW!)4F#QANN!xabQg3xy;Ev+a$5zp`j|gjHD?$H^I+{j z44ijCwe?>yd$9(dhXp0NbaiO94vhm*-PW-~U2Tn;UfyuqRt$2E&TFr|7QbGR zyy4!gz2)Do8sT>Dbr=YRCi#Odi+9*i5xEjzhX<4#X#m?>~^&h_W@ zowpi;&E2hN@K|dYZ7)T}AnzsWVnt9gM*Kt#KHV=mUChR~e~5nVf7Lflr`^x`C?kdZ z?0(o!)T8YWl3ID&y*2C2H)qPv;iMpM7GdR^=<|v{NC3lpwfsyFT}Wm?1W+u zFNu!?U?%Qy`ARI=IiF0>oG)Fv)B>F+CN5^gaRNHOW9Y2IK|gwY+|W5&DOD9N9ahzc zSc9Ss(TXvEnur6C4E92!BUuC8aEc?N`br$2KFEdwz_YP5*k5%|B^ zhGB!0c$?cD1kPE?Mq`s$Bu}@wYt1no8r&+zUgVQlHyv2ple}hoOp4a?h>pRrcOdi} zZRLj7>LE3QJ-!5+p~-e-;vhxGn1~z!yP6pv4i?8p%p`2&OjoU>Eu;F58`(Z(1lmCQ zMeDi`-w&53HCfvo zGi+zw5dWL88iRI}4?-Rlv~z-EEIzW}7{x}NKCIe<#2j==Xp$51wj*{lxHNP=kFsz; z^Nrb-Lhu+u|F57NUl5WQjf=|VdfN*dla)?_f#|RHumR(m$e+LNo~tl|XD(vtD;SCO&OQMd4EH!4=X90ci)j+P@Pr8C0;t-#^3-Q_iLvIn8{*cIY z9b~pMK2R>|Ty1W1)C@$BJRfZAZAPtQ&7nq9`?g}VkvPc!=2CD5eXaB)?Md>)O*8Tv zAhi2Uk7gHT54sQfI$6A*xu4!-2;FfA-TSro{JRwqYWEf$!W(Q@33|sgKC3Jd$x}F5 z_^k1iAa%s-eoCLmft3a8um^Jx+M{)(G6Wl_9D`)n10=t1kn9YScN-+Tl~n+F#mZqN z>nw+1*^QRLaTv`5Zl48$2bWc}q4E@}hF?}SEyFF_19UsaQ+o6@BxVp_kRce`5PH+> zz?egMM2x{-wk?&`L5p>)n}-#L6%}aAb*w?HX^pqdfydc)P+0NfUwDE*o+G; zI)%S7is}Ti#Ep}O`WYX5n0T!oZb7!Nyl5dzIa=%&9a6nbA(AJ~L zX)J{W^qpngS{_-08Ec)A1-E$Gu>a!6bS9glLFW8aEI(U7=%A?3T#_?l#hNHzgXD4CrQwEr<1jfoPHDE8LJ{5+X-X-K zgsT_Vx-5B9$Q9zdVMPqL64S&wM}`aN$+F9mmqf*0e7wDIdX6s?3%|dc3#e-tB#WAX zDS`v`p1AJdJ^8%h`Tyl8j%u7`;>I*@F4YNGo5yZB!d1TX& zW;B&QA2E?QM{6+d3W%QDd$#)w@Ok#kS$8Hno18(SICD1V-6Ln5fc4CoGhc+@o;$ne zTWxMO{J*G2^h*kCuhn86BA#JUy6uf{7y(t;pSNu zz!1R&LmlDf>YH!A_2ygd?JiN=_eeNL@4Fw=f9QTR`v!T!{i60u_d$)BliEMH-&Ad* zllu@Mfl)wh^n$6v0ZN|hjEa*q(>xo_|GqIK=xmaxXhLZ-IBjMcF)xsg2+@PgAr;~u z+^>7uG6aDA^L{yVfz%=rM?Z8wAbX89CzaT})AP1e2=L#%!FTa`&ugzy8K@7_xi`*~ zvkbEazMYMcXb%%bz0GwKGTy&W=IO|OzRspB8#GBhO3)pPODsXZBZD(Uo0h`B;2jV)Dxk4qs_(kO# z?k?S9=;`O%{8zU~4HQ&o;u4PX4^~LQ0jJr+`GV%c2+Qr@qV9!@7A@kDFN_u_u3Ub2 z0i$6Cq)yJfRvr8M%6uU?aoXeK@BRe;))&9{MF_04Vv8_?sqREqps?|gTY_E;T$mpR z9dmnb787p+>X<3U-9?buGg$(UrDN4(iJflJqq{sdbI6lo*2q&uVuSy}Y=j2WiX|6M zCo3v2S)vu%g_JqUSabSAOU{-F&!*Y}#PpzR*Vf!CZz*vh9x zA1>@MSFNOLv9dX`uBxwT8&CEHn#;IGSH9;SG=?VXLM}5eGh!Rf zb;sP%x@DK?k2ok@oR*<-;)?v_<>-r96rGmB3=M~m)op*ojhq(RW-QE;sL04GrW)2} z<=|Gz-yl%jWTUK?qCcp`D3W{P4GnSHVF?QY<-KQ1XU_UFHIO(udx1ymOg9)TfKJYK ziRYd@lb?;wrH094klWIQ^DVe-e6ex~Cn?dyNjzy2C!RP(e66g{iwSL!?~Z;e(rx!Q4-Gm zYR(LIPdoO!5E(j(*n*Mk>$gyA!TlWdBeOo&ISgorF5J~ z83^!t?pz5F>84&a!gBS%Z)f2+|5&j(m1_X`b#-O{kqWt0XU(L)zEQz_1;r~m;Xklp71?2(1N3l_4cVS(*xh~UQjA%f0n80&QpFrx+!j^~rR!z1bn zxb2>)hzOIJ4$6Z+9&!KoLCOPc0|9ez^DPHg1S#CEUZ%65!G_y40|8HO+icR=a{AV^ zZ6wfkZdSc6H&kR8Q61Zep?6wbCE+~O%nqUDNBX5p(>7 zb?e604|BCiH=8(|BM!%!JK2IlTr~+Ig)}GaRAd;|_VtoPC$2mg9a{uL$I}pED255O z!IB_H`*l3No2Dahie%HIPs?TiSr($<20JbNbdG0y){!d^VY|q#;zo1q?37j!VRo}4p zuGCSjoF$?pn0wC5pbi2dkuf$HOfn#lL>4)Nxu5lZcMG0#9$!?|Rb6U{R_)$vuXnBW zzArL_1Y#jJ<4DjTaz)^}bOkbf>8{*omAuGEX%J9W#x2+6Z)yp-acB~X73P@gxTK5Rf;Su?P%ktwKf z8|k;Qs<-kVM3fg9v~ZbEx%<%;3-8)12cwr5ESIm363M;9;Cm6Pq2U!6c7?QV6UCU{ z6ZrRlX$i($6Lf7T%J?#wXmu#q1PXReu17ESHWxaS8zO;fjnfd%*3dj9n3cT{lVVGu zN^bDRKw67~h8G12*SQRcN(C+fBt@9r#HIh6MB%pm_lqcrntv2_!Z{89$a?0!J0+&CfyL)*ti--fM|o66c1OOSGSyC|#i`kThM z$!P>y&^B!*qM_vjiZQFN8+qv0$V4)WG?&^sPsq2aa}a+{Q@RUl8q7_~z}UmtE3h1( z0c%!QuA50;=TV9GC5ib(K)bVHiGej}y^(oZl?~gPHh-4X)%jegLim z(MzOpr0_*RBbLmu%npVfkL?^0|IJY9Kyx?W2S+3gwP)@NHIVNNiyh|NG!hRL6u4HL zOHv0}ZO}T9Q>IlCxmezvXZ%t2%MKeHl6Oa6CN?Tj7%aJP&y3OO?Lz1iK=cW}&^{3t zDknPJ#}{h6<`*s%bnCavj~*1?dxF@8h_^#!CZz#r-`%@s?BpDD&3vq6FezYoi+Tt$(8$>mT(k1;m@Dr%BWei^#=4p{rX&PSB07=ZtAf1<7RT zh5PIHc~I?4?VLp#fzrLVP_5+dNnHEO8*7}LUvGNeVEncc#tYVxg0D!z*1fItg`|zj zsx4yLU^O8*KwO{=oR72Us2FY7r&@Y6#XTDxD#6~3?vTt3Q&&UA*s5MRLrx6UfjE2~z;5b9)=BJv>tJ~~Pv8Q2g{=|MMd*eAvfG$DL#-C

    GMo<)~x7fb@c_#)qCq6&NcoQ z7~<~Hb@P+&MfCWc_dn2$3I1jD(b0A1oWz~+t~+y=cYg=kJK^r-{aywctL}Y%SJAh# z!^Pxr?L_vTUV?7C{8aGneKuq*(a%Bl&YyvbaZslOX? z5BY0wYf#s>h&)lE0HRy@epV(`W^(A&Svaz09V%H!iR)1oLko9@KH^5yxd26(uGY<0>&9*4m&mjHFywiQksIsG%{d2huk`m3?)&hxgFUSNn}if9sL$ zON@LNvOja$pL?a3k0YlS?`?Xy6Ioy8a2K+E^Cb2Y$cfdT*bT_~{N8*s7DCSCGjLbF zY4y)S_A9raeAD{;rWe6K2bm||^Z@e4Vm}W|2l?(|gYjN;ZJ#f;9{6p=b`P@ldC)Dz zb}zE=Gb-DC$YQl6_I_lsr&P8PWU<=p@e6R5=k7iGBIN!LKx3c>A=g8YeapW?9Vfy! z0CW%cG}lH0Su~3;y#UR+#vL2-n9<=pV+kfd!o8`Zt$-A4A@A-+zJEZV%3QVyWi|WL$L8jkykK3i5X$eNU8}PZr%? zGMCN8=5Lq%8Mg%z>-{!I>`x(!_jgsy$H*)G2hdZ{9O&V)*AJ1knp3Cj%F3&~$I_NgY`N*A@7cxqumiTl`-iK_iL1Mi(-l^^A+UvWQSb6T=T4b^2^X|D% z?%ob${pPmr+`UJT?ce>Z`%$>dy7g^>z6M#RJZJiKWb>HUUW^kXzSgzpoW4=;VvILm zeNMi?weI=(TiJpC7CIdgV;=K*?%o66Lf=N~{~fx^cYQtl_Ykh;50LNrA0gMDAnTQ9 z7MlT%pxc+Zo;Hx>Ec9)Gz6Tj6&%6G8vF^JCMcuu8YaLz6)7j{jTpu*IvKtU!_RvvHpBpk5o3#%Q~%LEc&>Dk!R07+`Wg8#hTB%=RUc6qsaQrZQZ$he?zwa+`Ye}yR2K^ zbI|jUb;@(5FCd%8y!K+881c2PJ?Hdd!HY58eDyi`2G_dhmv?;<`}nSlF^_pYckjVg z$hYzR)ZD?oAM#c3{6BwxbblAL=RG?JS$p2IgNyDQGMht+t$xoA#U|Fb$Q*gk4nr32 zdnP8eOh&#ITWXntZZFzXO9xqdYUwX}UCR;0R@X9sO{}$;BefifEZ$ngp3;o3Tv?`yjG5cl#-2rv z*p5RNt1Wl!cyzJex7bcV7ppC?v(UBs4d-vh+2|Y5{Y{VUq+;vEb}s)PAAp~X&3(*a Wj2Qpk?JGX-W&W0x@8V^62lO8}0=0Ai literal 6220 zcmZwKdC=BX6$kL=1px`hWx^#Dd|ok;RTF3dmBlgCD06JJCV~Nz!kL0Mvs^&UnKYQ1 zsjyLLaOsas&B~@Smu70DeV?ZFkD3;3nz2;eQ0V)4-runs)15h-?R(BW=iK|d&&${` z(b2`OE?P8DSFPEweq_}p>o$(8yA)330ikiB@u3N!6|uam)A?2e zbyT>VX9Y>NrjN1#{^-c!4-APvrqd7Ubo)#S&FXY{>9Ys=*unlsc0RQXhb+11#|^Ym z-9FPAUCnY?hXp@1yidvMM~5{>_NnPbZ{%rRUv#)*!zYLIcX)jLaCAg`!<}pfuF1c}W+)$<94ChBjh)|2hZ=+*qqO~3pL!}VpR)!VBg4>kI0B0In8 zZE@sYZ_7iapE}Tc>2<nE&-n9Gu~@*zGB| z9B65XO^?gN&A=TPO6UFXGeWZ>o70)0nVtOF$Tf$vBJazpKF^MxwV?EKM)jrU>fYMJ zT+9DRhPZd%<|UQy(dgwj?|()YQ~1ZC@7uTe+*jt#xa($ax%S1f1xTQb#D+gMyw>eyYTSEG~Dx@D=z2fLw_S40+e)(Em zT=jQ#WPQQlV)eHrq(6IAFV{t`UfkR2<@(5cHHVK!=9i~pw??j5{)*iena}s;%~%#P zlTU?P^-a@19nvqZpZccxeACOrKNFItzUk?aw|DmQg6T)Tp|geMy%@E9wzCa|U)$Mk zjLg0`bX8}&DYE#vjqT>huxu5(BQor%jqP)hVcGP!Gu(3S?%6FN``;RJ-nWIU+e7-s z?@Jx?!?y-#4|~eBU0{}Z@ofuzA|wv~Mi=+V$l~UNzL0mVAO5e{*w2p4XSVW*m8aF& zcju)ScSB^qDKK)_2X<$CV%7g(x9?XX@4xTAgJ;)+8Bgx&`FiBI(#dGd#gV2)zAwc0 z%`WG+I$bX{m-{=L-!A=$dmsese#=qz2P4D#U4^+WdEvhk;&cD+==S<xW<7*qqBpqg&1e{)*5wA@jk_3x>{jZ@1r-k>#p$a^{amXFoHtzYE$}Ih+gJ zwUJ@vgR@Va^%If#h1U?|Y%|ht!F~{50HxF`u7>ejb9s)dxf8 zyQZ7bFCyDpEiDGN?$$3O!-<2deCm=h55Df+`x=|sY!aAdHt-ul8$;^B)dxf8tGjn`WVxz7cWQTZ_V(^oEM9kSgdCF3 z-Lp^i_*7(mxz$~F@6O2jx1YN23b)kFcX#MZA$8()ruRgaM_#>%gMn{#_By98cX$}_ z^0nu5%YORK=zc5v;lB=@5rUCNUgz!}cniIa>iEKfPN?RCD+3Ov&@3;fzU%Cad^G!-;OM<&a5B#>Dbu4>wNl@Ppmwx&R#Rx71_HE zBZqxp^(9vQbr1j1^f@z3WeOx|}taCp%mFuJ4Ww z)|)Ixz3Wd!hWD<+)VsbXGGF_yKOdc4j_T=)DN;S^uW#$l#^zk^)kv0efxj#C)sXq% z<^@CNt8eS>$a2-Zd|S^(XK%l)ipA^O`dVaI`FvaUsc-AK$oz7vyXLkxvh%Q?y7z@! z>gIDGLm_qIFcZQp81p$W`os={>kUQ>Uww}+iEMARv>4dBTazNgiG!XJ`AY8Vr4 zRSjdK9}t4UYtM0!+daj>z^kEjylNO9+1@bX<%6vn@WM`x4_>_5^#WVpf^WL+%^xGX z*LAl2$a{ikS7ZAv{5g7DFMbP^hA4` zELYX%?mZu!y}f%Ci`U(|Ju<9(?w)<>?!6G1Uv72R-TO;q{ny?5YjjK9e18l5J)};& z&h(MU^2n`&PD-qr?zUNeZ%#C#`)2=N6)MEqHRHE8ynjj^Y{4l@P)D2M-DMC{=Yk+ R^SPJxe_8y6ybP}n{RjShxlI57 diff --git a/crates/renderling/shaders/bloom-shader-bloom_vertex.spv b/crates/renderling/shaders/bloom-shader-bloom_vertex.spv index 2e8d7dc129026644de513e5edab329acf908da2c..647e86fff5687686577cb9b785dbd8e27a07658d 100644 GIT binary patch delta 248 zcmYk0OA5k35JYR7L?IAd2!d-tL2;uS1*0aO$P?rcIf*yO-qX19hu|y7!iGmxch7Wp zo3&XUd((l^AZe)cHNVA4iFbSyHAX9Vs;8>C$2yeFB^lLQY71CHp+q^l1J@7yOS;^C ziJ!p(zegQ!UTje31$e&og?hhp_bR2Dqet+ZZePK%(h1z~l75%lr}!285A)Ek0tW{D E04hQnEdT%j delta 248 zcmYjLK?=e!5S%oLLLqn%1kZwk;-x((Xl(UIzMzljOZ-9azQ&VU5jul8xG>DjZZf-F z-sQn&i!rIW4)I0W*ZQ2)e#E_vw< z^^$l}AIPenFG{lfkx;()P1b&S%`Wg*kt3m;v@h~lE&2_#WR$$Lr`{6(VG8}i@JNFJ D8eGC8#moK1*;7oGyVEFcC z_jdR4AP+*<8TjxT09v>_!lxUb8S8xDA|f;D1qWHtFN5bI24vy5xz{d(|r+Qwc{HQn@$3Tz_5svg3^U0cGDCVgLXD delta 324 zcmX|+y$ZrW5QN9v#S|g<0}_Izy`msQ`~fYru}B&<`W)6`pDs`0bNK>_2+qL8gW=oE zZ1(obunZ&P4FdQL04;#AHFe;Gw8G_R>?TuPM1f6GJks?l!*7R5^D< z&Z#jqq59Mk79qKyl;!YwC$M%N@%OgQ(_R_-+T@N>ud)?)GtP5!uGrJi5<2zpoV7d+ js=b5rJTgOoE_tN%zxtIYlrFKPvNxYxKVAHCVoLo0LwXx1 diff --git a/crates/renderling/shaders/convolution-generate_mipmap_vertex.spv b/crates/renderling/shaders/convolution-generate_mipmap_vertex.spv index e8d8857ce0cd287ba681029a7c89134aaa6ba34b..e0e313dc1c292a75ae666fe62faa125e61113df6 100644 GIT binary patch literal 1204 zcmZva*-lhJ5QYmF7{>(|*;Eh@;))neG>Buw#2X)j5OQKjWQLGo;w6vd8~7|fgN!$E&E_;fZr z8uWX;k9EI3Js8&e$44i}2PgZZ`gB--h9OdQ3;Q8jF@sevW!%nqK4bH*pj#Q+a~)Nz zm&drW1d^u`AQiZSb#MBY>3li)BUXr6C$@*VSF!TzH+~Ik+#befvBvc;Q03$sc-*V& zC*;_ti#pR9SSz1CIj&>NjK*EdSKlF(`25{=Oy^me z9R0<2gSB|vcQa%8O5QEj;>OoW^Q?kbP&uqo&C|EYZr8BRdK>E;&hIScd_BXm_vS9o zzZQIl7{cD$>0By+IjXT{zfEi-o)OO^KYz^_IeM0g~~05YJQcp75A~_ z&Ya0N;rno=9nRZ#Fo7z*iyxfF1FX5;{X?|et#|z>-W@oN6%2XthJB#^&Hi2A7>N0cE6sH w{4cOd;TOL|<+smItTTy?+0XOaLFFm^eE+Yq-yWW)c)VWTaV+m2PI?#p3l0@OrT_o{ literal 1204 zcmZvaX-We@5QQs?#<;~b?wYu3RB#W93jXmJ5@e8oNkn4sXO83zJd3ArL-2h)-4Mkd zYN}r?ud2H`m0ZeLSHjG4R@R?2Y)Qj{ejPI#w3M^+&*@{~ziHH4jl0KYwNXDgxsB@4 zL!}vA*Q)om%KddKdT2&ZVlbDTmcFvIbxR{X9%nor@|gHO$)?BDoR_f3hX+4vTnL^5 zK&v2}m8LiBc~$OpcC!ij$OBV@*nVmFvEv_*#!n6WgVOl1k1C6k7iFPW_9ewoXIR3S zW`)u4VS{5tI-C(dd-#HX)cdiY%1{6F#~I+KAC17RfX5wbUu;>ItCbff279ngc-(25 z^fqEc+?4j<*p_wuPYc5d2RR6Fah;^iXwTVZrRkgV(tEg1?kw~=r@dMGC15{G^`3F} zuplon2)?-A*jMoQKVQ-Ni2s|nC>uGyeOcG*lI+whNZ>$-k8NpN);`RLGw}v^58+JA z`&hy{(*5%e5)PSr7w?+hiZHp%epM1?%dFQteiP%N_N*`M;XIO%k3LgAwbmuPhjYci z#cZBcmlq&z{56+0jx3WACnlwwVyqTo|82#82b)Z|%Ez=jpOU`GXe z@4ffldpE`yd(HP<&i^ut<;qzM^Y4G}`S+eVGw0rOUyJ4|wXR#JSzTS-5_NN0(s3kb#3cf)Oi12qON@n>mNOS+~o0N51ce+{J6e-CroVEYs}b54HHK;jGH`W z;`nj41=phD)HSX%y;rFx7rjPs;-dFf#dV?gD#yxY>;SN1 zoAGjL^rg3U`HirxQ%!5twjT3YQ}p_Qy|k@o*v`qR?hfg^wuGt_~GD{X~ug7jF&Th1ikU{ z_1qQDm2)UteRXEk^u9R0o(kOK#@pmPL-w}ZJJ+un&03tp_B5_LyOYbf9cXf{r7ir9 z1*bp!PT<6s{LV#usq=>_K4YTu$0~k7{!ay8>hDtM%;#6Ft=X>d&cS-EO>8aNV)JX; zn^SBvk1=9-ZO5C(arTahhJNGZ^kux*acaqFdtY~>_rAKu&DdQX=||GCC-wjv8+#Pk zJs5j5xMgAQ32sx^4d5kd-O19Ees7xRu53Pc_JQk4a}QXD=VA;kdG-Z&pyj@d1(zDp z9|!L_{w?45iZA^cH=!64e|-BFK6Ul$>qI}1W=^%$FxEZodGy)kT4{S;efGxg1$N!F zyW?@)4`v}f^S17Fi`350A#kqQZ?%j&l$d_R^r?+otahgV4(A&EzvfzYCgvZ+8gDM+ z&E18*5!?CM9mlw$H2B7i0T8ihT*Tg!V*5<$ z#je?q-e-VUZ`yZ!vQDM<3=N~7MsqJ|_obg+*dxHlRQ9)=tkpbRTt9-{qpM@9XTLGy z*MmEb=4Vgr1piy4!+60gKyV9=0?=$K|nq!93%y}}s*AI-+r+o^|y!PMI zTbH)Jf#~c;e;Q3~wX9_b{Y;wtyeikajI*9WG;?iepn%ef}GDch9;nkda zf}?XyrQHk8wa{0NbNtt=xO43dHcluc_;@0DPEhv4l& ze-%wG_v&h}@#Vd`20L2%qjfDoMzFqU-2|44*3DqG zM$w{m3piT(qjf7-U$kxm%MD|{^rXL?=De-fJo=O84zPJf(~{>-aPsI+p1Z*MlIL!) zT(s^1tL5iuwC=@@mi}nn2i6y@`@wS2dH}3eA6m2?1V>AMv>pQMi`K(nxoABCR?E-z zXg!J@E&b7Y46H9&kAvm1mQR44xAmGwfATyDHqTI6@;n7j9{tJlG+1BqJOh@C*0W%> z{O%F0=dh!tKU&X&^+oFiuw1lW1gquumT0|%9WDLQdKs)QTCafRqV+0REx+?b>ox3X z>5tayV13bg11y)dd=u=vt=ByIljkk4dG@3w&)eYSc?+C8?|}6s&%0o`XuStk%kO2; zdLKJl`lIy$SYNb01j|M1Bd}V2r;FCd*wNA-txv%EqV*|QE?S>~)$;pbwEl@5E&b8@ z9IP)|{{qWpEx!OeZ|gOWetn(j|4s85;NEr3jZF<-f~}!}mKy#8P7V4~!&hK^so`s| zT(rIctL69EXnl(vE&b8@4y-R)--G3%^#fQfzY9m}N9<_nkJe9MebM?EEEla`z-swD zI$FPCM@xUS{E*Zat!CJAS?A_p=WV^_(Vsjmz~=G$dGfS`OCJ5n7zEC-g0RtKIzoN_pNAkgNv5_Xsrm= z7p;}Ra#_oj!Oq)y&7(hgeg`&>?{Ueq3S9E&Po7o5`jTfguw1lO2dm{fV6@hNi9-ByuI^Un=yxgtu1SED7NR_ z-{!1!8ra`t)orZC+h_kC2KKjCH4hilJnu(VnBldtQ?Si#pS^q(*zsQBj;=WAocF01 z#_DsAPt(ce-1JSS9Ya&!K4-x**v^jV+2%>7KTey?z6Rh+bY&+~pZhOw^2IXbvJ@ABtX_IdQeS^VdG z?Q`B|gVlB4XAREB_TKBu8NC3^t*x!0{+xvi!TNF*E&|I%>te9+<$1pZJ6igqbtzb1 zwB~^2qIDTqt@6BIjvX!i(YgYxFIscKa`}v#2ewvo=<|H;#{8}XyU$${_q?{T-e1?( z^>aN-+jTB&<8nT)0((A<@q9Yg^XWZsjAukmd-t&MjWo}UyuEW;hcQ=!tu5-5Env0$jXqkp z!bMAev~C0Ii`MO6x!k8az}9LGee#{rz7ypY^WlbIf zTdO(rCCB4nbNIK7~ZMg0F!64Wt+SAe#Hbbu!*_b~!%J zlfBR1F7$8WbDU?akz(e;`K0D!Dd-t@6t=wa>d74qHjZ+d;-+HDmvPgoxaLLN zbU67k?wBf$u1W7$4Ee-4x8ty#hj~-W@o>(g>8Rs+!3#vG}ro0zo z$QzfrT?BS*tSQ{ZVAsa{;VuEYHs%Uv9FQ zyzyC=xnSeUb(x1PU&dWo#g*%F6`Xt-cXbs<*Od1f40+=+w`;+!jWvb44(!^PKiu_T z*T!7oZUDPB>SkST0{e_8&&(}w@?Kek+psqj)%aW!IFCf+w)d(k70YZ1cum%Ointy|r2uYs*w-Egmity|r2Z-A{^ z-PHUR*qZs*RNp%o?q_|e`8}|Ex8y#+cAu8qN7(L3x#ayAY~AXH`vh#=>W2FiY~AXH z`wVQ|>Sj-V4t7tL&#N!s-47TQS zPc91Qp469`+koAZCD#_tJy~)~!nr5ql6NVvb*me0X|Q#x8*Uk}b*me$9oV|nP0j7W z*37@A`Z~b5C-tS~j$rp>$#sTvPnKLgoO@C(c~<~ix4PlFf~{NKaNWSxt!}s#!Pc#A z_TG>sB{hKd^PHo0>NPTXVT52VlD= z^`+*4VE1InZ3gF_EV(V<+>>(2I~Z);>W14AY~AXH+X`&m>W14IY~AXn<{@BfCQVa) z+hV&X^`+)vVE1Injev7cmfZGm?n$}i-2rUf>W149Y~AXH+X-yl>W14HY~AXn=8xGF ze&6>B_esUMU&4J_apnE^9M10&YGiI-fUjGC`x4IY5@p<1a5pT#eGBL3fcc~MJ=o8I zlKTn!M`xR`B>V|WZS);n)n!#D4x~ZiloX-T;B3vstp9v+m zFr3eXl3NtcXM$XEECy$d>V|6rwnlZsEe^Iub;Gpo#V~p_~u{GuB^F4Dl*4+11`=5Ej^rrn65qVK< literal 13488 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 CI#LP% diff --git a/crates/renderling/shaders/cubemap-shader-cubemap_sampling_test_vertex.spv b/crates/renderling/shaders/cubemap-shader-cubemap_sampling_test_vertex.spv index fc548740e8896745823143e4c554b4621e6b24c5..b78c3b2a8bfbc6bf9c3cbc725ab0c66db21dccd0 100644 GIT binary patch delta 151 zcmX@ZafXAJnMs+Qft8Vgfq|dFWFxOJv!oG_4FbOzm>GnCv@sC>U|?b}o*c>CEDDkZ z@pOQ+69X%Q43O5J{E=DM!vMqrVmqKdRv-=H+cK~)$O36YAXWilkQ@t?{}X5m%rp@F Kmw}PN0*C=@ClI~> delta 151 zcmX@ZafXAJnMs+Qft8Vgfq|dFcq6Ydv!o%A4FbOzm>GnCv=I>hU|?b}njFd8EDDkZ z@pOQ+69X%Q43O5F{E=DMLm$KfVmqKdRv-=H+cK~)$O35tAXWilkQ@t?{}X5m%rp@F Kmw}PN0*C=79@S0yiX~gd!y!gaA^dsfd6kgqBbP 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 literal 27844 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 literal 21284 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 diff --git a/crates/renderling/shaders/debug-shader-debug_overlay_vertex.spv b/crates/renderling/shaders/debug-shader-debug_overlay_vertex.spv index 6f2d0c623e13eecb97adb6f6abe1ad60a205fea4..8c10f47ba1a8ede8bfdc85295ab16c8cfe8ce2c5 100644 GIT binary patch delta 123 zcmX@Wc7TnSnMs+Qft8Vgfq|bvdn0c+lcXk)4FbOzn1Nyp3|c_^gMo=bYjQ19z9>i* u#8Uy%P7JIJl0aI0G9$CFjs}PY#CAY^%s?8%{|QtH(*dIYGB7e&05Jfi(he{H delta 123 zcmX@Wc7TnSnMs+Qft8Vgfq|bvYa?$slcWZa4FbOzn1Nyp44OdvgMo=bb8;i* u#8Uy%P7JIJl0aH*G9$CFjyi}1#CAY^%s?8%{|QtH(*dIYGB7e&05JfgTn;4w diff --git a/crates/renderling/shaders/light-shader-light_tiling_bin_lights.spv b/crates/renderling/shaders/light-shader-light_tiling_bin_lights.spv new file mode 100644 index 0000000000000000000000000000000000000000..fd7bb316b418543aed665fd5dfaf28e1009d4439 GIT binary patch literal 26656 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 nI{RJ2yY|{^?{ELwrStIaRku!6RrRj+ zcV=SrtvXj)oR1Eus-D$(4SnXE+vkj1vv%>g@e{5!?!u~zQ{!)M_}##!Sh0NRvbD|4 zYnClqykvEAb3v`;R&XQnOd&I9`$jpeWVnUB~DWe6Se zY_(@E_SRhX+;!~Fkg9v*ekCS*c6J>(3y@C^9hz!R&$?r5>UovsnK$}obZbtYtv0u& zZ$m$O_R-s{-<-S9?WOgPt$H--+Knyt_?*X5xBJ_Je?GG@_S#zYS?AuuO;4OBvX*xV zS7Ug$PNA)0Zo}uk*CFo1F_j&71`iz-TA`gLsDtb)^`UOCe@!TLQz&*e1dar51nUd;eXv~bU)KEq9IpOwKLqPrU$wt=AAz;yp1#HU z*5(>>%bT+Wo4wNKp5=J%o~7sJ`PFsp-UHvOj}iHvt#6mH-ckGi0=j;OwtmbTi;b&s z?k>NGO}iua`=w&5$89QHLlbuiit9L5l|5gIu047aSnku*;QK!eY>f6^yjR*rfL-hS z;$KNF->Z?>^&Nogy&qL{-~NNeHoDk+|9v~iZJ;3h{i!`5pKgT<3j*?vSVN z2yzsWC-z<#qpm%*e+!<6m@9RD2llM>)p_#0Pwx49qzyTO7;nzhHW}_Zbo08W8R!mc z(>DcaMXW`fH*Y#Pyu5iW*j!7WwU|qu{JO3^Z{AH{d5v}88fzUtSOmj5jQJ7#6JkDb zzS*C_`DR@^-|R17ed*J$VExmOaDM}bt3TY|!TQ4e11z@%3HMKMxcb9A2G$quUtqcQ z_w6`(xcb9A0oE7pNwD0_>_6+CLJwDexTnGT@+NJEV?OP^NrRbpVAF1I+@rO6F812K z+TXga-E)$A0Uwckd+)!Qj7?3w@ujBr9(Sp3I$KH#~2T#S-@ z^312rc>8+=v;B6?H~KPlTE9Ji1>A)1MAfw#$}D!s9R`-`oNssm@$${@x3dQ9@Y~UM z2XYr8PduM~_`7i@*fssXh{ODHjWga{E0`V0wFLd15+jylj2!Lh*S%o-XI=FeW3%U# z;5Krb$M`z`essBhuesB!i!QHTt2HO5y_4rY&5`xo?^<;Ctj}Ef@*6OMTJ<|(yRz7r z8o&LsnXf`I*4|vLgYh@ti1v|1AH^&j%^&-s-Fl5z*I(C-%U!$%oV(-t-W_fBsm?Li zaei6-{Tv6L!|Xb(%;ulLY+gCuAJ=vE9F6zxdAGDX8+RCvy1!v{UHd=mXcF=-D`3{4 literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/light-shader-light_tiling_compute_tile_min_and_max_depth.spv b/crates/renderling/shaders/light-shader-light_tiling_compute_tile_min_and_max_depth.spv new file mode 100644 index 0000000000000000000000000000000000000000..c6fff5501dab8914619daee6e5e774ceeb1f7d1b GIT binary patch literal 3976 zcmZ9O%WqXx6o*gCrBGW%B4{wu^x+FA6%#?cSfNd!Ef!lvQ53jVT4@t5Hc}G@7zt5> zubC#Is2CK}3OE>GGt=X;%F5sdNZWoYSjVpI0G?u3M{UbxOA@|Z<~fzs;*|2dP4G8B#=4%} zRrFI9e)GX$XMXLhGh}m;j5bndDeqMqSpVSL!7hEw>ni3`c6mN!k*^sXzL76#(9W|N zFKUpt2K}u;K5AGDcQ<@1>a%<+cHQjew%^yHyC;`t*>&jFgXN8V4VgBu zw_(%6E?$xH^n#sZ@O@y{B78Qon`aZdd8{Gq2EcWYxdxN2zM$U>mTy7t?DdtFQ-g8u zg(B7#@I_YeTjA}Wy?Btl6^dLBfsJFIt!-PU{?-8)FPJXR*JLEYfZOri~ zuV0@=ZdpbWhi7>>f>89Idn(B<_i98c>N>xQ3sM891i}Yoc~{c0{-H~=ZEc+HO|00 z8~fCm&ChF}MHceVxp#6ld+-T*`>Ty}^gL^bw}Bl|zIymQ5BC%MIV%1xHTEB{xxR;2 z@7{;6J^C5)Y_4uj<-C7^oa?9jdZ&KCUb|jshM6ckNmAwZ$vbDh-`HJ$6G#2;;6EU9 zihJ<&&i@IS)0!mnTFY5TUD%xihn>$w*qsNf3%d&iJD-oR`xmS(?CPjD;yKf>t4FRb z?EGwmowE+R2IT6(ZhpbeXCdqwk*gb_f6n`TVt6*|9!c{)hD^CNn%~&^{Y9_rqdl{C zMPB*Ybk~<+YYhA9-O=`b^4Z50bm~iB=hBSczLy$P(| zyAi%O!-uc>@Vy1B&YAc=xfN_YZg*m&Ndh_@U*;;D~#E5Pc)w-c!iTT= z@a+Pt3*Xzo`g+&GcNKj2st@1W!Ro?yHCSKoU-+(p4`21+dnZ`kfvomUTnknf_w+dV zt<4-G>AmwIGJB=YGwb8rouzYYzl>MzJ@B2i9<0B!_5G!-chvsB0k7T__x8;sW4k2l zgzb#Q!24Q(8)eSbn>WqD#N|v$J4MQW4vBbvKMqasd+JXID#3->>=%fE{l;M?mM*i||s&)8X zdjLQ6t{0Q62i|Xzx@O+F+V#T2=A^z#2HzDM!Ro%o*JpQA;{AqwlVtr#c7omazkUN? zZTnJ;kPjl$-fx#Svnj@7BzL~r+nZe$!?HK(c0$VRh1lNs{gPMy5^>C10Xsiq8D}@V zE8;u>uS`F2F^=+xGX{26#+jl9do%*}UIf1_=?{}z{loCuD388w2jjwjH#L3qbtiIl z(brvxFZQ*PWW~Ndj!awoWQ^$RC|G;@s?7_jAA3mdS=7fnVFF&cy^43j0dTw%ir=c| zkgE&d!(e4ch!?&u!-uc>c%QriRu{gng7q!F$6kXEU-jYpI#^vim+yeBTe)*R%IfVLkgPg0_xoRV?Jo<4A?D>opb$tM~R&_-`{e4$?ua1N5t+BN?X80eX7wY}ad`{ne zPCkZL=J(QiXTUD&RVP0SS)aH!{qJ)U9Q~;I*Ycl2uFh{y74kWXT%RGghRF2=yvtnb zx&FNm$``ljOsaOmB2mQ5n A#Q*>R literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.spv b/crates/renderling/shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.spv new file mode 100644 index 0000000000000000000000000000000000000000..c29a469ba67fb0edc698fae29256d61ec7f847f3 GIT binary patch literal 3988 zcmZ9O?Q54+7{|{ZoK9ydsiowY`Knr@7b*JF>9*z`O54KH4Dz?t=C;_@XtSaOMJoCO z6f%M=A3%E`dLrvZ6h##CRlN@S1EN>a6Jejvy>r>k4xF9u^}Qa?bFV(GNOfxX`Rd5%%-nc&>e%Gm z#O(0Y%;e}u5x1Ur#$8Pf#$Hok<+M;!s!tVg15?{xymqo`+lQyvv1MT?xD6RE=G?Q~ zLY(>{?+WDGn8w=3>L~lkh2Ju8*qL8D>kO_gbF`E?>x=zu2J0X4?O=yK=5>_w$t}(& z7x|jN;T!p)2JPIN@uCK0YtY{sl%s}qNV||*n2t?UY_H{-bDx!4uxn>ExBXs^Zg;__ zbPKvYU}a<9Or{Rj&DeCZitoyKy1<@e$lYMaT734hnx}`=Jk}6)ec&3Vx%#uNwxquw ztlW&=v)9*oCp8%N0cOP755CR_`2e#0vlkDuwlE{tBVgm$XKOo{b@Ds2?A_Hq;yntM zYvr%C9%i~vr#9wzjOo~r8q*P0duI%%qm0d4U7!owW;*DdGhUe6f)K z*Iz=ue*MINeX_>O$exXTYE8?E+ONO`A3E1o_GS;>L2rMx@f_XHHsW=#LKUNvzke#R zuRo~xN1My|2W+mNkkz|(<7F5R1>on3j}4RD_8`~3Az{jALF0$=7#cVbA$<8wkyN&Sb!fsQ^&a)1?W_WdB*HW_cw-9!l;nfY&KhOJ3Vz@W!9?a)`4o==0 z&2Mb|{-Rg*(Vp46vMm35zUy1T#;~v69c>>XpMBg0R$mYHT$<23JQvTbL3^e-#HX@f zBRJ0aLpaZQIh^s-S&OlX+7`+3)~3%&uztq&ZkWqDwiCx;9optb-+r*V@ZAsA*ZUW~4?+ z-o!z$T-?+1_DjCLBH^v-i8cS?!ZItCbC%=(9h*8g4rH}rY8|Swd+DgET;M?GWb^P1*^M?ufN@%Ec*@nJafI7 zyTt1IuU{Wn+wL4A_*Mh1qOV7?T<&W%bLGAc!D(xsj1heu25WC$wRtJ`;{?gwi~4vIP9n?Ot9TPm zgX2vof2+>Gs|(+AV7arz3*Wbp!&iO0CvSt*h3|Q=zU6o90&@7O58sPmb@99W2yET* zp6kb~4$oEHC(KWoo~zh%)kax9`tcdq{TVCjx(c>db!9*OeXG1zUx4kcv9&j5_@AN| z>iy1qkni)C$Z|`V*83H!!+O;zf6cT$aaaD|=NoYJL;qiM{%^tR{Py_2slTJh^&Px5 zM6U0V9p+M}`~%Zm<}BZNb&-1>9J!76Th4tAUR^o2G2(49b~&cJ@(`;zUCVlZxBsS^ Hw4M1M0D^H% literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/light-shader-light_tiling_depth_pre_pass.spv b/crates/renderling/shaders/light-shader-light_tiling_depth_pre_pass.spv new file mode 100644 index 0000000000000000000000000000000000000000..6a1d48a6543527db06276cbe18c9eea0fb280370 GIT binary patch literal 35804 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 literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/light-shader-shadow_mapping_fragment.spv b/crates/renderling/shaders/light-shader-shadow_mapping_fragment.spv new file mode 100644 index 0000000000000000000000000000000000000000..e34f4c81be02c7972e1482080a9123ada47134d7 GIT binary patch literal 512 zcmYk2%}xSQ423I5z&{2=K{p2D(!DVlbm>-~fJ`C|B!UD<+`9BNeG4}xe&0A_=1$tv zp0?-SX}xyQjK)?(Byo!ObfXqB;@43`JL);FPx!V$>o42edOM6S@mJJ-bSQBm&<^O)OL=6$Ly@*y^$wgZ}b_Yl7eIxpX2at}O* z*$0g;>9PL+i}<*^smwU1MjP}!YFIb-4RTk}$aRc8>V8vAz%jkfbTIoL>GiH|!2$o= zVZo_W_Vo&`I?I}KJ>T|O=p7TQX|3e?#A;T#0lAuT4{X=BonX$}Z{0oIvLE%W{qUF9 F*f01C9TWfn literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/light-shader-shadow_mapping_vertex.spv b/crates/renderling/shaders/light-shader-shadow_mapping_vertex.spv new file mode 100644 index 0000000000000000000000000000000000000000..9ed8e4cff9c6bf68cf090e3b529afb61cb4595c1 GIT binary patch literal 32528 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 z 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 G%Krljl|rEa literal 108064 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 diff --git a/crates/renderling/shaders/primitive-shader-primitive_vertex.spv b/crates/renderling/shaders/primitive-shader-primitive_vertex.spv index 609b6ebb6fe460c14db5caf3d4b52edde102332d..2598456f628657986a8b595e290f7d70a08be48e 100644 GIT binary patch literal 44156 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 AdjJ3c literal 44156 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 DQbJ+7 diff --git a/crates/renderling/shaders/skybox-shader-skybox_cubemap_fragment.spv b/crates/renderling/shaders/skybox-shader-skybox_cubemap_fragment.spv new file mode 100644 index 0000000000000000000000000000000000000000..026d2275b4552c07cb249a97dd518f3609d18a52 GIT binary patch literal 1124 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 literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/skybox-shader-skybox_equirectangular_fragment.spv b/crates/renderling/shaders/skybox-shader-skybox_equirectangular_fragment.spv new file mode 100644 index 0000000000000000000000000000000000000000..d19617a868d15c4d8c0e2d2cca6d1a094d8539f3 GIT binary patch literal 1408 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 literal 0 HcmV?d00001 diff --git a/crates/renderling/shaders/tonemapping-tonemapping_vertex.spv b/crates/renderling/shaders/tonemapping-tonemapping_vertex.spv index 2dd7a0e91e8bf018bb81dc213638240e4be3c2d6..35d088882af0ec6d92f53a5a3498a7373b2ca2fd 100644 GIT binary patch delta 240 zcmZ9GJqp5L5JV^W5<|cb8-EbAveQC{s8JIOTN^!rXYd3bB5f|=QM`>Jf^S6|7aqGi zy9`sOb?RL>N)!i@S}L!8@A?~NtEZgW^aAb*Ra9qp3bN|vdY2hm20Jx0pf6wy6Bt6N zNS?j~yKV7u-~FgqP39cT$Lgo8m`$@h2PI^Z)?mMO>p)kUe+(lQJ3a_!p)KU}Z#Vsg GT@G)@Ar*%J delta 240 zcmZ9GI|{;J5QHb$#1Qbu#s`8{>9mlDj~Gb`Tbtwro*^gj5NUG>kK%0<5u5>ST=>}C z*=3k6?qX+t5+U>e3~;=;vrP}2RWBHZ>^XVBN8UDe@zVBglk1vVN>1ou#=ap7vLtg- zAb?}v65UFA*>|rIqR)9pJWevW@1bI*OPYpwfQYu|hA{lxpeIQ3KuP1`n2ySBEr&TX%EX5#4DHdUL9 z^Ey$y*L zdo1+l)Qax|R>RE3t2t*2w{PJEz#eMrTd-yQsn?^y(KCmf=PmbV4eeWVC+x)->Kw_O zoUZAK?NN2)qGN4|^IVMUUbv|n&J8urJRVg~E_!{ziHqLb4YxS6M_ntIwQGT0E0?u> z3zu4k7tVc9uP-85>t4zYZ@6AykD6C5d9w#gw4(msIJv}i2b)7K^?6OgrM~Qyaj9>m z5|{ecDxBBM`qnL+y(hO};ihZ2jSFXg8n;=)Ey?U5=V5(vIggyLT+X9A*#0r6{p6v2 z6tlIZ-;OS}x=Ueu)Le2?=8~(qvUcibZT8H#?Aco2#AVNNj>curb}ez)vwa&*U5{Fy z+?4gnO`huDeL=#J+!T7K+F0+dtl4%yXLIaa2io>Z-Q)9^&F#Ks{rO<~!2R>tYmA)hFJN}Pd^dL4=dLx?(TyGT`Du*% z?D}pf+Dpbe(~sAbM881Y>R z?!xFrMr*&C;dQRVJ|6+sozbo}{@nMG;OLA3&&lY;URd|FjH(g+(eU=o|Ic@Q!&iUS z-B8xVAK#6|r>=f|p6eKfIn`FfSo^LQvvqpSyRkby&*j|fI?|h&?YErsIB-XX*X%ZC zubF!Bj|Wd*>u`;6K7SmZ*MrRJ%4&;2ys{TU2b`}$9<4y}C{(&(GR(Tg+jnJ^T- zo_EE`HLS_iueGjI>v=MK3ccvo*?#faau%`1n=82&hd͎{StxU5g^bKyMy^BL*C z^Wp3}`_K6F!6oq16#G(adnf+Ousap|a_kw4eFgSR#l8}o|NVFUH5fA&`&#VTi#-;5 zmSW$EJ!`SYVb50V+py;-_IT{MihVowJjI@XJ#Vq^z@D$zcVc%d_FdTX7keUh_hR3T zy+E<=!CtV~_hK(p?EA1+E%yD`TNZl~_EyDy0DJ3VKZw0eu^+$e?fP$u?fP#U`v;y7y=_j8U%=M6E4KNaS0|s( z(;tZEfB&_A#AuJbF173b8QXinV+`mt=KWYNKLKo>Lz_H5vr^vyjQttra{h_g7;Sy0 zG};G)qcgVAJ_OF1^wo8)|Bjt7|6yR`)Eb6u4(s@pbspAX%x~DgGtBF(o-x|`*5-L~ zI`MyiJxBM*+}Rs9Lf`17wsvj|<4mT$%{fek?Hal0O$`@4{n2X=)|a)@fL%MNtnC1o zwfeJmTCl#X?F4r1rDg35a9OKAYi9)OJAvYlCw?ZdT(mla)$-Y&bLavWE&b8z3f32` znZa_=ngy(u&(3Jg3KuQ?(V7jcFIuyMEG_!>J0*jmk@FFED}o5RtX&i?YxQSs53s(hT@38n@n!Aea9OKAYkPt9W$lt+*ZO*vyi37lt^TZC z8mupCmj%1l_vBf-99-7w&)Vg|`m%NfaBFSJ`&YQE)t|L1g7szXs$kdp8k@YU!DX%f ztX&YxQUCT3~%yyDqr3ww&*Ja9OKAYu5+sv)6hMe--(B26!)r zyBf|OvKPXQfOD@r=Wrw8JP+&Hta*JJ1!w=NtB&i8vp2lPUMp+xxmBNiJ_CK0`Wm+_ zK6QK^`g-Sca&zuKpZ(k6)1TL`JO{Uj)8}iT&)prs9zJ*V?a0`P;d9nGdOL%o*N*tS zp6p^QdG)tmx0pTD)3+;QH->u7xfXkZt;4mRUvDw9@zs|1d_AYV!Paez>(xsg_wkzH z>ygiL>v$O3!#ea$V%*O#hqF11(bkvOwTHmb$?Mu=ICJZ(>s+7LwMW3lsWpte=CF=^ zS?6IL#_Wf^Kf}Dv>KUW0FFkz#IDKjE^yPtIeRZAdvquMkjZv#Vd6UEIY!0ulYhycS z?ZL*dhsLO*Zm$0!V6VT|zFz-B;asQR^F55&!}Ha5IO7P0xt*ie2OK@)`*XHl<0Iky z45wy#Zx6A`JBr!V0*OC2YGjj!() zPQ;Fu{%D;9))%dl!E({+3s!3oHKwk9*wNA-ty94IqID`*F0Zxy!PaUHeaSHZY>xUq zV<2{N=ueK*!1|Kobg*2s&H$@b-)EeO9WDLQ8U)rCt-)ZqXbl0YRo`a}#g3N#Xbl7F zi`Hot%5YSs5MH)2Oif3(Jc^+oF@uw1lm2Dh}z^}YozTKc0k7OXE?w}Rzz ze~trNt2y)~$8BJ9)b~N-v6Dl8a@-EqmmCwoa?!d2tX6$rbSHMS^hfJ1u)b(b1j|M1 zZg5MhJe%%;i$$DL5 zKdI^L^)}xAv%ln>t@S9@dKxlTWWUGEX@mximo{41QX`n-O>F?)D!`hI8p!BF2h{Wt>`r$2GE zmtAX|YjVyViBrG!^7L@>sV}|U3C=j<-IM4!XHVP**PFxj))e22@M`F@K7Bd&nXvVH zgzMaJwU@iV8S7qjZQ|`^`I#Gg7G~GX%Ix_%=X_@ed!5xzFV6wyf35w}pI)95tS`^S zxxjMv_HD$^4Yo(rvR|}~ac`{6+}2WUYpk|$>Fs&IBhfX+-gd3MZT+sXztnX0`WxTs z%Z9h_tlghO%!|+3Hf!tDwiNb!*!}UJ#~8=(nQs3ZcNw$q5%L+K8{D?oEN|^&uK)aM z!0ET1?#$NXoNK%Q*f?uhka?lTXAKL3twY~m8lU&eA`K>_rMsvx=sKqtdVtmT2-maW z>ix19oU!`sk;R!k+%J8-7)vnJch3E?3fOb2_ls+db4~hZMX>tyepv}yKJ{h4R&L^q zcfX?Noc(f-TyGB7TT^_ig4NJxefo0ltAX`Dg>ix0?oU!i3noYd-i~L%Ry*9IJ z)?xO1o%8vAU9h@db2Zju_HaM-tgdz0}N}{vB+*KKIES z>Zx6AdH2Tm0vm(&tf%?}DR~ z?$f+vb}MZD*IKJTYqtjLORsJZR!_dxVLj=`UBJd!n?KvJ=JZ}~uzrtl zyEdG?m22|@=Y4Sdwl;n4$sgDr?uowN89zGM1LyS3FJM1cxi;tfE1Y@tS+iQMQ={7Q z=^K9u!oD%a_2x)zo$z_R&0}pdV|!Sez8M)aFwEg>4r8?SrEj``qm#br3TJM8b)DE{&{I7NG&7Et%AEds#uI&$&%f21} zHoo@JfpF6O8TzAj5LjQd4hG9b>kzP7gP2m+p>Wb_>5tZ7V13a#94wd5b4P%!)g1bg zqYu~|_4}41;iS!>KRJ#9>r0NK!E(_$2CP>7zU5drX|?o6>o~B!XdMrhi`EHXwd(gR zC&Edqr9WCHf%Qe}WUyS$y)W2W&7m(j`hm^Sk16|m3Y@e#^e4xuV13EaA1oKG0pQj? za&Jd#Ae^*X`lEFkSYNbG2g^n446s`DyOuNIq}9?NtwCUY(Habv%efB$TdO(r$@_aH zL&5fhdt*$!54<0|uZ$ZGHr9K?-@)*n$?McvU|*;BU+Xn6&w{hzeT~xZJ$MeYhxeeq za~bC`yyu*wcRo0J#%Dh+gx9C0b*krDb*e3&XVt}EpH;@V-aM&q0ru8sjQ6PZ^}zP9 zK79)@7G#*i*&N1b>&vrh5pZ~b*wYxRb?(;HWS^`$qi1j|(&^{mUE(_RHOM(qLE=JfT*pN(D(wii6) zj30q5?=hg^Mq;a@FL9&5#`#*7xNESD)0enw!N&RXpTu2HczxEA`|3LG1@oz+-}k~xv1Tk-Uvg&uZiRRM ztRd$+4qM(M=X)Er=c_MqC1WE3AVocoGs^h7o0w8 zNbKF<#Mb@02VS3bB=)`%TlepNczxEA{Tt05nNJ=4*}q9(eeRcs+Y(9qPNzxa{pqVEyi~YkUr@3HEuiHgmPt zn!+~D&)Q3|?k`|}N6{E(*Q)*Jv*ge3nqI~p*~AQMV*EUAjCmGfZaq(#ecl=0ov}#6 zJ9|z2yz&az*M;f8c}@5nPTt><%X9DxZ2s4J4(iWy@Jq11{5<(9uw0)1KY~51L*Gw~ zpBdKYY`w;4>q}j~fURp<)<*j`IC)=tMpBKRX@19+_xyd%{{i+epFSQPZS5H9JDblK zZGCy&T9MZTUvGSWrOq1I9_r{@nXwYXb`);jCL<$6sE_VoKR%$@5s9lX9=>yBXk^*#0UWv%|K z?F81BwVlDPt?!|`z$LH#tnCWcm$fs4U0dH9&jOdV`m=Ucu)cgIyotW_Jgg_&&2Z*0 zR&E*2`xZE3_0@fHzub3Y76BXQ-ue4}?x{WKcU7xn`+Tt`zen@;`{dN>L7aQ;td`%? z_XPXBtNM#E7H@q1j&LvV>|yWdTb{83Lw)Cb$FvUEKB?a^xz;$>&@YMYl`o0U^VnvpT3;?x?uet;nr(7_rv#OBbe8RGuFM>po#Z8Cix8; zdn0Do{GHkJbym~w;a6#{e|xak-{0qy%YJW6taSpA;oHcgB*=-ZaD9mAZ?(c2yzJvDQU zcZAocruC}lT6L-|@3peFoxwhnjd8tsQs4GGv+_RP`gX}O z?p&`u!20Ss*JqFR1{we{7H4x9qpdG{bQCx` z*`uT3%&o7kbA9&cSg>(wxku)(j(u6@VI9WohrK_;yw2(wqpdG{bO1PeWbW+Ifna_4 z%ybY~F1>d!*!cQdbO?5|^hfJZu)b&=29}G~;b67uYts?f(b6BSK45*(Iub0G_tQs# zt<@a*lH+KwIqGZJG1$qWKRJ#C>r0N~z;e+#9;{aVe&+=2Xz7pEiC}%vIteTnt&_oO z)$e!uVn<7VwEBVdMe7uBizC{5`&4YT`hjzO`(sB-f3yaG^+jtSST66MPXl}2)@vU9 zsrhuUdFp%4Gq96KfAX9O)|Whkz;e+V3|6at$1?;wTKc0k6s#{=!@zRU8V**g{_f0K z*wNA-t+T=UqIC{fE`4+^*jmk@Pku@E^*pdW=KdH{?t2 z;c({GSJ$~d&%?99#;N7=&>YrrHS0XA!1Xim)_a4BGmi}lx z2-X*^hrn{#%gJER+j`BTKY1Poo2Nb#AHhx@{mJtvSYPry29}G~<6yPwGw})RXz7pE zlVE+(dI~HTt*60i`Q9gc`3!cn^hfJiu)b(L2bPQ0^I)~=?+(6z9WDLQdJ(KIS}%d+ zvX?J|J#XtZkN)I&1#F)BdxfuJCy)N*c@3;Dd0q$0Me7Z4ON;maIsbpbMN5CQ-URE5 z)>~k?XuS1FKbkfAD?mXz7pE2Vi~C`VcIaz5EF5 zd0Ve}^y~9;@yB4F0rswYZft#yUXAT@+1O9O#*bk5ccCMh{jBD9=$G(3z5v@p?nLHG z8_w6m#9h{K^}Ei?;f(b#&hJ03Xt=DEyRzZx+N&DQ@BH#z<<)R%I>LuLZnzqEJ)Ai!cLTQPQuE%}a8++i!?`x+aTD0w z>Ym#6=l|{POWZAB&qa;IjRkuy=1RZZ3U>@poXSw&cGPE*gou3(oxRLEGkpK-r=PkLnS=h*U<`vTi@@kpPuT9ON7nufCvSXe{-uelHUA1HU*mpj;%d#m!^zjUKbp8& zGmpPEdE?S^?cm%)YYI0Nocm?|a8tv%H|7f09?pGGH|Nm->>lL$`n;PK&Ytne9!v)( zZ+zBvY~t!3Ob;ht<2p5Qbq{8Mldo|zHgR^@jixGrG#!TjO6g53vm zg_{}dKB$}Xm=)|E)V#C9d5`GJ9?S{$9;w{iaNZ+w$uS?;8r2Bb4Q!2Sgqt61jcSDJ z4z@=1^88o;tfm^SF~-`x7Z(J3FV-Gj7*5_JwJ(D0eWx#653u)G~ z?AelFbJT0UG`9DNzT{XI>^)Jr<>BoA%Ka72UYE;WtO&Mlb;GR$wr+L9tqitqb;GR! zwr+J(^J-vgu6?)$wtcNHHLnG>hby-Zw*6YUb+PSDx#V3BY~AXHTOVxQ>W13@Y~AXH z+YoHs>ZazugRQyt=Em6eroPm?3E1AO+-7k0rd)Dt3ARQx!fge%Mm5514Yo!#!fgY# zM)lI0+k(|p!!^dFH@5@ZoAueU1Dt&A&7H9AO?^3^UBLEc<#vU$H!HV0oV_WRJ=+s( zj@p}hW80hhl4D=6y;-^a;q1-I9SCP{%4IJO0$aDb;SL5{x4PjD0b94a;SL2`x4NnM zaIiJk-t2>IZ|Y0UM}h6l${mAkZ&vO&Yqcn{vrluM3#!Pcloxck7?s7AQ^!PcloxJh7ZR4={x09Z{mTw{#i zHBM&s@Vmy1xvts|GyHDR+0V#J!fWgEXNmsp$75iBPQ4yJKcD+P?r}Kzd=7X5?0X6M za8H7LhF9(>Z10`QJ&kS6a_+J3J)QygBAMTdGjakg(l8E zOWcca^465Nmzp@QZQ@>rlebRy*zXNq0b7r`)G@~W+o0LMjhL&w;S{!U{(g>HOMtIn zHpbbt>U$0H_cE`7M>a8je{77upJI%87RUCwIeUGL?*Y#BbdFYUuBB@?g>&}WtLa+% zWRFf59O@X`8(U6&XTQ(42VQ4gu95NUz(2+O27E{6{>@0w{0m;+IIibu_}&DoA#dKd zm_5v^?`_6A4D&jBp2leFOCA3Prw;odb-W9oI{dynb-V|!FLk^RRzu!8K4A8+4t*ao zK4O^H**c8T)|Way2B!}DEOmSWpE?G?r;bnI^`(x_z-q`_$A6eTtV7@Dj4v4Gb+!&; zwDqNqFTtt9K29B9!KaQ(;Zw)g@cL56H()j7YYube=NaFEjWe%(X+76*{Z9iwLC;vP zJ!OB@{c_);@jX}_b=7ch&u=`16D)c zIyx|WSckr88PhS$>uepyXzNQI9l@!i-V4*ir;d6rbb{BHI%Y7AA#WWsGN%rGGch_d z%b)=*yuQ>iH&_k%n!{Y_v3bD8nb-cap7hvL^pN%1W4RZyU(V5(53G*5 zYPh%YbpxxTPmSz*uD^3)=Lf5$wmSAoeBHrn=~G8v>Uo7)JU+P#9oI2{g zuo8UgsQ1Fk@cL56DquC_tz%W@)S+)R#_A07I$MV^+WJz*8sOAX?}attQ%AiQ)`HiU zI@SiOAzyQtD?PRj*f{grf7X*8dxjpeUVAL}LiWo!8ta19QCAK3Hoo=1>gZD=`=0CX zoY?ijYN@S`y%OIBV72tAqc3$ni@tvARKq>rnAyV~)c+6cO&IR6v-@F;w!ZB7W?=W+ z{r1ScusOVY?ta&MVGGwXvgccZ)sVN2t(ZNmL*LenZ5ZZtwhm*o^`(w&!KtI(3){h` zj(RU_53etE>;P6n-a2+>;g_5^ojG;r+k>$u!@SPcVT`uE)Ug*hb<}%dZ}`+v?}dHf^`(w|!D`6Y9Og=o?FTl_ zy!M~y(KrHZtU1;9o`}W^@ZK|O-&QJ`LZ$goon-%a~X8?dxTrI;k;MFE!S|~H{q6VID1&m&t(_#j|{8n z5$>Xfi=J^8H(d1O{@HL+@rd5#4OjK9Xt=6(Wy4jy5pbSM)f?GxRc}BdpFp%))(#`u;)?N-ivLlzQo-JwvXJ$aQB1lBljmYPXZgOFL4im?Jf7h z?`iDa2f@bbOWZ?X?+1P1CWGzin)hLB^SVFD`v}-reOdb`*u3sV@;(MOR$t;C2Yb)y zi{2Ap>(Q6EC&AX@`G$K6?7q}mp2jv-U*ettTZ?;}TAl?Pt1ofSfxXxDCGL5!_2^67 z3t($;Ps6wK=;7ccQ_kRJ#h%t$S-z}Xv)aIeF8-5lAg zH{gubm$ssT~jK(YQ`qi*5@0nAWJ*-E6ckFHq^E+FQG1~f0=ls22765y%xHsVzY&iEI z+(Hfa=N|mIc2T$s8EWJ@^#prARc>)?@14pmg>6rpD{Gel+tZa>4*QBJxD~POHEYV+ zmBIE}P3Gou(8qK z9_*pMzJD;*W~lERt#!caxi-E0H*k7cf3C&4;2~)0&vSJ>uzTe`WKY%y%Nw7#4Z!Z7 z*CcTpg5_)6M%Z3UuT$dw4wg4A-2Z^BO)fu^+8AtZbzNhO{pVhI-tIx_*#tc0d2b4r z^VXm9-V8j1^VXkz+Z^n|yWeJAl!fp}uqWW>>I!u1)Xl2F^9mpKGu?cnF&Mvwjcol>4(MoV@Yb+r7YQ$z|={ z;3==mK5+8J<$U)AdyT!;(c2F!Z(Ody{$O*POC4j}SNFp6b`PR?Ab862J_s)7tv}~| zFn9>(tv~q>0UM()=W{4{%Dp%YPQJz+jy+}H9swtBTx#qCo^pSVgp)Te=Y15|dd#Jc zG4;GX|McE5VB_5j_sd?Wy=M<5_BgQduD56H;k>5y1&?N2&$yxC{X3(6;7$zJ8l(0p z%F=YNw&Uta%S#r8FB7;EwxdOCjf2Qr&4wsZ2G0anWx z^=mC>Vq1eg>x$3!nS-#+qtD#>e9axo?BV@o%n-(4hIKewhcVjvsx6>(~HMs}vI{e>W zzsC9c?;zB@&cCgaPH^|^lo;XT|xV@_k7&Tzk+t=AZB zeV(g-Q+Nj0f7=0>|NhO_`_!JlT~+%tY!9{deaQHLp_a4S#%Sxy-+X-nj!ypO>r*&$ z>Z|KqpL6^V*f_P^D|1-KAl7+UhcSb(hcL|Rte!F2`tmm%L&2V(-xr(PpCx+k!@&CT zw-Up_a($bEElcwz-sv&ZM4qEj+XvtT>#b>tqZ|& zc~)EmwpMfKOOA`d=J5O1r9WD?fb~UdELbjDw}REG zfA2L8J6igqb(?XFXpINUrH^h0TdO(r&A=#?<@D`zz0>JHf_!ulYByxd-!{ zaZc=AVB=ly^UY^cp0_`7FYEWnbNT0ntIy?M8m@j1`74~US?lMp-x@A!<$iCty7rHT z^E=GE=kPx)r=}xZJ2*8R;iiI9(~JLj16chUH*Le!xar`` zS-FmIo=eR;eZy6~P7UYUoW~4cbE}*8Ni%|dKdditGl4x9H4@hu?75gL_f!|K>y6hx z0G-5l#g0aFXNGg%YW`WU&95(Uvx40Z&o#Mb1FLDgesd*$cI?!a{ByuXBXM)WncqD~ z++1Mu>r1Y=!D_0Z-(2>py)_TEz3GwP;hPuEz0jAq`I3|Nxqtrvd*0S-9{tJV53bEq-|Mu4OCJ5nGZk20@=Ohui&lHETJ^ooG;q<mwTC;)Gs_%7Xhl`f}Xw3oE7p*zL za?zR#tXBQo_PODrr9WEpfb~UdUa(xW<^!u$|F*pwT(tB@Yksi4Xmtn6WiJ;1d*0S- z9{tI)AlN+hZ`&7wOCJ5nvoKg+^85uX7p+CWEv<6>7ln(K{%G|8>x))Tuw1kj1FKd4 zwtaE9Xz7nuFR;F7EdiE`){fg361s5&-(OMd;FIvlh<+7K{f<15RHIIIMJ-L6D z1N#iHcinSiQ^WG$Rt@DoTLCUL=uZuQ1?x)swGvpZ2}NsVxM=B*)+%6q(OMNO z7p>L6YWd&I$vwL|T(tB@YYj0YT5E#kqO}%St+7RGZMbOZkJdV1ebM?GST6g#F4*(7 zUi0Wrp7p@yxwYh3A1-E?S3x)w;829SRpM z{n0uMtS?%JgXN-i1XwNqd*Z394_vhLN9#zizGxiCxGRmbs|`;yNlLIaM98qt&_p}qSY5H7p;C^ zweBfer@%!^f3!{o>x))@uw1@38K9404t>cn5Nrgd5&)eiq8Vi+L8@For%q zTb#}8;b#kd=P=G?sPCMAOY}-`f8y%DL+V=NT$6LY46MGN9kTXvZ28oee~0vnCeC>G zBzn%-6ZgUO=5W0=#dj504Sm+9FXw(WSieWO5e?^lcr8aTkAySUy%^QR`|ps-U(?vv zGP~wFX3y6-|K{3gu)2O$$R1pe?X}mJ`|bvCdP{$L>qfA?^wt=#T(oWi8(%+*-HaVA z{n5GwtS?$)!E({M6|7eMEH(~1TKc1P8(3eo#)IXebvszC`dMrOcC_?I>khEKXx#~x z%d_P!u;*>P=Fz`4N<-PxiD2&=_t<+#+j#rM>*e+E`c&KNR&C?*H+y%3N1|)YFlN{K za}%$rYrN;wboQPw-h0%0P~O?|>cg6Qz}A*Mxfk2}{l4aY{{r9e=6;{ltancTJ^(%! zznTv+9%6XEPi`C?D5B$Jv=vkPcWWjsPCM6 z_BC*S;_ChGTH{=kbAB1De!bsc!In>bx!+%H;*58%qvxDGaUWc74%b^#e6NGm&}V)6 za_(<{^?QW-SHso&{Y^My-HW%Hc<*=lw;TH%X4m|i+4FVI{r)akUHd+J@E*3;USIC_ z_rbXr^ygmq0IVw%*68(g&XN9%X6zG(dcmdkZ&o1Wgr zHitg>#n_8>@b1Sw3}cdeDzLd9EV-wKOK$zi-5#tjxu*fkMXLi?t%r)%v~bbVAFb)Y z`l8hlEElcm!D>w|TAkpcr9WCTfb~UdMzCD=WG1k+nnPc5bOxK_;gX{ZTyp47j;>&R z$uTonE?TpI)q138%?cMS{n45YtS?%#gXN+%2Ux8~i`JZQ(b6BSxxo6OH8)r;=RObE zTFs$vv$l?Hi_-%0f|sKgj$sU7*dOkb@!n_oKH1sluWJ^-=Q{7Pv#HJRo_*H##P>IB z{T|`gZ8)E$a(+L*72jXWdxYB>&h_E^8Okb9+le-+gOj}-5p!r z_?*WcVB_j}?1?R3Ur!9Ctu_CY2xa6>Dca#y4jaA!9FAEJu?_izV5+LZ0~)2*_Yv9@AJx?jqN>M zxpT3-f90}&=Y!2r_wPb%?@N8jaWU9?uyU7Rd%sogGHmZHx$ME^VCz;l+!bK!RyW+0 zVCz;l+*M%fRyQ?|09$jtmZPw}XY{4!Yr)LuuDW-Rg!L1Ga8; z!`%e7Zgs=m47P4{Q}bA`HP^lxhiyOWOU>iK_HN}SVB4payA#`bz}Bs9xQSrv zRyW+;VC!z_Ha&R{wsotUp1coiPuAzvBslrnlMiCsllpQVlfm|6 z0Bqgrrsj{p)?9n?6Ks1@UuymgY)@A1b8LIEa$jQGlXA)X71+Af4fi$Jy44N$4cNL{ zx=l}hi*4QNrYFA#+mrRR;zv07+LJ$H+mrfo9>0R^$;$nXZBJIN4Sjo3E_*cEP_i%1sYvPs(KvI)SZQ-EcF2ty|r2GlH#K-EcF3ty|sH+y!jS zwI^qWvnTbX=2^k^WaVauvnMMzC!9Sgm%MXsB{hPq1~jbeo=B4BNWZ zO)ZP^8DIc8{C%QuJ>dpU!7UEw`+*v_1l;LUaLd5?EcbVjqPHB}#3{HH;O?G+TM_P_ zhRb=Z1ZR!vhFckIjp~M51#FG#hFcYEjq0YBHNoE3{$5nLwc)(4EB7}z@9WB~2j_h) zmmKTES);n)HUL|ry5TkiTcf(+HUe9ty6K_+0nba0+C%?<^SbLx&6|R~?v>jd&g)*e zE#bWGa>=_D*t*pXw>8+h)eW}|*t*pXw=LMZ)lDrsi>cY)D+|{f&K|1VZgBQc<@SKH zhbp%ZoIUhd(c2Hs9;(~{aQ0B;4uZ3XQ00z?vxnr8;{-TsR5#p-U~5!2+(}?-R5#qoU~5!2J=71} zjU2UyPKC3F^rhwjV0)-?r@`4nl{*8@9+FGmGr`uaZn!~U>sB}1V6b(o8*T{Ly46iB z=ZLA<-!BYz9-KW?xeMUzp~_tZXAf2GQaF3a-%X6(<#6^;<*tOYhbnh9oINC$nn%D{ zqq^Znf~`^AaHGK1sBXAxz}Bd4YPlY45BYnN;ckSphbngyoIO;zTj1;=x#SoNXN~HH zyA^DW>V_K!wnlZs-3GQsb<;z)gS(TX_Rt-0_K?2Rd>7ars@&ah_E6>Sg|mm`lJ`Ea zb*mfhez0|`8*UQVy44N$0NA?KO)Za#sd)iLxX0n_p~^i8XAf2GX*heRa?iurLklvZ z_adAChqH$&_aU4;B$pf?!C9la;XVdiqq^Zf0b8TG;XVahqq^a~2dmk7?lkW~e!y0< z_1tN=AFUB0_us$sc8-e;fv_T97ZeuwY7U*ALb>(`2HPs|LA4vdbBPK-_3+PC#>IQ^Rtc{HZ{dZ(9%}1bq-FiCw`7B(XAU{fTkiK7+PCJ;*h@3i zIfgkoU9%LnN7a#wjdRgk zm-<#Kaj9?J!gyn>?sMDAihUw2NUWOQR z4q#aC0@yyUjF(g6bY}Nceobua@j6&j)(-@GXj{*qmi2%3nJv5jI^C#YFj(Co%xaiF zI%k916?-VybL&q0lFY^?-aNw?ZEgJ@NZ#QsyKNoyM}V!{b6J{mHt$HrQVl)_oV@3P zf8+4{ye{sab*OVbvpVK=k1u34xBHs)7lG{q_s?gqF>${_9FB$KUGsfAW_NB~fYqz5!_vkW4>be5FTd_xhYu#63d#;JU3hXse%bZs; z;u{T~mC=ig)_yI+>s*I@J_fD_qg`wKzVBnf(YX#h52F`*Vcj<{sz&s0g12w}f4-X= zzWTH7ma-=P_--veb@l7>T*ooYskR!%+IPK}t1Q~zvY}KfIBg~ zW_K}r&D4v3B6y}^PXf=zurGW*o8LWm_S(qZ!^j@q2liYt{p-d)@(0m`)s#1?e0|NGq&cp4%Zmx^T*+NO=VVBUi;C;Ha6$^7+<~0gfpg&Xbf(A?x*qY&)IObuYcF-(AtNgjlMY?y*Lw} z3B%y)c~_iV!<$?KTI)Kuo+l%w(Ti@K?H8XdBZ)QMT*u%QWqop=2j}@; z#7O^L0B7IXf5xW|E`y(;*q3A5JMmwE-MQGKuxBpzmDsZs`zma{{=0rG#_Ywu4tuU* zkH?;)*tcVMEA}1Oa~Atf?753Q0ejwJ--SJYu_t0LQ0%+07cBN9?C!tUS^Ap(KN8Vp`c&}yHOTI?iUp@<-EU~M=`ToWC1|Izx-(!8o z&Fj5A6?=8!?J4a?nO7|K#n_({8^7;yz9_cqzbdxtzi#aBctY%Ib8`Fyw$9zK&F{Px z`Fx&!M?7EuwZF$`kG&za>;Dnkd%$BHXfX4Bte2kzHqW6=o*!AM?*PXB40AdEz-)}R zzSA4+gTc|cqtQMD&YJYqb*}%0oiP7lVB^#piER$+_?dMc)?v&q*uOH&>#UwJ+WOYx zc`}6f-@u-udt~nHjT@owrlz)bZVcmWrvA-2Oo#0nx#&#~7d`#aYY*0!wKITSJG89r z0GGA;v$i8xU)FX8yLMDr+XXIb^=IwOV0|Z3{7J;m0+x$bSFl<>`*RMn!bMAev}ObA zi`ML5xoFJ+R?BB+w7S7XOMkTH1nY~|Twu9ATo+$s=LTD=IrJsRJYaM9`jH&-!X=0P zd)Fm z!1}Uwajd)FvvysuzO3C4?Ap=gd^dv2TK!qOF<76ywj}Xalh0>> z_j0(=aQ2YB5bhc{_sVk)cP*UfVLg4C*QYUX_OH6?xXw6x!)xrdvId`9_1Wh$&}XTy zaXaEu$LFE1cRnY#=Kk~9zY{+FdHu?BaA!Duz6Sc--39F7b64N4jNKSMXPu+BJ2-mn zh|lZE9>$Vazj}Kzd#I;xFUH;s^_+7p_61vqYdt^L8Do64NQQpaRo zGkiVrS#BMVV0&1HzA23R8Rl>{hcVjv^1AjAI68Sg&rmnqh9|==B3f&-j6yt=IS% zc)y2JGre*w*m!-`ZVvU-uC{#6<#@2YVvOs}oxME)oV_(JdwU{SUtVuc0?Vb2lflN< z_Y0?BM@xUSP6g|W)@fk5X!QrHHIy1t*8uEj>5tawV13a#11y)<+JRteHHW_B7z8#) zeV=hAc5>)Xj=^Ak$uR^h7p=3vYSs4{XJbc8f3${z^+jtKST0(_!D`j_86&Wxr9WCD z!TO?g4p=T)=YrK5Q1}cta*7;z4(YgRE*N5kepE+Cz_PnjvJo=O8BCvVt`-+RP zlShB@TmsgYJePvyqIDTqt@=LWa_ng7kJc4nebE{Pmh-j6&qb~Tt1ln@tHA2l_aawg zM_+&RM}zf6{~EAdw5|oKRo|P8!H$;xXpIHyi`I2uxzu_+Sbh2E-vCy>zJIw9JNo*g ze-l_=^lt{sMe7!@TJ`)Xj=RD7l4BBBE?W11Tj$REfILs`g^QN{Xx#_a7p=)) zxoF)FR%>**r>0;>OMkQ;0PBm^gJ8L6Jp@+E?>AG|!`RW%AFW5g`l2-zESLN9QLyK2 zz2?!MJdc6R%)`qzFs){`r!Myr@(%0b`C3sl3)b%u?!AU{KfIn}nBRvp*1hAM1I_G@<4fZ;#onHC` zoLgpWL)#el!dlE_?rK|8wT=6R&q}?vpM%FT8#9vGwSJal zy{@sJ)O7ZG8*l&FU-Hh@dMssm&Ea}$if?9kHS}4ZzMT6k z*!n%fb#1uX%d^56>t4*(#M{gAvp4n}%&zIi?D;z9eCGmtoz+e+&kg3QwO{(v%kzNs z<+(U7SkB(Qi}?A#_J~^ci?%WDjkTHETB>c0)iy4@JwJFXy2jYsuC=$V-!=A^n$BK- z<6C{%@b;ax`*Vl|@L5|QK5g%fy&(2L{1-ANFnp%l|HfU(?0bZKkI)@%M{Jh2_A%Fg zAvNIiTTc&W>v7ICUKnhgwJgHiv+-HOqG0RLw^-xzep$T1gtT;*Fa}-c^um&0wLQWu z)o}HGSsKn*efG#Q%pUHSzFv%F8R|Rdepv(Txz+o{wZ^$7{j(}q{d&KwhAp4^vR|t= zamKq}(R0pzxks)yhwH5=zBR#W=(9e3Irl$;^?QU{tKsVXvNoKt?!`Jyy!VUzx{bXa zvuoC8_I#c5{r!eub-m_lY{cy0e(Kwpu?fR<&gr2|!RaC6^L^%K@P6;5X7+S*u<`ob zCv&K$cD3c*8{Z3T0rvY$V_a|U)ciNT-}kcw^H}rS*dErb?+wP^8Rl>{hcVjv@|nb& z;OOKtiMQa)t*@?gy|wuo^$yrLwY-nbVI5nt&ciy4*$TT4!@SPw8KbQ)&!?@ye6{-1 z+<8821J;*)+!n0g-ptzVu=#4O)t|N7gY~6XcLu8`U+b`*^y402*9`Z-IeqgT*zc=coAdo1&b<1pSuNM8 zQEmD3&Cg)_#u(R|Beiwx0#DzV$J%DW_OLd6oftDR%;9VfW3=_9Z@Pe^lfIc5&fNOy zI@hOfx`K^U%f2y(b?n#dt92N&KlT9(^E#_%jJCd9`vbvzwXVInbL|g;)R)(_gTZpy z*F(U@*FHKFj<1%M{%9Qr))%eA!E(_$0<6|h)~2o_;rME4>5tY?V13c*3zp0Gb4P=% z)g1bgqaWBD_4Afv;P`6g(4QQ~g7qcGabUS<9S>Hke%^8d9A7Oh{n0uRtS?$8f#srg zGFYwpdCMtqe6_UnN9$CuzG$5Wmdm;K2V1K-^d-jtusH^xnf*N-j;~e@{mF3#SYL7s z1j|Kh5Lm7HS<9Jle6_UnM{6)xU$lmR<)U>KSgrb5%h_;zwY2m{YbaP>w1$D@a_+;y z)@lxY^8Q}Q2(Ufj-WXHw1Mdg#E91@q8|%H{?_hY($id(Js}7lET^eD>oKcztSGr+Thcr`qy)R$T`6S!Imt&6D~TCo z#(UKI7RC0kK79)@x--n-Yz||z_2pT$2sk=;2n#9aqA&eyWUU5{;?zQo-CHqM{_B<@CR$8^JSJ!hdm`@%3z8CJznmfSy zk~8~vC%pS-4LRQl*zz7Z-@C9qUww(22sW$R0e}aCM&_YdF_tpC5;FU(^WqM8l~O?#YHzBj@=vcu|Jm<9THNo`KV+ zc4D6eC${e2bMX4inb;RfY~8;X;q_TdVqY$?){)N}Z)ESRLw(m7m%V)ztlvF$jn9E~ zz&=mbW3KkP)7ZxOy>@TbEe7^?6pe9qt=hjoOMd^X={4-JP0Yw9#_z|CF;7os^E&&y zGrk97@rHNyn)?09>tJ6OW(4Oo;WIe-`g;30Heaphp#D4uzX0pY&y)WHmdo@1d$5Of z==*{3Bg6Wft=AZBeW~jwuyu80ZM1)ZllQe}EYy7WP)L8@DLmho9Gge}_&RHE}wDsk6Yc+6m^18J;oOSD~>s+7L ztu?{MspT~_hjp~4Mi1*SW(MpI4D&jxXNjj~XP$@k zgc}EE4rAq3pr+g4jMZ27$^CNQjaeLQoO|c*`?;s~pr2K(f$j6fn*1Ei-|v%CYf0kV zb7!^uoPH^=pS!BRG-H{@=kEyj0zb{HZ`sD@XH3gA7*|WTH@3RYxfhlPtL+hPg@*IF zH=YW;7ybZetUh~ZMP?6sN8d_}l^Nw zJ=SaDjCa4H=bZg=k6dpK*IQG38-Uf&XMOr|?i+&jdxYDl;oJ}3lZ|2C7|vMtVv{D` z&zR&lZS2jMU9&l}=j*JdpTn=xT>ti9ufM;~DVP1;f>`tBnXx6Z!O zf}^KquJO+B`qZ>u^<1k?wdK85*0w9yXRaK9+)>qfL-rBq;b~lEh)<|q~S;y|I^RNzM_Q2kgVP0qTjM3JY z=i6T3JfqB=>$NvnUtQ<=?9skpW7Kl5%#l4hjQpOPKU251e%Kz?rtb*G;S6hWHit3V z`m#rT!O_Vc9Svu0eRZAdvq#5(jZ@1#GKY2S&pHq5Fy;X40~zLZR?ir1ec7Xfz}X{n zXO9jB>&y2{hk)hMdxwIJudhXiVMj}UvxVjzH=&ewDd>oG_byC^#{vEYXDfS0rWwx@9Egl(jToe!1|&!5G3P z2lG6?2)sDM*M|D~aIrBA{od1;Fnf4U>${Y38N++nIeM3aqi1|R@4f~4(k}rIuGkG<{Ip48Rm6X&lqiexnIVB(=X;uzl;Uz zOTSzPmdn0g4>rC&4{yMZmi}nn2-X*^o4|6>x*6O$Z|YB7x4=b9f3$7|>xoUa-Ds-3OM7)?~0+1Ik|Bj~y-j(V7C*7p(`ta?yGatX6&QJ%k-C z{n2_DtS?%RfaS86Q^B6M^_oY2@;nMQPkkmnhMhe6ljm`;zT|lVEElaO!D`iK;#1hs z(jTp-!TO^03|KB&e*vrId!O{>v)IwnAFb!W`l9tbST0&GfYqwMJNP1YwDd>oC9u9| zy$qJiUcLhMysg(f`jh8XuzBk56~2a@Jo=O8b+EqV`72m1T7LtpRe!JW@7U4OAFVgQ z`l9s@uw1nM30ABA{@|O~(b6BSx4`^6wmTUEalxmi}nH2i6y@_rY@6 z%MZYwxAmGwzdpY&{t)alz}|Jwjjhko(bzthjr|C0{51^!F7#SvzgP1!^hYmZ;-!0%X*%N(6hEUt~Xx)AaoKx9y=P*y&cYdtNHK1 zHov~a-3fL-JlEu!09Mm@{pL#iUD&BD`6t3fBXM`bncqD~+$6C1^(EImU^UgyZ?5#) zz1a4q$B3qX@56R4^d)XG*f{$#ara|;9{LhD1#FzXnz#qBtwCSn9t3;uc!YbX;cD+c z+;HiA@2`)!-@GS1vi1{f`O1BY?YVfQS3iT3H$H1WZ{p0GxG&)3YutaDIBQAVmvHhm z?yDxwdoyug!^zjUZ?Ubpp6_?q?yE=Eeh(*ad}{uoiK{jL2q$0Tern=s%|FA**SKGr zxLWhCaPr2b=Y9jbht?F1$7GxPW&UvO;M^N?g_{n}eNZ>&(H_n{$o2JkHv^nKh+ z04HyJ)^=>->K@DpCtu?_HF0$hW`dKiah;pEx(8k0>kv--Qc`O^kom`0(*~CZXP)A5xL};A8d_kgj)b?jcSBj5NwTV zgzFBrM)mUiSO~198m=+M+PxQhfV~%M4=(~I?~&RU#rD3_7jAK|_gLkYg!6u?+|qE~ zJ962xUSM<7Yrh<}_ldsbSRU*>QMo_B+5eSW3C>=Z%U-Muwr+L9tpc`gb;GR+wr+L9 ztp>JkbyM>iU~8^@_(yE}T3>2j8*C3(Ze48qwQ}oY+naL9y8+m`)eW~H*t*pXw-MO7 z)eW~X*t*qC&6|R)x%TGf*!HHr)Vu}Q-mKh~aQ3ELa%>H@Mm5511GYvr!fgw-Mm551 z2ewA_(wp0Z)l|bZ#-ulQ0Nb1O*|HOyeC^F$ut!krDaM)lI0 zL&0jQ;TmJoo5R5NrnTpMM!?C}-aH4}-qe@#IS*`aR_+2gd$V#E!P%Q~$#DtT9JMzu z!?ri|CC3$Dd$V#^!r7aZyBf~kl*?X>23xnf;jRH&x4Pl31zWee;l_ZiTiw)r9oU*{ zZ{C1yZ|Y0UH-YWV%H4u(Z&q#`w!JBrytjd^TitNu!Pc#AxZACK10YO3KH zWBjafDzk^5HEzLm)qa%WXN%5$kGvebwmyHB=-+;<$@lC2oO&aCet+)!xX1C!=lg&s zuzfEfAMQ!8&+y7Uh3&mlxu>zMSIFt@>Vr{JqR8;IU22$R@_$Pcg!Gb zy_&AIPxj<@Sv}M-c2{gU^_~4Z-yV34b-6~yuMht$^Xu@Pmv*&4yw!YNyPjKq64^qdQ@TtSkyHm$o@cL56+h8^1t>YbL z59`qPF5^9hd7Z7p7;Sy2<9%@Iu+LJ*2k@z5D17Sp5ME#E_z0|qymkDG*~2>Yea!eb z!@SPcVT`uE)bR;8b=b$L<5T$5F$z9)dZq%RdmG|H$m&p6mY!`)7uG?CiN1qpdG{{wvr$xBon{=fA|q`Hrf0NgnAh1ljM3JYI%WW;j(RV2fKMIuUg!v~FLlfaRzu!8Ix(jX zeKRpSGtBF39mZ(uOC4RnsiWQtGsCBjdN0fZuP=3U1*;)%9kVj04t=vRW@nh!**c8T z)|Wcw0H=<6FLZ-X9ra$A6JB5Hm_~rwvqfd?Od#=B8V&?~|rM5cuN_-1|)zYVqzSQ{_^z~b(8t(bR%pUfj z{zb5RGTdWl_rn-%ecAKH!0x%%-6QwH;_&Xd*S+2gOTg>Po-YYjL*6=;V)n2OeM>Wz zVVKw1I*ifQmpXcZQ%AiQmW59p^F$Xmy%%&9})YK+wx=5@9XW3=_9jy1rkquvW^!l#aU zFZ>Z+U+P#3tcHBeVXpMp+F;|%YyVkKdhA(x$a?Lu+zZ(+=V+`8R!3bm+}rrp1FNG? zjqH1_zjI>O2dkyFI`&F@8-Uf)r;fhV`5gNCty2y6d{br*dr<#o*qbxlV`uln7;Syo z^DV&cx%=&rd*M&;?z#J2?}aVl^<~eu0;?f!9etQRtV7?{jBOa^b+!&;wDqNqZNaId z-V58or;d6rY!9z5b?g9EL*6=eWKJFWc4F+zFt4+97^AH(b?gF89ra$=6+U&;dtod%IP=8;_C;emOgd#rOubo*KeI_*k30wdw9R;KN0&R zhP69egE89rsx5EcrC5J5*q<*OW8b+p-*YaDu6~bj%Qc+$YPjAF=Y11y`G&KH<@~Rk=zxm3N;4OjK9 zX}GF)ZNpW)>)_mns&{?ERlOS;uIk;`aO&lAo15UwtuNfoU~{XHpU2(;HdbHaZUuWT zb?rE8*IHB7-Uc>SU)GKXyVe}xZU{{y!cQ4rUsB7=THdbHaCWGxG_c7f4VEf4ZNzGHh#_CJl z17Lg0z3_7yd-p-GvHBAC5ZL=cU$}?C_H@nr2)23MpX8kiHdbHOJ_-rM+ z9N2pFCGL5!wYaC@UI1H*=bQ6*5p1l!#JvP||7tBSV;ie4aj$@V#^{UQt6=NVm)F-P z`HWP45ZBe`@IbJK&tZM1V?V|0bJuwaJun#m(`B8{b^GFFo(=M6f`>6u%gb=~h9lf- za9%e@_Ud&wWA!EO?_l@Tk+?VDjMbO8H^H8-BXMuR8LO{LQ{&rUpH&Mn^k@A$V11rL zxDT`XOAOs?ZC$BOI&-f&o@WnW&j(jFEw_MYxY)ues{Vf z*!}e!jJdn%p-v5N?}h6OXI$lGhI3tdv>VvN9#x|&V-|)z>g;<1W3=_ zHt&xT=bZO0bApX^t#N8b<5hV5YFL-|%&E*C)}wy`?D-hxceWm5wDk?){Jmcm1beTz zH{rTBoO=*%p@#c?4}M?U6Yc_r8o5r3fxVw9w*B{xSwtp+P zBDTF|O_;lAnHk+C|%eR58(tpT<^&pF(hVE0bF z=>HLHZ1lGWd#JB(GsapB^_`=&HdsB^rkB?Nrqqp3gZ_XJP7KYPK+8=t-1 z8?2UG*6stI_PYETPTshj@4jHKvDZ3!`+?<+%Qe^^Y;JR@V~qRiUU=T_K{O8pPkY`6 z!R5U5=e!RF59hq~C;uT}WAx>G4h2uU7l*;g*SN#6r|sJ#;N*=loKFZfJP_&gc|y zM}}*SQTtS8_upA<<4yw`Yd-(qQ1caE|Ay1&|C2{wUjJUh_BC!KYw{X85Wo7TGn+5A zbMg%Wt7VM(wU#rntwEo4#pnCX!Pw@}XKsDI=AO;$;r(UIS&ShJ>u|OXW3=^ETRwFS z1zVdj*5O*e_xAVFhk^Bb$ocFT-f;G5;zl%_-|yz{!bZZ$8?TP}^KTb8C;zE@9$~CC zxd-h!{NG-`&iVT9Ak@9izqjBVjs9q;qplkM+YI{LzX9;-=yMwDsk0zCHj) zCx7$xA)Gn&)pf4VIsOZ5oLcUcIjmza>pZN(m?79_G0f|%o-x|`^0yLagFQb#FE+P7 zOZ41_g7xKZC5D0J`Zs$s9BjOw??!6`cC_?IYb01-w9Wy`MeAI!T7E_wt@E&>r9WEd zgY`x00n(Yg|>R{eXgtFWV`KU!CV^+jtmST0)EfYlmM&hc98Xz7pE7_h!*jRni) zIe#74^R`~|=ue*O!RD!d3w8r`^5{>V8^QXL=O(aRv~C8gRsY`W7VK#0kJhbVebE{R zmW$SHV72PsdyU7Ami}nn4%Qc~JHT@3qdURYY7TvQ)=dE0WA2YJ^}h1{%5!QW*jVp1 z{{}YqV4gG1iM<nn2=Th@_Xt=7^vEf{s^OzCN-0J3iQYWzQhxH|HCa~wCM&deyJr{H3 zp6UX2z47`7u`Ka3V@D&pv%tA;HGfw)^Xp68tYG)Ub4{+1B&qH70 z=5ONc)x<3TXASxiw;-)F2;TH8l$Km<<{_UNHb8TMp-iI@6AmepFo`)a6 z>l=sH_fpGIhwo3W0Q>%8<)$v*U+7z&(VOA>31^>!#%Sxy`$udZ`_ z-sh|WHcl3^E>oDeH?0+-N>#UwJ+WK-(H9u%o3vTK@s-i`JK5xoCX_R;#|x`5HS~`lIy?SYNch1W4 z9bB~ZM{7E;zGzJkmWx(5tYN zV13c*29}G~oM5%;-?q;M7cKqKnj5SyTJwPAqBSpAt@^j^^T9<+f3)TY>xfg360T(U((OMF$FIr21<)XDTxOI+vPn#ZJ1}<9qqty$nFIvlj<+7K{fjw{Q zHIIIMOL7172Kx-KcinSiQ^WFLYZzVbvlZY{gZ|X;2e7`>up(G4S}TFonpCt_hKrW| zXsrU)7p+yna?x51td{@Zob1i&aM98qtu?^3vmsb6S{s4Y^8d#it&QQLr9WDm zfb~UdQ?OjLHUq2W|FdOs}EQ% zd$~2(^R`~|=ue()z^$4~FKr8#Jo=MoJFvdw*&ZwxtsTH>O(-?*2p28=(b@^DFIqc; z<)XC1M7>{?qIoS?EzNH|A%(2%bsx2(jTq8!1|)KH&`xvxewU$ zwqEn-Po6)6%`>s&*%vN(^e4}LV13E6KUgkW2Y}VOyJ#H<7cKqKItZ*US_gyWqIC#Z zE&re3IsZf9qNP7thk^A)>u|7Kw2lC)<^NAST1Ub~OMkSE0_%%bU$9*E@@TNJOI7=OzQd)@lxY$#FW^9QTvMf1}d>r}!|i z@7D+6^ZmNB@Bf!%AI}62$M1Xi!Qdeb{~gk^8caxQ?b+C_b@uz7)@PSs*L#E;)^L6= zlz$g@+I8TTF8=Jn^>AK$eYx*$0H?R~r?+kd>q~Fl1eS}| z&0yo}_hPqTM@xUSZUyU$);O?Sv~B~dRlgS-j~y-j(YhV1FIsni<)U>bSgrcK*aYlo z>5tZ3V13b=2$svU*waa1?;H2ndq~@O`^D?!_3-*s+v`?sRi=hSreo-p2f)O%3g+4JhhntQ?4mOZ%-+xvY=bH9I%Z$xvy zPifXWr+*&+pNC(~2N@4Byx$*gFezF!J%Vj+=k)Saufet!(kSbg^RizyVIAh(5zc=yT@A7Xn_CJ_i^G{~a*E#q5n_zYA z`|QD6*j{^mx!>Og=U&jCd*L0hzT6A%g5{$19@zMLzrT+iE&b8@0IV-sAA;qg^$}RD zdcXe*J6igq^)XmqwEhj2%WK>xU~4spKJU*<*@I8P_PKlF{i$uN*Vp}Z|J=`NyU*1& zF8AkWVDC?3ygyy*{pmGujrWL}&i1hJ-c#N)^3I;qF|7F5tZoV13c*1eVL5%mlVpbLdNs&R}yq zT5@zTj?)^*(4QPLgY_lHEMU24bp@;SSkamlE?WAdH5*u8v}Om(MQaYQT8|g4ZgA1k zAFVmT`l2-#ST5&2H`rRup|4L{r?zD{w|T(5xt9GH0~q#)`((WLSw2s8_WA3Y1@XDg zd+Z!)^Rs84wM*e!4_m)Sxb+*(XQ`Z@&-dZ;Yk7}wTf@0NoIgX^2F}>ZZHsNJM}AJW z9k#sj>bZ7%F~hux+W}j?#_ia|`7?#Y?F1)Z<92T1c$EA%ZWlQD#CdMJVtXDrUu)S7 z&hx0;?%2k9B<~*B^2X;p_5>SO&tora`5L!(6Iah;A2|6M_va?Ap2xm$^2X(7VEcjH zS8EElKiEAqf4Bp{?w7g39SC-B)Xnuh2<*P(XE*N4!Eo+N z#?^f}99zD|9nr+qeK`_NzQ!HZ#MOQ23ny<}&h2Qhdt*)E`hndW^M^YI?B19w+_7Ny zM&0boabWkwyg9ey;oO(Xoq%nuNA~4JY@%X?Geh9y>mHnq?Y*xr z`!WpdeO|c{*xu8XI|tkQS1$W^9@rdp|1QAxzSNf-7lFM8D|ZRD_gm#I!}i{i%lTdo zwr+L9T>-Xkb;FGUTerI5t^`}Rx~chUur=3fc@4JrjK0)72JHP&x$CgK7bJ^2B)J*h7>e+0HCEB7(BJz2R=u z3~b%%hWi|B-Rg$>0&LytrYFAy+mrRR;%hkh+LPa6+mrfo9^ZrQ$;$nRZBJJ2XKZ^? zE_?MW*c`Pd+o;2y)R!F7!P%3QYY%5nR;~k_Jt>#-?FeVx>V}&UY~AXH>jbuLb;HdB zwr+J(a~H5R*PfgO&Ysklnr8*ula-qt&YrAXH#mDzE_vq!TerI5<^o%{y5Z&qTerI5 z<^fx`x~X|Sur=47Tma6V)R&sOgYC)6^?#GJ;BzkZn#Ck)~#;1#lY6B zZn(w4)~#-8>B;v11IXd;6NOt0?(}K6CE$ENP~(<@8#oQOES%4Be-|lwz2PQJ!>s^! z&otbMaQ8M`YF-J>8r2QAGT0i`4Yvx|8r2QAD%cv;O)YDJy|4YfsBmk+d0$s<9XRjn z%B=_IeJz(9>%&>2y5TkeTcf(+HUwLvy5TkgTcf(^p-sT^kfZj{W^i72eX03>z+U&t z{Rz(NUb(H{yzX+z+Xrmj>W14IY~AXH+Xigi>W14EY~AXnmYwxev%gmsZdW*asB*i* z*+Z4v6V4v0+@Im>p~s5eesK0sp-0=7nV!yO8?Ms>p- z2DV0Zb8bh0?IC|ZF5J;@_E6=HfwPAycO0BOB$ph=!&#%c;Z6Wsqq^Zv1Y4uJ;Z6cu zqq^y#Q^50)qxR5gaQ2YC)I0!e4^{3AID4pagW&8Tx#T?)Y~AXH8w|E?b;At-TerI5 z&H`Jvx~XNPeropj3&WiYXAf2Gd^mfkau>qcLzTM}&K~l26Qg%IoIO;zQE>K9<*tIW zhvZW8)o|9RZn)84Yg9MfHDGI0H{7*gYg9M2To1N~{5{EVH^SLNmAe_v9;)1}aQ2W~ za*TtsMs>s82DV0Z!;J@9qq^a42V0}M>7hHp3y`Ds&|Pr$kiOJ>H`pGk+&ysiQ04A} zvxnr8cQV+z)eUz)*t*pXHwA3n>V|s&Y~AXnmPhqd^MZ_UkHgtRm3tD-9;)2aaQ0B; zo`bW8x-+8p0-QZmxtHMVp~}4iXAjAx=2zjYQQdH_fvr*9aIb@{QQdHV1zV%KspTJF zduSm>xHsYKp~}4tXAf2GT{wG4E;-(Vvqp8py$`lVb;ErCwnlZseF(Njb;ErLR@0sd z_Z7C9_Ds01vDLI^!hM6SrahCM{0`gSA@&IOeZ$qy9)4)J`rh#;IA8bF$X@*d-g+AD zH*8<`YFxX{ydR&2n;y<*p!uUW1Ki+gxQ=i>18ZC-xU(8A=Q|UeHL4q~GuRr{4c7&1 zjp~M*8ElQ}rk1W??=SZv+-z|7Ps7at=lxaV=7f8o;gVx6IBQfl+}vPmR5#o_U~5!2 z+`M3GR5#orU^VTLa6Pfrv`4}%imj$S5^gbUHSLl7OnPx_HPvv9G5&n3BfX+e+yU(G VoBMgW|F)|?e{%kX?~GPs{4Zb!q9_0W diff --git a/crates/renderling/src/linkage/light_tiling_bin_lights.rs b/crates/renderling/src/linkage/light_tiling_bin_lights.rs index 6db4017f..f5cd5b20 100644 --- a/crates/renderling/src/linkage/light_tiling_bin_lights.rs +++ b/crates/renderling/src/linkage/light_tiling_bin_lights.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "light::light_tiling_bin_lights"; + pub const ENTRY_POINT: &str = "light::shader::light_tiling_bin_lights"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/light-light_tiling_bin_lights.spv") + wgpu::include_spirv!("../../shaders/light-shader-light_tiling_bin_lights.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "light_tiling_bin_lights"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "lightlight_tiling_bin_lights"; + pub const ENTRY_POINT: &str = "lightshaderlight_tiling_bin_lights"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/light-light_tiling_bin_lights.wgsl") + wgpu::include_wgsl!("../../shaders/light-shader-light_tiling_bin_lights.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "light_tiling_bin_lights"); diff --git a/crates/renderling/src/linkage/light_tiling_clear_tiles.rs b/crates/renderling/src/linkage/light_tiling_clear_tiles.rs index dcd8723b..6f858507 100644 --- a/crates/renderling/src/linkage/light_tiling_clear_tiles.rs +++ b/crates/renderling/src/linkage/light_tiling_clear_tiles.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "light::light_tiling_clear_tiles"; + pub const ENTRY_POINT: &str = "light::shader::light_tiling_clear_tiles"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/light-light_tiling_clear_tiles.spv") + wgpu::include_spirv!("../../shaders/light-shader-light_tiling_clear_tiles.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "light_tiling_clear_tiles"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "lightlight_tiling_clear_tiles"; + pub const ENTRY_POINT: &str = "lightshaderlight_tiling_clear_tiles"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/light-light_tiling_clear_tiles.wgsl") + wgpu::include_wgsl!("../../shaders/light-shader-light_tiling_clear_tiles.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "light_tiling_clear_tiles"); diff --git a/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth.rs b/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth.rs index 9067d0d8..66ad2071 100644 --- a/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth.rs +++ b/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth.rs @@ -3,9 +3,11 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "light::light_tiling_compute_tile_min_and_max_depth"; + pub const ENTRY_POINT: &str = "light::shader::light_tiling_compute_tile_min_and_max_depth"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/light-light_tiling_compute_tile_min_and_max_depth.spv") + wgpu::include_spirv!( + "../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth.spv" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +22,11 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "lightlight_tiling_compute_tile_min_and_max_depth"; + pub const ENTRY_POINT: &str = "lightshaderlight_tiling_compute_tile_min_and_max_depth"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/light-light_tiling_compute_tile_min_and_max_depth.wgsl") + wgpu::include_wgsl!( + "../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth.wgsl" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs b/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs index 22f3b90c..9c1af43d 100644 --- a/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs +++ b/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs @@ -3,11 +3,10 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "light::light_tiling_compute_tile_min_and_max_depth_multisampled"; + pub const ENTRY_POINT: &str = + "light::shader::light_tiling_compute_tile_min_and_max_depth_multisampled"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!( - "../../shaders/light-light_tiling_compute_tile_min_and_max_depth_multisampled.spv" - ) + wgpu :: include_spirv ! ("../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -22,11 +21,10 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "lightlight_tiling_compute_tile_min_and_max_depth_multisampled"; + pub const ENTRY_POINT: &str = + "lightshaderlight_tiling_compute_tile_min_and_max_depth_multisampled"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!( - "../../shaders/light-light_tiling_compute_tile_min_and_max_depth_multisampled.wgsl" - ) + wgpu :: include_wgsl ! ("../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/linkage/light_tiling_depth_pre_pass.rs b/crates/renderling/src/linkage/light_tiling_depth_pre_pass.rs index 0423c693..8b11c26d 100644 --- a/crates/renderling/src/linkage/light_tiling_depth_pre_pass.rs +++ b/crates/renderling/src/linkage/light_tiling_depth_pre_pass.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "light::light_tiling_depth_pre_pass"; + pub const ENTRY_POINT: &str = "light::shader::light_tiling_depth_pre_pass"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/light-light_tiling_depth_pre_pass.spv") + wgpu::include_spirv!("../../shaders/light-shader-light_tiling_depth_pre_pass.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +20,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "lightlight_tiling_depth_pre_pass"; + pub const ENTRY_POINT: &str = "lightshaderlight_tiling_depth_pre_pass"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/light-light_tiling_depth_pre_pass.wgsl") + wgpu::include_wgsl!("../../shaders/light-shader-light_tiling_depth_pre_pass.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "light_tiling_depth_pre_pass"); diff --git a/crates/renderling/src/linkage/shadow_mapping_fragment.rs b/crates/renderling/src/linkage/shadow_mapping_fragment.rs index a730025a..5f92e841 100644 --- a/crates/renderling/src/linkage/shadow_mapping_fragment.rs +++ b/crates/renderling/src/linkage/shadow_mapping_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "light::shadow_mapping_fragment"; + pub const ENTRY_POINT: &str = "light::shader::shadow_mapping_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/light-shadow_mapping_fragment.spv") + wgpu::include_spirv!("../../shaders/light-shader-shadow_mapping_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "shadow_mapping_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "lightshadow_mapping_fragment"; + pub const ENTRY_POINT: &str = "lightshadershadow_mapping_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/light-shadow_mapping_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/light-shader-shadow_mapping_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "shadow_mapping_fragment"); diff --git a/crates/renderling/src/linkage/shadow_mapping_vertex.rs b/crates/renderling/src/linkage/shadow_mapping_vertex.rs index bb5ece96..2b2bc317 100644 --- a/crates/renderling/src/linkage/shadow_mapping_vertex.rs +++ b/crates/renderling/src/linkage/shadow_mapping_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "light::shadow_mapping_vertex"; + pub const ENTRY_POINT: &str = "light::shader::shadow_mapping_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/light-shadow_mapping_vertex.spv") + wgpu::include_spirv!("../../shaders/light-shader-shadow_mapping_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "shadow_mapping_vertex"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "lightshadow_mapping_vertex"; + pub const ENTRY_POINT: &str = "lightshadershadow_mapping_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/light-shadow_mapping_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/light-shader-shadow_mapping_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "shadow_mapping_vertex"); diff --git a/crates/renderling/src/linkage/skybox_cubemap_fragment.rs b/crates/renderling/src/linkage/skybox_cubemap_fragment.rs index 611d7cbb..46367957 100644 --- a/crates/renderling/src/linkage/skybox_cubemap_fragment.rs +++ b/crates/renderling/src/linkage/skybox_cubemap_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "skybox::skybox_cubemap_fragment"; + pub const ENTRY_POINT: &str = "skybox::shader::skybox_cubemap_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/skybox-skybox_cubemap_fragment.spv") + wgpu::include_spirv!("../../shaders/skybox-shader-skybox_cubemap_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "skybox_cubemap_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "skyboxskybox_cubemap_fragment"; + pub const ENTRY_POINT: &str = "skyboxshaderskybox_cubemap_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/skybox-skybox_cubemap_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/skybox-shader-skybox_cubemap_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "skybox_cubemap_fragment"); diff --git a/crates/renderling/src/linkage/skybox_cubemap_vertex.rs b/crates/renderling/src/linkage/skybox_cubemap_vertex.rs index f6e073c0..5a9a1890 100644 --- a/crates/renderling/src/linkage/skybox_cubemap_vertex.rs +++ b/crates/renderling/src/linkage/skybox_cubemap_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "skybox::skybox_cubemap_vertex"; + pub const ENTRY_POINT: &str = "skybox::shader::skybox_cubemap_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/skybox-skybox_cubemap_vertex.spv") + wgpu::include_spirv!("../../shaders/skybox-shader-skybox_cubemap_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "skybox_cubemap_vertex"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "skyboxskybox_cubemap_vertex"; + pub const ENTRY_POINT: &str = "skyboxshaderskybox_cubemap_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/skybox-skybox_cubemap_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/skybox-shader-skybox_cubemap_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "skybox_cubemap_vertex"); diff --git a/crates/renderling/src/linkage/skybox_equirectangular_fragment.rs b/crates/renderling/src/linkage/skybox_equirectangular_fragment.rs index 55d579c7..532a4706 100644 --- a/crates/renderling/src/linkage/skybox_equirectangular_fragment.rs +++ b/crates/renderling/src/linkage/skybox_equirectangular_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "skybox::skybox_equirectangular_fragment"; + pub const ENTRY_POINT: &str = "skybox::shader::skybox_equirectangular_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/skybox-skybox_equirectangular_fragment.spv") + wgpu::include_spirv!("../../shaders/skybox-shader-skybox_equirectangular_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +20,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "skyboxskybox_equirectangular_fragment"; + pub const ENTRY_POINT: &str = "skyboxshaderskybox_equirectangular_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/skybox-skybox_equirectangular_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/skybox-shader-skybox_equirectangular_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/linkage/skybox_vertex.rs b/crates/renderling/src/linkage/skybox_vertex.rs index 97f15663..81ac3605 100644 --- a/crates/renderling/src/linkage/skybox_vertex.rs +++ b/crates/renderling/src/linkage/skybox_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "skybox::skybox_vertex"; + pub const ENTRY_POINT: &str = "skybox::shader::skybox_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/skybox-skybox_vertex.spv") + wgpu::include_spirv!("../../shaders/skybox-shader-skybox_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "skybox_vertex"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "skyboxskybox_vertex"; + pub const ENTRY_POINT: &str = "skyboxshaderskybox_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/skybox-skybox_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/skybox-shader-skybox_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "skybox_vertex"); diff --git a/crates/renderling/src/skybox.rs b/crates/renderling/src/skybox.rs index 570d8e58..a654fbf0 100644 --- a/crates/renderling/src/skybox.rs +++ b/crates/renderling/src/skybox.rs @@ -1,95 +1,7 @@ -//! Skybox shaders and CPU code. -use crabslab::{Id, Slab}; -use glam::{Mat3, Mat4, Vec2, Vec3, Vec4, Vec4Swizzles}; -use spirv_std::{ - image::{Cubemap, Image2d}, - spirv, Sampler, -}; - -#[allow(unused_imports)] -use spirv_std::num_traits::Float; - -use crate::{ - camera::shader::CameraDescriptor, - math::{self, IsVector}, -}; - +//! Rendering skylines at infinite distances. #[cfg(not(target_arch = "spirv"))] mod cpu; #[cfg(not(target_arch = "spirv"))] pub use cpu::*; -const INV_ATAN: Vec2 = Vec2::new(0.1591, core::f32::consts::FRAC_1_PI); - -/// Takes a unit direction and converts it to a uv lookup in an equirectangular -/// map. -pub fn direction_to_equirectangular_uv(dir: Vec3) -> Vec2 { - let mut uv = Vec2::new(f32::atan2(dir.z, dir.x), f32::asin(dir.y)); - uv *= INV_ATAN; - uv += 0.5; - uv -} - -/// Vertex shader for a skybox. -#[spirv(vertex)] -pub fn skybox_vertex( - #[spirv(instance_index)] camera_index: u32, - #[spirv(vertex_index)] vertex_index: u32, - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - local_pos: &mut Vec3, - #[spirv(position)] clip_pos: &mut Vec4, -) { - let camera_id = Id::::from(camera_index); - let camera = slab.read(camera_id); - let point = math::CUBE[vertex_index as usize]; - *local_pos = point; - let camera_view_without_translation = Mat3::from_mat4(camera.view()); - let rot_view = Mat4::from_mat3(camera_view_without_translation); - let position = camera.projection() * rot_view * point.extend(1.0); - *clip_pos = position.xyww(); -} - -/// Colors a skybox using a cubemap texture. -#[spirv(fragment)] -pub fn skybox_cubemap_fragment( - #[spirv(descriptor_set = 0, binding = 1)] texture: &Cubemap, - #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, - local_pos: Vec3, - out_color: &mut Vec4, -) { - let env_color: Vec3 = texture.sample(*sampler, local_pos.alt_norm_or_zero()).xyz(); - *out_color = env_color.extend(1.0); -} - -/// Vertex shader that draws a cubemap. -/// -/// Uses the `instance_index` as the [`Id`] for a [`CameraDescriptor`]. -/// -/// Used to create a cubemap from an equirectangular image as well as cubemap -/// convolutions. -#[spirv(vertex)] -pub fn skybox_cubemap_vertex( - #[spirv(instance_index)] camera_id: Id, - #[spirv(vertex_index)] vertex_index: u32, - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - local_pos: &mut Vec3, - #[spirv(position)] gl_pos: &mut Vec4, -) { - let camera = slab.read(camera_id); - let pos = crate::math::CUBE[vertex_index as usize]; - *local_pos = pos; - *gl_pos = camera.view_projection() * pos.extend(1.0); -} - -/// Fragment shader that colors a skybox using an equirectangular texture. -#[spirv(fragment)] -pub fn skybox_equirectangular_fragment( - #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, - local_pos: Vec3, - out_color: &mut Vec4, -) { - let uv = direction_to_equirectangular_uv(local_pos.alt_norm_or_zero()); - let env_color: Vec3 = texture.sample(*sampler, uv).xyz(); - *out_color = env_color.extend(1.0); -} +pub mod shader; diff --git a/crates/renderling/src/skybox/shader.rs b/crates/renderling/src/skybox/shader.rs new file mode 100644 index 00000000..bc9047a0 --- /dev/null +++ b/crates/renderling/src/skybox/shader.rs @@ -0,0 +1,91 @@ +//! Skybox shaders. + +use crabslab::{Id, Slab}; +use glam::{Mat3, Mat4, Vec2, Vec3, Vec4, Vec4Swizzles}; +use spirv_std::{ + image::{Cubemap, Image2d}, + spirv, Sampler, +}; + +#[allow(unused_imports)] +use spirv_std::num_traits::Float; + +use crate::{ + camera::shader::CameraDescriptor, + math::{self, IsVector}, +}; + +const INV_ATAN: Vec2 = Vec2::new(0.1591, core::f32::consts::FRAC_1_PI); + +/// Takes a unit direction and converts it to a uv lookup in an equirectangular +/// map. +pub fn direction_to_equirectangular_uv(dir: Vec3) -> Vec2 { + let mut uv = Vec2::new(f32::atan2(dir.z, dir.x), f32::asin(dir.y)); + uv *= INV_ATAN; + uv += 0.5; + uv +} + +/// Vertex shader for a skybox. +#[spirv(vertex)] +pub fn skybox_vertex( + #[spirv(instance_index)] camera_index: u32, + #[spirv(vertex_index)] vertex_index: u32, + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], + local_pos: &mut Vec3, + #[spirv(position)] clip_pos: &mut Vec4, +) { + let camera_id = Id::::from(camera_index); + let camera = slab.read(camera_id); + let point = math::CUBE[vertex_index as usize]; + *local_pos = point; + let camera_view_without_translation = Mat3::from_mat4(camera.view()); + let rot_view = Mat4::from_mat3(camera_view_without_translation); + let position = camera.projection() * rot_view * point.extend(1.0); + *clip_pos = position.xyww(); +} + +/// Colors a skybox using a cubemap texture. +#[spirv(fragment)] +pub fn skybox_cubemap_fragment( + #[spirv(descriptor_set = 0, binding = 1)] texture: &Cubemap, + #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, + local_pos: Vec3, + out_color: &mut Vec4, +) { + let env_color: Vec3 = texture.sample(*sampler, local_pos.alt_norm_or_zero()).xyz(); + *out_color = env_color.extend(1.0); +} + +/// Vertex shader that draws a cubemap. +/// +/// Uses the `instance_index` as the [`Id`] for a [`CameraDescriptor`]. +/// +/// Used to create a cubemap from an equirectangular image as well as cubemap +/// convolutions. +#[spirv(vertex)] +pub fn skybox_cubemap_vertex( + #[spirv(instance_index)] camera_id: Id, + #[spirv(vertex_index)] vertex_index: u32, + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], + local_pos: &mut Vec3, + #[spirv(position)] gl_pos: &mut Vec4, +) { + let camera = slab.read(camera_id); + let pos = crate::math::CUBE[vertex_index as usize]; + *local_pos = pos; + *gl_pos = camera.view_projection() * pos.extend(1.0); +} + +/// Fragment shader that colors a skybox using an equirectangular texture. +#[spirv(fragment)] +pub fn skybox_equirectangular_fragment( + #[spirv(descriptor_set = 0, binding = 1)] texture: &Image2d, + #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, + local_pos: Vec3, + out_color: &mut Vec4, +) { + let uv = direction_to_equirectangular_uv(local_pos.alt_norm_or_zero()); + let env_color: Vec3 = texture.sample(*sampler, uv).xyz(); + *out_color = env_color.extend(1.0); +} From a86e60f1ff489a3b0c1f037428834bf126ff8063 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Fri, 19 Sep 2025 16:48:57 +1200 Subject: [PATCH 19/31] Atlas: update images in place --- crates/renderling/src/atlas/atlas_image.rs | 20 +++ crates/renderling/src/atlas/cpu.rs | 188 +++++++++++++++++---- crates/renderling/src/light/shadow_map.rs | 8 +- 3 files changed, 176 insertions(+), 40 deletions(-) diff --git a/crates/renderling/src/atlas/atlas_image.rs b/crates/renderling/src/atlas/atlas_image.rs index 08aa9aee..ec4bf3a2 100644 --- a/crates/renderling/src/atlas/atlas_image.rs +++ b/crates/renderling/src/atlas/atlas_image.rs @@ -46,6 +46,26 @@ pub enum AtlasImageFormat { D32FLOAT, } +impl From for wgpu::TextureFormat { + fn from(value: AtlasImageFormat) -> Self { + match value { + AtlasImageFormat::R8 => wgpu::TextureFormat::R8Unorm, + AtlasImageFormat::R8G8 => wgpu::TextureFormat::Rg8Unorm, + AtlasImageFormat::R8G8B8 => wgpu::TextureFormat::Rgba8Unorm, // No direct 3-channel format, using 4-channel + AtlasImageFormat::R8G8B8A8 => wgpu::TextureFormat::Rgba8Unorm, + AtlasImageFormat::R16 => wgpu::TextureFormat::R16Unorm, + AtlasImageFormat::R16G16 => wgpu::TextureFormat::Rg16Unorm, + AtlasImageFormat::R16G16B16 => wgpu::TextureFormat::Rgba16Unorm, // No direct 3-channel format, using 4-channel + AtlasImageFormat::R16G16B16A16 => wgpu::TextureFormat::Rgba16Unorm, + AtlasImageFormat::R16G16B16A16FLOAT => wgpu::TextureFormat::Rgba16Float, + AtlasImageFormat::R32FLOAT => wgpu::TextureFormat::R32Float, + AtlasImageFormat::R32G32B32FLOAT => wgpu::TextureFormat::Rgba32Float, // No direct 3-channel format, using 4-channel + AtlasImageFormat::R32G32B32A32FLOAT => wgpu::TextureFormat::Rgba32Float, + AtlasImageFormat::D32FLOAT => wgpu::TextureFormat::Depth32Float, + } + } +} + impl AtlasImageFormat { pub fn from_wgpu_texture_format(value: wgpu::TextureFormat) -> Option { match value { diff --git a/crates/renderling/src/atlas/cpu.rs b/crates/renderling/src/atlas/cpu.rs index f978ee02..b1f138fc 100644 --- a/crates/renderling/src/atlas/cpu.rs +++ b/crates/renderling/src/atlas/cpu.rs @@ -17,7 +17,7 @@ use crate::{ TextureModes, }, bindgroup::ManagedBindGroup, - texture::{CopiedTextureBuffer, Texture}, + texture::{self, CopiedTextureBuffer, Texture}, }; use super::atlas_image::{convert_pixels, AtlasImage}; @@ -41,6 +41,11 @@ pub enum AtlasError { #[snafu(display("Missing bindgroup {layer}"))] MissingBindgroup { layer: u32 }, + + #[snafu(display("{source}"))] + Texture { + source: crate::texture::TextureError, + }, } /// A staged texture in the texture atlas. @@ -200,6 +205,8 @@ pub struct Atlas { layers: Arc>>, label: Option, descriptor: Hybrid, + /// Used for user updates into the atlas by blit images into specific frames. + blitter: AtlasBlitter, } impl Atlas { @@ -286,13 +293,18 @@ impl Atlas { size: UVec3::new(size.width, size.height, size.depth_or_array_layers), }); let label = label.map(|s| s.to_owned()); - + let blitter = AtlasBlitter::new( + slab.device(), + texture.texture.format(), + wgpu::FilterMode::Linear, + ); Atlas { slab: slab.clone(), layers: Arc::new(RwLock::new(layers)), - texture_array: Arc::new(RwLock::new(texture)), descriptor, label, + blitter, + texture_array: Arc::new(RwLock::new(texture)), } } @@ -523,6 +535,107 @@ impl Atlas { } images } + + /// Update the given [`AtlasTexture`] with a [`Texture`](crate::texture::Texture). + /// + /// This will blit the `Texture` into the frame of the [`Atlas`] pointed to by the + /// `AtlasTexture`. + /// + /// Returns a submission index that can be polled with [`wgpu::Device::poll`]. + pub fn update_texture( + &self, + atlas_texture: &AtlasTexture, + source_texture: &texture::Texture, + ) -> Result { + self.update_textures(Some((atlas_texture, source_texture))) + } + + /// Update the given [`AtlasTexture`]s with [`Texture`](crate::texture::Texture)s. + /// + /// This will blit the `Texture` into the frame of the [`Atlas`] pointed to by the + /// `AtlasTexture`. + /// + /// Returns a submission index that can be polled with [`wgpu::Device::poll`]. + pub fn update_textures<'a>( + &self, + updates: impl IntoIterator, + ) -> Result { + let updates = updates.into_iter().collect::>(); + let op = AtlasBlittingOperation::new(&self.blitter, &self, updates.len()); + let runtime = self.slab.runtime(); + let mut encoder = runtime + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Atlas::update_texture"), + }); + for (i, (atlas_texture, source_texture)) in updates.into_iter().enumerate() { + op.run( + &runtime, + &mut encoder, + source_texture, + i as u32, + &self, + atlas_texture, + )?; + } + Ok(runtime.queue.submit(Some(encoder.finish()))) + } + + /// Update the given [`AtlasTexture`]s with new data. + /// + /// This will blit the image data into the frame of the [`Atlas`] pointed to by the + /// `AtlasTexture`. + /// + /// Returns a submission index that can be polled with [`wgpu::Device::poll`]. + pub fn update_images<'a>( + &self, + updates: impl IntoIterator)>, + ) -> Result { + let (atlas_textures, images): (Vec<_>, Vec<_>) = updates.into_iter().unzip(); + let mut textures = vec![]; + for image in images.into_iter() { + let image: AtlasImage = image.into(); + let atlas_format = self.get_texture().texture.format(); + let bytes = super::atlas_image::convert_pixels( + image.pixels, + image.format, + atlas_format, + image.apply_linear_transfer, + ); + let (channels, subpixel_bytes) = + texture::wgpu_texture_format_channels_and_subpixel_bytes(atlas_format) + .context(TextureSnafu)?; + let texture = texture::Texture::new_with( + self.slab.runtime(), + Some("atlas-image-update"), + Some(wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST), + None, + atlas_format, + channels, + subpixel_bytes, + image.size.x, + image.size.y, + 1, + &bytes, + ); + textures.push(texture); + } + self.update_textures(atlas_textures.into_iter().zip(textures.iter())) + } + + /// Update the given [`AtlasTexture`]s with new data. + /// + /// This will blit the image data into the frame of the [`Atlas`] pointed to by the + /// `AtlasTexture`. + /// + /// Returns a submission index that can be polled with [`wgpu::Device::poll`]. + pub fn update_image( + &self, + atlas_texture: &AtlasTexture, + source_image: impl Into, + ) -> Result { + self.update_images(Some((atlas_texture, source_image))) + } } fn pack_images<'a>( @@ -750,6 +863,30 @@ pub struct AtlasBlittingOperation { } impl AtlasBlittingOperation { + pub fn new( + blitter: &AtlasBlitter, + into_atlas: &Atlas, + source_layers: usize, + ) -> AtlasBlittingOperation { + AtlasBlittingOperation { + desc: into_atlas + .slab + .new_value(AtlasBlittingDescriptor::default()), + atlas_slab_buffer: Arc::new(Mutex::new(into_atlas.slab.commit())), + bindgroups: { + let mut bgs = vec![]; + for _ in 0..source_layers { + bgs.push(ManagedBindGroup::default()); + } + Arc::new(bgs) + }, + pipeline: blitter.pipeline.clone(), + sampler: blitter.sampler.clone(), + bindgroup_layout: blitter.bind_group_layout.clone(), + from_texture_id: Default::default(), + } + } + /// Copies the data from texture this [`AtlasBlittingOperation`] was created with /// into the atlas. /// @@ -760,7 +897,7 @@ impl AtlasBlittingOperation { runtime: impl AsRef, encoder: &mut wgpu::CommandEncoder, from_texture: &crate::texture::Texture, - layer: u32, + from_layer: u32, to_atlas: &Atlas, atlas_texture: &AtlasTexture, ) -> Result<(), AtlasError> { @@ -788,15 +925,15 @@ impl AtlasBlittingOperation { .texture .create_view(&wgpu::TextureViewDescriptor { label: Some("atlas-blitting"), - base_array_layer: layer, + base_array_layer: from_layer, array_layer_count: Some(1), dimension: Some(wgpu::TextureViewDimension::D2), ..Default::default() }); let bindgroup = self .bindgroups - .get(layer as usize) - .context(MissingBindgroupSnafu { layer })? + .get(from_layer as usize) + .context(MissingBindgroupSnafu { layer: from_layer })? .get(should_invalidate, || { runtime .device @@ -874,19 +1011,20 @@ impl AtlasBlitter { /// /// # Arguments /// - `device` - A [`wgpu::Device`] - /// - `format` - The [`wgpu::TextureFormat`] of the texture that will be copied to. This has to be renderable. - /// - `sample_type` - The [`wgpu::Sampler`] Filtering Mode + /// - `format` - The [`wgpu::TextureFormat`] of the atlas being updated. + /// - `mag_filter` - The filtering algorithm to use when magnifying. + /// This is used when the input source is smaller than the destination. pub fn new( device: &wgpu::Device, format: wgpu::TextureFormat, - sample_type: wgpu::FilterMode, + mag_filter: wgpu::FilterMode, ) -> Self { let sampler = device.create_sampler(&wgpu::SamplerDescriptor { label: Some("atlas-blitter"), address_mode_u: wgpu::AddressMode::ClampToEdge, address_mode_v: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: sample_type, + mag_filter, ..Default::default() }); @@ -908,7 +1046,7 @@ impl AtlasBlitter { visibility: wgpu::ShaderStages::FRAGMENT, ty: wgpu::BindingType::Texture { sample_type: wgpu::TextureSampleType::Float { - filterable: sample_type == wgpu::FilterMode::Linear, + filterable: mag_filter == wgpu::FilterMode::Linear, }, view_dimension: wgpu::TextureViewDimension::D2, multisampled: false, @@ -918,7 +1056,7 @@ impl AtlasBlitter { wgpu::BindGroupLayoutEntry { binding: 2, visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(if sample_type == wgpu::FilterMode::Linear { + ty: wgpu::BindingType::Sampler(if mag_filter == wgpu::FilterMode::Linear { wgpu::SamplerBindingType::Filtering } else { wgpu::SamplerBindingType::NonFiltering @@ -976,30 +1114,6 @@ impl AtlasBlitter { sampler: sampler.into(), } } - - pub fn new_blitting_operation( - &self, - into_atlas: &Atlas, - layers: usize, - ) -> AtlasBlittingOperation { - AtlasBlittingOperation { - desc: into_atlas - .slab - .new_value(AtlasBlittingDescriptor::default()), - atlas_slab_buffer: Arc::new(Mutex::new(into_atlas.slab.commit())), - bindgroups: { - let mut bgs = vec![]; - for _ in 0..layers { - bgs.push(ManagedBindGroup::default()); - } - Arc::new(bgs) - }, - pipeline: self.pipeline.clone(), - sampler: self.sampler.clone(), - bindgroup_layout: self.bind_group_layout.clone(), - from_texture_id: Default::default(), - } - } } #[cfg(test)] diff --git a/crates/renderling/src/light/shadow_map.rs b/crates/renderling/src/light/shadow_map.rs index e0649887..c520ee71 100644 --- a/crates/renderling/src/light/shadow_map.rs +++ b/crates/renderling/src/light/shadow_map.rs @@ -204,9 +204,11 @@ impl ShadowMap { let atlas_textures_array = lighting .light_slab .new_array(atlas_textures.iter().map(|t| t.id())); - let blitting_op = lighting - .shadow_map_update_blitter - .new_blitting_operation(atlas, if is_point_light { 6 } else { 1 }); + let blitting_op = AtlasBlittingOperation::new( + &lighting.shadow_map_update_blitter, + atlas, + if is_point_light { 6 } else { 1 }, + ); let light_space_transforms = lighting .light_slab From d95167e15399b826f961bfe57ba7f13d9199263f Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 08:13:45 +1200 Subject: [PATCH 20/31] move test utils into lib under feature gate --- Cargo.lock | 1 + crates/examples/Cargo.toml | 3 +- crates/examples/src/lib.rs | 7 +- crates/examples/src/skybox.rs | 21 +++++- crates/renderling-build/src/lib.rs | 10 +++ crates/renderling/Cargo.toml | 8 +- crates/renderling/src/lib.rs | 113 +++++++++++++++------------- crates/renderling/src/skybox/cpu.rs | 3 +- 8 files changed, 104 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d05e257b..55c64253 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1182,6 +1182,7 @@ dependencies = [ "env_logger", "futures-lite 1.13.0", "renderling", + "renderling_build", "tokio", ] diff --git a/crates/examples/Cargo.toml b/crates/examples/Cargo.toml index 116e1e5c..06c8170a 100644 --- a/crates/examples/Cargo.toml +++ b/crates/examples/Cargo.toml @@ -7,5 +7,6 @@ edition = "2024" doc-comment = "0.3" env_logger.workspace = true futures-lite.workspace = true -renderling = { path = "../renderling" } +renderling = { path = "../renderling", features = ["test-utils"] } +renderling_build = { path = "../renderling-build" } tokio = { workspace = true, features = ["full"] } diff --git a/crates/examples/src/lib.rs b/crates/examples/src/lib.rs index a0ca8ea0..3f364334 100644 --- a/crates/examples/src/lib.rs +++ b/crates/examples/src/lib.rs @@ -25,8 +25,11 @@ pub fn cwd_to_manual_assets_dir() -> std::path::PathBuf { } pub fn workspace_dir() -> std::path::PathBuf { - let current_dir = std::path::PathBuf::from(std::env!("CARGO_WORKSPACE_DIR")); - current_dir.canonicalize().unwrap() + renderling_build::workspace_dir().canonicalize().unwrap() +} + +pub fn test_output_dir() -> std::path::PathBuf { + renderling_build::test_output_dir().canonicalize().unwrap() } pub fn cwd_to_cargo_workspace() -> std::path::PathBuf { diff --git a/crates/examples/src/skybox.rs b/crates/examples/src/skybox.rs index f7de222c..f1c20586 100644 --- a/crates/examples/src/skybox.rs +++ b/crates/examples/src/skybox.rs @@ -1,6 +1,6 @@ //! Skybox manual page. -use crate::workspace_dir; +use crate::{test_output_dir, workspace_dir}; #[tokio::test] async fn manual_skybox() { @@ -60,4 +60,23 @@ async fn manual_skybox() { image.save("skybox.png").unwrap(); frame.present(); // ANCHOR_END: render_skybox + // + + let frame = ctx.get_next_frame().unwrap(); + renderling::capture_gpu_frame(&ctx, test_output_dir().join("skybox.gputrace"), || { + stage.render(&frame.view()); + }); + let image = frame.read_image().await.unwrap(); + image.save("skybox.png").unwrap(); + frame.present(); + let frame = ctx.get_next_frame().unwrap(); + stage.render(&frame.view()); + let image = frame.read_image().await.unwrap(); + image.save("skybox.png").unwrap(); + frame.present(); + let frame = ctx.get_next_frame().unwrap(); + stage.render(&frame.view()); + let image = frame.read_image().await.unwrap(); + image.save("skybox.png").unwrap(); + frame.present(); } diff --git a/crates/renderling-build/src/lib.rs b/crates/renderling-build/src/lib.rs index 7ad7a0de..64a1a2dd 100644 --- a/crates/renderling-build/src/lib.rs +++ b/crates/renderling-build/src/lib.rs @@ -137,6 +137,16 @@ fn wgsl(spv_filepath: impl AsRef, destination: impl AsRef std::path::PathBuf { + std::path::PathBuf::from(std::env!("CARGO_WORKSPACE_DIR")) +} + +/// The test_output directory. +pub fn test_output_dir() -> std::path::PathBuf { + workspace_dir().join("test_output") +} + #[derive(Debug)] pub struct RenderlingPaths { /// `cargo_workspace` is not available when building outside of the project directory. diff --git a/crates/renderling/Cargo.toml b/crates/renderling/Cargo.toml index 40e726e3..f5b37fd8 100644 --- a/crates/renderling/Cargo.toml +++ b/crates/renderling/Cargo.toml @@ -26,6 +26,7 @@ crate-type = ["rlib", "cdylib"] default = ["gltf", "ui", "winit"] gltf = ["dep:gltf", "dep:serde_json"] test_i8_i16_extraction = [] +test-utils = ["dep:metal", "dep:wgpu-core"] ui = ["dep:glyph_brush", "dep:loading-bytes", "dep:lyon"] wasm = ["wgpu/fragile-send-sync-non-atomic-wasm"] debug-slab = [] @@ -90,17 +91,18 @@ human-repr = "1.1.0" icosahedron = "0.1" img-diff = { path = "../img-diff" } naga.workspace = true +renderling_build = { path = "../renderling-build" } ttf-parser = "0.20.0" wasm-bindgen-test.workspace = true -wgpu-core.workspace = true winit.workspace = true wire-types = { path = "../wire-types" } [target.'cfg(not(target_arch = "spirv"))'.dev-dependencies] glam = { workspace = true, features = ["std", "debug-glam-assert"] } -[target.'cfg(target_os = "macos")'.dev-dependencies] -metal.workspace = true +[target.'cfg(target_os = "macos")'.dependencies] +metal = { workspace = true, optional = true } +wgpu-core = { workspace = true, optional = true } [dev-dependencies.web-sys] workspace = true diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index db85adf2..19a7b60b 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -253,6 +253,55 @@ macro_rules! println { } } +#[cfg(all(cpu, feature = "test-utils"))] +#[allow(unused, reason = "Used in debugging on macos")] +pub fn capture_gpu_frame( + ctx: &crate::context::Context, + path: impl AsRef, + f: impl FnOnce() -> T, +) -> T { + let path = path.as_ref(); + let parent = path.parent().unwrap(); + std::fs::create_dir_all(parent).unwrap(); + + #[cfg(target_os = "macos")] + { + if path.exists() { + log::info!( + "deleting {} before writing gpu frame capture", + path.display() + ); + std::fs::remove_dir_all(path).unwrap(); + } + + if std::env::var("METAL_CAPTURE_ENABLED").is_err() { + log::error!("Env var METAL_CAPTURE_ENABLED must be set"); + panic!("missing METAL_CAPTURE_ENABLED=1"); + } + + let m = metal::CaptureManager::shared(); + let desc = metal::CaptureDescriptor::new(); + + desc.set_destination(metal::MTLCaptureDestination::GpuTraceDocument); + desc.set_output_url(path); + let maybe_metal_device = unsafe { ctx.get_device().as_hal::() }; + if let Some(metal_device) = maybe_metal_device { + desc.set_capture_device(metal_device.raw_device().try_lock().unwrap().as_ref()); + } else { + panic!("not a capturable device") + } + m.start_capture(&desc).unwrap(); + let t = f(); + m.stop_capture(); + t + } + #[cfg(not(target_os = "macos"))] + { + log::warn!("capturing a GPU frame is only supported on macos"); + f() + } +} + #[cfg(test)] mod test { use super::*; @@ -264,19 +313,22 @@ mod test { use pretty_assertions::assert_eq; use stage::Stage; + pub use renderling_build::{test_output_dir, workspace_dir}; + #[cfg_attr(not(target_arch = "wasm32"), ctor::ctor)] fn init_logging() { let _ = env_logger::builder().is_test(true).try_init(); log::info!("logging is on"); } - pub fn workspace_dir() -> std::path::PathBuf { - std::path::PathBuf::from(std::env!("CARGO_WORKSPACE_DIR")) - } - - #[allow(dead_code)] - pub fn test_output_dir() -> std::path::PathBuf { - workspace_dir().join("test_output") + #[allow(unused, reason = "Used in debugging on macos")] + pub fn capture_gpu_frame( + ctx: &Context, + path: impl AsRef, + f: impl FnOnce() -> T, + ) -> T { + let path = workspace_dir().join("test_output").join(path); + super::capture_gpu_frame(ctx, path, f) } /// Marker trait to block on futures in synchronous code. @@ -315,53 +367,6 @@ mod test { (sunlight_a.into_generic(), sunlight_b.into_generic()) } - #[allow(unused, reason = "Used in debugging on macos")] - pub fn capture_gpu_frame( - ctx: &Context, - path: impl AsRef, - f: impl FnOnce() -> T, - ) -> T { - let path = workspace_dir().join("test_output").join(path); - let parent = path.parent().unwrap(); - std::fs::create_dir_all(parent).unwrap(); - - #[cfg(target_os = "macos")] - { - if path.exists() { - log::info!( - "deleting {} before writing gpu frame capture", - path.display() - ); - std::fs::remove_dir_all(&path).unwrap(); - } - - if std::env::var("METAL_CAPTURE_ENABLED").is_err() { - log::error!("Env var METAL_CAPTURE_ENABLED must be set"); - panic!("missing METAL_CAPTURE_ENABLED=1"); - } - - let m = metal::CaptureManager::shared(); - let desc = metal::CaptureDescriptor::new(); - - desc.set_destination(metal::MTLCaptureDestination::GpuTraceDocument); - desc.set_output_url(path); - let maybe_metal_device = unsafe { ctx.get_device().as_hal::() }; - if let Some(metal_device) = maybe_metal_device { - desc.set_capture_device(metal_device.raw_device().try_lock().unwrap().as_ref()); - } else { - panic!("not a capturable device") - } - m.start_capture(&desc).unwrap(); - let t = f(); - m.stop_capture(); - t - } - #[cfg(not(target_os = "macos"))] - { - f() - } - } - #[test] fn sanity_transmute() { let zerof32 = 0f32; diff --git a/crates/renderling/src/skybox/cpu.rs b/crates/renderling/src/skybox/cpu.rs index a81d22a1..88023af1 100644 --- a/crates/renderling/src/skybox/cpu.rs +++ b/crates/renderling/src/skybox/cpu.rs @@ -152,7 +152,8 @@ pub(crate) fn create_skybox_render_pipeline( /// A clone of a skybox is a reference to the same skybox. /// /// Only available on the CPU. Not available in shaders. -// TODO: spilt Skybox into Skybox and IBL components. +// TODO: move brdf lut into Stage or Context, we only need one, ever +// TODO: decouple Skybox and IBL // Skybox and IBL are different things. Sometimes you want to use a // skybox without having it shade things. // Also, the brdf_lut doesn't change, so should probably live in `Lighting` From fd625b80d0700de3880776207e04b6f10fc0894e Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 09:04:36 +1200 Subject: [PATCH 21/31] separated brdf lut from skybox --- crates/renderling/src/pbr.rs | 24 ++--- crates/renderling/src/pbr/brdf.rs | 10 +++ crates/renderling/src/pbr/brdf/cpu.rs | 108 +++++++++++++++++++++++ crates/renderling/src/pbr/brdf/shader.rs | 21 +++++ crates/renderling/src/skybox/cpu.rs | 105 ++-------------------- crates/renderling/src/stage/cpu.rs | 17 +++- crates/renderling/src/texture.rs | 2 + 7 files changed, 169 insertions(+), 118 deletions(-) create mode 100644 crates/renderling/src/pbr/brdf.rs create mode 100644 crates/renderling/src/pbr/brdf/cpu.rs create mode 100644 crates/renderling/src/pbr/brdf/shader.rs diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index 69fde69b..cb3518ca 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -1,4 +1,4 @@ -//! "Physically based" shader types and functions. +//! "Physically based" types and functions. //! //! ## References //! * @@ -23,7 +23,9 @@ use crate::{ println as my_println, }; +pub mod brdf; pub mod debug; + use debug::DebugChannel; /// Trowbridge-Reitz GGX normal distribution function (NDF). @@ -163,22 +165,6 @@ pub fn sample_specular_reflection, S: IsSampler>( .xyz() } -pub fn sample_brdf, S: IsSampler>( - brdf: &T, - brdf_sampler: &S, - // camera position in world space - camera_pos: Vec3, - // fragment position in world space - in_pos: Vec3, - // normal vector - n: Vec3, - roughness: f32, -) -> Vec2 { - let v = (camera_pos - in_pos).alt_norm_or_zero(); - brdf.sample_by_lod(*brdf_sampler, Vec2::new(n.dot(v).max(0.0), roughness), 0.0) - .xy() -} - /// Returns the `Material` from the stage's slab. pub fn get_material( material_id: Id, @@ -382,7 +368,8 @@ pub fn fragment_impl( n, roughness, ); - let brdf = sample_brdf(brdf, brdf_sampler, camera.position(), in_pos, n, roughness); + let brdf = + brdf::shader::sample_brdf(brdf, brdf_sampler, camera.position(), in_pos, n, roughness); fn colorize(u: Vec3) -> Vec4 { ((u.alt_norm_or_zero() + Vec3::splat(1.0)) / 2.0).extend(1.0) @@ -668,6 +655,7 @@ mod test { atlas::AtlasImage, geometry::Vertex, glam::{Vec3, Vec4}, + pbr::brdf::BrdfLut, test::BlockOnFuture, }; diff --git a/crates/renderling/src/pbr/brdf.rs b/crates/renderling/src/pbr/brdf.rs new file mode 100644 index 00000000..c51e8bdd --- /dev/null +++ b/crates/renderling/src/pbr/brdf.rs @@ -0,0 +1,10 @@ +//! BRDF computation. +//! +//! Helpers for computing (and holding onto) a Bidirectional Reflectance Distribution Function. + +#[cfg(cpu)] +mod cpu; +#[cfg(cpu)] +pub use cpu::*; + +pub mod shader; diff --git a/crates/renderling/src/pbr/brdf/cpu.rs b/crates/renderling/src/pbr/brdf/cpu.rs new file mode 100644 index 00000000..b041f1eb --- /dev/null +++ b/crates/renderling/src/pbr/brdf/cpu.rs @@ -0,0 +1,108 @@ +//! CPU side of BRDF stuff. +use craballoc::runtime::WgpuRuntime; + +use crate::texture; + +/// Pre-computed texture of the brdf integration. +#[derive(Clone)] +pub struct BrdfLut { + pub(crate) inner: texture::Texture, +} + +impl BrdfLut { + /// Create a new pre-computed BRDF look-up texture. + pub fn new(runtime: impl AsRef) -> Self { + let runtime = runtime.as_ref(); + let device = &runtime.device; + let queue = &runtime.queue; + let vertex_linkage = crate::linkage::brdf_lut_convolution_vertex::linkage(device); + let fragment_linkage = crate::linkage::brdf_lut_convolution_fragment::linkage(device); + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("brdf_lut_convolution"), + layout: None, + vertex: wgpu::VertexState { + module: &vertex_linkage.module, + entry_point: Some(vertex_linkage.entry_point), + buffers: &[], + compilation_options: Default::default(), + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + mask: !0, + alpha_to_coverage_enabled: false, + count: 1, + }, + fragment: Some(wgpu::FragmentState { + module: &fragment_linkage.module, + entry_point: Some(fragment_linkage.entry_point), + targets: &[Some(wgpu::ColorTargetState { + format: wgpu::TextureFormat::Rg16Float, + blend: Some(wgpu::BlendState { + color: wgpu::BlendComponent::REPLACE, + alpha: wgpu::BlendComponent::REPLACE, + }), + write_mask: wgpu::ColorWrites::ALL, + })], + compilation_options: Default::default(), + }), + multiview: None, + cache: None, + }); + + let framebuffer = texture::Texture::new_with( + runtime, + Some("brdf_lut"), + Some( + wgpu::TextureUsages::RENDER_ATTACHMENT + | wgpu::TextureUsages::TEXTURE_BINDING + | wgpu::TextureUsages::COPY_SRC, + ), + None, + wgpu::TextureFormat::Rg16Float, + 2, + 2, + 512, + 512, + 1, + &[], + ); + + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); + { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some("brdf_lut_convolution"), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &framebuffer.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::RED), + store: wgpu::StoreOp::Store, + }, + depth_slice: None, + })], + depth_stencil_attachment: None, + ..Default::default() + }); + + render_pass.set_pipeline(&pipeline); + render_pass.draw(0..6, 0..1); + } + queue.submit([encoder.finish()]); + + BrdfLut { inner: framebuffer } + } + + /// Return the underlying [`Texture`](crate::texture::Texture). + pub fn texture(&self) -> &texture::Texture { + &self.inner + } +} diff --git a/crates/renderling/src/pbr/brdf/shader.rs b/crates/renderling/src/pbr/brdf/shader.rs new file mode 100644 index 00000000..8249f674 --- /dev/null +++ b/crates/renderling/src/pbr/brdf/shader.rs @@ -0,0 +1,21 @@ +//! Shader side of BRDF stuff. + +use glam::{Vec2, Vec3, Vec4Swizzles}; + +use crate::math::{IsSampler, IsVector, Sample2d}; + +pub fn sample_brdf, S: IsSampler>( + brdf: &T, + brdf_sampler: &S, + // camera position in world space + camera_pos: Vec3, + // fragment position in world space + in_pos: Vec3, + // normal vector + n: Vec3, + roughness: f32, +) -> Vec2 { + let v = (camera_pos - in_pos).alt_norm_or_zero(); + brdf.sample_by_lod(*brdf_sampler, Vec2::new(n.dot(v).max(0.0), roughness), 0.0) + .xy() +} diff --git a/crates/renderling/src/skybox/cpu.rs b/crates/renderling/src/skybox/cpu.rs index 88023af1..287a8d77 100644 --- a/crates/renderling/src/skybox/cpu.rs +++ b/crates/renderling/src/skybox/cpu.rs @@ -9,7 +9,7 @@ use glam::{Mat4, UVec2, Vec3}; use crate::{ atlas::AtlasImage, camera::shader::CameraDescriptor, convolution::VertexPrefilterEnvironmentCubemapIds, - cubemap::EquirectangularImageToCubemapBlitter, texture::Texture, + cubemap::EquirectangularImageToCubemapBlitter, pbr::brdf::BrdfLut, texture::Texture, }; /// Render pipeline used to draw a skybox. @@ -166,8 +166,6 @@ pub struct Skybox { // Cubemap texture and mip maps of the specular highlights, // where each mip level is a different roughness. pub prefiltered_environment_cubemap: Texture, - // Texture of the pre-computed brdf integration - pub brdf_lut: Texture, } impl Skybox { @@ -271,13 +269,10 @@ impl Skybox { views, ); - let brdf_lut = Skybox::create_precomputed_brdf_texture(runtime); - Skybox { environment_cubemap, irradiance_cubemap, prefiltered_environment_cubemap, - brdf_lut, } } @@ -556,95 +551,6 @@ impl Skybox { 5, ) } - - fn create_precomputed_brdf_texture(runtime: impl AsRef) -> Texture { - let runtime = runtime.as_ref(); - let device = &runtime.device; - let queue = &runtime.queue; - let vertex_linkage = crate::linkage::brdf_lut_convolution_vertex::linkage(device); - let fragment_linkage = crate::linkage::brdf_lut_convolution_fragment::linkage(device); - let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("brdf_lut_convolution"), - layout: None, - vertex: wgpu::VertexState { - module: &vertex_linkage.module, - entry_point: Some(vertex_linkage.entry_point), - buffers: &[], - compilation_options: Default::default(), - }, - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: None, - unclipped_depth: false, - polygon_mode: wgpu::PolygonMode::Fill, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState { - mask: !0, - alpha_to_coverage_enabled: false, - count: 1, - }, - fragment: Some(wgpu::FragmentState { - module: &fragment_linkage.module, - entry_point: Some(fragment_linkage.entry_point), - targets: &[Some(wgpu::ColorTargetState { - format: wgpu::TextureFormat::Rg16Float, - blend: Some(wgpu::BlendState { - color: wgpu::BlendComponent::REPLACE, - alpha: wgpu::BlendComponent::REPLACE, - }), - write_mask: wgpu::ColorWrites::ALL, - })], - compilation_options: Default::default(), - }), - multiview: None, - cache: None, - }); - - let framebuffer = Texture::new_with( - runtime, - Some("brdf_lut"), - Some( - wgpu::TextureUsages::RENDER_ATTACHMENT - | wgpu::TextureUsages::TEXTURE_BINDING - | wgpu::TextureUsages::COPY_SRC, - ), - None, - wgpu::TextureFormat::Rg16Float, - 2, - 2, - 512, - 512, - 1, - &[], - ); - - let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor::default()); - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some("brdf_lut_convolution"), - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &framebuffer.view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::RED), - store: wgpu::StoreOp::Store, - }, - depth_slice: None, - })], - depth_stencil_attachment: None, - ..Default::default() - }); - - render_pass.set_pipeline(&pipeline); - render_pass.draw(0..6, 0..1); - } - queue.submit([encoder.finish()]); - framebuffer - } } #[cfg(test)] @@ -741,9 +647,12 @@ mod test { fn precomputed_brdf() { assert_eq!(2, std::mem::size_of::()); let r = Context::headless(32, 32).block(); - let brdf_lut = Skybox::create_precomputed_brdf_texture(&r); - assert_eq!(wgpu::TextureFormat::Rg16Float, brdf_lut.texture.format()); - let copied_buffer = Texture::read(&r, &brdf_lut.texture, 512, 512, 2, 2); + let brdf_lut = BrdfLut::new(&r); + assert_eq!( + wgpu::TextureFormat::Rg16Float, + brdf_lut.texture().texture.format() + ); + let copied_buffer = Texture::read(&r, &brdf_lut.texture().texture, 512, 512, 2, 2); let pixels = copied_buffer.pixels(r.get_device()).block().unwrap(); let pixels: Vec = bytemuck::cast_slice::(pixels.as_slice()) .iter() diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index e453bfaa..b3406cba 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -14,6 +14,7 @@ use crate::geometry::{shader::GeometryDescriptor, MorphTarget, Vertex}; use crate::gltf::GltfDocument; use crate::light::{DirectionalLight, IsLight, Light, PointLight, SpotLight}; use crate::material::Material; +use crate::pbr::brdf::BrdfLut; use crate::primitive::Primitive; use crate::{ atlas::{AtlasError, AtlasImage, AtlasImageError}, @@ -267,8 +268,8 @@ impl StageRendering<'_> { prefiltered_texture_sampler: &skybox .prefiltered_environment_cubemap .sampler, - brdf_texture_view: &skybox.brdf_lut.view, - brdf_texture_sampler: &skybox.brdf_lut.sampler, + brdf_texture_view: &self.stage.brdf_lut.inner.view, + brdf_texture_sampler: &self.stage.brdf_lut.inner.sampler, shadow_map_texture_view: &shadow_map.view, shadow_map_texture_sampler: &shadow_map.sampler, } @@ -394,6 +395,8 @@ pub struct Stage { pub(crate) debug_overlay: DebugOverlay, pub(crate) background_color: Arc>, + pub(crate) brdf_lut: BrdfLut, + pub(crate) skybox: Arc>, pub(crate) skybox_bindgroup: Arc>>>, pub(crate) has_skybox: Arc, @@ -739,6 +742,13 @@ impl Stage { &self.runtime().queue } + /// Returns a reference to the [`BrdfLut`]. + /// + /// This is used for creating skyboxes used in image based lighting. + pub fn brdf_lut(&self) -> &BrdfLut { + &self.brdf_lut + } + /// Sum the byte size of all used GPU memory. /// /// Adds together the byte size of all underlying slab buffers. @@ -997,6 +1007,8 @@ impl Stage { let geometry_buffer = geometry.slab_allocator().commit(); let lighting = Lighting::new(stage_config.shadow_map_atlas_size, &geometry); + let brdf_lut = BrdfLut::new(runtime); + Self { materials, draw_calls: Arc::new(RwLock::new(DrawCalls::new( @@ -1018,6 +1030,7 @@ impl Stage { skybox_bindgroup: Default::default(), skybox_pipeline: Default::default(), has_skybox: Arc::new(AtomicBool::new(false)), + brdf_lut, bloom, tonemapping, has_bloom: AtomicBool::from(true).into(), diff --git a/crates/renderling/src/texture.rs b/crates/renderling/src/texture.rs index fd9205df..5832a870 100644 --- a/crates/renderling/src/texture.rs +++ b/crates/renderling/src/texture.rs @@ -84,6 +84,8 @@ pub(crate) fn get_next_texture_id() -> usize { #[derive(Debug, Clone)] pub struct Texture { pub texture: Arc, + // TODO: revisit whether we really need to create view and sampler for textures + // automatically pub view: Arc, pub sampler: Arc, pub(crate) id: usize, From 9b26d7c952e963e70872999b907647c453c93fc5 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 09:59:19 +1200 Subject: [PATCH 22/31] move ibl into pbr --- crates/renderling/src/ibl/mod.rs | 5 - .../src/ibl/prefiltered_environment.rs | 108 ----------------- crates/renderling/src/lib.rs | 2 +- crates/renderling/src/pbr.rs | 1 + crates/renderling/src/pbr/ibl.rs | 10 ++ .../diffuse_irradiance => pbr/ibl}/cpu.rs | 110 +++++++++++++++++- .../src/pbr/ibl/diffuse_irradiance.rs | 13 +++ .../ibl/shader.rs} | 10 +- crates/renderling/src/skybox/cpu.rs | 19 +-- 9 files changed, 146 insertions(+), 132 deletions(-) delete mode 100644 crates/renderling/src/ibl/mod.rs delete mode 100644 crates/renderling/src/ibl/prefiltered_environment.rs create mode 100644 crates/renderling/src/pbr/ibl.rs rename crates/renderling/src/{ibl/diffuse_irradiance => pbr/ibl}/cpu.rs (55%) create mode 100644 crates/renderling/src/pbr/ibl/diffuse_irradiance.rs rename crates/renderling/src/{ibl/diffuse_irradiance.rs => pbr/ibl/shader.rs} (91%) diff --git a/crates/renderling/src/ibl/mod.rs b/crates/renderling/src/ibl/mod.rs deleted file mode 100644 index 98ba804e..00000000 --- a/crates/renderling/src/ibl/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Shader resources for image based lighting. - -pub mod diffuse_irradiance; -#[cfg(not(target_arch = "spirv"))] -pub mod prefiltered_environment; diff --git a/crates/renderling/src/ibl/prefiltered_environment.rs b/crates/renderling/src/ibl/prefiltered_environment.rs deleted file mode 100644 index 353922c0..00000000 --- a/crates/renderling/src/ibl/prefiltered_environment.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Pipeline for creating a prefiltered environment map from an existing -//! environment cubemap. - -pub fn create_pipeline_and_bindgroup( - device: &wgpu::Device, - buffer: &wgpu::Buffer, - environment_texture: &crate::texture::Texture, -) -> (wgpu::RenderPipeline, wgpu::BindGroup) { - let label = Some("prefiltered environment"); - let bindgroup_layout_desc = wgpu::BindGroupLayoutDescriptor { - label, - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Storage { read_only: true }, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - view_dimension: wgpu::TextureViewDimension::Cube, - multisampled: false, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 2, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - }; - let bg_layout = device.create_bind_group_layout(&bindgroup_layout_desc); - let bindgroup = device.create_bind_group(&wgpu::BindGroupDescriptor { - label, - layout: &bg_layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer(buffer.as_entire_buffer_binding()), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::TextureView(&environment_texture.view), - }, - wgpu::BindGroupEntry { - binding: 2, - resource: wgpu::BindingResource::Sampler(&environment_texture.sampler), - }, - ], - }); - let pp_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label, - bind_group_layouts: &[&bg_layout], - push_constant_ranges: &[], - }); - let vertex_linkage = crate::linkage::prefilter_environment_cubemap_vertex::linkage(device); - let fragment_linkage = crate::linkage::prefilter_environment_cubemap_fragment::linkage(device); - let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: Some("prefiltered environment"), - layout: Some(&pp_layout), - vertex: wgpu::VertexState { - module: &vertex_linkage.module, - entry_point: Some(vertex_linkage.entry_point), - buffers: &[], - compilation_options: Default::default(), - }, - primitive: wgpu::PrimitiveState { - topology: wgpu::PrimitiveTopology::TriangleList, - strip_index_format: None, - front_face: wgpu::FrontFace::Ccw, - cull_mode: None, - unclipped_depth: false, - polygon_mode: wgpu::PolygonMode::Fill, - conservative: false, - }, - depth_stencil: None, - multisample: wgpu::MultisampleState { - mask: !0, - alpha_to_coverage_enabled: false, - count: 1, - }, - fragment: Some(wgpu::FragmentState { - module: &fragment_linkage.module, - entry_point: Some(fragment_linkage.entry_point), - targets: &[Some(wgpu::ColorTargetState { - format: wgpu::TextureFormat::Rgba16Float, - blend: Some(wgpu::BlendState { - color: wgpu::BlendComponent::REPLACE, - alpha: wgpu::BlendComponent::REPLACE, - }), - write_mask: wgpu::ColorWrites::ALL, - })], - compilation_options: Default::default(), - }), - multiview: None, - cache: None, - }); - (pipeline, bindgroup) -} diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index 19a7b60b..e8c277ca 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -216,7 +216,6 @@ pub mod draw; pub mod geometry; #[cfg(all(cpu, gltf))] pub mod gltf; -pub mod ibl; #[cfg(cpu)] pub mod internal; pub mod light; @@ -313,6 +312,7 @@ mod test { use pretty_assertions::assert_eq; use stage::Stage; + #[allow(unused_imports)] pub use renderling_build::{test_output_dir, workspace_dir}; #[cfg_attr(not(target_arch = "wasm32"), ctor::ctor)] diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index cb3518ca..3440a7d1 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -25,6 +25,7 @@ use crate::{ pub mod brdf; pub mod debug; +pub mod ibl; use debug::DebugChannel; diff --git a/crates/renderling/src/pbr/ibl.rs b/crates/renderling/src/pbr/ibl.rs new file mode 100644 index 00000000..a082400d --- /dev/null +++ b/crates/renderling/src/pbr/ibl.rs @@ -0,0 +1,10 @@ +//! Image based lighting +//! +//! For more info on image based lighting, see . + +#[cfg(cpu)] +mod cpu; +#[cfg(cpu)] +pub use cpu::*; + +pub mod shader; diff --git a/crates/renderling/src/ibl/diffuse_irradiance/cpu.rs b/crates/renderling/src/pbr/ibl/cpu.rs similarity index 55% rename from crates/renderling/src/ibl/diffuse_irradiance/cpu.rs rename to crates/renderling/src/pbr/ibl/cpu.rs index 141cdb9c..7673ff18 100644 --- a/crates/renderling/src/ibl/diffuse_irradiance/cpu.rs +++ b/crates/renderling/src/pbr/ibl/cpu.rs @@ -1,4 +1,112 @@ -//! Pipeline and bindings for for diffuse irradiance convolution shaders. +//! CPU side of IBL + +/// Pipeline for creating a prefiltered environment map from an existing +/// environment cubemap. +pub(crate) fn create_prefiltered_environment_pipeline_and_bindgroup( + device: &wgpu::Device, + buffer: &wgpu::Buffer, + environment_texture: &crate::texture::Texture, +) -> (wgpu::RenderPipeline, wgpu::BindGroup) { + let label = Some("prefiltered environment"); + let bindgroup_layout_desc = wgpu::BindGroupLayoutDescriptor { + label, + entries: &[ + wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Storage { read_only: true }, + has_dynamic_offset: false, + min_binding_size: None, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 1, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Texture { + sample_type: wgpu::TextureSampleType::Float { filterable: true }, + view_dimension: wgpu::TextureViewDimension::Cube, + multisampled: false, + }, + count: None, + }, + wgpu::BindGroupLayoutEntry { + binding: 2, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), + count: None, + }, + ], + }; + let bg_layout = device.create_bind_group_layout(&bindgroup_layout_desc); + let bindgroup = device.create_bind_group(&wgpu::BindGroupDescriptor { + label, + layout: &bg_layout, + entries: &[ + wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer(buffer.as_entire_buffer_binding()), + }, + wgpu::BindGroupEntry { + binding: 1, + resource: wgpu::BindingResource::TextureView(&environment_texture.view), + }, + wgpu::BindGroupEntry { + binding: 2, + resource: wgpu::BindingResource::Sampler(&environment_texture.sampler), + }, + ], + }); + let pp_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label, + bind_group_layouts: &[&bg_layout], + push_constant_ranges: &[], + }); + let vertex_linkage = crate::linkage::prefilter_environment_cubemap_vertex::linkage(device); + let fragment_linkage = crate::linkage::prefilter_environment_cubemap_fragment::linkage(device); + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("prefiltered environment"), + layout: Some(&pp_layout), + vertex: wgpu::VertexState { + module: &vertex_linkage.module, + entry_point: Some(vertex_linkage.entry_point), + buffers: &[], + compilation_options: Default::default(), + }, + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: None, + unclipped_depth: false, + polygon_mode: wgpu::PolygonMode::Fill, + conservative: false, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + mask: !0, + alpha_to_coverage_enabled: false, + count: 1, + }, + fragment: Some(wgpu::FragmentState { + module: &fragment_linkage.module, + entry_point: Some(fragment_linkage.entry_point), + targets: &[Some(wgpu::ColorTargetState { + format: wgpu::TextureFormat::Rgba16Float, + blend: Some(wgpu::BlendState { + color: wgpu::BlendComponent::REPLACE, + alpha: wgpu::BlendComponent::REPLACE, + }), + write_mask: wgpu::ColorWrites::ALL, + })], + compilation_options: Default::default(), + }), + multiview: None, + cache: None, + }); + (pipeline, bindgroup) +} pub fn diffuse_irradiance_convolution_bindgroup_layout( device: &wgpu::Device, diff --git a/crates/renderling/src/pbr/ibl/diffuse_irradiance.rs b/crates/renderling/src/pbr/ibl/diffuse_irradiance.rs new file mode 100644 index 00000000..2fd2bc4a --- /dev/null +++ b/crates/renderling/src/pbr/ibl/diffuse_irradiance.rs @@ -0,0 +1,13 @@ +//! Diffuse irradiance convolution. + +use glam::{Vec3, Vec4, Vec4Swizzles}; +#[cfg(target_arch = "spirv")] +use spirv_std::num_traits::Float; +use spirv_std::{image::Cubemap, spirv, Sampler}; + +use crate::math::IsVector; + +#[cfg(not(target_arch = "spirv"))] +mod cpu; +#[cfg(not(target_arch = "spirv"))] +pub use cpu::*; diff --git a/crates/renderling/src/ibl/diffuse_irradiance.rs b/crates/renderling/src/pbr/ibl/shader.rs similarity index 91% rename from crates/renderling/src/ibl/diffuse_irradiance.rs rename to crates/renderling/src/pbr/ibl/shader.rs index df73f386..d9a8eab3 100644 --- a/crates/renderling/src/ibl/diffuse_irradiance.rs +++ b/crates/renderling/src/pbr/ibl/shader.rs @@ -1,17 +1,11 @@ -//! Diffuse irradiance convolution. - +//! Shader side of IBL use glam::{Vec3, Vec4, Vec4Swizzles}; -#[cfg(target_arch = "spirv")] +#[cfg(gpu)] use spirv_std::num_traits::Float; use spirv_std::{image::Cubemap, spirv, Sampler}; use crate::math::IsVector; -#[cfg(not(target_arch = "spirv"))] -mod cpu; -#[cfg(not(target_arch = "spirv"))] -pub use cpu::*; - /// Diffuse irradiance convolution. #[spirv(fragment)] pub fn di_convolution_fragment( diff --git a/crates/renderling/src/skybox/cpu.rs b/crates/renderling/src/skybox/cpu.rs index 287a8d77..8d153acf 100644 --- a/crates/renderling/src/skybox/cpu.rs +++ b/crates/renderling/src/skybox/cpu.rs @@ -9,7 +9,7 @@ use glam::{Mat4, UVec2, Vec3}; use crate::{ atlas::AtlasImage, camera::shader::CameraDescriptor, convolution::VertexPrefilterEnvironmentCubemapIds, - cubemap::EquirectangularImageToCubemapBlitter, pbr::brdf::BrdfLut, texture::Texture, + cubemap::EquirectangularImageToCubemapBlitter, texture::Texture, }; /// Render pipeline used to draw a skybox. @@ -442,13 +442,12 @@ impl Skybox { ) -> Texture { let runtime = runtime.as_ref(); let device = &runtime.device; - let pipeline = - crate::ibl::diffuse_irradiance::DiffuseIrradianceConvolutionRenderPipeline::new( - device, - wgpu::TextureFormat::Rgba16Float, - ); + let pipeline = crate::pbr::ibl::DiffuseIrradianceConvolutionRenderPipeline::new( + device, + wgpu::TextureFormat::Rgba16Float, + ); - let bindgroup = crate::ibl::diffuse_irradiance::diffuse_irradiance_convolution_bindgroup( + let bindgroup = crate::pbr::ibl::diffuse_irradiance_convolution_bindgroup( device, Some("irradiance"), buffer, @@ -479,7 +478,7 @@ impl Skybox { views: [Mat4; 6], ) -> Texture { let (pipeline, bindgroup) = - crate::ibl::prefiltered_environment::create_pipeline_and_bindgroup( + crate::pbr::ibl::create_prefiltered_environment_pipeline_and_bindgroup( &runtime.as_ref().device, buffer, environment_texture, @@ -558,7 +557,9 @@ mod test { use glam::Vec3; use super::*; - use crate::{context::Context, test::BlockOnFuture, texture::CopiedTextureBuffer}; + use crate::{ + context::Context, pbr::brdf::BrdfLut, test::BlockOnFuture, texture::CopiedTextureBuffer, + }; #[test] fn hdr_skybox_scene() { From 19a61d01bc464685d7bf3ddf10fb34459c99ebb0 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 10:05:37 +1200 Subject: [PATCH 23/31] make Skybox.environment_cubemap private, provide getter --- crates/renderling/src/skybox/cpu.rs | 13 ++++++++++--- crates/renderling/src/stage/cpu.rs | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/crates/renderling/src/skybox/cpu.rs b/crates/renderling/src/skybox/cpu.rs index 8d153acf..753f7e63 100644 --- a/crates/renderling/src/skybox/cpu.rs +++ b/crates/renderling/src/skybox/cpu.rs @@ -7,9 +7,11 @@ use crabslab::Id; use glam::{Mat4, UVec2, Vec3}; use crate::{ - atlas::AtlasImage, camera::shader::CameraDescriptor, + atlas::AtlasImage, + camera::shader::CameraDescriptor, convolution::VertexPrefilterEnvironmentCubemapIds, - cubemap::EquirectangularImageToCubemapBlitter, texture::Texture, + cubemap::EquirectangularImageToCubemapBlitter, + texture::{self, Texture}, }; /// Render pipeline used to draw a skybox. @@ -160,7 +162,7 @@ pub(crate) fn create_skybox_render_pipeline( #[derive(Debug, Clone)] pub struct Skybox { // Cubemap texture of the environment cubemap - pub environment_cubemap: Texture, + environment_cubemap: Texture, // Cubemap texture of the pre-computed irradiance cubemap pub irradiance_cubemap: Texture, // Cubemap texture and mip maps of the specular highlights, @@ -276,6 +278,11 @@ impl Skybox { } } + /// Return a reference to the environment cubemap texture. + pub fn environment_cubemap_texture(&self) -> &texture::Texture { + &self.environment_cubemap + } + /// Convert an HDR [`AtlasImage`] into a texture. pub fn hdr_texture_from_atlas_image( runtime: impl AsRef, diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index b3406cba..5cbf651d 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -1367,7 +1367,7 @@ impl Stage { let bg = Arc::new(crate::skybox::create_skybox_bindgroup( self.device(), geometry_slab_buffer, - &self.skybox.read().unwrap().environment_cubemap, + self.skybox.read().unwrap().environment_cubemap_texture(), )); *bindgroup = Some(bg.clone()); bg From 74d225f68c37f367c2f02659c0dba0f40d2db737 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 14:16:47 +1200 Subject: [PATCH 24/31] split Skybox and Ibl --- crates/example/src/lib.rs | 4 +- crates/examples/src/lib.rs | 4 +- crates/examples/src/skybox.rs | 28 +- ...-shader-brdf_lut_convolution_fragment.spv} | Bin 5172 -> 5180 bytes ...on-shader-brdf_lut_convolution_vertex.spv} | Bin 1420 -> 1428 bytes ...ution-shader-generate_mipmap_fragment.spv} | Bin 608 -> 616 bytes ...olution-shader-generate_mipmap_vertex.spv} | Bin 1204 -> 1212 bytes ...refilter_environment_cubemap_fragment.spv} | Bin 6524 -> 6532 bytes ...-prefilter_environment_cubemap_vertex.spv} | Bin 13488 -> 13496 bytes ...use_irradiance-di_convolution_fragment.spv | Bin 4096 -> 0 bytes .../shaders/light-light_tiling_bin_lights.spv | Bin 26648 -> 0 bytes .../light-light_tiling_clear_tiles.spv | Bin 4568 -> 0 bytes ..._tiling_compute_tile_min_and_max_depth.spv | Bin 3968 -> 0 bytes ...te_tile_min_and_max_depth_multisampled.spv | Bin 3980 -> 0 bytes .../light-light_tiling_depth_pre_pass.spv | Bin 35796 -> 0 bytes .../shaders/light-shadow_mapping_fragment.spv | Bin 504 -> 0 bytes .../shaders/light-shadow_mapping_vertex.spv | Bin 32520 -> 0 bytes crates/renderling/shaders/manifest.json | 46 +- ...pbr-ibl-shader-di_convolution_fragment.spv | Bin 0 -> 4088 bytes .../primitive-shader-primitive_fragment.spv | Bin 108064 -> 108064 bytes .../skybox-skybox_cubemap_fragment.spv | Bin 1116 -> 0 bytes .../shaders/skybox-skybox_cubemap_vertex.spv | Bin 12648 -> 0 bytes ...skybox-skybox_equirectangular_fragment.spv | Bin 1400 -> 0 bytes .../shaders/skybox-skybox_vertex.spv | Bin 10940 -> 0 bytes crates/renderling/src/bloom/cpu.rs | 2 +- crates/renderling/src/convolution.rs | 529 +++++++------- crates/renderling/src/internal/cpu.rs | 2 +- .../linkage/brdf_lut_convolution_fragment.rs | 8 +- .../linkage/brdf_lut_convolution_vertex.rs | 8 +- .../src/linkage/di_convolution_fragment.rs | 8 +- .../src/linkage/generate_mipmap_fragment.rs | 8 +- .../src/linkage/generate_mipmap_vertex.rs | 8 +- .../prefilter_environment_cubemap_fragment.rs | 12 +- .../prefilter_environment_cubemap_vertex.rs | 12 +- crates/renderling/src/pbr.rs | 643 +----------------- crates/renderling/src/pbr/ibl/cpu.rs | 318 +++++++++ crates/renderling/src/pbr/shader.rs | 643 ++++++++++++++++++ crates/renderling/src/primitive/shader.rs | 2 +- crates/renderling/src/skybox/cpu.rs | 276 +------- crates/renderling/src/stage/cpu.rs | 213 ++++-- crates/renderling/src/texture.rs | 90 ++- manual/src/assets/gltf-example.png | Bin 12924 -> 0 bytes manual/src/assets/skybox.png | Bin 78137 -> 99449 bytes 43 files changed, 1555 insertions(+), 1309 deletions(-) rename crates/renderling/shaders/{convolution-brdf_lut_convolution_fragment.spv => convolution-shader-brdf_lut_convolution_fragment.spv} (78%) rename crates/renderling/shaders/{convolution-brdf_lut_convolution_vertex.spv => convolution-shader-brdf_lut_convolution_vertex.spv} (87%) rename crates/renderling/shaders/{convolution-generate_mipmap_fragment.spv => convolution-shader-generate_mipmap_fragment.spv} (61%) rename crates/renderling/shaders/{convolution-generate_mipmap_vertex.spv => convolution-shader-generate_mipmap_vertex.spv} (80%) rename crates/renderling/shaders/{convolution-prefilter_environment_cubemap_fragment.spv => convolution-shader-prefilter_environment_cubemap_fragment.spv} (54%) rename crates/renderling/shaders/{convolution-prefilter_environment_cubemap_vertex.spv => convolution-shader-prefilter_environment_cubemap_vertex.spv} (82%) delete mode 100644 crates/renderling/shaders/ibl-diffuse_irradiance-di_convolution_fragment.spv delete mode 100644 crates/renderling/shaders/light-light_tiling_bin_lights.spv delete mode 100644 crates/renderling/shaders/light-light_tiling_clear_tiles.spv delete mode 100644 crates/renderling/shaders/light-light_tiling_compute_tile_min_and_max_depth.spv delete mode 100644 crates/renderling/shaders/light-light_tiling_compute_tile_min_and_max_depth_multisampled.spv delete mode 100644 crates/renderling/shaders/light-light_tiling_depth_pre_pass.spv delete mode 100644 crates/renderling/shaders/light-shadow_mapping_fragment.spv delete mode 100644 crates/renderling/shaders/light-shadow_mapping_vertex.spv create mode 100644 crates/renderling/shaders/pbr-ibl-shader-di_convolution_fragment.spv delete mode 100644 crates/renderling/shaders/skybox-skybox_cubemap_fragment.spv delete mode 100644 crates/renderling/shaders/skybox-skybox_cubemap_vertex.spv delete mode 100644 crates/renderling/shaders/skybox-skybox_equirectangular_fragment.spv delete mode 100644 crates/renderling/shaders/skybox-skybox_vertex.spv create mode 100644 crates/renderling/src/pbr/shader.rs delete mode 100644 manual/src/assets/gltf-example.png diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index a097f0b7..d7497135 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -218,7 +218,9 @@ impl App { let img = AtlasImage::from_hdr_bytes(&bytes).unwrap(); let skybox = Skybox::new(self.stage.runtime(), img); self.skybox_image_bytes = Some(bytes); - self.stage.set_skybox(skybox); + self.stage.use_skybox(&skybox); + let ibl = self.stage.new_ibl(&skybox); + self.stage.use_ibl(&ibl); } pub fn load_default_model(&mut self) { diff --git a/crates/examples/src/lib.rs b/crates/examples/src/lib.rs index 3f364334..ca671edd 100644 --- a/crates/examples/src/lib.rs +++ b/crates/examples/src/lib.rs @@ -29,7 +29,9 @@ pub fn workspace_dir() -> std::path::PathBuf { } pub fn test_output_dir() -> std::path::PathBuf { - renderling_build::test_output_dir().canonicalize().unwrap() + let dir = renderling_build::test_output_dir(); + std::fs::create_dir_all(&dir).unwrap(); + dir.canonicalize().unwrap() } pub fn cwd_to_cargo_workspace() -> std::path::PathBuf { diff --git a/crates/examples/src/skybox.rs b/crates/examples/src/skybox.rs index f1c20586..d2f85a06 100644 --- a/crates/examples/src/skybox.rs +++ b/crates/examples/src/skybox.rs @@ -1,6 +1,6 @@ //! Skybox manual page. -use crate::{test_output_dir, workspace_dir}; +use crate::{cwd_to_manual_assets_dir, test_output_dir, workspace_dir}; #[tokio::test] async fn manual_skybox() { @@ -16,7 +16,8 @@ async fn manual_skybox() { let ctx = Context::headless(256, 256).await; let stage: Stage = ctx .new_stage() - .with_background_color(Vec4::new(0.25, 0.25, 0.25, 1.0)); + .with_background_color(Vec4::new(0.25, 0.25, 0.25, 1.0)) + .with_lighting(false); let _camera: Camera = { let aspect = 1.0; @@ -50,9 +51,11 @@ async fn manual_skybox() { let skybox = stage .new_skybox_from_path(workspace_dir().join("img/hdr/helipad.hdr")) .unwrap(); - stage.set_skybox(skybox); + stage.use_skybox(&skybox); // ANCHOR_END: skybox + cwd_to_manual_assets_dir(); + // ANCHOR: render_skybox let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); @@ -60,23 +63,4 @@ async fn manual_skybox() { image.save("skybox.png").unwrap(); frame.present(); // ANCHOR_END: render_skybox - // - - let frame = ctx.get_next_frame().unwrap(); - renderling::capture_gpu_frame(&ctx, test_output_dir().join("skybox.gputrace"), || { - stage.render(&frame.view()); - }); - let image = frame.read_image().await.unwrap(); - image.save("skybox.png").unwrap(); - frame.present(); - let frame = ctx.get_next_frame().unwrap(); - stage.render(&frame.view()); - let image = frame.read_image().await.unwrap(); - image.save("skybox.png").unwrap(); - frame.present(); - let frame = ctx.get_next_frame().unwrap(); - stage.render(&frame.view()); - let image = frame.read_image().await.unwrap(); - image.save("skybox.png").unwrap(); - frame.present(); } diff --git a/crates/renderling/shaders/convolution-brdf_lut_convolution_fragment.spv b/crates/renderling/shaders/convolution-shader-brdf_lut_convolution_fragment.spv similarity index 78% rename from crates/renderling/shaders/convolution-brdf_lut_convolution_fragment.spv rename to crates/renderling/shaders/convolution-shader-brdf_lut_convolution_fragment.spv index cc9214b5a65854c0db9ce55f8e07ece29fd09833..d4b69afed2659799a0d41807208825b3b0260329 100644 GIT binary patch delta 40 ucmdm@u}5Qqm#h#23j+fK6A&lo=auE>l$K=X=UG`5XC$Vi7Hy2bDhvSI_zZIZ delta 32 mcmdm^u|;Eom#6>(3j+fK6A&lo=auE>l$K=X=WR^CDhvRI<_U%X diff --git a/crates/renderling/shaders/convolution-brdf_lut_convolution_vertex.spv b/crates/renderling/shaders/convolution-shader-brdf_lut_convolution_vertex.spv similarity index 87% rename from crates/renderling/shaders/convolution-brdf_lut_convolution_vertex.spv rename to crates/renderling/shaders/convolution-shader-brdf_lut_convolution_vertex.spv index 3085d581d74cb671ed1e42b7a44fed63bc4d739b..8cb385782fa16178c63450bceadaf7491f6a8c89 100644 GIT binary patch delta 40 rcmeC-p29uBNLH8u1Q>xhIX|x~Kc}=LGe6JDsyHJtCADayyDKXI!T1Xo delta 32 jcmbQj-NQY>NK}vk1Q>xhIX|x~Kc}=LGe2*mzbh*Maux_G diff --git a/crates/renderling/shaders/convolution-generate_mipmap_fragment.spv b/crates/renderling/shaders/convolution-shader-generate_mipmap_fragment.spv similarity index 61% rename from crates/renderling/shaders/convolution-generate_mipmap_fragment.spv rename to crates/renderling/shaders/convolution-shader-generate_mipmap_fragment.spv index e1f12d06d03210cf8ed1244398eb8c2ce42f6a47..46c2734ba1ea55361db9244b4b0216042ef6df09 100644 GIT binary patch delta 40 ucmaFB@`7c8k*qKS3j+fKBM>L&=auE>l$K=X=UG`5XC$Vi7HxEwWC8%$oePEl delta 32 mcmaFC@_=Q6k*FX83j+fKBM>L&=auE>l$K=X=WXt delta 32 mcmZoM{$n)3OH`DBg@J*A35b*P^UCsbN=q{H^ERf-N&*0h;0XQz diff --git a/crates/renderling/shaders/convolution-prefilter_environment_cubemap_vertex.spv b/crates/renderling/shaders/convolution-shader-prefilter_environment_cubemap_vertex.spv similarity index 82% rename from crates/renderling/shaders/convolution-prefilter_environment_cubemap_vertex.spv rename to crates/renderling/shaders/convolution-shader-prefilter_environment_cubemap_vertex.spv index 3bef66f8e47437107dacec877fa788185f5dbf72..9db41d93a8a8e2f4e19f1609a52e41d91320f0b0 100644 GIT binary patch delta 40 rcmdmxxg&Fek*ov*2rvS1a(-S}eokpgW`3TPRdGgQN@~$Y_e>K2>GTY9 delta 32 jcmdmyxgm3ck*F902rvS1a(-S}eokpgW`5pA|4b7Ak;(~% diff --git a/crates/renderling/shaders/ibl-diffuse_irradiance-di_convolution_fragment.spv b/crates/renderling/shaders/ibl-diffuse_irradiance-di_convolution_fragment.spv deleted file mode 100644 index f3df3c568bced8d63e07909f0effecb9edffb91f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmZ9OX^2*37>19dDN#8|rlqChT4;{0_E351JJok9$Fptmu-p~Ck=RNN^pY7}Vbt;Z&R}@8k zu~f&^rKl@}`h8uC;<%z?Z9RI-HDelQ&2DNOdj8q!Iv4GAwSVi2u0;oM9o8~=`mkY5 zEmNk%=KDCr!Pvxpj7Gn12k`5j&Bp z*6M_frm|cw%*(a9>e}2sm^sE>_r<(iJE?K+E9=C&5#=_E2CO^Ulku*t(ZIjm@aD^( zM2GJ9J}{@?#e>nPKNa)Jx<_rbaAa3cV-2+W;y!{$#@uIfAsO<0k zJA?B%xBXmO!*ze`EOtpe0CSe3c5E?_b#m&!x!RS$zGswJt?M)K#;uuq8U)^3f7Pg- z^c@UV>x^oBChDVY1n;fiJ<@ms*!}c!Z7=8dihcwW%Ka=2n?$^BmP#-iH~HrKhMI{=o~7L~aN!R8xF?jf+bby#x$ z0?TX3{Tpn)vEzA0&UYBIr_bE@cKUcm{=tm-><+L)Co1ClllwIGuM0TuUwjC!#iE)>L~poIUi>t^lhwex2lF0`t;Sbl_f}$S%Ge*=-`W!6 zYCZ46+f%=z{7&5uw)PV0`u;os_HuuWJ&3Kt%o98N`f{z$>>I$&uVy2*2{Y#G4`I%3 zY%^AkZDH;F#vU$X&i+V=akZY0;+;XC*&hR2yAgBtt#~hIH}*L81ZJK%XJs3h+bvGO z%n$!$$#=%PCpm*pfz2@UfoBsjIkqH6+MON*`EuZhw&EOv7Su5YATfpA4v1*?Ad0*#&2cWUGdTaWBu-z{m1M%~Twa1U+ zn=u%_fVG^u@o*>O7qXVOZqC%ZC68;{xA(yEo`dM#2b<4do9+X!d{y^hsjHsRkKp9h z<=K1;w$HW-_X*gVRqj*P=F4T4z2FU)SDx!UdGe`FYSl(XI?E|ZG=IFiz z%iBL^^eeD^tYJLbufba|pK-WvzZ>_BLnRg}FeY1}9s?EHs z!PYe9yw%tm*6vp|W{*{H_SEOM&EMX&C9lsr^&NN+=I>ITL}#`4?gd-W@3A8Q!*9E{*??1(pZm`)dB{{eg1!w3KX diff --git a/crates/renderling/shaders/light-light_tiling_bin_lights.spv b/crates/renderling/shaders/light-light_tiling_bin_lights.spv deleted file mode 100644 index 64bc018798cc1bd29081e8ff6e2bdff0698e16c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26648 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 diff --git a/crates/renderling/shaders/light-light_tiling_compute_tile_min_and_max_depth.spv b/crates/renderling/shaders/light-light_tiling_compute_tile_min_and_max_depth.spv deleted file mode 100644 index 80fa344549600e59a1c4345fcdc81cfba2715267..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3968 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 K;?<+C$y<0a@%uKrW+&;X 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 Iw>s_r0JHLWTmS$7 diff --git a/crates/renderling/shaders/manifest.json b/crates/renderling/shaders/manifest.json index ac13dd96..b2297abe 100644 --- a/crates/renderling/shaders/manifest.json +++ b/crates/renderling/shaders/manifest.json @@ -30,34 +30,34 @@ "wgsl_entry_point": "bloomshaderbloom_vertex" }, { - "source_path": "shaders/convolution-brdf_lut_convolution_fragment.spv", - "entry_point": "convolution::brdf_lut_convolution_fragment", - "wgsl_entry_point": "convolutionbrdf_lut_convolution_fragment" + "source_path": "shaders/convolution-shader-brdf_lut_convolution_fragment.spv", + "entry_point": "convolution::shader::brdf_lut_convolution_fragment", + "wgsl_entry_point": "convolutionshaderbrdf_lut_convolution_fragment" }, { - "source_path": "shaders/convolution-brdf_lut_convolution_vertex.spv", - "entry_point": "convolution::brdf_lut_convolution_vertex", - "wgsl_entry_point": "convolutionbrdf_lut_convolution_vertex" + "source_path": "shaders/convolution-shader-brdf_lut_convolution_vertex.spv", + "entry_point": "convolution::shader::brdf_lut_convolution_vertex", + "wgsl_entry_point": "convolutionshaderbrdf_lut_convolution_vertex" }, { - "source_path": "shaders/convolution-generate_mipmap_fragment.spv", - "entry_point": "convolution::generate_mipmap_fragment", - "wgsl_entry_point": "convolutiongenerate_mipmap_fragment" + "source_path": "shaders/convolution-shader-generate_mipmap_fragment.spv", + "entry_point": "convolution::shader::generate_mipmap_fragment", + "wgsl_entry_point": "convolutionshadergenerate_mipmap_fragment" }, { - "source_path": "shaders/convolution-generate_mipmap_vertex.spv", - "entry_point": "convolution::generate_mipmap_vertex", - "wgsl_entry_point": "convolutiongenerate_mipmap_vertex" + "source_path": "shaders/convolution-shader-generate_mipmap_vertex.spv", + "entry_point": "convolution::shader::generate_mipmap_vertex", + "wgsl_entry_point": "convolutionshadergenerate_mipmap_vertex" }, { - "source_path": "shaders/convolution-prefilter_environment_cubemap_fragment.spv", - "entry_point": "convolution::prefilter_environment_cubemap_fragment", - "wgsl_entry_point": "convolutionprefilter_environment_cubemap_fragment" + "source_path": "shaders/convolution-shader-prefilter_environment_cubemap_fragment.spv", + "entry_point": "convolution::shader::prefilter_environment_cubemap_fragment", + "wgsl_entry_point": "convolutionshaderprefilter_environment_cubemap_fragment" }, { - "source_path": "shaders/convolution-prefilter_environment_cubemap_vertex.spv", - "entry_point": "convolution::prefilter_environment_cubemap_vertex", - "wgsl_entry_point": "convolutionprefilter_environment_cubemap_vertex" + "source_path": "shaders/convolution-shader-prefilter_environment_cubemap_vertex.spv", + "entry_point": "convolution::shader::prefilter_environment_cubemap_vertex", + "wgsl_entry_point": "convolutionshaderprefilter_environment_cubemap_vertex" }, { "source_path": "shaders/cubemap-shader-cubemap_sampling_test_fragment.spv", @@ -99,11 +99,6 @@ "entry_point": "debug::shader::debug_overlay_vertex", "wgsl_entry_point": "debugshaderdebug_overlay_vertex" }, - { - "source_path": "shaders/ibl-diffuse_irradiance-di_convolution_fragment.spv", - "entry_point": "ibl::diffuse_irradiance::di_convolution_fragment", - "wgsl_entry_point": "ibldiffuse_irradiancedi_convolution_fragment" - }, { "source_path": "shaders/light-shader-light_tiling_bin_lights.spv", "entry_point": "light::shader::light_tiling_bin_lights", @@ -139,6 +134,11 @@ "entry_point": "light::shader::shadow_mapping_vertex", "wgsl_entry_point": "lightshadershadow_mapping_vertex" }, + { + "source_path": "shaders/pbr-ibl-shader-di_convolution_fragment.spv", + "entry_point": "pbr::ibl::shader::di_convolution_fragment", + "wgsl_entry_point": "pbriblshaderdi_convolution_fragment" + }, { "source_path": "shaders/primitive-shader-primitive_fragment.spv", "entry_point": "primitive::shader::primitive_fragment", diff --git a/crates/renderling/shaders/pbr-ibl-shader-di_convolution_fragment.spv b/crates/renderling/shaders/pbr-ibl-shader-di_convolution_fragment.spv new file mode 100644 index 0000000000000000000000000000000000000000..3f26658da38eb315d2cfa14668f7b1e715a3bf4c GIT binary patch literal 4088 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 z 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 G%Krljl|rEa diff --git a/crates/renderling/shaders/skybox-skybox_cubemap_fragment.spv b/crates/renderling/shaders/skybox-skybox_cubemap_fragment.spv deleted file mode 100644 index 792aea28a7bd74e2412c40102138163c6d63df14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1116 zcmYk5%T7~K6oxnD(h!J1K<)|!;zUCn03kKVkO>2cQA`jBg#rdkiLHrDpbXHCd>UWK zhcH|c62I@Tx3ZJ}thN4i-Rqpwnw!pt_LdMrPiXS=^o3lIQT`qXp(}J`_R8wp)!ABo zZ+33}rE!l!t0H^$kl%)$1GS^mQuSN0crUkizn03Cos;eTFFOa7@^L+jH?|#gfL<8$ z@?eE3`U*fU*;D8qZS$UH*1hc%#yhiq?T7L9Nb!Ssxl)(}L&QEtYTI*?=OEI2`Fh|gVb-$F*-a$>T?c#?oz+Dxz6Cxb{FnWZh=VepZdCwYpi$3 zC1S0=4y>o`-9G^Dxd!XpC18x_GID$9@*>5R(T#Ji6nB6wFD_#4A-ehcQtl^obDcBg z9-+&Nl=~Uoe0|;A()lVN?MnYI`uHx7qtAD7#Wos9&n>spR|O})eW>3c8_||;#(B@s z{Z8!j6V9ET1LxKEFt36Ahd;uY3s3;oHr|@jANMhG?jXf&M$Ub{VIJ#k0rQR5@10&Vh2M(4JGQt8{sI9qP3Hgr diff --git a/crates/renderling/shaders/skybox-skybox_cubemap_vertex.spv b/crates/renderling/shaders/skybox-skybox_cubemap_vertex.spv deleted file mode 100644 index ea18476282000d7139212017056e06bbd69fed2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12648 zcmaKx2eehy6-7TFO}d~c<@4zRUj+peP*I9#jEW+5ML;xwhz$ix#NK<4u}6))#TZ-c zJ;oR-rimt&^k#3F^KsYr42C0ja6N0Sz0cbFo_Egs?>$>I@87zvWwW}vx=wXNR$<`k zQrEmr#c_GJy1I^aEo!>|?NryfhK(OGf61(ci^q;#G0vF1Xx5wsGY_0`*qnn8owJyD zb8hEo+mgE#_Y_$F3ad{cV*sPMTaqRAGRMpOfsD?zviZ(ivxZlx;l5xmbB*<@u@!!6 zRXBduP_utE^PSg%u^so&iVtG^rsgVjgA1-l54cz9s}^5-O`gwYUPGZ-Pi=Um^E)b4b6xaXib>}B8mgUx=9;-au9=tI zczunn;MOuejC*zBYcn=*do{p^Fk)5Hd-DqDZBBi)C*(`^$VaJw`CL=2jmEx4!=Nkog;cz2w#( zS!3VuQ8m7Fd^dU+4c2!x|>(8n55R0Qf6C)^W`yFzThI&%_F^&{wR_B(yf%u8(KIn40;M8Lg|H=hy-~fZKe} ziur2hPhm7)y`EL~oY-@D*H?R6PuJb~^>pB#HQ!s!{qN|VwciTN^>8EJ>fhm3bFI9i zZ(V4{qkk8i{8Hbh$S-}it@1M`KHF9KE9+AWz4YI{@L8b`uC37y=stt}+MC#3^!~H*#pzTdlY;p zuzM`=oxz@?@Lj;|3%)D3Gj}6Z8X0%z_FR>>?<3Y|;BHpCSM2*e!SUS-?B9pHE_;JZ zkND3*_ndxPY<8uW@yy$&n3H&7bBdV0#*Mju_vN;x-g=np`CNyw6}M|8pUBv<;6uR8 zxqaToy0*3R@de4Q&$r!;%=WeUk{sWshS%n`tDV=c(DsJ^zuR@|NzT{gnr|)ht?haA zMf6#`_vSXw(L1$UkYnvh+<9GEqWN6mt>Esb@Ye9Q1#bgiwcu^x?FzmsyhFj;!8;bb zJ-k!FJHWdXyd!+If_H*VdDB6>>hm+uAk#3%=ho@KIEGgJ_pV=XFs>B#rK2L zUhTRK&A+|NnV{~PSm%8WxIQD(*gM>Bb6d;tQ$};-#*VAJ-v!6#uFCs8GVkzPBV+*fC;qfvauSH;E@j48w7O%s> zdbvl_*J60QjK^yU*jT)d0IN-9t^M0{B-rP+U+Wl8ouk0kaqp+j(eTtUo;u$L8%v#I zz-sYY3f9Z_&UhUQkC*Xy9S1fRuj9dL@j3ylmwyl9bs{`o#^ZGo*jT(y2CK#E6tG^t zhsWzwc)X0q>ol;jc%2Sb%UYfR_POoXI>uAyOt5t(6+NE?PaWf_b2ivm>i9iHEneq> z_44mbdOi;xFXQn#A8agM7l75`bs<hN7Ox+` z<7GTvmw}DN>xW>qtmWlkpWA+|V?1@P09(iR;MBPio;t=;=PIzV)VUh07O!i-diggv zUf06oWjtO#0vn6hbzrr4T@TjFzu)n?0Uj^o@%k~?SiEiotHtXkuwMS{kJrucco~n^ zEns8ux)rRJwY&}NbK9?Vj2rWB`0Zfd1Khi=xw+}#4zNA=w=F%~2~Q8k)5Be0W9i{; zuv)x+0@lmVF7dht9xvnZ`YG60yzT|7#p`Eaz5Lu0ulwNfG9It{!N%hC09Y+v4}$gb zGgG`Cg2&5vynYTg7O#iFYFXz;z&^MATE}?mJPNjspT$z=F?i}2Po2lX#!}}Auv)yH z1ncGJxOhDUkC*XyJq1qfTEkdsGzVM5?`fOzIexY|d$rXOnY|s@`Cif5SDJ0zQGE~TfM%{Szgu)<^zyrfu}<8bx%GG4foHV0-eA8+ z`2Eq#XK=20&dD?P0PF8}hs^B>S5JRa=|#_8Ri62!pT1cW*TMPLaK1eyRu9(0nEe^c zv-bfT_lnj~X|9K_rN2YdQ2JCN*=J*}kx&F@XYw8@&oSu%J3G+Rx zo!ys|BeUyJDZ-Hac|D;d7n^WO4Q~~ zgj?G&dwCMr`Cic`R~luT&ifW<<{ER4Phs@(*^F(;y%o3qjybbCfmc57&Na_DdFE+g z{mb*dBV0ZG<-AX?^2~Ql;^&w(*$nJ_YdGJY65AQ9hcWvzmS^7uY}_l_u9fC`xc5Bo zyP=uuTI^osd*0ResQ8|Y&e@C6=XK0^p8?j_eV;Yh8}4gwEN65kn3uM;hQ@OiW`T|6 zEX)S0#cLn1`Q>?^1CN*Sc*ar}2CX!0vO`#62%J*Voteb^Tn=lDp0&H!tV&0I=uN9M7k7J)gb?&hd=s>F6Fd z-!tWzQFrv21~F$L*xs@p2f{s{4J<%jr-RV49>%jC2ZN1eJq`h@#p_V8UjC*UuSIC_ zG9ItPz{cWrI9M%Si@|#Ndu+UxpvB90yp8}Hi`S80wY*M8f$h~A#?<|d`e?B0F_zn$ z)c!u$+Wz*N+Q*=!w(-aZT@o4cf9g2?bRB_QsZ>6HT)erHO@dw4dbbCCfHbNoCQ{k*V$mb z{0%%_=b**Qc)ZR98;jR@V6}Li57x`y&*OCgTD*+M>q4-xcwGcm%d=k$wpVKyn_B%p zpi98FQ^U{h&A{#t*U5a(*<5tblcVpy{(p_ji8;?RW;64N`CjXHfVcQNXWT2=@=7DE z_TDfP;Qt%VXVELjpM$mqn(xO~Rr5X9#^hIX+lQllEvvY(3DtYhHDJB+#VO06^8T(3Mw7r46lnY$X; zyz)7^!qv;XZdG3S9IK>64>S`V=6WvysE z!LE(Id3}3IM>sRHK>(U=hz04a> z)aiZ%r7+UT2g847k?_}BDo!{jSzjc{|l zvM%eu)y>bktP3`;T$lCW>Sf;WDz99Z5oqdV-uhJ@LsQ)iAnNAj*+zn08+(d23hdfg zKiX)pYh$fw8-iUMeX}lOz`jS6XJ#B+-79Ob3EZ=9EZTUm=e*Q5hkK?=Z6e(BtCsbf z47NtOepBF{OJk|A71%RaYFooSZ>6>k+_R;Y=iL@;-}*+|4s750Mw<$@Z+)X}54LZ8 z)AKa2J(sWLbhu~6SbE+W?D;6QUE!XEQrjKwzE?}#J;3&@Z?rwZ_N{NUy}a?P9SOEZxhIc? zyC;pM#xY>`WT_nscTbku@o@K~TAud=uzl+r?L@GB>l^JPuzl+r?PRch>zkfW1>1AE zCr^jFCyk}&Gr{i3Qac;&o-DO<;qFPb)IASu-}**7A8gn z_RPPg{w{^MCyk}&%fRl*Qo9`Po-DO1;qFPb)V&I9-}*+o8f@SCM!N=V-}*+o7Hr@8 zW=~!Rc2DxJ={atIsC%X78{zIrW6^E~yC+NSR=9hz)NY5nC)Ki6cY>`^?#a91?nz^* zaSzx%S!(yf-IJwuAKX2umgl`6Y~T7udjM?T`bK*YY~T7udkAdb`ljcH!S-D4$w%St zNn`2xaj<)`)SiU9Crj;VxO-A9b)Ny-x4zMy1>3j2(Vhd_x4zMy2iv#4>G=h)J@c=r zzZW6yNn`2xC9r$4)Lw?WCrj;BxO-A9bzcM9x4zL{2iv#4(cS>tx4zMqf$dx0^n4u) z?B{*2XxCR-`S<*WN;5UjaT8=DUV22k1w3jc?KZU0D`|J2ZMc$lH`+Wj>&NdN@cfmu zd(rk^NxKhiL8aw+??)UHHMpMc nk!Y{O^>mNqx8^tCdg|dEbNr6jialVg{Eq2&%`bU}*@*jp*6~aY diff --git a/crates/renderling/shaders/skybox-skybox_equirectangular_fragment.spv b/crates/renderling/shaders/skybox-skybox_equirectangular_fragment.spv deleted file mode 100644 index 3617b009b633ee441210129c9420b48c3e27f028..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1400 zcmYk5%Wuq46vuB{orw^wXjC7V=}03=Ss+p|U3Sw&MZ!*Jw9_G|=p#XhX{vN(>9If& zkA=s^KV)q!R3h>D{N`Snn|$Y-^F5Dy&iUQxXfNeMXIluND}3eGvoo{@8Rhq$5VnO} zW=~9>n;czSnjJlU;+SzeLWd&z?IL;$dOKLWdi&CiTVrEQIbFNCd}X0Fvs9h0FJG%J zOwTP;>(^`ZOIe;dogfFgVa(5i399KU0=Z-lp?kEwUBA61yVY;qeZZsNJCePd>|X2w z=*71ulg+!d`=V_R1?+yL_sQ>~qXA?QW)P`9LX7qH0#CA=_cg|Q$l2e*7Yqtvyf19c zW-!+|oHZS7kN2m!irD=`l_Gz@0FL%);j?Vl=9{v0^}B0hwB41v_O29v6n*f=Q28X0?kmmd{(fU!M4pK~RnV<> zmS6XB2ULJ(Epm6!c*7%Zrtm+dwy8U&>uUuK@c>xvS{%O*DIXfZYK4 zwlk&utpV@!`|AJ3J?amEK6m+xZ9GGI{xGM$M_?T|zxpQ97;X9W*zXf`-;uQ*!}%Sa zf(p>rnrHq`{z1k(2Yyd$8*j}t?+bMO&YQTGkwY+BKAY_oy0iK2%`qm$Z=hR4f7-?C zXm=wwK-%S7bZhwz688?>c;8a`Ht*4mEwpeS(2bRwVt)UtAAzy@d^aWJ4Dju17m=Sp z2RKj8F!FQcjJp8mOkW~zy);)X@`(T3T;$qXxO(K=;S~F_-eq9E@%sI4WxB{A_5EdA Gr@%iD&v4uT diff --git a/crates/renderling/shaders/skybox-skybox_vertex.spv b/crates/renderling/shaders/skybox-skybox_vertex.spv deleted file mode 100644 index 049c982e9a36af02badeb46a75d17cee52a08cf0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10940 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 f32 { - bits = (bits << 16u32) | (bits >> 16u32); - bits = ((bits & 0x55555555u32) << 1u32) | ((bits & 0xAAAAAAAAu32) >> 1u32); - bits = ((bits & 0x33333333u32) << 2u32) | ((bits & 0xCCCCCCCCu32) >> 2u32); - bits = ((bits & 0x0F0F0F0Fu32) << 4u32) | ((bits & 0xF0F0F0F0u32) >> 4u32); - bits = ((bits & 0x00FF00FFu32) << 8u32) | ((bits & 0xFF00FF00u32) >> 8u32); - (bits as f32) * 2.328_306_4e-10 // / 0x100000000 -} -fn hammersley(i: u32, n: u32) -> Vec2 { - Vec2::new(i as f32 / n as f32, radical_inverse_vdc(i)) -} +pub mod shader { + //! Shader side of convolution. + use crabslab::{Id, Slab, SlabItem}; + use glam::{Vec2, Vec3, Vec4, Vec4Swizzles}; + use spirv_std::{ + image::{Cubemap, Image2d}, + num_traits::Zero, + spirv, Sampler, + }; -fn importance_sample_ggx(xi: Vec2, n: Vec3, roughness: f32) -> Vec3 { - let a = roughness * roughness; + #[allow(unused_imports)] + use spirv_std::num_traits::Float; - let phi = 2.0 * core::f32::consts::PI * xi.x; - let cos_theta = f32::sqrt((1.0 - xi.y) / (1.0 + (a * a - 1.0) * xi.y)); - let sin_theta = f32::sqrt(1.0 - cos_theta * cos_theta); + use crate::{camera::shader::CameraDescriptor, math::IsVector}; - // Convert spherical to cartesian coordinates - let h = Vec3::new(phi.cos() * sin_theta, phi.sin() * sin_theta, cos_theta); + // Allow manual bit rotation because this code is `no_std`. + #[allow(clippy::manual_rotate)] + fn radical_inverse_vdc(mut bits: u32) -> f32 { + bits = (bits << 16u32) | (bits >> 16u32); + bits = ((bits & 0x55555555u32) << 1u32) | ((bits & 0xAAAAAAAAu32) >> 1u32); + bits = ((bits & 0x33333333u32) << 2u32) | ((bits & 0xCCCCCCCCu32) >> 2u32); + bits = ((bits & 0x0F0F0F0Fu32) << 4u32) | ((bits & 0xF0F0F0F0u32) >> 4u32); + bits = ((bits & 0x00FF00FFu32) << 8u32) | ((bits & 0xFF00FF00u32) >> 8u32); + (bits as f32) * 2.328_306_4e-10 // / 0x100000000 + } - // Convert tangent-space vector to world-space vector - let up = if n.z.abs() < 0.999 { - Vec3::new(0.0, 0.0, 1.0) - } else { - Vec3::new(1.0, 0.0, 0.0) - }; - let tangent = up.cross(n).alt_norm_or_zero(); - let bitangent = n.cross(tangent); + fn hammersley(i: u32, n: u32) -> Vec2 { + Vec2::new(i as f32 / n as f32, radical_inverse_vdc(i)) + } - let result = tangent * h.x + bitangent * h.y + n * h.z; - result.alt_norm_or_zero() -} + fn importance_sample_ggx(xi: Vec2, n: Vec3, roughness: f32) -> Vec3 { + let a = roughness * roughness; + + let phi = 2.0 * core::f32::consts::PI * xi.x; + let cos_theta = f32::sqrt((1.0 - xi.y) / (1.0 + (a * a - 1.0) * xi.y)); + let sin_theta = f32::sqrt(1.0 - cos_theta * cos_theta); -fn geometry_schlick_ggx(n_dot_v: f32, roughness: f32) -> f32 { - let r = roughness; - let k = (r * r) / 2.0; + // Convert spherical to cartesian coordinates + let h = Vec3::new(phi.cos() * sin_theta, phi.sin() * sin_theta, cos_theta); - let nom = n_dot_v; - let denom = n_dot_v * (1.0 - k) + k; + // Convert tangent-space vector to world-space vector + let up = if n.z.abs() < 0.999 { + Vec3::new(0.0, 0.0, 1.0) + } else { + Vec3::new(1.0, 0.0, 0.0) + }; + let tangent = up.cross(n).alt_norm_or_zero(); + let bitangent = n.cross(tangent); - if denom.is_zero() { - 0.0 - } else { - nom / denom + let result = tangent * h.x + bitangent * h.y + n * h.z; + result.alt_norm_or_zero() } -} -fn geometry_smith(normal: Vec3, view_dir: Vec3, light_dir: Vec3, roughness: f32) -> f32 { - let n_dot_v = normal.dot(view_dir).max(0.0); - let n_dot_l = normal.dot(light_dir).max(0.0); - let ggx1 = geometry_schlick_ggx(n_dot_v, roughness); - let ggx2 = geometry_schlick_ggx(n_dot_l, roughness); + fn geometry_schlick_ggx(n_dot_v: f32, roughness: f32) -> f32 { + let r = roughness; + let k = (r * r) / 2.0; - ggx1 * ggx2 -} + let nom = n_dot_v; + let denom = n_dot_v * (1.0 - k) + k; -const SAMPLE_COUNT: u32 = 1024; + if denom.is_zero() { + 0.0 + } else { + nom / denom + } + } -pub fn integrate_brdf(mut n_dot_v: f32, roughness: f32) -> Vec2 { - n_dot_v = n_dot_v.max(f32::EPSILON); - let v = Vec3::new(f32::sqrt(1.0 - n_dot_v * n_dot_v), 0.0, n_dot_v); + fn geometry_smith(normal: Vec3, view_dir: Vec3, light_dir: Vec3, roughness: f32) -> f32 { + let n_dot_v = normal.dot(view_dir).max(0.0); + let n_dot_l = normal.dot(light_dir).max(0.0); + let ggx1 = geometry_schlick_ggx(n_dot_v, roughness); + let ggx2 = geometry_schlick_ggx(n_dot_l, roughness); - let mut a = 0.0f32; - let mut b = 0.0f32; + ggx1 * ggx2 + } + + const SAMPLE_COUNT: u32 = 1024; + + pub fn integrate_brdf(mut n_dot_v: f32, roughness: f32) -> Vec2 { + n_dot_v = n_dot_v.max(f32::EPSILON); + let v = Vec3::new(f32::sqrt(1.0 - n_dot_v * n_dot_v), 0.0, n_dot_v); - let n = Vec3::Z; + let mut a = 0.0f32; + let mut b = 0.0f32; - for i in 1..SAMPLE_COUNT { - let xi = hammersley(i, SAMPLE_COUNT); - let h = importance_sample_ggx(xi, n, roughness); - let l = (2.0 * v.dot(h) * h - v).alt_norm_or_zero(); + let n = Vec3::Z; - let n_dot_l = l.z.max(0.0); - let n_dot_h = h.z.max(0.0); - let v_dot_h = v.dot(h).max(0.0); + for i in 1..SAMPLE_COUNT { + let xi = hammersley(i, SAMPLE_COUNT); + let h = importance_sample_ggx(xi, n, roughness); + let l = (2.0 * v.dot(h) * h - v).alt_norm_or_zero(); - if n_dot_l > 0.0 { - let g = geometry_smith(n, v, l, roughness); - let denom = n_dot_h * n_dot_v; - let g_vis = (g * v_dot_h) / denom; - let f_c = (1.0 - v_dot_h).powf(5.0); + let n_dot_l = l.z.max(0.0); + let n_dot_h = h.z.max(0.0); + let v_dot_h = v.dot(h).max(0.0); - a += (1.0 - f_c) * g_vis; - b += f_c * g_vis; + if n_dot_l > 0.0 { + let g = geometry_smith(n, v, l, roughness); + let denom = n_dot_h * n_dot_v; + let g_vis = (g * v_dot_h) / denom; + let f_c = (1.0 - v_dot_h).powf(5.0); + + a += (1.0 - f_c) * g_vis; + b += f_c * g_vis; + } } - } - a /= SAMPLE_COUNT as f32; - b /= SAMPLE_COUNT as f32; + a /= SAMPLE_COUNT as f32; + b /= SAMPLE_COUNT as f32; - Vec2::new(a, b) -} + Vec2::new(a, b) + } -/// This function doesn't work on rust-gpu, presumably because of the loop. -pub fn integrate_brdf_doesnt_work(mut n_dot_v: f32, roughness: f32) -> Vec2 { - n_dot_v = n_dot_v.max(f32::EPSILON); - let v = Vec3::new(f32::sqrt(1.0 - n_dot_v * n_dot_v), 0.0, n_dot_v); + /// This function doesn't work on rust-gpu, presumably because of the loop. + pub fn integrate_brdf_doesnt_work(mut n_dot_v: f32, roughness: f32) -> Vec2 { + n_dot_v = n_dot_v.max(f32::EPSILON); + let v = Vec3::new(f32::sqrt(1.0 - n_dot_v * n_dot_v), 0.0, n_dot_v); - let mut a = 0.0f32; - let mut b = 0.0f32; + let mut a = 0.0f32; + let mut b = 0.0f32; - let n = Vec3::Z; + let n = Vec3::Z; - let mut i = 0u32; - while i < SAMPLE_COUNT { - i += 1; + let mut i = 0u32; + while i < SAMPLE_COUNT { + i += 1; - let xi = hammersley(i, SAMPLE_COUNT); - let h = importance_sample_ggx(xi, n, roughness); - let l = (2.0 * v.dot(h) * h - v).alt_norm_or_zero(); + let xi = hammersley(i, SAMPLE_COUNT); + let h = importance_sample_ggx(xi, n, roughness); + let l = (2.0 * v.dot(h) * h - v).alt_norm_or_zero(); - let n_dot_l = l.z.max(0.0); - let n_dot_h = h.z.max(0.0); - let v_dot_h = v.dot(h).max(0.0); + let n_dot_l = l.z.max(0.0); + let n_dot_h = h.z.max(0.0); + let v_dot_h = v.dot(h).max(0.0); - if n_dot_l > 0.0 { - let g = geometry_smith(n, v, l, roughness); - let denom = n_dot_h * n_dot_v; - let g_vis = (g * v_dot_h) / denom; - let f_c = (1.0 - v_dot_h).powf(5.0); + if n_dot_l > 0.0 { + let g = geometry_smith(n, v, l, roughness); + let denom = n_dot_h * n_dot_v; + let g_vis = (g * v_dot_h) / denom; + let f_c = (1.0 - v_dot_h).powf(5.0); - a += (1.0 - f_c) * g_vis; - b += f_c * g_vis; + a += (1.0 - f_c) * g_vis; + b += f_c * g_vis; + } } - } - a /= SAMPLE_COUNT as f32; - b /= SAMPLE_COUNT as f32; + a /= SAMPLE_COUNT as f32; + b /= SAMPLE_COUNT as f32; - Vec2::new(a, b) -} + Vec2::new(a, b) + } -/// Used by [`prefilter_environment_cubemap_vertex`] to read the camera and -/// roughness values from the slab. -#[derive(Clone, Copy, Default, SlabItem)] -pub struct VertexPrefilterEnvironmentCubemapIds { - pub camera: Id, - // TODO: does this have to be an Id? Pretty sure it can be inline - pub roughness: Id, -} + /// Used by [`prefilter_environment_cubemap_vertex`] to read the camera and + /// roughness values from the slab. + #[derive(Clone, Copy, Default, SlabItem)] + pub struct VertexPrefilterEnvironmentCubemapIds { + pub camera: Id, + // TODO: does this have to be an Id? Pretty sure it can be inline + pub roughness: Id, + } -/// Vertex shader for rendering a "prefilter environment" cubemap. -#[spirv(vertex)] -pub fn prefilter_environment_cubemap_vertex( - #[spirv(instance_index)] prefilter_id: Id, - #[spirv(vertex_index)] vertex_id: u32, - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], - out_pos: &mut Vec3, - out_roughness: &mut f32, - #[spirv(position)] gl_pos: &mut Vec4, -) { - let in_pos = crate::math::CUBE[vertex_id as usize]; - let VertexPrefilterEnvironmentCubemapIds { camera, roughness } = slab.read(prefilter_id); - let camera = slab.read(camera); - *out_roughness = slab.read(roughness); - *out_pos = in_pos; - *gl_pos = camera.view_projection() * in_pos.extend(1.0); -} + /// Vertex shader for rendering a "prefilter environment" cubemap. + #[spirv(vertex)] + pub fn prefilter_environment_cubemap_vertex( + #[spirv(instance_index)] prefilter_id: Id, + #[spirv(vertex_index)] vertex_id: u32, + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] slab: &[u32], + out_pos: &mut Vec3, + out_roughness: &mut f32, + #[spirv(position)] gl_pos: &mut Vec4, + ) { + let in_pos = crate::math::CUBE[vertex_id as usize]; + let VertexPrefilterEnvironmentCubemapIds { camera, roughness } = slab.read(prefilter_id); + let camera = slab.read(camera); + *out_roughness = slab.read(roughness); + *out_pos = in_pos; + *gl_pos = camera.view_projection() * in_pos.extend(1.0); + } -/// Fragment shader for rendering a "prefilter environment" cubemap. -/// -/// Lambertian prefilter. -#[spirv(fragment)] -pub fn prefilter_environment_cubemap_fragment( - #[spirv(descriptor_set = 0, binding = 1)] environment_cubemap: &Cubemap, - #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, - in_pos: Vec3, - in_roughness: f32, - frag_color: &mut Vec4, -) { - let mut n = in_pos.alt_norm_or_zero(); - // `wgpu` and vulkan's y coords are flipped from opengl - n.y *= -1.0; - let r = n; - let v = r; - - let mut total_weight = 0.0f32; - let mut prefiltered_color = Vec3::ZERO; - - for i in 0..SAMPLE_COUNT { - let xi = hammersley(i, SAMPLE_COUNT); - let h = importance_sample_ggx(xi, n, in_roughness); - let l = (2.0 * v.dot(h) * h - v).alt_norm_or_zero(); - - let n_dot_l = n.dot(l).max(0.0); - if n_dot_l > 0.0 { - let mip_level = if in_roughness == 0.0 { - 0.0 - } else { - calc_lod(n_dot_l) - }; - prefiltered_color += environment_cubemap - .sample_by_lod(*sampler, l, mip_level) - .xyz() - * n_dot_l; - total_weight += n_dot_l; + /// Fragment shader for rendering a "prefilter environment" cubemap. + /// + /// Lambertian prefilter. + #[spirv(fragment)] + pub fn prefilter_environment_cubemap_fragment( + #[spirv(descriptor_set = 0, binding = 1)] environment_cubemap: &Cubemap, + #[spirv(descriptor_set = 0, binding = 2)] sampler: &Sampler, + in_pos: Vec3, + in_roughness: f32, + frag_color: &mut Vec4, + ) { + let mut n = in_pos.alt_norm_or_zero(); + // `wgpu` and vulkan's y coords are flipped from opengl + n.y *= -1.0; + let r = n; + let v = r; + + let mut total_weight = 0.0f32; + let mut prefiltered_color = Vec3::ZERO; + + for i in 0..SAMPLE_COUNT { + let xi = hammersley(i, SAMPLE_COUNT); + let h = importance_sample_ggx(xi, n, in_roughness); + let l = (2.0 * v.dot(h) * h - v).alt_norm_or_zero(); + + let n_dot_l = n.dot(l).max(0.0); + if n_dot_l > 0.0 { + let mip_level = if in_roughness == 0.0 { + 0.0 + } else { + calc_lod(n_dot_l) + }; + prefiltered_color += environment_cubemap + .sample_by_lod(*sampler, l, mip_level) + .xyz() + * n_dot_l; + total_weight += n_dot_l; + } } - } - prefiltered_color /= total_weight; - *frag_color = prefiltered_color.extend(1.0); -} + prefiltered_color /= total_weight; + *frag_color = prefiltered_color.extend(1.0); + } -pub fn calc_lod_old(n: Vec3, v: Vec3, h: Vec3, roughness: f32) -> f32 { - // sample from the environment's mip level based on roughness/pdf - let d = crate::pbr::normal_distribution_ggx(n, h, roughness); - let n_dot_h = n.dot(h).max(0.0); - let h_dot_v = h.dot(v).max(0.0); - let pdf = (d * n_dot_h / (4.0 * h_dot_v)).max(f32::EPSILON); + pub fn calc_lod_old(n: Vec3, v: Vec3, h: Vec3, roughness: f32) -> f32 { + // sample from the environment's mip level based on roughness/pdf + let d = crate::pbr::shader::normal_distribution_ggx(n, h, roughness); + let n_dot_h = n.dot(h).max(0.0); + let h_dot_v = h.dot(v).max(0.0); + let pdf = (d * n_dot_h / (4.0 * h_dot_v)).max(f32::EPSILON); - let resolution = 512.0; // resolution of source cubemap (per face) - let sa_texel = 4.0 * core::f32::consts::PI / (6.0 * resolution * resolution); - let sa_sample = 1.0 / (SAMPLE_COUNT as f32 * pdf + f32::EPSILON); + let resolution = 512.0; // resolution of source cubemap (per face) + let sa_texel = 4.0 * core::f32::consts::PI / (6.0 * resolution * resolution); + let sa_sample = 1.0 / (SAMPLE_COUNT as f32 * pdf + f32::EPSILON); - 0.5 * (sa_sample / sa_texel).log2() -} + 0.5 * (sa_sample / sa_texel).log2() + } -pub fn calc_lod(n_dot_l: f32) -> f32 { - let cube_width = 512.0; - let pdf = (n_dot_l * core::f32::consts::FRAC_1_PI).max(0.0); - 0.5 * (6.0 * cube_width * cube_width / (SAMPLE_COUNT as f32 * pdf).max(f32::EPSILON)).log2() -} + pub fn calc_lod(n_dot_l: f32) -> f32 { + let cube_width = 512.0; + let pdf = (n_dot_l * core::f32::consts::FRAC_1_PI).max(0.0); + 0.5 * (6.0 * cube_width * cube_width / (SAMPLE_COUNT as f32 * pdf).max(f32::EPSILON)).log2() + } -#[spirv(vertex)] -/// Vertex shader for generating texture mips. -pub fn generate_mipmap_vertex( - #[spirv(vertex_index)] vertex_id: u32, - out_uv: &mut Vec2, - #[spirv(position)] gl_pos: &mut Vec4, -) { - let i = vertex_id as usize; - *out_uv = crate::math::UV_COORD_QUAD_CCW[i]; - *gl_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i]; -} + #[spirv(vertex)] + /// Vertex shader for generating texture mips. + pub fn generate_mipmap_vertex( + #[spirv(vertex_index)] vertex_id: u32, + out_uv: &mut Vec2, + #[spirv(position)] gl_pos: &mut Vec4, + ) { + let i = vertex_id as usize; + *out_uv = crate::math::UV_COORD_QUAD_CCW[i]; + *gl_pos = crate::math::CLIP_SPACE_COORD_QUAD_CCW[i]; + } -#[spirv(fragment)] -/// Fragment shader for generating texture mips. -pub fn generate_mipmap_fragment( - #[spirv(descriptor_set = 0, binding = 0)] texture: &Image2d, - #[spirv(descriptor_set = 0, binding = 1)] sampler: &Sampler, - in_uv: Vec2, - frag_color: &mut Vec4, -) { - *frag_color = texture.sample(*sampler, in_uv); -} + #[spirv(fragment)] + /// Fragment shader for generating texture mips. + pub fn generate_mipmap_fragment( + #[spirv(descriptor_set = 0, binding = 0)] texture: &Image2d, + #[spirv(descriptor_set = 0, binding = 1)] sampler: &Sampler, + in_uv: Vec2, + frag_color: &mut Vec4, + ) { + *frag_color = texture.sample(*sampler, in_uv); + } -#[repr(C)] -#[derive(Clone, Copy)] -struct Vert { - pos: [f32; 3], - uv: [f32; 2], -} + #[repr(C)] + #[derive(Clone, Copy)] + struct Vert { + pos: [f32; 3], + uv: [f32; 2], + } -/// A screen-space quad. -const BRDF_VERTS: [Vert; 6] = { - let bl = Vert { - pos: [-1.0, -1.0, 0.0], - uv: [0.0, 1.0], - }; - let br = Vert { - pos: [1.0, -1.0, 0.0], - uv: [1.0, 1.0], - }; - let tl = Vert { - pos: [-1.0, 1.0, 0.0], - uv: [0.0, 0.0], - }; - let tr = Vert { - pos: [1.0, 1.0, 0.0], - uv: [1.0, 0.0], + /// A screen-space quad. + const BRDF_VERTS: [Vert; 6] = { + let bl = Vert { + pos: [-1.0, -1.0, 0.0], + uv: [0.0, 1.0], + }; + let br = Vert { + pos: [1.0, -1.0, 0.0], + uv: [1.0, 1.0], + }; + let tl = Vert { + pos: [-1.0, 1.0, 0.0], + uv: [0.0, 0.0], + }; + let tr = Vert { + pos: [1.0, 1.0, 0.0], + uv: [1.0, 0.0], + }; + + [bl, br, tr, bl, tr, tl] }; - [bl, br, tr, bl, tr, tl] -}; - -#[spirv(vertex)] -/// Vertex shader for creating a BRDF LUT. -pub fn brdf_lut_convolution_vertex( - #[spirv(vertex_index)] vertex_id: u32, - out_uv: &mut glam::Vec2, - #[spirv(position)] gl_pos: &mut glam::Vec4, -) { - let Vert { pos, uv } = BRDF_VERTS[vertex_id as usize]; - *out_uv = Vec2::from(uv); - *gl_pos = Vec3::from(pos).extend(1.0); -} + #[spirv(vertex)] + /// Vertex shader for creating a BRDF LUT. + pub fn brdf_lut_convolution_vertex( + #[spirv(vertex_index)] vertex_id: u32, + out_uv: &mut glam::Vec2, + #[spirv(position)] gl_pos: &mut glam::Vec4, + ) { + let Vert { pos, uv } = BRDF_VERTS[vertex_id as usize]; + *out_uv = Vec2::from(uv); + *gl_pos = Vec3::from(pos).extend(1.0); + } -#[spirv(fragment)] -/// Fragment shader for creating a BRDF LUT. -pub fn brdf_lut_convolution_fragment(in_uv: glam::Vec2, out_color: &mut glam::Vec2) { - *out_color = integrate_brdf(in_uv.x, in_uv.y); + #[spirv(fragment)] + /// Fragment shader for creating a BRDF LUT. + pub fn brdf_lut_convolution_fragment(in_uv: glam::Vec2, out_color: &mut glam::Vec2) { + *out_color = integrate_brdf(in_uv.x, in_uv.y); + } } #[cfg(test)] @@ -320,14 +324,17 @@ mod test { fn integrate_brdf_sanity() { let points = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0), (1.0, 1.0)]; for (x, y) in points.into_iter() { - assert!(!integrate_brdf(x, y).is_nan(), "brdf is NaN at {x},{y}"); + assert!( + !shader::integrate_brdf(x, y).is_nan(), + "brdf is NaN at {x},{y}" + ); } let size = 32; let mut img = image::RgbaImage::new(size, size); for (x, y, image::Rgba([r, g, _, a])) in img.enumerate_pixels_mut() { let u = x as f32 / size as f32; let v = y as f32 / size as f32; - let brdf = integrate_brdf(u, v); + let brdf = shader::integrate_brdf(u, v); *r = (brdf.x * 255.0) as u8; *g = (brdf.y * 255.0) as u8; *a = 255; diff --git a/crates/renderling/src/internal/cpu.rs b/crates/renderling/src/internal/cpu.rs index 2e7b1704..c0566de0 100644 --- a/crates/renderling/src/internal/cpu.rs +++ b/crates/renderling/src/internal/cpu.rs @@ -1,4 +1,4 @@ -//! Internal CPU stuff. +//! Internal CPU utilities and stuff. use std::sync::Arc; use snafu::{OptionExt, ResultExt}; diff --git a/crates/renderling/src/linkage/brdf_lut_convolution_fragment.rs b/crates/renderling/src/linkage/brdf_lut_convolution_fragment.rs index 47cf8a95..810a04e4 100644 --- a/crates/renderling/src/linkage/brdf_lut_convolution_fragment.rs +++ b/crates/renderling/src/linkage/brdf_lut_convolution_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "convolution::brdf_lut_convolution_fragment"; + pub const ENTRY_POINT: &str = "convolution::shader::brdf_lut_convolution_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/convolution-brdf_lut_convolution_fragment.spv") + wgpu::include_spirv!("../../shaders/convolution-shader-brdf_lut_convolution_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +20,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "convolutionbrdf_lut_convolution_fragment"; + pub const ENTRY_POINT: &str = "convolutionshaderbrdf_lut_convolution_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/convolution-brdf_lut_convolution_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/convolution-shader-brdf_lut_convolution_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/linkage/brdf_lut_convolution_vertex.rs b/crates/renderling/src/linkage/brdf_lut_convolution_vertex.rs index 2ada2506..85504cba 100644 --- a/crates/renderling/src/linkage/brdf_lut_convolution_vertex.rs +++ b/crates/renderling/src/linkage/brdf_lut_convolution_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "convolution::brdf_lut_convolution_vertex"; + pub const ENTRY_POINT: &str = "convolution::shader::brdf_lut_convolution_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/convolution-brdf_lut_convolution_vertex.spv") + wgpu::include_spirv!("../../shaders/convolution-shader-brdf_lut_convolution_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +20,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "convolutionbrdf_lut_convolution_vertex"; + pub const ENTRY_POINT: &str = "convolutionshaderbrdf_lut_convolution_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/convolution-brdf_lut_convolution_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/convolution-shader-brdf_lut_convolution_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "brdf_lut_convolution_vertex"); diff --git a/crates/renderling/src/linkage/di_convolution_fragment.rs b/crates/renderling/src/linkage/di_convolution_fragment.rs index 8d26d94f..bc8f7165 100644 --- a/crates/renderling/src/linkage/di_convolution_fragment.rs +++ b/crates/renderling/src/linkage/di_convolution_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "ibl::diffuse_irradiance::di_convolution_fragment"; + pub const ENTRY_POINT: &str = "pbr::ibl::shader::di_convolution_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/ibl-diffuse_irradiance-di_convolution_fragment.spv") + wgpu::include_spirv!("../../shaders/pbr-ibl-shader-di_convolution_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "di_convolution_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "ibldiffuse_irradiancedi_convolution_fragment"; + pub const ENTRY_POINT: &str = "pbriblshaderdi_convolution_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/ibl-diffuse_irradiance-di_convolution_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/pbr-ibl-shader-di_convolution_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "di_convolution_fragment"); diff --git a/crates/renderling/src/linkage/generate_mipmap_fragment.rs b/crates/renderling/src/linkage/generate_mipmap_fragment.rs index eec4a4ae..e72fa2ad 100644 --- a/crates/renderling/src/linkage/generate_mipmap_fragment.rs +++ b/crates/renderling/src/linkage/generate_mipmap_fragment.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "convolution::generate_mipmap_fragment"; + pub const ENTRY_POINT: &str = "convolution::shader::generate_mipmap_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/convolution-generate_mipmap_fragment.spv") + wgpu::include_spirv!("../../shaders/convolution-shader-generate_mipmap_fragment.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "generate_mipmap_fragment"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "convolutiongenerate_mipmap_fragment"; + pub const ENTRY_POINT: &str = "convolutionshadergenerate_mipmap_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/convolution-generate_mipmap_fragment.wgsl") + wgpu::include_wgsl!("../../shaders/convolution-shader-generate_mipmap_fragment.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "generate_mipmap_fragment"); diff --git a/crates/renderling/src/linkage/generate_mipmap_vertex.rs b/crates/renderling/src/linkage/generate_mipmap_vertex.rs index cdeab9dd..38b11edd 100644 --- a/crates/renderling/src/linkage/generate_mipmap_vertex.rs +++ b/crates/renderling/src/linkage/generate_mipmap_vertex.rs @@ -3,9 +3,9 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "convolution::generate_mipmap_vertex"; + pub const ENTRY_POINT: &str = "convolution::shader::generate_mipmap_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/convolution-generate_mipmap_vertex.spv") + wgpu::include_spirv!("../../shaders/convolution-shader-generate_mipmap_vertex.spv") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating native linkage for {}", "generate_mipmap_vertex"); @@ -17,9 +17,9 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "convolutiongenerate_mipmap_vertex"; + pub const ENTRY_POINT: &str = "convolutionshadergenerate_mipmap_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/convolution-generate_mipmap_vertex.wgsl") + wgpu::include_wgsl!("../../shaders/convolution-shader-generate_mipmap_vertex.wgsl") } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!("creating web linkage for {}", "generate_mipmap_vertex"); diff --git a/crates/renderling/src/linkage/prefilter_environment_cubemap_fragment.rs b/crates/renderling/src/linkage/prefilter_environment_cubemap_fragment.rs index 0cc0ce40..e559d794 100644 --- a/crates/renderling/src/linkage/prefilter_environment_cubemap_fragment.rs +++ b/crates/renderling/src/linkage/prefilter_environment_cubemap_fragment.rs @@ -3,9 +3,11 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "convolution::prefilter_environment_cubemap_fragment"; + pub const ENTRY_POINT: &str = "convolution::shader::prefilter_environment_cubemap_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/convolution-prefilter_environment_cubemap_fragment.spv") + wgpu::include_spirv!( + "../../shaders/convolution-shader-prefilter_environment_cubemap_fragment.spv" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +22,11 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "convolutionprefilter_environment_cubemap_fragment"; + pub const ENTRY_POINT: &str = "convolutionshaderprefilter_environment_cubemap_fragment"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/convolution-prefilter_environment_cubemap_fragment.wgsl") + wgpu::include_wgsl!( + "../../shaders/convolution-shader-prefilter_environment_cubemap_fragment.wgsl" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/linkage/prefilter_environment_cubemap_vertex.rs b/crates/renderling/src/linkage/prefilter_environment_cubemap_vertex.rs index 31878097..052672ff 100644 --- a/crates/renderling/src/linkage/prefilter_environment_cubemap_vertex.rs +++ b/crates/renderling/src/linkage/prefilter_environment_cubemap_vertex.rs @@ -3,9 +3,11 @@ use crate::linkage::ShaderLinkage; #[cfg(not(target_arch = "wasm32"))] mod target { - pub const ENTRY_POINT: &str = "convolution::prefilter_environment_cubemap_vertex"; + pub const ENTRY_POINT: &str = "convolution::shader::prefilter_environment_cubemap_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_spirv!("../../shaders/convolution-prefilter_environment_cubemap_vertex.spv") + wgpu::include_spirv!( + "../../shaders/convolution-shader-prefilter_environment_cubemap_vertex.spv" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -20,9 +22,11 @@ mod target { } #[cfg(target_arch = "wasm32")] mod target { - pub const ENTRY_POINT: &str = "convolutionprefilter_environment_cubemap_vertex"; + pub const ENTRY_POINT: &str = "convolutionshaderprefilter_environment_cubemap_vertex"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu::include_wgsl!("../../shaders/convolution-prefilter_environment_cubemap_vertex.wgsl") + wgpu::include_wgsl!( + "../../shaders/convolution-shader-prefilter_environment_cubemap_vertex.wgsl" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index 3440a7d1..875e4fed 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -4,651 +4,12 @@ //! * //! * //! * -use crabslab::{Id, Slab}; -use glam::{Mat4, Vec2, Vec3, Vec4, Vec4Swizzles}; - -#[allow(unused)] -use spirv_std::num_traits::{Float, Zero}; - -use crate::{ - atlas::shader::AtlasTextureDescriptor, - geometry::shader::GeometryDescriptor, - light::shader::{ - DirectionalLightDescriptor, LightStyle, LightingDescriptor, PointLightDescriptor, - ShadowCalculation, SpotLightCalculation, - }, - material::shader::MaterialDescriptor, - math::{self, IsSampler, IsVector, Sample2d, Sample2dArray, SampleCube}, - primitive::shader::PrimitiveDescriptor, - println as my_println, -}; pub mod brdf; pub mod debug; pub mod ibl; -use debug::DebugChannel; - -/// Trowbridge-Reitz GGX normal distribution function (NDF). -/// -/// The normal distribution function D statistically approximates the relative -/// surface area of microfacets exactly aligned to the (halfway) vector h. -pub fn normal_distribution_ggx(n: Vec3, h: Vec3, roughness: f32) -> f32 { - let a = roughness * roughness; - let a2 = a * a; - let ndot_h = n.dot(h).max(0.0); - let ndot_h2 = ndot_h * ndot_h; - - let num = a2; - let denom = (ndot_h2 * (a2 - 1.0) + 1.0).powf(2.0) * core::f32::consts::PI; - - num / denom -} - -fn geometry_schlick_ggx(ndot_v: f32, roughness: f32) -> f32 { - let r = roughness + 1.0; - let k = (r * r) / 8.0; - let num = ndot_v; - let denom = ndot_v * (1.0 - k) + k; - - num / denom -} - -/// The geometry function statistically approximates the relative surface area -/// where its micro surface-details overshadow each other, causing light rays to -/// be occluded. -fn geometry_smith(n: Vec3, v: Vec3, l: Vec3, roughness: f32) -> f32 { - let ndot_v = n.dot(v).max(0.0); - let ndot_l = n.dot(l).max(0.0); - let ggx1 = geometry_schlick_ggx(ndot_v, roughness); - let ggx2 = geometry_schlick_ggx(ndot_l, roughness); - - ggx1 * ggx2 -} - -/// Fresnel-Schlick approximation function. -/// -/// The Fresnel equation describes the ratio of light that gets reflected over -/// the light that gets refracted, which varies over the angle we're looking at -/// a surface. The moment light hits a surface, based on the surface-to-view -/// angle, the Fresnel equation tells us the percentage of light that gets -/// reflected. From this ratio of reflection and the energy conservation -/// principle we can directly obtain the refracted portion of light. -fn fresnel_schlick( - // dot product result between the surface's normal n and the halfway h (or view v) direction. - cos_theta: f32, - // surface reflection at zero incidence (how much the surface reflects if looking directly at - // the surface) - f0: Vec3, -) -> Vec3 { - f0 + (1.0 - f0) * (1.0 - cos_theta).clamp(0.0, 1.0).powf(5.0) -} - -fn fresnel_schlick_roughness(cos_theta: f32, f0: Vec3, roughness: f32) -> Vec3 { - f0 + (Vec3::splat(1.0 - roughness).max(f0) - f0) * (1.0 - cos_theta).clamp(0.0, 1.0).powf(5.0) -} - -#[allow(clippy::too_many_arguments)] -pub fn outgoing_radiance( - light_color: Vec4, - albedo: Vec3, - attenuation: f32, - v: Vec3, - l: Vec3, - n: Vec3, - metalness: f32, - roughness: f32, -) -> Vec3 { - my_println!("outgoing_radiance"); - my_println!(" light_color: {light_color:?}"); - my_println!(" albedo: {albedo:?}"); - my_println!(" attenuation: {attenuation:?}"); - my_println!(" v: {v:?}"); - my_println!(" l: {l:?}"); - my_println!(" n: {n:?}"); - my_println!(" metalness: {metalness:?}"); - my_println!(" roughness: {roughness:?}"); - - let f0 = Vec3::splat(0.4).lerp(albedo, metalness); - my_println!(" f0: {f0:?}"); - let radiance = light_color.xyz() * attenuation; - my_println!(" radiance: {radiance:?}"); - let h = (v + l).alt_norm_or_zero(); - my_println!(" h: {h:?}"); - // cook-torrance brdf - let ndf: f32 = normal_distribution_ggx(n, h, roughness); - my_println!(" ndf: {ndf:?}"); - let g: f32 = geometry_smith(n, v, l, roughness); - my_println!(" g: {g:?}"); - let f: Vec3 = fresnel_schlick(h.dot(v).max(0.0), f0); - my_println!(" f: {f:?}"); - - let k_s = f; - let k_d = (Vec3::splat(1.0) - k_s) * (1.0 - metalness); - my_println!(" k_s: {k_s:?}"); - - let numerator: Vec3 = ndf * g * f; - my_println!(" numerator: {numerator:?}"); - let n_dot_l = n.dot(l).max(0.0); - my_println!(" n_dot_l: {n_dot_l:?}"); - let denominator: f32 = 4.0 * n.dot(v).max(0.0) * n_dot_l + 0.0001; - my_println!(" denominator: {denominator:?}"); - let specular: Vec3 = numerator / denominator; - my_println!(" specular: {specular:?}"); - - (k_d * albedo / core::f32::consts::PI + specular) * radiance * n_dot_l -} - -pub fn sample_irradiance, S: IsSampler>( - irradiance: &T, - irradiance_sampler: &S, - // Normal vector - n: Vec3, -) -> Vec3 { - irradiance.sample_by_lod(*irradiance_sampler, n, 0.0).xyz() -} - -pub fn sample_specular_reflection, S: IsSampler>( - prefiltered: &T, - prefiltered_sampler: &S, - // camera position in world space - camera_pos: Vec3, - // fragment position in world space - in_pos: Vec3, - // normal vector - n: Vec3, - roughness: f32, -) -> Vec3 { - let v = (camera_pos - in_pos).alt_norm_or_zero(); - let reflect_dir = math::reflect(-v, n); - prefiltered - .sample_by_lod(*prefiltered_sampler, reflect_dir, roughness * 4.0) - .xyz() -} - -/// Returns the `Material` from the stage's slab. -pub fn get_material( - material_id: Id, - has_lighting: bool, - material_slab: &[u32], -) -> MaterialDescriptor { - if material_id.is_none() { - // without an explicit material (or if the entire render has no lighting) - // the entity will not participate in any lighting calculations - MaterialDescriptor { - has_lighting: false, - ..Default::default() - } - } else { - let mut material = material_slab.read_unchecked(material_id); - material.has_lighting &= has_lighting; - material - } -} - -pub fn texture_color, S: IsSampler>( - texture_id: Id, - uv: Vec2, - atlas: &A, - sampler: &S, - atlas_size: glam::UVec2, - material_slab: &[u32], -) -> Vec4 { - let texture = material_slab.read(texture_id); - // uv is [0, 0] when texture_id is Id::NONE - let uv = texture.uv(uv, atlas_size); - crate::println!("uv: {uv}"); - let mut color: Vec4 = atlas.sample_by_lod(*sampler, uv, 0.0); - if texture_id.is_none() { - color = Vec4::splat(1.0); - } - color -} - -/// PBR fragment shader capable of being run on CPU or GPU. -#[allow(clippy::too_many_arguments)] -pub fn fragment_impl( - atlas: &A, - atlas_sampler: &S, - irradiance: &C, - irradiance_sampler: &S, - prefiltered: &C, - prefiltered_sampler: &S, - brdf: &T, - brdf_sampler: &S, - shadow_map: &DtA, - shadow_map_sampler: &S, - - geometry_slab: &[u32], - material_slab: &[u32], - lighting_slab: &[u32], - - renderlet_id: Id, - - frag_coord: Vec4, - in_color: Vec4, - in_uv0: Vec2, - in_uv1: Vec2, - in_norm: Vec3, - in_tangent: Vec3, - in_bitangent: Vec3, - in_pos: Vec3, - - output: &mut Vec4, -) where - A: Sample2dArray, - T: Sample2d, - DtA: Sample2dArray, - C: SampleCube, - S: IsSampler, -{ - let renderlet = geometry_slab.read_unchecked(renderlet_id); - let geom_desc = geometry_slab.read_unchecked(renderlet.geometry_descriptor_id); - crate::println!("pbr_desc_id: {:?}", renderlet.geometry_descriptor_id); - crate::println!("pbr_desc: {geom_desc:#?}"); - let GeometryDescriptor { - camera_id, - atlas_size, - resolution: _, - debug_channel, - has_lighting, - has_skinning: _, - perform_frustum_culling: _, - perform_occlusion_culling: _, - } = geom_desc; - - let material = get_material(renderlet.material_id, has_lighting, material_slab); - crate::println!("material: {:#?}", material); - - let albedo_tex_uv = if material.albedo_tex_coord == 0 { - in_uv0 - } else { - in_uv1 - }; - let albedo_tex_color = texture_color( - material.albedo_texture_id, - albedo_tex_uv, - atlas, - atlas_sampler, - atlas_size, - material_slab, - ); - my_println!("albedo_tex_color: {:?}", albedo_tex_color); - - let metallic_roughness_uv = if material.metallic_roughness_tex_coord == 0 { - in_uv0 - } else { - in_uv1 - }; - let metallic_roughness_tex_color = texture_color( - material.metallic_roughness_texture_id, - metallic_roughness_uv, - atlas, - atlas_sampler, - atlas_size, - material_slab, - ); - my_println!( - "metallic_roughness_tex_color: {:?}", - metallic_roughness_tex_color - ); - - let normal_tex_uv = if material.normal_tex_coord == 0 { - in_uv0 - } else { - in_uv1 - }; - let normal_tex_color = texture_color( - material.normal_texture_id, - normal_tex_uv, - atlas, - atlas_sampler, - atlas_size, - material_slab, - ); - my_println!("normal_tex_color: {:?}", normal_tex_color); - - let ao_tex_uv = if material.ao_tex_coord == 0 { - in_uv0 - } else { - in_uv1 - }; - let ao_tex_color = texture_color( - material.ao_texture_id, - ao_tex_uv, - atlas, - atlas_sampler, - atlas_size, - material_slab, - ); - - let emissive_tex_uv = if material.emissive_tex_coord == 0 { - in_uv0 - } else { - in_uv1 - }; - let emissive_tex_color = texture_color( - material.emissive_texture_id, - emissive_tex_uv, - atlas, - atlas_sampler, - atlas_size, - material_slab, - ); - - let (norm, uv_norm) = if material.normal_texture_id.is_none() { - // there is no normal map, use the normal normal ;) - (in_norm, Vec3::ZERO) - } else { - // convert the normal from color coords to tangent space -1,1 - let sampled_norm = (normal_tex_color.xyz() * 2.0 - Vec3::splat(1.0)).alt_norm_or_zero(); - let tbn = glam::mat3( - in_tangent.alt_norm_or_zero(), - in_bitangent.alt_norm_or_zero(), - in_norm.alt_norm_or_zero(), - ); - // convert the normal from tangent space to world space - let norm = (tbn * sampled_norm).alt_norm_or_zero(); - (norm, sampled_norm) - }; - - let n = norm; - let albedo = albedo_tex_color * material.albedo_factor * in_color; - let roughness = metallic_roughness_tex_color.y * material.roughness_factor; - let metallic = metallic_roughness_tex_color.z * material.metallic_factor; - let ao = 1.0 + material.ao_strength * (ao_tex_color.x - 1.0); - let emissive = - emissive_tex_color.xyz() * material.emissive_factor * material.emissive_strength_multiplier; - let irradiance = sample_irradiance(irradiance, irradiance_sampler, n); - let camera = geometry_slab.read(camera_id); - let specular = sample_specular_reflection( - prefiltered, - prefiltered_sampler, - camera.position(), - in_pos, - n, - roughness, - ); - let brdf = - brdf::shader::sample_brdf(brdf, brdf_sampler, camera.position(), in_pos, n, roughness); - - fn colorize(u: Vec3) -> Vec4 { - ((u.alt_norm_or_zero() + Vec3::splat(1.0)) / 2.0).extend(1.0) - } - - crate::println!("debug_mode: {debug_channel:?}"); - match debug_channel { - DebugChannel::None => {} - DebugChannel::UvCoords0 => { - *output = colorize(Vec3::new(in_uv0.x, in_uv0.y, 0.0)); - return; - } - DebugChannel::UvCoords1 => { - *output = colorize(Vec3::new(in_uv1.x, in_uv1.y, 0.0)); - return; - } - DebugChannel::Normals => { - *output = colorize(norm); - return; - } - DebugChannel::VertexColor => { - *output = in_color; - return; - } - DebugChannel::VertexNormals => { - *output = colorize(in_norm); - return; - } - DebugChannel::UvNormals => { - *output = colorize(uv_norm); - return; - } - DebugChannel::Tangents => { - *output = colorize(in_tangent); - return; - } - DebugChannel::Bitangents => { - *output = colorize(in_bitangent); - return; - } - DebugChannel::DiffuseIrradiance => { - *output = irradiance.extend(1.0); - return; - } - DebugChannel::SpecularReflection => { - *output = specular.extend(1.0); - return; - } - DebugChannel::Brdf => { - *output = brdf.extend(1.0).extend(1.0); - return; - } - DebugChannel::Roughness => { - *output = Vec3::splat(roughness).extend(1.0); - return; - } - DebugChannel::Metallic => { - *output = Vec3::splat(metallic).extend(1.0); - return; - } - DebugChannel::Albedo => { - *output = albedo; - return; - } - DebugChannel::Occlusion => { - *output = Vec3::splat(ao).extend(1.0); - return; - } - DebugChannel::Emissive => { - *output = emissive.extend(1.0); - return; - } - DebugChannel::UvEmissive => { - *output = emissive_tex_color.xyz().extend(1.0); - return; - } - DebugChannel::EmissiveFactor => { - *output = material.emissive_factor.extend(1.0); - return; - } - DebugChannel::EmissiveStrength => { - *output = Vec3::splat(material.emissive_strength_multiplier).extend(1.0); - return; - } - } - - *output = if material.has_lighting { - shade_fragment( - shadow_map, - shadow_map_sampler, - camera.position(), - n, - in_pos, - albedo.xyz(), - metallic, - roughness, - ao, - emissive, - irradiance, - specular, - brdf, - lighting_slab, - frag_coord, - ) - } else { - crate::println!("no shading!"); - in_color * albedo_tex_color * material.albedo_factor - }; -} - -#[allow(clippy::too_many_arguments)] -pub fn shade_fragment( - shadow_map: &T, - shadow_map_sampler: &S, - // camera's position in world space - camera_pos: Vec3, - // normal of the fragment - in_norm: Vec3, - // position of the fragment in world space - in_pos: Vec3, - // base color of the fragment - albedo: Vec3, - metallic: f32, - roughness: f32, - ao: f32, - emissive: Vec3, - irradiance: Vec3, - prefiltered: Vec3, - brdf: Vec2, - - light_slab: &[u32], - frag_coord: Vec4, -) -> Vec4 -where - S: IsSampler, - T: Sample2dArray, -{ - let n = in_norm.alt_norm_or_zero(); - let v = (camera_pos - in_pos).alt_norm_or_zero(); - // There is always a `LightingDescriptor` stored at index `0` of the - // light slab. - let lighting_desc = light_slab.read_unchecked(Id::::new(0)); - // If light tiling is enabled, use the pre-computed tile's light list - let analytical_lights_array = if lighting_desc.light_tiling_descriptor_id.is_none() { - lighting_desc.analytical_lights_array - } else { - let tiling_descriptor = light_slab.read_unchecked(lighting_desc.light_tiling_descriptor_id); - let tile_index = tiling_descriptor.tile_index_for_fragment(frag_coord.xy()); - let tile = light_slab.read_unchecked(tiling_descriptor.tiles_array.at(tile_index)); - tile.lights_array - }; - my_println!("lights: {analytical_lights_array:?}"); - my_println!("surface normal: {n:?}"); - my_println!("vector from surface to camera: {v:?}"); - - // accumulated outgoing radiance - let mut lo = Vec3::ZERO; - for light_id_id in analytical_lights_array.iter() { - // calculate per-light radiance - let light_id = light_slab.read(light_id_id); - if light_id.is_none() { - break; - } - let light = light_slab.read(light_id); - let transform = light_slab.read(light.transform_id); - crate::println!("transform: {transform:?}"); - let transform = Mat4::from(transform); - - // determine the light ray and the radiance - let (radiance, shadow) = match light.light_type { - LightStyle::Point => { - let PointLightDescriptor { - position, - color, - intensity, - } = light_slab.read(light.into_point_id()); - let position = transform.transform_point3(position); - // This definitely is the direction pointing from fragment to the light. - // It needs to stay this way. - // For more info, see - // - let frag_to_light = position - in_pos; - let distance = frag_to_light.length(); - if distance == 0.0 { - crate::println!("distance between point light and surface is zero"); - continue; - } - let l = frag_to_light.alt_norm_or_zero(); - let attenuation = intensity / (distance * distance); - let radiance = - outgoing_radiance(color, albedo, attenuation, v, l, n, metallic, roughness); - let shadow = if light.shadow_map_desc_id.is_some() { - // Shadow is 1.0 when the fragment is in the shadow of this light, - // and 0.0 in darkness - ShadowCalculation::new(light_slab, light, in_pos, n, l).run_point( - light_slab, - shadow_map, - shadow_map_sampler, - position, - ) - } else { - 0.0 - }; - (radiance, shadow) - } - - LightStyle::Spot => { - let spot_light_descriptor = light_slab.read(light.into_spot_id()); - let calculation = - SpotLightCalculation::new(spot_light_descriptor, transform, in_pos); - crate::println!("calculation: {calculation:#?}"); - if calculation.frag_to_light_distance == 0.0 { - continue; - } - let attenuation: f32 = spot_light_descriptor.intensity * calculation.contribution; - let radiance = outgoing_radiance( - spot_light_descriptor.color, - albedo, - attenuation, - v, - calculation.frag_to_light, - n, - metallic, - roughness, - ); - let shadow = if light.shadow_map_desc_id.is_some() { - // Shadow is 1.0 when the fragment is in the shadow of this light, - // and 0.0 in darkness - ShadowCalculation::new(light_slab, light, in_pos, n, calculation.frag_to_light) - .run_directional_or_spot(light_slab, shadow_map, shadow_map_sampler) - } else { - 0.0 - }; - (radiance, shadow) - } - - LightStyle::Directional => { - let DirectionalLightDescriptor { - direction, - color, - intensity, - } = light_slab.read(light.into_directional_id()); - let direction = transform.transform_vector3(direction); - let l = -direction.alt_norm_or_zero(); - let attenuation = intensity; - let radiance = - outgoing_radiance(color, albedo, attenuation, v, l, n, metallic, roughness); - let shadow = - if light.shadow_map_desc_id.is_some() { - // Shadow is 1.0 when the fragment is in the shadow of this light, - // and 0.0 in darkness - ShadowCalculation::new(light_slab, light, in_pos, n, l) - .run_directional_or_spot(light_slab, shadow_map, shadow_map_sampler) - } else { - 0.0 - }; - (radiance, shadow) - } - }; - crate::println!("radiance: {radiance}"); - crate::println!("shadow: {shadow}"); - lo += radiance * (1.0 - shadow); - } - - my_println!("lo: {lo:?}"); - // calculate reflectance at normal incidence; if dia-electric (like plastic) use - // F0 of 0.04 and if it's a metal, use the albedo color as F0 (metallic - // workflow) - let f0: Vec3 = Vec3::splat(0.04).lerp(albedo, metallic); - let cos_theta = n.dot(v).max(0.0); - let fresnel = fresnel_schlick_roughness(cos_theta, f0, roughness); - let ks = fresnel; - let kd = (1.0 - ks) * (1.0 - metallic); - let diffuse = irradiance * albedo; - let specular = prefiltered * (fresnel * brdf.x + brdf.y); - let color = (kd * diffuse + specular) * ao + lo + emissive; - color.extend(1.0) -} +pub mod shader; #[cfg(test)] mod test { @@ -739,7 +100,7 @@ mod test { let hdr_image = AtlasImage::from_hdr_path("../../img/hdr/resting_place.hdr").unwrap(); let skybox = crate::skybox::Skybox::new(&ctx, hdr_image); - stage.set_skybox(skybox); + stage.use_skybox(&skybox); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); diff --git a/crates/renderling/src/pbr/ibl/cpu.rs b/crates/renderling/src/pbr/ibl/cpu.rs index 7673ff18..921861fa 100644 --- a/crates/renderling/src/pbr/ibl/cpu.rs +++ b/crates/renderling/src/pbr/ibl/cpu.rs @@ -1,5 +1,236 @@ //! CPU side of IBL +use core::sync::atomic::AtomicBool; +use std::sync::Arc; + +use craballoc::{runtime::WgpuRuntime, slab::SlabAllocator, value::Hybrid}; +use crabslab::Id; +use glam::{Mat4, Vec3}; + +use crate::{ + camera::Camera, convolution::shader::VertexPrefilterEnvironmentCubemapIds, skybox::Skybox, + texture, +}; + +/// Image based lighting resources. +#[derive(Clone)] +pub struct Ibl { + is_empty: Arc, + // Cubemap texture of the pre-computed irradiance cubemap + pub(crate) irradiance_cubemap: texture::Texture, + // Cubemap texture and mip maps of the specular highlights, + // where each mip level is a different roughness. + pub(crate) prefiltered_environment_cubemap: texture::Texture, +} + +impl Ibl { + pub fn create_irradiance_and_prefilters( + runtime: impl AsRef, + skybox: &Skybox, + ) -> Self { + let runtime = runtime.as_ref(); + let slab = SlabAllocator::new(runtime, "ibl", wgpu::BufferUsages::VERTEX); + let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1, 10.0); + let camera = Camera::new(&slab).with_projection(proj); + let roughness = slab.new_value(0.0f32); + let prefilter_ids = slab.new_value(VertexPrefilterEnvironmentCubemapIds { + camera: camera.id(), + roughness: roughness.id(), + }); + + let buffer = slab.commit(); + let mut buffer_upkeep = || { + let possibly_new_buffer = slab.commit(); + debug_assert!(!possibly_new_buffer.is_new_this_commit()); + }; + + let views = [ + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(1.0, 0.0, 0.0), + Vec3::new(0.0, -1.0, 0.0), + ), + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(-1.0, 0.0, 0.0), + Vec3::new(0.0, -1.0, 0.0), + ), + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, -1.0, 0.0), + Vec3::new(0.0, 0.0, -1.0), + ), + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, 1.0, 0.0), + Vec3::new(0.0, 0.0, 1.0), + ), + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, 0.0, 1.0), + Vec3::new(0.0, -1.0, 0.0), + ), + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, 0.0, -1.0), + Vec3::new(0.0, -1.0, 0.0), + ), + ]; + + let environment_cubemap = skybox.environment_cubemap_texture(); + + // Convolve the environment map. + let irradiance_cubemap = create_irradiance_map( + runtime, + &buffer, + &mut buffer_upkeep, + environment_cubemap, + &camera, + views, + ); + + // Generate specular IBL pre-filtered environment map. + let prefiltered_environment_cubemap = create_prefiltered_environment_map( + runtime, + &buffer, + &mut buffer_upkeep, + &camera, + &roughness, + prefilter_ids.id(), + environment_cubemap, + views, + ); + + Self { + is_empty: Arc::new(skybox.is_empty().into()), + irradiance_cubemap, + prefiltered_environment_cubemap, + } + } + /// Create a new [`Ibl`] resource. + pub fn new(runtime: impl AsRef, skybox: &Skybox) -> Self { + let runtime = runtime.as_ref(); + let slab = SlabAllocator::new(runtime, "ibl", wgpu::BufferUsages::VERTEX); + let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1, 10.0); + let camera = Camera::new(&slab).with_projection(proj); + let roughness = slab.new_value(0.0f32); + let prefilter_ids = slab.new_value(VertexPrefilterEnvironmentCubemapIds { + camera: camera.id(), + roughness: roughness.id(), + }); + + let buffer = slab.commit(); + let mut buffer_upkeep = || { + let possibly_new_buffer = slab.commit(); + debug_assert!(!possibly_new_buffer.is_new_this_commit()); + }; + + let views = [ + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(1.0, 0.0, 0.0), + Vec3::new(0.0, -1.0, 0.0), + ), + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(-1.0, 0.0, 0.0), + Vec3::new(0.0, -1.0, 0.0), + ), + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, -1.0, 0.0), + Vec3::new(0.0, 0.0, -1.0), + ), + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, 1.0, 0.0), + Vec3::new(0.0, 0.0, 1.0), + ), + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, 0.0, 1.0), + Vec3::new(0.0, -1.0, 0.0), + ), + Mat4::look_at_rh( + Vec3::new(0.0, 0.0, 0.0), + Vec3::new(0.0, 0.0, -1.0), + Vec3::new(0.0, -1.0, 0.0), + ), + ]; + + let environment_cubemap = skybox.environment_cubemap_texture(); + + // Convolve the environment map. + let irradiance_cubemap = create_irradiance_map( + runtime, + &buffer, + &mut buffer_upkeep, + environment_cubemap, + &camera, + views, + ); + + // Generate specular IBL pre-filtered environment map. + let prefiltered_environment_cubemap = create_prefiltered_environment_map( + runtime, + &buffer, + &mut buffer_upkeep, + &camera, + &roughness, + prefilter_ids.id(), + environment_cubemap, + views, + ); + + Self { + is_empty: Arc::new(skybox.is_empty().into()), + irradiance_cubemap, + prefiltered_environment_cubemap, + } + } + + /// Returns whether this [`Ibl`] is empty. + /// + /// An [`Ibl`] is empty if it was created from an empty [`Skybox`]. + pub fn is_empty(&self) -> bool { + self.is_empty.load(std::sync::atomic::Ordering::Relaxed) + } +} + +fn create_irradiance_map( + runtime: impl AsRef, + buffer: &wgpu::Buffer, + buffer_upkeep: impl FnMut(), + environment_texture: &texture::Texture, + camera: &Camera, + views: [Mat4; 6], +) -> texture::Texture { + let runtime = runtime.as_ref(); + let device = &runtime.device; + let pipeline = crate::pbr::ibl::DiffuseIrradianceConvolutionRenderPipeline::new( + device, + wgpu::TextureFormat::Rgba16Float, + ); + + let bindgroup = crate::pbr::ibl::diffuse_irradiance_convolution_bindgroup( + device, + Some("irradiance"), + buffer, + environment_texture, + ); + + texture::Texture::render_cubemap( + runtime, + &pipeline.0, + buffer_upkeep, + camera, + &bindgroup, + views, + 32, + None, + ) +} + /// Pipeline for creating a prefiltered environment map from an existing /// environment cubemap. pub(crate) fn create_prefiltered_environment_pipeline_and_bindgroup( @@ -108,6 +339,93 @@ pub(crate) fn create_prefiltered_environment_pipeline_and_bindgroup( (pipeline, bindgroup) } +#[allow(clippy::too_many_arguments)] +fn create_prefiltered_environment_map( + runtime: impl AsRef, + buffer: &wgpu::Buffer, + mut buffer_upkeep: impl FnMut(), + camera: &Camera, + roughness: &Hybrid, + prefilter_id: Id, + environment_texture: &texture::Texture, + views: [Mat4; 6], +) -> texture::Texture { + let (pipeline, bindgroup) = + crate::pbr::ibl::create_prefiltered_environment_pipeline_and_bindgroup( + &runtime.as_ref().device, + buffer, + environment_texture, + ); + let mut cubemap_faces = Vec::new(); + + for (i, view) in views.iter().enumerate() { + for mip_level in 0..5 { + let mip_width: u32 = 128 >> mip_level; + let mip_height: u32 = 128 >> mip_level; + + let mut encoder = + runtime + .as_ref() + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("specular convolution"), + }); + + let cubemap_face = texture::Texture::new_with( + runtime.as_ref(), + Some(&format!("cubemap{i}{mip_level}prefiltered_environment")), + Some(wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC), + None, + wgpu::TextureFormat::Rgba16Float, + 4, + 2, + mip_width, + mip_height, + 1, + &[], + ); + + // update the roughness for these mips + roughness.set(mip_level as f32 / 4.0); + // update the view to point at one of the cube faces + camera.set_view(*view); + buffer_upkeep(); + { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some(&format!("cubemap{i}")), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &cubemap_face.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), + store: wgpu::StoreOp::Store, + }, + depth_slice: None, + })], + depth_stencil_attachment: None, + ..Default::default() + }); + + render_pass.set_pipeline(&pipeline); + render_pass.set_bind_group(0, Some(&bindgroup), &[]); + render_pass.draw(0..36, prefilter_id.inner()..prefilter_id.inner() + 1); + } + + runtime.as_ref().queue.submit([encoder.finish()]); + cubemap_faces.push(cubemap_face); + } + } + + texture::Texture::new_cubemap_texture( + runtime, + Some("prefiltered environment cubemap"), + 128, + cubemap_faces.as_slice(), + wgpu::TextureFormat::Rgba16Float, + 5, + ) +} + pub fn diffuse_irradiance_convolution_bindgroup_layout( device: &wgpu::Device, ) -> wgpu::BindGroupLayout { diff --git a/crates/renderling/src/pbr/shader.rs b/crates/renderling/src/pbr/shader.rs new file mode 100644 index 00000000..bc033894 --- /dev/null +++ b/crates/renderling/src/pbr/shader.rs @@ -0,0 +1,643 @@ +//! Physically based shader code. +use crabslab::{Id, Slab}; +use glam::{Mat4, Vec2, Vec3, Vec4, Vec4Swizzles}; + +#[allow(unused)] +use spirv_std::num_traits::{Float, Zero}; + +use crate::{ + atlas::shader::AtlasTextureDescriptor, + geometry::shader::GeometryDescriptor, + light::shader::{ + DirectionalLightDescriptor, LightStyle, LightingDescriptor, PointLightDescriptor, + ShadowCalculation, SpotLightCalculation, + }, + material::shader::MaterialDescriptor, + math::{self, IsSampler, IsVector, Sample2d, Sample2dArray, SampleCube}, + primitive::shader::PrimitiveDescriptor, + println as my_println, +}; + +use super::{brdf, debug}; + +/// Trowbridge-Reitz GGX normal distribution function (NDF). +/// +/// The normal distribution function D statistically approximates the relative +/// surface area of microfacets exactly aligned to the (halfway) vector h. +pub fn normal_distribution_ggx(n: Vec3, h: Vec3, roughness: f32) -> f32 { + let a = roughness * roughness; + let a2 = a * a; + let ndot_h = n.dot(h).max(0.0); + let ndot_h2 = ndot_h * ndot_h; + + let num = a2; + let denom = (ndot_h2 * (a2 - 1.0) + 1.0).powf(2.0) * core::f32::consts::PI; + + num / denom +} + +fn geometry_schlick_ggx(ndot_v: f32, roughness: f32) -> f32 { + let r = roughness + 1.0; + let k = (r * r) / 8.0; + let num = ndot_v; + let denom = ndot_v * (1.0 - k) + k; + + num / denom +} + +/// The geometry function statistically approximates the relative surface area +/// where its micro surface-details overshadow each other, causing light rays to +/// be occluded. +fn geometry_smith(n: Vec3, v: Vec3, l: Vec3, roughness: f32) -> f32 { + let ndot_v = n.dot(v).max(0.0); + let ndot_l = n.dot(l).max(0.0); + let ggx1 = geometry_schlick_ggx(ndot_v, roughness); + let ggx2 = geometry_schlick_ggx(ndot_l, roughness); + + ggx1 * ggx2 +} + +/// Fresnel-Schlick approximation function. +/// +/// The Fresnel equation describes the ratio of light that gets reflected over +/// the light that gets refracted, which varies over the angle we're looking at +/// a surface. The moment light hits a surface, based on the surface-to-view +/// angle, the Fresnel equation tells us the percentage of light that gets +/// reflected. From this ratio of reflection and the energy conservation +/// principle we can directly obtain the refracted portion of light. +fn fresnel_schlick( + // dot product result between the surface's normal n and the halfway h (or view v) direction. + cos_theta: f32, + // surface reflection at zero incidence (how much the surface reflects if looking directly at + // the surface) + f0: Vec3, +) -> Vec3 { + f0 + (1.0 - f0) * (1.0 - cos_theta).clamp(0.0, 1.0).powf(5.0) +} + +fn fresnel_schlick_roughness(cos_theta: f32, f0: Vec3, roughness: f32) -> Vec3 { + f0 + (Vec3::splat(1.0 - roughness).max(f0) - f0) * (1.0 - cos_theta).clamp(0.0, 1.0).powf(5.0) +} + +#[allow(clippy::too_many_arguments)] +pub fn outgoing_radiance( + light_color: Vec4, + albedo: Vec3, + attenuation: f32, + v: Vec3, + l: Vec3, + n: Vec3, + metalness: f32, + roughness: f32, +) -> Vec3 { + my_println!("outgoing_radiance"); + my_println!(" light_color: {light_color:?}"); + my_println!(" albedo: {albedo:?}"); + my_println!(" attenuation: {attenuation:?}"); + my_println!(" v: {v:?}"); + my_println!(" l: {l:?}"); + my_println!(" n: {n:?}"); + my_println!(" metalness: {metalness:?}"); + my_println!(" roughness: {roughness:?}"); + + let f0 = Vec3::splat(0.4).lerp(albedo, metalness); + my_println!(" f0: {f0:?}"); + let radiance = light_color.xyz() * attenuation; + my_println!(" radiance: {radiance:?}"); + let h = (v + l).alt_norm_or_zero(); + my_println!(" h: {h:?}"); + // cook-torrance brdf + let ndf: f32 = normal_distribution_ggx(n, h, roughness); + my_println!(" ndf: {ndf:?}"); + let g: f32 = geometry_smith(n, v, l, roughness); + my_println!(" g: {g:?}"); + let f: Vec3 = fresnel_schlick(h.dot(v).max(0.0), f0); + my_println!(" f: {f:?}"); + + let k_s = f; + let k_d = (Vec3::splat(1.0) - k_s) * (1.0 - metalness); + my_println!(" k_s: {k_s:?}"); + + let numerator: Vec3 = ndf * g * f; + my_println!(" numerator: {numerator:?}"); + let n_dot_l = n.dot(l).max(0.0); + my_println!(" n_dot_l: {n_dot_l:?}"); + let denominator: f32 = 4.0 * n.dot(v).max(0.0) * n_dot_l + 0.0001; + my_println!(" denominator: {denominator:?}"); + let specular: Vec3 = numerator / denominator; + my_println!(" specular: {specular:?}"); + + (k_d * albedo / core::f32::consts::PI + specular) * radiance * n_dot_l +} + +pub fn sample_irradiance, S: IsSampler>( + irradiance: &T, + irradiance_sampler: &S, + // Normal vector + n: Vec3, +) -> Vec3 { + irradiance.sample_by_lod(*irradiance_sampler, n, 0.0).xyz() +} + +pub fn sample_specular_reflection, S: IsSampler>( + prefiltered: &T, + prefiltered_sampler: &S, + // camera position in world space + camera_pos: Vec3, + // fragment position in world space + in_pos: Vec3, + // normal vector + n: Vec3, + roughness: f32, +) -> Vec3 { + let v = (camera_pos - in_pos).alt_norm_or_zero(); + let reflect_dir = math::reflect(-v, n); + prefiltered + .sample_by_lod(*prefiltered_sampler, reflect_dir, roughness * 4.0) + .xyz() +} + +/// Returns the `Material` from the stage's slab. +pub fn get_material( + material_id: Id, + has_lighting: bool, + material_slab: &[u32], +) -> MaterialDescriptor { + if material_id.is_none() { + // without an explicit material (or if the entire render has no lighting) + // the entity will not participate in any lighting calculations + MaterialDescriptor { + has_lighting: false, + ..Default::default() + } + } else { + let mut material = material_slab.read_unchecked(material_id); + material.has_lighting &= has_lighting; + material + } +} + +pub fn texture_color, S: IsSampler>( + texture_id: Id, + uv: Vec2, + atlas: &A, + sampler: &S, + atlas_size: glam::UVec2, + material_slab: &[u32], +) -> Vec4 { + let texture = material_slab.read(texture_id); + // uv is [0, 0] when texture_id is Id::NONE + let uv = texture.uv(uv, atlas_size); + crate::println!("uv: {uv}"); + let mut color: Vec4 = atlas.sample_by_lod(*sampler, uv, 0.0); + if texture_id.is_none() { + color = Vec4::splat(1.0); + } + color +} + +/// PBR fragment shader capable of being run on CPU or GPU. +#[allow(clippy::too_many_arguments)] +pub fn fragment_impl( + atlas: &A, + atlas_sampler: &S, + irradiance: &C, + irradiance_sampler: &S, + prefiltered: &C, + prefiltered_sampler: &S, + brdf: &T, + brdf_sampler: &S, + shadow_map: &DtA, + shadow_map_sampler: &S, + + geometry_slab: &[u32], + material_slab: &[u32], + lighting_slab: &[u32], + + renderlet_id: Id, + + frag_coord: Vec4, + in_color: Vec4, + in_uv0: Vec2, + in_uv1: Vec2, + in_norm: Vec3, + in_tangent: Vec3, + in_bitangent: Vec3, + in_pos: Vec3, + + output: &mut Vec4, +) where + A: Sample2dArray, + T: Sample2d, + DtA: Sample2dArray, + C: SampleCube, + S: IsSampler, +{ + let renderlet = geometry_slab.read_unchecked(renderlet_id); + let geom_desc = geometry_slab.read_unchecked(renderlet.geometry_descriptor_id); + crate::println!("pbr_desc_id: {:?}", renderlet.geometry_descriptor_id); + crate::println!("pbr_desc: {geom_desc:#?}"); + let GeometryDescriptor { + camera_id, + atlas_size, + resolution: _, + debug_channel, + has_lighting, + has_skinning: _, + perform_frustum_culling: _, + perform_occlusion_culling: _, + } = geom_desc; + + let material = get_material(renderlet.material_id, has_lighting, material_slab); + crate::println!("material: {:#?}", material); + + let albedo_tex_uv = if material.albedo_tex_coord == 0 { + in_uv0 + } else { + in_uv1 + }; + let albedo_tex_color = texture_color( + material.albedo_texture_id, + albedo_tex_uv, + atlas, + atlas_sampler, + atlas_size, + material_slab, + ); + my_println!("albedo_tex_color: {:?}", albedo_tex_color); + + let metallic_roughness_uv = if material.metallic_roughness_tex_coord == 0 { + in_uv0 + } else { + in_uv1 + }; + let metallic_roughness_tex_color = texture_color( + material.metallic_roughness_texture_id, + metallic_roughness_uv, + atlas, + atlas_sampler, + atlas_size, + material_slab, + ); + my_println!( + "metallic_roughness_tex_color: {:?}", + metallic_roughness_tex_color + ); + + let normal_tex_uv = if material.normal_tex_coord == 0 { + in_uv0 + } else { + in_uv1 + }; + let normal_tex_color = texture_color( + material.normal_texture_id, + normal_tex_uv, + atlas, + atlas_sampler, + atlas_size, + material_slab, + ); + my_println!("normal_tex_color: {:?}", normal_tex_color); + + let ao_tex_uv = if material.ao_tex_coord == 0 { + in_uv0 + } else { + in_uv1 + }; + let ao_tex_color = texture_color( + material.ao_texture_id, + ao_tex_uv, + atlas, + atlas_sampler, + atlas_size, + material_slab, + ); + + let emissive_tex_uv = if material.emissive_tex_coord == 0 { + in_uv0 + } else { + in_uv1 + }; + let emissive_tex_color = texture_color( + material.emissive_texture_id, + emissive_tex_uv, + atlas, + atlas_sampler, + atlas_size, + material_slab, + ); + + let (norm, uv_norm) = if material.normal_texture_id.is_none() { + // there is no normal map, use the normal normal ;) + (in_norm, Vec3::ZERO) + } else { + // convert the normal from color coords to tangent space -1,1 + let sampled_norm = (normal_tex_color.xyz() * 2.0 - Vec3::splat(1.0)).alt_norm_or_zero(); + let tbn = glam::mat3( + in_tangent.alt_norm_or_zero(), + in_bitangent.alt_norm_or_zero(), + in_norm.alt_norm_or_zero(), + ); + // convert the normal from tangent space to world space + let norm = (tbn * sampled_norm).alt_norm_or_zero(); + (norm, sampled_norm) + }; + + let n = norm; + let albedo = albedo_tex_color * material.albedo_factor * in_color; + let roughness = metallic_roughness_tex_color.y * material.roughness_factor; + let metallic = metallic_roughness_tex_color.z * material.metallic_factor; + let ao = 1.0 + material.ao_strength * (ao_tex_color.x - 1.0); + let emissive = + emissive_tex_color.xyz() * material.emissive_factor * material.emissive_strength_multiplier; + let irradiance = sample_irradiance(irradiance, irradiance_sampler, n); + let camera = geometry_slab.read(camera_id); + let specular = sample_specular_reflection( + prefiltered, + prefiltered_sampler, + camera.position(), + in_pos, + n, + roughness, + ); + let brdf = + brdf::shader::sample_brdf(brdf, brdf_sampler, camera.position(), in_pos, n, roughness); + + fn colorize(u: Vec3) -> Vec4 { + ((u.alt_norm_or_zero() + Vec3::splat(1.0)) / 2.0).extend(1.0) + } + + crate::println!("debug_mode: {debug_channel:?}"); + use debug::DebugChannel::*; + match debug_channel { + None => {} + UvCoords0 => { + *output = colorize(Vec3::new(in_uv0.x, in_uv0.y, 0.0)); + return; + } + UvCoords1 => { + *output = colorize(Vec3::new(in_uv1.x, in_uv1.y, 0.0)); + return; + } + Normals => { + *output = colorize(norm); + return; + } + VertexColor => { + *output = in_color; + return; + } + VertexNormals => { + *output = colorize(in_norm); + return; + } + UvNormals => { + *output = colorize(uv_norm); + return; + } + Tangents => { + *output = colorize(in_tangent); + return; + } + Bitangents => { + *output = colorize(in_bitangent); + return; + } + DiffuseIrradiance => { + *output = irradiance.extend(1.0); + return; + } + SpecularReflection => { + *output = specular.extend(1.0); + return; + } + Brdf => { + *output = brdf.extend(1.0).extend(1.0); + return; + } + Roughness => { + *output = Vec3::splat(roughness).extend(1.0); + return; + } + Metallic => { + *output = Vec3::splat(metallic).extend(1.0); + return; + } + Albedo => { + *output = albedo; + return; + } + Occlusion => { + *output = Vec3::splat(ao).extend(1.0); + return; + } + Emissive => { + *output = emissive.extend(1.0); + return; + } + UvEmissive => { + *output = emissive_tex_color.xyz().extend(1.0); + return; + } + EmissiveFactor => { + *output = material.emissive_factor.extend(1.0); + return; + } + EmissiveStrength => { + *output = Vec3::splat(material.emissive_strength_multiplier).extend(1.0); + return; + } + } + + *output = if material.has_lighting { + shade_fragment( + shadow_map, + shadow_map_sampler, + camera.position(), + n, + in_pos, + albedo.xyz(), + metallic, + roughness, + ao, + emissive, + irradiance, + specular, + brdf, + lighting_slab, + frag_coord, + ) + } else { + crate::println!("no shading!"); + in_color * albedo_tex_color * material.albedo_factor + }; +} + +#[allow(clippy::too_many_arguments)] +pub fn shade_fragment( + shadow_map: &T, + shadow_map_sampler: &S, + // camera's position in world space + camera_pos: Vec3, + // normal of the fragment + in_norm: Vec3, + // position of the fragment in world space + in_pos: Vec3, + // base color of the fragment + albedo: Vec3, + metallic: f32, + roughness: f32, + ao: f32, + emissive: Vec3, + irradiance: Vec3, + prefiltered: Vec3, + brdf: Vec2, + + light_slab: &[u32], + frag_coord: Vec4, +) -> Vec4 +where + S: IsSampler, + T: Sample2dArray, +{ + let n = in_norm.alt_norm_or_zero(); + let v = (camera_pos - in_pos).alt_norm_or_zero(); + // There is always a `LightingDescriptor` stored at index `0` of the + // light slab. + let lighting_desc = light_slab.read_unchecked(Id::::new(0)); + // If light tiling is enabled, use the pre-computed tile's light list + let analytical_lights_array = if lighting_desc.light_tiling_descriptor_id.is_none() { + lighting_desc.analytical_lights_array + } else { + let tiling_descriptor = light_slab.read_unchecked(lighting_desc.light_tiling_descriptor_id); + let tile_index = tiling_descriptor.tile_index_for_fragment(frag_coord.xy()); + let tile = light_slab.read_unchecked(tiling_descriptor.tiles_array.at(tile_index)); + tile.lights_array + }; + my_println!("lights: {analytical_lights_array:?}"); + my_println!("surface normal: {n:?}"); + my_println!("vector from surface to camera: {v:?}"); + + // accumulated outgoing radiance + let mut lo = Vec3::ZERO; + for light_id_id in analytical_lights_array.iter() { + // calculate per-light radiance + let light_id = light_slab.read(light_id_id); + if light_id.is_none() { + break; + } + let light = light_slab.read(light_id); + let transform = light_slab.read(light.transform_id); + crate::println!("transform: {transform:?}"); + let transform = Mat4::from(transform); + + // determine the light ray and the radiance + let (radiance, shadow) = match light.light_type { + LightStyle::Point => { + let PointLightDescriptor { + position, + color, + intensity, + } = light_slab.read(light.into_point_id()); + let position = transform.transform_point3(position); + // This definitely is the direction pointing from fragment to the light. + // It needs to stay this way. + // For more info, see + // + let frag_to_light = position - in_pos; + let distance = frag_to_light.length(); + if distance == 0.0 { + crate::println!("distance between point light and surface is zero"); + continue; + } + let l = frag_to_light.alt_norm_or_zero(); + let attenuation = intensity / (distance * distance); + let radiance = + outgoing_radiance(color, albedo, attenuation, v, l, n, metallic, roughness); + let shadow = if light.shadow_map_desc_id.is_some() { + // Shadow is 1.0 when the fragment is in the shadow of this light, + // and 0.0 in darkness + ShadowCalculation::new(light_slab, light, in_pos, n, l).run_point( + light_slab, + shadow_map, + shadow_map_sampler, + position, + ) + } else { + 0.0 + }; + (radiance, shadow) + } + + LightStyle::Spot => { + let spot_light_descriptor = light_slab.read(light.into_spot_id()); + let calculation = + SpotLightCalculation::new(spot_light_descriptor, transform, in_pos); + crate::println!("calculation: {calculation:#?}"); + if calculation.frag_to_light_distance == 0.0 { + continue; + } + let attenuation: f32 = spot_light_descriptor.intensity * calculation.contribution; + let radiance = outgoing_radiance( + spot_light_descriptor.color, + albedo, + attenuation, + v, + calculation.frag_to_light, + n, + metallic, + roughness, + ); + let shadow = if light.shadow_map_desc_id.is_some() { + // Shadow is 1.0 when the fragment is in the shadow of this light, + // and 0.0 in darkness + ShadowCalculation::new(light_slab, light, in_pos, n, calculation.frag_to_light) + .run_directional_or_spot(light_slab, shadow_map, shadow_map_sampler) + } else { + 0.0 + }; + (radiance, shadow) + } + + LightStyle::Directional => { + let DirectionalLightDescriptor { + direction, + color, + intensity, + } = light_slab.read(light.into_directional_id()); + let direction = transform.transform_vector3(direction); + let l = -direction.alt_norm_or_zero(); + let attenuation = intensity; + let radiance = + outgoing_radiance(color, albedo, attenuation, v, l, n, metallic, roughness); + let shadow = + if light.shadow_map_desc_id.is_some() { + // Shadow is 1.0 when the fragment is in the shadow of this light, + // and 0.0 in darkness + ShadowCalculation::new(light_slab, light, in_pos, n, l) + .run_directional_or_spot(light_slab, shadow_map, shadow_map_sampler) + } else { + 0.0 + }; + (radiance, shadow) + } + }; + crate::println!("radiance: {radiance}"); + crate::println!("shadow: {shadow}"); + lo += radiance * (1.0 - shadow); + } + + my_println!("lo: {lo:?}"); + // calculate reflectance at normal incidence; if dia-electric (like plastic) use + // F0 of 0.04 and if it's a metal, use the albedo color as F0 (metallic + // workflow) + let f0: Vec3 = Vec3::splat(0.04).lerp(albedo, metallic); + let cos_theta = n.dot(v).max(0.0); + let fresnel = fresnel_schlick_roughness(cos_theta, f0, roughness); + let ks = fresnel; + let kd = (1.0 - ks) * (1.0 - metallic); + let diffuse = irradiance * albedo; + let specular = prefiltered * (fresnel * brdf.x + brdf.y); + let color = (kd * diffuse + specular) * ao + lo + emissive; + color.extend(1.0) +} diff --git a/crates/renderling/src/primitive/shader.rs b/crates/renderling/src/primitive/shader.rs index 9aac4ae5..ef8a5c1b 100644 --- a/crates/renderling/src/primitive/shader.rs +++ b/crates/renderling/src/primitive/shader.rs @@ -270,7 +270,7 @@ pub fn primitive_fragment( output: &mut Vec4, ) { // proxy to a separate impl that allows us to test on CPU - crate::pbr::fragment_impl( + crate::pbr::shader::fragment_impl( atlas, atlas_sampler, irradiance, diff --git a/crates/renderling/src/skybox/cpu.rs b/crates/renderling/src/skybox/cpu.rs index 753f7e63..edbbfe02 100644 --- a/crates/renderling/src/skybox/cpu.rs +++ b/crates/renderling/src/skybox/cpu.rs @@ -1,15 +1,13 @@ //! CPU-side code for skybox rendering. -use craballoc::{ - prelude::{Hybrid, SlabAllocator}, - runtime::WgpuRuntime, -}; -use crabslab::Id; +use core::sync::atomic::AtomicBool; +use std::sync::Arc; + +use craballoc::{prelude::SlabAllocator, runtime::WgpuRuntime}; use glam::{Mat4, UVec2, Vec3}; use crate::{ atlas::AtlasImage, - camera::shader::CameraDescriptor, - convolution::VertexPrefilterEnvironmentCubemapIds, + camera::Camera, cubemap::EquirectangularImageToCubemapBlitter, texture::{self, Texture}, }; @@ -154,6 +152,7 @@ pub(crate) fn create_skybox_render_pipeline( /// A clone of a skybox is a reference to the same skybox. /// /// Only available on the CPU. Not available in shaders. +// TODO: make the Skybox API a builder // TODO: move brdf lut into Stage or Context, we only need one, ever // TODO: decouple Skybox and IBL // Skybox and IBL are different things. Sometimes you want to use a @@ -161,13 +160,9 @@ pub(crate) fn create_skybox_render_pipeline( // Also, the brdf_lut doesn't change, so should probably live in `Lighting` #[derive(Debug, Clone)] pub struct Skybox { + is_empty: Arc, // Cubemap texture of the environment cubemap environment_cubemap: Texture, - // Cubemap texture of the pre-computed irradiance cubemap - pub irradiance_cubemap: Texture, - // Cubemap texture and mip maps of the specular highlights, - // where each mip level is a different roughness. - pub prefiltered_environment_cubemap: Texture, } impl Skybox { @@ -181,7 +176,9 @@ impl Skybox { format: crate::atlas::AtlasImageFormat::R32G32B32A32FLOAT, apply_linear_transfer: false, }; - Self::new(runtime, hdr_img) + let s = Self::new(runtime, hdr_img); + s.is_empty.store(true, std::sync::atomic::Ordering::Relaxed); + s } /// Create a new `Skybox`. @@ -190,15 +187,8 @@ impl Skybox { log::trace!("creating skybox"); let slab = SlabAllocator::new(runtime, "skybox-slab", wgpu::BufferUsages::VERTEX); - let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1, 10.0); - let camera = slab.new_value(CameraDescriptor::default().with_projection(proj)); - let roughness = slab.new_value(0.0f32); - let prefilter_ids = slab.new_value(VertexPrefilterEnvironmentCubemapIds { - camera: camera.id(), - roughness: roughness.id(), - }); - + let camera = Camera::new(&slab).with_projection(proj); let buffer = slab.commit(); let mut buffer_upkeep = || { let possibly_new_buffer = slab.commit(); @@ -249,32 +239,9 @@ impl Skybox { views, ); - // Convolve the environment map. - let irradiance_cubemap = Skybox::create_irradiance_map( - runtime, - &buffer, - &mut buffer_upkeep, - &environment_cubemap, - &camera, - views, - ); - - // Generate specular IBL pre-filtered environment map. - let prefiltered_environment_cubemap = Skybox::create_prefiltered_environment_map( - runtime, - &buffer, - &mut buffer_upkeep, - &camera, - &roughness, - prefilter_ids.id(), - &environment_cubemap, - views, - ); - Skybox { + is_empty: Arc::new(false.into()), environment_cubemap, - irradiance_cubemap, - prefiltered_environment_cubemap, } } @@ -321,7 +288,7 @@ impl Skybox { buffer: &wgpu::Buffer, buffer_upkeep: impl FnMut(), hdr_texture: &Texture, - camera: &Hybrid, + camera: &Camera, views: [Mat4; 6], ) -> Texture { let runtime = runtime.as_ref(); @@ -344,7 +311,7 @@ impl Skybox { hdr_texture, ); - Self::render_cubemap( + texture::Texture::render_cubemap( runtime, &pipeline.0, buffer_upkeep, @@ -356,206 +323,9 @@ impl Skybox { ) } - #[allow(clippy::too_many_arguments)] - fn render_cubemap( - runtime: impl AsRef, - pipeline: &wgpu::RenderPipeline, - mut buffer_upkeep: impl FnMut(), - camera: &Hybrid, - bindgroup: &wgpu::BindGroup, - views: [Mat4; 6], - texture_size: u32, - mip_levels: Option, - ) -> Texture { - let runtime = runtime.as_ref(); - let device = &runtime.device; - let queue = &runtime.queue; - let mut cubemap_faces = Vec::new(); - let mip_levels = mip_levels.unwrap_or(1); - - // Render every cube face. - for (i, view) in views.iter().enumerate() { - let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some(&format!("cubemap{i}")), - }); - - let mut cubemap_face = Texture::new_with( - runtime, - Some(&format!("cubemap{i}")), - Some( - wgpu::TextureUsages::RENDER_ATTACHMENT - | wgpu::TextureUsages::COPY_SRC - | wgpu::TextureUsages::COPY_DST - | wgpu::TextureUsages::TEXTURE_BINDING, - ), - None, - wgpu::TextureFormat::Rgba16Float, - 4, - 2, - texture_size, - texture_size, - 1, - &[], - ); - - // update the view to point at one of the cube faces - camera.modify(|c| c.set_view(*view)); - buffer_upkeep(); - - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some(&format!("cubemap{i}")), - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &cubemap_face.view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), - store: wgpu::StoreOp::Store, - }, - depth_slice: None, - })], - depth_stencil_attachment: None, - ..Default::default() - }); - - render_pass.set_pipeline(pipeline); - render_pass.set_bind_group(0, Some(bindgroup), &[]); - render_pass.draw(0..36, 0..1); - } - - queue.submit([encoder.finish()]); - let mips = cubemap_face.generate_mips(runtime, Some("cubemap mips"), mip_levels); - cubemap_faces.push(cubemap_face); - cubemap_faces.extend(mips); - } - - Texture::new_cubemap_texture( - runtime, - Some("skybox cubemap"), - texture_size, - cubemap_faces.as_slice(), - wgpu::TextureFormat::Rgba16Float, - mip_levels, - ) - } - - fn create_irradiance_map( - runtime: impl AsRef, - buffer: &wgpu::Buffer, - buffer_upkeep: impl FnMut(), - environment_texture: &Texture, - camera: &Hybrid, - views: [Mat4; 6], - ) -> Texture { - let runtime = runtime.as_ref(); - let device = &runtime.device; - let pipeline = crate::pbr::ibl::DiffuseIrradianceConvolutionRenderPipeline::new( - device, - wgpu::TextureFormat::Rgba16Float, - ); - - let bindgroup = crate::pbr::ibl::diffuse_irradiance_convolution_bindgroup( - device, - Some("irradiance"), - buffer, - environment_texture, - ); - - Self::render_cubemap( - runtime, - &pipeline.0, - buffer_upkeep, - camera, - &bindgroup, - views, - 32, - None, - ) - } - - #[allow(clippy::too_many_arguments)] - fn create_prefiltered_environment_map( - runtime: impl AsRef, - buffer: &wgpu::Buffer, - mut buffer_upkeep: impl FnMut(), - camera: &Hybrid, - roughness: &Hybrid, - prefilter_id: Id, - environment_texture: &Texture, - views: [Mat4; 6], - ) -> Texture { - let (pipeline, bindgroup) = - crate::pbr::ibl::create_prefiltered_environment_pipeline_and_bindgroup( - &runtime.as_ref().device, - buffer, - environment_texture, - ); - let mut cubemap_faces = Vec::new(); - - for (i, view) in views.iter().enumerate() { - for mip_level in 0..5 { - let mip_width: u32 = 128 >> mip_level; - let mip_height: u32 = 128 >> mip_level; - - let mut encoder = runtime.as_ref().device.create_command_encoder( - &wgpu::CommandEncoderDescriptor { - label: Some("specular convolution"), - }, - ); - - let cubemap_face = Texture::new_with( - runtime.as_ref(), - Some(&format!("cubemap{i}{mip_level}prefiltered_environment")), - Some(wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC), - None, - wgpu::TextureFormat::Rgba16Float, - 4, - 2, - mip_width, - mip_height, - 1, - &[], - ); - - // update the roughness for these mips - roughness.set(mip_level as f32 / 4.0); - // update the view to point at one of the cube faces - camera.modify(|c| c.set_view(*view)); - buffer_upkeep(); - { - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: Some(&format!("cubemap{i}")), - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &cubemap_face.view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), - store: wgpu::StoreOp::Store, - }, - depth_slice: None, - })], - depth_stencil_attachment: None, - ..Default::default() - }); - - render_pass.set_pipeline(&pipeline); - render_pass.set_bind_group(0, Some(&bindgroup), &[]); - render_pass.draw(0..36, prefilter_id.inner()..prefilter_id.inner() + 1); - } - - runtime.as_ref().queue.submit([encoder.finish()]); - cubemap_faces.push(cubemap_face); - } - } - - Texture::new_cubemap_texture( - runtime, - Some("prefiltered environment cubemap"), - 128, - cubemap_faces.as_slice(), - wgpu::TextureFormat::Rgba16Float, - 5, - ) + /// Returns whether this skybox is empty. + pub fn is_empty(&self) -> bool { + self.is_empty.load(std::sync::atomic::Ordering::Relaxed) } } @@ -581,21 +351,21 @@ mod test { let skybox = stage .new_skybox_from_path("../../img/hdr/resting_place.hdr") .unwrap(); - + let ibl = stage.new_ibl(&skybox); assert_eq!( wgpu::TextureFormat::Rgba16Float, - skybox.irradiance_cubemap.texture.format() + ibl.irradiance_cubemap.texture.format() ); assert_eq!( wgpu::TextureFormat::Rgba16Float, - skybox.prefiltered_environment_cubemap.texture.format() + ibl.prefiltered_environment_cubemap.texture.format() ); for i in 0..6 { // save out the irradiance face let copied_buffer = CopiedTextureBuffer::read_from( &ctx, - &skybox.irradiance_cubemap.texture, + &ibl.irradiance_cubemap.texture, 32, 32, 4, @@ -618,7 +388,7 @@ mod test { // save out the prefiltered environment faces' mips let copied_buffer = CopiedTextureBuffer::read_from( &ctx, - &skybox.prefiltered_environment_cubemap.texture, + &ibl.prefiltered_environment_cubemap.texture, mip_size as usize, mip_size as usize, 4, @@ -643,7 +413,7 @@ mod test { } } - stage.set_skybox(skybox); + stage.use_skybox(&skybox); let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index 5cbf651d..7db97dd8 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -15,6 +15,7 @@ use crate::gltf::GltfDocument; use crate::light::{DirectionalLight, IsLight, Light, PointLight, SpotLight}; use crate::material::Material; use crate::pbr::brdf::BrdfLut; +use crate::pbr::ibl::Ibl; use crate::primitive::Primitive; use crate::{ atlas::{AtlasError, AtlasImage, AtlasImageError}, @@ -252,7 +253,7 @@ impl StageRendering<'_> { .get(should_invalidate_renderlet_bind_group, || { log::trace!("recreating renderlet bind group"); let atlas_texture = self.stage.materials.atlas().get_texture(); - let skybox = self.stage.skybox.read().unwrap(); + let ibl = self.stage.ibl.read().unwrap(); let shadow_map = self.stage.lighting.shadow_map_atlas.get_texture(); RenderletBindGroup { device: self.stage.device(), @@ -262,12 +263,10 @@ impl StageRendering<'_> { light_buffer: &commit_result.lighting_buffer, atlas_texture_view: &atlas_texture.view, atlas_texture_sampler: &atlas_texture.sampler, - irradiance_texture_view: &skybox.irradiance_cubemap.view, - irradiance_texture_sampler: &skybox.irradiance_cubemap.sampler, - prefiltered_texture_view: &skybox.prefiltered_environment_cubemap.view, - prefiltered_texture_sampler: &skybox - .prefiltered_environment_cubemap - .sampler, + irradiance_texture_view: &ibl.irradiance_cubemap.view, + irradiance_texture_sampler: &ibl.irradiance_cubemap.sampler, + prefiltered_texture_view: &ibl.prefiltered_environment_cubemap.view, + prefiltered_texture_sampler: &ibl.prefiltered_environment_cubemap.sampler, brdf_texture_view: &self.stage.brdf_lut.inner.view, brdf_texture_sampler: &self.stage.brdf_lut.inner.sampler, shadow_map_texture_view: &shadow_map.view, @@ -397,8 +396,11 @@ pub struct Stage { pub(crate) brdf_lut: BrdfLut, + pub(crate) ibl: Arc>, + pub(crate) skybox: Arc>, pub(crate) skybox_bindgroup: Arc>>>, + // TODO: remove Stage.has_skybox, replace with Skybox::is_empty pub(crate) has_skybox: Arc, pub(crate) has_bloom: Arc, @@ -728,6 +730,132 @@ impl Stage { } } +/// Skybox methods +impl Stage { + /// Return the cached skybox render pipeline, creating it if necessary. + fn get_skybox_pipeline_and_bindgroup( + &self, + geometry_slab_buffer: &wgpu::Buffer, + ) -> (Arc, Arc) { + let msaa_sample_count = self.msaa_sample_count.load(Ordering::Relaxed); + // UNWRAP: safe because we're only ever called from the render thread. + let mut pipeline_guard = self.skybox_pipeline.write().unwrap(); + let pipeline = if let Some(pipeline) = pipeline_guard.as_mut() { + if pipeline.msaa_sample_count() != msaa_sample_count { + *pipeline = Arc::new(crate::skybox::create_skybox_render_pipeline( + self.device(), + Texture::HDR_TEXTURE_FORMAT, + Some(msaa_sample_count), + )); + } + pipeline.clone() + } else { + let pipeline = Arc::new(crate::skybox::create_skybox_render_pipeline( + self.device(), + Texture::HDR_TEXTURE_FORMAT, + Some(msaa_sample_count), + )); + *pipeline_guard = Some(pipeline.clone()); + pipeline + }; + // UNWRAP: safe because we're only ever called from the render thread. + let mut bindgroup = self.skybox_bindgroup.lock().unwrap(); + let bindgroup = if let Some(bindgroup) = bindgroup.as_ref() { + bindgroup.clone() + } else { + let bg = Arc::new(crate::skybox::create_skybox_bindgroup( + self.device(), + geometry_slab_buffer, + self.skybox.read().unwrap().environment_cubemap_texture(), + )); + *bindgroup = Some(bg.clone()); + bg + }; + (pipeline, bindgroup) + } + + /// Used the given [`Skybox`]. + /// + /// To remove the currently used [`Skybox`], call [`Skybox::remove_skybox`]. + pub fn use_skybox(&self, skybox: &Skybox) -> &Self { + // UNWRAP: if we can't acquire the lock we want to panic. + let mut guard = self.skybox.write().unwrap(); + *guard = skybox.clone(); + self.has_skybox + .store(true, std::sync::atomic::Ordering::Relaxed); + *self.skybox_bindgroup.lock().unwrap() = None; + *self.textures_bindgroup.lock().unwrap() = None; + self + } + + /// Removes the currently used [`Skybox`]. + /// + /// Returns the currently used [`Skybox`], if any. + /// + /// After calling this the [`Stage`] will not render with any [`Skybox`], until + /// [`Skybox::use_skybox`] is called with another [`Skybox`]. + pub fn remove_skybox(&self) -> Option { + let mut guard = self.skybox.write().unwrap(); + if guard.is_empty() { + // Do nothing, the skybox is already empty + None + } else { + let skybox = guard.clone(); + *guard = Skybox::empty(self.runtime()); + Some(skybox) + } + } + + /// Returns a new [`Skybox`] using the HDR image at the given path, if possible. + /// + /// The returned [`Skybox`] must be **used** with [`Stage::use_skybox`]. + pub fn new_skybox_from_path( + &self, + path: impl AsRef, + ) -> Result { + let hdr = AtlasImage::from_hdr_path(path)?; + Ok(Skybox::new(self.runtime(), hdr)) + } + + /// Returns a new [`Skybox`] using the bytes of an HDR image, if possible. + /// + /// The returned [`Skybox`] must be **used** with [`Stage::use_skybox`]. + pub fn new_skybox_from_bytes(&self, bytes: &[u8]) -> Result { + let hdr = AtlasImage::from_hdr_bytes(bytes)?; + Ok(Skybox::new(self.runtime(), hdr)) + } +} + +/// Image based lighting methods +impl Stage { + /// Crate a new [`Ibl`] from the given [`Skybox`]. + pub fn new_ibl(&self, skybox: &Skybox) -> Ibl { + Ibl::new(self.runtime(), skybox) + } + + /// Use the given image based lighting. + /// + /// Use [`Stage::new_ibl`] to create a new [`Ibl`]. + pub fn use_ibl(&self, ibl: &Ibl) -> &Self { + let mut guard = self.ibl.write().unwrap(); + *guard = ibl.clone(); + self + } + + /// Remove the current image based lighting from the stage and return it, if any. + pub fn remove_ibl(&self) -> Option { + let mut guard = self.ibl.write().unwrap(); + if guard.is_empty() { + // Do nothing, we're already not using IBL + None + } else { + let ibl = guard.clone(); + *guard = Ibl::new(self.runtime(), &Skybox::empty(self.runtime())); + Some(ibl) + } + } +} + impl Stage { /// Returns the runtime. pub fn runtime(&self) -> &WgpuRuntime { @@ -1008,6 +1136,8 @@ impl Stage { let lighting = Lighting::new(stage_config.shadow_map_atlas_size, &geometry); let brdf_lut = BrdfLut::new(runtime); + let skybox = Skybox::empty(runtime); + let ibl = Ibl::new(runtime, &skybox); Self { materials, @@ -1026,7 +1156,8 @@ impl Stage { renderlet_bind_group: ManagedBindGroup::default(), renderlet_bind_group_created: Arc::new(0.into()), - skybox: Arc::new(RwLock::new(Skybox::empty(runtime))), + ibl: Arc::new(RwLock::new(ibl)), + skybox: Arc::new(RwLock::new(skybox)), skybox_bindgroup: Default::default(), skybox_pipeline: Default::default(), has_skybox: Arc::new(AtomicBool::new(false)), @@ -1283,17 +1414,6 @@ impl Stage { self } - /// Set the skybox. - pub fn set_skybox(&self, skybox: Skybox) { - // UNWRAP: if we can't acquire the lock we want to panic. - let mut guard = self.skybox.write().unwrap(); - *guard = skybox; - self.has_skybox - .store(true, std::sync::atomic::Ordering::Relaxed); - *self.skybox_bindgroup.lock().unwrap() = None; - *self.textures_bindgroup.lock().unwrap() = None; - } - /// Turn the bloom effect on or off. pub fn set_has_bloom(&self, has_bloom: bool) { self.has_bloom @@ -1333,48 +1453,6 @@ impl Stage { self } - /// Return the skybox render pipeline, creating it if necessary. - fn get_skybox_pipeline_and_bindgroup( - &self, - geometry_slab_buffer: &wgpu::Buffer, - ) -> (Arc, Arc) { - let msaa_sample_count = self.msaa_sample_count.load(Ordering::Relaxed); - // UNWRAP: safe because we're only ever called from the render thread. - let mut pipeline_guard = self.skybox_pipeline.write().unwrap(); - let pipeline = if let Some(pipeline) = pipeline_guard.as_mut() { - if pipeline.msaa_sample_count() != msaa_sample_count { - *pipeline = Arc::new(crate::skybox::create_skybox_render_pipeline( - self.device(), - Texture::HDR_TEXTURE_FORMAT, - Some(msaa_sample_count), - )); - } - pipeline.clone() - } else { - let pipeline = Arc::new(crate::skybox::create_skybox_render_pipeline( - self.device(), - Texture::HDR_TEXTURE_FORMAT, - Some(msaa_sample_count), - )); - *pipeline_guard = Some(pipeline.clone()); - pipeline - }; - // UNWRAP: safe because we're only ever called from the render thread. - let mut bindgroup = self.skybox_bindgroup.lock().unwrap(); - let bindgroup = if let Some(bindgroup) = bindgroup.as_ref() { - bindgroup.clone() - } else { - let bg = Arc::new(crate::skybox::create_skybox_bindgroup( - self.device(), - geometry_slab_buffer, - self.skybox.read().unwrap().environment_cubemap_texture(), - )); - *bindgroup = Some(bg.clone()); - bg - }; - (pipeline, bindgroup) - } - /// Adds a primitive to the internal list of renderlets to be drawn each /// frame. /// @@ -1415,19 +1493,6 @@ impl Stage { } } - pub fn new_skybox_from_path( - &self, - path: impl AsRef, - ) -> Result { - let hdr = AtlasImage::from_hdr_path(path)?; - Ok(Skybox::new(self.runtime(), hdr)) - } - - pub fn new_skybox_from_bytes(&self, bytes: &[u8]) -> Result { - let hdr = AtlasImage::from_hdr_bytes(bytes)?; - Ok(Skybox::new(self.runtime(), hdr)) - } - /// Create a new [`NestedTransform`]. pub fn new_nested_transform(&self) -> NestedTransform { NestedTransform::new(self.geometry.slab_allocator()) diff --git a/crates/renderling/src/texture.rs b/crates/renderling/src/texture.rs index 5832a870..c44a4806 100644 --- a/crates/renderling/src/texture.rs +++ b/crates/renderling/src/texture.rs @@ -6,7 +6,7 @@ use std::{ }; use craballoc::runtime::WgpuRuntime; -use glam::UVec2; +use glam::{Mat4, UVec2}; use image::{ load_from_memory, DynamicImage, GenericImage, GenericImageView, ImageBuffer, ImageError, Luma, PixelWithColorType, Rgba32FImage, @@ -14,7 +14,10 @@ use image::{ use mips::MipMapGenerator; use snafu::prelude::*; -use crate::atlas::{AtlasImage, AtlasImageFormat}; +use crate::{ + atlas::{AtlasImage, AtlasImageFormat}, + camera::Camera, +}; pub mod mips; @@ -713,6 +716,89 @@ impl Texture { id: get_next_texture_id(), } } + + #[allow(clippy::too_many_arguments)] + pub(crate) fn render_cubemap( + runtime: impl AsRef, + pipeline: &wgpu::RenderPipeline, + mut buffer_upkeep: impl FnMut(), + camera: &Camera, + bindgroup: &wgpu::BindGroup, + views: [Mat4; 6], + texture_size: u32, + mip_levels: Option, + ) -> Self { + let runtime = runtime.as_ref(); + let device = &runtime.device; + let queue = &runtime.queue; + let mut cubemap_faces = Vec::new(); + let mip_levels = mip_levels.unwrap_or(1); + + // Render every cube face. + for (i, view) in views.iter().enumerate() { + let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some(&format!("cubemap{i}")), + }); + + let mut cubemap_face = Texture::new_with( + runtime, + Some(&format!("cubemap{i}")), + Some( + wgpu::TextureUsages::RENDER_ATTACHMENT + | wgpu::TextureUsages::COPY_SRC + | wgpu::TextureUsages::COPY_DST + | wgpu::TextureUsages::TEXTURE_BINDING, + ), + None, + wgpu::TextureFormat::Rgba16Float, + 4, + 2, + texture_size, + texture_size, + 1, + &[], + ); + + // update the view to point at one of the cube faces + camera.set_view(*view); + buffer_upkeep(); + + { + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: Some(&format!("cubemap{i}")), + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &cubemap_face.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), + store: wgpu::StoreOp::Store, + }, + depth_slice: None, + })], + depth_stencil_attachment: None, + ..Default::default() + }); + + render_pass.set_pipeline(pipeline); + render_pass.set_bind_group(0, Some(bindgroup), &[]); + render_pass.draw(0..36, 0..1); + } + + queue.submit([encoder.finish()]); + let mips = cubemap_face.generate_mips(runtime, Some("cubemap mips"), mip_levels); + cubemap_faces.push(cubemap_face); + cubemap_faces.extend(mips); + } + + Texture::new_cubemap_texture( + runtime, + Some("skybox cubemap"), + texture_size, + cubemap_faces.as_slice(), + wgpu::TextureFormat::Rgba16Float, + mip_levels, + ) + } } pub async fn read_depth_texture_to_image( diff --git a/manual/src/assets/gltf-example.png b/manual/src/assets/gltf-example.png deleted file mode 100644 index a3aa105ba929a4b8d8b13c8e6862e40fef33f270..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12924 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 Vugf$7|Eol^Bt4h7E8*qB{{}}oLdyUE diff --git a/manual/src/assets/skybox.png b/manual/src/assets/skybox.png index 7617f3fec5541085a0afff8780c5ef6715b8b4c2..4081a39aab3165f25c351f88db235622ea790b1f 100644 GIT binary patch literal 99449 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

    50qmCtt0YcDI-_MA-meV+1G@*zg} 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�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

    AK

    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 ck$!lPUO4vN!^eM Date: Sat, 20 Sep 2025 14:36:36 +1200 Subject: [PATCH 25/31] fixed tests --- crates/examples/src/skybox.rs | 2 +- crates/renderling/Cargo.toml | 4 ++++ crates/renderling/src/bloom/cpu.rs | 2 ++ crates/renderling/src/lib.rs | 2 +- crates/renderling/src/pbr.rs | 4 +++- manual/src/SUMMARY.md | 2 +- manual/src/skybox.md | 6 ++++-- 7 files changed, 16 insertions(+), 6 deletions(-) diff --git a/crates/examples/src/skybox.rs b/crates/examples/src/skybox.rs index d2f85a06..c039c9b1 100644 --- a/crates/examples/src/skybox.rs +++ b/crates/examples/src/skybox.rs @@ -1,6 +1,6 @@ //! Skybox manual page. -use crate::{cwd_to_manual_assets_dir, test_output_dir, workspace_dir}; +use crate::{cwd_to_manual_assets_dir, workspace_dir}; #[tokio::test] async fn manual_skybox() { diff --git a/crates/renderling/Cargo.toml b/crates/renderling/Cargo.toml index f5b37fd8..8c9e6b81 100644 --- a/crates/renderling/Cargo.toml +++ b/crates/renderling/Cargo.toml @@ -104,6 +104,10 @@ glam = { workspace = true, features = ["std", "debug-glam-assert"] } metal = { workspace = true, optional = true } wgpu-core = { workspace = true, optional = true } +[target.'cfg(target_os = "macos")'.dev-dependencies] +metal.workspace = true +wgpu-core.workspace = true + [dev-dependencies.web-sys] workspace = true features = [ diff --git a/crates/renderling/src/bloom/cpu.rs b/crates/renderling/src/bloom/cpu.rs index 8191fe36..c81152a1 100644 --- a/crates/renderling/src/bloom/cpu.rs +++ b/crates/renderling/src/bloom/cpu.rs @@ -762,6 +762,8 @@ mod test { .new_skybox_from_path("../../img/hdr/night.hdr") .unwrap(); stage.use_skybox(&skybox); + let ibl = stage.new_ibl(&skybox); + stage.use_ibl(&ibl); let _doc = stage .load_gltf_document_from_path("../../gltf/EmissiveStrengthTest.glb") diff --git a/crates/renderling/src/lib.rs b/crates/renderling/src/lib.rs index e8c277ca..472dff5a 100644 --- a/crates/renderling/src/lib.rs +++ b/crates/renderling/src/lib.rs @@ -252,7 +252,7 @@ macro_rules! println { } } -#[cfg(all(cpu, feature = "test-utils"))] +#[cfg(all(cpu, any(test, feature = "test-utils")))] #[allow(unused, reason = "Used in debugging on macos")] pub fn capture_gpu_frame( ctx: &crate::context::Context, diff --git a/crates/renderling/src/pbr.rs b/crates/renderling/src/pbr.rs index 875e4fed..5c3b3543 100644 --- a/crates/renderling/src/pbr.rs +++ b/crates/renderling/src/pbr.rs @@ -17,7 +17,6 @@ mod test { atlas::AtlasImage, geometry::Vertex, glam::{Vec3, Vec4}, - pbr::brdf::BrdfLut, test::BlockOnFuture, }; @@ -102,6 +101,9 @@ mod test { let skybox = crate::skybox::Skybox::new(&ctx, hdr_image); stage.use_skybox(&skybox); + let ibl = stage.new_ibl(&skybox); + stage.use_ibl(&ibl); + let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); let img = frame.read_image().block().unwrap(); diff --git a/manual/src/SUMMARY.md b/manual/src/SUMMARY.md index dab7eaa7..58c7ae85 100644 --- a/manual/src/SUMMARY.md +++ b/manual/src/SUMMARY.md @@ -5,4 +5,4 @@ - [Context creation](./context.md) - [Staging resources](./stage.md) - [Loading GLTF files](./gltf.md) -- [Skybox](./skybox.md) +- [Rendering with a skybox](./skybox.md) diff --git a/manual/src/skybox.md b/manual/src/skybox.md index 372c5ded..8b05374b 100644 --- a/manual/src/skybox.md +++ b/manual/src/skybox.md @@ -1,10 +1,12 @@ -# Skybox 🌌 +# Rendering a skybox 🌌 One of the most striking effects we can provide is a [skybox](https://en.wikipedia.org/wiki/Skybox_(video_games)). Using a skybox is an easy way to improve immersion, and with -`renderling` your skyboxes also illuminate the scene. +`renderling` your skyboxes can also illuminate the scene, but +we'll save that for a later example. For now let's set up +simple skybox for our marble bust scene. ## Building on the stage example From 1397dda3f2b621329608f2b62857f6ce39dc01e7 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 15:03:06 +1200 Subject: [PATCH 26/31] manual: lighting stubs --- crates/renderling/src/atlas/cpu.rs | 6 +++--- manual/src/SUMMARY.md | 3 +++ manual/src/lighting.md | 13 +++++++++++++ manual/src/lighting/analytical.md | 3 +++ manual/src/lighting/ibl.md | 3 +++ 5 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 manual/src/lighting.md create mode 100644 manual/src/lighting/analytical.md create mode 100644 manual/src/lighting/ibl.md diff --git a/crates/renderling/src/atlas/cpu.rs b/crates/renderling/src/atlas/cpu.rs index b1f138fc..7ec71622 100644 --- a/crates/renderling/src/atlas/cpu.rs +++ b/crates/renderling/src/atlas/cpu.rs @@ -561,7 +561,7 @@ impl Atlas { updates: impl IntoIterator, ) -> Result { let updates = updates.into_iter().collect::>(); - let op = AtlasBlittingOperation::new(&self.blitter, &self, updates.len()); + let op = AtlasBlittingOperation::new(&self.blitter, self, updates.len()); let runtime = self.slab.runtime(); let mut encoder = runtime .device @@ -570,11 +570,11 @@ impl Atlas { }); for (i, (atlas_texture, source_texture)) in updates.into_iter().enumerate() { op.run( - &runtime, + runtime, &mut encoder, source_texture, i as u32, - &self, + self, atlas_texture, )?; } diff --git a/manual/src/SUMMARY.md b/manual/src/SUMMARY.md index 58c7ae85..b1f1b29d 100644 --- a/manual/src/SUMMARY.md +++ b/manual/src/SUMMARY.md @@ -6,3 +6,6 @@ - [Staging resources](./stage.md) - [Loading GLTF files](./gltf.md) - [Rendering with a skybox](./skybox.md) +- [Lighting](./lighting.md) + - [Analytical lights](./lighting/analytical.md) + - [Image based lighting](./lighting/ibl.md) diff --git a/manual/src/lighting.md b/manual/src/lighting.md new file mode 100644 index 00000000..1e0b6286 --- /dev/null +++ b/manual/src/lighting.md @@ -0,0 +1,13 @@ +# Lighting 💡 + +Lighting in `renderling` comes in a few flavors: + +1. Unlit +2. Analytical lights + * directional + * point + * spot +3. Image based lighting + +We've already used the "unlit" method of turning off all lighting on the stage. +Now let's learn about analytical lights, and then image based lighting. diff --git a/manual/src/lighting/analytical.md b/manual/src/lighting/analytical.md new file mode 100644 index 00000000..818aa0b0 --- /dev/null +++ b/manual/src/lighting/analytical.md @@ -0,0 +1,3 @@ +# Analytical lights + +TODO diff --git a/manual/src/lighting/ibl.md b/manual/src/lighting/ibl.md new file mode 100644 index 00000000..06422137 --- /dev/null +++ b/manual/src/lighting/ibl.md @@ -0,0 +1,3 @@ +# Image based lighting + +TODO From a34e92ac4227bf134ef4f4d59f6049b43ba257eb Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 15:15:10 +1200 Subject: [PATCH 27/31] remove done todos --- crates/renderling/src/pbr/ibl/cpu.rs | 14 +++----------- crates/renderling/src/primitive/cpu.rs | 2 -- crates/renderling/src/skybox/cpu.rs | 16 +++++++--------- 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/crates/renderling/src/pbr/ibl/cpu.rs b/crates/renderling/src/pbr/ibl/cpu.rs index 921861fa..c79e0002 100644 --- a/crates/renderling/src/pbr/ibl/cpu.rs +++ b/crates/renderling/src/pbr/ibl/cpu.rs @@ -494,22 +494,16 @@ pub struct DiffuseIrradianceConvolutionRenderPipeline(pub wgpu::RenderPipeline); impl DiffuseIrradianceConvolutionRenderPipeline { /// Create the rendering pipeline that performs a convolution. pub fn new(device: &wgpu::Device, format: wgpu::TextureFormat) -> Self { - log::trace!("creating convolution render pipeline with format '{format:?}'"); let vertex_linkage = crate::linkage::skybox_cubemap_vertex::linkage(device); let fragment_linkage = crate::linkage::di_convolution_fragment::linkage(device); - // let fragment_shader = device.create_shader_module(wgpu::include_wgsl!( - // // TODO: rewrite this shader in Rust after atomics are added to naga spv - // "../../wgsl/diffuse_irradiance_convolution.wgsl" - // )); - log::trace!(" done."); let bg_layout = diffuse_irradiance_convolution_bindgroup_layout(device); let pp_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("convolution pipeline layout"), bind_group_layouts: &[&bg_layout], push_constant_ranges: &[], }); - // TODO: merge irradiance pipeline with cubemap - let pipeline = DiffuseIrradianceConvolutionRenderPipeline(device.create_render_pipeline( + + DiffuseIrradianceConvolutionRenderPipeline(device.create_render_pipeline( &wgpu::RenderPipelineDescriptor { label: Some("convolution pipeline"), layout: Some(&pp_layout), @@ -547,8 +541,6 @@ impl DiffuseIrradianceConvolutionRenderPipeline { multiview: None, cache: None, }, - )); - log::trace!(" completed pipeline creation"); - pipeline + )) } } diff --git a/crates/renderling/src/primitive/cpu.rs b/crates/renderling/src/primitive/cpu.rs index 15b03dbb..b154f802 100644 --- a/crates/renderling/src/primitive/cpu.rs +++ b/crates/renderling/src/primitive/cpu.rs @@ -210,7 +210,6 @@ impl Primitive { /// Get the transform. /// /// Returns a reference to the current `Transform`, if any. - // TODO: see if we really need to provide this. pub fn transform(&self) -> impl Deref> + '_ { self.transform.lock().unwrap() } @@ -244,7 +243,6 @@ impl Primitive { /// Get the material. /// /// Returns a reference to the current `Material`, if any. - // TODO: see if we really need to provide this. pub fn material(&self) -> impl Deref> + '_ { self.material.lock().unwrap() } diff --git a/crates/renderling/src/skybox/cpu.rs b/crates/renderling/src/skybox/cpu.rs index edbbfe02..7f64cb55 100644 --- a/crates/renderling/src/skybox/cpu.rs +++ b/crates/renderling/src/skybox/cpu.rs @@ -147,17 +147,15 @@ pub(crate) fn create_skybox_render_pipeline( } } -/// An HDR skybox that also provides IBL cubemaps and lookups. +/// An HDR skybox. /// -/// A clone of a skybox is a reference to the same skybox. +/// Skyboxes provide an environment cubemap around all your scenery +/// that acts as a background. /// -/// Only available on the CPU. Not available in shaders. -// TODO: make the Skybox API a builder -// TODO: move brdf lut into Stage or Context, we only need one, ever -// TODO: decouple Skybox and IBL -// Skybox and IBL are different things. Sometimes you want to use a -// skybox without having it shade things. -// Also, the brdf_lut doesn't change, so should probably live in `Lighting` +/// A [`Skybox`] can also be used to create [`Ibl`], which illuminates +/// your scene using the environment map as a light source. +/// +/// All clones of a skybox point to the same underlying data. #[derive(Debug, Clone)] pub struct Skybox { is_empty: Arc, From e3afa58b480f01b909e9ea62764e222e5d19edff Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 15:18:20 +1200 Subject: [PATCH 28/31] workflows: bump cargo gpu --- .github/workflows/push.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 94801214..a4899f37 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -10,7 +10,7 @@ on: env: # For setup-rust, see https://github.com/moonrepo/setup-rust/issues/22 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CARGO_GPU_COMMITSH: 39b238f25b7652ba79d153626e252321942cb558 + CARGO_GPU_COMMITSH: e3c0cd135f90e3f9a1706b4e6bddcb1bd00444cf jobs: # Installs cargo deps and sets the cache directory for subsequent jobs From 0da890aacb8af62670958a0ea218b6c1d6ac0849 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 15:32:16 +1200 Subject: [PATCH 29/31] update example-culling to new API --- Cargo.lock | 16 ++++++++++++++-- Cargo.toml | 4 ++-- crates/example-culling/src/main.rs | 10 +++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55c64253..2750aed1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1174,6 +1174,18 @@ dependencies = [ "winit", ] +[[package]] +name = "example-culling" +version = "0.1.0" +dependencies = [ + "env_logger", + "example", + "fastrand 2.3.0", + "log", + "renderling", + "winit", +] + [[package]] name = "examples" version = "0.1.0" @@ -5673,9 +5685,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winit" -version = "0.30.11" +version = "0.30.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4409c10174df8779dc29a4788cac85ed84024ccbc1743b776b21a520ee1aaf4" +checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" dependencies = [ "ahash", "android-activity", diff --git a/Cargo.toml b/Cargo.toml index ad4db4b8..dc2adaf0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ members = [ "crates/example", "crates/examples", - #"crates/example-culling", + "crates/example-culling", #"crates/example-wasm", "crates/loading-bytes", "crates/renderling", @@ -60,7 +60,7 @@ wasm-bindgen = "0.2" wasm-bindgen-futures = "0.4" wasm-bindgen-test = "0.3" web-sys = "0.3" -winit = { version = "0.30" } +winit = { version = "0.30.12" } wgpu = { version = "26.0" } wgpu-core = { version = "26.0" } metal = "0.32" diff --git a/crates/example-culling/src/main.rs b/crates/example-culling/src/main.rs index 1121eb2b..7d927667 100644 --- a/crates/example-culling/src/main.rs +++ b/crates/example-culling/src/main.rs @@ -3,15 +3,15 @@ use std::sync::Arc; use example::{camera::CameraController, utils::*}; -use glam::*; use renderling::{ bvol::{Aabb, BoundingSphere}, camera::{shader::CameraDescriptor, Camera}, + context::Context, geometry::Vertex, + glam::{EulerRot, Mat4, Quat, UVec2, Vec3, Vec4}, light::{AnalyticalLight, DirectionalLight}, material::Material, math::hex_to_vec4, - prelude::*, primitive::Primitive, stage::Stage, tonemapping::srgba_to_linear, @@ -137,7 +137,11 @@ impl ApplicationHandler for CullingExample { .. } => { if c.as_str() == "r" { - self.primitives.drain(..); + // remove all the primitives, dropping their resources + for primitive in self.primitives.drain(..) { + self.stage.remove_primitive(&primitive); + } + let _ = self.stage.commit(); self.primitives.extend(Self::make_aabbs( self.next_k, From 3191a5e9bbc6c0bb8417e55eff2667867dc43917 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sat, 20 Sep 2025 15:49:07 +1200 Subject: [PATCH 30/31] workflow: bump cargo gpu to bugfix rev --- .github/workflows/push.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index a4899f37..563f126d 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -10,7 +10,7 @@ on: env: # For setup-rust, see https://github.com/moonrepo/setup-rust/issues/22 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CARGO_GPU_COMMITSH: e3c0cd135f90e3f9a1706b4e6bddcb1bd00444cf + CARGO_GPU_COMMITSH: 31153a8edd3bc626d4b9fb0cd7bdb7a8b30797d3 jobs: # Installs cargo deps and sets the cache directory for subsequent jobs From 10ec7567c133ccafc98e4210cf0146da1d7ca53f Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Sun, 21 Sep 2025 10:55:02 +1200 Subject: [PATCH 31/31] xtask: manual has configurable docs url --- crates/xtask/src/main.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 157cfd4c..30c48cdc 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -47,6 +47,10 @@ pub struct Manual { #[clap(long)] no_test: bool, + /// The URL to the renderling docs + #[clap(long, default_value = "http://localhost:4000")] + docs_url: String, + /// Serve the manual instead of simply building it #[clap(long)] serve: bool, @@ -155,6 +159,7 @@ async fn main() { Command::Manual(Manual { no_build_docs, no_test, + docs_url, serve, }) => { log::info!("checking dependencies for the manual"); @@ -177,7 +182,7 @@ async fn main() { .current_dir( std::path::PathBuf::from(env!("CARGO_WORKSPACE_DIR")).join("manual"), ) - .env("DOCS_URL", "http://localhost:4000") + .env("DOCS_URL", docs_url) .spawn() .unwrap(); let build_status = build.wait().await.unwrap(); @@ -189,7 +194,7 @@ async fn main() { let mut build = tokio::process::Command::new("mdbook") .arg("build") - .env("DOCS_URL", "http://docs.rs/renderling/latest") + .env("DOCS_URL", docs_url) .current_dir( std::path::PathBuf::from(env!("CARGO_WORKSPACE_DIR")).join("manual"), )

    _u(8Agm%>xbSI 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 diff --git a/manual/src/gltf.md b/manual/src/gltf.md index ba6d493d..1c2eea3f 100644 --- a/manual/src/gltf.md +++ b/manual/src/gltf.md @@ -1,4 +1,4 @@ -# GLTF +# Loading GLTF files 📂 `renderling`'s built-in model format is [GLTF](https://www.khronos.org/gltf/), a versatile and efficient format for transmitting 3D models. GLTF, which stands @@ -47,7 +47,7 @@ unload the mesh geometry from the CPU. ## Result -![a loaded GLTF file, Fox, in shadow](assets/gltf-example-shadow.png) +![a loaded GLTF file, a marble bust, in shadow](assets/gltf-example-shadow.png) But wait! It's all in shadow. @@ -63,7 +63,7 @@ For now we'll go with option `1`, as lighting happens in a later section: {{#include ../../crates/examples/src/gltf.rs:no_lights}} ``` -![a loaded GLTF file, Fox, unlit](assets/gltf-example-unlit.png) +![a loaded GLTF file, a marble bust, unlit](assets/gltf-example-unlit.png) [`Context`]: {{DOCS_URL}}/renderling/context/struct.Context.html [`Stage`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html diff --git a/manual/src/setup.md b/manual/src/setup.md index a81ed6c4..d628da42 100644 --- a/manual/src/setup.md +++ b/manual/src/setup.md @@ -20,7 +20,7 @@ section of our `Cargo.toml`: ```toml [patch.crates-io] -spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "425328a" } +spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "de03e8d" } ``` This is a temporary workaround that will be resolved after the next Rust-GPU diff --git a/manual/src/skybox.md b/manual/src/skybox.md index 65f6ad61..372c5ded 100644 --- a/manual/src/skybox.md +++ b/manual/src/skybox.md @@ -9,33 +9,25 @@ Using a skybox is an easy way to improve immersion, and with ## Building on the stage example We'll start out this example by extending the example from the -[stage](./stage). In that example we created a cube with colored -vertices: +[loading GLTF files](./gltf) section. In that example we loaded +a model of an old marble bust: ```rust,ignore {{#include ../../crates/examples/src/skybox.rs:setup}} ``` -Then we rendered: - -```rust,ignore -{{#include ../../crates/examples/src/skybox.rs:render_cube}} -``` - -Which gave us this scene: - -![image of a unit cube with colored vertices](assets/stage-example.png) +![image of a marble bust](assets/gltf-example-unlit.png) ## Adding the skybox In `renderling`, skyboxes get their background from an "HDR" image. These are typically large three dimensional images. You can find -free HDR images [here](https://polyhaven.com/hdris) and other +free HDR images [at PolyHaven](https://polyhaven.com/hdris) and other places around the web. For this example we'll be using this HDR: -![Qwantani Dusk 2 (Pure Sky)](assets/qwantani_dusk_2_puresky.webp) +![Rooftop helipad](assets/helipad.jpg) ```rust,ignore {{#include ../../crates/examples/src/skybox.rs:skybox}} diff --git a/manual/src/stage.md b/manual/src/stage.md index 563cbf6a..9d06a2c7 100644 --- a/manual/src/stage.md +++ b/manual/src/stage.md @@ -1,23 +1,25 @@ -# Stage +# Staging resources 🎭 The [`Stage`] is the most important type in `renderling`. It's responsible for staging all your scene's data on the GPU, as well as linking all the various effects together and rendering it all. -- [Stage](#stage) - - [Stage creation](#stage-creation) - - [Resource creation](#resource-creation) - - [Camera](#camera) - - [glam and re-exports](#glam-and-re-exports) - - [Creation](#creation) - - [Geometry](#geometry) - - [Material](#material) - - [Primitive](#primitive) - - [Rendering](#rendering) - - [Results](#results) +- [Stage creation](#stage-creation) +- [Resource creation](#resource-creation) + - [Camera](#camera) + - [glam and re-exports](#glam-and-re-exports) + - [Creation](#creation) + - [Geometry](#geometry) + - [Material](#material) + - [Primitive](#primitive) +- [Rendering](#rendering) +- [Results](#results) +- [Removing resources](#removing-resources) +- [Visibility](#visibility) + ## Stage creation The `Stage` is created with [`Context::new_stage`]. @@ -174,10 +176,21 @@ Now let's remove the cube primitive, drop the other resources, and render again: {{#include ../../crates/examples/src/stage.rs:removal}} ``` +![the cube is gone](assets/stage-example-gone.png) + +## Visibility + +If instead we wanted to keep the resources around but make the [`Primitive`] invisible, +we could have used [`Primitive::set_visible`]. + +See the [`Stage`] and [`Primitive`] docs for more info. + [`Stage`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html [`Stage::new_camera`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html#method.new_camera +[`Stage::remove_primitive`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html#method.remove_primitive [`Context::new_stage`]: {{DOCS_URL}}/renderling/context/struct.Context.html#method.new_stage [`Primitive`]: {{DOCS_URL}}/renderling/primitive/struct.Primitive.html +[`Primitive::set_visible`]: {{DOCS_URL}}/renderling/primitive/struct.Primitive.html#method.set_visible [`Camera`]: {{DOCS_URL}}/renderling/camera/struct.Camera.html [`Camera::with_default_perspective`]: {{DOCS_URL}}/renderling/camera/struct.Camera.html#method.with_default_perspective [`Vertices`]: {{DOCS_URL}}/renderling/geometry/struct.Vertices.html From 1cdeeb925c203912215dd163d3bf20ecc2a93fc1 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Fri, 19 Sep 2025 11:40:57 +1200 Subject: [PATCH 18/31] move skybox shader stuff to a shader module --- Cargo.lock | 6 +- Cargo.toml | 6 +- .../atlas-shader-atlas_blit_vertex.spv | Bin 6220 -> 6220 bytes .../shaders/bloom-shader-bloom_vertex.spv | Bin 1344 -> 1344 bytes ...onvolution-brdf_lut_convolution_vertex.spv | Bin 1420 -> 1420 bytes .../convolution-generate_mipmap_vertex.spv | Bin 1204 -> 1204 bytes ...n-prefilter_environment_cubemap_vertex.spv | Bin 13488 -> 13488 bytes ...ap-shader-cubemap_sampling_test_vertex.spv | Bin 1100 -> 1100 bytes .../shaders/cull-shader-compute_culling.spv | Bin 27844 -> 27844 bytes .../debug-shader-debug_overlay_fragment.spv | Bin 21284 -> 21284 bytes .../debug-shader-debug_overlay_vertex.spv | Bin 832 -> 832 bytes .../light-shader-light_tiling_bin_lights.spv | Bin 0 -> 26656 bytes .../light-shader-light_tiling_clear_tiles.spv | Bin 0 -> 4576 bytes ..._tiling_compute_tile_min_and_max_depth.spv | Bin 0 -> 3976 bytes ...te_tile_min_and_max_depth_multisampled.spv | Bin 0 -> 3988 bytes ...ght-shader-light_tiling_depth_pre_pass.spv | Bin 0 -> 35804 bytes .../light-shader-shadow_mapping_fragment.spv | Bin 0 -> 512 bytes .../light-shader-shadow_mapping_vertex.spv | Bin 0 -> 32528 bytes crates/renderling/shaders/manifest.json | 66 ++++++------- .../primitive-shader-primitive_fragment.spv | Bin 108064 -> 108064 bytes .../primitive-shader-primitive_vertex.spv | Bin 44156 -> 44156 bytes .../skybox-shader-skybox_cubemap_fragment.spv | Bin 0 -> 1124 bytes .../skybox-shader-skybox_cubemap_vertex.spv | Bin 0 -> 12656 bytes ...shader-skybox_equirectangular_fragment.spv | Bin 0 -> 1408 bytes .../shaders/skybox-shader-skybox_vertex.spv | Bin 0 -> 10948 bytes .../tonemapping-tonemapping_vertex.spv | Bin 1180 -> 1180 bytes .../shaders/tutorial-slabbed_renderlet.spv | Bin 44200 -> 44200 bytes .../src/linkage/light_tiling_bin_lights.rs | 8 +- .../src/linkage/light_tiling_clear_tiles.rs | 8 +- ...t_tiling_compute_tile_min_and_max_depth.rs | 12 ++- ...ute_tile_min_and_max_depth_multisampled.rs | 14 ++- .../linkage/light_tiling_depth_pre_pass.rs | 8 +- .../src/linkage/shadow_mapping_fragment.rs | 8 +- .../src/linkage/shadow_mapping_vertex.rs | 8 +- .../src/linkage/skybox_cubemap_fragment.rs | 8 +- .../src/linkage/skybox_cubemap_vertex.rs | 8 +- .../skybox_equirectangular_fragment.rs | 8 +- .../renderling/src/linkage/skybox_vertex.rs | 8 +- crates/renderling/src/skybox.rs | 92 +----------------- crates/renderling/src/skybox/shader.rs | 91 +++++++++++++++++ 40 files changed, 182 insertions(+), 177 deletions(-) create mode 100644 crates/renderling/shaders/light-shader-light_tiling_bin_lights.spv create mode 100644 crates/renderling/shaders/light-shader-light_tiling_clear_tiles.spv create mode 100644 crates/renderling/shaders/light-shader-light_tiling_compute_tile_min_and_max_depth.spv create mode 100644 crates/renderling/shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.spv create mode 100644 crates/renderling/shaders/light-shader-light_tiling_depth_pre_pass.spv create mode 100644 crates/renderling/shaders/light-shader-shadow_mapping_fragment.spv create mode 100644 crates/renderling/shaders/light-shader-shadow_mapping_vertex.spv create mode 100644 crates/renderling/shaders/skybox-shader-skybox_cubemap_fragment.spv create mode 100644 crates/renderling/shaders/skybox-shader-skybox_cubemap_vertex.spv create mode 100644 crates/renderling/shaders/skybox-shader-skybox_equirectangular_fragment.spv create mode 100644 crates/renderling/shaders/skybox-shader-skybox_vertex.spv create mode 100644 crates/renderling/src/skybox/shader.rs diff --git a/Cargo.lock b/Cargo.lock index 63fca90f..d05e257b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4220,7 +4220,7 @@ dependencies = [ [[package]] name = "spirv-std" version = "0.9.0" -source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=de03e8d#de03e8d8c997c68aed1a950863c0d79ba9bd8c72" +source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=05b34493ce661dccd6694cf58afc13e3c8f7a7e0#05b34493ce661dccd6694cf58afc13e3c8f7a7e0" dependencies = [ "bitflags 1.3.2", "glam", @@ -4233,7 +4233,7 @@ dependencies = [ [[package]] name = "spirv-std-macros" version = "0.9.0" -source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=de03e8d#de03e8d8c997c68aed1a950863c0d79ba9bd8c72" +source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=05b34493ce661dccd6694cf58afc13e3c8f7a7e0#05b34493ce661dccd6694cf58afc13e3c8f7a7e0" dependencies = [ "proc-macro2", "quote", @@ -4244,7 +4244,7 @@ dependencies = [ [[package]] name = "spirv-std-types" version = "0.9.0" -source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=de03e8d#de03e8d8c997c68aed1a950863c0d79ba9bd8c72" +source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=05b34493ce661dccd6694cf58afc13e3c8f7a7e0#05b34493ce661dccd6694cf58afc13e3c8f7a7e0" [[package]] name = "stable_deref_trait" diff --git a/Cargo.toml b/Cargo.toml index 5f947154..ad4db4b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,8 +51,8 @@ serde_json = "1.0.117" send_wrapper = "0.6.0" similarity = "0.2.0" snafu = "0.8" -spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "de03e8d" } -spirv-std-macros = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "de03e8d" } +spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "05b34493ce661dccd6694cf58afc13e3c8f7a7e0" } +spirv-std-macros = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "05b34493ce661dccd6694cf58afc13e3c8f7a7e0" } syn = { version = "2.0.49", features = ["full", "extra-traits", "parsing"] } tokio = "1.47.1" tracing = "0.1.41" @@ -75,4 +75,4 @@ opt-level = 3 opt-level = 3 [patch.crates-io] -spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "de03e8d" } +spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "05b34493ce661dccd6694cf58afc13e3c8f7a7e0" } diff --git a/crates/renderling/shaders/atlas-shader-atlas_blit_vertex.spv b/crates/renderling/shaders/atlas-shader-atlas_blit_vertex.spv index 45f710aff724a52b60599633f22d17c7012ef787..ae3e85f7a7d2688e31c9d7df02e9617340883e8c 100644 GIT binary patch literal 6220 zcmZvf3#`{=8OMKzBOD1*@~(mXkH=KtfH%+pm5T$^$jfY|Q-`SJWoQkKbW=IX)Jmh( zYGLzoR%*+YQdwq8u(q0%cCWRrYis3gZI%d1aQb|H|My$3tap2OZr|s5pXYhs-}~qE zjv44{#`ZK#vv1RkfwA6#phf~zU}J-Z00nFF_JiK2Qar2;m%?f++MB0UY);lvtRwQ;r8WB)7#0&J(WHO+4D

  • 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�o$ajZcJOoecSm|z_mBX=T(1K#P`ZbZ(T#cZ5Q57E7|4!}9)nlF z@BrxEs~dqUKnL&@1mg;Z#eqN-)CO}k->A+%8pMHcfsMb$ zg02t%{%>6BE!~Km?P2r5GZus8S%-EI8wE=qexuq+5=c#Qk^qm^qyRiy3{N!>5J07^ z&6uu~`U6nMRE}-Q;3C^H2v@6KdHH4T7(9pL0QKttCI(dYfUo)I8)69rR15^rKnAR0 zAM~TkKmeWuF2I8%IQ2^O4y;@%O$kU6hcuaoz_jv$2k3J;T-%NYKGk>ze8DlHfhUCq z+8|hGr}l5!Kl!PRr$v7C;~P&wIpvTw#{sJ|SweGdW5DXp^tN<0V3j&)MFnvf0C2zp z(Q4K~@T}kAc<5pF|3)NM)ACu# z1E|%goW>4ZA=?0KgSsj~-@qO28`SFJx4+A%rKg{LUe1AGejq%3qlBxyn?Fi}a|i+G z_(~a7)ASATr%s>Zt&vBs^8(L8 z5MboNx9ke{efJn?4>pVgQ{V+G--s76+4?VUh!}{ye~1{U5}d=9!LFU!GDr?*IkLdZ zw8|Tp*gyf>VotONhLRs@{{JjjSdd{kgC)EGFr%;5n-y5awgqYcIm|o8ImyEL$9=D@ zVq&{9r=YE|x6R@PChaX(OfGGFb3@RC@YD zl84@^83wKK1N@nsWq7q>0yvwa@e{KOv{tIU+o)}ACe1YR#*cc3Z_T+Os@xwgHX86P z2}=dTh*M0!FhIUhaPyX1*BBQdG9a{m2m{M|KM#WPSb67+1#Et{fUWR<Z^esO%?D?A5;O>6Kknq@aLjo zbOCTEVprvujkap5(rENh1-LJu7z0xUo_&rN^q^_6B&U6nagR#fmMrY5+{uhc;Y^0!!!L4HdNuNd))tbBVS_u^SdR$Tp z%{@MzFx;!VCsT`&MtC>Ghj_=Kxnnp2wxFdN>TNO`g$jxKNYN_J_Q+5~D1jYeV2C1{ zJBNEfg$EvFijs!=r=NZ9#dNw4)z$@Aw*U~2@WKC~Rd*A7eb{1T8FJIJk1gDseGE5Q z^ozrqMuIYC z(d({r@%$OEtTZ5edQb0~=U?&3mtJxSSk5@lD-{t?89hBsTZDz+pWD-^RhX3^d`lb! z|N9s=Kwg#OylSess>1w~c+WF59Y{+%P*}Oa-P_tFvzm)pUD(`3FNbb5kTkV4Ifia_ zWaGkytJmY*ZdiZIhLQF8hKcnX@UQiA81mZ!rfl|YJl|5jmC}hR*xLdxMe%XS)0)ir zu&xN3YR*sEeQnMs6~9sn!HwR7Z{v}%&wQ3+KIeQh0Bpz1P2!(Cl|5yBd4j*SYWI;~ z3Lcai^Pf`xavrWx!(WenZ?k^3>1~u6tl!UMTTY9^KJRq4cP+tHL6#qPJGbRqTj=uH z=4`r=^mzW$RgYf_ebOB(22}mIq0!od3zru38pKc4YNm$zm?yxv3*tIr$}rV4$v`Uy zGv`E|KXiE~6sj(duN1ye^)A0`sxOH!^&Df6cfHHY>L(v+cJ8SGW|{+nZ61eA^%}cy z{fp;s!zYC{-=7|tLYr@EwC|(M&-cdA7dzdXIM-vaKhz!T^}2Jt5&YHZ7e3Xuuo=iC z#2lM}IW_|kkB^4mK3W_rktuNManzIJsO*~SucZZGg|VIsCsG+dg^p2K{wTMn&E7rt zTn_x^x76(GV?9`Y)Vr$LGeX%CivVt0NV=<)YczYG>K)fA0+H6}s@VtEU)W4Yq7DKA zku4$V_J+H25dBQ#&3T2eIJbM=;`wcbrQ(ts&dwHS_GJ4gM-J<;=?^h<2ylqVfL~Gb2cv(1yZvjFK2Hh&`K0H&Q!~^}*Zbw0;yk~S-!Bo04unHDS5heooTw%vwfxU2jmTR*U@QE7 ztdk9I`J@m+nN-Wq{5}E-q{MzC2w}(2>3pmKQtihcfVF(=0VwJaaRN_b69BxxaR##7M(oKAGjKXB&oj@9v_zOh58*D#~3^NtMME-Cf##?C(bAv%_bb zPoptHbUriB+dG!9JITJD;WS&WzTTS3HZ^FG1btU)>lIfYruWcW<8M7~cO>RL5m0pR zrEGoh@UPg|(bpTK>%rG=T*1X}d@CBeX;NW)4@g<&L5=Tf>^{BY-QhFfL-11wX|8N1 zHL`y1-f`N*$=5^hL3c0k{<@mryPM~xu~UlU(0xk?TI?S{7a#3(2c0nt0t@ZM&f74< zqrt1m@9Uo0!~Z)PKmOMk{wkcoFXmcW`eUzW3P6tGp1rviBi8$d``qCRL8=h?!oye#YL%q5k_r`9U_+Q_ZK*&%=Xes+r!OeV{N?bBR6p z*ylku5P#5Q5H}E&OhEJzKb3u~hjxGpZn>-mC$HLk`<$h7$Id(Vye{~9H2t&M=j zfZK=gKX!PC;?XwuRSxvD##6L+L0odU%v79y+|(EOdV9VW!JSO>HmZPvvPV>bLrADT z(w~Pe&qaSE$a<51`st^V!w12>?~H@C4XbrSeZ*Ri_dWkx$k^Y^Ed!tE=|NP#;6$HY zJp#g>@x_$w5n>6hzQE-J&hsT)eH~a!N9Jv!|6JpF^!Q%$=jidzsK=L6^IVCZh2A-` zA%n(w)A~~Y+W9{j{*yI(PDgC|>r3>1{y*CPkM$c)tnY7VW8!ab>Y??IZbtWSgCAw< zht`K*ptb(M<#XCk2~zN**7?op@58=?aVq0gX^WnvSlc-4+w~1b3E@GJBnrd+*Y9Nn z0Bh(OWb);ZPKkWG5Y38hvp)C#@F!zMN_UZTw9z{Mo!}0b0KgE!Z!v`s833g6rRAH~ zkFCF%QC1bZO8!9e7CssPg%za z6i;{EY3tXKZ^mDbuAkk|aTvf0jcwRadeEO}K`|Jxg8#(yr#h?e=MaLNziiBBUyeY4 zWR<_)00hkXX`7)o=1X6P00G*Z#(S!mKINZ9j*QDH2r3e(??6Cb7b8|_AmFoeRslcE zjW5^MhOIR=>EjHB~_?2ELLdmr6jTD?C)eH0*1+a^K5%Fb#=XCs6TI2n*Cg~s1S zE>#z|J_l1HoAUW`u7_Rze*Z9Z`flfXTsOF>TWW&OkqStYUZ!lHQrSMmA(ZLEZC}{S zu58AxuIZiQF)Cc}?^{<-EPBICePG3-0B%Cb2{SY?M_4iw@ALT zv113ub&~T84MsZ;CO4VjYq7yL3yWXUV{rK$@4?3@R#)&$#?VtwqNbDdbG%D{LewQn zI@CoO+;gc-?Ht;d`S22o9{bdO$tGFQXL5_S@v52K8T#8!lH0>}4zgDtnGF4L`1D(@ zzFS8pL*GV6&z8neREovX1vK{D8~fiiUO;2do4-I~f6l0SRKSIeM>j02A4AP+uUnc+ z<5v~O8*JP@s{5*^RlKPGBw&$G3w#g~B*_M$d;cVKZ*$yf50594A-kt`e5dGTj=qXP zDSA8zUp3%(+x$Y~>uRk>gk_pj$dbHPU z7$@8u=%wDa4%m}#x4nL3-NE&<>&Dr}=hpWCJdLPlie(!Pk`7QOPZLm#&S2pPTkDm? zRB24aopO+nazZ2Z2M`*#flt6V8*1Vkhz%TqY9cpT1OF^}^NOaQL<0{reOS|@fkl|t zRC&GQ%8)0#8^}_3t_JI>{WuZ_Xa%>dUb7}!yNa*|E&R0D!qK8J%QMdN=+**!d=5T7 zo60w3wYI%>jkx&eRie(sy5o&o0uV81keD2~u|isbOjP&Kxkb~EkeAIadhd;quR8a| z8*Os`q>QBAx%K1u)781-kH^oa1Z7rf4$Vo84ojdb5c19$MbgNP9~#^F26HGDCH6qE zjtubF-Q0uev)t63E0x2u0MgY&kfUe#JFKcaBP3!chF#OPnx?WFv85`&!C+^wQ(_JzQWasarVZ}fhebR%>|U(jI<6fD z@Fjqd4&;o2Q3^4YFPQ9QunXgQ5D?O**3Pf%v&ole^0M1;B@f1XPCRy!s1=%gAn2pxp8Py|JlC15U}5B_==m`1h9SL@ zcn(Ity-D(-endY?$+RIIeoglH`!H6MotN7#w)k`x5ARhoI?Q&u5UVQzJRd|4AKms` z#&dd}e;h6we)HR5N+&_j{7R%({`?olTd~WhUjkPa7Jo-GTIlo8=keujA8TGwDmJlU zz>!3}pd%V$C`&076o4aP<4^wqED$mrUNAx)YxeG_4-!1UAvAKlZMH~Eily+J}4OYj?mw|(%$60y-?--js}ao0xaoe zjwO~(f^^IN-(fJ)ezgo%VJwn=Ic@Le`eJ*}w`kK2b2S<~EF(R5L9@vb&`fh14{x|) z{hRCN*LSgMN9@_2DsjewYocug{`24_dB5cid?hL#Z;~ERZ{YUJ1uT@$$aolY8li!c z92frdj=HRYQ)id0E->+XsIxC);w>&h6SyQKJ}Cj-`UuV$JRHt2!IK@FUk7X9A4dz1 zj65lM4A#gnW(O~!ppA25F2gaV3@tqO7M^cttVuLg5WR32ZrI>=HHlM z<2_Wr-x_=q?`_j}*qslTfV_!wgWtw)F7UZjeF1bPN0Va)ESV>!My|SA<(>oNU{N5*enl9-~dn$xjBR0m1x)f z_5}JJXt@Pwo#S}j?L(cBZi&ADn7eI^=FHN`LAd8g*|R2&Wv7ESnj;3~=)^Gq{wo0a zPdQHRj?`Tv(bj!BmyM1Rc50(T2M>Au$rLOf9piMOw*DP6()o5h7wCetu6R9A?w;4r z2F`~zjpvW-x1U+u~Yp!ZqXa^(;7YK6wMu|e{ROG z{{0bp=zgxe98}tBJ|A+(TU<`q@^`-dt6vEYI!OZT-_ZTdA3rpn6K#-90Nt+f9CW+- zcLx8Q^=>RyKvA~@eop5~e=Z@a!{X7I&%AekvGK}fZ#I98-uNU8fXO*2Y$H3jybi zW$QOS_ZZi%E{>stR^(J<_enhkgdz`9_Anqq6fW{mv5ON10t4RpWjvmH?rmVUrWwiP z%GwGtok%K=7^+c?{WS4mTmgi}j$1#Wi}Oa|7ZkROr8%kWI8a=T>i9mejlV(t=~o!m z>z}>*oaG)B9gp-H*z*vN$V%;AQp1^FJDK{BrSH>MibY){%K&i`l>r>B!t_V{E_->uCT^k4|UIKYEm z-ocpEpYFp0qK(dl$)lV)QIqDX{4K)+R2^vWemGnLaPQZ zC!Ks9;d^37QWW3gWmlxAvFx?Fi>YokTYR?mH2f36oURt1qs8Y_-Dz49bMWc-zu}+F z*0=Cau7UsG!MiJ=uUaDFlp}@6P+RrORtl5Qp=NVFT`@pGQ?Ie=m8kAF{$ezqEx}z7 z`#Sb8X@AmVHciL40V31L>N~J7VyGI=_OkF_U#zQ zLAHZ!|Hggd+u=deMj0h^)6mnMH~QqHOxLDzaqgPR1L-asNHUgVfftX)+q%>4cr}-T z93}6L`3ZIRWVHMDz7w4BA-qSlJB{)7DV3Jy-u>9t%_;ZsN=5gvTz%bH_v|W2FjtbX z;oCqwP76IFlQEug`2~b@07-;1jLh0V{-wr`FMGB58#MKo)zmxk91Z9>TEGmx3hjIC zy8UZUUjw*K%)WNb{cA^15Z-S8h5q-N#kJjaqwCjoFs08adW_=`csodNNX|%?YttD$ zP?{^#@L)3oSPXP_RHQZJipq9rP&6hV6W%!<5}G@JD;^LQ;u{RivF6SI&^V%-0BQ20 zvGDlgxekX@fvCPR&;`%DJLnuN(2z&l{Nr4TdkQ8xtc}1$_o~7o^o;-)Z=W6|xBSDT z(36Wr;bn(s6!y{q7-3;rQzN&5JU**Xj9TjDw8ZNQ1BP*n)%~gc1wA2 z%*~j~t=F;u8tooBt*hqV%~5z8>0FLtCvUvEd1a1AHz%zh!}iS_k27bgu{YX}@VWfx z;lt^Qv;LMemmB=G0xyo=C$~S9a>~6Yjpbon3S+r7a|N-r(9K(@tnjp>`}8Q3_f04t zVDuaSiGp=skKvqf6#qJ~?(1vc#%>PR7@_E~wF`Kr9r))8CFFH9wbSfDtq5o#OzrZ= z^M$V9jz>!mJsmi18S9=vIoHk80*D&TAsV6fsLTjVl57-6_bG4bm1^!!R;qbm-L(wo z01^+(-WO>gSL%f#4y&o7H7KwjKayH!SixNFZ5=IpeQQIGe;DPaLsQ7KKr7Ed#AWO9 zwb`1+YW#A|v11bi1_%(A=I*psE^KIJ(P(Zti(DYb(OGiO@*4?2zDBMg@4gejSsqCEj5uml4is^(SKM))qU?=yA90r@Vy| zXYxI@IxD}DJ1{Ex$6I$YmAi(+shlr3el{ZvV(+e+H`(?39}qRhjZ>ay!*$nvd%Bp% znH#{Jm&P{h-1o6_YaYLc+hXjBYTnisJrYK%f6Kvf?^6y3;$A3^SS3h5~roZ+S{x|sVKDq|e`F1fR-BOKps@i-@aFaAqSU1H}c2% z%npOxGtWK`?i~WVP3=Fo?GUT>q~B3?f7d5ChFyYqU~k8_eROHDCwD^*V;X37@9W{k zNyi}(RQWXY;y?r0A|*_h5OJ)x>%?w|wv8@$Xx^4$6F7Itp2u*9Mstnm@VPnS)B33X zkxOdLz1n6^jPPcPgJ#81T}FEjP(fS8ppbgbQZLWRYuWDtCF&P)ZGdlz#0rl~IKEoi2Nji+Mv+{pjwpveQB?puEy-}e5s zqifdYYfg7~idX!dwR39mZ6MJSj*u=a@*N=2T$B5RMZ#lo7F6Y+kJswv-p!C3o*+c4w+?Rd6JcNGX``sS20V^!J=16A(>P)-c zDcfUs3v=Z{FnQqH zk(u}To!WY|%}H8kWDK5=&BzoWSCG~T0?=Z03>+8nFuq&vZ8g6G1n`zF1x0tw{qk2I zG&0hxLmY%m0;*=Mr~%=Tg&WhT%tDh4SqOnP%Td6ccN#>wOEWyLgJFml4%h}90RJKO zFMGS+bq2nOyZOKDKb+BvcmTnRevq`n0|Eqw2sqD&C3l(P2?@fICMBIzW|v8sjTMY0 zYgicQokfL3!j+kW$4dpH8@?7Gm){~t^cg?6{m z0qFh*)X)8Q5h1mBv3@_9Os720-u=0fIK% zNb~CsXnxPujI2Gd=AB^o^gkL1R%dIPtG~8p48y_V>ajJeSMOWXA$8vc6WYZ}ac8nX z>RkZ@(1NTN5I}Wf!^^2J!&hT{%GrAZr3S=$W&og)-Va^AEZy72`cH&IyWC?VWsiQn zowr0zLfPv$ZdinmYjN0wPXPe!@v!TOC$L;yC|YFgu^flN{@LeVph=#SJw2vc91(LL zzAWWC`EAD+rq>5<9^lKK&yCH`;ZSBin++QHFU1g{CZIe7YbNQT&&Tn#zt`W2T7CtX8UI-^mUZCj1>d${jTtsT(yo|upm z*WaQQ9_|#tHhAnHll+N=-r{MGV-VzRD{*4%Xu9{2!KEAAo2gh6` zwr_Q{9b2~zwfPM)Y6?@Pth}{(6lI^}1D8OlNxCVaWyPbdV2A^(Ly9=={4ym2 zY3^d?Nj^w-r!d9~l*e%x07(;AE*Rgs^&8*F?i=SYpWV{{56@}dn|HLAbEVDJ)-iMN zflxql+9^C(bID0S!c*~)9BcYw+(eO-9yy4$50%?57_$^D?_n7+k1Rl!a!)W0g>bc<7(F!}Z zE5XaRXIBmI^1X-O)p+Bw$I-(}^zc{J!v`=A&#M$(tw#Ou>Q!jetJi#T_2`<_y*0hH zeN;uP4P&RR#BxvprLLH6Vr2J*t>kM>>}Z^3F4jJqJLRCUt0scrtPa=M*fU(2Y(;0N zUxQ*)Da6wb+ibDB!iLm{i$G~`jo%9gBw*zO7{DJ5x7Z4ybCmKFw?dlyGH`f16>~fOMmn9Wo8kLBGQc^iUfylcAnQ#! z4CVp%`9&jNpm@P%bGY55qN`8Sk*<9;?5N*?g*An6MngJ;bQ2!wCt{7|)&{{Q>uYJ5 zH=3c?JcqbZ9qM-;}D7@(Yp@{QLQ}kY1mR=SIlZ#SXw!Q8MHd*qu z1$*-cK468esvK50G_82Kvmw0JpXtNU`-!v*#uNcCG)8IFT4PB2vuDgiH=H%-MqEeR zxI%-jo7%~v3M8yFhgTG8s+yDi!3!hy4C2mEe;(h1DnvINb#u1oj7bO?Iy6`t@$Iwl z7>(g~mThQ4Ht)b0H|UJ>JA6fZ6ys`nTQOR~?Dj5vm-s*U8slI1PYdln09?D5V+!XP zTI{whtfKaYNxa-ws&k_PBV?Wh8J#;jhGAS{y3gW4O6TuTQhG9q$7%QToW<#K2j}hi zGaf6;v^l!ulFjtmC?4WxI9$NpOIy$d4MI?sD!DOhgb(YjH*O17tVuiggg%TXdVwvd zgEjRJ7+N>{az@ODk^CEl&Yd1XU;>u{v#k?G!Dl?>eb3jDzD3vnwHQW< zTb_&I(VH!hl(x5SJR@0{$SI*n(ZFQyxz@YEB%&<-<`S3FL+_SNj#c=XYW5E2W>P{P zAG_L0x89A9THPVB4@-fI-@u!Ij?uaU+=#u~LuB#Mp{Cp5&92SC+t$+C=-OSx8<*a( z?{573vIo$yyXe@jt7F5&z8>=U+I6#Q_pd2dkE}Vqdfx}eR)1i1@qyb{PkaFXVfE^z z4~(qN^w;9*t}197ja-sC`#7TKWvV6h-q-@mk8A20y?0>*Mk^=x9y&R6R9W8RbW@p+ z_^|M;;baq6BbU5v;#;5rgJ=-^4ke!dkFxg+lJh#(#N0gr07>25>%Hr}yX&&cuB~#p zT;+1vWtYpLcK3&OZ4nqu1{fug)RittkrYXZne6F4-`9Ea41k$I4on~^F-MUismvf= zNeqgVsCbpG0*Q?A^E~f4=li-bl)2JVm~#zr(Qd zS`}X)!19R=0nHPama8d7R9&r7b!mx`jqS7K!LfY?F^A#T8SvZ~%YMuHJ<{y2DF(-h zGCAi_T}MO55@^Uu`1ZQDQk^Zdno6|$k+s`yEwS`QqAhuyL_3Dsy?`I1a2#5@@7^<` zaICVXx7ys0H40W?`I_)@E1HEUuCvl#ckREDb1n}v$FtGxVGRXXb_FrG%B2ZdcJ;$4 zUGwI}(~Q8i6oH$)ppOx+^D98~;`tDY805V3yk1D^IJkS+Up}<8uw@tQqJ{+ax}qL- zX)>c8M0N&nf*@q)QU^0)JD?Q`cP`4=p|G<{LzCuDD2`Ajcju~~r@{Mj+?zHeDl+nE zH)zWosrMzI-r4Y4SVN-+;De<6+8yNEtDj~{X}hP@TnoV?ZpD{}C*TJ>0|&aZ@;ab< z4RRUc1wi(6OEO+U6%2LdPK9rMMn}~U<&gGuUWtrEM%eDjH)I@*Ty{R^wj-7e8_73$ zF2qxvG`lB`;C{*N#CDrCUklu6=BsJ!m^BY{Dpq75Y0j*QZa$7Wk6*Svj_1#>II={X z`$RvW-BWMNVM3b$uvY=>4Jtj=(c|VvH;M}d0z_q-#o`ds4j6sBsOp*7f ztmlW;5I>`Kjp78T^m}F^oJ(5A^4Pa>$v6-XNQJ-h7s!fv+=g-mI7hJ}oU`akO$vTz zIM6md2HzAlwjp6 z?#q=gxi6N#;9e}f@B%1p9>)Wan}!}l^uWSRljdnr^aCt|XP3@2MRaw9#=-^VI5+^6<4L)*_U9Z#~y_m|{T5fQ^TG>Bz#BixUms=V`bZ>pT1K z%3DD;u8%f=SU7@}SR2blau`VGyjlZ9ywNVVOiKS!>G;Hp0QELN{SN~5b<7muZTh@P z)I_&+*OnUK`}gDJvE}jBme$sWWr&;SH!n!xSXyMZ0_D7PDI~!&5d88rxi|$%8}aoV zBny?9N=Q+M=6QBaOwc6{V7`nkVRs_#`4>y(b!XnW2k=kdcq7S9SK8eYalAhcH^h*O zYibQ$LFUJ!>E*0D*3M(U3|uF?GT7!)oq~nVXk6UAgeLdI$qx|40plX&cy072DESHW zv@|IRzo8~u>j#zGM=90(dE>=;KWrot1qXy|nPxw9P^E6y z&Q25;2{#nSR~58M!R|zHv2dbzM)WPvZazG(n!};XEe?~K8Mso&Mfr9?1)ait-ZTxa z>Gl7ORZ((qm36Wslu)jWA&PskyaFQbF6rYg@{gp5ZB;Ms<@K)|qMQVZ6UL`-@}|#U zLh|D)XgM9;61=T!S%5@D;he<00pYy4*Iiao1g=kus55(<>k@njPKFMk+oR{r zw*>4iS()>+Mct*aJIBjou-yo=tzE>BX$M7tRB8-+TskqbX%qnqjxjbnxgY`UE!R zABJBDLhQx^u}7lLF-yR8Lbun=EdyuJ9n_y1pqr|B%NoaCjRag!0WW7NV7|6f*xgF+ zggdzookNPZz1aBPs8^++2QHq%5wD7er?~7b*+`ud-;AOmG2mvc&5jiWAIMB=6Y&hW zP2vY~$Hz!6ZfXIbTSB^f@hoCDcs3kz_m%2LC%I_6`LQ-|yXUgYJaSin+#3RNf8IUU z^X#*qbI+7S!Si>en*koMn^;Ir3sFg0v}kx&-x)W_=-{9t@`7O`Sv>vGz6A!-0sKh<-+_J?7%>_eqp{I(T@8hVH>z*v$?P0(u1=xPyS6 z=vFsDcN5DC8;WZfbbqCEYT^k%_Y9!>T|xI0%)_ZI8%VoBzQ?!h9q%0*A0OX4_JQ&7 zF}|m_u{y9ElzeOozoz3o_?^9Dg>g4l93Pt=Z^#~RASu@b71GsOsX*R+m>}OLke5O3 z^>*dnLDH?9n#u_x)G4>4nst;j-!RIzVUpOZKVl(~{TN60?s(42*47Seo>^mc9KJ}! zZir!F&-&6=!OiJVbB2t| z;1o&q=cO}jaKm*UZ4Vpg?2CAL9etz~+wf(A z3LtqMFBfwtO?l{4VL7_wW9?S(ulW~->p57@Jn+h84zNyr9XX4O8#bLbeZefIFc@G@ z&#M5|XV1G|#?Sng58w#v6yp$&kEdJ8m$KMQs&Rq%E zNtL@+O457Gxd(`+GcNTzK)eEQtcX%3RTJ|NuhZ#|CvcX^WR9Ktsf-Ie#NQTX(?kA^ z-LIC*uocY`aDe!XpGz3<$`xdRthEqB_aHA@o*FJVy3$m6QkdE@7TdBulKur!Ju5SGt;6yO8U+d(5U&PX~vm90Hu}W*q>rGwB7&qkZoOU{qntSQu^!n2&k38VGx}>9lBuK{#aPWSkcl;GJ_X zYz3ShyD0#rW}au>c|HyIz6yL?0563b(C??&JoLZR5r^Z2FH+!tKyKm_@gyguoWkf! zaHhapL@5XTwu1rCpNnJAW(xLs)}EMuZrIQLwE+K!{(yh5a3DGi@h=p<;J$dabpT)a z@@1D@b`VcNAKHO0eJS}Ok>9;ge%^h)B;_5EH)!wR?6RY!ziY#c^6+6s%-iPy{4?fG z_%zX}o4Nb8F^B$nF;zsYB>1SzV5fWrrJ=tVWCrohv1;B9v-!Ecaz~g`fL2o zQ+E>^P;q6T>jla6I3W`c=8nhjFx6(@pFoFCFx8gM_J9Rfaq}>*9j>>VtwPiA|Es0d ziOR%%=l~Yb0US{W(7P3B_sOl(TZ-dbc8wRu#*?ugp#Ja2`bS4mAx3u-1%I}Az43G7&8fydL<~^@32SZ)8GiRu4xJ9+BV>C)OKIE<}1?1eZL}o4u{` z%775amSvPmve5~>^t8P|YJs<}V`fZhk%CjstQmvH|1^9X3Rpe*fxvXpM^+rotA zo-Lmp{{XvHLcKsg*|I+1e`+?;IL_;O{Wku{@|HH3ejO@6P03AO10VVTGW{sjhl$Ki zojz*>{K|!_5rA}Kjet0}geYGksYIzw%^l*dM!;lxTJX1NhCMgJjx1-s5ip_NkGw?} z-V`tZ4OyAkzU7+qm2<6ts2K`0NP`#bMfpJ^QKwO;)4Sb03uDPW72I1;xzimgA9M#w zgn!HHh-kvd{C-LH0k&6*$31Mx=w-|-fs&%^&wo947)3;gJlU`SrIr7jNk8jV0`d3Izu&(Y1^s9W1^o7M1ok_4 z@aP^r_SZe`H;@lWJ?_5*+;2}T0QYwT_m2tp>xi{aj;EmU`^Nf4#{l+sj`ol7ozd#p z+4=-NhyQA0h0zAy!1hPS?inqPjZTeCk~eH^pO>DWLefvv2y8&Ql{0adKtP2re?~Jv za;08?ye4Y~w6)XXb)@2+RMj{*%1WB$G*w5*%RQf>qOZNM^v~H0FbXHs_F;GwP>r~U zWNkEr@zn6>X?owt?PQMX;OV}yK!UkHhzGg}A%JITJm3@qpnza9i zKmHLfpZ+69jvPC7%pI?sXr3&dIO$H5j-v@+7x3PD=mY-vd*28k?;i4(@BHv>%&=z% zNUeZQ4=2ry^dn=!%`u!t^Q_;i`8(H8^BacH0_Zz#FOdYvrz8uvwcIFp-jr9|6{0=^U7BhSwp zT-F(9!)_V8tFge!1m;x29%E{+8Ni3xsRQm{^T$*go?ZzPFV|Y=kJmgAQaI+KIF~8}d9g=Lv zYHuK}RpszVVj3VqJC9o!wNM}*%g)OF*7|;VN4m=v84dKF2JG0Fees7Hz;GANIF~y2iaEn|whSgvdtT)lCf&aNnx*3D#!J+Hn`DK|{_kZw zUd!QK6ZONLFL@y;>sujU`R>un`abGG5yJWp%K)nVz{C8Ew%9Yh&jy46c_6!>-96L$ zIfMb-bN$lypLZ{$FD758eX;PRD&Cqv^#pX@Jzw#V?hMlLf1^8ioNL^G>0y(bf%*e6 z4v&Z$xbeX*H9tSk#*^$(-FJp;4NcGQfb|Y*wUp;)@BHXTD9X92oWG$xgLM>Vco57E z;GyS&b$&N|Fyq;Yz=E)cos-ydFGj$6FJF(w=_|r@OiOwr9)eT5w}lq0-fCd6vC;Zh z0Pm|4&j8v_2-@3Q`b3K+N#|$AK0qAj54??y?HcVJ866!-N6RB_v@r6;(Z9rpqa*wr z-}uWef_#g-e{y_kOC1tw6{9rRY9*X6MVv>s?#=ti`bk<$*q28s-qJ1X)29T|v!yiZ zk^_1lS|;ny1N~u(yjxJNWWqkj-d+Oj4`Jn)z0+kHnia-ZpkJjJePsOtdJVpzf57Qw znO6V6oC|qBBY4cWV6P45Mk$ni7tBA?$^PXpeu+LAXpeFD-~Imge-Pro3siqEJyOG9 zh4B3ke*o409eTvy{`%Ly`qeLg`3r4Mz@8eP)Z_+PwTUq71LK!BByHcXa`&eFy>ZoR zSOpqXcW9o9K7)Kn-6!eyI4^gVRgl+jFcgJ?{I_Aa9XS6y0{WabiS0ywJ6JwFkJcEC zu~%1Fec2M9iSt4M&9(oP#hPREPKv7g+kax>KGqu|vI$*}w7>EZu0l;PiVg4v=V#2W zrHPK|t?M|9iD?eErFGs6Wd5yN_tUB3(Z<`3@!ewyEU9lIVls&apsAILTxG+#Oos*l zfB$7&8<)b>2kb@FjB24x#_u`q(XmFJCsju^F&L3B*R5tdZ7~Ur?#^rb8J{-u+{fP3;E_rD1Rk2oZe}0W z&0+w~Cg6zwoKUt#*1TCMPDbrP&kX-L1GmQ7_?+-W{J$+H?_0YW@LwYwd1haT`TB~+ zIIIJ}C@<7~?o7fug=uC!C$YiLHEO81&FV_J4q%USpH3&!u7KLLzJj0lW0$)-DW+IY zhv5BW6|auy?c>9#8t#ap$Zxm2_Vc;g9!37F5zzA`cqP7q;CF}YI|kmv#Jf+~cM$xS zwN2hq_EF+zA3%xU=G{5L`)M=+N0qW?h?um?_qf*L(%$!drrJzn_$I~1)QI$>?1B0* zK0Z=w1s?TUzi7Ux{qA!h?$5c;C(l>G@e41^zL>m_0R2-D`U=p$-w3^XqLhPwsre6e zPnhMic=W1xu$d$M6Ow+r6^4+}Lb8k*vxhg^nXY07@Hg?ww|BB|eKr{P>MM#_QKX*#KWR&Dv^5cT z7N7&D`VQdh>HwZV2XIOqK(b|u*grM46A)j=n;U&#q%c~;TVtdjC=aY}kCaF6$0yv# z?C1GFUgL~eB5o}Yyy|*hhD|CjBpN}Q|S-6+R zuOJkQCp7*N7t?Zg9Z?y)-r$}}LLTl-+U1>T!pK)mPpyr})x zUVi!29N@>oFGpRK}h zGIn42PX%|*a?-_z3S`rq7MJtjZuV28_o#j1K*076a3{7?bs{&z`Ml+VuArXg+YQ_y zKKa)LN9eMJ&9?;k9%>iAxCyIXz?Zbj(rfS@@tp#z@ZFdrm3+4+*<0IJ+`q4}zXn`S z_V7mNG6r)H9JBHvOkd2_BZEbU`6ARok$O>SwR2fN=b=*X2;J_FY&ys|t4*Ll>!Y&+(iDB0U-vo_XQmYtiMDo)LpfnrV@_3 zpJ}h;Zn%ZRgE(jnvzgOa-#LZ8QX_D1-FpCbdqL`xr0w?NwvIj^LE?5BjyD0~fy>vh zbry@orlr$!YYlO{gzu>Vc?Y9M`Sy)h4#)wIxoJ5udZ8n*Q8YO+dYJV#Movbr#qBmO zmu;R6DZL;6w6xaZ+102Rp;g5{!17YT5bCD%Y!vZmq198Ym#5$#swef4)eFmgW-n;= zy+m_x_0J_h^V;Woke{D?zV`X#IrnS=Sw78Byz;nvY`v%O54(p-#Bc@F8F4dlKB)5t z!H4NMMHI&|rnwWk(j1YGC~itnfblS-%zd*R6LQgL{lOKU$@_wgo8G{^vb$wv&Z{hE zFs?QgeX2d|Jd^iCo)0|AYPsIpEtkdOsm{BFzIlid^T`~-Apmmb^052ZP`uG7*Nw@) zCLDhRIKEmc2+5n{(_=kg?sKE}j`R+Xj0`6uJ;NizK=R=)kDN6;jQ8<2GLj4fbXOPr7LRnA%xU5 z3h%3zC_K*^S&?P)@)Ukg-nS19yQKQ(o-YNh-fqO?7c?c5Hm8N}sS>a<Xb0)_e1zACgLGq;S``ZY z6cqY}Ev@lM*h}{zDLOvBI@YF?)P|H)!?+yNcs1nhliV0*B`?&Yd5Gx|&(ga$$%m~B z#*@9CWE{p?%n0Pf(QqKK^Dq;YG9ah^Lma=(7RlS58roNEHu-W0c0tVCcdUiLR=V(7 z;ETcA1URsa<>3{v2A0#`T~@>^!OHS<_xzp&cRf2`cie_i>H=>sV`@6shKe#JQ&iZi z@?1M)R5-(L0yt+VLWAb_(%6RC$jeE~Gspd*PiYglj#OwAbHrS|BF+_?MXwCy09@jb z+Ebn`p9zUm9oLyqV7h$XaYy*V?kKPoNXexb#Q=n-fba%*`4ny>m_4tuHN~pAHulc| zwDAq!o)la)nQ;$Q`p`>NDtlqLPo@n$4^^zSzycfS@sRPgIlekq(G~1x3BLv3Zn+fo zc&R2r@5sW5-g%vS4fICELCMj09FprOJE}VxcF*?CeHQ|vZgkTWknN}mYW!vXMmP1M zriljh4m@0T4~n0hcJXk?qdE9SW145;+;I<8-g9y4@{hX5%8$Dz`X$Ui<(^KSNk7*D zdLugjT>aT9;`7PVm8X&?-4lfD%A@X)zK0>tJmelM39k+v=wl%hQv$_@<_rjW9FhRlI)%S#tDo5U_`Mu`6HAO2_^;Q7Y@X!q0V&k8?p z{H*d*_mdJ3n4B7;ZUKb-fiOen)t6uX8gmvp4;izTx*bJENG~|F2lnmDvS-3xO3jW}m<3s86g@^}s79Sh^@FtNc& zj=PoPcyzRv$L^C^eDxtOBu}5F3j9CH<0u0NQ1X z(Eno~o5FhF-qM8D6xQ=`4;?6r6|30`kSz&^kge(V4}JJ=Y`)z?HvJ$*=zRm5dzpj> zfWa@1*`VLR5MYIQ`!-_FSBpTK0y}yKFR^PmN(DEFZQof%=#~>V2GXFirkeu}QSdB8 z1Ximkn&ie{Ihx>Dj{Z4YuOO$e_lnOrQ86-YG+jou)o|tV@fSXR1vPY@ZiPYE{rQM| z2GxvesN0N3kIX;l`9RG4!%?=3_8sFpW?>f;^!v{EU$$^qBQKQ@(2=}D>8 z0pwU5O9V&CUW?{P!7B*MP`5YmzUy+LuGu&yRV&o=l!fpWXqsoj&D&+s@;51w6YS{|{i>eWsUra(7?pu-_s}xG?nGa4$bQHFS z4M^!#@NW)iCLaQI&t^Bm@CHcl83ddI9M|S;a#PYxN*4nrniEcaqyvqiIn_qMDceLL zJ)9d;(&dsra>3OR&b!gvGw>K4&1vbOp9l(oUJYG%E*frt&Jyeq9b?vT*Kl{(%yPQa zw}WmQS6R8m4YI%q<&HNNOxr>(QEt=@Uk5wqfj!fWXdVNP_@3p7xAqp$79pHdKY@G# z;XJpL=20*%8sb6A`CIsesMPc}*OJb|=pEzk@-uOYr30Xwj5@$taISp{S=7CYc)Lpz z#4i)vp`Kohy$G0fBk`WzTHcaieyyE05>Rd6^nTZar@US1!83oL+)E^1s;uKGH&13#)2u?Cou4^ z7}xSE-J@gGrrBXDx;;|fR|w)-WBB8NxX59FYvoM z*}`7p2KF5`xR*Hb;QfZc`!0cZP2fE}Iy+Jv9$5rLyWt)nv>WOZe!o0a7;fV2nW5tF z(EM-<7!4bI5@C06@f1Qi)L!~b3yMv5-nR64V`6RwrM#dH2h$^`z*!|xfB6RY; z1=8kPKKkh6ygUXVEvek2w29@fz6MHesug3TZ}khQzngxq{rwWO^Y49^Q2ZT&@mrd3 zeEnNI6GTQF3cu+8ixy-1{IedA={g%tc>o8QEG4SpVTe4lxFLtLn&FIAD&)n!j zo55|E+|OeE5me1Gs;1o=hAGMOYFlT3$J@u&kynFR*YMG{u?>V|eggerVXTU`-J|Om z%0T?GIdT>cCi+Kw{PyTHGMJ>{Ot^E_B5YQ0A3;W*a~7bzp?6#hxw%~-hur4k+zb<% zYEk6jA^sy9S|&6O>8!WFJr7ro!Ur_ss+y~`XU^8l`8{*w;mWxCh+A}$^cu-8%<)qn zlFyBbN9<-hD+xW*(8-{T`z70^wikA^fY%Aye1|eo67SBTwG3{9YZg8D%30b6lB445 zUMM$!1pN;Ddo88hHqijFjeqBsxEo@B0u5j|ZbWR_m|bQ!lmTkxVNxy*%d7G959my- zoIOORR1SYGEQrMhgO9>H0bZL>PQ2#57TA_~9w2)TD}3tQ-`+%oectsEm)*|F)8#{z zUP8dMn@$?QXncp1U9Vv>olF~_#!7cLSB6%;KA7E_OqXfF?7FP(4tS1E_n(I6m|5eN z7q69DWKC5E*X=H zM!#ERJDBq(@B^XIRhVoJjDE;H>>f!TO&+T~-UCg!{Y3HcCu)x;Lg)k>yYiqDLYIwS zcK|ers+cN4PPsH522j*Mve$&@KgqJq)W)?~XJGUX!I5qV82!4@Y#%hDAZm&zEc$0V z(rK2yq^-?%GwAvrqYv`Ycd=~!3o@1+aGEbbh%&%w>=d3#C!30<1FCUrZ=q@&`z^ur z0l{=bFrAF{px8~1%nlzO>Kg=;9!!VaV0ox9xPc$wzoEfrhWh!-&`>(KZfJ0jpLBx- zeAI)FmWQT>+aqwsM{1+>u_`uxq+2Vx+sR#6$tTxPmoJ5qZdEDd*18yWR++LDb3r5Y z=xru6H*HYLA$V_xi5LAuYLkiup(VAu*-E%ch3E|z`sG(6dNZ{K^tMT#TW`M|wGXv7 zdfePUvqoo-g^nJ=U(fD<`0cH3;&*r@>AE8!_&2}V^Q~{a?%vq&CSFo+z4h(4zU|)X z!_WNHy;*o8dA&qM<{JWUoR)kF!i;PSr$LqJAk>HNg@)9H--xI!vf(tEYepae9MU2I z+*D4nBGg#nx2(t#l49Xz7jBFXlV_&c`~1)uUyS@c>~lBKp6!DA1qtafm`o0ThN=qu zM*TDg^yB|LpHREh_!uF)0%o1~yTNMIF{@jf*o9WWyd+m2&2SKMc654tVeGSlZKCzB zl%!;uavLzaiCqa0Kd~qwxuAFZ zv2LUNvcA2J?y(yWMp8N?DU@Vor>YCZ#f2HHmvr;RIl#7?bu%SVY?I3)YD;Ytr}ePS zvy|a>KJ1+X?%;9r3C5^{nD&}fJC2p}kX_B5R88q2)V#Hj8zLoJdrhns49z5=jn|_Gi6^Q2v78j;K@5TjfK=&*ioT)8^@kHR=cD)r~_rA(p zxt9|O+b81KWnq)ZNYAhABb=22ai^21==7GMjcdo5IdC1`${pn=}^eLq5TW6lEiyJq~&6rGk( zHg0K#3{X8P=t@v9&v8a0VorE?)Q7>H#l4B_?z6z`hmwcWN2-q&AA7X@SpCuDk@Vr@ zq2$5JXOquV9&q4Qn+l}NZ=7n#NLnWIB=0^$h{GgtAofiX9F8ovJ}_XEH6Am7?5yxjfzl+8(uWqY<6(S6_ud4(<)|{f%!nzEya=`mOcf z1V9s^-QSgX1U$q3+E;y37nB!W`lr+bB4-a%b&-4sp6%5`Q4#f?Ui%hKw(l@)rZ%}(MZN@icfq+`(x-NL}Qv06(>X)ThR){376HYD(PV@H%KPzaVRUtb*^3^qa3&)gOh(qX z){wv8v_m3*P9TVvB0&FXW_^ucTqtPl2IxC@S*dB_<}e5KN9To2UObPnhYV-tQpm<_rdjgEoZ~E$#PBpRK{EbDlQ#8nOeF z3jSefoh-c;r+{e0ZsAO5&WYd^EPSb4>Mr5H0zGZa z9bAYNg63(@5Siz;RL4oGo0!sdWz2(>dw|2U=% zZ@g>u;5&+eFZsR&rqT6fu7=IWHvS#cBcxCQ!GWupJ3(@D*pHqlusV_SDpVMWYB&Y7IXXv$zLyn zUlF#tT6A2Jr#QAq6Qkoc1rEhP>u89|7SJ$~ZJS+Cne{KgHwRCvNdysJcu8g@s8VE7_4vZ!TWBom!EA97B=t0n;SffzmFgIlT(}f_`eJ$n|BRPQaqm= zZou14Aetu-&3U161qHO!h2S6*WE8%36sg+GVs-} zK|bFAAm=4VufCdmz42NJc>ZKp=Vao-ytoCxl-<2tG~{GCVe?(q1MZPp^Mw=YMt zoL`UB9!1}0)-3@l&u2b%aITLuczc0C(lOKdAE^oJnWH39jLi_8CmFZ%i*dJha}au znI4pGT-~X=c`L1?iQli6R2hR-9>85VYKF3u93HTL47^9?4O=9b+G}(+`kX?7QRR3T|sQkT^b-Bvj~9r8kWAaz`WqK&>N^D5Y+p%7hnZXVy zKVeAz?jItQ1Ie=?u;6I>A+Re^sNr5_d)flC;&iT+W~mjO$@%KTbYVNiKc<1Z{Mrat@Two@q5KDe@@<0h89{kdjRt9BDFf1$~)|GRn)+t{fwX=5@c@)jAeIehswqiOs~PgvZbj3U{i2t zF8Cq9RxzB=#F+mA?tDzgn)s$nR<@V>Ntq|gJ16?_-NcW*rQ!sxN+^_;Ce{;Z3AGMy zi{+V056V0mnFzObjS4R!cjD4rB6lFue%vmS=_qkWRvJLp9ALV?8k*8&-(6&ypo@Zn zhM&S+#-+V+{WhKJpZx4&5p`i*+wIF9bUnTCY7BLuT(-fz+R`sz)UemrZOkNXnH9BiUJ1V|$FFH1;VEG$1zp?lVbE8KM zJxHQF{~;c8Av9!|8`(1;*KO+$?78CEGiDK>Yhxcjj(StOeVS<@G4lLFA?~aYcV38F z92%Y*ng%%r75>cT!a#NNhJk_2n+G=IXEy+%JdkcK4?MnkJwF>hSsggb{sjMEGO)pZ z2OlhMo&|$$0HYHq;0frn14froCrgN&NdgZFxF8y3Iq>I!+6 zXlKz4vX|wH%D<$%e@&R?Ed5Z)hOua}RL}3f44CcUkYpyg?Ufv=`Ei;Mo3ZZfd4WWh0WlQT4HRH`s8AIoVk>`dhLy3L^djf`jF+2^VZh{Zj zFo9Urz8_8?a-BaT;b$t~f0ht;<218nQos$Tc@}eaOpKPXzVW#5I=vhrzPv*Lk8|09 z5yx~H)g2?}oDh#9c&Ay;^J-8H2M&-+s5Y!d4-00D2o#dZ?KZ|kY5?k_Q9-=ap$#ts zqx*!>4o606GGo=ZfdyxSQtzvC`;b8%rQ;Q(n6u6^;b_=+!G}~hz;s9~j(94Z9j-HA znhz~LFq7ZKg>x_+O=yWS?qdv)84+gSo6C7{zcO&T3Y>0J=$=Jh5mPJ}CrAO;txB<6 znJyoi=mAbYUg{SmF5Nv*EKkfy?VhaE(CpOdzM(b{of9bC4oWw?gqgF=f|k~;2`&<1 zboIcvjuC8%#zZ)TwBW!3-qv8m+%)<)6hDFU=b|3RcAw2Y_c!Lj8KE-Wr2L~F{TSeE z*gS5zGJ!J~@hM(V>bp4-95Ni9S)#Kg89XN@*Xbg~-iO}9#=`CI6Fg&&KG4}=x4yeK zJzTwS`Ti=nZ{NKPiY50X*tPGlYrk?Z;jVp?fd$9L9zA#Td1&-$-D-9hAX~=bpU(&5-=LfU8 zNHEhM*ro?SPCh3^^YSy>rK zR{o2f1CS1O;^%=C{E82D4&bLB5A+e60l&?`UWCX78$;FM;s}Jps;IIPRqj9k{PV$; z9ffR}Ze~U2fjHEi%eCY*=31@rL`4wUT5#o9{S1gXDa}(flaGEQykPX?F5PPah*Y}k z=CJeZMXfl+9#Y#vVOI2YNa7$qhS3+sfN)@QT$xK!VuH*Dy(N|V(rN=YsI3spBVi_E zei~tLropk9uMcqi!VBq(jV}~m)N*A}5+o)z{B6%kt zH%en)k=V}?ZfTt?A?7z^s6zUD7%3Js>p+kD#j<2On{16MAP@~p1;p*qDM`{J+lKov zbucvC7@C5H{m5`X<^u6yZK!Ae{-Jb#VJO+(Gqium?O#8Hm;DfadS$2we7{uUxcO;9gz#qz-JQaOEP@+{X&PP6dy}?rNlU!lIRhl9XELZqFq|4rnM9$xYjH- zn)OBsTu!Qqa2XG~jA~6>2D+o$$Z*-SX92UAYDQE)k&picWJaXGV%-|VvK1&f0&SCh zI%GWA8pZMqdJCrs!X7hQuw#v;hi05`HJdu*d1&?&I(uN*U;&jG_wjP>W*pA?rAj1{ zL01{=uIkpth4Fd2xnUFvbfs0^1z8iw1Lxfr3rEkbwJR%#i9`k|8qDEb<=`kfr%nZO-Gu(t|h5CoE4|DY|eU3oaUah z_c5exak-T1ONrA^uC=k$aGF4Eog6h6(hvZ(v};8UBT!S7^tN=q$p|qw`~y6f1`q?R zle?39>i2FxT)Ve;4@h%*cY^zHl0)vGJ5b)A>??^dqcw{HZ*Xceox0O<_8?8)OsNT+ zYE&T}3!L25)48RixELw~yX89L0?2o0J9GHermrwTebG0#aSGJLPuftnq-Ys=Gisx4 zKS5=dYKhj8zOzSZYL}?bUA!4EDU?B1|t2Rzu7k=*$e$Ngr2)REy(7&>b|5mEY=jiL(N7$`! zHku#%%*t|e<<5b^rgUK4rh$P?n>GzJHWdckrVRu9ke^u@C~h8@g^4}5xjtAQssYtW zuHCo;xpwE34An0Lz4q%OI$+)V(_xuu)ct}2$->zoffLrtfZUKU%K~P|gd+pymy>Y^ z%0XqqOWG9)T;~pyr?AS@-&gk1D_?)@8)zhQ_O!wJEo>gLSh!ZK7{Q*4nV}WD0@-V_ zBui-5bQgi0uR2T?(k)VR{M6HDJ^c&?alkva{S-g{T=MzC^L4E1E8!FPG=3A1{-h30 z+*==Q4$ZWn_T4E|_q4>1Hgk?TsNS7?7l%6&p)uIpA$xz~N?wYKQ|xgax;KO0uv$XW z+-vP|=Q%mO>FhSTowuXaNp#!MO5sAKlty{x=BtlGI3=zZFT2cLS_Z%71~YKqiz=R6 zJE-2Z@!D9^FnxGret6qZWv~j8joo`AJBQa1;DPIH%o9!l(C^>(4Vx-NS2;b>!hWB+ zU+x304iOyf!o{TUa9`dRz2Q%K59Um}`AqcY3(RVuQ5B-M@f45VX2&dnSIKSOhx4eD zf&ln=0ll@FJOs@CG<=5_gp_daeS7>yx65vVkI3P*;qc<9;6c@(vGvqzXy;R4HeN3d zFPm~@!l6QxZ+EwqZY7V#K2|I>prH)B=0TCN3^t!VZ8>E`&)a1luw^Ps@xF-61l{P` znou6G!}uR1?@{H(IyG-!n%Pn0$uvcxu2!NGvE#PeFpot#T|sn=V+7pEQ$4SVI5)0X zoYe@yEQK4yV8N&-%d->3(!`ym#%keovieu2PXn#-b{g=2pYhA;>8aI2rC#w}yaE{Q^{YyKrYwI`qM6T}u;%e)A;rn)U)$#Ue#yjGk{j;L z#7(Q7UUQ^G{5q^Xp^*pdri!Og1e6&OY*GkdHzaS*u(KR@(7b(+yA!?>i= z2H5>Ui*m0K8jHLtf;Uy~0N(p@k+F!~xHEox*@w9M@!aDC7;-xyH#9E%OIldRqj|t$ z!fx7qr}U6e+6J^LLg^KubPKt!;=tzlfwKX+1YY9p?53XOS|9oi~|DmIzc4O~< zX1Ta&IoVWLetuIg|NNZcat)ZAVrMCtc141B|9QOD5u~OJ#SyDeya~s9!!Csl=N0d8 zhiHb#CPHV5H%#eUMS*dWc#v2JMPgV6yAxdqB6|8_126jA$+U~S)vSJ~;}o7}B8)VVcY>KQh|uuRL)$rCU#CJ||fSYU8f(jxM`Os{rLS;TIMc7`b|?_+)xW&P|hf<>GJB4YzR5ZU1#2JFd0;ufAE7xOfL!kjcHW5R!qvBnfr zf%U;zlfH)!4fX8XH#EJkmttINZ(-l;-m__S`M2qP#i4!4P+@Ots4!UbZ+8yO0k|8` z#H(7?!+p87tOt(*V_T&Dl;SyXt)5XaY))V>PG24MyPWloCDjcpMm?XcQu75HSki!Kb#8%-loHr_OB~4Uf(HEP8CRsW<58u@iJ?1Z_V(t!iR6 z?l%@@x3^3qfjB=}8EIFV<>`q-V%Lq;>C=T%b-XQ}?g2(muNF(INvW{9hu-z#L<{(g z6abus6cR=i1l#Z#ez$CDjH~C+`3#rZz>UY3{8Zo^65mF!9{@blPGeP(5YEK6Icmti z0-bZou$&J5`kQZhllqdkO;o=0RYzRhx9%%SEX zIVXDi=vUy={(8lqc^{gDIxKJ&CVM_T(j|L)Og>ZVd_O{MkQ{tyvDb`GZ!i}c?HFes zF%bYl?Vx%mEnEtVD`pzCNsReT>YBNlD^y+)r+(#*V(AW?Dk1a>(7{g$pLZFH7Kff5 zC~g{<+O%P5)6yn_@umYyXK|U)5?z%YdzT7$TaVw{v9xK^j$~8s#*Ldcr5n%MgkLt| z{f!&lruF(2AFphhAE-kjuRo4G56uffX#eeO`v^-?fqqchJ zE-!V|o@=cTO7O$<)Gay0hI+%31;mEI;sKi>S%e0*kcGPxJOEgD)@Q&T-$c1g#!Vc=IP;>qwBPiW^S?B#mwEX$CPG> zVrH_qM{F=z8q_SWSE84M48$z=*9@>deZJZAXCM3V!Z;O6GzuWl`l<^HY;nna*xV}4 z9i{ld*)2gXG2VaKt2+?eZ?Ga_TUE~tYA!x0qjaX{kwYVeI94BRjZ6(M3_+k7S{Ur- zM8W3GbR-kv>s_sr{OhmTkGt{>bxxOea1 z;NE>2DI6Ny2HAXQXlA%B!fhJ>xWT7OE{}Wet+@>I2p!lh#_eaWBUxA3<$j(1F zi!8d2^_zI(E~{MXG&oJyIzhV3#t74T?wAjT#F^**uhIm+gsd5~$BN*L?Hqn(;)lpB?{OOq-u`vL;h z5k zfv+ja-@L{qXI9W_!>ky$?K_W7I)sM+3~42^xg}+N3>lvo+uv$$gMdEtDH$ zWuQ79w7IJcEL&{M^X!UZWe%ua9joE0IBdBcX%1toU~p(@u()}!y;-A#v%~X4edH$l zb_16idw;p-pvL+keK$s$Sf@t@&0TtM$1i}Qj(!pQRI=-4A`Ax#Ezncj=wUCXHJk8l ztHTwm@GuM%w)T-~Oz>brs!T9!w)GyK3xnZd?B|ge!xZ9~$~PX?nmFu@bO0t$*V0c$uw7Kr#W zAe=osi=G>Au3VY`ge~H2S~o5a#4LUtV*|b1I6pnMpjA(^n9^&Od(c8PCuT~m)pb(0 zS68d23#%m3?sOl4_;mf0J6Slj^JLGdQzxfR^#h#&%rmF^f!EMnXIB>?gyT`SCW_?= z46Pvz4h0+xH3b%@!eSsa(%|a>#nQpu+=d8ax`f-}W^De0jSVEGfQ;%v;Vy{aq5-HM zk!HhDi!}SW=M0H$iCL$O{ra14b!5SR`m>+?;upLzm}|^7{r->dzW3e{j$q+m1~~{l zrCHe;AAp!2GH24kJrrkHEI(WQ1mxFcw^G3kGESGlCHrdoR}R$or~48hZ~|Uk*_o_V zu;GI@j|;C1fC*UAhl#+RSj(seAutH`0}51DRM|>+4hX?P?KZ3W*A^%vyo@HE+eHenUtYc_Bz z+i`g-zlqK5g>8qhe(=!to^9K?M0lIqSUz_ju(tvFOyEu6LAz0hfH#w64gqfyyL$<| zs)RY>3=K-Mo%jBzB1%If4N+=Gu!}0=DTqHS%xy@AoK!VF!< zb)woP`jx-oZ1ih?_s!Seh*~!h-tQy}Ovk7*>#GUs9SS8VI)T@l&_v!iyGYerD|fKH z7GwR%L%oDw_h1juHZ`!t(`*EpdzZ){tbDQ8@+8@|m1OCf9OR-!%%LAOKPcON;l%ZZ zxyF;B!;3?`P_Bn2 z_pXCdfggLDd;0L}p1t#XdPyW6-d)&J#ap_&cMrsj#_sZ-8a|xejV>_3DF5!kDGcnl zFcnzCz&^L+5t$Jpzp$*0Cna9ku{!s>2C#i89l(z{J7D~n6MY=B=bD_!@yW5d(FKJW5SZbB^W;Pm3>kE{x;lBfd8$vWxN&Og zWY38cCz~eUIU7+$T`RVs)wCpiYq=qx6y=i(2|{S&kn^RAy!I)^y;<5tYG@P5XW^ zOhqeP7Wwg;LHvIE?H^rCf{elFe-uIP(7$QdC}YN?t*Q9>cSNF38GC0w6z@qQ~I6*=Y;%aGWw))ceG+dk;caz9lo=fqv=tjVn+#R}IDc*{F5VVu~lLt0{RXm`#^nt$n z3DgNMkI?}TIi}u6vf+;aAc(36MZX>58Hhm?MjIWDY8VvB;nE5s{I%k208VVm*EZP0d zUmHh8icD3KgW+;4wSQ;eI9fojz3}h`?M40xqySOu z^L*sN!ets{xG?8a`*>L-+0x&c4`%|>y53-&8_$kVexti7xw&#na%+0qp4-#g(p!^T z@bOLVMt4Kf0o-dLw^Z%?Do{~sJheglxaguMwBT0hF*StViVmEbN{n&p%(yX9joxsw z{U3SAb;`}X3E1reWU)!?!tO3J`r{vWAKPHUHlW+Vj5g%Pm1}TR5+QdLq`EQQ#yT8q zycwMvnHg?@Nhhm~)4jmq)9q8eK;=^lCwotvJb7~RL~{I`699-4$B!S!FUNPB=mCDW z!L4g2r%xei22xGjuC2}>G~PfWJVl@k#1Eid5tAlpyUCKN+96Vgq8{K56%49mgl#sX z43vpXONz@p>j>MF;vmF9);>lQ_YEKQJEP14g*>*o-6Er*09@4 z+LnauTQ=qfQ9YjB#2fbPY0+ZL%tY-`}7 zWxP${t-aW%&sFjM?#04FW3i9nKWq%%c5ZRwxicG^;Ml2<+lgaWz_H8SId4Q`Y>}vF zO$TzvqSHM!>PJ$TDf99+=c*_?R}HvX{Q}RCNMEpn>>Ar63XA$_?B$L_)J%Ef z&MP2y=282cw^{_BU855&La!k)d?ix)g#{=Mc!{YomRQAFORb78FL&p9YE@9HFke_a zj1j}ieT~Bvj26Z%dD+vAqwJq;&p_~9<#WuAQxrGMt&m!ae?(zfm}$Z?Z@?7C{Wg!J zEEXCpU)J*O=Xu`;8c0;rM;^ZFPmt>v9Me`YD%$LDh1EDrW(pFkbEH16q<64uFKD|< z&hm0Lo_kA;RgfA3MgpnHtrM;+sS2nUH!lrTHcb!p!b%>j?k(;Cqb}~=Gq<}R$P6sT zZ8W><0PDqFg`Ew&CA-Qyr||2WyQVO{KaCYT^^p{0+JQ{l_B#uTxr@td%G@0o?9&kz z70a#J@#oJ+Bs>N~7sL^y`Jr4RV-h@to=bDsz;|^lyTV}bq<_!YAu(9f_8nw8t~%)i zVeo0s@TEOn<34#7`&mQb)mx5 zzUUkV&44r=e&=y9T}%PoA1QxeoLhKTa;5=pz)Lc<}h_iFG8>o=Kk+ zlZMRA|D0rQSku+jDS&bh{wcL`jTd8L9v#?>;Wwz<4k|Zt@nyn}7I+-)mwkm-p_# zX3wdk){Uc0oya76qt&301PDWCx0Ea=E7hItUB%tI>br}(cDHs_g~tgDQK_(4tra;Z zBkL2O+Z7a%UcMr@)Q+=S^m^X|Cq>H*Ju#AUrk@ zA=&1!EH|N*6+X&qwoMl4mdl*6X)!7&&w^z9(=trPPCCWM=rgAfxl^?nSYm(}LQ|Kq zO_r+@v!xWW*}KaohIRwqAat=N4PISam&B8TNRs zg`UNQ#o2{|KHa;358MJT+&P=SkB|6=(uFd9EzIx3A9HwLKs~jwzNrSFP9=s{P%it& zaBspm^zioPr8E!;CS@N^2HhmIQag@p^I?9WVXzk-< ztIm*g+qncOvv*@WcI%Ao|i@4UMqk^zCxQ)zRX!KLNiiD-B-ZEPB}mMV}U zuc&Yal~4yQCq~ctJKuiub(^2&ot0lzvik+x0mEA>MW;0_^T72s-b%7#d>V9~ErQH$ z`{LB1&TySAYm3qvBjvUa3U$>=zvt67YIPZ^eo#zdIopP@iuCVf>sed2Y#HBz(=j&g zM5?Q}r>!-JnLdp7&-=l@fq}_Q2qq3Dduv4NX~1)3=j^WH&Rvb2gqQ@y{UO~-Z7<4gcSQ+3fr z7v^D_#z`knmKehxlPB1xCD>vrZHTx8&XB|)onQ8t|2NPr;xu7ehqy!JwrM+F|H|FTLYIjjpSSAP0P_yADYo=>EKc-*FfkmV!kD_piv5qGu!kaIEw)Ke~SoBZ_>g*@SuGTtdlfH z!Fxgfu(B-ZiY#cNvujlAxcwCWB5u3ufj2e@%G{nPmnH$uZws7T0O#)soF6c7-dKPf zQQuA#+ife7A}2uCCb}C~1q-~BP4D1?bm44#f0pA%8Y<)D*9?!X*T@zS zTia2@uVowNd~9E&G!Fwh5q<1y#UqHK7R>Gx#ue;pS^%84ViH4HEm_rc z=nQA5KN@y?V`l3mAh!7Ro8SI!TvJ9TJA}X)RP#(;G>VQS+XJIf!fbv)k!)Go)+_Hp ztg+vic6x9MIGrA-U|ylb9?c6UUN=#P#(v0?=`d4jfSE~xz-k}V>Y%j>b$|CexJy&o zw*q2b`+k8V2soh@Q#3w(ZC?E5jn-Ce^AWKyibXm^CXX5$QntRpqD}C7x_$Wf3K^WT z54-KnPOQd2Jx5rZm=YXV#DoEc3aW!()h&3@J@|IEcJYui<=k%xk&(WE|JUR5fi-gX0;!_La{@w^YWlc z-h^^LewB$ucEY?}9Vj=EJZD$m^greNYEy4094QLfO}VAvK=bZ5%Y}w@Al-y=uAr@9 z|7;u6_uDizurO2}tOCcY0P)7jJ~Hf+?nLi#!FNHJ?T+^!LtN?D@#?X{@$^{Xs5{m^ zS~#|Jw0P|3wqx6myAy@uGXU=*eQfjttC+mT2v@UI7wfLV!%l(Xq!gHvt#jw7YxRRk z0>j|CCBVcZS6>|w?1Tg*r za6;6i>49e-TluMD;JcZN$#yt;hM`8arAiy)71uUB90xY9hj#_MpM2sm6x%iQa6gu{ z^f8isJ_O}-SzYl$@^WSfmNVrhAu~6?O?H$ORLgj?=7YUOvK=*6WU3%jLlY;4gAA|_H`!zWJ$pmPhUY~xd_UUam6hD1K?bGR}((9A!@ac&18{n9$VZ%L=B_9>HCq1XJ z#HT%qkHHS4ww?vXNop*ZrUXZXdL@x0oto+tj$=%w`N;VH%0p?(TNt3bF3YA7>h(x7 zbvY156^qPs!cDKfyM42fe)?=mxa33>)q%1$Pxxs-~}j{;WHU#(FcHiaU5rmMj;6 z$8n(<4)nK0ra*r>hsdyTA@UajfqzMg`)inV{U&@w68KG6W$LHAq8pA|yTT>e2$vsK zy4=IR%`D1DLJJ!>e8hh@*(XuL?jghdkAVK#wsiYG;C%}8s(?uHdS^zfIpM|zsC_oR z8v*e>VHe^sOm zSi3_9SS$ni+Y?iz0+9c>U_Sxuzb4p!#9)7WZQCT_zPiwZwy-hZPpqDszh|z1TVOuG z-pV>GyqC_d!$ezYY#x2l6Ml!7D`$y#fwjRt~)+*K4+5i`rjCD^DLecBj}Nersah4 zCON(9EZr7N^1STM8L+DZ`a^cNP2=7q?*RYreE0iEzuT8H;oUk74&TP=Y+p`OKjsi^rY64p7yN;mAJDsS_q*`W^^F-uOd*A;5i?B^qDah}FZRqchbGbo`j)X@SS_)VL zcxAZD&jI)X*o50xIdJp@96hQ&?>vsXIi`N0LQvi1AX}Pe2B*pk=4gg*rK$>HUp_F#(OV*x1LgGgEmb-j23$?@9p`mvs)$Bykd z+DmwzInw(c(7F0v`AGe}UcC3-(vfvQiKD=3AoP(cP}&_`e+(ak!XKSEwjR`;s{FC^ zcppXhB$#E#$;EGI|YtoDW`NtJC zuqaBDZVa#|XvD0ZMl3CIbOLs8!K28o#o?Z$Ybj|?We;0PQ3N^PiaLlwNC`9Cp%oC@ zR-2(F{?C!6ckVWm5iZ0=jWn7Dmadu&hZ*hxFL^-==9DTAB;8@u3*RP;0XAHNXx+fD zVHv}Q1?)Czm#`1_^y(d}cT|Mj!0?H$3b`LFRqx=ybr~uZp_D-ovn$&L5 zaBo?I)>sCeU7wO{`7Px1B|D^cX3*h{Uxs1Fr|muv3!zhM|K_*ec=Oxe!9g~T&ap9@ z8@uIJZAlYJ_hzW+r5>kQktvxHsI!)Nhg&Kyrz=GYy;X3@3c?&EJk^W=vOmMOjNf7# zQe@L<8j}(nRJSE>3nfEfOygJqCb2x15KV0zi^S1UBBp`EX~FVmY?HW_P<{5ZeiH2N zI}aVa=HPzbwk3?_))YJxlJgns63&RUdn>$4T~|mMY7uOX(8$H`nr| zz~}}x=vH_33~U}~aWOzm;A|JrFu{f|sc|q4YBNTTTRA`SPdk7ahYfmibe}z&CN4)d zjU$)gvUc+MT`6E4><*(Vp2KDNJdsT+zjjctY;-ycuo*7@n+VL-H{{5^Av1c`%iR_I z2F>oO1jw9zGQGBV-L;MDddW=d*SD^#1DA`}fJ@`Ip_nIE;{OmqHOYKUbha6JgJ&u^ z4_i>pJK(?unS=)!p9pN4y&Z*f`ZAfc1gVs)$%{LtkY)$?wp;(*t#rW=sGxLCeC8?k z-Cj=U$%WPO_^jzdTVrdNw*@*~(+Zwx?An{X(8rQ&hLnF!JjE@a9{7WcvpM=pX-t01bTp<*$Ejyqep`@oy%v zHeH>C4!XMjQ8?s=(5~Jmzdz>{5TTRVbS|B5EzB+Up!U__!Bzn;RUsIMm67IyQ(OWx zD=?1ghSL$z+0*G&pBmQ;c7W&Kl22pg>lZ(hh8_s@_q>Sy21}n`JZd63gKA&;5^Zpg z&$*o1zvuDR`8FS%_$;|-4SddmYLro>qA&7t%k`|;WU1y4!0z@UIyU8ae6BJ%-oQ4! zDX{4p(inwPMCJyN`6O`pMd9*&r77VuBWR6<)_i-emn^S7yAF5@Oqe}1Q<(no%sD(Z zKo*^z=Ja~J=RfE{!EVkbbA5a~UKp)PC4k-p&`X#5FGfdkv*8%hN8{tbU$?b% zUU0i(B1fK`M_^9~$ObZ=tksX=trik81DauSvk-HcF^Se8owf~G^86GS(%gsd`xx?= zerlUxa-3YmIV6%ZO^)M=ZjzVTr~vcpS@8t|n@-*lNK)-328$I5gzVaf9F-O}?HsWPo5)Qqko3IW_{UqM?T74DQ=OZ~Ov_@a4n8H1Qh5(TvroW>O#T zgkVpTO&@1w9Lw*-k*kBP&25Cw7B=>ryK!TBZem%<8eYna3+b*l4C|@o^`gWK+%EO( zSlW?b?_R>O2Yh3f7I*YuaIuMHJv(-kF*^cC-mwm!;eT`ZD8cV9?U-GHEWWhVT&`gR z#c_9T0}^<3s172{B|h9GkYEpAg3)bab@}~9zB<(JKvd1bSqramWVFu5_iffEM!fcM zbNSpFX5)y_o*;m0$&g*J8Hqj~AR3B(y?TJy?n>Y=;5xmg z_Q@Wg-NLo?Pu8wUuTF%|$rTmo+}VwiEwsL7y8(r;qdim}~D9-UT+lo4mLC z-NGMty}L{T{oZ?XM+#8ADRH-swgU>g6C0FLLv-q7g5_q(Y8_OWtKuBI?ezpL!WPE9 z>gNcyBC*8KR}PPT%f2RGW=?J2pT*;cz0B?T^5;zE4tPwy%$%Ct*Cm~MvnAC!bna+# zbB&6H%LT}O@=JgmobHIoW_H8Aw`n%s5?Y+WRbYFaj9}-$ z_%SVjeu(n6soVcH2gV>NVUR0Y+L0`Ku512d-I+dOT9W3WQZ69A4evJY{a z(}Xq1HieS}!{T2{N$Q`do2#t~FbnnQhHr*N&mCn=Z^eg10@> zWqiHDOcQSl(}gK6Myuo3`t*7pEWAxE@Oh}tRAEgK`OgZY6!ocR;ngr>J z_L$*9Ljbhf@~>0*6bar?IF_WCyVLX2N4k}@+VH9@g!3AhD=8&(VRLu{9-GB$ zuD7pmgJg!yz=AV0Y*fvhgw5!oC&(sXCmx)u0B4N!Z`?F5d`^JRNKDoiH*h?GT@0rZ z<|+R}o!;44=>b)qUY=X(1(+=z!WO+HyfyIF!dnxAifCo|q1#bL`lYZv-Ej_Z4=*YH zv}5~DU^@QIEu!`EQVr5YFLiG>&<3-vLCPUo^Y)npn}2N4NSG$--K)gEA>iJ z9)zZ~y9CSFBgw`^ksk*Pd$_J%RlB-)&DAT{^q{Y(U7cQ)e!^XudZc##=Bf&ix{U23 zrQk#WsUIW30Do3dV@k&(bvEkd=M*7l@Y^iSk8LQR8b_U3qYeqkj=4q8vK?lA7ZCU} zotkU^JFaudjeD&L)o2GPaO3(@2;3Eg$cfVokz=79wunw)5gz97ksm^=v5naS2;0et zI`U<;qdg#owIfsS%>$8>cWZwvynD|d%kNhISpEMQdk-+V&htw1sp_smHvkf%WJw-t zJR^J8W3N5?*xt3r-d)=}GrRNbSj?g=2PKjql_=S}mb~+fMF54W|K3}vtGkgC2?j9d z9A!}wDUu?oL}f7{=NyC@=aXW0C3X+Fw~hOS$FpF%lKND(&26y+>zwmR9? zH2V^JI~u^a#7*tumKbkgKkK(c#HQVk<6V?IWO(f)VaK*j#%sPVWL^O>zX~$nYsh>} z<8ni0+-4PaJypufpfvsIiK%xRk(=Zn@HhJ~l}%R2?$zzzomxLRu7BTdcBdYhO`Zly z3#auUhwO|qT=kPv+}2N4INQEDHJO3%VQPe5BAu=-1J0pUVR`ohDzy_JoI)lTipz|4 zl{@^^Tg+(lqK8Gc?K}Cb6(Ag$Te4$0h-Q+bg1T&ni}ML60#u34hT*dZqj?a`1LYUp zeDf`q*HN{?DIgG1dcaufFi~_NjTKiE4L2G&$Uxl9@1pUCe^L^sN6Vu>Gwh5YBf&Eo zrfLS{0qv)@64e_8sH%LvtQi^(5i`8k*0A^74@|@n!$Q=6Wr9v zSO(?Nr0uIPEJSX{a2@v`iQ5Y7aQ-`nE;JAhX$ybDM7)?F7lx9Ie6=-MrCn#_23Gi#(s+X=?Ajyy{;8nwxbjpfp|TeMv3Uf;<25-$@@i+{o)9j48A zW<5|yvm!*&WQELtX&Yml!?bK?4~suS_2F@`uRnoAD43pYJpc5kfBf9@78vs;?H%Sk zo3ee9N?OywZD(_Fd%g_yAyBLLTqk-nQFF4d3U2vyb!xgZ)n@Ls&{@Z)3!M@9)4FTe zhR!8;jcCi>>mZ7Ag2FwF5XY9zRdE6K)7AvW*>f1v2uAX6ylUc~ zjNLp=61zylF+rsSQ|IXgRRLhU&oRNLG`BvLe;Z!NcV+!Ahs)r|1t zo4qxo4A-UbPS<6Mm|d2f)dsQs_!;8qrg_VsR&SRy?|0@j(Noo0c;TW(8L!QdDFe1D z=$R!nE07vG50A;hqZrW!my6yJuvJ2rGT#=G&;~s$p%wdPQT}V2wBki{jF7n=75|rE zVe2AJg#@vaPl3pvX@l4sKiBzec1iM?6ogJdXq_6F*wC-K=^mh6bA5P$$wrmOZ6yfW@)`V-$BS$VVuVjtu2m7|je+H(MH@cr1t@lnd`;{k0P z%zwH1%FBtGy)sa{No6hlyY*(;$k4xomDQ~X*Xr$RsFmcctx#518(^CNQ~9@bFgg1qC?9nc=Vixgs>3g4f(F%*@X0*G} zKM##2YQcC*Ygv`G4ubIr9C+MsPqYVDOjZX#blb*w38Hn9IuEltqs5^yfWGFEIXHWp zHM;iEVQ72r9vg*X=uG*Xw^}Q>%rOS`6cZ<&c>M9N&+?hAe$InnE(3{k-h#CK zAIkOfCe8hkZ&S2uX>m&ta(ISD@!I4vXsn>suqAYEbtP`ofzLMW=-gg90;R!Vr;5(r z=#YHK43#ejm5+nU*BdHtXxwI~Tr+!=?Q0aWtQkxRIGm9d5j(cm^HGLI$Fb2ObgF(neAM-T#m0=v{w0;8Mw^8m^XBR z%f2UCQ42r{9+le3wQ$oD(ZcO?YjtMZw5jWFSZJ-;5tkvQ59ez5<4->6xU55Al^Ani zCRd?3*MG~%8kAbnF*{iH#xrD|lI&4!LDuEOn z%0|4Xf*CL7hnj`^9l8v1Kl{Z+eJapd;^z0LFjG}_Ig@##&24dUiZMi^TjRlt6k-eRmDBw|p_?AM`<+CQPM9zq=lM6d> zokCN5*dD0_E6P(V%CqyjnheloDsDJC)A(CWyzMgygwumJWb0e6X6WVZ6J4NxaCE-# z-cTN_UwNc{_%NVzBpe>&gMFGDuJGjuLTE4yau@NT+e;F=OmNfKy>|EF9eB52kcK8mP8X6hs-=+)suP2$iH!Lq zn#QeaJwZsmVRKr9jdu|7meF$;)-;jY;-H{GjzI5PWNj4 zWLCG0&d>Gq+u#GLg8o!}iVB{w_d3xn@d2%SXS;912ZGHk&1-dpbfdl*Zb7xl$nh?< zdS+b;8U&Qtko)xY>T9nDH4|!HfQt4jy}w%wVWTmG^^LoYA#^dedxQlllYLZ=%HZ;e zN`D!*oB4b_r_H4k<5Y~g2Kx}MCLgK2xh0Gc;I2N(e02al=uYBmOpjoHC(BcyJ~PQY ziP1FakFa(zh6M88{MP?q&525ECj?o9;J6;;&}JWi8H#V z+a!VZ%HE2B^(Lgt>TFN!QI+)_;$_t}YkQnXvwF>>jSbR?vmiF8J;5;DA23X}&n;V} zK!FD9HdkH&#%oM|drb{my%x8-y-qD&YSj;ivPk&+#02ZmAJAO zz7(wzC)jLhagAAlbgB}!h@{qqSK=a`Fi$hHV;`5PrY@P9oh@WmDIUdhhvr+~>GFBr zQwtxp6HZi8BYP)YDpc8EbMndTQ{7Kr_L=sltDpLG@~HxllZ(Q_fDf#SR@47KsuDb} zR^(cnnyB4LW}kIY+vaq&YL&cFaX^-cm{;NDklE~%S&qn;Y5_%++()4OUS5ai=C!*l zKBukJo&_heEF=Hxag%b?^ye*FEigHlP@YnYcd5nu2FTsZdzV!ehUl*+ddNU)>}YE8 z&WQ}E985`$b-W6nJW@Fvj&#A^!$;D?l|#wlu|st6g3E`(;X2bs_>&!;qmPFV9a?vI zj<6Zb?(lP~j?{qlBUJ2zW4+^@6K(48IW%$UExaa3ZX%+G2**;;K_IJJ>kh}EH)fkC zTS7pwBos3|H^dfqtjWdJ%y(j(*m3Fcso5{1Wz) zV9@KGSg)IlU4q`&KD}3YZxhP3)#XmMC%)C}QbfMJiP{df_RM$L%g)=VXKCfE?pyw3 z*7}|?J4H%Ul$vA(iS)-}9InJ}6sE=zmsKWDSkz3_I0-|3NAwn6;7+qcB`!ZZVG@1! z_0$npeSgB-Yok!U+5mS=;~@jw%5)cX+|BEBvO5?ROPijUV_-Tl@g&%~oZF`UoE{rT zuMd%%$7lXUzn3Xr&us--2*BGxP){tDpHN{ZGhnw>G-Ktk+xT0?rFhS@!LDa`tiDz; zlH1guo?Ts2UYqLeQE*qFSq;T5_qGRLTh*bRjcrYnoX@_)Q?(|0e_6=;n5Ds=CNODE zbrim3Rd3tQp*FF=9uBe+^df#M7j89n%{-kXYqA#8?i7Rfdc7Vq-8-5yT#NcPfk!IY zSTuMNc34$MiTMj0zY6_B3^E_OfLrw%kf4yx{nobd*Shb-_N&g0}Z z)b0$mJ3F&~#^~v%OYaT{-92IzUQW}wKdQ2zH{G17fV=%QQ>)i1431Gf&ZVHsVdbhf zS1w;U$1aUkE2k*2du!UXx}`v?S`Yl_nUtuQ#`1WuJFj``zR1G)#GI8%TG*I1I%J5f zN<>6t{XDXYUUqN90!d~dE45CpaTmvBTG2~w;&~@Td?N4T(NG?tdS`&j-Y1o77&ie(eEDjgAhsCb-CMZL}USq|s^#r&99hsS9>!L-Aie;NC zF<GA3b;@>H@bRg-Syx#m-c%v1OG~h*3$64K1H-BrU9sPdxW=V`Q z3R_5G#8Qn-Xw0r_Z7t;EOJZFc2ZsA{@b!?7FDVS^VQ$O{TdQkhZVWk4b*-Ru8(Wro zt<-GgQ2Hx}Jl<^wdq5XTwQX1mM4H(yG-0r2XR2Glj;-`2yVXv&jmJTzomw^lO~VjP zUDqbBP3{htK*Bb$FvnBi6lFU%o{L&`HlBVb#|F@oyAKy`KFD+a0o*S>;(+*S>Xr#}LkPW7w3{<2;T=h6fR2Kw{15caKH9;kK2GsHJ?`pWrJHeE-J9rlQ5X_RTSmqpW2a=nQrfNp z&T@KA3ujq{Z7~r1-KJq%X$#20U2XphoEJO;Vhd+kQLthxi7VLNfoxlza4xSTl;$=C znhv`6}%C~`UnV%f-!>Uk*})Z>VI=@8I0B0TOJ3~qTRBE6)Qu= zW$XfFz3;eX4aS=Y-tV6hO)RUcD5z$0}okQ8>`wP@pZi|I#!$~zSPvL0>y*1+Ce`K zYjOo!Ow^>pyucpTwV$_LlX~PAP92K}EAdL^3O03ZlH)9=qT(tih}g+FoWX{O-9Dpt z`dk60mc6FtOfcMLgdJ)C>1$5PBeu$xTs8^#)lAq~&Aj<8x3IFtTw4vq&6snmYsPL$ z&3BoHU|Bm&`B}+01g6^CxA|0KaVde7$>Xjo_^5AbE^b&+UAbbga*Uk4;kZlTZRPLN zH5n~kG^hjM@Pl}ETv`CQx~LT@o1d>>(Zp~;BQ9c}OlC&Ruy4>pjj=dp;GIEu^hQiH z!KQZNrWG9_+*T0Ros^Os!ohHMaOu`s+jR36(Xwl=dw)>@;Z-X^F&th&{qx{MRv`<- zRUT)6c=r>ReX{$B?BeQ0fOfJlxlo{;SUt?zD#LcnahogcC9%tOaf5S>+RFvE?rdu- zL~3dTfZKv&)-b@1&dTF*D9P0Mr2ugMTg4tBdNDc{6WyOhU9s#Tq@z?6hlTSZFd(Kr(=Mzl~0@ibdMd+ zj`|sxW^!05FOSVTLtv+v&3)?-kv##~Q;@v_tk?NX`9p7jrs=e)n7d>sGFWBx z_zA(g&dpRDycKKauN%CNvKS^iW<`&%TV#gs?S2Iy2jf@t=5(RVTz+Y9gpcj+2wy6` zH?OCA`GOC!4b*m!-%hc6^&NdbBdpG7Jo{Vd=N>@AZnVFq->dd}9TeTVtQ6@tfmBs6 zl{X90W$Nw9XPQ*wG{%f1V#|n3?8!1R+U>C=`Q+nlb zGm0-u7{NwDW3G~J%@+R=+@_GMPDexw*z3@Qnl0%)2K}Ct^$kyTtyI80d$fG1u+>Ls zJ^d`)ypLIitNAqOVB?#kF(oAf68D( z|Mux4t4?R|PU4iNlXTEVuJhbs_6*z;P}cPS?^(mX}A?e-fD{O2sLaZFZfIJnt8X?nmC3Z|gDE;>uSV|{){V`#t zuB>h%;WD}A#WV?!bJKurn5~8tpn(1Z=@biFY9c;lS8QKuCW|= zI95Fhj*n1^XGq)KLvtOth1TtZ@4#6-c;Fx)#e02t@W7aT#k+8@d0_d$cNwx5aBo1L z9;zJf9hwH#P5d6Gyu{N6)!WDBA3uH^0s)0U2}tPBPF}6O#-MWa?JHdf>p zIo)u4u?jBL@XCnTNWo>Q(XE&_IjLq~9Tqi!_*kg}kU~gXnx2TT<^>m!;_$KW&|fW0 zT&Kh-6R8=YP)iD`eB|SuiuXzscN6-WO;PxSLwdr8Ds?#qi{d>ho6hxeeHb{)0Xrtn zsFq@_WIb8}Z12&sZPgQJg)B~&mQ2G_twjqCh9-k7jx=r6I#Y72T4$pCncXwmr!#nr z@>$Ib?degp#A#F@OG6|BHL0)SgjYuCbyv=ztXB0s&CI^miav|!AR}&j+^$+~C-toW zp}h)ES7a-zt5$aKq$#$;nighs3o+7BIur>pH=>!8MnY^HeZi}30?1UbO)6N#a$9qj zhR~vOniw^s!iJVuUaqvAu4(zH)Mg*{_5cBNj6j-XT8fA{LfdwG)zyyBRztmih|op! zr#MrQrk#&+N)@7cc0qb!cj2asIt$YavkQ{*Q!B7_9FbMn!`yd{%3f^P^6+U)G5sA? z#JDG+>nN^(l=Ajvw&y5jl-Y*Me{4+8%x8C0jO~?y*(Rl_%yxl1Cw<|9BD5}jTrFD6 zsiDr+A?d2Kb)H-IoSKU4jR{F`yl0yx3&}~>4=A%I)@Tq>Yjr>)uMq`1ax}$n?i{MC zjy`m#cW@L)KG-=>*`FO4rGng_9JqOZ9XvPyD(?>mM)n`rzvjS*VRY+2a&Ux)hl7;^ zlLxDZ4lX}bqxL?GdENDbJ3ETYtztVpF~=(HSE#f(CFJ$_9O(51jXPFs2ipR2R8~yv zv`!uqGgzjy33SP7{bL6~Jhj>xH?X>a6oa1E)w79RnZl@@!|G<7v)8!iLB zjD*Q(-dc|bhyw^jr8yw0$Tmb4B;#ecdVUo7!XVkkkC`8x7upDw)>>_t{L@%zyCsc+ zuEE~1dn?a}YY>@%GW+37Q~EDGb5VAN^2WpxD8qTo9hwmdQ~E;k-muno4ZSF})ubjr zI>RUMQafw3NQ8CXNOWea_v7mrIG(Qbl@4je#KRGR&I2LzT_E(&8v6~Q*EYUw@Z6mk zurqUvS-02e)@->lpt{TK z)a*gdbwF1SQ=`)?y1?*niXFuD#Oi5vSxa0G*0!Z|c$2_Rj?IOzKKt+?%}M!`S&Bty z%;#?p&1*~Pn6Mtr>v$%%fir7=M$6U}SFp-0mgCC$2ap`^y62wzH1Zq$NaggSl+&iI zQ%ofeGxw=WuCrQCJ+7q>a&~?9*XsuUTWeUTTXKiWHXc z-9^ny!xtM$(ikj@GqOC9fwphozKx}6WRYc=PX(pn-xj1#C41~qmLj4L>(DD{l||Ng zV|F!sP_5H+PMckALn;&mXQc_5-HMcs{#VvK9Sv(QrIqhdDXk4wrL@=5E~UF+{b}1+ zh0GUuwL{?IT=|LPM-9jGsJHiaDa~t|xeZA1NST?P|3)2$?9bleC9l)H z@4GR-;|7g%{!sF<hl)a_oN?_tjShEBI;l@-lgL&e-k>HlOoGGA#dH5-EB$!=S1#ss5ylb6`x zqMB9M;exSf-w^C3fghn7;wmhG<`=F@1 zLh3=Yr_s)b?)dlr6TLF3RNg9|Ye$TDt~&b=zqtdt5M94?%$zx-t0}$Rnuf?$r8HI; zD^hLY9Ru{#o;JYDfE{Fi9bg|8+wP1D+j-tqZV%0IJFX+D=sCET3T{HSc2JichHX0f z<6l>$6TzK5wWzr7{}Zl?do1v6o9k_MN!;X@gn}PAx6LhbKNmR$zQgKM9o%hef_(*s ziXk#g$un`);!1=lS_v&@q93v_EB>lfmu~UHW*D-y2^2r&x>+A zKMIMoQ1sFT_^f=3S32O^WR)j$&d2`>dF6<0`Wt9-)H3((1`B~W=I`T*KX}OZ^MA4( zo!SgBeNnQwkCKGe$-?b^b z`cATJuHDNw6nPuxBaA{9o&AU=;=?Vv%UaX@WdnrwwyOAqA}AqGo{)lSZqR8oshviH z@{eDxNv1Be&&K{=n0WiF^V3=2?^$wzKWnAv>Q)hN;BQ@wvt@P%e>2P#2Eh*1cr*)? z`+k1?Z(UDpI3D>x0Mp^$vu_q0MmLpr{?Nn8$I_3t&+lDOmo|Oj1=)p_3(^ZGF6f+} zU^>@XSWtoRU}MMxj0)U^&`vfecDld?O!Uc*8dm3PZ19?4o|oKni9o18vTfMxR7aRW z>Uule*aY`Q=ruX|LB|Uq5ps7tW4@cFRDcT(^jgm)jc z_QM}jA6aIuu+-_K_0*h5!EcHtd6{p%y2lt{6P=gnA?`@{VNS{gE+7x_PryukCKb z7wwUUkNnsF8vZHyVsdG9(WM=veg02&>n=(zO(Jpd_01jvcW|9RYkTV!McUm}qFMZh zvfQ7wL+Q}2zTr{sw z?L!?uFX5yW=I~g)D@8;}2!MfJrN7rWS2)5{6@jOHfN0pw2+v zsZm9Q84@&@989JIWk;+fZ-VFuDLMpwgw7s}L;K+*htUN(7^nHk3KJ75%eIq?58O8K zc~&9}lT2Hd%3oWB(lC_yog*j|ucL4{?Nft?@?88ZKR!R7Bntg-C(gKb0V@~!{aCJ< zsrX^P*$j^0PE#EHGP~oT9=&dm5Y>RLq~0@oj0ZzMq)0UP{qhleIeCb&-xMmbL) z8vU@c1RraEd~kl{g4O4DK0eCVUkVS`Oe#noXhKnmG9 z(Q z8Aa$dzHFMorpEI|5o!`6*x_rE3-AP{WUeqOuae%MH91_hhR>a)fH^VoO4{K*X%?se zggd9w1q2}Z12YvlP18w5$=mH}2bPLAkakD)x2vZdtk)?zbjV5IwcP!D7U>5*@PX4$ z=gk~~#0I;$Lr`c26)LeYV8T#8e54UA`~vigxKn=GNnsL12j62(R({1!UfWi42jAS& z@*vh>{62zyf%%MfyZ7ER)sy+KQg`0wW&>I68o(zg#tut1fCxvgAWxuZ@UTf^hm}E* zI+pxX`-`KLK$o_^Sh+M6;v1>;^{bqZBrXe-L`u7Divd5#Z+zB*_AVQIOa0^D_=aW} zSks5c?V?Ly!U5D(3l!-0)Rf9NK|f0psv4Dpi)UE)Y|AC+FJgM*UBs52)Ht9p_nO^{HvpQut+MsynT~NX_m@Y#MNa5CPd+$qZb5 z>|k2)=r+@WmrpgPubCR>D}7^XYV|a6f9wN#F$wJ}a*q?Sx<*TqB zT*xd0kywKOiNiyucjND)BiK||vk|-oya|e+8W4)$sl7XuzcMQU00{So2PzLH4L zbI;nnE!2b&_`np_Lb7jkKYl__sR1tb1MP#!p^S$1mWc!5M0mN0^Ut|uO5?!?3>D@3 z%PUYCFQhdqyEqJ_Ob0ahBTU&;*PIN%22Mf-ycGjwNo)Yph)4=+gbU;=!c>8LHCRV_ zv5G4V% zHknp7T=Cjzz($>1UeA$VQwFH0y)m8F8gB&G#7u%FPeK6nnfMFh%NkJUNAE~>I6Wk= z|7QdHm5ogX_O~@&GO*9c)KzGxrhw-!uBfEXPBmG{&|6skNZL%+fbU>@a&=lGWdtF& zgLwE%Z)1F^k0dchfPAR|nC;+wMhHJ617LxAjTYD7c)702mn)#B8F3z|7r^`AnDC)r zG`ZE9i=)pv3`<>-7xjPdXHR&JS!%pWCxw_B-d?AG6k>zziRKBYs?U#fR11<-_2KViJ6}`=*E??28gf*>aF60Hipd-{D z#k-lKE*iAIDrUod&RUuz$$B6_ zc>pW4!ujtl!@O1aZV-eIaeS=7y!-)<%{ePQvwcQ5y@jVg22icg=HFh%Q3?qKe%mJ~ z=yIsArbf9W7zTy86=>v4l`PG=71H=~SY47m`;cc2+T%A8iRRC3QzJ$+=c*`DT{Ou# z0Po-~``Yf{^MnI`I2wTabfSaJ@X*Tb*qlTA!7gVI7-wClQPMqp1m+;A2QOht4RJ6y zKmh;!pj?s;5&iS@0O@ZV6E`cTe_>qKv(*96-&;qE7@+6$y=Pty0xR6XUpYX8VQ4HD zuv9hBpC<|X%LdXE=%07pdF#Bn2)`{~n8M^*lYmwD*=Aoz1lED)B0;z}fd8!rk_W2~ zJs2Juq3~Ju@LY)nSPKXP>4WJ5&HKZB$-Q%p0o)~pG~CfBgaOMb=jG6K*T!uzw-1U~ z6eK_mNJjZs2&_$BM(u~HgH)opI-q^WOe|ZZ-T_ju0MEF358m(2k_U!~g2)2YabT;~ z^?{j_X~fuAx*U!}SBR(pllid{bPzz)2-3@1%=*vPWn}jItEX1ASJt(LSE4#qmIq{k zY=7OX01&>ymLO#y>>WWDnA&sw?#ixZ+@^QW1D(J?Zo9es6L`WE@Pxo4D|-fe>(UJN z?d@YH)RafqpF$5(LW1E)I2!N{TF`@cnQtI|pt{)!LSp=YSuMg0>NOn`29$J7F0lD= zRG4-lSd?G}LEu$bD@qGesSnR>16fa3&&m=wXS`Lal0{E!q>*i&?4D)0zz%4MY61Ev z`{{-)fXLtwRaj%wp$)!;-;P-cqV3m_N0tz_4f1TeS7a_dXdYw_`Z&ZK& z#>$^p->{4v1AM^8@JeII4{~Y1RGeb#wfbt8(F77$^fH+UQ;PrN~5zP_PExoQp;hWfDk~hS(%H2nh%0X3&L>HJF4W9UJrj?K~*r@MR+o zN*8QtY&X(i=0V!QJeWWi7-6@WmSo>UkqR0(VNHrF(4BU8skYIK4T37jgE^%iK`M>)`P)q>S|ZR*!g2pNb^ zxL^>@ZCZ<7lgt);0=UWL0yhb0*Eg3y{%6S~$XoPOaQOf*1cT4B-)clj&L@2I7qXLW zwCuCmWwpu5B*^*1`t@8WkxzV>O%*ZiCOK+Do8Unt1MAwCbcTs$TvA^WNykN{3?LOSOuOYRuV7hV#um_5aD+`#6>kr-a zat@)KfR3q(mI8uX%Q&{Zs9YI@bwo0AhL4V)rmrxmQ>Bq7c(5QmuT`FVip zvJMo0Q|?x!rU3*yY0akQpkEjTU^bo!0PYT`>AwC^6RyI?Yc}aET-aPV91L$u(fol} z{TC4eTaZ-$LjsU909dXv1gZhW;GOA~%m0D__>Laisx3$0yEz2lSDXUGB%w(FrU9^} zhdaYv&AY=rt$R}#K=pz9+YiiReLTpGcMtX-Nbb+>gC5+|qU;~LGuHj#wuVHU5*t1>-={4(?uQFGQO9K|auB>aANdINKXd#I^kobLy7goX2=wI&B+P|PKzzm+ zw%rrxt{RX<&9sb?1J(TpQmg-~d-itsjBwRX@16sI0W7;8+EurYyVBiteZ6Z}fB>x6 zJ=d_GD_r>BF`b~cSKh$@*v|m`lrkbPR91lBqAY$7ZTALv5%J9-_<6}8aKz^fh#}(J zCTe@AxUUsuIphxwf+!Kqfc#Q?&>ey(3dE>D6a{={Y@Q#C{QwIewSBIz2)rY}6jHX9c1s zaGxg!3uQpkz*!!rjq@01ApS5=8@` zNmnH`b{t4}ata^#$Mq?Jg6zC7+yjzCUCIgjoD&APd5P=n~NCY&v$B%@Wf8Kc-K98teN(^8g zfFgM-R*@L6DlBjRE9DKf`wq^5H$!adq9FBc|E> z9>{>y1$DGK8PE(LV*^hhooTkR22@z@zLEn(Y&}kcXvXD%i59lKW4pR$AjPm^Z5il^ zb6L-b2YTP$+hP+5yDB@wj)wEtNCIL^K&!e$1N@L8Xn^|t7%s0AEU6bUS2lT{BtbDJ zZR-~I49w4prh&^@aeOI?E=iTBdL*Bu zgXUz9TQaEocXYDWLp(I)7{VUMMW&<~u`^bVBE*s|kbRJdI&7f#K*tEDF<9W#K_{t) zp?5HA&OH4GG$2^Kz|yk$#GWW17=OsuaNb8~T`H!L4ebMJL|xUo(s>SGM^QmgVHiDR zo4jTfp*Q?{67gRfIBYWeScfb{jSz0H-=Vtj&g8Dv-RV8qy=(7l-<#eO?rz-$ zvyedG(E--h&?d-zg1AAtJr%`Mc~oVu0J7(F!Bi~M35;X zM&_{35JsB`wX$!6A|zJCx@!Oa{p!Wkz+ht;Cawg=0jIAFd`ex% zLU$RR?|})4M~Gw{4u=}%&z4yQ&pNLMf4iv&TiAYK6)$2pAS2As5iG1FT48DLlL-ki zYTzviwjq1N?cGDm;kG}S88(PC`)XY_MGR3ayDTNBNU{q@0jR*iY+@CmZ!rK`5*W8i zt6@UafP;648jwJJv&k4-ajYgY``}!p4^tWuT0{$aOqS{$l=meb@%4g7e7~{Rctna| z(6?bSebENCn%e>UZm6_2a$C)9k{it*c7qG>F|=S0Ef!geQ|soK$<^XvqoNHQHyafK zK1Cs*X9RKh-L?aZ+Zwsm#>L7D9|)%_OPHM1f*K6l4#S5|u`YyMBZ!fLLLo4Tpondi zSV584a>v0>ii?5noE2Ch=8nTmi9jiClL)Zc)Ou*7AeRXKOj)e^HOt4F5sVhZh5fXp zYm67Ls9h^l?~UaPoEn6!&27o{up`|$s>{B&tGP4XF?Tx@V5Bu)g^Gq4-YJX zKx^U+jI5eu!ZR1ofWwqB{}j)aPdRr<_iHosqnMOW)Wixq+i;>wb|LY@ne@1fhgBw4 z46q;u9geF^NE#4y)Vx3v20Gt;EEi)XcIEnlPNIPTS(Ab+hLXO}WXyn%^n)P8;TFSj zR30zLr&HS5?Xw+*Tww4~1Gd|XAeh473_;f$Pp7u{VZ^{hW82*6c0TnANyf2$yyn_) z-2xawt};LoZV9)xZVR^uREG4f?%h-ORPVkgy?ca;GTfEk*}8*o-PXJ{xupT2KxoFI zK!x%Q!H^p$yHZRsi-Kv{L~t=7FP&64!Sb{qQ4^$5nVz6gZFIk~DoZ|sMqB-(d0y`= z;sgafxI{U_@ag$+%7DcT!@{wA_)qwFlU{^6Y62yPa)$B{Tu#u*NE{u=3JnbXNj5as zr|Z(S!Hy#Aa++{Q^B@N+rWJHW!fH-u`}%vcJ-ywdLh{b8>dswjcAlaVK*FHC>+h)P zGbn#$XR>2~-@Ai5^xYj{XU!fMc2;(*gGbcFBKX+cxe~sR>>3qONOw26jmnDX?|~s? zYIR8HWyoL$qtxEuV$E)N@s)6eW-EDr$8jfYadg2@n) zsZ524#>1=ufFu(vn!wJ93?X@S=setQX;z}F1x3hb0OlOwk7tmCxSiS&@h(JIUduWc zAPF(BXzFX&J?zt@iT2~m1qoV>-P9{jOcf;Z4p>Qx9 zXuvI$KXlQ7XIn3fw&v(E#2BJYPD7?GW)ZmX@ExhO^n;bNh>w3=@h+@iF$9+$sMy31 zN^^Z}zqVAud7{_4f^-3y61S-=#M$-@M_`jF+=fUI;^kv5oNZ{XJy0@fFag6DB-BSNY-UC+GPM-5DXaPWDT2d?ARYgL*9Zk^Uhv(>z^Rk!cr zjv28?ldAlRd6`v05*~0M_*vr@E$TqLWg{21=Y>LbNY1XGbIv*Eo=fEx&ikc8cQAtC zE=2fnBkB&bWrvGnE}U%AC3&V{*ym`9uj>wl2f?pnr5c$A=(g{{+JR^24wh;#hH)cI zTK3%kF5!V(gRT#w7@BZkuAFfUPLfd1Lhi_sZpc}N5)M%3@Z#u8FKyYJYzbS_ZR1+I zylvZ_Y-?>zw~TH^Itwp0@<@%$vKUxUJELb7@<@#(X`^bUG>xy@`{_RytG(k6(;5__ z(OT6;50|y@j1r169Z1c1-6z+9MaibFEu9_xVikOmV^}mSO2cs{*ESBv7}^fQ!{9X; zaAD3dW=u0ESO%{rY7&}~SO!fg=Z2^@NNSkt>a_w4YEcl?P)Rz4O*Zg})oleA+Sm@g z&Zu-*lh&*whMq<&tpV5ARAdXu;LV91ZpAg6)0A>dW0%+h!2=z)II1X3ihw|5Vs)}+ z+_p=_y1ji-&VwdZ&SnPTqX5z`%pKYaEGq{RzubAS;Gx_w>gJimz^w;)5B4i*Ny?}b zF)(IeEi`IRur`|Y>wn$U1Mg!rYG8RYWe|K@haDt0)lEP!c97nl-O;^sTzLY$-POA@ zy(7E5bz5?4>y~hH>!xsH14^Mijk<@ma*c0mR{E4#K}jHDfY{40D@-_4FIIqVkCaCzTCYS>eKWmUD)=)4(j|7%$KStAuz#X5=+o-hvu1 z{t;@Ba6&QX5~d~^a5RXFhABm4NVraAdpmnZ_MJDb}#!5X?d_^BN`+E9emJIBNiRKrg0s_x#^-`ztmNYvg4 zjNx!-WYO;&ayj07cnj<0dOQjIC>kh;pvgUHLj(1KHe1O|GdY1uPKM7-G$fwo#al@= zD5n)sQLtEz5zHW#ZeQIvOe=a5BRo=+U^u8Kmkq3oF>-<@&4eY7@T(dP{B73_%EEzf zf8oV{Y3{^OIna~5TTi^igOqL#c@&5!iPNMb{iE5jQE4f?qnZ)bI+Q{L>O6xGfw1>q z$*7e+qi6lCR3JRxFsZ=BS~3TvaNU9oGzWilJIIn{+PDdF{1V z71Ru`v4|$Ms`+vl~BN zLGl>kfw$^?a~X{nDS|^yq=5EDYidZlwH{jrM-jY-Wy`{4qt6|+73yXP*2&PKp*%8! z#Ila>F+-xn3*3+hA8ix|abIZ4L#)`;%wW7A=E2Z%2`3cFLrj7#9)=xlA4b9TaKaQk zMd5D^By{OPBZMVAxb|?9vR)ofF!8}6J2pC7%9>esPjG!a_0%)5xkpzAEsZ&2*8C6b ziRYewF1*lwu`Y+=rOn}`QRwXE_Ddr#zVu>vVN|^}$xjq|+JbkcA!%HJzzG&O~K$dawfEPbQ?L>UhC%LcKCk1XRB`XfB*I__nV_C$Z>#0bv{O+1q$pkCX^ zgsg}b5r#m7vF=PFtXGd?LXTs5QX)a?jh}qs9k<2#&2B@?=yLo8IYy7x{FC_*tY23d zlw<@TY!R1?2wh)d6CPz)`71e{5a}5rf^_6?_1sOHAOWfpuM5{VZ%A&0BHSFH64l#o z?cTQP_7R{V+?L%sdJC&5xj8@}S~rC2E7yf<&o}m9J7G>ASY4$S?wK(x%P5FH_*zqZ zHtGr2{;3OIu+bu?0D;K)!*Hr_Y@L~PzE8MdK5ZiwiP0)V?XhKOvkqiF z1k8tE;({h`aG337#1)uKxxTuN!~$I^l10|&EJa>!I|wQxsHov=Bw5fJ+RG-?8AJRf zOl5oeySuvvkcgc-dpp8*l!NV+ZN2TyZ4-RFoUgO(6YV@SqRRt5?b zUFjMR_V|^Dv`Xw^ll-<)P#|z`b}@(P4}}1Uf;I+=EFERdwn@=TLGm zVP-@NrqI~4*QkQ21~bTl84J-_kf>|Qfy~{=7rgMAp&j^u1BnOPYuRj359IbD^P1lq z2Z6<;qSs<)+s0c`53D9D%LjImP@eZRBn@j7_5u*gd`_2ADX)<+K?h2v=6lRclT9gc{lfnH9TFghQ}JmjWsl> zy++X|m=#%*DiEex;|BC10*^H-44HW14t5bmUH=Q`OmXm@fKK?>eFCVGDo@JLeHI7qO)Q72&^FQeo#n3PJ~=*#Degb zwGVv=P7waOF&v4+7)149pJYU_rW(xP1WYvm!SWOQtpCBn;kg@8WEA=nBG{%~7$?YE z9MuAG^(JwG^KQ67s+vubq1cL70FFe-lF-_J;t8my9RzKPfzg8ReV?<3BpMJ}`0-Dm z2F?wBnmiYtue^{xU*l4E?)mUs`qS`}%8$d38d|1s39>b&56APMXr#167(2oKYVWt||mBCMJ5 zA~AwuAn}k95EXYf!ej!CK~guPR05|20hPd723NL_2ok0dgsBwkO)-HEXEAr<@fLl_ z12&@ry4ferJI9pjG^KkH>ml&?<<|Jf%&kWmbpY)5)^k;HDi%vmM_+NWl^tx6*lCiX zS66x4Cp%N=t>j?I-k>^3sxh6ai?eEUlDr0WG^&%KMJIz!KbM@~EI^%%nug>?gP$HW zUa)|0{(pNKQgQyDSq)!^1XhU}QCPWWI$Kw%8g(;B;EG{{avC90Y~TuMlHI-7+?@kZ z7LHTE$Z)vo>SWWHSb%6ia(&BaKz4KQmJy1d!L8L>Zq05&h> zAKM`RhKTw*!24;}46>bbsA44;bjdTOXazPTi77}{5~qiL1DrSK;F$9IInq-MzNYwM zt`g+!j7?trGSbg8q&HoOU6o{kX-g&BAdeQvHW*UEqNDLGNT0Vf799(oEl?s$#=)0x zUm11uh=&V?P%nY>>1V$AKYq&tTI%w4nZOzs*zMenEwG-D!Paeor%PauR={%;h-$S6 zT=Wi%GbQ>Uod*XGPJm)+3<(H0E!a|>$3v^aw$ZJmx1(vR>_7|;6m?XLCFYwayQc*R zo-$3qB-Y392WA@to*}sJzIz#KSn6BMRe`cY5T&#~)3&NB0s^Hg!aM>oNhQ8KMsRYE zfY&X`0`dsBsAH61uE_#F*VG2ii~{46SDN?(37$#7GpQcNHff`lFdG{ZRA792PiwbO z{+k8Lf2HxVq5QaAbVB1U=hToLq~Nc#CYp02ZiC)J@&UKr(h7)PGkgzAPvtv;_6Yc0 zzDkO3R+`I}j@XY@8vUh}M#e2!I?`AQBds)6FCF)v<1c78yYKV$ zrY;Py?MKJJj~0r33#JVGc`24~JLeVH)d3Io*i9S)<`npeTpd6jU_x><4|H8fBKSf0 z;XIK6=m2j&PJS{1FGzn}`APEQQ@P(+swlws!n42a6hI@6MFF02Ng(o6JT7m$g`+<7 zK)Ang->^9WZi=y$TLqBPt8BT#NVQazOEeb1o*e^XISVKz8EK=&`i;hK)OWQ*zr`$Y zS%9MK*YZe$ClY*HHbvJ9GMytdHZ%*G)MW5IqX8`<3Du!6;4Gj9k_=GPRN%LJZ3zP+ zDw?;+0Id|3Oywh!K=ttxhxCM4$N`ywRs{5I|hp;R|D! zO-QAj%fRzh_5=9r^4Dw%*VJ>&Pi{zW?A?^!JgTsIxT$$_c2gU)PeJ?Ewc(o9rU2SE z1ok=F+veuGTWmtK?G3!N8pbPqmz7Rh>T4abkY#8R}@N(>{BNVgxoQ z!+U7M#qSlp^mau05{8gpl>5pOG?{bkhJlW#%2--53<99f(T`*aI6sOZnq3Xd%9hul z{L8Gmr_q%G7d=>Hch?A@B)CznzBAiVqm4ZcF&|#;uiY z>DKDDt;x2qbqt0;if-%HYvBhy_(5gc02N@z_Q8&>O8&4bGcM4i-ft2izz9D)&sc!F z1q`pF+z+pw;vB$w7QNg@rgahsXi!+`kfA0SuZGE8aOJ$NvSMGW!`Pr(OqLvo3k1w^ zI+!y6w+V{mz^zv1SeNVFP652wHwvI>hoS)PkgDQ&;txGM00;1LKUO_#bzbyX#q(TV z@T(C(uCd4{YP(Rt(+>vZ=@vJuZ2{j>jRX+s%=mS{A zWCatBs`nob8xYY@A7{r@E}#VaU;2_FTpkRNoT{zUXM9`sR$(qSP|2#+qw}Axm9$#) z=ty7n*`7J>$B_k*2fwAbXa52BdBrS2Na+pib4(&l2}3u)QNKk$LKD=_$PgwNBq>P= zL4F#)864JQWH%^qm0o1I|ceb*m&L0zprC&($MCle^(f@^zX<>r;t3QnZ*N$<#3Eemw7A)2Parladp3Np&UFC|NPe*3hd*H1@@BX1{~&z7^}Y1jMh^Jj5^;Uz>1Tj^ zW3IV2_0LQNI1hXg=UA_A?y zhPd$xYrDn{up2>>*%Ol#Nx*<1313DBSTfgJ6wkLKu+QB%v!fQH&pKr$p2Fl1746LLvz zaauFP`L+7j0rh=uNw3Dstm7`5$WVkB`Pk{r<$~m1U6)BO>(19B>?`imf#f%E3pS#w zJFug&ArQg-jrO1oWv~GrFh&hNYQ@~axDy9zfv~<}jSIng9+f2>YvyEn|ek&EC4ZHPB^Zm3>=LmSS(_pWIgXJ}m+u9)lk zfa;;J{(Z3^@{Q3Yr<^i`$v<$-)1GrEoiZx60NEBzBM|p2QwB2#!hd;ht`XRHL!%6K z>R|Zn0+$HPpOQZiE}lCi4B`Cwg*{*rK^`yQ%t$P%6g?`lvD{6Z0Z9buy5`yxOCV)* zK}T$%V`pVe*f5OVyw1yZB|(goW_pa_Gll`WmEbGK}z z^0l|lmN}HL`a0QC*_v@nwv2Mm)^y95KVr+4+ej@Nr$~)$RJQiF&2jO;=)`uC3mLdM zW?uR3-B5}aa}=uk>4Khb@`6nal8^A~^4d*az)2{K1d7ZzltFk?jSGq<3M)95n7MVK z{a#mWMVx1li!j}gN@}sz8H-12XGlJ;6!px>g$>cr?wOC-yxoli&mh<)8h6p5li2UTW-Og zjygv&2wuu-1OtJ?C0ph}NsL<%(<%}Mxu9U&!UBiSmdS-q8&)+I*@cmdlBi$-@jP~D zssil7vIf3O-=gwthN_^=T23$Qk*YsoEM7-N@=&u7iIxcB zJ!??o1=lP{h^09PCtf~rLT#YoSa!5^Br#zjInYCL$(X~jcQ4TvdU3V72*QeBe6JuF z_cY!xg3%&kC~na+hhTDP&3Hi{UT_1qCmZiz(mz0=KYZjJp4Adq1h=qc+-d^dy<9A$ zfsBCq0QM+j&?1AN#6${#2oQ*tnFmZs6oUwpr}DeozN@9^nF0w1xqUG1_5tkSshM;K8LcrXtHf(B|s=0Rq9L0p*5p7yRLhE6&h`pq7T~xdv{= zLWmxMGiym}4@GGW2Juy+5KvXo>L<1GDE8k0=t$z2})0^x!~27)oA2`RESsT5!ey#ieR=#vqkM0}{_+S#z83@YlvCx6>01AuoD!(djh5Fh9-{z8n9qmm>RFedBF zUmJ;KY?<;c>>q#r7+3Re!!0B3?o zD?lJvW*v|0c|YgaO&!YFhpy`+F#2mpfl!Xg>FHGLHlw-uft196+7fg!c1pLcI6!U{ z)J$?!U_iDTl6Tj^8Q6z+o;R+C);6T`vUXxwhy{>Y7 z!mWSZ2xWR z0rs_uw2X{;!aZ#=Mm$M7<_b{?@?5~*|6TapZ-2HV6xgh-oQb|gDIn*GH88||g#u&^ zB*Y3^3^0^R5cvNq4j`Q)1N(K{hGYUIOFPWQR+kJZfR4`Qn3$Xxpr!7d07ok5*}ZL( zTi0%>Z0>AnZtiXQHLG!fl`WL5dgG&R`r1CbSCS$!@k}#vTRGy+uYqnn9D4y&s2s;$1nelPq^w|GDJ@EYc-{oW9%R0X*fl z7$U6u6huO{%jRi4M8P1eX%vn@kqsyyeUoKK*v%Z$RS_vfJ;Zckg^E%am@dzNosF%H z;>h9w+Sz21N-%Ix_rV8%dh|&b0P3xdr`q(&djjIC| zk=ZyW8f9VqZ?J_9FNopw;69n)Tf0f!Gk6izytT~BU7p2dFTbnUgmCOd)jK2fi0@n1!qc~F9P@P z7vO$-agLg{^wlNHnCIGz@G9im#p6LN52`ue4vL!WPJa}F)Y!6FD1@`(f%|8{| z>$@%P8Z$<~BYO4-%mY3q+`h47qCw68QKAj@TY3PAE3_BPSh6}0K@;h;WI5MPwt)hL z0)H;ybH?d3$i;((i3f@g%p7<$%xIB1o~0ke{6N0hnodidWg=~P#zDh&Sl?f{pz=_m zwS-HOwN&9*;=?vi?&_#;|}*BXZU zUuO8>mmV^eE7!Q3gK7mk0kzc|*Y1^wzMktU90Gu!qzY1jR%(nd``iuWHiW3E`d-4sBv3C+fGLUVI0+1bpi8gaou^N2htyZh z_0r!ps&6wEl*Y#jA4m8yL3aJF=66qb8JL8S(3R|<9>zd70_g>9r?#JJM-8i*bR#rl zcpzs48iXiCAn#HvjWUp(@Sc1Oa+Cxxyd?>QPhFxlTIK{c39&E~;vi&C54a>y&JY@< zcGk*orRvTYHKYJsv*nwEfI zoJ(-YZw)gFvgH&$w@6Vn_yM>BKWkR1z`ubhlu3#AI) zRM&!1|lP`e0aJiADUx(&@&i0!JyBeC?9T;_i}>#Y+|^OUB6} zYbT+IUz{$fE0nZ&@rEVuvrqK7zRNp4(HHtES=?MQxp*wUH{nzJ{^G?`OR9|}9m;-u z1f6rqrW|U(X~M0EV=$J3eyUTD27_es)KbAeqvCH7#||HSn~ERp*$e}laA-T~g+s)b zJ*x^!^_3C+XEJ^|_HndszLA0B(Z zdR>QkRhvuj0BhDK6rnk3nhfjpme?aO+ZfP%0t*BT>-=Tr3`D$V!W?j)+TKisW_Z8I z@!k$Oz{Acn0a1?q98aj++kF1<#TTD;@kPE3!@1<#>NvW07T$mc6&T_tf2q@~sPrLm zD)r%XXTj~xsH_RA$D;bhyaH@n&?-!k4nTzEh%77jlWxl3Zg01#v{UN*3L9UW4q2!Q zhlyf_wNR2qc_EvbO*$Ni0j%tfJLm)V58%#qm;kO}M_2ls15zverR^TVT7`>qo-R;b zquf#+xdxG7RJK9d>p%ih(t`_p0G9!(wpEQnR7c|c!WjTk)k)ySfYSgVC`Jlq3@iAh zx6lAkEqwCxdHahkUC$NB?TR!2-6hWzs4a1ZHUK6_=w&4r$pUzQ7_7{JTpchpfV<>q zfFl;xjhCoEfC^++rdN$Z1+H3m^$06oJRn?=ZcHw(dmxHaqp{q_^4PNpHF4()Q~&o& z7Lbbpt|-l<0c;w@^noD_nBfBq#}k#;UYtPSion~a1w{kuwgjzJK+T4^D&WnAnnOVN zleAz)+e(j&YMTy2#$isQ1oSPaI*Az2r89+n95puG-rd&SI<;kla(}Qnd8x8_CATZM zt$Ar4Xr+2puoX5h;1hjrU-IGV%}u8VJ=B4)WdwH6fgNn!+TK>(j-oxP2wZ|=o?1Jj!R$4`tK=R5@JeZXta4*)2tYK53(FDs85F?=2 zk}qpQ!4(^Svj`GMY<1S0?{)EVF`5|$b4@8Q?JVhxtH{yD3{?nRFcSMiV?nMJNbG<8 zH6}iKpFn^rC`H(WDkx77h!3Xw#xzfBFO8ZhLo_t6l$8|#7hQ6YU;T;bEok}kK07uOBpmuy;GS=8Yc7B{&qP>NX>F*p6;J4-THL}hVj z$q0-hAwJNy$Uve2$ywb744}HImyqc8@W_Nymzi}bruu=?btsa{{%<7#oSdVkfjlsn zhX!o6tW$s}`s--=yq>bqK-@&xLP=&RhRyz||G7^#G!7sV5UYO028;tJHeh8x*T&_S zUjbRZdea|nQr!g&IXOqJY4FBDA!gRVr?X57@n_cO*p72t| zPswjmKZ}og&82=T`6opIynic}{5C?MRP(Fx`~Qfi&V3>87c7ktIC+17rMEsdvtw{x zP6A}xkPlD_1UV-$5|Etvt7n`6eyW_*e-Kfk%%Z0x`g6`UL4l0(z&dRX+u*X8E9BSJ zkx={B1^*h`Rbi!dniKhW!@g+-8#TW>aJ;t>aKOE3M|=zP@8S0C_PG95gZ(LK0O$kc z5lI7NR`YYNlI#Z?Or&~$*eswUJu;eFeD;7R0D_G!oIUl};)6c7(AH)tKNvY`u1hJ` z@(;AOAWZ@EZURJk%9g4KtExZ!#u4eAwrbJFUA_$UB|CR@Iln+^?y_)sb>roL`W4kH zuULKM7z_IfE$(ndwvjSfBBwg(S|DVFJUwj^t43At2TqI;GRnO>5Cg)>b#hN-GP?r@RRW4x>xt% z2Mv+{nnDb6yE`v4^cj*4Wx3Z5c$2o&x)p#*z^&+V~zhC z#&#*8N;*G#lnhgr4;(R~_bEg4wu>NSb-SM{?1FSQ<%{QnPT=SML{x^o&cAsIlgSdUy0o}i!EPlT~#vbH9Y=49P7Cms$ z;;^W)I9)VipEVb6;;U@YglhsK4cU_U>;YybfG@}b35&QY{Yr-^s9Hf7XhI6!uX4qA zF{;0kex+^9SwV7U%fbNR+?v?|8u~ILDj3MqKyD6O?;WXQrD4X0U{@`xyQfb<{8(|%t@Yp`G^-N zZY%%nt6xhV%^vH19q@-47(Gb8K8L*Fqexfj*P34qUzuC1>o0|e8k$7UvL+pig4ZCZf31K|P2M3Jkske!2?Y%9m#Q-W;ZQLJ?-fF)~gEiYK?5166-%k-xh zofmlkCD|q6Grt`VmZ2KE=%R}}#vMc4QTx~A04SS=7S0X|Lhx*A;iyt>|;JN>1+4R88dM|{1{?$v|*P4{xM2PT~Ko$Blk#Jy&F zBVUDVl&|=^SFmpIBGjUoVQ;1E%(xo#A|xwxRpB|N35I#}kiMj|9 z!2#8?hYI9|fyNaoG$@%M&|*+K`)s2@^NGL#1NyUeZMLRKejtTMq_h>*=_W-kps~~} z17=?_C9}(AWyf@OH2ujxV+1jyswGD}=yqLbU{>25f&As3^KD_W^@Oyeh6y9HdlGjS%WmZmC4G8m|lt52o>}aaEM%1Q0Q< zi?I6tplvPXF|?3Vv5QQ z)MvssN9CM`@645;;LTWpUaZ!S0&+rz%}{;*x$g5TU+6raJ(vD8{Rs@@N8yLHAN&9Z zf!wxpj1U7?L>ELcau=bLxXOJ5^=CseN=CvAmN7#jD6tIbv$HhD`E@;MpH5GXVmnL#2`;2-FyxWIQHcb}YjrpVuP#Fxkq8(%fkeXbCus>nig3jhj=r)i{(A&{L;c9IayLh2s7ni{<`o=EC(DkJhlRg|Qnd2m5N!#c} zbQ~?e z%}2tQ8@3V|Dd-_UX9mW2xttIPG+WTPLE&g=5k{FRCkLg*L9IJ+TW!wD1>l1V2es5h zXZ7;?W=uh6?BGwe6Z<|~M7U;01E}Jh9#|@HC=;luyJlkqhT(vwH4!A|IyVSs*3U5Q zEUa4Kmqo$91HA-+4uJ{MBlP_zIQfaNnPa)SiUhQQ56ilwR6+N7#GE zNp@9vo*Nk^O<7sgAkk*p4n55FXJ==3%+5~lA3J|c145`Z2stDbG$24y`Km0F_1?Yj zg-KJD<&A`-s*?8}Aqj-=pz_|xmuN(zM)csO8`$sf-1}ZcmgrekzRbwT$W%nU`|j`j ze&=`2+0dLWEaxy3XT*2&XN>vwd0p`+6F3r%O137Srau^u)tu`Vr3RUGDB^l#DGJs7 znv@9#{Q^eLedt~sKt1{d8T?qf0z#cYXem(6Mq1v3=`6?q>P4C1X_W%K6B1*oKm>Js zb;5Kab4zSl2uomOTe!W{64rYzBhbrD4i+1@bwu!+WOGzzAlsU48@s7;^Y~2-NyFQ2 z%C>0~PzIa!C;}Q_8P3L}r;iRxhVya36gpG@x@}Ydx=TJ1R*rZkK$F%$O(1=AqB-86gEgl)jL{m!UXrv&Uv0h8K-@>?Zvw=Xm)kGxc(F#i z(371P&p7#_{&hc{eBwp_Qr#fjy*LDz+s8{UZg^=xvVr7;?B)KDHh4KVp*w%I@3mK( z_~CNY0>|V7k6Mu65FGf?kAhm@fBbt>5d3G+{2xt%zry=phy}#+Bm>^3H7xuNVO_zp z;zk-0TEz-*8%Bb2)S}Xu5wObBTi+=c{4-X;pcgz@VtB6*Y6;QUW1vSe=qd(#_SW_y z8o2$*0e{dP@`v3Ke>6MRcl_As@xBu@SLwI>!0{99<9){fbAEV)2T^6^D66jQb9>W0 zZubnKcnRa~+at12eFOEi*A8I9YJ~CN=%1<!H4AifC@pD++7SA++ky>iWpx{>&`KyS8ureGO} z4xg8~i7?;x(> ziD=|~h-)RFnJ*y3v=2%?Gjt~_Ab>aXEc4`RPZQO;XY((+uO!d;uk@n=kaK#j4Ve39 zXFl`HGf&6V6GY!?|AppL8(L~X-XlOSS0jKP%_;2DA@Ltn{}4z9K-bnRN{q}6%1NOz zh7}Q=^BE9b@@ynlY{LI3BwVrJ~9o_Ii`4N}?*rL5i_j_fxkU4CB}1l2J+G%Hpp;4d8n zrGlTupI`GC`Kjpux;mQuuP)z~x&M?9P$vi~O?>3?45=dN-=x*Vgepy&qeId^>=@1E zCmC&z0r>quwvan}X~1YZh(7*e<)nM@*^`wMx1FqGRDY4yUkyb8FP?1Lk18iUU)MwI z-HTNMfbo~wFZaFjatGhL6#}}~Gb-8y^*Q4RDA96%_nrdl%@x>7*SooY75e>}+<#~o zsFN$KSCyYN3nX$!HM1bqO^isu(GC`gdQhKu2TH1bQ)n>JGo5G$OdYCjn;J~L@B>09 z0#}E&#B^sYb|T?fbP@^~&##&DiEQV$zBTLHAvq9@fxF!929%wWeh1PI95`Tge+M&I zd+W&P(dx0I$5tP$Vie4dG{N?q3Tn6C?Q2*M0N{P5v2@D>D2*TST>y`48hCndHlW;3 z<(?|?0nj7T0aFpa*Y}C@dLWicd=5D{d;wP6B;$lD3k%X3mc&fK>O!RWA`PwcOR=zcSWOC zar;;T$nFpVfUY4hj2j4!KufenLsbX>Y`0{q>@5N)y9me+VA{Xc0ji0R0ss{P+;SVz z76AYk%lSs|3t0VYv;LU|;Q%3l`;vbu z0r1~t>3yq8K}wPk@#*W z0Na6u`AGbMcxmnnJ8#7N0QrAvn9mz)nb=6<4f8`g06;(Zt=uKk4fLbu4=bmY_YHjD z10VP+JxjN-ZvzslMi%?Yfq31Z^wUO?iW!H>kHL>Tn(zaazv;&Cv5pZMS62CvegT@| zNiq4!=0=;%t)1^toPl5D$Qaql?>RpW^w9^=93ORk;od>}UgDYK!JD$NypOU1z+9~? z8NM-=VoXiJ!oErHoOTwbZF+hI`b`5t+LT=1tpF_i{$X^X^8fCN!7JlZ{J6XN59CZK zdHp-YdKCe>>;EEX^%2P}{~wA|3#T7guFRA<0CX7v=I>RE0<|MXih}(VtCuPkz-X!$ z8DF}wxoLEBvSpnOz>-Ujlm!+Gf@CCIDUQo=Z*PpBM&~hEgIcn}b_sLq&;~Tb=!0_ZMe`Odh$Y7^SW#8ANOHbS= z)1JR@8fttYm-?*~Fi4` zd-;`&Zrv}vJoeHA+#SrGI9a74t$Cty@;Q$7iF&9v1Jvo|dBSsK@t8PS6Ub*L2ld5Z ze$9)cFLhq_R0z7)JZ3(Rk55Ah{hKvaXt^Jq^H#|6zm51V>7D)kr$1%f;Ot-gqMPK0 zwu9vw98h3+!%i-6P6-+57~&B(HUzqq`sb$$)*duR!MT`8+?q&DPBrqWSgFMGd!xO- zx5O{v`4_P~_DX zTiu@f>0rQaLN?|lp|%USC9|7hKcnP6H^8Q#BzwJz)1*aasPC0mGwMi$*{4d(9tX46 z8D?iIJ1c4eC+X_V-ca3#0HV~4iDI+%6H?2 z$6hvlPb$6#l10f$DHv^1Wt5{aO6e$>rPxtxO$sOeJk1vjnfMZt&$#&F(-e32v6;qe z%D%ofpH2Hh4X@7;H7~1LqqhZQc2Bq`Yb^UO=1*l`syyBLQU#taIL@AQPt?so;vOA&IXn>5xe&iF_P$8{X;Byr& z1+#YfwH4UhV0k5YkU$LF85TDI%_{V*T2~ zGULhR{)+QTs6_+@PD-qGpZqU!eRRw1ZK#9^K!vH^664WTuN4Px=2B7;OU$_hTjyr8 z0|c;*XiK{xH4P$EP+nhc0{lAcWgDuT?)JtiXFU^F9;Xwns?9SSi9nrsP{~7}^FDSN z0Eu@)u^9o$6sWaKOR1B);UTSw0JU!6pA)Oah4I@n-=$El%7RbKA`~v-HZ|FES1CZb zA}$j-<#|Uf|Bd&6HIgBd*OdR3gRU;hV_o(fP@AnEl3Zho4KE6(15KUV43-?F6*Jdm zZe5)xRA;FIj2iD(GkZCIsiti9*o#$Avvabh`tPkL`i`F%KVCVpi32(J#PR$@!_430 zY?I>;o=8a8lDmzN>qM`ORrkFF;^rW(Ja(!c$4MVaG`;11@GnH70bc5*dK~mUId2qm z_si*)^8S@^=+l5#DaQ-+^dsy}iK>i8n}Oa4N}SD5q`bumdU3b3*MUs73l%)N+=Z0? zGllR;DTH0%jo#rdmHxVUgRFsw>g?;WeAw+ucl$klZ?-Sn-#kz|NL%s^2kXYDvjctm z5BU9lUq6yM?eq3JxU<{kUPyr7G|*<##i#OSv%m)*oiS&F-=4%`z+dyyDY^RW8(>PdEFE@ycCYq{B+{Z=;P{q)61NHuD&X(XJY<>XN~eb4%Bsi2=Gl=oBg5qR$}7|o+k?uhc=I;>xTPPoWtRVD@!vDKU|OB57;Ak z(CBbYTTQkU8qL?{(#o(~nhdX9>W0&$t>J_t1KaauO{{vYl@6??WRSSf7oIt%lBIHi zI>z$AovqAADvvQ15)fq#edxdc&y>?e{jmgU9LraSU9>>z9{D^p;4}8D^dk@z&Gb?m z*)pNeKsB4CmDCwhk1Av}0bNk7I{HmqE`PE$O6X`#kwOcs1BDJ8+Q8a9SVN|H*gujy z>K@A;?dpeu`Gko6PR4t(ny)22`fMh0!Wol9xGd#>Gw?IFCe2uty+$PN|j`)LAI) zu9yu&@}E7ctA(R%@%nMLxjD0X(VZC3 zU71=EJo%WvG=WTOSdPjsM5gl#2bBN^s?^ReK@4}Lrmxpf*Ng;SM+f@c;&oIQ7~ScN zt4s3)=Qu<19y{50;$-JUO_f?6^xkrO&`P?ktovA<6z#ENW5+AFuj;!07>_xYaXffD z;qi?V`n}_uBh4N?Ie`=0Q|aY#u+`X}Uw5a{H{AEnR-dvT`~bnT1axdm8qWJ;`ro}P zy5)=fcQniY+WjWQK-4pnSIp**joFkN=4pr?q;XE6TmO04cZ$Wy7PT$p`HI%M(J&u& zs)*<%q$AatWj;c>Jo5(WPhrlnav;O>==y!$+-&X}Gfg0e2_s~G_q*S9bOdp`G9W$Q z+qVx&-M|6AfB(MC`}2LRy?##yfCv680G~xT@J)Qfga&Z)uYFDZL7>k8!Jm~!t&8Bq z7d)eoOw?A1wiv`kAvk0vLU^oZGpm{i4HUXJ#jPE)6u^NPC}GUrMg4oacyw0)XPR7d zpf|epP-s7L1`IkNI278%Z};=s&j4`u-)EtH!=K-N`)$s1seQX2Hs7Rh0xP@(@9g#b zHG;oDo|~4KF+YXj_nRetXW;in!|%HM>ageO5~YRUAU9d-pmGmGmW9)9X}>mgAUR*! z;4?SZ1I-!7W{x(;B**B|%97O_;~cr&uIblS!^2^2IUKvC8aidX6U%sOyG&Swxb|A- z0EyT8tH& zVU!j_XL5xfyaOgF2F2S&$TrDaPY%c?)|LEOVz#aaiQb{lG_E!Xc3{}k5ntfgTngw) z?*0LVw9`%n^S$D0+D{$@XvHa0K4Lq-F0Y2m&JOg>#qDWhVcazn2caD&N zi7T+X{@AWU+r)r{w(uw%RP#Djw3R|PyRF3CU{@1hN4YWrc8S+U*?%8iwM^-S%n zMw-f^BX{M{6{6Lb39;R!{VHx}KCX{l?EFO%L)7UQ$UYmTo2x`mG?un;kxY@gCA5lO zXC${BPq<$iwIOYvb+bt-h)r;8hBx54909azs-nm!?m#8rV+G}zRqS5k+v~GFp9#F% zfVTkL!QQL4{B3tmfIlbg@}+hRR5xo4f)V0|L%!^xs^&ZCwW$*dYUlhJgWvwFyD$ zvH@e*63;Q()D+6O6$4>280PB#oq}ImNLKrcgtR-^K6gq>?qT8@-_tqbV zJ~lsjJ37pR!TcA$EOl-&*0AkR%f?wH2Xm&LbqpPY%uVR{oj0+;5wbC@lH|yV`xb55i zJCNq@W!A5&wFj5l-aVW4w)gnm`L2u(9@7ACARHY3_P5=)8dl2t4fpkt9#y*})>ClV zn00~6Q>E?GfY}OsyTBa9?I}x$nA(gDhRnQWYuBE^+ZUlZ3fykAUn>Z4#y8FALZGkR zGL)JNnGKr%v5U+@LT0G7Wu+SdnWb%~B&8k2Y7(~n_cH_LzSqF!_N(nzS}*s#M0H>K zqB!*rOH59{@ve1qlJKXjW8(7m_wGk(^VnZa^tCF)$ zje!S5FDSTmu_uHZhJY@GFjJ=z79t8faw{RRUeEJ=;@PS-qbh-aJ)}l5+~7y>Z_%TAQ`Vr<*fK6v%^|vw8CDvD#+CF6-7OxY%c#JE+)ZOMV_kEuR%{8Nw30b{Sb#)~)1Uh+{L|cx6!J-jYFx=Mpdx=?YD+B`R za<^<|RCR*PzQ`?{ZA5%tTv#+ha@P+Ot~7VuG-Y98PTPGlg@@P89O15Rgyq!}129$S zQvcD4&9RZlt|GJS!h|aIA!Fhe0r<^B!I!pyu+gp0@z}|k=CKY_S(c-+Hx2!v;-h#U zYJ$#Io}j41$D1@rO@Qrzi0;SN9cwU{l4fgPKAIlOjuHhNJ(hFR9le)0AUlSY8t6ZE zY|Zhy`1tYc#3)7C9%(&vV@qDoPt{d;4AL{Z6`XfJOvq>diPG63;XT=GfSzo&aGpZ4 z->Rxl@5Oly46|%DvAZomH+gk0#>2q7<}}-xjCI)N1S<`^Bcgmv?uFc5na?&7US_mS zSa(mKDVXn8)~J-mea(HnuBIH{^xsOq?Y`6ZU2s09F;|nivfaCPt=~PmtNDWaUiRJW zJL$K1%r~=d(8;5Ob^lyV<+<+J8C|k%&fSGi0P1GlHBcAXffJQf=N{ZVmOQkKwOM-b z^hCOCUFL#9W9uTKx@qPG-!Ar@i0XvGcm$NTR&iKek|i4gdjJdEkDOOX=72hUn{fe_ zuomAQFuo0_`yVF==BhIwn8Ua5!<4$P6vpk|$mz=0#97vYY8$H8us^=kGH8D*Li;}f z?Ar|3X%K_2ti7x=+yK)d(qho7h1-JVrAzMtgl}C^S$rGElO-50T{5%66?|J1;i=!F-{OYWkr1&Z3iz}gKPm84Gpr_*Q7{%C;QDVQ6WG!$kI zkZS}c<`1s}bJ?|e%;VxMa@#HrdsU#)GTO37X@}C488Nr49oMt75Z2aq3|~o)80c;n z=bWu`4PjcQULZWJk%f-E8TfA7srcU|H} zjDpQ4^oWaj$IF87?LInaJo*wKHzcSvI*u^ugJ+6ED}#=!Ev|gGc3L-@#jaGytT{#9 z9v0oOMbFdDF^u_;o>m)T`W&sGHxYb!#rX0nIh+o5Fqy;FU}hc=st7_o*UB0Yb&}(s z%wgWp-6>mDUF#2e-G)F5b}}3iw41l=bz&u8ZtZymMF|RG(6<#>bu-xHR;@W~=n5Cg zz;HcL*L~(Yk<)$h%+R$Uq+deR=RQ9e>bmI_ITy)aetGLp`OkacWrbQVh3|qHHd-X&r_zr z6)9@Xb&;t%RB{2IZdhS6+vpt=ss06M`#%8NfBMG&w!u249HBV1Y~T$`#;{Hk)+u?Si5a{LkxjEw-THsa zKG`F6o3KAI7h|vLObA;{eTRal_+z2@9zS;ppBI& zAT7~2`;FRAkseg})*to~Xu!6F+UV=%G%~*D$Ad`QZ@u*vXq*2X^?h*Yx;nT2tpjcw zr%t_bicvtXL#7=G>b_TAZCb0l7KFNK<%Tcj7!t*-|31R+FM!`K82q}xs>jJY3!6rl zP8aZU82)Ynbe$djY#56HFt=nH22SxP9nB?!`p$0qB?H{DpJj`u*`xI+Np;P|4LxS@ zlFs58;UW5thqf1=XAjih(4UEaOt)9V*Le~#?M-sL3ZArf*qdNJ zfU+eJWf7lWVtu)aZM!wFmq%QZImV_B(^&i?@4fiq)7)rq>j3m@DeSftY`G(nD%o|q zNp3Zb70#E6`CN5}30ZDl9d9N(Yak>6=XsjKc|Au(BO?Cc5(DU`Abm883+cQ3x__sM z=Xba}`wi>wx!d34?{)XpB>SwszoDKk_uudD(@;;6Gyd)d592~~cg%>3Skqr`yVcz? zA|25x5Vw_x8B#M;bDR1@m@RZS@=y?Jc5{V?5#LphD@LsljdK=~kOAMRF$(>-wR!Uv zMbgt#1U6)p+IqmcE6@6^lzK{HTkYT62miRl_mF?@Mz%naxSNF}CY1LpDq%5XrdZ`@ zx#$`Ic0-&{g_F6!o)SZiA|P<&7+=v|UN0tOH z{2`zA6Tm5k%afY^vZt$zzU}a^JejF?OFy>zxZ_;@-*(&Xx1Z>HM>|@6c^w&G0tao# zL=2R$#lS(byE4i$nKy#E>DMWn%+;UkBe+-h;?>lnvFM`l_$5aWlVM>ZcFuuyHDe@f*luctrq;)u7uwLBOYgEh9_8 zKCYms5PVElClu&X?jjU0Y7*=@SubJ%D|dB|olmuEj0K*;M@~bF zBKb{63r8^EAl>QL{WttK-M3l<19gP+?|x_FcRSx{La=e70Q}JM=hLtH=LXe}^~>tF z;+{E!zhtNnzeY7Do$Ve!=ds7SwK7FM`+j%dh3uFG!{#~P9@2?cHB)31O@a)#UjV%t0wO7>6<#*>XrGvo)2r1mx&yuZB5>_L%aJ4kj&YD+l}N$rwk&*Pa@|31DJoSVZK?w zTf==zhsT%pEm^u5fcHykfbNnP7FQOHa(r)b-5}mA9$(V8bV+k*KHL=7rVGo8<$gs9 z_@1XkW4PwE=Yhh;WW^Z%Oc#YgalyNz$ZZj&;4bj)jT_xx^?%?4AN&A{VZh^Z?CU#b zz5~dYU#|S&l~)#fSb*f1J1nSo*uDzZV;h$;h6*eKBunjey{aB4EZ zxU+m>S#@~XaK}%YzU^*O&-Nr;msA1K=ab5+gUO@>Z@mF6cxns3L{3_zuS57JiPw*- zy`^6>P;6X&{kgpq#*!G(OD5RVbhbdZ-G2+US?;ow+N|kCc11=w&)HKejAz12`4wg{X|z{zBun|r20v923Tg;nl4p6{m{ zMO~HqMBPq2ugj{c&=#)XMVBe)(BsT~gmgXxdgjy=wA;cw8-q!W>{VSD9nKU#l3phP zZM}B#(RQcV?tqYMh{9AHPsO}4%*T(nkBuJfJ92dGkp`#;W%h?FNA?{~j0X>1G@w)-+I=}Sp!CnDU-JNE-#5RJ ze>4A<+C+bA^SASFRRB)GWd3#cwc7JkO*xQ~UqOXVpK(u5?*&Qs#O$a-2h$fiw0m&+ z1CV1_#=Y9k+}&pwujoZdcUuKs@xN*h<26b)WE0yG#JFf_DRuae!ZqPcNyhURg{yA z8orkq5ZCwOOPv?{RFj9iqT;>d_zRDV8~-%oM5DY&sh2)1>0HO@TT7$7d5rvb6T&cNJfM)gTZOvLGKp7sSLd2Uss zq1)W{A&WS7-cHcz@5t_~vPRuql{=evRqh_UYX}~E2bmK--0jKEY)7))-8Rgxc7c~w ztDcRvW&?=vzb%m0$YmhJbT~8UwS{W2T*O}4#+EHpQarokY+w^CA+y=S>)kSsH)H%vu5c6(@@hJC?@?YR$K6on(UU0MBG8yGaEFq^V;pUIdz^8IpYb63#G?-#dVuJ_ z9o_`;=f~QXg+2)}&ai_g*ufJ@yF`rL8}Bk*9A#X(cv0C!659Rv4@?#h71bt-3-OV~ zL40*W6XMHkRz_q}F$T3O8JP*g+-?0`mfsY%0NR%ZSlEKQ z>%6bXCdO&p}CwJWiIl1f(xCt@IjzE2T zxNp!4Bdqth#=@3E++(4B1olGrhNvjo*Mg7;mz2v}GLI_Qe|2tA6y2+PtD8yfZ5-YH z@9U;{yT79Yz8SjR_x&55<|R#rzU3;-Z>lt(*sqDJp+j9@dQ4FM^9bcX0LpI2$OZsH0=b&8E=;uV%K zT}vcHyIb9D>2|ln@9evMXLkGK9euao(Y!t1>2|p7>22=ThG8kYMoqhh+ghPgV|;yzg;rTLkqE%qRvkzIi&A14Oh;YCNrpbmC^XxV+}egkOen->o|dr# z5sQgqp*mW|EcF#r_e;<~y-1WvWzo5ht3Vvc0669-xch|rWWwmtbE8arnodmFk*tM5 zCw2?#x@yS#Bye80Ea8GlP>kq?U|b5Po3iP82`%QRv|E$(TlcCM>L7e;K)bUgA$1@O zKlBV6l(qrgb;RUR6CNzF(9L)AlDY22MxeXy^V173l+NKkUAGnDKIuP^ut1V)9BfxG zm|o!v81%9Cr`m`hpxYGC>Aj4m%ow|k4f06nevW*f$8ep{%A3SEx;7$kC}s9A-src& zwl{$WUK7J_x%61;Xk7{7qn#sb4%dW(YJM?xsB*AJC*89^&)4nt^eUoBCw8 z^obu-4(1%I4dENZQ zf845QO>jv>UnISH@zO-(ZpBEKACppck4$?s@M8(d?#a4Aru!1u_l$!ZyRYQWHE0v^ z{8zu~pYMF_=C5}E$>vwxa~TZSqZ2zo(gBiZnnql@u*84e!~gN2hmeUM=wf9MiUCVe ziXh~HmW5Ir_CQ{T(O|cAR@hL=!Vb4CK_;1D8Db^bq>H)H>9!X}q+~QeDH9V48&LlG z*S~WA^gCTI*3U$N&0zf#RX#bhV)dhJ5bOYy^&hTCI{ z-gxj!FXsSe>tq%!`*tCtr#TIONk3<+V)M`HK%qI?ZS02yGgG_ z&s{2m<%`2Wk)Tc+UMu_*P2fqIJgrKrnv^EDuCADZIa9OoWJf*IG^U&V7y4O>P-8$l z+ujDWD;(7wJ9g$f`nK=Lpucr^vqm`iFT6J{*R2MCh4>t{I5@DITol)o0z5-Oe}bWf3>fgyLr*_W5S!jPaN5q3QTLPN8#Kl&j1 zM@inz{YCMxtZnbLF$OO&8$5zeYwtY(p)+)3s=&-(3C)*+ZwxTeu=8VTm z**Y`c!DI9jee!fH%SZa{_QuES+#JCItOz+X+4%}EeHIa|wYIG}8-V_A`3TC_-rnd6!N}{$226IBH;9y4! zkj|Z%+d5ST1cif({h~oFs|8wEZe9xR50)~w`&^31J-x?jO~q9T15U4X*E9%ecv0>u zULFKkI=8xi7Q??&bZ!~N`avOG6K>l;L3mC}2a{BwmXNjOaf;>R{USUZIOGTbM#28J zb+u_43+{*o`w5q(UV`_8lx|v8PlDmCLk$7^!9%+bRt}AGxPxa2<8@a7`+&YbRJRCV z%c1p$M~^h{j*%R0QZJo>=nfC|ObOqwyz=TRud>U(2Cz>%6_Fj2ko&=3nD}i>c#8II zL^uNbRP9>^F`qQFTk0C2sa4RvX>$dqV>6=bhWG=E?LB6(3DS26JlQ&8;OVyfzo%jQ zt)|zB3-3UxBS8#~f~I#XLw4`II9Dx2+>;|N`XM$zcM#frvGJ5KV*j)U-~E?8Y`FT> z=bmeR^_J(WzHLrcmI}rLf_v;XQy$Nka2+n}&F|Gb z**eiOL~rBYuN)Dk|6|1Tm%;RV4Ac8bNFiAfqt^wSOI9yl1D^UtRiHIr)DXZfT+~`v zS@hV#%7V=tw~|&`0}AW@ocptd>lP6aNa5BsDU(=EfwM=9mPLz+;v-uyKnr zm)4Y#iD6?h*i}x>_!@*uE1t6>o-CpqaF>N%Fl9DXTjg<$2X8jJYK;hX8)-_gH-jwK zq@A>HtFdghkKUF8v;#!8ws!KH68Ld{09qxp*%ep2cK{WwW zEAGVf=66Sm969pFf+C|gyEQ{y3zn*Az4e5|0>tyqS?E5=0N2*a+6vz2=86VyIBafI zIbI-^dOVy6XeoO8lXL>M>yukGXO?RN08Li?W@M`-#gB}vSv3X^rm+|cN_r{{$BYB3 zriV8UIU{xlJKx%eOp)ajBXO1hzivCu0Dc3C<}?^iHA?EqNk5D$A&4KZ8wYmRrgPjU zXeCXpcK|=!Mz*lr=aSF6>qR@kJ~y`}2J9B33T=)4dWsbT;wk<_0Rz5Uz(kERnoX#r zYm8UXws(lq1q1_+AKLetWHvl^Pjs zExKU4BJUoUfRbbhxTeekL*;ED{XbLkxkd-NM*Whq-l9;OaM~#AjxwWb9%%d^HNl#@ ze|GG00OUX|AAOVtMJc@m(PqEso=U&upU$4~;8~4Xe~{Li%752BSNZDrbA4ZVt^<}; zpM4g-njz|DU-C~0%ls4kfyes!Q;)z_-NVx!3YI1byY9XO1IqcBPJTOAwb=hW#W{hi za_*!0B`k9r&NnP8Lg+GvHt7xxj3%Q2&Zac07M!_}a}CRWg|aKg8nNtW)DBILwL_dB z#CWR*uG4#sLNUmylD65Y^!4mD_iEoO09u{1{W3(g`r?cDnQ{u&I(P>9jvnjan-{44 zDuUWcK(P>^b3cGQWp?Q0&8x;GzFD> ztB-s^g?om&_v8!C(If2+`vpCeV`2ehcEN&tVU_Q1T3Cgj=B6GSHT8>IhKib8Rb$VK zMM~276alEw$50m)-6%t3gf(vUnM!?vHKKSSoHE%MC+vlTAw3Hyx{J@kk#jm5b+Spl z!zYD?7dJ5VSh!Bxmx;%=cS*cciq@)>#6|-hHUF~M2~Rh`qHxi*-VH8}mVC6QP(Zp) zzYv_u#BFg~-8Rqk;OR=$A|u<8-BP)A;+7_x4rBlPP3g9bMyoOL>Nftnl6QvWtNEUS zP@*KJB@}}7sTUE|4AZUnH$h(Q&A=9b*qegI2h-z9M%IKK%!=8uSmp~os0j|;#}fF# zbkKqKIC!7Bc=$&jRMNP(Y6|1iluL$liFp^+IT$V%QX#;hJ#)M~TrDDKz8e9vq9L( zv~w-oPzWS}+2gCHUbXE1k%Fq;P}N_yQ|Y{+_m*NQb^n<&nZ#W49JmEQvIX) zxv8YmE#QKd(B!6|Yskj*DcEch8%+30whq$es9kQMAZO5Yy*r3N6jFO!#VO#*pI8J? zFL3kId46tkqrahUc?AcsHn==YICh^(BY$ilgafOEa@^~a>Sj*^qRy}|&m=&0Rs7k; z5Y!Gc7^N7SL73-2Q_$bgG*fr-Hms3=pp{YMEk)nhmnM_dmApw}-V`PH@aUn@gS7)R zZ`^dCLJ#E%tsJK_%8(BZh8m9US0iPOL8xgc^4Nhv{nUQk;n8;-s4^{i-NAmNnFkM! z8uI3c`;OpDb|w`Ms3C~jZe}m0=*8}p#Pni!swTPE{p~CS#%|S-`fUAPX{SOf7N?}- z2u@jO#R6SVY84jDd0~mMx_oP9wBoIOgh628x4*S_N&1d_*{OmYC@PFgA8_ovZ~OXCi8G? zhvnXC1XbAmuz>~;Rbl@IS@PG(mSc@-Vu@;*6x=yJdaQkP)Swl39nrrdKGSuCn5oVuKu`cosiLNMtt-}yAn30? z@BtHV<3uQbQF0n&UK+El?()x0?PzJ$K2h89SONq)gCB8KdX7Rf)#)n;JxBWJFpwSAbCN0xYv_ zRVa+xI#Yld3FO92%%$m<@&NQOp05yVC*0V-2x2YRLx>SbBteHZ6Xhxe3hEPnK0s5D z$bv=k+Ja@+U0+48^`E_f4bfaBY}Q@5)_8`|3^w*FhPn)LYMrif-13usSiPjr3a}}c zv*{*czi!=oic6sIIqMqenAS{@y4!23 z=L4X`)?Otqpn{(yX_?J9LuB1HGR-hj@Q5M{2Cm`w%}T#=u*Ay_k8>kcIA?oRGwHBn z)xGf>wk~W`W$HC6$wDm7aqG@|$F8+Syz?f*MmdcGHqzfIcEu3m?8&^Q_>7Zl-JC{P zf9`LTzWns3-DjrT5+rOR=@0F!8#?;Ab;WMbPAX&!7*kXj5~XBa{mKl%xt;W-kmf3H z+$fDea`Mbo0y<`@!O6uq$&dhwVw`?)O0GqPHbGc*H&8%~aZPg>d@n54Z5{YeK#Z?- zpkmp=q7YV#u?$6-jfB-90i)rfwUYFkXGY;HNC_B=`lYL~5lUBe6kdz)K4OH#11ikK?AWNgrS2KWjQ58TA?zeo31 z4y@-`yT9M=I{=hc`SJP#^@CvRfibbt9Be#vsC76$k{cQI%y>v}9Ql{)=&i59MH9H_ zjF?0Ipwcn%Y)yXS_A?!$pg`x7eNVtb6M)e@n!-R+ zj72F8eNs>{xyRjoUO_%j%ar05sYwlUH`h&ga9jVppa6h^AP&S~`1vN(<+e(6i1 zQM`4DK=IEaD3&s+RMaUls!>l=0{5dDsZt7Q9X%`D_tQ6Ws3!wC;GNmaO=fQmoK*L4 zLZBu+QkWgt!mZxMxhCTIo0VzA$Ng*?4+T9H-U$pW9$(Y}6G>MZFt`PEL&RGboWm8m zKm?1=B3j{a3#P~K?1xP*;{N!s=7QPbp?YNa&1^wKcP*HoFGzS~CZ%b%I{p_Kq7Z_s>ccw%RqFLHsbU9t5s@+Kv)AAzv2D$Qewj&xs%2hO z1&6}bl8Fje;XzVp4Oa!LrA8|<8bblgj`DQ-#GRR+sTRV~2je$PixH$^$mW*j)+)4Z z^|qSSK#@Xa<81AjCJRo0rf&Ir08>NL z=v(4^aLNLlx*Ogf_fj!XtH9|tzWBtPIYE{UIVw|S-4zv*RI_?TS$HT`F%$2U`=l%2 zhjaxMG*r^fxiJf&h>~!+>oZ_C2@$1d)M1tl+Vi)KlZYS(Pct>X@Nz48ieXtMkfnaD z8a^DY$}ubP(Ox=cUVwaYC0V0F+R4)Gl#D#GGGQpU$-K(*&4kp7+48|x{f7yy@#pAeV9M@E)G$9D4zgJnYdgbIuYt<i8IO z74kVJjXg3q3E%5MBH&=fccy}nhBBWA!lTZ7SjXFS=FyZ6D%iAs4DN>m#*&))na8{R! z+8XhjH7$cJ){^AJT`3MG+L!>h^>N884#-t?ZVnxV{!^w~6S7LxWuHYIg^Y3mjv_$x z%ap{?Iamc+n?^%x0@tzqH8ml2`)BZFe?0c>e|{fi)s8c{cOO6CpB|_OeE}eL(AH%C z1n|q>JJ5;P%S=D~OF5;m>4}i-OyHvqJ}MP>2;_y4st<;Lvx*4pe)Pvd1Qzc8Bv_XM z9fgk;B5*PGIQY?&oJv?vYQJrSG%TnO@pgoaLRe8!<08B0QG!E4eG2YchkDC!b~!0x zu)BL!k>rff>mGzj!b#DC9i-GF2Mc_gPqn|)_w<*xJze_}^|0+P<+zio^oI6eZT5Kj zn19q82^H4*`x|gvGN)72)Ay>!1kE9bhjj+?aV0ihaHdo?%n@9+Pd)p zSh*Mk1v&{KxZGXEt_S3joIi)y#R_zouFw^G-Oq+dTt=wVhdUHd*GJUd4eCB(sM{wdicU+~a^a$} zg*EB3YXCy2IyLRQe!=Sbl?7jzUzzs^U)vlx$F})(!%=7CbpDtW+=YwZy|* zzA`PkRfLj-ZXvnWqEOfVBiKUIKo^$s}2br0TV107~=(nkF^QL^W%)1P8 z&A0UPDztTGoBK9x&Nk)1OG>kx6mWEF&hLUt;S1_gO{a}Rff>zzOn)^0WFY!RVI zU}{2Ym@?F1pi!~Hb40@&J+>9Pq~yc&B(a9y#3g)$)+nQk zS%+>>3(L+Bd{X)<7sf`Ai{aTI*!YSn2=|*6`HCUKI)lCSD?1}~GymWiPFA&&oDH@w z_+bQYGWV)$)SyXY6P6Q5>ARe)b?YkV1$2K<=cQ3Pu1zDX4TOZIs$6i+d@hAo%1u+?nxCJLB@wUmm;fCuPCeQE=E`x>v7FeA z)DCrchy3!sWy>{PEHh=*qpW(aK|fFK93?FM=Tl&e{|9c|l-egXX>fCR8m6eatGbn^ z{!-AGlPTg@G(J2-3Yrl|OH&c8g-|Uu1fwts!U*<57`^8AW!7FI$AL>Y>&%LiNmXr| zDBKJc#j9!4QRPZ$uWBF6$wp=e*6nxulKt!VRraN+DZBJZmz!>Q`%O(*SO}7oIR8}S4 z2Tzz=M}#<4Rt=$%yJ@KFz;(9`1(%LwRd+|-d^+y#^d5IF?OFja_W<|4 z=3l)1sZl1a@IvNguVb%XYGPPDq zB|H3wpO|Lq{{HN@)MZIV+8?Uh0*s#WVS$yyYU5#u#2!p^ri>KhmDP}X7^18;wIfH5 z9L?3_gBs=zR<3|r&4^mx1+^YE)XEl(!w*56g=-hojo#f1Kuydy_dq`HJy61Vq73$x z+k9i6`IOC1<~8Rx?E871-%|EMcj_49`-}sKo40m;6^NUFe?mkTv`I^n(gfbD3$jYp zG9)5ZvILA%Af!g{66U)AC#)zb;2J{;ML=wT-#s+*EVfzZ)!7F7U{HaJ&bQUuM2v+c2Yuo$j(gZ-*tABP;&|w zO4g@#HAZh78l>7$*OY#Ci~glJzfPWMsG*siNoWvV<9%Hr)qSGECV1AA`cK{}-Y|Dr zJtA9g$HN|Udmj_m!j>rZ3c#6i5_RC>(kMOVI2$M*@y*%YAkOHYwheI38FGbJLzWB% z$oxo2h|AjWJ*lbm0a?7HMKQ9p`b7(qRcowhbmPj$<>rx{Ctp!vmc;-!#csG+Sw4z$ z)AQ9KF;*lqn)4_AFyjYdDuHfI3M5yok!_6W1p-F53Y8LIl*GeaB35RK?#fhF>0-gB zA-Dt9bZ@4&E#9mOox+Nvi zJ`2?~y#Yj<3r8ckl;Y~SrsR8Lp2sqDR8?a4t>lH&Eeu$$aJ+zw z?(^O}t1cpAu&V}S^pW6UNFo_|rQ>jzlZ+9@ehQOZ%t zCGC_=BYBxA87;)@QQprru=y(Qdvb70qu|!;Un79qw|Cz?du{&uo;~^A%AR`xLIGpb zK(Swd$RWVow6AafzVZE|a`iN^wq}PLR_H=XvF{k@=Rm)dK1S}P)NDNNH5;xLDp1_t zR)6pVl+!;)IsFkG8qCKd3Ks|9BAr?n!(aZ=q*JgD@bmImOArd;X~-%{70^UDX##^K zh3kT!T4x~$*#@Rn5~C+PP?k~zfNs0ZZJ!1r?Tl6)cV`NDYXtHZx|+KO2b4}!LNR;9 zKRWOjV5blNc=L(AC!ZL9vP#RL?2EN0p=}dSwx4J{&Nwol&_7(~_Z~Djbikpz7eKw+ z-Ida(Eg@}~?r_^1x5d1n7~3qn#NqBGWg93cn_Jfir`D~h^kQJQ%?i2W(-hLb2z2dN zVrvls&1i}fxToh3Z-0S-NTh1!96AlwPMvxk%2p?Ac@>*ZisLi`2I;2YFr8+gU{elf zVc_8-P2+Ak(tG7VK*DxJ!mopbPZ|;?khVU-Ah5Myjo}(tmvL=9JFhbL_IVXkK}0zuu>2`W12hg^{Xof#-hvvKjop~aB< z@cU^-p~<2kom~SVXUNXR3lU_C$Q4YEZOxAkba*S;&`{NQ^rL7?rIk!8-Ac^`JXymg z=vG7D#AZ_^sPOdn7+o@oc5m)ya81_b4*bmo(akIR4bfHrV9AO}fb16>e)$kM#t(#j z>y7EP1YXUN9L$nTNygGJE4Q}uZgiSrsSr-lxFBlO=PRI6H2&LM4iYLgOUHjCy*Qg9 zR8qYkA}W~E$CWSa5<2OWu&nDEoCIar4}*h5UhA((uJ%?_0m&q6>Ee`!j{A=UoPxn& z0xLM2BzL#@48y7J$)sF`*h?*VMa?~Ij*-7mxq3_PDWrbcW5nW67GyNVs+rWZ{ddd= z)gH-lzEqJE$M+2eSlYL5-^AY99%x!?PqOzrOda=o#z3>Z{M)mAZv$`xy(R=)IRd2L z-#L&|hv^PmiRO`vl%Gd-%uc4D)}Y!8y`rR_duH>dY>8u+n$`|Lt{ z{F!K5?7!>&Y0z-%H^>9pgq-#uSR1=EVs=VcGaV_rh`G6p2ekjl3gg!Oj;)fI$RPBV zoW0G`%E)?#T)~8j3)SsN$oMso0U>P;=n`ooC1;c^gR%*-T90)euRTGzS$Ndwd zk9Xi|jN0;#WY9GaUCSaq`MZI?JN4(p1a~$9S97bA`)F)D-~Zo{m2 zk**DwDFFz+TDBV+3=@7#54i|)CV*1P;L7pD>GZ4KABDwV7s4WJjp|e0%dWCmr1C&2 z_jg0)BQ>t(zYm*!gOlT5XZX;o(>Y~wlD_mZ6NQ^lwj7|U9y@m2Q;FMDONtgb;*Pw@ zKH}6^#Hp`r;3OSxoL>cm900X_-gGinN?K{}=4t`4?AF{I2y4x& z&Yd@R%szMQ^G@z<0&0e89-c;~5cJ9x4Cw#Cfl1XZ>RU|WE< za}c)Xm9sPAQ|Q(TdEOgE>mK9^TZ`5VZZuMMiG{;T*%jS=2C%*xS96zL*yU=4Saj{R zb7Imi_8zd1*mjpfk)*%)Tu7@^)^;xst;yP%A)}r%myEb2fT=P~2JdTKA5o zZ8^ia{A86yGfoCiaXqV_Z`U=~HrXEPBqP!&Tm?mQb7v~mQn(z{B5kN_SqpNV7m>@XE6T{uon05b0;EOcZq4kj02y9}x7u+Wq6Wac6wPN5JM*ZJ){;I) zV{1V)nf7a>thHnYL4s1x=F3_gUin3)xTr0X>cwwHG&lirSm6^17&vH6ZdmLvO$fhitztJN*7uuv4nEzD6 zoGpNxpTjfiktbC!sJSdE7!2~H+Q-V*at0(UY=g?gDpGfw`%Q2b1shbLVtb%C*dUXa zwF!>l46d^3L$WQilrk=f3@)o3d8TD z(bpY;xVd{$`egh2GX%?wK~&90T94KsY>(ddSm)9Fk^JEtxEp-Hs{ARP$RK4dk}`jX zyM1uy&Yc1B{B47dG%oo^(I!k0pTa?elHC>04c5_9o&a@}#wb^=bltN>cJ`v_XQF zxtBap*E})6?A+s;+vAQ=RYSi-NAJWO$WvY|gPV;VNcRVJHW5+pX;ANJLp{uzAQK;K z>mq2K`Aq;%ptp8j!gbg;7q~-uoLdw2`MH&OV;rkF^10Ij9s+)Ic|c`ei^I*GZufGR z0Fxv)KjlWQ8(`<$HrVJnCXh16h*TRe46brdhdkTn{E~i6gu#c94Qp@H1|~~EsRKv@ zpJgkmi;J%FC*7DTFuGX7r=Z(pOaY^nM3Xb>PEn=$?UMJvNeXN%D4iKvWO}^%oTy`( zp(SGDr`fZ9*ZeF{x?mLLHO}wB#>J?w=k#cqpko9_8&?IU8yh7eENg8uE9Zj*ezr3@e5qv7ml~Q|o|6q_r zU=$XBiI`IJj5DQNoq%zmunhP$=ZDDs9mr_Cm7F}jgkl*B4h%6P3i-1K1*Kh^Zxqu1`oya^T;P~!NS~7`~Bj+CBahNUV7JX zXK51;cN1Qhk(ondf!AebFp>V~F_`cd$;?TA6!dvBm?$$>@H)ykfIj>(WabL!JFCzi z$+Vio#By_q<%uOw8AbP`=lX?u;2xcMIk`EzAj83FdzZoHbj8~2IzXT*cNc~khZ;G7 zBZ<-tf;i>Z*6i&Evjkj|0GZo!cz0#bdJebyEYL0ho_(=T9?)C8M;W?3d)Dl2@57n0 zZ(nBU<_~0+oAXGN_0W6Ph@Rw0CFfM{FwF|-1Iu%7%nmrmmTNfIGrKe>lt2BcW#>fm zBy*BNP^+n(%j zpq#s-VW~N2o(4js26Wkj`9tl8#~-Ou8JIniJi6|Y_QOpkKxOzvGIDSk_$E^4??_>E zZb!P^LFZx%FJGE6Q{tFpljCI4X@rGLqeUX{L7s3S8_Aw(0XX2@#6#2D&0mwd|Gcz^ zNNMvr(L}X-cojWl|zg94fLln+g z!mUZmz~Dp5upd?S1xQ;HA?-;Z?OB7g7E8afU}F9{P^Qf#P?^`^*vf{tiDSQzOdPHu zG@1(zRiSAeQfUkDSGH9BZV@M!l_Ti19y7g85tmG3@p7)MovF(!obK6nx_c1FtvOee zUi*RoC?XK2*?lm@O-VnpDS0$2O%^+IAN%8|DNb>VSfN5;sf<4H>UGzV%AXP4BC2`^ zZRh{4_$AL@?KlLY0fJ;k2>i^hIww~k`XBh|n+XwF4JDm^n>F#X9D5~`6YI7BR&zTR0C5N%k!fm_z67H%qB&tqMlM?s`X5w9s<)FGWA6UGpwahCPiFok#R_U31B23$`ax~+AyO3F@(Cy@#>TP68rMk zB-i>mgGC_oH#iNAeK|6+slkgB#2f`trRc~Mpom0@d~ru5JKGtROL|c7(j>i=Vf=7& zGlB>Yx$@>;^buY>@Zty_+%^8{^yB`j)ZoP<8^Q^J7oMaUKjdGWcHxEc0vNS&^6QFN zX+uh4B^|wAiF-7bgC2OmimC*FF%d?Rd%;`x!r@icJJP`OCO%^D!ZB-n|FKAXEKa*9s^jK z`};(gGP<;6hds%z>{x0(kCetNv?ND=a<3+@x!2E*l*!DBMfF^;E23q+ZAb!T3Qms# zN=ht|6HSU?Ntv`R&McH4t&5-=hCwlf(?bJHL`ycFQ|7yR0fo^v^r}e7cS+TQ=y+pI z?k-Q=y1zFAO!5bs5B5FuVDq6G*{+ASJX}-GtMgFn!5o2*2iyzlkihaJu-xtGPEP{M z-Im_!Zb`{rHA42vZ%ypP`Hh1-nV<^(|6oZ7`gpYj0&dmsi5-O&DY2})bZ>+^ywq^aD&7U+>j^jI6w;}Ou~ zxgZ0Y_O}M@Z~pu-D3F7?)Q!WepF4OXyB9myT-H4U0PMT$#ws^xOQ?-)E^0$PKH%Sn zJM2+B((ctm!iU|VyX{B%%p-KCek+^XA8)OjJ4@_JAA&1Bn&imbyf#?XrnZh|;Sxt| zt{3^~%=$308Br>233ir~&UVeFW{=1L=L2n~TORX24Gnhq?5#9A?2G1Fa zdYDZ&a6%{yKE>ab<@yt{T(-{@L3HqQ*tKF91xSe>xiCq?X#f#(E2KUVC3ec8_)0yXDH->$X0DBa}2?Qpl(?~rGz3~x5D8(-cu zp9h{nV^KM$Pyq*npo~SS*gQ0rQWle1#xnmgWILHHL$|r6b!Z&wX3t8@B8NhPMO_Tj zJ3M{Ne9_I6{M6OyHGx2-pM>LBj?7=@jXkB;=Qq^t@)Lu~(BhkP7X;l_FUI)-!cjxG zWZmL6J&&4TTV7&YhN;mb7zb?gP^Z&XLw|+Gy5S?X6{?}IZI;e?IO%5Ia9hugKAvFY znX*l)E;xreiQ5a~as(t%r#?CJM;W2gS%o1}f!w%iFIHgT>Fk}@Qw7*ogI$%~H|^?w zVb?Bww08~gg_|$D;C3}$cp==VFu=HO-#oOd4&d$D-P|>RbO-?M-Zi6=r z8CciC)|epz+bf>!=#&f5?D>Hb@ z@5}G+d*J@&168!YJ0EO6&;-!>?!7Mq)3Uq$UFn_K9sc$Pun0J2+kwej(_8!(lA9gU zUrJ$r93fg%_B&kBxRItN)m?iKknYWLY1`2i+T})=F(mlK1Xt;uf15TbVd|siE7t^R zYU_k(KB z2bphv-@N%y9S~$IU_~R}2rwX7W$rk~Yd0oyn>Qlx-3Z><4<+wYLpUH!~47gJjxwqN5NtR@9l1G(9c82U> z2_6tAL^sKZTY0uTbIM%wB9L2T<%4k6b0Pxa%q|cJWzJnUyE{@o2y<>uh0r>U(|l-S zr7RWL<1QTpoq2c6Vc{-LJ_0NF@V{pZ(jF9igoM`uo{gInqZ#fPHv)K!8x`3$&JZiw zsn@^NgM^o15q88Ke5H`17J^epT3lOvs0|;I6?GwC(=Uw*U}eZ3FB`3G#p>lZ3viqY z|3MQ6lKf_P%W&Va;f>42u@c%egq16DU?XSM$Sd!BRX836I7en`uqOzf3Lccl69!9D z8R8WRJcwf4O_iISc>_g|{KYnMOwDvi?~tG()ngP%20>>DDtE1$6KcT%ez5UdA(+1& z9gV;&!+F~z^jaSVyR60L+cLc1M(kHYW`g&h@lk4Xa3OD8i2sFgA!V6_7akGS zBefMn85qkF&K0}Q1(Mp7X0kY;#0xr}DbXZ5yu5z25CJg4sKpGxfDoZoLK|A7n8s9! z)*e|6TmT!RD{9i!I-o^OoBzgL*$e3|_d;dYkr!qOEkFrA*^%w46__y&vbbH-4KE^A zw8=r47}wgg>RP>_83ouF=FSxCP zwy8*H>+&MMBiWfDvUyO$-<{plytjGZ8jKXx`yaS}%;u@L?yus8Z{ODfHJZkRGMJEq z3Hj~GZCO`Ub2ouXphimZg4@{BLtKpmcuqaQK_4hZc*+$?|EB$>1+2DTsL=WURH3uX z5uxm=hYXpG@9noW7D?EFIYLhMk`B4=5AxoE9w?g*_;9c2tv7Fk?Ckjor($P!EIaB2 zBhAC|@3jszsf?h@4C%)JBAX+K+zE($!$3q%^qRKJ2}}2kkyQ_@CNiB3H&$*Ky)n5V zyOFL1#9EG9x~GC}UAduo<81EL{raIkZdl9Rw}CzUg8tBrlXG!g%pHZ@%x34Xtwcfu zBEQ;6D?j9MHTk89HK5dpLal_e5TCR?vtRHIis$6)&^7JPuJbQPBWI3WM<`?UTasVn zJ|UQ)#x}4W{}I)2CB&F27(Mf2!R1#VjHQJBx6<0)^|tpQj7@7OvqHicUWr>cOR`aq zEaxzqsqsl@pBa`i4(MiI%UUv3z?KSP8`X zevr~tb?cT77|=io$|i%3R%n6hz$o2~(+p`s;|J@9gy(}jYgUxuqA7x%s~%hG4qjPw zk#v_OWXWZUP`sOxD)^Tm^oKwE;R`P$d1`777n=63pu`oD08*S9Kg<-^0RL>}f#sk> znhwV~3}PZ#AT}>fZ*Z#TpiLIWd$csgQr4L^MhF$;wii@+hx7U4%i$k5DIX?h)RFvX zmQXZMZnQB}G{}VU4P=J*gd(PdzgOixdWiD~KRhV8RKLYN6~0fFZUCa%@FR!w00~dl z?-mLkjzKvnn)D12J(UnFZX<4u5JmJV$)DYM%?yiPLD}CT(8PU+b*G9hp_7~w!MPrs z6G6K}Ju_hHzxLW|=MdIppAfl8KjlB2eujh&+FeFOlW~dVXm_po?FDzyfv0c&0>U-9 zmq_3?IoCYk`kXRj|Jls4K%Oj+WV&olYS1KipRz!LCdqW!N6`^4$$+L%X8f)an!166 zpealYnjZ8XE-qfN91v=8Gvxk24BPb30&8cH@~5f+89Tj@%8E z8y`X=5IQ;gdc%#|xX*JieT!q79vzSi=u*{VT{P;(4i>-)a(F(!gMUyt+2)eLxcw|+ zL&BORzRs3Wv`U^)0+r_3yZ?``HxH8QyskXw6xCyQ+n#Pu2wMRK6aX#~MUmP`ai{i$ zl4a4H-?`t*tb!ad0VJwW1r$*E@|}C`Ip^Ll{}WKqh;4|Zx5cxnQTB7Y)ik5F|0>;HQh{wj&2<@ZF#MCL(oKSZj-S%Z- ze|mTxiU2wpkmHo0cw4TsnVXO0U+AX5i_j~>_k?BmNDu-j;qWSGQO7^ zt%&yc9e66c`V@z;oM@r0O(zr_1`@}?T5CiRu-1q})jO?GeUT@-Cuz+uLl0X~S&6h8 zlTC=N0Hy0n>#0Gd4eOgs=F|Qi*x1_8fGehJOKZ4)QfrQ4TH4r*B2NW!Gnyk$1#*R$ z<}HW7e+HvSNA)CgZwXr3j1ZphY+dY`b{uNdpE{jUooG2{1cO^TShpjkc^x~zOSIN} zvPt}Zq!?EFLjG9({Md7)>(7l}FH=L3Yti+mu0>Z<9{YIzi_{paEc>sQp1VHsT;uud zh5W^sM0t#(Af?Q|QeiaI#Io61toZG3<7R({`Vmgz>9Z+dNcmfDq3&pv1uJpik62~# zuT?x`4w+om_J)dMcx(!oc~)vi+Z+Oty?pvEt5dF9`RKe;kiXdJ;%T%c3i(LeOh-trC=6qoOk42L147 zXke{bQG|d5LD8%1qXZnJ2&h?64M64Lmen9`$Ma>Y?fsa(zt`5olq<3l&{o9U(pzV= zE4Fb$OIYP$nIz^}iEJSPwJQ!btm7%oo1tN;V_XaWbtHEdcS#?jX~B)96sYsc;vZp zpsPLY{Yk=$s(CNrl#h<_!pisC*}*sWlc2rYk!kTugA2Re&RK2oD|jvu!h4^Z5jrgs zzU&)QyuoXm9^XWa_AYOVWrQ(6ubgo&6;iE8kwoKkUu`GZ#I|VSB=miL{Rk_5%~#pJ zeOztFwr%G)W(Hv2I>ZBz-@1#(Ujy`+f&JLF;q5tbw1g2Omg(~}$Gk@PZ@`*e)~z5t zOhKo?@e;9&hFIcF#p@(wO%T97R_I>{V6?V+xgdeXgib;TZDy0TFn*{;JiBLM z@k)so(;ScxATCCi5f>nztx49VCxO-xHNWpwq1mQm4S7=~dv`!!(j1eh)Ta;-iY8c_Jn`Pp$ zOgue?Pv+>grw4bI-Cu_G7PQt8xU70q%zlJfC`HFbL2BlnWVk2Nyqr0OkjLA&LR=$NX`RC{{X! zE|#5cJXL!7sgqAvo}wgVPnAwTm7GpbB`5h4lmt&n&>2(wZAyaQ=L_|#MlL=y6I$KD zzi*uc9WtE+Avx>!RSvwe@apyd?EhErvLIREmHZH|IRXGq1tAVoK;5=2`KyeBWnXE%SbBk8qVhbs`m87phl}E{kK%C6ibK4< zB6!T!RpcG)UAvE6(qgB{nwyjXUM-?(zq&PLe(zUDfZ44kvG6H-Ykyv!a%*PW-?0zy zx9BbOE8aEUgKfA9^&k zXyQ96Q!zx1x*}B_0`Zq%HIx>xGfZi+PyshxQLm7nHcYY7quL`i9W)V`9P+jeuzdS% z6rULlh|b=`gSfXxduIdt%1KG_f2P_{JRe?A%mn!ds(fpTK)d-Wx412#zmNdt zZu`{Sxknl6o;G|~RaCY4s^yiyQpJwEm@%BUMkrWm^WO!q&KGcxVg; z>AW%>8e)+&j^Dv`$wK^jGa?w#MNI25I%9J~pfLINJ=>mov{&sLFNa5&_C(Oqsd>@@ z`4}G>NFo z)Jd)R#q}k$3)CZgl@$q=OtLED)=Q0i?N&`%w|*zhJ&i`PrnH(Ol&*?VyV&wBD&dzW zR*C!)zgUu&Ul5XM{(+c*R)4QY@@iKi{x@cv)jqESeTsg=?eEgnl;Gudk;5yjd+rhy zqR?>2yRSB+XyR1i0qUS^=n;Ml1-xF;Hr@tu*U;lFyf9K5`SzS*<7h9&u9c}YC$2_Q z?rP7})YR3hSEuYm%Zt`18Iqi5lfAb7d!vUjd$&t=b- zUU)vXHYG;qa$ifSL++K2z542_3PqXB6*`p=i0*sswRSafZ{7^ewrWHzGJnSX;NQ%U zxo(I=htZ#+RguhPIv3qB#b{=)f{0Xzqg@6vP?vD5duOFbeNVhs0vE#6L65-YkNBe$ znBz$}kT^TlINhsLIe9#FI({lb@rsy!9X#Ej8f8?Y_*i_@Q;poAxKOvKZ7emb?eaTm zh)miNZ}9YoVMJBcNd5~m}zy9?Hv?mTL?lWbUegtdj!Mng>e`x9yv=y*TK(}*jI73}r09`RO?J|^n1IEv+1k=N zYg^I{2^$sEvGfTUzy|LASh6<*sb1lHdX~8MfAZXfUFYztcJY8N7s^$O;J=hh)2^g8 zh+wpn&*sH)+p`VW!p}jw>J8eJP;_4Z{P{EXDb%?2E5Pmox3IPd-fu>}TRJ=Jk}c|n zU&Z&&b3thJCMz2%_CCQgau zvrU^$g&Z9)=(pCX8rbvXr!*xmlS*ZSVf$4z3%mw7iaps&9x)|j&caYI%rB7u2hr8M ze0$ALdxlii;(xJX(XJNz%`DLlyY}i2u=B>;a=Tt=@CQ;`_$8_nU^3+{EF4X(&BDmn}7LDo35Zj9wM zrgEZ8RZW?4d;3H+;2Km3r9Tofi2n8%uA#=Ieou^TAEQl$xl-2WJPevIbc?Fg>?Nj8 zdGx7xd5m?RvKt{^-CDD2ZJj%(qE}14CZ{$e12i=&5_G7<8Wc~164Rg%lcqt5AE@6S zbKN{9R~QAA6T*MuHif#ZKM8e#|EJ$qwz9xt#Tg?Menc3j1UES2SaBfh&W9|Ys=Vd8 zQi4xO@IsO&8&9nSokUPp~;IeRy~J@(3jM{9@CfjZ`921=r_Fz zrx?fzenlC-ps9aGZm{}wtEuPe ztaKFEkAeM|CWODmHIW7HJGzt~;~xR`>jWm+c82dXA-r6RxYnOe!~So6Q_QkRm6~}* zqmH%u{Q~vhdoLuAXUbBt+_g1_Nm|_YI&OPhXi_nd@9{5Qddb?3(u-^yY+!hKGI~_( z=L+;cQK0`Y=>HW%|9oAG<4<|*ssmWN({LY17w$KC99Uh)0*rW6R;^mi>pfbPtgdP_ z(LPK`Saoc5nJT~^f*4`WQ#aIPjI1g1B{OB01#L-a?Y&z2l$48|!=sgQJ+}576!0t* z5fRtU=H4RTMHIE(t2$5plv42@WocMbVU9*vhN603n4#)CRTr$QP+_p9;?UvGfBy4x z=g!4NcDHxkar+&2+{x{(VL4R%`TyeH>9H6Y8`E10xbGwG`M&m{ecEw(OXw>)!j>uo zLIs@#Te&E7^a3Vpd21_owYF4?c292y%f$B zQp6T4z2VTlI#00FE4OmiO!dk=QlmI@Eh@w-bQZkUE*d0y33p#@x|h)0oi+?e@BaAQ zW5rrX|3-2C%^h;`>Fy4vECRjB!4hi>L zdxHKY@8(uMAu&upc~=k4@ZCCV`nOxRRI!k<(n{kF)=PojTNK zdI}x;sH210OTOZkmOlcfeps8}`lj_R=GJ!iw53tEzuR6*QoB4WbvWynq7mCf3}Gu8 z3l$9=`Uu8b(WozqdGV;Rh-oYktSA_zRRh_o22`oOc2u22V|BJFA4sSc@$!@=BF42S zEw*wW(?^7Y5fm-;5usox)g?vC-4@TiIbx`wRohCwy-|F0u?X7Rh4UilSETZjh`Qd29kJiz%LiMQc_Iu=Xcp8WVhdic%NRFn* z(&Ob5$B$nnVZoT8AB1*k*Aa| zYZii)5gfpeNw=C_W1|U3_d$e}aVztWmecCUR(2jmPthpgfOo%1N(X6*>jUlH{0Sp5mB4dEAl)lce%(;oWOrB%qc-CFU*$CFi6doNj4(I1Op+=i-6 z`#pcUC;Z*jG~=~ZJ18#+MWrICDzRKwgZUZF`{xAiS>3h?^d&W{oo&GAHjZhdlwb~U zsa>tAo1ZEYAu4>lP^N6>8Fzzje>ePDQO2?HkQ1i6uvKjq^wfQiv32;!=jVQ&FpXAd z-f;&vzq{)bch8tv>68)ofLe@ChM{Xndm&G?r>^T%5e#P&r+V7rlm-W|`DY$a=lLc= znl)zVA$`30#7#&x(rolVylFg9dYrQWQtK%y@&XbhnEDn^?TBb9w4emv#d_{X*%$_F(HXcvCM#s8BdQd+gY;qZAJ9;sS3Vs1_pa z^c89==qsG~sVaxMU=COSWt8^~DXcQp+}9&~I*K5f6|^T-UQ+u~sDEO|ZYKEJ43?;F z#3nr@sFA9$>t}B;`yM@p*B{xVXl)-zFA0x|vg6T{8X`>9pfSe(b30g?cMoWUiAH0P z>24jBb49`RxpF%uB+fS9$~|hCG(UkHpqUBrCF&8AYL@7eAzH)gg!$w?k_cA6=Q! zMa0Wus|&I@{KAB6wz>!vg}4xxVlGllQD{efZ>1=xx)=JAE|ZQCtSBz$cHw7-D({h( zYN+QGE|s+s+Tm9sJx>qlr58&1q#2Ak`HE|m>gATo;AqiB3@c^O+7?}J1|wte>b|Mu zN`2~USE8xmE7F;$0#jF#sp!fm*zc!yUM=HlrtD*dF=TTkh?@Wc&ZS!Nf4om&I+zBn91wd{k%|q#PA3!-pRh ztFApzpgvufn-jsTVFIgJC3KvvZDz=p8)h#k{<^Scn*c(@9e4Xj%nL&1bejzSZqAU?PRX!@F|FttO^Zv ze0I7^u&E9kc~_ed<`mnI?|yWv+JyHz!CZ9-Z@=Zwry(We7wOYrk2$-KR){(sI zk%khaq4>oz>ku-Q{gjEsHJ%&1Ub`0H{+R;qJ#hbZgZl=lTWLFEYYef3TBC-~hVKIR zI&+(tu85cgN=VAL~)%+pt6(2 z!cFCH(W<4SIMfvhX*2@=I+zR70+AG=&OJ?&o5!6BS-$UI1b4x@fMV0V0XPPOTOz<*%1t}t5SKYt$@Fxn7&4)`zD6-B&KTt^ zG`1u<&?eS&HW_)b{gKDJ#rpZ-zEHz;Xp?^_@6JfA*}ljrWP8j}0P^_KZY?W1cn;@; zl`1RS7Irvcv?E&`^kUXkC5n*rTPbsA3W30Yir3_-<Wl_D_TqoI(1I9r4aj7foXr z?Py!upn5w$8_0fe5j+Z!W&??|8rct^j>rS3r??2o@&+!#;J}Ghg9AAb-arT{Ed|As zM`EabX%Q}ggWbor_A(|I>j83IBCSV>Y18=EOb#l2o(ptq0pnI~)vASPEGvlHK;B{a z%sdX(I1;wb(o5ls1-U`-HnmSUv9Ae+%ks&;pv3_!!U;>>2Mh4rt)@y)b`;=8xXYzXu3a`vbgzWd?7DZpNV zrp{t#D1I^RK7-+#P0*eIoCbTTLsALZsuf-ZYz!T%kHYTmpTRNQi zdqWLC7eV-S^U%@fE8#k8W({BxyB%peJM1LuR((>X@EZhMu))vIO# z_=l^-_L6XFsxY4azMoeEK_v7jqx5O?uH(mr@{+;fr+H@3-s>gK*8wq@jvGz*8#8F#Of0w~PS( zn!UhR$a#WU>xGw$(;_cfkri|C;R}j5`Sx}|0RTe;!&-mR+tz!adsPU7PQ)?Fz$?aF zf}#k-NQa0nW)lF@=!OU~Sjq5k@=a2F+`<^e2NU>_G86r7X=&NgWLdU6T~S)OqRIOI zmHM%JAi`fBUfEcYBKRa$5)vc!@dCccLoxP%VyZ#ynXU&?drEV02>OiLTMWP*=n2$b z>RperXQ~L|n{}{AGkiLfO?r=}_~a3&B8b(S(&OrMWKUMqNyemA8(%1s=g1)TW3*z~ z)rus42X)VZ^k{1QN{?YbF#n^=-2!`lxXV?&y}aj28M;3@Rk}LWysD82l1bt&IufL24R{lGMDso3j%dE;*yQA3=@3jmJ6z_r z89m~TR#@nN#2<}#*BvPzJwh2M!z8oA`Jv=sd>}z{EA2JLuWAtE1*;lp6?Lcv-m=1~ z1~eQ5+f@yuoYIUu@fU4*XU3T_#hT(`63@Kg8z%AGyR~=R+uflQ*c4ukSQ4iqSS*QC z624J=^&1%Ro&rFn{aO!a(c0neF{?>31fJyiF2-Q+guO(bj8L-XU%Hh)qxy$Z@PAt= z_zk7tTUH9{YeQKp%1gJ^GFQfE&O{ z7^v|FJ{>+}AJ%8=&+2cuRaN_oegMaz{o7Ro{41*)tI9}462hAtGS$vRHJMLRo|bMR zr;|vSlhCoHPNpKQ1PTG#y3|W7XHM2|?BPQ{VOl`jwj>L|k7O>)nHgEKq^v+;aGgPe7bH5FD-C@BmL024K4t!5qyS+iLyx2((7 zAv12(8=fP+FBTtB8f}W)SuIJdFUqMRvvCUehU|OVMueuK?@fy~av<5;ep6d6*6FmbBP8j(14^|7`K!=6s{AKvAnFjv$KfaBAp(rIc zWL`Tbqw%7@S(QWwqoJl#i?vSwCUXr!EkRLGF^Tc)w7|gRALb3z3sF;IB%qQ;=eTZ= z{+NP-JHC0-Mn_qxXwH$-ZEY0BqH>LOWooVFKkJX~-fH_jw{G1}>0p3wGX*u;@>3pc zaa84STe_`aY}vePOAjrDc?c~+N#Ynejiz!)p7Dp6=ArZ?MsppbnH$x5%`klzd_^~? zJ%msU0Hi1E6_8ZG#yxx|3nER&*@A3Xv=H8^NByqEbfHi^6!?0;+K5m=@Q4>t45%Qb zrH>>_^JUHD%@wm&G6QK9>2$n%C%RqEsra0vG&9__8rZBngAc6sNOiUg+SR7KWwgRE?sgpy|(@44%q zq^xIe;|quz2^FW#Mt)}%N83hfY#Z_4zFCe!n7xBWE7|!*jb@{_SVyesiGOc)LU9Cl zv0ST|pRnOONlRf-m1ua+d*hDiU|n!lUrmQ{BWk(?B400VK%$(-^`Qq8r$z_G5Cof$MLB}gW+EB z)Rq|gz%%)fQdBJA>e{|RiyU)wEiH=4f3afn3yR5it(Xuz1>&3?K)+g6GebUj0~ruM zvZ|MA5PoJ9ixD1w%VTh$D-;Z8@9@4~)uTG0Kf2qjgismeL#O6IhtqXogu%EHsjB zBX1@k*~l(TR7O_~Ce-dMW>Jmdp<0itDG1L%c9#mAaz?U(QG2&ij4BGo0mX@ zgWSX)U_HLI5RBfLK}Z4cUDj)IH_J4R*k$QiAtbdJfJ8me6s>08W}7Jx6ePI0dV*|K9JuP(>5e~GunpqK*)=fCY9oq+so^Vc0jlQ zObABtAYaNckD$msM~UB9hon$64I)wY&CusX1KF53U~J2XBR zylu@_4lnM&%=qa31IFbcMLN3e=xqXPJYFq?3MnC`4unR-owinLf*NW77 zQ~GNL*E%kVZ4662IUm2czrg9RBhWq6ZHDdrK!AdvTAi+;V~h2}r3JPL(`RcMTX$~h38IfqK#sPIgUy-Lu+6gz#1?96MGHr3 zZ9c@v^C%BzXS8{hgUx)Zw&^J;MpBc;*|s;tp*OMv*k4F!v~Ho%5H9Ya1yOtnBxh}e zthoesc|x1#9wsY!kt{Mh?0*^&bl;tiTA?8UFw;<#0PjJm!e6> zjvC%ry z&SL7?fm=fxa^Ib+32L|!pdFP#Xr4Cv62fF^F9~X-=Knv2`R{@GZy4qa@2k>Wg772cM)6-gB(XiQDZN6;Awqw=4mK+w<2-6FoGrE4G z8^~^VcOmz<1GjYKo@2*Cg;3H%?m@_rBAVPc+dBFOLW~qT&j}X`7E&R=?XdW*hJRe> zJ$_|HoSyyG6bMur3Pb{>SCR<@i%sC*-tgv{!J?qCMVVj+2q!O8E&k%e;)579OvK)= z(AQPv!7GTD)bR>xz)9T_p~z2&%57PPY|33)lHEs@J8_aKar~G&`bk?|5ln*p0u)jC z-87zMtYC~%5kxoKUno1oZ}Av=G+CxOBp2UoBU`+x<>66Ce1FH|@UL1c@ zPSwcUC16PIv9_)@kapy~r|qRmo=FqR7&kqHmKT5yNYQbRQ2H7T`po4xDCls!*+oxh zb$~{_f7%l`9H@PjNyXbK1%z+ziYW!6_c8`V?_=nF@^B2d&!_{9C5=Z~OZ(`&L=bok zFKaA~P;Ukw$>H>6A_noI(!xav&Tzs-D?NyglbDVZ6a5ssr`FJb#f*^QM$C0b{%~5x zxxpL`cVvKIxBZrd|He&hX6`RQ_XeDeoD>}y-#t5%Um_56D}WntfBIro3x|d zRT=$Q#IpAKmh8$Xr2%DT=VZSX1%3hjKe&XZb7?F{Ik5iLWns$Yp(~l(f%Iwu?n|PH z@dSD~Jn^e+_al7xQv9_#rtr;*f4+)(-5wwdr`@~n^}ZGgz#DHkgqn)b-@V%l7KY%b z`_cb6(;Co{q-l;nt<;dDB>D+~v6lfLY#cw%(B{n-mPjLxuY*rxu77E#!GF9v-IMMu z?c1BO79TdSZ`b}VI3q8H9s64_{nDPj85JPbdEgRi5}tCt#7K$lD4mW1x2ci0a?a#o9uJZ=EQpSduHV&fqGF^Y}D22P)+*}4wr&ukt&yV@kd6~O=R4g9|k z_`hS|AEEizV6wX*`U9(=^{euM9^tiM8%0L2Ep*4_(z}h7(ZDetnUEZ}OXe4!$$@h{ zR43AbGAd6Ds4Ey$CNGp|i~wL)xKn&tZm?sMatyF143lc)s)mFQtUS?=U=So4@&3Nx z1#2{*H~|dHYml=dA^mRTGj>=8w}Lo-I4y%~$i-8t^YCGJr0eLhW5qJ*x$)!e4Cx}}l0Y>r-qWI# z!CB61(DFBt`9%BbwN?=>-yj2w`JHNJogWeBSU}OY?9mBI+JUZ9xOnfc38gxX1Ms9M zpqlW=Hq|%o=k2jgwatl+M*+;k_S4NnAb8W5yrrj{t^L*%7=u4#jY718V$Llb+&wH# zbk|G=jvv&dA0>$HpN)J=Z zOA9c0lZEM`d~s{Z*dtx2XDDd#(i#c>osSGI$rk5}QYvl&ftQUNqszqi(izN4KyK~3 zLj?l46JziE%S@mhs9_$~kP0foY&78=5hAbViE5a)6`gma1O4RQme}CJRFTveE$t?> zN-Q&dBEh&#I8tOg2T_64&27WVQ4Py$_gl)ivqR|W(d8jP*-h@g^s$SVF6k!^ezD)A z7rVmm^NY1h`NfKUlh~V!?vlG$<_u5c`_#uRJ-g^Z;1M%-Xv2A z(N0I?$05GQmg=mN>DLrkpz~dA-9|y52+^ialK+PD+biPoVQtZ$DAH+DU^7G;NO4$P zRD?R+hZQ6naz4^*6y?`!hcnTgeH}D+9RJHA6I^icJVvweI}*5j4wyIhR!s?eW?xg_ zo$kqYr>4{-WpVv}onqc>zU0c`iZF5GXU?fnQ_;cTLBK;GLDyL+jmRT3VdhBOsN zE+)^Hv|hb=y?)JdTCJ%D39SI!XAHQ%18~1r%u1p)N6P9j;L4 zTFjAjt_r8S)0pJ1dCu+TE-FMM4nwO=U7N1G>LXH5GrWTk}-5?-{^lH~Ut z|I_WapFAm6E$u}L`OFx$(P||%q>-aE6nXjCg=ZSn7uWbiZfhF^)Rw~5v+1A=RWWN` zeV!0$I1Gt7YK+sEGlVd^kzR68I_zsm^gZQ-J18|PU0$Rgsqe7wzGRV+HDBb8__mn6lpi!A8NMFShQeX zw^eQFFa>Pu*oL@R@E{$=%}aS{poZTcKah~hi6P%PfL+Gt&KH-KEFOo0N2D~fCD9|T zC8fn+cA4pnd{IWOJ~iA<9!N}2k73-g;dWxU&A$ZW4(o#~G3)n(A^4_jxS2k@b5_Vx z1vy>$8&u;0za_oMrz@%Xa45?jy3L|j=5pB&N0c7(dyw#Jz9mL5ahFSzms^uvmrO|+ zx)g!MT>|Wjm;UNvH1W3=qf4HLvqu>$KXj=H=Qj5g&Rx24IYm-uns>@yjiKBmah#NO z5Ao&@b9_+;JUb}2d!>fjasxbfA-9mjgitDrqZp=pyYkMv@4V~Y`-@`I%5s>~SsZgl zrx~}b(YCBEgpOx0?$CG%p@S_N!?=ae9>yJuamPE;UCrHtd#WUcAbvGb?}?VuM|?x$ni~h1j+( zB+O7LUgI?-aTP<9Tx~v8x-ykvV+Y7SXOR60kp05~vOSy_u>+Po1XKfIBGm_1)=3qU zIaC~AC25g_DI(rsuCPKjfH&RPM9@(NN}?5~L3L+hOTp5|;M)RoQkXe-F8w~U{U({I z?1J?6>2!7GC>cfN-gRFf&kZqjPYQUDe(QapI!|wa^==6$^v|yO*$%23tcT@tV%&D~ z?g<)-?%Z42jwqD-#EBF1&a7ahch)d&olu>|C;?T*C^arqGfelzjs^|PIGizi3M3GD ztcMJ3y-BYSVF^YX#yO5pYr@#5PjBIvt0b(ye3@jCu#~t06aeFHVFg_Vrmb<=>BW%B zyojn9j0?o!+A~qSpxQwkkvhURs1`dIXl|qojBA`P;?)>I8zQ=EniG3H+Dnp!5CU+K z?F99__Lv5r7>6Z>vX${C%;hqDeOoM-EsVJlR=wq?tol)kM>>)tX3)<>XtI8qI9 zC_whRI!4137K9T+=v|w7g8jK^)1Ym0YT3awDFi#&#_86Ueu+s=syQwxIT@pk)`e8S zw6>koSTUgpzYfXCZWezkWIMfvr?U+*LMORJHN1$wV5@xo^Vp!%3|mkQxN@yigKA7n zbdqdA1D&L_c+v3UNGbUxi*qWjUs5$=WyF9wRs40)A~cfHf`#dV(!-GL_@NZCog#0g z6ygM#B;g9Ccj{cJ+Y2K!BDfc^x21=c&&JlYM!yDdYp;UVl|e#Oa^T&#xd7qE*(@j)(GjaN2kJvYli#sosCnqmuIHv;j#^oFVCBQlQd3-HF zM3GAxaxNCGbYG1vT&X=g63}}C;}%qXM`w~o0QxPKtTzo^5;_XHdpCk~_Z8E#ux|I0 z{-1LAc9E`kAAG{*sDg&l*$CHR-3~keZ+VrlfdUmpFOir+E)}ITYQ#GkPj}>CdTIBr z!QFb&TYGBwrePt+@a}w9V`sV}g?RhX)GSi|ek)-VO?a-u__Pu_F})n7|HQvDJhuS7 zOwx`=Y9mrbW^x9gyC3uwLsI%?-;Un$Z+3SEq?DShp_g-TtHtL1D=e)b)lzziebDs+ z$TMP+`Smz>qWM(?n_?k&<4O~MBw+YO!|)fu@Shll*MlxjelbD54hRmnKGcS47uMV6 zD{3o8S9F8f!gR&D(iL;;clt#i(-|!}c%JeY0nTGAxGY~7oQ2{s|r})Z#v!8Bjw3M>B9|>epnlIcmWJ9uAzCB@0e)SEZxHjkj<4|*x!r%YF`|?3&swW2Izto`t1OPP=3zEBk?7boK;vserW?r=d za?S`*SROu2&?y;g^YdgZ9d82UrCmFRcSR&ySf``T%r+r(=qM(mOhY+EN$w~1r!D5h^VNp`x7}O) zJOg6p?P*sX&B-_cqIY*-Px3e%YY?D$xG(AcYsuK0qWffKD_pT5#_bxNyCq-~x2R^Mhdejup}J z-F)2WxqZCO=a>rdfcmh3Ivy&2Z3wXfWY-{74ywB~-CB0QBf%ZywCN4KT6`{QXTd*3 z+#N@w5tGC4e2hVy=EWmqQG%KJx@Xpj! zyp$D~;^NC$vRLLh@+(UN)I`>0vDV=ehUmg{jndjA74K*hUACs86?3=)=vaPLX#lY2 zuj;9GoyCj9C6Q+Qf(qe9rf68g(vfCL^Jb_s?vDTC)E%czLF|u9p9vy5`b=jAwhbaY z5u)}X#HeT-&y)eaYu(ap5^864N?S??PIUXI;nV~-Yedn|yS8uNPBPyC`EotQ>o?7@8?fH!!cv2bl{jSzoQ9!od(T4JhcdzqSU`!FDb*4#p~ z7;1+bZ^Zom(8-y6UZB1}AJiAWPmp2|OUwuLNHLyBOniTe51Pa8D^krG3wA850Q(C^ z7j-RMxCkykwy=yp-h{~K5c%|h(*1>So|*s?7r-Cip4@ipTy~(&4cOl)(tiIetI|cP zDIBHP8~8j8N_$^_!2g)d28pRKNilVAdM-;KwA&!&!f6JoNv3H~a!hVjU{GfQZN=1( z37>54f{w%Qhc69Z^sxBxiOPkEi3<+=Pr|$LMD+q6n(!C8`NRb8rxz-E<1R!KiG7fd zPQ({-{?6fvZmSs+6FZUIVg7@cS`yfkV4G%FW)pNr#bFjpkK~#SRXNjf+>3QmGn%KB zb?RQ}GT-zY{+l%-?(AFB)|_H}0w+Db(FaKE>p zpANNxVo?Y=s3$n5ZLM9e8c`h2Zgw0^s}!-Z{$w~FNk&U!qbbEgxq*B~S+r?qv}>OU zH_aUlh<-krP#sc)o7jXKc20=vx1&jH z9XRa?DND$hdJ|HS?(P1Lc++0qTnRCDHcSwSbgw25e#tgQ_*p|lePAht^mX@KFQwUz z0m2`R!#G?j-k)Bnkc~pVDN`k~$ujL;s1#SNQcUQj^wHzLv|>SKU4u<-6;Y1?)EtzY zl>>X|0;mt7`{R@bng9mI32*Sh~ z1=>@}K^>M)0?$S=AC*<=9@F-lIt{%RCpg#76%)l*04|VxJVCl#HyFty8U43n_-)C? zq<9hh;F4@&j)ECk;nCz|--&wY0 zvb#bNAdguE^sI;oY(k2JA)-rP=7DLpETJxskqNy8#WqW5F)S4o9q^ z+teV4ybuBP8t~wu@SHZuFRIw(csb~o0WyzZJB)rDJ|7{nyA43OfjRr`H+~0jZvgb&0(3sQZ)1Pp^eP1#M@X@k znQHQg?S4yUV{REsRdcSnN5l!(-W|ktuDr6$rKGUNGzBS;pD_Z@tSH=G$81Tj69GVO z7o9F_QVTwE9(w`uvPsDz79vjRUSs#k{W+3*{?OpVGH^JJ@4d8_@1h*mVd9BUbzm2rOhW7xuPYAN)=<7p_MnnwB4U-sZTq?uQhb~sc+4lh6U~~*d z=R8I))Xq;{C8)7hxJ*<`c#rpaTfRW zda=n2xcRnx&ri>sIfA(cL2#tf#rnj><5#fcsL!&Mw?@U<6qoS8s9NEo^B6FEv+HMo+HArG?;}|de~j9bpVcW z6NrR`6zg>1wV6VU9Bkqkp{!O@ZMWgzXEAkiOx+NIgA7xI7zG-*Pj_;g3a0n4uHyIQ zn6`&eJ1BkX)M+%(0My}3bE)fXk`9(~dukb#GnBS*b4rVX*^?InoXwBf<&678WaaE;&WqTKRc+wKQ)vN9+>P zqDjTgy?LJvq!b+yrIQny)4MRR zn-66V=74H?Uq(I5h?)S*cO^(AAtV?b_3Z;>-N9bNR1$1}YA>%HD~BlHZikjcc21EE zuBCJ>=_P{HD*Hb9X8CSiUFX%58J}j$4ue2B5_n@9gS6B_$t7EvXCVFGLf%q|+q9{I z1`bsQNiU+2T+AoB1hW$pyDmiM2YI9yW}QEO{(}ABZG2vz=N-pqdh}6#b3Wq_9s-p; zL>eZ&e*)igBDvTt!i>U_UMfuj%!x!6r_s(FH_AZSA~ zI7G-?sPsKTDcY%yM6OXH_g0Pd0}-BQuMH9jmHm%D*TG~_WgO2LvWgv;(jFx;gzV+{~FgA}KO38XmXxz|qT*x=Z!!!$Ru zYH;j6EaPUn-*g4Z#C`duc3KiW(iLT% z7O&wEw#qX3Elk$rw>0i>&T7!OLNLG86Ux;k<7~R9CvlHzA7A8pf;KW9gKJXPZ%&+jU5@|}N z)HzOsU_KC?LvqU$L>JDw$;qVH?obafuU<2PV;ku)(Aucwm!dJ|Z~(aWu~3Q+@N#hMj)E`~ z_aj%BbO>`gKS34A?r%KMd~gJZJ9_B&!*-I*&_iWr%JK&@DIn?n$$b@8`k;S{DPx!3 zosu6+?nv0)?B=?owIlv;jrkvcpnJcC^@$L&=*Y0V%4>9taD^(3%MOM`Vchwf(ax;6IH~HixWA7`r^e5T|CT%#+Q>T=~P!+ z;t*gv27@#eSS3&}gJpFJsZ@ zp0P5ojG@scFrFE!PMZlZt|KCKukfPcMqvVh=X$o3?+&eYzxnrt_Wi36A#4xn&+su( zzi*H>diXAlSiA4nAl5twzonVm8$SK7OaXO1V3L0XOeIMi>Yz7y=s>}tYJ1|;wF z^5Ep)rFwzoFBz8q6O-}V;FVJEGP>RHSy<2 zgojzsn&CN`oqPOK#h8zBDgt$0-@1+Ih z`N)jcAvH62WiF|su{^Uq9{gd@+>s)VAFji&Lo_9f0S2kV-PwJ|Qyfuq3NY_BEI)QM zJ~GQfhBkyRa#uAd_d9DKd2cb>O%$F$vB?}9;rh=;@B^`SAa}C8PM$ChKBYI~5iE^2 zR@KP>vLG_lIyTWd$Ds_1|4A2_F=7UWru28iqZxMvj}HO)H5hphT-(|rt#KLQk%R5) zH;k|E6Rx*EB@~bC?7#KvPr%4G!p27#nyqL9SZ=wMWNS_^Jl>w*V`^gyeX8B7RdFrd zX0Y2%Y~$YA*Uf7;fD^FjiG^}-Wifc7MA~H*ps`;uv4l^{vg~Yh)K0HndiXHC!~Q87(+~5T9CNNMzOTJT{A3Q~vn_i_iFWPv zUQFt{AO5*8dS>if3>)Jz%V&tSYEb zDc$qP*l0yf^vK8%5Sl(beYM9?qQ@;bxN!nZcNo zS#%yGk--GrV+x0o7H9HuGFg)UP`OC&6Bn@kioy2N2HW0XJHjWch=Gro=7Ho)WDW}5 zT5+=g7!(GH?FXyqq7^%qN6Y?(w@uOU6|9{WQRnk}3d9;&sX5P;D;o+_3!k-#tH~*8 z32V39`mUgLq#Kh>6_ic1Nk@uMI&_50!PYJRco(TRh=!}Rcd>KbSV-!!|Fxjox>JSB zZBsIkEaTh4X6W|beL<6kV<~UIGT);&S&k68joNYg^iw4F$Py}b5VC|U$9O<%HWWEQ zxKO?fgoSYDKr;1;6-(_Ui!0`|pAdVye8u4M#m2!#`VC~1-(Xb3fAsfD{5#8(d7BZ#kFDq!C5-@)p?;eA1Lfal2G4sYl) zeHx73u%V@(xVf7fbHtO3%t_3Ct!)U?8Hp1S?6y?tT^9`0pt{Ynl{fjM+O1CL$mFh& zF+`o%QDfbP#l}oOar>nY8(KRixcuA%@dSE&XL1*!GGMLDNkr5qLp`bJN;Mz&dkN5k zqSs*feL2iJ$R#OZL4QYPGnKsot?7&qX87{_BgNr-A?RH*hRt+UxKv~Ki^`X1RAicB zw-W1zbXio0{s`5inO=PJPYId{GyX!qype5MPfjs1wI7 z2JqbvXU)WK_wyQ7;wOJsAPL~@J`#3Q%aBJ%!^@svGbJQD0lqUxb~e}=+M#p2Y|~l| zt)#+xBRetSb6`6~AW8C+Fpnx@%KbpUW|i@eW)SPnJms%!p3+Q1_w$~g{fvo9fZP3e zRtL9l(>7AYrP`Wh=&G*=D}w2EQNj%ebb*4n$vbYD0> z!*A`gg{q2`z_AFGw5RChH1xo&MXkANtZ?GMgaW;Zl(c8>xKN4)|Ai52>ySgH#E7*T zWE;GMSkLqnPjTwv>8JdiHSS=o<5fObYIR8)^6Er{>!eEJg{4IcW1+ZXSyKK;wzSMB zb-XNMvqrB{-g+XIk1xA9%vjrwE3LT##Slh_dkRDjXCr9!k<4UA3623YUP43D$ zb9&|}1FI>&G5Y+MOQ~nI4*GT`WnI&L^|W zF~UZb;Knr~e=(WuK%BMNNL?`k?SQeER6}G61}11vBFC zZGOqL@na?4n)cYTFUtnra~QOpkjY*TkuFw%ur-Ng7LweIMb~I`{bMy+-5OU>M=h9W zUE@MV=0Cao4|KnBw{oolgI1R_Ha5n+I?m1d=koO7&wC04766MswY z>PFaA2d%|`l5DMD2L~3&+=m7;PL~0{%s>lWpI(|XRwsY3w3t;ErA5Y-L0LHW!VC0LoLu&=mr6o<1;CO61iAl(^IP>C?}yAL2{o8<^XX`8WhPb6g(Ro5Y^n#+llNBx$%l1veaACrP@exZ0H5 zKJHtcjmuq2)QzIc-X|vL;HkUo2pe_G;jX}x-Jv>6Il*R3QKT~z>C)Y%Y~=H@`Gfa1 z?knAY-|qWoi!1Y!2k*HDcHbY7;Twc5=g{T+o)mQ>xl@si?6zKx5j<+@hCf_2bdC?y zNn+O#qd{h%S;*{d5tWcxJed{rL~6ti#FrCcb8J3>mgR5T zo*+u6W-+F=UtkD?ZfvYij9l1xzI5*ViE~|N&z?JX_N+fwIm>(5*=~NrPd?zzcIh+c z&bo7b`kX#`?rd@{I(rHV9i1CJzw<(Kq5(%v;m1tP8%LJnVKMEPJykOfvCs~4snIpm z=-M~pZ&n%G{x&9}hHR#n5$br;8VW}liX6Wmp>O;iI)UjM2H7(Z`vZWofb6yk9b{;s zHhwFp%`xBdrw}+aao23-t7elEV=gSNpLvRA=syxOar4Hd(X zmA!6GW@K_MT}p-56BiY%4+Q!9hS+0<*dvD6gQjYXujme%G74(6Y;bvxAu#w`IAjsH zEPU=ZOkM_bM?A{>Zgg1<>?U<5z;>MJW5B&^**+UEG=aoJop->&(WVym(5Q8Qh2PpQ7R?J+3%ZlXX6w`+Bhoa4@aP&hbrlGwoi`Qa zCgagYxzq!z__~o#d$F6^ zq`ZgLWBUe!4a)2GN9_XZr(%rhuSZiWkUJVo1*{8Gk4t1f; zVAfHSS~*nbO0%NL>NQ&`M6SDb?@_wvcM!a4euO*f=Q0MPu!!{O42qrML^S6&?=5o> z$d3EEB~0-cxqtS3_Ky8>|NW!)4F#QANN!xabQg3xy;Ev+a$5zp`j|gjHD?$H^I+{j z44ijCwe?>yd$9(dhXp0NbaiO94vhm*-PW-~U2Tn;UfyuqRt$2E&TFr|7QbGR zyy4!gz2)Do8sT>Dbr=YRCi#Odi+9*i5xEjzhX<4#X#m?>~^&h_W@ zowpi;&E2hN@K|dYZ7)T}AnzsWVnt9gM*Kt#KHV=mUChR~e~5nVf7Lflr`^x`C?kdZ z?0(o!)T8YWl3ID&y*2C2H)qPv;iMpM7GdR^=<|v{NC3lpwfsyFT}Wm?1W+u zFNu!?U?%Qy`ARI=IiF0>oG)Fv)B>F+CN5^gaRNHOW9Y2IK|gwY+|W5&DOD9N9ahzc zSc9Ss(TXvEnur6C4E92!BUuC8aEc?N`br$2KFEdwz_YP5*k5%|B^ zhGB!0c$?cD1kPE?Mq`s$Bu}@wYt1no8r&+zUgVQlHyv2ple}hoOp4a?h>pRrcOdi} zZRLj7>LE3QJ-!5+p~-e-;vhxGn1~z!yP6pv4i?8p%p`2&OjoU>Eu;F58`(Z(1lmCQ zMeDi`-w&53HCfvo zGi+zw5dWL88iRI}4?-Rlv~z-EEIzW}7{x}NKCIe<#2j==Xp$51wj*{lxHNP=kFsz; z^Nrb-Lhu+u|F57NUl5WQjf=|VdfN*dla)?_f#|RHumR(m$e+LNo~tl|XD(vtD;SCO&OQMd4EH!4=X90ci)j+P@Pr8C0;t-#^3-Q_iLvIn8{*cIY z9b~pMK2R>|Ty1W1)C@$BJRfZAZAPtQ&7nq9`?g}VkvPc!=2CD5eXaB)?Md>)O*8Tv zAhi2Uk7gHT54sQfI$6A*xu4!-2;FfA-TSro{JRwqYWEf$!W(Q@33|sgKC3Jd$x}F5 z_^k1iAa%s-eoCLmft3a8um^Jx+M{)(G6Wl_9D`)n10=t1kn9YScN-+Tl~n+F#mZqN z>nw+1*^QRLaTv`5Zl48$2bWc}q4E@}hF?}SEyFF_19UsaQ+o6@BxVp_kRce`5PH+> zz?egMM2x{-wk?&`L5p>)n}-#L6%}aAb*w?HX^pqdfydc)P+0NfUwDE*o+G; zI)%S7is}Ti#Ep}O`WYX5n0T!oZb7!Nyl5dzIa=%&9a6nbA(AJ~L zX)J{W^qpngS{_-08Ec)A1-E$Gu>a!6bS9glLFW8aEI(U7=%A?3T#_?l#hNHzgXD4CrQwEr<1jfoPHDE8LJ{5+X-X-K zgsT_Vx-5B9$Q9zdVMPqL64S&wM}`aN$+F9mmqf*0e7wDIdX6s?3%|dc3#e-tB#WAX zDS`v`p1AJdJ^8%h`Tyl8j%u7`;>I*@F4YNGo5yZB!d1TX& zW;B&QA2E?QM{6+d3W%QDd$#)w@Ok#kS$8Hno18(SICD1V-6Ln5fc4CoGhc+@o;$ne zTWxMO{J*G2^h*kCuhn86BA#JUy6uf{7y(t;pSNu zz!1R&LmlDf>YH!A_2ygd?JiN=_eeNL@4Fw=f9QTR`v!T!{i60u_d$)BliEMH-&Ad* zllu@Mfl)wh^n$6v0ZN|hjEa*q(>xo_|GqIK=xmaxXhLZ-IBjMcF)xsg2+@PgAr;~u z+^>7uG6aDA^L{yVfz%=rM?Z8wAbX89CzaT})AP1e2=L#%!FTa`&ugzy8K@7_xi`*~ zvkbEazMYMcXb%%bz0GwKGTy&W=IO|OzRspB8#GBhO3)pPODsXZBZD(Uo0h`B;2jV)Dxk4qs_(kO# z?k?S9=;`O%{8zU~4HQ&o;u4PX4^~LQ0jJr+`GV%c2+Qr@qV9!@7A@kDFN_u_u3Ub2 z0i$6Cq)yJfRvr8M%6uU?aoXeK@BRe;))&9{MF_04Vv8_?sqREqps?|gTY_E;T$mpR z9dmnb787p+>X<3U-9?buGg$(UrDN4(iJflJqq{sdbI6lo*2q&uVuSy}Y=j2WiX|6M zCo3v2S)vu%g_JqUSabSAOU{-F&!*Y}#PpzR*Vf!CZz*vh9x zA1>@MSFNOLv9dX`uBxwT8&CEHn#;IGSH9;SG=?VXLM}5eGh!Rf zb;sP%x@DK?k2ok@oR*<-;)?v_<>-r96rGmB3=M~m)op*ojhq(RW-QE;sL04GrW)2} z<=|Gz-yl%jWTUK?qCcp`D3W{P4GnSHVF?QY<-KQ1XU_UFHIO(udx1ymOg9)TfKJYK ziRYd@lb?;wrH094klWIQ^DVe-e6ex~Cn?dyNjzy2C!RP(e66g{iwSL!?~Z;e(rx!Q4-Gm zYR(LIPdoO!5E(j(*n*Mk>$gyA!TlWdBeOo&ISgorF5J~ z83^!t?pz5F>84&a!gBS%Z)f2+|5&j(m1_X`b#-O{kqWt0XU(L)zEQz_1;r~m;Xklp71?2(1N3l_4cVS(*xh~UQjA%f0n80&QpFrx+!j^~rR!z1bn zxb2>)hzOIJ4$6Z+9&!KoLCOPc0|9ez^DPHg1S#CEUZ%65!G_y40|8HO+icR=a{AV^ zZ6wfkZdSc6H&kR8Q61Zep?6wbCE+~O%nqUDNBX5p(>7 zb?e604|BCiH=8(|BM!%!JK2IlTr~+Ig)}GaRAd;|_VtoPC$2mg9a{uL$I}pED255O z!IB_H`*l3No2Dahie%HIPs?TiSr($<20JbNbdG0y){!d^VY|q#;zo1q?37j!VRo}4p zuGCSjoF$?pn0wC5pbi2dkuf$HOfn#lL>4)Nxu5lZcMG0#9$!?|Rb6U{R_)$vuXnBW zzArL_1Y#jJ<4DjTaz)^}bOkbf>8{*omAuGEX%J9W#x2+6Z)yp-acB~X73P@gxTK5Rf;Su?P%ktwKf z8|k;Qs<-kVM3fg9v~ZbEx%<%;3-8)12cwr5ESIm363M;9;Cm6Pq2U!6c7?QV6UCU{ z6ZrRlX$i($6Lf7T%J?#wXmu#q1PXReu17ESHWxaS8zO;fjnfd%*3dj9n3cT{lVVGu zN^bDRKw67~h8G12*SQRcN(C+fBt@9r#HIh6MB%pm_lqcrntv2_!Z{89$a?0!J0+&CfyL)*ti--fM|o66c1OOSGSyC|#i`kThM z$!P>y&^B!*qM_vjiZQFN8+qv0$V4)WG?&^sPsq2aa}a+{Q@RUl8q7_~z}UmtE3h1( z0c%!QuA50;=TV9GC5ib(K)bVHiGej}y^(oZl?~gPHh-4X)%jegLim z(MzOpr0_*RBbLmu%npVfkL?^0|IJY9Kyx?W2S+3gwP)@NHIVNNiyh|NG!hRL6u4HL zOHv0}ZO}T9Q>IlCxmezvXZ%t2%MKeHl6Oa6CN?Tj7%aJP&y3OO?Lz1iK=cW}&^{3t zDknPJ#}{h6<`*s%bnCavj~*1?dxF@8h_^#!CZz#r-`%@s?BpDD&3vq6FezYoi+Tt$(8$>mT(k1;m@Dr%BWei^#=4p{rX&PSB07=ZtAf1<7RT zh5PIHc~I?4?VLp#fzrLVP_5+dNnHEO8*7}LUvGNeVEncc#tYVxg0D!z*1fItg`|zj zsx4yLU^O8*KwO{=oR72Us2FY7r&@Y6#XTDxD#6~3?vTt3Q&&UA*s5MRLrx6UfjE2~z;5b9)=BJv>tJ~~Pv8Q2g{=|MMd*eAvfG$DL#-C + +# Welcome + +Welcome to the `renderling` operator's manual! + +`renderling` is a cutting-edge, GPU-driven renderer designed to efficiently +handle complex scenes by leveraging GPU capabilities for most rendering +operations. It is particularly suited for indie game developers and researchers +interested in high-performance graphics rendering while working with GLTF files +and large-scale scenes. + +The library is written in Rust and supports modern rendering techniques such as +forward+ rendering and physically based shading, making it ideal for +applications requiring advanced lighting and material effects. + + +This project is funded through [NGI Zero Core](https://nlnet.nl/core), a fund +established by [NLnet](https://nlnet.nl) with financial support from the +European Commission's [Next Generation Internet](https://ngi.eu) program. +Learn more at the [NLnet project page](https://nlnet.nl/project/Renderling). + +[NLnet foundation logo](https://nlnet.nl) [NGI Zero Logo](https://nlnet.nl/core) + +## Helpful Links + +* The official website is . + Here you can read the latest news and implementation details. + You're also likely reading this on this site! + +* The documentation is <{{DOCS_URL}}/renderling/index.html>. + +* The GitHub repo and issue track is . + +* The project site on NLnet is From 02aaa7ff8bed40ad322fed72f4a90ce7e5f5d814 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Thu, 18 Sep 2025 11:26:07 +1200 Subject: [PATCH 16/31] manual: stage remove resources --- Cargo.lock | 5 +-- Cargo.toml | 2 +- crates/examples/Cargo.toml | 1 + crates/examples/src/stage.rs | 24 +++++++++++++- crates/renderling/src/bloom/cpu.rs | 4 +++ crates/renderling/src/draw/cpu.rs | 11 +++++-- crates/renderling/src/stage/cpu.rs | 40 +++++++++++++++++++---- crates/renderling/src/tonemapping/cpu.rs | 4 +++ manual/src/assets/stage-example-gone.png | Bin 0 -> 1945 bytes manual/src/stage.md | 29 +++++++++++++++- 10 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 manual/src/assets/stage-example-gone.png diff --git a/Cargo.lock b/Cargo.lock index 372a3ec8..d47bb34c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -833,9 +833,9 @@ dependencies = [ [[package]] name = "craballoc" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c9d96bb4eed7f67b467d045c9563040dd5101b359bc60c9d355d3bb9ea858d1" +checksum = "6042c2cfdfce510235f88fea69e263ab3d3a1780f4a645fbddca2adf3af8d6bc" dependencies = [ "async-channel 1.9.0", "bytemuck", @@ -1179,6 +1179,7 @@ name = "examples" version = "0.1.0" dependencies = [ "doc-comment", + "env_logger", "futures-lite 1.13.0", "renderling", "tokio", diff --git a/Cargo.toml b/Cargo.toml index eb7e3684..8ba0ae4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ bytemuck = { version = "1.19.0", features = ["derive"] } cfg_aliases = "0.2" clap = { version = "4.5.23", features = ["derive"] } console_log = "1.0.0" -craballoc = { version = "0.3.0" } +craballoc = { version = "0.3.1" } crabslab = { version = "0.6.6", default-features = false } plotters = "0.3.7" ctor = "0.2.2" diff --git a/crates/examples/Cargo.toml b/crates/examples/Cargo.toml index 800b8bc0..116e1e5c 100644 --- a/crates/examples/Cargo.toml +++ b/crates/examples/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" [dependencies] doc-comment = "0.3" +env_logger.workspace = true futures-lite.workspace = true renderling = { path = "../renderling" } tokio = { workspace = true, features = ["full"] } diff --git a/crates/examples/src/stage.rs b/crates/examples/src/stage.rs index e9358108..aaf8f866 100644 --- a/crates/examples/src/stage.rs +++ b/crates/examples/src/stage.rs @@ -2,6 +2,8 @@ #[tokio::test] async fn manual_stage() { + env_logger::init(); + // ANCHOR: creation use renderling::{context::Context, glam::Vec4, stage::Stage}; @@ -63,7 +65,7 @@ async fn manual_stage() { // ANCHOR_END: material // ANCHOR: prim - let _prim = stage + let prim = stage .new_primitive() .with_vertices(&vertices) .with_material(&material); @@ -83,4 +85,24 @@ async fn manual_stage() { img.save("stage-example.png").unwrap(); frame.present(); // ANCHOR_END: render + + // ANCHOR: committed_size_bytes + let bytes_committed = stage.used_gpu_buffer_byte_size(); + println!("bytes_committed: {bytes_committed}"); + // ANCHOR_END: committed_size_bytes + + // ANCHOR: removal + let staged_prim_count = stage.remove_primitive(&prim); + assert_eq!(0, staged_prim_count); + drop(vertices); + drop(material); + drop(prim); + // ANCHOR_END: removal + + let frame = ctx.get_next_frame().unwrap(); + stage.render(&frame.view()); + + let img = frame.read_image().await.unwrap(); + img.save("stage-example-gone.png").unwrap(); + frame.present(); } diff --git a/crates/renderling/src/bloom/cpu.rs b/crates/renderling/src/bloom/cpu.rs index f059cd13..d9abc23a 100644 --- a/crates/renderling/src/bloom/cpu.rs +++ b/crates/renderling/src/bloom/cpu.rs @@ -470,6 +470,10 @@ impl Bloom { } } + pub(crate) fn slab_allocator(&self) -> &SlabAllocator { + &self.slab + } + pub fn set_mix_strength(&self, strength: f32) { self.mix_strength.set(strength); } diff --git a/crates/renderling/src/draw/cpu.rs b/crates/renderling/src/draw/cpu.rs index 88276c95..2f840589 100644 --- a/crates/renderling/src/draw/cpu.rs +++ b/crates/renderling/src/draw/cpu.rs @@ -45,6 +45,10 @@ impl IndirectDraws { } } + pub(crate) fn slab_allocator(&self) -> &SlabAllocator { + &self.slab + } + fn invalidate(&mut self) { if !self.draws.is_empty() { log::trace!("draining indirect draws after invalidation"); @@ -91,8 +95,7 @@ pub(crate) struct DrawingStrategy { } impl DrawingStrategy { - #[cfg(test)] - pub fn as_indirect(&self) -> Option<&IndirectDraws> { + pub(crate) fn as_indirect(&self) -> Option<&IndirectDraws> { self.indirect.as_ref() } } @@ -146,6 +149,10 @@ impl DrawCalls { } } + pub(crate) fn drawing_strategy(&self) -> &DrawingStrategy { + &self.drawing_strategy + } + /// Returns whether compute culling is available. pub fn get_compute_culling_available(&self) -> bool { matches!( diff --git a/crates/renderling/src/stage/cpu.rs b/crates/renderling/src/stage/cpu.rs index 091d97c7..e453bfaa 100644 --- a/crates/renderling/src/stage/cpu.rs +++ b/crates/renderling/src/stage/cpu.rs @@ -739,6 +739,30 @@ impl Stage { &self.runtime().queue } + /// Sum the byte size of all used GPU memory. + /// + /// Adds together the byte size of all underlying slab buffers. + /// + /// ## Note + /// This does not take into consideration staged data that has not yet + /// been committed with either [`Stage::commit`] or [`Stage::render`]. + pub fn used_gpu_buffer_byte_size(&self) -> usize { + let num_u32s = self.geometry.slab_allocator().len() + + self.lighting.slab_allocator().len() + + self.materials.slab_allocator().len() + + self.bloom.slab_allocator().len() + + self.tonemapping.slab_allocator().len() + + self + .draw_calls + .read() + .unwrap() + .drawing_strategy() + .as_indirect() + .map(|draws| draws.slab_allocator().len()) + .unwrap_or_default(); + 4 * num_u32s + } + pub fn hdr_texture(&self) -> impl Deref + '_ { self.hdr_texture.read().unwrap() } @@ -1338,23 +1362,27 @@ impl Stage { (pipeline, bindgroup) } - /// Adds a renderlet to the internal list of renderlets to be drawn each + /// Adds a primitive to the internal list of renderlets to be drawn each /// frame. /// + /// Returns the number of primitives added. + /// /// If you drop the renderlet and no other references are kept, it will be /// removed automatically from the internal list and will cease to be /// drawn each frame. - pub fn add_primitive(&self, renderlet: &Primitive) { + pub fn add_primitive(&self, renderlet: &Primitive) -> usize { // UNWRAP: if we can't acquire the lock we want to panic. let mut draws = self.draw_calls.write().unwrap(); - draws.add_primitive(renderlet); + draws.add_primitive(renderlet) } - /// Erase the given renderlet from the internal list of renderlets to be + /// Erase the given primitive from the internal list of primitives to be /// drawn each frame. - pub fn remove_primitive(&self, renderlet: &Primitive) { + /// + /// Returns the number of primitives added. + pub fn remove_primitive(&self, renderlet: &Primitive) -> usize { let mut draws = self.draw_calls.write().unwrap(); - draws.remove_primitive(renderlet); + draws.remove_primitive(renderlet) } /// Sort the drawing order of renderlets. diff --git a/crates/renderling/src/tonemapping/cpu.rs b/crates/renderling/src/tonemapping/cpu.rs index 4dd0edf8..be98f3fa 100644 --- a/crates/renderling/src/tonemapping/cpu.rs +++ b/crates/renderling/src/tonemapping/cpu.rs @@ -165,6 +165,10 @@ impl Tonemapping { } } + pub(crate) fn slab_allocator(&self) -> &SlabAllocator { + &self.slab + } + pub fn set_hdr_texture(&self, device: &wgpu::Device, hdr_texture: &Texture) { // UNWRAP: safe because the buffer is created in `Self::new` and guaranteed to // exist diff --git a/manual/src/assets/stage-example-gone.png b/manual/src/assets/stage-example-gone.png new file mode 100644 index 0000000000000000000000000000000000000000..c06b0e02d30f0f1b4b2a64e7ad999704a33f96ea GIT binary patch literal 1945 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|GzJFt1Wy;okP61P2bdSAL{2;Q z@qhWd-V(zg4t?<~=tN+78fSgtT*RO~vy&C#I yJ`k*N|ER{%z!^?hhyFGu|I7dyGf7KGd^II%i!ti=d#Wzp$PzBp{sKM literal 0 HcmV?d00001 diff --git a/manual/src/stage.md b/manual/src/stage.md index 663a4047..563cbf6a 100644 --- a/manual/src/stage.md +++ b/manual/src/stage.md @@ -145,7 +145,34 @@ so we can see it here. ![image of a unit cube with colored vertices](assets/stage-example.png) -And there you have it! +And there you have it! We've rendered a nice cube. + +## Removing resources + +To remove resources from the stage we can usually just `Drop` them from all +scopes. There are a few types that require extra work to remove, though. + +[`Primitive`]s must be manually removed with [`Stage::remove_primitive`], +which removes the primitive from all internal lists (like the list of draw calls). + +Lights must also be removed from the stage for similar reasons. + +Now we'll run through removing the cube primitive, but first let's see how many +bytes we've committed to the GPU through the stage: + +```rust,ignore +{{#include ../../crates/examples/src/stage.rs:committed_size_bytes}} +``` + +As of this writing, these lines print out `8296`, or roughly 8k bytes. +That may seem like a lot for one cube, but keep in mind that is a count of +all bytes in all buffers, including any internal machinery. + +Now let's remove the cube primitive, drop the other resources, and render again: + +```rust,ignore +{{#include ../../crates/examples/src/stage.rs:removal}} +``` [`Stage`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html [`Stage::new_camera`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html#method.new_camera From e5ebab9fbc3d75e5d2507f6fe135320f75917c91 Mon Sep 17 00:00:00 2001 From: Schell Carl Scivally Date: Fri, 19 Sep 2025 09:26:16 +1200 Subject: [PATCH 17/31] manual gltf model swap and hdr swap --- Cargo.lock | 6 +- Cargo.toml | 8 +-- crates/examples/src/gltf.rs | 14 ++-- crates/examples/src/skybox.rs | 68 ++++++++---------- crates/examples/src/stage.rs | 3 +- manual/src/assets/gltf-example-shadow.png | Bin 12924 -> 6923 bytes manual/src/assets/gltf-example-unlit.png | Bin 12067 -> 27975 bytes manual/src/assets/helipad.jpg | Bin 0 -> 14778 bytes .../src/assets/qwantani_dusk_2_puresky.webp | Bin 2804 -> 0 bytes .../src/assets/qwantani_dusk_2_puresky_1k.hdr | Bin 1166018 -> 0 bytes manual/src/assets/skybox.png | Bin 28323 -> 78137 bytes manual/src/gltf.md | 6 +- manual/src/setup.md | 2 +- manual/src/skybox.md | 18 ++--- manual/src/stage.md | 37 ++++++---- 15 files changed, 77 insertions(+), 85 deletions(-) create mode 100644 manual/src/assets/helipad.jpg delete mode 100644 manual/src/assets/qwantani_dusk_2_puresky.webp delete mode 100644 manual/src/assets/qwantani_dusk_2_puresky_1k.hdr diff --git a/Cargo.lock b/Cargo.lock index d47bb34c..63fca90f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4220,7 +4220,7 @@ dependencies = [ [[package]] name = "spirv-std" version = "0.9.0" -source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=425328a#425328a3ac7f1f18db914d24b3d4754bf13bb7ac" +source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=de03e8d#de03e8d8c997c68aed1a950863c0d79ba9bd8c72" dependencies = [ "bitflags 1.3.2", "glam", @@ -4233,7 +4233,7 @@ dependencies = [ [[package]] name = "spirv-std-macros" version = "0.9.0" -source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=425328a#425328a3ac7f1f18db914d24b3d4754bf13bb7ac" +source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=de03e8d#de03e8d8c997c68aed1a950863c0d79ba9bd8c72" dependencies = [ "proc-macro2", "quote", @@ -4244,7 +4244,7 @@ dependencies = [ [[package]] name = "spirv-std-types" version = "0.9.0" -source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=425328a#425328a3ac7f1f18db914d24b3d4754bf13bb7ac" +source = "git+https://github.com/rust-gpu/rust-gpu.git?rev=de03e8d#de03e8d8c997c68aed1a950863c0d79ba9bd8c72" [[package]] name = "stable_deref_trait" diff --git a/Cargo.toml b/Cargo.toml index 8ba0ae4f..5f947154 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] members = [ - # "crates/example", + "crates/example", "crates/examples", #"crates/example-culling", #"crates/example-wasm", @@ -51,8 +51,8 @@ serde_json = "1.0.117" send_wrapper = "0.6.0" similarity = "0.2.0" snafu = "0.8" -spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "425328a" } -spirv-std-macros = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "425328a" } +spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "de03e8d" } +spirv-std-macros = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "de03e8d" } syn = { version = "2.0.49", features = ["full", "extra-traits", "parsing"] } tokio = "1.47.1" tracing = "0.1.41" @@ -75,4 +75,4 @@ opt-level = 3 opt-level = 3 [patch.crates-io] -spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "425328a" } +spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "de03e8d" } diff --git a/crates/examples/src/gltf.rs b/crates/examples/src/gltf.rs index d8c93429..e1684646 100644 --- a/crates/examples/src/gltf.rs +++ b/crates/examples/src/gltf.rs @@ -16,17 +16,16 @@ async fn manual_gltf() { let ctx = Context::headless(256, 256).await; let stage: Stage = ctx .new_stage() - .with_background_color(Vec4::new(0.5, 0.5, 0.5, 1.0)); + .with_background_color(Vec4::new(0.25, 0.25, 0.25, 1.0)); let _camera: Camera = { let aspect = 1.0; let fovy = core::f32::consts::PI / 4.0; let znear = 0.1; - let zfar = 1000.0; + let zfar = 10.0; let projection = Mat4::perspective_rh(fovy, aspect, znear, zfar); - let y = 50.0; - let eye = Vec3::new(120.0, y, 120.0); - let target = Vec3::new(0.0, y, 0.0); + let eye = Vec3::new(0.5, 0.5, 0.8); + let target = Vec3::new(0.0, 0.3, 0.0); let up = Vec3::Y; let view = Mat4::look_at_rh(eye, target, up); @@ -38,10 +37,11 @@ async fn manual_gltf() { // ANCHOR: load use renderling::{gltf::GltfDocument, types::GpuOnlyArray}; - let _model: GltfDocument = stage - .load_gltf_document_from_path(workspace_dir().join("gltf/Fox.glb")) + let model: GltfDocument = stage + .load_gltf_document_from_path(workspace_dir().join("gltf/marble_bust_1k.glb")) .unwrap() .into_gpu_only(); + println!("bounds: {:?}", model.bounding_volume()); // ANCHOR_END: load super::cwd_to_manual_assets_dir(); diff --git a/crates/examples/src/skybox.rs b/crates/examples/src/skybox.rs index 086aa907..f7de222c 100644 --- a/crates/examples/src/skybox.rs +++ b/crates/examples/src/skybox.rs @@ -1,12 +1,13 @@ //! Skybox manual page. +use crate::workspace_dir; + #[tokio::test] -async fn manual_stage() { +async fn manual_skybox() { // ANCHOR: setup use renderling::{ camera::Camera, context::Context, - geometry::Vertex, glam::Vec4, glam::{Mat4, Vec3}, stage::Stage, @@ -15,52 +16,39 @@ async fn manual_stage() { let ctx = Context::headless(256, 256).await; let stage: Stage = ctx .new_stage() - .with_background_color(Vec4::new(0.5, 0.5, 0.5, 1.0)); - - let _camera: Camera = stage - .new_camera() - .with_default_perspective(256.0, 256.0) - .with_view(Mat4::look_at_rh(Vec3::splat(1.5), Vec3::ZERO, Vec3::Y)); - - let vertices = stage.new_vertices(renderling::math::unit_cube().into_iter().map( - |(position, normal)| { - Vertex::default() - .with_position(position) - .with_normal(normal) - .with_color({ - // The color can vary from vertex to vertex - // - // X axis is green - let g: f32 = position.x + 0.5; - // Y axis is blue - let b: f32 = position.y + 0.5; - // Z is red - let r: f32 = position.z + 0.5; - Vec4::new(r, g, b, 1.0) - }) - }, - )); - - let material = stage.new_material().with_albedo_factor(Vec4::ONE); + .with_background_color(Vec4::new(0.25, 0.25, 0.25, 1.0)); + + let _camera: Camera = { + let aspect = 1.0; + let fovy = core::f32::consts::PI / 4.0; + let znear = 0.1; + let zfar = 10.0; + let projection = Mat4::perspective_rh(fovy, aspect, znear, zfar); + let eye = Vec3::new(0.5, 0.5, 0.8); + let target = Vec3::new(0.0, 0.3, 0.0); + let up = Vec3::Y; + let view = Mat4::look_at_rh(eye, target, up); + + stage + .new_camera() + .with_projection_and_view(projection, view) + }; - let _prim = stage - .new_primitive() - .with_vertices(&vertices) - .with_material(&material); - // ANCHOR_END: setup + use renderling::{gltf::GltfDocument, types::GpuOnlyArray}; + let model: GltfDocument = stage + .load_gltf_document_from_path(workspace_dir().join("gltf/marble_bust_1k.glb")) + .unwrap() + .into_gpu_only(); + println!("bounds: {:?}", model.bounding_volume()); - // ANCHOR: render_cube let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); frame.present(); - // ANCHOR_END: render_cube - - // Excluded from the manual because it's off-topic - super::cwd_to_manual_assets_dir(); + // ANCHOR_END: setup // ANCHOR: skybox let skybox = stage - .new_skybox_from_path("qwantani_dusk_2_puresky_1k.hdr") + .new_skybox_from_path(workspace_dir().join("img/hdr/helipad.hdr")) .unwrap(); stage.set_skybox(skybox); // ANCHOR_END: skybox diff --git a/crates/examples/src/stage.rs b/crates/examples/src/stage.rs index aaf8f866..6d7963b7 100644 --- a/crates/examples/src/stage.rs +++ b/crates/examples/src/stage.rs @@ -97,12 +97,11 @@ async fn manual_stage() { drop(vertices); drop(material); drop(prim); - // ANCHOR_END: removal let frame = ctx.get_next_frame().unwrap(); stage.render(&frame.view()); - let img = frame.read_image().await.unwrap(); img.save("stage-example-gone.png").unwrap(); frame.present(); + // ANCHOR_END: removal } diff --git a/manual/src/assets/gltf-example-shadow.png b/manual/src/assets/gltf-example-shadow.png index a3aa105ba929a4b8d8b13c8e6862e40fef33f270..e22d44d02ec2a2d13911e73ea35389feac995f28 100644 GIT binary patch literal 6923 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 literal 12924 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 Vugf$7|Eol^Bt4h7E8*qB{{}}oLdyUE diff --git a/manual/src/assets/gltf-example-unlit.png b/manual/src/assets/gltf-example-unlit.png index db65b791290fa44976d8807af425c598a614136e..04c26d2a87e723adb09c96906f0b7fbedd8eace6 100644 GIT binary patch literal 27975 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,#+8dX~L@{`VmRD;xt1K(L|_iGDih!|h^ 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 literal 12067 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 WI<(96&hBT`LZL1U=f|Ljh5rK?H3Mh> literal 0 HcmV?d00001 diff --git a/manual/src/assets/qwantani_dusk_2_puresky.webp b/manual/src/assets/qwantani_dusk_2_puresky.webp deleted file mode 100644 index 1970a7561fe275de60237088876a7b2bf058c712..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2804 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 diff --git a/manual/src/assets/qwantani_dusk_2_puresky_1k.hdr b/manual/src/assets/qwantani_dusk_2_puresky_1k.hdr deleted file mode 100644 index 62d1e3b0e2abc27872237587a4b189a394e29992..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1166018 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

    XidE*Zqc&#Ptb9r-gPtX>=V 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 |5y*KHu!y`>YPrDh)i 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

    _u(8Agm%>xbSI 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 literal 0 HcmV?d00001 diff --git a/manual/src/assets/stage-example.png b/manual/src/assets/stage-example.png new file mode 100644 index 0000000000000000000000000000000000000000..98ef0adfd94616dda2e8705da52979c02dcbcf3e GIT binary patch literal 33422 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 literal 0 HcmV?d00001 diff --git a/manual/src/chapter_1.md b/manual/src/chapter_1.md deleted file mode 100644 index b743fda3..00000000 --- a/manual/src/chapter_1.md +++ /dev/null @@ -1 +0,0 @@ -# Chapter 1 diff --git a/manual/src/context.md b/manual/src/context.md new file mode 100644 index 00000000..ac933837 --- /dev/null +++ b/manual/src/context.md @@ -0,0 +1,57 @@ +# Context + +The first step of any `renderling` program starts with [`renderling::context::Context`][Context]. + +The `Context` is responsible for managing the underlying [`wgpu`][wgpu] runtime, including the +instance, adapter and queue. +It also sets up the [`RenderTarget`][RenderTarget], according to how the `Context` was created. + +On that note, it's important to know that there are two main ways to create a `Context`: + +1. A headless context, which renders to a texture, can be created with + [`Context::headless`][Context#headless] or + [`Context::try_new_headless`][Context#try_headless], depending on your error + handling scenario. +2. A surface context, with a window (possibly from [`winit`][winit]) or a canvas + from [`web-sys`][web-sys]. + +```rust, ignore +{{#include ../../crates/examples/src/context.rs:create}} +``` + +## Getting a frame + +Another important concept is the [`Frame`][Frame]. Each time you'd like to present a new image +you must acquire a frame from the `Context` with [`Context::get_next_frame`][Context#get_next_frame] +and present it with [`Frame::present`][Frame#present]. + +### Presenting on WASM + +When on WASM (aka running in a browser), [`Frame::present`][Frame#present] is a noop. +It's still a good idea to use it though, so you don't forget when programming in native. + +### Saving the frame + +You can also read out the frame to an image provided by the [`image`][image] +crate. See the [`Frame`][Frame] docs for help with the `read_*` functions. + +### Frame example + +```rust, ignore +{{#include ../../crates/examples/src/context.rs:frame}} +``` + +[Context]: {{DOCS_URL}}/renderling/context/struct.Context.html +[Context#headless]: {{DOCS_URL}}/renderling/context/struct.Context.html#method.headless +[Context#try_headless]: {{DOCS_URL}}/renderling/context/struct.Context.html#method.try_headless +[Context#get_next_frame]: {{DOCS_URL}}/renderling/context/struct.Context.html#method.get_next_frame + +[Frame]: {{DOCS_URL}}/renderling/context/struct.Frame.html +[Frame#present]: {{DOCS_URL}}/renderling/context/struct.Frame.html#method.present + +[RenderTarget]: {{DOCS_URL}}/renderling/context/struct.RenderTarget.html + +[image]: https://crates.io/crates/image +[wgpu]: https://crates.io/crates/wgpu +[winit]: https://crates.io/crates/winit +[web-sys]: https://crates.io/crates/web-sys diff --git a/manual/src/gltf.md b/manual/src/gltf.md new file mode 100644 index 00000000..ba6d493d --- /dev/null +++ b/manual/src/gltf.md @@ -0,0 +1,79 @@ +# GLTF + +`renderling`'s built-in model format is [GLTF](https://www.khronos.org/gltf/), a +versatile and efficient format for transmitting 3D models. GLTF, which stands +for GL Transmission Format, is designed to be a compact, interoperable format +that can be used across various platforms and applications. It supports a wide +range of features including geometry, materials, animations, and more, making it +a popular choice for 3D graphics. + +## Using GLTF files + +The previous section on [staging resources](./stage) covered the creation of +various GPU resources such as [`Camera`], [`Vertices`], [`Material`], +[`Primitive`], and [`Transform`]. When you load a GLTF file into `renderling`, +it automatically stages a collection of these resources. This means that the +GLTF file is parsed, and the corresponding GPU resources are created and +returned to you, allowing you to integrate them into your application +seamlessly. + +## Example + +We'll start by creating our [`Context`], [`Stage`] and [`Camera`]: + +```rust,ignore +{{#include ../../crates/examples/src/gltf.rs:setup}} +``` + +Then we load our GLTF file through the [`Stage`] with +[`Stage::load_gltf_document_from_path`], and as long as there are no errors it returns a +[`GltfDocument`]: + +```rust,ignore +{{#include ../../crates/examples/src/gltf.rs:load}} +``` + +On WASM we would use [`Stage::load_gltf_document_from_bytes`] as the filesystem +is unavailable. + +Notice how in the above example we call [`GltfDocument::into_gpu_only`] to +unload the mesh geometry from the CPU. + +## Render + +```rust,ignore +{{#include ../../crates/examples/src/gltf.rs:render_1}} +``` + +## Result + +![a loaded GLTF file, Fox, in shadow](assets/gltf-example-shadow.png) + +But wait! It's all in shadow. + +This is because we haven't added any lighting. + +We have two options here: +1. Turn of lighting and show the scene "unlit", using [`Stage::set_has_lighting`] +2. Add some lights + +For now we'll go with option `1`, as lighting happens in a later section: + +```rust,ignore +{{#include ../../crates/examples/src/gltf.rs:no_lights}} +``` + +![a loaded GLTF file, Fox, unlit](assets/gltf-example-unlit.png) + +[`Context`]: {{DOCS_URL}}/renderling/context/struct.Context.html +[`Stage`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html +[`Stage::load_gltf_document_from_bytes`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html#method.load_gltf_document_from_bytes +[`Stage::load_gltf_document_from_path`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html#method.load_gltf_document_from_path +[`Stage::set_has_lighting`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html#method.set_has_lighting +[`GltfDocument`]: {{DOCS_URL}}/renderling/gltf/struct.GltfDocument.html +[`GltfDocument::into_gpu_only`]: {{DOCS_URL}}/renderling/gltf/struct.GltfDocument.html#method.into_gpu_only +[`Camera`]: {{DOCS_URL}}/renderling/camera/struct.Camera.html +[`Material`]: {{DOCS_URL}}/renderling/material/struct.Material.html +[`Primitive`]: {{DOCS_URL}}/renderling/primitive/struct.Primitive.html +[`Vertices`]: {{DOCS_URL}}/renderling/geometry/struct.Vertices.html +[`Transform`]: {{DOCS_URL}}/renderling/transform/struct.Transform.html diff --git a/manual/src/reflinks.md b/manual/src/reflinks.md new file mode 100644 index 00000000..3c0252d8 --- /dev/null +++ b/manual/src/reflinks.md @@ -0,0 +1,43 @@ +# docs + +[`Camera`]: {{DOCS_URL}}/renderling/camera/struct.Camera.html +[`Camera::with_default_perspective`]: {{DOCS_URL}}/renderling/camera/struct.Camera.html#method.with_default_perspective + +[`Context`]: {{DOCS_URL}}/renderling/context/struct.Context.html +[`Context::new_stage`]: {{DOCS_URL}}/renderling/context/struct.Context.html#method.new_stage +[`Context::headless`]: {{DOCS_URL}}/renderling/context/struct.Context.html#method.headless +[`Context::try_headless`]: {{DOCS_URL}}/renderling/context/struct.Context.html#method.try_headless +[`Context::get_next_frame`]: {{DOCS_URL}}/renderling/context/struct.Context.html#method.get_next_frame + +[`Frame`]: {{DOCS_URL}}/renderling/context/struct.Frame.html +[`Frame::present`]: {{DOCS_URL}}/renderling/context/struct.Frame.html#method.present + +[`Primitive`]: {{DOCS_URL}}/renderling/primitive/struct.Primitive.html + +[`Material`]: {{DOCS_URL}}/renderling/material/struct.Material.html + +[`Mat4`]: https://docs.rs/glam/latest/glam/f32/struct.Mat4.html + +[`RenderTarget`]: {{DOCS_URL}}/renderling/context/struct.RenderTarget.html + +[`Stage`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html +[`Stage::new_camera`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html#method.new_camera + +[`Vertices`]: {{DOCS_URL}}/renderling/geometry/struct.Vertices.html +[`Vertices::get_vertex`]: {{DOCS_URL}}/renderling/geometry/struct.Vertices.html#method.get_vertex +[`Vertices::modify_vertex`]: {{DOCS_URL}}/renderling/geometry/struct.Vertices.html#method.modify_vertex +[`Vertices::set_vertex`]: {{DOCS_URL}}/renderling/geometry/struct.Vertices.html#method.set_vertex + +[`Vertex`]: {{DOCS_URL}}/renderling/geometry/struct.Vertex.html + +# friends + +[glam]: https://crates.io/crates/glam +[image]: https://crates.io/crates/image +[wgpu]: https://crates.io/crates/wgpu +[winit]: https://crates.io/crates/winit +[web-sys]: https://crates.io/crates/web-sys + +# other + +[builder-pattern]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html diff --git a/manual/src/setup.md b/manual/src/setup.md new file mode 100644 index 00000000..a81ed6c4 --- /dev/null +++ b/manual/src/setup.md @@ -0,0 +1,40 @@ +# Setup + +`renderling` is a Rust library, so first you'll need to get familiar with the +language. Visit if you're not +already familiar. + +Once you're ready, start a new project with `cargo new`. +Then `cd` into your project directory and add `renderling` as a dependency: + +``` +cargo add --git https://github.com/schell/renderling.git --branch main +``` + +## patch crates.io + +`renderling` is special in that all the shaders are written in Rust using +[Rust-GPU](https://rust-gpu.github.io/), which is currently between +releases. For this reason we need to add an entry to the `[patch.crates-io]` +section of our `Cargo.toml`: + +```toml +[patch.crates-io] +spirv-std = { git = "https://github.com/rust-gpu/rust-gpu.git", rev = "425328a" } +``` + +This is a temporary workaround that will be resolved after the next Rust-GPU +release. + +The rest is Rust business as usual. + +## WASM + +TODO: write about setting up a WASM project. + +## Re-exports + +`renderling` **re-exports** [`glam`][glam] from its top level module, +because it provides the underlying mathematical types used throughout the API. + +[glam]: https://crates.io/crates/glam diff --git a/manual/src/skybox.md b/manual/src/skybox.md new file mode 100644 index 00000000..65f6ad61 --- /dev/null +++ b/manual/src/skybox.md @@ -0,0 +1,55 @@ +# Skybox 🌌 + +One of the most striking effects we can provide is a +[skybox](https://en.wikipedia.org/wiki/Skybox_(video_games)). + +Using a skybox is an easy way to improve immersion, and with +`renderling` your skyboxes also illuminate the scene. + +## Building on the stage example + +We'll start out this example by extending the example from the +[stage](./stage). In that example we created a cube with colored +vertices: + +```rust,ignore +{{#include ../../crates/examples/src/skybox.rs:setup}} +``` + +Then we rendered: + +```rust,ignore +{{#include ../../crates/examples/src/skybox.rs:render_cube}} +``` + +Which gave us this scene: + +![image of a unit cube with colored vertices](assets/stage-example.png) + +## Adding the skybox + +In `renderling`, skyboxes get their background from an "HDR" image. +These are typically large three dimensional images. You can find +free HDR images [here](https://polyhaven.com/hdris) and other +places around the web. + +For this example we'll be using this HDR: + +![Qwantani Dusk 2 (Pure Sky)](assets/qwantani_dusk_2_puresky.webp) + +```rust,ignore +{{#include ../../crates/examples/src/skybox.rs:skybox}} +``` + +Then we render: + +```rust,ignore +{{#include ../../crates/examples/src/skybox.rs:render_skybox}} +``` + + +## Results + +And there we go! + +![renderling skybox](assets/skybox.png) diff --git a/manual/src/stage.md b/manual/src/stage.md new file mode 100644 index 00000000..663a4047 --- /dev/null +++ b/manual/src/stage.md @@ -0,0 +1,169 @@ +# Stage + +The [`Stage`] is the most important type in `renderling`. +It's responsible for staging all your scene's data on the GPU, as well as +linking all the various effects together and rendering it all. + + +- [Stage](#stage) + - [Stage creation](#stage-creation) + - [Resource creation](#resource-creation) + - [Camera](#camera) + - [glam and re-exports](#glam-and-re-exports) + - [Creation](#creation) + - [Geometry](#geometry) + - [Material](#material) + - [Primitive](#primitive) + - [Rendering](#rendering) + - [Results](#results) + + +## Stage creation + +The `Stage` is created with [`Context::new_stage`]. + +```rust,ignore +{{#include ../../crates/examples/src/stage.rs:creation}} +``` + +Notice that context creation is _asynchronous_. Most of the `renderling` API is +synchronous, but context creation is one of two exceptions - the other being +reading data back from the GPU. + +Also note that we can set the background color of the stage using a `Vec4`. +Above we've set the background to a light gray. + +## Resource creation + +Now we'll begin using the `Stage` to create our scene's resources. At the end of +all our staging we should end up with a [`Camera`] and one simple +[`Primitive`] representing a colored unit cube, sitting right in +front of the camera. + +### Camera + +In order to see our scene we need a [`Camera`]. + +The camera controls the way our scene looks when rendered. It uses separate projection and view +matrices to that end. Discussing these matrices is out of scope for this manual, but there are +plenty of resources online about what they are and how to use them. + +#### glam and re-exports + +One important detail about these matrices, though, is that they come from the [`glam`][glam] +library. Specifically they are [`Mat4`][Mat4], which are a 4x4 transformation matrix. + +#### Creation + +On with our camera. Creation is dead simple using [`Stage::new_camera`]. + +```rust,ignore +{{#include ../../crates/examples/src/stage.rs:camera}} +``` + +Each resource returned by the many `Stage::new_*` functions return resources that adhere +to the [builder pattern][builder]. That means the value a `Stage::new_*` function returns +can be chained with other calls that configure it. This pattern is nice because it +allows your editor to display the customizations available, which makes API discovery +easier for everyone. + +Above we use [`Camera::with_default_perspective`] to +set the camera to use a default perspective projection. + +Note that usually when we create a `Camera`, we have to tell +the `Stage` that we want to **use** the camera, but the first `Camera` created will +automatically be used. We could potentially have _many_ cameras and switch them around at will +by calling `Stage::use_camera` before rendering. + +### Geometry + +The first step to creating a [`Primitive`] is staging some vertices in a triangle +mesh. For this example we'll use the triangle mesh of the unit cube. The +[`renderling::math`][math] module provides a convenience function for generating this mesh. + +```rust,ignore +{{#include ../../crates/examples/src/stage.rs:unit_cube_vertices}} +``` + +Here we create [`Vertices`], which stages the unit cube points on the GPU. + +Next we'll unload those points from the CPU, to free up the memory: + +```rust,ignore +{{#include ../../crates/examples/src/stage.rs:unload_vertices}} +``` + +Unloading the CPU memory like this isn't strictly necessary, but it's beneficial to +know about. If we were planning on inspecting or modifying the underlying +[`Vertex`] values with [`Vertices::get_vertex`] and +[`Vertices::modify_vertex`], we could skip this step. +After unloading, however, we can still set a [`Vertex`] at a specific +index using [`Vertices::set_vertex`]. + +### Material + +Next we stage a [`Material`]. + +Materials denote how a mesh looks by specifying various colors and shading values, +as well as whether or not the material is lit by our lighting, which we'll talk about +in later chapters. For now we'll provide a material that doesn't really do anything +except let the vertex colors show through. + +```rust,ignore +{{#include ../../crates/examples/src/stage.rs:material}} +``` + +### Primitive + +Now that we have some [`Vertices`] and a [`Material`] we can create our primitive +using the familiar builder pattern. + +```rust,ignore +{{#include ../../crates/examples/src/stage.rs:prim}} +``` + +We don't actually do anything with the primitive at this point though. + +## Rendering + +Now the scene is set and we're ready to render. + +Rendering is a three-step process: + +1. Get the next frame +2. Render the staged scene into the view of the frame +3. Present the frame + +```rust,ignore +{{#include ../../crates/examples/src/stage.rs:render}} +``` + +Above we added an extra step where we read an image of the frame from the GPU, +so we can see it here. + +## Results + +![image of a unit cube with colored vertices](assets/stage-example.png) + +And there you have it! + +[`Stage`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html +[`Stage::new_camera`]: {{DOCS_URL}}/renderling/stage/struct.Stage.html#method.new_camera +[`Context::new_stage`]: {{DOCS_URL}}/renderling/context/struct.Context.html#method.new_stage +[`Primitive`]: {{DOCS_URL}}/renderling/primitive/struct.Primitive.html +[`Camera`]: {{DOCS_URL}}/renderling/camera/struct.Camera.html +[`Camera::with_default_perspective`]: {{DOCS_URL}}/renderling/camera/struct.Camera.html#method.with_default_perspective +[`Vertices`]: {{DOCS_URL}}/renderling/geometry/struct.Vertices.html +[`Vertices::get_vertex`]: {{DOCS_URL}}/renderling/geometry/struct.Vertices.html#method.get_vertex +[`Vertices::modify_vertex`]: {{DOCS_URL}}/renderling/geometry/struct.Vertices.html#method.modify_vertex +[`Vertices::set_vertex`]: {{DOCS_URL}}/renderling/geometry/struct.Vertices.html#method.set_vertex +[`Vertex`]: {{DOCS_URL}}/renderling/geometry/struct.Vertex.html +[`Material`]: {{DOCS_URL}}/renderling/material/struct.Material.html + +[math]: {{DOCS_URL}}/renderling/math/index.html + +[Mat4]: https://docs.rs/glam/latest/glam/f32/struct.Mat4.html + +[glam]: https://crates.io/crates/glam + +[builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html diff --git a/manual/src/welcome.md b/manual/src/welcome.md new file mode 100644 index 00000000..b2f53510 --- /dev/null +++ b/manual/src/welcome.md @@ -0,0 +1,41 @@ +