From 5bc615f510d4e6063722671fecf731442c85f1fc Mon Sep 17 00:00:00 2001 From: Robin KAY Date: Tue, 14 Jun 2022 17:46:12 +0100 Subject: [PATCH 1/8] Add ViewRangefinder3d and update distance calculations to use it. --- crates/bevy_core_pipeline/src/core_3d/mod.rs | 13 +++++++--- crates/bevy_pbr/src/material.rs | 26 +++++--------------- crates/bevy_pbr/src/wireframe.rs | 6 ++--- crates/bevy_render/src/lib.rs | 1 + crates/bevy_render/src/rangefinder.rs | 24 ++++++++++++++++++ examples/shader/animate_shader.rs | 6 ++--- examples/shader/shader_defs.rs | 6 ++--- examples/shader/shader_instancing.rs | 6 ++--- 8 files changed, 52 insertions(+), 36 deletions(-) create mode 100644 crates/bevy_render/src/rangefinder.rs diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 6342d8471291b..b6cea285e02e7 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -11,6 +11,8 @@ pub mod graph { } } +use std::cmp::Reverse; + pub use camera_3d::*; pub use main_pass_3d_node::*; @@ -87,11 +89,12 @@ pub struct Opaque3d { } impl PhaseItem for Opaque3d { - type SortKey = FloatOrd; + // NOTE: Values increase towards the camera. Front-to-back ordering for opaque means we need a descending sort. + type SortKey = Reverse; #[inline] fn sort_key(&self) -> Self::SortKey { - FloatOrd(self.distance) + Reverse(FloatOrd(self.distance)) } #[inline] @@ -122,11 +125,12 @@ pub struct AlphaMask3d { } impl PhaseItem for AlphaMask3d { - type SortKey = FloatOrd; + // NOTE: Values increase towards the camera. Front-to-back ordering for alpha mask means we need a descending sort. + type SortKey = Reverse; #[inline] fn sort_key(&self) -> Self::SortKey { - FloatOrd(self.distance) + Reverse(FloatOrd(self.distance)) } #[inline] @@ -157,6 +161,7 @@ pub struct Transparent3d { } impl PhaseItem for Transparent3d { + // NOTE: Values increase towards the camera. Back-to-front ordering for transparent means we need an ascending sort. type SortKey = FloatOrd; #[inline] diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 28620aaec1d03..088e34b11141b 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -17,6 +17,7 @@ use bevy_ecs::{ use bevy_render::{ extract_component::ExtractComponentPlugin, mesh::{Mesh, MeshVertexBufferLayout}, + rangefinder::ViewRangefinder3d, render_asset::{RenderAsset, RenderAssetPlugin, RenderAssets}, render_phase::{ AddRenderCommand, DrawFunctions, EntityRenderCommand, RenderCommandResult, RenderPhase, @@ -359,8 +360,7 @@ pub fn queue_material_meshes( .get_id::>() .unwrap(); - let inverse_view_matrix = view.transform.compute_matrix().inverse(); - let inverse_view_row_2 = inverse_view_matrix.row(2); + let rangefinder = ViewRangefinder3d::from_view(view); let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples); for visible_entity in &visible_entities.entities { @@ -396,21 +396,15 @@ pub fn queue_material_meshes( } }; - // 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 let bias = M::depth_bias(material); - let mesh_z = inverse_view_row_2.dot(mesh_uniform.transform.col(3)) + bias; + let distance = rangefinder.distance(&mesh_uniform.transform) + bias; match alpha_mode { AlphaMode::Opaque => { opaque_phase.add(Opaque3d { entity: *visible_entity, draw_function: draw_opaque_pbr, pipeline: pipeline_id, - // NOTE: Front-to-back ordering for opaque with ascending sort means near should have the - // lowest sort key and getting further away should increase. As we have - // -z in front of the camera, values in view space decrease away from the - // camera. Flipping the sign of mesh_z results in the correct front-to-back ordering - distance: -mesh_z, + distance, }); } AlphaMode::Mask(_) => { @@ -418,11 +412,7 @@ pub fn queue_material_meshes( entity: *visible_entity, draw_function: draw_alpha_mask_pbr, pipeline: pipeline_id, - // NOTE: Front-to-back ordering for alpha mask with ascending sort means near should have the - // lowest sort key and getting further away should increase. As we have - // -z in front of the camera, values in view space decrease away from the - // camera. Flipping the sign of mesh_z results in the correct front-to-back ordering - distance: -mesh_z, + distance, }); } AlphaMode::Blend => { @@ -430,11 +420,7 @@ pub fn queue_material_meshes( entity: *visible_entity, draw_function: draw_transparent_pbr, pipeline: pipeline_id, - // NOTE: Back-to-front ordering for transparent with ascending sort means far should have the - // lowest sort key and getting closer should increase. As we have - // -z in front of the camera, the largest distance is -far with values increasing toward the - // camera. As such we can just use mesh_z as the distance - distance: mesh_z, + distance, }); } } diff --git a/crates/bevy_pbr/src/wireframe.rs b/crates/bevy_pbr/src/wireframe.rs index 6a7a4c3c297c2..4bea286a87086 100644 --- a/crates/bevy_pbr/src/wireframe.rs +++ b/crates/bevy_pbr/src/wireframe.rs @@ -6,6 +6,7 @@ use bevy_core_pipeline::core_3d::Opaque3d; use bevy_ecs::{prelude::*, reflect::ReflectComponent}; use bevy_reflect::std_traits::ReflectDefault; use bevy_reflect::{Reflect, TypeUuid}; +use bevy_render::rangefinder::ViewRangefinder3d; use bevy_render::{ extract_resource::{ExtractResource, ExtractResourcePlugin}, mesh::{Mesh, MeshVertexBufferLayout}, @@ -117,8 +118,7 @@ fn queue_wireframes( .unwrap(); let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples); for (view, visible_entities, mut opaque_phase) in views.iter_mut() { - let view_matrix = view.transform.compute_matrix(); - let view_row_2 = view_matrix.row(2); + let rangefinder = ViewRangefinder3d::from_view(view); let add_render_phase = |(entity, mesh_handle, mesh_uniform): (Entity, &Handle, &MeshUniform)| { @@ -142,7 +142,7 @@ fn queue_wireframes( entity, pipeline: pipeline_id, draw_function: draw_custom, - distance: view_row_2.dot(mesh_uniform.transform.col(3)), + distance: rangefinder.distance(&mesh_uniform.transform), }); } }; diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 0caa1a75bc29c..b69eb85c35c17 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -6,6 +6,7 @@ pub mod extract_component; pub mod extract_resource; pub mod mesh; pub mod primitives; +pub mod rangefinder; pub mod render_asset; pub mod render_graph; pub mod render_phase; diff --git a/crates/bevy_render/src/rangefinder.rs b/crates/bevy_render/src/rangefinder.rs new file mode 100644 index 0000000000000..bff749649c610 --- /dev/null +++ b/crates/bevy_render/src/rangefinder.rs @@ -0,0 +1,24 @@ +use bevy_math::{Mat4, Vec4}; + +use crate::view::ExtractedView; + +pub struct ViewRangefinder3d { + inverse_view_row_2: Vec4, +} + +/// A helper for calculating the draw order of meshes. +impl ViewRangefinder3d { + pub fn from_view(view: &ExtractedView) -> ViewRangefinder3d { + let inverse_view_matrix = view.transform.compute_matrix().inverse(); + ViewRangefinder3d { + inverse_view_row_2: inverse_view_matrix.row(2), + } + } + + /// Calculates the view-space Z value for a mesh's origin + pub fn distance(&self, mesh_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(mesh_transform.col(3)) + } +} diff --git a/examples/shader/animate_shader.rs b/examples/shader/animate_shader.rs index 048657c3ca9cb..c621cafe9192b 100644 --- a/examples/shader/animate_shader.rs +++ b/examples/shader/animate_shader.rs @@ -12,6 +12,7 @@ use bevy::{ prelude::*, render::{ mesh::MeshVertexBufferLayout, + rangefinder::ViewRangefinder3d, render_asset::RenderAssets, render_phase::{ AddRenderCommand, DrawFunctions, EntityRenderCommand, RenderCommandResult, RenderPhase, @@ -116,8 +117,7 @@ fn queue_custom( | MeshPipelineKey::from_primitive_topology(PrimitiveTopology::TriangleList); for (view, mut transparent_phase) in views.iter_mut() { - let view_matrix = view.transform.compute_matrix(); - let view_row_2 = view_matrix.row(2); + let rangefinder = ViewRangefinder3d::from_view(view); for (entity, mesh_uniform, mesh_handle) in material_meshes.iter() { if let Some(mesh) = render_meshes.get(mesh_handle) { let pipeline = pipelines @@ -127,7 +127,7 @@ fn queue_custom( entity, pipeline, draw_function: draw_custom, - distance: view_row_2.dot(mesh_uniform.transform.col(3)), + distance: rangefinder.distance(&mesh_uniform.transform), }); } } diff --git a/examples/shader/shader_defs.rs b/examples/shader/shader_defs.rs index 3164da5c0179b..8931103faca5b 100644 --- a/examples/shader/shader_defs.rs +++ b/examples/shader/shader_defs.rs @@ -10,6 +10,7 @@ use bevy::{ render::{ extract_component::{ExtractComponent, ExtractComponentPlugin}, mesh::MeshVertexBufferLayout, + rangefinder::ViewRangefinder3d, render_asset::RenderAssets, render_phase::{AddRenderCommand, DrawFunctions, RenderPhase, SetItemPipeline}, render_resource::{ @@ -151,8 +152,7 @@ fn queue_custom( .unwrap(); let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples); for (view, mut transparent_phase) in views.iter_mut() { - let view_matrix = view.transform.compute_matrix(); - let view_row_2 = view_matrix.row(2); + let rangefinder = ViewRangefinder3d::from_view(view); for (entity, mesh_handle, mesh_uniform, is_red) in material_meshes.iter() { if let Some(mesh) = render_meshes.get(mesh_handle) { let key = @@ -169,7 +169,7 @@ fn queue_custom( entity, pipeline, draw_function: draw_custom, - distance: view_row_2.dot(mesh_uniform.transform.col(3)), + distance: rangefinder.distance(&mesh_uniform.transform), }); } } diff --git a/examples/shader/shader_instancing.rs b/examples/shader/shader_instancing.rs index 4d45397a72653..2af208e06c898 100644 --- a/examples/shader/shader_instancing.rs +++ b/examples/shader/shader_instancing.rs @@ -9,6 +9,7 @@ use bevy::{ render::{ extract_component::{ExtractComponent, ExtractComponentPlugin}, mesh::{GpuBufferInfo, MeshVertexBufferLayout}, + rangefinder::ViewRangefinder3d, render_asset::RenderAssets, render_phase::{ AddRenderCommand, DrawFunctions, EntityRenderCommand, RenderCommandResult, RenderPhase, @@ -117,8 +118,7 @@ fn queue_custom( let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples); for (view, mut transparent_phase) in views.iter_mut() { - let view_matrix = view.transform.compute_matrix(); - let view_row_2 = view_matrix.row(2); + let rangefinder = ViewRangefinder3d::from_view(view); for (entity, mesh_uniform, mesh_handle) in material_meshes.iter() { if let Some(mesh) = meshes.get(mesh_handle) { let key = @@ -130,7 +130,7 @@ fn queue_custom( entity, pipeline, draw_function: draw_custom, - distance: view_row_2.dot(mesh_uniform.transform.col(3)), + distance: rangefinder.distance(&mesh_uniform.transform), }); } } From 738d487002fd3ecb35f02290cc729de3dda04a9c Mon Sep 17 00:00:00 2001 From: Robin KAY Date: Tue, 14 Jun 2022 18:17:41 +0100 Subject: [PATCH 2/8] Add unit test for ViewRangefinder3d. --- crates/bevy_render/src/rangefinder.rs | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/crates/bevy_render/src/rangefinder.rs b/crates/bevy_render/src/rangefinder.rs index bff749649c610..33ab58b4a7e94 100644 --- a/crates/bevy_render/src/rangefinder.rs +++ b/crates/bevy_render/src/rangefinder.rs @@ -22,3 +22,31 @@ impl ViewRangefinder3d { self.inverse_view_row_2.dot(mesh_transform.col(3)) } } + +#[cfg(test)] +mod tests { + use bevy_math::{Mat4, Vec3}; + use bevy_transform::prelude::Transform; + + use crate::view::ExtractedView; + + use super::ViewRangefinder3d; + + #[test] + fn distance() { + let view = ExtractedView { + projection: Mat4::IDENTITY, + transform: Transform::identity() + .with_translation(Vec3::new(0.0, 0.0, -1.0)) + .into(), + width: 0, + height: 0, + }; + let rangefinder = ViewRangefinder3d::from_view(&view); + assert_eq!(rangefinder.distance(&Mat4::IDENTITY), 1.0); + assert_eq!( + rangefinder.distance(&Mat4::from_translation(Vec3::new(0.0, 0.0, 1.0))), + 2.0 + ); + } +} From d2a1d253157e0f0ae568156c2e2383dfe18ce780 Mon Sep 17 00:00:00 2001 From: Robin KAY Date: Tue, 14 Jun 2022 19:44:40 +0100 Subject: [PATCH 3/8] Improve documentation. --- crates/bevy_render/src/rangefinder.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/bevy_render/src/rangefinder.rs b/crates/bevy_render/src/rangefinder.rs index 33ab58b4a7e94..adb1f52f763f8 100644 --- a/crates/bevy_render/src/rangefinder.rs +++ b/crates/bevy_render/src/rangefinder.rs @@ -2,12 +2,13 @@ use bevy_math::{Mat4, Vec4}; use crate::view::ExtractedView; +/// A distance calculator for the draw order of [PhaseItems](crate::render_phase::PhaseItem). pub struct ViewRangefinder3d { inverse_view_row_2: Vec4, } -/// A helper for calculating the draw order of meshes. impl ViewRangefinder3d { + /// Creates a rangefinder for a view pub fn from_view(view: &ExtractedView) -> ViewRangefinder3d { let inverse_view_matrix = view.transform.compute_matrix().inverse(); ViewRangefinder3d { @@ -15,11 +16,11 @@ impl ViewRangefinder3d { } } - /// Calculates the view-space Z value for a mesh's origin - pub fn distance(&self, mesh_transform: &Mat4) -> f32 { + /// Calculates the distance, or view-space Z value, for a transform + 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(mesh_transform.col(3)) + self.inverse_view_row_2.dot(transform.col(3)) } } From 7df30aae47df4c7c8d3098519b0dc25925eeda41 Mon Sep 17 00:00:00 2001 From: Robin KAY Date: Tue, 14 Jun 2022 20:00:42 +0100 Subject: [PATCH 4/8] Fix clippy::doc-markdown lint. --- crates/bevy_render/src/rangefinder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/rangefinder.rs b/crates/bevy_render/src/rangefinder.rs index adb1f52f763f8..5326104d6cc9b 100644 --- a/crates/bevy_render/src/rangefinder.rs +++ b/crates/bevy_render/src/rangefinder.rs @@ -2,7 +2,7 @@ use bevy_math::{Mat4, Vec4}; use crate::view::ExtractedView; -/// A distance calculator for the draw order of [PhaseItems](crate::render_phase::PhaseItem). +/// A distance calculator for the draw order of [`PhaseItem`](crate::render_phase::PhaseItem)s. pub struct ViewRangefinder3d { inverse_view_row_2: Vec4, } From d2ff01371aec185a526f229678cc69aa61717da6 Mon Sep 17 00:00:00 2001 From: Robin KAY Date: Wed, 29 Jun 2022 20:46:06 +0100 Subject: [PATCH 5/8] Fix new PhaseItem::sort() impls to match SortKey behaviour in this PR. --- crates/bevy_core_pipeline/src/core_3d/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 02bd72e2c9387..c49c8634b30f7 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -104,7 +104,8 @@ impl PhaseItem for Opaque3d { #[inline] fn sort(items: &mut [Self]) { - radsort::sort_by_key(items, |item| item.distance); + // Key negated to match reversed SortKey ordering + radsort::sort_by_key(items, |item| -item.distance); } } @@ -145,7 +146,8 @@ impl PhaseItem for AlphaMask3d { #[inline] fn sort(items: &mut [Self]) { - radsort::sort_by_key(items, |item| item.distance); + // Key negated to match reversed SortKey ordering + radsort::sort_by_key(items, |item| -item.distance); } } From 9b0a02d59c5d1f45f10f7aff59353292cd831431 Mon Sep 17 00:00:00 2001 From: Robin KAY Date: Mon, 4 Jul 2022 18:30:29 +0100 Subject: [PATCH 6/8] Add inline annotation to distance() function. --- crates/bevy_render/src/rangefinder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_render/src/rangefinder.rs b/crates/bevy_render/src/rangefinder.rs index 5326104d6cc9b..0f375fad04408 100644 --- a/crates/bevy_render/src/rangefinder.rs +++ b/crates/bevy_render/src/rangefinder.rs @@ -17,6 +17,7 @@ impl ViewRangefinder3d { } /// Calculates the distance, or view-space Z value, for a transform + #[inline] 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 From f687c3d0e921d043c7c276f3566def1666f502db Mon Sep 17 00:00:00 2001 From: Robin KAY Date: Mon, 4 Jul 2022 22:37:43 +0100 Subject: [PATCH 7/8] Add rangefinder3d() function to ExtractedView. --- crates/bevy_pbr/src/material.rs | 3 +- crates/bevy_pbr/src/wireframe.rs | 3 +- crates/bevy_render/src/rangefinder.rs | 25 +++------- crates/bevy_render/src/view/mod.rs | 8 ++++ crates/bevy_render/src/view/rangefinder.rs | 54 ++++++++++++++++++++++ examples/shader/animate_shader.rs | 3 +- examples/shader/shader_instancing.rs | 3 +- 7 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 crates/bevy_render/src/view/rangefinder.rs diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index fa28aa89fe56f..b2581a9b2a161 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -21,7 +21,6 @@ use bevy_render::{ extract_component::ExtractComponentPlugin, mesh::{Mesh, MeshVertexBufferLayout}, prelude::Image, - rangefinder::ViewRangefinder3d, render_asset::{PrepareAssetLabel, RenderAssets}, render_phase::{ AddRenderCommand, DrawFunctions, EntityRenderCommand, RenderCommandResult, RenderPhase, @@ -349,7 +348,7 @@ pub fn queue_material_meshes( .get_id::>() .unwrap(); - let rangefinder = ViewRangefinder3d::from_view(view); + let rangefinder = view.rangefinder3d(); let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples); for visible_entity in &visible_entities.entities { diff --git a/crates/bevy_pbr/src/wireframe.rs b/crates/bevy_pbr/src/wireframe.rs index 4bea286a87086..0a215eab5cbba 100644 --- a/crates/bevy_pbr/src/wireframe.rs +++ b/crates/bevy_pbr/src/wireframe.rs @@ -6,7 +6,6 @@ use bevy_core_pipeline::core_3d::Opaque3d; use bevy_ecs::{prelude::*, reflect::ReflectComponent}; use bevy_reflect::std_traits::ReflectDefault; use bevy_reflect::{Reflect, TypeUuid}; -use bevy_render::rangefinder::ViewRangefinder3d; use bevy_render::{ extract_resource::{ExtractResource, ExtractResourcePlugin}, mesh::{Mesh, MeshVertexBufferLayout}, @@ -118,7 +117,7 @@ fn queue_wireframes( .unwrap(); let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples); for (view, visible_entities, mut opaque_phase) in views.iter_mut() { - let rangefinder = ViewRangefinder3d::from_view(view); + let rangefinder = view.rangefinder3d(); let add_render_phase = |(entity, mesh_handle, mesh_uniform): (Entity, &Handle, &MeshUniform)| { diff --git a/crates/bevy_render/src/rangefinder.rs b/crates/bevy_render/src/rangefinder.rs index 0f375fad04408..c11b8e679d4c7 100644 --- a/crates/bevy_render/src/rangefinder.rs +++ b/crates/bevy_render/src/rangefinder.rs @@ -1,16 +1,14 @@ use bevy_math::{Mat4, Vec4}; -use crate::view::ExtractedView; - /// A distance calculator for the draw order of [`PhaseItem`](crate::render_phase::PhaseItem)s. pub struct ViewRangefinder3d { inverse_view_row_2: Vec4, } impl ViewRangefinder3d { - /// Creates a rangefinder for a view - pub fn from_view(view: &ExtractedView) -> ViewRangefinder3d { - let inverse_view_matrix = view.transform.compute_matrix().inverse(); + /// Creates a 3D rangefinder for a view matrix + pub fn from_view_matrix(view_matrix: &Mat4) -> ViewRangefinder3d { + let inverse_view_matrix = view_matrix.inverse(); ViewRangefinder3d { inverse_view_row_2: inverse_view_matrix.row(2), } @@ -27,24 +25,13 @@ impl ViewRangefinder3d { #[cfg(test)] mod tests { - use bevy_math::{Mat4, Vec3}; - use bevy_transform::prelude::Transform; - - use crate::view::ExtractedView; - use super::ViewRangefinder3d; + use bevy_math::{Mat4, Vec3}; #[test] fn distance() { - let view = ExtractedView { - projection: Mat4::IDENTITY, - transform: Transform::identity() - .with_translation(Vec3::new(0.0, 0.0, -1.0)) - .into(), - width: 0, - height: 0, - }; - let rangefinder = ViewRangefinder3d::from_view(&view); + let view_matrix = Mat4::from_translation(Vec3::new(0.0, 0.0, -1.0)); + let rangefinder = ViewRangefinder3d::from_view_matrix(&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 2638e94d4581a..f6abdf02ecf05 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -12,6 +12,7 @@ use crate::{ camera::ExtractedCamera, extract_resource::{ExtractResource, ExtractResourcePlugin}, prelude::Image, + rangefinder::ViewRangefinder3d, render_asset::RenderAssets, render_resource::{DynamicUniformBuffer, ShaderType, Texture, TextureView}, renderer::{RenderDevice, RenderQueue}, @@ -81,6 +82,13 @@ pub struct ExtractedView { pub height: u32, } +impl ExtractedView { + /// Creates a 3D rangefinder for a view + pub fn rangefinder3d(&self) -> ViewRangefinder3d { + ViewRangefinder3d::from_view_matrix(&self.transform.compute_matrix()) + } +} + #[derive(Clone, ShaderType)] pub struct ViewUniform { view_proj: Mat4, diff --git a/crates/bevy_render/src/view/rangefinder.rs b/crates/bevy_render/src/view/rangefinder.rs new file mode 100644 index 0000000000000..0f375fad04408 --- /dev/null +++ b/crates/bevy_render/src/view/rangefinder.rs @@ -0,0 +1,54 @@ +use bevy_math::{Mat4, Vec4}; + +use crate::view::ExtractedView; + +/// A distance calculator for the draw order of [`PhaseItem`](crate::render_phase::PhaseItem)s. +pub struct ViewRangefinder3d { + inverse_view_row_2: Vec4, +} + +impl ViewRangefinder3d { + /// Creates a rangefinder for a view + pub fn from_view(view: &ExtractedView) -> ViewRangefinder3d { + let inverse_view_matrix = view.transform.compute_matrix().inverse(); + ViewRangefinder3d { + inverse_view_row_2: inverse_view_matrix.row(2), + } + } + + /// Calculates the distance, or view-space Z value, for a transform + #[inline] + 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)) + } +} + +#[cfg(test)] +mod tests { + use bevy_math::{Mat4, Vec3}; + use bevy_transform::prelude::Transform; + + use crate::view::ExtractedView; + + use super::ViewRangefinder3d; + + #[test] + fn distance() { + let view = ExtractedView { + projection: Mat4::IDENTITY, + transform: Transform::identity() + .with_translation(Vec3::new(0.0, 0.0, -1.0)) + .into(), + width: 0, + height: 0, + }; + let rangefinder = ViewRangefinder3d::from_view(&view); + assert_eq!(rangefinder.distance(&Mat4::IDENTITY), 1.0); + assert_eq!( + rangefinder.distance(&Mat4::from_translation(Vec3::new(0.0, 0.0, 1.0))), + 2.0 + ); + } +} diff --git a/examples/shader/animate_shader.rs b/examples/shader/animate_shader.rs index f900b7446258d..d06e0f43f648c 100644 --- a/examples/shader/animate_shader.rs +++ b/examples/shader/animate_shader.rs @@ -12,7 +12,6 @@ use bevy::{ prelude::*, render::{ mesh::MeshVertexBufferLayout, - rangefinder::ViewRangefinder3d, render_asset::RenderAssets, render_phase::{ AddRenderCommand, DrawFunctions, EntityRenderCommand, RenderCommandResult, RenderPhase, @@ -117,7 +116,7 @@ fn queue_custom( | MeshPipelineKey::from_primitive_topology(PrimitiveTopology::TriangleList); for (view, mut transparent_phase) in views.iter_mut() { - let rangefinder = ViewRangefinder3d::from_view(view); + let rangefinder = view.rangefinder3d(); for (entity, mesh_uniform, mesh_handle) in material_meshes.iter() { if let Some(mesh) = render_meshes.get(mesh_handle) { let pipeline = pipelines diff --git a/examples/shader/shader_instancing.rs b/examples/shader/shader_instancing.rs index 95a28ee23ebff..e497920629b4c 100644 --- a/examples/shader/shader_instancing.rs +++ b/examples/shader/shader_instancing.rs @@ -9,7 +9,6 @@ use bevy::{ render::{ extract_component::{ExtractComponent, ExtractComponentPlugin}, mesh::{GpuBufferInfo, MeshVertexBufferLayout}, - rangefinder::ViewRangefinder3d, render_asset::RenderAssets, render_phase::{ AddRenderCommand, DrawFunctions, EntityRenderCommand, RenderCommandResult, RenderPhase, @@ -118,7 +117,7 @@ fn queue_custom( let msaa_key = MeshPipelineKey::from_msaa_samples(msaa.samples); for (view, mut transparent_phase) in views.iter_mut() { - let rangefinder = ViewRangefinder3d::from_view(view); + let rangefinder = view.rangefinder3d(); for (entity, mesh_uniform, mesh_handle) in material_meshes.iter() { if let Some(mesh) = meshes.get(mesh_handle) { let key = From 906790fcc2675a67344ae7daa06d8baa19884505 Mon Sep 17 00:00:00 2001 From: Robin KAY Date: Mon, 4 Jul 2022 23:18:13 +0100 Subject: [PATCH 8/8] Remove accidently duplicated file. --- crates/bevy_render/src/view/rangefinder.rs | 54 ---------------------- 1 file changed, 54 deletions(-) delete mode 100644 crates/bevy_render/src/view/rangefinder.rs diff --git a/crates/bevy_render/src/view/rangefinder.rs b/crates/bevy_render/src/view/rangefinder.rs deleted file mode 100644 index 0f375fad04408..0000000000000 --- a/crates/bevy_render/src/view/rangefinder.rs +++ /dev/null @@ -1,54 +0,0 @@ -use bevy_math::{Mat4, Vec4}; - -use crate::view::ExtractedView; - -/// A distance calculator for the draw order of [`PhaseItem`](crate::render_phase::PhaseItem)s. -pub struct ViewRangefinder3d { - inverse_view_row_2: Vec4, -} - -impl ViewRangefinder3d { - /// Creates a rangefinder for a view - pub fn from_view(view: &ExtractedView) -> ViewRangefinder3d { - let inverse_view_matrix = view.transform.compute_matrix().inverse(); - ViewRangefinder3d { - inverse_view_row_2: inverse_view_matrix.row(2), - } - } - - /// Calculates the distance, or view-space Z value, for a transform - #[inline] - 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)) - } -} - -#[cfg(test)] -mod tests { - use bevy_math::{Mat4, Vec3}; - use bevy_transform::prelude::Transform; - - use crate::view::ExtractedView; - - use super::ViewRangefinder3d; - - #[test] - fn distance() { - let view = ExtractedView { - projection: Mat4::IDENTITY, - transform: Transform::identity() - .with_translation(Vec3::new(0.0, 0.0, -1.0)) - .into(), - width: 0, - height: 0, - }; - let rangefinder = ViewRangefinder3d::from_view(&view); - assert_eq!(rangefinder.distance(&Mat4::IDENTITY), 1.0); - assert_eq!( - rangefinder.distance(&Mat4::from_translation(Vec3::new(0.0, 0.0, 1.0))), - 2.0 - ); - } -}