双Pass Direct2D模糊效果输出纹理尺寸异常问题排查
双Pass模糊效果第二Pass采样异常问题
我正在实现一个带遮罩支持的简单双Pass模糊效果:
- 仅输出第一Pass结果时,图像能铺满整个画布,符合预期:
var bitmapProps = new SharpDX.Direct2D1.BitmapProperties1( new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied), TargetBitmap!.DotsPerInch.Width, TargetBitmap.DotsPerInch.Height, SharpDX.Direct2D1.BitmapOptions.Target); //Copy the current content of the canvas/TargetBitmap into the new source bitmap. using var effectSource = new SharpDX.Direct2D1.Bitmap1(DeviceContext, new SharpDX.Size2(CanvasWidth, CanvasHeight), bitmapProps); effectSource.CopyFromBitmap(TargetBitmap); _blurEffect1.SetInput(0, effectSource, true); DeviceContext.DrawImage(_blurEffect1, new SharpDX.Mathematics.Interop.RawVector2(0, 0));
- 但将第一Pass结果传入第二Pass输出时,图像无法铺满画布,剩余区域显示随机颜色:
_blurEffect1.SetInput(0, effectSource, true); _blurEffect2.SetInput(0, effectSource, true); _blurEffect2.SetInput(1, _blurEffect1.Output, false); //Draw to canvas DeviceContext.DrawImage(_blurEffect2, new SharpDX.Mathematics.Interop.RawVector2(0, 0));

通过GetImageLocalBounds获取两者分辨率,结果一致:
var aa = DeviceContext.GetImageLocalBounds(_blurEffect1.Output); var bb = DeviceContext.GetImageLocalBounds(_blurEffect2.Output);
第二Pass的HLSL代码逻辑简单:
Texture2D OriginalTexture : register(t0); Texture2D BlurredInputTexture : register(t1); SamplerState InputSampler : register(s0); float4 main(float4 pos : SV_POSITION, float4 posScene : SCENE_POSITION, float4 uv0 : TEXCOORD0) : SV_Target { float2 uv = uv0.xy; float mask = ComputeShapeMask(uv); float4 original = OriginalTexture.Sample(InputSampler, uv); if (mask == 0.0) return original; return BlurredInputTexture.Sample(InputSampler, uv); }
请问是什么原因导致第二Pass的输入采样异常?
问题原因及解决方案
核心原因
- 输入边界参数错误:设置第二Pass输入时,对
_blurEffect1.Output使用了false参数,Direct2D没有保留输入图像的完整边界信息,导致模糊后的纹理有效区域被截断,超出部分采样出现随机颜色。 - UV坐标不匹配:直接使用
uv0.xy作为采样坐标,没有考虑模糊效果可能改变的纹理UV空间范围,部分区域采样坐标越界。 - 采样器地址模式问题:默认采样器地址模式可能为
Wrap,越界采样时会循环取数,表现为随机颜色。
修复步骤
修正输入边界保留参数
将第二Pass输入1的参数改为true,确保Direct2D传递完整的模糊纹理区域:_blurEffect2.SetInput(1, _blurEffect1.Output, true);适配UV坐标到纹理空间
改用posScene计算准确的UV坐标,确保适配模糊后的纹理尺寸:float2 uv = posScene.xy / float2(OriginalTexture.Width, OriginalTexture.Height);设置采样器为Clamp模式
修改采样器状态,越界时取边缘像素,避免随机颜色:SamplerState InputSampler : register(s0) { Filter = MIN_MAG_MIP_LINEAR; AddressU = CLAMP; AddressV = CLAMP; };
内容的提问来源于stack exchange,提问作者Nicke Manarin
相关产品推荐
相关产品推荐

