Building Pine Flatwoods In UE4

Jonathan Holmes from the Quixel team shared a detailed breakdown of his recent environment Pine Flatwoods discussing the workflow in Quixel Mixer and SpeedTree as well as export and material & lighting setup in UE4.

Introduction

Hey there! My name is Jonathan Holmes. I work for Quixel, now part of Epic Games, performing community management and product support. I perform support duties at Quixel, but not just product support! Community management is a vital part of my duties, and the ability to work with our art tools and our content library is critical to being able to effectively manage a community of artists. I’m very active in the Quixel Art Community on that note, which is a fantastic resource for artists of all skill levels to learn from one another and grow.

This particular project was done during the evenings over the course of a couple of weeks. Unreal is one of my core focus points as I've worked with the engine since UT3 and UDK in 2009.

Pine Flatwoods: Quixel Mixer Texturing

Mixer made up a large chunk of this project, including the Florida Trail sign in the foreground. This prop was made without baked normals - the entire model has a single chamfer on all edges which doubles its poly count (from roughly 500 polygons to 1k) but allows me to work with weighted normals to produce a high-poly-like result. This also has the advantage of skipping the baking process entirely - something I didn’t need to do for this project because nothing here was designed to be game-res.

You can see my layer setup here. It’s pretty simple overall, just groups controlling different aspects of the material. One thing I created specifically for this project was my Wood Weathering Smart Material. This allows you to create cracks in wooden objects that look pretty realistic with minimal effort. You can actually add this Smart Material to your own copy of Mixer and any projects you’re working on by grabbing it here.

Check out this quick demo of it in action!

You can also adjust the intensity of the cracks by playing with the Crack Depth and Crack Controller 1/2 layers:

Getting the Smart Material into Mixer is pretty easy. Navigate to your Megascans library folder and open the *\Custom\smartmaterial\ path, then extract the Wood Weathering archive to it. From Mixer, select Library → Refresh Library and you’ll see it in your Smart Material tab. I’d really appreciate a shout-out if you use this - it’s always great to see what people do with art.

Getting the Florida Trail logo in required a bit of PS work. This is done by placing the image I’m working with on the canvas with the UVs overlaid so I know where it needs to be set:

From there I simply export a transparent PNG containing only the FTNST logo and load that into Mixer via a Paint decal. The final result works out quite well and I’m pretty happy with how it turned out.

SpeedTree Foliage Breakdown

I spent a significant amount of time working in SpeedTree to get the foliage looking appropriate to the pine flatwoods ecosystem, which is a very large part of the Floridian peninsula. This scene used several versions of longleaf pine and saw palmetto, aptly named for its razorblade-like stems. I worked with SpeedTree because it’s the best solution I’ve found currently for creating real-time foliage, even though I use it in a way that’s more targeted toward offline usage. Here’s the general process behind working with it:

I use PureRef to manage the references I’ve gathered. Most of these are shot by me. Some are taken from Google Images, and some are taken from Street View. Having a wide variety of references guarantees a much more accurate result than what you’d get working from a single image or subject.

After references were gathered, I set up a simple leaf model using a pine atlas from the Megascans library. I had to do it this way particularly because longleaf pine assets do not exist in the library… yet! To get the look of a longleaf requires having large bushy pine needle clusters generally pointing upward at the end of an arrangement of branches.

This asset is made up of several planes that were rotated until it was full and bushy. It’s not terribly convincing to create assets like this with just a single plane. The duplication, rotation, and vertex noise help sell the final look from up close and afar. I’ve added modified vertex normals as well - you can read about this on the Polycount wiki.

Once the modeling for the atlas is done, it’s exported as a FBX at the origin (with an appropriate pivot point centered in the needle bush) and loaded into SpeedTree. This is done by using the Material window → Manage Materials:

I created a material called Longleaf and added all of the textures for this asset into the slot. Most of this is arbitrary (aside from the albedo/opacity texture) since I’m not going to use SpeedTree to create texture atlases - it’s simply creating geometry that I’ll refine with materials in UE4 later. The Material window should look similar to this when you’re done adding textures:

The next step is simply adding a custom mesh (identical to how materials are added) and assigning it to the Meshes tab in the Materials window.

This can then be dragged and dropped via the hand directly onto a leaf generator in the viewport or in the Generation window. My Generation window looks like this:

SpeedTree makes setting up trees relatively easy, so the tree settings themselves aren’t terribly important. I won’t go over the specifics of how I built the tree in the interests of brevity because I could write an entire short story about the design process that went into this tree and the trees based on it. 

What’s important to know is that the tree hierarchy is the focal point of everything. If the hierarchy isn’t built correctly, nothing else will be either. Note again that these trees are set up to be mid-poly/high-poly and aren’t optimized for game use. I use Unreal as an offline renderer, so I’ve modeled everything except for the individual needles instead of using atlases for branches connected to the needles.

Starting from the Tree generator, we move to the Trunk. This is essentially the root of the entire tree. I didn’t add literal roots to it because they wouldn’t be visible in the scene due to the amount of ground foliage I added. The Knot and Twigs generators are there to add visual interest in the trunk and break it up so it doesn’t look like a long pole.

Big Branches sets up the core of the longleaf’s look. The first Big Branches connect to the Trunk. The second Big Branches connect to the Twigs from which all of the Leaf Mesh needles sprout. This design was necessary to make it look like a longleaf pine. They grow in a very particular, rather top-heavy way, and have a generally rounded bell-like profile when seen from the side. Getting this look is crucial to nailing the pine flatwoods ecosystem. Without that look, they could be any other type of pine and it wouldn’t be flatwoods!

One other thing: The branches use Interval generation so they grow and change as the tree itself lengthens, shortens, or is otherwise adjusted. This method of tree generation allows for creating several variations of the same tree with minimal effort.

Using the references I mentioned earlier, I set SpeedTree up for modeling much like how I work with 3ds Max: perspective and orthogonal views.

The bark was made with Mixer using older pine bark scans. Longleaf pines have a tinge of red and white in the bark as they grow older and this helps differentiate them from the similar loblolly pine. The UV placement was generally left to be adjusted via material instancing in Unreal, but I did try to get the UVs at least looking relatively accurately tiled from a distance in ST. I try to keep the UVs on the branches scaled about the same as they are on the trunk. At the distance these trees are seen, it’s mostly just to avoid any weird artifacting from mip mapping.

The material is somewhat stylized in Mixer so that the defining pine characteristics show through at a distance. This was achieved using several curvature layer blends in Mixer with varying bits of noise in the layer masks breaking up the surface.

I created a charred version of this texture as well as any accurate flatwoods recreation needs to have some evidence of burning, as flatwoods only exist due to frequent fires. This was mixed together in Unreal using a simple vertex paint setup with the displacement map from Mixer controlling the blend.

The saw palmettos were created using this palm asset from the scan library. We have several ready-made palm fronds that I could have used but it would have led to a lot of easily visible repetition. 

The saw palmettos were created with individual frond geometry in 3ds Max. I traced over each frond piece using a plane and shaped the plane to fit the shape of the frond texture, with a line down the middle to allow it to fold and bend where the fold exists on the texture. This offered me total control over each frond and how it was visually represented. 

Each frond was exported individually at the origin and imported into SpeedTree in a manner just like the pine needles, except I assigned all of the palm frond components to a single material so that each frond would use all of the frond components at random to help keep it from creating easily recognizable patterns.

The palmetto was set up in a nearly identical manner to the pine. This is because SpeedTree is really easy to work with, so there’s no reason to alter the basic behavior of a tree unless it’s radically different in the overall composition. If it has what could be considered a trunk, that’ll be the focal point. In this case, I just made sure to offset the Trunk vertically so it sunk underground, and had all of the Big Branches sprouting from it at different positions on the mesh (First/Last property in Generation). From that, Branch pops out. This is where it really differs from the pine. The branch is an invisible guide to how the Fronds grow.

The Fronds simply path themselves along the spines of the Branches. This is done by setting the Skin property of the Branches to Type: Spine Only. It then becomes a framework that the Fronds are laid on. There are varying adjustments you can make but ultimately I chose what would best represent a saw palmetto from a distance  - these aren’t meant to be seen up-close, although they definitely do hold up well enough to do so.

Exporting SpeedTrees To Unreal

This is where it all comes together. Exporting to Unreal brings up an option box:

These are the settings I use when exporting to Unreal. I’ve chosen no atlasing, no texture exports, and no LODs. I let Unreal handle the LODs for some performance gains while working in-engine to reduce the amount of work I’m doing on the SpeedTree side of the project. “Separate materials” creates as many material slots in Unreal as your tree has materials applied, so I apply the same materials I added in ST inside of Unreal. From here it’s as simple as dragging and dropping the *.ST file into UE4’s Content Browser.

Material Setups

The materials I used in this scene are hand-made. They’re not the most complex or the most technically impressive, but they work for what I need them to do. You’re welcome to use them if you’d like! There’s no need to even credit me if you don’t want to - but it would be nice if you pinged me and let me know what you used them in.

Included in this link is the terrain master material, foliage master material, and environment master material. All you’ll need to do is extract these .UASSET files into your Content folder using Windows Explorer (you can’t do it via the Unreal Engine interface) and then open them in Unreal and assign a set of default textures to them. Albedo to albedo, RMA-packed to RMA-packed, etc. It’s pretty simple to do. Once you’ve done this, save and compile and create an instance of it. Within the instance you can add the textures you’re working with for a specific asset or terrain.

MASTER_Environment control rundown:

Enable Wind Setup: This enables basic SimpleGrassWind in Unreal.

Emissive: Enables Emissive and controls for Emissive textures.

Emissive Flickering: Simulates flickering lighting. Controls are as follows:

Emissive Flicker Speed: Controls the sine wave speed.

Emissive Fresnel Exponent: Controls the directionality of the emissive light.

No AO: Disables the AO map by filling it with white. Doesn’t have any real effect unless your scene is running static lighting.

No Metalness: This can generally be ignored. It’s there to test out how some materials look with/without metalness values.

No RMA: Enable this if you’re working with a roughness map that isn’t channel-packed.

Specular Control: Enable this if you’d like to control the IOR of your material. This takes the black/white values of the albedo map and uses it to drive the specular reflectance. Specularity in Unreal isn’t the same as the specular/gloss workflow. Values of 0.5 are a constant level of IOR, while values below 0.5 reflect less light and values above 0.5 reflect more. This has no effect on metallic materials.

SpeedTree Wind: You’ll need a wind actor in the engine to use it. This allows ST wind properties to work in-engine. Play with the settings for it until you find something you like.

X Power: Essentially a levels modifier with no three point levels control. Values higher than 1.0 add more levels contrast, values lower than 1.0 reduce contrast.

X Strength: Combined with the associated Power node, you can get PS-like contrast on a particular map. 

The following images depict the Specular channel set to 48 Strength and 2.5 Power on the right, vs unmodified Specular on the left.

With lighting, it looks like this:

The X Power/Strength nodes can be used for granular control of roughness maps. The material is also set up so that you can set Albedo Saturation to 1.0 and achieve limited recoloration of an albedo map via the Albedo Color.

U/V: Values above or below 1.0 adjust the tiling of each channel individually.

Normal Strength: Allows for individual control of normal map channels. Use this with caution. I find that plants often look much more convincing when their normal B channel is set to 0.5 with the R/G channels set to 2.0, sometimes higher or lower depending on the asset.

TERRAIN_Master is set up in a similar manner. The major differences:

H Levels/Strength: H stands for Height. This allows you to get more control over height-based blending. It requires a heightmap for terrain blending (basically a very clamped texture) placed in the albedo alpha channel.

AO: Multiplies the AO map over the terrain albedo texture which can produce visually pleasing results.

MASTER_Foliage is also set up in a similar way. Here are the differences:

Moss Shading: Enables the FuzzyShading setup with associated controls.

Fresnel SSR: Something I was toying with to see if it would add some depth to subsurface scattering. Best to leave it alone unless you’d like to tinker with it.

Color Breakup: Utilizes per-instance color shifting. This is most prominent when using the Foliage Painter. Small values go a long way.

Opacity: Controls the depth of the subsurface scattering.

Alpha Strength/Levels: As before, these two controls can produce some interesting results. Setting Strength above 1.0 can make foliage appear much more prominently in your scene.

Scene Design & Layout

The pines were originally placed using Unreal’s Foliage Painter, but this doesn’t work as well for trees when you need them placed precisely. I only painted the trees in the far distance with the painter. At that point it’s necessary to use the painter to create a realistic canopy of treetops in a reasonable amount of time.

The ground-level foliage is entirely composed of premade plants from the Megascans library. Each one is chosen based on how similar it is to plants found in the pine flatwoods ecosystem. They are as follows:

All of the ground-level foliage, with a few exceptions (saw palmetto in specific locations) is placed via the Foliage Painter. There are just too many plants to place to do it by hand in a reasonable amount of time. I usually vary up the scale of the plants by 15 to 40% per instance from a base scale of 1.0, so from 0.9 to 1.4. I also paint one type of foliage at a time and then come back to it and use the “Reapply settings to instances” tool in the painter to adjust the foliage density at random, either up or down. 

With the grass clumps in particular, I also vary them up by playing with their Z offset and Z scaling (via Free scaling) so that they tend to be below the terrain when placed but have the top-most grass blades randomly poking up with a Z scale set to a value like 1.5 - 3.0. This helps produce sparse areas of grass without them all being at the same height, which seriously pushes the realism.

The main terrain uses a lot of “Tip” brush blending in the Landscape Painter with a low tool strength, usually set to 0.1 to 0.3. Repeatedly laying down a material produces some visually interesting effects on the terrain with height-based blending:

The terrain itself is simplistic - this is Florida after all, there’s no canyons or valleys here! Subtle terrain changes are key to getting a believable flatland environment to work. I used a lot of terrain painting with very low tool strengths to get the effect I was looking for.

With foliage covering up any texture repetition, I’d like to think that I created a pretty neat looking environment.

Lighting

This scene uses the new SkyAtmosphere setup introduced in UE 4.24! 

I’ve been looking forward to this for a long time. It significantly reduces the amount of work necessary to produce a visually pleasing composition and allows for more natural lighting in the environment without necessarily needing to use a sky sphere to create backgrounds. It fully simulates a real-world sky lighting system provided that you’ve set up your directional light as an Atmosphere / Fog Sun Light with a Skylight.

You can see the impact this has on scene creation! With the new procedural cloud system in UE 4.25 you’ll be able to forego a sky sphere almost entirely if you want total control of the environment.

Lighting in this scene is produced entirely by a raytraced Directional Light. The only difference from a stock DL is that it’s set to an intensity of 8.0, an arbitrary number that brings out the mid-range and highlights but doesn’t over-expose. This is important (keep it in mind, I’ll go over it again at the end) as the final product is processed through Photoshop similar to a RAW photo from a DSLR/mirrorless camera, so having a good mid-range to work with helps keep the final product grounded in realistic values when doing final image processing.

The Skylight uses a very low value. The Intensity is only 0.25. The raytracing environment does a lot of the work with GI and AO. The skylight simply helps fill in light from the open sky. Unfortunately this can result in too much blue lighting because the whole environment isn’t built, only the visible portion is. This means that the area behind the camera is basically blank with a huge swath of blue that projects right on to the trees and other foreground objects with nothing else to break it up. Keeping it at a low value helps mitigate this. Any light leaking in the final product can be adjusted in Photoshop.

The SkyAtmosphere actor has some tweaks done to it to emulate a late-day sky here in my native Orlando, FL.

The changes I made were as follows:

Mie Scattering scale brought out more dust in the atmosphere, common in this time of year (March→May) which is part of our dry season.

Mie Anisotropy was set from 0.8 to 0.9 to put an emphasis on the dust being most visible where the sun is beginning to set.

Mie Exponential Distribution brings down the dust altitude to roughly 1km, helping keep it at a realistic value for the locale.

Tip Value was changed from 1.0 to 3.0 which helped bring some additional blue into the sky facing north, in the rightmost part of the image.

Aerial Perspective View Distance was set to 2.0 from 1.0 to help bring more dust into the foreground without making it overbearing.

Camera Work

Camera work is always my favorite part of any project. I shoot using the Olympus Micro 4/3s System and my previous projects normally worked with the M43 filmback, but these days I’ve transitioned over to using full-frame. This scene was shot using a Cinematic Camera Actor set to 22.5mm at f/2.0. The only changes to the camera were as follows:

  • Slope: 0.95
  • Toe: 0.2
  • Shoulder: 0.0
  • White Clip: 0.0
  • RTAA was enabled with 4 samples per pixel.
  • RTGI was enabled with 1 bounce and 8 samples per pixel.
  • RTR (RT Reflections) were set to 2 bounces and 4 samples per pixel, with Area Shadows and Translucent Objects enabled.
  • RTT (RT Translucency) was enabled with 1 ray and 2 samples per pixel, with area shadows. Refraction caused some visual artifacts in the saw palmettos so I kept that disabled.

Post Processing, Final Image Grading

I treated this scene like I had actually shot it using my camera. Using Unreal’s cinematic system, I rendered out EXR files to get full 32-bit images to work with. Since I wanted to use the Photoshop Camera Raw plugin, I had to convert the images to 16-bit. The base EXR looks like this when imported into PS:

Once brought into PS, reducing it to 16-bits presents another challenge - getting the image into 16-bit format without messing up the color grading or any other aspect of it. That’s what my Unreal 4 preset does:

This converts from 32-bit to 16-bit without causing any noticeable quality loss. The image stays the same for all intents and purposes. Once at 16-bit it’s capable of being edited with Camera Raw. I won’t make this into a full CR tutorial since that’s not the purpose of this writeup, but it is an essential piece of the final product so I’ll touch on it.

Here are the general settings I used:

The settings I used were chosen specifically to produce a late-day ambiance. I wanted the sun to be bright but not overly bright, so keeping a lot of my final image in the mid-range allowed me to really work with the values and push/pull without much clipping. As a result, shadows only needed to be brought down a little while I was able to get the mid-range up by adjusting a slider until I was happy with the result. Bringing the Texture down reduced a lot of the CG look and bringing the Clarity up helped bring out the light and shadows.

Sharpening was added via the Detail panel, and I did intentionally add 30 levels of Grain to the final product via the Effects (FX) panel because I felt that it added to the photographic authenticity I was aiming for. There’s no camera in the world that produces noise-free images. Some people prefer noise-free, some people prefer a little noise, and some people prefer more noise than that. I went with the middle ground and added a bit of it but tried to keep it from being overbearing.

Progression

Here’s how the scene evolved. One thing to take away from this is that any scene will look better as you work on it provided you work with feedback and take a rest from looking at it. Don’t use tired eyes to look at your work. Take a break, do something else for a bit. Come back at it when you’re refreshed. I made some silly choices in retrospect as I kept making versions of this project, but ultimately I ended up with something I’m proud of that represents one of my favorite environments in a faithful way.

Thanks for reading - I hope this has helped you out even in a small way.

Jonathan Holmes, Community Manager at Quixel

Join discussion

Comments 2

  • piro_6650405

    Спасибо за очень хороший,учебник!
    Все очень понятно и интересно!

    0

    piro_6650405

    ·3 years ago·
  • facatic

    Awesome work, very detailed, natural, nice atmosphere, great lighting.
    I am keen to check out your master materials as they seem to have some functionality with additional interesting usage and advantages.
    Would you share your computer specs?
    How did you build up your scene? How did you start? How did you decide where to put what? Can you explain more about the look development process? Any recommendations on literature?. Breaking the ice and start to populate the scene seems to me the hardest part.

    0

    facatic

    ·3 years ago·

You might also like

We need your consent

We use cookies on this website to make your browsing experience better. By using the site you agree to our use of cookies.Learn more