Prevent visual glitch when shadow blur width is very high (#4245)
* Closes https://github.com/emilk/egui/issues/4238 The comment in the code explains it well, but the short of it is this: we can't handle a shadow blur width larger than the shadow rectangle, so we need to clamp the blur. This means smaller things will cast shadows with a smaller blur width, but that's better than having visual glitches.
This commit is contained in:
parent
947b5813d7
commit
a15e6c2122
|
|
@ -1,3 +1,5 @@
|
|||
use emath::NumExt as _;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// The color and fuzziness of a fuzzy shape.
|
||||
|
|
@ -16,7 +18,7 @@ pub struct Shadow {
|
|||
|
||||
/// The width of the blur, i.e. the width of the fuzzy penumbra.
|
||||
///
|
||||
/// A value of 0.0 means no blur.
|
||||
/// A value of 0.0 means a sharp shadow.
|
||||
pub blur: f32,
|
||||
|
||||
/// Expand the shadow in all directions by this much.
|
||||
|
|
@ -47,12 +49,26 @@ impl Shadow {
|
|||
color,
|
||||
} = *self;
|
||||
|
||||
let rect = rect.translate(offset);
|
||||
let rect = rect.translate(offset).expand(spread);
|
||||
|
||||
// We simulate a blurry shadow by tessellating a solid rectangle using a very large 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;
|
||||
let blur = blur.at_most(rect.size().min_elem() - eps).at_least(0.0);
|
||||
|
||||
// TODO(emilk): if blur <= 0, return a simple `Shape::Rect` instead of using the tessellator
|
||||
|
||||
let rounding_expansion = spread.abs() + 0.5 * blur;
|
||||
let rounding = rounding.into() + Rounding::from(rounding_expansion);
|
||||
let rounding = rounding.into() + Rounding::same(rounding_expansion);
|
||||
|
||||
let rect = RectShape::filled(rect.expand(spread), rounding, color);
|
||||
let rect = RectShape::filled(rect, rounding, color);
|
||||
let pixels_per_point = 1.0; // doesn't matter here
|
||||
let font_tex_size = [1; 2]; // unused since we are not tessellating text.
|
||||
let mut tessellator = Tessellator::new(
|
||||
|
|
|
|||
Loading…
Reference in New Issue