Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[editorial] Explain the relationship between color management and -srgb formats #4587

Open
kainino0x opened this issue Apr 17, 2024 · 7 comments · May be fixed by #4597
Open

[editorial] Explain the relationship between color management and -srgb formats #4587

kainino0x opened this issue Apr 17, 2024 · 7 comments · May be fixed by #4597
Assignees
Labels
api WebGPU API copyediting Pure editorial stuff (copyediting, *.bs file syntax, etc.)
Milestone

Comments

@kainino0x
Copy link
Contributor

kainino0x commented Apr 17, 2024

In this section we specify

WebGPU does not provide color management. All values within WebGPU (such as texture elements) are raw numeric values, not color-managed color values.

This kind of sounds like it conflicts with the existence of -srgb formats.

I just wrote this explanation and realized it should be in the spec too (integrated in some way that makes sense, probably in that section):

<div class=note heading>
    Textures with `-srgb` formats have gamma-encoding/decoding properties, which
    are useful for *manually* managing colors, but are not color-managed by the
    platform. For example:

    - {{GPUTextureFormat/"rgba8unorm"}} textures are not color-managed as
        <l>''color()/srgb-linear''</l>; they very often actually contain
        sRGB-nonlinear values, non-linear display-native values, or non-color values.
    - {{GPUTextureFormat/"rgba8unorm-srgb"} textures are not color-managed as
        <l>''color()/srgb''</l>; they apply sRGB's gamma conversion when read or
        written in certain ways, but do not have to be sRGB.
        For instance, <l>''color()/display-p3''</l> also uses sRGB's gamma conversion.
        It is also a decent approximation of many display-native gamma curves.
</div>
@kainino0x kainino0x added the copyediting Pure editorial stuff (copyediting, *.bs file syntax, etc.) label Apr 17, 2024
@kainino0x kainino0x added this to the Milestone 0 milestone Apr 17, 2024
@kainino0x
Copy link
Contributor Author

Accidentally posted before I finished writing. Updated above.

cc @toji

@kdashg
Copy link
Contributor

kdashg commented Apr 18, 2024

I believe you have them backwards, but I'm going to double-check.

@kdashg kdashg removed the copyediting Pure editorial stuff (copyediting, *.bs file syntax, etc.) label Apr 18, 2024
@kainino0x
Copy link
Contributor Author

What I wrote mostly only says what's not true. Do you mean the part about gamma conversion?

@kdashg
Copy link
Contributor

kdashg commented Apr 18, 2024

I believe the spec should stand as-is, and that we should only describe the transfer function for reading and writing -srgb formats and let people decide if they want that. I think it is unexpectedly valuable to purposefully avoid talking about common purposes here, and really just say, "it's math, it behaves like so". My foremost recommendation is to at-most non-normatively note that "-srgb formats are often used for rendering and blending in srgb-linear space".

I do not think we should describe -srgb formats as "useful for manually managing colors". Rather, they are used to support doing (physically-)linear rendering, whereas non--srgb "linear unorm" formats do filtering and blending naively on post-srgb-gamma'd "perceptual" values. The proposal alludes to this, but it was unclear enough that I had to go double (and triple) check. Here is what I've said about this previously: https://hackmd.io/@jgilbert/colorspace-ctes#Physically-Linear-Blending

While the proposal correctly says "unorm is not like css-color(srgb-linear", I think it would be better to either not mention the css-color, or to explicitly and verbosely say "unorm is not like css-color(srgb-linear, but more closely aligned with css-color(srgb". (and vice-versa) I really do believe that it's more clear to either do not mention either css-color form, or instead to be clear that it's the opposite of what one would expect by listing both for both.

I removed the "editorial" tag since I was unclear whether the intent here is to add a non-normative section, since the current section in question is normative. Feel free to add it back if the intent is for a non-normative note.

@kdashg
Copy link
Contributor

kdashg commented Apr 18, 2024

What I wrote mostly only says what's not true. Do you mean the part about gamma conversion?

You're right, and that section is technically correct, but the association of the two, due to their textual proximity, made me go off and double-check.

@kainino0x
Copy link
Contributor Author

Oh, yes, it can be non-normative. That makes sense since the point of this text is just to point out that -srgb format textures have nothing to do with platform-level color management. The little details I used to illustrate that are not meant to be normative. Edited to make non-normative.

I'll try to incorporate your feedback and send a PR.

@kainino0x kainino0x added the copyediting Pure editorial stuff (copyediting, *.bs file syntax, etc.) label Apr 24, 2024
@kainino0x kainino0x self-assigned this Apr 24, 2024
@kainino0x kainino0x added the api WebGPU API label Apr 30, 2024
@greggman
Copy link
Contributor

greggman commented May 6, 2024

Throwing out more ideas. I think being explicit that how the data in the texture is interpreted by the browser/css/display is "out-of-scope". In other words, talking about "linear color spaces" is irrelevant and misleading? since you can use -srgb texture formats for any reason. What matters in the end is what values you ultimately put in the texture. That texture is then handed off to the browser and how the values in the texture are interpreted is up to the other specs, not WebGPU.

All -srgb formats do is do a conversion when reading from and writing to -srgb textures in WGSL.

Reading

  • non-srgb

    v = textureXXX(...)  // no extra math
    
  • -srgb

    fn fromSRGB(c: vec4f) -> vec4f {
      let overLowThreshold = c.rgb > 0.04045;
      let rgb = select(c.rgb / 12.92, pow((c.rgb + 0.055) / 1.055, 2.4), overLowThreshold);
      return vec4f(saturate(rgb), c.a);
    }
    
    v = fromSRGB(textureXXX(...)) // extra math
    

    Note: This is from the OpenGL ES 3.1 spec which also says that whether this conversion happens per before or after linear interpolation is implementation defined.

Writing

fn toSRGB(c: vec4f) -> vec4f {
  let greaterThanZero = c.rgb > 0.0;
  let underLowThreshold = c.rgb < 0.0031308;
  let greaterThanOrEqualToOne = c.rgb >= 1.0;
  let rgb = select(
     vec3f(0),
     select(
       c.rgb * 12.92,
       select(
          pow(1.055 * c.rgb, 0.41666) - 0.055,
          vec3f(1),
          greaterThanOrEqualToOn,
       ),
       underLowThreshold,
     ),
     greaterThanZero,
  )
  var rgb = select(c.rgb, vec3f(0), c <= 0.0);
}

@fragment fn f() -> @location(0) vec4f {
   ...
   return someColor;  // returned as `toSRGB(someColor);
}

Dang that's hard to read 😱. Maybe show the formula from one of the specs 😅

Another code way might be

fn toSRGBComponent(c: f32) -> f32 { 
  if (c <= 0.0) return 0.0;
  if (c < 0.0031308) return 12.95 * c;
  if (c < 1.0) return pow(1.055 * c, 0.41666) - 0.055;
  return 1.0;
}

fn toSRGB(c: vec4f) -> vec4f {
  return vec4f(
     toSRGBComponent(c.r),
     toSRGBComponent(c.g),
     toSRGBComponent(c.b),
     c.a);
}

I'm not sure this is helpful. I just worry any word about "linear color space" seems to assume the values in the texture mean more than they do?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api WebGPU API copyediting Pure editorial stuff (copyediting, *.bs file syntax, etc.)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants