A glowing pod with a magical creature growing inside it
A seed pod with a small herbal creature asleep inside, lit from within. Particles were ruled out, so the life inside the gel had to be maths on a surface.
Summary
The subject: a seed pod cradled in petals, a small herbal creature curled up asleep inside it, lit from within — close enough to an embryo in a womb that the concept board pinned ultrasound photographs beside the paint-overs.
The constraint: no particles. Keeping a particle system inside a deforming shell means adding collision to the pod and to everything it is held against, in every scene it appears in.
The solution: the interior is a ray-march through 3D noise on the shell surface, and the blur is one tap into HDRP’s own colour pyramid. Every part of the look is a material property, so an animator can key it.
What the pod had to do
It is a light source in its scenes: it has to throw mint green across a room and read as alive from across it. And it has to act — three story states, healthy, weaker and dead, with the transition between them a performance rather than a material swap.
So none of those states is a separate material. Density, Scatter, the two gel colours, the noise offset and the blur ceiling are the performance: healthy is dense, saturated and drifting, dead is thin, desaturated and still. They are ordinary material properties, so they key on a Timeline, and they get tuned per shot so the pod reads at whatever distance the camera sits.


The three states
Same material, same graph. Only the sliders move.
Why the blur is one texture tap
The obvious move is a blur kernel in the fragment shader. It is also the wrong one, because HDRP has already done it: for rough refraction the pipeline builds _ColorPyramidTexture, a gaussian mip chain of the frame. The HD Scene Color node samples that pyramid and takes a Lod input.
So the blur is a single tap with a computed mip level — trilinear filtering gives the transition between levels for free, no loop, no divergence. The mip comes from a ray–shell intersection: remap the scene depth between the entry and exit surfaces into 0–1, multiply by the chord length, run it through Beer-Lambert. The same term drives the tint, so colour and blur cannot drift apart.
float depthSpan = max(backEye - frontEye, 1e-4);
float segLen = length(exitWS - PositionWS);
// 0 at the entry surface, 1 at or beyond the back of the shell
float t = saturate((GelSceneEye(uvR) - frontEye) / depthSpan);
float pathLen = segLen * t;
float lod = (1.0 - exp(-Density * pathLen)) * lodMax;Next steps
- A blend slider between this shader and the SSS shader the production already uses, so a shot can sit anywhere between translucent gel and skin.
- The PBR side of the opaque region is thin: where the opacity map goes white it is an albedo and a gloss range, and it should carry real surface detail.
- The ellipsoid is fitted to the world-space AABB, which is larger than the real shape when the mesh is rotated. Object-space extents from a small [ExecuteAlways] component would be exact.
- The blur still mixes two systems — a mip pyramid and a full-screen gaussian. One should go.