I've been making some tests with the latest version of CefGlue (for CEF tag v3.2454.1320.g807de3c), with the WPFOsr sample.
The problem happens when you try to render something with alpha applied and instead of rendering against the background it renders against black (or at least ir seems).
My tests are simple:
- Set the WpfCefBrowser.AllowsTransparency to True;
- Load an HTML with a DIV with white background and alpha to 0.5;
Result:
- Instead of a White rectangle you get a Grey rectangle;
I've tried against a pattern background and the results (obviously) are the same.
Some examples:
Image on the left: Result against a white background.
Image on the right: Expected result against a white background.
.
Image on the left: Result against a pattern background.
Image on the right: Expected result against a pattern background.
Test.html:
- Code: Select all
<html lang="us">
<head>
<style>
#normal{ width: 350px; height: 350px; background-color: rgba(255,255,255,1.0); position: absolute; top: 25px; left: 25px; outline: #000000 solid 5px;}
#alpha{ width: 350px; height: 350px; background-color: rgba(255,255,255,0.5); position: absolute; top: 25px; left: 410px; outline: #000000 solid 5px;}
p{position:relative; top:350px;}
</style>
</head>
<body>
<div id="normal"><p>NORMAL</p></div>
<div id="alpha"><p>ALPHA</p></div>
</body>
</html>
After spending some time searching and reading the web for the issue I now know that both Skia and WPF have their workflow using premultiplied alpha so I've decide to write a simple Shader that demultiplies the RGB component, and applied it to the the CefBrowserWindow. Although it works quite fine for the majority of the cases, the problem with this solution is that it is lossy and the errors aggravate in the regions where the alpha value is near zero. So you get this:
Image on the left: Result with the shader applied. Notice the posterize effect on the glare.
Image on the right: Expected result.
Code for the shader:
- Code: Select all
sampler2D input : register(s0);
float someInput : register(c0);
float4 main(float2 uv : TEXCOORD) : COLOR {
float4 src = tex2D(input, uv);
float4 dst = src;
dst.rgb /= src.a;
return dst;
}
I've tried this same example with the CEFClient sample of this build (generated the VisualStudio solution with CMake), tested with the command-line switches "-off-screen-rendering-enabled -transparent-painting-enabled" and in client::OsrRenderer - void OsrRenderer::Render() changed the gradient to a white and opaque background. The result was OK, the alpha is correctly rendered and applied against the background.
I've also checked the buffer for the given viewrect passed to the internal void HandlePopupPaint(int width, int height, CefRectangle[] dirtyRects, IntPtr sourceBuffer) in the WpfCefBrowser class of CefGLue and it is (as expected?) with the alpha already premultiplied.
It seems to me that the WPF control isn't handling the rendered image from CEF correctly. Shouldn't the image be blendeded against the control's background instead of a black background, so you can achieve real transparency when it's enabled?
Thanks in advance,
Best regards
P.S.: sorry for the long post, tried to provide as much information as possible.