winforms - Direct2D 与 GDI+ 渲染目标混合透明为黑色
问题描述
重现此项目中的问题:
https://github.com/adrotter/GDIDirect2DDualRenderer
我正在尝试使 Direct2D 与我们当前的渲染引擎 GDI+ 一起工作。为此,我将所有对 GDI+ 的调用抽象化,并为 GDI+ 和 Direct2D 创建了一个具体的类。很多人似乎遇到的一个问题是,当您在具有透明颜色的渲染目标上调用 Clear 时,您会得到完全不透明的黑色背景。
来自上述堆栈溢出帖子的答案表明我需要一个 WS_EX_LAYERED 窗口,或者使用 DirectComposition,但我不确定这样做在 WinForms 中是否有效。此外,他们只是在谈论使窗口透明而不是位图上的像素。我想出的部分可行的解决方案是,如果调用了 Graphics.Clear,但我还没有开始使用渲染目标进行绘制,那么我在 Drawing.Graphics 对象上调用 Clear,然后开始绘制。如果我使用 Graphics.Clear(Color.Transparent),这将使背景完全透明(解决人们对黑色背景的问题)。
这是 100% 不透明度时的样子:
左边的色带是 Direct2D 渲染,右边的色带是 GDI+。它们看起来相似,但 Direct2D 看起来更暗。它变得更糟。
这是 50% 的不透明度
1% 不透明度
现在这就是我的解决方案部分有效的原因:0% 的不透明度效果很好。看这里。
现在我实际上并不认为将黑色与透明混合的目标是我首先使用 System.Drawing.Graphics 对象调用 Clear 的结果,因为我在没有使用我的技巧的情况下测试了部分透明度(我没有调用 GDI+ 图形完全)。对于不透明度 50 和 1,我仍然会得到与上面相同的结果。似乎使用具有部分透明度的位图调用 DrawBitmap 将始终将部分透明颜色与黑色混合。
以下是我的渲染目标的制作方式供参考:
Dim targetProperties As New RenderTargetProperties
targetProperties.Type = RenderTargetType.Default
targetProperties.PixelFormat = New Direct2D1.PixelFormat(Format.B8G8R8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied)
targetProperties.Usage = RenderTargetUsage.GdiCompatible
Dim factory = New Direct2D1.Factory()
_target = New DeviceContextRenderTarget(factory, targetProperties)
_target.BindDeviceContext(_graphics.GetHdc(), rec)
这里还可以参考我如何将 System.Drawing.Bitmap 转换为 Direct2D1Bitmap:
Private Function GetDirect2DBitmap(bmp As System.Drawing.Bitmap) As SharpDX.Direct2D1.Bitmap
Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits(
New System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb)
Dim stream As New SharpDX.DataStream(bmpData.Scan0, bmpData.Stride * bmpData.Height, True, False)
Dim pFormat As New SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, Direct2D1.AlphaMode.Premultiplied)
Dim bmpProps As New SharpDX.Direct2D1.BitmapProperties(pFormat)
Dim result As New SharpDX.Direct2D1.Bitmap(
_targets(_selectedTargetIdx),
New SharpDX.Size2(bmp.Width, bmp.Height),
stream,
bmpData.Stride,
bmpProps)
bmp.UnlockBits(bmpData)
stream.Dispose()
Return result
End Function
这是获取我的半透明位图的简化:
//using C# style comments so this looks prettier
//Make empty bitmap to draw on
dim canvasBMP = new System.Drawing.Bitmap(100,100)
//Make the bitmap that has partial transparent pixels
dim partialTransparentBMP as System.Drawing.Bitmap = GetSemiTransparentBMP(100,100)
Using g as System.Drawing.Graphics = Graphics.FromImage(canvasBMP)
g.Clear(Color.White)
dim d2dTarget = MakeRenderTarget(g, g.VisibleClipBounds)
d2dTarget.BeginDraw()
d2dTarget.DrawBitmap(GetDirect2DBitmap(partialTransparentBMP), GetDirect2DRect(...), 1.0F, BitmapInterpolationMode.Linear)
d2dTarget.EndDraw()
End Using
如何使用 GDI+ 渲染目标获得白色混合的部分透明像素而不是黑色像素?
解决方案
推荐阅读
- python - ValueError:检查目标时出错:预期 lstm_2 有 3 个维度,但得到了形状为 (1, 184800) 的数组
- reactjs - Reactjs——父、子——各自的状态处理架构
- postgresql - 从 Postgres 到 Hive/HDFS 的每日数据归档
- jmeter - 如何在 PKS 上安装 apache Jmeter (pivotal-container-service)
- python - 我怎样才能随机获取摩尔斯电码输入和输出意大利语单词?
- javascript - 如何将数据从剪贴板粘贴到多个输入字段?
- c++ - 双线程二叉搜索树 - 保存父节点和祖父节点以设置线程
- python-3.x - 打印账单
- c# - 使用同一个类存储函数多次运行的数据
- php - Lavarel - 关系错误:调用模型 [App\Nota] 上的未定义关系 [nota]