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
7 changes: 7 additions & 0 deletions crates/bevy_light/src/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,12 @@ pub struct GeneratedEnvironmentMapLight {
/// Whether this light contributes diffuse lighting to meshes that already
/// have baked lightmaps.
pub affects_lightmapped_mesh_diffuse: bool,

/// Whether to re-filter the environment map.
///
/// After setting this to true, it will automatically be toggled
/// back to false at the end of the frame.
pub regenerate: bool,
}

impl Default for GeneratedEnvironmentMapLight {
Expand All @@ -283,6 +289,7 @@ impl Default for GeneratedEnvironmentMapLight {
intensity: 0.0,
rotation: Quat::IDENTITY,
affects_lightmapped_mesh_diffuse: true,
regenerate: true,
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions crates/bevy_pbr/src/atmosphere/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,14 @@ pub fn validate_environment_map_size(size: UVec2) -> UVec2 {
new_size
}

pub fn request_atmosphere_environment_map_regeneration(
mut probes: Query<&mut GeneratedEnvironmentMapLight, With<AtmosphereEnvironmentMap>>,
) {
for mut env_map in &mut probes {
env_map.regenerate = true;
}
}

pub fn prepare_atmosphere_probe_components(
probes: Query<(Entity, &AtmosphereEnvironmentMapLight), (Without<AtmosphereEnvironmentMap>,)>,
mut commands: Commands,
Expand Down Expand Up @@ -239,6 +247,7 @@ pub fn prepare_atmosphere_probe_components(
intensity: env_map_light.intensity,
rotation: Quat::IDENTITY,
affects_lightmapped_mesh_diffuse: env_map_light.affects_lightmapped_mesh_diffuse,
regenerate: true,
});
}
}
Expand Down
12 changes: 10 additions & 2 deletions crates/bevy_pbr/src/atmosphere/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ use bevy_shader::load_shader_library;
use environment::{
atmosphere_environment, init_atmosphere_probe_layout, init_atmosphere_probe_pipeline,
prepare_atmosphere_probe_bind_groups, prepare_atmosphere_probe_components,
prepare_probe_textures, AtmosphereEnvironmentMap,
prepare_probe_textures, request_atmosphere_environment_map_regeneration,
AtmosphereEnvironmentMap,
};
use node::{atmosphere_luts, render_sky};
use resources::{
Expand Down Expand Up @@ -115,7 +116,14 @@ impl Plugin for AtmospherePlugin {
UniformComponentPlugin::<GpuAtmosphere>::default(),
UniformComponentPlugin::<GpuAtmosphereSettings>::default(),
))
.add_systems(Update, prepare_atmosphere_probe_components);
.add_systems(
Update,
(
prepare_atmosphere_probe_components,
request_atmosphere_environment_map_regeneration
.ambiguous_with(crate::light_probe::generate::generate_environment_map_light),
),
);

if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app.add_systems(ExtractSchedule, extract_atmosphere);
Expand Down
59 changes: 41 additions & 18 deletions crates/bevy_pbr/src/light_probe/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use bevy_core_pipeline::mip_generation::{self, DownsampleShaders, DownsamplingCo
use bevy_ecs::{
component::Component,
entity::Entity,
query::Without,
query::{With, Without},
resource::Resource,
schedule::IntoScheduleConfigs,
system::{Commands, Query, Res, ResMut},
Expand All @@ -41,7 +41,7 @@ use bevy_render::{
sync_component::{SyncComponent, SyncComponentPlugin},
sync_world::RenderEntity,
texture::{CachedTexture, GpuImage, TextureCache},
Extract, ExtractSchedule, Render, RenderApp, RenderStartup, RenderSystems,
ExtractSchedule, MainWorld, Render, RenderApp, RenderStartup, RenderSystems,
};

// Implementation: generate diffuse and specular cubemaps required by PBR
Expand Down Expand Up @@ -433,17 +433,17 @@ pub fn initialize_generated_environment_map_resources(
}

pub fn extract_generated_environment_map_entities(
query: Extract<
Query<(
RenderEntity,
&GeneratedEnvironmentMapLight,
&EnvironmentMapLight,
)>,
>,
mut commands: Commands,
mut main_world: ResMut<MainWorld>,
render_images: Res<RenderAssets<GpuImage>>,
) {
for (entity, filtered_env_map, env_map_light) in query.iter() {
let mut query = main_world.query::<(
RenderEntity,
&mut GeneratedEnvironmentMapLight,
&EnvironmentMapLight,
)>();

for (entity, mut filtered_env_map, env_map_light) in query.iter_mut(&mut main_world) {
let Some(env_map) = render_images.get(&filtered_env_map.environment_map) else {
continue;
};
Expand All @@ -467,10 +467,16 @@ pub fn extract_generated_environment_map_entities(
rotation: filtered_env_map.rotation,
affects_lightmapped_mesh_diffuse: filtered_env_map.affects_lightmapped_mesh_diffuse,
};
commands

let mut entity_commands = commands
.get_entity(entity)
.expect("Entity not synced to render world")
.insert(render_filtered_env_map);
.expect("Entity not synced to render world");
entity_commands.insert(render_filtered_env_map);

if filtered_env_map.regenerate {
entity_commands.insert(RegenerateEnvironmentMap);
filtered_env_map.regenerate = false;
}
}
}

Expand All @@ -485,6 +491,13 @@ pub struct RenderEnvironmentMap {
pub affects_lightmapped_mesh_diffuse: bool,
}

/// Marks a `RenderEnvironmentMap` as needing (re)generation.
///
/// Persists until `filtering_system` has run, so the work gets
/// retried across frames if pipelines or assets aren't ready yet.
#[derive(Component)]
pub struct RegenerateEnvironmentMap;

#[derive(Component)]
pub struct IntermediateTextures {
pub environment_map: CachedTexture,
Expand All @@ -500,7 +513,7 @@ fn compute_mip_count(size: u32) -> u32 {

/// Prepares textures needed for single pass downsampling
pub fn prepare_generated_environment_map_intermediate_textures(
light_probes: Query<(Entity, &RenderEnvironmentMap)>,
light_probes: Query<(Entity, &RenderEnvironmentMap), With<RegenerateEnvironmentMap>>,
render_device: Res<RenderDevice>,
mut texture_cache: ResMut<TextureCache>,
mut commands: Commands,
Expand Down Expand Up @@ -557,7 +570,10 @@ pub struct GeneratorBindGroups {

/// Prepares bind groups for environment map generation pipelines
pub fn prepare_generated_environment_map_bind_groups(
light_probes: Query<(Entity, &IntermediateTextures, &RenderEnvironmentMap)>,
light_probes: Query<
(Entity, &IntermediateTextures, &RenderEnvironmentMap),
With<RegenerateEnvironmentMap>,
>,
render_device: Res<RenderDevice>,
pipeline_cache: Res<PipelineCache>,
queue: Res<RenderQueue>,
Expand Down Expand Up @@ -840,7 +856,7 @@ fn create_placeholder_storage_view(render_device: &RenderDevice) -> TextureView
}

pub fn downsampling_system(
query: Query<(&GeneratorBindGroups, &RenderEnvironmentMap)>,
query: Query<(&GeneratorBindGroups, &RenderEnvironmentMap), With<RegenerateEnvironmentMap>>,
pipeline_cache: Res<PipelineCache>,
pipelines: Option<Res<GeneratorPipelines>>,
mut ctx: RenderContext,
Expand Down Expand Up @@ -940,9 +956,13 @@ pub fn downsampling_system(
}

pub fn filtering_system(
query: Query<(&GeneratorBindGroups, &RenderEnvironmentMap)>,
query: Query<
(Entity, &GeneratorBindGroups, &RenderEnvironmentMap),
With<RegenerateEnvironmentMap>,
>,
pipeline_cache: Res<PipelineCache>,
pipelines: Option<Res<GeneratorPipelines>>,
mut commands: Commands,
mut ctx: RenderContext,
) {
let Some(pipelines) = pipelines else {
Expand All @@ -960,7 +980,7 @@ pub fn filtering_system(
let diagnostics = ctx.diagnostic_recorder();
let diagnostics = diagnostics.as_deref();

for (bind_groups, env_map_light) in &query {
for (entity, bind_groups, env_map_light) in &query {
// Radiance convolution pass
{
let mut compute_pass =
Expand Down Expand Up @@ -1011,6 +1031,9 @@ pub fn filtering_system(

irr_span.end(&mut compute_pass);
}

// The filtering has run, clear the marker.
commands.entity(entity).remove::<RegenerateEnvironmentMap>();
}
}

Expand Down
Loading