Model Descriptors
A model descriptor is a JSON file in the models/ directory.
It defines a mesh — either loaded from an external asset or generated procedurally by the engine.
Scene nodes of type model reference descriptors by path (models://filename.json).
Top-level structure
The exact top-level fields depend on the model type:
| Field | gltf | glitter_primitive | glitter_skydome | Description |
|---|---|---|---|---|
description | optional | optional | optional | Human-readable label |
type | required | required | required | Model type string |
gltf / glitter_primitive / glitter_skydome | required | required | required | Type-specific block |
modifier | optional {} | — | optional {} | Reserved — always {} |
shaders | required | — | required | Shader package(s) for rendering |
textures | — | — | required | Texture bindings (skydome only) |
Model types
gltf
Loads a mesh from a glTF 2.0 file on disk.
{
"description": "Sponza atrium",
"type": "gltf",
"gltf": {
"package": "data/Sponza/glTF/Sponza.gltf"
},
"modifier": {},
"shaders": [
{ "name": "pbr.json", "format": "json-package" }
]
}
| Field | Description |
|---|---|
package | Path to the .gltf JSON file (relative to the model descriptor) |
binary | Path to a .glb binary alternative — both can coexist, engine picks one |
glitter_primitive
Engine-native procedural geometry. One or more primitive shapes share a set of
material references (materials:// URIs). Each element can assign individual
faces to different materials, enabling varied surfaces on a single draw call.
Geometry is generated at load time — no external mesh file needed.
Single-element example (cube with one material):
{
"description": "Playground cube — 1 × 1 × 1 m",
"type": "glitter_primitive",
"glitter_primitive": {
"materials": [
"materials://prototypes/orange_grid.json"
],
"elements": [
{
"shape": "cube",
"size": [1.0, 1.0, 1.0],
"offset": [0.0, 0.0, 0.0],
"face": { "material": 0, "uv_scale": 1.0 }
}
]
}
}
Multi-element example (staircase with 3 steps):
{
"description": "Staircase — 3 steps, 0.5 m rise",
"type": "glitter_primitive",
"glitter_primitive": {
"materials": [
"materials://prototypes/orange_stair.json",
"materials://prototypes/orange_stair_side.json"
],
"elements": [
{ "shape": "cube", "size": [3.5, 0.5, 4.2], "offset": [0.0, 0.25, 0.0],
"face": { "material": 0, "uv_scale": 1.0 } },
{ "shape": "cube", "size": [3.5, 0.5, 2.8], "offset": [0.0, 0.75, 0.7],
"face": { "material": 0, "uv_scale": 1.0 } },
{ "shape": "cube", "size": [3.5, 0.5, 1.4], "offset": [0.0, 1.25, 1.4],
"face": { "material": 0, "uv_scale": 1.0 } }
]
}
}
Per-face material example (pillar with a capped top):
{
"description": "Pillar — structural column with a metal cap",
"type": "glitter_primitive",
"glitter_primitive": {
"materials": [
"materials://prototypes/orange_grid.json",
"materials://prototypes/orange_metal.json"
],
"elements": [
{
"shape": "cube",
"size": [0.5, 2.0, 0.5],
"offset": [0.0, 1.0, 0.0],
"faces": [
{ "material": 0, "uv_scale": 1.0 },
{ "material": 0, "uv_scale": 1.0 },
{ "material": 1, "uv_scale": 1.0 },
{ "material": 0, "uv_scale": 1.0 },
{ "material": 0, "uv_scale": 1.0 },
{ "material": 0, "uv_scale": 1.0 }
]
}
]
}
}
glitter_primitive fields
| Field | Required | Description |
|---|---|---|
materials | yes | Array of materials:// URIs; each entry is a material descriptor |
elements | yes | One or more shape elements (all merged into a single draw call) |
Element fields
| Field | Required | Description |
|---|---|---|
shape | yes | Shape type — see table below |
size / radius / height / etc. | shape-dependent | Shape dimensions — see table below |
offset | no | [x, y, z] local translation of this element’s centre within the compound |
face | use one | Single material + UV scale applied to all faces: { "material": 0, "uv_scale": 1.0 } |
faces | use one | Per-face material array (cube: 6 entries, in −X/+X/+Y/−Y/−Z/+Z order) |
Shapes
shape | Extra fields | Description |
|---|---|---|
cube | size [x,y,z] | Axis-aligned box |
sphere | radius, rings, sectors | UV sphere |
plane | size [x,z], subdivisions | Flat XZ quad |
cylinder | radius, height, segments | Capped cylinder |
capsule | radius, height, segments | Capsule (cylinder + hemispherical caps) |
uv_scale (default 1.0) — world units per texture tile. 1.0 = one tile per metre; 2.0 = one tile every 2 m.
glitter_skydome
A UV sphere used as a sky backdrop, driven by texture and generation parameters.
{
"description": "Sun and clouds sky",
"type": "glitter_skydome",
"glitter_skydome": {
"rings": 40,
"sectors": 40
},
"textures": [
{ "name": "skydomes/skydome.png" }
],
"modifier": {},
"shaders": [
{ "name": "skydome.json", "format": "json-package" }
]
}
| Field | Description |
|---|---|
rings | Latitude subdivisions |
sectors | Longitude subdivisions |
Skydome descriptors are referenced by skydome scene nodes, not model nodes.
See the Node Types page for the scene-side format.
Shaders (glTF and skydome)
glTF and skydome descriptors declare a shader package at the descriptor level:
"shaders": [
{ "name": "pbr.json", "format": "json-package" }
]
| Field | Description |
|---|---|
name | Shader descriptor filename, resolved from the shaders:// resource folder |
format | Always "json-package" for the current pipeline |
For glitter_primitive models, the shader is declared inside the material descriptor,
not the model descriptor. See Material Descriptors.
Textures (skydome only)
Skydome descriptors bind a texture directly on the descriptor:
"textures": [
{ "name": "skydomes/skydome.png" }
]
| Field | Description |
|---|---|
name | Path relative to the textures:// resource root |
For glitter_primitive models, textures are declared inside the material descriptor.
For gltf models, textures are embedded in the glTF asset.
File naming conventions
| Prefix | Use |
|---|---|
| (none) | Named asset — e.g. s0001_sponza.json, m0001_damaged_helmet.json |
d | Sky / atmosphere descriptor — e.g. d001_sun_and_clouds.json |
pg_ | Playground geometry primitives |
kg_ | glTF material comparison models |
Relationship to scene nodes
A scene model node only holds a models:// reference, a transform, and
instance flags. All shape, material, and texture data lives in the descriptor.
This means the same descriptor can be instanced multiple times with different
transforms — e.g. pg_pillar.json placed five times in playground.json.
See Scene Format and Node Types for the full scene and node format.