Heightfield Ocean: Root-Finding Ray Tracing

Visual impression: a quiet sea where light glides across gentle swells to the horizon, as if wind and sun were stroking the surface.

The technique is heightfield tracing with root finding. Instead of SDF sphere tracing that “walks” by a distance function, the water is defined as a height function h(x, z), and we solve for the ray time t where the ray’s height y equals the surface height: f(t) = y − h(x, z) = 0. We combine the secant method with bisection: first find a bracket where f(t) changes sign, then converge safely and quickly to the zero. Iterations are capped; if convergence fails we return the best estimate to avoid frame drops. The ray origin and direction are handled by ro and rd, time progression by iTime, and a far cutoff by FAR_CLIP.

The strength of a heightfield is treating the water as a single-valued, continuous surface. By avoiding horizontal displacement and keeping h(x, z) single-valued, f(t) behaves well and root finding is stable. Several sine waves are layered and phase-animated over time to produce believable ocean motion. The mean sea level is set via SEA_LEVEL. Sharp folding or multi-valued behavior would introduce multiple roots and instability, so we balance “visual richness” against “solver stability.”

After a hit, the normal comes from the gradient of h. Using a small ε offset in x and z, we take finite differences and form n = normalize(vec3(-∂h/∂x, 1, -∂h/∂z)). This makes the shading track the wave slope: steeper facets catch stronger reflections, flatter areas read as diffuse. We apply the Fresnel approximation (Schlick’s formula) so reflection vs. body color changes smoothly with view angle—grazing angles reflect more, near-normal angles show more bluish diffusion. A mirror highlight uses a half-vector against the sun direction sunDir. The sky is a horizon-to-zenith gradient with a sun glow; sampling it along the reflection direction paints sky colors onto the water. Toward the distance we blend with exponential fog to the sky tone, conveying depth and air.

Water foam is suggested by slope: where n.y is small (steep facets), we add a touch of bright, noisy tone so crests feel alive without covering the image in uniform white. A slight vignette darkens the edges to focus the eye. The camera orbits by moving ro around a target lookAt, then builds rd. Rays pointing strongly upward typically miss the sea and render the sky directly; downward rays run the bracket searchroot solveshading pipeline. Work is bounded by MAX_BRACKET_STEPS for sign-change search and MAX_ROOT_ITERS for solving, so worst-case cost stays under control. Functions such as heightHF, fRayHeight, bracketRoot, and solveRoot separate roles clearly, improving readability and maintenance.

In short, this ocean isn’t “walking by distance” but solving for the intersection where height matches the ray. By keeping the surface single-valued and smooth, then layering small physical cues—gradient-based normals, Fresnel, reflection, and fog—we get convincing water with modest computation: a lightweight, robust ocean rendering built on heightfield root finding.



https://geni.us/N8x4hRy

Comments

Popular posts from this blog

Japan Jazz Anthology Select: Jazz of the SP Era

In practice, the most workable approach is to measure a composite “civility score” built from multiple indicators.