I've a 2d background, some sprites, blitted onto it. And over all that in the final pass I draw colored lights, to make projectiles look cooler. Basically I apply a classic lightmap, which is colored in the process of blitting.

With RGB I used simple, but incorrect code:

//dr,dg,db - source before highlight
//e = light energy
//lr,lg,lb - color filter applied to the light energy
ResultColor = RGB(lighten(dr,e*lr),lighten(dg,e*lg),lighten(db,e*lb));

//light energy divisor (0x100*4*32)
#define EDIV 15
uint8_t lighten(int t, int e) {
  return clamp_byte(t + ((t*e)>>EDIV));

Now in CIE-style spaces, instead of RGB, we have luminance coordinate (L in LUV, or Y in XYZ), and two chroma coords, picking the chroma inside the color triangle.

Calculating light in CIE appears to be simple, it is just:

result_light = dst_light*incoming_light

But what about XZ or UV? I tried doing simple averaging:

result_x = 0.5*dx + 0.5*lx;
result_z = 0.5*dz + 0.5*lz;

but it gave too bland of a result, compared to the original RGB color-filter:

enter image description here

Maybe instead of taking 0.5, these weights should depend on the light component somehow? If so, what is the proper matrix? I'm sure it can exist, because the transform from CIE XYZ to RGB is linear.

  • \$\begingroup\$ The matrices for converting CIE XYZ to RGB (or vise versa) depend on RGB working space & the reference white. If an overview description of that is all that you want, I can write it up & post it; if you want more than that it might help if your question described the overall game effect you are trying accomplish. If you need to get into the details on color space math, the Computer Graphics SE might be a better place to ask. \$\endgroup\$
    – Pikalek
    Aug 16, 2019 at 13:50
  • \$\begingroup\$ I want projectiles to light environment in their color. I.e. a fireball would give its surrounding orange tint, in addition to increasing brightness. On the attached GIF I want more meaty red, instead of just a pink hint of red, I got with (dx+sx)/2. In my case I use RGB white, and an equilateral triangle, instead of CIE one, because equilateral triangle is easier to fit inside 256x256 quad, without sacrificing too much precision, but that doesn't really affect the math, as XYZ are still linear. \$\endgroup\$ Aug 16, 2019 at 15:41


You must log in to answer this question.

Browse other questions tagged .