Nel rendering grafico 3D (così come in quello 2D) DirectX effettua sostanzialmente un processo di scrittura a più fasi. Nella prima fase i modelli 3D e gli sprite vengono tracciati sul backbuffer che rappresenta sostanzialmente l'area di lavoro di DirectX e quando il backbuffer è pronto viene mandato al front buffer e quindi tracciato sullo schermo. Se ora ci pensiamo il backbuffer non è altro che una superficie grafica ossia una specie di grande matrice bidimensionale dove vengono memorizzati per ogni pixel i colori e le posizioni in profondità (questo comunque viene scritto nello Zbuffer) per ogni oggetto tracciato. Ogni volta che un nuovo oggetto viene disegnato sul backbuffer sfrutta i valori esistenti per venire tracciato (sfrutta ad esempio i colori già presenti per calcolare le trasparenze ed i valori dello ZBuffer per capire se un pixel stà dietro o davanti ad un oggetto). DirectX ci offre tra le sue tante funzioni la possibilità di gestire al meglio questo processo e addirittura di eseguirlo non solo sul backbuffer ma su qualsiasi superficie compatibile. Questo processo esistente da ormai molte versioni di DirectX è stato migliorato e semplificato notevolmente tanto da poter essere facilmente utilizzato senza problemi. La superficie più comoda su cui renderizzare una scena è senza dubbio una texture.
Le possibilità offerte da questa tecnica sono numerosissime. Potete infatti renderizzare una scena 3D su una texture e metterla su un monitor in modo da simulare una telecamera o mettere su texture la stessa scena vista da diversi angoli e visualizzarle come sprite. Nei videogiochi di ultima generazione il rendering su texture viene utilizzato anche per i riflessi degli oggetti (i riflessi di una pista su un'auto) o per preparare zone molto complesse da utilizzare spesso (ad esempio un quadro). Insomma ci si possono fare tante cose alcune semplici, altre complicate ma tutte passano per questo processo quasi banale che in DirectX9 viene gestito dall'oggetto RenderToSurface.
Codice
Cominciamo a creare una texture adatta a questo processo
renderTex = New Texture(device, 256, 256, 1, Usage.RenderTarget, Format.R5G6B5, Pool.Default)
Dove renderTex è una normale texture. Con questo codice ho creato una texture di dimensioni 256 x 256, ad 1 livello di mipmapping (usate questo per il momento) e di formato R5G6B5. Queste carattestische come vedete sono molto simili a quelle che passate al device per la sua creazione. Notate l'opzione principale:
UsageRenderTarget
Questa specifica che la texture sarà usate per questo processo. La texture creata è ora vuota quindi non usatela finchè non l'avete riempita.
Ora creiamo il renderToSurface
renderSur = New RenderToSurface(device, 256, 256, Format.R5G6B5, True, DepthFormat.D16)
Come vedete le dimensioni ed il formato sono uguali a quelle della texture. Questa ha però anche un valore booleano che indica se vogliamo usare il depthbuffer (come per il backbuffer) in modo da usare lo Z buffer o eventualmente lo stencil buffer (si vedrà in prossimi tutorial) e ne chiede il formato (se avete impostato false mettete quello che volete che tanto non lo usa).
Ora potete già usarli per renderizzare una scena. Il processo è molto semplice:
dichiarate un oggetto viewport e settatelo
Dim v As Viewport
v.Width = 256
v.Height = 256
v.MaxZ = 1
Il viewport è un oggetto che serve ad indicare una zona dove disegnare. Nel nostro caso mettiamo la grandezza della texture ed impostiamo il maxZ ad 1. Per maggiori dettagli consulta il mini tutorial nella sezione varie ma comunque non necessario qui. Ora apriamo un ciclo con la funzione beginscene di renderSur
renderSur.BeginScene(renderTex.GetSurfaceLevel(0), v)
La funzione chiede il viewport in ultima posizione ed una surface in prima. Utilizzando
renderTex.GetSurfaceLevel(0)
La texture renderTex restituisce la superficie ad essa associata (ricordo che una texture è un oggetto che contiene una superficie di tipo surface).
Per chiudere la scena
renderSur.EndScene(Filter.None)
Come vedete questa chiede un filtro per migliorare la qualità, settatelo a none perchè è veramente poco supportata dalle schede video, difficilmente in data odierna funzionerà con le vostre. All'interno delle due istruzioni avete la stessa identica situazione di un rendering normale. Potete fare le stesse identiche cose che fate le stesse identiche cose che fate normalmente come settare luci, usare clear, tracciare mesh etc.
renderSur.BeginScene(renderTex.GetSurfaceLevel(0), v)
//////TUTTA LA SCENA VA QUI
renderSur.EndScene(Filter.None)
Ci sono delle regole molto severe da rispettare per non generare errori:
1) non usate present, quello va usato quando andrete ad usare la texture nel normale rendering.
2)non dovete usare il rendering su superficie all'interno del ciclo beginscene e end scene di un'altro rendering compreso quello del device
3)le dimensioni ed i formati sono relativi alla dimensione delle texture. Occhio quindi alle proporzioni per testo e sprite. A seconda di come visualizzate la scena potrebbe essere necessario settare il parametro aspectRatio della projection matrix. Ad esempio se la texture quadrata sarà visualizzata su un quadrato allora conviene settarlo ad 1 ma se invece sarà usata su un oggetto di proporzioni qualsiasi dovrete farvi un paio di conti.
4)Le impostazioni che date al device durante il processo non ritornano a posto. Dovete essere voi a rimettere tutto a posto nel momento in cui ritornate al rendering normale (ad esempio telecamere e luci).
5)Più la texture è grande migliore sarà l'effetto a discapito della velocità sappiatevi regolare.
Dato che dovete usare il rendering su surface fuori da altri cicli il metodo giusto è quello di effettuare prima tutti i rendering su surface e poi fare un normale rendering usando le texture create in questo modo come volete (diventano normalissime texture).
Potete usare quante texture volete (non necessariamente tutte dello stesso formato). Ricordate però che servirà un oggetto renderToSurface per ogni diversa grandezza e formato (se usate più texture con ugual formato ne basta quindi una sola).
Vi lascio ad un semplice esempio che renderizza una scena dentro lo schermo di televisore.
Esempio VB.Net
Esempio C#
I commenti sono disabilitati.