diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs index 4c00945c..b3ac3f48 100644 --- a/wgpu/src/quad.rs +++ b/wgpu/src/quad.rs @@ -317,18 +317,7 @@ fn color_target_state( ) -> [Option; 1] { [Some(wgpu::ColorTargetState { format, - blend: Some(wgpu::BlendState { - color: wgpu::BlendComponent { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - alpha: wgpu::BlendComponent { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add, - }, - }), + blend: Some(wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING), write_mask: wgpu::ColorWrites::ALL, })] } diff --git a/wgpu/src/quad/gradient.rs b/wgpu/src/quad/gradient.rs index 3c5fc33f..351e941d 100644 --- a/wgpu/src/quad/gradient.rs +++ b/wgpu/src/quad/gradient.rs @@ -97,6 +97,8 @@ impl Pipeline { "../shader/quad/gradient.wgsl" ), "\n", + include_str!("../shader/color.wgsl"), + "\n", include_str!("../shader/color/oklab.wgsl") ) } else { @@ -109,6 +111,8 @@ impl Pipeline { "../shader/quad/gradient.wgsl" ), "\n", + include_str!("../shader/color.wgsl"), + "\n", include_str!( "../shader/color/linear_rgb.wgsl" ) diff --git a/wgpu/src/quad/solid.rs b/wgpu/src/quad/solid.rs index 317a248c..fa1db172 100644 --- a/wgpu/src/quad/solid.rs +++ b/wgpu/src/quad/solid.rs @@ -74,6 +74,8 @@ impl Pipeline { label: Some("iced_wgpu.quad.solid.shader"), source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed( concat!( + include_str!("../shader/color.wgsl"), + "\n", include_str!("../shader/quad.wgsl"), "\n", include_str!("../shader/vertex.wgsl"), diff --git a/wgpu/src/shader/color.wgsl b/wgpu/src/shader/color.wgsl new file mode 100644 index 00000000..a8066368 --- /dev/null +++ b/wgpu/src/shader/color.wgsl @@ -0,0 +1,14 @@ +fn premultiply(color: vec4) -> vec4 { + return vec4(color.xyz * color.a, color.a); +} + +fn unpack_color(data: vec2) -> vec4 { + return premultiply(unpack_u32(data)); +} + +fn unpack_u32(data: vec2) -> vec4 { + let rg: vec2 = unpack2x16float(data.x); + let ba: vec2 = unpack2x16float(data.y); + + return vec4(rg.y, rg.x, ba.y, ba.x); +} diff --git a/wgpu/src/shader/quad/gradient.wgsl b/wgpu/src/shader/quad/gradient.wgsl index 4ad2fea8..a1b4b107 100644 --- a/wgpu/src/shader/quad/gradient.wgsl +++ b/wgpu/src/shader/quad/gradient.wgsl @@ -56,7 +56,7 @@ fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput { out.offsets = input.offsets; out.direction = input.direction * globals.scale; out.position_and_scale = vec4(pos, scale); - out.border_color = input.border_color; + out.border_color = premultiply(input.border_color); out.border_radius = border_radius * globals.scale; out.border_width = input.border_width * globals.scale; @@ -119,14 +119,14 @@ fn gradient( @fragment fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { let colors = array, 8>( - unpack_u32(input.colors_1.xy), - unpack_u32(input.colors_1.zw), - unpack_u32(input.colors_2.xy), - unpack_u32(input.colors_2.zw), - unpack_u32(input.colors_3.xy), - unpack_u32(input.colors_3.zw), - unpack_u32(input.colors_4.xy), - unpack_u32(input.colors_4.zw), + unpack_color(input.colors_1.xy), + unpack_color(input.colors_1.zw), + unpack_color(input.colors_2.xy), + unpack_color(input.colors_2.zw), + unpack_color(input.colors_3.xy), + unpack_color(input.colors_3.zw), + unpack_color(input.colors_4.xy), + unpack_color(input.colors_4.zw), ); let offsets_1: vec4 = unpack_u32(input.offsets.xy); @@ -179,7 +179,7 @@ fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { internal_distance ); - mixed_color = mix(mixed_color, input.border_color, vec4(border_mix, border_mix, border_mix, border_mix)); + mixed_color = mix(mixed_color, input.border_color, border_mix); } var dist: f32 = distance_alg( @@ -194,12 +194,5 @@ fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { border_radius + 0.5, dist); - return vec4(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha); -} - -fn unpack_u32(color: vec2) -> vec4 { - let rg: vec2 = unpack2x16float(color.x); - let ba: vec2 = unpack2x16float(color.y); - - return vec4(rg.y, rg.x, ba.y, ba.x); + return mixed_color * radius_alpha; } diff --git a/wgpu/src/shader/quad/solid.wgsl b/wgpu/src/shader/quad/solid.wgsl index 8eee16bb..f4c39f3d 100644 --- a/wgpu/src/shader/quad/solid.wgsl +++ b/wgpu/src/shader/quad/solid.wgsl @@ -56,13 +56,13 @@ fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { ); out.position = globals.transform * transform * vec4(vertex_position(input.vertex_index), 0.0, 1.0); - out.color = input.color; - out.border_color = input.border_color; + out.color = premultiply(input.color); + out.border_color = premultiply(input.border_color); out.pos = input.pos * globals.scale + snap; out.scale = input.scale * globals.scale; out.border_radius = border_radius * globals.scale; out.border_width = input.border_width * globals.scale; - out.shadow_color = input.shadow_color; + out.shadow_color = premultiply(input.shadow_color); out.shadow_offset = input.shadow_offset * globals.scale; out.shadow_blur_radius = input.shadow_blur_radius * globals.scale; @@ -97,7 +97,7 @@ fn solid_fs_main( internal_distance ); - mixed_color = mix(input.color, input.border_color, vec4(border_mix, border_mix, border_mix, border_mix)); + mixed_color = mix(input.color, input.border_color, border_mix); } var dist: f32 = distance_alg( @@ -113,7 +113,7 @@ fn solid_fs_main( dist ); - let quad_color = vec4(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha); + let quad_color = mixed_color * radius_alpha; if input.shadow_color.a > 0.0 { let shadow_radius = select_border_radius( @@ -121,17 +121,11 @@ fn solid_fs_main( input.position.xy - input.shadow_offset, (input.pos + input.scale * 0.5).xy ); - let shadow_distance = max(rounded_box_sdf(input.position.xy - input.pos - input.shadow_offset - (input.scale / 2.0), input.scale / 2.0, shadow_radius), 0.); - - let shadow_alpha = 1.0 - smoothstep(-input.shadow_blur_radius, input.shadow_blur_radius, shadow_distance); - let shadow_color = input.shadow_color; - let base_color = mix( - vec4(shadow_color.x, shadow_color.y, shadow_color.z, 0.0), - quad_color, - quad_color.a - ); - return mix(base_color, shadow_color, (1.0 - radius_alpha) * shadow_alpha); + let shadow_distance = max(rounded_box_sdf(input.position.xy - input.pos - input.shadow_offset - (input.scale / 2.0), input.scale / 2.0, shadow_radius), 0.); + let shadow_alpha = 1.0 - smoothstep(-input.shadow_blur_radius, input.shadow_blur_radius, shadow_distance); + + return mix(quad_color, input.shadow_color, (1.0 - radius_alpha) * shadow_alpha); } else { return quad_color; } diff --git a/wgpu/src/shader/triangle/gradient.wgsl b/wgpu/src/shader/triangle/gradient.wgsl index 1a8ae3b5..31a48026 100644 --- a/wgpu/src/shader/triangle/gradient.wgsl +++ b/wgpu/src/shader/triangle/gradient.wgsl @@ -87,14 +87,14 @@ fn gradient( @fragment fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { let colors = array, 8>( - unpack_u32(input.colors_1.xy), - unpack_u32(input.colors_1.zw), - unpack_u32(input.colors_2.xy), - unpack_u32(input.colors_2.zw), - unpack_u32(input.colors_3.xy), - unpack_u32(input.colors_3.zw), - unpack_u32(input.colors_4.xy), - unpack_u32(input.colors_4.zw), + unpack_color(input.colors_1.xy), + unpack_color(input.colors_1.zw), + unpack_color(input.colors_2.xy), + unpack_color(input.colors_2.zw), + unpack_color(input.colors_3.xy), + unpack_color(input.colors_3.zw), + unpack_color(input.colors_4.xy), + unpack_color(input.colors_4.zw), ); let offsets_1: vec4 = unpack_u32(input.offsets.xy); @@ -122,13 +122,6 @@ fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4 { return gradient(input.raw_position, input.direction, colors, offsets, last_index); } -fn unpack_u32(color: vec2) -> vec4 { - let rg: vec2 = unpack2x16float(color.x); - let ba: vec2 = unpack2x16float(color.y); - - return vec4(rg.y, rg.x, ba.y, ba.x); -} - fn random(coords: vec2) -> f32 { return fract(sin(dot(coords, vec2(12.9898,78.233))) * 43758.5453); } diff --git a/wgpu/src/shader/triangle/solid.wgsl b/wgpu/src/shader/triangle/solid.wgsl index 9ef81982..b0d8057b 100644 --- a/wgpu/src/shader/triangle/solid.wgsl +++ b/wgpu/src/shader/triangle/solid.wgsl @@ -12,7 +12,7 @@ struct SolidVertexOutput { fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { var out: SolidVertexOutput; - out.color = input.color; + out.color = premultiply(input.color); out.position = globals.transform * vec4(input.position, 0.0, 1.0); return out; diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs index 6d0b0322..a3f850dd 100644 --- a/wgpu/src/triangle.rs +++ b/wgpu/src/triangle.rs @@ -595,7 +595,7 @@ fn fragment_target( ) -> wgpu::ColorTargetState { wgpu::ColorTargetState { format: texture_format, - blend: Some(wgpu::BlendState::ALPHA_BLENDING), + blend: Some(wgpu::BlendState::PREMULTIPLIED_ALPHA_BLENDING), write_mask: wgpu::ColorWrites::ALL, } } @@ -754,6 +754,8 @@ mod solid { include_str!("shader/triangle.wgsl"), "\n", include_str!("shader/triangle/solid.wgsl"), + "\n", + include_str!("shader/color.wgsl"), )), ), }); @@ -913,6 +915,8 @@ mod gradient { "shader/triangle/gradient.wgsl" ), "\n", + include_str!("shader/color.wgsl"), + "\n", include_str!("shader/color/oklab.wgsl") ) } else { @@ -923,6 +927,8 @@ mod gradient { "shader/triangle/gradient.wgsl" ), "\n", + include_str!("shader/color.wgsl"), + "\n", include_str!( "shader/color/linear_rgb.wgsl" )