Skip to content
Andrew Voirol
Monday, August 31, 2026terragemini-build

3x3 Sobel normal gradient convolution for procedural coastlines

ShadersWebGLVisualization

To highlight continental boundaries and island archipelagos without adding heavy vector geometry, TerraGemini applies a discrete 3×33 \times 33×3 Sobel convolution filter across the 4K raster landmass mask I(x,y)I(x, y)I(x,y):

Gx=[−10+1−20+2−10+1]∗I(x,y),Gy=[−1−2−1000+1+2+1]∗I(x,y)G_x = \begin{bmatrix} -1 & 0 & +1 \\ -2 & 0 & +2 \\ -1 & 0 & +1 \end{bmatrix} * I(x, y), \quad G_y = \begin{bmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ +1 & +2 & +1 \end{bmatrix} * I(x, y)Gx​=​−1−2−1​000​+1+2+1​​∗I(x,y),Gy​=​−10+1​−20+2​−10+1​​∗I(x,y)

The normalized edge magnitude is computed per vertex:

Sedge(x,y)=min⁡(1.0,Gx(x,y)2+Gy(x,y)24.0)S_{\text{edge}}(x, y) = \min\left(1.0, \frac{\sqrt{G_x(x, y)^2 + G_y(x, y)^2}}{4.0}\right)Sedge​(x,y)=min(1.0,4.0Gx​(x,y)2+Gy​(x,y)2​​)

Dynamic Shader Coastline Modulation

In the vertex and fragment shaders, the uniform u_edge_sensitivity dynamically scales point size and brightness along coastlines:

float threshold = 1.0 - (u_edge_sensitivity * 0.85 + 0.08);
float edgeFactor = smoothstep(threshold, 1.0, a_edge_strength);
gl_PointSize = clamp(baseSize * fresnel * (1.0 + 1.6 * edgeFactor * u_edge_sensitivity), 1.0, 64.0);

This emphasizes continental boundaries while preserving smooth, anti-aliased transitions under high-speed globe rotation.

← Previous

Blinn-Phong specular ocean glint and raytraced atmospheric scattering

Next →

MGRS/UTM geodetic conversion and 3D screen-to-sphere raycasting


Andrew Voirol

Builder, hacker, shipper. Currently leaving localhost.

Navigate

WorkThreadsBuilder's LogAboutContactRSS Feed

Connect

X / TwitterGitHubLinkedIn

© 2026 Andrew Voirol·Back to top ↑
✦Just one prompt away from figuring it all out.