Single Layer Water + Translucent Materials

Hello,

UE4.27 project.

I am using the Single Layer Water material for my water. My game has blocks that can be distributed by the player throughout the entire world, including in and out of water. Some of these blocks can be transparent (translucent materials).

Because the Single Layer Water shader is opaque, if a transparent block is partially submerged in water, the side on the other side of the water from the camera is not rendered. Is there a way around this? Simple example shown. Green cube is opaque and renders properly above and below water. Red cube is translucent, only above the water renders, because the depth check cuts it off when below the water surface.
image

I have tried turning off the depth check and doing it manually based on the Shading Model ID. If its landscape, don’t fade, if its Single Layer Water, fade. However if an opaque object comes in between the water surface and the submerged block, the translucent object shows through the opaque object. Example below, green opaque, red translucent material, blue translucent with a custom depth test against Single Layer Water

And an example of the problem this solution produces

Have I missed something here? Is there a standard way of achieving translucent materials behind Single Layer Water surfaces?

I’d be grateful for any assistance,
Thanks.

You’re not gonna like this but the standard way of dealing with multiple translucencies intersecting is “don’t do it”. It wasn’t even until the latest release that unreal added support for Order Independent Translucency. Deferred rendering sucks at translucent materials.

But if you must,

You could probably sample the original depth buffer in your post process and determine which pixels are in front of the custom depth stencil and use it to create a mask.

You could also render the mesh twice, once as transparent and again as masked and skip the postprocess altogether. In the masked version, mask out anything above the water line. Unreal has a new feature “overlay materials” that might be used to achieve this double rendering. The underwater portion could be left either totally opaque, or dithered to make it look kind of transparent.

I would ask myself does it really need to be translucent? The answer is no surprisingly often. Most games, even AAA use true translucency extremely sparingly.

Hello @BananableOffense, thank you for your reply.

Unfortunately it is not up to me if the blocks are transparent, so I have to make it work.

After posting I did manage to achieve what I wanted, but it requires all opaque objects to have Custom Depth turned on when they come in contact with the water, which is not ideal, partly for performance and partly because it breaks things we use stencils for. (We do not currently use stencils in bitmask mode).
image

I am not sure what you mean here. I am not doing any post processing related to this yet. And I can’t use the original depth buffer for this information because the Single Layer Water writes into the depth buffer, overwriting the information I would need.
I think the idea of what you are saying is how I have achieved the result with the Custom Depth though.

This is a possibility, but the difference in appearance I feel is going to be quite noticeable between above and below the water, I might give it a try anyway just to see it.

Do you have any reference material for this, I cannot find anything about it, but its interesting as this would have been one of my approaches for the above if using Unity, as they allow multiple materials to be applied to a single polygon. My understanding was Unreal does not.

If anyone is interested in how I have it working right now (as bad as it may be) this is the material function

But I am still looking for something better!

Single Layer Water materials actually can sample the original depth using the “Scene Depth Without Water” node.

Overlay materials are in the mesh details panel. Not sure if theres any documentation for it yet, but it seems to work as expected. Pick a material to layer on top, and set a max draw distance if needed.

This stuff will also be a lot less noticeable if you add a normal map to your water, as the reflections will make what’s underwater less visible. Although if you plan on using refraction, your depth and custom depth buffers won’t automatically refract along with it causing them to become misaligned.

I’d probably go with the second material pass if you plan to use refraction, and the depth masking if you don’t.

Thanks for continuing to reply @BananableOffense.

I did not know about the Scene Depth Without Water, that may be useful in the future, thanks.
It does not help me in this situation however, as the node is only available in a Single Layer Water material. I don’t see how I could get that information out, so its usable in the Translucency pass, where my glass is being rendered.

I found out where this is, its in Unreal Engine 5/5.1, not 4.27. Unfortunately my project is stuck on 4.27, something out of my control.

The actual water and objects look very different, the images provided are the most basic example of the problem, I don’t have permission to show the actual game yet.

It does not help me in this situation however, as the node is only available in a Single Layer Water material. I don’t see how I could get that information out, so its usable in the Translucency pass, where my glass is being rendered.

If it exists, it can be piped out to a buffer and sampled somewhere else. Here’s a screenshot of a standard translucent cylinder sampling the scene depth w/o water output of the cube, which is using SLW. The sphere is opaque and fully obscured, so it wouldn’t show in the standard scene depth as you noted.
In this example, I hijacked the Material AO buffer, as to my knowledge SLW with opacity set to 0 would have no contributions from it’s Material AO anyway.


If you aren’t willing to sacrifice any of the buffers to store the depth w/o water, you’d need a render target to write it to I guess.

I found out where this is, its in Unreal Engine 5/5.1, not 4.27. Unfortunately my project is stuck on 4.27, something out of my control.

Ah yes, the native overlay feature is unfortunately brand new but it wouldn’t be too hard to replicate if you go that route.

The actual water and objects look very different, the images provided are the most basic example of the problem, I don’t have permission to show the actual game yet.

Gotcha. Well, look out for refraction regardless. It can be manually replicated for your samplers but it’s a good bit of work.

Thanks @BananableOffense, that is a good example.

I might have a spare buffer I could use. I use the Anisotropy channel in a similar method for something else, just didn’t occur to me to do it for this. If I do not have a spare buffer, is there a way to pipe it out to a render target without C++. Like directly from the material? The only methods I know of would require baked data or a scene capture, scene captures in my tests are expensive and a frame or two behind, and baked data is not suitable because players can change the location of objects.

Thanks, I have seen that it is not affecting the glass already, I’m hoping it will not be noticeable, or I will fake it.

You can bake out render targets directly from materials with blueprints, but I’ve only used it in that way for baking textures which didn’t need to have any sort of view projection.

Perhaps you could have an invisible camera aligned plane shaded with SLW. Then you could have it save it’s scene depth w/o water directly from it via bp like baking any texture. You could probably get away with doing it at less than screen resolution. If you need info on how to render a material out to a target with BP, Ryan Brucks has a tutorial that could give you a head start.