From c459950282f245c2355d13c6843d40a0689fee2a Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Tue, 5 Aug 2025 10:59:42 +0200 Subject: [PATCH 1/3] Fix gamma issue by applying tone mapping in the shader Vello renders it's values to an RgbaUnorm texture but if we try to use this in the main rendering pipeline which renders to an Srgb surface gamma mapping is applied twice. --- desktop/src/render/composite_shader.wgsl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/desktop/src/render/composite_shader.wgsl b/desktop/src/render/composite_shader.wgsl index b939ecbff6..a297a59d6c 100644 --- a/desktop/src/render/composite_shader.wgsl +++ b/desktop/src/render/composite_shader.wgsl @@ -51,8 +51,10 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { let vp_cord = (in.tex_coords - constants.viewport_offset) * constants.viewport_scale; - let ov = textureSample(t_overlays, s_diffuse, vp_cord); - let vp = textureSample(t_viewport, s_diffuse, vp_cord); + let ov_raw = textureSample(t_overlays, s_diffuse, vp_cord); + let ov = vec4(srgb_to_linear(ov_raw.rgb), ov_raw.a); + let vp_raw = textureSample(t_viewport, s_diffuse, vp_cord); + let vp = vec4(srgb_to_linear(vp_raw.rgb), vp_raw.a); if (ov.a < 0.001) { return blend(ui, vp); @@ -62,6 +64,14 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { return blend(ui, comp); } +fn srgb_to_linear(srgb: vec3) -> vec3 { + return select( + pow((srgb + 0.055) / 1.055, vec3(2.4)), + srgb / 12.92, + srgb <= vec3(0.04045) + ); +} + fn blend(fg: vec4, bg: vec4) -> vec4 { let a = fg.a + bg.a * (1.0 - fg.a); let rgb = fg.rgb * fg.a + bg.rgb * bg.a * (1.0 - fg.a); From 9b6d308f6909c9679da9612a9d0186b3b1f526f0 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Tue, 5 Aug 2025 11:35:07 +0200 Subject: [PATCH 2/3] Add comment explaining why we do this to the shader --- desktop/src/render/composite_shader.wgsl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/desktop/src/render/composite_shader.wgsl b/desktop/src/render/composite_shader.wgsl index a297a59d6c..f714490fb8 100644 --- a/desktop/src/render/composite_shader.wgsl +++ b/desktop/src/render/composite_shader.wgsl @@ -51,6 +51,8 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { let vp_cord = (in.tex_coords - constants.viewport_offset) * constants.viewport_scale; + // Vello renders its values to an `RgbaUnorm` texture, but if we try to use this in the main rendering pipeline + // which renders to an `Srgb` surface, gamma mapping is applied twice. This converts back to linear to compensate. let ov_raw = textureSample(t_overlays, s_diffuse, vp_cord); let ov = vec4(srgb_to_linear(ov_raw.rgb), ov_raw.a); let vp_raw = textureSample(t_viewport, s_diffuse, vp_cord); From 163052b98a35c5a53a89e8addf1ab0d99abaa4e8 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Tue, 5 Aug 2025 11:47:19 +0200 Subject: [PATCH 3/3] Rename variables --- desktop/src/render/composite_shader.wgsl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/desktop/src/render/composite_shader.wgsl b/desktop/src/render/composite_shader.wgsl index f714490fb8..3232e44f96 100644 --- a/desktop/src/render/composite_shader.wgsl +++ b/desktop/src/render/composite_shader.wgsl @@ -49,21 +49,21 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4 { return ui; } - let vp_cord = (in.tex_coords - constants.viewport_offset) * constants.viewport_scale; + let viewport_coordinate = (in.tex_coords - constants.viewport_offset) * constants.viewport_scale; // Vello renders its values to an `RgbaUnorm` texture, but if we try to use this in the main rendering pipeline // which renders to an `Srgb` surface, gamma mapping is applied twice. This converts back to linear to compensate. - let ov_raw = textureSample(t_overlays, s_diffuse, vp_cord); - let ov = vec4(srgb_to_linear(ov_raw.rgb), ov_raw.a); - let vp_raw = textureSample(t_viewport, s_diffuse, vp_cord); - let vp = vec4(srgb_to_linear(vp_raw.rgb), vp_raw.a); + let overlay_raw = textureSample(t_overlays, s_diffuse, viewport_coordinate); + let overlay = vec4(srgb_to_linear(overlay_raw.rgb), overlay_raw.a); + let viewport_raw = textureSample(t_viewport, s_diffuse, viewport_coordinate); + let viewport = vec4(srgb_to_linear(viewport_raw.rgb), viewport_raw.a); - if (ov.a < 0.001) { - return blend(ui, vp); + if (overlay.a < 0.001) { + return blend(ui, viewport); } - let comp = blend(ov, vp); - return blend(ui, comp); + let composite = blend(overlay, viewport); + return blend(ui, composite); } fn srgb_to_linear(srgb: vec3) -> vec3 {