Skip to content

Commit 14f7b0f

Browse files
Merge branch 'master' into improve-save-document
2 parents 9a85877 + 67a7b98 commit 14f7b0f

File tree

1 file changed

+42
-20
lines changed

1 file changed

+42
-20
lines changed

desktop/src/render/composite_shader.wgsl

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,38 +44,60 @@ var s_diffuse: sampler;
4444

4545
@fragment
4646
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
47-
let ui = textureSample(t_ui, s_diffuse, in.tex_coords);
48-
if (ui.a >= 0.999) {
49-
return ui;
47+
let ui_linear = textureSample(t_ui, s_diffuse, in.tex_coords);
48+
if (ui_linear.a >= 0.999) {
49+
return ui_linear;
5050
}
5151

5252
let viewport_coordinate = (in.tex_coords - constants.viewport_offset) * constants.viewport_scale;
5353

54-
// Vello renders its values to an `RgbaUnorm` texture, but if we try to use this in the main rendering pipeline
55-
// which renders to an `Srgb` surface, gamma mapping is applied twice. This converts back to linear to compensate.
56-
let overlay_raw = textureSample(t_overlays, s_diffuse, viewport_coordinate);
57-
let overlay = vec4<f32>(srgb_to_linear(overlay_raw.rgb), overlay_raw.a);
58-
let viewport_raw = textureSample(t_viewport, s_diffuse, viewport_coordinate);
59-
let viewport = vec4<f32>(srgb_to_linear(viewport_raw.rgb), viewport_raw.a);
54+
let overlay_srgb = textureSample(t_overlays, s_diffuse, viewport_coordinate);
55+
let viewport_srgb = textureSample(t_viewport, s_diffuse, viewport_coordinate);
6056

61-
if (overlay.a < 0.001) {
62-
return blend(ui, viewport);
57+
// UI texture is premultiplied, we need to unpremultiply before blending
58+
let ui_srgb = linear_to_srgb(unpremultiply(ui_linear));
59+
60+
if (overlay_srgb.a < 0.001) {
61+
if (ui_srgb.a < 0.001) {
62+
return srgb_to_linear(viewport_srgb);
63+
} else {
64+
return srgb_to_linear(blend(ui_srgb, viewport_srgb));
65+
}
6366
}
6467

65-
let composite = blend(overlay, viewport);
66-
return blend(ui, composite);
67-
}
68+
let composite_linear = blend(srgb_to_linear(overlay_srgb), srgb_to_linear(viewport_srgb));
6869

69-
fn srgb_to_linear(srgb: vec3<f32>) -> vec3<f32> {
70-
return select(
71-
pow((srgb + 0.055) / 1.055, vec3<f32>(2.4)),
72-
srgb / 12.92,
73-
srgb <= vec3<f32>(0.04045)
74-
);
70+
if (ui_srgb.a < 0.001) {
71+
return composite_linear;
72+
}
73+
74+
return srgb_to_linear(blend(ui_srgb, linear_to_srgb(composite_linear)));
7575
}
7676

7777
fn blend(fg: vec4<f32>, bg: vec4<f32>) -> vec4<f32> {
7878
let a = fg.a + bg.a * (1.0 - fg.a);
7979
let rgb = fg.rgb * fg.a + bg.rgb * bg.a * (1.0 - fg.a);
8080
return vec4<f32>(rgb, a);
8181
}
82+
83+
fn linear_to_srgb(in: vec4<f32>) -> vec4<f32> {
84+
let cutoff = vec3<f32>(0.0031308);
85+
let lo = in.rgb * 12.92;
86+
let hi = 1.055 * pow(max(in.rgb, vec3<f32>(0.0)), vec3<f32>(1.0/2.4)) - 0.055;
87+
return vec4<f32>(select(lo, hi, in.rgb > cutoff), in.a);
88+
}
89+
90+
fn srgb_to_linear(in: vec4<f32>) -> vec4<f32> {
91+
let cutoff = vec3<f32>(0.04045);
92+
let lo = in.rgb / 12.92;
93+
let hi = pow((in.rgb + 0.055) / 1.055, vec3<f32>(2.4));
94+
return vec4<f32>(select(lo, hi, in.rgb > cutoff), in.a);
95+
}
96+
97+
fn unpremultiply(in: vec4<f32>) -> vec4<f32> {
98+
if (in.a > 0.0) {
99+
return vec4<f32>((in.rgb / in.a), in.a);
100+
} else {
101+
return vec4<f32>(0.0);
102+
}
103+
}

0 commit comments

Comments
 (0)