Direct2D 另一种与D3D创建类似的方法

在进行D2D学习的时候,发现了这样一篇文档,

Direct2D Quickstart for Windows 8

只有这么一小段介绍,

Direct2D is a native-code, immediate-mode API for creating 2D graphics. This topic illustrates how to use Direct2D to draw to a Windows::UI::Core::CoreWindow.

与先前使用CreateHwndRenderTarget直接创建渲染目标的方法不同,它使用的D3D中的交换链技术,也就是先创建Device,再从Device中创建context,有了context后,再在context中创建渲染对象,并将后缓存区绑定到渲染对象上。最终调用context来绘制图形。并使用交换链的技术present来显示图像。

目前不知道这个与之前d2d的绘图方法的主要区别,我猜测是性能方面可能是交换链技术更高,毕竟涉及到D3D。

以下的创建的详细步骤,

步骤1:包括Direct2D标头

除了应用程序所需的头之外,还包括d2d1.h和d2d1_1.h头。

步骤2:创建一个ID2D1Factory1

任何Direct2D示例所做的第一件事就是创建一个ID2D1Factory1

DX::ThrowIfFailed(
        D2D1CreateFactory(
            D2D1_FACTORY_TYPE_SINGLE_THREADED,
            __uuidof(ID2D1Factory1),
            &options,
            &m_d2dFactory
            )
        );

所述ID2D1Factory1接口是使用的Direct2D的起点; 使用ID2D1Factory1创建Direct2D资源。

创建工厂时,可以指定它是多线程还是单线程。(有关多线程工厂的更多信息,请参见ID2D1Factory参考页上的说明。)本示例创建一个单线程工厂。

通常,您的应用程序应创建一次工厂,并在应用程序的生命周期内保留它。

步骤3:创建一个ID2D1Device和一个ID2D1DeviceContext

创建工厂后,使用它创建Direct2D设备,然后使用该设备创建Direct2D设备上下文。为了创建这些Direct2D对象,您必须具有Direct3D 11设备DXGI设备DXGI交换链有关创建必要先决条件的信息,请参见设备和设备上下文

   // Obtain the underlying DXGI device of the Direct3D11.1 device.
    DX::ThrowIfFailed(
        m_d3dDevice.As(&dxgiDevice)
        );

    // Obtain the Direct2D device for 2-D rendering.
    DX::ThrowIfFailed(
        m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)
        );

    // And get its corresponding device context object.
    DX::ThrowIfFailed(
        m_d2dDevice->CreateDeviceContext(
            D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
            &m_d2dContext
            )
        );

设备上下文是可以执行绘图操作并创建与设备相关的绘图资源(如画笔)的设备。您还可以使用设备上下文将ID2D1Bitmap链接到DXGI曲面以用作渲染目标。设备上下文可以呈现给不同类型的目标。

此处的代码声明了位图的属性,该位图链接到渲染到CoreWindow的DXGI交换链ID2D1DeviceContext :: CreateBitmapFromDxgiSurface方法从表面DXGI得到了Direct2D的表面。这使得渲染到目标ID2D1Bitmap的所有内容都渲染到交换链的表面。

有了Direct2D曲面后,请使用ID2D1DeviceContext :: SetTarget方法将其设置为活动渲染目标。

   // Now we set up the Direct2D render target bitmap linked to the swapchain. 
    // Whenever we render to this bitmap, it will be directly rendered to the 
    // swapchain associated with the window.
    D2D1_BITMAP_PROPERTIES1 bitmapProperties = 
        BitmapProperties1(
            D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
            PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
            m_dpi,
            m_dpi
            );

    // Direct2D needs the dxgi version of the backbuffer surface pointer.
    ComPtr<IDXGISurface> dxgiBackBuffer;
    DX::ThrowIfFailed(
        m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
        );

    // Get a D2D surface from the DXGI back buffer to use as the D2D render target.
    DX::ThrowIfFailed(
        m_d2dContext->CreateBitmapFromDxgiSurface(
            dxgiBackBuffer.Get(),
            &bitmapProperties,
            &m_d2dTargetBitmap
            )
        );

    // So now we can set the Direct2D render target.
    m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());

第4步:创建画笔

就像工厂一样,设备上下文可以创建图形资源。在此示例中,设备上下文创建画笔。

ComPtr<ID2D1SolidColorBrush> pBlackBrush;
DX::ThrowIfFailed(
   m_d2dContext->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black),
        &pBlackBrush
        )
);

画笔是绘制区域的对象,例如形状的笔触或几何图形的填充。在此示例中,笔刷用预定义的纯色黑色绘制区域。

Direct2D还提供其他类型的笔刷:用于绘制线性和径向渐变的渐变笔刷,用于使用位图和图案进行绘制位图画笔,以及从Windows 8开始使用的用于绘制渲染图像图像笔刷

一些绘图API提供了用于绘制轮廓的笔和用于填充形状的画笔。Direct2D有所不同:它不提供笔对象,但使用笔刷绘制轮廓和填充形状。绘制轮廓时,请使用ID2D1StrokeStyle接口,或者在Windows 8中从ID2D1StrokeStyle1接口开始,使用画笔来控制路径描边操作。

画笔只能与创建画笔的渲染目标以及同一资源域中的其他渲染目标一起使用。通常,您应该只创建一次画笔,并在创建它们的渲染目标的整个生命周期内保留它们。ID2D1SolidColorBrush是唯一的异常;由于创建起来相对便宜,因此每次绘制框架时都可以创建一个ID2D1SolidColorBrush,而不会明显降低性能。您也可以使用一个ID2D1SolidColorBrush,并且每次使用时只需更改其颜色或不透明度。

步骤5:绘制矩形

接下来,使用设备上下文绘制矩形

m_d2dContext->BeginDraw();

m_d2dContext->DrawRectangle(
    D2D1::RectF(
        rc.left + 100.0f,
        rc.top + 100.0f,
        rc.right - 100.0f,
        rc.bottom - 100.0f),
        pBlackBrush);

DX::ThrowIfFailed(
    m_d2dContext->EndDraw()
);

DX::ThrowIfFailed(
    m_swapChain->Present1(1, 0, &parameters);
);

DrawRectangle的方法有两个参数:要绘制的矩形,并使用画笔绘制矩形的轮廓。(可选)您还可以指定笔划宽度,虚线图案,线连接和端盖选项。

您必须在发出任何绘图命令之前调用BeginDraw方法,并且在完成发出绘图命令之后必须调用EndDraw方法。EndDraw方法返回HRESULT指示绘图命令是否成功。如果失败,则ThrowIfFailed帮助器函数将引发异常。

所述IDXGISwapChain ::Present方法是交换缓冲面与上屏幕表面,以显示结果。

原文地址:https://www.cnblogs.com/strive-sun/p/14282093.html