Posted by alexharri 7 days ago
>> 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
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
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! :)
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.
Legacy OpenGL APIs used to assume sRGB, so you had to specify GL_LUMINANCE for non-color 'intensity' maps (which couldn't be blitted to FBOs, e.g.).
Modern OpenGL assumes linear color, so instead you have to specify sRGB on texture load to direct the driver to do colorspace conversion (e.g. GL_SRGB8 for typical RRGGBB byte triples).
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))
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.
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.
- Safari: decent but still obviously present
- Chrome: quite bad looking
- Firefox: something in between
(tested on macOS)0. https://github.com/alexharri/website/blob/eb9551dd7312685704...
Thanks for raising this
Have reblogged it and will refer back to it if ever I have some time to learn how to write them :)
Chances are sampling a 2D height field and projecting, etc. would be more expensive.