Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
scenefx: fade follows the rounded outline; fix fade-mode scale corruption
Two rect fade bugs that together made cell corner radii invisible:
- quad_round.frag faded by distance to the STRAIGHT edges (a per-axis
product), forming a square-cornered onset that visually swamped the
corner arcs whenever fade and radius were combined. The fade now uses
the same rounded-rect SDF that cuts the corners, so it hugs the arcs.
- The render entity multiplied the whole wire-encoded fade value
(inset_px * 1000 + fade_mode) by the output scale, corrupting the mode
digit — quadratic became gaussian on a 2x output. Only the inset part
scales now.
Co-Authored-By: Claude Fable 5 <[email protected]>
scenefx/render/fx_renderer/shaders/quad_round.frag | 30 +++++++++-------------
scenefx/types/scene/wlr_scene.c | 8 +++++-
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/scenefx/render/fx_renderer/shaders/quad_round.frag b/scenefx/render/fx_renderer/shaders/quad_round.frag
index 8a2a0e4..0097061 100644
--- a/scenefx/render/fx_renderer/shaders/quad_round.frag
+++ b/scenefx/render/fx_renderer/shaders/quad_round.frag
@@ -65,33 +65,27 @@ void main() {
vec4 final_color = v_color;
if (fade_inset > 0.0) {
- // Calculate distance to closest vertical and horizontal edges
- float dist_x = min(relative_pos.x + 0.5, size.x - 0.5 - relative_pos.x);
- float dist_y = min(relative_pos.y + 0.5, size.y - 0.5 - relative_pos.y);
+ // Fade by distance to the ROUNDED outline — the same SDF that cuts
+ // the corners — not the straight edges. The old per-axis product
+ // formed a square-cornered onset at each corner that visually
+ // swamped the corner arcs whenever fade and radius were combined.
+ float edge_dist = -dist;
// Clamp to [0, fade_inset] and normalize
- float factor_x = clamp(dist_x / fade_inset, 0.0, 1.0);
- float factor_y = clamp(dist_y / fade_inset, 0.0, 1.0);
+ float factor = clamp(edge_dist / fade_inset, 0.0, 1.0);
- // Apply fade mode to components individually for best S-curve transition
if (fade_mode == 1) {
- factor_x = smoothstep(0.0, 1.0, factor_x);
- factor_y = smoothstep(0.0, 1.0, factor_y);
+ factor = smoothstep(0.0, 1.0, factor);
} else if (fade_mode == 2) {
- factor_x = factor_x * factor_x;
- factor_y = factor_y * factor_y;
+ factor = factor * factor;
} else if (fade_mode == 3) {
- factor_x = 0.5 - 0.5 * cos(factor_x * 3.14159265);
- factor_y = 0.5 - 0.5 * cos(factor_y * 3.14159265);
+ factor = 0.5 - 0.5 * cos(factor * 3.14159265);
} else if (fade_mode == 4) {
- float x = 1.0 - factor_x;
- factor_x = clamp((exp(-3.0 * x * x) - 0.049) / 0.951, 0.0, 1.0);
- float y = 1.0 - factor_y;
- factor_y = clamp((exp(-3.0 * y * y) - 0.049) / 0.951, 0.0, 1.0);
+ float x = 1.0 - factor;
+ factor = clamp((exp(-3.0 * x * x) - 0.049) / 0.951, 0.0, 1.0);
}
- float combined_factor = factor_x * factor_y;
- final_color *= pow(combined_factor, 2.2);
+ final_color *= pow(factor, 2.2);
}
gl_FragColor = final_color * quad_corner_alpha * clip_corner_alpha;
diff --git a/scenefx/types/scene/wlr_scene.c b/scenefx/types/scene/wlr_scene.c
index 79b4f47..97d5a40 100644
--- a/scenefx/types/scene/wlr_scene.c
+++ b/scenefx/types/scene/wlr_scene.c
@@ -2279,11 +2279,17 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren
// TODO: Use the base wlr_render_pass_add_rect as a fast-path in the future
if (!fx_corner_radii_is_empty(&rect_corners) || scene_rect->fade_inset > 0) {
+ // fade_inset is wire-encoded as inset_px * 1000 + fade_mode:
+ // scale only the inset part — multiplying the whole encoding
+ // also multiplied the mode digit (quadratic became gaussian on
+ // a 2x output).
+ int fade_enc = scene_rect->fade_inset;
+ int fade_px = (int)((float)(fade_enc / 1000) * data->scale + 0.5f);
struct fx_render_rounded_rect_options rounded_rect_options = {
.base = rect_options.base,
.corners = fx_corner_radii_scale(rect_corners, data->scale),
.clipped_region = rect_options.clipped_region,
- .fade_inset = scene_rect->fade_inset * data->scale,
+ .fade_inset = fade_px * 1000 + fade_enc % 1000,
};
fx_render_pass_add_rounded_rect(fx_pass, &rounded_rect_options);
} else {