Compositor behaviour with premultipliedAlpha

30 views
Skip to first unread message

Daniel Lewis

unread,
Mar 13, 2023, 4:51:43 PM3/13/23
to WebGL Dev List
I wonder if anyone can shed light onto what's happening on some browsers with this rather simple HTML document.

This page has an <img> behind a <canvas>, which is a WebGL canvas with {premultipliedAlpha: true} set in its context attributes.

    https://madeinhaste.github.io/webgl-premultipliedalpha-quirk/

I'm rendering 3 orange gradients onto this WebGL canvas (just using scissor/clear for simplicity - hit "view page source" to see the full code):

1) the first gradient is (rgb * alpha, alpha), where I would expect a "normal"/"source-over" interaction with the background, fading from opaque to transparent.

2) the second gradient is (rgb * alpha, 0), where I was hoping for an additive effect on the background.

3) the third gradient is (rgb * alpha, 1/255), which I'd expect to be similar to the second.

(You can mouse over the canvas to see the pixel values read back from the drawing buffer).

For me, the appearance of this page depends on the browser:

- Chrome & Firefox on Linux, Firefox on Windows 10, Safari on my iPhones 7 & 14, Chrome on my Pixel 3, all display gradients 1, 2 & 3 "correctly" - that is, with normal and additive blending effects.

- Chrome & Edge on Windows 10, and Chrome & Safari on a MacBook running Ventura display only gradients 1 & 3. The second gradient with alpha=0 is invisible.

I can't see anything in the WebGL spec about intended blending behaviour, and so far I have not found any other posts about this. Just wondering if anyone has any insight as this variance surprised me a little.

Dan.

Ken Russell

unread,
Mar 13, 2023, 5:34:53 PM3/13/23
to webgl-d...@googlegroups.com
Hi Dan,

Specifying "premultipliedAlpha:true" tells the browser that you are promising to produce colors where the alpha channel is already multiplied into the color channel. Your gradients (2) and (3) violate this invariant because the values in the red, green, or blue channels are greater than the alpha channel. The compositing results are undefined in this situation.

I'm not sure whether it's possible to achieve the blending results you want with the browser's compositing. Even if you specify "premultipliedAlpha:false" during WebGL context creation - which isn't recommended as it incurs a run-time performance penalty - the browser will multiply the alpha channel into the color channels itself, and then perform src-over compositing with the web page contents behind the canvas.

-Ken



--
You received this message because you are subscribed to the Google Groups "WebGL Dev List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webgl-dev-lis...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/webgl-dev-list/7546a6b0-b1fa-45a6-933a-e9690b3db155n%40googlegroups.com.

Kelsey Gilbert

unread,
Mar 13, 2023, 8:09:05 PM3/13/23
to webgl-d...@googlegroups.com
To add to Ken, normally we'd love to specify it such that there's only one behavior in undefined-results cases like this, but in this case it would be too expensive (for performance) to guarantee a standardized handling on all platforms. That's why you see reasonable-ish behavior in some places, and really surprising behavior elsewhere for the same content.

Kai Ninomiya

unread,
Mar 13, 2023, 8:54:25 PM3/13/23
to webgl-d...@googlegroups.com
To achieve blending effects between different HTML elements you must use the CSS mix-blend-mode attribute. Unfortunately I don't think any of its modes are equivalent to additive blending, but 'screen' with alpha=1 is _somewhat_ similar.

Ivan Popelyshev

unread,
Mar 14, 2023, 4:44:13 AM3/14/23
to WebGL Dev List
Oh, we reported it years ago.

Last time I checked this, it had "wont fix" status.

https://bugs.chromium.org/p/chromium/issues/detail?id=1034121

вторник, 14 марта 2023 г. в 03:54:25 UTC+3, kai...@chromium.org:
Reply all
Reply to author
Forward
0 new messages