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

Direct2D噪点效果边框可见问题的解决方法咨询

问题:带模糊+噪点的圆角矩形出现CLSID_D2D1Border导致的边框问题

我需要绘制带模糊效果的圆角矩形,并叠加噪点效果。预期效果为:

  • 模糊强度5f、噪点不透明度1f
  • 模糊强度10f、噪点不透明度1f

但实际实现时,噪点矩形因使用CLSID_D2D1Border效果出现了轻微可见的边框(例如模糊强度10f、噪点不透明度0.05f时的效果)。

我的实现代码如下:

var colorBrush = Brushes.CreateGetColorBrush(color);
var bitmapNoise = LoadImage.LoadGetBitmapSource(@"C:\Users\me\Documents\DivineAloexGit\RenderAddition\TestImages\NoiseTest.png");
var gaussBlureOffset = gaussBlurePower * 3.5f;

ID2D1BitmapRenderTarget* bitmapTarget;
RendererManager.DeviceContext->CreateCompatibleRenderTarget(&bitmapTarget);

bitmapTarget->BeginDraw();
var roundedRect = new RoundedRect()
{
    rect = RectF.Create(gaussBlureOffset / 2, gaussBlureOffset / 2, rect.Width - gaussBlureOffset, rect.Height - gaussBlureOffset),
    radiusX = roundVector.X,
    radiusY = roundVector.Y,
};
bitmapTarget->FillRoundedRectangle(&roundedRect, colorBrush);
bitmapTarget->EndDraw();

ID2D1Bitmap* bitmap;
bitmapTarget->GetBitmap(&bitmap);

ID2D1Effect* noiseBitmapSourceEffect;
RendererManager.DeviceContext->CreateEffect(D2D1Apis.CLSID_D2D1BitmapSource, &noiseBitmapSourceEffect);
noiseBitmapSourceEffect->SetValue((uint)BitmapSourceProp.WicBitmapSource, PropertyType.Unknown, (byte*)&bitmapNoise, 8);

ID2D1Effect* noiseBorderEffect;
RendererManager.DeviceContext->CreateEffect(D2D1Apis.CLSID_D2D1Border, &noiseBorderEffect);
var edgeX = BorderEdgeMode.Wrap;
var edgeY = BorderEdgeMode.Wrap;
noiseBorderEffect->SetValue((uint)BorderProp.EdgeModeX, PropertyType.Unknown, (byte*)&edgeX, sizeof(BorderEdgeMode));
noiseBorderEffect->SetValue((uint)BorderProp.EdgeModeY, PropertyType.Unknown, (byte*)&edgeY, sizeof(BorderEdgeMode));
noiseBorderEffect->SetInputEffect(0, noiseBitmapSourceEffect);

ID2D1Effect* noiseOpacityEffect;
RendererManager.DeviceContext->CreateEffect(D2D1Apis.CLSID_D2D1Opacity, &noiseOpacityEffect);
noiseOpacityEffect->SetValue((uint)OpacityProp.Opacity, PropertyType.Unknown, (byte*)&noiseOpacity, sizeof(float));
noiseOpacityEffect->SetInputEffect(0, noiseBorderEffect);

ID2D1Effect* gaussBlure;
RendererManager.DeviceContext->CreateEffect(D2D1Apis.CLSID_D2D1GaussianBlur, &gaussBlure);
gaussBlure->SetInput(0, (ID2D1Image*)bitmap);
gaussBlure->SetValue((uint)GaussianBlurProp.StandardDeviation, PropertyType.Unknown, (byte*)&gaussBlurePower, sizeof(float));

ID2D1Effect* compositeEffect;
RendererManager.DeviceContext->CreateEffect(D2D1Apis.CLSID_D2D1Composite, &compositeEffect);
var compositeSourceOver = CompositingMode.SourceOver;
compositeEffect->SetValue((uint)CompositeProp.Mode, PropertyType.Unknown, (byte*)&compositeSourceOver, sizeof(CompositingMode));
compositeEffect->SetInputEffect(0, noiseOpacityEffect);
compositeEffect->SetInputEffect(1, gaussBlure);

bitmapTarget->Release();
bitmap->Release();
noiseBitmapSourceEffect->Release();
noiseBorderEffect->Release();
noiseOpacityEffect->Release();
gaussBlure->Release();
//compositeEffect->Release();

RoundedNoiseRectCache[effectKey] = (nint)compositeEffect;
return compositeEffect;

我曾尝试使用CLSID_D2D12DAffineTransform但未成功,请问如何在保留模糊及模糊边框效果的前提下解决该问题?


解决方案

核心思路:用AlphaMask限定噪点区域

问题根源是CLSID_D2D1Border的平铺效果会超出圆角矩形的模糊区域,产生可见边框。通过CLSID_D2D1AlphaMask效果,将模糊后的圆角矩形作为掩码,让噪点只在掩码区域内显示,即可消除边框。

修改后的代码实现

替换原代码中创建compositeEffect的部分,改用AlphaMask:

// 保留原代码中创建gaussBlure、noiseOpacityEffect的逻辑

// 创建AlphaMask效果,用模糊后的圆角矩形作为掩码裁剪噪点
ID2D1Effect* alphaMaskEffect;
RendererManager.DeviceContext->CreateEffect(D2D1Apis.CLSID_D2D1AlphaMask, &alphaMaskEffect);
alphaMaskEffect->SetInputEffect(0, noiseOpacityEffect); // 输入1:处理好的噪点层
alphaMaskEffect->SetInputEffect(1, gaussBlure);        // 输入2:模糊后的圆角矩形作为掩码

// 释放原有的compositeEffect(如果已创建)
compositeEffect->Release();

// 缓存并返回最终效果
RoundedNoiseRectCache[effectKey] = (nint)alphaMaskEffect;
return alphaMaskEffect;

// 记得释放不再需要的对象(和原代码一致)
bitmapTarget->Release();
bitmap->Release();
noiseBitmapSourceEffect->Release();
noiseBorderEffect->Release();
noiseOpacityEffect->Release();
gaussBlure->Release();

其他可选方案

  1. 调整Border效果的边缘模式:将BorderEdgeMode.Wrap改为BorderEdgeMode.Clamp,同时确保噪点位图的尺寸与目标区域完全匹配,减少平铺接缝,但这种方法可靠性不如AlphaMask。
  2. 直接在圆角区域内绘制噪点:创建与圆角矩形匹配的渲染目标,手动重复绘制噪点位图到该区域,再叠加模糊效果,从根源避免Border效果的边缘问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:37:01