Jak renderować przy użyciu kontekstu urządzenia Direct2D
W tym temacie dowiesz się, jak tworzyć Direct2Dkontekst urządzenia w systemie Windows 8. Te informacje dotyczą Użytkownika, jeśli tworzysz aplikacje ze Sklepu Windows lub aplikację klasyczną przy użyciu funkcji Direct2D. W tym temacie opisano przeznaczenie obiektów kontekstu urządzenia Direct2D, sposób tworzenia tego obiektu oraz przewodnik krok po kroku dotyczący renderowania i wyświetlania elementów pierwotnych i obrazów Direct2D. Dowiesz się również o przełączaniu elementów docelowych renderowania i dodawaniu efektów do aplikacji.
- Co to jest urządzenie Direct2D?
- Co to jest kontekst urządzenia Direct2D?
- renderowanie z funkcją Direct2D w systemie Windows 8
- Dlaczego używać kontekstu urządzenia do renderowania?
- Jak utworzyć kontekst urządzenia Direct2D na potrzeby renderowania
- Wybieranie celu
- Jak renderować i wyświetlać
Co to jest urządzenie Direct2D?
Potrzebujesz urządzenia Direct2D i urządzenia Direct3D do utworzenia kontekstu urządzenia Direct2D. Urządzenie Direct2D (ujawnia wskaźnik interfejsu ID2D1Device) reprezentuje adapter wyświetlacza. Urządzenie Direct3D (udostępnia wskaźnik interfejsu ID3D11Device) jest skojarzone z urządzeniem Direct2D. Każda aplikacja musi mieć jedno urządzenie Direct2D, ale może mieć więcej niż jedno urządzenie .
Co to jest kontekst urządzenia Direct2D?
Kontekst urządzenia Direct2D (udostępnia wskaźnik interfejsu ID2D1DeviceContext ) reprezentuje zestaw stanów i poleceń buforów, które są używane do renderowania na obiekt docelowy. W kontekście urządzenia można wywołać metody, aby ustawić stan potoku i wygenerować polecenia renderowania przy użyciu zasobów, należących do urządzenia.
Renderowanie za pomocą funkcji Direct2D w systemie Windows 8
W systemie Windows 7 i starszych użyjesz ID2D1HwndRenderTarget lub innego interfejsu renderowania docelowego do renderowania na oknie lub powierzchni. Począwszy od systemu Windows 8, nie zalecamy renderowania przy użyciu metod opartych na interfejsach, takich jak ID2D1HwndRenderTarget, ponieważ nie będą działać z aplikacjami ze Sklepu Windows. Możesz użyć kontekstu urządzenia do renderowania na Hwnd, jeśli chcesz utworzyć aplikację desktopową i nadal korzystać z dodatkowych funkcji kontekstu urządzenia . Jednak kontekst urządzenia jest wymagany do renderowania zawartości w aplikacjach ze Sklepu Windows za pomocą Direct2D.
Dlaczego warto użyć kontekstu urządzenia do renderowania?
- Możesz renderować aplikacje ze Sklepu Windows.
- Element docelowy renderowania można zmienić w dowolnym momencie przed renderowaniem, w trakcie i po renderowaniu. Kontekst urządzenia zapewnia, że wywołania metod rysowania są wykonywane w kolejności i są stosowane podczas przełączania obiektu docelowego renderowania.
- Można użyć więcej niż jednego typu okna z kontekstem urządzenia. Możesz użyć kontekstu urządzenia i łańcucha wymiany DXGI do renderowania bezpośrednio do Windows::UI::Core::CoreWindow lub Windows::UI::XAML::SwapChainBackgroundPanel.
- Możesz użyć kontekstu urządzeniaDirect2D, aby utworzyć efekty Direct2D i renderować wynik efektu obrazu lub wykresu efektu do celu renderowania.
- Można mieć wiele kontekstów urządzenia, co może być przydatne w celu poprawy wydajności w aplikacji wielowątkowej. Aby uzyskać więcej informacji, zobacz Wielowątkowane aplikacje Direct2D.
- Kontekst urządzenia ściśle współdziała z usługą Direct3D, co zapewnia większy dostęp do opcji Direct3D.
Jak utworzyć kontekst urządzenia Direct2D na potrzeby renderowania
W tym miejscu pokazano, jak utworzyć urządzenie Direct3D11, pobrać skojarzone urządzenie DXGI, utworzyć urządzenie Direct2D, a następnie utworzyć kontekst urządzenia Direct2D na potrzeby renderowania.
Oto diagram wywołań metod i interfejsów używanych przez ten kod.
Notatka
Ten kod zakłada, że masz już obiekt ID2D1Factory1, aby uzyskać więcej informacji, zobacz stronę referencyjną 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
)
);
Przyjrzyjmy się krokom z poprzedniego przykładu kodu.
Pobierz wskaźnik interfejsu ID3D11Device, który będzie potrzebny do utworzenia kontekstu urządzenia.
Zadeklaruj flagi tworzenia, aby skonfigurować urządzenie Direct3D do obsługi BGRA. Direct2D wymaga kolejności kolorów BGRA.
Zadeklaruj tablicę wpisów D3D_FEATURE_LEVEL reprezentujących zestaw poziomów funkcji obsługiwanych przez aplikację.
Notatka
direct3D przeszukuje listę do momentu znalezienia poziomu funkcji obsługiwanego przez system hosta.
Użyj funkcji D3D11CreateDevice, aby utworzyć obiekt ID3D11Device, funkcja zwróci również obiekt ID3D11DeviceContext, ale ten obiekt nie jest wymagany w tym przykładzie.
Wykonaj zapytanie o urządzenie Direct3D 11 w celu uzyskania interfejsu urządzenia DXGI.
Utwórz obiekt ID2D1Device, wywołując metodę ID2D1Factory::CreateDevice i przekazując obiekt IDXGIDevice.
Utwórz wskaźnik ID2D1DeviceContext, używając metody ID2D1Device::CreateDeviceContext.
Wybieranie miejsca docelowego
W tym kodzie pokazano, jak uzyskać 2-wymiarową teksturę Direct3D dla bufora tylnego okna i utworzyć obiekt docelowy mapy bitowej, który łączy się z tą teksturą, do której renderuje kontekst urządzenia 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());
Omówimy kroki opisane w poprzednim przykładzie kodu.
Przydziel strukturę DXGI_SWAP_CHAIN_DESC1 i zdefiniuj ustawienia łańcucha wymiany .
Te ustawienia pokazują przykład tworzenia łańcucha wymiany, z którego może korzystać aplikacja ze Sklepu Windows.
Pobierz adapter, na którym działa urządzenie Direct3D i urządzenie DXGI , oraz uzyskaj obiekt IDXGIFactory z nimi skojarzony. Należy użyć tego DXGI fabryki, aby upewnić się, że łańcuch wymiany jest tworzony na tym samym adapterze.
Wywołaj metodę IDXGIFactory2::CreateSwapChainForCoreWindow, aby utworzyć łańcuch wymiany. Użyj klasy Windows::UI::CoreWindow dla głównego okna aplikacji ze Sklepu Windows.
Pamiętaj, aby ustawić maksymalne opóźnienie ramki na 1, aby zminimalizować zużycie energii.
Jeśli chcesz renderować zawartość Direct2D w aplikacji ze Sklepu Windows, zobacz metodę CreateSwapChainForComposition.
Pobierz bufor wsteczny z łańcucha wymiany . Bufor wsteczny udostępnia interfejs ID3D11Texture2D przydzielony przez łańcuch wymiany
Zadeklaruj strukturę D2D1_BITMAP_PROPERTIES1 i ustaw wartości właściwości. Ustaw format pikseli na BGRA, ponieważ jest to format używany przez urządzenia Direct3D oraz DXGI.
Pobierz bufor wsteczny jako IDXGISurface, aby przekazać go do Direct2D. Direct2D nie akceptuje bezpośrednio ID3D11Texture2D.
Utwórz obiekt ID2D1Bitmap z buforu wstecznego, korzystając z metody ID2D1DeviceContext::CreateBitmapFromDxgiSurface.
Teraz bitmapa Direct2D jest połączona z buforem wstecznym. Ustaw element docelowy w kontekście urządzenia Direct2D na mapę bitową .
Jak renderować i wyświetlać
Teraz, gdy masz docelową mapę bitową, możesz narysować elementy pierwotne, obrazy, efekty obrazu i tekst przy użyciu kontekstu urządzenia Direct2D. W tym miejscu pokazano, jak narysować prostokąt.
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, ¶meters);
);
Omówimy kroki opisane w poprzednim przykładzie kodu.
- Wywołaj CreateSolidColorBrush, aby utworzyć pędzl do malowania prostokąta.
- Przed wystawieniem jakichkolwiek poleceń rysunku wywołaj metodę BeginDraw.
- Wywołaj metodę DrawRectangle z prostokątem, który ma zostać narysowany, oraz pędzlem.
- Wywołaj metodę EndDraw po zakończeniu wydawania poleceń rysunkowych.
- Wyświetl wynik, wywołując metodę IDXGISwapChain::Present.
Teraz możesz użyć kontekstu urządzenia Direct2D, rysowania elementów pierwotnych, obrazów, efektów obrazu i tekstu na ekranie.