egui icon indicating copy to clipboard operation
egui copied to clipboard

Use sRGBA unaware textures, and let the GPU interpolate in sRGB space.

Open karhu opened this issue 9 months ago β€’ 9 comments

This is one potential fix to the issues we are seeing around GPU texture interpolation of semi-transparent values:

With this change: image Without: image

More

Note that this intentionally switches texture interpolation from linear to gamma. On one hand this makes interpolation more consistent with how it is done everywhere else in egui (vertex blending, and cpu computations). On the other hand it breaks a current assumption (see the screenshot from the rendering demo app).

image

If linear texture interpolation is not necessary, I think this is our best option, and I want to put it forward for discussion. See below for alternatives.

Alternatives that allow for linear blending:

  • Use sRGB aware textures, store sRGB values, but do not premultiply the stored values.
    • This will open us up to interpolation artifacts due to interpolating in non-premultiplied spaces (i.e color bleeding) and is hence undesirable.
  • Use sRGB unaware textures, store linear RGB values, but still premultiply them.
    • We will loose the precision gains that gamma encoding in u8 gives us. Still, if linear texture interpolation is strictly desired, this is our best option, perhaps in combination with a higher precision linear texture format.

Missing:

  • If these changes are acceptable I'll update the PR with matching changes to the glow backend.
  • [x] I have followed the instructions in the PR template

Related:

  • https://github.com/emilk/egui/pull/5824
  • Closes https://github.com/emilk/egui/issues/5810

karhu avatar Mar 21 '25 11:03 karhu

Preview available at https://egui-pr-preview.github.io/pr/5839-bugfix-srgb-interpolate-textures Note that it might take a couple seconds for the update to show up after the preview_build workflow has completed.

github-actions[bot] avatar Mar 21 '25 11:03 github-actions[bot]

Interesting! I would love to see if this does anything for text sharpness

emilk avatar Mar 21 '25 13:03 emilk

Yes, I saw your other PR on that topic and at some point was also experimenting with changes to the encoding there, but then figured to keep the two separate. I consider this here more a correctness fix, enabling proper calibration (your CL) afterwards.

karhu avatar Mar 21 '25 13:03 karhu

Unfortunately don't have time right now and in the coming days to delve deeper into this but it seems to me more and more that we want to be content aware: For "general rendering" the usual expectation is that srgb conversions are a pure encoding artifact, therefore all of blending, interpolation and premultiplication (well that's just blending) should happen in linear space. And that's also what all modern graphics APIs do with their "srgb" post-fixed formats - they do conversions strictly on read & write, and any math done with the color happens on the linear side which is a very intentional choice. However, it seems that for some select operations we want to do part or all of it in gamma space or at least as-if in gamma. In other words, I'm very very nervous about forcing this "gamma space math" upon all texture and rendering. I'd still hope we could get rid of the hack of using non-srgb-converting output textures (which pretty much force gamma-space blending) in the first place, but I need to ponder this a bit more.

Wumpf avatar Mar 21 '25 15:03 Wumpf

this one might have been posted somewhere already probably, but love this take πŸ˜„ (as a bit of counterpoint to what I wrote above) https://erikmcclure.com/blog/everyone-does-srgb-wrong-because/

But one can hardly blame you, because everyone is doing it wrong. CSS does it wrong because SVG does it wrong because Photoshop does it wrong because everyone else does it wrong. It’s all wrong.

... but in the end that's what is causing the ringing as also shown there so there's that :/

Wumpf avatar Mar 21 '25 15:03 Wumpf

No need to rush from my side :) And don't get me wrong, even though that might not be obvious from my last couple comments here, coming from 3D rendering, ideologically I'm very much in the "math in linear space" camp πŸ˜….

My main priority here is to fix obvious rendering artifacts, and if I'm pushing for "math in gamma space", then it's because:

  • eGUI currently seems to mostly operate in gamma space (textures being the one exception), and I was hoping sticking with it would be the path of least resistance.
  • eGUI being a UI library, and being consistent with CSS has some value here.

Regarding the ringing we see here: It's not because we do either gamma or linear interpolation. It's because we do linear interpolation wrong πŸ™ˆ We rely on the automatic GPU conversion upon read/write, which assumes non-premultiplied values, which, well, is not the case :P

karhu avatar Mar 21 '25 17:03 karhu

PS: I'm also wondering if we should treat "image textures" and "font/shape atlas textures" separately. Image textures contain colors, with all the headache that entails. The atlas textures (which could actually be cut down in size to 1/4) contain "pixel coverage", which we might or might not want to treat differently, see: for example https://hikogui.org/2022/10/24/the-trouble-with-anti-aliasing.html

karhu avatar Mar 21 '25 17:03 karhu

PS: I'm also wondering if we should treat "image textures" and "font/shape atlas textures" separately.

With the new parley work, the font atlas texture will be full color (in order to support color emojis): https://github.com/emilk/egui/pull/5784

emilk avatar Apr 22 '25 09:04 emilk

This also improves how icons (with translucency) are blended.

I'd like to have a screenshot test for this improvement

Before: image

After: image

  • EDIT: test added in #7309

emilk avatar May 20 '25 10:05 emilk

I'm forking this PR so that I can finish it up (including updating the snapshot images):

  • https://github.com/emilk/egui/pull/7311

emilk avatar Jul 07 '25 12:07 emilk