#![warn(missing_docs)]
use bevy::{
asset::embedded_asset,
core_pipeline::core_3d::graph::{Core3d, Node3d},
prelude::*,
render::{
extract_component::ExtractComponentPlugin,
render_graph::{RenderGraphApp, ViewNodeRunner},
render_resource::{PipelineCache, SpecializedRenderPipelines, TextureFormat},
view::{ExtractedView, ViewTarget},
Render, RenderApp, RenderSet,
},
};
use components::DitherPostProcessPipelineId;
use resources::{DitherPostProcessPipeline, DitherPostProcessingPipelineKey};
use crate::components::DitherPostProcessSettings;
pub use nodes::DitherRenderLabel;
pub struct DitherPostProcessPlugin;
pub mod components;
mod nodes;
mod resources;
impl Plugin for DitherPostProcessPlugin {
fn build(&self, app: &mut App) {
embedded_asset!(app, "../assets/shaders/dither_post_process.wgsl");
app.add_plugins((ExtractComponentPlugin::<DitherPostProcessSettings>::default(),));
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
render_app
.add_systems(
Render,
prepare_post_processing_pipelines.in_set(RenderSet::Prepare),
)
.init_resource::<SpecializedRenderPipelines<DitherPostProcessPipeline>>()
.add_render_graph_node::<ViewNodeRunner<nodes::DitherRenderNode>>(
Core3d,
nodes::DitherRenderLabel,
)
.add_render_graph_edges(
Core3d,
(
Node3d::Tonemapping,
nodes::DitherRenderLabel,
Node3d::EndMainPassPostProcessing,
),
);
}
fn finish(&self, app: &mut App) {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return;
};
render_app.init_resource::<resources::DitherPostProcessPipeline>();
}
}
fn prepare_post_processing_pipelines(
mut commands: Commands,
pipeline_cache: Res<PipelineCache>,
mut pipelines: ResMut<SpecializedRenderPipelines<DitherPostProcessPipeline>>,
post_processing_pipeline: Res<DitherPostProcessPipeline>,
views: Query<(Entity, &ExtractedView), With<DitherPostProcessSettings>>,
) {
for (entity, view) in views.iter() {
let pipeline_id = pipelines.specialize(
&pipeline_cache,
&post_processing_pipeline,
DitherPostProcessingPipelineKey {
texture_format: if view.hdr {
ViewTarget::TEXTURE_FORMAT_HDR
} else {
TextureFormat::bevy_default()
},
},
);
commands
.entity(entity)
.insert(DitherPostProcessPipelineId(pipeline_id));
}
}