1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-01 14:20:04 -04:00

Add RectShape::blur_width to implement shadows (#4267)

This is mostly a refactor, but has some performance benefits:
* We (re)use the same tessellator as for everything else, leading to
less allocations
* We cull shapes before rendering them

Adding `RectShape::blur_width` means it can also be used for other
effects, such as glow.
This commit is contained in:
Emil Ernerfeldt
2024-03-29 20:29:42 +01:00
committed by GitHub
parent 73dbfd689b
commit a541e021aa
7 changed files with 62 additions and 51 deletions

View File

@@ -1503,9 +1503,10 @@ impl Tessellator {
pub fn tessellate_rect(&mut self, rect: &RectShape, out: &mut Mesh) {
let RectShape {
mut rect,
rounding,
mut rounding,
fill,
stroke,
mut blur_width,
fill_texture_id,
uv,
} = *rect;
@@ -1524,6 +1525,29 @@ impl Tessellator {
rect.min = rect.min.at_least(pos2(-1e7, -1e7));
rect.max = rect.max.at_most(pos2(1e7, 1e7));
let old_feathering = self.feathering;
if old_feathering < blur_width {
// We accomplish the blur by using a larger-than-normal feathering.
// Feathering is usually used to make the edges of a shape softer for anti-aliasing.
// The tessellator can't handle blurring/feathering larger than the smallest side of the rect.
// Thats because the tessellator approximate very thin rectangles as line segments,
// and these line segments don't have rounded corners.
// When the feathering is small (the size of a pixel), this is usually fine,
// but here we have a huge feathering to simulate blur,
// so we need to avoid this optimization in the tessellator,
// which is also why we add this rather big epsilon:
let eps = 0.1;
blur_width = blur_width
.at_most(rect.size().min_elem() - eps)
.at_least(0.0);
rounding += Rounding::same(0.5 * blur_width);
self.feathering = self.feathering.max(blur_width);
}
if rect.width() < self.feathering {
// Very thin - approximate by a vertical line-segment:
let line = [rect.center_top(), rect.center_bottom()];
@@ -1566,6 +1590,8 @@ impl Tessellator {
path.stroke_closed(self.feathering, stroke, out);
}
self.feathering = old_feathering; // restore
}
/// Tessellate a single [`TextShape`] into a [`Mesh`].