Obi Official Forum

Full Version: fluid shader doesn't show transparent materials behind it properly
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Take a look at this: https://imgur.com/a/72rK6d5

This is a bottle with the builtin rp standard shader set to transparent mode with some fluid inside of it and another drop of fluid in front of it. While the fluid inside the bottle looks alright, the drop in front of it pretty much removes any opacity from the transparent material behind it, which is especially noticeably in the outer region of the drop that is not colorized.

Is there some way to fix this or is this a hard limitation of the shader?
(02-05-2022, 10:40 AM)locque Wrote: [ -> ]Take a look at this: https://imgur.com/a/72rK6d5

This is a bottle with the builtin rp standard shader set to transparent mode with some fluid inside of it and another drop of fluid in front of it. While the fluid inside the bottle looks alright, the drop in front of it pretty much removes any opacity from the transparent material behind it, which is especially noticeably in the outer region of the drop that is not colorized.

Is there some way to fix this or is this a hard limitation of the shader?

There's no *cheap* way to fix this. It's due to the good old limitation with transparent object rendering: you need them to be sorted back to front for alpha blending to work correctly.

All fluid in the scene is rendered before other transparent objects. This means the fluid is rendered first, then other transparents on top. This more or less covers the typical use case of fluid inside a transparent bottle (for 100% correct results, triangles at the back of the bottle should be rendered first, then the fluid, then triangles at the front of the bottle).

In your case, for correct rendering you'd need to render back of the bottle, fluid inside the bottle, front of the bottle, fluid on front of the bottle, in that specific order. The only way to do that is to sort all triangles in the bottle and all particles in the fluid back to front (according to their distance to the camera), which is very expensive.

Note this is not a limitation of Obi, but of all realtime rendering engines that use rasterization + alpha blending to render transparent objects: you can't render intersecting transparent objects correctly. The only way to do that is use raytracing or OIT (order-independent transparency, which oftentimes is implemented using screen door transparency and very common to dither out objects like walls or columns that get in between the player and the camera in 3rd person games without the need to sort literally everything in the scene)
Thanks for the explanation!

Is there some way to force a transparent material to sort above the fluid shader though? Looks like you can't control it through the render queue parameter, even at 3999 the material will render first and then the fluid.

It would be a very helpful way to mitigate this effect in a different case. Not for the bottle, but the glass dropper that is supposed to be inserted into the bottle to suck up some of the liquid inside. Right now any part of it that is inside of the fluid is not rendered at all. I'd much rather have it render on top of the fluid at all times than not seeing it at all, even if that means it would look weird if you look at the dropper behind the bottle through the liquid.

(02-05-2022, 10:51 AM)josemendez Wrote: [ -> ]Note this is not a limitation of Obi, but of all realtime rendering engines that use rasterization + alpha blending to render transparent objects: you can't render intersecting transparent objects correctly. The only way to do that is use raytracing or OIT (order-independent transparency, which oftentimes is implemented using screen door transparency and very common to dither out objects like walls or columns that get in between the player and the camera in 3rd person games without the need to sort literally everything in the scene)

Cool, didn't know about this! I actually noticed this screen door effect everywhere when I first played GTA IV, always thought it was just a very weird stylistic choice. Haven't seen it in any other third person game since, I played some Division 2 recently which looks great and doesn't have it anywhere.
(02-05-2022, 11:11 AM)locque Wrote: [ -> ]Thanks for the explanation!

Is there some way to force a transparent material to sort above the fluid shader though? Looks like you can't control it through the render queue parameter, even at 3999 the material will render first and then the fluid.

It would be a very helpful way to mitigate this effect in a different case. Not for the bottle, but the glass dropper that is supposed to be inserted into the bottle to suck up some of the liquid inside. Right now any part of it that is inside of the fluid is not rendered at all. I'd much rather have it render on top of the fluid at all times than not seeing it at all, even if that means it would look weird if you look at the dropper behind the bottle through the liquid.


Open up ObiFluidRendererFeature.cs and you'll notice a bunch of render pass events set to "RenderPassEvent.BeforeRenderingTransparents +1;". You can try setting them to anything else like "AfterRenderingTransparents" (see: https://docs.unity3d.com/Packages/com.un...Event.html).

I can't 100% guarantee this will work without side effects, though.

(02-05-2022, 11:11 AM)locque Wrote: [ -> ]Cool, didn't know about this! I actually noticed this screen door effect everywhere when I first played GTA IV, always thought it was just a very weird stylistic choice. Haven't seen it in any other game since.

Pretty much all games I've played that need to fade objects obscuring the player use this approach. Most recent one that I know for sure does it this way is Elden Ring. (not too sure about Division 2)

Rather than a stylistic choice, it's done out of necessity: objects that are transparent (or ever need to become transparent) must be sorted back-to-front to render correctly. If any opaque object in your game (walls, trees, boxes, columns, roofs) can potentially become transparent to avoid obscuring the player, using alpha blending would mean you need to sort everything in the world, every frame.

That's of course not an option if you want decent performance, so the next best thing is to fake transparency using any method that does not require sorting. Screendoor transparency is a good one, and if you can afford to have TAA (temporal anti-aliasing) then it will hide the stipple/dither pattern rather effectively. This can make it look like there's no dithering most of the time, but if you move the camera around fast enough the illusion will break.

If you've ever tried to render a double-sided transparent object in Unity and noticed weird artifacts with triangles disappearing, same reason: you can't sort all individual triangles based on distance to the camera every frame, so depending on the order they appear on the mesh they will just vanish because they're being rendered behind an already rendered triangle (and failing the z-buffer test).

cheers!