Open wobbier opened 3 years ago
We have the same issue with our SVG logo on CPU renderer.
Hello!
Sorry it took so long to get back to you-- the reason for the black-fringe is because Bitmaps are actually encoded with premultiplied alpha, see the following note about color-space in the in-header documentation:
/// Blue Green Red Alpha channels, 32-bits per pixel.
///
/// Encoding: 8-bits per channel, unsigned normalized.
///
/// Color-space: sRGB gamma with premultiplied linear alpha channel.
///
kBitmapFormat_BGRA8_UNORM_SRGB,
We use premultiplied alpha throughout Ultralight for a number of reasons, you can read up a bit more here: https://developer.nvidia.com/content/alpha-blending-pre-or-not-pre
When displaying premultipled alpha bitmaps in your engine you'll need to make sure your blend function is set correctly.
For OpenGL: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
For D3D11: See AppCore's D3D11 blend state here.
This dive into alpha compositing did identify a bug in Bitmap::WritePNG
-- the PNG format expects straight alpha (eg, RGB channels should not be pre-multiplied with the alpha channel). Rather than modifying Bitmap::WritePNG
(which is primarily used for debug to inspect the state of the bitmap), I've decided to add a new function Bitmap::ConvertToStraightAlpha
which can be called before calling Bitmap::WritePNG
to encode transparency in a format that most image viewers expect.
To verify the results are accurate, here is a render of the following HTML with the CPU renderer, written to disk via Bitmap::ConvertToStraightAlpha()
and Bitmap::WritePNG
:
<html>
<head>
<style type="text/css">
body {
margin: 0;
padding: 0;
overflow: hidden;
color: white;
font-family: Arial;
/* Linear gradient from seafoam green to fully transparent */
background: linear-gradient(rgba(51, 253, 184, 1.0), rgba(51, 253, 184, 0.0));
display: flex;
justify-content: center;
align-items: center;
font-size: 4em;
}
</style>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
So the issue I'm experiencing is when using white text on a transparent background while using the C++ CPU renderer.
I've tried 1.2 and this 1.3 commit.
The HTML is just a simple div with text and 'body { background: transparent; color: white; }' for the CSS
The raw output of bitmap->WritePNG(path);
I have a GitHub dark mode on so adding the raw image on top of a white background for clarity:
The final pass of my game view: