Path: blob/main/crates/bevy_post_process/src/auto_exposure/mod.rs
6596 views
use bevy_app::prelude::*;1use bevy_asset::{embedded_asset, AssetApp, Assets, Handle};2use bevy_ecs::prelude::*;3use bevy_render::{4extract_component::ExtractComponentPlugin,5render_asset::RenderAssetPlugin,6render_graph::RenderGraphExt,7render_resource::{8Buffer, BufferDescriptor, BufferUsages, PipelineCache, SpecializedComputePipelines,9},10renderer::RenderDevice,11ExtractSchedule, Render, RenderApp, RenderStartup, RenderSystems,12};1314mod buffers;15mod compensation_curve;16mod node;17mod pipeline;18mod settings;1920use buffers::{extract_buffers, prepare_buffers, AutoExposureBuffers};21pub use compensation_curve::{AutoExposureCompensationCurve, AutoExposureCompensationCurveError};22use node::AutoExposureNode;23use pipeline::{AutoExposurePass, AutoExposurePipeline, ViewAutoExposurePipeline};24pub use settings::AutoExposure;2526use crate::auto_exposure::{27compensation_curve::GpuAutoExposureCompensationCurve, pipeline::init_auto_exposure_pipeline,28};29use bevy_core_pipeline::core_3d::graph::{Core3d, Node3d};3031/// Plugin for the auto exposure feature.32///33/// See [`AutoExposure`] for more details.34pub struct AutoExposurePlugin;3536#[derive(Resource)]37struct AutoExposureResources {38histogram: Buffer,39}4041impl Plugin for AutoExposurePlugin {42fn build(&self, app: &mut App) {43embedded_asset!(app, "auto_exposure.wgsl");4445app.add_plugins(RenderAssetPlugin::<GpuAutoExposureCompensationCurve>::default())46.init_asset::<AutoExposureCompensationCurve>()47.register_asset_reflect::<AutoExposureCompensationCurve>();48app.world_mut()49.resource_mut::<Assets<AutoExposureCompensationCurve>>()50.insert(&Handle::default(), AutoExposureCompensationCurve::default())51.unwrap();5253app.add_plugins(ExtractComponentPlugin::<AutoExposure>::default());5455let Some(render_app) = app.get_sub_app_mut(RenderApp) else {56return;57};5859render_app60.init_resource::<SpecializedComputePipelines<AutoExposurePipeline>>()61.init_resource::<AutoExposureBuffers>()62.add_systems(63RenderStartup,64(init_auto_exposure_pipeline, init_auto_exposure_resources),65)66.add_systems(ExtractSchedule, extract_buffers)67.add_systems(68Render,69(70prepare_buffers.in_set(RenderSystems::Prepare),71queue_view_auto_exposure_pipelines.in_set(RenderSystems::Queue),72),73)74.add_render_graph_node::<AutoExposureNode>(Core3d, node::AutoExposure)75.add_render_graph_edges(76Core3d,77(Node3d::EndMainPass, node::AutoExposure, Node3d::Tonemapping),78);79}80}8182pub fn init_auto_exposure_resources(mut commands: Commands, render_device: Res<RenderDevice>) {83commands.insert_resource(AutoExposureResources {84histogram: render_device.create_buffer(&BufferDescriptor {85label: Some("histogram buffer"),86size: pipeline::HISTOGRAM_BIN_COUNT * 4,87usage: BufferUsages::STORAGE,88mapped_at_creation: false,89}),90});91}9293fn queue_view_auto_exposure_pipelines(94mut commands: Commands,95pipeline_cache: Res<PipelineCache>,96mut compute_pipelines: ResMut<SpecializedComputePipelines<AutoExposurePipeline>>,97pipeline: Res<AutoExposurePipeline>,98view_targets: Query<(Entity, &AutoExposure)>,99) {100for (entity, auto_exposure) in view_targets.iter() {101let histogram_pipeline =102compute_pipelines.specialize(&pipeline_cache, &pipeline, AutoExposurePass::Histogram);103let average_pipeline =104compute_pipelines.specialize(&pipeline_cache, &pipeline, AutoExposurePass::Average);105106commands.entity(entity).insert(ViewAutoExposurePipeline {107histogram_pipeline,108mean_luminance_pipeline: average_pipeline,109compensation_curve: auto_exposure.compensation_curve.clone(),110metering_mask: auto_exposure.metering_mask.clone(),111});112}113}114115116