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] - Frustum culling #2861

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
563e396
Add primitives to support frustum culling
superdump Sep 14, 2021
0371410
Copy over RenderLayers from the old renderer
superdump Sep 14, 2021
bc9faf3
Add functionality to Mesh to compute an AABB
superdump Sep 14, 2021
b44698b
Load AABBs from glTF models
superdump Sep 14, 2021
dd47c76
Add far() method to CameraProjection trait
superdump Sep 14, 2021
087fd7b
Add visibility types and systems
superdump Sep 14, 2021
ea546a9
Add VisibleEntities and Frustum to camera and light bundles as approp…
superdump Sep 14, 2021
b4fd252
Add Visibility and ComputedVisibility to entities to be drawn
superdump Sep 14, 2021
34f785c
Extract mesh/sprite entities based on ComputedVisibility
superdump Sep 14, 2021
c1954bc
Extract VisibleEntities for cameras
superdump Sep 14, 2021
2cb2490
Enable VisibilityPlugin within the ViewPlugin
superdump Sep 14, 2021
2a4cf48
Remove unnecessary Camera.far member
superdump Sep 14, 2021
27287cd
Pass the plane normal to Aabb::relative_radius()
superdump Sep 14, 2021
273d8fa
Add sphere - obb intsersection test
superdump Sep 14, 2021
69d2440
Add a CubeFrusta type containing 6 frusta for cube maps
superdump Sep 14, 2021
e25b1da
Add CubeFrustaVisibleEntities for use with cube maps
superdump Sep 14, 2021
69d824d
Add culling for lights
superdump Sep 14, 2021
7c03a3d
Minor renaming
superdump Sep 15, 2021
69845d2
Unify bounded entity query into visible entity query for performance
superdump Sep 15, 2021
e0c88f4
Register types to support loading from glTF models
superdump Sep 16, 2021
d5c2c2c
Fix the logic of the point light sphere vs mesh obb test
superdump Sep 16, 2021
1fe1df6
Remove unnecessary With<PointLight> in check_light_visibility query
superdump Sep 23, 2021
5727a9d
Address review comments
superdump Nov 7, 2021
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
Prev Previous commit
Next Next commit
Minor renaming
CubeFrusta -> CubemapFrusta
CubeFrustaVisibleEntities -> CubemapVisibleEntities
  • Loading branch information
superdump committed Nov 4, 2021
commit 7c03a3d7e4aebbc031ec49fcd5448962578f80d8
20 changes: 10 additions & 10 deletions pipelined/bevy_pbr2/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bevy_asset::Handle;
use bevy_ecs::bundle::Bundle;
use bevy_render2::{
mesh::Mesh,
primitives::{CubeFrusta, Frustum},
primitives::{CubemapFrusta, Frustum},
view::{ComputedVisibility, Visibility, VisibleEntities},
};
use bevy_transform::components::{GlobalTransform, Transform};
Expand Down Expand Up @@ -34,34 +34,34 @@ impl Default for PbrBundle {
}

#[derive(Clone, Debug, Default)]
pub struct CubeFrustaVisibleEntities {
cube_frusta_visible_entities: [VisibleEntities; 6],
pub struct CubemapVisibleEntities {
data: [VisibleEntities; 6],
}

impl CubeFrustaVisibleEntities {
impl CubemapVisibleEntities {
pub fn get(&self, i: usize) -> &VisibleEntities {
&self.cube_frusta_visible_entities[i]
&self.data[i]
}

pub fn get_mut(&mut self, i: usize) -> &mut VisibleEntities {
&mut self.cube_frusta_visible_entities[i]
&mut self.data[i]
}

pub fn iter(&self) -> impl DoubleEndedIterator<Item = &VisibleEntities> {
self.cube_frusta_visible_entities.iter()
self.data.iter()
}

pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut VisibleEntities> {
self.cube_frusta_visible_entities.iter_mut()
self.data.iter_mut()
}
}

/// A component bundle for "point light" entities
#[derive(Debug, Bundle, Default)]
pub struct PointLightBundle {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all lights need to cast shadows, and given how expensive point light shadows are, its probably worth adding a way to disable shadows for lights. This should also skip entity visibility calculations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have another branch for that that comes when I knew it would be needed - before clustered forward rendering. Can we add it in after #3072 or do I have to move it in here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm definitely down to wait!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do it in whatever order works best for you :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I'll wait on this one as it's coming just after depth prepass and alpha modes. Thanks. :)

pub point_light: PointLight,
pub cube_frusta_visible_entities: CubeFrustaVisibleEntities,
pub cube_frusta: CubeFrusta,
pub cubemap_visible_entities: CubemapVisibleEntities,
pub cubemap_frusta: CubemapFrusta,
pub transform: Transform,
pub global_transform: GlobalTransform,
}
Expand Down
34 changes: 17 additions & 17 deletions pipelined/bevy_pbr2/src/render/light.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
AmbientLight, CubeFrustaVisibleEntities, DirectionalLight, DirectionalLightShadowMap,
MeshUniform, NotShadowCaster, PbrPipeline, PointLight, PointLightShadowMap, TransformBindGroup,
AmbientLight, CubemapVisibleEntities, DirectionalLight, DirectionalLightShadowMap, MeshUniform,
NotShadowCaster, PbrPipeline, PointLight, PointLightShadowMap, TransformBindGroup,
SHADOW_SHADER_HANDLE,
};
use bevy_asset::Handle;
Expand All @@ -15,7 +15,7 @@ use bevy_render2::{
camera::CameraProjection,
color::Color,
mesh::Mesh,
primitives::{Aabb, CubeFrusta, Frustum, Sphere},
primitives::{Aabb, CubemapFrusta, Frustum, Sphere},
render_asset::RenderAssets,
render_component::DynamicUniformIndex,
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
Expand Down Expand Up @@ -304,22 +304,22 @@ pub fn update_directional_light_frusta(
}

pub fn update_point_light_frusta(
mut views: Query<(&GlobalTransform, &PointLight, &mut CubeFrusta)>,
mut views: Query<(&GlobalTransform, &PointLight, &mut CubemapFrusta)>,
) {
let projection = Mat4::perspective_infinite_reverse_rh(std::f32::consts::FRAC_PI_2, 1.0, 0.1);
let view_rotations = CUBE_MAP_FACES
.iter()
.map(|CubeMapFace { target, up }| GlobalTransform::identity().looking_at(*target, *up))
.collect::<Vec<_>>();

for (transform, point_light, mut cube_frusta) in views.iter_mut() {
for (transform, point_light, mut cubemap_frusta) in views.iter_mut() {
// 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_backward = transform.back();

for (view_rotation, frustum) in view_rotations.iter().zip(cube_frusta.iter_mut()) {
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();

Expand All @@ -338,8 +338,8 @@ pub fn check_light_visibility(
(
&PointLight,
&GlobalTransform,
&CubeFrusta,
&mut CubeFrustaVisibleEntities,
&CubemapFrusta,
&mut CubemapVisibleEntities,
Option<&RenderLayers>,
),
With<PointLight>,
Expand Down Expand Up @@ -392,10 +392,10 @@ pub fn check_light_visibility(
}

// Point lights
for (point_light, transform, cube_frusta, mut cube_frusta_visible_entities, maybe_view_mask) in
for (point_light, transform, cubemap_frusta, mut cubemap_visible_entities, maybe_view_mask) in
point_lights.iter_mut()
{
for visible_entities in cube_frusta_visible_entities.iter_mut() {
for visible_entities in cubemap_visible_entities.iter_mut() {
visible_entities.entities.clear();
}
let view_mask = maybe_view_mask.copied().unwrap_or_default();
Expand All @@ -422,9 +422,9 @@ pub fn check_light_visibility(
if light_sphere.intersects_obb(aabb, &model_to_world) {
continue;
}
for (frustum, visible_entities) in cube_frusta
for (frustum, visible_entities) in cubemap_frusta
.iter()
.zip(cube_frusta_visible_entities.iter_mut())
.zip(cubemap_visible_entities.iter_mut())
{
if frustum.intersects_obb(aabb, &model_to_world) {
computed_visibility.is_visible = true;
Expand All @@ -433,7 +433,7 @@ pub fn check_light_visibility(
}
} else {
computed_visibility.is_visible = true;
for visible_entities in cube_frusta_visible_entities.iter_mut() {
for visible_entities in cubemap_visible_entities.iter_mut() {
visible_entities.entities.push(VisibleEntity { entity })
}
}
Expand All @@ -452,7 +452,7 @@ pub fn extract_lights(
point_lights: Query<(
Entity,
&PointLight,
&CubeFrustaVisibleEntities,
&CubemapVisibleEntities,
&GlobalTransform,
)>,
directional_lights: Query<(
Expand All @@ -478,7 +478,7 @@ pub fn extract_lights(
// NOTE: When using various PCF kernel sizes, this will need to be adjusted, according to:
// https://catlikecoding.com/unity/tutorials/custom-srp/point-and-spot-shadows/
let point_light_texel_size = 2.0 / point_light_shadow_map.size as f32;
for (entity, point_light, cube_frusta_visible_entities, transform) in point_lights.iter() {
for (entity, point_light, cubemap_visible_entities, transform) in point_lights.iter() {
commands.get_or_spawn(entity).insert_bundle((
ExtractedPointLight {
color: point_light.color,
Expand All @@ -495,7 +495,7 @@ pub fn extract_lights(
* point_light_texel_size
* std::f32::consts::SQRT_2,
},
cube_frusta_visible_entities.clone(),
cubemap_visible_entities.clone(),
));
}
for (entity, directional_light, visible_entities, transform) in directional_lights.iter() {
Expand Down Expand Up @@ -882,7 +882,7 @@ pub fn queue_shadows(
mut pipeline_cache: ResMut<RenderPipelineCache>,
mut view_lights: Query<&ViewLights>,
mut view_light_shadow_phases: Query<(&LightEntity, &mut RenderPhase<Shadow>)>,
point_light_entities: Query<&CubeFrustaVisibleEntities, With<ExtractedPointLight>>,
point_light_entities: Query<&CubemapVisibleEntities, With<ExtractedPointLight>>,
directional_light_entities: Query<&VisibleEntities, With<ExtractedDirectionalLight>>,
) {
for view_lights in view_lights.iter_mut() {
Expand Down
4 changes: 2 additions & 2 deletions pipelined/bevy_render2/src/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,11 @@ impl Frustum {
}

#[derive(Debug, Default)]
pub struct CubeFrusta {
pub struct CubemapFrusta {
pub frusta: [Frustum; 6],
}

impl CubeFrusta {
impl CubemapFrusta {
pub fn iter(&self) -> impl DoubleEndedIterator<Item = &Frustum> {
self.frusta.iter()
}
Expand Down