← dominic.balass.one

Thursday shader series

Shader Demos: Fire & Drip

Week 1. Two fragment shaders that run on any DOM element. The element is rasterized to a texture with SVG foreignObject, then a fullscreen triangle does the rest. Fire gets the word FRAG; drip gets an orb.

🔥 Fire fragment shader

Layered noise scrolls upward through a black → red → orange → pale-yellow ramp. Flame columns rise from the letters themselves, the type ignites from the base up, and embers drift skyward.

Source element (plain DOM)
fire.frag · live WebGL

💧 Drip fragment shader

Slow and viscous. The orb sags under its own weight, thick strands swell and recede, and glossy droplets form necks, detach, and fall — tinted with the orb’s own color.

Source element (plain DOM)
drip.frag · live WebGL

How it works

  1. Rasterize. The source element’s HTML (inline styles only, so it survives serialization) goes into an SVG foreignObject, drawn to a 2D canvas at 2x. That canvas becomes the WebGL texture. No screenshots, no html2canvas.
  2. Shade. A single fullscreen triangle runs the fragment shader. Uniforms are just the element texture, time, resolution, the element’s rectangle, and its average color. Fire scrolls noise upward; drip displaces the sample coordinate downward.
  3. Respect motion. If prefers-reduced-motion is set, time freezes and one composed frame renders. The pause button does the same on demand.
fire.frag

    
drip.frag

    

In this series