From e98e0562b8c731beb826727dae2ce4f1e1ee8a04 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Sun, 8 Feb 2026 22:27:11 -0800 Subject: [PATCH] Fill water tile gaps at coastlines with neighbor checking Fixes visible square gaps in ocean near coastlines by rendering masked tiles if they have any water neighbors. Creates smoother, more natural coastlines. Implementation: - Check 8 neighboring tiles when a tile is masked out - If any neighbor is water, render the edge tile anyway - Creates 1-tile overlap at coastline boundaries - Fills square gaps between water tiles Before: Hard square edges with missing ocean tiles at coast After: Continuous water coverage with smooth blended coastlines The straight-line grid artifacts are reduced by ensuring adjacent water tiles connect properly instead of leaving rectangular voids. --- src/rendering/water_renderer.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/rendering/water_renderer.cpp b/src/rendering/water_renderer.cpp index 6ecf602f..56820684 100644 --- a/src/rendering/water_renderer.cpp +++ b/src/rendering/water_renderer.cpp @@ -482,6 +482,7 @@ void WaterRenderer::createWaterMesh(WaterSurface& surface) { for (int y = 0; y < gridHeight - 1; y++) { for (int x = 0; x < gridWidth - 1; x++) { // Check render mask - each bit represents a tile + // Also render edge tiles to blend coastlines (avoid square gaps) bool renderTile = true; if (!surface.mask.empty()) { int tileIndex; @@ -501,6 +502,27 @@ void WaterRenderer::createWaterMesh(WaterSurface& surface) { bool lsbOrder = (maskByte & (1 << bitIndex)) != 0; bool msbOrder = (maskByte & (1 << (7 - bitIndex))) != 0; renderTile = lsbOrder || msbOrder; + + // If this tile is masked out, check neighbors to fill gaps + if (!renderTile && x > 0 && y > 0 && x < gridWidth-2 && y < gridHeight-2) { + // Check adjacent tiles - render if any neighbor is water (blend coastline) + for (int dy = -1; dy <= 1; dy++) { + for (int dx = -1; dx <= 1; dx++) { + if (dx == 0 && dy == 0) continue; + int neighborIdx = (y + dy) * surface.width + (x + dx); + int nByteIdx = neighborIdx / 8; + int nBitIdx = neighborIdx % 8; + if (nByteIdx < static_cast(surface.mask.size())) { + uint8_t nMask = surface.mask[nByteIdx]; + if ((nMask & (1 << nBitIdx)) || (nMask & (1 << (7 - nBitIdx)))) { + renderTile = true; + goto found_neighbor; + } + } + } + } + found_neighbor:; + } } }