Home Technical Talk

Smooth foliage like in Breath of the Wild / Europa by Helder Pinto - Mini tutorial

grand marshal polycounter
Offline / Send Message
Obscura grand marshal polycounter
Hey people. Recently I started working on a small stylized meadow scene, inspired by the beautiful work of Helder Pinto, called Europa. It has a very painterly look, similar to BotW. I was able to achieve similar style / looking foliage in a fairly easy way and I thought I would share my experiences with you guys, regarding stylized foliage shading.

For teasing purposes, this is how my results looks currently:


As some of you may already know, edited vertex normals are often used on foliage meshes, to smooth the shading of the cards. If this isn't done, the rotation of the cards will make ugly, sudden changes in the shading. This is one of the things that needs to be fixed, but there is more.

Here is a tree mesh without edited vertex normals, to demonstrate the issue:



Not too bad, but we can clearly see those shading changes everywhere. Now here is a tree with edited vertex normals:



Despite the world normal pass looking smooth, we can still see some darker leaves. This is because the leaf  planes has darker shading on the back face of them. This is a natural behavior, but it looks like we don't want it. Luckily, we can make both sides of the planes have the same lighting using a simple trick in the material. In Unreal, you can do this, and hook it up to the normal input:

We simply flip the normals on the back faces.

And the result will look like this:

You can play with the shadow bias and resolution settings to adjust the falloff of the shadows.

I did the same tricks with the grass in this scene:

Before:

After:


Grass world normals after the tricks applied:


Now these tricks might not be applicable in all cases, and may not look as good with realistic art style, but it definitely works very nicely with heavily stylized assets, for almost zero rendering cost and a little bit of work with the normals(which is actually automatic, because its done with a script.).

I hope that this breakdown will be useful for some people. Have a nice day!


Replies

  • Mark Dygert
    Great write up, awesome tutorial thanks for posting!

    One other thing that helps too is baking in some AO into the vertex colors and pump that into the Ambient Occlusion in unreal.



    This really helps the model self shadow and it can be almost impossible to do AO the standard route with texture map when so many separate leaf planes, laying them out in their own unique UV space to make a lightmap would be very impractical.


    Another trick is to use DFAO (Distance Field Ambient Occlusion) this works by making a shadow volume out of voxels, for each model. It can make foliage and just about everything, look really good, by shadowing the underside of a canopy and the inner parts of the tree.

    You do have to be careful. It can be costly in game and it can take a while it calculates the distance fields, when loading a level for the first time or adjusting distance field settings. Tuning the DF on each model can be a bitch sometimes too, but it does looks pretty awesome...

    One key thing to note about DFAO, is that the shadow volume is static and if you use anything like pixel depth offset to fake a bit of wind the distance field for that object won't move with it so you usually get some flickering. That's why I generally stick to the vertcolor AO bake method, it looks almost as good as DFAO but has less overhead and less glitches.
  • bitinn
    Offline / Send Message
    bitinn polycounter lvl 6
    Another simple trick is to use Pixel Depth to lerp between 2 subtly different leaf colors, which also can give the foliage a bit more volume.
  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    I actually have a parameter in the material setup to darken the leaves towards the center of the tree, but It doesn't look the way I wanted, so I only added a slight darkening. There is also actually a way to fake this ao effect cheaper than dfao. You can take the distance to the center of the x and y component of the bounding box of the mesh, after subtracting 0,5 from the local position. This works if you have the trunk of the tree roughly on the middle of the mesh. Then you can lerp between a brighter and a darker color based on this distance. Simple ssao also works nicely. I have some on these renders.
  • Berserker44
    Offline / Send Message
    Berserker44 polycounter lvl 5
    Great job! these look awesome. What was your workflow when editing the normals in 3ds max? Would love to try the same with my trees. 
  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    @Berserker44 - I used the normal thief script to transfer the normal directions of an elongated hemisphere to the foliage. The grass normals were hand edited.
  • melviso
    Offline / Send Message
    melviso polycounter lvl 10
    Nice work, mate. Looking nice. I think Non photorealistic shading/look should be tried out more in games. 
  • thomasp
    Offline / Send Message
    thomasp hero character
    Great trick with the TwoSidedSign! That solves a longstanding problem for me.

  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    I'm glad to hear that @thomasp :)
  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    Applying this technique to realistic moss looks nice too.


  • Maximum-Dev
    Obscura said:
    You can take the distance to the center of the x and y component of the bounding box of the mesh, after subtracting 0,5 from the local position.
    Hi Obscura,

    Can you please share your setup for that?
  • radiancef0rge
    Offline / Send Message
    radiancef0rge ngon master
    Obscura said:
    Applying this technique to realistic moss looks nice too.
    are those moss fibers cards?
  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    Hello guys. Its the same setup as the grass in the stylized example. I had some small slightly angled planes for the moss, and I projected  The vertex normals of the underlaying geo to their vertex normal so in the shading you don't see that they are actually perpendicular cards. This at least doubles the vertex count in this particular case(the many small cards), but you can always do a lod without the moss cards. The texture atlas was like this, but not this particular one. I can't find the actual one right now.
    https://quixel.com/assets/shrkeiwi2

    Example image from wiki:

    The only difference is that my ones were only cards instead of these axis aligned crossed planes.


  • Yerus
    Offline / Send Message
    Yerus polycounter lvl 4
    Vertex tweaking is key when talking about NPRS. It's important to have the proper tools.
    Blender have a built-in normal tranfer for it's own, and I've seen a result pretty similar to that one. 
    Also, take a look at this vertex control: https://www.youtube.com/watch?v=6BdzaK2z43s
  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    Obscura said:
    You can take the distance to the center of the x and y component of the bounding box of the mesh, after subtracting 0,5 from the local position.
    Hi Obscura,

    Can you please share your setup for that?
    @Maximum-Dev - This is how to do that.  Just a quick mockup, but I think its straight forward. I would call this a distance to point function. You can move the point by changing the value of the subtract to a vector parameter. You could also stretch the point by either dividing or multiplying the output of the subtract, before hooking it up to the distance node. Changing the length and falloff of the gradient can be done in multiple ways...You could also have more points than one by rolling the thing into a function and placing it multiple times. I'm also thinking that something like this would be doable for automatic spherical normals, by generating world space normals instead of gradients. But I haven't tried that.


    Example usage:


  • Maximum-Dev
    Obscura, Thanks for sharing. The issue is when foliage is distributed procedurally it picks up the entire volume bounds instead of each meshes' inside the volume. Below you can see the dark spot is in the center of the large volume. Works fine when placed as single static mesh though.





  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter


    @Maximum-Dev - In case of instanced static meshes, you could do it like this. Unfortunately the object radius has to be manually set. I didn't find a way to stabilize it. 
  • Maximum-Dev
    Obscura, One remaining issue is with scale variation the dot can't be centered on all instances anymore. But that has very good potential and already a good start for me to play around and improve the foliage lighting with this. Many thanks

  • Maximum-Dev
    Obscura, Ended up selecting some verts in the middle of the tree and doing a green vert paint. Inverting it in material and plugging to AO slot. Looks fine now regardless of scale variation.


  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    Can't try it currently, but I think if you would multiply the constant object radius parameter from my example, by an object scale node, it should work with scale variation too. Will check it out later.
  • warvlax
    Offline / Send Message
    warvlax polycounter lvl 2
    Hey obscura ! thanks for your advices but i struggle to get the result i wish and i thought that maybe you can help me ? 

    The tree on the right is using your tech and the one on the left as just cast shadows disabled how can i reduce / remove all the small inner shadows when cast shadows is on ? 

    i've tried playing with bias but only putting it to something between 5 and 7 would make them vanish which is way to high for other objects. 

    Changing shadow resolution doesn't work also i'm using dynamic lighting !

    Thanks in advance !
  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    Hi @warvlax . Try adjusting the shadow bias setting of the light source.
  • MisterSande
    Offline / Send Message
    MisterSande polycounter lvl 8
    warvlax said:
    Hey obscura ! thanks for your advices but i struggle to get the result i wish and i thought that maybe you can help me ? 

    The tree on the right is using your tech and the one on the left as just cast shadows disabled how can i reduce / remove all the small inner shadows when cast shadows is on ? 

    i've tried playing with bias but only putting it to something between 5 and 7 would make them vanish which is way to high for other objects. 

    Changing shadow resolution doesn't work also i'm using dynamic lighting !

    Thanks in advance !

    HI there, did you find a solution ? im facing a similar problem with my grass.

  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    Make the tip brighter so its visible even from this view. Make it having a gradient basically.
    Edit - I see it has some... Maybe try changing the falloff of it.
  • MisterSande
    Offline / Send Message
    MisterSande polycounter lvl 8
    @Obscura like this ? , I do still wonder if its normal to achieve these darker patches (taller grass) and how to get rid of them.


  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    Disable shadow casting on the grass. If you haven't disabled it already.
  • Optimo
    Are your leafcards camera-facing? do you know if it's possible to have one model that has multiple billboard cards camera-face? rather than having to import separate objects into UE therefor having more drawcalls? currently my entire geometry camera faces at one central axis rather than the individual polygons axis'
  • Obscura
    Offline / Send Message
    Obscura grand marshal polycounter
    Optimo said:
    Are your leafcards camera-facing? do you know if it's possible to have one model that has multiple billboard cards camera-face? rather than having to import separate objects into UE therefor having more drawcalls? currently my entire geometry camera faces at one central axis rather than the individual polygons axis'
    You could use a particle for that. It would be way more efficient. Or a shader that turns them towards the camera. Its possible even with multiple planes treated as one mesh. There are a few tutorials for that on the internet. But I'm not sure why would anyone want camerafacing planes in 2020 especially for expensive. They look terrible.
  • MisterSande
    Offline / Send Message
    MisterSande polycounter lvl 8
    they are def. not camera facing (no need for optimizing the grass atm). @Obscura thank you ill look into disabling shadow casting on the grass!
  • Optimo
    Obscura said:
    Optimo said:
    Are your leafcards camera-facing? do you know if it's possible to have one model that has multiple billboard cards camera-face? rather than having to import separate objects into UE therefor having more drawcalls? currently my entire geometry camera faces at one central axis rather than the individual polygons axis'
    You could use a particle for that. It would be way more efficient. Or a shader that turns them towards the camera. Its possible even with multiple planes treated as one mesh. There are a few tutorials for that on the internet. But I'm not sure why would anyone want camerafacing planes in 2020 especially for expensive. They look terrible.
    reducing draw calls for running an android project, having static plane with billboard mesh on instead of emitters. i believe the setup im using is using a drawcall per emitter, they dont really have to move so replaced with planes, combined as one mesh so its loaded in one drawcall instead of 15 is the idea
  • Vegel_Grady
    Offline / Send Message
    Vegel_Grady polycounter lvl 4
    Thank you so much for sharing this!! :smiley:  
Sign In or Register to comment.