Path: blob/main/crates/bevy_post_process/src/bloom/upsampling_pipeline.rs
9395 views
use bevy_core_pipeline::FullscreenShader;12use super::{3downsampling_pipeline::BloomUniforms, Bloom, BloomCompositeMode, BLOOM_TEXTURE_FORMAT,4};5use bevy_asset::{load_embedded_asset, AssetServer, Handle};6use bevy_ecs::{7prelude::{Component, Entity},8resource::Resource,9system::{Commands, Query, Res, ResMut},10};11use bevy_render::{12render_resource::{13binding_types::{sampler, texture_2d, uniform_buffer},14*,15},16view::ViewTarget,17};18use bevy_shader::Shader;19use bevy_utils::default;2021#[derive(Component)]22pub struct UpsamplingPipelineIds {23pub id_main: CachedRenderPipelineId,24pub id_final: CachedRenderPipelineId,25}2627#[derive(Resource)]28pub struct BloomUpsamplingPipeline {29pub bind_group_layout: BindGroupLayoutDescriptor,30/// The asset handle for the fullscreen vertex shader.31pub fullscreen_shader: FullscreenShader,32/// The fragment shader asset handle.33pub fragment_shader: Handle<Shader>,34}3536#[derive(PartialEq, Eq, Hash, Clone)]37pub struct BloomUpsamplingPipelineKeys {38composite_mode: BloomCompositeMode,39final_pipeline: bool,40}4142pub fn init_bloom_upscaling_pipeline(43mut commands: Commands,44fullscreen_shader: Res<FullscreenShader>,45asset_server: Res<AssetServer>,46) {47let bind_group_layout = BindGroupLayoutDescriptor::new(48"bloom_upsampling_bind_group_layout",49&BindGroupLayoutEntries::sequential(50ShaderStages::FRAGMENT,51(52// Input texture53texture_2d(TextureSampleType::Float { filterable: true }),54// Sampler55sampler(SamplerBindingType::Filtering),56// BloomUniforms57uniform_buffer::<BloomUniforms>(true),58),59),60);6162commands.insert_resource(BloomUpsamplingPipeline {63bind_group_layout,64fullscreen_shader: fullscreen_shader.clone(),65fragment_shader: load_embedded_asset!(asset_server.as_ref(), "bloom.wgsl"),66});67}6869impl SpecializedRenderPipeline for BloomUpsamplingPipeline {70type Key = BloomUpsamplingPipelineKeys;7172fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {73let texture_format = if key.final_pipeline {74ViewTarget::TEXTURE_FORMAT_HDR75} else {76BLOOM_TEXTURE_FORMAT77};7879let color_blend = match key.composite_mode {80BloomCompositeMode::EnergyConserving => {81// At the time of developing this we decided to blend our82// blur pyramid levels using native WGPU render pass blend83// constants. They are set in the bloom node's run function.84// This seemed like a good approach at the time which allowed85// us to perform complex calculations for blend levels on the CPU,86// however, we missed the fact that this prevented us from using87// textures to customize bloom appearance on individual parts88// of the screen and create effects such as lens dirt or89// screen blur behind certain UI elements.90//91// TODO: Use alpha instead of blend constants and move92// compute_blend_factor to the shader. The shader93// will likely need to know current mip number or94// mip "angle" (original texture is 0deg, max mip is 90deg)95// so make sure you give it that as a uniform.96// That does have to be provided per each pass unlike other97// uniforms that are set once.98BlendComponent {99src_factor: BlendFactor::Constant,100dst_factor: BlendFactor::OneMinusConstant,101operation: BlendOperation::Add,102}103}104BloomCompositeMode::Additive => BlendComponent {105src_factor: BlendFactor::Constant,106dst_factor: BlendFactor::One,107operation: BlendOperation::Add,108},109};110111RenderPipelineDescriptor {112label: Some("bloom_upsampling_pipeline".into()),113layout: vec![self.bind_group_layout.clone()],114vertex: self.fullscreen_shader.to_vertex_state(),115fragment: Some(FragmentState {116shader: self.fragment_shader.clone(),117entry_point: Some("upsample".into()),118targets: vec![Some(ColorTargetState {119format: texture_format,120blend: Some(BlendState {121color: color_blend,122alpha: BlendComponent {123src_factor: BlendFactor::Zero,124dst_factor: BlendFactor::One,125operation: BlendOperation::Add,126},127}),128write_mask: ColorWrites::ALL,129})],130..default()131}),132..default()133}134}135}136137pub fn prepare_upsampling_pipeline(138mut commands: Commands,139pipeline_cache: Res<PipelineCache>,140mut pipelines: ResMut<SpecializedRenderPipelines<BloomUpsamplingPipeline>>,141pipeline: Res<BloomUpsamplingPipeline>,142views: Query<(Entity, &Bloom)>,143) {144for (entity, bloom) in &views {145let pipeline_id = pipelines.specialize(146&pipeline_cache,147&pipeline,148BloomUpsamplingPipelineKeys {149composite_mode: bloom.composite_mode,150final_pipeline: false,151},152);153154let pipeline_final_id = pipelines.specialize(155&pipeline_cache,156&pipeline,157BloomUpsamplingPipelineKeys {158composite_mode: bloom.composite_mode,159final_pipeline: true,160},161);162163commands.entity(entity).insert(UpsamplingPipelineIds {164id_main: pipeline_id,165id_final: pipeline_final_id,166});167}168}169170171