Skip to content

Commit 3a1af10

Browse files
TMHSDigitalclaude
andcommitted
fix(showcase): terrain-scatter quality pass — weathered erratics on a meadow diorama
The stones were 80-tri flat-shaded icosphere blobs, one with a pure-black face, on a bare slab. They are now quad cube-sphere glacial erratics (4 segments for boulders, 3 for cobbles): sub-rounded blocky shapes with closed-form lumps and shallow cleaves, smooth-shaded with fracture edges over 48 deg kept sharp. Render path only: weathered granite shader with lichen and a moss line, a soil section on the cut sides (turf lip, humus, banded clay, cobble bed, jointed bedrock) keyed to depth below the hill, ~37k grass blades, wildflower drifts, juniper/hazel/gorse shrubs, a worn footpath chosen to clear the stones, and warm key / cool fill lighting. Budgets re-fitted: base tris 2398 -> 2986 (band 1400-2800 -> 2000-3800, same relative width), declared outer Z 0.570 -> 0.609 m (tolerance unchanged), collider 36 -> 54 tris (ceiling 120). Default exit 0 and all ten falsifiers exit their documented codes (9, 15-23) on 4.5.11 LTS, 5.1.2 and 5.2.1 LTS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 2f91cbf commit 3a1af10

6 files changed

Lines changed: 975 additions & 202 deletions

File tree

14.5 KB
Loading
68.3 KB
Loading

‎showcase/gallery.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@
109109
"name": "terrain-scatter",
110110
"dir": "showcase/terrain-scatter",
111111
"category": "terrain",
112-
"teaches": "A Geometry Nodes hill tile with embedded, varied stone scatter through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.",
113-
"alt": "A square hill tile of patchy grass over dark earth with a rounded soil edge, nine faceted grey stones sunk across it among grass tufts and pebbles.",
114-
"witnessesFix": "Recomputed: 2398 tris, two materials with 720 stone faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.800x1.800x0.570 m, grounded zmin, 9 stones of >=80 faces each sealed into the ground in 8/8 sectors, footprint ratio 9.8, rim tilt step 33.5 deg, no stone pairs overlapping, LOD ratios in band, convex collider 36 tris, hygiene zero, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z 16; --poke-rock 17; --float-rocks 18; --box-rocks 19; --pile-rocks 20; --perch-rocks 21; --uniform-rocks 22; --sharp-rim 23.",
112+
"teaches": "A Geometry Nodes hill tile with an embedded scatter of glacier-worn boulders of varied size through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.",
113+
"alt": "A square meadow hillside tile in dense green grass, nine lichen-blotched granite boulders sunk among taller tufts, a bare-earth footpath with pebbles winding across it, drifts of daisies and pink and purple wildflowers, three round shrubs, one dotted with yellow gorse bloom, and a cut side showing a turf lip, dark humus, ochre clay, a cobble bed and grey bedrock.",
114+
"witnessesFix": "Recomputed: 2986 tris, two materials with 654 stone faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.800x1.800x0.609 m, grounded zmin, 9 stones of >=54 faces each sealed into the ground in 8/8 sectors, footprint ratio 9.8, rim tilt step 33.5 deg, no stone pairs overlapping, LOD ratios in band, convex collider 54 tris, hygiene zero, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z 16; --poke-rock 17; --float-rocks 18; --box-rocks 19; --pile-rocks 20; --perch-rocks 21; --uniform-rocks 22; --sharp-rim 23.",
115115
"hero": "docs/gallery/assets/terrain-scatter-hero.webp",
116116
"preview": "showcase/terrain-scatter/preview.webp",
117117
"tags": [

‎showcase/terrain-scatter/README.md‎

Lines changed: 89 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
A showcase piece, not an example. Geometry Nodes sine-hill Mesh Grid
44
with an Index-jittered Instance-on-Points scatter, realized cubes
5-
replaced by closed-form cleaved, faceted stones seated on sampled dirt Z,
5+
replaced by closed-form, glacier-worn boulders seated on sampled dirt Z,
66
then the shipped pipeline: unique-cell UVs, Cycles high-to-low normal
77
bake, LOD chain, convex collider, Unity glTF export.
88

@@ -25,16 +25,61 @@ imported as a package). Hygiene combinatorics match
2525

2626
Intended size: 1.80 m square hill tile, ~0.16 m sine amplitude, nine
2727
embedded stones from cobble to boulder; outer AABB 1.800 × 1.800 ×
28-
0.570 m.
28+
0.609 m.
2929

30-
**Hero.** On the render path, grass is blended into the dirt shader where
31-
the ground faces up (geometry normal Z), broken by a coarse patch noise so
32-
bare soil shows through. The rounded rim and the cut sides tip past the
33-
band, so the section still reads as topsoil over subsoil. A render-only
34-
dressing, drawn with a fixed seed from the up-facing dirt faces, adds 120
35-
clumped grass tufts and 40 sunk pebbles in the stone material. The dressing
36-
is staging, parented to the tile, and is not part of the asset, its budgets
37-
or its export. The asset sheet judges `TerrainLow` alone.
30+
**Hero.** The render path dresses the tile as a hand-made meadow diorama.
31+
None of it is part of the asset, its budgets or its export; the dressing
32+
is drawn with a fixed seed, parented to the tile, and the asset sheet
33+
judges `TerrainLow` alone.
34+
35+
- **Soil section.** Render-only point attributes give each dirt vertex
36+
its depth below the hill surface over it (exact on the vertical walls,
37+
which are single quads). The cut sides layer down from the hill's own
38+
top: a turf lip, dark humus with roots, then level horizons in object
39+
Z on wobbled boundaries: banded ochre clay under a paler loam with the
40+
odd stone, a cobble bed, and jointed grey bedrock at the foot.
41+
- **Boulders.** Weathered granite: a grey per stone, three scales of
42+
noise, feldspar and mica speckle, rain streaks on the flanks, crustose
43+
lichen blotches (grey-green and sulphur, sparse orange) on the
44+
up-facing stone, moss and a soil stain where it meets the ground, read
45+
from a render-only height-above-ground attribute.
46+
- **Ground cover.** About 37 000 curved, tapering blades in clumps of
47+
varied height and hue (a few dry straw blades among the greens); taller
48+
grass and seed stalks ring each stone, where grazing and mowing miss in
49+
a real field; a turf lip is combed out and down over the cut edge;
50+
drifts of ox-eye daisy, buttercup, knapweed and clover; three shrubs
51+
(juniper, hazel, flowering gorse) placed where they clear the stones,
52+
the path and each other.
53+
- **Worn path.** A bare-earth foot path with grit meanders across the
54+
hill. Its closed-form centre line is chosen at render time from a fixed
55+
candidate set as the one that threads furthest from every stone; the
56+
soil shader and the dressing share it, so no blade grows on it and the
57+
pebbles gather along it.
58+
- **Light.** A warm late-afternoon key from camera-left throws the
59+
boulders' and the grass's shadows across the slope, a cool fill keeps
60+
every stone face off black, a back rim lifts the grass tips and the
61+
lip, and the warm wedge lands on the backdrop.
62+
63+
### Why the stones are worn boulders now
64+
65+
The third pass found the stones read as placeholders at 100%: faceted
66+
grey icosphere blobs, one with a pure-black flat face. Glacial erratics,
67+
the boulders strewn across upland meadows, are sub-rounded to
68+
sub-angular blocks of granite or gneiss, rounded by transport in the ice
69+
with a few flat fracture and abrasion faces, lichen on their tops and
70+
moss where they meet the turf.
71+
72+
- **Shape.** Each stone is a quad cube-sphere (4 segments a side for the
73+
boulders, size factor ≥ 0.9; 3 for the cobbles) pushed out to a
74+
superellipsoid of exponent `BLOCK_EXP` = 2.6, which squares the
75+
shoulders into a block, with two closed-form low-frequency lumps of up
76+
to `LUMP_AMP` = 13% and four shallow cleaves (`CLEAVE_DEPTH` 0.68).
77+
`STONE_R_BOUND` grows by the superellipsoid's plan bulge and the lump
78+
amplitude, so the relaxation still spaces the stones by their real
79+
reach.
80+
- **Shading.** Smooth over the worn body, with edges folding more than
81+
`STONE_SHARP_DEG` = 48° kept sharp, so the fracture faces keep a crisp
82+
arris. Flat-shaded, the same stones read as low-poly placeholders.
3883

3984
## Budgets
4085

@@ -43,14 +88,14 @@ materials, UVs, evaluated LOD, collider, or export file.
4388

4489
| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) |
4590
| --- | --- | --- |
46-
| Base triangles | 1400–2800 | 2398 / 2398 / 2398 |
47-
| LOD1 ratio | 0.32–0.62 of base | 0.4996 / 0.4996 / 0.4996 |
48-
| LOD2 ratio | 0.10–0.35 of base | 0.2193 / 0.2193 / 0.2193 |
49-
| Materials | exactly 2 distinct, ≥24 stone faces | 2 slots, 720 stone |
91+
| Base triangles | 2000–3800 | 2986 / 2986 / 2986 |
92+
| LOD1 ratio | 0.32–0.62 of base | 0.4997 / 0.4997 / 0.4997 |
93+
| LOD2 ratio | 0.10–0.35 of base | 0.2197 / 0.2197 / 0.2197 |
94+
| Materials | exactly 2 distinct, ≥24 stone faces | 2 slots, 654 stone |
5095
| UVs | in `0..1`, AABB overlap ≤ 1e-5 | in range, overlap 0 |
51-
| Outer AABB | (1.800, 1.800, 0.570) m ± 0.015 | (1.8000, 1.8008, 0.5700), zmin 0 |
52-
| Collider tris | ≤ 120 | 36 |
53-
| Export | written, size > 0 | 198908 / 198908 / 198900 bytes (4.5.11 / 5.1.2 / 5.2.1) |
96+
| Outer AABB | (1.800, 1.800, 0.609) m ± 0.015 | (1.8000, 1.8008, 0.6085), zmin 0 |
97+
| Collider tris | ≤ 120 | 54 |
98+
| Export | written, size > 0 | 218868 / 218868 / 218860 bytes (4.5.11 / 5.1.2 / 5.2.1) |
5499

55100
Base triangles rose from **1194 to 1758** in the first quality pass: 9-vert hill
56101
became a 21-vert grid, and bevelled cubes became subdiv-2 icospheres.
@@ -65,6 +110,19 @@ triangles because it now hulls a coarse, unbevelled 9-vertex tile
65110
(`COLLIDER_GRID`): the chamfer and micro-relief are visual, and on the
66111
full-resolution tile they pushed the hull to 178, over its ceiling.
67112

113+
The third pass took them from **2398 to 2986**, and the declared band
114+
was re-fitted from 1400–2800 to 2000–3800 around the new count, the same
115+
relative width. The 80-triangle icosphere stones became quad
116+
cube-spheres: 192 triangles for each of the four boulders, 108 for each
117+
of the five cobbles (1308 for the stones, against 720). At 80
118+
triangles a 0.4 m boulder's silhouette showed its facets, and smooth
119+
shading cannot hide a polygonal outline. The outer Z rose from 0.570 m
120+
to 0.609 m: the blocky superellipsoid keeps more of its height than the
121+
cleaved ellipsoid did, and the declared size was re-centred on the
122+
measured 0.6085 m (the ± 0.015 tolerance is unchanged). The collider
123+
rose from 36 to 54 triangles, still under its ceiling of 120, because
124+
the rounder stones put a few more vertices on the hull.
125+
68126
DECIMATE COLLAPSE triangle counts are **not** guaranteed identical across
69127
series — the gate is a ratio band, not an exact count. This mesh matched
70128
on 4.5.11 / 5.1.2 / 5.2.1. Bake pixels are stochastic; the gate is
@@ -87,12 +145,12 @@ Recomputed from the generated mesh, not asserted about the script.
87145
| Coplanar disjoint face pairs | 0 | 0 |
88146
| Grounded: `zmin` | within 1e-4 of 0 | 0.0000 |
89147
| Stone shells | 9 | 9 |
90-
| Per-stone faces | ≥ 40 | 80 |
91-
| Stone floor `zmin` | ≥ 0.012 m | 0.06946 |
92-
| Seat offset (`zmin` − dirt Z) | ≤ 0.02 m | −0.03326 |
148+
| Per-stone faces | ≥ 40 | 54 (cobbles) / 96 (boulders) |
149+
| Stone floor `zmin` | ≥ 0.012 m | 0.08305 |
150+
| Seat offset (`zmin` − dirt Z) | ≤ 0.02 m | −0.03775 |
93151
| Interpenetrating stone pairs (BVH overlap) | 0 | 0 |
94152
| Sealed sectors per stone (buried vertex in each of 8) | 8 / 8 | 8 / 8 |
95-
| Stone footprint ratio (largest / smallest) | ≥ 3.0 | 9.812 |
153+
| Stone footprint ratio (largest / smallest) | ≥ 3.0 | 9.757 |
96154
| Rim tilt step between adjacent dirt faces | ≤ 40° | 33.52° |
97155

98156
### Why the stones are cleaved, relaxed and faceted
@@ -105,8 +163,9 @@ also interpenetrated, because the GN scatter jitters by up to 0.22 m on a
105163
- **Cleaved.** Each ellipsoid is cut by `N_CLEAVES` planes whose normals
106164
and depths come from the stone's own centre, closed form. Every vertex
107165
beyond a plane is projected onto it, which leaves flat broken faces.
108-
Stones are shaded flat, because broken rock is faceted; smooth shading
109-
turned the cleaved stones back into eggs.
166+
The first pass shaded them flat, because smooth shading turned the
167+
cleaved ellipsoids back into eggs; the third pass replaced them with
168+
blocky superellipsoids that hold their shape smooth-shaded (above).
110169
- **Scaled.** Cleaving takes about a third off each stone, and at the old
111170
size they read as pebbles, so every semi-axis is `ROCK_SCALE` = 1.35×.
112171
- **Relaxed.** Stone centres are pushed apart to
@@ -145,16 +204,16 @@ with pebbles dropped on it.
145204
- **Ground, not a sine.** Two closed-form relief terms, 14 mm and 7 mm,
146205
ride on the hill in the same GN tree. The hill and rim are
147206
smooth-shaded, because flat shading printed the 21×21 grid on the
148-
ground; stones and walls stay flat.
207+
ground; the walls stay flat (the stones were flat until the third pass).
149208
- **Materials.** Stones are mid-grey (they were near-white where the key
150209
hit them), and the dirt darkens toward a subsoil colour below the slab
151210
lift, in object space, without adding a material.
152211

153212
`stone_overlap_audit` BVH-tests every stone pair. `--pile-rocks` skips
154-
the relaxation and draws the scatter in to 40% so neighbours collide: 7
155-
pairs interpenetrate, and the piece exits 20. Skipping the
156-
relaxation alone would prove nothing, because the cleaved stones miss
157-
each other unrelaxed.
213+
the relaxation and draws the scatter in to 40% so neighbours collide: 8
214+
pairs interpenetrate (7 with the second pass's stones), and the piece
215+
exits 20. Skipping the relaxation alone proved nothing in the second
216+
pass, because the cleaved stones missed each other unrelaxed.
158217

159218
### Falsifiers
160219

@@ -170,8 +229,8 @@ and returned the same code on each.
170229
| `--float-rocks` | seat offset vs sampled dirt Z | 18 |
171230
| `--box-rocks` | per-stone face floor | 19 |
172231
| `--pile-rocks` | stone-to-stone interpenetration is 0 | 20 |
173-
| `--perch-rocks` | every stone sealed in 8/8 sectors (measures 3/8) | 21 |
174-
| `--uniform-rocks` | footprint ratio ≥ 3.0 (measures 1.851) | 22 |
232+
| `--perch-rocks` | every stone sealed in 8/8 sectors (measures 4/8) | 21 |
233+
| `--uniform-rocks` | footprint ratio ≥ 3.0 (measures 2.317) | 22 |
175234
| `--sharp-rim` | rim tilt step ≤ 40° (measures 88.50°) | 23 |
176235

177236
## Run
60.3 KB
Loading

0 commit comments

Comments
 (0)