Path: blob/main/crates/bevy_post_process/src/auto_exposure/buffers.rs
6596 views
use bevy_ecs::prelude::*;1use bevy_platform::collections::{hash_map::Entry, HashMap};2use bevy_render::{3render_resource::{StorageBuffer, UniformBuffer},4renderer::{RenderDevice, RenderQueue},5sync_world::RenderEntity,6Extract,7};89use super::{pipeline::AutoExposureUniform, AutoExposure};1011#[derive(Resource, Default)]12pub(super) struct AutoExposureBuffers {13pub(super) buffers: HashMap<Entity, AutoExposureBuffer>,14}1516pub(super) struct AutoExposureBuffer {17pub(super) state: StorageBuffer<f32>,18pub(super) settings: UniformBuffer<AutoExposureUniform>,19}2021#[derive(Resource)]22pub(super) struct ExtractedStateBuffers {23changed: Vec<(Entity, AutoExposure)>,24removed: Vec<Entity>,25}2627pub(super) fn extract_buffers(28mut commands: Commands,29changed: Extract<Query<(RenderEntity, &AutoExposure), Changed<AutoExposure>>>,30mut removed: Extract<RemovedComponents<AutoExposure>>,31) {32commands.insert_resource(ExtractedStateBuffers {33changed: changed34.iter()35.map(|(entity, settings)| (entity, settings.clone()))36.collect(),37removed: removed.read().collect(),38});39}4041pub(super) fn prepare_buffers(42device: Res<RenderDevice>,43queue: Res<RenderQueue>,44mut extracted: ResMut<ExtractedStateBuffers>,45mut buffers: ResMut<AutoExposureBuffers>,46) {47for (entity, settings) in extracted.changed.drain(..) {48let (min_log_lum, max_log_lum) = settings.range.into_inner();49let (low_percent, high_percent) = settings.filter.into_inner();50let initial_state = 0.0f32.clamp(min_log_lum, max_log_lum);5152let settings = AutoExposureUniform {53min_log_lum,54inv_log_lum_range: 1.0 / (max_log_lum - min_log_lum),55log_lum_range: max_log_lum - min_log_lum,56low_percent,57high_percent,58speed_up: settings.speed_brighten,59speed_down: settings.speed_darken,60exponential_transition_distance: settings.exponential_transition_distance,61};6263match buffers.buffers.entry(entity) {64Entry::Occupied(mut entry) => {65// Update the settings buffer, but skip updating the state buffer.66// The state buffer is skipped so that the animation stays continuous.67let value = entry.get_mut();68value.settings.set(settings);69value.settings.write_buffer(&device, &queue);70}71Entry::Vacant(entry) => {72let value = entry.insert(AutoExposureBuffer {73state: StorageBuffer::from(initial_state),74settings: UniformBuffer::from(settings),75});7677value.state.write_buffer(&device, &queue);78value.settings.write_buffer(&device, &queue);79}80}81}8283for entity in extracted.removed.drain(..) {84buffers.buffers.remove(&entity);85}86}878889