4

Problem Description

Hi! I'm creating a WebGL 2.0 vector shapes renderer and I'm facing a serious problem that I don't know how to resolve. My current rendering pipeline looks like this:

  1. I'm drawing shapes in my shaders with premultiplied colors in linear RGB space.
  2. When two shapes overlap I'm blending them (either in shaders or in render passes) using blendEquationSeparate(FUNC_ADD,FUNC_ADD); blendFuncSeparate(ONE,ONE_MINUS_SRC_ALPHA,ONE,ONE_MINUS_SRC_ALPHA );. See the link to learn more why: http://www.realtimerendering.com/blog/gpus-prefer-premultiplication
  3. After all the shapes are drawn, the colors of the final buffer are unpremultiplied, converted to sRGB space, and premultiplied again. It results in premultiplied sRGB color space, which is what the browser want for me (as far as I am aware).

However, it seems that the browser does the alpha blending in sRGB space instead (not linear one). This gives very strange results, especially on big, transparent areas (that I need). In order to clearly see the problem, consider the screenshot below:

enter image description here

What you see here is a red circle on 2 green backgrounds. The green background on the right side of the picture is a background composed in my shaders in a linear sRGB space. The background on the left side of the picture is just an HTML website. As you can see, my color blending is correct (do not have dark transition pixels). More info about why blending in linear space is the correct one is here: http://www.realtimerendering.com/blog/?s=srgb

Here is a more convincing example - it's a shadow. Top of the image is composited in linear RGB (correct way), the bottom is composited by Chrome in sRGB space (incorrect way):

enter image description here

Unfortunately, it seems that the browser composer works in sRGB space. Even if we do 2 divs, they are blended in the wrong way

.circle{
    position:absolute;
    background:#ff0000;
    width:100px;
    height:100px;
    text-align:center;    
    -webkit-border-radius: 50px;  
    -moz-border-radius: 50px;  
    border-radius: 50px;
}


.circle2{
    position:absolute;
    margin-left:40px;
    background:#00ff00;
    width:100px;
    height:100px;
    text-align:center;    
    -webkit-border-radius: 50px;  
    -moz-border-radius: 50px;  
    border-radius: 50px;
}
<div class="circle"> </div>
<div class="circle2"> </div> 

Question

The question is simple - are we able to somehow ask the browser (I'm asking both for cross-browser as well as a browser-specific solution) to blend the WebGL canvas with the HTML in the background in linear RGB space?

LJᛃ
  • 7,655
  • 2
  • 24
  • 35
Wojciech Danilo
  • 11,573
  • 17
  • 66
  • 132
  • No idea but [here's some multi year old discussion](https://github.com/WICG/canvas-color-space/blob/master/CanvasColorSpaceProposal.md) which leads down a long rabbit hole of threads and proposals – gman Feb 12 '20 at 02:39
  • @gman thank you for editing and making the question nicer! I was already browsing this thread you've linked and it left me a little bit hopeless :( I've seen a lot of threads on Chrome mailing list about adding support for selecting canvas color profile, but it seems nothing was ever implemented. I still hope I am wrong. – Wojciech Danilo Feb 12 '20 at 02:41
  • Following a few of the threads it clearly is a bigger issue than just WebGL and canvas. Like should it be a CSS setting (to fix your div example). If it is a CSS setting what happens if 2 elements are set to use different color spaces, in what space are they blended. If you set it for the body what happens on iframes and shadow elements? etc... it's quite a mess :( – gman Feb 12 '20 at 02:45
  • @gman definitely, there are some more complex cases, but hmm, please correct me if I'm wrong, blending colors in sRGB is just the worst of all solutions. So even switching to just always blend in linear RGB would be much better. Of course, it would be super cool to be able to fine tune the color space for particular needs, but ugh, leaving only sRGB just kills any proper WebGL <> HTML blending. – Wojciech Danilo Feb 12 '20 at 02:49
  • PS: I tested FF and Safari on Mac with your div example. They all do the same so it's not a Chrome issue. They are all just using the GPU's built in blending. – gman Feb 12 '20 at 03:06
  • As for switching eveything to linear it's not that simple. It's slower, there are tons of paths through the browser, OpenGL, DirectX, Metal, CoreGraphics, Skia, there's also software rendernig that would get slower. [Even font rendereing](https://jsfiddle.net/greggman/z8bg2dtk/) and having to deal with cleartype issues, etc. – gman Feb 12 '20 at 03:14

0 Answers0