use ViewNodeRunner in the post_processing example (#9127)
- I forgot to update the example after the `ViewNodeRunner` was merged. It was even partially mentioned in one of the comments. - 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:
parent
633f121502
commit
2a02929b1a
@ -16,7 +16,7 @@ use bevy::{
|
|||||||
extract_component::{
|
extract_component::{
|
||||||
ComponentUniforms, ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin,
|
ComponentUniforms, ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin,
|
||||||
},
|
},
|
||||||
render_graph::{Node, NodeRunError, RenderGraphApp, RenderGraphContext},
|
render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext},
|
||||||
render_resource::{
|
render_resource::{
|
||||||
BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor,
|
BindGroupDescriptor, BindGroupEntry, BindGroupLayout, BindGroupLayoutDescriptor,
|
||||||
BindGroupLayoutEntry, BindingResource, BindingType, CachedRenderPipelineId,
|
BindGroupLayoutEntry, BindingResource, BindingType, CachedRenderPipelineId,
|
||||||
@ -27,11 +27,15 @@ use bevy::{
|
|||||||
},
|
},
|
||||||
renderer::{RenderContext, RenderDevice},
|
renderer::{RenderContext, RenderDevice},
|
||||||
texture::BevyDefault,
|
texture::BevyDefault,
|
||||||
view::{ExtractedView, ViewTarget},
|
view::ViewTarget,
|
||||||
RenderApp,
|
RenderApp,
|
||||||
},
|
},
|
||||||
utils::Duration,
|
utils::Duration,
|
||||||
};
|
};
|
||||||
|
use bevy_internal::{
|
||||||
|
ecs::query::QueryItem,
|
||||||
|
render::render_graph::{ViewNode, ViewNodeRunner},
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@ -83,8 +87,11 @@ impl Plugin for PostProcessPlugin {
|
|||||||
// you need to extract it manually or with the plugin like above.
|
// you need to extract it manually or with the plugin like above.
|
||||||
// Add a [`Node`] to the [`RenderGraph`]
|
// Add a [`Node`] to the [`RenderGraph`]
|
||||||
// The Node needs to impl FromWorld
|
// The Node needs to impl FromWorld
|
||||||
.add_render_graph_node::<PostProcessNode>(
|
//
|
||||||
// Specifiy the name of the graph, in this case we want the graph for 3d
|
// 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,
|
core_3d::graph::NAME,
|
||||||
// It also needs the name of the node
|
// It also needs the name of the node
|
||||||
PostProcessNode::NAME,
|
PostProcessNode::NAME,
|
||||||
@ -113,60 +120,42 @@ impl Plugin for PostProcessPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The post process node used for the render graph
|
// The post process node used for the render graph
|
||||||
struct PostProcessNode {
|
#[derive(Default)]
|
||||||
// The node needs a query to gather data from the ECS in order to do its rendering,
|
struct PostProcessNode;
|
||||||
// but it's not a normal system so we need to define it manually.
|
|
||||||
query: QueryState<&'static ViewTarget, With<ExtractedView>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PostProcessNode {
|
impl PostProcessNode {
|
||||||
pub const NAME: &str = "post_process";
|
pub const NAME: &str = "post_process";
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromWorld for PostProcessNode {
|
// The ViewNode trait is required by the ViewNodeRunner
|
||||||
fn from_world(world: &mut World) -> Self {
|
impl ViewNode for PostProcessNode {
|
||||||
Self {
|
// The node needs a query to gather data from the ECS in order to do its rendering,
|
||||||
query: QueryState::new(world),
|
// 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;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Runs the node logic
|
// Runs the node logic
|
||||||
// This is where you encode draw commands.
|
// 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,
|
// This will run on every view on which the graph is running.
|
||||||
// you'll need to make sure you have a marker component to identify which camera(s) should run the effect.
|
// 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(
|
fn run(
|
||||||
&self,
|
&self,
|
||||||
graph_context: &mut RenderGraphContext,
|
_graph: &mut RenderGraphContext,
|
||||||
render_context: &mut RenderContext,
|
render_context: &mut RenderContext,
|
||||||
|
view_target: QueryItem<Self::ViewQuery>,
|
||||||
world: &World,
|
world: &World,
|
||||||
) -> Result<(), NodeRunError> {
|
) -> Result<(), NodeRunError> {
|
||||||
// Get the entity of the view for the render graph where this node is running
|
// Get the pipeline resource that contains the global data we need
|
||||||
let view_entity = graph_context.view_entity();
|
// to create the render pipeline
|
||||||
|
|
||||||
// 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
|
|
||||||
let post_process_pipeline = world.resource::<PostProcessPipeline>();
|
let post_process_pipeline = world.resource::<PostProcessPipeline>();
|
||||||
|
|
||||||
// The pipeline cache is a cache of all previously created pipelines.
|
// 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>();
|
let pipeline_cache = world.resource::<PipelineCache>();
|
||||||
|
|
||||||
// Get the pipeline from the cache
|
// Get the pipeline from the cache
|
||||||
@ -191,9 +180,11 @@ impl Node for PostProcessNode {
|
|||||||
|
|
||||||
// The bind_group gets created each frame.
|
// 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 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
|
let bind_group = render_context
|
||||||
.render_device()
|
.render_device()
|
||||||
.create_bind_group(&BindGroupDescriptor {
|
.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
|
// Scale it to a more reasonable level
|
||||||
intensity *= 0.015;
|
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;
|
setting.intensity = intensity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user