Developed by VEA Games |
Custom foliage system (FoliagePainter Pro)
Setting up LAMDetailsAutoPainter
Setting up Multi-Foliage Brush
LAM for Unity is a comprehensive terrain and foliage toolset that adds a multitude of features to Unity’s built-in Terrain system. LAM consists of:
LAM Unity includes a fully setup and fine-tuned forest setting. While you can add LAM components to an empty scene and start from scratch, it is easier by far to start with included setting and change it. LAM tools will ensure that whatever changes to the terrain you make, texturing and foliage will adapt auto-magically.
To add LAM setting to a scene, find a terrain prefab in the project. By default, it’s located at Assets/Plugins/LandscapeAutoMaterial/Prefabs/Forest.prefab. Select it, and the go to menu GameObject->3D Object->Terrain from prefab. This will spawn a new terrain in the scene, complete with all LAM scripts attached and set-up. By default, new terrain will not have any grass, because grass foliage is set to be generated at runtime only. You can rebuild all foliage, including grass, by pressing “Rebuild all meshes” button in the BatchedFoliage inspector.
LAM default settings include quite a bit of grass. Enough, actually, to stall even the most powerful GPU were it to render it all. To make sure only the grass that is close to the camera is rendered, LAM uses layer-based culling feature of Unity.
To set up layer culling, locate your main camera and add the SetLayerCullDistances component to it. By default, LAM grass meshes use layer 8, called “Grass” in LAM project. SetLayerCullDistances inspector will show cull distances for all named layers in your project; set the one for grass layer to something like 100 units for manageable performance.
If you need to change the layer used for grass rendering, find grass prefabs (default location is Assets/Plugins/ LandscapeAutoMaterial/Objects/Grass) and change their layers.
There are a few more places in LAM that have to do with grass render distance. LAM grass shader has a fading range setting to make grass disappear gradually, and foliage types in BatchedFoliage component may have special culling set up. Check relevant chapters in this manual to understand how those are used.
There is also a script called LAMQualitySettings that handles all that hassle for you. It can tweak several properties of LAM terrain to match a given quality level - including grass draw distance, grass shadows, density adjustment etc.
Looking at the LAM terrain object you’ve just created, you will notice three extra components attached to it. The first one is LAMTerrainTool, that is used to set up and tweak LAM terrain shader.
LAM terrain shader is similar to built-in terrain in that it has several texture layers that can be painted on the landscape and mixed with each other. The layers are set up in the Layers tab of LAMTerrainTool inspector. In it, you will find list of all layers defined for the terrain. Each layer has a number of properties defined here - most notably, the color, normal and smoothness-specular-occlusion textures used. Check the LAMTerrainTool chapter for a more complete explanation of individual properties.
You can notice that the same layers - and also additional “Auto” layer - can be found in built-in terrain inspector. They are there only so the layer painting interface works - do not add or remove any layers here (unless working with additive shader - see below).
The “Auto” texture layer is special, and holds a lot of LAM magic. Basically, wherever you paint with “Auto” layer, terrain shader will mix all (or some) of your defined layers based on height and slope in every pixel. That way you can define a grassy layer for plain ground and a rocky one for steep slopes - and they will automatically appear correctly! In fact, that’s exactly how LAM forest setting is set up.
The Curves tab in the inspector is used to tweak this auto-painting behaviour. Every layer that has its “Use Auto” box ticked will show here as two graphs: one for slope dependency, and one for height dependency. Click on a layer name on any graph to select it, and set curve properties.
Note that height dependency is applied in world space. This means that moving terrain vertically effectively moves the curve - be sure to change it afterwards, or just finalize terrain position and size before tweaking these curves.
The next tab is called Displacement&Coloring, and takes care of non-layer-based shader properties. You can enable and tweak DX11 dynamic tessellation here, and add coloring and paint textures. The coloring texture is applied to all your terrain using overlay blend mode (just like in Photoshop), but you can set blend amount and texture scaling per-layer. It’s a good way to break up monotony and repetitiveness caused by layer texture tiling. The painting texture is overlaid over the entire terrain, using double-multiplicative blend; it allows you to paint additional colors directly onto terrain, using the “Paint” button. Don’t forget to check the
“Read/Write Enabled” box in this texture’s properties, as it must be written to when painting.
The final, and possibly most important, tab is called Shader. LAM is shipped with 3 different terrain shader variants:
The Displacement variants are the most advanced, supporting full LAM functionality including dynamic tessellation. However, they only work on DX11+ or GLCore renderers. They also have a hard limit of layers: 3 and 6 respectively, not counting the Auto layer.
The Additive shader variant is simpler: it does not support dynamic tessellation, but it can work on DX9 renderer. It is also have the unique property of playing nice with Unity built-in additive terrain painting: in addition to 3 layers that have all the LAM functionality, you can add further layers that use, basically, Unity’s shading. They can only have color and normal maps, and do not support nice features like triplanar texturing etc, but there’s no hard limit on their number. Just as with builtin shaders, however, every 4 layers add another rendering pass to the terrain, so they’re not exactly unlimited.
Also in this tab is the global scale multiplier slider - handy when you want to scale all terrain layers simultaneously; and the “Apply properties” button. The LAMTerrainTool editor should automatically sync terrain material with all changes you make; but in case something goes wrong, or you find an especially clever way to change properties (from script perhaps) clicking this button forces syncing all material properties.
The next component to pay attention to is BatchedFoliage. This script allows painting foliage meshes that use any shader you want; or just painting prefabs over terrain. Meshes painted in this way are automatically batched together to reduce draw calls, somewhat (but not exactly) like built-in grass and detail meshes. Behind the scenes, BatchedFoliage splits terrain into a number of “patches”, and combines similar foliage instances in a patch into single mesh.
BatchedFoliage makes use of FoliageDefinition assets. Each such asset specifies mesh prefab to paint (it’s a prefab, not simply a Mesh reference, to combine mesh with material(s) and renderer settings), and a bunch of settings pertaining to foliage generation: scale variation, rotation, offset etc. It also has an “Instance Prefab” property - this is a prefab that gets spawned per-instance without batching, and can be used to sprinkle your terrain with more advanced game objects - like not-batched meshes with LOD settings, light sources, particle effects, or even sounds.
An important setting is “Update At Runtime” box: when it’s not set (the default), all painted foliage is batched in-editor and resulting meshes are saved with the scene - in the same way as static batching works. This mode works great for relatively sparse and big foliage - big bushes, rocks etc. For dense grass, however, storing all batched meshes with the scene is impractical because of memory and storage requirements: really dense grass may generate gigabytes of mesh data!
When “Update At Runtime” box is ticked, batched meshes are NOT stored in the scene, even if you generate them in editor. Instead, they are dynamically created and destroyed at runtime, only covering an area around the player (as defined by main camera). This saves a lot of memory and startup time, for some performance cost and a visible delay when the game is running but the grass meshes are not created yet. For smooth performance, BatchedFoliage spreads batching calculations over several frames, only spending a preset amount of time per-frame. This is regulated by “Runtime Frame Budget” setting.
Runtime-built foliage has another advanced ability, turned on with “Runtime Culling” box. When it’s ticked, you can specify two ranges. At farther range, the whole patch mesh stops rendering; at closer range, the mesh still renders, but shadow casting is forcibly turned off. This allows you to lessen impact of grass shadows, which look great but are quite expensive.
FoliageDefinitions are added to component’s types list, and can be edited inline in its editor. To place foliage on terrain, press “Paint” button - it will switch terrain editor into custom paint mode and allow you to place selected foliage on terrain, or remove it (with Ctrl pressed).
If you change some settings on an already-painted FoliageDefinition, you may need to re-run batching process, especially if it’s not an updated-at-runtime foliage. There’s a button to do just that, and also buttons to rebuild all static (i.e. saved in scene) foliages, and all defined foliages together.
BatchedFoliage is combined with all other LAM features in the included forest setting, but it can be used independently, on regular terrains, with whatever FoliageDefinitions you might create.
The last LAM component on your new terrain is LAMDetailsAutoPainter. This component takes care of planting foliage for you, so you don’t have to place every bush and grass patch by hand. LAMDetailsAutoPainter can paint both built-in terrain details and trees, and BatchedFoliage foliage types; note that it references foliage by index - that means that changing or removing foliage types, or detail meshes, may break your AutoPainter setup. Make sure you set up its layers only after you’ve finalized your foliage types (or detail meshes, or tree prototypes - whatever you use).
LAMDetailsAutoPainter works by defining a list of “layers”, each specifying what foliage to place, where, and how much. Foliage is defined by “Type” and “Paint” properties; amount to place by “Density”. Internally, density is the number of foliage instances per terrain detail tile - see “Detail Resolution” in terrain settings. Fractional density is interpreted probabilistically - that is, density of 0.5 means 50% chance for every tile to have foliage instance, and density of 2.5 means 50% chance of 2 instances and 50% chance of 3. This allows smooth variations, especially for BatchedFoliage instances that can spawn at most once per tile.
Density is affected by three additional settings: terrain textures, terrain slope and mask. Mask allows you to select an additional texture (make sure it has Read/Write Enabled in import settings) and color channel. The texture is projected on terrain and density is multiplied by this channel’s value. Using this, you can make specific foliage patterns repeating in eligible places.
After you’ve defined the layers, clicking “Repaint Layers” button places foliage all over the terrain. The layers are also auto-applied when you paint height or texture layers on the terrain, unless you turn it off in the preferences.
LAMDetailsAutoPainter in included forest setting is set up with LAM shader textures and BatchedFoliage grass and trees. However, the script itself does not require other LAM components - you can use LAMDetailsAutoPainter with built-in terrain shaders, and probably even other third-party ones (as long as they use terrain texture layers). You can also use LAMDetailsAutoPainter to place built-in details and trees, with or without BatchedFoliage component.
Another useful tool, though not an additional component, is the MultiFoliage brush. It can be accessed by pressing the last button in the Terrain inspector. MultiFoliage brush allows painting multiple foliage varieties at the same time, including built-in grass, trees and BatchedFoliage types.
It works by defining a number of “Paints”, analogous to LAMDetailsAutoPainter component. Each paint has a foliage type and index defined, and also density to paint with. When you paint, all defined paints are applied independently to every painted detail tile - unless the brush has “Use Weights” box ticked.
The “Use Weights” mode adds weight property to every paint. When it’s activated, on painting every tile first selects a single paint according to its weight - i.e. if a paint has weight of 0.13, it has 13% chance to be selected. Then only this paint is applied to the tile in question - according to the paint density, which means that foliage instance may not, in the end, be generated. If all paint weights add up to less that 1, there’s chance that nothing will be painted at all in the tile; and the brush editor ensures weights never add up to more than 1.
The MultiFoliage brush supports saving presets - lists of defined paints - into a Preset Library asset. There’s one included in LAM, and you may add more presets to it, or create your own. To use a preset library, drag its asset to “Library” slot and select preset using the drop-down. Use buttons below the drop-down to edit presets: in order, save current paints to selected preset, create new preset (with current paints) and delete selected preset. To create new library asset, clear the “Library” slot and a button would appear.
Note that MultiFoliage paints, just like AutoPainter layers, use foliage index to reference foliage. This means that a preset may not work on a terrain with different foliage setup, or may become broken if you edit or remove foliage.
LAM Unity adds several settings to editor preferences, accessible through Edit->Preferences menu, LAM tab. Here you can turn on or off AutoPainter “realtime” updates: if the “Update AutoPainter while painting” box is ticked, all terrain painting will automatically schedule AutoPainter (and BatchedFoliage) updates in affected area (it will be shown with red rectangles in scene view). With many layers and foliage types defined, updates may be slow. Current update progress is shown with a progress bar in lower-right corner of scene view.
When auto-updates are enabled, “AutoPainter update delay” setting controls delay between releasing mouse button and start of update process (giving you time to “batch” several painting atcions together). “AutoPainter time per frame” is maximum time, in milliseconds, the update process is allowed to run before giving Unity editor chance to do its job. Higher values will make updates finish faster, but the editor would be less responsive during update.
“Update runtime-only batched foliage” allows you to exclude foliage types with “Update At Runtime” set from this updating process. This may speed up work, since these foliage type are not needed in the scene - they will be recreated at runtime anyway.
The “Edit-time foliage reduction” allows you to reduce density for these foliage types when created in editor. In-game, runtime-updated foliage is only supposed to exist around the camera, but in editor, it’s generated everywhere on terrain. This may put additional strain on editor performance and eat a lot of memory - reducing density would help with that, at a cost of not seeing exactly the same foliage in the editor as in-game.
LAM Editor preferences take care of in-editor performance, but what if you want to change settings in-game, to support multiple quality levels? There’s a LAMQualitySettings component for that; look for “Settings” game object in the demo scene for the example of its setup.
LAMQualitySettings define a list of LAM-specific settings to go with built-in Unity quality settings, the ones available in Edit->Project Settings->Quality menu. Each LAM quality level corresponds to Unity quality level, and the component automatically selects and applies one on scene start - the level that is closest to select Unity quality.
LAMQualitySettings levels can override draw distance, density and shadows rendering for grass foliage, and turn terrain shader tessellation on or off - for shaders that support it. The “grass” adjustments apply to some foliage definitions in BatchedFoliage - specifically, those that have layer Grass specified. If you use another layer, or layers, for grass, you can set them in “Grass Layers” property of LAMQualitySettings, so that it knows which foliage types to change.
LAMQualitySettings does not work with built-in grass and trees, however, and does nothing if you don’t use either LAM terrain shaders or BatchedFoliage.
Before setting up LAM terrain, decide what layer(s) would be used for your grass models. Grass included with LAM uses layer 8, but you can change this.
Grass layer is important, because no computer is probably fast enough to render ALL the grass at the same time. To get nice performance, you need to only render grass that is close to camera, and that is done through layers. After deciding on a layer, put a LAMQualitySettings component somewhere in the scene. You can use prefab included with LAM that can be found in Plugins/LandscapeAutoMaterial/Prefabs. Set the grass mask in this object’s inspector to your grass layers.
Then, create a Terrain object. Set up its settings: size, position, heightmap and detail map resolutions. Changing these values afterwards may destroy you work.
Note that LAM shaders may misbehave if you rotate or scale terrain object.
LAMTerrainTool handles terrain texturing, auto-painting and additional shader features. Add it with AddComponent button, or use a special button in the Terrain inspector settings tab.
Your first stop is Shader tab in LAMTerrainTool inspector: select the shader you want to use here. The difference between shader variants is explained above in “Quickstart”.
Next, visit “Layers” tab. Here you add actual texture layers for the terrain. First layer in the Terrain inspector is used to mark auto-painted areas; all the actual textures use layers after it. Add a new layer using “+” button. You can set its name, textures and all the other properties here. You can add more layers than the shader supports, they just won’t be rendered (this is to prevent you from losing work if you ever switch to a shader with less layers than already defined). Don’t forget to tick the “Use Auto” checkbox for every layer that you want auto-painted.
After adding your textures, switch to “Curves” tab. Every layer used in auto-painting will have its slope- and height-dependency curves defined here. By default, these curves are equal to 0 everywhere. A dependency curve is defined by three values: “From”, “To”, “Smoothing”. They mean that a layer’s weight would begin to raise at “From”, go up to one, and then fall again to zero at “To”. The higher the “Smoothing” value, the more abrupt this rise and fall would be.
Click on a layer name on the graph, and set up its curve for slope, and then for height. You should notice changes on the terrain immediately.
After setting up texture layers, and maybe painting for a while, switch to “Disp&Coloring” tab. Here you can set up terrain displacement (if the shader supports it). More importantly, you can select a “Color Overlay” texture to mix with your layers. Important note: if you’re using linear lighting, make sure to tick “Bypass sRGB Sampling” in this texture’s import settings. Overlay texture is mixed in a way that does not make use of gamma, and using gamma adjustment with it leads to wrong results. Every layer has its own properties for overlay strength and scale - be sure to check them to get the desired look.
Another texture you can add here is the “Color Paint Texture”. This is a texture that stores painted color - that you paint directly on top of terrain. The texture used here should have “Read/Write enabled” ticked in its import settings, as well as “Bypass sRGB Sampling”. Start with a texture filled with neutral grey (128,128,128) color - this value means no adjustment for the terrain. If you assign, say, a white texture here, your terrain would suddenly turn super-bright.
Once you’ve set up all the layers and overlays to your liking, the terrain is ready to paint. Do your elevation and texturing work now, or move to foliage setup.
If you want to make use of LAM foliage shaders or foliage system, you need to add LAMBatchedFoliage component to your terrain object. Just as before, you can do that by clicking a button in Terrain inspector.
LAMBatchedFoliage needs foliage definitions to work. If you’re using LAM assets, just use the files from Plugins/LandscapeAutoMaterial/Foliage. Otherwise, you need to create your own definition by selecting Assets/Create/LAM Foliage Definition in the menu.
A foliage definition need a link to foliage mesh. If the foliage is batched (grass, trees, rocks etc), link a single model prefab to the “Patch Prefab” slot. The actual foliage in the game would use this prefab to create batches - copying all renderer settings, but switching the mesh to a batched one. Or, if you don’t want batching, link a prefab to the “Instance Prefab” slot. Instance prefabs are simply spawned as individual gameobjects by the system, and are useful for trees (that can’t be batched as they use multiple submeshes) or non-mesh objects like particle effects.
The rest of foliage definition settings control instances placement and runtime behaviour. Check “Updated at Runtime” box to have foliage regenerate at runtime instead of saving with the scene - this works great for dense grass that would eat lots of memory if saved, and is only rendered close to camera anyway.
One you have your definitions ready, add them to the LAMBatchedFoliage by clicking the “+” button and dragging the definition asset to the corresponding slot. You’ll notice that Foliage Definition inspector is displayed right here too, so you can change foliage settings without hunting for the asset file in your project.
You can place foliage right now by clicking the “Paint” button in LAMBatchedFoliage inspector, but it’s pretty barebones. It’s way better to set up automatic painting and Multi-Foliage brush first.
LAMDetailsAutoPainter is the script that places foliage for you automatically. To add is, as before, you can click the button in Terrain inspector, or just add it like any other component.
LAMDetailsAutoPainter, too, uses layers to define foliage placement rules. Each layer spawns some foliage - either built-in or LAM - according to weights you set up. Click “+” button to add a layer. Select foliage type and index (called “Paint”) to set what foliage will be placed. Note that internally, “Paint” is the foliage index in the list - so if you remove some tree or grass type, this setting may end up pointing to the wrong foliage. Try to finalize setting up LAMBatchedFoliage, and/or tree and grass settings in the terrain object, before you set up AutoPainter.
Next, set up layer rules. Texture weights define on what terrain texture the foliage would spawn; slope cutoff allows you to define additional slope dependency (just like with terrain textures). Use Min Weight setting to stop foliage from spawning if weight is small - without it, really low weights lead to spawning maybe one or two bushes where they otherwise don’t grow.
A very powerful concept in LAMDetailsAutoPainter is a “Mask Texture”. This allows you to select a texture and color channel, and modify foliage weight by the value of this color channel, from the texture projected onto the terrain. By combining several channels, you can paint patterns and formations as simple colors, and then AutoPainter would turn them into actual grass and bushes.
Spawning foliage can be a lengthy process, especially if you have many layers defined. By default, LAM would regenerate auto-placed foliage as you paint on the terrain. You can turn this off in the Preferences, however. If you made some sweeping changes and want to recreate foliage all over the terrain, click “Repaint” button.
If you want even more control over your foliage, you can use “Paint erase layer” button to mark areas where auto foliage does not spawn no matter what. Then you can place anything you want there by hand.
Multi-Foliage Brush is not a terrain component, but an editor tool that is the preferred way to place foliage in LAM - especially when using LAMBatchedFoliage. It can be found in the last tab in Terrain inspector. Multi-Foliage Brush uses a number of “Paints” not unlike LAMDetailsAutoPainter layers (in fact, they use the same code internally). A brush paint defines a foliage type and index, and desired density. When you paint on the terrain, brush places all the foliage in its list, with probability defined by density.
To set up the brush, open its tab in Terrain inspector and click “+” button. Select the added paint, choose foliage type and index for the paint, and set up density (it’s 0 by default).
You can also tick the “Use Weights” checkbox and a weight control would appear. In weights mode, the brush tools first selects one paint from the list, randomly based on it’s weight, and only then decides whether to place an instance. Use this mode when you’re placing mutually exclusive foliage like rocks or trees.
Once you’ve set up the paints list that you like, you can save it onto a brush preset library. Choose a library asset (or create one by clicking “Create new” button with no library selected, then press “Add new” to add a preset. You can also update, delete and clone existing presets if you select one. A preset library can store any number of presets.
Note that’ just like with AutoPainter, Multi-Foliage Brush presets store foliage index. They may become wrong if you delete a foliage type from the middle of the list.
LAM includes a nifty “Terrain Prefab” functionality. If you plan to make several terrains with similar settings, you can create a terrain prefab by simply dragging the terrain gameobject to the Project window. Now, when you do that the resulting prefab still references the same underlying data assets that the terrain in the scene. Simply putting it into another scene won’t work as expected. However, with LAM you can use “Terrain from prefab” in the GameObject menu to create a full copy of the prefab in the scene. LAM would correctly duplicate underlying asset files, fix up all links and you’d have a new terrain in the scene, all set up and ready to go - just like the one included with LAM.