24

I was chasing that faceted low-poly island aesthetic. My first attempts used a smooth normal PlaneGeometry so it looked like melted plastic, not crisp facets. Also the terrain wasn't reproducible so I could never get the same island back.

Two constraints fixed it: force flat shading by not sharing vertices between triangles (or computeVertexNormals after de-indexing), and drive the heightmap from seeded value noise so a seed always yields the same island. Coloring by height bands sold the toy-diorama feel.

How are people handling water? A flat translucent plane feels cheap next to the facets.

THE PROMPT
Create a self-contained three.js scene of a low-poly procedural island. Requirements:
- Seeded value-noise heightmap (mulberry32 -> value noise -> fbm, 4 octaves) applied to a {SIZE}x{SIZE} plane (default 120 segments).
- Faceted look: de-index the geometry (`toNonIndexed()`) so each triangle has its own vertices, then `computeVertexNormals()` for true flat shading; use MeshStandardMaterial with flatShading:true.
- Radial falloff so edges sink below sea level, making an island not a slab.
- Color by height BANDS via vertex colors: deep sand, grass, rock, snow, with hard-ish transitions (small smoothstep), not a continuous ramp.
- One directional light + hemisphere light for the diorama look; soft shadows on.
- OrbitControls with damping; a translucent water plane at y=0.
- A `regenerate(seed)` function and a seed readout.
State the seed->mesh determinism guarantee and the triangle count.

2 Answers

7

De-indexing for real flat facets is the correct move, people fight normals for hours before finding it. For water: skip the flat plane, use a second low-poly plane with a gentle sine-sum vertex displacement in the shader and a fresnel-ish opacity (more opaque at grazing angles). It reads as water without a reflection pass.

THE PROMPT
Water: MeshStandardMaterial with onBeforeCompile injecting `pos.y += sin(pos.x*0.3+time)*0.15 + sin(pos.z*0.5+time*1.3)*0.1;` and opacity = mix(0.5,0.9, fresnel). Cheap, no render targets.
7

Watch the memory on de-indexed geometry at 120 segments, you triple the vertex count. Fine on desktop, but if you target mobile drop to ~80 segments or the GC pause on regenerate is visible. Otherwise a great recipe.

Your Answer