Replace mix calls with proper alpha blending in quad shaders

This commit is contained in:
Héctor Ramón Jiménez 2025-05-03 22:22:23 +02:00
parent 7a97773f17
commit 469261e5a6
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
5 changed files with 35 additions and 42 deletions

View file

@ -317,18 +317,7 @@ fn color_target_state(
) -> [Option<wgpu::ColorTargetState>; 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,
})]
}

View file

@ -20,7 +20,7 @@ fn interpolate_color(from_: vec4<f32>, to_: vec4<f32>, factor: f32) -> vec4<f32>
var color = to_rgb * (mixed * mixed * mixed);
// Alpha interpolation
color.a = mix(from_.a, to_.a, factor);
color = to_ * factor + from_ * (1.0 - factor);
return color;
}

View file

@ -5,6 +5,10 @@ struct Globals {
@group(0) @binding(0) var<uniform> globals: Globals;
fn blend(over: vec4<f32>, under: vec4<f32>, alpha: f32) -> vec4<f32> {
return over * alpha + under * (1.0 - alpha);
}
fn distance_alg(
frag_coord: vec2<f32>,
position: vec2<f32>,

View file

@ -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<f32>(pos, scale);
out.border_color = input.border_color;
out.border_color = vec4(input.border_color.xyz * input.border_color.a, input.border_color.a);
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<f32> {
let colors = array<vec4<f32>, 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<f32> = unpack_u32(input.offsets.xy);
@ -179,7 +179,7 @@ fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4<f32> {
internal_distance
);
mixed_color = mix(mixed_color, input.border_color, vec4<f32>(border_mix, border_mix, border_mix, border_mix));
mixed_color = blend(input.border_color, mixed_color, border_mix);
}
var dist: f32 = distance_alg(
@ -194,12 +194,18 @@ fn gradient_fs_main(input: GradientVertexOutput) -> @location(0) vec4<f32> {
border_radius + 0.5,
dist);
return vec4<f32>(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha);
return mixed_color * radius_alpha;
}
fn unpack_u32(color: vec2<u32>) -> vec4<f32> {
let rg: vec2<f32> = unpack2x16float(color.x);
let ba: vec2<f32> = unpack2x16float(color.y);
fn unpack_color(data: vec2<u32>) -> vec4<f32> {
let color = unpack_u32(data);
return vec4(color.xyz * color.a, color.a);
}
fn unpack_u32(data: vec2<u32>) -> vec4<f32> {
let rg: vec2<f32> = unpack2x16float(data.x);
let ba: vec2<f32> = unpack2x16float(data.y);
return vec4<f32>(rg.y, rg.x, ba.y, ba.x);
}

View file

@ -56,13 +56,13 @@ fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput {
);
out.position = globals.transform * transform * vec4<f32>(vertex_position(input.vertex_index), 0.0, 1.0);
out.color = input.color;
out.border_color = input.border_color;
out.color = vec4(input.color.xyz * input.color.a, input.color.a);
out.border_color = vec4(input.border_color.xyz * input.border_color.a, input.border_color.a);
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 = vec4(input.shadow_color.xyz, input.shadow_color.a);
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<f32>(border_mix, border_mix, border_mix, border_mix));
mixed_color = blend(input.border_color, input.color, border_mix);
}
var dist: f32 = distance_alg(
@ -113,7 +113,7 @@ fn solid_fs_main(
dist
);
let quad_color = vec4<f32>(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<f32>(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 blend(input.shadow_color, quad_color, (1.0 - radius_alpha) * shadow_alpha);
} else {
return quad_color;
}