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:
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.