Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use ViewNodeRunner in the post_processing example #9127

Merged
merged 3 commits into from
Aug 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 36 additions & 44 deletions examples/shader/post_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -401,7 +392,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;
}
}