-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Transparency improvements #2223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
After some discussion in #rendering it seems that WBOIT indeed makes the best trade-offs for general use of the current solutions. So I'd like to suggest that as the first one to implement. The 7 vulkan implementations includes a WBOIT implementation that can be used as a reference, see the fragment shader, for example: https://github.com/nvpro-samples/vk_order_independent_transparency/blob/master/oitWeighted.frag.glsl |
I'm only familiar with this topic in that I know order independent transparency can be expensive and is an active area of research. Unless WBOIT is approximately a drop-in replacement for "traditional transparency" performance-wise, I think it should probably be opt-in / not default. If that is the case, we should pick an algorithm that can be selectively enabled for specific cases that need it. But yeah, this is definitely something we need to do. Thanks for collecting material for it! |
Weight blended OIT sounded like the most promising while discussing on discord. To me it stands out because it seems to be the easiest to implement and most robust (it's basically a weighted sum over all transparent surfaces - no sorting, no limits to how many transparent layers are possible, etc.). Performance wise I don't see it having much of an impact. The other techniques seem much more elaborate here as they actually perform sorting or some separation of layers. The main downside is that WBOIT is incorrect but it still produces a "plausible" looking result. Unless I'm missing something, compared to traditional transparency it requires one additional fullscreen rendertarget where everything transparent renders to (additively) and one additional compositing pass to resolve the transparency buffer and blend it with the opaque buffer (post process). I also thought about it in terms of playing nice with the rest of the rendering and didn't come up with any blockers. Even from the MSAA perspective it should work very well (the compositing step will also resolve MSAA in this case). |
'Traditional' transparency already breaks down for the transparent sphere, though. So it quickly requires extra effort from the user to make it work. Let alone what happens with more complex meshes. |
But if order-independent transparency is too expensive, some common cases like "drawing lots of grass on the ground" might be very slow by default (although "traditional transparency" also isn't ideal for that use case afaik). The only thing that I currently know performs well enough to be a default is "traditional transparency". But we should implement as many options as we can, compare them, then make a call. This is a case where giving people lots of options is a good idea anyway, so it wouldn't be wasted effort. |
Closely related to #64. |
Noting two things:
|
This isn't relevant to me right now and it doesn't seem like it's something bevy needs right now either. |
Order-independent-transparency would still be a welcome addition. We can track that separately when that comes up though. |
I don’t think this should be closed. And I know @IceSentry has been working on OIT. |
Yep, I'm planning on upstreaming my work during the 0.13 dev cycle |
[Alpha to coverage] (A2C) replaces alpha blending with a hardware-specific multisample coverage mask when multisample antialiasing is in use. It's a simple form of [order-independent transparency] that relies on MSAA. ["Anti-aliased Alpha Test: The Esoteric Alpha To Coverage"] is a good summary of the motivation for and best practices relating to A2C. This commit implements alpha to coverage support as a new variant for `AlphaMode`. You can supply `AlphaMode::AlphaToCoverage` as the `alpha_mode` field in `StandardMaterial` to use it. When in use, the standard material shader automatically applies the texture filtering method from ["Anti-aliased Alpha Test: The Esoteric Alpha To Coverage"]. Objects with alpha-to-coverage materials are binned in the opaque pass, as they're fully order-independent. The `transparency_3d` example has been updated to feature an object with alpha to coverage. Happily, the example was already using MSAA. This is part of #2223, as far as I can tell. [Alpha to coverage]: https://en.wikipedia.org/wiki/Alpha_to_coverage [order-independent transparency]: https://en.wikipedia.org/wiki/Order-independent_transparency ["Anti-aliased Alpha Test: The Esoteric Alpha To Coverage"]: https://bgolus.medium.com/anti-aliased-alpha-test-the-esoteric-alpha-to-coverage-8b177335ae4f --- ## Changelog ### Added * The `AlphaMode` enum now supports `AlphaToCoverage`, to provide limited order-independent transparency when multisample antialiasing is in use.
OIT has been merged; closing as resolved :) |
Uh oh!
There was an error while loading. Please reload this page.
What problem does this solve or what need does it fill?
Currently transparency is handled by splitting entities into two groups and rendering them in sorted order:
Visible::is_transparent == false
)- front-to-back;Visible::is_transparent == true
) - back-to-front.Unfortunately this is not enough to handle the general case. One of the simplest problem cases is when rendering a transparent sphere with another transparent inside. Since the sorting happens by entity transform, the object inside will be incorrectly rendered first if it's behind the origin of the sphere. And it will be incorrectly rendered last if it's in front of the origin of the sphere. To render this situation correctly the back of the sphere needs to be rendered first, then the object inside and then the front of the sphere. This cannot be done by sorting entities.
A reasonable introduction to the problem and evaluation of some solutions can be read in this presentation by nvidia. This slide captures the problem in a nutshell:
What solution would you like?
I think we need to evaluate the costs/benefits of a few different solutions and maybe even implement more than one of them.
Order Independent Transparency seems the most general solution, but the performance cost can be significant. It seems like Weighted Blended Order Independent Transparency has the best trade-off of the common implementations.
What alternative(s) have you considered?
There's a number of different possible solutions:
Additional context
This demo shows 7 different algorithms for OIT implemented using Vulkan.
This video discusses how FrostBite uses OIT for rendering hair.
The text was updated successfully, but these errors were encountered: