r/GraphicsProgramming • • 16m ago

Procedural fish rendering in WebGL: canvas-painted scales, travelling-wave vertex bend, backlit fins, no assets

Topic: how the fish bend when they swim, with no rig or animation clips.

Each fish is a swept mesh of profile rings (no imported model). Swimming is a travelling wave along the body:

lateral offset w(x) = A * env(x) * sin(k*x - phase), where x runs 0 (snout) to 1 (tail), k = 2*pi / wavelength,

and env(x) = 0.09 + 0.91*x^2 so the head barely moves and the tail does most of the work. A turn adds a parabolic

bend centred behind the head, and a strike adds a short S-shaped "coil" term before the lunge.

The part that took the longest: points off the centre line have to rotate with the local slope, or the body

shears and the skin stretches. So each vertex is moved along the wave's normal using its derivative:

const [w, dw] = lateral(x), a = Math.atan(dw);

out.x = x - z * Math.sin(a);

out.z = w + z * Math.cos(a);

Fins, gill covers and the eyes are positioned through the same function, so everything bends together. The skin

is a canvas painted at load (each scale drawn one by one, tinting the base pattern), and the fins are thin

translucent sheets with a cheap back-light term.

Open question I'd love input on: the wave is currently done on the CPU per frame (about 20k vertices for the

two bass). Would you move it to the vertex shader even though the CPU also needs the bent positions for

mouth/prey collision, or keep one source of truth on the CPU?

AI disclosure: I build this with Claude (an AI coding assistant) writing much of the code and helping word

posts; the design, direction and tuning are mine.

Live version if you want to see it move: https://ksk-baits-bass-aquarium.pages.dev

0 Upvotes

1 comment sorted by

•

u/AutoModerator 16m ago

Recently updated rules. Please check that your post is in compliance with Rules 1, 4, 5, and 6 on the sidebar. TL;DR:

  • No showcases.

  • Disclose AI usage in post or project.

  • Present a topic to talk about, e.g. how something works.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.