A flowing WebGL gradient, deconstructed

https://news.ycombinator.com/rss Hits: 17
Summary

A flowing WebGL gradient, deconstructedApril 12, 2025A few weeks ago I embarked on a journey to create a flowing gradient effect — here’s what I ended up making: This effect is written in a WebGL shader using noise functions and some clever math. In this post, I’ll break it down step by step. You need no prior knowledge of WebGL or shaders — we’ll start by building a mental model for writing shaders and then recreate the effect from scratch. We’ll cover a lot in this post: writing shaders, interpolation, color mapping, gradient noise, and more. I’ll help you develop an intuition for these concepts using dozens of visual (and interactive!) explanations. If you just want to see the final code, I’ll include a link to the shader code at the end of the post (this blog is open source so you can just take a look). Let’s get started! Color as a function of position Building the gradient effect will boil down to writing a function that takes in a pixel position and returns a color value: type Position = { x: number, y: number }; function pixelColor({ x, y }: Position): Color; For every pixel on the canvas, we’ll invoke the color function with the pixel’s position to calculate its color. A canvas frame might be rendered like so: for (let x = 0; x < canvas.width; x++) { for (let y = 0; y < canvas.height; y++) { const color = pixelColor({ x, y }); canvas.drawPixel({ x, y }, color); }} To start, let’s write a color function that produces a linear gradient like so: To produce this red-to-blue gradient we’ll blend red and blue with a blend factor that increases from to over the width of the canvas — let’s call that blending factor . We can calculate it like so: function pixelColor({ x, y }: Position): Color { const t = x / (canvas.width - 1);} Having calculated the blending factor , we’ll use it to mix red and blue: const red = color("#ff0000");const blue = color("#0000ff"); function pixelColor({ x, y }: Position): Color { const t = x / (canvas.width - 1); return mix(red, blue, t)...

First seen: 2025-04-15 22:14

Last seen: 2025-04-16 14:18