How do you fade foliage out when culling in the distance?

I’ve been working for a couple of weeks now on trying to get a field of grass running in UE4. I’ve been through all the tutorials and read all the forum posts I can find on the topic, but am finding it a frustrating task.

Because I’m developing a VR game, I’ve discounted billboard grass entirely since this never seemed to look good in stereo vision. Instead I have geometry for all my grass, with multiple blades of a small number of quads per instance at 4 LODs. I also have geometry flowers in the grass that use Opacity Mask for the petals, so even though my grass blades can be Opaque, I need a method to suit my flowers too. And because of the VR requirement, I have twice the scene-rendering hit, so my LOD and culling strategy for the grass has to be pretty good.

The main issue I have is how to cull the grass in the distance nicely. I can set the Landscape folliage cull to start at 4000 and end at 5000, but this culls the entire block of grass and not the instances. We are told to use PerInstanceFadeAmount to fade our models over this distance, which is great. However, currently you cannot use Transparent as a Blend Model for grass, which means you have no Opacity to plug the value into.

One workaround is to multiply it with your Alpha mask and plug it into Opacity Mask, but this means that you get a sudden cull point per instance and not a nice gradual fade. It looks a lot nicer than a whole block of grass appearing from nowhere, however. This is currently my best solution.

I came up with an interesting concept of using PerInstanceFadeAmount to lower each vertex in the grass so that the grass faded back into the ground in the distance, but depending on the terrain slope this looked a little bit like the grass was sprouting magically out of the ground before you. And while this sort of worked with the grass (fading into the landscape texture), it was not so great at successfully fading a bright yellow flower in that grass. Because what would be awesome is actually fading the flower or grass in with opacity, if that were possible.

I’ve also spent many, many hours frustratingly fiddling with Subsurface, because there are the odd forum posts that mention it as a means to get both Opacity Masking for petals, and Opacity for fading the model out. I must not understand Subsurface because I could not get this to work at all, and nothing I tried made the instance at all transparent.

Can anyone share any tips on getting PerInstanceFadeAmount to actually fade grass instances?

Use PerInstanceFadeAmount passes the current cull distance value, it seems to work well. I just tested it on a cube placed as foliage, using a masked material that’s just red base color and a linearGradient * PerInstanceFadeAmount plugged into opacitymask. It smoothly modifies the opacity mask gradient across all instances at the same rate nicely, no cluster popping.

I think your problem may be that your opacity map is just black and white with no gradient. Try blurring your opacity map texture. With opacity masking, Grays will dissolve faster, and white will be last to dissolve. After you’ve modified the opacity texture mask, your resulting foliage might look thinner or thicker alpha before the cull distances, you can use OpacityMaskClipValue in the material’s parameters to get the fully unculled alpha to be closer to where it was before the blurring. Once you get the hang of it, you can plan ahead and bake out pseudo-heightmaps or curvature maps or whatever needed to use for opacitymasks so you can better control the thinning of the dissolve look with masked materials.

Also with this technique you can mimic the vertex scaling trick you mentioned, by making a vertical gradient in your mask texture, with white at the bottom of the texture. That way it will appear to scale the foliage towards the base, without the geometry aligned to slopes issue.

I know the dissolve look on masked materials isn’t ideal as transparent fading. You might want to try a noise applied to your opacity mask, and try using DitherTemporalAA and see if that softens it up.

Just tested the DitherTemporalAA. With your original alpha mask (unblurred, no gray transition) you can get a kinda translucent fading approximation, with some minimal screen-door artifacts:

AlphaChannel * PerInstanceFadeAmount –> plug result into “AlphaThreshold (S)” pin of DitherTemporalAA —> OpacityMask slot of material.

You can reduce the screen-door stippling artifacts via setting “Random(S)” to 0, but then you see the foliage pop out. 0.5- 1.0 works well in my case.

1 Like

That is exactly my solution and thanks so much for your reply. This has been plaguing me for weeks.

Because my grass is single blades of geometry, I had no alpha channel in the texture, and it never occurred to me to add one. Now I have added a gradient from top to bottom in the texture, although your LinearGradient idea worked just as well (although probably has a render hit over just looking up the alpha value). I’m imagining that for flowers in the grass I can probably create a radial gradient and make the flower appear to shrink in to the center.

As you suggested, I now have PerInstanceFadeAmount Multiplied by the alpha of my texture, going into a DitherTemporalAA and then to OpacityMask. In the material settings I have Masked blend mode and currently 0.05 Opacity Mask. I’m having to fine-tune a few of the variables (cull distance, and the gradient range) to get the best fade in of my grass, without seeing the dithering effect too close. But the fading in of the grass means that I can have a cull distance of half what I had before and not really notice it. Grass ghosts-in in front of you, but I think that’s acceptable. “Ghosting” is the new “Fog”, right? :slight_smile:

Without the Dither it looks like it will be hard to achieve the same fade, since effectively the top of the grass blade is not drawn at distance, leaving only the lower part which is textured to be darker, so you get a dispersed (due to LOD level) dark fringe to the grass. I suppose this is one advantage of my previous method of lowering the grass vertices over distance since the tip of the grass is the last part to vanish.

Such is the way of things that I’d never heard of DitherTemporalAA until today.

Although… :slight_smile: a bit more testing with the Rift and I find a potential issue.

Having a sharp contrast with the dithering does not look good. So, light green grass against light blue sky is great, but dark shadowed grass against light blue sky is nasty. Not only because you see the dithering which is much more apparent at the lower res of the Rift, but I think there’s something odd about the stereo effect. It looks kind of “fuzzy”. And now I remember reading somewhere that Temporal AA should be disabled as a post-process for the Rift as it is not supported and causes strange visual effects. I guess this uses the same mechanism. Potentially I can mask this with some more anti-aliasing and setting the lighting to avoid sudden changes of contrast where they can be seen.

Otherwise we’re back to plugging the gradient into OpacityMask without the dither, which has its own issues. But maybe I can also manipulate the colour of the grass as it fades so the lower part of the stalk is brightened slightly and matches my landscape texture. Or maybe set up my alpha to fade in horizontally instead of vertically for each blade.

I know a lot of posts a few months ago about Temporal AA not working well for VR, I’m not sure but I think it may have been improved since then. At the moment TemporalAA is working fine for me in DK2 with no issues in 4.5, just a bit blurry but nicely minimizes the aliasing. And in Epic’s Crescent Bay demo they mentioned using DitherTemporalAA for one effect or two, so it must’ve been upgraded since then. But I haven’t checked the ditherTemporalAA effect yet on my foliage test case, I’ll have to give it a go.

Just wondering Moo, do you have a posting on Oculus’ forum in the works in progress section? would love to see what you’re up to.

Thanks. I’ll keep plugging away at it. If nothing else then the flowers in the grass have acceptable dithering via this method, and I can probably hide the grass issues with lighting.

The dithering did look a bit strange to my eyes, but I couldn’t decide if it was just normal aliasing due to small movements of my head, or stereo-incorrect aliasing. Either way, there was a lot of fuzziness. I might look into additional anti-aliasing or depth of field or something.

I don’t have anything to show as a WIP other than a big expanse of grass at the moment. So, given my rate of progress, I’ll probably be in a position to post something round about the time that CV1 eventually appears on the shelves. :slight_smile:

My simple “grass disappearing” material, like Z-buffer:

This is awesome, AntonioModer! Thank you very much for sharing!

I am happy to help! :slight_smile:

Thanks. I’ll try that idea out. Seems like there would have to be some tuning of the alpha in the texture and the Clip Value to get it to smoothly fade out, rather than just mask to a circle round the camera.

Currently for my grass material I have:

PerInstanceFaceAmount — Multiply (with Texture alpha) ---- DitherTemporalAA — Opacity Mask.

I fiddled with the alpha gradient on the texture and I think my current settings are from 0.4 to 1.0 and then I set the Random in DitherTemporalAA to 0.2. OpacityMaskClipValue is 0.05. BlendMode is Masked.

This seems to work, but there are some artifacts due to the dithering. Not too bad for the grass fading into the ground texture, but not so great when you see dithered grass on a hill against the sky, or grass in the sunshine dithered against a patch of dark shadowed grass.

I did this and it worked for exactly what I wanted, thanks for your help guys.

Excellent examples. If you wanted to start the transition earlier how would you go about that? e.g. fadeout starts earlier and lasts longer.

4 years later, the engine being broken AF, instead of “fading” it may be better to pull the foliage under the landscape with a distance based offset on the Z of world position.

1 Like

there’s a node called distancecullfade that can help with this.

1 Like