我想将我的电影渲染软件从 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;
Run Code Online (Sandbox Code Playgroud)
这个版本工作得很好:GDI 对象使用纯色绘制,DrawTextEx-Text 具有透明背景。
为了优化性能,我想在“后台缓冲区”中进行 GDI 绘图,因此只需要在发生变化时才需要完成。否则我只能渲染缓存的位图。位图是空的和透明的,所以只有绘制的对象应该是可见的。
所以我创建了一个 CompatibleRenderTarget ID2D1BitmapRenderTarget,alpha 模式是D2D1_ALPHA_MODE_PREMULTIPLIED:
HwdRenderTarget.CreateCompatibleRenderTarget(nil, nil, nil, D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_GDI_COMPATIBLE, CompatibleRenderTarget);
Run Code Online (Sandbox Code Playgroud)
现在我在 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); …Run Code Online (Sandbox Code Playgroud)