bevyengine / bevyengine/bevy

feature: Add multiplicative blending for 2d

Open
#24,230 3 comments 0 reactions 0 assignees View on GitHub
A-Rendering C-Feature D-Modest S-Blocked
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.