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! :)
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.
Luminance[1], not luminescence[2].
Googled "luminescence" and OpenGL -- don't seem to return relevant results. Could you point to where it's described?
replace/luminescence/luminance (thanks autocorrect).
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).
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))