Ok. So I have a game I am working on with a bunch of colored particles. Each of them gets their own color however they are all close to a specific shade.

To explain that better I am using the HSV color space, and I have a global variable that is cycling from 0-360 (H) and each of the specific particles add or subtract a random amount from that.

enter image description here I use HSV because it is the easiest way for me to cycle through colors because you can just change H.

This looks very nice and all, however the particles are supposed to be pure light that is colored. Right now all they are are circles colored with the shade, but later on I might add glow effects and other shading techniques.

The problem is that not all shades (I dont mess with H or V) are equal as far as the brightness our eyes see, and this causes problems. For example when all of them are shades of blue things look pretty dark.

Obviously in the shader I have to convert these HSV colors to RGB colors and doing some math I quickly saw what was wrong... the colors didn't have equal luminance!

As I understand it luminance is roughly (0.2126*color.r + 0.7152*color.g + 0.0722*color.b) which is why everything is off.

Is their a way to get it so I can still get all of the different chroma (colors on the wheels degrees) while maintaining a high luminance? Perhaps I should work with a different type of color then HSV, or perhaps their is a formula that finds a color at degree x on the color wheel with luminance of y?

Thanks much!

  • \$\begingroup\$ There are limits to this unfortunately. If you look at a perceptually-uniform colour space like the Munsell colour system, you'll see that bright yellow has a much higher perceived value than a strong blue. That means if you want to keep uniform perceived value/luminance, then you can get either a rich royal blue paired with a dark ochre in the yellow hue, or a bright yellow with pale baby blue. Either way you sacrifice some saturation somewhere in the colour wheel. \$\endgroup\$ – DMGregory Feb 15 '16 at 15:17
  • 1
    \$\begingroup\$ As you noted, RGB and HSL are designed around possible screen colors and not around human eyes. Take a look at HUSL and HCL. Sometimes I'll use L*a*b* too. \$\endgroup\$ – amitp Feb 15 '16 at 17:05
  • \$\begingroup\$ @amitp those color spaces seem to be fairly new and I am seeing some difference in how they color spaces are defined, and how they are converted. Which source would be the most reliable for this? \$\endgroup\$ – J.Doe Feb 16 '16 at 6:25
  • \$\begingroup\$ I'm on a bus, so I better not write a formal answer, but here's what lies underneath the problem: you're going to need to solve a equation system where you plug three variables: Hue, Luminance and Saturation. So here you're searching for a specific Value, given H and S, that meets the condition of having certain luminance. Not quite hard. But you'll soon find out that some colors can't get as luminous as some (try finding a blue as luminous as a 100V yellow), so you may want to clamp the values, in order to get values representable on the screen. \$\endgroup\$ – Gustavo Maciel Feb 18 '16 at 0:40
  • \$\begingroup\$ Yeah I've been working on that. I got a recursive formula going... AND a non recursive one (that isn't quite working). \$\endgroup\$ – J.Doe Feb 18 '16 at 0:43

HCY could be better for your needs. According to Wikipedia's HSL and HSV page, the problem you're having with HSV -- that the same "V" with different hues doesn't correspond to human perception -- is similar with HSL, but HCY could suit your needs -- the "Y" in HCY is for "luma":

Luma is roughly similar [in lightness to the original color image], but differs somewhat at high chroma. HSL L and HSV V, by contrast, diverge substantially from perceptual lightness.

HCY is described in the Wikipedia page as "luma/chroma/hue". This page, on the other hand, appears to use the "HCY" shorthand and shows how to convert it to and from RGB.

  • 2
    \$\begingroup\$ Your alternative division suggestion won't work for colours like blue (0, 0, 1) - because we can end up saturating the range of our primaries before reaching the desired luma. A blue phosphor on the player's screen can't be driven arbitrarily brightly (though HDR could dim the rest of the screen to try to give the illusion that the blue is as bright. Or you could set your luma target to 0.0722 to be able to divide any colour to that luma, at the cost of very dark colours overall) \$\endgroup\$ – DMGregory Feb 15 '16 at 15:02
  • \$\begingroup\$ Good point. I'll improve that part of the answer. \$\endgroup\$ – Jibb Smart Feb 16 '16 at 1:52
  • \$\begingroup\$ There are a bunch of ways to improve the alternative suggestion, but it gets quite complex before actually getting the kind of results OP likely wants, so I removed my alternative. HCY should suffice. \$\endgroup\$ – Jibb Smart Feb 16 '16 at 2:07
  • \$\begingroup\$ I am doing some experimentation with all of this. I will be updating in couple days to see how these color spaces preform. Thank you guys so much! \$\endgroup\$ – J.Doe Feb 16 '16 at 5:52
  • \$\begingroup\$ @DMGregory could you please explain more about what you mean by "set your luma target to 0.0722 to be able to divide any colour to that luma, at the cost of very dark colours overall"? \$\endgroup\$ – J.Doe Feb 16 '16 at 6:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.