zoukankan      html  css  js  c++  java
  • Direct2D CreateHwndRenderTarget 和 CreateDCRenderTarget

    前段时间稍微看了点Direct3D, 觉得挺有意思的,但是想着要有3D得先从2D开始。故开始了D2D旅行。

    如标题所示,CreateHwndRenderTarget 是在用来创建一个渲染到窗口的渲染目标。

    创建渲染目标并且可以使用硬件加速时,可以在计算机的GPU上分配资源。通过一次创建渲染目标并保留尽可能长的时间,您可以获得性能上的好处。您的应用程序应一次创建渲染目标,并在应用程序的生命周期内或在收到D2DERR_RECREATE_TARGET错误之前将其保留。收到此错误时,您需要重新创建渲染目标(及其创建的所有资源)。

    它与CreateDCRenderTarget最大的区别,也就是GDI的绘图技巧与D2D的区别了。

    我的个人理解是,前者是自己在GPU上创建渲染目标,并停留一段时间用来绘制,不用我们操心上下文的环境了。 而后者的作用是

    创建一个绘制目标,以绘制到Windows图形设备接口(GDI)设备上下文。

    很显然它是用来充当D2D与GDI的交互的。

    这篇文档是介绍这个作用的, Direct2D and GDI Interoperability Overview

    在代码上使用肯定也是有区别的。

    前者的使用,可以先看D2D入门的代码,下面的代码是用来将图片绘制到窗口上,

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <Windows.h>
    #include <d2d1.h>
    #include <d2d1_1.h>
    
    #include <wincodec.h>
    
    #pragma comment(lib, "d2d1.lib")
    #pragma comment(lib, "Windowscodecs.lib")
    
    #define SAFE_RELEASE(P) if(P){P->Release() ; P = NULL ;}
    
    
    extern "C" ID2D1Bitmap * mybitmapcreate(ID2D1DCRenderTarget*);
    float left = 5;
    float top = 10;
    float Bottom = 10;
    float Right = 30;
    ID2D1Bitmap* pBitmap = NULL;
    IWICImagingFactory* pIWICFactory = NULL;
    HWND hWnd;
    ID2D1HwndRenderTarget* m_pRenderTarget;
    
    void initize();
    void draw();
    D2D1_RECT_F myrect = D2D1::RectF(left, top, Bottom, Right);
    ID2D1Bitmap* mybitmap;
    ID2D1Factory* l;
    REFIID x = __uuidof(ID2D1Factory);
    
    HRESULT LoadBitmapFromFile(
        ID2D1RenderTarget* pRenderTarget,
        IWICImagingFactory* pIWICFactory,
        PCWSTR uri,
        UINT destinationWidth,
        UINT destinationHeight
    )
    {
        HRESULT hr = S_OK;
    
        IWICBitmapDecoder* pDecoder = NULL;
        IWICBitmapFrameDecode* pSource = NULL;
        IWICStream* pStream = NULL;
        IWICFormatConverter* pConverter = NULL;
        IWICBitmapScaler* pScaler = NULL;
    
    
        hr = pIWICFactory->CreateDecoderFromFilename(
            uri,
            NULL,
            GENERIC_READ,
            WICDecodeMetadataCacheOnLoad,
            &pDecoder
        );
        if (SUCCEEDED(hr))
        {
    
            // Create the initial frame.
            hr = pDecoder->GetFrame(0, &pSource);
        }
        if (SUCCEEDED(hr))
        {
            hr = pIWICFactory->CreateFormatConverter(&pConverter);
        }
        // If a new width or height was specified, create an
    // IWICBitmapScaler and use it to resize the image.
        if (destinationWidth != 0 || destinationHeight != 0)
        {
            UINT originalWidth, originalHeight;
            hr = pSource->GetSize(&originalWidth, &originalHeight);
            if (SUCCEEDED(hr))
            {
                if (destinationWidth == 0)
                {
                    FLOAT scalar = static_cast<FLOAT>(destinationHeight) / static_cast<FLOAT>(originalHeight);
                    destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth));
                }
                else if (destinationHeight == 0)
                {
                    FLOAT scalar = static_cast<FLOAT>(destinationWidth) / static_cast<FLOAT>(originalWidth);
                    destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight));
                }
    
                hr = pIWICFactory->CreateBitmapScaler(&pScaler);
                if (SUCCEEDED(hr))
                {
                    hr = pScaler->Initialize(
                        pSource,
                        destinationWidth,
                        destinationHeight,
                        WICBitmapInterpolationModeCubic
                    );
                }
                if (SUCCEEDED(hr))
                {
                    hr = pConverter->Initialize(
                        pScaler,
                        GUID_WICPixelFormat32bppPBGRA,
                        WICBitmapDitherTypeNone,
                        NULL,
                        0.f,
                        WICBitmapPaletteTypeMedianCut
                    );
                }
            }
        }
        if (SUCCEEDED(hr))
        {
            // Create a Direct2D bitmap from the WIC bitmap.
            hr = pRenderTarget->CreateBitmapFromWicBitmap(
                pConverter,
                NULL,
                &pBitmap
            );
        }
    
        SAFE_RELEASE(pDecoder);
        SAFE_RELEASE(pSource);
        SAFE_RELEASE(pStream);
        SAFE_RELEASE(pConverter);
        SAFE_RELEASE(pScaler);
    
        return TRUE;
    }
    
    LRESULT CALLBACK WndProcFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        RECT rc;
        switch (message)
        {
        case WM_PAINT:
        {
            draw();
        }
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    int main(int argc, char* argv[])
    {
        WNDCLASS wc{};
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WndProcFunc;
        wc.hInstance = GetModuleHandle(NULL);
        wc.lpszClassName = L"Class_Name";
        wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
        RegisterClass(&wc);
    
        hWnd = CreateWindow(L"Class_Name", L"Test", WS_OVERLAPPEDWINDOW, 100, 100, 1000, 500, NULL, NULL, GetModuleHandle(NULL), NULL);
        initize();
    
        ShowWindow(hWnd, 1);
        UpdateWindow(hWnd);
    
        MSG Msg;
        while (GetMessage(&Msg, NULL, 0, 0))
        {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
    
        return 0;
    }
    
    void initize()
    {
        CoInitializeEx(NULL, COINIT_MULTITHREADED);
        CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void**>(&pIWICFactory));
    
        HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &l);
    
        RECT rc;
        GetClientRect(hWnd, &rc);
    
        D2D1_SIZE_U size = D2D1::SizeU(
            rc.right - rc.left,
            rc.bottom - rc.top
        );
    
        // Create a Direct2D render target.
        hr = l->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(hWnd, size),
            &m_pRenderTarget
        );
    
    }
    
    void draw()
    {
    
        LoadBitmapFromFile(m_pRenderTarget, pIWICFactory, L"timg.bmp", 650, 400);
    
    
        m_pRenderTarget->BeginDraw();
    
        m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
    
        D2D1_SIZE_F size = pBitmap->GetSize();
        D2D1_POINT_2F upperLeftCorner = D2D1::Point2F(0.f, 0.f);
    
        // Draw bitmap
        m_pRenderTarget->DrawBitmap(
            pBitmap,
            D2D1::RectF(
                upperLeftCorner.x,
                upperLeftCorner.y,
                upperLeftCorner.x + size.width,
                upperLeftCorner.y + size.height)
        );
        m_pRenderTarget->EndDraw();
    
    }

    后者则是需要使用ID2D1DCRenderTarget::BindDC 将渲染目标绑定到向其发出绘图命令的设备上下文。

    需要更改的代码部分,

    //创建DC的渲染目标
    ID2D1DCRenderTarget* pow;
    ...
    
    void initize()
    {
        CoInitializeEx(NULL, COINIT_MULTITHREADED);
        CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, reinterpret_cast<void**>(&pIWICFactory));
    
        HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &l);
    
        D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
            D2D1_RENDER_TARGET_TYPE_DEFAULT,
            D2D1::PixelFormat(
                DXGI_FORMAT_B8G8R8A8_UNORM,
                D2D1_ALPHA_MODE_IGNORE),
            0,
            0,
            D2D1_RENDER_TARGET_USAGE_NONE,
            D2D1_FEATURE_LEVEL_DEFAULT
        );   
        l->CreateDCRenderTarget(&props, &pow);
    
    }
    void draw()
    {
    
        LoadBitmapFromFile(m_pRenderTarget, pIWICFactory, L"timg.bmp", 650, 400);
    
    
        pow->BeginDraw();
    
        pow->Clear(D2D1::ColorF(D2D1::ColorF::White));
    
        D2D1_SIZE_F size = pBitmap->GetSize();
        D2D1_POINT_2F upperLeftCorner = D2D1::Point2F(0.f, 0.f);
    
        // Draw bitmap
        pow->DrawBitmap(
            pBitmap,
            D2D1::RectF(
                upperLeftCorner.x,
                upperLeftCorner.y,
                upperLeftCorner.x + size.width,
                upperLeftCorner.y + size.height)
        );
        pow->EndDraw();
    
    }
    
    case WM_PAINT:
    {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            GetClientRect(hwnd, &rc);
            pow->BindDC(ps.hdc, &rc);
            draw();
            EndPaint(hwnd, &ps);
    }
    break;
    ...
  • 相关阅读:
    我的第一篇博客
    文献笔记5
    文献笔记4
    文献笔记8
    文献笔记6
    文献笔记10
    文献笔记7
    文献笔记1
    文献笔记2
    文献笔记3
  • 原文地址:https://www.cnblogs.com/strive-sun/p/14282000.html
Copyright © 2011-2022 走看看