首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GDI与Direct2D

GDI与Direct2D
EN

Stack Overflow用户
提问于 2012-11-08 11:28:53
回答 3查看 16K关注 0票数 16

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

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

我的问题是,当使用GDI时,我可以很容易地绘制400+椭圆,并且仍然有400fps。当我用Direct2D做相同数量的椭圆时,我的FPS下降到30FPS。

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

下面是我使用GDI的绘图代码:

代码语言:javascript
复制
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的开始和结束函数:

代码语言:javascript
复制
VOID BeginDrawing() {
    this->RenderTarget->BeginDraw();
    RenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::CornflowerBlue));
    RenderTarget->SetTransform(this->ScalingMatrix * this->TranslateMatrix);
}
VOID EndDrawing() {
    this->RenderTarget->EndDraw();
}

下面是我如何设置我的Direct2D界面。它都包装在类中;这就是我不能发布完整代码的原因:

代码语言:javascript
复制
    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);

提前谢谢你。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-08 13:04:26

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

我必须说,我曾尝试使用它来绘制简单的几何图元,而Direct2D似乎是一个更健壮的库,也许在复杂的场景中可以提高性能,但这不是我的情况。

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

这是一个相关的问题:Is TDirect2DCanvas slow or am I doing something wrong?

票数 5
EN

Stack Overflow用户

发布于 2013-09-23 06:01:19

第一次尝试Direct2D的一个常见错误是,开发人员没有正确地缓存D2D资源,而是过于频繁地创建和销毁资源。如果所有椭圆的大小相似,则应该创建并缓存此椭圆对象一次。如果您有30种不同的大小/形状,只需为所有30种大小/形状创建一次椭圆版本。这极大地提高了Direct2D的速度。矩形和所有其他原语也是如此。扩展缓存对象而不是重复创建/销毁也是一些方案的一种解决方案,如果原语存在太多变化,尽管使用原生大小的资源是理想的,并且存储卡有相当大的内存来存储资源。

Gdi椭圆看起来绝对可怕,直接使用Direct3D相当复杂,特别是对于椭圆、大多边形和高级基元。通过正确使用Direct2D,您应该能够获得良好的速度和高质量的渲染。

票数 40
EN

Stack Overflow用户

发布于 2020-05-11 18:04:51

我正在研究d2d。基本上它比gdi快2到3倍,如果你停留在基本绘图上的话。绘制线条,矩形,椭圆,..比如RenderTarget->DrawLine。在全局上,直接在渲染目标上绘制比gdi快2倍3倍。此外,不要忘记在d2d后台缓冲区而不是hwnd上绘制。这与使用GDI位图后台缓冲区但使用direct2d资源的过程完全相同。

如果要使用高级d2d对象,如几何体,这是另一回事。

例如,如果不创建矩形的变换几何图形的实例,则无法移动此矩形。

D2D资源是不可变的,尽管它们是在cpu级别管理的,但您不能修改源形状并只绘制它。您必须为每个平移、旋转创建此形状的副本...

如果你使用像paint这样的应用程序绘图,这不是一个大问题...但是如果你想使用一个实时系统,有大量的图形,鼠标点击测试,缩放,滚动等。然后,这可能会在性能上造成漏洞。

在我的测试中,我(在调试模式下)大约需要0.5s来转换/平移一个源几何体1000000次。

代码测试示例:

代码语言:javascript
复制
void TestGeometryPerf() { //1000000 = 0.35s/0.45s (in msvc 2019 debug mode)
    ID2D1RectangleGeometry *r;
    ID2D1TransformedGeometry *t;
    D2D1_RECT_F rect = D2D1::RectF(0, 0, 1, 1);
    D2D1::Matrix3x2F matrix = D2D1::Matrix3x2F::Translation(10,10);

    //create geometry source
    m_factory->CreateRectangleGeometry(rect, &r);

    for(int x = 0; x < 1000000; x++) {

        //create a transformed geometry from geometry source
        m_factory->CreateTransformedGeometry(r, matrix, &t);
        if( t->Release() != 0) {
            throw;
        }

    }
    if( r->Release() != 0) {
        throw;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13281964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档