Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ GDI与Direct2D_C++_Winapi_Direct2d - Fatal编程技术网

C++ GDI与Direct2D

C++ GDI与Direct2D,c++,winapi,direct2d,C++,Winapi,Direct2d,我正在编写一个模拟程序,我想将我的应用程序从使用GDI移植到使用Direct2D。但是我的Direct2D代码比我的GDI代码慢得多 我在屏幕上渲染了很多椭圆。在我的GDI应用程序中,我绘制内存设备上下文,然后使用BitBlt绘制windows设备上下文。使用Direct2D,我将绘制到ID2D1HwndRenderTarget上 我的问题是,当使用GDI时,我可以轻松地画出400多个椭圆,但仍然有400 FPS。当我用Direct2D做同样数量的椭圆时,我的FPS下降到30FPS 我已经关闭了

我正在编写一个模拟程序,我想将我的应用程序从使用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);
}
在开始函数和结束函数之间,我用标准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);

提前感谢。

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

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

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

这是一个相关的问题:

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


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

我正在研究d2d。基本上它比gdi快2倍或3倍左右,如果您继续使用基本绘图的话。画线,矩形,椭圆。。类似于RenderTarget->DrawLine。从全局来看,直接在渲染目标上绘制比gdi快2倍3倍。另外,不要忘记使用d2d backbuffer而不是hwnd。这与使用gdi位图backbuffer的过程完全相同,但使用的是direct2d资源

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

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

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

这不是一个大问题,如果你使用应用程序绘图,如油漆。。。但是如果你想使用一个实时系统,有大量的形状,鼠标点击测试,缩放,滚动等等。。。那么这可能会在表演中给人留下一个洞

在我的测试中,转换/转换源几何体1000000次(在调试模式下)大约需要0.5秒

代码测试示例:

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;
    }
}
void TestGeometryPerf(){//1000000=0.35s/0.45s(在msvc 2019调试模式下)
ID2D1RectangleGeometry*r;
ID2D1变压器测量*t;
D2D1_RECT_F RECT=D2D1::RectF(0,0,1,1);
D2D1::Matrix3x2F矩阵=D2D1::Matrix3x2F::翻译(10,10);
//创建几何图形源
m_工厂->创建矩形几何体(矩形和r);
对于(int x=0;x<1000000;x++){
//从几何图形源创建变换的几何图形
m_工厂->创建转换几何(r、矩阵和t);
如果(t->Release()!=0){
投掷;
}
}
如果(r->Release()!=0){
投掷;
}
}

您没有显示D2D的绘图代码绘图代码是用于绘制椭圆的标准Direct2D代码。我使用了FillEllipse和DrawEllipse函数,其他什么都没有,这就是我没有发布它的原因。引入Direct2D的主要目的是一个新的干净API和DirectWrite的基本框架。绘制文本是当今最昂贵的操作,DirectWrite对于高质量文本的速度有了巨大的提高。也许你应该考虑用其他基本绘图原语进行测试。我怀疑你的应用程序只是在画省略号。嗨,谢谢你的回答。我考虑过使用Direct3D,但我的项目时间非常有限。这就是我用最简单的方法画椭圆的方法。在Direct3D中实现相同的结果要复杂得多。我想我只会使用GDI,并接受较低质量的椭圆。但奇怪的是,应该利用图形卡的东西比GDI慢很多。从GDI到GDI+的移植应该很简单。GDI+支持抗锯齿输出,因此质量与Direct2D一样好,而且GDI+的性能仍然比Direct2D好。Direct2D取决于DirectX 10/11驱动程序的存在。在它不存在的情况下,DATT2D将回到软件渲染,在这种情况下,它的性能是最差的。