Livio Ambrosini shared an enormous breakdown of the Before The Storm project, explained the working process behind the terrain, and thoroughly explained how to create foilage using SpeedTree, 3ds Max, and Megascans.
Introduction
Hello there, I'm Livio and I'm an Environment/Lighting Artist currently working at Playground Games on Forza Horizon 5. I studied Game Design at the ETPA in France and graduated in 2017. After a bit of freelance work, I was hired as an Environment Artist at Ubisoft Sofia where I had the chance to contribute to titles like The Division 2 and Assassin's Creed: Valhalla. I'm here to talk about how I approached my latest personal project, Before the Storm.
Getting Started
When I started Before the Storm, my goals and ideas were completely different from what the project ended up being. At first, I wanted to do a small project to train in vegetation modeling and composition, something focused only on one main shot or something like that. I was inspired by a concept from Espen Olsen Saetervik. Here is what my early blockout looked like:
But quickly, I realized that I was having a lot of fun doing vegetation assets and I thought it would be cool to do an idea I had in the back of my head for a while and a tribute to one of my favorite games ever: making a jungle scene inspired by Uncharted 4. I knew from the beginning that I would have to completely rethink the scope of the project, as Uncharted games play a lot on changes of scale and big vista reveals, so I started thinking about a new blockout and location.
When watching the live-action version of Mulan, I fell in love with those round-shaped villages and the rice fields around them, and I thought it would be a cool fit for my scene. So I started thinking about starting from a high point, deep in the jungle, in the hills around the villages, to then arrive at the vista reveal point, and start to go all the way down to the village.
I also started to think about having a full video showcasing the entire level from a player perspective, as I thought it would be a great way to understand the scale and I wanted the viewers to imagine it could be part of an actual game. Once the idea was properly formed in my head, I started gathering references.
Planning
So basically, I knew it would be huge and that it would require a big variety of assets and different types of treatment in the level art. I really didn't want it to be just a dense jungle from the top to the bottom, so I started doing top view drawings, trying to figure out a good way to have a nice rhythm along the level, going from a dense and almost claustrophobic jungle to a wide-open area, etc... I'm doing a lot of shitty drawings like that when I'm working, even on professional projects, they look terrible and most of the time I'm the only one who can understand them, but they really help me figure out how to approach things:
This is when I started to think about the river, and how I could use it as a nice way to breadcrumb the path. Basically, when you watch the video, you realize that you cross the river any time there is a change in the type of environment. Here is a top shot showing it (path in red, river in blue):
So from this point, I was able to start planning the assets I would need, even though the number just kept growing during the project.
Vegetation
So let's first talk about the vegetation. I already did some for one of my previous projects, Japanese Village, but it was nothing compared to what I would need here. Also, I really wanted the scene to be more realistic, so I had to improve my skills. I spent a lot of time iterating on the trees, grass, etc before being happy with how they looked.
Let's go with the grass first. I wanted realistic grass, with blades, and which would work from top view as well without making it too obvious that it's just simple planes. The 1st step was to get proper blades. I started looking into the Megascans library. Once I found all the things I needed, I started gathering the atlases in 3ds Max. From there, I would be able to create my own clusters. The process is fairly simple, I just apply a material with the base color and alpha from Megascans to a plane, and then cut the areas I want to keep. Here I selected what I thought were the best blades and I just decimated them. Then I can start creating clusters. I created four of them and placed them in front of a squared plane, to see how they will look once baked.
I can now import the mesh into SpeedTree. Here you can easily set it up to be in a planar view, perfect for baking textures. There is a good tutorial for card creation on SpeedTree's YouTube channel. I imported the material from Megascans and applied it to the blades, and voila, you now have a clean atlas. As far as I know, SpeedTree is the only software where you can bake information from an existing Normal Map, which is perfect for baking foliage coming from scans.
All the plants and ground debris are done using the exact same process, this time mixing multiple atlases from Megascans. Here are shots from 3ds Max with the various atlases gathered, ready to be exported into SpeedTree for baking:
Now, I stay in SpeedTree and just create clusters for the grass and plants, set up the wind properly, and once I'm happy with the result I can finally send them to Unreal.
The same goes for other types of plants, here are some examples:
Getting the material right for the grass was a bit of a challenge, I had a hard time getting the proper "green" and the proper SSS color and value. I found several different talks from Epic about that and tried to apply what I learned. Something which helped to define more the grass and add more detail to the color was using the "FuzzyShadingGrass" node, which let you darken or lighten the edges, as well as change the core darkness of the blades.
Here is what the final grass material looks like:
To get the grass to look sharper, I also disabled the Mipmapping on the Opacity texture (I did that to all vegetation atlases actually), it costs a bit more but the result is way better. Here is how to do it and a comparative shot:
For the trees, the process was a mix between the grass one and the classic SpeedTree process. I started by gathering references.
Then, I created a proper bark texture. Nothing fancy here, I mixed different photos with a scan bark I found in the Megascans library to get a result that I liked. I then used Substance Alchemist to generate the AO and the Normal Maps.
Once that was done, I created a simple branch card, that I will then use to spawn smaller branches with leaves. For this, I just used the same scene setup in SpeedTree as for baking the grass and tried to get a good branch shape. I left a lot of space at 1st with the idea that I would create other branches later on, but I never had the need and it stayed like that. For a professional project, I would have done it better using the maximum space of the UVs.
Once happy with the 1st branch, I moved to the ones with leaves. The same process, except that I added a leaves atlas from Megascans. I decided to create 2 branches and 3 single leaves (position on the atlas is not "optimal", but I really wanted to avoid going into 3ds Max to create the cards, and SpeedTree only allows you to place your pivot going up, so I stuck with it).
So now I have 3 sets of textures for the trees, one bark, one branch, and the leaves. I can start creating the trees.
Like with anything in our job, it's always best to start with the big shape and then go into details. So the idea is 1st to have a "dead" tree that looks convincing. The best way, in my opinion, to have beautiful and detailed branches without having 1 million polygons is to terminate all the branches by the one we created earlier, using a card. Then, you can spawn new branches from the cards you just added using anchor points. This will help give a denser aspect to your tree. You can then add new smaller branches (actual meshes this time) and repeat the same process until you get this convincing dead tree.
Once you are happy with it, you can start spawning the leaves from those branches. It's important to make them face the sky as much as possible (with always a bit of randomness so it doesn't look artificial). This way, the reflection will react really properly on your leaves and it looks more realistic, as leaves always try to face the sun as much as possible in real life. Don't forget to also play with Fold, Curl and Twist parameters as well to help give a realistic look to the tree.
Now, let's move to the vines along the trunk. The idea here is to convert the trunk of your tree into "force". It will simply create a copy of your trunk which will act as a force that the vines will use to grow against. You can do it by selecting your trunk (and roots in this case if you have some), and using the Create Collection from Selection button.
Now, you can create simple trunks and place them around your trunk using the placement parameters. Then, you tell them to use the newly created "force", and you play with parameters to make them follow your trunk the way you want. You need to set up the force to Attract in Force Action and Obstruct in Collide Action. A trick to help is also to add a direction force pointing up, this will force your vines to always go up.
Now, you can simply spawn leaves from the vines and that's it.
Now, let's talk quickly about optimization and wind for the trees. A good way to have good-looking trees with detailed trunks, but for a cheap cost, is to use the curve to reduce the polycount at the end of the trunk and on the higher branches. Players will never see those areas, so it's totally fine. (we will see LOD creation later as this was handled in Unreal).
For the wind, once you have a preset that works for you, you need to tune it for every specific part of the tree. For instance, I didn't want the leaves from the vines to move as much as the leaves at the top of the tree. They are not supposed to receive as much wind as they are deep inside the forest.
Once everything is working fine, you can export the tree into Unreal. Here is the final tree in SpeedTree:
I usually don't use the materials made by SpeedTree as I rather use my own ones. The only thing is to be sure to add the SpeedTree node, or the wind won't work.
And here is the final tree into Unreal:
Variety
Now that the process was working for me, I could start producing a good variety of trees and plants. In the end, a tree would take me around 1 or 2 hours to get done and be happy with the result, as I could re-use most of the graphs from the 1st tree. The goal was to have at least 2 tall trees to have variety in the canopy, as I knew there would be the vista point from which you can see the top of the forest. Then I wanted one very big and tall tree to have large trunks at some spots in the forest. I repeated the same approach with middle-sized and small trees, having every time between 2 and 4 variations of each. Those were the most generic trees that would be used everywhere.
I also needed trees with good shapes for composition, to frame the path and lead the view, so I created those two shorter but more interesting trees.
Then came the special-shaped trees, with more unique shapes. I created 2 of them but ended up using mostly the 1st one on the vista point. This one needed to have this long and shaped by the wind trunk, to enhance the height and feel of the place, and also lead the player's view. Here is a screenshot of the one I used mainly:
Now, the thing I needed to give the jungle a proper dense aspect, was small-sized trees growing around the big ones. So I created those sorts of cheap bushes, which were very useful to block the view and give density.
Then, I needed something on the ground. Using the exact same material as for the trees, I created the ground foliage that I would then be able to scatter everywhere.
After that, variety was added using the ferns and small palm plants. For almost every type of vegetation, I had 3 variations: a big, a medium, and a small one. Here is a shot with all the ground vegetation types.
I also created small debris to scatter on the path. Those were created in 3ds Max using atlases baked in SpeedTree, following the same process we saw earlier:
I used the procedural foliage volume to scatter the forest everywhere, and excluded the path and the village area, to have manual control on those zones. Then, using the foliage tool, I hand placed everything along the player's path. It took a while, but at least I had full control of the composition.
The roots were sculpted in ZBrush, textured in Substance Painter, and are using Virtual Texturing to blend with the ground.
Materials, Cliffs, and Terrain
For the materials, I started the project by creating a bunch of master materials I knew I would need. So I have a standard one, a one ready for RGB Mask texturing, a foliage one, etc...
But the most challenging one was the one for the cliffs. I spent quite some time getting these to work fine. First of all, I needed rocks. I started by sculpting the bigger rocks, then the medium ones, and finally the small ones. I was also able to use some from my previous Star Wars project. Here are some sculpts examples:
Then I did multiple tests to get the texturing right. I knew I needed the textures to be tileable, as I wanted to be able to scale the rocks quite a lot for variety. I tried Megascans materials, photo sourced ones, etc. but I was never happy with the result. I ended up creating 3 materials in Substance Designer, one basic noisy flat one, one with big shapes, and one with detailed damages. Those would be applied as tileable and scalable materials on top of the baked AO and Normal from the mesh.
I then created an RGB Mask for each rock in Substance Painter. Considering Black is the base rock material, it goes this way :
- red for Big shapes material
- blue for Damages material
- green for dirt/dust
- alpha for edge damages
Here is the result in the engine:
On top of that, I added a simple detail Normal Map created in Substance Designer to be sure that the rocks would still look fine from up close.
But I felt the rocks were still lacking something. Big drips/leaks due to weather, and color variations. So I created two masks in Substance Designer, that would then be applied using world space position. The leaks mask is then using black color and a different roughness to add humidity, and the color variation one is using a desaturation node. I also added the ability to use vertex paint to add humidity, especially for the waterfall areas and for rocks touching the water.
Here is what it looked like in Unreal :
After that, I wanted the rocks to either have moss or have the forest ground texture be applied on planar surfaces, to help blend everything together. I used a top blend function to achieve that, following this tutorial.
I also needed the rocks to blend with the terrain, so I used virtual texturing to sample the terrain materials and apply them to the rocks when entering the ground.
After all that, I was happy with the way the rocks look so I started building the cliffs. Here is the final result:
And here is what the final material looks like:
The terrain material is fairly straightforward, it's using 6 materials that I grabbed from Megascans and modified in Quixel Mixer when needed. All the materials have the same parameters as I did for the standard master material, so I have control over Color, Normal, etc. I used the Height Map of each material as a blend mask, to be sure that they would blend properly, and also activated tesselation for more details when running around. Here is what the 6 materials look like :
For the rice fields, it was getting a bit tricky. I wanted to use a spline blueprint, but you can't paint foliage on a blueprint actor. So I first created them using the spline, and then I exported those splines to 3ds Max to create unique meshes from them, so I was able to paint the grass on them. I was also able to create the water planes to follow the fields' shapes.
Optimization
Now let's talk about optimization. I really needed the scene to run at least at 30 FPS for the video. In the end, I managed to do it for a normal HD screen but not in 4K (video is captured in 4k, that's why there are some lags here and there...). First of all, for all the assets, I used Simplygon, which is the plugin already set up in Unreal to generate LODs for your meshes. It's extremely powerful and really lets you control how many LODs you want, and at which distance you want them to change.
Obviously, the heaviest part was the vegetation, and a classic LOD system was not enough to get the scene running. So I had to create imposters for all the trees. I followed this tutorial and downloaded the plugin. It was a bit tricky at first, but after one or two trees, it was a matter of 5 minutes per asset, and it saved a LOT of memory. Basically, all the trees which are at 100m from the player's path are just imposters and are 4 triangles.
For the ground vegetation, I used the culling system from the foliage tool to make it disappear in the distance. I could have gone a bit further in terms of optimization, but it's not the funniest part and I just needed the scene to run smoothly for one video.
I tried to send the scene into Unreal Engine 5 at the beginning, and even though the lighting was really cool, Nanite was off the grid for the vegetation as I needed it to move with the wind using vertex offset. Also, they got rid of Tessellation, so I stuck with UE4.
Lighting
For the sky, I used the Atmosphere System and the Volumetric Clouds, as I wanted a nice pre-storm sky. I downloaded this amazing volumetric cloud shader from Dinusty and just started to play with the values. I wanted everything to be dynamic. The scene is only using Directional Light and Sky Light. I watched all the videos from William Faucher about lighting in Unreal, I learned a lot of stuff from there.
I was able to use ray tracing for reflection, but it was off the grid for everything else as it doesn't work well with vegetation. So I had to use the good old distance field system. This enabled me to have good AO in the trees and nice shadows in the distance. It was tricky to get it right and to find the right balance though. I also had to set up a proper exposure that would work inside and outside of the forest.
I then used post-process volumes to make everything a bit darker and more contrasted in the forest, and a bit more luminous outside.
I also enabled contact shadows, as they really help make everything more grounded. I also ended up creating 2 LUT tables, one inside the forest and one outside, just to slightly tweak the colors and make sure everything worked together.
One of the main things to have a nice jungle feeling was the fog. I really needed this very hot and wet aspect in the air coming from tropical forests, and it would give nice god rays, and everyone loves god rays. So I just created some simple local fog volumes that I was able to scatter along the path. They are surprisingly really not heavy in terms of perfs, as they spawn a really low amount of particles. I followed this great video from Epics and this tutorial, but I removed the color control and made it cheaper in terms of particles.
I also added a light function to have fake clouds shadows moving along the entire level. It really gives a good sense of life and helps sell the stormy sky. I followed this tutorial. Here is a shot without the foliage to really see the effect it has on the scene:
In the end, I created fake clouds for the distance, nothing fancy here, but it really helped give depth to the scene.
Conclusion
This project was a big challenge as a whole. The scale of the scene really made everything harder to do. I had to make sure everything was running, lighting was super hard to get right and I kept tweaking it until the very last moment, getting the vegetation right took me a lot of time, and I had to tackle a lot of issues that I never encountered before.
First of all, one of the main problems was that I didn't plan it well enough, and I kept adding new assets all along. Also, I was never happy with what I had, and I redid a lot of stuff a lot of time. The scene went through 3 or 4 different blockouts, and at some point, I changed everything even though I was pretty advanced in terms of level art, so I lost quite some time redoing everything.
Also, the ambition was too big at first. Something I haven't mentioned is that I also wanted to create the interior of the village, with a lot of new props, etc... Not only it would've been a challenge for the lighting, but also the time to create all of this would have doubled. I decided at the very end to cut it.
In the end, the scene took around 4 months from the moment I decided it would be a jungle. But you can add one month more when I was working on the first totally different blockout, so roughly 5 months.
It was really hard to keep the motivation all along, and I ended up really close to burnout as on one hand I was working to finish Forza Horizon 5 at Playground during the day, and working on this scene in the evenings and the weekends. I don't think I'll do another personal project this big one day.
I really want to thank all my friends who supported me throughout the project and gave me feedback, they helped me a lot. I also want to give a special shoutout to my little brother Enzo Ambrosini for making the sound design of the scene and to my friend Florent Fontalbar for making the music, what their work adds to the final scene is enormous. I also want to thank 80 Level, it was really cool to go through the process, and I hope it will help some people!
Livio Ambrosini, 3D Environment Artist
Interview conducted by Arti Sergeev
Keep reading
You may find these articles interesting