Skip to content

Blend Scatter Demo

App: apps/blend_scatter_demo/

Demonstrates Blender foliage import (engine PLM-252, Block BLD): the .blend loader emits baked scatter as GPU-instanced draws. GrassField.blend carries a hidden grass-blade prototype plus a Plume_Scatter Empty whose plume3d_scatter_xforms bakes 196 blade transforms + colours, and BlendResult.instantiateScatter(scene) turns each baked prototype into one InstancedMesh — a single GPU-instanced draw per prototype, coordinate-converted onto the ground plane, with per-instance frustum culling and wind sway. The clean visual proof of the baked-scatter pipeline.

Terminal window
% ./plume3d blend_scatter_demo

A camera looks across the grass patch. The demo captures a screenshot at frame 60 — printing the number of instanced meshes created — and exits at frame 80.

  • Loads a grass shader first so it is the active shader (the instanced draw path uses the active shader), plus a lit shader for the ground plane:

    Graphics.loadShader("shaders/grass") // FIRST -> active shader for the instanced foliage
    _lit = Graphics.loadShader("shaders/lit")
  • Loads the baked .blend and emits the scatter as instanced draws in one call, which returns the number of InstancedMeshes created (one per baked prototype):

    var blend = Resource.loadBlend("Models/GrassField.blend")
    _created = blend.instantiateScatter(_scene)
    System.print("instantiateScatter created %(_created) instanced mesh(es)")
  • Sets a global wind (Graphics.setWind) the grass shader reads to sway the blades, adds a flat ground plane (MeshGen.plane) for context, and draws the scene (_scene.draw() submits the instanced foliage with the active grass shader).

  • Resource — loadBlend.
  • BlendResult — instantiateScatter (emit the blend’s baked foliage as one GPU-instanced mesh per prototype; returns the count created).
  • InstancedMesh — the single GPU-instanced draw each prototype becomes (per-instance colour + frustum culling + wind).
  • Graphics — loadShader, setWind; MeshGen — plane.
  • The scatter is authored + baked in Blender, not in script. Where Grass Field hand-places instances in Wren and Scatter Demo places them procedurally with the Scatter factories, this demo loads a field baked into the .blend — the geometry-nodes / particles / collection-instances authoring workflow round-tripped through the loader.
  • One InstancedMesh per prototype. Each baked prototype is a single GPU-instanced draw; per-instance colour comes from the baked table (the params.x scale + wind conventions of enhanced instancing apply). Coordinates convert automatically (Blender Z-up → engine Y-up).

See BlendResult for the full blend surface and the Foliage + Terrain Demo for baked scatter plus an auto-collidered terrain — the latter loads its whole level in one call with Scene.loadBlendScene, which composes instantiateScatter with terrain and static props.