Skip to content

feat(biome): milestone 4 - biome stitching, world config & release workflow#18

Open
maxfelker wants to merge 4 commits into
mainfrom
feature/biome-m4-stitching
Open

feat(biome): milestone 4 - biome stitching, world config & release workflow#18
maxfelker wants to merge 4 commits into
mainfrom
feature/biome-m4-stitching

Conversation

@maxfelker

Copy link
Copy Markdown
Owner

Milestone 4: Biome Stitching + World Config

This PR completes Milestone 4 from the biome system implementation plan, adding per-vertex biome transition blending, adjacency enforcement, world-scale configuration, and a tag-triggered release CI workflow.


What's Changed

🌍 Biome Transition Rendering

  • WASM output extended: goGenerateChunk now returns 3 metadata floats per chunk — primaryBiomeId, secondaryBiomeId, and blendFactor — instead of a single biome ID
  • Terrain fragment shader (terrain.frag.wgsl): new getTransitionBlendedColor() function blends primary and secondary biome colors using the per-chunk blend factor; elevation-based rock and snow zones applied on top
  • Chunk uniform layout: biomeData = vec4(primary, secondary, blend, 0) written at byte offset 128 in the chunk uniform buffer

🧬 Adjacency Buffering (new file: wasm/biome/adjacency.go)

  • Deterministic Desert ↔ Swamp incompatibility rule: when both biomes have non-zero Gaussian weights, each transfers its minimum weight to Grassland, ensuring the two incompatible biomes never co-dominate a chunk boundary
  • applyAdjacencyBuffering() runs after Gaussian normalization in the generator pipeline

🌐 World Config & BiomeScale

  • biomeScale from WorldConfig is now applied during biome noise sampling: scaledX = worldX / scale, so larger values produce wider biome regions
  • GetBiomeParamsWithScale() added to selector.go; GetBiomeParams delegates to it
  • goLoadWorldConfig validates BiomeScale is in [0.1, 100.0] range

🎛️ World Config UI (Settings Panel)

  • New World Config section in the Settings panel with seed and biome scale number inputs and an Apply button
  • Wired through: Settings.tsxGameCanvas.tsxApp.tsxGameEngine.applyWorldConfig()WasmClient.loadWorldConfig()ChunkManager.reloadChunks()

🚀 Release Workflow (new file: .github/workflows/release.yml)

  • Triggers on v*.*.* version tag pushes (not on every commit)
  • test job: runs go test ./... and npm test before any build
  • build job (depends on test): builds the production Docker image tagged with the version and latest; push: false by default with a clear TODO comment for adding registry credentials

Files Changed

Area Files
WASM Go wasm/biome/generator.go, wasm/biome/selector.go, wasm/biome/adjacency.go (new), wasm/main.go
WASM Tests wasm/biome/adjacency_test.go (new), wasm/biome/transition_test.go (new)
Engine TS src/engine/WasmClient.ts, src/engine/ChunkManager.ts, src/engine/GameEngine.ts
Worker src/engine/worker/terrain.worker.ts, src/engine/worker/WasmBridge.ts
Shader src/shaders/terrain.frag.wgsl
UI src/components/Settings/Settings.tsx, src/components/Settings/Settings.module.css
App wiring src/components/GameCanvas/GameCanvas.tsx, src/App.tsx
Tests src/engine/ChunkManager.test.ts, src/components/Settings/Settings.test.tsx, src/components/GameCanvas/GameCanvas.test.tsx
CI .github/workflows/release.yml (new)

Test Results

  • ✅ Go: all packages pass (go test ./... in wasm/)
  • ✅ TypeScript: 61 tests across 11 files pass (npm test)
  • ⚠️ Pre-existing lint warning: unused _desc param in TextureManager.test.ts (not introduced by this PR)
  • ⚠️ Pre-existing build issue: crypto.hash requires Node ≥20.19; CI environment has 20.11 (not introduced by this PR)

Next: Milestone 5 — Flora & Decoration

Closes out M4. Ready to branch into feature/biome-m5-flora for procedural vegetation placement.

maxfelker and others added 4 commits March 15, 2026 23:03
- Add Gaussian-weighted biome blending with per-vertex climate sampling
  and adjacency buffering (desert↔swamp never co-dominate, buffer to grassland)
- Export chunk biome transition metadata (primary, secondary, blendFactor)
  from Go WASM; wire through worker → WasmClient → ChunkManager uniform
- Update terrain.frag.wgsl to interpolate between primary and secondary biome
  colors using chunk-level blend factor and elevation-based rock/snow zones
- Apply biomeScale from WorldConfig during biome noise sampling so larger
  values produce bigger biome regions
- Add World Config section in Settings panel (seed + biomeScale + Apply);
  wire through GameEngine.applyWorldConfig → loadWorldConfig → chunk reload
- Add adjacency.go, adjacency_test.go, transition_test.go with full test coverage
  for buffering weights, biome transition selection, and biomeScale sampling

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Runs Go and TypeScript tests, then builds the production Docker image
tagged with the version. Set push: true and add registry credentials
to enable publishing to a container registry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kept M4's ChunkGenerationResult return type in WasmClient.generateChunk
and integrated main's storeHeightmap fire-and-forget pool call for physics
collision detection. Accepted goStoreHeightmap function from main in wasm/main.go.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The dev service in docker-compose.yml referenced a 'dev' target stage
that did not exist in the Dockerfile, causing builds to fail.

- Add Stage 3 'dev': builds Go WASM in wasm-builder, installs npm deps,
  copies WASM artifacts to /wasm-dist, and runs 'npm run dev -- --host'
  on startup (copies WASM into the mounted /app/public before starting Vite)
- Add anonymous /app/node_modules volume in docker-compose so the
  container's installed node_modules are not overridden by the host mount
- Renumber production stage comment to Stage 4

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants