Skip to content

Commit b539af9

Browse files
committed
added frustum culling implementation for sprites and sprite atlases
1 parent 89a41bc commit b539af9

File tree

17 files changed

+218
-115
lines changed

17 files changed

+218
-115
lines changed

crates/bevy_pbr/src/entity.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{light::Light, material::StandardMaterial, render_graph::FORWARD_PIPE
22
use bevy_asset::Handle;
33
use bevy_ecs::Bundle;
44
use bevy_render::{
5-
draw::Draw,
5+
draw::{Draw, Transparent},
66
mesh::Mesh,
77
pipeline::{RenderPipeline, RenderPipelines},
88
prelude::Visible,
@@ -18,6 +18,7 @@ pub struct PbrBundle {
1818
pub main_pass: MainPass,
1919
pub draw: Draw,
2020
pub visible: Visible,
21+
pub transparent: Transparent,
2122
pub render_pipelines: RenderPipelines,
2223
pub transform: Transform,
2324
pub global_transform: GlobalTransform,
@@ -31,6 +32,7 @@ impl Default for PbrBundle {
3132
)]),
3233
mesh: Default::default(),
3334
visible: Default::default(),
35+
transparent: Default::default(),
3436
material: Default::default(),
3537
main_pass: Default::default(),
3638
draw: Default::default(),

crates/bevy_render/src/camera/visible_entities.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{Camera, DepthCalculation};
2-
use crate::prelude::Visible;
2+
use crate::{draw::Transparent, prelude::Visible};
33
use bevy_core::FloatOrd;
44
use bevy_ecs::{Entity, Query, With};
55
use bevy_reflect::{Reflect, ReflectComponent};
@@ -204,8 +204,8 @@ pub fn visible_entities_system(
204204
&mut VisibleEntities,
205205
Option<&RenderLayers>,
206206
)>,
207-
visible_query: Query<(Entity, &Visible, Option<&RenderLayers>)>,
208-
visible_transform_query: Query<&GlobalTransform, With<Visible>>,
207+
visible_query: Query<(Entity, Option<&RenderLayers>, Option<&Transparent>), With<Visible>>,
208+
visible_transform_query: Query<(&GlobalTransform, Option<&Transparent>), With<Visible>>,
209209
) {
210210
for (camera, camera_global_transform, mut visible_entities, maybe_camera_mask) in
211211
camera_query.iter_mut()
@@ -216,17 +216,16 @@ pub fn visible_entities_system(
216216

217217
let mut no_transform_order = 0.0;
218218
let mut transparent_entities = Vec::new();
219-
for (entity, visible, maybe_entity_mask) in visible_query.iter() {
220-
if !visible.is_visible {
221-
continue;
222-
}
223219

220+
for (entity, maybe_entity_mask, transparent) in visible_query.iter() {
224221
let entity_mask = maybe_entity_mask.copied().unwrap_or_default();
225222
if !camera_mask.intersects(&entity_mask) {
226223
continue;
227224
}
228225

229-
let order = if let Ok(global_transform) = visible_transform_query.get(entity) {
226+
let order = if let Ok(global_transform) =
227+
visible_transform_query.get_component::<GlobalTransform>(entity)
228+
{
230229
let position = global_transform.translation;
231230
// smaller distances are sorted to lower indices by using the distance from the camera
232231
FloatOrd(match camera.depth_calculation {
@@ -239,7 +238,7 @@ pub fn visible_entities_system(
239238
order
240239
};
241240

242-
if visible.is_transparent {
241+
if let Some(_) = transparent {
243242
transparent_entities.push(VisibleEntity { entity, order })
244243
} else {
245244
visible_entities.value.push(VisibleEntity { entity, order })

crates/bevy_render/src/draw.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,21 @@ pub enum RenderCommand {
4848

4949
#[derive(Debug, Clone, Reflect)]
5050
#[reflect(Component)]
51-
pub struct Visible {
52-
pub is_visible: bool,
53-
// TODO: consider moving this to materials
54-
pub is_transparent: bool,
55-
}
51+
pub struct Visible;
5652

5753
impl Default for Visible {
5854
fn default() -> Self {
59-
Visible {
60-
is_visible: true,
61-
is_transparent: false,
62-
}
55+
Visible
56+
}
57+
}
58+
59+
#[derive(Debug, Clone, Reflect)]
60+
#[reflect(Component)]
61+
pub struct Transparent;
62+
63+
impl Default for Transparent {
64+
fn default() -> Self {
65+
Transparent
6366
}
6467
}
6568

crates/bevy_render/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub mod texture;
1313

1414
use bevy_ecs::{IntoExclusiveSystem, IntoSystem, SystemStage};
1515
use bevy_reflect::RegisterTypeBuilder;
16-
use draw::Visible;
16+
use draw::{Transparent, Visible};
1717
pub use once_cell;
1818

1919
pub mod prelude {
@@ -129,6 +129,7 @@ impl Plugin for RenderPlugin {
129129
.register_type::<Camera>()
130130
.register_type::<Draw>()
131131
.register_type::<Visible>()
132+
.register_type::<Transparent>()
132133
.register_type::<RenderPipelines>()
133134
.register_type::<OrthographicProjection>()
134135
.register_type::<PerspectiveProjection>()

crates/bevy_render/src/pipeline/render_pipelines.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{
66
renderer::RenderResourceBindings,
77
};
88
use bevy_asset::{Assets, Handle};
9-
use bevy_ecs::{Query, Res, ResMut};
9+
use bevy_ecs::{Query, Res, ResMut, With};
1010
use bevy_reflect::{Reflect, ReflectComponent};
1111
use bevy_utils::HashSet;
1212

@@ -82,13 +82,9 @@ pub fn draw_render_pipelines_system(
8282
mut render_resource_bindings: ResMut<RenderResourceBindings>,
8383
msaa: Res<Msaa>,
8484
meshes: Res<Assets<Mesh>>,
85-
mut query: Query<(&mut Draw, &mut RenderPipelines, &Handle<Mesh>, &Visible)>,
85+
mut query: Query<(&mut Draw, &mut RenderPipelines, &Handle<Mesh>), With<Visible>>,
8686
) {
87-
for (mut draw, mut render_pipelines, mesh_handle, visible) in query.iter_mut() {
88-
if !visible.is_visible {
89-
continue;
90-
}
91-
87+
for (mut draw, mut render_pipelines, mesh_handle) in query.iter_mut() {
9288
// don't render if the mesh isn't loaded yet
9389
let mesh = if let Some(mesh) = meshes.get(mesh_handle) {
9490
mesh

crates/bevy_render/src/render_graph/nodes/pass_node.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,8 @@ where
237237
continue;
238238
};
239239

240-
if let Ok(visible) = world.get::<Visible>(visible_entity.entity) {
241-
if !visible.is_visible {
242-
continue;
243-
}
240+
if let Err(_) = world.get::<Visible>(visible_entity.entity) {
241+
continue;
244242
}
245243

246244
// each Draw component contains an ordered list of render commands. we turn those into actual render commands here

crates/bevy_render/src/render_graph/nodes/render_resources_node.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,11 @@ fn render_resources_node_system<T: RenderResources>(
437437
mut entities_waiting_for_textures: Local<Vec<Entity>>,
438438
render_resource_context: Res<Box<dyn RenderResourceContext>>,
439439
mut queries: QuerySet<(
440-
Query<(Entity, &T, &Visible, &mut RenderPipelines), Or<(Changed<T>, Changed<Visible>)>>,
441-
Query<(Entity, &T, &Visible, &mut RenderPipelines)>,
440+
Query<
441+
(Entity, &T, Option<&Visible>, &mut RenderPipelines),
442+
Or<(Changed<T>, Changed<Visible>)>,
443+
>,
444+
Query<(Entity, &T, &mut RenderPipelines), With<Visible>>,
442445
)>,
443446
) {
444447
let state = state.deref_mut();
@@ -456,9 +459,7 @@ fn render_resources_node_system<T: RenderResources>(
456459

457460
// handle entities that were waiting for texture loads on the last update
458461
for entity in std::mem::take(&mut *entities_waiting_for_textures) {
459-
if let Ok((entity, uniforms, _visible, mut render_pipelines)) =
460-
queries.q1_mut().get_mut(entity)
461-
{
462+
if let Ok((entity, uniforms, mut render_pipelines)) = queries.q1_mut().get_mut(entity) {
462463
if !setup_uniform_texture_resources::<T>(
463464
&uniforms,
464465
render_resource_context,
@@ -470,7 +471,7 @@ fn render_resources_node_system<T: RenderResources>(
470471
}
471472

472473
for (entity, uniforms, visible, mut render_pipelines) in queries.q0_mut().iter_mut() {
473-
if !visible.is_visible {
474+
if let None = visible {
474475
continue;
475476
}
476477
uniform_buffer_arrays.prepare_uniform_buffers(entity, uniforms);
@@ -497,13 +498,7 @@ fn render_resources_node_system<T: RenderResources>(
497498
&mut |mut staging_buffer, _render_resource_context| {
498499
// if the buffer array was resized, write all entities to the new buffer, otherwise only write changes
499500
if resized {
500-
for (entity, uniforms, visible, mut render_pipelines) in
501-
queries.q1_mut().iter_mut()
502-
{
503-
if !visible.is_visible {
504-
continue;
505-
}
506-
501+
for (entity, uniforms, mut render_pipelines) in queries.q1_mut().iter_mut() {
507502
state.uniform_buffer_arrays.write_uniform_buffers(
508503
entity,
509504
&uniforms,
@@ -517,7 +512,7 @@ fn render_resources_node_system<T: RenderResources>(
517512
for (entity, uniforms, visible, mut render_pipelines) in
518513
queries.q0_mut().iter_mut()
519514
{
520-
if !visible.is_visible {
515+
if let None = visible {
521516
continue;
522517
}
523518

crates/bevy_render/src/shader/shader_defs.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use bevy_asset::{Asset, Assets, Handle};
22

3-
use crate::{pipeline::RenderPipelines, Texture};
3+
use crate::{pipeline::RenderPipelines, prelude::Visible, Texture};
44
pub use bevy_derive::ShaderDefs;
5-
use bevy_ecs::{Query, Res};
5+
use bevy_ecs::{Query, Res, With};
66

77
/// Something that can either be "defined" or "not defined". This is used to determine if a "shader def" should be considered "defined"
88
pub trait ShaderDef {
@@ -60,7 +60,7 @@ impl ShaderDef for Option<Handle<Texture>> {
6060
}
6161

6262
/// Updates [RenderPipelines] with the latest [ShaderDefs]
63-
pub fn shader_defs_system<T>(mut query: Query<(&T, &mut RenderPipelines)>)
63+
pub fn shader_defs_system<T>(mut query: Query<(&T, &mut RenderPipelines), With<Visible>>)
6464
where
6565
T: ShaderDefs + Send + Sync + 'static,
6666
{
@@ -93,7 +93,7 @@ pub fn clear_shader_defs_system(mut query: Query<&mut RenderPipelines>) {
9393
/// Updates [RenderPipelines] with the latest [ShaderDefs] from a given asset type
9494
pub fn asset_shader_defs_system<T: Asset>(
9595
assets: Res<Assets<T>>,
96-
mut query: Query<(&Handle<T>, &mut RenderPipelines)>,
96+
mut query: Query<(&Handle<T>, &mut RenderPipelines), With<Visible>>,
9797
) where
9898
T: ShaderDefs + Send + Sync + 'static,
9999
{

crates/bevy_sprite/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.4.0", features = ["bevy"
2424
bevy_render = { path = "../bevy_render", version = "0.4.0" }
2525
bevy_transform = { path = "../bevy_transform", version = "0.4.0" }
2626
bevy_utils = { path = "../bevy_utils", version = "0.4.0" }
27+
bevy_window = { path = "../bevy_window", version = "0.4.0" }
2728

2829
# other
2930
rectangle-pack = "0.2"

crates/bevy_sprite/src/entity.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
use bevy_asset::Handle;
66
use bevy_ecs::Bundle;
77
use bevy_render::{
8+
draw::Transparent,
89
mesh::Mesh,
910
pipeline::{RenderPipeline, RenderPipelines},
1011
prelude::{Draw, Visible},
@@ -20,6 +21,7 @@ pub struct SpriteBundle {
2021
pub main_pass: MainPass,
2122
pub draw: Draw,
2223
pub visible: Visible,
24+
pub transparent: Transparent,
2325
pub render_pipelines: RenderPipelines,
2426
pub transform: Transform,
2527
pub global_transform: GlobalTransform,
@@ -32,10 +34,8 @@ impl Default for SpriteBundle {
3234
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
3335
SPRITE_PIPELINE_HANDLE.typed(),
3436
)]),
35-
visible: Visible {
36-
is_transparent: true,
37-
..Default::default()
38-
},
37+
visible: Visible,
38+
transparent: Transparent,
3939
main_pass: MainPass,
4040
draw: Default::default(),
4141
sprite: Default::default(),
@@ -57,6 +57,7 @@ pub struct SpriteSheetBundle {
5757
/// Data pertaining to how the sprite is drawn on the screen
5858
pub draw: Draw,
5959
pub visible: Visible,
60+
pub transparent: Transparent,
6061
pub render_pipelines: RenderPipelines,
6162
pub main_pass: MainPass,
6263
pub mesh: Handle<Mesh>, // TODO: maybe abstract this out
@@ -70,10 +71,8 @@ impl Default for SpriteSheetBundle {
7071
render_pipelines: RenderPipelines::from_pipelines(vec![RenderPipeline::new(
7172
SPRITE_SHEET_PIPELINE_HANDLE.typed(),
7273
)]),
73-
visible: Visible {
74-
is_transparent: true,
75-
..Default::default()
76-
},
74+
visible: Visible,
75+
transparent: Transparent,
7776
main_pass: MainPass,
7877
mesh: QUAD_HANDLE.typed(),
7978
draw: Default::default(),

0 commit comments

Comments
 (0)