Build a scroll-driven WebGL hero in 30 lines This article provides a tutorial for creating a scroll-driven WebGL hero section using approximately 30 lines of JavaScript, two MIT-licensed npm packages, and no framework or build step. The implementation uses two images, a shader that morphs between them based on scroll position, and a `scrollPlateau` function that reshapes linear scroll progress into a bathtub curve to ensure the destination image is visible longer. The tutorial also highlights 60 built-in transitions that can be swapped in with a single identifier change, such as `crossZoom`, `pageCurl`, or `paintBleed`. Hero sections that respond to scroll are one of those features that look complicated and actually aren't, once you have the right pieces. Two images, a shader that morphs between them, scroll position drives the morph. That's it. The rest is plumbing. This tutorial builds exactly that — a scroll-driven WebGL hero — in about 30 lines of JavaScript. Plain HTML, no framework, no build step. Drop it into a CodePen or a static HTML file and it works. What we're building Three behaviors, tied together: - As the user scrolls down into the hero section, image A morphs into image B. - While the hero is centered in the viewport, the morph holds on image B. - As the user scrolls down past the hero, image B morphs back to image A. That's the standard scroll-driven hero shape. Sites like Apple's product pages, Linear's marketing, and Vercel's case studies all use this pattern. The trick is the holding part — without it, the transition feels like it ends too fast and the user never sees the destination. The dependencies Two npm packages, both MIT, both tiny. pnpm add @vysmo/scroll @vysmo/transitions Combined, that's about 6 KB gzipped. Less than a logo SVG. The HTML A section, a canvas, two