Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Use Affine3A for GlobalTransform to allow any affine transformation #4379

Closed
wants to merge 10 commits into from
59 changes: 27 additions & 32 deletions crates/bevy_pbr/src/light.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashSet;

use bevy_ecs::prelude::*;
use bevy_math::{Mat4, Quat, UVec2, UVec3, Vec2, Vec3, Vec3A, Vec3Swizzles, Vec4, Vec4Swizzles};
use bevy_math::{Mat4, UVec2, UVec3, Vec2, Vec3, Vec3A, Vec3Swizzles, Vec4, Vec4Swizzles};
use bevy_reflect::prelude::*;
use bevy_render::{
camera::{Camera, CameraProjection, OrthographicProjection},
Expand All @@ -12,7 +12,7 @@ use bevy_render::{
renderer::RenderDevice,
view::{ComputedVisibility, RenderLayers, VisibleEntities},
};
use bevy_transform::components::GlobalTransform;
use bevy_transform::{components::GlobalTransform, prelude::Transform};
use bevy_utils::tracing::warn;

use crate::{
Expand Down Expand Up @@ -755,13 +755,21 @@ pub(crate) fn point_light_order(
// data required for assigning lights to clusters
pub(crate) struct PointLightAssignmentData {
entity: Entity,
translation: Vec3,
rotation: Quat,
transform: GlobalTransform,
range: f32,
shadows_enabled: bool,
spot_light_angle: Option<f32>,
}

impl PointLightAssignmentData {
pub fn sphere(&self) -> Sphere {
Sphere {
center: self.transform.translation_vec3a(),
radius: self.range,
}
}
}

#[derive(Default)]
pub struct GlobalVisiblePointLights {
entities: HashSet<Entity>,
Expand Down Expand Up @@ -815,8 +823,7 @@ pub(crate) fn assign_lights_to_clusters(
.map(
|(entity, transform, point_light, _visibility)| PointLightAssignmentData {
entity,
translation: transform.translation,
rotation: Quat::default(),
transform: GlobalTransform::from_translation(transform.translation()),
shadows_enabled: point_light.shadows_enabled,
range: point_light.range,
spot_light_angle: None,
Expand All @@ -830,8 +837,7 @@ pub(crate) fn assign_lights_to_clusters(
.map(
|(entity, transform, spot_light, _visibility)| PointLightAssignmentData {
entity,
translation: transform.translation,
rotation: transform.rotation,
transform: *transform,
shadows_enabled: spot_light.shadows_enabled,
range: spot_light.range,
spot_light_angle: Some(spot_light.outer_angle),
Expand Down Expand Up @@ -872,11 +878,7 @@ pub(crate) fn assign_lights_to_clusters(
if lights_in_view_count == MAX_UNIFORM_BUFFER_POINT_LIGHTS + 1 {
false
} else {
let light_sphere = Sphere {
center: Vec3A::from(light.translation),
radius: light.range,
};

let light_sphere = light.sphere();
let light_in_view = frusta
.iter()
.any(|frustum| frustum.intersects_sphere(&light_sphere, true));
Expand Down Expand Up @@ -932,7 +934,8 @@ pub(crate) fn assign_lights_to_clusters(
lights
.iter()
.map(|light| {
-inverse_view_row_2.dot(light.translation.extend(1.0)) + light.range
-inverse_view_row_2.dot(light.transform.translation().extend(1.0))
+ light.range
})
.reduce(f32::max)
.unwrap_or(0.0)
Expand Down Expand Up @@ -966,10 +969,7 @@ pub(crate) fn assign_lights_to_clusters(
if config.dynamic_resizing() {
let mut cluster_index_estimate = 0.0;
for light in lights.iter() {
let light_sphere = Sphere {
center: Vec3A::from(light.translation),
radius: light.range,
};
let light_sphere = light.sphere();

// Check if the light is within the view frustum
if !frustum.intersects_sphere(&light_sphere, true) {
Expand Down Expand Up @@ -1124,10 +1124,7 @@ pub(crate) fn assign_lights_to_clusters(

let mut update_from_light_intersections = |visible_lights: &mut Vec<Entity>| {
for light in lights.iter() {
let light_sphere = Sphere {
center: Vec3A::from(light.translation),
radius: light.range,
};
let light_sphere = light.sphere();

// Check if the light is within the view frustum
if !frustum.intersects_sphere(&light_sphere, true) {
Expand Down Expand Up @@ -1177,8 +1174,7 @@ pub(crate) fn assign_lights_to_clusters(
let spot_light_dir_sin_cos = light.spot_light_angle.map(|angle| {
let (angle_sin, angle_cos) = angle.sin_cos();
(
(inverse_view_transform * (light.rotation * Vec3::Z).extend(0.0))
.truncate(),
(inverse_view_transform * light.transform.back().extend(0.0)).truncate(),
angle_sin,
angle_cos,
)
Expand Down Expand Up @@ -1432,7 +1428,7 @@ pub fn update_directional_light_frusta(
* transform.compute_matrix().inverse();
*frustum = Frustum::from_view_projection(
&view_projection,
&transform.translation,
&transform.translation(),
&transform.back(),
directional_light.shadow_projection.far(),
);
Expand All @@ -1451,7 +1447,7 @@ pub fn update_point_light_frusta(
Mat4::perspective_infinite_reverse_rh(std::f32::consts::FRAC_PI_2, 1.0, POINT_LIGHT_NEAR_Z);
let view_rotations = CUBE_MAP_FACES
.iter()
.map(|CubeMapFace { target, up }| GlobalTransform::identity().looking_at(*target, *up))
.map(|CubeMapFace { target, up }| Transform::identity().looking_at(*target, *up))
.collect::<Vec<_>>();

for (entity, transform, point_light, mut cubemap_frusta) in &mut views {
Expand All @@ -1467,7 +1463,7 @@ pub fn update_point_light_frusta(
// ignore scale because we don't want to effectively scale light radius and range
// by applying those as a view transform to shadow map rendering of objects
// and ignore rotation because we want the shadow map projections to align with the axes
let view_translation = GlobalTransform::from_translation(transform.translation);
let view_translation = Transform::from_translation(transform.translation());
let view_backward = transform.back();

for (view_rotation, frustum) in view_rotations.iter().zip(cubemap_frusta.iter_mut()) {
Expand All @@ -1476,7 +1472,7 @@ pub fn update_point_light_frusta(

*frustum = Frustum::from_view_projection(
&view_projection,
&transform.translation,
&transform.translation(),
&view_backward,
point_light.range,
);
Expand All @@ -1503,7 +1499,6 @@ pub fn update_spot_light_frusta(

// ignore scale because we don't want to effectively scale light radius and range
// by applying those as a view transform to shadow map rendering of objects
let view_translation = GlobalTransform::from_translation(transform.translation);
let view_backward = transform.back();

let spot_view = spot_light_view_matrix(transform);
Expand All @@ -1512,7 +1507,7 @@ pub fn update_spot_light_frusta(

*frustum = Frustum::from_view_projection(
&view_projection,
&view_translation.translation,
&transform.translation(),
&view_backward,
spot_light.range,
);
Expand Down Expand Up @@ -1623,7 +1618,7 @@ pub fn check_light_mesh_visibility(

let view_mask = maybe_view_mask.copied().unwrap_or_default();
let light_sphere = Sphere {
center: Vec3A::from(transform.translation),
center: Vec3A::from(transform.translation()),
radius: point_light.range,
};

Expand Down Expand Up @@ -1686,7 +1681,7 @@ pub fn check_light_mesh_visibility(

let view_mask = maybe_view_mask.copied().unwrap_or_default();
let light_sphere = Sphere {
center: Vec3A::from(transform.translation),
center: Vec3A::from(transform.translation()),
radius: point_light.range,
};

Expand Down
16 changes: 8 additions & 8 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use bevy_render::{
},
Extract,
};
use bevy_transform::components::GlobalTransform;
use bevy_transform::{components::GlobalTransform, prelude::Transform};
use bevy_utils::FloatOrd;
use bevy_utils::{
tracing::{error, warn},
Expand Down Expand Up @@ -728,7 +728,7 @@ pub fn calculate_cluster_factors(
// could move this onto transform but it's pretty niche
pub(crate) fn spot_light_view_matrix(transform: &GlobalTransform) -> Mat4 {
// the matrix z_local (opposite of transform.forward())
let fwd_dir = transform.local_z().extend(0.0);
let fwd_dir = transform.back().extend(0.0);

let sign = 1f32.copysign(fwd_dir.z);
let a = -1.0 / (fwd_dir.z + sign);
Expand All @@ -745,7 +745,7 @@ pub(crate) fn spot_light_view_matrix(transform: &GlobalTransform) -> Mat4 {
right_dir,
up_dir,
fwd_dir,
transform.translation.extend(1.0),
transform.translation().extend(1.0),
)
}

Expand Down Expand Up @@ -779,7 +779,7 @@ pub fn prepare_lights(
Mat4::perspective_infinite_reverse_rh(std::f32::consts::FRAC_PI_2, 1.0, POINT_LIGHT_NEAR_Z);
let cube_face_rotations = CUBE_MAP_FACES
.iter()
.map(|CubeMapFace { target, up }| GlobalTransform::identity().looking_at(*target, *up))
.map(|CubeMapFace { target, up }| Transform::identity().looking_at(*target, *up))
.collect::<Vec<_>>();

global_light_meta.entity_to_index.clear();
Expand Down Expand Up @@ -893,7 +893,7 @@ pub fn prepare_lights(
* light.intensity)
.xyz()
.extend(1.0 / (light.range * light.range)),
position_radius: light.transform.translation.extend(light.radius),
position_radius: light.transform.translation().extend(light.radius),
flags: flags.bits,
shadow_depth_bias: light.shadow_depth_bias,
shadow_normal_bias: light.shadow_normal_bias,
Expand Down Expand Up @@ -989,7 +989,7 @@ pub fn prepare_lights(
// ignore scale because we don't want to effectively scale light radius and range
// by applying those as a view transform to shadow map rendering of objects
// and ignore rotation because we want the shadow map projections to align with the axes
let view_translation = GlobalTransform::from_translation(light.transform.translation);
let view_translation = GlobalTransform::from_translation(light.transform.translation());

for (face_index, view_rotation) in cube_face_rotations.iter().enumerate() {
let depth_texture_view =
Expand Down Expand Up @@ -1042,7 +1042,7 @@ pub fn prepare_lights(
.enumerate()
{
let spot_view_matrix = spot_light_view_matrix(&light.transform);
let spot_view_transform = GlobalTransform::from_matrix(spot_view_matrix);
let spot_view_transform = spot_view_matrix.into();

let angle = light.spot_light_angles.expect("lights should be sorted so that \
[point_light_shadow_maps_count..point_light_shadow_maps_count + spot_light_shadow_maps_count] are spot lights").1;
Expand Down Expand Up @@ -1152,7 +1152,7 @@ pub fn prepare_lights(
ExtractedView {
width: directional_light_shadow_map.size as u32,
height: directional_light_shadow_map.size as u32,
transform: GlobalTransform::from_matrix(view.inverse()),
transform: GlobalTransform::from(view.inverse()),
projection,
},
RenderPhase::<Shadow>::default(),
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ impl SkinnedMeshJoints {
let start = buffer.len();
for (inverse_bindpose, joint) in bindposes.zip(skin_joints).take(MAX_JOINTS) {
if let Ok(joint) = joints.get(*joint) {
buffer.push(joint.compute_affine() * *inverse_bindpose);
buffer.push(joint.affine() * *inverse_bindpose);
} else {
buffer.truncate(start);
return None;
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_render/src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ fn prepare_view_uniforms(
inverse_view,
projection,
inverse_projection,
world_position: camera.transform.translation,
world_position: camera.transform.translation(),
width: camera.width as f32,
height: camera.height as f32,
}),
Expand Down
5 changes: 2 additions & 3 deletions crates/bevy_render/src/view/visibility/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
mod render_layers;

use bevy_math::Vec3A;
pub use render_layers::*;

use bevy_app::{CoreStage, Plugin};
Expand Down Expand Up @@ -205,7 +204,7 @@ pub fn update_frusta<T: Component + CameraProjection + Send + Sync + 'static>(
projection.get_projection_matrix() * transform.compute_matrix().inverse();
*frustum = Frustum::from_view_projection(
&view_projection,
&transform.translation,
&transform.translation(),
&transform.back(),
projection.far(),
);
Expand Down Expand Up @@ -324,7 +323,7 @@ pub fn check_visibility(
let model = transform.compute_matrix();
let model_sphere = Sphere {
center: model.transform_point3a(model_aabb.center),
radius: (Vec3A::from(transform.scale) * model_aabb.half_extents).length(),
radius: transform.radius_vec3a(model_aabb.half_extents),
};
// Do quick sphere-based frustum culling
if !frustum.intersects_sphere(&model_sphere, false) {
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_sprite/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,9 +410,9 @@ pub fn queue_sprites(
extracted_sprites.sort_unstable_by(|a, b| {
match a
.transform
.translation
.translation()
.z
.partial_cmp(&b.transform.translation.z)
.partial_cmp(&b.transform.translation().z)
{
Some(Ordering::Equal) | None => a.image_handle_id.cmp(&b.image_handle_id),
Some(other) => other,
Expand Down Expand Up @@ -517,7 +517,7 @@ pub fn queue_sprites(
});

// These items will be sorted by depth with other phase items
let sort_key = FloatOrd(extracted_sprite.transform.translation.z);
let sort_key = FloatOrd(extracted_sprite.transform.translation().z);

// Store the vertex data and add the item to the render phase
if current_batch.colored {
Expand Down
12 changes: 6 additions & 6 deletions crates/bevy_text/src/text2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ pub fn extract_text2d_sprite(
) {
let scale_factor = windows.scale_factor(WindowId::primary()) as f32;

for (entity, computed_visibility, text, transform, calculated_size) in text2d_query.iter() {
for (entity, computed_visibility, text, text_transform, calculated_size) in text2d_query.iter()
{
if !computed_visibility.is_visible() {
continue;
}
Expand All @@ -100,9 +101,6 @@ pub fn extract_text2d_sprite(
HorizontalAlign::Right => Vec3::new(-width, 0.0, 0.0),
};

let mut text_transform = *transform;
text_transform.scale /= scale_factor;

for text_glyph in text_glyphs {
let color = text.sections[text_glyph.section_index]
.style
Expand All @@ -118,8 +116,10 @@ pub fn extract_text2d_sprite(
let glyph_transform = Transform::from_translation(
alignment_offset * scale_factor + text_glyph.position.extend(0.),
);

let transform = text_transform.mul_transform(glyph_transform);
// NOTE: Should match `bevy_ui::render::extract_text_uinodes`
let transform = *text_transform
* GlobalTransform::from_scale(Vec3::splat(scale_factor.recip()))
* glyph_transform;

extracted_sprites.sprites.push(ExtractedSprite {
entity,
Expand Down
Loading