Hillshade

Horn's-method hillshade, ported from the sibling iOS app's HillshadeTileOverlay.swift: shadow-only output (black RGB, alpha = shadow depth) so it composites correctly over both light and dark basemaps without a separate light-mode palette, plus the three cleanup passes iOS added against real artifacts in Puget Sound data — despiked water, sea-surface noise, and flattened-valley noise all showing up as fake terrain.

elevations must be padded by exactly 1px of real neighbor data on every side of the width×height output area (a 3×3 kernel needs one ring of context per output pixel) — i.e. an ElevationTile of size (width+2)×(height+2). Getting that padding from adjacent tiles, not just clamping at this tile's own edge, is the caller's job (mirroring iOS's TerrainStore.elevationTile(margin:)); this function only shades.

Fixed light source (azimuth 315°/NW, altitude 45°) — not configurable, matching iOS: a single consistent light direction is what makes shading readable across differently-oriented terrain on the same map.

Properties

Link copied to clipboard
const val MARGIN: Int = 1

How far outside the output area ElevationTiles passed to shade must be padded with real neighbor data.

Functions

Link copied to clipboard
fun shade(padded: ElevationTile, width: Int, height: Int, maxShadowAlpha: Float): FloatArray

Shadow alpha per output pixel, 0f (no shading) to 1f (full shadow), row-major, width×height.