Skip to content

Commit 54733e8

Browse files
ickshonpemockersf
authored andcommitted
box-shadow clipping fix (#16790)
Instead of clipping the non-visable sections of box-shadows, the shadow is scaled to fit into the remaining area after clipping because the normalized coordinates that are meant to border the unclipped subsection of the shadow are always set to `[Vec2::ZERO, Vec2::X, Vec2::ONE, Vec2::Y]`, Calculate the coordinates for the corners of the visible area. Test app: ```rust use bevy::color::palettes::css::RED; use bevy::color::palettes::css::WHITE; use bevy::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .run(); } fn setup(mut commands: Commands) { commands.spawn(Camera2d); commands .spawn(Node { ..Default::default() }) .with_children(|commands| { commands .spawn(( Node { width: Val::Px(100.), height: Val::Px(100.), margin: UiRect { left: Val::Px(100.), top: Val::Px(300.), ..Default::default() }, overflow: Overflow::clip(), ..Default::default() }, BackgroundColor(WHITE.into()), )) .with_children(|commands| { commands.spawn(( Node { position_type: PositionType::Absolute, left: Val::Px(50.), top: Val::Px(50.), width: Val::Px(100.), height: Val::Px(100.), ..Default::default() }, BackgroundColor(RED.into()), BoxShadow::from(ShadowStyle { x_offset: Val::ZERO, y_offset: Val::ZERO, spread_radius: Val::Px(50.), blur_radius: Val::Px(6.), ..Default::default() }), )); }); }); } ``` Main: <img width="103" alt="bad_shadow" src="https://github.com/user-attachments/assets/6f7ade0e-959f-4d18-92e8-903630eb8cd3" /> This PR: <img width="98" alt="clipped_shadow" src="https://github.com/user-attachments/assets/7f576c94-908c-4fe6-abaa-f18fefe05207" />
1 parent 832934a commit 54733e8

File tree

1 file changed

+20
-9
lines changed

1 file changed

+20
-9
lines changed

crates/bevy_ui/src/render/box_shadow.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ impl SpecializedRenderPipeline for BoxShadowPipeline {
217217
pub struct ExtractedBoxShadow {
218218
pub stack_index: u32,
219219
pub transform: Mat4,
220-
pub rect: Rect,
220+
pub bounds: Vec2,
221221
pub clip: Option<Rect>,
222222
pub camera_entity: Entity,
223223
pub color: LinearRgba,
@@ -317,10 +317,7 @@ pub fn extract_shadows(
317317
stack_index: uinode.stack_index,
318318
transform: transform.compute_matrix() * Mat4::from_translation(offset.extend(0.)),
319319
color: box_shadow.color.into(),
320-
rect: Rect {
321-
min: Vec2::ZERO,
322-
max: shadow_size + 6. * blur_radius,
323-
},
320+
bounds: shadow_size + 6. * blur_radius,
324321
clip: clip.map(|clip| clip.clip),
325322
camera_entity,
326323
radius,
@@ -408,9 +405,7 @@ pub fn prepare_shadows(
408405
while item_index < ui_phase.items.len() {
409406
let item = &mut ui_phase.items[item_index];
410407
if let Some(box_shadow) = extracted_shadows.box_shadows.get(item.entity()) {
411-
let uinode_rect = box_shadow.rect;
412-
413-
let rect_size = uinode_rect.size().extend(1.0);
408+
let rect_size = box_shadow.bounds.extend(1.0);
414409

415410
// Specify the corners of the node
416411
let positions = QUAD_VERTEX_POSITIONS
@@ -472,7 +467,23 @@ pub fn prepare_shadows(
472467
box_shadow.radius.bottom_left,
473468
];
474469

475-
let uvs = [Vec2::ZERO, Vec2::X, Vec2::ONE, Vec2::Y];
470+
let uvs = [
471+
Vec2::new(positions_diff[0].x, positions_diff[0].y),
472+
Vec2::new(
473+
box_shadow.bounds.x + positions_diff[1].x,
474+
positions_diff[1].y,
475+
),
476+
Vec2::new(
477+
box_shadow.bounds.x + positions_diff[2].x,
478+
box_shadow.bounds.y + positions_diff[2].y,
479+
),
480+
Vec2::new(
481+
positions_diff[3].x,
482+
box_shadow.bounds.y + positions_diff[3].y,
483+
),
484+
]
485+
.map(|pos| pos / box_shadow.bounds);
486+
476487
for i in 0..4 {
477488
ui_meta.vertices.push(BoxShadowVertex {
478489
position: positions_clipped[i].into(),

0 commit comments

Comments
 (0)