mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +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,
|
TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType, TextureUsages,
|
||||||
},
|
},
|
||||||
renderer::{RenderContext, RenderDevice},
|
renderer::{RenderContext, RenderDevice},
|
||||||
|
sync_component::SyncComponentPlugin,
|
||||||
sync_world::RenderEntity,
|
sync_world::RenderEntity,
|
||||||
texture::{BevyDefault, CachedTexture, TextureCache},
|
texture::{BevyDefault, CachedTexture, TextureCache},
|
||||||
view::{
|
view::{
|
||||||
|
@ -211,6 +212,8 @@ impl Plugin for DepthOfFieldPlugin {
|
||||||
app.register_type::<DepthOfFieldMode>();
|
app.register_type::<DepthOfFieldMode>();
|
||||||
app.add_plugins(UniformComponentPlugin::<DepthOfFieldUniform>::default());
|
app.add_plugins(UniformComponentPlugin::<DepthOfFieldUniform>::default());
|
||||||
|
|
||||||
|
app.add_plugins(SyncComponentPlugin::<DepthOfField>::default());
|
||||||
|
|
||||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -820,8 +823,21 @@ fn extract_depth_of_field_settings(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (entity, depth_of_field, projection) in query.iter_mut() {
|
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.
|
// Depth of field is nonsensical without a perspective projection.
|
||||||
let Projection::Perspective(ref perspective_projection) = *projection else {
|
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;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -829,24 +845,20 @@ fn extract_depth_of_field_settings(
|
||||||
calculate_focal_length(depth_of_field.sensor_height, perspective_projection.fov);
|
calculate_focal_length(depth_of_field.sensor_height, perspective_projection.fov);
|
||||||
|
|
||||||
// Convert `DepthOfField` to `DepthOfFieldUniform`.
|
// Convert `DepthOfField` to `DepthOfFieldUniform`.
|
||||||
commands
|
entity_commands.insert((
|
||||||
.get_entity(entity)
|
*depth_of_field,
|
||||||
.expect("Depth of field entity wasn't synced.")
|
DepthOfFieldUniform {
|
||||||
.insert((
|
focal_distance: depth_of_field.focal_distance,
|
||||||
*depth_of_field,
|
focal_length,
|
||||||
DepthOfFieldUniform {
|
coc_scale_factor: focal_length * focal_length
|
||||||
focal_distance: depth_of_field.focal_distance,
|
/ (depth_of_field.sensor_height * depth_of_field.aperture_f_stops),
|
||||||
focal_length,
|
max_circle_of_confusion_diameter: depth_of_field.max_circle_of_confusion_diameter,
|
||||||
coc_scale_factor: focal_length * focal_length
|
max_depth: depth_of_field.max_depth,
|
||||||
/ (depth_of_field.sensor_height * depth_of_field.aperture_f_stops),
|
pad_a: 0,
|
||||||
max_circle_of_confusion_diameter: depth_of_field
|
pad_b: 0,
|
||||||
.max_circle_of_confusion_diameter,
|
pad_c: 0,
|
||||||
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,
|
TextureDimension, TextureFormat, TextureSampleType, TextureUsages,
|
||||||
},
|
},
|
||||||
renderer::{RenderContext, RenderDevice},
|
renderer::{RenderContext, RenderDevice},
|
||||||
|
sync_component::SyncComponentPlugin,
|
||||||
sync_world::RenderEntity,
|
sync_world::RenderEntity,
|
||||||
texture::{BevyDefault, CachedTexture, TextureCache},
|
texture::{BevyDefault, CachedTexture, TextureCache},
|
||||||
view::{ExtractedView, Msaa, ViewTarget},
|
view::{ExtractedView, Msaa, ViewTarget},
|
||||||
|
@ -52,6 +53,8 @@ impl Plugin for TemporalAntiAliasPlugin {
|
||||||
|
|
||||||
app.register_type::<TemporalAntiAliasing>();
|
app.register_type::<TemporalAntiAliasing>();
|
||||||
|
|
||||||
|
app.add_plugins(SyncComponentPlugin::<TemporalAntiAliasing>::default());
|
||||||
|
|
||||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -373,12 +376,20 @@ fn extract_taa_settings(mut commands: Commands, mut main_world: ResMut<MainWorld
|
||||||
cameras_3d.iter_mut(&mut main_world)
|
cameras_3d.iter_mut(&mut main_world)
|
||||||
{
|
{
|
||||||
let has_perspective_projection = matches!(camera_projection, Projection::Perspective(_));
|
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 {
|
if camera.is_active && has_perspective_projection {
|
||||||
commands
|
entity_commands.insert(taa_settings.clone());
|
||||||
.get_entity(entity)
|
|
||||||
.expect("Camera entity wasn't synced.")
|
|
||||||
.insert(taa_settings.clone());
|
|
||||||
taa_settings.reset = false;
|
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>>,
|
mapper: Extract<Query<RenderEntity>>,
|
||||||
) {
|
) {
|
||||||
for (entity, clusters, camera) in &views {
|
for (entity, clusters, camera) in &views {
|
||||||
|
let mut entity_commands = commands
|
||||||
|
.get_entity(entity)
|
||||||
|
.expect("Clusters entity wasn't synced.");
|
||||||
if !camera.is_active {
|
if !camera.is_active {
|
||||||
|
entity_commands.remove::<(ExtractedClusterableObjects, ExtractedClusterConfig)>();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,17 +558,14 @@ pub fn extract_clusters(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
commands
|
entity_commands.insert((
|
||||||
.get_entity(entity)
|
ExtractedClusterableObjects { data },
|
||||||
.expect("Clusters entity wasn't synced.")
|
ExtractedClusterConfig {
|
||||||
.insert((
|
near: clusters.near,
|
||||||
ExtractedClusterableObjects { data },
|
far: clusters.far,
|
||||||
ExtractedClusterConfig {
|
dimensions: clusters.dimensions,
|
||||||
near: clusters.near,
|
},
|
||||||
far: clusters.far,
|
));
|
||||||
dimensions: clusters.dimensions,
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -455,6 +455,7 @@ impl Plugin for PbrPlugin {
|
||||||
render_app
|
render_app
|
||||||
.world_mut()
|
.world_mut()
|
||||||
.add_observer(remove_light_view_entities);
|
.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 shadow_pass_node = ShadowPassNode::new(render_app.world_mut());
|
||||||
let mut graph = render_app.world_mut().resource_mut::<RenderGraph>();
|
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>>>,
|
cameras_3d: Extract<Query<(RenderEntity, &Camera, Option<&PreviousViewData>), With<Camera3d>>>,
|
||||||
) {
|
) {
|
||||||
for (entity, camera, maybe_previous_view_data) in cameras_3d.iter() {
|
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 {
|
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 {
|
if let Some(previous_view_data) = maybe_previous_view_data {
|
||||||
entity.insert(previous_view_data.clone());
|
entity.insert(previous_view_data.clone());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
entity.remove::<PreviousViewData>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,6 +379,10 @@ pub fn extract_lights(
|
||||||
) in &directional_lights
|
) in &directional_lights
|
||||||
{
|
{
|
||||||
if !view_visibility.get() {
|
if !view_visibility.get() {
|
||||||
|
commands
|
||||||
|
.get_entity(entity)
|
||||||
|
.expect("Light entity wasn't synced.")
|
||||||
|
.remove::<(ExtractedDirectionalLight, RenderCascadesVisibleEntities)>();
|
||||||
continue;
|
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(
|
pub(crate) fn remove_light_view_entities(
|
||||||
trigger: Trigger<OnRemove, LightViewEntities>,
|
trigger: Trigger<OnRemove, LightViewEntities>,
|
||||||
query: Query<&LightViewEntities>,
|
query: Query<&LightViewEntities>,
|
||||||
|
|
|
@ -30,6 +30,7 @@ use bevy_render::{
|
||||||
*,
|
*,
|
||||||
},
|
},
|
||||||
renderer::{RenderAdapter, RenderContext, RenderDevice, RenderQueue},
|
renderer::{RenderAdapter, RenderContext, RenderDevice, RenderQueue},
|
||||||
|
sync_component::SyncComponentPlugin,
|
||||||
sync_world::RenderEntity,
|
sync_world::RenderEntity,
|
||||||
texture::{CachedTexture, TextureCache},
|
texture::{CachedTexture, TextureCache},
|
||||||
view::{Msaa, ViewUniform, ViewUniformOffset, ViewUniforms},
|
view::{Msaa, ViewUniform, ViewUniformOffset, ViewUniforms},
|
||||||
|
@ -72,6 +73,8 @@ impl Plugin for ScreenSpaceAmbientOcclusionPlugin {
|
||||||
);
|
);
|
||||||
|
|
||||||
app.register_type::<ScreenSpaceAmbientOcclusion>();
|
app.register_type::<ScreenSpaceAmbientOcclusion>();
|
||||||
|
|
||||||
|
app.add_plugins(SyncComponentPlugin::<ScreenSpaceAmbientOcclusion>::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&self, app: &mut App) {
|
fn finish(&self, app: &mut App) {
|
||||||
|
@ -531,11 +534,13 @@ fn extract_ssao_settings(
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let mut entity_commands = commands
|
||||||
|
.get_entity(entity)
|
||||||
|
.expect("SSAO entity wasn't synced.");
|
||||||
if camera.is_active {
|
if camera.is_active {
|
||||||
commands
|
entity_commands.insert(ssao_settings.clone());
|
||||||
.get_entity(entity)
|
} else {
|
||||||
.expect("SSAO entity wasn't synced.")
|
entity_commands.remove::<ScreenSpaceAmbientOcclusion>();
|
||||||
.insert(ssao_settings.clone());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,6 +276,15 @@ pub fn extract_volumetric_fog(
|
||||||
volumetric_lights: Extract<Query<(RenderEntity, &VolumetricLight)>>,
|
volumetric_lights: Extract<Query<(RenderEntity, &VolumetricLight)>>,
|
||||||
) {
|
) {
|
||||||
if volumetric_lights.is_empty() {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -537,6 +537,10 @@ pub fn extract_default_ui_camera_view(
|
||||||
for (entity, camera, ui_anti_alias, shadow_samples) in &query {
|
for (entity, camera, ui_anti_alias, shadow_samples) in &query {
|
||||||
// ignore inactive cameras
|
// ignore inactive cameras
|
||||||
if !camera.is_active {
|
if !camera.is_active {
|
||||||
|
commands
|
||||||
|
.get_entity(entity)
|
||||||
|
.expect("Camera entity wasn't synced.")
|
||||||
|
.remove::<(DefaultCameraView, UiAntiAlias, UiBoxShadowSamples)>();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue