notJustCode.it
 
\\ Home : Articoli
Device e Context
Di robydx (del 26/01/2010 @ 20:41:39, in Direct3D11, linkato 2458 volte)

Il Device ed il DeviceContext sono gli oggetti principali di Direct3D11. Fino alla versione 10 erano un unico oggetto mentre ora sono stati suddivisi per competenze, il primo è dedicato alla creazione delle risorse, il secondo al loro utilizzo. Un’applicazione Direct3D inizia quando questi 2 oggetti sono creati e termina quando vengono distrutti.

Il device è legato ad un controllo dotato di Handle, un codice univoco con cui Windows identifica un controllo come ad esempio una finestra; per tanto è necessario creare un Form ed inizializzare a partire da esso il nostro Device. Oltre al Device è fondamentale un secondo oggetto: lo Swap Chain. Come spiegato nei precedenti articoli Direct3D prende dati in ingresso e genera ogni istante un’immagine da copiare su una superficie. Questa superficie deve essere inviata al monitor e questo legame è fatto tramite lo SwapChain. Questo può essere di 2 tipi: Windowed o FullScreen. Il primo racchiude l’intera visualizzazione all’interno della finestra lasciando il resto del desktop perfettamente visibile, l’altra invece prevede che l’intero schermo sia utilizzato come zona di visualizzazione nascondendo tutto ciò che c’è sotto. Dal punto di vista della creazione non cambia molto ma bisogna stare attenti a gestire gli eventi dell’utente. Ad esempio in modalità Windowed l’utente può ridimensionare a piacimento la finestra mentre in quella FullScreen potrebbe ridurre l’applicazione ad icona e poi riaprirla. Per evitare crash bisogna imparare a gestire le due situazioni. L’istruzione D3DCreateDeviceAndSwapChain crea in un sol colpo tutti e 3 gli oggetti. Questa può essere eseguita appena dopo la creazione della finestra.

Come parametri prende alcune impostazioni ed una struttura, la DXGI_SWAP_CHAIN_DESC che descrive come creare lo SwapChain

DXGI_SWAP_CHAIN_DESC sd;

ZeroMemory( &sd, sizeof( sd ) );

sd.BufferCount = 1;

sd.BufferDesc.Width = 1024;

sd.BufferDesc.Height = 768;

sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

sd.BufferDesc.RefreshRate.Numerator = 60;

sd.BufferDesc.RefreshRate.Denominator = 1;

sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

sd.OutputWindow = handle;

sd.SampleDesc.Count = 1;

sd.SampleDesc.Quality = 0;

sd.Windowed = TRUE;

D3D_FEATURE_LEVEL FeatureLevelsRequested[3]= {D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0};

D3D_FEATURE_LEVEL FeatureLevelsSupported[6];

IDXGISwapChain* swapChain;

ID3D11Device* device;

ID3D11DeviceContext* context;

HRESULT hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, FeatureLevelsRequested, 3, D3D11_SDK_VERSION, &sd, & swapChain, & device, FeatureLevelsSupported, & context)));

Con lo DXGI_SWAP_DESC si specificano i parametri di creazione come la risoluzione (1024 x 768), se in modalità finestra (Windowed =true) e diversi altri parametri che sono spiegati in dettaglio nella SDK e che saranno oggetti di futuri tutorial. In modalità windowed la risoluzione deve essere parti a quella della finestra (o meglio la client area che non include la barra della finestra). In modalità FullScreen dovrete utilizzare per forza una delle modalità supportate dalla scheda. Il primo parametro permette di passare l’adapter che si vuole usare (NULL indica quello di default) mentre il secondo indica la modalità (solitamente HARDWARE ma si possono utilizzare la modalità REFERENCE che permette a qualsiasi scheda video di supportate tutto ma a velocità nell’ordine di un centesimo). I 3 oggetti sono ora creati ma non è ancora sufficiente. Tornando alla Pipeline di Direct3D il rendering viene fatto su superfici da riversare sullo swap chain. Queste superfici sono i render target. Per creare un render target è sufficiente

ID3D11RenderTargetView* renderTargetView;

ID3D11Texture2D *pBackBuffer;

swapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pBackBuffer ) ) );

device->CreateRenderTargetView( pBackBuffer, NULL, &renderTargetView );

pBackBuffer->Release();

Dallo SwapChain si prende la superficie e la si converte in una Texture (una superficie 2D di Direct3D) e da questa si crea un oggetto ID3D11RenderTargetView. La texture si può a questo punto anche rilasciare. Il metodo GetBuffer e CreateRenderTargetView restituiscono HRESULT che non mostrerò per brevità ma che devono essere gestiti.

A supporto del Render Target va creato un secondo oggetto chiamato DepthStencil, responsabile della gestione della profondità. Questa superficie gestisce la profondità nella scena ed è necessario per scene 3D in cui un oggetto può apparire dietro ad un altro (ossia nel 99% dei casi).

D3D11_TEXTURE2D_DESC descDepth;

descDepth.Width = 1024;

descDepth.Height = 768;

descDepth.MipLevels = 1;

descDepth.ArraySize = 1;

descDepth.Format = DXGI_FORMAT_D32_FLOAT;

descDepth.SampleDesc.Count = 1;

descDepth.SampleDesc.Quality = 0;

descDepth.Usage = D3D11_USAGE_DEFAULT;

descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;

descDepth.CPUAccessFlags = 0;

descDepth.MiscFlags = 0;

ID3D11Texture2D *pDepthBuffer;

device->CreateTexture2D( &descDepth, NULL, &pDepthBuffer );

D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;

descDSV.Flags=0;

descDSV.Format = DXGI_FORMAT_D32_FLOAT;

descDSV.ViewDimension= D3D11_DSV_DIMENSION_TEXTURE2D;

descDSV.Texture2D.MipSlice=0;

ID3D11DepthStencilView* renderTargetDepth;

device->CreateDepthStencilView( pDepthBuffer, &descDSV, &renderTargetDepth );

pDepthBuffer->Release();

Creato il DepthStencilView ed il RenderTargetView questi possono essere associati al DeviceContext descrivendo tramite l’oggetto viewport la dimensione degli stessi. Il numero 1 indica quanti render target utilizzare. Infatti è possibile utilizzare più render target contemporaneamente ma in questo tutorial tratteremo l'utilizzo di default.

context->OMSetRenderTargets( 1, &renderTargetView, renderTargetDepth);

D3D11_VIEWPORT vp;

vp.Width = 1024;

vp.Height = 768;

vp.MinDepth = 0.0f;

vp.MaxDepth = 1.0f;

vp.TopLeftX = 0;

vp.TopLeftY = 0;

context->RSSetViewports( 1, &vp );

Ora finalmente la nostra applicazione può essere utilizzata. Ogni rendering prevede la pulizia dei RenderTarget, l’esecuzione dei shader e draw dei buffer e quindi il present dello swap chain.

Nel primo esempio mostrerò una semplice finestra blu. Per far questo si utilizzeranno le prime istruzioni base di Direct3D. La prima è il Clear che rende il render target del colore desiderato pulendolo del precedente rendering.

float ClearColor[4] = { r, g, b, a};

context->ClearRenderTargetView(renderTargetView,ClearColor);

Il second è il Clear del DepthStencil (che azzera la profondità)

context->ClearDepthStencilView(renderTargetDepth,D3D11_CLEAR_DEPTH,1,0);

Come vedete è il DeviceContext ad eseguire i metodi.

Infine lo SwapChain manda il render target a video

swapChain->Present(0,0);

In quest’istante il contenuto del back buffer verrà mostrato a video. Inserendo le 3 istruzioni in una funzione e chiamandola dal ciclo di gestione dei messaggi di windows si farà in modo che questa venga eseguita anche migliaia di volte al secondo, i cosiddetti fotogrammi al secondo o FPS (frame per second). Una scena complessa ovviamente richiederà più tempo ma saranno sufficienti 20-30 FPS per avere una buona fluidità (l’ideale sono 60 FPS).

In caso la finestra richieda di essere ridimensionata (a seguito di un resize) occorrerà fermare il rendering, distruggere i 2 target (tramite metodo Release), ridimensionare lo SwapChain tramite il suo metodo

ResizeBuffers(1,width,height,DXGI_FORMAT_R8G8B8A8_UNORM,2);

E quindi ricreare i 2 target prima di procedere di nuovo al rendering. Consiglio la visione del demo allegato all’articolo.

Per i programmatori .Net

La struttura è la stessa presente in C++. Ci sono solo piccole differenze come il fatto che i metodi non restituiscono HR ma sollevano eccezioni e che i parametri NULL sono sostituiti da override di metodi (diventando quindi opzionali).

Demo CPP

Demo .Net

Articolo Articolo  Storico Storico Stampa Stampa
I commenti sono disabilitati.
"Il tempo è un grande professore, ma sfortunatamente uccide tutti i suoi allievi"

Hector Berlioz


Cerca per parola chiave
 

Titolo
Articoli (4)
C++ (4)
Direct3D10 (30)
Direct3D11 (20)
DirectX9 (82)
DotNet (10)
English (9)
FanGames (22)
ManagedDX11 (2)
Materiale Utile (4)
News (39)
Shader Library (12)
SharpDX (1)
Software (25)
Tecnologia (19)
Varie (9)

Gli interventi più cliccati

Ultimi commenti:
If you wish to retai...
23/05/2013 @ 13:07:45
Di chanel outlet
You deficit of self-...
23/05/2013 @ 13:07:13
Di cartier watches uk
Reinforce your own l...
23/05/2013 @ 13:06:37
Di replica watches
Whenever you"re shiv...
23/05/2013 @ 13:06:11
Di swiss replica watches
It's likely you have...
23/05/2013 @ 13:05:02
Di chanel handbags
Cheap automobile ins...
23/05/2013 @ 13:04:28
Di replica watches

Titolo
Con quale tecnologia state realizzando o avete intenzione di realizzare i vostri progetti?

 DirectX11
 DirectX10
 DirectX9
 XNA
 DirectX8 o Precedenti
 OpenGL
 Motori grafici già pronti
 Altro

Titolo
Umorismo (17)

Le fotografie più cliccate



Ci sono 1089 persone collegate
Sono state visualizzate  pagine

22/11/2024 @ 16:27:26
script eseguito in 31 ms