GDI 与 Direct2D

新手上路,请多包涵

我现在正在编写一个模拟程序,我想将我的应用程序从使用 GDI 移植到使用 Direct2D。但是我的 Direct2D 代码比我的 GDI 代码慢得多。

我在屏幕上渲染了很多椭圆。在我的 GDI 应用程序中,我绘制到内存设备上下文,然后使用 BitBlt 在 Windows 设备上下文上绘制。使用 Direct2D,我在 ID2D1HwndRenderTarget 上绘图。

我的问题是,当使用 GDI 时,我可以轻松绘制 400 多个椭圆并且仍然有 400 FPS。当我用 Direct2D 做相同数量的椭圆时,我的 FPS 下降到 30FPS。

我已经关闭了抗锯齿,但它并没有真正帮助。有趣的是,与 GDI 相比,在 Direct2D 中仅绘制几个椭圆会更快。我可以做些什么来提高 Direct2D 的性能,还是应该让我的应用程序继续使用 GDI?

这是我使用 GDI 绘制的代码:

 VOID Begin() {
    SelectObject(this->MemDeviceContext, this->MemoryBitmap);
    this->BackgroundBrush = CreateSolidBrush(this->BackgroundColor);
    HBRUSH OldBrush = (HBRUSH)SelectObject(this->MemDeviceContext, this->BackgroundBrush);
    Rectangle(this->MemDeviceContext, -1, -1, 801, 601);
    SelectObject(this->MemDeviceContext, OldBrush);
    DeleteObject(this->BackgroundBrush);
    SetViewportOrgEx(this->MemDeviceContext, 400, 300, &this->OldOrigin);
}
VOID End() {
    SetViewportOrgEx(this->MemDeviceContext, this->OldOrigin.x, this->OldOrigin.y, 0);
    BitBlt(this->DeviceContext, 0, 0, 800, 600, this->MemDeviceContext, 0, 0, SRCCOPY);
}

在我的 Begin 和 End 函数之间,我以标准 GDI 方式绘制椭圆。

这是我使用 Direct2D 的开始和结束函数:

 VOID BeginDrawing() {
    this->RenderTarget->BeginDraw();
    RenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
    RenderTarget->SetTransform(this->ScalingMatrix * this->TranslateMatrix);
}
VOID EndDrawing() {
    this->RenderTarget->EndDraw();
}

下面是我设置 Direct2D 接口的方法。一切都在课堂上;这就是为什么我不能发布完整的代码:

     if(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &Direct2DFactory) != S_OK)
        throw std::runtime_error("RENDERWINDOW::InitializeDirect2D: Failed to create a factory interface.");
    RECT WindowRect;
    memset(&WindowRect, 0, sizeof(RECT));
    GetClientRect(this->WndHandle, &WindowRect);
    D2D1_SIZE_U WindowSize = D2D1::SizeU(WindowRect.right, WindowRect.bottom);
    Direct2DFactory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_HARDWARE),
    D2D1::HwndRenderTargetProperties(this->WndHandle, WindowSize, D2D1_PRESENT_OPTIONS_IMMEDIATELY), &RenderTarget);

先感谢您。

原文由 roohan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 838
2 个回答

前段时间,由于性能低下,我拒绝将渲染代码从 GDI 迁移到 Direct2D。据我从谷歌了解到,Direct2D 性能取决于驱动程序和硬件优化,您不应该期望在不同硬件上具有相同的速度。 GDI 已经很老了,几乎在所有地方都能正常工作。

必须说我已经尝试使用它来绘制简单的几何图元,而 Direct2D 似乎是更强大的库,并且在复杂场景中可能会提高性能,但这不是我的情况。

如果您需要更高质量的 GDI 性能 - 尝试直接使用 OpenGL 或 Direct3D。

这是一个相关的问题: TDirect2DCanvas 是慢还是我做错了什么?

原文由 Eugene 发布,翻译遵循 CC BY-SA 3.0 许可协议

首次尝试 Direct2D 的一个常见错误是开发人员没有正确缓存 D2D 资源,而是过于频繁地创建和销毁资源。如果所有椭圆的大小都相似,则应创建并缓存此椭圆对象一次。如果您有 30 种不同的尺寸/形状,请为所有 30 种尺寸/形状创建一次椭圆版本。这显着加快了 Direct2D。矩形和所有其他基元也是如此。如果原语存在太多变化,则缩放缓存对象与重复创建/销毁也是某些场景的解决方案,尽管使用其本机大小的资源是理想的,并且存储卡有相当多的内存来存储您的资源。

Gdi 椭圆看起来非常糟糕,直接使用 Direct3D 相当复杂,尤其是对于椭圆、大多边形和更高级别的图元。通过正确使用 Direct2D,您应该能够获得良好的速度和高质量的渲染。

原文由 Robert 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题