In the last year, I learned a lot about landscape creation and besides Unreal, I used a lot of different tools to get the result I was looking for. My journey began with World Machine and I started to love and hate it. The results were amazing, but the usability was and still is a pain. I decided to look for something different and ended up using Houdini with the Gaea Bridge. These tools are fundamental for my landscape creation workflow, but when the work is done there, I end up in Unreal with a grey landscape without much character to it.
You’ll find some tutorials out there about landscape materials, but a lot of them are incomplete or just a fraction of what you need for your landscape. Besides that, creating natural landscapes is kind of a niche in CG and that makes it even harder to find proper resources. So after reading dozens of forum threads and watching tutorials, I decided it was about time to give something back to the community. Something you can learn from or just use it as your own.
I made an advanced and modular landscape material with a pretty nice performance and some nifty material functions in it. Rodrigo Villani helped me along the way.
In order not to waste your time, below is a little breakdown of the nodes and a description of what they do. I hope you can learn something from it!
You can also download the material here to study it on your own.
When working with landscapes, you have multiple kinds of surfaces. In my case which was a Mongolian scene, I used soil, grass, gravel, cliff, and snow layers.
Managing these can be a real waste of time when duplicating texture samples over and over again. For exactly this problem, I created this Material Layer function. Out of the box, you just have to plug in your textures, connect them with the rest of your node system and it works. You probably should rename the basic parameters to get access to them in your material instance, but besides that, it’s an out-of-the-box solution.
One thing to mention is that I multiply by default the AO channel on top of the BaseColor. Technically, this is wrong and breaks the PBR workflow, but it really helps to get better definition in your material, because most of the time a regular material can’t handle self-shadowing in small crevices. So I added this little option, which you can always turn off using a simple boolean.
Also, for saving some texture samples, I am using the AO multiplied by 0.5 for getting some kind of a specular approximation.
Sometimes, your material does not look right and you do not want to change these parameters in Substance, Mixer or anywhere else. And it’s easier and faster to do this in the material. For this case, I added a pretty big Adjustment Layer function. Most of it is pretty self-explanatory, so just play a bit around with it, open it if you like and look through it. The most important part of this function is the Heightmap functions. With these parameters, you can control the contrast of your heightmap for - and this is important - the blending between your materials. Using a normalized heightmap is often not enough to get a nice transition, especially when you are dealing with sharp rocks, so you need to raise up the contrast.
The result is still not perfect, but I am working on a better solution for this, not using the internal LayerBlend node.
The problem with big and open landscapes is that you quickly see repetitions on your surface, caused by the tiling textures. To overcome this, I created a Distance Overlay function to lerp an overlay over your albedo and normal channels. This one is pretty expensive because it is using a high res texture - in my case, an 8k one - which I made with the data maps from Gaea, processed in Substance Designer. If you are interested in creating this texture, let me know and I’ll write a tutorial for it.
You can control the overall intensity of the basecolor and the normal channel. More importantly, there's an option for excluding material layers from the overlay. In my case, I excluded the cliff surface to preserve the rock structure projected via a special stochastic tri-planar function made by Rodrigo Villani. More about it later.
I made Color Variation function for the same reason as Distance Overlay. At a far distance, the surface tiles look repetitive and that’s not how nature works. When you take a look at a grass surface, you’ll see a lot of different colors like dead grass patches, fresh green grass or something in between. To mimic this behavior, I created this node.
Basically, it's just a color multiply with some other parameters like intensity, contrast, etc.
The problem with large landscapes is that at a certain distance, they catch too many reflections and it does not look believable at all. Unreal is restricted in how much it can show on the screen so, for example, the grass gets culled at a distance. In the real world, the grass is still there and scatters the light in every direction. It can be compared to a really rough surface which reflects the rays of light in a very chaotic way. The easiest way to solve this problem is to use a mask based on the distance to manipulate the roughness and specular values and to mimic this behavior.
Do you know Brushify or any other auto-landscape material? That’s basically the same. You can utilize it for every task - in my case, I use it for the cliff detection, avoid resolution restrictions… and it’s just easier to add slopes. So yeah. Use it as you like.
This feature is the one I am extremely proud of and the best thing is that I didn’t do anything for it!
I am watching a lot of GDC talks to stay up to date and learn new things in areas I am not even related to. One day, I watched a talk about the rendering in FarCry 4 and I was blown away. Besides the procedural approach of creating this beautiful world and all the super technical stuff, I was also very interested in how they are dealing with cliff faces. They developed a super cheap method of creating a tri-planar function using just a single texture sample. They also released a paper with even more information - check it here if you're interested. Long story short, I am more of an artist, so I needed some help to get this function into Unreal - and here's when Rodrigo Villani took the stage. I understand the basic logic of this function but I basically have no idea how he accomplished this node. You can just use it or keep an eye on his YouTube channel as he planned to upload a video about this tri-planar projection node in the future.
There are a few more material functions but some of them are just too basic to cover them here. Just download the sample scene and study the material or just grab and migrate it to your project. I hope you’ll find this material useful!
Before I end this article, I want to thank several people for their help. Besides Rodrigo Villani, I want to say thanks to Aydin Yanik who helped me with his VDB Cloud Pack. For me, finding proper clouds is pretty hard but his pack is great. I simply took a few clouds and rendered them.
I'd also like to mention Sooii. Last year, I started my career as a professional 3D artist there and I got a lot of support from my co-workers and especially my boss. Plus, I get a lot of freedom to develop my skills there. So I want to say thank you!