Wow, that's great. Have to try this out!
Wow beautiful environment. Very thorough and detailed. But I think there are a few images that are not showing up (error?). Is that just me? Interested in seeing those other pictures...
Jack. First of all, I want to apologize for offending you. We published this just to show how the tech could be used. We don't actually care about the message. But you do bring up a viable point, that for some people - this might be an issue, so I take this post down.
3d artist Ilari Lampinen talked about the way he managed to build a whole procedural arctic biome with some clever programming.
My name is Ilari Lampinen, a student sharpening his focus on environment art from Helsinki, Finland. I currently study 3D graphics in Metropolia University of Applied Sciences. Last year we put out a virtual reality murder mystery game where I worked on some of the major props. I’m very excited to talk about the ins and outs of my latest project.
I wanted to try my hand at making a large photoreal environment with the added twist of tessellating most of the geometry, even the trees. I’ve seen amazing work from game artist and archviz people that ran in real time inside Unreal Engine so naturally I had to pick it up and start tinkering with it. I must give special thanks to Koola, his work is fantastic and the winter scene he kindly shared with the world was both a great source of knowledge and inspiration. This scene is still a work in progress, the pictures in this article are from various stages of development.
A lot of research has gone into getting myself up to speed on industry standard practices for this kind of scene. I wanted to work efficiently so I familiarized myself with some powerful procedural tools like World Machine. In the process I discovered working prodecurally is also lots of fun! I get a kick every time I just turn some knobs and start exploring a new scene. A sense of wonder and excitement persists even now as I’ve looked at the same project for dozens of hours.
With a scene of this scope and complexity I had to think of “lazy” approaches to creating everything. I drew inspiration from Epic’s A Boy and His Kite demo so the landscape makes heavy use of all kinds of texture maps World Machine can output that serve as masks when compositing the final landscape in Unreal. I ask myself where would snow naturally fall and deposit? At what angle should cliff faces generally be bare? Do I need noise to break up any obvious tiling? The rock materials themselves in Unreal are also slope masked to blend with snow accordingly. The interplay of these two approaches (World Machine masks and ”smart” Unreal materials) give pretty good results out-of-the-box. Landscape materials are a complex subject and I learn more as I keep reading about it, in the future I’m planning to retool the material to get heightmap based blending between layers to work properly.
The materials in this project were generated procedurally in Substance Designer. Creating different types of rocks is quick since the primary and secondary forms are controlled with their own tile sampler nodes. The snow variations are driven by more complex node networks.
The spruces were modeled entirely in Maya. In addition to photo reference I was lucky to find Norway spruces (picea abies) in a nearby park to study.
The tree models run the whole gamut from young to old. Variety is important as a forest is a dynamic environment where things are constantly growing and dying, here are key elements I found were important:
- Give each of your trees a distinct look, make some spry and fluffy while others look tired with their branches hanging down, snow is heavy so remember to give the trunk a little bend.
- Strive to have variation on every level of the forest. Different tree tops to break the ”skyline” of the trees, some older trees should have shed most of their lower branches while others still cling onto them, natural trees can look pretty ragged so to avoid a picturesque look prune away excess branches and break symmetry whenever possible.
- Don’t scale your trees too much, this applies to individual branches as well. If your tree needs a wider base instead of duplicating and scaling nearby branches model a new branch from scratch. Remember that scaling done to branches is compounded with whatever random scaling you do to the trees in-engine.
- Snow may not cover the trees uniformly, look at reference and decide if snow coverage should be heavier on the top or bottom, randomise and mix it up a little.
- A small thing that helps spruces look grounded on sloped terrain is to arc the lowest branches beneath ground level.
I started by building a master branch in Maya with Paint Effects, then bringing it over to Zbrush and adding needles with fibermesh. I broke up the branch so I had 2 main branches (the ones with snow covering the middle) and some smaller ones. The snow was done by dynameshing the branches in Zbrush, deleting the bottom half of the dynameshed model, applying surface noise as a mask and deleting unneeded polys. Thickness was added with Zmodeler, after that the snow was dynameshed again and I used the Inflate brush to enlarge or hide clumps to get a more natural looking snow distribution.
There are 3 branch texture variations: dead, light snow and heavy snow.
In Maya I built branches of different types. Most branches were blocked out with the 2 major branch cards I mentioned earlier with smaller ones added for flavor. The small thin frond cards were used to build the tree tops which have very specific forms. There are also some more crooked branches that are bare.
I laid the branches out vertically and started thinking of the silhouette of the tree while maintaining a constant scale. This “slice” of branches was then duplicated radially around the trunk mesh and given some random rotations and transforms on the y-axis. Final touches were made by grabbing the tip vertex of some branches with soft select and moving/rotating them around.
Things progressed pretty quickly after the first tree was done as I could just duplicate the meshes, randomly transform/rotate them again and just check that a branch hadn’t flipped upside down.
I wanted the trees to have enough snow variation to be distinguishable from each other at a distance, so I plugged in a per-instance generated random number that modified the overall amount of snow on any given tree, virtually every tree in the scene is unique in this respect.
For now I’ve been placing the trees with the standard foliage painting tools but I’m looking forward to trying Unreal Engine’s procedural foliage placement system.
The snow uses a subsurface scattering shader, it’s basically just a solid white color with normal and roughness maps for surface detail and a nice glint in the sunlight. I made a few snow variations and wrapped them inside material functions so any changes I make propagate automatically to every material that uses them, like the tree branches. The snow is projected triplanarry with world aligned texture nodes to allow the freedom to sculpt the landscape at any time.
Apparently tessellation used in conjunction with LODs on foliage objects has caused major performance problems for some users, but I went in knowing from the start that rendering a realtime forest with tessellated foliage was a tall order. Initially the trees performed well enough, but I grew hungrier and the scene grew bigger until optimization couldn’t be ignored.
My solution was to aggressively cut down on the amount of tessellated geometry on-screen at any given time. The trees were heavily pruned of polygons. The material I created for the trees decreases the tessellation iterations dynamically as distance from the camera grows, the performance was still quite awful until I removed tessellation altogether from LOD1 and up. Visually no different but a modest improvement in framerate, there is evidently a large overhead cost you must pay when using a tessellated material.
These measures helped but the scene still chugs in many densely forested places. Flythroughs may have to wait until I get better hardware.
The material uses vertex colors to determine what branches get a light or heavy coat of snow, the dead branches originally had their own material but were integrated into the main one to make painting possible and save on drawcalls. Ambient occlusion was baked with Turtle in Maya into the vertex colors of the trees to serve as a base for painting since some of the inner areas are really hard to reach with a brush, the rest of the painting was done inside UE. The key component of this material is the world aligned blend node that determines whether the normals of a face are pointing up or down in the world and biases it toward light or heavy snow accordingly.
The tessellation factor and displacement amount are controlled by the camera’s distance to the object. Distance to the camera is sampled per-pixel instead of taking the transform coordinates from each tree because of a quirk in Unreal’s foliage system that hides this information (it must be related to the way Unreal batches foliage meshes together for optimization).
Dynamic tessellation on this scale is impractical in my view. To run a heavy scene like this in realtime all the trees would have to be pretessellated within the modeling software and unnecessary polygons culled to reduce overdraw. This adds some hoops in the workflow one must power through, but it is a promising concept. The takeaway for me is that it’s worth thinking about how to economically create high resolution foliage models for use in games since the visual difference is very noticeable, especially in this project where the subsurface snow material can really shine when it has actual geometry to work with.
This project has been a great personal learning experience so far and if others want to look under the hood I’m happy to share my work. I’ll do my best to get this thing wrapped up well before the holiday season.