From e6a0f75a63f2be25b5f305fce025be7da9f45b4c Mon Sep 17 00:00:00 2001 From: Lynn <62256001+lynn-lumen@users.noreply.github.com> Date: Mon, 3 Jun 2024 18:10:14 +0200 Subject: [PATCH 1/5] More gizmos builders (#13261) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective - Add GizmoBuilders for some primitives as discussed in #13233 ## Solution - `gizmos.primitive_2d(CIRCLE)` and `gizmos.primitive_2d(ELLIPSE)` now return `Ellipse2dBuilder` aswell. - `gizmos.primitive_3d(SPHERE)` and `gizmos.sphere()` now return the same `SphereBuilder`. - the `.circle_segments` method on the `SphereBuilder` that used to be returned by `.sphere()` is now called `.segments` - the sphere primitive gizmo now matches the `gizmos.sphere` gizmo - `gizmos.primitive_2d(ANNULUS)` now returns a `Annulus2dBuilder` allowing the configuration of the `segments` - gizmos cylinders and capsules now have only 1 line per axis, similar to `gizmos.sphere` ## Migration Guide - Some `gizmos.primitive_nd` methods now return some or different builders. You may need to adjust types and match statements - Replace any calls to `circle_segments()` with `.segments()` --------- Co-authored-by: Raphael Büttgenbach <62256001+solis-lumine-vorago@users.noreply.github.com> --- crates/bevy_gizmos/src/circles.rs | 102 ++++++++++ crates/bevy_gizmos/src/gizmos.rs | 85 +------- crates/bevy_gizmos/src/primitives/dim2.rs | 105 ++++++++-- crates/bevy_gizmos/src/primitives/dim3.rs | 192 +++++++------------ crates/bevy_gizmos/src/primitives/helpers.rs | 52 ----- examples/math/render_primitives.rs | 8 +- 6 files changed, 259 insertions(+), 285 deletions(-) diff --git a/crates/bevy_gizmos/src/circles.rs b/crates/bevy_gizmos/src/circles.rs index aa4bc7d7c348b..6fcd0349381db 100644 --- a/crates/bevy_gizmos/src/circles.rs +++ b/crates/bevy_gizmos/src/circles.rs @@ -178,6 +178,45 @@ where resolution: DEFAULT_CIRCLE_RESOLUTION, } } + + /// Draw a wireframe sphere in 3D made out of 3 circles around the axes. + /// + /// This should be called for each frame the sphere needs to be rendered. + /// + /// # Example + /// ``` + /// # use bevy_gizmos::prelude::*; + /// # use bevy_render::prelude::*; + /// # use bevy_math::prelude::*; + /// # use bevy_color::Color; + /// fn system(mut gizmos: Gizmos) { + /// gizmos.sphere(Vec3::ZERO, Quat::IDENTITY, 1., Color::BLACK); + /// + /// // Each circle has 32 line-segments by default. + /// // You may want to increase this for larger spheres. + /// gizmos + /// .sphere(Vec3::ZERO, Quat::IDENTITY, 5., Color::BLACK) + /// .resolution(64); + /// } + /// # bevy_ecs::system::assert_is_system(system); + /// ``` + #[inline] + pub fn sphere( + &mut self, + position: Vec3, + rotation: Quat, + radius: f32, + color: impl Into, + ) -> SphereBuilder<'_, 'w, 's, Config, Clear> { + SphereBuilder { + gizmos: self, + radius, + position, + rotation, + color: color.into(), + resolution: DEFAULT_CIRCLE_RESOLUTION, + } + } } /// A builder returned by [`Gizmos::ellipse`]. @@ -266,3 +305,66 @@ where self.gizmos.linestrip_2d(positions, self.color); } } + +/// Builder for configuring the drawing options of [`Sphere`]. +pub struct SphereBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, + + // Radius of the sphere + radius: f32, + + // Rotation of the sphere around the origin in 3D space + rotation: Quat, + // Center position of the sphere in 3D space + position: Vec3, + // Color of the sphere + color: Color, + + // Number of line-segments used to approximate the sphere geometry + resolution: usize, +} + +impl SphereBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + /// Set the number of line-segments used to approximate the sphere geometry. + pub fn resolution(mut self, resolution: usize) -> Self { + self.resolution = resolution; + self + } +} + +impl Drop for SphereBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + fn drop(&mut self) { + if !self.gizmos.enabled { + return; + } + + let SphereBuilder { + radius, + position: center, + rotation, + color, + resolution, + .. + } = self; + + // draws one great circle around each of the local axes + Vec3::AXES.into_iter().for_each(|axis| { + let normal = *rotation * axis; + self.gizmos + .circle(*center, Dir3::new_unchecked(normal), *radius, *color) + .resolution(*resolution); + }); + } +} diff --git a/crates/bevy_gizmos/src/gizmos.rs b/crates/bevy_gizmos/src/gizmos.rs index 9c0d1cb3b8370..3b101a36f496f 100644 --- a/crates/bevy_gizmos/src/gizmos.rs +++ b/crates/bevy_gizmos/src/gizmos.rs @@ -2,14 +2,13 @@ use std::{iter, marker::PhantomData, mem}; -use crate::circles::DEFAULT_CIRCLE_RESOLUTION; use bevy_color::{Color, LinearRgba}; use bevy_ecs::{ component::Tick, system::{Deferred, ReadOnlySystemParam, Res, Resource, SystemBuffer, SystemMeta, SystemParam}, world::{unsafe_world_cell::UnsafeWorldCell, World}, }; -use bevy_math::{Dir3, Quat, Rotation2d, Vec2, Vec3}; +use bevy_math::{Quat, Rotation2d, Vec2, Vec3}; use bevy_transform::TransformPoint; use bevy_utils::default; @@ -459,45 +458,6 @@ where strip_colors.push(LinearRgba::NAN); } - /// Draw a wireframe sphere in 3D made out of 3 circles around the axes. - /// - /// This should be called for each frame the sphere needs to be rendered. - /// - /// # Example - /// ``` - /// # use bevy_gizmos::prelude::*; - /// # use bevy_render::prelude::*; - /// # use bevy_math::prelude::*; - /// # use bevy_color::Color; - /// fn system(mut gizmos: Gizmos) { - /// gizmos.sphere(Vec3::ZERO, Quat::IDENTITY, 1., Color::BLACK); - /// - /// // Each circle has 32 line-segments by default. - /// // You may want to increase this for larger spheres. - /// gizmos - /// .sphere(Vec3::ZERO, Quat::IDENTITY, 5., Color::BLACK) - /// .resolution(64); - /// } - /// # bevy_ecs::system::assert_is_system(system); - /// ``` - #[inline] - pub fn sphere( - &mut self, - position: Vec3, - rotation: Quat, - radius: f32, - color: impl Into, - ) -> SphereBuilder<'_, 'w, 's, Config, Clear> { - SphereBuilder { - gizmos: self, - position, - rotation: rotation.normalize(), - radius, - color: color.into(), - resolution: DEFAULT_CIRCLE_RESOLUTION, - } - } - /// Draw a wireframe rectangle in 3D. /// /// This should be called for each frame the rectangle needs to be rendered. @@ -790,49 +750,6 @@ where } } -/// A builder returned by [`Gizmos::sphere`]. -pub struct SphereBuilder<'a, 'w, 's, Config, Clear = ()> -where - Config: GizmoConfigGroup, - Clear: 'static + Send + Sync, -{ - gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, - position: Vec3, - rotation: Quat, - radius: f32, - color: Color, - resolution: usize, -} - -impl SphereBuilder<'_, '_, '_, Config, Clear> -where - Config: GizmoConfigGroup, - Clear: 'static + Send + Sync, -{ - /// Set the number of line-segments per circle for this sphere. - pub fn resolution(mut self, resolution: usize) -> Self { - self.resolution = resolution; - self - } -} - -impl Drop for SphereBuilder<'_, '_, '_, Config, Clear> -where - Config: GizmoConfigGroup, - Clear: 'static + Send + Sync, -{ - fn drop(&mut self) { - if !self.gizmos.enabled { - return; - } - for axis in Dir3::AXES { - self.gizmos - .circle(self.position, self.rotation * axis, self.radius, self.color) - .resolution(self.resolution); - } - } -} - fn rect_inner(size: Vec2) -> [Vec2; 4] { let half_size = size / 2.; let tl = Vec2::new(-half_size.x, half_size.y); diff --git a/crates/bevy_gizmos/src/primitives/dim2.rs b/crates/bevy_gizmos/src/primitives/dim2.rs index 1c0b699e60401..9acca8356be6c 100644 --- a/crates/bevy_gizmos/src/primitives/dim2.rs +++ b/crates/bevy_gizmos/src/primitives/dim2.rs @@ -102,7 +102,7 @@ where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, { - type Output<'a> = () where Self: 'a; + type Output<'a> = crate::circles::Ellipse2dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_2d( &mut self, @@ -111,11 +111,7 @@ where _angle: f32, color: impl Into, ) -> Self::Output<'_> { - if !self.enabled { - return; - } - - self.circle_2d(position, primitive.radius, color); + self.circle_2d(position, primitive.radius, color) } } @@ -205,46 +201,114 @@ where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, { - type Output<'a> = () where Self: 'a; + type Output<'a> = crate::circles::Ellipse2dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; - fn primitive_2d( + fn primitive_2d<'a>( &mut self, primitive: &Ellipse, position: Vec2, angle: f32, color: impl Into, ) -> Self::Output<'_> { - if !self.enabled { - return; - } - - self.ellipse_2d(position, angle, primitive.half_size, color); + self.ellipse_2d(position, angle, primitive.half_size, color) } } // annulus 2d +/// Builder for configuring the drawing options of [`Annulus`]. +pub struct Annulus2dBuilder<'a, 'w, 's, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, + position: Vec2, + inner_radius: f32, + outer_radius: f32, + color: Color, + inner_resolution: usize, + outer_resolution: usize, +} + +impl Annulus2dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + /// Set the number of line-segments for each circle of the annulus. + pub fn resolution(mut self, resolution: usize) -> Self { + self.outer_resolution = resolution; + self.inner_resolution = resolution; + self + } + + /// Set the number of line-segments for the outer circle of the annulus. + pub fn outer_resolution(mut self, resolution: usize) -> Self { + self.outer_resolution = resolution; + self + } + + /// Set the number of line-segments for the inner circle of the annulus. + pub fn inner_resolution(mut self, resolution: usize) -> Self { + self.inner_resolution = resolution; + self + } +} + impl<'w, 's, Config, Clear> GizmoPrimitive2d for Gizmos<'w, 's, Config, Clear> where Config: GizmoConfigGroup, Clear: 'static + Send + Sync, { - type Output<'a> = () where Self: 'a; + type Output<'a> = Annulus2dBuilder<'a, 'w, 's, Config, Clear> where Self: 'a; fn primitive_2d( &mut self, primitive: &Annulus, position: Vec2, - angle: f32, + _angle: f32, color: impl Into, ) -> Self::Output<'_> { - if !self.enabled { + Annulus2dBuilder { + gizmos: self, + position, + inner_radius: primitive.inner_circle.radius, + outer_radius: primitive.outer_circle.radius, + color: color.into(), + inner_resolution: crate::circles::DEFAULT_CIRCLE_RESOLUTION, + outer_resolution: crate::circles::DEFAULT_CIRCLE_RESOLUTION, + } + } +} + +impl Drop for Annulus2dBuilder<'_, '_, '_, Config, Clear> +where + Config: GizmoConfigGroup, + Clear: 'static + Send + Sync, +{ + fn drop(&mut self) { + if !self.gizmos.enabled { return; } - let color = color.into(); - self.primitive_2d(&primitive.inner_circle, position, angle, color); - self.primitive_2d(&primitive.outer_circle, position, angle, color); + let Annulus2dBuilder { + gizmos, + position, + inner_radius, + outer_radius, + inner_resolution, + outer_resolution, + color, + .. + } = self; + + gizmos + .circle_2d(*position, *outer_radius, *color) + .resolution(*outer_resolution); + gizmos + .circle_2d(*position, *inner_radius, *color) + .resolution(*inner_resolution); } } @@ -266,8 +330,7 @@ where ) -> Self::Output<'_> { if !self.enabled { return; - } - + }; let [a, b, c, d] = [(1.0, 0.0), (0.0, 1.0), (-1.0, 0.0), (0.0, -1.0)].map(|(sign_x, sign_y)| { Vec2::new( diff --git a/crates/bevy_gizmos/src/primitives/dim3.rs b/crates/bevy_gizmos/src/primitives/dim3.rs index ec6ab6d6512e3..31cb395526701 100644 --- a/crates/bevy_gizmos/src/primitives/dim3.rs +++ b/crates/bevy_gizmos/src/primitives/dim3.rs @@ -1,7 +1,7 @@ //! A module for rendering each of the 3D [`bevy_math::primitives`] with [`Gizmos`]. use super::helpers::*; -use std::f32::consts::TAU; +use std::f32::consts::{FRAC_PI_2, PI, TAU}; use bevy_color::Color; use bevy_math::primitives::{ @@ -10,6 +10,7 @@ use bevy_math::primitives::{ }; use bevy_math::{Dir3, Quat, Vec3}; +use crate::circles::SphereBuilder; use crate::prelude::{GizmoConfigGroup, Gizmos}; const DEFAULT_RESOLUTION: usize = 5; @@ -55,41 +56,6 @@ where // sphere -/// Builder for configuring the drawing options of [`Sphere`]. -pub struct SphereBuilder<'a, 'w, 's, Config, Clear> -where - Config: GizmoConfigGroup, - Clear: 'static + Send + Sync, -{ - gizmos: &'a mut Gizmos<'w, 's, Config, Clear>, - - // Radius of the sphere - radius: f32, - - // Rotation of the sphere around the origin in 3D space - rotation: Quat, - // Center position of the sphere in 3D space - position: Vec3, - // Color of the sphere - color: Color, - - // Resolution of the gizmos used to approximate the sphere geometry - // The number of vertices used to approximate the sphere geometry. - resolution: usize, -} - -impl SphereBuilder<'_, '_, '_, Config, Clear> -where - Config: GizmoConfigGroup, - Clear: 'static + Send + Sync, -{ - /// Set the number of lines used to approximate the sphere geometry. - pub fn resolution(mut self, resolution: usize) -> Self { - self.resolution = resolution; - self - } -} - impl<'w, 's, Config, Clear> GizmoPrimitive3d for Gizmos<'w, 's, Config, Clear> where Config: GizmoConfigGroup, @@ -104,59 +70,7 @@ where rotation: Quat, color: impl Into, ) -> Self::Output<'_> { - SphereBuilder { - gizmos: self, - radius: primitive.radius, - position, - rotation, - color: color.into(), - resolution: DEFAULT_RESOLUTION, - } - } -} - -impl Drop for SphereBuilder<'_, '_, '_, Config, Clear> -where - Config: GizmoConfigGroup, - Clear: 'static + Send + Sync, -{ - fn drop(&mut self) { - if !self.gizmos.enabled { - return; - } - - let SphereBuilder { - radius, - position: center, - rotation, - color, - resolution, - .. - } = self; - - // draws the upper and lower semi spheres - [-1.0, 1.0].into_iter().for_each(|sign| { - let top = *center + (*rotation * Vec3::Y) * sign * *radius; - draw_semi_sphere( - self.gizmos, - *radius, - *resolution, - *rotation, - *center, - top, - *color, - ); - }); - - // draws one great circle of the sphere - draw_circle_3d( - self.gizmos, - *radius, - *resolution, - *rotation, - *center, - *color, - ); + self.sphere(position, rotation, primitive.radius, color) } } @@ -578,30 +492,27 @@ where resolution, } = self; - let normal = *rotation * Vec3::Y; + let normal = Dir3::new_unchecked(*rotation * Vec3::Y); + let up = normal.as_vec3() * *half_height; // draw upper and lower circle of the cylinder [-1.0, 1.0].into_iter().for_each(|sign| { - draw_circle_3d( - gizmos, - *radius, - *resolution, - *rotation, - *position + sign * *half_height * normal, - *color, - ); + gizmos + .circle(*position + sign * up, normal, *radius, *color) + .resolution(*resolution); }); // draw lines connecting the two cylinder circles - draw_cylinder_vertical_lines( - gizmos, - *radius, - *resolution, - *half_height, - *rotation, - *position, - *color, - ); + [Vec3::NEG_X, Vec3::NEG_Z, Vec3::X, Vec3::Z] + .into_iter() + .for_each(|axis| { + let axis = *rotation * axis; + gizmos.line( + *position + up + axis * *radius, + *position - up + axis * *radius, + *color, + ); + }); } } @@ -691,26 +602,57 @@ where resolution, } = self; - let normal = *rotation * Vec3::Y; + // Draw the circles at the top and bottom of the cylinder + let y_offset = *rotation * Vec3::Y; + gizmos + .circle( + *position + y_offset * *half_length, + Dir3::new_unchecked(y_offset), + *radius, + *color, + ) + .resolution(*resolution); + gizmos + .circle( + *position - y_offset * *half_length, + Dir3::new_unchecked(y_offset), + *radius, + *color, + ) + .resolution(*resolution); + let y_offset = y_offset * *half_length; - // draw two semi spheres for the capsule - [1.0, -1.0].into_iter().for_each(|sign| { - let center = *position + sign * *half_length * normal; - let top = center + sign * *radius * normal; - draw_semi_sphere(gizmos, *radius, *resolution, *rotation, center, top, *color); - draw_circle_3d(gizmos, *radius, *resolution, *rotation, center, *color); - }); + // Draw the vertical lines and the cap semicircles + [Vec3::X, Vec3::Z].into_iter().for_each(|axis| { + let normal = *rotation * axis; - // connect the two semi spheres with lines - draw_cylinder_vertical_lines( - gizmos, - *radius, - *resolution, - *half_length, - *rotation, - *position, - *color, - ); + gizmos.line( + *position + normal * *radius + y_offset, + *position + normal * *radius - y_offset, + *color, + ); + gizmos.line( + *position - normal * *radius + y_offset, + *position - normal * *radius - y_offset, + *color, + ); + + let rotation = *rotation + * Quat::from_euler(bevy_math::EulerRot::ZYX, 0., axis.z * FRAC_PI_2, FRAC_PI_2); + + gizmos + .arc_3d(PI, *radius, *position + y_offset, rotation, *color) + .resolution(*resolution / 2); + gizmos + .arc_3d( + PI, + *radius, + *position - y_offset, + rotation * Quat::from_rotation_y(PI), + *color, + ) + .resolution(*resolution / 2); + }); } } diff --git a/crates/bevy_gizmos/src/primitives/helpers.rs b/crates/bevy_gizmos/src/primitives/helpers.rs index 286ed1d8cf022..3ca4a6ad183ed 100644 --- a/crates/bevy_gizmos/src/primitives/helpers.rs +++ b/crates/bevy_gizmos/src/primitives/helpers.rs @@ -46,33 +46,6 @@ pub(crate) fn circle_coordinates(radius: f32, resolution: usize) -> impl Iterato .take(resolution) } -/// Draws a semi-sphere. -/// -/// This function draws a semi-sphere at the specified `center` point with the given `rotation`, -/// `radius`, and `color`. The `resolution` parameter determines the level of detail, and the `top` -/// argument specifies the shape of the semi-sphere's tip. -pub(crate) fn draw_semi_sphere( - gizmos: &mut Gizmos<'_, '_, Config, Clear>, - radius: f32, - resolution: usize, - rotation: Quat, - center: Vec3, - top: Vec3, - color: Color, -) where - Config: GizmoConfigGroup, - Clear: 'static + Send + Sync, -{ - circle_coordinates(radius, resolution) - .map(|p| Vec3::new(p.x, 0.0, p.y)) - .map(rotate_then_translate_3d(rotation, center)) - .for_each(|from| { - gizmos - .short_arc_3d_between(center, from, top, color) - .resolution(resolution / 2); - }); -} - /// Draws a circle in 3D space. /// /// # Note @@ -97,28 +70,3 @@ pub(crate) fn draw_circle_3d( .map(rotate_then_translate_3d(rotation, translation)); gizmos.linestrip(positions, color); } - -/// Draws the connecting lines of a cylinder between the top circle and the bottom circle. -pub(crate) fn draw_cylinder_vertical_lines( - gizmos: &mut Gizmos<'_, '_, Config, Clear>, - radius: f32, - resolution: usize, - half_height: f32, - rotation: Quat, - center: Vec3, - color: Color, -) where - Config: GizmoConfigGroup, - Clear: 'static + Send + Sync, -{ - circle_coordinates(radius, resolution) - .map(move |point_2d| { - [1.0, -1.0] - .map(|sign| sign * half_height) - .map(|height| Vec3::new(point_2d.x, height, point_2d.y)) - }) - .map(|ps| ps.map(rotate_then_translate_3d(rotation, center))) - .for_each(|[start, end]| { - gizmos.line(start, end, color); - }); -} diff --git a/examples/math/render_primitives.rs b/examples/math/render_primitives.rs index 30ba73380e052..e347cc33ffa19 100644 --- a/examples/math/render_primitives.rs +++ b/examples/math/render_primitives.rs @@ -452,8 +452,10 @@ fn draw_gizmos_2d(mut gizmos: Gizmos, state: Res>, time PrimitiveSelected::RectangleAndCuboid => { gizmos.primitive_2d(&RECTANGLE, POSITION, angle, color); } - PrimitiveSelected::CircleAndSphere => gizmos.primitive_2d(&CIRCLE, POSITION, angle, color), - PrimitiveSelected::Ellipse => gizmos.primitive_2d(&ELLIPSE, POSITION, angle, color), + PrimitiveSelected::CircleAndSphere => { + gizmos.primitive_2d(&CIRCLE, POSITION, angle, color); + } + PrimitiveSelected::Ellipse => drop(gizmos.primitive_2d(&ELLIPSE, POSITION, angle, color)), PrimitiveSelected::Triangle => gizmos.primitive_2d(&TRIANGLE_2D, POSITION, angle, color), PrimitiveSelected::Plane => gizmos.primitive_2d(&PLANE_2D, POSITION, angle, color), PrimitiveSelected::Line => drop(gizmos.primitive_2d(&LINE2D, POSITION, angle, color)), @@ -469,7 +471,7 @@ fn draw_gizmos_2d(mut gizmos: Gizmos, state: Res>, time PrimitiveSelected::Cylinder => {} PrimitiveSelected::Cone => {} PrimitiveSelected::ConicalFrustum => {} - PrimitiveSelected::Torus => gizmos.primitive_2d(&ANNULUS, POSITION, angle, color), + PrimitiveSelected::Torus => drop(gizmos.primitive_2d(&ANNULUS, POSITION, angle, color)), PrimitiveSelected::Tetrahedron => {} PrimitiveSelected::Arc => gizmos.primitive_2d(&ARC, POSITION, angle, color), PrimitiveSelected::CircularSector => { From 36f2542f63f7378b335529eb425d25da957c65a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Rica=20Pais=20da=20Silva?= Date: Mon, 3 Jun 2024 18:33:14 +0200 Subject: [PATCH 2/5] feat: Reflection implementations on Identifier (#13648) # Objective - Follow-up on some changes in #11498 - Unblock using `Identifier` to replace `ComponentId` internals. ## Solution - Implement the same `Reflect` impls from `Entity` onto `Identifier` as they share same/similar purposes, ## Testing - No compile errors. Currently `Identifier` has no serialization impls, so there's no need to test a serialization/deserialization roundtrip to ensure correctness. --- ## Changelog ### Added - Reflection implementations on `Identifier`. --- crates/bevy_ecs/src/identifier/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/bevy_ecs/src/identifier/mod.rs b/crates/bevy_ecs/src/identifier/mod.rs index 66ff28af43516..04a93cde45c0c 100644 --- a/crates/bevy_ecs/src/identifier/mod.rs +++ b/crates/bevy_ecs/src/identifier/mod.rs @@ -3,6 +3,9 @@ //! or other IDs that can be packed and expressed within a `u64` sized type. //! [`Identifier`]s cannot be created directly, only able to be converted from other //! compatible IDs. +#[cfg(feature = "bevy_reflect")] +use bevy_reflect::Reflect; + use self::{error::IdentifierError, kinds::IdKind, masks::IdentifierMask}; use std::{hash::Hash, num::NonZeroU32}; @@ -15,6 +18,8 @@ pub(crate) mod masks; /// segment, a 31-bit high segment, and the significant bit reserved as type flags to denote /// entity kinds. #[derive(Debug, Clone, Copy)] +#[cfg_attr(feature = "bevy_reflect", derive(Reflect))] +#[cfg_attr(feature = "bevy_reflect", reflect_value(Debug, Hash, PartialEq))] // Alignment repr necessary to allow LLVM to better output // optimised codegen for `to_bits`, `PartialEq` and `Ord`. #[repr(C, align(8))] From 7570c9f3d2e75d4f2e660a4a105d82648cfa233b Mon Sep 17 00:00:00 2001 From: Brandon Reinhart Date: Mon, 3 Jun 2024 11:33:24 -0500 Subject: [PATCH 3/5] Map entities from a resource when written to the world. (#13650) # Objective - Fix #10958 by performing entity mapping on the entities inside of resources. ## Solution - Resources can reflect(MapEntitiesResource) and impl MapEntities to get access to the mapper during the world insert of the scene. ## Testing - A test resource_entity_map_maps_entities confirms the desired behavior. ## Changelog - Added reflect(MapEntitiesResource) for mapping entities on Resources in a DynamicScene. fixes 10958 --- crates/bevy_ecs/src/reflect/map_entities.rs | 31 ++++++ crates/bevy_ecs/src/reflect/mod.rs | 2 +- crates/bevy_scene/src/dynamic_scene.rs | 111 +++++++++++++++----- 3 files changed, 119 insertions(+), 25 deletions(-) diff --git a/crates/bevy_ecs/src/reflect/map_entities.rs b/crates/bevy_ecs/src/reflect/map_entities.rs index 0d783885dab63..4bc70acc3e55e 100644 --- a/crates/bevy_ecs/src/reflect/map_entities.rs +++ b/crates/bevy_ecs/src/reflect/map_entities.rs @@ -73,3 +73,34 @@ impl FromType for ReflectMapEntities { } } } + +/// For a specific type of resource, this maps any fields with values of type [`Entity`] to a new world. +/// Since a given `Entity` ID is only valid for the world it came from, when performing deserialization +/// any stored IDs need to be re-allocated in the destination world. +/// +/// See [`SceneEntityMapper`] and [`MapEntities`] for more information. +#[derive(Clone)] +pub struct ReflectMapEntitiesResource { + map_entities: fn(&mut World, &mut SceneEntityMapper), +} + +impl ReflectMapEntitiesResource { + /// A method for applying [`MapEntities`] behavior to elements in an [`EntityHashMap`]. + pub fn map_entities(&self, world: &mut World, entity_map: &mut EntityHashMap) { + SceneEntityMapper::world_scope(entity_map, world, |world, mapper| { + (self.map_entities)(world, mapper); + }); + } +} + +impl FromType for ReflectMapEntitiesResource { + fn from_type() -> Self { + ReflectMapEntitiesResource { + map_entities: |world, entity_mapper| { + if let Some(mut resource) = world.get_resource_mut::() { + resource.map_entities(entity_mapper); + } + }, + } + } +} diff --git a/crates/bevy_ecs/src/reflect/mod.rs b/crates/bevy_ecs/src/reflect/mod.rs index c1dfde5f02543..322bf3c9b544c 100644 --- a/crates/bevy_ecs/src/reflect/mod.rs +++ b/crates/bevy_ecs/src/reflect/mod.rs @@ -19,7 +19,7 @@ pub use bundle::{ReflectBundle, ReflectBundleFns}; pub use component::{ReflectComponent, ReflectComponentFns}; pub use entity_commands::ReflectCommandExt; pub use from_world::{ReflectFromWorld, ReflectFromWorldFns}; -pub use map_entities::ReflectMapEntities; +pub use map_entities::{ReflectMapEntities, ReflectMapEntitiesResource}; pub use resource::{ReflectResource, ReflectResourceFns}; /// A [`Resource`] storing [`TypeRegistry`] for diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 99aa528cda471..97e22844342b3 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -11,7 +11,7 @@ use bevy_utils::TypeIdMap; #[cfg(feature = "serialize")] use crate::serde::SceneSerializer; use bevy_asset::Asset; -use bevy_ecs::reflect::ReflectResource; +use bevy_ecs::reflect::{ReflectMapEntitiesResource, ReflectResource}; #[cfg(feature = "serialize")] use serde::Serialize; @@ -71,28 +71,6 @@ impl DynamicScene { ) -> Result<(), SceneSpawnError> { let type_registry = type_registry.read(); - for resource in &self.resources { - let type_info = resource.get_represented_type_info().ok_or_else(|| { - SceneSpawnError::NoRepresentedType { - type_path: resource.reflect_type_path().to_string(), - } - })?; - let registration = type_registry.get(type_info.type_id()).ok_or_else(|| { - SceneSpawnError::UnregisteredButReflectedType { - type_path: type_info.type_path().to_string(), - } - })?; - let reflect_resource = registration.data::().ok_or_else(|| { - SceneSpawnError::UnregisteredResource { - type_path: type_info.type_path().to_string(), - } - })?; - - // If the world already contains an instance of the given resource - // just apply the (possibly) new value, otherwise insert the resource - reflect_resource.apply_or_insert(world, &**resource, &type_registry); - } - // For each component types that reference other entities, we keep track // of which entities in the scene use that component. // This is so we can update the scene-internal references to references @@ -153,6 +131,35 @@ impl DynamicScene { } } + // Insert resources after all entities have been added to the world. + // This ensures the entities are available for the resources to reference during mapping. + for resource in &self.resources { + let type_info = resource.get_represented_type_info().ok_or_else(|| { + SceneSpawnError::NoRepresentedType { + type_path: resource.reflect_type_path().to_string(), + } + })?; + let registration = type_registry.get(type_info.type_id()).ok_or_else(|| { + SceneSpawnError::UnregisteredButReflectedType { + type_path: type_info.type_path().to_string(), + } + })?; + let reflect_resource = registration.data::().ok_or_else(|| { + SceneSpawnError::UnregisteredResource { + type_path: type_info.type_path().to_string(), + } + })?; + + // If the world already contains an instance of the given resource + // just apply the (possibly) new value, otherwise insert the resource + reflect_resource.apply_or_insert(world, &**resource, &type_registry); + + // Map entities in the resource if it implements [`MapEntities`]. + if let Some(map_entities_reflect) = registration.data::() { + map_entities_reflect.map_entities(world, entity_map); + } + } + Ok(()) } @@ -198,12 +205,68 @@ where #[cfg(test)] mod tests { - use bevy_ecs::entity::EntityHashMap; + use bevy_ecs::entity::{Entity, EntityHashMap, EntityMapper, MapEntities}; + use bevy_ecs::reflect::{ReflectMapEntitiesResource, ReflectResource}; + use bevy_ecs::system::Resource; use bevy_ecs::{reflect::AppTypeRegistry, world::Command, world::World}; use bevy_hierarchy::{Parent, PushChild}; + use bevy_reflect::Reflect; use crate::dynamic_scene_builder::DynamicSceneBuilder; + #[derive(Resource, Reflect, Debug)] + #[reflect(Resource, MapEntitiesResource)] + struct TestResource { + entity_a: Entity, + entity_b: Entity, + } + + impl MapEntities for TestResource { + fn map_entities(&mut self, entity_mapper: &mut M) { + self.entity_a = entity_mapper.map_entity(self.entity_a); + self.entity_b = entity_mapper.map_entity(self.entity_b); + } + } + + #[test] + fn resource_entity_map_maps_entities() { + let type_registry = AppTypeRegistry::default(); + type_registry.write().register::(); + + let mut source_world = World::new(); + source_world.insert_resource(type_registry.clone()); + + let original_entity_a = source_world.spawn_empty().id(); + let original_entity_b = source_world.spawn_empty().id(); + + source_world.insert_resource(TestResource { + entity_a: original_entity_a, + entity_b: original_entity_b, + }); + + // Write the scene. + let scene = DynamicSceneBuilder::from_world(&source_world) + .extract_resources() + .extract_entity(original_entity_a) + .extract_entity(original_entity_b) + .build(); + + let mut entity_map = EntityHashMap::default(); + let mut destination_world = World::new(); + destination_world.insert_resource(type_registry); + + scene + .write_to_world(&mut destination_world, &mut entity_map) + .unwrap(); + + let &from_entity_a = entity_map.get(&original_entity_a).unwrap(); + let &from_entity_b = entity_map.get(&original_entity_b).unwrap(); + + let test_resource = destination_world.get_resource::().unwrap(); + assert_eq!(from_entity_a, test_resource.entity_a); + assert_eq!(from_entity_b, test_resource.entity_b); + } + #[test] fn components_not_defined_in_scene_should_not_be_affected_by_scene_entity_map() { // Testing that scene reloading applies EntityMap correctly to MapEntities components. From 5ca7ba2c18b6c72912ca9fefc5c6783228e0f4b2 Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Mon, 3 Jun 2024 12:54:29 -0400 Subject: [PATCH 4/5] Unrevert (vert?) "Add `on_unimplemented` Diagnostics to Most Public Traits" (#13414) # Objective - https://github.com/bevyengine/bevy/pull/13347 was good actually ## Solution - Add it back to main (once #13366 is merged) --------- Co-authored-by: Alice Cecile From 9b9d3d81cba698e69d1a6b7cb863c109f9aa8b46 Mon Sep 17 00:00:00 2001 From: Ricky Taylor Date: Mon, 3 Jun 2024 17:56:53 +0100 Subject: [PATCH 5/5] Normalise matrix naming (#13489) # Objective - Fixes #10909 - Fixes #8492 ## Solution - Name all matrices `x_from_y`, for example `world_from_view`. ## Testing - I've tested most of the 3D examples. The `lighting` example particularly should hit a lot of the changes and appears to run fine. --- ## Changelog - Renamed matrices across the engine to follow a `y_from_x` naming, making the space conversion more obvious. ## Migration Guide - `Frustum`'s `from_view_projection`, `from_view_projection_custom_far` and `from_view_projection_no_far` were renamed to `from_clip_from_world`, `from_clip_from_world_custom_far` and `from_clip_from_world_no_far`. - `ComputedCameraValues::projection_matrix` was renamed to `clip_from_view`. - `CameraProjection::get_projection_matrix` was renamed to `get_clip_from_view` (this affects implementations on `Projection`, `PerspectiveProjection` and `OrthographicProjection`). - `ViewRangefinder3d::from_view_matrix` was renamed to `from_world_from_view`. - `PreviousViewData`'s members were renamed to `view_from_world` and `clip_from_world`. - `ExtractedView`'s `projection`, `transform` and `view_projection` were renamed to `clip_from_view`, `world_from_view` and `clip_from_world`. - `ViewUniform`'s `view_proj`, `unjittered_view_proj`, `inverse_view_proj`, `view`, `inverse_view`, `projection` and `inverse_projection` were renamed to `clip_from_world`, `unjittered_clip_from_world`, `world_from_clip`, `world_from_view`, `view_from_world`, `clip_from_view` and `view_from_clip`. - `GpuDirectionalCascade::view_projection` was renamed to `clip_from_world`. - `MeshTransforms`' `transform` and `previous_transform` were renamed to `world_from_local` and `previous_world_from_local`. - `MeshUniform`'s `transform`, `previous_transform`, `inverse_transpose_model_a` and `inverse_transpose_model_b` were renamed to `world_from_local`, `previous_world_from_local`, `local_from_world_transpose_a` and `local_from_world_transpose_b` (the `Mesh` type in WGSL mirrors this, however `transform` and `previous_transform` were named `model` and `previous_model`). - `Mesh2dTransforms::transform` was renamed to `world_from_local`. - `Mesh2dUniform`'s `transform`, `inverse_transpose_model_a` and `inverse_transpose_model_b` were renamed to `world_from_local`, `local_from_world_transpose_a` and `local_from_world_transpose_b` (the `Mesh2d` type in WGSL mirrors this). - In WGSL, in `bevy_pbr::mesh_functions`, `get_model_matrix` and `get_previous_model_matrix` were renamed to `get_world_from_local` and `get_previous_world_from_local`. - In WGSL, `bevy_sprite::mesh2d_functions::get_model_matrix` was renamed to `get_world_from_local`. --- assets/shaders/array_texture.wgsl | 2 +- assets/shaders/custom_gltf_2d.wgsl | 6 +- assets/shaders/custom_vertex_attribute.wgsl | 4 +- assets/shaders/instancing.wgsl | 6 +- ...irradiance_volume_voxel_visualization.wgsl | 8 +- crates/bevy_core_pipeline/src/prepass/mod.rs | 4 +- .../bevy_core_pipeline/src/skybox/skybox.wgsl | 4 +- .../src/skybox/skybox_prepass.wgsl | 8 +- crates/bevy_gizmos/src/line_joints.wgsl | 22 ++--- crates/bevy_gizmos/src/lines.wgsl | 14 +-- crates/bevy_gltf/src/loader.rs | 4 +- crates/bevy_pbr/src/cluster/assign.rs | 95 ++++++++++--------- .../src/deferred/pbr_deferred_functions.wgsl | 2 +- crates/bevy_pbr/src/light/mod.rs | 54 +++++------ .../src/light_probe/irradiance_volume.wgsl | 2 +- .../bevy_pbr/src/light_probe/light_probe.wgsl | 10 +- crates/bevy_pbr/src/light_probe/mod.rs | 28 +++--- .../bevy_pbr/src/meshlet/cull_meshlets.wgsl | 44 ++++----- crates/bevy_pbr/src/meshlet/gpu_scene.rs | 4 +- .../src/meshlet/visibility_buffer_raster.wgsl | 6 +- .../meshlet/visibility_buffer_resolve.wgsl | 32 +++---- crates/bevy_pbr/src/prepass/mod.rs | 16 ++-- crates/bevy_pbr/src/prepass/prepass.wgsl | 18 ++-- .../src/prepass/prepass_bindings.wgsl | 4 +- crates/bevy_pbr/src/render/light.rs | 34 +++---- crates/bevy_pbr/src/render/mesh.rs | 46 ++++----- crates/bevy_pbr/src/render/mesh.wgsl | 12 +-- .../bevy_pbr/src/render/mesh_functions.wgsl | 28 +++--- .../bevy_pbr/src/render/mesh_preprocess.wgsl | 44 ++++----- crates/bevy_pbr/src/render/mesh_types.wgsl | 8 +- .../bevy_pbr/src/render/mesh_view_types.wgsl | 4 +- crates/bevy_pbr/src/render/pbr_fragment.wgsl | 4 +- crates/bevy_pbr/src/render/pbr_functions.wgsl | 10 +- .../src/render/pbr_prepass_functions.wgsl | 4 +- .../bevy_pbr/src/render/pbr_transmission.wgsl | 2 +- crates/bevy_pbr/src/render/shadows.wgsl | 2 +- crates/bevy_pbr/src/render/skinning.wgsl | 8 +- .../src/render/view_transformations.wgsl | 42 ++++---- crates/bevy_pbr/src/ssao/gtao.wgsl | 14 +-- crates/bevy_render/src/camera/camera.rs | 32 +++---- crates/bevy_render/src/camera/projection.rs | 20 ++-- crates/bevy_render/src/primitives/mod.rs | 42 ++++---- .../src/render_phase/rangefinder.rs | 14 +-- crates/bevy_render/src/view/mod.rs | 58 +++++------ crates/bevy_render/src/view/view.wgsl | 14 +-- crates/bevy_render/src/view/visibility/mod.rs | 6 +- crates/bevy_sprite/src/mesh2d/material.rs | 2 +- crates/bevy_sprite/src/mesh2d/mesh.rs | 20 ++-- crates/bevy_sprite/src/mesh2d/mesh2d.wgsl | 6 +- .../src/mesh2d/mesh2d_functions.wgsl | 26 ++--- .../bevy_sprite/src/mesh2d/mesh2d_types.wgsl | 6 +- crates/bevy_sprite/src/render/sprite.wgsl | 2 +- .../src/components/global_transform.rs | 4 +- .../src/components/transform.rs | 4 +- crates/bevy_ui/src/render/mod.rs | 11 ++- crates/bevy_ui/src/render/ui.wgsl | 2 +- crates/bevy_ui/src/render/ui_material.wgsl | 2 +- examples/2d/mesh2d_manual.rs | 6 +- examples/3d/irradiance_volumes.rs | 12 +-- 59 files changed, 476 insertions(+), 472 deletions(-) diff --git a/assets/shaders/array_texture.wgsl b/assets/shaders/array_texture.wgsl index 3fa77933b2b14..21c8fb274124d 100644 --- a/assets/shaders/array_texture.wgsl +++ b/assets/shaders/array_texture.wgsl @@ -36,7 +36,7 @@ fn fragment( is_front, ); - pbr_input.is_orthographic = view.projection[3].w == 1.0; + pbr_input.is_orthographic = view.clip_from_view[3].w == 1.0; pbr_input.N = normalize(pbr_input.world_normal); diff --git a/assets/shaders/custom_gltf_2d.wgsl b/assets/shaders/custom_gltf_2d.wgsl index 1ea793ad35696..b92b09858bf76 100644 --- a/assets/shaders/custom_gltf_2d.wgsl +++ b/assets/shaders/custom_gltf_2d.wgsl @@ -1,6 +1,6 @@ #import bevy_sprite::{ mesh2d_view_bindings::globals, - mesh2d_functions::{get_model_matrix, mesh2d_position_local_to_clip}, + mesh2d_functions::{get_world_from_local, mesh2d_position_local_to_clip}, } struct Vertex { @@ -19,8 +19,8 @@ struct VertexOutput { @vertex fn vertex(vertex: Vertex) -> VertexOutput { var out: VertexOutput; - let model = get_model_matrix(vertex.instance_index); - out.clip_position = mesh2d_position_local_to_clip(model, vec4(vertex.position, 1.0)); + let world_from_local = get_world_from_local(vertex.instance_index); + out.clip_position = mesh2d_position_local_to_clip(world_from_local, vec4(vertex.position, 1.0)); out.color = vertex.color; out.barycentric = vertex.barycentric; return out; diff --git a/assets/shaders/custom_vertex_attribute.wgsl b/assets/shaders/custom_vertex_attribute.wgsl index 89cefd80f1e49..f8062ab77be3f 100644 --- a/assets/shaders/custom_vertex_attribute.wgsl +++ b/assets/shaders/custom_vertex_attribute.wgsl @@ -1,4 +1,4 @@ -#import bevy_pbr::mesh_functions::{get_model_matrix, mesh_position_local_to_clip} +#import bevy_pbr::mesh_functions::{get_world_from_local, mesh_position_local_to_clip} struct CustomMaterial { color: vec4, @@ -20,7 +20,7 @@ struct VertexOutput { fn vertex(vertex: Vertex) -> VertexOutput { var out: VertexOutput; out.clip_position = mesh_position_local_to_clip( - get_model_matrix(vertex.instance_index), + get_world_from_local(vertex.instance_index), vec4(vertex.position, 1.0), ); out.blend_color = vertex.blend_color; diff --git a/assets/shaders/instancing.wgsl b/assets/shaders/instancing.wgsl index 5491921a6e151..2e37ed2153421 100644 --- a/assets/shaders/instancing.wgsl +++ b/assets/shaders/instancing.wgsl @@ -1,4 +1,4 @@ -#import bevy_pbr::mesh_functions::{get_model_matrix, mesh_position_local_to_clip} +#import bevy_pbr::mesh_functions::{get_world_from_local, mesh_position_local_to_clip} struct Vertex { @location(0) position: vec3, @@ -18,12 +18,12 @@ struct VertexOutput { fn vertex(vertex: Vertex) -> VertexOutput { let position = vertex.position * vertex.i_pos_scale.w + vertex.i_pos_scale.xyz; var out: VertexOutput; - // NOTE: Passing 0 as the instance_index to get_model_matrix() is a hack + // NOTE: Passing 0 as the instance_index to get_world_from_local() is a hack // for this example as the instance_index builtin would map to the wrong // index in the Mesh array. This index could be passed in via another // uniform instead but it's unnecessary for the example. out.clip_position = mesh_position_local_to_clip( - get_model_matrix(0u), + get_world_from_local(0u), vec4(position, 1.0) ); out.color = vertex.i_color; diff --git a/assets/shaders/irradiance_volume_voxel_visualization.wgsl b/assets/shaders/irradiance_volume_voxel_visualization.wgsl index f85a9d9cb708d..26a8deb87eb35 100644 --- a/assets/shaders/irradiance_volume_voxel_visualization.wgsl +++ b/assets/shaders/irradiance_volume_voxel_visualization.wgsl @@ -3,8 +3,8 @@ #import bevy_pbr::mesh_view_bindings struct VoxelVisualizationIrradianceVolumeInfo { - transform: mat4x4, - inverse_transform: mat4x4, + world_from_voxel: mat4x4, + voxel_from_world: mat4x4, resolution: vec3, // A scale factor that's applied to the diffuse and specular light from the // light probe. This is in units of cd/m² (candela per square meter). @@ -18,12 +18,12 @@ var irradiance_volume_info: VoxelVisualizationIrradianceVolumeInfo; fn fragment(mesh: VertexOutput) -> @location(0) vec4 { // Snap the world position we provide to `irradiance_volume_light()` to the // middle of the nearest texel. - var unit_pos = (irradiance_volume_info.inverse_transform * + var unit_pos = (irradiance_volume_info.voxel_from_world * vec4(mesh.world_position.xyz, 1.0f)).xyz; let resolution = vec3(irradiance_volume_info.resolution); let stp = clamp((unit_pos + 0.5) * resolution, vec3(0.5f), resolution - vec3(0.5f)); let stp_rounded = round(stp - 0.5f) + 0.5f; - let rounded_world_pos = (irradiance_volume_info.transform * vec4(stp_rounded, 1.0f)).xyz; + let rounded_world_pos = (irradiance_volume_info.world_from_voxel * vec4(stp_rounded, 1.0f)).xyz; // `irradiance_volume_light()` multiplies by intensity, so cancel it out. // If we take intensity into account, the cubes will be way too bright. diff --git a/crates/bevy_core_pipeline/src/prepass/mod.rs b/crates/bevy_core_pipeline/src/prepass/mod.rs index 1162b1450a2bf..861bba12b6dc8 100644 --- a/crates/bevy_core_pipeline/src/prepass/mod.rs +++ b/crates/bevy_core_pipeline/src/prepass/mod.rs @@ -71,8 +71,8 @@ pub struct DeferredPrepass; #[derive(Component, ShaderType, Clone)] pub struct PreviousViewData { - pub inverse_view: Mat4, - pub view_proj: Mat4, + pub view_from_world: Mat4, + pub clip_from_world: Mat4, } #[derive(Resource, Default)] diff --git a/crates/bevy_core_pipeline/src/skybox/skybox.wgsl b/crates/bevy_core_pipeline/src/skybox/skybox.wgsl index 0534c57854f41..2a353706b5c9b 100644 --- a/crates/bevy_core_pipeline/src/skybox/skybox.wgsl +++ b/crates/bevy_core_pipeline/src/skybox/skybox.wgsl @@ -24,7 +24,7 @@ fn coords_to_ray_direction(position: vec2, viewport: vec4) -> vec3, viewport: vec4) -> vec3, - view_proj: mat4x4, + view_from_world: mat4x4, + clip_from_world: mat4x4, } @group(0) @binding(0) var view: View; @@ -13,8 +13,8 @@ struct PreviousViewUniforms { @fragment fn fragment(in: FullscreenVertexOutput) -> @location(1) vec4 { let clip_pos = uv_to_ndc(in.uv); // Convert from uv to clip space - let world_pos = view.inverse_view_proj * vec4(clip_pos, 0.0, 1.0); - let prev_clip_pos = (previous_view.view_proj * world_pos).xy; + let world_pos = view.world_from_clip * vec4(clip_pos, 0.0, 1.0); + let prev_clip_pos = (previous_view.clip_from_world * world_pos).xy; let velocity = (clip_pos - prev_clip_pos) * vec2(0.5, -0.5); // Copied from mesh motion vectors return vec4(velocity.x, velocity.y, 0.0, 1.0); diff --git a/crates/bevy_gizmos/src/line_joints.wgsl b/crates/bevy_gizmos/src/line_joints.wgsl index 974a5266286be..822442922502e 100644 --- a/crates/bevy_gizmos/src/line_joints.wgsl +++ b/crates/bevy_gizmos/src/line_joints.wgsl @@ -39,9 +39,9 @@ fn vertex_bevel(vertex: VertexInput) -> VertexOutput { ); var position = positions[vertex.index]; - var clip_a = view.view_proj * vec4(vertex.position_a, 1.); - var clip_b = view.view_proj * vec4(vertex.position_b, 1.); - var clip_c = view.view_proj * vec4(vertex.position_c, 1.); + var clip_a = view.clip_from_world * vec4(vertex.position_a, 1.); + var clip_b = view.clip_from_world * vec4(vertex.position_b, 1.); + var clip_c = view.clip_from_world * vec4(vertex.position_c, 1.); // Manual near plane clipping to avoid errors when doing the perspective divide inside this shader. clip_a = clip_near_plane(clip_a, clip_c); @@ -97,10 +97,10 @@ fn vertex_miter(vertex: VertexInput) -> VertexOutput { vec3(0, 0, 0.5), ); var position = positions[vertex.index]; - - var clip_a = view.view_proj * vec4(vertex.position_a, 1.); - var clip_b = view.view_proj * vec4(vertex.position_b, 1.); - var clip_c = view.view_proj * vec4(vertex.position_c, 1.); + + var clip_a = view.clip_from_world * vec4(vertex.position_a, 1.); + var clip_b = view.clip_from_world * vec4(vertex.position_b, 1.); + var clip_c = view.clip_from_world * vec4(vertex.position_c, 1.); // Manual near plane clipping to avoid errors when doing the perspective divide inside this shader. clip_a = clip_near_plane(clip_a, clip_c); @@ -148,9 +148,9 @@ fn vertex_miter(vertex: VertexInput) -> VertexOutput { @vertex fn vertex_round(vertex: VertexInput) -> VertexOutput { - var clip_a = view.view_proj * vec4(vertex.position_a, 1.); - var clip_b = view.view_proj * vec4(vertex.position_b, 1.); - var clip_c = view.view_proj * vec4(vertex.position_c, 1.); + var clip_a = view.clip_from_world * vec4(vertex.position_a, 1.); + var clip_b = view.clip_from_world * vec4(vertex.position_b, 1.); + var clip_c = view.clip_from_world * vec4(vertex.position_c, 1.); // Manual near plane clipping to avoid errors when doing the perspective divide inside this shader. clip_a = clip_near_plane(clip_a, clip_c); @@ -245,4 +245,4 @@ struct FragmentOutput { fn fragment(in: FragmentInput) -> FragmentOutput { // return FragmentOutput(vec4(1, 1, 1, 1)); return FragmentOutput(in.color); -} \ No newline at end of file +} diff --git a/crates/bevy_gizmos/src/lines.wgsl b/crates/bevy_gizmos/src/lines.wgsl index 6edc3eca677ec..64c02f439b841 100644 --- a/crates/bevy_gizmos/src/lines.wgsl +++ b/crates/bevy_gizmos/src/lines.wgsl @@ -44,8 +44,8 @@ fn vertex(vertex: VertexInput) -> VertexOutput { let position = positions[vertex.index]; // algorithm based on https://wwwtyro.net/2019/11/18/instanced-lines.html - var clip_a = view.view_proj * vec4(vertex.position_a, 1.); - var clip_b = view.view_proj * vec4(vertex.position_b, 1.); + var clip_a = view.clip_from_world * vec4(vertex.position_a, 1.); + var clip_b = view.clip_from_world * vec4(vertex.position_b, 1.); // Manual near plane clipping to avoid errors when doing the perspective divide inside this shader. clip_a = clip_near_plane(clip_a, clip_b); @@ -69,13 +69,13 @@ fn vertex(vertex: VertexInput) -> VertexOutput { line_width /= clip.w; // get height of near clipping plane in world space - let pos0 = view.inverse_projection * vec4(0, -1, 0, 1); // Bottom of the screen - let pos1 = view.inverse_projection * vec4(0, 1, 0, 1); // Top of the screen + let pos0 = view.view_from_clip * vec4(0, -1, 0, 1); // Bottom of the screen + let pos1 = view.view_from_clip * vec4(0, 1, 0, 1); // Top of the screen let near_clipping_plane_height = length(pos0.xyz - pos1.xyz); // We can't use vertex.position_X because we may have changed the clip positions with clip_near_plane - let position_a = view.inverse_view_proj * clip_a; - let position_b = view.inverse_view_proj * clip_b; + let position_a = view.inverse_clip_from_world * clip_a; + let position_b = view.inverse_clip_from_world * clip_b; let world_distance = length(position_a.xyz - position_b.xyz); // Offset to compensate for moved clip positions. If removed dots on lines will slide when position a is ofscreen. @@ -84,7 +84,7 @@ fn vertex(vertex: VertexInput) -> VertexOutput { uv = (clipped_offset + position.y * world_distance) * resolution.y / near_clipping_plane_height / line_gizmo.line_width; #else // Get the distance of b to the camera along camera axes - let camera_b = view.inverse_projection * clip_b; + let camera_b = view.view_from_clip * clip_b; // This differentiates between orthographic and perspective cameras. // For orthographic cameras no depth adaptment (depth_adaptment = 1) is needed. diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 848a6a0e7dc49..a50a99c6d608c 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -615,7 +615,7 @@ async fn load_gltf<'a, 'b, 'c>( .skins() .map(|gltf_skin| { let reader = gltf_skin.reader(|buffer| Some(&buffer_data[buffer.index()])); - let inverse_bindposes: Vec = reader + let local_to_bone_bind_matrices: Vec = reader .read_inverse_bind_matrices() .unwrap() .map(|mat| Mat4::from_cols_array_2d(&mat)) @@ -623,7 +623,7 @@ async fn load_gltf<'a, 'b, 'c>( load_context.add_labeled_asset( skin_label(&gltf_skin), - SkinnedMeshInverseBindposes::from(inverse_bindposes), + SkinnedMeshInverseBindposes::from(local_to_bone_bind_matrices), ) }) .collect(); diff --git a/crates/bevy_pbr/src/cluster/assign.rs b/crates/bevy_pbr/src/cluster/assign.rs index 95e2bc4bfb291..c6bef3426c9fa 100644 --- a/crates/bevy_pbr/src/cluster/assign.rs +++ b/crates/bevy_pbr/src/cluster/assign.rs @@ -209,20 +209,20 @@ pub(crate) fn assign_lights_to_clusters( let mut requested_cluster_dimensions = config.dimensions_for_screen_size(screen_size); - let view_transform = camera_transform.compute_matrix(); - let view_inv_scale = camera_transform.compute_transform().scale.recip(); - let view_inv_scale_max = view_inv_scale.abs().max_element(); - let inverse_view_transform = view_transform.inverse(); - let is_orthographic = camera.projection_matrix().w_axis.w == 1.0; + let world_from_view = camera_transform.compute_matrix(); + let view_from_world_scale = camera_transform.compute_transform().scale.recip(); + let view_from_world_scale_max = view_from_world_scale.abs().max_element(); + let view_from_world = world_from_view.inverse(); + let is_orthographic = camera.clip_from_view().w_axis.w == 1.0; let far_z = match config.far_z_mode() { ClusterFarZMode::MaxLightRange => { - let inverse_view_row_2 = inverse_view_transform.row(2); + let view_from_world_row_2 = view_from_world.row(2); lights .iter() .map(|light| { - -inverse_view_row_2.dot(light.transform.translation().extend(1.0)) - + light.range * view_inv_scale.z + -view_from_world_row_2.dot(light.transform.translation().extend(1.0)) + + light.range * view_from_world_scale.z }) .reduce(f32::max) .unwrap_or(0.0) @@ -239,12 +239,12 @@ pub(crate) fn assign_lights_to_clusters( // 3,2 = r * far and 2,2 = r where r = 1.0 / (far - near) // rearranging r = 1.0 / (far - near), r * (far - near) = 1.0, r * far - 1.0 = r * near, near = (r * far - 1.0) / r // = (3,2 - 1.0) / 2,2 - (camera.projection_matrix().w_axis.z - 1.0) / camera.projection_matrix().z_axis.z + (camera.clip_from_view().w_axis.z - 1.0) / camera.clip_from_view().z_axis.z } (false, 1) => config.first_slice_depth().max(far_z), _ => config.first_slice_depth(), }; - let first_slice_depth = first_slice_depth * view_inv_scale.z; + let first_slice_depth = first_slice_depth * view_from_world_scale.z; // NOTE: Ensure the far_z is at least as far as the first_depth_slice to avoid clustering problems. let far_z = far_z.max(first_slice_depth); @@ -269,9 +269,9 @@ pub(crate) fn assign_lights_to_clusters( // this overestimates index counts by at most 50% (and typically much less) when the whole light range is in view // it can overestimate more significantly when light ranges are only partially in view let (light_aabb_min, light_aabb_max) = cluster_space_light_aabb( - inverse_view_transform, - view_inv_scale, - camera.projection_matrix(), + view_from_world, + view_from_world_scale, + camera.clip_from_view(), &light_sphere, ); @@ -337,7 +337,7 @@ pub(crate) fn assign_lights_to_clusters( clusters.dimensions.x * clusters.dimensions.y * clusters.dimensions.z <= 4096 ); - let inverse_projection = camera.projection_matrix().inverse(); + let view_from_clip = camera.clip_from_view().inverse(); for lights in &mut clusters.lights { lights.entities.clear(); @@ -364,7 +364,7 @@ pub(crate) fn assign_lights_to_clusters( for x in 0..=clusters.dimensions.x { let x_proportion = x as f32 / x_slices; let x_pos = x_proportion * 2.0 - 1.0; - let view_x = clip_to_view(inverse_projection, Vec4::new(x_pos, 0.0, 1.0, 1.0)).x; + let view_x = clip_to_view(view_from_clip, Vec4::new(x_pos, 0.0, 1.0, 1.0)).x; let normal = Vec3::X; let d = view_x * normal.x; x_planes.push(HalfSpace::new(normal.extend(d))); @@ -374,7 +374,7 @@ pub(crate) fn assign_lights_to_clusters( for y in 0..=clusters.dimensions.y { let y_proportion = 1.0 - y as f32 / y_slices; let y_pos = y_proportion * 2.0 - 1.0; - let view_y = clip_to_view(inverse_projection, Vec4::new(0.0, y_pos, 1.0, 1.0)).y; + let view_y = clip_to_view(view_from_clip, Vec4::new(0.0, y_pos, 1.0, 1.0)).y; let normal = Vec3::Y; let d = view_y * normal.y; y_planes.push(HalfSpace::new(normal.extend(d))); @@ -384,8 +384,8 @@ pub(crate) fn assign_lights_to_clusters( for x in 0..=clusters.dimensions.x { let x_proportion = x as f32 / x_slices; let x_pos = x_proportion * 2.0 - 1.0; - let nb = clip_to_view(inverse_projection, Vec4::new(x_pos, -1.0, 1.0, 1.0)).xyz(); - let nt = clip_to_view(inverse_projection, Vec4::new(x_pos, 1.0, 1.0, 1.0)).xyz(); + let nb = clip_to_view(view_from_clip, Vec4::new(x_pos, -1.0, 1.0, 1.0)).xyz(); + let nt = clip_to_view(view_from_clip, Vec4::new(x_pos, 1.0, 1.0, 1.0)).xyz(); let normal = nb.cross(nt); let d = nb.dot(normal); x_planes.push(HalfSpace::new(normal.extend(d))); @@ -395,8 +395,8 @@ pub(crate) fn assign_lights_to_clusters( for y in 0..=clusters.dimensions.y { let y_proportion = 1.0 - y as f32 / y_slices; let y_pos = y_proportion * 2.0 - 1.0; - let nl = clip_to_view(inverse_projection, Vec4::new(-1.0, y_pos, 1.0, 1.0)).xyz(); - let nr = clip_to_view(inverse_projection, Vec4::new(1.0, y_pos, 1.0, 1.0)).xyz(); + let nl = clip_to_view(view_from_clip, Vec4::new(-1.0, y_pos, 1.0, 1.0)).xyz(); + let nr = clip_to_view(view_from_clip, Vec4::new(1.0, y_pos, 1.0, 1.0)).xyz(); let normal = nr.cross(nl); let d = nr.dot(normal); y_planes.push(HalfSpace::new(normal.extend(d))); @@ -432,9 +432,9 @@ pub(crate) fn assign_lights_to_clusters( // note: caching seems to be slower than calling twice for this aabb calculation let (light_aabb_xy_ndc_z_view_min, light_aabb_xy_ndc_z_view_max) = cluster_space_light_aabb( - inverse_view_transform, - view_inv_scale, - camera.projection_matrix(), + view_from_world, + view_from_world_scale, + camera.clip_from_view(), &light_sphere, ); @@ -463,13 +463,13 @@ pub(crate) fn assign_lights_to_clusters( // as they often assume that the widest part of the sphere under projection is the // center point on the axis of interest plus the radius, and that is not true! let view_light_sphere = Sphere { - center: Vec3A::from(inverse_view_transform * light_sphere.center.extend(1.0)), - radius: light_sphere.radius * view_inv_scale_max, + center: Vec3A::from(view_from_world * light_sphere.center.extend(1.0)), + radius: light_sphere.radius * view_from_world_scale_max, }; let spot_light_dir_sin_cos = light.spot_light_angle.map(|angle| { let (angle_sin, angle_cos) = angle.sin_cos(); ( - (inverse_view_transform * light.transform.back().extend(0.0)) + (view_from_world * light.transform.back().extend(0.0)) .truncate() .normalize(), angle_sin, @@ -477,7 +477,7 @@ pub(crate) fn assign_lights_to_clusters( ) }); let light_center_clip = - camera.projection_matrix() * view_light_sphere.center.extend(1.0); + camera.clip_from_view() * view_light_sphere.center.extend(1.0); let light_center_ndc = light_center_clip.xyz() / light_center_clip.w; let cluster_coordinates = ndc_position_to_cluster( clusters.dimensions, @@ -586,7 +586,7 @@ pub(crate) fn assign_lights_to_clusters( far_z, clusters.tile_size.as_vec2(), screen_size.as_vec2(), - inverse_projection, + view_from_clip, is_orthographic, clusters.dimensions, UVec3::new(x, y, z), @@ -613,7 +613,8 @@ pub(crate) fn assign_lights_to_clusters( distance_closest_point > cluster_aabb_sphere.radius; let front_cull = v1_len - > cluster_aabb_sphere.radius + light.range * view_inv_scale_max; + > cluster_aabb_sphere.radius + + light.range * view_from_world_scale_max; let back_cull = v1_len < -cluster_aabb_sphere.radius; if !angle_cull && !front_cull && !back_cull { @@ -657,7 +658,7 @@ fn compute_aabb_for_cluster( z_far: f32, tile_size: Vec2, screen_size: Vec2, - inverse_projection: Mat4, + view_from_clip: Mat4, is_orthographic: bool, cluster_dimensions: UVec3, ijk: UVec3, @@ -675,8 +676,8 @@ fn compute_aabb_for_cluster( // Convert to view space at the cluster near and far planes // NOTE: 1.0 is the near plane due to using reverse z projections - let mut p_min = screen_to_view(screen_size, inverse_projection, p_min, 0.0).xyz(); - let mut p_max = screen_to_view(screen_size, inverse_projection, p_max, 0.0).xyz(); + let mut p_min = screen_to_view(screen_size, view_from_clip, p_min, 0.0).xyz(); + let mut p_max = screen_to_view(screen_size, view_from_clip, p_max, 0.0).xyz(); // calculate cluster depth using z_near and z_far p_min.z = -z_near + (z_near - z_far) * ijk.z / cluster_dimensions.z as f32; @@ -687,8 +688,8 @@ fn compute_aabb_for_cluster( } else { // Convert to view space at the near plane // NOTE: 1.0 is the near plane due to using reverse z projections - let p_min = screen_to_view(screen_size, inverse_projection, p_min, 1.0); - let p_max = screen_to_view(screen_size, inverse_projection, p_max, 1.0); + let p_min = screen_to_view(screen_size, view_from_clip, p_min, 1.0); + let p_max = screen_to_view(screen_size, view_from_clip, p_max, 1.0); let z_far_over_z_near = -z_far / -z_near; let cluster_near = if ijk.z == 0.0 { @@ -763,14 +764,14 @@ fn ndc_position_to_cluster( /// `X` and `Y` in normalized device coordinates with range `[-1, 1]` /// `Z` in view space, with range `[-inf, -f32::MIN_POSITIVE]` fn cluster_space_light_aabb( - inverse_view_transform: Mat4, - view_inv_scale: Vec3, - projection_matrix: Mat4, + view_from_world: Mat4, + view_from_world_scale: Vec3, + clip_from_view: Mat4, light_sphere: &Sphere, ) -> (Vec3, Vec3) { let light_aabb_view = Aabb { - center: Vec3A::from(inverse_view_transform * light_sphere.center.extend(1.0)), - half_extents: Vec3A::from(light_sphere.radius * view_inv_scale.abs()), + center: Vec3A::from(view_from_world * light_sphere.center.extend(1.0)), + half_extents: Vec3A::from(light_sphere.radius * view_from_world_scale.abs()), }; let (mut light_aabb_view_min, mut light_aabb_view_max) = (light_aabb_view.min(), light_aabb_view.max()); @@ -806,10 +807,10 @@ fn cluster_space_light_aabb( light_aabb_clip_xymax_near, light_aabb_clip_xymax_far, ) = ( - projection_matrix * light_aabb_view_xymin_near.extend(1.0), - projection_matrix * light_aabb_view_xymin_far.extend(1.0), - projection_matrix * light_aabb_view_xymax_near.extend(1.0), - projection_matrix * light_aabb_view_xymax_far.extend(1.0), + clip_from_view * light_aabb_view_xymin_near.extend(1.0), + clip_from_view * light_aabb_view_xymin_far.extend(1.0), + clip_from_view * light_aabb_view_xymax_near.extend(1.0), + clip_from_view * light_aabb_view_xymax_far.extend(1.0), ); let ( light_aabb_ndc_xymin_near, @@ -872,12 +873,12 @@ fn view_z_to_z_slice( z_slice.min(z_slices - 1) } -fn clip_to_view(inverse_projection: Mat4, clip: Vec4) -> Vec4 { - let view = inverse_projection * clip; +fn clip_to_view(view_from_clip: Mat4, clip: Vec4) -> Vec4 { + let view = view_from_clip * clip; view / view.w } -fn screen_to_view(screen_size: Vec2, inverse_projection: Mat4, screen: Vec2, ndc_z: f32) -> Vec4 { +fn screen_to_view(screen_size: Vec2, view_from_clip: Mat4, screen: Vec2, ndc_z: f32) -> Vec4 { let tex_coord = screen / screen_size; let clip = Vec4::new( tex_coord.x * 2.0 - 1.0, @@ -885,7 +886,7 @@ fn screen_to_view(screen_size: Vec2, inverse_projection: Mat4, screen: Vec2, ndc ndc_z, 1.0, ); - clip_to_view(inverse_projection, clip) + clip_to_view(view_from_clip, clip) } // NOTE: This exploits the fact that a x-plane normal has only x and z components diff --git a/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl b/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl index c02e55a24f8ff..f317f15b5ab7b 100644 --- a/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl +++ b/crates/bevy_pbr/src/deferred/pbr_deferred_functions.wgsl @@ -95,7 +95,7 @@ fn pbr_input_from_deferred_gbuffer(frag_coord: vec4, gbuffer: vec4) -> let N = octahedral_decode(octahedral_normal); let world_position = vec4(position_ndc_to_world(frag_coord_to_ndc(frag_coord)), 1.0); - let is_orthographic = view.projection[3].w == 1.0; + let is_orthographic = view.clip_from_view[3].w == 1.0; let V = pbr_functions::calculate_view(world_position, is_orthographic); pbr.frag_coord = frag_coord; diff --git a/crates/bevy_pbr/src/light/mod.rs b/crates/bevy_pbr/src/light/mod.rs index aabae1b443689..2da2ddde1f540 100644 --- a/crates/bevy_pbr/src/light/mod.rs +++ b/crates/bevy_pbr/src/light/mod.rs @@ -277,13 +277,13 @@ pub struct Cascades { #[derive(Clone, Debug, Default, Reflect)] pub struct Cascade { /// The transform of the light, i.e. the view to world matrix. - pub(crate) view_transform: Mat4, + pub(crate) world_from_cascade: Mat4, /// The orthographic projection for this cascade. - pub(crate) projection: Mat4, + pub(crate) clip_from_cascade: Mat4, /// The view-projection matrix for this cascade, converting world space into light clip space. /// Importantly, this is derived and stored separately from `view_transform` and `projection` to /// ensure shadow stability. - pub(crate) view_projection: Mat4, + pub(crate) clip_from_world: Mat4, /// Size of each shadow map texel in world units. pub(crate) texel_size: f32, } @@ -329,8 +329,8 @@ pub fn build_directional_light_cascades( // users to not change any other aspects of the transform - there's no guarantee // `transform.compute_matrix()` will give us a matrix with our desired properties. // Instead, we directly create a good matrix from just the rotation. - let light_to_world = Mat4::from_quat(transform.compute_transform().rotation); - let light_to_world_inverse = light_to_world.inverse(); + let world_from_light = Mat4::from_quat(transform.compute_transform().rotation); + let light_to_world_inverse = world_from_light.inverse(); for (view_entity, projection, view_to_world) in views.iter().copied() { let camera_to_light_view = light_to_world_inverse * view_to_world; @@ -353,7 +353,7 @@ pub fn build_directional_light_cascades( calculate_cascade( corners, directional_light_shadow_map.size as f32, - light_to_world, + world_from_light, camera_to_light_view, ) }) @@ -369,13 +369,13 @@ pub fn build_directional_light_cascades( fn calculate_cascade( frustum_corners: [Vec3A; 8], cascade_texture_size: f32, - light_to_world: Mat4, - camera_to_light: Mat4, + world_from_light: Mat4, + light_from_camera: Mat4, ) -> Cascade { let mut min = Vec3A::splat(f32::MAX); let mut max = Vec3A::splat(f32::MIN); for corner_camera_view in frustum_corners { - let corner_light_view = camera_to_light.transform_point3a(corner_camera_view); + let corner_light_view = light_from_camera.transform_point3a(corner_camera_view); min = min.min(corner_light_view); max = max.max(corner_light_view); } @@ -408,8 +408,8 @@ fn calculate_cascade( // It is critical for `world_to_cascade` to be stable. So rather than forming `cascade_to_world` // and inverting it, which risks instability due to numerical precision, we directly form // `world_to_cascade` as the reference material suggests. - let light_to_world_transpose = light_to_world.transpose(); - let world_to_cascade = Mat4::from_cols( + let light_to_world_transpose = world_from_light.transpose(); + let cascade_from_world = Mat4::from_cols( light_to_world_transpose.x_axis, light_to_world_transpose.y_axis, light_to_world_transpose.z_axis, @@ -419,18 +419,18 @@ fn calculate_cascade( // Right-handed orthographic projection, centered at `near_plane_center`. // NOTE: This is different from the reference material, as we use reverse Z. let r = (max.z - min.z).recip(); - let cascade_projection = Mat4::from_cols( + let clip_from_cascade = Mat4::from_cols( Vec4::new(2.0 / cascade_diameter, 0.0, 0.0, 0.0), Vec4::new(0.0, 2.0 / cascade_diameter, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new(0.0, 0.0, 1.0, 1.0), ); - let cascade_view_projection = cascade_projection * world_to_cascade; + let clip_from_world = clip_from_cascade * cascade_from_world; Cascade { - view_transform: world_to_cascade.inverse(), - projection: cascade_projection, - view_projection: cascade_view_projection, + world_from_cascade: cascade_from_world.inverse(), + clip_from_cascade, + clip_from_world, texel_size: cascade_texel_size, } } @@ -551,7 +551,7 @@ pub fn update_directional_light_frusta( *view, cascades .iter() - .map(|c| Frustum::from_view_projection(&c.view_projection)) + .map(|c| Frustum::from_clip_from_world(&c.clip_from_world)) .collect::>(), ) }) @@ -567,7 +567,7 @@ pub fn update_point_light_frusta( Or<(Changed, Changed)>, >, ) { - let projection = + let clip_from_view = Mat4::perspective_infinite_reverse_rh(std::f32::consts::FRAC_PI_2, 1.0, POINT_LIGHT_NEAR_Z); let view_rotations = CUBE_MAP_FACES .iter() @@ -591,11 +591,11 @@ pub fn update_point_light_frusta( let view_backward = transform.back(); for (view_rotation, frustum) in view_rotations.iter().zip(cubemap_frusta.iter_mut()) { - let view = view_translation * *view_rotation; - let view_projection = projection * view.compute_matrix().inverse(); + let world_from_view = view_translation * *view_rotation; + let clip_from_world = clip_from_view * world_from_view.compute_matrix().inverse(); - *frustum = Frustum::from_view_projection_custom_far( - &view_projection, + *frustum = Frustum::from_clip_from_world_custom_far( + &clip_from_world, &transform.translation(), &view_backward, point_light.range, @@ -625,12 +625,12 @@ pub fn update_spot_light_frusta( // by applying those as a view transform to shadow map rendering of objects let view_backward = transform.back(); - let spot_view = spot_light_view_matrix(transform); - let spot_projection = spot_light_projection_matrix(spot_light.outer_angle); - let view_projection = spot_projection * spot_view.inverse(); + let spot_world_from_view = spot_light_world_from_view(transform); + let spot_clip_from_view = spot_light_clip_from_view(spot_light.outer_angle); + let clip_from_world = spot_clip_from_view * spot_world_from_view.inverse(); - *frustum = Frustum::from_view_projection_custom_far( - &view_projection, + *frustum = Frustum::from_clip_from_world_custom_far( + &clip_from_world, &transform.translation(), &view_backward, spot_light.range, diff --git a/crates/bevy_pbr/src/light_probe/irradiance_volume.wgsl b/crates/bevy_pbr/src/light_probe/irradiance_volume.wgsl index 18a738689c85f..01b2741c2ab53 100644 --- a/crates/bevy_pbr/src/light_probe/irradiance_volume.wgsl +++ b/crates/bevy_pbr/src/light_probe/irradiance_volume.wgsl @@ -32,7 +32,7 @@ fn irradiance_volume_light(world_position: vec3, N: vec3) -> vec3 let resolution = vec3(textureDimensions(irradiance_volume_texture) / vec3(1u, 2u, 3u)); // Make sure to clamp to the edges to avoid texture bleed. - var unit_pos = (query_result.inverse_transform * vec4(world_position, 1.0f)).xyz; + var unit_pos = (query_result.light_from_world * vec4(world_position, 1.0f)).xyz; let stp = clamp((unit_pos + 0.5) * resolution, vec3(0.5f), resolution - vec3(0.5f)); let uvw = stp / atlas_resolution; diff --git a/crates/bevy_pbr/src/light_probe/light_probe.wgsl b/crates/bevy_pbr/src/light_probe/light_probe.wgsl index ab5a8c91c8ed3..e1ab71070805f 100644 --- a/crates/bevy_pbr/src/light_probe/light_probe.wgsl +++ b/crates/bevy_pbr/src/light_probe/light_probe.wgsl @@ -13,7 +13,7 @@ struct LightProbeQueryResult { intensity: f32, // Transform from world space to the light probe model space. In light probe // model space, the light probe is a 1×1×1 cube centered on the origin. - inverse_transform: mat4x4, + light_from_world: mat4x4, }; fn transpose_affine_matrix(matrix: mat3x4) -> mat4x4 { @@ -53,16 +53,16 @@ fn query_light_probe( } // Unpack the inverse transform. - let inverse_transform = - transpose_affine_matrix(light_probe.inverse_transpose_transform); + let light_from_world = + transpose_affine_matrix(light_probe.light_from_world_transposed); // Check to see if the transformed point is inside the unit cube // centered at the origin. - let probe_space_pos = (inverse_transform * vec4(world_position, 1.0f)).xyz; + let probe_space_pos = (light_from_world * vec4(world_position, 1.0f)).xyz; if (all(abs(probe_space_pos) <= vec3(0.5f))) { result.texture_index = light_probe.cubemap_index; result.intensity = light_probe.intensity; - result.inverse_transform = inverse_transform; + result.light_from_world = light_from_world; // TODO: Workaround for ICE in DXC https://github.com/microsoft/DirectXShaderCompiler/issues/6183 // We can't use `break` here because of the ICE. diff --git a/crates/bevy_pbr/src/light_probe/mod.rs b/crates/bevy_pbr/src/light_probe/mod.rs index 964ffbc7c2a46..97607d34a74ab 100644 --- a/crates/bevy_pbr/src/light_probe/mod.rs +++ b/crates/bevy_pbr/src/light_probe/mod.rs @@ -111,7 +111,7 @@ pub struct LightProbe; struct RenderLightProbe { /// The transform from the world space to the model space. This is used to /// efficiently check for bounding box intersection. - inverse_transpose_transform: [Vec4; 3], + light_from_world_transposed: [Vec4; 3], /// The index of the texture or textures in the appropriate binding array or /// arrays. @@ -179,10 +179,10 @@ where C: LightProbeComponent, { // The transform from world space to light probe space. - inverse_transform: Mat4, + light_from_world: Mat4, // The transform from light probe space to world space. - affine_transform: Affine3A, + world_from_light: Affine3A, // Scale factor applied to the diffuse and specular light generated by this // reflection probe. @@ -508,8 +508,8 @@ where image_assets: &RenderAssets, ) -> Option> { environment_map.id(image_assets).map(|id| LightProbeInfo { - affine_transform: light_probe_transform.affine(), - inverse_transform: light_probe_transform.compute_matrix().inverse(), + world_from_light: light_probe_transform.affine(), + light_from_world: light_probe_transform.compute_matrix().inverse(), asset_id: id, intensity: environment_map.intensity(), }) @@ -523,7 +523,7 @@ where center: Vec3A::default(), half_extents: Vec3A::splat(0.5), }, - &self.affine_transform, + &self.world_from_light, true, false, ) @@ -533,7 +533,7 @@ where /// suitable for distance sorting. fn camera_distance_sort_key(&self, view_transform: &GlobalTransform) -> FloatOrd { FloatOrd( - (self.affine_transform.translation - view_transform.translation_vec3a()) + (self.world_from_light.translation - view_transform.translation_vec3a()) .length_squared(), ) } @@ -598,14 +598,14 @@ where // Transpose the inverse transform to compress the structure on the // GPU (from 4 `Vec4`s to 3 `Vec4`s). The shader will transpose it // to recover the original inverse transform. - let inverse_transpose_transform = light_probe.inverse_transform.transpose(); + let light_from_world_transposed = light_probe.light_from_world.transpose(); // Write in the light probe data. self.render_light_probes.push(RenderLightProbe { - inverse_transpose_transform: [ - inverse_transpose_transform.x_axis, - inverse_transpose_transform.y_axis, - inverse_transpose_transform.z_axis, + light_from_world_transposed: [ + light_from_world_transposed.x_axis, + light_from_world_transposed.y_axis, + light_from_world_transposed.z_axis, ], texture_index: cubemap_index as i32, intensity: light_probe.intensity, @@ -620,8 +620,8 @@ where { fn clone(&self) -> Self { Self { - inverse_transform: self.inverse_transform, - affine_transform: self.affine_transform, + light_from_world: self.light_from_world, + world_from_light: self.world_from_light, intensity: self.intensity, asset_id: self.asset_id.clone(), } diff --git a/crates/bevy_pbr/src/meshlet/cull_meshlets.wgsl b/crates/bevy_pbr/src/meshlet/cull_meshlets.wgsl index abfd9aed55db1..e25532b31938f 100644 --- a/crates/bevy_pbr/src/meshlet/cull_meshlets.wgsl +++ b/crates/bevy_pbr/src/meshlet/cull_meshlets.wgsl @@ -44,11 +44,11 @@ fn cull_meshlets( // Calculate world-space culling bounding sphere for the cluster let instance_uniform = meshlet_instance_uniforms[instance_id]; let meshlet_id = meshlet_cluster_meshlet_ids[cluster_id]; - let model = affine3_to_square(instance_uniform.model); - let model_scale = max(length(model[0]), max(length(model[1]), length(model[2]))); + let world_from_local = affine3_to_square(instance_uniform.world_from_local); + let world_scale = max(length(world_from_local[0]), max(length(world_from_local[1]), length(world_from_local[2]))); let bounding_spheres = meshlet_bounding_spheres[meshlet_id]; - var culling_bounding_sphere_center = model * vec4(bounding_spheres.self_culling.center, 1.0); - var culling_bounding_sphere_radius = model_scale * bounding_spheres.self_culling.radius; + var culling_bounding_sphere_center = world_from_local * vec4(bounding_spheres.self_culling.center, 1.0); + var culling_bounding_sphere_radius = world_scale * bounding_spheres.self_culling.radius; #ifdef MESHLET_FIRST_CULLING_PASS // Frustum culling @@ -60,14 +60,14 @@ fn cull_meshlets( } // Calculate view-space LOD bounding sphere for the meshlet - let lod_bounding_sphere_center = model * vec4(bounding_spheres.self_lod.center, 1.0); - let lod_bounding_sphere_radius = model_scale * bounding_spheres.self_lod.radius; - let lod_bounding_sphere_center_view_space = (view.inverse_view * vec4(lod_bounding_sphere_center.xyz, 1.0)).xyz; + let lod_bounding_sphere_center = world_from_local * vec4(bounding_spheres.self_lod.center, 1.0); + let lod_bounding_sphere_radius = world_scale * bounding_spheres.self_lod.radius; + let lod_bounding_sphere_center_view_space = (view.view_from_world * vec4(lod_bounding_sphere_center.xyz, 1.0)).xyz; // Calculate view-space LOD bounding sphere for the meshlet's parent - let parent_lod_bounding_sphere_center = model * vec4(bounding_spheres.parent_lod.center, 1.0); - let parent_lod_bounding_sphere_radius = model_scale * bounding_spheres.parent_lod.radius; - let parent_lod_bounding_sphere_center_view_space = (view.inverse_view * vec4(parent_lod_bounding_sphere_center.xyz, 1.0)).xyz; + let parent_lod_bounding_sphere_center = world_from_local * vec4(bounding_spheres.parent_lod.center, 1.0); + let parent_lod_bounding_sphere_radius = world_scale * bounding_spheres.parent_lod.radius; + let parent_lod_bounding_sphere_center_view_space = (view.view_from_world * vec4(parent_lod_bounding_sphere_center.xyz, 1.0)).xyz; // Check LOD cut (meshlet error imperceptible, and parent error not imperceptible) let lod_is_ok = lod_error_is_imperceptible(lod_bounding_sphere_center_view_space, lod_bounding_sphere_radius); @@ -77,12 +77,12 @@ fn cull_meshlets( // Project the culling bounding sphere to view-space for occlusion culling #ifdef MESHLET_FIRST_CULLING_PASS - let previous_model = affine3_to_square(instance_uniform.previous_model); - let previous_model_scale = max(length(previous_model[0]), max(length(previous_model[1]), length(previous_model[2]))); - culling_bounding_sphere_center = previous_model * vec4(bounding_spheres.self_culling.center, 1.0); - culling_bounding_sphere_radius = previous_model_scale * bounding_spheres.self_culling.radius; + let previous_world_from_local = affine3_to_square(instance_uniform.previous_world_from_local); + let previous_world_from_local_scale = max(length(previous_world_from_local[0]), max(length(previous_world_from_local[1]), length(previous_world_from_local[2]))); + culling_bounding_sphere_center = previous_world_from_local * vec4(bounding_spheres.self_culling.center, 1.0); + culling_bounding_sphere_radius = previous_world_from_local_scale * bounding_spheres.self_culling.radius; #endif - let culling_bounding_sphere_center_view_space = (view.inverse_view * vec4(culling_bounding_sphere_center.xyz, 1.0)).xyz; + let culling_bounding_sphere_center_view_space = (view.view_from_world * vec4(culling_bounding_sphere_center.xyz, 1.0)).xyz; let aabb = project_view_space_sphere_to_screen_space_aabb(culling_bounding_sphere_center_view_space, culling_bounding_sphere_radius); // Halve the view-space AABB size as the depth pyramid is half the view size @@ -101,13 +101,13 @@ fn cull_meshlets( // Check whether or not the cluster would be occluded if drawn var meshlet_visible: bool; - if view.projection[3][3] == 1.0 { + if view.clip_from_view[3][3] == 1.0 { // Orthographic - let sphere_depth = view.projection[3][2] + (culling_bounding_sphere_center_view_space.z + culling_bounding_sphere_radius) * view.projection[2][2]; + let sphere_depth = view.clip_from_view[3][2] + (culling_bounding_sphere_center_view_space.z + culling_bounding_sphere_radius) * view.clip_from_view[2][2]; meshlet_visible = sphere_depth >= occluder_depth; } else { // Perspective - let sphere_depth = -view.projection[3][2] / (culling_bounding_sphere_center_view_space.z + culling_bounding_sphere_radius); + let sphere_depth = -view.clip_from_view[3][2] / (culling_bounding_sphere_center_view_space.z + culling_bounding_sphere_radius); meshlet_visible = sphere_depth >= occluder_depth; } @@ -132,7 +132,7 @@ fn cull_meshlets( fn lod_error_is_imperceptible(cp: vec3, r: f32) -> bool { let d2 = dot(cp, cp); let r2 = r * r; - let sphere_diameter_uv = view.projection[0][0] * r / sqrt(d2 - r2); + let sphere_diameter_uv = view.clip_from_view[0][0] * r / sqrt(d2 - r2); let view_size = f32(max(view.viewport.z, view.viewport.w)); let sphere_diameter_pixels = sphere_diameter_uv * view_size; return sphere_diameter_pixels < 1.0; @@ -140,9 +140,9 @@ fn lod_error_is_imperceptible(cp: vec3, r: f32) -> bool { // https://zeux.io/2023/01/12/approximate-projected-bounds fn project_view_space_sphere_to_screen_space_aabb(cp: vec3, r: f32) -> vec4 { - let inv_width = view.projection[0][0] * 0.5; - let inv_height = view.projection[1][1] * 0.5; - if view.projection[3][3] == 1.0 { + let inv_width = view.clip_from_view[0][0] * 0.5; + let inv_height = view.clip_from_view[1][1] * 0.5; + if view.clip_from_view[3][3] == 1.0 { // Orthographic let min_x = cp.x - r; let max_x = cp.x + r; diff --git a/crates/bevy_pbr/src/meshlet/gpu_scene.rs b/crates/bevy_pbr/src/meshlet/gpu_scene.rs index acb76196e5f11..f13b44808d9af 100644 --- a/crates/bevy_pbr/src/meshlet/gpu_scene.rs +++ b/crates/bevy_pbr/src/meshlet/gpu_scene.rs @@ -131,8 +131,8 @@ pub fn extract_meshlet_meshes( flags |= MeshFlags::SIGN_DETERMINANT_MODEL_3X3; } let transforms = MeshTransforms { - transform: (&transform).into(), - previous_transform: (&previous_transform).into(), + world_from_local: (&transform).into(), + previous_world_from_local: (&previous_transform).into(), flags: flags.bits(), }; gpu_scene diff --git a/crates/bevy_pbr/src/meshlet/visibility_buffer_raster.wgsl b/crates/bevy_pbr/src/meshlet/visibility_buffer_raster.wgsl index b72079b7f1065..86b34cd2f0f22 100644 --- a/crates/bevy_pbr/src/meshlet/visibility_buffer_raster.wgsl +++ b/crates/bevy_pbr/src/meshlet/visibility_buffer_raster.wgsl @@ -50,9 +50,9 @@ fn vertex(@builtin(vertex_index) vertex_index: u32) -> VertexOutput { let instance_id = meshlet_cluster_instance_ids[cluster_id]; let instance_uniform = meshlet_instance_uniforms[instance_id]; - let model = affine3_to_square(instance_uniform.model); - let world_position = mesh_position_local_to_world(model, vec4(vertex.position, 1.0)); - var clip_position = view.view_proj * vec4(world_position.xyz, 1.0); + let world_from_local = affine3_to_square(instance_uniform.world_from_local); + let world_position = mesh_position_local_to_world(world_from_local, vec4(vertex.position, 1.0)); + var clip_position = view.clip_from_world * vec4(world_position.xyz, 1.0); #ifdef DEPTH_CLAMP_ORTHO let unclamped_clip_depth = clip_position.z; clip_position.z = min(clip_position.z, 1.0); diff --git a/crates/bevy_pbr/src/meshlet/visibility_buffer_resolve.wgsl b/crates/bevy_pbr/src/meshlet/visibility_buffer_resolve.wgsl index 7f8e50573e109..0a6ca684bfa8f 100644 --- a/crates/bevy_pbr/src/meshlet/visibility_buffer_resolve.wgsl +++ b/crates/bevy_pbr/src/meshlet/visibility_buffer_resolve.wgsl @@ -109,11 +109,11 @@ fn resolve_vertex_output(frag_coord: vec4) -> VertexOutput { let instance_id = meshlet_cluster_instance_ids[cluster_id]; let instance_uniform = meshlet_instance_uniforms[instance_id]; - let model = affine3_to_square(instance_uniform.model); + let world_from_local = affine3_to_square(instance_uniform.world_from_local); - let world_position_1 = mesh_position_local_to_world(model, vec4(vertex_1.position, 1.0)); - let world_position_2 = mesh_position_local_to_world(model, vec4(vertex_2.position, 1.0)); - let world_position_3 = mesh_position_local_to_world(model, vec4(vertex_3.position, 1.0)); + let world_position_1 = mesh_position_local_to_world(world_from_local, vec4(vertex_1.position, 1.0)); + let world_position_2 = mesh_position_local_to_world(world_from_local, vec4(vertex_2.position, 1.0)); + let world_position_3 = mesh_position_local_to_world(world_from_local, vec4(vertex_3.position, 1.0)); let clip_position_1 = position_world_to_clip(world_position_1.xyz); let clip_position_2 = position_world_to_clip(world_position_2.xyz); @@ -129,8 +129,8 @@ fn resolve_vertex_output(frag_coord: vec4) -> VertexOutput { let vertex_normal = mat3x3(vertex_1.normal, vertex_2.normal, vertex_3.normal) * partial_derivatives.barycentrics; let world_normal = normalize( mat2x4_f32_to_mat3x3_unpack( - instance_uniform.inverse_transpose_model_a, - instance_uniform.inverse_transpose_model_b, + instance_uniform.local_from_world_transpose_a, + instance_uniform.local_from_world_transpose_b, ) * vertex_normal ); let uv = mat3x2(vertex_1.uv, vertex_2.uv, vertex_3.uv) * partial_derivatives.barycentrics; @@ -140,9 +140,9 @@ fn resolve_vertex_output(frag_coord: vec4) -> VertexOutput { let world_tangent = vec4( normalize( mat3x3( - model[0].xyz, - model[1].xyz, - model[2].xyz + world_from_local[0].xyz, + world_from_local[1].xyz, + world_from_local[2].xyz ) * vertex_tangent.xyz ), vertex_tangent.w * (f32(bool(instance_uniform.flags & MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT)) * 2.0 - 1.0) @@ -150,13 +150,13 @@ fn resolve_vertex_output(frag_coord: vec4) -> VertexOutput { #ifdef PREPASS_FRAGMENT #ifdef MOTION_VECTOR_PREPASS - let previous_model = affine3_to_square(instance_uniform.previous_model); - let previous_world_position_1 = mesh_position_local_to_world(previous_model, vec4(vertex_1.position, 1.0)); - let previous_world_position_2 = mesh_position_local_to_world(previous_model, vec4(vertex_2.position, 1.0)); - let previous_world_position_3 = mesh_position_local_to_world(previous_model, vec4(vertex_3.position, 1.0)); - let previous_clip_position_1 = previous_view_uniforms.view_proj * vec4(previous_world_position_1.xyz, 1.0); - let previous_clip_position_2 = previous_view_uniforms.view_proj * vec4(previous_world_position_2.xyz, 1.0); - let previous_clip_position_3 = previous_view_uniforms.view_proj * vec4(previous_world_position_3.xyz, 1.0); + let previous_world_from_local = affine3_to_square(instance_uniform.previous_world_from_local); + let previous_world_position_1 = mesh_position_local_to_world(previous_world_from_local, vec4(vertex_1.position, 1.0)); + let previous_world_position_2 = mesh_position_local_to_world(previous_world_from_local, vec4(vertex_2.position, 1.0)); + let previous_world_position_3 = mesh_position_local_to_world(previous_world_from_local, vec4(vertex_3.position, 1.0)); + let previous_clip_position_1 = previous_view_uniforms.clip_from_world * vec4(previous_world_position_1.xyz, 1.0); + let previous_clip_position_2 = previous_view_uniforms.clip_from_world * vec4(previous_world_position_2.xyz, 1.0); + let previous_clip_position_3 = previous_view_uniforms.clip_from_world * vec4(previous_world_position_3.xyz, 1.0); let previous_partial_derivatives = compute_partial_derivatives( array(previous_clip_position_1, previous_clip_position_2, previous_clip_position_3), frag_coord_ndc, diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index ce7c3087e4983..56ee5a86efa22 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -204,10 +204,10 @@ pub fn update_previous_view_data( query: Query<(Entity, &Camera, &GlobalTransform), PreviousViewFilter>, ) { for (entity, camera, camera_transform) in &query { - let inverse_view = camera_transform.compute_matrix().inverse(); + let view_from_world = camera_transform.compute_matrix().inverse(); commands.entity(entity).try_insert(PreviousViewData { - inverse_view, - view_proj: camera.projection_matrix() * inverse_view, + view_from_world, + clip_from_world: camera.clip_from_view() * view_from_world, }); } } @@ -608,19 +608,19 @@ pub fn prepare_previous_view_uniforms( }; for (entity, camera, maybe_previous_view_uniforms) in views_iter { - let view_projection = match maybe_previous_view_uniforms { + let prev_view_data = match maybe_previous_view_uniforms { Some(previous_view) => previous_view.clone(), None => { - let inverse_view = camera.transform.compute_matrix().inverse(); + let view_from_world = camera.world_from_view.compute_matrix().inverse(); PreviousViewData { - inverse_view, - view_proj: camera.projection * inverse_view, + view_from_world, + clip_from_world: camera.clip_from_view * view_from_world, } } }; commands.entity(entity).insert(PreviousViewUniformOffset { - offset: writer.write(&view_projection), + offset: writer.write(&prev_view_data), }); } } diff --git a/crates/bevy_pbr/src/prepass/prepass.wgsl b/crates/bevy_pbr/src/prepass/prepass.wgsl index 3084601f534a4..cb1328fae1ebf 100644 --- a/crates/bevy_pbr/src/prepass/prepass.wgsl +++ b/crates/bevy_pbr/src/prepass/prepass.wgsl @@ -63,14 +63,14 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput { #endif #ifdef SKINNED - var model = skinning::skin_model(vertex.joint_indices, vertex.joint_weights); + var world_from_local = skinning::skin_model(vertex.joint_indices, vertex.joint_weights); #else // SKINNED // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug. // See https://github.com/gfx-rs/naga/issues/2416 - var model = mesh_functions::get_model_matrix(vertex_no_morph.instance_index); + var world_from_local = mesh_functions::get_world_from_local(vertex_no_morph.instance_index); #endif // SKINNED - out.world_position = mesh_functions::mesh_position_local_to_world(model, vec4(vertex.position, 1.0)); + out.world_position = mesh_functions::mesh_position_local_to_world(world_from_local, vec4(vertex.position, 1.0)); out.position = position_world_to_clip(out.world_position.xyz); #ifdef DEPTH_CLAMP_ORTHO out.clip_position_unclamped = out.position; @@ -87,7 +87,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput { #ifdef NORMAL_PREPASS_OR_DEFERRED_PREPASS #ifdef SKINNED - out.world_normal = skinning::skin_normals(model, vertex.normal); + out.world_normal = skinning::skin_normals(world_from_local, vertex.normal); #else // SKINNED out.world_normal = mesh_functions::mesh_normal_local_to_world( vertex.normal, @@ -99,7 +99,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput { #ifdef VERTEX_TANGENTS out.world_tangent = mesh_functions::mesh_tangent_local_to_world( - model, + world_from_local, vertex.tangent, // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug. // See https://github.com/gfx-rs/naga/issues/2416 @@ -138,11 +138,11 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput { prev_vertex.joint_weights, ); #else // HAS_PREVIOUS_SKIN - let prev_model = mesh_functions::get_previous_model_matrix(prev_vertex.instance_index); + let prev_model = mesh_functions::get_previous_world_from_local(prev_vertex.instance_index); #endif // HAS_PREVIOUS_SKIN #else // SKINNED - let prev_model = mesh_functions::get_previous_model_matrix(prev_vertex.instance_index); + let prev_model = mesh_functions::get_previous_world_from_local(prev_vertex.instance_index); #endif // SKINNED out.previous_world_position = mesh_functions::mesh_position_local_to_world( @@ -174,9 +174,9 @@ fn fragment(in: VertexOutput) -> FragmentOutput { #endif // DEPTH_CLAMP_ORTHO #ifdef MOTION_VECTOR_PREPASS - let clip_position_t = view.unjittered_view_proj * in.world_position; + let clip_position_t = view.unjittered_clip_from_world * in.world_position; let clip_position = clip_position_t.xy / clip_position_t.w; - let previous_clip_position_t = prepass_bindings::previous_view_uniforms.view_proj * in.previous_world_position; + let previous_clip_position_t = prepass_bindings::previous_view_uniforms.clip_from_world * in.previous_world_position; let previous_clip_position = previous_clip_position_t.xy / previous_clip_position_t.w; // These motion vectors are used as offsets to UV positions and are stored // in the range -1,1 to allow offsetting from the one corner to the diff --git a/crates/bevy_pbr/src/prepass/prepass_bindings.wgsl b/crates/bevy_pbr/src/prepass/prepass_bindings.wgsl index fdc38a4c49654..a8dae83b8e57a 100644 --- a/crates/bevy_pbr/src/prepass/prepass_bindings.wgsl +++ b/crates/bevy_pbr/src/prepass/prepass_bindings.wgsl @@ -1,8 +1,8 @@ #define_import_path bevy_pbr::prepass_bindings struct PreviousViewUniforms { - inverse_view: mat4x4, - view_proj: mat4x4, + view_from_world: mat4x4, + clip_from_world: mat4x4, } #ifdef MOTION_VECTOR_PREPASS diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 56107f81178cb..88ccb462d3b13 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -68,7 +68,7 @@ bitflags::bitflags! { #[derive(Copy, Clone, ShaderType, Default, Debug)] pub struct GpuDirectionalCascade { - view_projection: Mat4, + clip_from_world: Mat4, texel_size: f32, far_bound: f32, } @@ -479,7 +479,7 @@ pub fn calculate_cluster_factors( // we will also construct it in the fragment shader and need our implementations to match, // so we reproduce it here to avoid a mismatch if glam changes. we also switch the handedness // could move this onto transform but it's pretty niche -pub(crate) fn spot_light_view_matrix(transform: &GlobalTransform) -> Mat4 { +pub(crate) fn spot_light_world_from_view(transform: &GlobalTransform) -> Mat4 { // the matrix z_local (opposite of transform.forward()) let fwd_dir = transform.back().extend(0.0); @@ -502,7 +502,7 @@ pub(crate) fn spot_light_view_matrix(transform: &GlobalTransform) -> Mat4 { ) } -pub(crate) fn spot_light_projection_matrix(angle: f32) -> Mat4 { +pub(crate) fn spot_light_clip_from_view(angle: f32) -> Mat4 { // spot light projection FOV is 2x the angle from spot light center to outer edge Mat4::perspective_infinite_reverse_rh(angle * 2.0, 1.0, POINT_LIGHT_NEAR_Z) } @@ -828,7 +828,7 @@ pub fn prepare_lights( ); let mut view_lights = Vec::new(); - let is_orthographic = extracted_view.projection.w_axis.w == 1.0; + let is_orthographic = extracted_view.clip_from_view.w_axis.w == 1.0; let cluster_factors_zw = calculate_cluster_factors( clusters.near, clusters.far, @@ -909,9 +909,9 @@ pub fn prepare_lights( point_light_shadow_map.size as u32, point_light_shadow_map.size as u32, ), - transform: view_translation * *view_rotation, - view_projection: None, - projection: cube_face_projection, + world_from_view: view_translation * *view_rotation, + clip_from_world: None, + clip_from_view: cube_face_projection, hdr: false, color_grading: Default::default(), }, @@ -936,12 +936,12 @@ pub fn prepare_lights( .take(spot_light_shadow_maps_count) .enumerate() { - let spot_view_matrix = spot_light_view_matrix(&light.transform); - let spot_view_transform = spot_view_matrix.into(); + let spot_world_from_view = spot_light_world_from_view(&light.transform); + let spot_world_from_view = spot_world_from_view.into(); let angle = light.spot_light_angles.expect("lights should be sorted so that \ [point_light_count..point_light_count + spot_light_shadow_maps_count] are spot lights").1; - let spot_projection = spot_light_projection_matrix(angle); + let spot_projection = spot_light_clip_from_view(angle); let depth_texture_view = directional_light_depth_texture @@ -970,9 +970,9 @@ pub fn prepare_lights( directional_light_shadow_map.size as u32, directional_light_shadow_map.size as u32, ), - transform: spot_view_transform, - projection: spot_projection, - view_projection: None, + world_from_view: spot_world_from_view, + clip_from_view: spot_projection, + clip_from_world: None, hdr: false, color_grading: Default::default(), }, @@ -1027,7 +1027,7 @@ pub fn prepare_lights( { gpu_lights.directional_lights[light_index].cascades[cascade_index] = GpuDirectionalCascade { - view_projection: cascade.view_projection, + clip_from_world: cascade.clip_from_world, texel_size: cascade.texel_size, far_bound: *bound, }; @@ -1066,9 +1066,9 @@ pub fn prepare_lights( directional_light_shadow_map.size as u32, directional_light_shadow_map.size as u32, ), - transform: GlobalTransform::from(cascade.view_transform), - projection: cascade.projection, - view_projection: Some(cascade.view_projection), + world_from_view: GlobalTransform::from(cascade.world_from_cascade), + clip_from_view: cascade.clip_from_cascade, + clip_from_world: Some(cascade.clip_from_world), hdr: false, color_grading: Default::default(), }, diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index ae1d44e4432bd..299b719f7b4b5 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -250,22 +250,22 @@ impl Plugin for MeshRenderPlugin { #[derive(Component)] pub struct MeshTransforms { - pub transform: Affine3, - pub previous_transform: Affine3, + pub world_from_local: Affine3, + pub previous_world_from_local: Affine3, pub flags: u32, } #[derive(ShaderType, Clone)] pub struct MeshUniform { // Affine 4x3 matrices transposed to 3x4 - pub transform: [Vec4; 3], - pub previous_transform: [Vec4; 3], + pub world_from_local: [Vec4; 3], + pub previous_world_from_local: [Vec4; 3], // 3x3 matrix packed in mat2x4 and f32 as: // [0].xyz, [1].x, // [1].yz, [2].xy // [2].z - pub inverse_transpose_model_a: [Vec4; 2], - pub inverse_transpose_model_b: f32, + pub local_from_world_transpose_a: [Vec4; 2], + pub local_from_world_transpose_b: f32, pub flags: u32, // Four 16-bit unsigned normalized UV values packed into a `UVec2`: // @@ -287,7 +287,7 @@ pub struct MeshUniform { #[repr(C)] pub struct MeshInputUniform { /// Affine 4x3 matrix transposed to 3x4. - pub transform: [Vec4; 3], + pub world_from_local: [Vec4; 3], /// Four 16-bit unsigned normalized UV values packed into a `UVec2`: /// /// ```text @@ -334,14 +334,14 @@ pub struct MeshCullingDataBuffer(RawBufferVec); impl MeshUniform { pub fn new(mesh_transforms: &MeshTransforms, maybe_lightmap_uv_rect: Option) -> Self { - let (inverse_transpose_model_a, inverse_transpose_model_b) = - mesh_transforms.transform.inverse_transpose_3x3(); + let (local_from_world_transpose_a, local_from_world_transpose_b) = + mesh_transforms.world_from_local.inverse_transpose_3x3(); Self { - transform: mesh_transforms.transform.to_transpose(), - previous_transform: mesh_transforms.previous_transform.to_transpose(), - lightmap_uv_rect: lightmap::pack_lightmap_uv_rect(maybe_lightmap_uv_rect), - inverse_transpose_model_a, - inverse_transpose_model_b, + world_from_local: mesh_transforms.world_from_local.to_transpose(), + previous_world_from_local: mesh_transforms.previous_world_from_local.to_transpose(), + lightmap_uv_rect: pack_lightmap_uv_rect(maybe_lightmap_uv_rect), + local_from_world_transpose_a, + local_from_world_transpose_b, flags: mesh_transforms.flags, } } @@ -475,7 +475,7 @@ pub struct RenderMeshInstanceGpuBuilder { /// Data that will be placed on the [`RenderMeshInstanceGpu`]. pub shared: RenderMeshInstanceShared, /// The current transform. - pub transform: Affine3, + pub world_from_local: Affine3, /// Four 16-bit unsigned normalized UV values packed into a [`UVec2`]: /// /// ```text @@ -631,7 +631,7 @@ impl RenderMeshInstancesCpu { self.get(&entity) .map(|render_mesh_instance| RenderMeshQueueData { shared: &render_mesh_instance.shared, - translation: render_mesh_instance.transforms.transform.translation, + translation: render_mesh_instance.transforms.world_from_local.translation, }) } @@ -724,7 +724,7 @@ impl RenderMeshInstanceGpuBuilder { ) -> usize { // Push the mesh input uniform. let current_uniform_index = current_input_buffer.push(MeshInputUniform { - transform: self.transform.to_transpose(), + world_from_local: self.world_from_local.to_transpose(), lightmap_uv_rect: self.lightmap_uv_rect, flags: self.mesh_flags.bits(), previous_input_index: match self.previous_input_index { @@ -737,7 +737,7 @@ impl RenderMeshInstanceGpuBuilder { render_mesh_instances.insert( entity, RenderMeshInstanceGpu { - translation: self.transform.translation, + translation: self.world_from_local.translation, shared: self.shared, current_uniform_index: (current_uniform_index as u32) .try_into() @@ -859,13 +859,15 @@ pub fn extract_meshes_for_cpu_building( no_automatic_batching, ); - let transform = transform.affine(); + let world_from_local = transform.affine(); queue.push(( entity, RenderMeshInstanceCpu { transforms: MeshTransforms { - transform: (&transform).into(), - previous_transform: (&previous_transform.map(|t| t.0).unwrap_or(transform)) + world_from_local: (&world_from_local).into(), + previous_world_from_local: (&previous_transform + .map(|t| t.0) + .unwrap_or(world_from_local)) .into(), flags: mesh_flags.bits(), }, @@ -995,7 +997,7 @@ pub fn extract_meshes_for_gpu_building( let gpu_mesh_instance_builder = RenderMeshInstanceGpuBuilder { shared, - transform: (&transform.affine()).into(), + world_from_local: (&transform.affine()).into(), lightmap_uv_rect, mesh_flags, previous_input_index, diff --git a/crates/bevy_pbr/src/render/mesh.wgsl b/crates/bevy_pbr/src/render/mesh.wgsl index dce832304d91f..f4386d97ed27b 100644 --- a/crates/bevy_pbr/src/render/mesh.wgsl +++ b/crates/bevy_pbr/src/render/mesh.wgsl @@ -38,16 +38,16 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput { #endif #ifdef SKINNED - var model = skinning::skin_model(vertex.joint_indices, vertex.joint_weights); + var world_from_local = skinning::skin_model(vertex.joint_indices, vertex.joint_weights); #else // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug. // See https://github.com/gfx-rs/naga/issues/2416 . - var model = mesh_functions::get_model_matrix(vertex_no_morph.instance_index); + var world_from_local = mesh_functions::get_world_from_local(vertex_no_morph.instance_index); #endif #ifdef VERTEX_NORMALS #ifdef SKINNED - out.world_normal = skinning::skin_normals(model, vertex.normal); + out.world_normal = skinning::skin_normals(world_from_local, vertex.normal); #else out.world_normal = mesh_functions::mesh_normal_local_to_world( vertex.normal, @@ -59,7 +59,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput { #endif #ifdef VERTEX_POSITIONS - out.world_position = mesh_functions::mesh_position_local_to_world(model, vec4(vertex.position, 1.0)); + out.world_position = mesh_functions::mesh_position_local_to_world(world_from_local, vec4(vertex.position, 1.0)); out.position = position_world_to_clip(out.world_position.xyz); #endif @@ -72,7 +72,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput { #ifdef VERTEX_TANGENTS out.world_tangent = mesh_functions::mesh_tangent_local_to_world( - model, + world_from_local, vertex.tangent, // Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug. // See https://github.com/gfx-rs/naga/issues/2416 @@ -92,7 +92,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput { #ifdef VISIBILITY_RANGE_DITHER out.visibility_range_dither = mesh_functions::get_visibility_range_dither_level( - vertex_no_morph.instance_index, model[3]); + vertex_no_morph.instance_index, world_from_local[3]); #endif return out; diff --git a/crates/bevy_pbr/src/render/mesh_functions.wgsl b/crates/bevy_pbr/src/render/mesh_functions.wgsl index ce8e9701271a5..2ebc96dd331e1 100644 --- a/crates/bevy_pbr/src/render/mesh_functions.wgsl +++ b/crates/bevy_pbr/src/render/mesh_functions.wgsl @@ -13,23 +13,23 @@ #import bevy_render::maths::{affine3_to_square, mat2x4_f32_to_mat3x3_unpack} -fn get_model_matrix(instance_index: u32) -> mat4x4 { - return affine3_to_square(mesh[instance_index].model); +fn get_world_from_local(instance_index: u32) -> mat4x4 { + return affine3_to_square(mesh[instance_index].world_from_local); } -fn get_previous_model_matrix(instance_index: u32) -> mat4x4 { - return affine3_to_square(mesh[instance_index].previous_model); +fn get_previous_world_from_local(instance_index: u32) -> mat4x4 { + return affine3_to_square(mesh[instance_index].previous_world_from_local); } -fn mesh_position_local_to_world(model: mat4x4, vertex_position: vec4) -> vec4 { - return model * vertex_position; +fn mesh_position_local_to_world(world_from_local: mat4x4, vertex_position: vec4) -> vec4 { + return world_from_local * vertex_position; } // NOTE: The intermediate world_position assignment is important // for precision purposes when using the 'equals' depth comparison // function. -fn mesh_position_local_to_clip(model: mat4x4, vertex_position: vec4) -> vec4 { - let world_position = mesh_position_local_to_world(model, vertex_position); +fn mesh_position_local_to_clip(world_from_local: mat4x4, vertex_position: vec4) -> vec4 { + let world_position = mesh_position_local_to_world(world_from_local, vertex_position); return position_world_to_clip(world_position.xyz); } @@ -44,8 +44,8 @@ fn mesh_normal_local_to_world(vertex_normal: vec3, instance_index: u32) -> if any(vertex_normal != vec3(0.0)) { return normalize( mat2x4_f32_to_mat3x3_unpack( - mesh[instance_index].inverse_transpose_model_a, - mesh[instance_index].inverse_transpose_model_b, + mesh[instance_index].local_from_world_transpose_a, + mesh[instance_index].local_from_world_transpose_b, ) * vertex_normal ); } else { @@ -62,7 +62,7 @@ fn sign_determinant_model_3x3m(instance_index: u32) -> f32 { return f32(bool(mesh[instance_index].flags & MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT)) * 2.0 - 1.0; } -fn mesh_tangent_local_to_world(model: mat4x4, vertex_tangent: vec4, instance_index: u32) -> vec4 { +fn mesh_tangent_local_to_world(world_from_local: mat4x4, vertex_tangent: vec4, instance_index: u32) -> vec4 { // NOTE: The mikktspace method of normal mapping requires that the world tangent is // re-normalized in the vertex shader to match the way mikktspace bakes vertex tangents // and normal maps so that the exact inverse process is applied when shading. Blender, Unity, @@ -74,9 +74,9 @@ fn mesh_tangent_local_to_world(model: mat4x4, vertex_tangent: vec4, in return vec4( normalize( mat3x3( - model[0].xyz, - model[1].xyz, - model[2].xyz + world_from_local[0].xyz, + world_from_local[1].xyz, + world_from_local[2].xyz ) * vertex_tangent.xyz ), // NOTE: Multiplying by the sign of the determinant of the 3x3 model matrix accounts for diff --git a/crates/bevy_pbr/src/render/mesh_preprocess.wgsl b/crates/bevy_pbr/src/render/mesh_preprocess.wgsl index 614c9091a6e2a..02d8042d5f954 100644 --- a/crates/bevy_pbr/src/render/mesh_preprocess.wgsl +++ b/crates/bevy_pbr/src/render/mesh_preprocess.wgsl @@ -14,7 +14,7 @@ // Per-frame data that the CPU supplies to the GPU. struct MeshInput { // The model transform. - model: mat3x4, + world_from_local: mat3x4, // The lightmap UV rect, packed into 64 bits. lightmap_uv_rect: vec2, // Various flags. @@ -92,7 +92,7 @@ struct IndirectParameters { // // `aabb_center.w` should be 1.0. fn view_frustum_intersects_obb( - model: mat4x4, + world_from_local: mat4x4, aabb_center: vec4, aabb_half_extents: vec3, ) -> bool { @@ -103,9 +103,9 @@ fn view_frustum_intersects_obb( let relative_radius = dot( abs( vec3( - dot(plane_normal, model[0]), - dot(plane_normal, model[1]), - dot(plane_normal, model[2]), + dot(plane_normal, world_from_local[0]), + dot(plane_normal, world_from_local[1]), + dot(plane_normal, world_from_local[2]), ) ), aabb_half_extents @@ -135,8 +135,8 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3) { // Unpack. let input_index = work_items[instance_index].input_index; let output_index = work_items[instance_index].output_index; - let model_affine_transpose = current_input[input_index].model; - let model = maths::affine3_to_square(model_affine_transpose); + let world_from_local_affine_transpose = current_input[input_index].world_from_local; + let world_from_local = maths::affine3_to_square(world_from_local_affine_transpose); // Cull if necessary. #ifdef FRUSTUM_CULLING @@ -144,29 +144,29 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3) { let aabb_half_extents = mesh_culling_data[input_index].aabb_half_extents.xyz; // Do an OBB-based frustum cull. - let model_center = model * vec4(aabb_center, 1.0); - if (!view_frustum_intersects_obb(model, model_center, aabb_half_extents)) { + let model_center = world_from_local * vec4(aabb_center, 1.0); + if (!view_frustum_intersects_obb(world_from_local, model_center, aabb_half_extents)) { return; } #endif // Calculate inverse transpose. - let inverse_transpose_model = transpose(maths::inverse_affine3(transpose( - model_affine_transpose))); + let local_from_world_transpose = transpose(maths::inverse_affine3(transpose( + world_from_local_affine_transpose))); // Pack inverse transpose. - let inverse_transpose_model_a = mat2x4( - vec4(inverse_transpose_model[0].xyz, inverse_transpose_model[1].x), - vec4(inverse_transpose_model[1].yz, inverse_transpose_model[2].xy)); - let inverse_transpose_model_b = inverse_transpose_model[2].z; + let local_from_world_transpose_a = mat2x4( + vec4(local_from_world_transpose[0].xyz, local_from_world_transpose[1].x), + vec4(local_from_world_transpose[1].yz, local_from_world_transpose[2].xy)); + let local_from_world_transpose_b = local_from_world_transpose[2].z; // Look up the previous model matrix. let previous_input_index = current_input[input_index].previous_input_index; - var previous_model: mat3x4; + var previous_world_from_local: mat3x4; if (previous_input_index == 0xffffffff) { - previous_model = model_affine_transpose; + previous_world_from_local = world_from_local_affine_transpose; } else { - previous_model = previous_input[previous_input_index].model; + previous_world_from_local = previous_input[previous_input_index].world_from_local; } // Figure out the output index. In indirect mode, this involves bumping the @@ -180,10 +180,10 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3) { #endif // Write the output. - output[mesh_output_index].model = model_affine_transpose; - output[mesh_output_index].previous_model = previous_model; - output[mesh_output_index].inverse_transpose_model_a = inverse_transpose_model_a; - output[mesh_output_index].inverse_transpose_model_b = inverse_transpose_model_b; + output[mesh_output_index].world_from_local = world_from_local_affine_transpose; + output[mesh_output_index].previous_world_from_local = previous_world_from_local; + output[mesh_output_index].local_from_world_transpose_a = local_from_world_transpose_a; + output[mesh_output_index].local_from_world_transpose_b = local_from_world_transpose_b; output[mesh_output_index].flags = current_input[input_index].flags; output[mesh_output_index].lightmap_uv_rect = current_input[input_index].lightmap_uv_rect; } diff --git a/crates/bevy_pbr/src/render/mesh_types.wgsl b/crates/bevy_pbr/src/render/mesh_types.wgsl index 2e1e6aee410fe..7b45bac0ca95c 100644 --- a/crates/bevy_pbr/src/render/mesh_types.wgsl +++ b/crates/bevy_pbr/src/render/mesh_types.wgsl @@ -3,15 +3,15 @@ struct Mesh { // Affine 4x3 matrices transposed to 3x4 // Use bevy_render::maths::affine3_to_square to unpack - model: mat3x4, - previous_model: mat3x4, + world_from_local: mat3x4, + previous_world_from_local: mat3x4, // 3x3 matrix packed in mat2x4 and f32 as: // [0].xyz, [1].x, // [1].yz, [2].xy // [2].z // Use bevy_pbr::mesh_functions::mat2x4_f32_to_mat3x3_unpack to unpack - inverse_transpose_model_a: mat2x4, - inverse_transpose_model_b: f32, + local_from_world_transpose_a: mat2x4, + local_from_world_transpose_b: f32, // 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options. flags: u32, lightmap_uv_rect: vec2, diff --git a/crates/bevy_pbr/src/render/mesh_view_types.wgsl b/crates/bevy_pbr/src/render/mesh_view_types.wgsl index 4f0fb86aed309..e294aa5b5cf66 100644 --- a/crates/bevy_pbr/src/render/mesh_view_types.wgsl +++ b/crates/bevy_pbr/src/render/mesh_view_types.wgsl @@ -17,7 +17,7 @@ const POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT: u32 = 1u; const POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE: u32 = 2u; struct DirectionalCascade { - view_projection: mat4x4, + clip_from_world: mat4x4, texel_size: f32, far_bound: f32, } @@ -115,7 +115,7 @@ struct ClusterOffsetsAndCounts { struct LightProbe { // This is stored as the transpose in order to save space in this structure. // It'll be transposed in the `environment_map_light` function. - inverse_transpose_transform: mat3x4, + light_from_world_transposed: mat3x4, cubemap_index: i32, intensity: f32, }; diff --git a/crates/bevy_pbr/src/render/pbr_fragment.wgsl b/crates/bevy_pbr/src/render/pbr_fragment.wgsl index 52b299f4c9872..9f1a6349b3e41 100644 --- a/crates/bevy_pbr/src/render/pbr_fragment.wgsl +++ b/crates/bevy_pbr/src/render/pbr_fragment.wgsl @@ -40,7 +40,7 @@ fn pbr_input_from_vertex_output( pbr_input.flags = mesh[in.instance_index].flags; #endif - pbr_input.is_orthographic = view.projection[3].w == 1.0; + pbr_input.is_orthographic = view.clip_from_view[3].w == 1.0; pbr_input.V = pbr_functions::calculate_view(in.world_position, pbr_input.is_orthographic); pbr_input.frag_coord = in.position; pbr_input.world_position = in.world_position; @@ -297,7 +297,7 @@ fn pbr_input_from_standard_material( // TODO: Meshlet support #ifndef MESHLET_MESH_MATERIAL_PASS thickness *= length( - (transpose(mesh[in.instance_index].model) * vec4(pbr_input.N, 0.0)).xyz + (transpose(mesh[in.instance_index].world_from_local) * vec4(pbr_input.N, 0.0)).xyz ); #endif pbr_input.material.thickness = thickness; diff --git a/crates/bevy_pbr/src/render/pbr_functions.wgsl b/crates/bevy_pbr/src/render/pbr_functions.wgsl index 90c8c71ec9514..e2cac858c83b3 100644 --- a/crates/bevy_pbr/src/render/pbr_functions.wgsl +++ b/crates/bevy_pbr/src/render/pbr_functions.wgsl @@ -213,7 +213,7 @@ fn calculate_view( var V: vec3; if is_orthographic { // Orthographic view vector - V = normalize(vec3(view_bindings::view.view_proj[0].z, view_bindings::view.view_proj[1].z, view_bindings::view.view_proj[2].z)); + V = normalize(vec3(view_bindings::view.clip_from_world[0].z, view_bindings::view.clip_from_world[1].z, view_bindings::view.clip_from_world[2].z)); } else { // Only valid for a perspective projection V = normalize(view_bindings::view.world_position.xyz - world_position.xyz); @@ -342,10 +342,10 @@ fn apply_pbr_lighting( #endif // STANDARD_MATERIAL_DIFFUSE_TRANSMISSION let view_z = dot(vec4( - view_bindings::view.inverse_view[0].z, - view_bindings::view.inverse_view[1].z, - view_bindings::view.inverse_view[2].z, - view_bindings::view.inverse_view[3].z + view_bindings::view.view_from_world[0].z, + view_bindings::view.view_from_world[1].z, + view_bindings::view.view_from_world[2].z, + view_bindings::view.view_from_world[3].z ), in.world_position); let cluster_index = clustering::fragment_cluster_index(in.frag_coord.xy, view_z, in.is_orthographic); let offset_and_counts = clustering::unpack_offset_and_counts(cluster_index); diff --git a/crates/bevy_pbr/src/render/pbr_prepass_functions.wgsl b/crates/bevy_pbr/src/render/pbr_prepass_functions.wgsl index e267631dddb2c..abdaccbd303f6 100644 --- a/crates/bevy_pbr/src/render/pbr_prepass_functions.wgsl +++ b/crates/bevy_pbr/src/render/pbr_prepass_functions.wgsl @@ -53,9 +53,9 @@ fn prepass_alpha_discard(in: VertexOutput) { #ifdef MOTION_VECTOR_PREPASS fn calculate_motion_vector(world_position: vec4, previous_world_position: vec4) -> vec2 { - let clip_position_t = view.unjittered_view_proj * world_position; + let clip_position_t = view.unjittered_clip_from_world * world_position; let clip_position = clip_position_t.xy / clip_position_t.w; - let previous_clip_position_t = previous_view_uniforms.view_proj * previous_world_position; + let previous_clip_position_t = previous_view_uniforms.clip_from_world * previous_world_position; let previous_clip_position = previous_clip_position_t.xy / previous_clip_position_t.w; // These motion vectors are used as offsets to UV positions and are stored // in the range -1,1 to allow offsetting from the one corner to the diff --git a/crates/bevy_pbr/src/render/pbr_transmission.wgsl b/crates/bevy_pbr/src/render/pbr_transmission.wgsl index 1e4af0ca89c0c..83a71096ebdfe 100644 --- a/crates/bevy_pbr/src/render/pbr_transmission.wgsl +++ b/crates/bevy_pbr/src/render/pbr_transmission.wgsl @@ -30,7 +30,7 @@ fn specular_transmissive_light(world_position: vec4, frag_coord: vec3, let exit_position = world_position.xyz + T * thickness; // Transform exit_position into clip space - let clip_exit_position = view_bindings::view.view_proj * vec4(exit_position, 1.0); + let clip_exit_position = view_bindings::view.clip_from_world * vec4(exit_position, 1.0); // Scale / offset position so that coordinate is in right space for sampling transmissive background texture let offset_position = (clip_exit_position.xy / clip_exit_position.w) * vec2(0.5, -0.5) + 0.5; diff --git a/crates/bevy_pbr/src/render/shadows.wgsl b/crates/bevy_pbr/src/render/shadows.wgsl index 21b25f7f3aebf..c4a470fdf5316 100644 --- a/crates/bevy_pbr/src/render/shadows.wgsl +++ b/crates/bevy_pbr/src/render/shadows.wgsl @@ -125,7 +125,7 @@ fn world_to_directional_light_local( let light = &view_bindings::lights.directional_lights[light_id]; let cascade = &(*light).cascades[cascade_index]; - let offset_position_clip = (*cascade).view_projection * offset_position; + let offset_position_clip = (*cascade).clip_from_world * offset_position; if (offset_position_clip.w <= 0.0) { return vec4(0.0); } diff --git a/crates/bevy_pbr/src/render/skinning.wgsl b/crates/bevy_pbr/src/render/skinning.wgsl index 1ec9ef15ebe03..1ed9393308995 100644 --- a/crates/bevy_pbr/src/render/skinning.wgsl +++ b/crates/bevy_pbr/src/render/skinning.wgsl @@ -51,15 +51,15 @@ fn inverse_transpose_3x3m(in: mat3x3) -> mat3x3 { } fn skin_normals( - model: mat4x4, + world_from_local: mat4x4, normal: vec3, ) -> vec3 { return normalize( inverse_transpose_3x3m( mat3x3( - model[0].xyz, - model[1].xyz, - model[2].xyz + world_from_local[0].xyz, + world_from_local[1].xyz, + world_from_local[2].xyz ) ) * normal ); diff --git a/crates/bevy_pbr/src/render/view_transformations.wgsl b/crates/bevy_pbr/src/render/view_transformations.wgsl index b592fd6add1ed..63ee78a0c0641 100644 --- a/crates/bevy_pbr/src/render/view_transformations.wgsl +++ b/crates/bevy_pbr/src/render/view_transformations.wgsl @@ -31,31 +31,31 @@ /// Convert a view space position to world space fn position_view_to_world(view_pos: vec3) -> vec3 { - let world_pos = view_bindings::view.view * vec4(view_pos, 1.0); + let world_pos = view_bindings::view.world_from_view * vec4(view_pos, 1.0); return world_pos.xyz; } /// Convert a clip space position to world space fn position_clip_to_world(clip_pos: vec4) -> vec3 { - let world_pos = view_bindings::view.inverse_view_proj * clip_pos; + let world_pos = view_bindings::view.world_from_clip * clip_pos; return world_pos.xyz; } /// Convert a ndc space position to world space fn position_ndc_to_world(ndc_pos: vec3) -> vec3 { - let world_pos = view_bindings::view.inverse_view_proj * vec4(ndc_pos, 1.0); + let world_pos = view_bindings::view.world_from_clip * vec4(ndc_pos, 1.0); return world_pos.xyz / world_pos.w; } /// Convert a view space direction to world space fn direction_view_to_world(view_dir: vec3) -> vec3 { - let world_dir = view_bindings::view.view * vec4(view_dir, 0.0); + let world_dir = view_bindings::view.world_from_view * vec4(view_dir, 0.0); return world_dir.xyz; } /// Convert a clip space direction to world space fn direction_clip_to_world(clip_dir: vec4) -> vec3 { - let world_dir = view_bindings::view.inverse_view_proj * clip_dir; + let world_dir = view_bindings::view.world_from_clip * clip_dir; return world_dir.xyz; } @@ -65,31 +65,31 @@ fn direction_clip_to_world(clip_dir: vec4) -> vec3 { /// Convert a world space position to view space fn position_world_to_view(world_pos: vec3) -> vec3 { - let view_pos = view_bindings::view.inverse_view * vec4(world_pos, 1.0); + let view_pos = view_bindings::view.view_from_world * vec4(world_pos, 1.0); return view_pos.xyz; } /// Convert a clip space position to view space fn position_clip_to_view(clip_pos: vec4) -> vec3 { - let view_pos = view_bindings::view.inverse_projection * clip_pos; + let view_pos = view_bindings::view.view_from_clip * clip_pos; return view_pos.xyz; } /// Convert a ndc space position to view space fn position_ndc_to_view(ndc_pos: vec3) -> vec3 { - let view_pos = view_bindings::view.inverse_projection * vec4(ndc_pos, 1.0); + let view_pos = view_bindings::view.view_from_clip * vec4(ndc_pos, 1.0); return view_pos.xyz / view_pos.w; } /// Convert a world space direction to view space fn direction_world_to_view(world_dir: vec3) -> vec3 { - let view_dir = view_bindings::view.inverse_view * vec4(world_dir, 0.0); + let view_dir = view_bindings::view.view_from_world * vec4(world_dir, 0.0); return view_dir.xyz; } /// Convert a clip space direction to view space fn direction_clip_to_view(clip_dir: vec4) -> vec3 { - let view_dir = view_bindings::view.inverse_projection * clip_dir; + let view_dir = view_bindings::view.view_from_clip * clip_dir; return view_dir.xyz; } @@ -99,25 +99,25 @@ fn direction_clip_to_view(clip_dir: vec4) -> vec3 { /// Convert a world space position to clip space fn position_world_to_clip(world_pos: vec3) -> vec4 { - let clip_pos = view_bindings::view.view_proj * vec4(world_pos, 1.0); + let clip_pos = view_bindings::view.clip_from_world * vec4(world_pos, 1.0); return clip_pos; } /// Convert a view space position to clip space fn position_view_to_clip(view_pos: vec3) -> vec4 { - let clip_pos = view_bindings::view.projection * vec4(view_pos, 1.0); + let clip_pos = view_bindings::view.clip_from_view * vec4(view_pos, 1.0); return clip_pos; } /// Convert a world space direction to clip space fn direction_world_to_clip(world_dir: vec3) -> vec4 { - let clip_dir = view_bindings::view.view_proj * vec4(world_dir, 0.0); + let clip_dir = view_bindings::view.clip_from_world * vec4(world_dir, 0.0); return clip_dir; } /// Convert a view space direction to clip space fn direction_view_to_clip(view_dir: vec3) -> vec4 { - let clip_dir = view_bindings::view.projection * vec4(view_dir, 0.0); + let clip_dir = view_bindings::view.clip_from_view * vec4(view_dir, 0.0); return clip_dir; } @@ -127,13 +127,13 @@ fn direction_view_to_clip(view_dir: vec3) -> vec4 { /// Convert a world space position to ndc space fn position_world_to_ndc(world_pos: vec3) -> vec3 { - let ndc_pos = view_bindings::view.view_proj * vec4(world_pos, 1.0); + let ndc_pos = view_bindings::view.clip_from_world * vec4(world_pos, 1.0); return ndc_pos.xyz / ndc_pos.w; } /// Convert a view space position to ndc space fn position_view_to_ndc(view_pos: vec3) -> vec3 { - let ndc_pos = view_bindings::view.projection * vec4(view_pos, 1.0); + let ndc_pos = view_bindings::view.clip_from_view * vec4(view_pos, 1.0); return ndc_pos.xyz / ndc_pos.w; } @@ -143,7 +143,7 @@ fn position_view_to_ndc(view_pos: vec3) -> vec3 { /// Retrieve the perspective camera near clipping plane fn perspective_camera_near() -> f32 { - return view_bindings::view.projection[3][2]; + return view_bindings::view.clip_from_view[3][2]; } /// Convert ndc depth to linear view z. @@ -152,9 +152,9 @@ fn depth_ndc_to_view_z(ndc_depth: f32) -> f32 { #ifdef VIEW_PROJECTION_PERSPECTIVE return -perspective_camera_near() / ndc_depth; #else ifdef VIEW_PROJECTION_ORTHOGRAPHIC - return -(view_bindings::view.projection[3][2] - ndc_depth) / view_bindings::view.projection[2][2]; + return -(view_bindings::view.clip_from_view[3][2] - ndc_depth) / view_bindings::view.clip_from_view[2][2]; #else - let view_pos = view_bindings::view.inverse_projection * vec4(0.0, 0.0, ndc_depth, 1.0); + let view_pos = view_bindings::view.view_from_clip * vec4(0.0, 0.0, ndc_depth, 1.0); return view_pos.z / view_pos.w; #endif } @@ -165,9 +165,9 @@ fn view_z_to_depth_ndc(view_z: f32) -> f32 { #ifdef VIEW_PROJECTION_PERSPECTIVE return -perspective_camera_near() / view_z; #else ifdef VIEW_PROJECTION_ORTHOGRAPHIC - return view_bindings::view.projection[3][2] + view_z * view_bindings::view.projection[2][2]; + return view_bindings::view.clip_from_view[3][2] + view_z * view_bindings::view.clip_from_view[2][2]; #else - let ndc_pos = view_bindings::view.projection * vec4(0.0, 0.0, view_z, 1.0); + let ndc_pos = view_bindings::view.clip_from_view * vec4(0.0, 0.0, view_z, 1.0); return ndc_pos.z / ndc_pos.w; #endif } diff --git a/crates/bevy_pbr/src/ssao/gtao.wgsl b/crates/bevy_pbr/src/ssao/gtao.wgsl index 1fded0b53aa8e..ada9f1d123a6d 100644 --- a/crates/bevy_pbr/src/ssao/gtao.wgsl +++ b/crates/bevy_pbr/src/ssao/gtao.wgsl @@ -65,17 +65,17 @@ fn calculate_neighboring_depth_differences(pixel_coordinates: vec2) -> f32 fn load_normal_view_space(uv: vec2) -> vec3 { var world_normal = textureSampleLevel(normals, point_clamp_sampler, uv, 0.0).xyz; world_normal = (world_normal * 2.0) - 1.0; - let inverse_view = mat3x3( - view.inverse_view[0].xyz, - view.inverse_view[1].xyz, - view.inverse_view[2].xyz, + let view_from_world = mat3x3( + view.view_from_world[0].xyz, + view.view_from_world[1].xyz, + view.view_from_world[2].xyz, ); - return inverse_view * world_normal; + return view_from_world * world_normal; } fn reconstruct_view_space_position(depth: f32, uv: vec2) -> vec3 { let clip_xy = vec2(uv.x * 2.0 - 1.0, 1.0 - 2.0 * uv.y); - let t = view.inverse_projection * vec4(clip_xy, depth, 1.0); + let t = view.view_from_clip * vec4(clip_xy, depth, 1.0); let view_xyz = t.xyz / t.w; return view_xyz; } @@ -107,7 +107,7 @@ fn gtao(@builtin(global_invocation_id) global_id: vec3) { let view_vec = normalize(-pixel_position); let noise = load_noise(pixel_coordinates); - let sample_scale = (-0.5 * effect_radius * view.projection[0][0]) / pixel_position.z; + let sample_scale = (-0.5 * effect_radius * view.clip_from_view[0][0]) / pixel_position.z; var visibility = 0.0; for (var slice_t = 0.0; slice_t < slice_count; slice_t += 1.0) { diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index d0d9a4a6e1cd1..0eafaf46b5436 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -82,7 +82,7 @@ pub struct RenderTargetInfo { /// Holds internally computed [`Camera`] values. #[derive(Default, Debug, Clone)] pub struct ComputedCameraValues { - projection_matrix: Mat4, + clip_from_view: Mat4, target_info: Option, // size of the `Viewport` old_viewport_size: Option, @@ -340,8 +340,8 @@ impl Camera { /// The projection matrix computed using this camera's [`CameraProjection`]. #[inline] - pub fn projection_matrix(&self) -> Mat4 { - self.computed.projection_matrix + pub fn clip_from_view(&self) -> Mat4 { + self.computed.clip_from_view } /// Given a position in world space, use the camera to compute the viewport-space coordinates. @@ -398,7 +398,7 @@ impl Camera { let ndc = viewport_position * 2. / target_size - Vec2::ONE; let ndc_to_world = - camera_transform.compute_matrix() * self.computed.projection_matrix.inverse(); + camera_transform.compute_matrix() * self.computed.clip_from_view.inverse(); let world_near_plane = ndc_to_world.project_point3(ndc.extend(1.)); // Using EPSILON because an ndc with Z = 0 returns NaNs. let world_far_plane = ndc_to_world.project_point3(ndc.extend(f32::EPSILON)); @@ -453,9 +453,9 @@ impl Camera { world_position: Vec3, ) -> Option { // Build a transformation matrix to convert from world space to NDC using camera data - let world_to_ndc: Mat4 = - self.computed.projection_matrix * camera_transform.compute_matrix().inverse(); - let ndc_space_coords: Vec3 = world_to_ndc.project_point3(world_position); + let clip_from_world: Mat4 = + self.computed.clip_from_view * camera_transform.compute_matrix().inverse(); + let ndc_space_coords: Vec3 = clip_from_world.project_point3(world_position); (!ndc_space_coords.is_nan()).then_some(ndc_space_coords) } @@ -473,7 +473,7 @@ impl Camera { pub fn ndc_to_world(&self, camera_transform: &GlobalTransform, ndc: Vec3) -> Option { // Build a transformation matrix to convert from NDC to world space using camera data let ndc_to_world = - camera_transform.compute_matrix() * self.computed.projection_matrix.inverse(); + camera_transform.compute_matrix() * self.computed.clip_from_view.inverse(); let world_space_coords = ndc_to_world.project_point3(ndc); @@ -786,7 +786,7 @@ pub fn camera_system( camera.computed.target_info = new_computed_target_info; if let Some(size) = camera.logical_viewport_size() { camera_projection.update(size.x, size.y); - camera.computed.projection_matrix = camera_projection.get_projection_matrix(); + camera.computed.clip_from_view = camera_projection.get_clip_from_view(); } } } @@ -905,9 +905,9 @@ pub fn extract_cameras( .unwrap_or_else(|| Exposure::default().exposure()), }, ExtractedView { - projection: camera.projection_matrix(), - transform: *transform, - view_projection: None, + clip_from_view: camera.clip_from_view(), + world_from_view: *transform, + clip_from_world: None, hdr: camera.hdr, viewport: UVec4::new( viewport_origin.x, @@ -1021,8 +1021,8 @@ pub struct TemporalJitter { } impl TemporalJitter { - pub fn jitter_projection(&self, projection: &mut Mat4, view_size: Vec2) { - if projection.w_axis.w == 1.0 { + pub fn jitter_projection(&self, clip_from_view: &mut Mat4, view_size: Vec2) { + if clip_from_view.w_axis.w == 1.0 { warn!( "TemporalJitter not supported with OrthographicProjection. Use PerspectiveProjection instead." ); @@ -1032,8 +1032,8 @@ impl TemporalJitter { // https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK/blob/d7531ae47d8b36a5d4025663e731a47a38be882f/docs/techniques/media/super-resolution-temporal/jitter-space.svg let jitter = (self.offset * vec2(2.0, -2.0)) / view_size; - projection.z_axis.x += jitter.x; - projection.z_axis.y += jitter.y; + clip_from_view.z_axis.x += jitter.x; + clip_from_view.z_axis.y += jitter.y; } } diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index 1c1221da299a6..0a6c3ca00afab 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -75,7 +75,7 @@ pub struct CameraUpdateSystem; /// /// [`Camera`]: crate::camera::Camera pub trait CameraProjection { - fn get_projection_matrix(&self) -> Mat4; + fn get_clip_from_view(&self) -> Mat4; fn update(&mut self, width: f32, height: f32); fn far(&self) -> f32; fn get_frustum_corners(&self, z_near: f32, z_far: f32) -> [Vec3A; 8]; @@ -85,10 +85,10 @@ pub trait CameraProjection { /// This code is called by [`update_frusta`](crate::view::visibility::update_frusta) system /// for each camera to update its frustum. fn compute_frustum(&self, camera_transform: &GlobalTransform) -> Frustum { - let view_projection = - self.get_projection_matrix() * camera_transform.compute_matrix().inverse(); - Frustum::from_view_projection_custom_far( - &view_projection, + let clip_from_world = + self.get_clip_from_view() * camera_transform.compute_matrix().inverse(); + Frustum::from_clip_from_world_custom_far( + &clip_from_world, &camera_transform.translation(), &camera_transform.back(), self.far(), @@ -117,10 +117,10 @@ impl From for Projection { } impl CameraProjection for Projection { - fn get_projection_matrix(&self) -> Mat4 { + fn get_clip_from_view(&self) -> Mat4 { match self { - Projection::Perspective(projection) => projection.get_projection_matrix(), - Projection::Orthographic(projection) => projection.get_projection_matrix(), + Projection::Perspective(projection) => projection.get_clip_from_view(), + Projection::Orthographic(projection) => projection.get_clip_from_view(), } } @@ -185,7 +185,7 @@ pub struct PerspectiveProjection { } impl CameraProjection for PerspectiveProjection { - fn get_projection_matrix(&self) -> Mat4 { + fn get_clip_from_view(&self) -> Mat4 { Mat4::perspective_infinite_reverse_rh(self.fov, self.aspect_ratio, self.near) } @@ -391,7 +391,7 @@ pub struct OrthographicProjection { } impl CameraProjection for OrthographicProjection { - fn get_projection_matrix(&self) -> Mat4 { + fn get_clip_from_view(&self) -> Mat4 { Mat4::orthographic_rh( self.area.min.x, self.area.max.x, diff --git a/crates/bevy_render/src/primitives/mod.rs b/crates/bevy_render/src/primitives/mod.rs index 69af837842d97..bc09aefb047d1 100644 --- a/crates/bevy_render/src/primitives/mod.rs +++ b/crates/bevy_render/src/primitives/mod.rs @@ -76,13 +76,13 @@ impl Aabb { /// Calculate the relative radius of the AABB with respect to a plane #[inline] - pub fn relative_radius(&self, p_normal: &Vec3A, model: &Mat3A) -> f32 { + pub fn relative_radius(&self, p_normal: &Vec3A, world_from_local: &Mat3A) -> f32 { // NOTE: dot products on Vec3A use SIMD and even with the overhead of conversion are net faster than Vec3 let half_extents = self.half_extents; Vec3A::new( - p_normal.dot(model.x_axis), - p_normal.dot(model.y_axis), - p_normal.dot(model.z_axis), + p_normal.dot(world_from_local.x_axis), + p_normal.dot(world_from_local.y_axis), + p_normal.dot(world_from_local.z_axis), ) .abs() .dot(half_extents) @@ -117,11 +117,11 @@ pub struct Sphere { impl Sphere { #[inline] - pub fn intersects_obb(&self, aabb: &Aabb, local_to_world: &Affine3A) -> bool { - let aabb_center_world = local_to_world.transform_point3a(aabb.center); + pub fn intersects_obb(&self, aabb: &Aabb, world_from_local: &Affine3A) -> bool { + let aabb_center_world = world_from_local.transform_point3a(aabb.center); let v = aabb_center_world - self.center; let d = v.length(); - let relative_radius = aabb.relative_radius(&(v / d), &local_to_world.matrix3); + let relative_radius = aabb.relative_radius(&(v / d), &world_from_local.matrix3); d < self.radius + relative_radius } } @@ -219,24 +219,24 @@ pub struct Frustum { } impl Frustum { - /// Returns a frustum derived from `view_projection`. + /// Returns a frustum derived from `clip_from_world`. #[inline] - pub fn from_view_projection(view_projection: &Mat4) -> Self { - let mut frustum = Frustum::from_view_projection_no_far(view_projection); - frustum.half_spaces[5] = HalfSpace::new(view_projection.row(2)); + pub fn from_clip_from_world(clip_from_world: &Mat4) -> Self { + let mut frustum = Frustum::from_clip_from_world_no_far(clip_from_world); + frustum.half_spaces[5] = HalfSpace::new(clip_from_world.row(2)); frustum } - /// Returns a frustum derived from `view_projection`, + /// Returns a frustum derived from `clip_from_world`, /// but with a custom far plane. #[inline] - pub fn from_view_projection_custom_far( - view_projection: &Mat4, + pub fn from_clip_from_world_custom_far( + clip_from_world: &Mat4, view_translation: &Vec3, view_backward: &Vec3, far: f32, ) -> Self { - let mut frustum = Frustum::from_view_projection_no_far(view_projection); + let mut frustum = Frustum::from_clip_from_world_no_far(clip_from_world); let far_center = *view_translation - far * *view_backward; frustum.half_spaces[5] = HalfSpace::new(view_backward.extend(-view_backward.dot(far_center))); @@ -248,11 +248,11 @@ impl Frustum { // Rendering by Lengyel. /// Returns a frustum derived from `view_projection`, /// without a far plane. - fn from_view_projection_no_far(view_projection: &Mat4) -> Self { - let row3 = view_projection.row(3); + fn from_clip_from_world_no_far(clip_from_world: &Mat4) -> Self { + let row3 = clip_from_world.row(3); let mut half_spaces = [HalfSpace::default(); 6]; for (i, half_space) in half_spaces.iter_mut().enumerate().take(5) { - let row = view_projection.row(i / 2); + let row = clip_from_world.row(i / 2); *half_space = HalfSpace::new(if (i & 1) == 0 && i != 4 { row3 + row } else { @@ -280,11 +280,11 @@ impl Frustum { pub fn intersects_obb( &self, aabb: &Aabb, - model_to_world: &Affine3A, + world_from_local: &Affine3A, intersect_near: bool, intersect_far: bool, ) -> bool { - let aabb_center_world = model_to_world.transform_point3a(aabb.center).extend(1.0); + let aabb_center_world = world_from_local.transform_point3a(aabb.center).extend(1.0); for (idx, half_space) in self.half_spaces.into_iter().enumerate() { if idx == 4 && !intersect_near { continue; @@ -293,7 +293,7 @@ impl Frustum { continue; } let p_normal = half_space.normal(); - let relative_radius = aabb.relative_radius(&p_normal, &model_to_world.matrix3); + let relative_radius = aabb.relative_radius(&p_normal, &world_from_local.matrix3); if half_space.normal_d().dot(aabb_center_world) + relative_radius <= 0.0 { return false; } diff --git a/crates/bevy_render/src/render_phase/rangefinder.rs b/crates/bevy_render/src/render_phase/rangefinder.rs index 40e75183c8152..4222ee134b02f 100644 --- a/crates/bevy_render/src/render_phase/rangefinder.rs +++ b/crates/bevy_render/src/render_phase/rangefinder.rs @@ -2,16 +2,16 @@ use bevy_math::{Mat4, Vec3, Vec4}; /// A distance calculator for the draw order of [`PhaseItem`](crate::render_phase::PhaseItem)s. pub struct ViewRangefinder3d { - inverse_view_row_2: Vec4, + view_from_world_row_2: Vec4, } impl ViewRangefinder3d { /// Creates a 3D rangefinder for a view matrix. - pub fn from_view_matrix(view_matrix: &Mat4) -> ViewRangefinder3d { - let inverse_view_matrix = view_matrix.inverse(); + pub fn from_world_from_view(world_from_view: &Mat4) -> ViewRangefinder3d { + let view_from_world = world_from_view.inverse(); ViewRangefinder3d { - inverse_view_row_2: inverse_view_matrix.row(2), + view_from_world_row_2: view_from_world.row(2), } } @@ -20,7 +20,7 @@ impl ViewRangefinder3d { pub fn distance_translation(&self, translation: &Vec3) -> f32 { // NOTE: row 2 of the inverse view matrix dotted with the translation from the model matrix // gives the z component of translation of the mesh in view-space - self.inverse_view_row_2.dot(translation.extend(1.0)) + self.view_from_world_row_2.dot(translation.extend(1.0)) } /// Calculates the distance, or view-space `Z` value, for the given `transform`. @@ -28,7 +28,7 @@ impl ViewRangefinder3d { pub fn distance(&self, transform: &Mat4) -> f32 { // NOTE: row 2 of the inverse view matrix dotted with column 3 of the model matrix // gives the z component of translation of the mesh in view-space - self.inverse_view_row_2.dot(transform.col(3)) + self.view_from_world_row_2.dot(transform.col(3)) } } @@ -40,7 +40,7 @@ mod tests { #[test] fn distance() { let view_matrix = Mat4::from_translation(Vec3::new(0.0, 0.0, -1.0)); - let rangefinder = ViewRangefinder3d::from_view_matrix(&view_matrix); + let rangefinder = ViewRangefinder3d::from_world_from_view(&view_matrix); assert_eq!(rangefinder.distance(&Mat4::IDENTITY), 1.0); assert_eq!( rangefinder.distance(&Mat4::from_translation(Vec3::new(0.0, 0.0, 1.0))), diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 0a6dcc5e0020c..91a2767f65671 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -172,12 +172,12 @@ impl Msaa { #[derive(Component)] pub struct ExtractedView { - pub projection: Mat4, - pub transform: GlobalTransform, + pub clip_from_view: Mat4, + pub world_from_view: GlobalTransform, // The view-projection matrix. When provided it is used instead of deriving it from // `projection` and `transform` fields, which can be helpful in cases where numerical // stability matters and there is a more direct way to derive the view-projection matrix. - pub view_projection: Option, + pub clip_from_world: Option, pub hdr: bool, // uvec4(origin.x, origin.y, width, height) pub viewport: UVec4, @@ -187,7 +187,7 @@ pub struct ExtractedView { impl ExtractedView { /// Creates a 3D rangefinder for a view pub fn rangefinder3d(&self) -> ViewRangefinder3d { - ViewRangefinder3d::from_view_matrix(&self.transform.compute_matrix()) + ViewRangefinder3d::from_world_from_view(&self.world_from_view.compute_matrix()) } } @@ -404,13 +404,13 @@ impl ColorGrading { #[derive(Clone, ShaderType)] pub struct ViewUniform { - view_proj: Mat4, - unjittered_view_proj: Mat4, - inverse_view_proj: Mat4, - view: Mat4, - inverse_view: Mat4, - projection: Mat4, - inverse_projection: Mat4, + clip_from_world: Mat4, + unjittered_clip_from_world: Mat4, + world_from_clip: Mat4, + world_from_view: Mat4, + view_from_world: Mat4, + clip_from_view: Mat4, + view_from_clip: Mat4, world_position: Vec3, exposure: f32, // viewport(x_origin, y_origin, width, height) @@ -727,23 +727,23 @@ pub fn prepare_view_uniforms( }; for (entity, extracted_camera, extracted_view, frustum, temporal_jitter, mip_bias) in &views { let viewport = extracted_view.viewport.as_vec4(); - let unjittered_projection = extracted_view.projection; - let mut projection = unjittered_projection; + let unjittered_projection = extracted_view.clip_from_view; + let mut clip_from_view = unjittered_projection; if let Some(temporal_jitter) = temporal_jitter { - temporal_jitter.jitter_projection(&mut projection, viewport.zw()); + temporal_jitter.jitter_projection(&mut clip_from_view, viewport.zw()); } - let inverse_projection = projection.inverse(); - let view = extracted_view.transform.compute_matrix(); - let inverse_view = view.inverse(); + let view_from_clip = clip_from_view.inverse(); + let world_from_view = extracted_view.world_from_view.compute_matrix(); + let view_from_world = world_from_view.inverse(); - let view_proj = if temporal_jitter.is_some() { - projection * inverse_view + let clip_from_world = if temporal_jitter.is_some() { + clip_from_view * view_from_world } else { extracted_view - .view_projection - .unwrap_or_else(|| projection * inverse_view) + .clip_from_world + .unwrap_or_else(|| clip_from_view * view_from_world) }; // Map Frustum type to shader array, 6> @@ -753,14 +753,14 @@ pub fn prepare_view_uniforms( let view_uniforms = ViewUniformOffset { offset: writer.write(&ViewUniform { - view_proj, - unjittered_view_proj: unjittered_projection * inverse_view, - inverse_view_proj: view * inverse_projection, - view, - inverse_view, - projection, - inverse_projection, - world_position: extracted_view.transform.translation(), + clip_from_world, + unjittered_clip_from_world: unjittered_projection * view_from_world, + world_from_clip: world_from_view * view_from_clip, + world_from_view, + view_from_world, + clip_from_view, + view_from_clip, + world_position: extracted_view.world_from_view.translation(), exposure: extracted_camera .map(|c| c.exposure) .unwrap_or_else(|| Exposure::default().exposure()), diff --git a/crates/bevy_render/src/view/view.wgsl b/crates/bevy_render/src/view/view.wgsl index 4537a09428391..c67f382c23b6e 100644 --- a/crates/bevy_render/src/view/view.wgsl +++ b/crates/bevy_render/src/view/view.wgsl @@ -14,13 +14,13 @@ struct ColorGrading { } struct View { - view_proj: mat4x4, - unjittered_view_proj: mat4x4, - inverse_view_proj: mat4x4, - view: mat4x4, - inverse_view: mat4x4, - projection: mat4x4, - inverse_projection: mat4x4, + clip_from_world: mat4x4, + unjittered_clip_from_world: mat4x4, + world_from_clip: mat4x4, + world_from_view: mat4x4, + view_from_world: mat4x4, + clip_from_view: mat4x4, + view_from_clip: mat4x4, world_position: vec3, exposure: f32, // viewport(x_origin, y_origin, width, height) diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index b05451b8ca240..893f3abc7764f 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -468,9 +468,9 @@ pub fn check_visibility( // If we have an aabb, do frustum culling if !no_frustum_culling && !no_cpu_culling { if let Some(model_aabb) = maybe_model_aabb { - let model = transform.affine(); + let world_from_local = transform.affine(); let model_sphere = Sphere { - center: model.transform_point3a(model_aabb.center), + center: world_from_local.transform_point3a(model_aabb.center), radius: transform.radius_vec3a(model_aabb.half_extents), }; // Do quick sphere-based frustum culling @@ -478,7 +478,7 @@ pub fn check_visibility( return; } // Do aabb-based frustum culling - if !frustum.intersects_obb(model_aabb, &model, true, false) { + if !frustum.intersects_obb(model_aabb, &world_from_local, true, false) { return; } } diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 687c3328db008..a0257bc01a711 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -444,7 +444,7 @@ pub fn queue_material2d_meshes( mesh_instance.material_bind_group_id = material_2d.get_bind_group_id(); - let mesh_z = mesh_instance.transforms.transform.translation.z; + let mesh_z = mesh_instance.transforms.world_from_local.translation.z; transparent_phase.add(Transparent2d { entity: *visible_entity, draw_function: draw_transparent_2d, diff --git a/crates/bevy_sprite/src/mesh2d/mesh.rs b/crates/bevy_sprite/src/mesh2d/mesh.rs index 24d574ee0a0d8..16aee3f52937b 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh.rs +++ b/crates/bevy_sprite/src/mesh2d/mesh.rs @@ -156,31 +156,31 @@ impl Plugin for Mesh2dRenderPlugin { #[derive(Component)] pub struct Mesh2dTransforms { - pub transform: Affine3, + pub world_from_local: Affine3, pub flags: u32, } #[derive(ShaderType, Clone)] pub struct Mesh2dUniform { // Affine 4x3 matrix transposed to 3x4 - pub transform: [Vec4; 3], + pub world_from_local: [Vec4; 3], // 3x3 matrix packed in mat2x4 and f32 as: // [0].xyz, [1].x, // [1].yz, [2].xy // [2].z - pub inverse_transpose_model_a: [Vec4; 2], - pub inverse_transpose_model_b: f32, + pub local_from_world_transpose_a: [Vec4; 2], + pub local_from_world_transpose_b: f32, pub flags: u32, } impl From<&Mesh2dTransforms> for Mesh2dUniform { fn from(mesh_transforms: &Mesh2dTransforms) -> Self { - let (inverse_transpose_model_a, inverse_transpose_model_b) = - mesh_transforms.transform.inverse_transpose_3x3(); + let (local_from_world_transpose_a, local_from_world_transpose_b) = + mesh_transforms.world_from_local.inverse_transpose_3x3(); Self { - transform: mesh_transforms.transform.to_transpose(), - inverse_transpose_model_a, - inverse_transpose_model_b, + world_from_local: mesh_transforms.world_from_local.to_transpose(), + local_from_world_transpose_a, + local_from_world_transpose_b, flags: mesh_transforms.flags, } } @@ -236,7 +236,7 @@ pub fn extract_mesh2d( entity, RenderMesh2dInstance { transforms: Mesh2dTransforms { - transform: (&transform.affine()).into(), + world_from_local: (&transform.affine()).into(), flags: MeshFlags::empty().bits(), }, mesh_asset_id: handle.0.id(), diff --git a/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl b/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl index 00c1ec8442ad2..e909608be8ba1 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl +++ b/crates/bevy_sprite/src/mesh2d/mesh2d.wgsl @@ -35,9 +35,9 @@ fn vertex(vertex: Vertex) -> VertexOutput { #endif #ifdef VERTEX_POSITIONS - var model = mesh_functions::get_model_matrix(vertex.instance_index); + var world_from_local = mesh_functions::get_world_from_local(vertex.instance_index); out.world_position = mesh_functions::mesh2d_position_local_to_world( - model, + world_from_local, vec4(vertex.position, 1.0) ); out.position = mesh_functions::mesh2d_position_world_to_clip(out.world_position); @@ -49,7 +49,7 @@ fn vertex(vertex: Vertex) -> VertexOutput { #ifdef VERTEX_TANGENTS out.world_tangent = mesh_functions::mesh2d_tangent_local_to_world( - model, + world_from_local, vertex.tangent ); #endif diff --git a/crates/bevy_sprite/src/mesh2d/mesh2d_functions.wgsl b/crates/bevy_sprite/src/mesh2d/mesh2d_functions.wgsl index d76a88ab03832..0b994822112d8 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh2d_functions.wgsl +++ b/crates/bevy_sprite/src/mesh2d/mesh2d_functions.wgsl @@ -6,39 +6,39 @@ } #import bevy_render::maths::{affine3_to_square, mat2x4_f32_to_mat3x3_unpack} -fn get_model_matrix(instance_index: u32) -> mat4x4 { - return affine3_to_square(mesh[instance_index].model); +fn get_world_from_local(instance_index: u32) -> mat4x4 { + return affine3_to_square(mesh[instance_index].world_from_local); } -fn mesh2d_position_local_to_world(model: mat4x4, vertex_position: vec4) -> vec4 { - return model * vertex_position; +fn mesh2d_position_local_to_world(world_from_local: mat4x4, vertex_position: vec4) -> vec4 { + return world_from_local * vertex_position; } fn mesh2d_position_world_to_clip(world_position: vec4) -> vec4 { - return view.view_proj * world_position; + return view.clip_from_world * world_position; } // NOTE: The intermediate world_position assignment is important // for precision purposes when using the 'equals' depth comparison // function. -fn mesh2d_position_local_to_clip(model: mat4x4, vertex_position: vec4) -> vec4 { - let world_position = mesh2d_position_local_to_world(model, vertex_position); +fn mesh2d_position_local_to_clip(world_from_local: mat4x4, vertex_position: vec4) -> vec4 { + let world_position = mesh2d_position_local_to_world(world_from_local, vertex_position); return mesh2d_position_world_to_clip(world_position); } fn mesh2d_normal_local_to_world(vertex_normal: vec3, instance_index: u32) -> vec3 { return mat2x4_f32_to_mat3x3_unpack( - mesh[instance_index].inverse_transpose_model_a, - mesh[instance_index].inverse_transpose_model_b, + mesh[instance_index].local_from_world_transpose_a, + mesh[instance_index].local_from_world_transpose_b, ) * vertex_normal; } -fn mesh2d_tangent_local_to_world(model: mat4x4, vertex_tangent: vec4) -> vec4 { +fn mesh2d_tangent_local_to_world(world_from_local: mat4x4, vertex_tangent: vec4) -> vec4 { return vec4( mat3x3( - model[0].xyz, - model[1].xyz, - model[2].xyz + world_from_local[0].xyz, + world_from_local[1].xyz, + world_from_local[2].xyz ) * vertex_tangent.xyz, vertex_tangent.w ); diff --git a/crates/bevy_sprite/src/mesh2d/mesh2d_types.wgsl b/crates/bevy_sprite/src/mesh2d/mesh2d_types.wgsl index 4b14b919f3a26..d5038c818d58e 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh2d_types.wgsl +++ b/crates/bevy_sprite/src/mesh2d/mesh2d_types.wgsl @@ -3,14 +3,14 @@ struct Mesh2d { // Affine 4x3 matrix transposed to 3x4 // Use bevy_render::maths::affine3_to_square to unpack - model: mat3x4, + world_from_local: mat3x4, // 3x3 matrix packed in mat2x4 and f32 as: // [0].xyz, [1].x, // [1].yz, [2].xy // [2].z // Use bevy_render::maths::mat2x4_f32_to_mat3x3_unpack to unpack - inverse_transpose_model_a: mat2x4, - inverse_transpose_model_b: f32, + local_from_world_transpose_a: mat2x4, + local_from_world_transpose_b: f32, // 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options. flags: u32, }; diff --git a/crates/bevy_sprite/src/render/sprite.wgsl b/crates/bevy_sprite/src/render/sprite.wgsl index 7d820fcc9e6ff..03e43d0d5b5a3 100644 --- a/crates/bevy_sprite/src/render/sprite.wgsl +++ b/crates/bevy_sprite/src/render/sprite.wgsl @@ -37,7 +37,7 @@ fn vertex(in: VertexInput) -> VertexOutput { 0.0 ); - out.clip_position = view.view_proj * affine3_to_square(mat3x4( + out.clip_position = view.clip_from_world * affine3_to_square(mat3x4( in.i_model_transpose_col0, in.i_model_transpose_col1, in.i_model_transpose_col2, diff --git a/crates/bevy_transform/src/components/global_transform.rs b/crates/bevy_transform/src/components/global_transform.rs index 3348119c39d3b..a69689bcae851 100644 --- a/crates/bevy_transform/src/components/global_transform.rs +++ b/crates/bevy_transform/src/components/global_transform.rs @@ -224,8 +224,8 @@ impl From for GlobalTransform { } impl From for GlobalTransform { - fn from(matrix: Mat4) -> Self { - Self(Affine3A::from_mat4(matrix)) + fn from(world_from_local: Mat4) -> Self { + Self(Affine3A::from_mat4(world_from_local)) } } diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index 64ed8909307b0..ba82b8fb9de50 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -80,8 +80,8 @@ impl Transform { /// Extracts the translation, rotation, and scale from `matrix`. It must be a 3d affine /// transformation matrix. #[inline] - pub fn from_matrix(matrix: Mat4) -> Self { - let (scale, rotation, translation) = matrix.to_scale_rotation_translation(); + pub fn from_matrix(world_from_local: Mat4) -> Self { + let (scale, rotation, translation) = world_from_local.to_scale_rotation_translation(); Transform { translation, diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index be0b0172182a3..33f7443787225 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -671,7 +671,7 @@ pub fn extract_uinode_outlines( ), ]; - let transform = global_transform.compute_matrix(); + let world_from_local = global_transform.compute_matrix(); for edge in outline_edges { if edge.min.x < edge.max.x && edge.min.y < edge.max.y { extracted_uinodes.uinodes.insert( @@ -679,7 +679,8 @@ pub fn extract_uinode_outlines( ExtractedUiNode { stack_index: node.stack_index, // This translates the uinode's transform to the center of the current border rectangle - transform: transform * Mat4::from_translation(edge.center().extend(0.)), + transform: world_from_local + * Mat4::from_translation(edge.center().extend(0.)), color: outline.color.into(), rect: Rect { max: edge.size(), @@ -755,13 +756,13 @@ pub fn extract_default_ui_camera_view( ); let default_camera_view = commands .spawn(ExtractedView { - projection: projection_matrix, - transform: GlobalTransform::from_xyz( + clip_from_view: projection_matrix, + world_from_view: GlobalTransform::from_xyz( 0.0, 0.0, UI_CAMERA_FAR + UI_CAMERA_TRANSFORM_OFFSET, ), - view_projection: None, + clip_from_world: None, hdr: camera.hdr, viewport: UVec4::new( physical_origin.x, diff --git a/crates/bevy_ui/src/render/ui.wgsl b/crates/bevy_ui/src/render/ui.wgsl index 5fd6f5d96a659..89dbed1f6668a 100644 --- a/crates/bevy_ui/src/render/ui.wgsl +++ b/crates/bevy_ui/src/render/ui.wgsl @@ -41,7 +41,7 @@ fn vertex( ) -> VertexOutput { var out: VertexOutput; out.uv = vertex_uv; - out.position = view.view_proj * vec4(vertex_position, 1.0); + out.position = view.clip_from_world * vec4(vertex_position, 1.0); out.color = vertex_color; out.flags = flags; out.radius = radius; diff --git a/crates/bevy_ui/src/render/ui_material.wgsl b/crates/bevy_ui/src/render/ui_material.wgsl index 575df198ae6c6..f7fdedd859038 100644 --- a/crates/bevy_ui/src/render/ui_material.wgsl +++ b/crates/bevy_ui/src/render/ui_material.wgsl @@ -18,7 +18,7 @@ fn vertex( ) -> UiVertexOutput { var out: UiVertexOutput; out.uv = vertex_uv; - out.position = view.view_proj * vec4(vertex_position, 1.0); + out.position = view.clip_from_world * vec4(vertex_position, 1.0); out.size = size; out.border_widths = border_widths; return out; diff --git a/examples/2d/mesh2d_manual.rs b/examples/2d/mesh2d_manual.rs index ffdcc0184c29a..75b018c3681d9 100644 --- a/examples/2d/mesh2d_manual.rs +++ b/examples/2d/mesh2d_manual.rs @@ -246,7 +246,7 @@ struct VertexOutput { fn vertex(vertex: Vertex) -> VertexOutput { var out: VertexOutput; // Project the world position of the mesh into screen position - let model = mesh2d_functions::get_model_matrix(vertex.instance_index); + let model = mesh2d_functions::get_world_from_local(vertex.instance_index); out.clip_position = mesh2d_functions::mesh2d_position_local_to_clip(model, vec4(vertex.position, 1.0)); // Unpack the `u32` from the vertex buffer into the `vec4` used by the fragment shader out.color = vec4((vec4(vertex.color) >> vec4(0u, 8u, 16u, 24u)) & vec4(255u)) / 255.0; @@ -325,7 +325,7 @@ pub fn extract_colored_mesh2d( } let transforms = Mesh2dTransforms { - transform: (&transform.affine()).into(), + world_from_local: (&transform.affine()).into(), flags: MeshFlags::empty().bits(), }; @@ -386,7 +386,7 @@ pub fn queue_colored_mesh2d( let pipeline_id = pipelines.specialize(&pipeline_cache, &colored_mesh2d_pipeline, mesh2d_key); - let mesh_z = mesh2d_transforms.transform.translation.z; + let mesh_z = mesh2d_transforms.world_from_local.translation.z; transparent_phase.add(Transparent2d { entity: *visible_entity, draw_function: draw_colored_mesh2d, diff --git a/examples/3d/irradiance_volumes.rs b/examples/3d/irradiance_volumes.rs index 49d1de8fb0810..9f9e93fc6a9c9 100644 --- a/examples/3d/irradiance_volumes.rs +++ b/examples/3d/irradiance_volumes.rs @@ -50,7 +50,7 @@ static CLICK_TO_MOVE_HELP_TEXT: &str = "Left click: Move the object"; static GIZMO_COLOR: Color = Color::Srgba(YELLOW); -static VOXEL_TRANSFORM: Mat4 = Mat4::from_cols_array_2d(&[ +static VOXEL_FROM_WORLD: Mat4 = Mat4::from_cols_array_2d(&[ [-42.317566, 0.0, 0.0, 0.0], [0.0, 0.0, 44.601563, 0.0], [0.0, 16.73776, 0.0, 0.0], @@ -132,8 +132,8 @@ struct VoxelVisualizationExtension { #[derive(ShaderType, Debug, Clone)] struct VoxelVisualizationIrradianceVolumeInfo { - transform: Mat4, - inverse_transform: Mat4, + world_from_voxel: Mat4, + voxel_from_world: Mat4, resolution: UVec3, intensity: f32, } @@ -242,7 +242,7 @@ fn spawn_camera(commands: &mut Commands, assets: &ExampleAssets) { fn spawn_irradiance_volume(commands: &mut Commands, assets: &ExampleAssets) { commands .spawn(SpatialBundle { - transform: Transform::from_matrix(VOXEL_TRANSFORM), + transform: Transform::from_matrix(VOXEL_FROM_WORLD), ..SpatialBundle::default() }) .insert(IrradianceVolume { @@ -571,8 +571,8 @@ fn create_cubes( base: StandardMaterial::from(Color::from(RED)), extension: VoxelVisualizationExtension { irradiance_volume_info: VoxelVisualizationIrradianceVolumeInfo { - transform: VOXEL_TRANSFORM.inverse(), - inverse_transform: VOXEL_TRANSFORM, + world_from_voxel: VOXEL_FROM_WORLD.inverse(), + voxel_from_world: VOXEL_FROM_WORLD, resolution: uvec3( resolution.width, resolution.height,