mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
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
1 changed files with 37 additions and 45 deletions
|
@ -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,8 +87,11 @@ 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>(
|
||||
// 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,
|
||||
// It also needs the name of the node
|
||||
PostProcessNode::NAME,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue