mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 12:13:25 +00:00
Remove components if not extracted (#15948)
# Objective - Fixes https://github.com/bevyengine/bevy/issues/15871 (Camera is done in #15946) ## Solution - Do the same as #15904 for other extraction systems - Added missing `SyncComponentPlugin` for DOF, TAA, and SSAO (According to the [documentation](https://dev-docs.bevyengine.org/bevy/render/sync_component/struct.SyncComponentPlugin.html), this plugin "needs to be added for manual extraction implementations." We may need to check this is done.) ## Testing Modified example locally to add toggles if not exist. - [x] DOF - toggling DOF component and perspective in `depth_of_field` example - [x] TAA - toggling `Camera.is_active` and TAA component - [x] clusters - not entirely sure, toggling `Camera.is_active` in `many_lights` example (no crash/glitch even without this PR) - [x] previous_view - toggling `Camera.is_active` in `skybox` (no crash/glitch even without this PR) - [x] lights - toggling `Visibility` of `DirectionalLight` in `lighting` example - [x] SSAO - toggling `Camera.is_active` and SSAO component in `ssao` example - [x] default UI camera view - toggling `Camera.is_active` (nop without #15946 because UI defaults to some camera even if `DefaultCameraView` is not there) - [x] volumetric fog - toggling existence of volumetric light. Looks like optimization, no change in behavior/visuals
This commit is contained in:
parent
fe7f98f7f0
commit
61350cd36f
9 changed files with 99 additions and 41 deletions
|
@ -46,6 +46,7 @@ use bevy_render::{
|
|||
TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, TextureUsages,
|
||||
},
|
||||
renderer::{RenderContext, RenderDevice},
|
||||
sync_component::SyncComponentPlugin,
|
||||
sync_world::RenderEntity,
|
||||
texture::{BevyDefault, CachedTexture, TextureCache},
|
||||
view::{
|
||||
|
@ -211,6 +212,8 @@ impl Plugin for DepthOfFieldPlugin {
|
|||
app.register_type::<DepthOfFieldMode>();
|
||||
app.add_plugins(UniformComponentPlugin::<DepthOfFieldUniform>::default());
|
||||
|
||||
app.add_plugins(SyncComponentPlugin::<DepthOfField>::default());
|
||||
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
@ -820,8 +823,21 @@ fn extract_depth_of_field_settings(
|
|||
}
|
||||
|
||||
for (entity, depth_of_field, projection) in query.iter_mut() {
|
||||
let mut entity_commands = commands
|
||||
.get_entity(entity)
|
||||
.expect("Depth of field entity wasn't synced.");
|
||||
|
||||
// Depth of field is nonsensical without a perspective projection.
|
||||
let Projection::Perspective(ref perspective_projection) = *projection else {
|
||||
// TODO: needs better strategy for cleaning up
|
||||
entity_commands.remove::<(
|
||||
DepthOfField,
|
||||
DepthOfFieldUniform,
|
||||
// components added in prepare systems (because `DepthOfFieldNode` does not query extracted components)
|
||||
DepthOfFieldPipelines,
|
||||
AuxiliaryDepthOfFieldTexture,
|
||||
ViewDepthOfFieldBindGroupLayouts,
|
||||
)>();
|
||||
continue;
|
||||
};
|
||||
|
||||
|
@ -829,24 +845,20 @@ fn extract_depth_of_field_settings(
|
|||
calculate_focal_length(depth_of_field.sensor_height, perspective_projection.fov);
|
||||
|
||||
// Convert `DepthOfField` to `DepthOfFieldUniform`.
|
||||
commands
|
||||
.get_entity(entity)
|
||||
.expect("Depth of field entity wasn't synced.")
|
||||
.insert((
|
||||
*depth_of_field,
|
||||
DepthOfFieldUniform {
|
||||
focal_distance: depth_of_field.focal_distance,
|
||||
focal_length,
|
||||
coc_scale_factor: focal_length * focal_length
|
||||
/ (depth_of_field.sensor_height * depth_of_field.aperture_f_stops),
|
||||
max_circle_of_confusion_diameter: depth_of_field
|
||||
.max_circle_of_confusion_diameter,
|
||||
max_depth: depth_of_field.max_depth,
|
||||
pad_a: 0,
|
||||
pad_b: 0,
|
||||
pad_c: 0,
|
||||
},
|
||||
));
|
||||
entity_commands.insert((
|
||||
*depth_of_field,
|
||||
DepthOfFieldUniform {
|
||||
focal_distance: depth_of_field.focal_distance,
|
||||
focal_length,
|
||||
coc_scale_factor: focal_length * focal_length
|
||||
/ (depth_of_field.sensor_height * depth_of_field.aperture_f_stops),
|
||||
max_circle_of_confusion_diameter: depth_of_field.max_circle_of_confusion_diameter,
|
||||
max_depth: depth_of_field.max_depth,
|
||||
pad_a: 0,
|
||||
pad_b: 0,
|
||||
pad_c: 0,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ use bevy_render::{
|
|||
TextureDimension, TextureFormat, TextureSampleType, TextureUsages,
|
||||
},
|
||||
renderer::{RenderContext, RenderDevice},
|
||||
sync_component::SyncComponentPlugin,
|
||||
sync_world::RenderEntity,
|
||||
texture::{BevyDefault, CachedTexture, TextureCache},
|
||||
view::{ExtractedView, Msaa, ViewTarget},
|
||||
|
@ -52,6 +53,8 @@ impl Plugin for TemporalAntiAliasPlugin {
|
|||
|
||||
app.register_type::<TemporalAntiAliasing>();
|
||||
|
||||
app.add_plugins(SyncComponentPlugin::<TemporalAntiAliasing>::default());
|
||||
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
};
|
||||
|
@ -373,12 +376,20 @@ fn extract_taa_settings(mut commands: Commands, mut main_world: ResMut<MainWorld
|
|||
cameras_3d.iter_mut(&mut main_world)
|
||||
{
|
||||
let has_perspective_projection = matches!(camera_projection, Projection::Perspective(_));
|
||||
let mut entity_commands = commands
|
||||
.get_entity(entity)
|
||||
.expect("Camera entity wasn't synced.");
|
||||
if camera.is_active && has_perspective_projection {
|
||||
commands
|
||||
.get_entity(entity)
|
||||
.expect("Camera entity wasn't synced.")
|
||||
.insert(taa_settings.clone());
|
||||
entity_commands.insert(taa_settings.clone());
|
||||
taa_settings.reset = false;
|
||||
} else {
|
||||
// TODO: needs better strategy for cleaning up
|
||||
entity_commands.remove::<(
|
||||
TemporalAntiAliasing,
|
||||
// components added in prepare systems (because `TemporalAntiAliasNode` does not query extracted components)
|
||||
TemporalAntiAliasHistoryTextures,
|
||||
TemporalAntiAliasPipelineId,
|
||||
)>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -530,7 +530,11 @@ pub fn extract_clusters(
|
|||
mapper: Extract<Query<RenderEntity>>,
|
||||
) {
|
||||
for (entity, clusters, camera) in &views {
|
||||
let mut entity_commands = commands
|
||||
.get_entity(entity)
|
||||
.expect("Clusters entity wasn't synced.");
|
||||
if !camera.is_active {
|
||||
entity_commands.remove::<(ExtractedClusterableObjects, ExtractedClusterConfig)>();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -554,17 +558,14 @@ pub fn extract_clusters(
|
|||
}
|
||||
}
|
||||
|
||||
commands
|
||||
.get_entity(entity)
|
||||
.expect("Clusters entity wasn't synced.")
|
||||
.insert((
|
||||
ExtractedClusterableObjects { data },
|
||||
ExtractedClusterConfig {
|
||||
near: clusters.near,
|
||||
far: clusters.far,
|
||||
dimensions: clusters.dimensions,
|
||||
},
|
||||
));
|
||||
entity_commands.insert((
|
||||
ExtractedClusterableObjects { data },
|
||||
ExtractedClusterConfig {
|
||||
near: clusters.near,
|
||||
far: clusters.far,
|
||||
dimensions: clusters.dimensions,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -455,6 +455,7 @@ impl Plugin for PbrPlugin {
|
|||
render_app
|
||||
.world_mut()
|
||||
.add_observer(remove_light_view_entities);
|
||||
render_app.world_mut().add_observer(extracted_light_removed);
|
||||
|
||||
let shadow_pass_node = ShadowPassNode::new(render_app.world_mut());
|
||||
let mut graph = render_app.world_mut().resource_mut::<RenderGraph>();
|
||||
|
|
|
@ -588,14 +588,15 @@ pub fn extract_camera_previous_view_data(
|
|||
cameras_3d: Extract<Query<(RenderEntity, &Camera, Option<&PreviousViewData>), With<Camera3d>>>,
|
||||
) {
|
||||
for (entity, camera, maybe_previous_view_data) in cameras_3d.iter() {
|
||||
let mut entity = commands
|
||||
.get_entity(entity)
|
||||
.expect("Camera entity wasn't synced.");
|
||||
if camera.is_active {
|
||||
let mut entity = commands
|
||||
.get_entity(entity)
|
||||
.expect("Camera entity wasn't synced.");
|
||||
|
||||
if let Some(previous_view_data) = maybe_previous_view_data {
|
||||
entity.insert(previous_view_data.clone());
|
||||
}
|
||||
} else {
|
||||
entity.remove::<PreviousViewData>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -379,6 +379,10 @@ pub fn extract_lights(
|
|||
) in &directional_lights
|
||||
{
|
||||
if !view_visibility.get() {
|
||||
commands
|
||||
.get_entity(entity)
|
||||
.expect("Light entity wasn't synced.")
|
||||
.remove::<(ExtractedDirectionalLight, RenderCascadesVisibleEntities)>();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -473,6 +477,16 @@ pub(crate) fn add_light_view_entities(
|
|||
}
|
||||
}
|
||||
|
||||
/// Removes [`LightViewEntities`] when light is removed. See [`add_light_view_entities`].
|
||||
pub(crate) fn extracted_light_removed(
|
||||
trigger: Trigger<OnRemove, (ExtractedDirectionalLight, ExtractedPointLight)>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
if let Some(mut v) = commands.get_entity(trigger.entity()) {
|
||||
v.remove::<LightViewEntities>();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn remove_light_view_entities(
|
||||
trigger: Trigger<OnRemove, LightViewEntities>,
|
||||
query: Query<&LightViewEntities>,
|
||||
|
|
|
@ -30,6 +30,7 @@ use bevy_render::{
|
|||
*,
|
||||
},
|
||||
renderer::{RenderAdapter, RenderContext, RenderDevice, RenderQueue},
|
||||
sync_component::SyncComponentPlugin,
|
||||
sync_world::RenderEntity,
|
||||
texture::{CachedTexture, TextureCache},
|
||||
view::{Msaa, ViewUniform, ViewUniformOffset, ViewUniforms},
|
||||
|
@ -72,6 +73,8 @@ impl Plugin for ScreenSpaceAmbientOcclusionPlugin {
|
|||
);
|
||||
|
||||
app.register_type::<ScreenSpaceAmbientOcclusion>();
|
||||
|
||||
app.add_plugins(SyncComponentPlugin::<ScreenSpaceAmbientOcclusion>::default());
|
||||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
|
@ -531,11 +534,13 @@ fn extract_ssao_settings(
|
|||
);
|
||||
return;
|
||||
}
|
||||
let mut entity_commands = commands
|
||||
.get_entity(entity)
|
||||
.expect("SSAO entity wasn't synced.");
|
||||
if camera.is_active {
|
||||
commands
|
||||
.get_entity(entity)
|
||||
.expect("SSAO entity wasn't synced.")
|
||||
.insert(ssao_settings.clone());
|
||||
entity_commands.insert(ssao_settings.clone());
|
||||
} else {
|
||||
entity_commands.remove::<ScreenSpaceAmbientOcclusion>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -276,6 +276,15 @@ pub fn extract_volumetric_fog(
|
|||
volumetric_lights: Extract<Query<(RenderEntity, &VolumetricLight)>>,
|
||||
) {
|
||||
if volumetric_lights.is_empty() {
|
||||
// TODO: needs better way to handle clean up in render world
|
||||
for (entity, ..) in view_targets.iter() {
|
||||
commands
|
||||
.entity(entity)
|
||||
.remove::<(VolumetricFog, ViewVolumetricFogPipelines, ViewVolumetricFog)>();
|
||||
}
|
||||
for (entity, ..) in fog_volumes.iter() {
|
||||
commands.entity(entity).remove::<FogVolume>();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -537,6 +537,10 @@ pub fn extract_default_ui_camera_view(
|
|||
for (entity, camera, ui_anti_alias, shadow_samples) in &query {
|
||||
// ignore inactive cameras
|
||||
if !camera.is_active {
|
||||
commands
|
||||
.get_entity(entity)
|
||||
.expect("Camera entity wasn't synced.")
|
||||
.remove::<(DefaultCameraView, UiAntiAlias, UiBoxShadowSamples)>();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue