Skip to content

Terrain descriptor (molen/terrain@2) ​

Streamed heightmap terrain: tiles, chunk grid, height range, layers, LOD, and residency budgets.

Example ​

json
{
  "format": "molen/terrain@2",
  "name": "island",
  "chunkSize": 128,
  "tileResolution": 129,
  "gridSize": [
    4,
    4
  ],
  "height": {
    "min": 0,
    "max": 200
  },
  "tiles": {
    "heightUrl": "tiles/h_{x}_{z}.png"
  },
  "layers": [
    {
      "name": "grass",
      "tiling": 8
    },
    {
      "name": "rock",
      "tiling": 6,
      "auto": {
        "slopeMin": 0.6
      }
    },
    {
      "name": "snow",
      "tiling": 4,
      "auto": {
        "heightMin": 150
      }
    }
  ]
}

JSON Schema ​

json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "description": "Terrain name."
    },
    "origin": {
      "default": [
        0,
        0
      ],
      "minItems": 2,
      "maxItems": 2,
      "type": "array",
      "items": {
        "type": "number"
      },
      "description": "World [x, z] in meters of the corner of chunk (0, 0); default [0, 0]."
    },
    "chunkSize": {
      "default": 128,
      "type": "number",
      "exclusiveMinimum": 0,
      "description": "Chunk edge length in meters (default 128)."
    },
    "tileResolution": {
      "default": 129,
      "type": "integer",
      "minimum": 2,
      "maximum": 1025,
      "description": "Height samples per chunk edge, borders shared with neighbors (default 129)."
    },
    "gridSize": {
      "default": [
        1,
        1
      ],
      "minItems": 2,
      "maxItems": 2,
      "type": "array",
      "items": {
        "type": "integer",
        "exclusiveMinimum": 0,
        "maximum": 9007199254740991
      },
      "description": "Number of chunks along [x, z]; default [1, 1]."
    },
    "height": {
      "type": "object",
      "properties": {
        "min": {
          "type": "number",
          "description": "Height in meters encoded by sample value 0."
        },
        "max": {
          "type": "number",
          "description": "Height in meters encoded by the maximum sample value."
        }
      },
      "required": [
        "min",
        "max"
      ],
      "additionalProperties": false,
      "description": "Height range in meters the PNG16 samples map onto."
    },
    "tiles": {
      "type": "object",
      "properties": {
        "heightUrl": {
          "type": "string",
          "minLength": 1,
          "description": "PNG16 height tile URL template with {x}/{z} chunk placeholders, e.g. 'tiles/h_{x}_{z}.png'; relative to the descriptor."
        },
        "splatUrl": {
          "type": "string",
          "minLength": 1,
          "description": "Optional splat-weight tile URL template with {x}/{z} placeholders."
        }
      },
      "required": [
        "heightUrl"
      ],
      "additionalProperties": false,
      "description": "Tile sources."
    },
    "layers": {
      "default": [],
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Layer name, e.g. 'grass' or 'rock'."
          },
          "materialRef": {
            "type": "string",
            "minLength": 1,
            "description": "Material reference for the layer surface (project material doc id)."
          },
          "color": {
            "type": "string",
            "pattern": "^#[0-9a-fA-F]{6}$",
            "description": "Flat '#rrggbb' color used for vertex-color splat banding (v1 shading)."
          },
          "tiling": {
            "default": 8,
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Texture repeats per chunk edge for the layer material (default 8)."
          },
          "auto": {
            "type": "object",
            "properties": {
              "heightMin": {
                "type": "number",
                "description": "Lowest height in meters at which the layer applies."
              },
              "heightMax": {
                "type": "number",
                "description": "Highest height in meters at which the layer applies."
              },
              "slopeMin": {
                "type": "number",
                "description": "Minimum slope 0..1 (0 = flat, 1 = vertical) at which the layer applies."
              },
              "slopeMax": {
                "type": "number",
                "description": "Maximum slope 0..1 (0 = flat, 1 = vertical) at which the layer applies."
              }
            },
            "additionalProperties": false,
            "description": "Automatic height/slope banding that selects where the layer paints."
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      },
      "description": "Surface layers painted by splat weights or auto banding, in order."
    },
    "lod": {
      "default": {
        "levels": 4,
        "distanceBands": [
          256,
          512,
          1024,
          2048
        ],
        "skirts": true
      },
      "type": "object",
      "properties": {
        "levels": {
          "default": 4,
          "type": "integer",
          "minimum": 1,
          "maximum": 6,
          "description": "Number of LOD levels (each halves the sample density; default 4)."
        },
        "distanceBands": {
          "default": [
            256,
            512,
            1024,
            2048
          ],
          "type": "array",
          "items": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "description": "Camera distances in meters (strictly increasing) beyond which each coarser LOD level applies."
        },
        "skirts": {
          "default": true,
          "type": "boolean",
          "description": "Add vertical skirts along chunk edges to hide LOD cracks (default true)."
        }
      },
      "additionalProperties": false,
      "description": "Level-of-detail settings."
    },
    "collision": {
      "default": {
        "enabled": false
      },
      "type": "object",
      "properties": {
        "enabled": {
          "default": false,
          "type": "boolean",
          "description": "Register the heightfield as the scene's ground/collision (default false)."
        }
      },
      "additionalProperties": false,
      "description": "Headless ground/collision settings."
    },
    "format": {
      "type": "string",
      "const": "molen/terrain@2",
      "description": "Format envelope; always 'molen/terrain@2'."
    },
    "metersPerUnit": {
      "type": "number",
      "exclusiveMinimum": 0,
      "description": "World meters per unit of the source projected space (origin/chunkSize are pre-multiplied); absent = 1."
    },
    "streaming": {
      "default": {
        "loadRadius": 3,
        "unloadRadius": 4,
        "maxConcurrentLoads": 4,
        "maxResidentTiles": 96
      },
      "type": "object",
      "properties": {
        "loadRadius": {
          "default": 3,
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "Radius around the camera, in chunks, that is kept resident (default 3)."
        },
        "unloadRadius": {
          "default": 4,
          "type": "number",
          "exclusiveMinimum": 0,
          "description": "Hysteresis radius in chunks; resident tiles outside it may be evicted (>= loadRadius; default 4)."
        },
        "maxConcurrentLoads": {
          "default": 4,
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 32,
          "description": "Maximum height-tile requests in flight at once (default 4)."
        },
        "maxResidentTiles": {
          "default": 96,
          "type": "integer",
          "exclusiveMinimum": 0,
          "maximum": 4096,
          "description": "Hard ceiling on decoded resident tiles and their meshes (default 96)."
        }
      },
      "additionalProperties": false,
      "description": "Tile residency budgets."
    }
  },
  "required": [
    "name",
    "height",
    "tiles",
    "format"
  ],
  "additionalProperties": false
}

37 guides · 36 schema formats · 41 API entry points · 10 samples. API, CLI and schema pages are generated from the shipped build.