Skip to main content

TreeLayer

TreeLayer renders procedural, instanced 3D trees: connected trunk-and-branch meshes with Gaussian-splat foliage drawn by SplatLayer. Eight species share templates, so size, season, color, crops and wind vary per tree without unique meshes. It runs on WebGL2 and WebGPU.

The demo above is the Seasonal Farm example.

Usage​

import {TreeLayer} from '@deck.gl-community/layers';

new TreeLayer({
id: 'trees',
data: [
{position: [-122.4194, 37.7749], species: 'oak', height: 10, season: 'autumn'},
{
position: [-122.4196, 37.7749],
species: 'citrus',
height: 5,
crop: {kind: 'fruit', color: [244, 153, 34, 255], count: 40, radius: 0.08}
}
],
windStrength: 0.025,
pickable: true
});

Each row is a TreeSpec by default. Use getTree to map other records:

new TreeLayer({
data: records,
getTree: record => ({position: record.coordinates, species: record.kind, height: record.height})
});

Properties​

Inherits all CompositeLayer properties. Picking, autoHighlight and highlightedObjectIndex use the source row.

PropertyDefaultDescription
getTreed => dReturns the TreeSpec for a row.
characteristics{}Shared crown morphology for every tree. See Characteristics.
sizeScale1Multiplier for all tree and crop dimensions.
windStrength0Wind bend as a fraction of tree height. 0.025 is a gentle breeze.
windTimenullWind clock in seconds. null follows deck.gl's animation timeline.
maxCanopySplats'auto'Shared foliage splat budget. 'auto' picks one for the device.
maxCanopyPixelsInfinityPixel cap for foliage rendering. Lower values soften leaves.
foveationStrength00–1. Under a tight budget, favors crowns near the screen center.
getCoverageWeight1Per-tree optical coverage, for fading trees in and out.

Per-field accessors​

Each accessor overrides one TreeSpec field, so you can change a single trait, such as a global season, without rebuilding your data. Function accessors follow deck.gl's updateTriggers convention.

AccessorOverridesFallback
getPositionpositiond => d.position
getElevationelevation0
getTreeTypespecies'pine'
getHeightheightspecies default
getTrunkHeightFractiontrunkHeightFractionspecies default
getTrunkRadiustrunkRadiusspecies default
getCanopyRadiuscrownRadiusspecies default
getTrunkColortrunkColorspecies default
getCanopyColorcanopyColorspecies and season default
getSeasonseason'summer'
getBranchLevelsbranchLevels3
getCropcropnull

getCanopyRadius uses a legacy scale: broadleaf crowns render at about half its value. For a crown radius in metres, set crownRadius in getTree instead.

Types​

TreeSpec​

FieldDescription
positionTree base position. Required.
speciesOne of the species below. Required.
heightTotal height in metres.
crownRadiusCrown radius in metres.
trunkRadiusTrunk base radius in metres.
trunkHeightFractionFraction of height below the crown, 0–1.
elevationBase elevation in metres.
seasonspring, summer, autumn or winter.
cropOptional CropConfig. Trees never get crops unless you supply them.
windtrue, false or a bend fraction up to 0.2. Defaults to windStrength.
characteristicsPer-tree characteristics, merged over the layer prop.
trunkColorRGBA bark color override.
canopyColorRGBA foliage color override.
branchLevelsPine tier count, 1–5.

Species are pine, oak, palm, birch, cherry, banyan, mangrove and citrus. Oak, birch and cherry lose their leaves in winter; the others are evergreen.

CropConfig​

FieldDescription
colorRGBA crop color.
countCrops attached inside the crown.
radiusEnclosing radius in metres. Crops too large to fit the crown are omitted.
droppedCountOptional crops scattered on the ground.
kindfruit (default), lemon, cone, acorn, catkin, flower or propagule.

Characteristics​

Characteristics shape broadleaf crowns and leaves. Pine and palm keep their own silhouettes. Changing them regenerates the shared templates, so keep the number of distinct combinations small.

FieldDefaultRangeEffect
seed0integerGrowth pattern.
crownSpread10.6–1.5Crown width.
crownDepth10.6–1.4Crown height.
crownAsymmetry10–2Lopsidedness.
branchDensity10.5–1.5Number of branches.
branchLift10–3Upward branch angle.
internodeLength10.7–1.4Branch segment length.
leafSize10.5–1.8Leaf size.
leafDensity10.25–2Leaf count.

Shadows​

Trees cast and receive deck.gl LightingEffect shadows on WebGL2, like other deck.gl layers. Opt out with deck.gl's standard shadowEnabled: false.

Limitations​

  • Supports MapView, GlobeView and Cartesian views. With MapView.repeat, trees render in the primary world copy only. See SplatLayer limitations.
  • On GlobeView, wood, crops and canopies share one east-north-up pose per tree, unchanged across the zoom-12 switch to Web Mercator. Canopies and connected wood behind the horizon are skipped; crops rely on a globe surface's depth, such as MapLibre's globe, to hide the far side.
  • In Cartesian and metre-offset coordinates, modelMatrix supports translation only.

Source​

modules/layers/src/tree-layer