World kit: exotic worlds

One ready preset per exotic world, stitched from the analysed kits. Everything is copied from kits/skies.json, materials.json, foliage.json and rocks.json; the same data as JSON is in kits/worlds.json. Paths are relative to ~/code/assets. Re-run node tools/kits/build-worlds.mjs after a kit changes.

For the game: read presets programmatically from ../assets/kits/worlds.json (worlds[i].sky for setEnv, terrain.a/b for buildTerrain layers with tiles = SIZE / repeat_m, foliage.set.layers and rocks.boulder_field / mountain_chunks for buildForest). Per-kit detail pages: ../assets/kits/skies.html, materials.html, foliage.html, rocks.html.

Dune desert (Tatooine / Jakku)

polyhaven-aarfontein_pan
polyhaven-aarfontein_pan dead-flat salt pan, low sun, nothing near the camera
fog #a7aca1 · exposure 0.85 · skyIntensity 0.163 · envMul 0.14 · skyFade [-0.02, 0.06]
sunDir [0.804, 0.059, 0.591] (az/el [126.3, 3.4]) · foreground clear 1
hdri/polyhaven-aarfontein_pan/aarfontein_pan_2k.hdr
polyhaven-quarry_01
polyhaven-quarry_01 #a2aca7
polyhaven-goegap
polyhaven-goegap #7fabf1
polyhaven-syferfontein_18d_clear
polyhaven-syferfontein_18d_clear #91adc6

Terrain

textures/ground/ambientcg-Ground093B
A ground: ambientcg-Ground093B @ 10 m
textures/rock/polyhaven-worn_rock_natural_01
B slope: polyhaven-worn_rock_natural_01 @ 14 m
blend by:'slope', lo 0.35, hi 0.6 · tint a 0xfff0d8, b 0xffe6c8

Dunes are gentle: lower lo/hi so rock only shows on real scarps. Pale sand is bright (L 0.73): exposure down a touch.

Foliage: desert-succulents

Photoscanned cacti (lite) as spires, Poly Haven dead quiver trunks, low-poly yuccas and sansevieria, Namaqualand flowers near the camera. · ~2.6M tris

layercountcollidemodels (height m)
spires80yesferocactus-acanthodes-lite.glb (6), pipe-organ-cactus__8rSaubjT4uM__poly-by-google__cc-by.glb (7), Cactus_2.glb (5)
hero12yesdead_quiver_trunk.gltf (4)
understory150large-yucca__flCC5m8pPS.glb (3), sansevieria-plant__2zmROipXIE.glb (1.2), ferocactus-wislizeni-lite.glb (1.2), dead_quiver_branch_01.glb (0.5)
near-flowers40flower_gazania.glb (0.25), flower_ursinia.glb (0.25), crystalline_iceplant.gltf (0.2)

Rocks: desert-sandstone

warm scans, no tint needed; [1.05,0.98,0.9] matches the canyon HDRI

boulder field: 10 kinds × 220 · mountain chunks: 3 kinds × 40

Cliff walls (closed, solidified scans)

solidified Poly Haven cliff scans: closed, so they sink and yaw without holes, but only the scan side is photographic. buildForest yaws at random: place walls in overlapping runs along the rim (sample()) so neighbours hide each other's darker synthetic backs, and keep them >= 150 m from the flight line. tint = red-canyon values; swap with tint_by_world

canyon walls: 5 kinds × 24 · mesa rims: 6 kinds × 40 · tint for this world {"sandstone":[1.12,1.02,0.88],"limestone":[1.2,1.02,0.82],"granite":[1.15,1,0.85]}
JSON preset (kits/worlds.jsondune-desert)
{
 "sky": {
  "hdri": "hdri/polyhaven-aarfontein_pan/aarfontein_pan_2k.hdr",
  "fog_hex": "#a7aca1",
  "exposure": 0.85,
  "skyIntensity": 0.163,
  "envMul": 0.14,
  "skyFade": [
   -0.02,
   0.06
  ],
  "sunDir": [
   0.8043,
   0.0585,
   0.5914
  ]
 },
 "terrain": {
  "a": {
   "folder": "textures/ground/ambientcg-Ground093B",
   "files": {
    "map": "Ground093B_2K-JPG_Color.jpg",
    "normalMap": "Ground093B_2K-JPG_NormalGL.jpg",
    "roughnessMap": "Ground093B_2K-JPG_Roughness.jpg"
   }
  },
  "b": {
   "folder": "textures/rock/polyhaven-worn_rock_natural_01",
   "files": {
    "map": "worn_rock_natural_01_diff_2k.jpg",
    "normalMap": "worn_rock_natural_01_nor_gl_2k.jpg",
    "roughnessMap": "worn_rock_natural_01_rough_2k.jpg"
   }
  },
  "a_repeat_m": 10,
  "b_repeat_m": 14,
  "by": "slope",
  "lo": 0.35,
  "hi": 0.6,
  "invert": false
 },
 "water": null,
 "foliage_set": "desert-succulents",
 "rock_set": "desert-sandstone"
}

Red canyon (Geonosis)

polyhaven-drakensberg_solitary_mountain
polyhaven-drakensberg_solitary_mountain summit shot, mesa + ranges, already proven on the canyon world
fog #97acc4 · exposure 0.72 · skyIntensity 0.506 · envMul 0.463 · skyFade [-0.06, -0.008]
sunDir [0.674, 0.551, 0.492] (az/el [126.1, 33.5]) · foreground clear 0.9
hdri/polyhaven-drakensberg_solitary_mountain/drakensberg_solitary_mountain_2k.hdr
polyhaven-toposcope_sunset
polyhaven-toposcope_sunset #a4abaf
polyhaven-fouriesburg_mountain_midday
polyhaven-fouriesburg_mountain_midday #a2abb5
polyhaven-golden_gate_hills
polyhaven-golden_gate_hills #93aebe

Terrain

textures/ground/polyhaven-red_sand
A ground: polyhaven-red_sand @ 8 m
textures/rock/polyhaven-cliff_side
B slope: polyhaven-cliff_side @ 12 m
blend by:'slope', lo 0.45, hi 0.7 · tint a 0xffffff, b 0xffe0cc (warmer strata)

cliff_side has horizontal strata: map UVs world-XZ as terrain.js does, strata then run sideways on walls (fine at 12 m).

Foliage: desert-succulents

Photoscanned cacti (lite) as spires, Poly Haven dead quiver trunks, low-poly yuccas and sansevieria, Namaqualand flowers near the camera. · ~2.6M tris

layercountcollidemodels (height m)
spires80yesferocactus-acanthodes-lite.glb (6), pipe-organ-cactus__8rSaubjT4uM__poly-by-google__cc-by.glb (7), Cactus_2.glb (5)
hero12yesdead_quiver_trunk.gltf (4)
understory150large-yucca__flCC5m8pPS.glb (3), sansevieria-plant__2zmROipXIE.glb (1.2), ferocactus-wislizeni-lite.glb (1.2), dead_quiver_branch_01.glb (0.5)
near-flowers40flower_gazania.glb (0.25), flower_ursinia.glb (0.25), crystalline_iceplant.gltf (0.2)

Rocks: desert-sandstone

warm scans, no tint needed; [1.05,0.98,0.9] matches the canyon HDRI

boulder field: 10 kinds × 220 · mountain chunks: 3 kinds × 40

Cliff walls (closed, solidified scans)

solidified Poly Haven cliff scans: closed, so they sink and yaw without holes, but only the scan side is photographic. buildForest yaws at random: place walls in overlapping runs along the rim (sample()) so neighbours hide each other's darker synthetic backs, and keep them >= 150 m from the flight line. tint = red-canyon values; swap with tint_by_world

canyon walls: 5 kinds × 24 · mesa rims: 6 kinds × 40 · tint for this world {"sandstone":[1.05,0.98,0.9],"limestone":[1.1,0.92,0.78],"granite":[1.08,0.95,0.84]}
JSON preset (kits/worlds.jsonred-canyon)
{
 "sky": {
  "hdri": "hdri/polyhaven-drakensberg_solitary_mountain/drakensberg_solitary_mountain_2k.hdr",
  "fog_hex": "#97acc4",
  "exposure": 0.72,
  "skyIntensity": 0.506,
  "envMul": 0.463,
  "skyFade": [
   -0.06,
   -0.008
  ],
  "sunDir": [
   0.6741,
   0.5513,
   0.4916
  ]
 },
 "terrain": {
  "a": {
   "folder": "textures/ground/polyhaven-red_sand",
   "files": {
    "map": "red_sand_diff_2k.jpg",
    "normalMap": "red_sand_nor_gl_2k.jpg",
    "roughnessMap": "red_sand_rough_2k.jpg"
   }
  },
  "b": {
   "folder": "textures/rock/polyhaven-cliff_side",
   "files": {
    "map": "cliff_side_diff_2k.jpg",
    "normalMap": "cliff_side_nor_gl_2k.jpg",
    "roughnessMap": "cliff_side_rough_2k.jpg"
   }
  },
  "a_repeat_m": 8,
  "b_repeat_m": 12,
  "by": "slope",
  "lo": 0.45,
  "hi": 0.7,
  "invert": false
 },
 "water": null,
 "foliage_set": "desert-succulents",
 "rock_set": "desert-sandstone"
}

Volcanic (Mustafar / Sullust)

ambientcg-EveningSkyHDRI030B
ambientcg-EveningSkyHDRI030B dark storm deck with a burning sunset band
fog #b2a994 · exposure 0.85 · skyIntensity 0.361 · envMul 0.867 · skyFade [-0.02, 0.1]
sunDir [0.998, 0.041, -0.039] (az/el [87.8, 2.4]) · foreground clear 1
hdri/ambientcg-EveningSkyHDRI030B/EveningSkyHDRI030B_2k.hdr
polyhaven-belfast_sunset_puresky
polyhaven-belfast_sunset_puresky #c5a384
polyhaven-rosendal_park_sunset_puresky
polyhaven-rosendal_park_sunset_puresky #d09d97

Terrain

textures/rock/polyhaven-dark_rock_02
A ground: polyhaven-dark_rock_02 @ 12 m
textures/ground/ambientcg-Lava001
B high/low: ambientcg-Lava001 @ 20 m
blend by:'height', lo -5, hi 5, invert · tint a 0xd8d0c8, emissive 0xff6a2a, emissiveIntensity 2.5

Lava must be layer B (terrain.js only emits on B). by height + invert = lava in the low ground; set lo/hi to the lava level +-5 m.

Foliage: volcanic-dead

Bone-white and charred dead forest on lava: EZ-Tree dead tree, Quaternius dead trees, Space Kit lava trees, photoscan trunks and roots (lite). · ~2.3M tris

layercountcollidemodels (height m)
canopy300yeseztree-alien-dead-1.glb (22), CommonTree_Dead_1.glb (14), Willow_Dead_2.glb (12), Tree_Lava_1.glb (30)
debris40dead_tree_trunk-lite.glb (2), root_cluster_02-lite.glb (3), pine_roots-lite.glb (2)

Rocks: volcanic-basalt

multiply tints darken and cool the scans; vesicular ShareTextures stones become scoria

boulder field: 8 kinds × 180 · mountain chunks: 3 kinds × 30

Cliff walls (closed, solidified scans)

solidified Poly Haven cliff scans: closed, so they sink and yaw without holes, but only the scan side is photographic. buildForest yaws at random: place walls in overlapping runs along the rim (sample()) so neighbours hide each other's darker synthetic backs, and keep them >= 150 m from the flight line. tint = red-canyon values; swap with tint_by_world

canyon walls: 5 kinds × 24 · mesa rims: 6 kinds × 40 · tint for this world {"sandstone":[0.3,0.27,0.27],"limestone":[0.34,0.3,0.3],"granite":[0.32,0.29,0.29]}
JSON preset (kits/worlds.jsonvolcanic)
{
 "sky": {
  "hdri": "hdri/ambientcg-EveningSkyHDRI030B/EveningSkyHDRI030B_2k.hdr",
  "fog_hex": "#b2a994",
  "exposure": 0.85,
  "skyIntensity": 0.361,
  "envMul": 0.867,
  "skyFade": [
   -0.02,
   0.1
  ],
  "sunDir": [
   0.9984,
   0.0414,
   -0.0391
  ]
 },
 "terrain": {
  "a": {
   "folder": "textures/rock/polyhaven-dark_rock_02",
   "files": {
    "map": "dark_rock_02_diff_2k.jpg",
    "normalMap": "dark_rock_02_nor_gl_2k.jpg",
    "roughnessMap": "dark_rock_02_rough_2k.jpg"
   }
  },
  "b": {
   "folder": "textures/ground/ambientcg-Lava001",
   "files": {
    "map": "Lava001_2K-JPG_Color.jpg",
    "normalMap": "Lava001_2K-JPG_NormalGL.jpg",
    "roughnessMap": "Lava001_2K-JPG_Roughness.jpg",
    "emissiveMap": "Lava001_2K-JPG_Emission.jpg"
   }
  },
  "a_repeat_m": 12,
  "b_repeat_m": 20,
  "by": "height",
  "lo": -5,
  "hi": 5,
  "invert": true
 },
 "water": null,
 "foliage_set": "volcanic-dead",
 "rock_set": "volcanic-basalt"
}

Ice world (Hoth)

polyhaven-snow_field_2
polyhaven-snow_field_2 flat overcast snow field (Hoth)
fog #a9aaaa · exposure 0.9 · skyIntensity 0.503 · envMul 0.159 · skyFade [-0.02, 0.06]
sunDir [0.758, 0.155, 0.633] (az/el [129.9, 8.9]) · foreground clear 0.95
hdri/polyhaven-snow_field_2/snow_field_2_2k.hdr
polyhaven-winter_lake_01
polyhaven-winter_lake_01 #afa9a1
polyhaven-passendorf_snow
polyhaven-passendorf_snow #84addd
polyhaven-horn-koppe_snow
polyhaven-horn-koppe_snow #92accd

Terrain

textures/ground/polyhaven-snow_01
A ground: polyhaven-snow_01 @ 8 m
textures/rock/ambientcg-Rock017
B slope: ambientcg-Rock017 @ 16 m
blend by:'slope', lo 0.5, hi 0.75 · tint a new THREE.Color(1.15, 1.17, 1.22) (reads white from altitude, as Hoth), b 0xdfe6ee

For snow on top of rock by altitude instead: a = rock, b = snow, by height.

Foliage: alpine

EZ-Tree pines near, Quaternius snow pines far. · ~2.6M tris

layercountcollidemodels (height m)
canopy60yeseztree-pine-1.glb (20), eztree-pine-2.glb (30)
far700yesPineTree_Snow_1.glb (18), PineTree_Snow_2.glb (22), PineTree_Snow_3.glb (20)

Rocks: ice-polished-granite

tints above 1 lift and cool the scans so they do not read as black silhouettes on snow (same as the current Hoth set)

boulder field: 7 kinds × 200 · mountain chunks: 4 kinds × 35

Cliff walls (closed, solidified scans)

solidified Poly Haven cliff scans: closed, so they sink and yaw without holes, but only the scan side is photographic. buildForest yaws at random: place walls in overlapping runs along the rim (sample()) so neighbours hide each other's darker synthetic backs, and keep them >= 150 m from the flight line. tint = red-canyon values; swap with tint_by_world

canyon walls: 5 kinds × 24 · mesa rims: 6 kinds × 40 · tint for this world {"sandstone":[1.2,1.25,1.4],"limestone":[1.2,1.25,1.38],"granite":[1.2,1.25,1.4]}
JSON preset (kits/worlds.jsonice-world)
{
 "sky": {
  "hdri": "hdri/polyhaven-snow_field_2/snow_field_2_2k.hdr",
  "fog_hex": "#a9aaaa",
  "exposure": 0.9,
  "skyIntensity": 0.503,
  "envMul": 0.159,
  "skyFade": [
   -0.02,
   0.06
  ],
  "sunDir": [
   0.7582,
   0.1555,
   0.6332
  ]
 },
 "terrain": {
  "a": {
   "folder": "textures/ground/polyhaven-snow_01",
   "files": {
    "map": "snow_01_diff_2k.jpg",
    "normalMap": "snow_01_nor_gl_2k.jpg",
    "roughnessMap": "snow_01_rough_2k.jpg"
   }
  },
  "b": {
   "folder": "textures/rock/ambientcg-Rock017",
   "files": {
    "map": "Rock017_2K-JPG_Color.jpg",
    "normalMap": "Rock017_2K-JPG_NormalGL.jpg",
    "roughnessMap": "Rock017_2K-JPG_Roughness.jpg"
   }
  },
  "a_repeat_m": 8,
  "b_repeat_m": 16,
  "by": "slope",
  "lo": 0.5,
  "hi": 0.75,
  "invert": false
 },
 "water": null,
 "foliage_set": "alpine",
 "rock_set": "ice-polished-granite"
}

Jungle (Yavin IV / Endor)

polyhaven-kloofendal_28d_misty_puresky
polyhaven-kloofendal_28d_misty_puresky bright sun through mist: steamy jungle
fog #aaa9aa · exposure 0.9 · skyIntensity 0.329 · envMul 0.107 · skyFade [-0.02, 0.1]
sunDir [0.863, 0.477, -0.165] (az/el [79.2, 28.5]) · foreground clear 1
hdri/polyhaven-kloofendal_28d_misty_puresky/kloofendal_28d_misty_puresky_2k.hdr
polyhaven-kloofendal_misty_morning_puresky
polyhaven-kloofendal_misty_morning_puresky #aaa9ad
polyhaven-kloofendal_48d_partly_cloudy_puresky
polyhaven-kloofendal_48d_partly_cloudy_puresky #a4aaba

Terrain

textures/ground/ambientcg-Ground037
A ground: ambientcg-Ground037 @ 6 m
textures/rock/polyhaven-mossy_rock
B slope: polyhaven-mossy_rock @ 10 m
blend by:'slope', lo 0.45, hi 0.7 · tint a 0xe8f0d8 (less yellow), b 0xffffff

From the air a jungle floor is mostly hidden by trees; spend the texture budget on the cliffs.

Water

normals
Water.js · normals @ 12 m · waterColor 0x1d3b2e

Foliage: canopy-from-above

Dense jungle canopy for the Yavin flight band (200-500 m). A roof of overlapping 64 m crown tiles lifted to ~30 m, 14 m impostor crowns rising through it, and real 3D EZ-Tree crown clusters only where the camera comes low (temple ring, trail edges). Counts are for buildForest area 3200 (a 6.4 km square, 41 km2) at full density; per_km2 is given per layer. Keep every layer out of the speeder trail corridor and the temple clearing (keepOut). Optional far layer: canopy-roof-a-256m.glb planes (or the tex/canopy-roof-a maps on a terrain mesh offset +30 m) under the fog. · ~2.5M tris

layercountcollidemodels (height m)
roof14350canopy-tile-64-a.glb (3.58), canopy-tile-64-b.glb (2.97), canopy-tile-64-c.glb (3.17)
emergent-crowns8200canopy-crown-green.glb (34), canopy-crown-olive.glb (34), canopy-crown-dark.glb (34), canopy-crown-flowering.glb (34)
near-clusters120yescanopy-cluster-7-a.glb (30), canopy-cluster-9-dense.glb (22), canopy-cluster-emergent.glb (40)

Other sets that fit: jungle-realistic, palm-pbr, alien-jungle, temperate-realistic

Rocks: mossy-jungle

moss is in the albedo: no tint; keep them small and half-buried among the photo trees

boulder field: 13 kinds × 200 · mountain chunks: 2 kinds × 20
JSON preset (kits/worlds.jsonjungle)
{
 "sky": {
  "hdri": "hdri/polyhaven-kloofendal_28d_misty_puresky/kloofendal_28d_misty_puresky_2k.hdr",
  "fog_hex": "#aaa9aa",
  "exposure": 0.9,
  "skyIntensity": 0.329,
  "envMul": 0.107,
  "skyFade": [
   -0.02,
   0.1
  ],
  "sunDir": [
   0.8631,
   0.4772,
   -0.1653
  ]
 },
 "terrain": {
  "a": {
   "folder": "textures/ground/ambientcg-Ground037",
   "files": {
    "map": "Ground037_2K-JPG_Color.jpg",
    "normalMap": "Ground037_2K-JPG_NormalGL.jpg",
    "roughnessMap": "Ground037_2K-JPG_Roughness.jpg"
   }
  },
  "b": {
   "folder": "textures/rock/polyhaven-mossy_rock",
   "files": {
    "map": "mossy_rock_diff_2k.jpg",
    "normalMap": "mossy_rock_nor_gl_2k.jpg",
    "roughnessMap": "mossy_rock_rough_2k.jpg"
   }
  },
  "a_repeat_m": 6,
  "b_repeat_m": 10,
  "by": "slope",
  "lo": 0.45,
  "hi": 0.7,
  "invert": false
 },
 "water": {
  "recipe": "Water.js",
  "normals": "textures/water/generated-water-calm/water-calm_normal_gl.jpg",
  "size_m": 12,
  "waterColor": "0x1d3b2e"
 },
 "foliage_set": "canopy-from-above",
 "rock_set": "mossy-jungle"
}

Coral coast (Scarif)

polyhaven-aristea_wreck_puresky
polyhaven-aristea_wreck_puresky sea-level sky with broken high cloud
fog #a3aab8 · exposure 0.85 · skyIntensity 0.574 · envMul 0.109 · skyFade [-0.02, 0.1]
sunDir [0.502, 0.744, 0.442] (az/el [131.4, 48]) · foreground clear 1
hdri/polyhaven-aristea_wreck_puresky/aristea_wreck_puresky_2k.hdr
polyhaven-umhlanga_sunrise
polyhaven-umhlanga_sunrise #9bacbe
polyhaven-table_mountain_1_puresky
polyhaven-table_mountain_1_puresky #99acbb

Terrain

textures/ground/polyhaven-coast_sand_01
A ground: polyhaven-coast_sand_01 @ 30 m
textures/rock/polyhaven-seaside_rock
B slope: polyhaven-seaside_rock @ 10 m
blend by:'slope', lo 0.45, hi 0.7 · tint a 0xfff6e6, b new THREE.Color(1.2, 1.15, 1.1) (seaside_rock is dark, L 0.25)

coast_sand_01 is an aerial scan (15 m real): best from flight altitude. Put the water plane just above the sand/rock transition.

Water

normals
Water.js · normals @ 30 m · waterColor 0x0e3a3c
caustics
seabed caustics
foam
shore foam

Foliage: alien-reef-forest

Smithsonian coral scans (lite, 20k tris) scaled 100-400x into a dry-seabed forest; CC-BY kelp as tall fronds. · ~2.3M tris

layercountcollidemodels (height m)
canopy60yesacropora-cervicornis-lite.glb (45), madrepora-hyacinthus-lite.glb (35), paragorgia-arborea-lite.glb (50), stylaster-sanguineus-lite.glb (30)
understory25yesdiploria-labyrinthiformis-lite.glb (12), fungia-crassa-lite.glb (10)
fronds300kelp__4cFllH6Iazk__poly-by-google__cc-by.glb (20), kelp__3VhttTFyADO__christopher-f__cc-by.glb (15)

Other sets that fit: jungle-realistic, palm-pbr

Rocks: mossy-jungle

moss is in the albedo: no tint; keep them small and half-buried among the photo trees

boulder field: 13 kinds × 200 · mountain chunks: 2 kinds × 20
JSON preset (kits/worlds.jsoncoral-coast)
{
 "sky": {
  "hdri": "hdri/polyhaven-aristea_wreck_puresky/aristea_wreck_puresky_2k.hdr",
  "fog_hex": "#a3aab8",
  "exposure": 0.85,
  "skyIntensity": 0.574,
  "envMul": 0.109,
  "skyFade": [
   -0.02,
   0.1
  ],
  "sunDir": [
   0.5018,
   0.7437,
   0.4417
  ]
 },
 "terrain": {
  "a": {
   "folder": "textures/ground/polyhaven-coast_sand_01",
   "files": {
    "map": "coast_sand_01_diff_2k.jpg",
    "normalMap": "coast_sand_01_nor_gl_2k.jpg",
    "roughnessMap": "coast_sand_01_rough_2k.jpg"
   }
  },
  "b": {
   "folder": "textures/rock/polyhaven-seaside_rock",
   "files": {
    "map": "seaside_rock_diff_2k.jpg",
    "normalMap": "seaside_rock_nor_gl_2k.jpg",
    "roughnessMap": "seaside_rock_rough_2k.jpg"
   }
  },
  "a_repeat_m": 30,
  "b_repeat_m": 10,
  "by": "slope",
  "lo": 0.45,
  "hi": 0.7,
  "invert": false
 },
 "water": {
  "recipe": "Water.js",
  "normals": "textures/water/generated-water-choppy/water-choppy_normal_gl.jpg",
  "size_m": 30,
  "waterColor": "0x0e3a3c",
  "caustics": "textures/water/generated-water-caustics/water-caustics.jpg",
  "foam": "textures/water/generated-water-foam/water-foam.jpg"
 },
 "foliage_set": "alien-reef-forest",
 "rock_set": "mossy-jungle"
}

Toxic swamp (Dagobah)

ambientcg-DaySkyHDRI068B
ambientcg-DaySkyHDRI068B black rain cell over a grey plain: tint yellow-green
fog #a6aba7 · exposure 0.85 · skyIntensity 1.7 · envMul 0.517 · skyFade [-0.02, 0.1]
sunDir [-0.484, 0.658, 0.577] (az/el [220, 41.1]) · foreground clear 1
hdri/ambientcg-DaySkyHDRI068B/DaySkyHDRI068B_2k.hdr
polyhaven-mud_road_puresky
polyhaven-mud_road_puresky #a9a9af
ambientcg-DaySkyHDRI053B
ambientcg-DaySkyHDRI053B #a8aba2

Terrain

textures/ground/polyhaven-mud_forest
A ground: polyhaven-mud_forest @ 4.7 m
textures/rock/ambientcg-Rock059
B slope: ambientcg-Rock059 @ 8 m
blend by:'slope', lo 0.45, hi 0.7

Water

normals
Water.js · normals @ 45 m · waterColor 0x0b3d14

Foliage: swamp

Weeping trees, Quaternius willows, lily pads and photoscan roots. · ~2.6M tris

layercountcollidemodels (height m)
canopy40yeseztree-alien-weeping-1.glb (22)
mid600yesWillow_1.glb (12), Willow_3.glb (11), Willow_Dead_1.glb (10)
water500Lilypad.glb (1.2), single_root-lite.glb (1.5)

Other sets that fit: mushroom-glow

Rocks: mossy-jungle

moss is in the albedo: no tint; keep them small and half-buried among the photo trees

boulder field: 13 kinds × 200 · mountain chunks: 2 kinds × 20
JSON preset (kits/worlds.jsontoxic-swamp)
{
 "sky": {
  "hdri": "hdri/ambientcg-DaySkyHDRI068B/DaySkyHDRI068B_2k.hdr",
  "fog_hex": "#a6aba7",
  "exposure": 0.85,
  "skyIntensity": 1.7,
  "envMul": 0.517,
  "skyFade": [
   -0.02,
   0.1
  ],
  "sunDir": [
   -0.4843,
   0.6578,
   0.5769
  ]
 },
 "terrain": {
  "a": {
   "folder": "textures/ground/polyhaven-mud_forest",
   "files": {
    "map": "mud_forest_diff_2k.jpg",
    "normalMap": "mud_forest_nor_gl_2k.jpg",
    "roughnessMap": "mud_forest_rough_2k.jpg"
   }
  },
  "b": {
   "folder": "textures/rock/ambientcg-Rock059",
   "files": {
    "map": "Rock059_2K-JPG_Color.jpg",
    "normalMap": "Rock059_2K-JPG_NormalGL.jpg",
    "roughnessMap": "Rock059_2K-JPG_Roughness.jpg"
   }
  },
  "a_repeat_m": 4.7,
  "b_repeat_m": 8,
  "by": "slope",
  "lo": 0.45,
  "hi": 0.7,
  "invert": false
 },
 "water": {
  "recipe": "Water.js",
  "normals": "textures/water/generated-water-viscous/water-viscous_normal_gl.jpg",
  "size_m": 45,
  "waterColor": "0x0b3d14"
 },
 "foliage_set": "swamp",
 "rock_set": "mossy-jungle"
}

Alien crystal world

ambientcg-NightSkyHDRI006
ambientcg-NightSkyHDRI006 pink/green aurora curtains with a bright moon
fog #43454d · exposure 1 · skyIntensity 1.431 · envMul 0.771 · skyFade [-0.02, 0.1]
sunDir [0.809, 0.588, 0] (az/el [90, 36]) · foreground clear 1
hdri/ambientcg-NightSkyHDRI006/NightSkyHDRI006_2k.hdr
polyhaven-qwantani_dusk_2_puresky
polyhaven-qwantani_dusk_2_puresky #c79fa9
ambientcg-MorningSkyHDRI009B
ambientcg-MorningSkyHDRI009B #b8a69e

Terrain

textures/alien/texturecan-red-crystal-ground
A ground: texturecan-red-crystal-ground @ 5 m
textures/alien/ambientcg-Onyx013
B slope: ambientcg-Onyx013 @ 14 m
blend by:'slope', lo 0.4, hi 0.65 · tint a 0xffffff, b 0xb8a8ff (purple obsidian)

Onyx013 is a polished-stone set (1k, flat normal): raise roughness via material.roughness multiply if it looks wet.

Foliage: crystal-garden

Low-poly crystals and Space Kit spike trees as a mineral forest. · ~1.2M tris

layercountcollidemodels (height m)
spires250yesbig-crystal__pf5lzmgr2J.glb (30), crystal__3saqXqoOti.glb (20), Tree_Spikes_1.glb (40)
groundcover1500crystal__dxCmHfpqc5.glb (3), sansevieria-plant__V1yPemXoOW.glb (4)

Other sets that fit: mushroom-glow, alien-jungle

Rocks: volcanic-basalt

multiply tints darken and cool the scans; vesicular ShareTextures stones become scoria

boulder field: 8 kinds × 180 · mountain chunks: 3 kinds × 30

Cliff walls (closed, solidified scans)

solidified Poly Haven cliff scans: closed, so they sink and yaw without holes, but only the scan side is photographic. buildForest yaws at random: place walls in overlapping runs along the rim (sample()) so neighbours hide each other's darker synthetic backs, and keep them >= 150 m from the flight line. tint = red-canyon values; swap with tint_by_world

canyon walls: 5 kinds × 24 · mesa rims: 6 kinds × 40
JSON preset (kits/worlds.jsonalien-crystal)
{
 "sky": {
  "hdri": "hdri/ambientcg-NightSkyHDRI006/NightSkyHDRI006_2k.hdr",
  "fog_hex": "#43454d",
  "exposure": 1,
  "skyIntensity": 1.431,
  "envMul": 0.771,
  "skyFade": [
   -0.02,
   0.1
  ],
  "sunDir": [
   0.809,
   0.5878,
   -0.0002
  ]
 },
 "terrain": {
  "a": {
   "folder": "textures/alien/texturecan-red-crystal-ground",
   "files": {
    "map": "red-crystal-ground_color_2k.jpg",
    "normalMap": "red-crystal-ground_normal_gl_2k.jpg",
    "roughnessMap": "red-crystal-ground_roughness_2k.jpg"
   }
  },
  "b": {
   "folder": "textures/alien/ambientcg-Onyx013",
   "files": {
    "map": "Onyx013_1K-JPG_Color.jpg",
    "normalMap": "Onyx013_1K-JPG_NormalGL.jpg",
    "roughnessMap": "Onyx013_1K-JPG_Roughness.jpg"
   }
  },
  "a_repeat_m": 5,
  "b_repeat_m": 14,
  "by": "slope",
  "lo": 0.4,
  "hi": 0.65,
  "invert": false
 },
 "water": null,
 "foliage_set": "crystal-garden",
 "rock_set": "volcanic-basalt"
}

Moon / asteroid

ambientcg-NightSkyHDRI009
ambientcg-NightSkyHDRI009 colourful Milky Way arch, full sphere
fog #42454e · exposure 1 · skyIntensity 1.268 · envMul 1.088 · skyFade [-0.02, 0.1]
sunDir [0.629, 0.772, -0.086] (az/el [82.2, 50.6]) · foreground clear 1
hdri/ambientcg-NightSkyHDRI009/NightSkyHDRI009_2k.hdr
ambientcg-NightSkyHDRI008
ambientcg-NightSkyHDRI008 #41464c
opengameart-space-skyboxes-1-westbeam-blue
opengameart-space-skyboxes-1-westbeam-blue #2a4158

Terrain

textures/ground/polyhaven-moon_01
A ground: polyhaven-moon_01 @ 10 m
textures/rock/polyhaven-marble_cliff_05
B slope: polyhaven-marble_cliff_05 @ 40 m
blend by:'slope', lo 0.4, hi 0.7 · tint a 0xe6e6e6, b 0xd0d0d0 (desaturate)

Moon regolith has high macro variation: keep anti-tile on and repeat >= 10 m.

Rocks: moon

multiply tints cannot desaturate, so the field uses near-grey scans only (moon rocks, OGA rock 2, rock_6, rock-14); for asteroids sink 0 and rotate freely

boulder field: 9 kinds × 260 · mountain chunks: 3 kinds × 25

Cliff walls (closed, solidified scans)

solidified Poly Haven cliff scans: closed, so they sink and yaw without holes, but only the scan side is photographic. buildForest yaws at random: place walls in overlapping runs along the rim (sample()) so neighbours hide each other's darker synthetic backs, and keep them >= 150 m from the flight line. tint = red-canyon values; swap with tint_by_world

canyon walls: 5 kinds × 24 · mesa rims: 6 kinds × 40 · tint for this world {"sandstone":[0.82,0.84,0.88],"limestone":[0.9,0.9,0.92],"granite":[0.9,0.9,0.92]}
JSON preset (kits/worlds.jsonmoon)
{
 "sky": {
  "hdri": "hdri/ambientcg-NightSkyHDRI009/NightSkyHDRI009_2k.hdr",
  "fog_hex": "#42454e",
  "exposure": 1,
  "skyIntensity": 1.268,
  "envMul": 1.088,
  "skyFade": [
   -0.02,
   0.1
  ],
  "sunDir": [
   0.6291,
   0.7725,
   -0.0861
  ]
 },
 "terrain": {
  "a": {
   "folder": "textures/ground/polyhaven-moon_01",
   "files": {
    "map": "moon_01_diff_2k.jpg",
    "normalMap": "moon_01_nor_gl_2k.jpg",
    "roughnessMap": "moon_01_rough_2k.jpg"
   }
  },
  "b": {
   "folder": "textures/rock/polyhaven-marble_cliff_05",
   "files": {
    "map": "marble_cliff_05_diff_2k.jpg",
    "normalMap": "marble_cliff_05_nor_gl_2k.jpg",
    "roughnessMap": "marble_cliff_05_rough_2k.jpg"
   }
  },
  "a_repeat_m": 10,
  "b_repeat_m": 40,
  "by": "slope",
  "lo": 0.4,
  "hi": 0.7,
  "invert": false
 },
 "water": null,
 "rock_set": "moon"
}

Deep space (fleet battle)

ambientcg-NightSkyHDRI009
ambientcg-NightSkyHDRI009 colourful Milky Way arch, full sphere
fog #42454e · exposure 1 · skyIntensity 1.268 · envMul 1.088 · skyFade [-0.02, 0.1]
sunDir [0.629, 0.772, -0.086] (az/el [82.2, 50.6]) · foreground clear 1
hdri/ambientcg-NightSkyHDRI009/NightSkyHDRI009_2k.hdr
ambientcg-NightSkyHDRI008
ambientcg-NightSkyHDRI008 #41464c
opengameart-space-skyboxes-1-westbeam-blue
opengameart-space-skyboxes-1-westbeam-blue #2a4158

Rocks: moon

multiply tints cannot desaturate, so the field uses near-grey scans only (moon rocks, OGA rock 2, rock_6, rock-14); for asteroids sink 0 and rotate freely

boulder field: 9 kinds × 260 · mountain chunks: 3 kinds × 25

Sci-fi hull sets

Death Star (dark grey)

textures/scifi/ambientcg-MetalPlates015A
ambientcg-MetalPlates015A
textures/scifi/ambientcg-MetalPlates015B
ambientcg-MetalPlates015B
textures/metal/polyhaven-metal_plate_02
polyhaven-metal_plate_02
opengameart-pipes-greeble
textures/scifi/ambientcg-Metal046B
ambientcg-Metal046B

Star Destroyer (light grey)

textures/scifi/ambientcg-MetalPlates001
ambientcg-MetalPlates001
textures/scifi/ambientcg-MetalPlates003
ambientcg-MetalPlates003
textures/scifi/ambientcg-MetalPlates017A
ambientcg-MetalPlates017A
textures/scifi/ambientcg-MetalPlates014
ambientcg-MetalPlates014
textures/scifi/ambientcg-Metal030
ambientcg-Metal030
JSON preset (kits/worlds.jsonspace)
{
 "sky": {
  "hdri": "hdri/ambientcg-NightSkyHDRI009/NightSkyHDRI009_2k.hdr",
  "fog_hex": "#42454e",
  "exposure": 1,
  "skyIntensity": 1.268,
  "envMul": 1.088,
  "skyFade": [
   -0.02,
   0.1
  ],
  "sunDir": [
   0.6291,
   0.7725,
   -0.0861
  ]
 },
 "terrain": null,
 "water": null,
 "rock_set": "moon"
}

Generated 2026-09-14 06:39 by tools/kits/build-worlds.mjs.