← Back to library
northlight.html
Open full screen ↗ This is the actual page the prompt produces — scroll and click inside it.

About this one

Exponential falloff around noise-displaced lines. It drifts like weather rather than sliding like an animation.

The prompt

THE ENGINE — about sixty lines, written by hand

Render a fragment shader across a full-bleed canvas behind the hero.
Raw WebGL, no Three.js: a 600KB scene graph to draw one quad is not a
trade worth making, and the shader is the entire effect anyway.

Set it up like this:
  - One oversized triangle at (-1,-1), (3,-1), (-1,3). It covers the
    viewport with no index buffer and no second draw call.
  - Uniforms: u_res (vec2), u_time (float, seconds), u_mouse (vec2),
    and three vec3 brand colours c1, c2, c3.
  - Include a value-noise function and a 5-octave fbm built on it. Every
    shader below is made of those two.

THE SHADER — curtains

        For each of three curtains, define a line across the screen:
        y = 0.45 + sin(uv.x * (2+i) + t * (1.3 + i*0.4)) * 0.14, displaced further
        by an fbm sample so it drifts rather than oscillating cleanly.

        Light each one with exp(-abs(uv.y - y) * (7 + i*3)). The exponential is the
        point — a gradient stop cannot give you that soft vertical bleed, and every
        attempt to fake it with a blur looks like a blur.

        Sum the three, mix c1 to c2 horizontally, push toward c3 where the light is
        strongest, and multiply by the summed band plus a small floor so the sky is
        not pure black.

PERFORMANCE — this is where shader pages usually go wrong

Cost is per pixel, so resolution is the only dial that matters. Cap
devicePixelRatio at 1.5. Pause the render loop with IntersectionObserver
when the canvas leaves the viewport, and on document visibilitychange —
a shader burning the GPU behind a hidden tab is why laptops get hot on
portfolio sites.

If getContext('webgl') returns null, paint a layered CSS radial-gradient
in the same three colours instead. A static gradient is a fine outcome;
a black rectangle is not.

Under prefers-reduced-motion, draw exactly one frame at t=3.0 and stop.

THE PAGE ON TOP

Full-height hero with the content bottom-aligned, so the shader owns the
upper two-thirds. A linear-gradient veil from the background colour at
the bottom to transparent at 58%, so the type sits on solid colour while
the field stays visible above it.

Headline at clamp(3rem, 9vw, 8rem), weight 700, letter-spacing -0.035em,
capped at 11 characters per line, with one word carrying a gradient fill
from the same three colours.

A fixed nav with mix-blend-mode: difference, so the links invert against
whatever the shader is doing underneath and stay readable without a bar.

Below the hero, a marquee strip and three cards explaining the technique.

RULES
The canvas stays at every breakpoint — it is the reason the page works.
Drop the nav links and the card grid to one column below 880px.

More in Shaders

Install 3D Website Full screen, opens straight from your home screen.