Use dynamic uniform buffer in post processing example (#13540)

# Objective

While learning about shaders and pipelines, I found this example to be
misleading; it wasn't clear to me how the node knew what the correct
"instance" of `PostProcessSettings` we should send to the shader (as the
combination of `ExtractComponentPlugin` and `UniformComponentPlugin`
extracts + sends _all_ of our `PostProcessSetting` components to the
GPU).

The goal of this PR is to clarify how to target the view specific
`PostProcessSettings` in the shader when there are multiple cameras.

## Solution

To accomplish this, we can use a dynamic uniform buffer for
`PostProcessSettings`, querying for the relevant `DynamicUniformIndex`
in the `PostProcessNode` to get the relevant index to use with the bind
group.

While the example in its current state is _correct_, I believe that fact
that it's intended to showcase a per camera post processing effect
warrants a dynamic uniform buffer (even though in the context of this
example we have only one camera, and therefore no adverse behaviour).

## Testing

- Run the `post_processing` example before and after this change,
verifying they behave the same.

## Reviewer notes

This is my first PR to Bevy, and I'm by no means an expert in the world
of rendering (though I'm trying to learn all I can). If there's a better
way to do this / a reason not to take this route, I'd love to hear it!

Thanks in advance.
This commit is contained in:
James Gayfer 2024-06-14 11:04:13 -07:00 committed by François
parent 7c0b1b9029
commit 727b0f6e27
No known key found for this signature in database

View file

@ -15,7 +15,8 @@ use bevy::{
prelude::*,
render::{
extract_component::{
ComponentUniforms, ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin,
ComponentUniforms, DynamicUniformIndex, ExtractComponent, ExtractComponentPlugin,
UniformComponentPlugin,
},
render_graph::{
NodeRunError, RenderGraphApp, RenderGraphContext, RenderLabel, ViewNode, ViewNodeRunner,
@ -124,6 +125,9 @@ impl ViewNode for PostProcessNode {
&'static ViewTarget,
// This makes sure the node only runs on cameras with the PostProcessSettings component
&'static PostProcessSettings,
// As there could be multiple post processing components sent to the GPU (one per camera),
// we need to get the index of the one that is associated with the current view.
&'static DynamicUniformIndex<PostProcessSettings>,
);
// Runs the node logic
@ -137,7 +141,7 @@ impl ViewNode for PostProcessNode {
&self,
_graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
(view_target, _post_process_settings): QueryItem<Self::ViewQuery>,
(view_target, _post_process_settings, settings_index): QueryItem<Self::ViewQuery>,
world: &World,
) -> Result<(), NodeRunError> {
// Get the pipeline resource that contains the global data we need
@ -209,7 +213,10 @@ impl ViewNode for PostProcessNode {
// This is mostly just wgpu boilerplate for drawing a fullscreen triangle,
// using the pipeline/bind_group created above
render_pass.set_render_pipeline(pipeline);
render_pass.set_bind_group(0, &bind_group, &[]);
// By passing in the index of the post process settings on this view, we ensure
// that in the event that multiple settings were sent to the GPU (as would be the
// case with multiple cameras), we use the correct one.
render_pass.set_bind_group(0, &bind_group, &[settings_index.index()]);
render_pass.draw(0..3, 0..1);
Ok(())
@ -240,7 +247,7 @@ impl FromWorld for PostProcessPipeline {
// The sampler that will be used to sample the screen texture
sampler(SamplerBindingType::Filtering),
// The settings uniform that will control the effect
uniform_buffer::<PostProcessSettings>(false),
uniform_buffer::<PostProcessSettings>(true),
),
),
);