"Per-cell white noise hash gives salt-and-pepper terrain instead of organic shade patches"
Your pixel-art or voxel terrain shade selection — e.g. choosing between a light and dark grass variant per cell — looks like a noisy checkerboard ("very variable and very scattered") instead of large organic meadow/dune patches. Greedy-mesh efficiency is also low because every second cell uses a different material.
The shade driver is a per-cell white-noise hash: something like hash = LatticeValue(x, y, seed); mat = hash < 0.5 ? GrassLight : GrassDark. White noise is uncorrelated cell-to-cell, so 50% of cells flip every boundary — salt-and-pepper everywhere, no spatial coherence. This also destroys greedy meshing because the merge key includes material, so no two adjacent cells with different shades merge.
Replace the per-cell hash driver with a two-frequency split:
-
Smooth low-frequency patch field — drive the primary shade from a value-noise lookup at a large scale (e.g.
Noise.ValueNoise(wx, wy, ~15m, seed)) so the result naturally forms large uniform patches with one dominant shade. -
Narrow per-cell hash dither at thresholds only — confine the random hash to a narrow band around each threshold:
hash < smoothstep(t - half, t + half, patchField)so only the patch edges dither, not the interiors.
This same "smooth field + narrow hash dither" primitive works for both in-biome shade variation and material-to-material transitions. For transitions, add intermediate atlas cells (blend stops) and pick a stop from a smoothstep blend + hash jitter (A → A-blend → B-blend → B, dithered only where 0.15 < blend < 0.85) to produce a watercolor wash instead of a hard dithered contour.
Measured improvement: on one terrain test, turning a 50/50 two-material checkerboard into large single-material fields raised greedy-mesh efficiency from 1.9x to 3.9x (render tris from 223k to 107k), with mixed and alpine biomes also improving, all at seed-stable determinism.
Nuance: elevation-band strata (horizontal bands on cliff faces keyed on raw height) are still desirable — keep those keyed on actual height, but let the elevation thresholds wander organically by comparing h + low-amplitude smooth noise perturbation instead of raw h, so the iso-lines follow contours naturally.
The rule of thumb: any time terrain color is chosen per cell, ask "is the driver spatially smooth?" If it's white noise, the result is static. Making the driver a low-frequency field ensures large coherent patches, and confining the hash to threshold edges preserves organic variety where it matters (boundaries) without destroying spatial coherence or greedy-mesh efficiency in the interiors.