- Notifications
You must be signed in to change notification settings - Fork353
Allow out-of-standard-gamut colors with float canvases#4526
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
458efacc5f6709741801dd706a20a4617717cf11daFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2148,21 +2148,88 @@ premultiplication) in which the WebGPU numeric values are to be interpreted. | ||
| WebGPU allows all of the color spaces in the {{PredefinedColorSpace}} enum. | ||
| Note, each color space is defined over an extended range, as defined by the referenced CSS definitions, | ||
| to represent color values outside of its space (in both chrominance and luminance). | ||
| Any numeric value in any color space is a well-defined "color" according to its extended color | ||
| space definition, regardless of whether the point represents a real or imaginary color | ||
| (WebGPU makes no distinction between real and imaginary colors). | ||
| That "color" can be represented in other color spaces as well, where it may be in-gamut. | ||
| <h4 data-dfn-type=dfn>Out-of-Range Premultiplied RGBA Values | ||
| <span id=out-of-gamut-premultiplied-rgba-value><!-- historical permalink --></span> | ||
| </h4> | ||
| An [=out-of-range premultiplied RGBA value=] is one for which the unpremultiplied representation | ||
| of the same color would be outside of the range of the format. | ||
| <div class=example> | ||
| For example, on a display with a color space of exactly Display P3, | ||
| the unpremultiplied sRGB RGBA value `[1.04, 0, 0, 0.5]` and the | ||
| premultiplied sRGB RGBA value `[0.52, 0, 0, 0.5]` both represent the | ||
| CSS color <code><a funcdef>color</a>(srgb 1.04 0 0 / 0.5)</code>, which is equivalent to the | ||
| in-gamut Display P3 color <code><a funcdef>color</a>(display-p3 0.95 0.21 0.15 / 0.5)</code>. | ||
| When represented in a {{PredefinedColorSpace/"srgb"}} {{GPUTextureFormat/"rgba8unorm"}} canvas, | ||
| both values are out-of-range for the purposes of this definition, | ||
| even though the premultiplied value is representable. | ||
| (The colors in this example are in the gamut of the display to avoid any gamut mapping.) | ||
| </div> | ||
| When a canvas containing such a value is | ||
| [$get a copy of the image contents of a context|used as an image source$], | ||
| the returned image must represent the original color values without clamping, | ||
| regardless of the canvas's {{GPUCanvasConfiguration/format}}. | ||
| However, when a ({{GPUCanvasAlphaMode/"premultiplied"}}) canvas containing such a value is | ||
| displayed *on screen*, the visible result for the entire canvas is undefined. | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Checking that I understand. Consider a canvas that is premultiplied, If the value This seems reasonable to me. Would the idea be to make this valid when in extended mode? | ||
| <div class=example> | ||
| For example, on a display with a color space of exactly Display P3, | ||
| an on-screen, solid-color {{PredefinedColorSpace/"srgb"}} canvas displays as follows: | ||
| <table class=data> | ||
| <thead> | ||
| <tr><th>{{GPUCanvasConfiguration/alphaMode}},<br>{{GPUCanvasConfiguration/format}}<th>Pixel Value<th>Result | ||
| <tbody> | ||
| <tr><td>{{GPUCanvasAlphaMode/"opaque"}},<br>{{GPUTextureFormat/"rgba16float"}} | ||
| <td rowspan=2>`[1.04, 0, 0, 1.0]` | ||
| <td rowspan=2><code><a funcdef>color</a>(display-p3 0.95 0.21 0.15 / 1.0)</code>. | ||
| <tr><td>{{GPUCanvasAlphaMode/"premultiplied"}},<br>{{GPUTextureFormat/"rgba16float"}} | ||
| <tr><td>{{GPUCanvasAlphaMode/"premultiplied"}},<br>{{GPUTextureFormat/"rgba16float"}} | ||
| <td>`[0.52, 0, 0, 0.5]` | ||
| <td><code><a funcdef>color</a>(display-p3 0.95 0.21 0.15 / 0.5)</code>. | ||
| <tr><td>{{GPUCanvasAlphaMode/"premultiplied"}},<br>{{GPUTextureFormat/"rgba8unorm"}} | ||
| <td>`[0.50, 0, 0, 0.5]` | ||
| <td><code><a funcdef>color</a>(display-p3 0.92 0.20 0.14 / 0.5)</code>. | ||
| <tr><td>{{GPUCanvasAlphaMode/"premultiplied"}},<br>{{GPUTextureFormat/"rgba8unorm"}} | ||
| <td>`[0.52, 0, 0, 0.5]` | ||
| <td>(undefined result), | ||
| <br>because the unpremultiplied color cannot be represented in this format. | ||
| <!-- POSTV1(#4108): add example for XR formats, which *probably* handle this --> | ||
| </table> | ||
| Visible results may be undefined because the value could be lost at different steps of display: | ||
ContributorAuthor
| ||
| - Value blended directly to the display buffer as | ||
| <code><a funcdef>color</a>(display-p3 0.95 0.21 0.15 / 0.5)</code>. | ||
| - Value blended through an intermediate sRGB buffer as `[0.5, 0, 0, 0.5]`, | ||
| then sent to the display buffer resulting in the appearance of | ||
| <code><a funcdef>color</a>(display-p3 0.92 0.2 0.14 / 0.5)</code>. | ||
| - Value displayed by some other process. | ||
| (The colors in this example are in the gamut of the display to avoid any gamut mapping.) | ||
| </div> | ||
| Note: | ||
| Implementations may defer compositing steps to operating system compositors, | ||
| which often have undefined behavior in these cases. Implementations may not be able to avoid | ||
| these undefined behaviors without significant power usage penalties. | ||
| ### Color Space Conversions ### {#color-space-conversions} | ||
| A color is converted between spaces by translating its representation in one space to a | ||
| representation in another according to the definitions above. | ||
| If the source value has fewer than 4 RGBA channels,any missing green/blue/alpha channels are set to | ||
| `0, 0, 1`, respectively, before converting for color space/encoding and alpha premultiplication. | ||
| After conversion, if the destination needs fewer than 4 channels, the additional channels | ||
| are ignored. | ||
| @@ -2174,11 +2241,12 @@ Colors are not lossily clamped during conversion: converting from one color spac | ||
| will result in values outside the range [0, 1] if the source color values were outside the range | ||
| of the destination color space's gamut. For an sRGB destination, for example, this can occur if the | ||
| source is rgba16float, in a wider color space like Display-P3, or is premultiplied and contains | ||
| [=out-of-range premultiplied RGBA values=]. | ||
| Similarly, precision must be preserved through color space conversion, with intermediate | ||
| computations being at least as precise as the less-precise of the source and destination | ||
| (for example copying a PNG with 16 bits per component, or a canvas with `float16` storage, into a | ||
| {{GPUTextureFormat/rgba16float}} texture). | ||
| ### Color Space Conversion Elision ### {#color-space-conversion-elision} | ||
| @@ -13748,19 +13816,14 @@ is being composited into (e.g. an HTML page rendering, or a 2D canvas). | ||
| : <dfn>"premultiplied"</dfn> | ||
| :: | ||
| Read RGBA as premultiplied: color values are premultiplied by their alpha value. | ||
| For example,100% red at 50% alpha is `[0.5, 0, 0, 0.5]`. | ||
| When alpha is 0, no color is represented, regardless of the RGB values. | ||
| (Attempting to compute the color results in division by zero.) | ||
| In this mode, with some texture formats, the canvas texture can hold | ||
| [=out-of-range premultiplied RGBA values=], which have undefined display results. | ||
| Refer to that section for details. | ||
| </dl> | ||
| # Errors & Debugging # {#errors-and-debugging} | ||