Opacity compositing

This commit is contained in:
2026-03-23 16:33:19 -04:00
parent 6079117f2c
commit e327516e5e
6 changed files with 42 additions and 10 deletions

View File

@@ -330,6 +330,7 @@ pub struct WgpuSceneRenderer {
image_cache_order: VecDeque<u64>,
#[allow(dead_code)]
glyph_atlas: GlyphAtlas,
base_color: Color,
}
const MAX_TEXT_CACHE_ENTRIES: usize = 64;
@@ -343,6 +344,7 @@ impl WgpuSceneRenderer {
target: impl HasDisplayHandle + HasWindowHandle + Send + Sync + 'static,
width: u32,
height: u32,
base_color: Color,
) -> Result<Self, Box<dyn Error>> {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle());
let surface = instance.create_surface(target)?;
@@ -361,6 +363,15 @@ impl WgpuSceneRenderer {
.copied()
.find(wgpu::TextureFormat::is_srgb)
.unwrap_or(caps.formats[0]);
let alpha_mode = if base_color.a < 255
&& caps
.alpha_modes
.contains(&wgpu::CompositeAlphaMode::PreMultiplied)
{
wgpu::CompositeAlphaMode::PreMultiplied
} else {
caps.alpha_modes[0]
};
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format,
@@ -368,7 +379,7 @@ impl WgpuSceneRenderer {
height: height.max(1),
present_mode: wgpu::PresentMode::AutoVsync,
desired_maximum_frame_latency: 2,
alpha_mode: caps.alpha_modes[0],
alpha_mode,
view_formats: vec![],
};
surface.configure(&device, &config);
@@ -415,7 +426,7 @@ fn sd_round_rect(point: vec2<f32>, rect: vec4<f32>, radius: f32) -> f32 {
fn rounded_rect_alpha(point: vec2<f32>, rect: vec4<f32>, radius: f32) -> f32 {
let distance = sd_round_rect(point, rect, radius);
return 1.0 - smoothstep(0.0, 1.0, distance);
return 1.0 - smoothstep(-0.5, 0.5, distance);
}
fn blurred_round_rect_alpha(point: vec2<f32>, rect: vec4<f32>, radius: f32, blur: f32) -> f32 {
@@ -553,7 +564,7 @@ fn sd_round_rect(point: vec2<f32>, rect: vec4<f32>, radius: f32) -> f32 {
fn rounded_rect_alpha(point: vec2<f32>, rect: vec4<f32>, radius: f32) -> f32 {
let distance = sd_round_rect(point, rect, radius);
return 1.0 - smoothstep(0.0, 1.0, distance);
return 1.0 - smoothstep(-0.5, 0.5, distance);
}
fn apply_clip_alpha(point: vec2<f32>, clip_rect: vec4<f32>, rounded_clip_rect: vec4<f32>, clip_params: vec2<f32>) -> f32 {
@@ -710,6 +721,7 @@ fn fs_main(input: VertexOut) -> @location(0) vec4<f32> {
image_cache: HashMap::new(),
image_cache_order: VecDeque::new(),
glyph_atlas,
base_color,
})
}
@@ -792,11 +804,16 @@ fn fs_main(input: VertexOut) -> @location(0) vec4<f32> {
depth_slice: None,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.03,
g: 0.04,
b: 0.08,
a: 1.0,
load: wgpu::LoadOp::Clear({
let a = self.base_color.a as f64 / 255.0;
// Premultiplied: multiply RGB by alpha so the compositor
// can blend correctly when alpha_mode is PreMultiplied.
wgpu::Color {
r: (self.base_color.r as f64 / 255.0) * a,
g: (self.base_color.g as f64 / 255.0) * a,
b: (self.base_color.b as f64 / 255.0) * a,
a,
}
}),
store: wgpu::StoreOp::Store,
},