Add lens dirt support to Bloom#24493
Conversation
|
Very nice |
|
Make the case for me: why should we add this as a feature, rather than repurposing it as a usage example? This seems like the sort of thing you would want to tune heavily on a per-game basis, and it's a nice moderate level of difficulty. |
Integrating lens dirt directly into the bloom pipeline is already standard practice across major engines:
For these reasons, Bevy’s Bloom should support this as well. Furthermore, lens dirt should not simply appear wherever the screen is bright; it should appear wherever Bloom is happening. It is important to recognize that lens dirt is a "cherry on top" effect—it should enhance the image, not pollute it. If developers are left to implement this via a custom fullscreen shader, they will likely base it on screen luminance. This often leads to excessive dirt artifacts that overwhelm the scene. By having Bevy provide this feature natively, we ensure that lens dirt stays correctly bounded by the Bloom intensity, preventing visual pollution by design. Regarding the existing TODO in the Bloom code: If we want to support a bloom mask to control per-region intensity in the future, we will indeed need to move blend factor computation entirely to the GPU during the upsample passes. One possible direction would be to keep CPU-side blend constants when no mask is present (maintaining the current simplicity), and switch to GPU-side calculation only when masks are used. This PR demonstrates that this minimal approach is sufficient for lens dirt. However, if Bloom is expected to gain more advanced features beyond my current knowledge, then fully removing CPU-side blend constants could be the cleaner long-term option. |
|
Lovely analysis; thanks for convincing me! |
|
Maybe instead of an optional texture inside a |
Personally, I don’t think there’s a huge difference right now between having If Bevy gains screen-space lens flare in the future—which is also a post-processing effect that accepts a lens dirt texture (and used heavily in games like Battlefield)—then it would make sense to promote lens dirt to its own component so that both effects can share the same texture. For now, though, I’d prefer to keep it as a field inside |
| @group(0) @binding(4) var dirt_sampler: sampler; | ||
|
|
||
| // Shader version of `compute_blend_factor`. | ||
| fn compute_blend_factor_gpu(mip: f32, max_mip: f32) -> f32 { |
There was a problem hiding this comment.
Why is this needed? This seems to conflict with #23824
There was a problem hiding this comment.
Oops, your explanation made me realize something—I may have been too quick to assume the TODO was strictly necessary.
It turns out we probably don't need to compute the blend factor on the GPU at all; we can simply calculate it on the CPU and upload it.
I think I was taking the TODO a bit too literally. My guess is that the original author wanted to support features like lens dirt, realized the GPU needed access to blend factors, but then ran into the issue that the mip count isn't fixed, making it awkward to fit into a uniform. That’s likely why they suggested moving compute_blend_factor to the GPU.
Instead, I’m now passing the blend factors via var<storage, read>, which works perfectly fine.
That said, I do feel like this approach conflicts even more with #23824... 😅
Objective
Solution
The effect is applied during the final upsampling stage and remains fully optional.
There's a TODO comment inupsampling_pipeline.rs, but I didn't follow it exactly for this lens dirt implementation.It felt like overkill for what I needed, and I just wanted a working lens dirt effect without too much extra complexity.
The TODO approach might make things cleaner in the long run, but this simpler version works well enough for now.
The upsampling process is now calculated on the CPU side and blended on the GPU side, which enables future features such as bloom mask without needing to move
compute_blend_factor()to the GPU side.Testing
bloom_3dexample adds a lens dirt effect and runs as expected.lens_dirt_texture.pngjust for review. This would probably be better placed inbevy_asset_files.lens_dirt.mov