我想将我的电影渲染软件从 DirectDraw 移植到 Direct2D。由于兼容性问题,需要在图像之上进行 GDI 渲染。为了优化性能,我想实现某种后缓冲机制,但是 alpha 通道信息似乎有问题,所有 GDI 绘图都显得有些透明。
我为我的窗口句柄创建了一个ID2D1HwndRenderTarget和一个用于将图像复制到的ID2D1Bitmap。位图的像素格式为DXGI_FORMAT_B8G8R8A8_UNORM,alpha 模式为D2D1_ALPHA_MODE_IGNORE。HwdRenderTarget 与 GDI 兼容,所以我的渲染函数看起来像这样:
HwdRenderTarget.BeginDraw;
HwdRenderTarget.DrawBitMap(myBitMap);
HwdRenderTarget.GetDC(dc);
... do GDI drawing here ...
HwdRenderTarget.ReleaseDC();
HwdRenderTarget.EndDraw;
这个版本工作得很好:GDI 对象用纯色绘制,DrawTextEx-Text 有透明背景。
为了优化性能,我想在“backbuffer”中进行 GDI 绘图,因此只需要在发生变化时进行。否则我只能渲染缓存的位图。位图是空的和透明的,所以只有绘制的对象应该是可见的。
所以我创建了一个 CompatibleRenderTarget ID2D1BitmapRenderTarget,alpha模式是D2D1_ALPHA_MODE_PREMULTIPLIED:
HwdRenderTarget.CreateCompatibleRenderTarget(nil, nil, nil, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE, CompatibleRenderTarget);
现在我在 CompatibleRenderTarget 中进行 GDI 渲染:
CompatibleRenderTarget.BeginDraw;
if Supports(CompatibleRenderTarget, ID2D1GdiInteropRenderTarget, GdiInteropRenderTarget) then
begin
GdiInteropRenderTarget.GetDC(D2D1_DC_INITIALIZE_MODE_CLEAR, dc);
... do GDI drawing here ...
GdiInteropRenderTarget.ReleaseDC(fDstSize);
end;
GdiInteropRenderTarget := nil;
CompatibleRenderTarget.EndDraw;
CompatibleRenderTarget.GetBitmap(BackBuffer); // save the bitmap for drawing
我的渲染函数现在看起来像这样:
HwdRenderTarget.BeginDraw;
HwdRenderTarget.DrawBitMap(myBitMap);
HwdRenderTarget.DrawBitmap(BackBuffer);
HwdRenderTarget.EndDraw;
现在的问题是,所有 GDI 绘图都是透明的,透明程度取决于底层图像像素的值。深色文本在深色图像背景上显示为深色,但在白色背景上变为白色。但是 GDI 中没有使用 alpha 通道,myBitmap 也没有 alpha 信息。
那么alpha信息是从哪里来的呢?有人有想法吗?提前致谢!
顺便说一句,在 CompatibleRenderTarget 上使用 Direct2D 绘图也可以正常工作。