GregOrigin - TerraDyne: Unified Runtime Terrain Sculpting with Real-Time Physics

[0.7.0] update, 2026-10-10 :man_climbing:

:sparkles: Added

  • Eight Paint Layers: Chunks paint eight layers (was four). Channels 0-3 stay where they were (WeightTexture, WeightData, InitialWeightMap); channels 4-7 live beside them in WeightTexture1, FTerraDyneChunkData::ExtraWeightData and UTerraDyneTileData::InitialWeightMap1, which stay empty while those layers are unused. Painting, normalization, undo, replication, saves and baked sets cover all eight. TerraDyne’s names for the channels are Grass, Rock, Soil, Snow, Sand, Gravel, Mud, ForestFloor; ATerraDyneManager::GetPaintLayerName gives each channel’s name (a converted Landscape’s own names when there are), and the tool panel shows a button for each channel the current material can show.
  • Landscape Materials On Chunks: A Landscape material can now paint TerraDyne chunks exactly as it paints the Landscape. A binding is a material instance of it that sets the parameters a Landscape sets on its components (weight textures and layer masks) for TerraDyne’s channels; a chunk whose material is a binding presents the surface the Landscape vertex factory gives its material (Landscape coordinates in UV 0-2, the weight textures in UV 3, tangents along +X). Layer blends (weight, alpha, height), LandscapeLayerCoords, LayerSample, LayerWeight, LayerSwitch and tangent-space normal maps work unchanged. Other materials keep the 0.6 surface.
  • Converting Eight-Layer Landscapes: The baker and the editor live import map up to eight layers (preferred names, then painted layers, then layers the material names but nothing paints yet) and bind the Landscape’s own material to them (MI_<Landscape>_TerraDyne, saved beside the tiles). When the material cannot run on a mesh, TerraDyne’s master shows its colour and normal textures instead. FTerraDyneLandscapeMigrationState::MaterialSource and MaterialNote record the outcome; the wizard reports layers beyond eight and fallbacks.
  • Eight-Layer Terrain Material: M_TerraDyne_Terrain is a Landscape material built from standard nodes: one MF_TerraDyne_TerrainLayer call per layer (near and far samples against tiling, tint), height-blended LandscapeLayerBlends, steep ground to rock unless soil is painted, broad colour variation. MI_TerraDyne_Terrain is its binding and the default for new conversions and the showcases. Layers 4-7 use four new Poly Haven CC0 sets at 2048 px (Coast Sand 04, Gravel Ground 01, Mud Forest, Forest Ground 04).
  • Building Terrain Materials: Content Browser: right-click a material > TerraDyne: Create Terrain Material. Python/Blueprint: UTerraDyneEditorLibrary::CreateTerrainMaterialBinding, CreateFallbackTerrainMaterial, GetLandscapeMaterialLayerNames; C++: TerraDyneMaterialBinding, UTerraDyneEditorLibrary::CreateLandscapeFromData.
  • Eight-Layer Showcase: The authored showcase Landscape is painted with all eight layers using M_TerraDyne_Terrain, and its bake binds that material to the chunks.
  • Docs: Docs/TerrainMaterials.md.
  • Tests: 28 new automation tests (74 in all): channel mapping, chunk channels, codec schema 2 and schema 1 compatibility, baked tiles, undo and names over eight layers, bindings (static parameters, compilation, layer names, rebinding in place, paint names), Landscape and mesh surfaces (UVs, tangents, switching, edits, editor worlds), the shipped master, fallback, eight- and nine-layer bakes, fallback and plain-material bakes, editor library calls, and rendering: a bound material on both weight textures, and fidelity — a Landscape and its converted chunks rendered from above with the same material match exactly for layers and Landscape coordinates (mean difference 0.00/255) and within 1.4/255 (99th percentile) for the tangent basis.

:bug: Fixed

  • Editor-World Material Switch: Assigning a bound material to existing chunks in the editor kept their old mesh layout until play (editor worlds do not tick); they are now laid out again at once.
  • Live Import Had No Weight Textures: Chunks created by the editor live import never began play, so they had no weight textures and their material read nothing (0.6 materials showed one layer; a bound Landscape material read every layer at full weight). The import now initializes each chunk at its component’s resolution.

:hammer_and_wrench: Changed

  • Adopting the Landscape’s material is on by default and now means binding it (it was refused for any material with Landscape nodes). A material without Landscape nodes is still used as it is.

  • Defaults: PreferredLayerOrder names all eight channels; the wizard’s conversion and the showcase game mode use MI_TerraDyne_Terrain (was M_TerraDyne_Terrain4K, which stays for existing worlds).

  • Formats: chunk packet schema 2 (schema 1 still decodes), save format 3 (formats 0-2 still load).

  • Version 0.7.0 (700).

  • Showcase: rebuilt with eight layers (64 tiles, 932 rocks, MaterialSource Bound); the Landscape and its chunks captured from four cameras show the same layers in the same places.

:warning: Known Limitations

  • A bound material evaluates every layer it binds on every pixel (a Landscape compiles only the layers each component uses).
  • Lighting: with the same material inputs, Lumen lights chunks slightly darker than the Landscape (less sky light).
  • Not bound: Runtime Virtual Texture output, landscape.MobileWeightTextureArray, and Material Layers containing Landscape nodes; LandscapeGrassOutput is ignored on chunks. A live-import binding is transient and does not replicate; bake for multiplayer.