Как отобразить с помощью контекста устройства Direct2D
Статья
В этом разделе вы узнаете о создании контекста устройства Direct2Dв Windows 8. Эта информация применяется к вам, если вы разрабатываете приложения Магазина Windows или классическое приложение с помощью Direct2D. В этом разделе описывается назначение объектов контекста устройства Direct2D, создание этого объекта и пошаговое руководство по отрисовке и отображению примитивов и изображений Direct2D. Вы также узнаете о переключении целевых объектов отрисовки и добавлении эффектов в приложение.
Для создания контекста устройства Direct2D и Direct3D требуется устройство Direct2D. Устройство Direct2D (предоставляет указатель интерфейса ID2D1Device) представляет адаптер дисплея. Устройство Direct3D (предоставляет указатель интерфейса ID3D11Device ) связано с устройством Direct2D. Каждое приложение должно иметь одно устройство Direct2D, но может иметь несколько устройств.
Что такое контекст устройства Direct2D?
Контекст устройства Direct2D (предоставляет указатель интерфейса ID2D1DeviceContext) представляет набор буферов состояния и команд, используемых для отрисовки в целевой объект. Методы в контексте устройства можно вызывать для задания состояния конвейера и создания команд отрисовки с помощью ресурсов, принадлежащих устройству.
Отрисовка с помощью Direct2D в Windows 8
В Windows 7 и более ранних версиях используется идентификатор ID2D1HwndRenderTarget или другой целевой интерфейс отрисовки для отрисовки в окне или поверхности. Начиная с Windows 8, мы не рекомендуем выполнять отрисовку с помощью методов, использующих такие интерфейсы, как ID2D1HwndRenderTarget, так как они не будут работать с приложениями Магазина Windows. Вы можете использовать контекст устройства для отрисовки в Hwnd, если вы хотите сделать классическое приложение и по-прежнему воспользоваться дополнительными функциями контекста устройства. Однако контекст устройства необходим для отрисовки содержимого в приложениях Магазина Windows с помощью Direct2D.
Зачем использовать контекст устройства для отрисовки?
Вы можете отрисовку для приложений Магазина Windows.
Целевой объект отрисовки можно изменить в любое время до, во время и после отрисовки. Контекст устройства гарантирует, что вызовы методов рисования выполняются в порядке и применяются при переключении целевого объекта отрисовки.
Можно использовать несколько контекстов устройств, которые могут быть полезны для повышения производительности в потоковом приложении. Дополнительные сведения см. в многопоточных приложениях Direct2D.
Контекст устройства тесно взаимодействует с Direct3D, предоставляя вам больше доступа к параметрам Direct3D.
Создание контекста устройства Direct2D для отрисовки
В приведенном здесь коде показано, как создать устройство Direct3D11, получить связанное устройство DXGI, создать устройство Direct2D и, наконец, создать контекст устройства Direct2D для отрисовки.
Ниже приведена схема вызовов методов и интерфейсов, которые использует этот код.
// 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
)
);
Давайте рассмотрим шаги, описанные в предыдущем примере кода.
Получите указатель интерфейса ID3D11Device, который потребуется для создания контекста устройства.
В приведенном ниже коде показано, как получить 2мерную текстуру Direct3D для буфера заднего окна и создать целевой объект растрового изображения, который связывается с этой текстурой, с которой отображается контекст устройства 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());
Давайте рассмотрим шаги, описанные в предыдущем примере кода.
Объявите структуру D2D1_BITMAP_PROPERTIES1 и задайте значения свойств. Задайте для формата пикселя BGRA, так как это формат устройства Direct3D и используемого устройства DXGI.
Получите обратный буфер в виде IDXGISurface для передачи в Direct2D. Direct2D не принимает идентификатор ID3D11Texture2D напрямую.
Теперь растровое изображение Direct2D связано с задним буфером. Задайте целевой объект в контексте устройства Direct2D растровым изображением.
Как отрисовка и отображение
Теперь, когда у вас есть целевой растровый рисунок, вы можете нарисовать в нем примитивы, изображения, эффекты изображения и текст в нем с помощью контекста устройства Direct2D. В этом коде показано, как нарисовать прямоугольник.
Используйте Azure Удаленная отрисовка для отрисовки трехмерной модели в проекте Unity. Модель можно развернуть в HoloLens 2 или использовать возможности смешанной реальности с помощью MRTK.