Sprite添加Acrylic Blur无效果求助(附修改后代码)
Win32 Composition Sprite添加模糊效果失败问题排查
我参考官方文档修改代码,尝试为生成的Sprite添加模糊效果,同时参考了Effect brushes示例和Stack Overflow帖子的指导,但Sprite完全没有产生模糊效果。以下是修改后的AddElement函数代码:
void CompositionHost::AddElement(float size, float x, float y) { if (m_target.Root()) // if there is an actual visual root { auto visuals = m_target.Root().as<ContainerVisual>().Children(); auto visual = m_compositor.CreateSpriteVisual(); // CreateSpriteVisual creates an instance of a SpriteVisual which is basically a 2D box auto element = m_compositor.CreateSpriteVisual(); uint8_t r = (double)(double)(rand() % 255); ; uint8_t g = (double)(double)(rand() % 255); ; uint8_t b = (double)(double)(rand() % 255); ; GaussianBlurEffect blurEffect{}; winrt::hstring blurStr = winrt::hstring(L"Blur"); blurEffect.Name(blurStr); blurEffect.BlurAmount(1.0f); blurEffect.BorderMode(EffectBorderMode::Hard); blurEffect.Optimization(EffectOptimization::Balanced); CompositionEffectSourceParameter sourceParameter = CompositionEffectSourceParameter(L"source"); blurEffect.Source(sourceParameter); CompositionEffectFactory blurEffectFactory = m_compositor.CreateEffectFactory(blurEffect); CompositionEffectBrush blurBrush = blurEffectFactory.CreateBrush(); CompositionBackdropBrush backDropBrush = m_compositor.CreateBackdropBrush(); blurBrush.SetSourceParameter(L"source", backDropBrush); // bind backdrop brush to effect brush element.Brush(blurBrush); // paints that 2D box element.Size({ size, size }); element.Offset({ x, y, 0.0f, }); auto animation = m_compositor.CreateVector3KeyFrameAnimation(); auto bottom = (float)600 - element.Size().y; // setting the y-coord of the 1st keyframe where animation should start atz animation.InsertKeyFrame(1, { element.Offset().x, bottom, 0 }); // telling where the first keyfram should start at using timeSpan = std::chrono::duration<int, std::ratio<1, 1>>; // <> is a template, instead of having many functions for different data types // you specify the data types inside <> std::chrono::seconds duration(2); // construct new duration, similar to = sign std::chrono::seconds delay(3); animation.Duration(timeSpan(duration)); animation.DelayTime(timeSpan(delay)); // delay before animation starts element.StartAnimation(L"Offset", animation); visuals.InsertAtTop(element); // insert the color on top, top refers to the topmost of the app I think visuals.InsertAtTop(visual); // insert the 2D box on top } }
问题分析
- 模糊源错误:你使用
CompositionBackdropBrush作为模糊效果的输入源,这意味着模糊的是Sprite背后的内容,而非Sprite自身。如果Sprite没有设置自身的可见内容(比如纯色Brush),且背后无有效内容,自然看不到模糊效果。 - 视觉遮挡:代码中创建了两个
SpriteVisual(visual和element),最后将空的visual插在element上方,完全遮挡了下方的模糊Sprite,导致无法看到效果。 - 模糊量太小:
BlurAmount(1.0f)的数值极低,1px的模糊程度几乎无法用肉眼察觉。
修正方案
以下是调整后的代码,解决上述问题:
void CompositionHost::AddElement(float size, float x, float y) { if (m_target.Root()) { auto visuals = m_target.Root().as<ContainerVisual>().Children(); auto element = m_compositor.CreateSpriteVisual(); // 生成随机颜色,简化转换逻辑 uint8_t r = rand() % 255; uint8_t g = rand() % 255; uint8_t b = rand() % 255; // 创建纯色Brush,作为Sprite的原始显示内容 auto colorBrush = m_compositor.CreateColorBrush(Windows::UI::ColorHelper::FromArgb(255, r, g, b)); // 创建模糊效果,调大模糊量至10px,便于观察 GaussianBlurEffect blurEffect{}; blurEffect.BlurAmount(10.0f); blurEffect.BorderMode(EffectBorderMode::Hard); blurEffect.Optimization(EffectOptimization::Balanced); CompositionEffectSourceParameter sourceParameter = CompositionEffectSourceParameter(L"source"); blurEffect.Source(sourceParameter); auto blurEffectFactory = m_compositor.CreateEffectFactory(blurEffect); auto blurBrush = blurEffectFactory.CreateBrush(); // 将纯色Brush绑定为模糊效果的输入,使模糊作用于Sprite自身 blurBrush.SetSourceParameter(L"source", colorBrush); element.Brush(blurBrush); element.Size({ size, size }); element.Offset({ x, y, 0.0f }); // 保留原有动画逻辑 auto animation = m_compositor.CreateVector3KeyFrameAnimation(); auto bottom = (float)600 - element.Size().y; animation.InsertKeyFrame(1, { element.Offset().x, bottom, 0 }); using timeSpan = std::chrono::duration<int, std::ratio<1, 1>>; std::chrono::seconds duration(2); std::chrono::seconds delay(3); animation.Duration(timeSpan(duration)); animation.DelayTime(timeSpan(delay)); element.StartAnimation(L"Offset", animation); visuals.InsertAtTop(element); // 移除多余的空Visual,避免遮挡 // visuals.InsertAtTop(visual); } }
关键修改点
- 移除了多余的
visual变量及其插入操作,避免遮挡模糊Sprite - 创建纯色Brush作为模糊效果的输入源,让模糊作用于Sprite自身的颜色内容
- 将
BlurAmount调至10.0f,使模糊效果更明显 - 简化了随机颜色的生成代码,去掉不必要的强制转换
如果你的需求是实现毛玻璃效果(模糊Sprite背后的背景),则需要:
- 确保
element不设置纯色Brush,保持透明 - 避免其他Visual遮挡
element - 确保
element下方有可见的UI内容可以被模糊
内容的提问来源于stack exchange,提问作者work work
相关产品推荐
相关产品推荐

