So here goes… my attempt at creating something with the wealth of knowledge I’ve acquired over the past two days regarding realistic landscape generation in World Machine, rendering in Unreal Engine with resources from Megascans.
While watching this video which creates a beauty shot of a Scottish highland landscape, complete with rocks and vegetation, I became inspired to do something to help me actually practice the skills on display in the tutorial but also combine this with my ideal workflow for generating heightmaps and masks from World Machine.
I purchased the Standard version of World Machine purely because it’s a great tool and I want to create higher resolution heightmaps than 512k. I do not own a subscription to Megascans but they do sell their themed “packs” for a reasonable one-off price. I intend to buy the ‘Wasteland’ pack very soon.
Megascans Assets
Thankfully, the nice people at Quixel gave me access to an academic pack, a selection of assets from some of the packs and the FREE assets at 4K… so I have the following landscape and natural assets to help me create my scene:
Meshes
Materials
Atlases
In addition to the above collection, the academic pack also included 19 concrete and plaster materials which will all be great for man-made scenes. I really am very grateful to Quixel for this opportunity to evaluate their products. Part of this experiment is to objectively analyse the tools, resources and workflows/approaches so I’ll be reporting on the suitability for Megascans assets in this context. As I mentioned in this post, I am feeling better about Megascans content but I think this will be the true test.
Objectives
When considering your challenge/task, it’s a good idea to have to hand the criteria/objectives that you set yourself. Criteria in this context can be aspects of your work you want to focus on or improve, new tools you want to explore, workflows and processes to experiment with or aspects influenced by external factors.
For both challenges in this experiment, I set out to explore and improve on the following 5 aspects of this subject (with more detail in this post):
- Higher terrain definition
- High fidelity terrain material and blending
- Better implementation of foliage
- Blend foliage and other objects onto the terrain more convincingly
- Make the scene look realistic using only dynamic lighting
I also want to add additional criteria just to be explicit regarding the output for the above:
6. Make each scene efficient enough to run as a game environment
7. Everything procedurally created
It’s important to state point 6. because the Unreal Engine is used quite frequently to generate beauty images and high fidelity interactive walkthroughs (usually for ArcViz). These outputs are small, contained examples where efficiency is sacrificed for aesthetic detail. Here you would expect high density meshes, 4 – 8k textures and complex material shaders.
This wouldn’t be appropriate for real-time games however so I am stating this as an objective because it requires significant consideration to how I create/use assets and how they are implemented in the world. It is also written down to remind me that what I create probably won’t look as good as the tutorial videos I have been inspired by. However, my intention is to make them look as close to the existing beauty shot examples whilst still maintaining an even, playable framerate.
I am not going to be too harsh with the restrictions but it’s still worth setting some idea goals. The playable framerate for these experiments will be anything more than 60fps at 1080p on a GTX1080. Plenty of power to play with there.
Point 7. I’ve added because when considering the scale of the environment I’m creating (4km²), it would be insane to have to paint all the masks and foliage by hand. I am producing this environment in a manner which respects the processes sustainable with regard to time management for asset production. Therefore I plan to place create the terrain geometry and the layer masks from texture maps without going near the landscape painting tools. I aim to try the same with foliage but this might require some intervention if there is little control over the procedural placement of the foliage (more on this later).
Let’s begin…
Day 1
Step 1: The terrain
I started in World Machine and created the following very basic terrain:
As I mentioned in my post regarding World Machine, this tool is a complex beast but to get something looking random yet realistic requires only a small amount of input. I have categorised the devices (remember, that’s what World Machine calls ‘nodes’) into 4 main functions identified and described below:
- Green – there is the terrain seed generator (Advanced Perlin). This just defines the base landscape based on a fractal noises. There is also a ‘Layout Generator’ device (image below this list) which is allows you to define impact features and their influence by drawing shapes and seeing how this section of terrain would tile with the rest of the ‘world’.
- Blue – these filters affect the terrain. ‘Terrace’ does what you might expect and applies a terracing (stepped) effect to the terrain. Then there’s the brown ‘Erosion’ filter which makes everything look realistic by simulating various types of natural weathering and wearing to the terrain.
- Orange – all these Macro’s do is extract one of the 3 outputs from the ‘Erosion’ (flow, wear and disposition) and combine them with the heightmap to create a map that shows the influence of each output. This generates a greyscale image. The purple selector ‘Slope’ is additional information I want to grab from World Machine which highlights the strength of a slope – this might be useful as an additional mask when deciding what material to place where.
- Red – These devices simply output the maps to image files (PNG for the bitmaps and RAW16 for the heightmap). Ignore the heightmap outside the red, that was put there so I could extract the heightmap as a PNG for this blog.
From World Machine I was left the following maps (in order: height, wear, flow, disposition and slope):
I am now done with World Machine as once your terrain is imported, there is little else you can do externally. That’s why exporting these maps is a good idea as you might be able to use them as masks when either sculpting terrain or creating the landscape material to apply to the terrain (Step 3).
Step 2: Creating the Landscape in Unreal Engine
This step is actually very straight forward providing you followed the guidelines regarding terrain sizes in Unreal:
The weird non-power-of-two numbers for setting your terrain heightmaps (i.e. 127, 253, 505, 1009, 2017, 4033 and 8129) will transfer and Unreal will set up the ‘Segment Size, ‘Sections per Component’ and ‘Number of Components’ from the heightmap (which is why you need to pay attention to the guide to see what resolution to set your heightmap in World Machine). Unreal will calculate the ‘Overall Resolution’ for you (which should be the same as your heightmap resolution).
This is the figure you will also use if you ever have to apply a texture (via a material) to your world on a 1:1 ratio, say for example when you want to use a texture map as a mask (as I will in the next step).
I used a resolution of 1009 x 1009 for everything. This gives me a medium-sized terrain and something I can populate with enough objects it’ll work well as a game environment. If you are using the free Basic version of World Machine, you will be restricted to a maximum size of 505 x 505 but this is still pretty large!
NOTE: while you are going through the terrain ‘import from file’ process (as opposed to creating a blank terrain and painting the heightmap manually – which you can do), you will be a shown a dark green wireframe approximation of the landscape. This is just to demonstrate scale and position. As soon as you hit import it will create the dense mesh version. I applied a basic white material to the landscape to best show up it’s form. I also used the Blank template when creating my Unreal project and deleted all the starter content. I just left the lights (but set them to ‘Movable’ – dynamic), atmospheric fog and sky sphere.
One final thing you should do is to create a Lightmass Importance Volume and make sure it encapsulates the entire landscape – even if you’re using dynamic lighting. Not 100% sure why but when you build your level without one, Unreal complains.
Time to create the landscape material!
Step 3: Creating the Landscape Material
Having watched a bunch of video tutorials on landscape materials in Unreal, I was eager to dive in and try a few things out. The first thing I needed to get my head around was the scale of materials to be applied to the landscape. I did a few experiments because I knew I was going to run into at least 1 issue…
Problem 1: Material Scale
I was expecting a problem and it arrived almost immediately. In this video, the author uses textures he created from Google Maps/Earth – which is a neat tick if you’re starting from scratch with everything or don’t have access to a resource library such as Megascans. This works fine to a degree, especially the macro (far) detail/view, but the micro (close) detail wasn’t that awesome. Plus I have the following surface materials I want to work with from Megascans (rock and grass):
This is where working with landscapes becomes complex because you want the micro detail of the material to show up underfoot but that’s not going to look great when a real-world 2m x 2m material is scaled across a landscape that’s approximately 1km x 1km. To cover the landscape, that material must tile 500 time in both directions, so 250,000 times across the landscape! You’re going to notice that… and indeed I did:
At ground level, everything looks lovely underfoot, although you can start to see the repetition of the tiling of the texture. It’s actually not a great material because there’s a very noticeable shallow ‘trench’ which runs along the centre of it (you can see this above). As a game environment, I could possibly live with this. I would cover it up with foliage to certain degree.
The real problem is evident when I raise the camera up to view the landscape as a whole:
Now we can really start see to the repetition of the material. As I said above, a very simple way to improve the result would be to “fix” the texture by removing the ‘trench’ that is clearly visible. But you might ask why are you bothered by this if it looks ok at ground level? If you’re playing a game that’s the only thing you’ll see right? Wrong. How about if I want a cinematic camera swoop into the player’s starting position as the game/level begins? How about if the character has access to vehicles which will cover the landscape faster and from a higher vantage point? This just won’t do.
One way to address this easily would be to find a trade off in scale/tiling where the landscape looks better from afar but sacrifices some fidelity up-close. That might look like this:
This looks acceptable from afar (if the ‘trenches’ were removed) but how does this look underfoot?
And there’s the problem… there is no mid-point that’s acceptable. You have to address this issue by making a material that looks great close-up (micro) and from a fair distance (macro). The solution? Distance Blending…
Solution 1: Material Scale: Distance Blending
Now I’m not sure if there is an official correct terminology to use here, but it sounds about right. There are many types of blending you can implement in the Unreal Engine. Blending is used frequently in landscape materials but it mostly refers to the blending between different materials that describe a different surface. For example, I only have a grass material applied to my entire terrain. It looks poor but I need to address the scale issue before adding any more complexity to the material shader. I will be adding at least 1 more materials int he form of rock. Eventually I will blend the grass into the rock. This issue refers solely to the process of making the material look good at different distances.
After some experimenting and exploring existing examples (the grass material that comes with the Unreal Engine Starter Pack is where I found most of my answers), I came up with this:
Looks good close, what about far away:
Not bad for a material with only 1 grass texture! How is this working? Essentially, I have 3 instances of the same grass texture (which I made look better in Photoshop be removing the obvious ‘trenches’). When the camera is close to the terrain, the normal texture at 1:1 texture scaling can be seen. However, it is also being blended with another instance of the same grass texture at the same 1:1 scaling ratio but 20% darker. The blending happens via a mask which is just a random noise texture (greyscale) scaled very low. This breaks up the tiling at close range.
In the distance, another instance again of the same grass texture is being blended in to the material BUT with a scale ratio 10x larger. This has yet another mask powering when it is faded in. The difference here is that this blend is being masked out until the material is far away from the camera. A special gradient mask based on the ‘PixelDepth’ of the scene means that this texture will only start to be displayed when the pixels are 2000 Unreal units away from the camera. Very clever and although the material graph looks complex:
It’s actually doing something quite simple. Actually, I could probably get rid of about half the nodes again but it’s easier to tweak things with them in for now.
I am treating the normal map much more simply. The 1:1 normal map texture is being processed until the camera is 2000 units away (driven by the same same distance mask as the colour map). After this point, the normal map is flattered by blending in a solid blue colour. You wouldn’t see the normal detail that far away anyway so it’s pointless trying to draw it.
I have set roughness and specular to 0. There is a roughness texture map for the grass material but it’s very subtle and unnecessarily complicated for a landscape material that is going to get complex with its distance and material blending. A value of 0 looks fine for grass. I might need to look at this when I tackle the rock material however. Especially close up.
You may also have noticed this is a Material Function. These are different from regular Materials in Unreal because you can instance them into a master material. Think of this as a Grass material in itself (complete with all the distance blending). Now, when I want to use this in my Landscape Master Material, I simply put a call to this function and it appears a single node. It’s a material inside a material and it’s extra useful to help keep things tidy. I’m going to have at least 1 other material that will work this way (rocks). Imagine if I had to wire all the different nodes for this inside the master material? It would be a mess.
Problem 2: Material Blending
Remember, one of my objectives is to ensure the materials look good enough for use as a game environment so it was essential I got that previous problem sorted. A lot of videos involving Megascans assets focus on beauty shots that are human scale, even this amazing example (which has inspired me). So now the grass looks great at virtually all distances it’s time to consider adding another material: Rocks.
I have the material (see top of this section). I have the mask which will power the blend between rock and grass (the ‘slope’ map generated in World Machine. All I need to do is repeat the above with the rock material. Let’s see how that goes:
Well, it doesn’t look too bad. But it’s definitely going to need a different approach to the grass. Look at the “straight line” right in the centre of the camera of repetitious detail. I’m going to need to address that!
After some tweaking of values and masks, I finally came up with this from close:
It features rock underfoot that is a little too stretched for my liking (about 1:3 ratio) but it’s a 4k texture so it holds up well and I figure the rock will mostly be in the background or hidden/blended in with the grass layer so that’s a kind of compromise. Games environments are always going to involve some compromise I guess. This is what it looks like from far away:
Not too repetitive at all. And this is still only the same texture map, distance blended and masked in the same way the grass was. In some ways, the grass was more important to get right, but I am happy with how this turned out.
Solution 2: Material Blending: Landscape Layer Blends
It’s now time to blend the 2 materials together to create terrain that is realistically covered, well, at least a little more interesting to look at:
I had to lighten and desaturate the rock texture a little as it looked too brown. I also tweaked the lighting and added some Exponential Height Fog which really helped make the scene look convincing. Finally, I rescaled the terrain slightly as it was too large. I might rescale it again before I tackle the next stage of foliage painting.
To say there is only two materials, 2 lights, a sky dome and 2 types of fog (Atmospheric and Exponential Height), I am quite happy with how it the scene is looking so far.
Day 2
Expansion 1: Revisit grass material and add an additional grass texture
I was happy with the product of yesterday’s exploration, but one way to improve the result even further is to blend in another grass texture map. This in itself would be straightforward because there is already a place where I could swap a texture map of the original instance with a different map (near/Micro blend), however, because this would happen close to the camera, I would also have to ensure I had an additional normal map for this new grass texture and blend them using the same mask. Also, the color map would have to be compatible in terms of scale, hue, brightness and saturation.
Although it looks good underfoot, and the blends with a darker contrast version of the same texture work and there’s a strong possibility that when I add foliage this will be less of an issue, but regardless, there needs to be more variety before progressing.
Here is the result of adding an additional texture to the mix plus some additional tweaks to the sizes of the masks (micro) and distance for mask to show (marco):
That looks far better and even though there’s an additional grass texture (part of start content pack that ships with Unreal), the material shader is actually less intensive because I am not multiplying the same texture against itself (to achieve patches of darkness on the surface). Also, the variety in texture looks more realistic because as good as the Megascans grass texture was, it was too green. The texture from Unreal starter content introduces some washed-out patches of dead grass to make the material look more convincing. I had to adjust some of the new grass texture sample’s attributes in the editor (non-destructively), but that’s about it! I also didn’t bother blending in this new texture’s normal map because it wasn’t required to look good and by not doing this, I have saved the shader quite a few extra instructions.
Expansion 2: Break up texture blends even more with a cloud layer
I decided to tone my scene on an overcast day as most of these epic scene environments are set on beautiful clear days so in the interest of being slightly original, and slightly crafty, I adjusted the Sky Sphere to make it look overcast and blended a layer on top of the current rock/grass blend that is simple a black colour map with a noise mask scaled quite high and a texture panner applied so the cloud layer actually moves:
From directly above:
This looks great when you’re standing in the scene and the clouds are moving overhead whilst fake casting shadows on the ground. It’s added quite a bit to the shader complexity but with nor drop in framerate, I’m going to stick with it for now as it breaks up the grass and rock layers even further. If the framerate starts dropping further down the line, this is one feature I am willing to sacrifice.
I am now perfectly happy with the landscape. It looks good and is as efficient as it’s going to get (with the exception of the cloud layer). I will profile the level later when I start to add foliage. Speaking of which…
Step 4: Foliage
“This is the fun part where you add static meshes to the terrain” – was my original opening statement to this section, but this comes with a caveat… it IS fun when you know what you’re doing and when you understand how to create a foliage shader that looks correct. Until you know these things (and there’s a lot to learn, believe me), then dealing with foliage can be the opposite of fun.
For example, there are 3 ways to actually apply foliage to your environments, each has it’s own workflows, requirements and best use-case scenarios. For the sake of my own sanity, I am summarising them here:
- Grass Layer – the simplest to get going – just create a sample of a layer from your landscape material, create a new ‘LandscapeGrassType’, add at least 1 static mesh of some suitable grass-type geometry (more for variation), set a few parameters and save the material. Whichever layer you sampled will now be covered in grass. This approach is suitable for basic grasses and low lying foliage. It is quite efficient because you have control over the cull-distance (when the renderer stops drawing instances in the distance). Combined with LOD and a scaling shader setup, you can fill a playable area with this type of foliage easily.
- Foliage Painting – the approach with the most control – if you want precise control of the placement of foliage, multiple foliage variety combined with the flexibility to specify individual properties for each variety AND the ability to specify cull-distances and other performance improving features, then this is the option. Good for both low-lying and larger foliage varieties. The only downside is that you have to paint them onto the terrain yourself. Not such an issue on a small environment, but time consuming on anything larger than a few square metres. Also, the placement is randomised within the brush stroke (all configurable), but placement of low-lying and medium dense foliage never really looks natural. Useful for finishing touches on foliage of all sizes.
- Procedural Foliage Volume – the easiest and most powerful approach of them all, but it’s not suitable for grass and low-lying foliage – if you want natural looking results for the placement and distribution of your large foliage then this is simply incredible. You can designate an area (or encapsulate your entire world) with this volume, add varieties of foliage (in much the same way as the other methods), learn what the major settings do and hit ‘ Re(simulate)’ and the results will knock your socks off.
So which one should you go for? Well, there’s a reason there’s 3 approaches… they all do different things. The best approach is to use all 3 in-conjunction with each other.
My journey – Research
I had to watch a LOT of YouTube in order to get my head around foliage – the creation of the geometry, the construction of the shader, the performance implications and finally the application to the environment all took a great deal of time to process and for me to devise a plan.
First was this video by Eoin O’Broin from Quixel which I haven using as my main aspiration throughout this part of the challenge. The core things I picked up from this video include: shaders for Megascans assets (object, surface and foliage) – key considerations are the specular and normal map offsets, ensuring greyscale masks are set accordingly when a texture is imported, the treatment of foliage layers, exponential height fog and the ‘Dither Temporal AA’ node in a material that can blend itself into that of an adjective material. Magic.
These videos from Epic’s YouTube channel:
- https://www.youtube.com/watch?v=3ispyNxpRyg
- https://www.youtube.com/watch?v=PDlGKZ1c3Zc
- https://www.youtube.com/watch?v=gMKjIZMPJ0Q
They all really helped getting my head around the implementation of foliage and its interactions with the landscape workflow. While on the subject of official support, this particular section of the online instructional manual for Unreal Engine covered creating open worlds and features excellent step-by-step instructions .
More from Quixel with this video about creating a scene with foliage and landscape using Megascans assets was really inspiring but in it the artist used baked lighting for a very small scale scene so there was nothing that useful despite being an excellent breakdown of a scene.
Yet more from Quixel but this time the end result was very useful. In this video, the artist demonstrates how to take an asset from the Megascans library, create a suitable mesh for it, and create a shader that gives the illusion of a densely populated wheat field sawing in the breeze. A little overkill for real-time but certain some interesting concepts.
Finally, I have to give a shout out to this video because I learned a great deal about how to create a complex and believable grass asset, a little overkill for a grass foliage layer maybe but the process was interesting and he did perfectly demonstrate the notion of vertex painting a mesh to denote how much wind would affect it – and then implement wind to the shader.
My journey – First attempts
My first attempt was to create a grass asset from some of the grass atlases (listed at the top of this post). It did not go well. The grass looked terrible, which was mostly the crappy shader I created and the fact I screwed the normals up on the mesh so the normal map was pointing in different directions and looked poor. The mesh and the shader combined did not look at all natural on the landscape.
I was a little demoralised but actually I learned a lot from my failure which resulted in the following advice I would give to anyone creating their first foliage asset:
- If your first (or subsequent) foliage asset doesn’t look great on it’s own on a big empty landscape, don’t bin it, create/add a few more and see how it looks blended in with them. Depending on the foliage type, it might look odd or unnatural on its own, but in a scene with others nearby or blended with it, it might not be that bad.
- If the asset doesn’t look like it “belongs” in the scene/on the landscape, especially with dynamic lighting, play about with the shader, especially the transparency/albedo map. They can massively impact on how well the shader looks in the environment. If you see bright ‘edges’ around your mesh, especially when far away, I found that darkening the background of the albedo map really helps. The guys in the Quixel videos have worked with the textures as they come and it seems to look good in their shaders (even with dynamic lighting) so I have no idea why I’ve had to do this when using Megascan texture atlases.
- Download the ‘Open World Demo Collection’ from the Unreal Engine asset store. It’s free and features loads of different types of asset for you to reverse engineer to get your head around the shaders and foliage implementation.
- The type of ground that your foliage sits on IS IMPORTANT. I placed my fern in the grass and it looked rubbish. The green’s didn’t match and the small clusters looked wrong and unnatural. Ferns wouldn’t grow on grass directly, their base would be made up of dead grass, dead ferns and straw-looking material. Or, in shady areas, near rocks with dead leaves all around.
- You can create grass layers combined with masks so you do have some control over where the grass foliage appears on the layer. I edited a mask from World Machine in Photoshop with levels. For multiple masks, use an RGBA image for up to 4 mask channels.
Finally, I created a fern mesh (see images below) and the shader seemed to look natural in the scene. Although, even with this relative success it still looked weird on it’s own (because I was still learning the above).
The ferns were placed using a Procedural Foliage Volume with relatively sparse distribution settings. Even so, there’s still 3.7k instances of the fern mesh in this scene! It’s amazing how quickly you’ll rack up the polygon count and shader complexity. The later is bad because foliage assets usually have a masked material meaning there could be several thousand layers to sample to decide the correct draw order and transparency value.
The heather isn’t mine. It’s borrowed from the Open World Demo collection. I will replace it with my version as soon as I understand the shader. In the scene below it is placed as a grass layer with medium density. Despite the patchy coverage, there’s over a 1,000,000 instances on display and the computer was still achieving 60fps+. This is pretty incredible considering there’s another 1,000,000 instances running in the editor at the same time. Standalone, this scene would still run capped at 120fps on my GTX1080.
I am quite happy with the end scene for the day and feel I have learned so much good stuff. I aim to produce a load of additional foliage types using Megascans assets and creating my own master foliage material for grass. I might even attempt a tree or two. Certainly some bushes, rocks and other foliage objects will be added when I purchase my Megascans packs tomorrow.