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" />
This commit is contained in:
parent
832934a1e0
commit
54733e82ae
@ -217,7 +217,7 @@ impl SpecializedRenderPipeline for BoxShadowPipeline {
|
||||
pub struct ExtractedBoxShadow {
|
||||
pub stack_index: u32,
|
||||
pub transform: Mat4,
|
||||
pub rect: Rect,
|
||||
pub bounds: Vec2,
|
||||
pub clip: Option<Rect>,
|
||||
pub camera_entity: Entity,
|
||||
pub color: LinearRgba,
|
||||
@ -317,10 +317,7 @@ pub fn extract_shadows(
|
||||
stack_index: uinode.stack_index,
|
||||
transform: transform.compute_matrix() * Mat4::from_translation(offset.extend(0.)),
|
||||
color: box_shadow.color.into(),
|
||||
rect: Rect {
|
||||
min: Vec2::ZERO,
|
||||
max: shadow_size + 6. * blur_radius,
|
||||
},
|
||||
bounds: shadow_size + 6. * blur_radius,
|
||||
clip: clip.map(|clip| clip.clip),
|
||||
camera_entity,
|
||||
radius,
|
||||
@ -408,9 +405,7 @@ pub fn prepare_shadows(
|
||||
while item_index < ui_phase.items.len() {
|
||||
let item = &mut ui_phase.items[item_index];
|
||||
if let Some(box_shadow) = extracted_shadows.box_shadows.get(item.entity()) {
|
||||
let uinode_rect = box_shadow.rect;
|
||||
|
||||
let rect_size = uinode_rect.size().extend(1.0);
|
||||
let rect_size = box_shadow.bounds.extend(1.0);
|
||||
|
||||
// Specify the corners of the node
|
||||
let positions = QUAD_VERTEX_POSITIONS
|
||||
@ -472,7 +467,23 @@ pub fn prepare_shadows(
|
||||
box_shadow.radius.bottom_left,
|
||||
];
|
||||
|
||||
let uvs = [Vec2::ZERO, Vec2::X, Vec2::ONE, Vec2::Y];
|
||||
let uvs = [
|
||||
Vec2::new(positions_diff[0].x, positions_diff[0].y),
|
||||
Vec2::new(
|
||||
box_shadow.bounds.x + positions_diff[1].x,
|
||||
positions_diff[1].y,
|
||||
),
|
||||
Vec2::new(
|
||||
box_shadow.bounds.x + positions_diff[2].x,
|
||||
box_shadow.bounds.y + positions_diff[2].y,
|
||||
),
|
||||
Vec2::new(
|
||||
positions_diff[3].x,
|
||||
box_shadow.bounds.y + positions_diff[3].y,
|
||||
),
|
||||
]
|
||||
.map(|pos| pos / box_shadow.bounds);
|
||||
|
||||
for i in 0..4 {
|
||||
ui_meta.vertices.push(BoxShadowVertex {
|
||||
position: positions_clipped[i].into(),
|
||||
|
Loading…
Reference in New Issue
Block a user