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();
其他可选方案
- 调整Border效果的边缘模式:将
BorderEdgeMode.Wrap改为BorderEdgeMode.Clamp,同时确保噪点位图的尺寸与目标区域完全匹配,减少平铺接缝,但这种方法可靠性不如AlphaMask。 - 直接在圆角区域内绘制噪点:创建与圆角矩形匹配的渲染目标,手动重复绘制噪点位图到该区域,再叠加模糊效果,从根源避免Border效果的边缘问题。
内容的提问来源于stack exchange,提问作者Aloex
相关产品推荐
相关产品推荐

