bevy_dither_post_process/
lib.rs1#![warn(missing_docs)]
2
3use bevy::{
7 asset::embedded_asset,
8 core_pipeline::core_3d::graph::{Core3d, Node3d},
9 prelude::*,
10 render::{
11 extract_component::ExtractComponentPlugin,
12 render_graph::{RenderGraphApp, ViewNodeRunner},
13 render_resource::{PipelineCache, SpecializedRenderPipelines, TextureFormat},
14 view::{ExtractedView, ViewTarget},
15 Render, RenderApp, RenderSet,
16 },
17};
18use components::DitherPostProcessPipelineId;
19use resources::{DitherPostProcessPipeline, DitherPostProcessingPipelineKey};
20
21use crate::components::DitherPostProcessSettings;
22
23pub use nodes::DitherRenderLabel;
24
25pub struct DitherPostProcessPlugin;
27
28pub mod components;
30
31mod nodes;
32mod resources;
33
34impl Plugin for DitherPostProcessPlugin {
35 fn build(&self, app: &mut App) {
36 embedded_asset!(app, "../assets/shaders/dither_post_process.wgsl");
37
38 app.add_plugins((ExtractComponentPlugin::<DitherPostProcessSettings>::default(),));
39
40 let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
41 return;
42 };
43
44 render_app
45 .add_systems(
46 Render,
47 prepare_post_processing_pipelines.in_set(RenderSet::Prepare),
48 )
49 .init_resource::<SpecializedRenderPipelines<DitherPostProcessPipeline>>()
50 .add_render_graph_node::<ViewNodeRunner<nodes::DitherRenderNode>>(
51 Core3d,
52 nodes::DitherRenderLabel,
53 )
54 .add_render_graph_edges(
55 Core3d,
56 (
57 Node3d::Tonemapping,
58 nodes::DitherRenderLabel,
59 Node3d::EndMainPassPostProcessing,
60 ),
61 );
62 }
63
64 fn finish(&self, app: &mut App) {
65 let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
66 return;
67 };
68
69 render_app.init_resource::<resources::DitherPostProcessPipeline>();
70 }
71}
72
73fn prepare_post_processing_pipelines(
74 mut commands: Commands,
75 pipeline_cache: Res<PipelineCache>,
76 mut pipelines: ResMut<SpecializedRenderPipelines<DitherPostProcessPipeline>>,
77 post_processing_pipeline: Res<DitherPostProcessPipeline>,
78 views: Query<(Entity, &ExtractedView), With<DitherPostProcessSettings>>,
79) {
80 for (entity, view) in views.iter() {
81 let pipeline_id = pipelines.specialize(
82 &pipeline_cache,
83 &post_processing_pipeline,
84 DitherPostProcessingPipelineKey {
85 texture_format: if view.hdr {
86 ViewTarget::TEXTURE_FORMAT_HDR
87 } else {
88 TextureFormat::bevy_default()
89 },
90 },
91 );
92
93 commands
94 .entity(entity)
95 .insert(DitherPostProcessPipelineId(pipeline_id));
96 }
97}