Iris remap on pupil dilation
The pupil grows from 3.5 mm to 7.8 mm on both eyes.
Left: the iris stays put and a bigger black disc covers it.
Right: the iris is remapped, so its fibres bunch up toward the edge.
The problem
Most eye shaders dilate the pupil by drawing a bigger black disc. The iris texture stays fixed, so a dilated pupil just covers the inner iris. On a real eye the iris tissue moves and bunches up toward the edge. With the camera held still, the difference shows.
How it works
The remap from zulubo/EyeShader works on the distance r from the eye centre, in 2 pieces:
r < pupil: map [0, pupil] onto [0, base pupil] of the texture
pupil < r < iris edge: map [pupil, edge] onto [base pupil, edge]
Then the UV is rescaled along that radius. The texture's own pupil always lands exactly on the current pupil, and the whole iris ring is squeezed or stretched to fit between the pupil and the edge. Nothing is covered.
The dashed ring marks the same spot in the iris pattern, at 62% of the iris radius. On the left it never moves. On the right it slides outward as the pupil opens.
My build
The whole eye is ray-traced in 1 fragment shader in three.js 0.170: an eyeball sphere, a cornea that refracts the ray (index 1.376) onto a recessed iris plane, sclera with faint veins, and a key highlight. The iris is procedural: fibres from angle-periodic noise, a jagged collarette ring, dark crypts and a limbal ring. Base pupil 0.30 of the iris radius, animated to 0.66. The readout assumes an 11.8 mm iris, so the pupil goes from 3.5 mm to 7.8 mm.
What I hit
My first iris colours were too saturated and the fibres too faint, so the squeeze was hard to see. Raising fibre contrast fixed that more than any overlay did.
The remap is linear. Real iris tissue does not compress evenly, so this is an approximation.
Trade-offs
- 1 extra remap before the texture read, no extra textures
- Works with any iris texture that has a round pupil
- Linear squeeze only
- Fibre detail stretches when the pupil shrinks below the texture's own pupil
When to use it
Any close-up eye: character portraits, dialogue cameras, creature eyes reacting to light.
Source and credits
Technique: radial iris remap for pupil dilation, from zulubo/EyeShader ("apply pupil dilation" in Eye.shader).
Repo: github.com/zulubo/EyeShader (MIT license), commit f5e4a63
Code: I ported the two-segment remap (r inside the pupil, and r between pupil and iris edge) from HLSL to GLSL. The eye, iris pattern, lighting and scene are my own procedural build; no textures or assets from the repo.
Topic from a question by @silic2023.