AppleyAppley Docs
Docs/Terrain

Terrain Painting

Paint texture layers on terrain surfaces with blending and splat maps.

13 min read Intermediate Updated 2026-07-01 v2.0 ~39 min to complete

Introduction

Terrain painting applies textures like grass, dirt, rock, and snow to terrain surfaces. This guide covers texture layers, splat maps, and blending techniques.

Guide 2 of 25

This is part of the Intermediate Guides collection. Category: Terrain. Estimated completion: 39 minutes. Difficulty: Intermediate.

Screenshot

Terrain Painting
Terrain Painting

Step-by-Step Guide

1

Create terrain layers

In the Terrain tab, navigate to Paint. Add layers: grass, dirt, rock, sand, snow. Assign a texture to each.

2

Set tiling per layer

Each layer has independent tiling. Grass at 4x4, rock at 2x2. Adjust for natural repetition patterns.

3

Paint with the brush

Select a layer and paint on the terrain. The brush blends layers based on opacity and falloff.

4

Use splat maps

Import a splat map PNG. Each color channel controls one layer intensity (R=grass, G=dirt, B=rock, A=snow).

5

Height-based blending

Configure automatic layer assignment by height and slope: grass low, rock steep, snow peaks.

6

Enable triplanar mapping

For steep surfaces where textures stretch, enable triplanar mapping per layer to prevent distortion.

FluxScript Example

Here is a complete FluxScript implementation for this guide:

Terrain Painting — FluxScript
on start {
  terrain.addLayer("grass", "textures/grass.png", { tiling: 4 })
  terrain.addLayer("dirt", "textures/dirt.png", { tiling: 3 })
  terrain.addLayer("rock", "textures/rock.png", { tiling: 2 })
  terrain.addLayer("snow", "textures/snow.png", { tiling: 4 })
  for x = 0 to 128 {
    for z = 0 to 128 {
      height = terrain.getHeight(x, z)
      slope = terrain.getSlope(x, z)
      if height > 25 {
        terrain.paint(x, z, "snow", 1.0, 3)
      } else if slope > 35 {
        terrain.paint(x, z, "rock", 1.0, 3)
      } else if height < 2 {
        terrain.paint(x, z, "dirt", 0.8, 3)
      } else {
        terrain.paint(x, z, "grass", 1.0, 4)
      }
    }
  }
  terrain.rebuild()
}

Node Graph Example

Prefer visual programming? Here is the equivalent Node Graph:

Terrain Painting — Node Graph
[On Start] --> [Add Layers: grass, dirt, rock, snow]
   --> [For X, Z: 0 to 128]
        --> [Get Height + Slope] --> [Branch]
             +-- > 25 --> [Paint: snow]
             +-- slope > 35 --> [Paint: rock]
             +-- < 2 --> [Paint: dirt]
             +-- else --> [Paint: grass]
   --> [Rebuild]

Optimization Tips

Keep your implementation fast and efficient with these optimization tips:

  • Limit terrain layers to 4-6. Each layer adds a texture sample in the shader — more layers means slower rendering.
  • Use texture atlases for terrain layers. Combining grass, dirt, and rock into one atlas reduces draw calls.
  • Enable triplanar mapping only for layers on steep surfaces. It is expensive — use it sparingly.
  • Paint large areas with splat maps instead of brushes for faster initial coverage.

Common Mistakes

Using too many terrain layers

Each layer adds shader complexity. Stick to 4-6 layers maximum.

Textures stretching on steep slopes

Enable triplanar mapping for layers that appear on cliffs.