Open mtsr opened 3 years ago
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.
'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.
I think this bug in sponza might be caused by entity transform ordering:
The column is visible behind the vegetation, but the banner is not. It could be an outright sorting bug though, the banner doesn't have any transparency and should be visible.
This is how it renders in windows 3d viewer:
I can open an issue if this is unrelated.
Closely related to #64.
Noting two things:
However, it can also diverge from the ground truth in scenarios where order strongly affects the result, such as when opacity is high.
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
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.