Dynamic Colors
To generate a galaxy full of interesting variety, I knew I would need to reuse textures. This was one of the reasons I switched to OpenGL 2.0, to use shaders to dynamically color textures.
Fragment Shader
To facilitate this, I needed a fragment shader that combined a grayscale texture (0-255) with a hue value (0-360) and a saturation value (0-100). However, OpenGL needs an RGB value, not an HSL value. Writing shaders is new to me, but thankfully I found some help online and came up with this:
precision mediump float;
uniform sampler2D u_TextureUnit;
uniform float u_Alpha;
uniform float u_Hue;
uniform float u_Sat;
varying vec2 v_TextureCoordinates;
vec3 hsl2rgb(vec3 HSL)
{
float R = abs(HSL.x * 6.0 - 3.0) - 1.0;
float G = 2.0 - abs(HSL.x * 6.0 - 2.0);
float B = 2.0 - abs(HSL.x * 6.0 - 4.0);
vec3 RGB = clamp(vec3(R,G,B), 0.0, 1.0);
float C = (1.0 - abs(2.0 * HSL.z - 1.0)) * HSL.y;
return (RGB - 0.5) * C + HSL.z;
}
void main()
{
gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);
vec3 rgb = hsl2rgb(vec3(u_Hue / 360.0, u_Sat / 100.0, gl_FragColor.x));
gl_FragColor = vec4(rgb.r, rgb.g, rgb.b, gl_FragColor.a*u_Alpha);
}
Results
Now using a single texture for a star like this:
I am able to dynamically color stars any hue.
And here is what changing the saturation for a particular hue looks like:
Texture Tools
To help create and test dynamically colored textures, I wrote some tools which can be found here. The following is an example using the current spacedust water texture.
The first script creates a grayscale image from a colored image.
./bin/extract-lightness examples/water.png examples/water-lightness.png
The second script applies a hue (and saturation) to the grayscale image, like the shader does.
./bin/apply-hue 300 39 examples/water-lightness.png examples/water-hue-300.png ./bin/apply-hue 100 39 examples/water-lightness.png examples/water-hue-100.png
HSV vs. HSL
My first attempt at a shader, I mistakenly used HSV instead of HSL. I honestly didn’t know there was a difference. HSV seems to be used more often, and many image editors have HSV color pickers. So that’s what I initially went with.
Simply put, the problem with HSV is the range of colors for a particular hue/saturation does not go from white at its lightest, to black at its darkest, leaving you with a smaller range of color to work with.
So, for example, using this star texture:
Stars colored different hues ended up looking like this:
Not a lot I could do with the limited range of colors. Thankfully HSL solved that problem!
If you are interested in learning more, there is a useful page on Wikipedia about HSV and HSL.
And if you are looking for a good HSL color picker (since many image editors don’t have one), I recommend this web tool, written by Brandon Mathis. You can read about his discovery of HSL here.