GRAPHICS: Improve TTF rendering on transparent surfaces. #2748
Conversation
Update color blending to match blending found in ManagedSurface. TTF rendering assumed the alpha channel of the surface was completely opaque. ULTIMA8 TTF rendering attempts to use a transparent surface and became near-illegible for text on scrolls. This change will affect TTF rendering on surfaces that are not already painted.
This looks good to me. I tried to find other uses of this code to see if there's any potential side-effects but I didn't find any place I thought it could cause any change other than U8. I may have missed something though so if anyone else wants to comment please feel free. |
if (sA > dA) { | ||
dA = static_cast<uint8>((sA * alpha) + (dA * (1.0 - alpha))); | ||
} | ||
|
criezy
Feb 18, 2021
Member
Where do those formula come from?
My understanding of color blending is that it should be:
double sAn = (double)sA / 255.0;
double dAn = (double)dA / 255.0;
dR = static_cast<uint8>(sR * sAn + dR * dAn * (1.0 - sAn) / (sAn + dAn * (1.0 - sAn)));
dG = static_cast<uint8>(sG * sAn + dG * dAn * (1.0 - sAn) / (sAn + dAn * (1.0 - sAn)));
dB = static_cast<uint8>(sB * sAn + dB * dAn * (1.0 - sAn) / (sAn + dAn * (1.0 - sAn)));
dA = static_cast<uint8>(sA + dA * (1.0 - sAn));
This also means there is no need for a special case if dA
is 0.
And you can of course optimise that code a bit by computing dAn * (1.0 - sAn)
only once instead of 6 times.
Where do those formula come from?
My understanding of color blending is that it should be:
double sAn = (double)sA / 255.0;
double dAn = (double)dA / 255.0;
dR = static_cast<uint8>(sR * sAn + dR * dAn * (1.0 - sAn) / (sAn + dAn * (1.0 - sAn)));
dG = static_cast<uint8>(sG * sAn + dG * dAn * (1.0 - sAn) / (sAn + dAn * (1.0 - sAn)));
dB = static_cast<uint8>(sB * sAn + dB * dAn * (1.0 - sAn) / (sAn + dAn * (1.0 - sAn)));
dA = static_cast<uint8>(sA + dA * (1.0 - sAn));
This also means there is no need for a special case if dA
is 0.
And you can of course optimise that code a bit by computing dAn * (1.0 - sAn)
only once instead of 6 times.
OMGPizzaGuy
Feb 19, 2021
Author
Member
Mostly followed suit with managed_surface.cpp:487-490
Figured if case for dA is 0 might be better to avoid calculations, but perhaps not.
Destination alpha... I just wasn't sure the best call.
Mostly followed suit with managed_surface.cpp:487-490
Figured if case for dA is 0 might be better to avoid calculations, but perhaps not.
Destination alpha... I just wasn't sure the best call.
OMGPizzaGuy
Feb 19, 2021
Author
Member
OK, looking at https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
If I'm understanding it correctly, what I used would be correct for dA being 255, but not complete enough for any other value.
I'll take another swing at this.
OK, looking at https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
If I'm understanding it correctly, what I used would be correct for dA being 255, but not complete enough for any other value.
I'll take another swing at this.
OMGPizzaGuy
Feb 19, 2021
•
Author
Member
Yep, the suggested code was great.
I went with calculating a normalized output alpha and converting that to a byte at the end.
I thought it would be a little more clear to anyone reading the code.
Yep, the suggested code was great.
I went with calculating a normalized output alpha and converting that to a byte at the end.
I thought it would be a little more clear to anyone reading the code.
Thank you. It looks good to me now. |
Update color blending to match blending found in ManagedSurface. TTF rendering assumed the alpha channel of the surface was completely opaque. ULTIMA8 TTF rendering attempts to use a transparent surface and became near-illegible for text on scrolls. This change will affect TTF rendering on surfaces that are not already painted.