From d167f04d6026ab6208e4e447ab49e808f74f0921 Mon Sep 17 00:00:00 2001 From: sloth58 Date: Sun, 15 Jan 2023 12:08:15 -0600 Subject: [PATCH] cascade rough implementation system --- crates/mani/fabled_math/Cargo.toml | 2 +- .../src/camera/calculation/camera.rs | 10 +- .../fabled_render/src/camera/component/mod.rs | 25 +++ .../fabled_render/src/light/component/csm.rs | 26 +++ .../fabled_render/src/light/component/mod.rs | 2 + crates/mani/fabled_render/src/light/mod.rs | 5 +- crates/mani/fabled_system/Cargo.toml | 4 +- .../fabled_system/src/container/camera/mod.rs | 1 + .../src/container/lighting/mod.rs | 3 + .../mani/fabled_system/src/container/mod.rs | 4 + .../fabled_system/src/startup/camera/mod.rs | 1 + .../fabled_system/src/startup/lighting/mod.rs | 10 + crates/mani/fabled_system/src/startup/mod.rs | 4 + .../chromatic_adaption_system.rs | 0 .../fabled_system/src/system/color/mod.rs | 0 .../lighting/construct_cascade_system.rs | 197 ++++++++++++++++++ .../fabled_system/src/system/lighting/mod.rs | 3 + crates/mani/fabled_system/src/system/mod.rs | 2 + 18 files changed, 291 insertions(+), 8 deletions(-) create mode 100644 crates/mani/fabled_render/src/light/component/csm.rs create mode 100644 crates/mani/fabled_system/src/container/camera/mod.rs create mode 100644 crates/mani/fabled_system/src/container/lighting/mod.rs create mode 100644 crates/mani/fabled_system/src/startup/camera/mod.rs create mode 100644 crates/mani/fabled_system/src/startup/lighting/mod.rs rename crates/mani/fabled_system/src/system/{lighting => color}/chromatic_adaption_system.rs (100%) create mode 100644 crates/mani/fabled_system/src/system/color/mod.rs create mode 100644 crates/mani/fabled_system/src/system/lighting/construct_cascade_system.rs diff --git a/crates/mani/fabled_math/Cargo.toml b/crates/mani/fabled_math/Cargo.toml index d3759db9..a0ac40b8 100644 --- a/crates/mani/fabled_math/Cargo.toml +++ b/crates/mani/fabled_math/Cargo.toml @@ -3,4 +3,4 @@ name = "fabled_math" version = "0.1.0" edition = "2018" -[dependencies] \ No newline at end of file +[dependencies] diff --git a/crates/mani/fabled_render/src/camera/calculation/camera.rs b/crates/mani/fabled_render/src/camera/calculation/camera.rs index cd7bab9b..63c0fe1a 100644 --- a/crates/mani/fabled_render/src/camera/calculation/camera.rs +++ b/crates/mani/fabled_render/src/camera/calculation/camera.rs @@ -65,9 +65,11 @@ pub fn un_project( } // todo this is +X=RIGHT, +Y=UP, +Z=BACK we want +Z=FORWARD. -pub fn compute_look_at_matrix(translation: Vector3, rotation: Quaternion) -> Matrix4x4 { - const Y_VEC3: Vector3 = Vector3::UP; - +pub fn compute_look_at_matrix( + translation: Vector3, + up_vector: Vector3, + rotation: Quaternion, +) -> Matrix4x4 { let forward = forward_vec3(rotation); let neg_translation = -translation; @@ -76,7 +78,7 @@ pub fn compute_look_at_matrix(translation: Vector3, rotation: Quaternion) -> Mat value: normalize(-forward.value), }; let x_axis = Vector3 { - value: normalize(cross(Y_VEC3.value, z_axis.value)), + value: normalize(cross(up_vector.value, z_axis.value)), }; let y_axis = Vector3 { value: cross(z_axis.value, x_axis.value), diff --git a/crates/mani/fabled_render/src/camera/component/mod.rs b/crates/mani/fabled_render/src/camera/component/mod.rs index c6b8a5a7..c3916de8 100644 --- a/crates/mani/fabled_render/src/camera/component/mod.rs +++ b/crates/mani/fabled_render/src/camera/component/mod.rs @@ -2,6 +2,8 @@ pub use aperture::*; pub use aspect_ratio::*; pub use clipping_plane::*; pub use f_stop::*; +use fabled_component::{Unique, Untracked}; +use fabled_math::Matrix4x4; pub use fov::*; pub use iso_speed::*; pub use oblique::*; @@ -30,3 +32,26 @@ mod viewport; // Orthographic // FStop -> ISO Speed -> Shutter -> ClippingPlane -> Viewport -> Orientation -> // Oblique (optional) + + +// The active camera's projection matrix. +// This is a resource since there can only be one camera rendered to a screen +#[derive(Copy, Clone, PartialEq)] +pub struct RenderProjection { + pub projection_matrix: Matrix4x4, +} + +impl Unique for RenderProjection { + type Tracking = Untracked; +} + +// The active camera's view matrix +// This is a resource since there can only be one camera rendered to a screen. +#[derive(Copy, Clone, PartialEq)] +pub struct RenderView { + pub view_matrix: Matrix4x4, +} + +impl Unique for RenderView { + type Tracking = Untracked; +} diff --git a/crates/mani/fabled_render/src/light/component/csm.rs b/crates/mani/fabled_render/src/light/component/csm.rs new file mode 100644 index 00000000..b4a2ec3d --- /dev/null +++ b/crates/mani/fabled_render/src/light/component/csm.rs @@ -0,0 +1,26 @@ +use fabled_component::{Component, Modification, Unique}; +use fabled_math::{Matrix4x4, Vector3, Vector4}; + + +// There will only be one Cascade map that can be active at any given time. +#[derive(Copy, Clone, PartialEq)] +pub struct CascadeSplit { + pub splits: Vector4, + pub lambda: f32, +} + +impl Unique for CascadeSplit { + type Tracking = Modification; +} + + +#[derive(Copy, Clone, PartialEq)] +pub struct CascadeFrustum { + pub center: [Vector3; 4], + pub min_extent: [Vector3; 4], + pub max_extent: [Vector3; 4], +} + +impl Unique for CascadeFrustum { + type Tracking = Modification; +} diff --git a/crates/mani/fabled_render/src/light/component/mod.rs b/crates/mani/fabled_render/src/light/component/mod.rs index 0ce67007..7bb61194 100644 --- a/crates/mani/fabled_render/src/light/component/mod.rs +++ b/crates/mani/fabled_render/src/light/component/mod.rs @@ -1,5 +1,6 @@ mod appearance; mod attenuation; +mod csm; mod ies_profile; mod light_caster; mod light_channel; @@ -12,6 +13,7 @@ mod sun_light; pub use appearance::*; pub use attenuation::*; +pub use csm::*; pub use ies_profile::*; pub use light_caster::*; pub use light_channel::*; diff --git a/crates/mani/fabled_render/src/light/mod.rs b/crates/mani/fabled_render/src/light/mod.rs index 6c06f0c8..f8e59281 100644 --- a/crates/mani/fabled_render/src/light/mod.rs +++ b/crates/mani/fabled_render/src/light/mod.rs @@ -1,12 +1,13 @@ +pub use component::*; pub use constant::*; pub use container::*; +pub use contract::*; pub use conversion::*; pub use ext::*; -pub use contract::*; mod component; mod constant; mod container; +mod contract; mod conversion; mod ext; -mod contract; diff --git a/crates/mani/fabled_system/Cargo.toml b/crates/mani/fabled_system/Cargo.toml index 5a4be168..20b27834 100644 --- a/crates/mani/fabled_system/Cargo.toml +++ b/crates/mani/fabled_system/Cargo.toml @@ -6,8 +6,10 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -shipyard = {version = "0.5.0", features = ["thread_local", "parallel"]} +shipyard = {version = "0.6.2", features = ["thread_local", "parallel"]} fabled_transform = {path = "../fabled_transform", version = "*"} fabled_render = {path = "../fabled_render", version = "*"} +fabled_math = {path = "../fabled_math", version = "*"} rayon = {version = "1.5.1"} bitflags = {version = "1.2.1"} +crunchy = {version = "0.2.2", features = ["default"]} diff --git a/crates/mani/fabled_system/src/container/camera/mod.rs b/crates/mani/fabled_system/src/container/camera/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/crates/mani/fabled_system/src/container/camera/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/mani/fabled_system/src/container/lighting/mod.rs b/crates/mani/fabled_system/src/container/lighting/mod.rs new file mode 100644 index 00000000..defceec0 --- /dev/null +++ b/crates/mani/fabled_system/src/container/lighting/mod.rs @@ -0,0 +1,3 @@ +mod csm_view; + +pub use csm_view::*; \ No newline at end of file diff --git a/crates/mani/fabled_system/src/container/mod.rs b/crates/mani/fabled_system/src/container/mod.rs index d0a94f53..a8e724b9 100644 --- a/crates/mani/fabled_system/src/container/mod.rs +++ b/crates/mani/fabled_system/src/container/mod.rs @@ -1,3 +1,7 @@ +mod camera; +mod lighting; mod world_flag; +pub use camera::*; +pub use lighting::*; pub use world_flag::*; diff --git a/crates/mani/fabled_system/src/startup/camera/mod.rs b/crates/mani/fabled_system/src/startup/camera/mod.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/crates/mani/fabled_system/src/startup/camera/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/mani/fabled_system/src/startup/lighting/mod.rs b/crates/mani/fabled_system/src/startup/lighting/mod.rs new file mode 100644 index 00000000..eb797d73 --- /dev/null +++ b/crates/mani/fabled_system/src/startup/lighting/mod.rs @@ -0,0 +1,10 @@ +use fabled_render::light::CascadeSplit; + + +pub fn construct_cascade_resource(primary_world: &shipyard::World) { + primary_world.add_unique(CascadeSplit { + splits: Default::default(), + }); + + // add the rest of the cascade parameter. +} diff --git a/crates/mani/fabled_system/src/startup/mod.rs b/crates/mani/fabled_system/src/startup/mod.rs index 4c788c38..a2c9566d 100644 --- a/crates/mani/fabled_system/src/startup/mod.rs +++ b/crates/mani/fabled_system/src/startup/mod.rs @@ -1,5 +1,9 @@ mod entity; +mod lighting; mod world; +mod camera; pub use entity::*; +pub use lighting::*; +pub use camera::*; pub use world::*; diff --git a/crates/mani/fabled_system/src/system/lighting/chromatic_adaption_system.rs b/crates/mani/fabled_system/src/system/color/chromatic_adaption_system.rs similarity index 100% rename from crates/mani/fabled_system/src/system/lighting/chromatic_adaption_system.rs rename to crates/mani/fabled_system/src/system/color/chromatic_adaption_system.rs diff --git a/crates/mani/fabled_system/src/system/color/mod.rs b/crates/mani/fabled_system/src/system/color/mod.rs new file mode 100644 index 00000000..e69de29b diff --git a/crates/mani/fabled_system/src/system/lighting/construct_cascade_system.rs b/crates/mani/fabled_system/src/system/lighting/construct_cascade_system.rs new file mode 100644 index 00000000..b5149467 --- /dev/null +++ b/crates/mani/fabled_system/src/system/lighting/construct_cascade_system.rs @@ -0,0 +1,197 @@ +use crate::PerspectiveCameraViewMut; +use fabled_math::matrix4x4_math::inverse_mat4; +use fabled_math::vector_math::{length, normalize, pow, round}; +use fabled_math::{from_euler_quat, EulerOrder, Matrix4x4, Swizzles4, Vector3, Vector4}; +use fabled_render::camera::{ + compute_look_at_matrix, compute_orthographic_matrix, compute_perspective_matrix, AspectRatio, + ClippingPlane, Fov, RenderProjection, RenderView, +}; +use fabled_render::light::{CascadeFrustum, CascadeSplit}; +use fabled_transform::{Rotation, Translation}; +use shipyard::{ + EntitiesViewMut, IntoIter, IntoWithId, IntoWorkload, UniqueView, UniqueViewMut, View, ViewMut, + Workload, +}; + +const MAX_CASCADE_SIZE: usize = 4; + +fn compute_csm_split_system( + plane: View, + mut csm_split: UniqueViewMut, +) { + for clipping_plane in plane.iter() { + let clipping_range = clipping_plane.far - clipping_plane.near; + + let ratio = clipping_plane.far / clipping_plane.near; + let rcp_clipping_range = 1.0 / clipping_range; + + let lambda = Vector4::broadcast(csm_split.lambda); + + // 4 Cascades + let p = Vector4::set(0.25, 0.5, 0.75, 1.0); + + let p_pow = Vector4 { + value: pow(Vector4::broadcast(ratio).value, p.value), + }; + + let p_mul_range = p * clipping_range; + let log = p_pow * clipping_plane.near; + + let uniform = p_mul_range + clipping_plane.near; + let log_min_uniform = log - uniform; + let d = lambda * log_min_uniform + uniform; + + // X = split_1, Y = split_2, Z = split_3, W = split_4 + let cascade_split = (d - clipping_plane.near) * rcp_clipping_range; + + csm_split.splits = cascade_split; + } +} + +fn compute_csm_frustum_system( + cascade_split: UniqueView, + projection: UniqueView, + view: UniqueView, + mut frustum: UniqueViewMut, +) { + let inverse_view_projection = inverse_mat4(view.view_matrix * projection.projection_matrix); + + for cascade_index in 0..MAX_CASCADE_SIZE { + let mut frustum_corner_ws = [ + Vector3::set(-1.0, 1.0, 0.0), + Vector3::set(1.0, 1.0, 0.0), + Vector3::set(1.0, -1.0, 0.0), + Vector3::set(-1.0, -1.0, 0.0), + Vector3::set(-1.0, 1.0, 1.0), + Vector3::set(1.0, 1.0, 1.0), + Vector3::set(1.0, -1.0, 1.0), + Vector3::set(-1.0, -1.0, 1.0), + ]; + + let prev_split_distance = if cascade_index == 0 { + 0.0 + } else { + cascade_split.splits.value[cascade_index - 1] + }; + + let current_split_distance = cascade_split.splits.value[cascade_index]; + + for index in 0..8 { + // temp solution + let inverse_point = inverse_view_projection + * Vector4::set( + frustum_corner_ws[index].x(), + frustum_corner_ws[index].y(), + frustum_corner_ws[index].z(), + 1.0, + ); + + frustum_corner_ws[index] = inverse_point.xyz() / inverse_point.w(); + } + + + for index in 0..4 { + let corner_ray = frustum_corner_ws[index + 4] - frustum_corner_ws[index]; + let near_corner_ray = corner_ray * prev_split_distance; + let far_corner_ray = corner_ray * current_split_distance; + frustum_corner_ws[index + 4] = frustum_corner_ws[i] + far_corner_ray; + frustum_corner_ws[i] = frustum_corner_ws[index] + near_corner_ray; + } + + let mut frustum_center = Vector3::ZERO; + + for index in 0..8 { + frustum_center += frustum_corner_ws[index]; + } + frustum_center *= 0.125; + + let mut sphere_radius = 0.0f32; + + for index in 0..8 { + let dist = length((frustum_corner_ws[index] - frustum_center).value); + sphere_radius = sphere_radius.max(dist); + } + + sphere_radius = (sphere_radius * 16.0).ceil() * 0.0625; + + let max_extent = Vector3::broadcast(sphere_radius); + let min_extent = -max_extent; + + // assignment + frustum.max_extent[cascade_index] = max_extent; + frustum.min_extent[cascade_index] = min_extent; + frustum.center[cascade_index] = frustum_center; + } +} + + +fn compute_csm_shadow_matrix_system( + cascade_frustum: UniqueViewMut, + mut projection: UniqueView, + mut view: UniqueView, +) { + for cascade_index in 0..MAX_CASCADE_SIZE { + let maximum_extent = cascade_frustum.max_extent[cascade_index]; + let minimum_extent = cascade_frustum.min_extent[cascade_index]; + + let cascade_extent = maximum_extent - minimum_extent; + + let orthographic_rect = Vector4::set( + maximum_extent.x(), + minimum_extent.x(), + maximum_extent.y(), + minimum_extent.y(), + ); + + let mut light_orthographic_matrix = compute_orthographic_matrix( + orthographic_rect, + ClippingPlane::new(cascade_extent.z(), 0.0), + ); + + // todo: khal the direction is hard coded. + let light_direction = cascade_frustum.center[cascade_index] + - Vector3 { + value: normalize(Vector3::set(-0.1, -0.5, 0.0).value), + } * -maximum_extent.z(); + + let light_view_matrix = compute_look_at_matrix( + cascade_frustum.center[cascade_index], + Vector3::UP, + from_euler_quat(light_direction, EulerOrder::XYZ), + ); + + let shadow_matrix = light_orthographic_matrix * light_view_matrix; + + let shadow_origin = (shadow_matrix * Vector4::W) * (2048.0 * 0.5); + + let rounded_origin = Vector4 { + value: round(shadow_origin.value), + }; + + let mut round_offset = rounded_origin - shadow_origin; + + round_offset = round_offset * 2.0 / 2048.0; + + let shadow_w = shadow_matrix.column_w + round_offset; + + light_orthographic_matrix = Matrix4x4::set( + light_orthographic_matrix.column_x, + light_orthographic_matrix.column_y, + light_orthographic_matrix.column_z, + shadow_w, + ); + + projection.projection_matrix = light_orthographic_matrix; + view.view_matrix = light_view_matrix; + } +} + + +pub fn construct_cascade_shadow_map() -> Workload { + ( + compute_csm_split_system, + compute_csm_frustum_system, + compute_csm_shadow_matrix_system, + ) + .into_workload() +} diff --git a/crates/mani/fabled_system/src/system/lighting/mod.rs b/crates/mani/fabled_system/src/system/lighting/mod.rs index 178105d4..058b8a84 100644 --- a/crates/mani/fabled_system/src/system/lighting/mod.rs +++ b/crates/mani/fabled_system/src/system/lighting/mod.rs @@ -1,2 +1,5 @@ mod chromatic_adaption_system; +mod construct_cascade_system; + pub use chromatic_adaption_system::*; +pub use construct_cascade_system::*; diff --git a/crates/mani/fabled_system/src/system/mod.rs b/crates/mani/fabled_system/src/system/mod.rs index 852367f5..71723e6d 100644 --- a/crates/mani/fabled_system/src/system/mod.rs +++ b/crates/mani/fabled_system/src/system/mod.rs @@ -1,4 +1,6 @@ +mod color; mod lighting; mod transform; +pub use color::*; pub use transform::*;