In our codebase, we have a system where players can choose their body colour and it get's applied to their mob's base sprite using ICON_ADD.
ICON_ADD is terrible since it adds a heavy white bias to the mob's appearance, because it basically takes the two RGB values and adds them. The person who implemented the system ended up darkening all the base sprites to compensate, but this is unsatisfactory as it reduces the amount of dynamic range available for showing details on the sprite.
Someone with more knowledge in graphics suggested we use ICON_MULTIPLY instead, but I'm a little unsure about it because I don't understand how it works.
How is it possible to multiply two RGB values and remain within the 8-bit channel range? Does it rescale the values after multiplication? How does it do so? Square root? Linear rescaling?
Ah, I see it would introduce a black bias then, because of the way multiplying numbers less than 1 always tends to zero.
Also if you blend two identical colours this way, you get a darker colour. Still, it seems better than adding RGB colours by a long shot. Do you know if there is a way to implement a custom colour blend mode? I'm thinking taking the square root of the product of the two colours would be much better. |
MapColors would be your best bet for better control, but as with any function LummoxJR has introduced to the software suite, it's as powerful as it is difficult to understand.
|
Just to make sure I understand MapColors right, it replaces each channel in the new colour with a weighted sum of the channels of the old colour?
So r_new = rr*r_old + rg*g_old + rb*b_old + ra*a_old + r0, etc? Or to put it another way, if colour_new and colour_old are vectors (r,g,b,a), then: colour_new = M*colour_old + (r0, b0, g0, a0) where M is the matrix: [ rr, rg, rb, ra ] Do I understand this correctly? I'm not so sure if this will work for my purposes, as what I want to do is make (r,g,b,a) a function of the old colour and the colour being blended in. Unless there is a way I can pass in a function to MapColors and have it use that as the elements of M. |
Alright. I just wish there was a way to blend colours that resulted in each channel having the square root of the product of that channel from two colours.
That way I wouldn't have to go and modify all of our icons to support colour blending. It also seems like it would be more useful than the current ICON_MULTIPLY in general, as it has the nice property of keeping the colour unchanged when two identical colours are blended together. |
LummoxJR wrote a library with some uses of MapColors(). The ColorTone() proc in particular may do about what you want:
http://www.byond.com/developer/LummoxJR/IconProcs http://www.byond.com/forum/?post=51608 |
So 255 would be 1, and 0 would be 0.
The math works out to be:
or shorthand: