use ViewNodeRunner in the post_processing example (#9127)

# Objective

- I forgot to update the example after the `ViewNodeRunner` was merged.
It was even partially mentioned in one of the comments.

## Solution

- Use the `ViewNodeRunner` in the post_processing example
- I also broke up a few lines that were a bit long

---------

Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
This commit is contained in:
IceSentry 2023-08-07 19:02:32 -04:00 committed by GitHub
parent 7ccb203b37
commit 171ff1b1e1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -16,7 +16,7 @@ use bevy::{
extract_component::{
ComponentUniforms, ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin,
},
render_graph::{Node, NodeRunError, RenderGraphApp, RenderGraphContext},
render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext},
render_resource::{
BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor,
BindGroupLayoutEntry, BindingResource, BindingType, CachedRenderPipelineId,
@ -27,11 +27,15 @@ use bevy::{
},
renderer::{RenderContext, RenderDevice},
texture::BevyDefault,
view::{ExtractedView, ViewTarget},
view::ViewTarget,
RenderApp,
},
utils::Duration,
};
use bevy_internal::{
ecs::query::QueryItem,
render::render_graph::{ViewNode, ViewNodeRunner},
};
fn main() {
App::new()
@ -83,7 +87,10 @@ impl Plugin for PostProcessPlugin {
// you need to extract it manually or with the plugin like above.
// Add a [`Node`] to the [`RenderGraph`]
// The Node needs to impl FromWorld
.add_render_graph_node::<PostProcessNode>(
//
// The [`ViewNodeRunner`] is a special [`Node`] that will automatically run the node for each view
// matching the [`ViewQuery`]
.add_render_graph_node::<ViewNodeRunner<PostProcessNode>>(
// Specify the name of the graph, in this case we want the graph for 3d
core_3d::graph::NAME,
// It also needs the name of the node
@ -113,60 +120,42 @@ impl Plugin for PostProcessPlugin {
}
}
/// The post process node used for the render graph
struct PostProcessNode {
// The node needs a query to gather data from the ECS in order to do its rendering,
// but it's not a normal system so we need to define it manually.
query: QueryState<&'static ViewTarget, With<ExtractedView>>,
}
// The post process node used for the render graph
#[derive(Default)]
struct PostProcessNode;
impl PostProcessNode {
pub const NAME: &str = "post_process";
}
impl FromWorld for PostProcessNode {
fn from_world(world: &mut World) -> Self {
Self {
query: QueryState::new(world),
}
}
}
impl Node for PostProcessNode {
// This will run every frame before the run() method
// The important difference is that `self` is `mut` here
fn update(&mut self, world: &mut World) {
// Since this is not a system we need to update the query manually.
// This is mostly boilerplate. There are plans to remove this in the future.
// For now, you can just copy it.
self.query.update_archetypes(world);
}
// The ViewNode trait is required by the ViewNodeRunner
impl ViewNode for PostProcessNode {
// The node needs a query to gather data from the ECS in order to do its rendering,
// but it's not a normal system so we need to define it manually.
//
// This query will only run on the view entity
type ViewQuery = &'static ViewTarget;
// Runs the node logic
// This is where you encode draw commands.
//
// This will run on every view on which the graph is running. If you don't want your effect to run on every camera,
// you'll need to make sure you have a marker component to identify which camera(s) should run the effect.
// This will run on every view on which the graph is running.
// If you don't want your effect to run on every camera,
// you'll need to make sure you have a marker component as part of [`ViewQuery`]
// to identify which camera(s) should run the effect.
fn run(
&self,
graph_context: &mut RenderGraphContext,
_graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
view_target: QueryItem<Self::ViewQuery>,
world: &World,
) -> Result<(), NodeRunError> {
// Get the entity of the view for the render graph where this node is running
let view_entity = graph_context.view_entity();
// We get the data we need from the world based on the view entity passed to the node.
// The data is the query that was defined earlier in the [`PostProcessNode`]
let Ok(view_target) = self.query.get_manual(world, view_entity) else {
return Ok(());
};
// Get the pipeline resource that contains the global data we need to create the render pipeline
// Get the pipeline resource that contains the global data we need
// to create the render pipeline
let post_process_pipeline = world.resource::<PostProcessPipeline>();
// The pipeline cache is a cache of all previously created pipelines.
// It is required to avoid creating a new pipeline each frame, which is expensive due to shader compilation.
// It is required to avoid creating a new pipeline each frame,
// which is expensive due to shader compilation.
let pipeline_cache = world.resource::<PipelineCache>();
// Get the pipeline from the cache
@ -191,9 +180,11 @@ impl Node for PostProcessNode {
// The bind_group gets created each frame.
//
// Normally, you would create a bind_group in the Queue set, but this doesn't work with the post_process_write().
// Normally, you would create a bind_group in the Queue set,
// but this doesn't work with the post_process_write().
// The reason it doesn't work is because each post_process_write will alternate the source/destination.
// The only way to have the correct source/destination for the bind_group is to make sure you get it during the node execution.
// The only way to have the correct source/destination for the bind_group
// is to make sure you get it during the node execution.
let bind_group = render_context
.render_device()
.create_bind_group(&BindGroupDescriptor {
@ -407,7 +398,8 @@ fn update_settings(mut settings: Query<&mut PostProcessSettings>, time: Res<Time
// Scale it to a more reasonable level
intensity *= 0.015;
// Set the intensity. This will then be extracted to the render world and uploaded to the gpu automatically.
// Set the intensity.
// This will then be extracted to the render world and uploaded to the gpu automatically by the [`UniformComponentPlugin`]
setting.intensity = intensity;
}
}