forked from bevyengine/bevy
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ViewRangefinder3d to reduce boilerplate when enqueuing standard 3…
…D PhaseItems. (bevyengine#5014) # Objective Reduce the boilerplate code needed to make draw order sorting work correctly when queuing items through new common functionality. Also fix several instances in the bevy code-base (mostly examples) where this boilerplate appears to be incorrect. ## Solution - Moved the logic for handling back-to-front vs front-to-back draw ordering into the PhaseItems by inverting the sort key ordering of Opaque3d and AlphaMask3d. The means that all the standard 3d rendering phases measure distance in the same way. Clients of these structs no longer need to know to negate the distance. - Added a new utility struct, ViewRangefinder3d, which encapsulates the maths needed to calculate a "distance" from an ExtractedView and a mesh's transform matrix. - Converted all the occurrences of the distance calculations in Bevy and its examples to use ViewRangefinder3d. Several of these occurrences appear to be buggy because they don't invert the view matrix or don't negate the distance where appropriate. This leads me to the view that Bevy should expose a facility to correctly perform this calculation. ## Migration Guide Code which creates Opaque3d, AlphaMask3d, or Transparent3d phase items _should_ use ViewRangefinder3d to calculate the distance value. Code which manually calculated the distance for Opaque3d or AlphaMask3d phase items and correctly negated the z value will no longer depth sort correctly. However, incorrect depth sorting for these types will not impact the rendered output as sorting is only a performance optimisation when drawing with depth-testing enabled. Code which manually calculated the distance for Transparent3d phase items will continue to work as before.
- Loading branch information
Showing
8 changed files
with
74 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
use bevy_math::{Mat4, Vec4}; | ||
|
||
/// 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 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), | ||
} | ||
} | ||
|
||
/// 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 super::ViewRangefinder3d; | ||
use bevy_math::{Mat4, Vec3}; | ||
|
||
#[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); | ||
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 | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters