Skip to content

Implement Premultiplied Alpha for OIT#22821

Open
Schmarni-Dev wants to merge 1 commit intobevyengine:mainfrom
Schmarni-Dev:premul_oit_new
Open

Implement Premultiplied Alpha for OIT#22821
Schmarni-Dev wants to merge 1 commit intobevyengine:mainfrom
Schmarni-Dev:premul_oit_new

Conversation

@Schmarni-Dev
Copy link
Copy Markdown

Objective

Solution

  • Store Premultiplied color in the OIT buffer and premultiply in the case of AlphaMode::Blend, this shouldn't have any downsides since blending was done with premultiplied alpha anyway.
  • It might be useful to actively break the oit_draw signature by adding a premultiply bool to ensure that shader authors are aware of the changed meaning of the color argument.

Testing

  • These changes have been tested by running the modified order_independent_transparency example, an older version of these changes has been in use in a project i work on.

Showcase

Here the Red Sphere uses AlphaMode::Blend, the Blue Sphere AlphaMode::Add and the Green Sphere AlphaMode::Premultiplied.

bevy-oit-example

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 5, 2026

Welcome, new contributor!

Please make sure you've read our contributing guide and we look forward to reviewing your pull request shortly ✨

@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-Rendering Drawing game state to the screen S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Feb 5, 2026
@IceSentry
Copy link
Copy Markdown
Contributor

IceSentry commented Feb 5, 2026

Thank you for making this PR! We are about to merge a big OIT refactor though so you will likely have some conflict with your PR #21831

@Schmarni-Dev
Copy link
Copy Markdown
Author

I can rebase these changes once that PR is merged

@beicause
Copy link
Copy Markdown
Contributor

beicause commented Feb 6, 2026

AlphaMode::Add operation is order independent so it doesn't need oit_draw.
😅 AlphaMode::Add seems to be result = vec4(src_alpha * src_color.rgb, 0.0) + 1 * dst_color.rgba which is not order independent.

It seems multiply is the only unsupported mode as it requires a different blend function, which is not free.

fn oit_draw(position: vec4f, color: vec4f) {
// Don't add fully transparent fragments to the list
// because we don't want to have to sort them in the resolve pass
if color.a < oit_settings.alpha_threshold {
Copy link
Copy Markdown
Contributor

@beicause beicause Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do this somewhere before premultiply_alpha?
For Add and Premultiplied modes we should not cull alpha in here

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or we could consider removing this setting. After all users can do it themselves in custom materials.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be fixed now, i adjusted the check to work correctly for premultiplied alpha, should have the same results as before this change

Copy link
Copy Markdown
Contributor

@beicause beicause Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not correct to compare individual components. An alternative is to compare luminance.

I think there should be a luminance threshold setting for premultiplied or add mode.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would it not be correct to compare the individual components? it should be the same check as the one that was here before, just now it acts on premultiplied color

Copy link
Copy Markdown
Contributor

@beicause beicause Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering the color contribution of premultiplied alpha, it seems more reasonable to compare the emitted luminance rather than comparing each component individually

Signed-off-by: Schmarni <marnistromer@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior S-Needs-Review Needs reviewer attention (from anyone!) to move forward

Projects

Status: Needs SME Triage
Status: No status

Development

Successfully merging this pull request may close these issues.

Rendering Ordering Issue with OIT and AlphaMode::Premultiplied

5 participants