I'm sure you're wrong about that black thing. The correct procedure should be: 1) multiply the texture with transparency by foreground, 2) place background color behind and let regular alpha formula (fg*alpha + bg*(1-alpha)) work.
Part of the problem is that after the Multiply, all alpha values are 100% opaque, so the background color never comes into effect. If I understand it right, this SHOULD also mean that the 'background color' never really comes into effect anywhere the source tile was 100% opaque, because the background section of the equation will then always equal 0.
Here is my work with Hematite Ore from the Mayday tileset. I will attempt to provide all of my work with explanations. Note that the only alpha values other than 100% in this image are the corners where it looks kind of light tan-ish. the value there is 40% according to Photoshop, which equates to 102/255.
I am posting these at their actual size, which is 16x16. This is to prevent stretch-distortion from getting in the way. I did all of this work at 16x16, zoomed to full 3200% in Photoshop so I could work at the pixel level easier. Feel free to download and zoom in to look closer.
The Original Source Tile, and the way DF Renders it from the Mayday tileset (Hematite is 'RED' which in Mayday is 200/20/0 RGB, with an LGRAY background, which in Mayday is 190/180/180)
If I use the method I outlined, merging to black first and then multiplying by the red value, you get (Left) Compared with that same image from DF's rendering : (Right)
Notice that the pixel values are virtually identical - close enough that it can be chalked up to rounding errors, most likely.
If I do a straight multiply with the source and the red color, I get :
-- obviously the 'background' corners are way off. the middle is not, because it was 100% opaque anyway. Further adding a LGRAY background and Merging would accomplish nothing, as all alpha values are already 100% now. Doing a Multiply with LGRAY will throw off the colors of the ore itself.
Finally, If I manually calculate the value for the corners, using the equation from the source code and plugging in the numbers into a spreadsheet, I get :
(fg = 200/20/0; bg = 190/180/180; src = 199/178/154; alpha = 102)((alpha * (src * fg)) + ((1-alpha) * bg)) *255
R : ((0.4 * (0.780392 * 0.784314)) + ((1-0.4) * 0.745098) * 255 ==
176.4314G : ((0.4 * (0.698039 * 0.078431)) + ((1-0.4) * 0.705882) * 255 ==
113.5843B : ((0.4 * (0.603922 * 0)) + ((1-0.4) * 0.705882) * 255 ==
108Rounding, I have 176/114/108, and this is what that looks like :
Clearly, THAT is not correct. The only explanation that I could discern was that it was because earlier in the code the texture surface is initialized to black, then the tilemap is loaded onto that. anywhere the tilemap is transparent, it will thus merge with the black, and THEN if you do the multiply with the red color, you get precisely what DF got. (+1 on two values, but again, possibly rounding errors, and damned close enough)
In a nutshell, that's how I reached my conclusion. All of the work shown here was done several times to ensure I made no mistakes mathematically, or in transcribing the numbers to photoshop.
I still want to do the work with other colors, but I don't have the time to finish that tonight. My next shot will be with Copper Ore, as it has a different background color.
If I have still managed to make some kind of critical error somewhere, please don't hesitate to speak up. As is often the case with these types of things, once you've done it so many times, you become blind to mistakes you repeatedly make.