Seagazer replaced its old particle spray with two curved sheets that follow the hull as the boat moves. Here’s how it works.
In
Seagazer, a Godot sailing game, the bow spray used to come from particle emitters on either side of the boat. Their unshaded, additive particles glowed at night and looked like they sat on top of the water. Playtesters noticed it, so
HeedlessNomad rebuilt the effect.
The new spray starts with a 64 × 24 grid mesh on each side of the hull. A vertex shader bends each grid into a curling sheet that tapers at both ends. Speed changes its size, while steering tilts the sheet on the inside of a turn.
HeedlessNomad split the ocean's fragment shader into shared files and uses that code for the spray too. A BOW_WATER_SHEET define adds a foam lip and softens the reflections.
Each frame, a controller copies any shared ocean uniforms that changed to the spray, including the sun direction and wave parameters. That keeps both surfaces shaded alike as the light changes from day to night.
The first sheets followed a curve placed beside the hull. They cut into the boat when it banked, so HeedlessNomad replaced that curve with a 23-plane stand-in for the hull.
The controller samples the water at 17 points per side every frame and pushes each point outward until it clears the hull. A curve joins them without overshooting.
An earlier inside-or-outside check made the base jump as waves passed. Measuring how far each point needs to move keeps it steady.
The bases sit 12 cm below the surface. With the sheets drawn first, the ocean covers their submerged edges and hides the seam without fading the spray out.
The spray follows the boat's measured speed, so it responds even while the boat coasts. The crests move faster as the boat accelerates, but multiplying elapsed time by the current speed would make them jump when speed changes.
HeedlessNomad advances the animation phase a little each frame instead, keeping the crests moving smoothly.
On long sails, the spray developed a crinkled look after ten to thirty minutes. Far from the world origin, 32-bit shader values could no longer represent the tiny differences used to calculate the sheets' normals.
HeedlessNomad now positions the sheets relative to the hull. The controller also computes and wraps each ocean wave's phase using 64-bit floats on the CPU before passing it to the shader. Both changes keep the values small enough for the spray to stay smooth on long trips.
Small droplets fly from the hull as the boat moves. A single MultiMesh draws them, and the ocean shader leaves a ring where each one lands.
Seagazer is coming soon. You can find the game and its creator here:
We just released our new
Godot All About VFX Bundle, it covers shaders, particles, and VFX for 2D, UI, and 3D games with step-by-step examples. Over 600 pages of content. ✨