Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1217,7 +1217,7 @@ pub fn queue_material_meshes(

match material.properties.render_phase_type {
RenderPhaseType::Transmissive => {
let distance = rangefinder.distance_translation(&mesh_instance.translation)
let distance = rangefinder.distance(&mesh_instance.center)
+ material.properties.depth_bias;
let Some(draw_function) = material
.properties
Expand Down Expand Up @@ -1304,7 +1304,7 @@ pub fn queue_material_meshes(
);
}
RenderPhaseType::Transparent => {
let distance = rangefinder.distance_translation(&mesh_instance.translation)
let distance = rangefinder.distance(&mesh_instance.center)
+ material.properties.depth_bias;
let Some(draw_function) = material
.properties
Expand Down
54 changes: 41 additions & 13 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,11 +715,11 @@ pub struct RenderMeshInstanceGpu {
/// uniform building paths.
#[deref]
pub shared: RenderMeshInstanceShared,
/// The translation of the mesh.
/// The representative position of the mesh instance in world-space.
///
/// This is the only part of the transform that we have to keep on CPU (for
/// distance sorting).
pub translation: Vec3,
/// This world-space center is used as a spatial proxy for view-dependent
/// operations such as distance computation and render-order sorting.
pub center: Vec3,
/// The index of the [`MeshInputUniform`] in the buffer.
pub current_uniform_index: NonMaxU32,
}
Expand All @@ -740,6 +740,12 @@ pub struct RenderMeshInstanceShared {
pub tag: u32,
/// Render layers that this mesh instance belongs to.
pub render_layers: Option<RenderLayers>,
/// A representative position of the mesh instance in local space,
/// derived from its axis-aligned bounding box.
///
/// This value is typically used as a spatial proxy for operations such as
/// view-dependent sorting (e.g., transparent object ordering).
pub center: Vec3,
}

/// Information that is gathered during the parallel portion of mesh extraction
Expand Down Expand Up @@ -832,6 +838,7 @@ impl RenderMeshInstanceShared {
not_shadow_caster: bool,
no_automatic_batching: bool,
render_layers: Option<&RenderLayers>,
aabb: Option<&Aabb>,
) -> Self {
Self::for_cpu_building(
previous_transform,
Expand All @@ -841,6 +848,7 @@ impl RenderMeshInstanceShared {
not_shadow_caster,
no_automatic_batching,
render_layers,
aabb,
)
}

Expand All @@ -853,6 +861,7 @@ impl RenderMeshInstanceShared {
not_shadow_caster: bool,
no_automatic_batching: bool,
render_layers: Option<&RenderLayers>,
aabb: Option<&Aabb>,
) -> Self {
let mut mesh_instance_flags = RenderMeshInstanceFlags::empty();
mesh_instance_flags.set(RenderMeshInstanceFlags::SHADOW_CASTER, !not_shadow_caster);
Expand All @@ -872,6 +881,7 @@ impl RenderMeshInstanceShared {
lightmap_slab_index: None,
tag: tag.map_or(0, |i| **i),
render_layers: render_layers.cloned(),
center: aabb.map_or(Vec3::ZERO, |aabb| aabb.center.into()),
}
}

Expand Down Expand Up @@ -959,12 +969,19 @@ impl RenderMeshInstancesCpu {
}

fn render_mesh_queue_data(&self, entity: MainEntity) -> Option<RenderMeshQueueData<'_>> {
self.get(&entity)
.map(|render_mesh_instance| RenderMeshQueueData {
self.get(&entity).map(|render_mesh_instance| {
let world_from_local = &render_mesh_instance.transforms.world_from_local;
let center = world_from_local
.matrix3
.mul_vec3(render_mesh_instance.shared.center)
+ world_from_local.translation;

RenderMeshQueueData {
shared: &render_mesh_instance.shared,
translation: render_mesh_instance.transforms.world_from_local.translation,
center,
current_uniform_index: InputUniformIndex::default(),
})
}
})
}

/// Inserts the given flags into the render mesh instance data for the given
Expand All @@ -986,7 +1003,7 @@ impl RenderMeshInstancesGpu {
self.get(&entity)
.map(|render_mesh_instance| RenderMeshQueueData {
shared: &render_mesh_instance.shared,
translation: render_mesh_instance.translation,
center: render_mesh_instance.center,
current_uniform_index: InputUniformIndex(
render_mesh_instance.current_uniform_index.into(),
),
Expand Down Expand Up @@ -1191,6 +1208,10 @@ impl RenderMeshInstanceGpuBuilder {

// Did the last frame contain this entity as well?
let current_uniform_index;
let world_from_local = &self.world_from_local;
let center =
world_from_local.matrix3.mul_vec3(self.shared.center) + world_from_local.translation;

match render_mesh_instances.entry(entity) {
Entry::Occupied(mut occupied_entry) => {
// Yes, it did. Replace its entry with the new one.
Expand All @@ -1210,8 +1231,8 @@ impl RenderMeshInstanceGpuBuilder {

occupied_entry.replace_entry_with(|_, _| {
Some(RenderMeshInstanceGpu {
translation: self.world_from_local.translation,
shared: self.shared,
center,
current_uniform_index: NonMaxU32::new(current_uniform_index)
.unwrap_or_default(),
})
Expand All @@ -1223,8 +1244,8 @@ impl RenderMeshInstanceGpuBuilder {
current_uniform_index = current_input_buffer.add(mesh_input_uniform);

vacant_entry.insert(RenderMeshInstanceGpu {
translation: self.world_from_local.translation,
shared: self.shared,
center,
current_uniform_index: NonMaxU32::new(current_uniform_index)
.unwrap_or_default(),
});
Expand Down Expand Up @@ -1296,8 +1317,11 @@ pub struct RenderMeshQueueData<'a> {
/// General information about the mesh instance.
#[deref]
pub shared: &'a RenderMeshInstanceShared,
/// The translation of the mesh instance.
pub translation: Vec3,
/// The representative position of the mesh instance in world-space.
///
/// This world-space center is used as a spatial proxy for view-dependent
/// operations such as distance computation and render-order sorting.
pub center: Vec3,
/// The index of the [`MeshInputUniform`] in the GPU buffer for this mesh
/// instance.
pub current_uniform_index: InputUniformIndex,
Expand Down Expand Up @@ -1334,6 +1358,7 @@ pub fn extract_meshes_for_cpu_building(
Has<NoAutomaticBatching>,
Has<VisibilityRange>,
Option<&RenderLayers>,
Option<&Aabb>,
)>,
>,
) {
Expand All @@ -1354,6 +1379,7 @@ pub fn extract_meshes_for_cpu_building(
no_automatic_batching,
visibility_range,
render_layers,
aabb,
)| {
if !view_visibility.get() {
return;
Expand Down Expand Up @@ -1387,6 +1413,7 @@ pub fn extract_meshes_for_cpu_building(
not_shadow_caster,
no_automatic_batching,
render_layers,
aabb,
);

let world_from_local = transform.affine();
Expand Down Expand Up @@ -1593,6 +1620,7 @@ fn extract_mesh_for_gpu_building(
not_shadow_caster,
no_automatic_batching,
render_layers,
aabb,
);

let lightmap_uv_rect = pack_lightmap_uv_rect(lightmap.map(|lightmap| lightmap.uv_rect));
Expand Down
27 changes: 8 additions & 19 deletions crates/bevy_render/src/render_phase/rangefinder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,25 @@ impl ViewRangefinder3d {
}
}

/// Calculates the distance, or view-space `Z` value, for the given `translation`.
/// Calculates the distance, or view-space `Z` value, for the given world-space `position`.
#[inline]
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.view_from_world_row_2.dot(translation.extend(1.0))
}

/// Calculates the distance, or view-space `Z` value, for the given `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.view_from_world_row_2.dot(transform.col(3))
pub fn distance(&self, position: &Vec3) -> f32 {
// NOTE: row 2 of the inverse view matrix dotted with the world-space position
// gives the z component of the point in view-space
self.view_from_world_row_2.dot(position.extend(1.0))
}
}

#[cfg(test)]
mod tests {
use super::ViewRangefinder3d;
use bevy_math::{Affine3A, Mat4, Vec3};
use bevy_math::{Affine3A, Vec3};

#[test]
fn distance() {
let view_matrix = Affine3A::from_translation(Vec3::new(0.0, 0.0, -1.0));
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))),
2.0
);
assert_eq!(rangefinder.distance(&Vec3::new(0., 0., 0.)), 1.0);
assert_eq!(rangefinder.distance(&Vec3::new(0., 0., 1.)), 2.0);
}
}
2 changes: 1 addition & 1 deletion examples/shader_advanced/custom_render_phase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ fn queue_custom_meshes(
continue;
}
};
let distance = rangefinder.distance_translation(&mesh_instance.translation);
let distance = rangefinder.distance(&mesh_instance.center);
// At this point we have all the data we need to create a phase item and add it to our
// phase
custom_phase.add(Stencil3d {
Expand Down
2 changes: 1 addition & 1 deletion examples/shader_advanced/custom_shader_instancing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ fn queue_custom(
entity: (entity, *main_entity),
pipeline,
draw_function: draw_custom,
distance: rangefinder.distance_translation(&mesh_instance.translation),
distance: rangefinder.distance(&mesh_instance.center),
batch_range: 0..1,
extra_index: PhaseItemExtraIndex::None,
indexed: true,
Expand Down