bevyengine / bevyengine/bevy

Custom Post-Processing Example is too low-level and doesn't generalize to reading depth buffer / getting view position

Open
#20,219 2 comments 5 reactions 0 assignees View on GitHub
A-Rendering C-Docs C-Examples D-Modest S-Ready-For-Implementation X-Uncontroversial
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 16h
Merged PRs (30d)
171

Description

The [custom post-processing example](https://bevy.org/examples/shaders/custom-post-processing/) shows how to read from and write to the camera target texture, but that's it.

A lot of effects require reading other information, like normals, depth, and camera view transform. Unfortunately, these don't fit into the pattern outlined by this example.

For example, [bevy atmosphere](https://github.com/bevyengine/bevy/blob/8878083cf77fc36a34aa03328fc8e561e4b9894f/crates/bevy_pbr/src/atmosphere/resources.rs#L568) introduces the `prepare_atmosphere_bind_groups` system, added to the `RenderApp` `RenderSystems::PrepareBindGroups` system set. As far as I can tell, this is necessary to be able to get layout information for uniforms like the view.

But there's no corresponding system in the custom-post-processing example, so even copying the logic from `bevy_atmosphere` is difficult. Since the custom-post-processing example is trying to be simple, it ends up completely skipping a pattern that becomes (I think?) necessary if you want to write a more complex post-process pass.

---

Error messages while debugging post-processing are also not ideal. Here are two that I ran into, for example:

```
thread '' panicked at C:\Users\nfenn\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-24.0.5\src\backend\wgpu_core.rs:3273:26:
wgpu error: Validation Error

Caused by:
In RenderPass::end
In a set_bind_group command
BindGroup with 'post_process_bind_group' label 0 expects 2 dynamic offsets. However 1 dynamic offset were provided.
```

In the above case, I added the `view` uniform to the bind group, but forgot to update the `set_bind_group` call to include the additional `dynamic_uniform_indices` value. In theory, Bevy has enough info (in principle) to reconstruct the exact mistake that I made, and tell me which bind group members need dynamic offsets (e.g. their names, ideally).

```
thread '' panicked at C:\Users\nfenn\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-24.0.5\src\backend\wgpu_core.rs:3273:26:
wgpu error: Validation Error

Caused by:
In RenderPass::end
In a pass parameter
Attempted to use Texture with 'main_texture_a' label (mips 0..1 layers 0..1) with conflicting usages. Current usage TextureUses(RESOURCE) and new usage TextureUses(COLOR_TARGET). TextureUses(COLOR_TARGET) is an exclusive usage and cannot be used with any other usages within the usage scope (renderpass or compute dispatch).
```

I am still not quite sure what's going on with this error. I must have accidentally declared that I'm both reading and writing to the render target, but I don't know how.

If you compare this to writing an `ExtendedMaterial`, there's a much, much steeper learning curve for post-processing, and very few real-world examples to go off of which are simple enough to adapt for custom shaders.

---

Ideally, the interface to implement for this kind of custom shader would be something like (pseudocode):

```rs

#[derive(Component)]
struct PostProcessingSettings {
radius: f32,
}

#[derive(CustomPostProcessingPass);
struct MyPostProcessing {
#[binding(0)]
depth: DepthTexture,

#[binding(1)]
view: ViewTexture,

#[binding(2)]
#[camera_component]
settings: PostProcessingSettings,

#[binding(3)]
#[view]
view: View,
}

impl PostProcessingShader for MyPostProcessing {
fn shader_path() -> &str {
"my_shader.wgsl"
}
}
```

For most bindings, there is an "obvious" place to obtain the binding - a type-directed API which knows how to look up various components/resources/etc to properly build/specialize the post-processing pass seems like it could be built declaratively, instead of requiring e.g. duplicate effort to define a `BindGroupLayout` and then separately extract/build a `BindGroup` etc.

Contributor guide

Open the contributing guide

Research direction

Start with the custom post-processing example and the prepare_atmosphere_bind_groups system in crates/bevy_pbr/src/atmosphere/resources.rs, including its RenderApp and RenderSystems::PrepareBindGroups integration. Compare the example with the reported bind-group and texture-usage errors; completion should leave a documented, generalizable path for complex post-processing bindings and clearer guidance for these failures.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
computer-graphics
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.