feat: seamless chunk boundaries via extended heightmap normals#12
Merged
Conversation
Uses a (resolution+2)×(resolution+2) extended heightmap to compute per-vertex normals without edge clamping. Right edge of chunk(0,0) and left edge of chunk(1,0) now produce matching normals, eliminating the lighting seam at chunk boundaries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Generates a (resolution+2)×(resolution+2) heightmap including a 1-cell border sampled one spacing unit beyond the chunk boundary. Used by ComputeNormalsFromExtended to compute correct cross-boundary normals without edge clamping. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace ComputeNormals (clamped edge sampling) with:
1. GenerateExtendedHeightmap — (res+2)×(res+2) heightmap with real
noise values 1 cell beyond chunk boundaries
2. ComputeNormalsFromExtended — uses extended grid for central
differences, no clamping needed
Edge normals now use actual neighbor terrain heights instead of
repeating the boundary value, eliminating the lighting seam at
chunk boundaries.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Visible seams appeared at chunk boundaries due to incorrect lighting at chunk edges.
Root Cause
ComputeNormalsused clamped sampling at boundary vertices:At the right edge (col=128), the central difference sees
hL = hR, giving zero horizontal gradient and a flat, incorrect normal. Heights are continuous across chunks (same world-space noise), but the lighting seam came from mismatched normals.Solution: Extended Heightmap Normal Computation
Generate a (resolution+2)×(resolution+2) = 131×131 heightmap for each chunk that includes a 1-cell border sampled one spacing unit beyond the chunk boundary. Use this extended heightmap to compute normals — every edge vertex now has real cross-boundary gradient data, no clamping.
Right edge of chunk(0,0) normal = central_diff(h(508), h(516)) / (2×4)
Left edge of chunk(1,0) normal = central_diff(h(508), h(516)) / (2×4)
Identical — seam eliminated.
Changes
wasm/terrain/heightmap.goGenerateExtendedHeightmap(cx, cz, cfg)wasm/terrain/normals.goComputeNormalsFromExtended(extHm, res, size, scale)wasm/main.gogoGenerateChunkwasm/terrain/heightmap_test.gowasm/terrain/normals_test.goPerformance
~7% more noise evaluations per chunk (131²=17,161 vs 129²=16,641). No TypeScript API changes. No GPU buffer format changes.