You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
    }
}

问题分析

  1. 模糊源错误:你使用CompositionBackdropBrush作为模糊效果的输入源,这意味着模糊的是Sprite背后的内容,而非Sprite自身。如果Sprite没有设置自身的可见内容(比如纯色Brush),且背后无有效内容,自然看不到模糊效果。
  2. 视觉遮挡:代码中创建了两个SpriteVisual(visual和element),最后将空的visual插在element上方,完全遮挡了下方的模糊Sprite,导致无法看到效果。
  3. 模糊量太小: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背后的背景),则需要:

  1. 确保element不设置纯色Brush,保持透明
  2. 避免其他Visual遮挡element
  3. 确保element下方有可见的UI内容可以被模糊

内容的提问来源于stack exchange,提问作者work work

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 19:35:29