Cara merender dengan menggunakan konteks perangkat Direct2D

Dalam topik ini Anda akan belajar tentang membuat konteks perangkatDirect2D dalam Windows 8. Informasi ini berlaku untuk Anda jika Anda mengembangkan aplikasi Bursa Windows atau aplikasi desktop dengan menggunakan Direct2D. Topik ini menjelaskan tujuan objek konteks perangkat Direct2D, cara membuat objek tersebut, dan panduan langkah demi langkah tentang merender dan menampilkan primitif dan gambar Direct2D. Anda juga akan mempelajari tentang beralih target render dan menambahkan efek ke aplikasi Anda.

Apa itu perangkat Direct2D?

Anda memerlukan perangkat Direct2D dan perangkat Direct3D untuk membuat konteks perangkat Direct2D. Perangkat Direct2D (mengekspos penunjuk antarmuka ID2D1Device ) mewakili adaptor tampilan. Perangkat Direct3D (mengekspos pointer antarmuka ID3D11Device ) dikaitkan dengan perangkat Direct2D. Setiap aplikasi harus memiliki satu perangkat Direct2D, tetapi dapat memiliki lebih dari satu perangkat.

Apa itu konteks perangkat Direct2D?

Konteks perangkatDirect2D (mengekspos penunjuk antarmuka ID2D1DeviceContext) mewakili serangkaian status dan buffer perintah yang Anda gunakan untuk merender ke target. Anda dapat memanggil metode pada konteks perangkat untuk mengatur status alur dan menghasilkan perintah penyajian dengan menggunakan sumber daya yang dimiliki oleh perangkat.

Penyajian dengan Direct2D di Windows 8

Pada Windows 7 dan yang lebih lama, Anda menggunakan ID2D1HwndRenderTarget atau antarmuka target render lain untuk dirender ke jendela atau permukaan. Dimulai dengan Windows 8, kami tidak menyarankan penyajian dengan menggunakan metode yang mengandalkan antarmuka seperti ID2D1HwndRenderTarget karena tidak akan berfungsi dengan aplikasi Windows Store. Anda dapat menggunakan konteks perangkat untuk merender ke Hwnd jika Anda ingin membuat aplikasi desktop dan masih memanfaatkan fitur tambahan konteks perangkat . Namun, konteks perangkat diperlukan untuk merender konten di aplikasi Windows Store dengan Direct2D.

Mengapa menggunakan konteks perangkat untuk dirender?

Cara membuat konteks perangkat Direct2D untuk penyajian

Kode di sini menunjukkan kepada Anda cara membuat perangkat Direct3D11, mendapatkan perangkat DXGI terkait, membuat perangkat Direct2D, lalu akhirnya membuat konteks perangkat Direct2D untuk penyajian.

Berikut adalah diagram panggilan metode dan antarmuka yang digunakan kode ini.

diagram perangkat direct2d dan direct3d dan konteks perangkat.

Catatan

Kode ini mengasumsikan Anda sudah memiliki objek ID2D1Factory1 , untuk informasi selengkapnya lihat halaman referensi ID2D1Factory.

 

    // This flag adds support for surfaces with a different color channel ordering than the API default.
    // You need it for compatibility with Direct2D.
    UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
    
    // This array defines the set of DirectX hardware feature levels this app  supports.
    // The ordering is important and you should  preserve it.
    // Don't forget to declare your app's minimum required feature level in its
    // description.  All apps are assumed to support 9.1 unless otherwise stated.
    D3D_FEATURE_LEVEL featureLevels[] = 
    {
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3,
        D3D_FEATURE_LEVEL_9_2,
        D3D_FEATURE_LEVEL_9_1
    };

    // Create the DX11 API device object, and get a corresponding context.
    ComPtr<ID3D11Device> device;
    ComPtr<ID3D11DeviceContext> context;

    DX::ThrowIfFailed(
        D3D11CreateDevice(
            nullptr,                    // specify null to use the default adapter
            D3D_DRIVER_TYPE_HARDWARE,
            0,                          
            creationFlags,              // optionally set debug and Direct2D compatibility flags
            featureLevels,              // list of feature levels this app can support
            ARRAYSIZE(featureLevels),   // number of possible feature levels
            D3D11_SDK_VERSION,          
            &device,                    // returns the Direct3D device created
            &m_featureLevel,            // returns feature level of device created
            &context                    // returns the device immediate context
            )
        );

    ComPtr<IDXGIDevice> dxgiDevice;
    // Obtain the underlying DXGI device of the Direct3D11 device.
    DX::ThrowIfFailed(
        device.As(&dxgiDevice)
        );

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

    // Get Direct2D device's corresponding device context object.
    DX::ThrowIfFailed(
        m_d2dDevice->CreateDeviceContext(
            D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
            &m_d2dContext
            )
        );

Mari kita telusuri langkah-langkah dalam sampel kode sebelumnya.

  1. Dapatkan penunjuk antarmuka ID3D11Device, Anda akan memerlukan ini untuk membuat konteks perangkat.

    • Nyatakan bendera pembuatan untuk menyiapkan perangkat Direct3D untuk dukungan BGRA. Direct2D memerlukan urutan warna BGRA.

    • Deklarasikan array entri D3D_FEATURE_LEVEL yang mewakili serangkaian tingkat fitur yang akan didukung aplikasi Anda.

      Catatan

      Direct3D mencari daftar Anda sampai menemukan tingkat fitur yang didukung oleh sistem host.

       

    • Gunakan fungsi D3D11CreateDevice untuk membuat objek ID3D11Device , fungsi juga akan mengembalikan objek ID3D11DeviceContext , tetapi objek tersebut tidak diperlukan untuk contoh ini.

  2. Kueri perangkat Direct3D 11 untuk antarmuka Perangkat DXGI-nya .

  3. Buat objek ID2D1Device dengan memanggil metode ID2D1Factory::CreateDevice dan meneruskan objek IDXGIDevice .

  4. Buat penunjuk ID2D1DeviceContext menggunakan metode ID2D1Device::CreateDeviceContext .

Memilih target

Kode di sini menunjukkan kepada Anda cara mendapatkan tekstur Direct3D 2 dimensi untuk buffer belakang jendela dan membuat target bitmap yang ditautkan ke tekstur ini yang dirender konteks perangkat Direct2D .

        // Allocate a descriptor.
        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
        swapChainDesc.Width = 0;                           // use automatic sizing
        swapChainDesc.Height = 0;
        swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
        swapChainDesc.Stereo = false; 
        swapChainDesc.SampleDesc.Count = 1;                // don't use multi-sampling
        swapChainDesc.SampleDesc.Quality = 0;
        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        swapChainDesc.BufferCount = 2;                     // use double buffering to enable flip
        swapChainDesc.Scaling = DXGI_SCALING_NONE;
        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all apps must use this SwapEffect
        swapChainDesc.Flags = 0;

        // Identify the physical adapter (GPU or card) this device is runs on.
        ComPtr<IDXGIAdapter> dxgiAdapter;
        DX::ThrowIfFailed(
            dxgiDevice->GetAdapter(&dxgiAdapter)
            );

        // Get the factory object that created the DXGI device.
        ComPtr<IDXGIFactory2> dxgiFactory;
        DX::ThrowIfFailed(
            dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
            );

        // Get the final swap chain for this window from the DXGI factory.
        DX::ThrowIfFailed(
            dxgiFactory->CreateSwapChainForCoreWindow(
                device.Get(),
                reinterpret_cast<IUnknown*>(m_window),
                &swapChainDesc,
                nullptr,    // allow on all displays
                &m_swapChain
                )
            );

        // Ensure that DXGI doesn't queue more than one frame at a time.
        DX::ThrowIfFailed(
            dxgiDevice->SetMaximumFrameLatency(1)
            );

    // Get the backbuffer for this window which is be the final 3D render target.
    ComPtr<ID3D11Texture2D> backBuffer;
    DX::ThrowIfFailed(
        m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
        );

    // Now we set up the Direct2D render target bitmap linked to the swapchain. 
    // Whenever we render to this bitmap, it is directly rendered to the 
    // swap chain 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_IGNORE),
            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
            )
        );

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

Mari kita telusuri langkah-langkah dalam contoh kode sebelumnya.

  1. Alokasikan struktur DXGI_SWAP_CHAIN_DESC1 dan tentukan pengaturan untuk rantai pertukaran.

    Pengaturan ini menunjukkan contoh cara membuat rantai pertukaran yang dapat digunakan aplikasi Windows Store.

  2. Dapatkan adaptor yang dijalankan perangkat Direct3D dan Perangkat DXGI dan dapatkan objek IDXGIFactory yang terkait dengannya. Anda harus menggunakan pabrik DXGI ini untuk memastikan rantai pertukaran dibuat pada adaptor yang sama.

  3. Panggil metode IDXGIFactory2::CreateSwapChainForCoreWindow untuk membuat rantai pertukaran. Gunakan kelas Windows::UI::CoreWindow untuk jendela utama aplikasi Windows Store.

    Pastikan untuk mengatur latensi bingkai maksimum ke 1 untuk meminimalkan konsumsi daya.

    Jika Anda ingin merender konten Direct2D di aplikasi Windows Store, lihat metode CreateSwapChainForComposition .

  4. Dapatkan buffer belakang dari rantai pertukaran. Buffer belakang mengekspos antarmuka ID3D11Texture2D yang dialokasikan oleh rantai pertukaran

  5. Deklarasikan struct D2D1_BITMAP_PROPERTIES1 dan atur nilai properti. Atur format piksel ke BGRA karena ini adalah format perangkat Direct3D dan penggunaan Perangkat DXGI .

  6. Dapatkan buffer belakang sebagai IDXGISurface untuk diteruskan ke Direct2D. Direct2D tidak menerima ID3D11Texture2D secara langsung.

    Buat objek ID2D1Bitmap dari buffer belakang menggunakan metode ID2D1DeviceContext::CreateBitmapFromDxgiSurface .

  7. Sekarang bitmap Direct2D ditautkan ke buffer belakang. Atur target pada konteks perangkat Direct2D ke bitmap.

Cara merender dan menampilkan

Sekarang setelah Anda memiliki bitmap target, Anda dapat menggambar primitif, gambar, efek gambar, dan teks ke dalamnya menggunakan konteks perangkat Direct2D. Kode di sini menunjukkan kepada Anda cara menggambar persegi panjang.

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

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);
);

Mari kita telusuri langkah-langkah dalam contoh kode sebelumnya.

  1. Panggil CreateSolidColorBrush untuk membuat kuas untuk melukis persegi panjang.
  2. Panggil metode BeginDraw sebelum mengeluarkan perintah gambar apa pun.
  3. Panggil metode DrawRectangle persegi panjang yang akan digambar dan kuas.
  4. Panggil metode EndDraw setelah Anda selesai mengeluarkan perintah gambar.
  5. Tampilkan hasilnya dengan memanggil metode IDXGISwapChain::P resent .

Sekarang Anda dapat menggunakan konteks perangkat Direct2D menggambar primitif, gambar, efek gambar, dan teks ke layar.