Improve texture filtering by doing it in gamma space (#7311)
* Closes https://github.com/emilk/egui/pull/5839 This makes some transparent images look a lot nicer when blended:  Cursive text will also look nicer. This unfortunately changes the contract of what `register_native_texture` expects --------- Co-authored-by: Adrian Blumer <blumer.adrian@gmail.com>
This commit is contained in:
parent
dd1052108e
commit
f46926aaf1
|
|
@ -97,9 +97,8 @@ fn vs_main(
|
|||
|
||||
@fragment
|
||||
fn fs_main_linear_framebuffer(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
// We always have an sRGB aware texture at the moment.
|
||||
let tex_linear = textureSample(r_tex_color, r_tex_sampler, in.tex_coord);
|
||||
let tex_gamma = gamma_from_linear_rgba(tex_linear);
|
||||
// We expect "normal" textures that are NOT sRGB-aware.
|
||||
let tex_gamma = textureSample(r_tex_color, r_tex_sampler, in.tex_coord);
|
||||
var out_color_gamma = in.color * tex_gamma;
|
||||
// Dither the float color down to eight bits to reduce banding.
|
||||
// This step is optional for egui backends.
|
||||
|
|
@ -115,9 +114,8 @@ fn fs_main_linear_framebuffer(in: VertexOutput) -> @location(0) vec4<f32> {
|
|||
|
||||
@fragment
|
||||
fn fs_main_gamma_framebuffer(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
// We always have an sRGB aware texture at the moment.
|
||||
let tex_linear = textureSample(r_tex_color, r_tex_sampler, in.tex_coord);
|
||||
let tex_gamma = gamma_from_linear_rgba(tex_linear);
|
||||
// We expect "normal" textures that are NOT sRGB-aware.
|
||||
let tex_gamma = textureSample(r_tex_color, r_tex_sampler, in.tex_coord);
|
||||
var out_color_gamma = in.color * tex_gamma;
|
||||
// Dither the float color down to eight bits to reduce banding.
|
||||
// This step is optional for egui backends.
|
||||
|
|
|
|||
|
|
@ -629,9 +629,9 @@ impl Renderer {
|
|||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: wgpu::TextureDimension::D2,
|
||||
format: wgpu::TextureFormat::Rgba8UnormSrgb, // Minspec for wgpu WebGL emulation is WebGL2, so this should always be supported.
|
||||
format: wgpu::TextureFormat::Rgba8Unorm,
|
||||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||
view_formats: &[wgpu::TextureFormat::Rgba8UnormSrgb],
|
||||
view_formats: &[wgpu::TextureFormat::Rgba8Unorm],
|
||||
})
|
||||
};
|
||||
let origin = wgpu::Origin3d::ZERO;
|
||||
|
|
@ -690,7 +690,7 @@ impl Renderer {
|
|||
///
|
||||
/// This enables the application to reference the texture inside an image ui element.
|
||||
/// This effectively enables off-screen rendering inside the egui UI. Texture must have
|
||||
/// the texture format [`wgpu::TextureFormat::Rgba8UnormSrgb`].
|
||||
/// the texture format [`wgpu::TextureFormat::Rgba8Unorm`].
|
||||
pub fn register_native_texture(
|
||||
&mut self,
|
||||
device: &wgpu::Device,
|
||||
|
|
@ -738,7 +738,7 @@ impl Renderer {
|
|||
/// This allows applications to specify individual minification/magnification filters as well as
|
||||
/// custom mipmap and tiling options.
|
||||
///
|
||||
/// The texture must have the format [`wgpu::TextureFormat::Rgba8UnormSrgb`].
|
||||
/// The texture must have the format [`wgpu::TextureFormat::Rgba8Unorm`].
|
||||
/// Any compare function supplied in the [`wgpu::SamplerDescriptor`] will be ignored.
|
||||
#[expect(clippy::needless_pass_by_value)] // false positive
|
||||
pub fn register_native_texture_with_sampler_options(
|
||||
|
|
|
|||
|
|
@ -161,12 +161,10 @@
|
|||
//!
|
||||
//! * egui uses premultiplied alpha, so make sure your blending function is `(ONE, ONE_MINUS_SRC_ALPHA)`.
|
||||
//! * Make sure your texture sampler is clamped (`GL_CLAMP_TO_EDGE`).
|
||||
//! * egui prefers linear color spaces for all blending so:
|
||||
//! * Use an sRGBA-aware texture if available (e.g. `GL_SRGB8_ALPHA8`).
|
||||
//! * Otherwise: remember to decode gamma in the fragment shader.
|
||||
//! * Decode the gamma of the incoming vertex colors in your vertex shader.
|
||||
//! * Turn on sRGBA/linear framebuffer if available (`GL_FRAMEBUFFER_SRGB`).
|
||||
//! * Otherwise: gamma-encode the colors before you write them again.
|
||||
//! * egui prefers gamma color spaces for all blending so:
|
||||
//! * Do NOT use an sRGBA-aware texture (NOT `GL_SRGB8_ALPHA8`).
|
||||
//! * Multiply texture and vertex colors in gamma space
|
||||
//! * Turn OFF sRGBA/gamma framebuffer (NO `GL_FRAMEBUFFER_SRGB`).
|
||||
//!
|
||||
//!
|
||||
//! # Understanding immediate mode
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f62d5375ff784e333e01a31b84d9caadf2dcbd2b19647a08977dab6550b48828
|
||||
size 179654
|
||||
oid sha256:fc3dbdcd483d4da7a9c1a00f0245a7882997fbcd2d26f8d6a6d2d855f3382063
|
||||
size 179724
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0e37b3ce49c9ccc1a64beb58b176e23ab6c1fa2d897f676b0de85e510e6bfa85
|
||||
size 100845
|
||||
oid sha256:c8ad2c2d494e2287b878049091688069e4d86b69ae72b89cb7ecbe47d8c35e33
|
||||
size 100766
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ impl ColorTest {
|
|||
ui.separator();
|
||||
|
||||
// TODO(emilk): test color multiplication (image tint),
|
||||
// to make sure vertex and texture color multiplication is done in linear space.
|
||||
// to make sure vertex and texture color multiplication is done in gamma space.
|
||||
|
||||
ui.label("Gamma interpolation:");
|
||||
self.show_gradients(ui, WHITE, (RED, GREEN), Interpolation::Gamma);
|
||||
|
|
@ -191,8 +191,8 @@ impl ColorTest {
|
|||
|
||||
ui.separator();
|
||||
|
||||
ui.label("Linear interpolation (texture sampling):");
|
||||
self.show_gradients(ui, WHITE, (RED, GREEN), Interpolation::Linear);
|
||||
ui.label("Texture interpolation (texture sampling) should be in gamma space:");
|
||||
self.show_gradients(ui, WHITE, (RED, GREEN), Interpolation::Gamma);
|
||||
}
|
||||
|
||||
fn show_gradients(
|
||||
|
|
@ -245,11 +245,10 @@ impl ColorTest {
|
|||
let g = Gradient::endpoints(left, right);
|
||||
|
||||
match interpolation {
|
||||
Interpolation::Linear => {
|
||||
// texture sampler is sRGBA aware, and should therefore be linear
|
||||
self.tex_gradient(ui, "Texture of width 2 (test texture sampler)", bg_fill, &g);
|
||||
}
|
||||
Interpolation::Linear => {}
|
||||
Interpolation::Gamma => {
|
||||
self.tex_gradient(ui, "Texture of width 2 (test texture sampler)", bg_fill, &g);
|
||||
|
||||
// vertex shader uses gamma
|
||||
self.vertex_gradient(
|
||||
ui,
|
||||
|
|
@ -330,7 +329,10 @@ fn vertex_gradient(ui: &mut Ui, bg_fill: Color32, gradient: &Gradient) -> Respon
|
|||
|
||||
#[derive(Clone, Copy)]
|
||||
enum Interpolation {
|
||||
/// egui used to want Linear interpolation for some things, but now we're always in gamma space.
|
||||
#[expect(unused)]
|
||||
Linear,
|
||||
|
||||
Gamma,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cbe9f58cce2466360b4b93b03afaaee36711b3017ddff1b2b56bfe49ea91a076
|
||||
size 31306
|
||||
oid sha256:13262df01a7f2cd5655b8b0bb9379ae02a851c877314375f047a7d749908125c
|
||||
size 31368
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b4f807098e0bc56eaacabb76d646a76036cc66a7a6e54b1c934fa9fecb5b0170
|
||||
size 26470
|
||||
oid sha256:27d5aa7b7e6bd5f59c1765e98ca4588545284456e4cc255799ea797950e09850
|
||||
size 26461
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fdf3535530c1abb1262383ff9a3f2a740ad2c62ccec33ec5fb435be11625d139
|
||||
size 35125
|
||||
oid sha256:aabc0e3821a2d9b21708e9b8d9be02ad55055ccabe719a93af921dba2384b4b3
|
||||
size 34297
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:16dc96246f011c6e9304409af7b4084f28e20cd813e44abca73834386e98b9b1
|
||||
size 70373
|
||||
oid sha256:a3f8873c9cfb80ddeb1ccc0fa04c1c84ea936db1685238f5d29ee6e89f55e457
|
||||
size 68814
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ae04cea447427982f1d68bb2250563aaa3be137a77f6dd3f253da77c194c84cf
|
||||
size 812
|
||||
oid sha256:e057c0bba4ec4c30e890c39153bd6dd17c511f410bfb894e66ef3ef9973d8fd4
|
||||
size 807
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ff053e309e6ae38a4b6fe1dd58f1255116fffab6182ce5f77b6360b00cf2af47
|
||||
size 2067
|
||||
oid sha256:c8b573f58a41efe26a0bf335e27cc123ffd4c13b24576e46d96ddedfed68b606
|
||||
size 2027
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9f6cf5b14056522d06f0cb1e56bafd7e5ab7a9033eb358748d43d748bb0ceef1
|
||||
size 553177
|
||||
oid sha256:39bd11647241521c0ad5c7163a1af4f1aa86792018657091a2d47bb7f2c48b47
|
||||
size 598408
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fd3bd1f64995db34a14dbc860ae8b8e269073ed7b8f10d10ce8f99b613cfc999
|
||||
size 769357
|
||||
oid sha256:080a59163ab60d60738cfab5afac7cfbddfb585d8a0ee7d03540924b458badea
|
||||
size 833822
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f12e6145f3a1c3fda6dede3daeb0e52ed2bffb35531d823133224a477798a14a
|
||||
size 907800
|
||||
oid sha256:216d3d028f48f4bfbd6aca0a25500655d4eb4d5581a387397ed0b048d57fc0c3
|
||||
size 984737
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:05bdcfd2c34b6d7badede14f5495dce34e5e9cfe421314f40dcea15e9f865736
|
||||
size 1024735
|
||||
oid sha256:399fc3d64e7ff637425effe6c80d684be1cf8bb9b555458352d0ae6c62bddb5a
|
||||
size 1109505
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8365c89f6b823f01464a9310bab7717bf25305b335cdeecf21711c7dca9f053f
|
||||
size 1140082
|
||||
oid sha256:30ce4874a1adb8acf8c8e404f3e19e683eca3133cdef15befbc50d6c09618094
|
||||
size 1241773
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b38021057ec6b5bb39c41bd4afaf5e9ff38687216d52d5bba8cbf7b6fdfe9a4f
|
||||
size 1291518
|
||||
oid sha256:135fbe5f4ee485ee671931b64c16410b9073d40bedb23dc2545fc863448e8c63
|
||||
size 1398091
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4ac90da596084a880487035b276177e98d711854143373d59860f01733b1c0cd
|
||||
size 45592
|
||||
oid sha256:1b0fe7aa33506c59142aff764c6b229e8c55b35c8038312b22ea2659987a081a
|
||||
size 45578
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e412d424aac7b9cbdfdb8e36bd598e6cbc77183da7733c94c5f20e70699b8b4a
|
||||
size 87263
|
||||
oid sha256:3a3512ea7235640db79e86aa84039621784270201c9213c910f15e7451e5600b
|
||||
size 87336
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:222a32da21c69ee46e847e29fb05fd5e1d2de6bb7a22358549bc426f8243fdcb
|
||||
size 119671
|
||||
oid sha256:dc4918a534f26b72d42ef20221e26c0f91a0252870a1987c1fe4cc4aa3c74872
|
||||
size 119406
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d42e11f50a9522dd5ae73e8f8336bfb01493751705055a63abea3f5258f7c9c1
|
||||
size 51626
|
||||
oid sha256:71182570a65693839fd7cd7390025731ab3f3f88ab55bc67d8be6466fe5a2c11
|
||||
size 51843
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c33617dfde24071fa65aff2543f22883f5526152fb344997b1877aeb38df72fe
|
||||
size 54848
|
||||
oid sha256:a0dc0294f990730da34fcbbc53f44280306ec6179826c20a6c9ee946e1148b61
|
||||
size 55042
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fbf40a1f56a6e280002719c6556fe477c93fa7fe88d398372ed36efaa1b83a62
|
||||
size 55282
|
||||
oid sha256:3004adfe5a864bdc768ceb42d1f09b6debcaf5413f8fea4d36b0aff99e4584f9
|
||||
size 55511
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:33621731155ebb463fb01ea41ab20272885250efcd7d5c7683c10936b296e14d
|
||||
size 36446
|
||||
oid sha256:b99360833f59a212a965a13d52485ab8ad0e6420b9288b2d6936507067c22a85
|
||||
size 36395
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:186bd8a3146ad8f1977955e3f7fa593877ad1bf1e8376d32f446c67f36a2aafe
|
||||
size 36493
|
||||
oid sha256:82aa004f668f0ac6b493717b4bff8436ccc1e991c7fb3fcde5b5f3a123c06b9f
|
||||
size 36428
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:62df72fd7e2404c4aa482f09eff5103ee28e8afc42ee8c8c74307a246f64cda6
|
||||
size 64651
|
||||
oid sha256:7e21bb01ae6e4226402a97b7086b49604cdde6b41a6770199df68dc940cd9a45
|
||||
size 64748
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3f5a7397601cb718d5529842a428d2d328d4fe3d1a9cf1a3ca6d583d8525f75e
|
||||
size 153190
|
||||
oid sha256:0626bc45888ad250bf4b49c7f7f462a93ab91e3a2817fd7d0902411043c97132
|
||||
size 153289
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:34d85b6015112ea2733f7246f8daabfb9d983523e187339e4d26bfc1f3a3bba3
|
||||
size 59460
|
||||
oid sha256:919a82c95468300bcd09471eb31d53d25d50cdcb02c27ddbc759d24e65da92b6
|
||||
size 59398
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4f51d75010cd1213daa6a1282d352655e64b69da7bca478011ea055a2e5349bc
|
||||
size 146500
|
||||
oid sha256:a55e39a640b0e2cc992286a86dcf38460f1abcc7b964df9022549ca1a94c4df5
|
||||
size 146408
|
||||
|
|
|
|||
|
|
@ -172,12 +172,7 @@ impl Painter {
|
|||
|
||||
let supported_extensions = gl.supported_extensions();
|
||||
log::trace!("OpenGL extensions: {supported_extensions:?}");
|
||||
let srgb_textures = shader_version == ShaderVersion::Es300 // WebGL2 always support sRGB
|
||||
|| supported_extensions.iter().any(|extension| {
|
||||
// EXT_sRGB, GL_ARB_framebuffer_sRGB, GL_EXT_sRGB, GL_EXT_texture_sRGB_decode, …
|
||||
extension.contains("sRGB")
|
||||
});
|
||||
log::debug!("SRGB texture Support: {:?}", srgb_textures);
|
||||
let srgb_textures = false; // egui wants normal sRGB-unaware textures
|
||||
|
||||
let supports_srgb_framebuffer = !cfg!(target_arch = "wasm32")
|
||||
&& supported_extensions.iter().any(|extension| {
|
||||
|
|
@ -202,11 +197,10 @@ impl Painter {
|
|||
&gl,
|
||||
glow::FRAGMENT_SHADER,
|
||||
&format!(
|
||||
"{}\n#define NEW_SHADER_INTERFACE {}\n#define DITHERING {}\n#define SRGB_TEXTURES {}\n{}\n{}",
|
||||
"{}\n#define NEW_SHADER_INTERFACE {}\n#define DITHERING {}\n{}\n{}",
|
||||
shader_version_declaration,
|
||||
shader_version.is_new_shader_interface() as i32,
|
||||
dithering as i32,
|
||||
srgb_textures as i32,
|
||||
shader_prefix,
|
||||
FRAG_SRC
|
||||
),
|
||||
|
|
|
|||
|
|
@ -43,25 +43,8 @@ vec3 dither_interleaved(vec3 rgb, float levels) {
|
|||
return rgb + noise / (levels - 1.0);
|
||||
}
|
||||
|
||||
// 0-1 sRGB gamma from 0-1 linear
|
||||
vec3 srgb_gamma_from_linear(vec3 rgb) {
|
||||
bvec3 cutoff = lessThan(rgb, vec3(0.0031308));
|
||||
vec3 lower = rgb * vec3(12.92);
|
||||
vec3 higher = vec3(1.055) * pow(rgb, vec3(1.0 / 2.4)) - vec3(0.055);
|
||||
return mix(higher, lower, vec3(cutoff));
|
||||
}
|
||||
|
||||
// 0-1 sRGBA gamma from 0-1 linear
|
||||
vec4 srgba_gamma_from_linear(vec4 rgba) {
|
||||
return vec4(srgb_gamma_from_linear(rgba.rgb), rgba.a);
|
||||
}
|
||||
|
||||
void main() {
|
||||
#if SRGB_TEXTURES
|
||||
vec4 texture_in_gamma = srgba_gamma_from_linear(texture2D(u_sampler, v_tc));
|
||||
#else
|
||||
vec4 texture_in_gamma = texture2D(u_sampler, v_tc);
|
||||
#endif
|
||||
|
||||
// We multiply the colors in gamma space, because that's the only way to get text to look right.
|
||||
vec4 frag_color_gamma = v_rgba_in_gamma * texture_in_gamma;
|
||||
|
|
|
|||
Loading…
Reference in New Issue