KhronosGroup / WebGL

The Official Khronos WebGL Repository
Other
2.66k stars 670 forks source link

Clarify UNPACK_PREMULTIPLY_ALPHA for floating-point and integer pixel formats #3667

Open lexaknyazev opened 3 months ago

lexaknyazev commented 3 months ago

The UNPACK_PREMULTIPLY_ALPHA_WEBGL parameter is defined in WebGL 1.0 spec that on its own supports only unsigned normalized pixel formats.

The WebGL 2.0 and the related WebGL extension specs should define how this parameter works with:

kdashg commented 3 months ago

I believe we should specifiy that:

lexaknyazev commented 3 months ago

ieee math happens

Inf and NaN included?

Int formats: clamping happens

Normalized (incl signed) formats: clamping happens

Since the values are normalized, multiplication results cannot be outside of [0, 1] or [-1, +1] ranges. The only tricky edge case is that -128 and -32768 must be treated as -127 and -32767 for the purposes of normalization.

kenrussell commented 2 months ago

Notes from the WebGL concall:

Inf and NaN included?

Thinking: we do whatever the CPU hardware does.

Int formats: clamping happens

Let's say that the integer math's done with 32 bits of precision and then clamp back to the 8-bit range. Or, say that clamping isn't better than masking? Not sure what's better.

Meta-question, should we be premultiplying integer values at all? Consider ignoring the state for these non-normalized integer textures.

More discussion to come.

kdashg commented 2 months ago

I wish we had never applied this setting to ArrayBufferView data. It really only makes sense for images, where you're trying to ensure consistency. This should be viewed like unpackColorSpace, where it sets the destination alpha premultiplication state when we call e.g. texImage(img). Different sources have different alpha premult states: Canvases are generally alpha-premult:true, whereas PNG is stored alpha-premult:false. Setting UNPACK_PREMULTIPLY_ALPHA:true means that for canvases, we do no alpha-premult-conversion, whereas for PNG, we multiply color by alpha before the color conversions step. Likewise for UNPACK_PREMULTIPLY_ALPHA:false, we have to "unpremultiply" by dividing color by alpha in order to make the data alpha-premult:false, whereas for PNG, we do not change the data. It's important to view these as the destination setters, rather than operations. (This also applies to the y-flip setting)

I believe Firefox warns if you use these things (such as flip-y) on ArrayBufferView data.

kdashg commented 2 months ago

In WG, we decided that we would try to spec UNPACK_PREMULTIPLY_ALPHA as ignored for non-TexImageSources (thus excluding ArrayBufferViews). Next step is writing a test to go with the spec change, and seeing if that breaks any implementations.

kenrussell commented 1 month ago

Additional information from WebGL WG meeting of 2024-09-19:

One remaining problem is uploading canvases to RGBA8UI textures with premultiplied alpha: https://registry.khronos.org/webgl/specs/latest/2.0/#3.7.6 . That's the only problematic format in the table. The WG resolved to test this, and if browsers behave differently, carve it out from the rest of the spec update.