feature: Add multiplicative blending for 2d
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## What problem does this solve or what need does it fill?
Currently 2d lighting requires sampling the screen texture and then returning a multiplied derivative of the screen color.
It would be a lot nicer if we could just define multiplicative blending outside of the shader. This would allow us to not sample the screen texture.
It would also make z-sorting light easier. Sampling the screen texture for example doesn't allow for displaying mist/fog easily that is not influenced by light that samples the screen texture.
## What solution would you like?
**NOTE:** There is most likely a good reason why this hasn't been added yet, but I'm not familiar enough with the codebase.
Addding a multiplicative `BlendState` / `BlendOperation` would solve this issue. Since these are part of `wgpu` it might be necessary to do the changes there.
## What alternative(s) have you considered?
I don't think there is a way to achieve true multiplicative blending without sampling the screen texture.
One could probably modify the render graph edges to allow "z-sorting by render graph edge", but this is more of a workaround and would not work for example if one relies on external crates for mist/lighting like [bevy_fast_mist](https://github.com/leomeinel/bevy_fast_mist) and [bevy_fast_light](https://github.com/leomeinel/bevy_fast_light) that define the render graph edges independently of each other (which only makes sense).
## Additional context
My current full screen multiplicative blending shader with the mentioned problems:
```wgsl
#import bevy_core_pipeline::fullscreen_vertex_shader::FullscreenVertexOutput
#import bevy_fast_light::light::types::AmbientLight2d
@group(0) @binding(0)
var screen_texture: texture_2d;
@group(0) @binding(1)
var screen_sampler: sampler;
@group(0) @binding(2)
var light_2d_texture: texture_2d;
@group(0) @binding(3)
var light_2d_sampler: sampler;
@group(0) @binding(4)
var ambient: AmbientLight2d;
@fragment
fn fragment(in: FullscreenVertexOutput) -> @location(0) vec4 {
let src_color = textureSample(screen_texture, screen_sampler, in.uv);
let light_2d_color = textureSample(light_2d_texture, light_2d_sampler, in.uv);
return src_color * (ambient.color + light_2d_color);
}
```
Contributor guide
Assessment
This issue has not been assessed yet.