[HN Gopher] A flowing WebGL gradient, deconstructed
___________________________________________________________________
A flowing WebGL gradient, deconstructed
Author : alexharri
Score : 206 points
Date : 2025-04-12 10:54 UTC (4 days ago)
(HTM) web link (alexharri.com)
(TXT) w3m dump (alexharri.com)
| mwkaufma wrote:
| >> The mix function is an interpolation function that linearly
| interpolates between the two input colors using a blend factor
| between and ( in our case).
|
| >> A mix function for two colors works the same way, except we
| mix the color components. To mix two RGB colors, for example,
| we'd mix the red, green, and blue channels.
|
| Colorspace alert! mix != lerp in sRGB
| danwills wrote:
| Quite right! I think if the values were linearized (~gamma 0.5)
| lerp might be mostly ok though, right?
|
| And what about doing rgb->hsv, then lerp, then hsv->rgb? I'm
| unclear whether that also needs linearization, or whether the
| gamma can maybe just be done to the 'v' component before
| lerping?
|
| Color is a surprisingly deep and fascinating topic, that's for
| sure! :)
| pornel wrote:
| Mixing of colors in an "objective" way like blur (lens focus)
| is a physical phenomenon, and should be done in linear color
| space.
|
| Subjective things, like color similarity and perception of
| brightness should be evaluated in perceptual color spaces.
| This includes sRGB (it's not very good at it, but it's
| trying).
|
| Gradients are weirdly in the middle. Smoothness and matching
| of colors are very subjective, but color interpolation is
| mathematically dubious in most perceptual color spaces,
| because [?](avg(a+b)) [?] avg([?](a) + [?](b))
| mwkaufma wrote:
| Perceptual colors -- both sRGB and HSB -- are nonlinear, so
| you can't expect linear combinations to produce meaningful
| results (they often "interpolate through mud").
|
| If you just want optical phenomena, you can just convert to
| luminescence -- WegGL and other modern graphics APIs actually
| does this internally when you load or render textures, so all
| shaders are handling optically-linear data, which is why the
| shader-produced images in the post look better than the
| javascript gradients.
| eurekin wrote:
| Googled "luminescence" and OpenGL -- don't seem to return
| relevant results. Could you point to where it's described?
| virtualritz wrote:
| Luminance[1], not luminescence[2].
|
| [1] https://en.wikipedia.org/wiki/Luminance
|
| [2] https://en.wikipedia.org/wiki/Luminescence
| mwkaufma wrote:
| Lol autocorrecttt ty
| itishappy wrote:
| To be fair, lerp still mixes colors, it just mixes ugly colors.
| immibis wrote:
| (1,0,0) and (0,0,1) are each twice as bright, in terms of
| photons, as (0.5,0,0.5).
|
| If you quickly apply gamma=2 so the midpoint is
| (0.707,0,0.707) your gradient will look much better. Although
| other commenters suggested mixing in more complicated colour
| spaces.
| rikroots wrote:
| I agree with the colorspace alert. Lerping red and blue in
| OKLAB or OKLCH colorspace produces a much nicer effect. Also,
| the article details linear interpolation, but I think there's a
| lot of fun to be had by introducing some easing functionality
| into the interpolation[1] - it's not difficult to achieve in
| code, even in shader code?
|
| I do disagree with the article about the need to do such work
| in the WebGL space. Modern CPUs are insanely fast nowadays, and
| browsers have put in a lot of work over the past few years to
| make the Canvas 2D API as performant as possible - including
| moving as much work as possible into the GPU behind the scenes.
| With a bit of effort, gradients can be animated in 2D canvases
| in many interesting ways![2][3]
|
| [1] - Easing a linear gradient in different color spaces:
| https://scrawl-v8.rikweb.org.uk/demo/canvas-003.html
|
| [2] - Animated gradient effect:
| https://codepen.io/kaliedarik/pen/poRLBLp
|
| [3] - Animating a gradient over a live video feed:
| https://codepen.io/kaliedarik/pen/MWMQyJZ
| meindnoch wrote:
| WebGL/OpenGL doesn't use sRGB in the shaders. If you load an
| sRGB texture, or render to an sRGB surface, the API
| automatically applies the gamma- (or inverse gamma) curve, so
| the shader only ever sees the linear values.
| kookamamie wrote:
| Correct, it uses just numbers without any specific
| information about a colorspace being involved. Decoding and
| encoding sRGB happen during (texture) read and write stages.
| sly010 wrote:
| Very cool, but by css-rotating (skewY(-6deg)) the canvas at the
| last moment, you introduced aliasing on the border between the
| canvas and the rest of the page which kills the vibe. The browser
| can't automatically blend the canvas with the rest of the page.
| It's noticeable even on a brand new retina display. Maybe you
| could keep your canvas square and introduce the skew in the
| shader.
| danwills wrote:
| Guess it depends on the browser as it looks sharp and free of
| aliasing for me, including when zooming in (Opera on Android)
| herpdyderp wrote:
| - Safari: decent but still obviously present - Chrome:
| quite bad looking - Firefox: something in between
|
| (tested on macOS)
| andrewmcwatters wrote:
| The funny thing is, as far as I know, skewY is a virtual draw
| command in the WebKit family of rendering engines.
|
| It's "in the shader" already. For whatever reason, your
| browser's compositor is failing to anti-alias the rendering
| bounds of the canvas.
|
| I don't know why, though. I don't see the issue in Safari on my
| system.
| vanyle wrote:
| As a workaround, you can add a transparent border (border: 2px
| solid transparent) around the skewed element to have
| antialiasing (at least on chrome)
| herpdyderp wrote:
| The linked source code [0] doesn't seem to have any license
| attached to it. So how could I actually use this? Is it published
| as a package somewhere, like npm?
|
| 0.
| https://github.com/alexharri/website/blob/eb9551dd7312685704...
| alexharri wrote:
| Hmm, good point. I'm abroad this week and don't have a laptop,
| but I'll look at adding an MIT licence to the shader itself
| when I'm home. (I don't want the post contents to be MIT
| licensed, but the website code and examples should be)
|
| Thanks for raising this
| ikesau wrote:
| Jesus christ, this is _such_ a polished article. Writing it must
| have taken at least 5 times as long as the shader!
|
| Have reblogged it and will refer back to it if ever I have some
| time to learn how to write them :)
| alexharri wrote:
| Thanks a lot! Yeah tons of work went into this post, I've been
| working on it since November. The shader itself was about 2-3
| weeks of evenings to get the effect 90% of the way
| heinternets wrote:
| This looks very smooth. Would this be in 10 bit colour if the
| display supports it? I can't see any banding even when zoomed in
| Safari or Brave on a MBP with HDR display.
| polygot wrote:
| Reminds me of the JetBrains installer--not a bad reminder, I like
| the animations.
| mrmagoo17 wrote:
| We need more articles as polished as this one. WebGL is a topic I
| wanted to get into for a while now but it's really difficult to
| find good content about it. Please keep sharing more experiments!
| flashblaze wrote:
| Could not agree more. Heard good things about
| https://webgl2fundamentals.org/, but I think it directly jumps
| into code without any background as such. At least that is what
| I felt. Not sure whether this is the only way to go about
| teaching WebGL.
| loige wrote:
| Thanks for sharing this one. I was looking for more material
| too!
| fallinditch wrote:
| Great post Alex, the gradients are lovely, I'm just starting to
| play around with webgl so the timing is perfect ...
| ww520 wrote:
| This is a great read. Very instructional. Build from simple
| concepts and explain clearly. Kudos for the work.
| qiqitori wrote:
| Nice, it's a bit like an extremely modern version of the oldskool
| plasma effect!
| tomaskafka wrote:
| The whole time I was expecting just a 2d height field ("terrain")
| with animated noise as z, overlooked from an angle by an
| isometric camera, it could imo produce a same effect in a much
| simpler way (and without need for expensive blur), right?
| akx wrote:
| The blur here isn't expensive (as discussed in the article
| itself).
|
| Chances are sampling a 2D height field and projecting, etc.
| would be more expensive.
| grishka wrote:
| This effect kinda reminds me of the PSP menu background
| cloogshicer wrote:
| Fantastic post, very well written.
| kemuri wrote:
| Amazing writeup, very inspiring!
| kookamamie wrote:
| Looks pretty nice. I think there'd be a way of computing the
| blurriness without the iterative approach and without the
| aliasing produced in the process.
| smjburton wrote:
| This is so cool. These flowing gradients have a mesmerizing
| effect (almost like watching a lava lamp), and seem like a great
| way to add visual interest to a page. I'll have to play around
| with this and see if I can incorporate these flowing gradients
| into some of my web projects. Awesome job detailing the design
| process for this post.
| zparky wrote:
| This is an exemplary post and what I come to HN for.
| nyarlathotep_ wrote:
| This is an excellent article. Thanks for this.
___________________________________________________________________
(page generated 2025-04-16 17:02 UTC)