Fix alpha blend factor so AA edges don't leak through on transparent surfaces - #22
Fix alpha blend factor so AA edges don't leak through on transparent surfaces#22mxaddict wants to merge 1 commit into
Conversation
You might want to check if you have all repos pulled and up to date. |
|
Thanks for the heads up, I'll check it when I get back on my PC
…On Sat, May 16, 2026, 20:53 Jakub Panek ***@***.***> wrote:
*panekj* left a comment (lapce/vger-rs#22)
<#22 (comment)>
Branch is currently based on cfdec48 (the rev floem_vger_renderer
pins); happy to rebase onto main if you'd like before merging.
You might want to check if you have all repos pulled and up to date.
Floem uses vger-rs pinned to 54ab813
<54ab813>
(which is on floem branch in this repo and we don't use main)
—
Reply to this email directly, view it on GitHub
<#22 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAIDAKM7AME4BAYSCSDWCTD43BQFVAVCNFSM6AAAAACZAP5WTSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DINRWHEYDKOJUHA>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
The pipeline used the same `SrcAlpha + OneMinusSrcAlpha` blend for both color AND alpha. For alpha that produces `out_a = src_a² + dst_a·(1 − src_a)` — the source alpha is squared. Antialiased SDF edges and text glyphs (where the conceptual fragment has full opacity but coverage < 1) end up writing alpha < their coverage to the framebuffer. On a transparent (PreMultiplied) Wayland surface that means the compositor blends every glyph / rounded-corner edge against the desktop, leaving visible "shine through" at borders and text. Color blend is unchanged. Alpha blend now uses `One + OneMinusSrcAlpha` so `out_a = src_a + dst_a·(1 − src_a)` — correct source-over alpha compositing. Also fixes a hidden-lifetime warning in `gpu_vec::bind_group_entry` (`wgpu::BindGroupEntry` → `wgpu::BindGroupEntry<'_>`). Caught by pikr (floem launcher) on a layer-shell Wayland surface.
|
Thanks @panekj — rebased onto One unrelated note from running |
|
Quick follow-up @panekj — I have an upcoming PR against |
Summary
The render pipeline uses
SrcAlpha + OneMinusSrcAlphafor both the colorand alpha components of the blend state (
src/lib.rsblend pipelinesetup). The color formula is correct source-over for a straight-alpha
fragment output:
…but applying the same factors to the alpha channel produces:
— the source alpha gets squared. For a fragment that is conceptually
fully opaque but partially covered (AA edge of an SDF shape, antialiased
glyph),
src.a = coverage, and the framebuffer ends up holdingcoverage²instead ofcoverage.On opaque surfaces (
CompositeAlphaMode::Opaque) this is invisible — thealpha channel is discarded. But on transparent surfaces (most Wayland
compositors negotiate
PreMultiplied, smoked-glass overlays, layer-shellpanels, popovers) the compositor blends every glyph and rounded-corner
edge against whatever is behind the window. Result: visible desktop
shine-through at borders and text.
This PR uses the standard "source-over with straight-alpha source" alpha
formula:
i.e.
One + OneMinusSrcAlphafor the alpha component. The color blendis unchanged.
Test plan
confirm no visible regression on opaque output (alpha is discarded
there, so should be byte-identical).
transparent surface — before: alpha-squared edges visibly translucent;
after: clean source-over compositing.
I came at this from the consumer side: the floem-based pikr launcher
(layer-shell Wayland surface) was bleeding the desktop through every
glyph edge and rounded badge corner. With this blend fix, the framebuffer
alpha matches the conceptual coverage.
Notes
The change also adjusts
gpu_vec::bind_group_entryto spell theelided lifetime explicitly (
wgpu::BindGroupEntry<'_>), silencing aclippy
mismatched_lifetime_syntaxeswarning on recent rustc. Drop-inclean-up only.
Branch is currently based on
cfdec48(the revfloem_vger_rendererpins); happy to rebase onto
mainif you'd like before merging.