Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Här visar vi hur du skapar en Direct3D-enhet, en växlingskedja och en återgivningsmålvy och hur du visar den renderade bilden på skärmen.
Mål: Konfigurera DirectX-resurser i en C++ UWP-app (Universal Windows Platform) och visa en solid färg.
Förutsättningar
Vi antar att du är bekant med C++. Du behöver också grundläggande erfarenhet av grafikprogrammeringsbegrepp.
Tid att slutföra: 20 minuter.
Instruktion
1. Deklarera Direct3D-gränssnittsvariabler med ComPtr
Vi deklarerar Direct3D-gränssnittsvariabler med ComPtr-smart pekare mall från Mallbiblioteket för Windows Runtime C++ (WRL), så att vi kan hantera livslängden för dessa variabler på ett undantagssäkert sätt. Vi kan sedan använda dessa variabler för att komma åt ComPtr-klassen och dess medlemmar. Till exempel:
ComPtr<ID3D11RenderTargetView> m_renderTargetView;
m_d3dDeviceContext->OMSetRenderTargets(
1,
m_renderTargetView.GetAddressOf(),
nullptr // Use no depth stencil.
);
Om du deklarerar ID3D11RenderTargetView med ComPtr kan du sedan använda ComPtr-metoden GetAddressOf för att få adressen till pekaren till ID3D11RenderTargetView (**ID3D11RenderTargetView) för att skicka till ID3D11DeviceContext::OMSetRenderTargets. OMSetRenderTargets binder återgivningsmålet till utdatasammanslagningssteg för att ange återgivningsmålet som utdatamål.
När exempelappen har startats, initieras den och laddas, och är sedan redo att köras.
2. Skapa Direct3D-enheten
Om du vill använda Direct3D-API:et för att återge en scen måste vi först skapa en Direct3D-enhet som representerar bildskärmskortet. För att skapa Direct3D-enheten anropar vi funktionen D3D11CreateDevice. Vi anger nivåerna 9.1 till 11.1 i matrisen med D3D_FEATURE_LEVEL värden. Direct3D går igenom matrisen i ordning och returnerar den högsta stödda funktionsnivån. För att få den högsta tillgängliga funktionsnivån listar vi därför de D3D_FEATURE_LEVEL matrisposterna från högsta till lägsta. Vi skickar flaggan D3D11_CREATE_DEVICE_BGRA_SUPPORT till parametern Flags så att Direct3D-resurser samverkar med Direct2D. Om vi använder felsökningsversionen skickar vi även flaggan D3D11_CREATE_DEVICE_DEBUG. Mer information om felsökning av appar finns i Använda felsökningsskiktet för att felsöka appar.
Vi erhåller Direct3D 11.1-enheten (ID3D11Device1) och enhetskontexten (ID3D11DeviceContext1) genom att anropa Direct3D 11-enhets- och enhetskontexten som returneras från D3D11CreateDevice.
// First, create the Direct3D device.
// This flag is required in order to enable compatibility with Direct2D.
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if defined(_DEBUG)
// If the project is in a debug build, enable debugging via SDK Layers with this flag.
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
// This array defines the ordering of feature levels that D3D should attempt to create.
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_1
};
ComPtr<ID3D11Device> d3dDevice;
ComPtr<ID3D11DeviceContext> d3dDeviceContext;
DX::ThrowIfFailed(
D3D11CreateDevice(
nullptr, // Specify nullptr to use the default adapter.
D3D_DRIVER_TYPE_HARDWARE,
nullptr, // leave as nullptr if hardware is used
creationFlags, // optionally set debug and Direct2D compatibility flags
featureLevels,
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION, // always set this to D3D11_SDK_VERSION
&d3dDevice,
nullptr,
&d3dDeviceContext
)
);
// Retrieve the Direct3D 11.1 interfaces.
DX::ThrowIfFailed(
d3dDevice.As(&m_d3dDevice)
);
DX::ThrowIfFailed(
d3dDeviceContext.As(&m_d3dDeviceContext)
);
3. Skapa växlingskedjan
Därefter skapar vi en växlingskedja som enheten använder för återgivning och visning. Vi deklarerar och initierar en DXGI_SWAP_CHAIN_DESC1 struktur för att beskriva växlingskedjan. Sedan konfigurerar vi växlingskedjan som flip-model (dvs. en växlingskedja som har värdet DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL inställt i SwapEffect- medlem) och ställer in Format medlem till DXGI_FORMAT_B8G8R8A8_UNORM. Vi anger Count medlem i den DXGI_SAMPLE_DESC struktur som SampleDesc- medlem anger till 1 och Quality medlem i DXGI_SAMPLE_DESC till noll eftersom flip-model inte stöder flera exempel på antialiasering (MSAA). Vi ställer in BufferCount medlemsvariabel till 2 så att växlingskedjan kan använda en framåtbuffert för att presentera för skärmen och en bakbuffert som fungerar som återgivningsmål.
Vi hämtar den underliggande DXGI-enheten genom att anropa Direct3D 11.1-device. För att minimera strömförbrukningen, vilket är viktigt att göra på batteridrivna enheter som bärbara datorer och surfplattor, anropar vi IDXGIDevice1::SetMaximumFrameLatency metod med 1 som det maximala antalet buffertramar som DXGI kan köa. Detta säkerställer att appen renderas endast efter det lodräta tomma objektet.
För att slutligen skapa växlingskedjan måste vi hämta den överordnade fabriken från DXGI-enheten. Vi anropar IDXGIDevice::GetAdapter för att hämta adaptern för enheten och anropar sedan IDXGIObject::GetParent på adaptern för att hämta den överordnade fabriken (IDXGIFactory2). För att skapa växlingskedjan anropar vi IDXGIFactory2::CreateSwapChainForCoreWindow med växlingskedjans beskrivning och appens kärnfönster.
// If the swap chain does not exist, create it.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Stereo = false;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.Scaling = DXGI_SCALING_NONE;
swapChainDesc.Flags = 0;
// Use automatic sizing.
swapChainDesc.Width = 0;
swapChainDesc.Height = 0;
// This is the most common swap chain format.
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
// Don't use multi-sampling.
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
// Use two buffers to enable the flip effect.
swapChainDesc.BufferCount = 2;
// We recommend using this swap effect for all applications.
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
// Once the swap chain description is configured, it must be
// created on the same adapter as the existing D3D Device.
// First, retrieve the underlying DXGI Device from the D3D Device.
ComPtr<IDXGIDevice2> dxgiDevice;
DX::ThrowIfFailed(
m_d3dDevice.As(&dxgiDevice)
);
// Ensure that DXGI does not queue more than one frame at a time. This both reduces
// latency and ensures that the application will only render after each VSync, minimizing
// power consumption.
DX::ThrowIfFailed(
dxgiDevice->SetMaximumFrameLatency(1)
);
// Next, get the parent factory from the DXGI Device.
ComPtr<IDXGIAdapter> dxgiAdapter;
DX::ThrowIfFailed(
dxgiDevice->GetAdapter(&dxgiAdapter)
);
ComPtr<IDXGIFactory2> dxgiFactory;
DX::ThrowIfFailed(
dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
);
// Finally, create the swap chain.
CoreWindow^ window = m_window.Get();
DX::ThrowIfFailed(
dxgiFactory->CreateSwapChainForCoreWindow(
m_d3dDevice.Get(),
reinterpret_cast<IUnknown*>(window),
&swapChainDesc,
nullptr, // Allow on all displays.
&m_swapChain
)
);
4. Skapa rendermålsvyn
För att återge grafik till fönstret måste vi skapa en återgivningsmålvy. Vi anropar IDXGISwapChain::GetBuffer för att hämta växlingskedjans backbuffert som ska användas när vi skapar återgivningsmålvyn. Vi anger bakbufferten som en 2D-textur (ID3D11Texture2D). För att skapa rendermålvyn anropar vi ID3D11Device::CreateRenderTargetView med växlingskedjans back-buffer. Vi måste specificera att rita till hela huvudfönstret genom att ange vyporten (D3D11_VIEWPORT) som hela storleken på swap-kedjans backbuffer. Vi använder visningsporten i ett anrop till ID3D11DeviceContext::RSSetViewports för att binda visningsporten till rastreringssteget av pipelinen. Rastreringssteget konverterar vektorinformation till en rasterbild. I det här fallet kräver vi ingen konvertering eftersom vi bara visar en helfärg.
// Once the swap chain is created, create a render target view. This will
// allow Direct3D to render graphics to the window.
ComPtr<ID3D11Texture2D> backBuffer;
DX::ThrowIfFailed(
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))
);
DX::ThrowIfFailed(
m_d3dDevice->CreateRenderTargetView(
backBuffer.Get(),
nullptr,
&m_renderTargetView
)
);
// After the render target view is created, specify that the viewport,
// which describes what portion of the window to draw to, should cover
// the entire window.
D3D11_TEXTURE2D_DESC backBufferDesc = {0};
backBuffer->GetDesc(&backBufferDesc);
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
viewport.Width = static_cast<float>(backBufferDesc.Width);
viewport.Height = static_cast<float>(backBufferDesc.Height);
viewport.MinDepth = D3D11_MIN_DEPTH;
viewport.MaxDepth = D3D11_MAX_DEPTH;
m_d3dDeviceContext->RSSetViewports(1, &viewport);
5. Att presentera den renderade bilden
Vi går in i en oändlig loop för att kontinuerligt återge och visa scenen.
I den här loopen anropar vi:
- ID3D11DeviceContext::OMSetRenderTargets för att ange återgivningsmålet som utdatamål.
- ID3D11DeviceContext::ClearRenderTargetView för att rensa återgivningsmålet till en solid färg.
- IDXGISwapChain::Present för att presentera den renderade bilden till fönstret.
Eftersom vi tidigare har angett den maximala bildrutefördröjningen till 1, saktar Windows vanligtvis ned återgivningsloopen till skärmuppdateringshastigheten, vanligtvis runt 60 Hz. Windows saktar ned återgivningsloopen genom att sätta appen i viloläge när appen anropar Present. Windows gör att appen förs viloläge tills skärmen uppdateras.
// Enter the render loop. Note that UWP apps should never exit.
while (true)
{
// Process events incoming to the window.
m_window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
// Specify the render target we created as the output target.
m_d3dDeviceContext->OMSetRenderTargets(
1,
m_renderTargetView.GetAddressOf(),
nullptr // Use no depth stencil.
);
// Clear the render target to a solid color.
const float clearColor[4] = { 0.071f, 0.04f, 0.561f, 1.0f };
m_d3dDeviceContext->ClearRenderTargetView(
m_renderTargetView.Get(),
clearColor
);
// Present the rendered image to the window. Because the maximum frame latency is set to 1,
// the render loop will generally be throttled to the screen refresh rate, typically around
// 60 Hz, by sleeping the application on Present until the screen is refreshed.
DX::ThrowIfFailed(
m_swapChain->Present(1, 0)
);
}
6. Ändra storlek på appfönstret och växlingskedjans buffert
Om storleken på appfönstret ändras måste appen ändra storlek på buffertarna i växlingskedjan, återskapa renderingsmålvyn och sedan presentera den omgjorda återgivna bilden. För att ändra storlek på växlingskedjans buffertar anropar vi IDXGISwapChain::ResizeBuffers. I det här anropet lämnar vi antalet buffertar och formatet för buffertarna oförändrade (parametern BufferCount till två och parametern NewFormat till DXGI_FORMAT_B8G8R8A8_UNORM). Vi gör storleken på växlingskedjans bakåtbuffert till samma storlek som det storleksanpassade fönstret. När vi har storleksanpassat växlingskedjans buffertar skapar vi det nya återgivningsmålet och presenterar den nya renderade avbildningen på samma sätt som när vi initierade appen.
// If the swap chain already exists, resize it.
DX::ThrowIfFailed(
m_swapChain->ResizeBuffers(
2,
0,
0,
DXGI_FORMAT_B8G8R8A8_UNORM,
0
)
);
Sammanfattning och nästa steg
Vi skapade en Direct3D-enhet, en växlingskedja och en återgivningsmålvy, och presenterade den renderade bilden på skärmen.
Därefter ritar vi också en triangel på skärmen.
Skapa skuggningar och rita primitiver