Open jakearchibald opened 2 years ago
plus-lighter
andplus-darker
were added when the compositing-2 doc was added 10f0d3d. I can't find any discussion of these, but I guess there must have been. @cabanier, @dbaron do either of you know the history here?
This was requested a long time ago by @grorg : https://lists.w3.org/Archives/Public/public-fx/2015JanMar/0021.html
I wonder if it would make sense to specify that all blend and compositing modes are clamped to 0-1. Then, remove
plus-lighter
from the spec, and renameplus-darker
todarker
and remove the clamping (since it'd be covered by the overall clamping.
It makes sense to clamp the alpha to 1. I can't think of a reason how it could ever exceed that. The color should not be clamped though as that will break certain effects where over-range colors are used.
This was requested a long time ago by @grorg : https://lists.w3.org/Archives/Public/public-fx/2015JanMar/0021.html
Ohhh thanks for finding that! @grorg, do you think we need both lighter
and plus-lighter
? Could we just have lighter
and darker
and have them both clamp.
It makes sense to clamp the alpha to 1. I can't think of a reason how it could ever exceed that.
Yeah, otherwise it gets weird when going between premultiplied and the other thing.
certain effects
Can a web API do that? Should I be seeing a difference in https://static-misc-3.glitch.me/composite-test/cap.html? If not, can you give me an example that shows it?
certain effects
Can a web API do that? Should I be seeing a difference in https://static-misc-3.glitch.me/composite-test/cap.html? If not, can you give me an example that shows it?
With HDR support, web APIs should be able to use it. For instance, an author could use plus
to do a dissolve between 2 bright lights.
I remember asking the same question to the CSS group and they said it was valid for a color to be over 1. Looking at the css color spec, it seems that they updated the language around color
but IMO they made it more confusing.
If we're going to clamp the color, it certainly shouldn't be 1 though since I though that not all color spaces go between 0 and 1.
With HDR support, web APIs should be able to use it.
By HDR you mean an image that has colours outside the colour space rather than, say, rec2020? I thought it was rec2020 it'd still be 0-1, but in another space.
By HDR you mean an image that has colours outside the colour space rather than, say, rec2020? I thought it was rec2020 it'd still be 0-1, but in another space.
If you convert HDR rec-2100
to rec-2020
(which uses the same primaries and whitepoint) you will get some colors with slightly negative, or greater than unity, components.
For example color(rec2100pq 0.71 0.78 0.67)
would be color(rec2020 1.796 2.431 1.505)
all the components are over 1.
I remember asking the same question to the CSS group and they said it was valid for a color to be over 1.
An out of gamut color has component values less than 0 or 0%, or greater than 1 or 100%. These are not invalid; instead, for display, they are gamut-mapped using a relative colorimetric intent which brings the values within the range 0/0% to 1/100% at computed-value time.
(Bearing in mind that CSS Color 4 is SDR-only, but designed to allow HDR to be built on top of it. Which is why all colors are defined over the extended range)
Ok. So is it justified to have lighter
and plus-lighter
where the only difference is that one is clamped?
For the cross-fading use-case we can use either.
It still isn't clear to me if https://static-misc-3.glitch.me/composite-test/cap.html is behaving correctly across browsers or not. @svgeesus what do you think?
Wait, maybe lighter
is the correct choice for the cross-fading case, because clamping to 1 messes with cases where we're cross-fading between two colours that are deliberately outside of the specified gamut.
Wait, maybe
lighter
is the correct choice for the cross-fading case, because clamping to 1 messes with cases where we're cross-fading between two colours that are deliberately outside of the specified gamut.
Yes. Thinking about this some more, the clamping seems separate from the compositing. In the normal case, you would want the color to be clamped to their range after the composite but for special effects, you might want to skip that.
Over in this issue, a very similar issue came up, and at least with respect to RGB (ignoring A for the moment), the general idea is that color values shouldn't be clamped, and should be allowed to express colors of any gamut. The compositor will, at the end, clamp the colors to the gamut of the display, and to the SDR range.
With respect to HDR, I do feel that the best thing to do is to specify "we will clamp to SDR unless something is explicitly specified using some yet-to-be-defined API".
To open the HDR bikeshed doors a bit ... my sense is that we will eventually want to add a spec that allows an individual element to explicitly enable HDR for-just-that-element. When enabling HDR, it can specify what kind of HDR is desired (just-extended-values, or treat-as-HLG, or treat-as-extended-with-metadata-sort-of-like-PQ). This proposal discusses adding HDR to canvas elements. This is also similar to specifying a "working interpolation space" for an element. (This issue discusses whether or not that "working pixel buffer space" should be independent of the "HDR type of space for compositing the element" but ... that's a whole nother bike shed). The status of that spec is "we need to write a prototype so people can feel their way around what is best". To return to the issue at hand, saying "clamp to SDR and the device's gamut at the end of the pipeline" is compatible with all of that.
Over in this issue, a very similar issue came up, and at least with respect to RGB (ignoring A for the moment), the general idea is that color values shouldn't be clamped, and should be allowed to express colors of any gamut. The compositor will, at the end, clamp the colors to the gamut of the display, and to the SDR range.
For "regular" drawing, color should be clamped to a valid range. Going outside that (ie with ICC color) will no longer result in accurate color rendering. Also, the compositor doesn't clamp to the gamut. It should render in (or receive pixels of) the output colorspace.
With respect to HDR, I do feel that the best thing to do is to specify "we will clamp to SDR unless something is explicitly specified using some yet-to-be-defined API".
I think that is reasonable. We would have to define what to clamp to though.
To open the HDR bikeshed doors a bit ... my sense is that we will eventually want to add a spec that allows an individual element to explicitly enable HDR for-just-that-element. When enabling HDR, it can specify what kind of HDR is desired (just-extended-values, or treat-as-HLG, or treat-as-extended-with-metadata-sort-of-like-PQ).
I don't quite understand how that would work with a single element. You always want to render a group of graphics to a single colorspace.
This proposal discusses adding HDR to canvas elements. This is also similar to specifying a "working interpolation space" for an element. (This issue discusses whether or not that "working pixel buffer space" should be independent of the "HDR type of space for compositing the element" but ... that's a whole nother bike shed). The status of that spec is "we need to write a prototype so people can feel their way around what is best".
Adobe applications have the "working colorspace" which is the colorspace that compositing takes place in and the "target colorspace" which is the one of the device. Typically they are the same but some workflows and placed content (ie PDF) allow them to be different. In the case of the web, iframes and canvas would be similar.
@grorg would you be happy with deprecating plus-lighter
and plus-darker
by aliasing them to lighter
and darker
? It seems like Safari supports darker
even though it isn't in the spec.
It still isn't clear to me when the colours would be clamped to the gamut.
@ccameron-chromium
The compositor will, at the end, clamp the colors to the gamut of the display
When is "the end"? For example:
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgb(100%, 0%, 0%)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgb(100%, 100%, 0%)';
ctx.globalCompositeOperation = 'lighter';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgb(50%, 50%, 0%)';
ctx.globalCompositeOperation = 'multiply';
ctx.fillRect(0, 0, canvas.width, canvas.height);
Is the multiply destination rgb(200%, 100%, 0%)
(unclamped after 'lighter') or rgb(100%, 100%, 0%)
(clamped after 'lighter')?
Would the result be different if the compositing was done with mix-blend-mode
or background-blend-mode
?
FYI, fiddling with the test that is being added in https://github.com/web-platform-tests/wpt/pull/41713 shows that all of Chromium, Gecko, and WebKit appear to implement lighter
using the spec formula for plus-lighter
rather than the formula given for lighter
. (Though I admit that that test is using sRGB as the canvas color space -- perhaps I should test a bit using other colorSpace options?)
That said, the test is testing values that have to be clamped, so I suppose there's no way the spec formula would result in passing. The question is really whether the test should have separately clamped the values after the compositing formula.
I guess the question is really whether the difference in clamping between the two formulas is meaningful when we start talking about other color spaces. If there is a difference, then which one is right? And if there isn't a difference, which one is a clearer way to specify it?
The CSS Working Group just discussed [compositing-2] 'lighter' vs 'plus-lighter'
, and agreed to the following:
RESOLVED: make lighter defined the way plus-lighter is now defined, pending checking some additional tests that might show differences
In a perfect world, we'd only have lighter
, and plus-lighter
wouldn't be a thing. The reason we pushed for plus-lighter
to be added to the spec is because Safari had already shipped it for years, so it seemed too late to have a naming discussion.
https://drafts.fxtf.org/compositing/#porterduffcompositingoperators_plus_lighter
The difference between
lighter
andplus-lighter
is thatplus-lighter
caps to 1. However, I can't find any cases wherelighter
allows values to go above 1. Here's a couple of canvases that I'd expect to be different if values were allowed to go above 1 https://static-misc-3.glitch.me/composite-test/cap.html - in this case both the red channel and alpha channel would go above 1.plus-lighter
andplus-darker
were added when the compositing-2 doc was added https://github.com/w3c/fxtf-drafts/commit/10f0d3dfd827022f156d033e3d9ac4f9f3ca05ef. I can't find any discussion of these, but I guess there must have been. @cabanier, @dbaron do either of you know the history here?I wonder if it would make sense to specify that all blend and compositing modes are clamped to 0-1. Then, remove
plus-lighter
from the spec, and renameplus-darker
todarker
and remove the clamping (since it'd be covered by the overall clamping.