\\ Home : Articoli : Stampa
Risorse e Texture
Di robydx (del 01/04/2007 @ 12:03:14, in Direct3D10, linkato 2165 volte)

DirectX memorizza tutte le sue risorse in buffer di memoria. Abbiamo già visto alcuni tipi di risorsa, come i vertex buffer.

Un tipo ormai fondamentale di risorsa è la texture. Una texture è una risorsa adibita alla gestione di immagini che sono utilizzate come rivestimento per il modello 3D. L’utilità è abbastanza ovvia. Per simulare la forma di un oggetto servono triangoli e se di dovesse rappresentare come triangoli ogni singolo dettaglio di un oggetto ne servirebbero troppi anche per una scheda DirectX10. Per questo si tende a rappresentare molti dei dettagli che non necessitano di uno spessore su di una immagine bitmap che viene avvolta attorno all’oggetto. Così un nostro ipotetico serpente non avrà le squame poligonali ma sarà un tubo con la foto della pelle applicata al modello. Questo ci fa risparmiare sia sui poligoni che sugli eventuali effetti per colori e luce.

Esistono vari tipi di texture e per ognuno differenti tipi di utilizzo.

In directX10 esistono 3 tipi di texture, tutte derivate dalla classe ID3D10Resource:

ID3D10Texture1D

ID3D10Texture2D

ID3D10Texture3D

Il primo rappresenta una immagine di altezza pari ad 1 pixel e larghezza variabile. Il secondo è la classica bitmap con larghezza ed altezza variabile. Il terzo invece rappresenta una collezione di immagini messe in pila una sull’altra.

Una texture si carica da file (generalmente bitmap o formati dedicati).

D3DX10CreateTextureFromFile (device, pathDelFile,info,NULL,&texture);

Gli argomenti sono il device, il percorso del file, una struttura info, una classe ID3DX10ThreadPump (serve per caricare in modo asincrono e sarà oggetto di futuri tutorial) e l’oggetto da caricare.

Info è una struttura di tipo

D3DX10_IMAGE_LOAD_INFO

Passare questa struttura permette di modificare l’immagine in fase di caricamento. I suoi parametri sono i seguenti

  • Width : larghezza desiderata o 0 per lasciare quella dell’immagine.
  • Height : altezza desiderata o 0 per lasciare quella dell’immagine.
  • Depth : profondità desiderata o 0 per lasciare quella dell’immagine.
  • FirstMipLevel :risoluzione massima per il mipmap (vedere più giù)
  • MipLevels :numero di mip level
  • Usage : uso della texture. Questo è molto importante in quanto una texture in DirectX10 ha molti usi. E’ un enum di tipo D3D10_USAGE
  • BindFlags : specifica l'utilizzo della risorsa. Nel caso di una texture D3D10_BIND_SHADER_RESOURCE
  • CpuAccessFlags : indica la modalità di accesso alla risorsa.
  • MiscFlags :attributi extra
  • Format : formato di colore da utilizzare
  • Filter : indica il modo in cui l’immagine viene ingrandita o rimpicciolita
  • MipFilter :modo in cui vengono generati i mip level
  • pSrcInfo : questa contiene un’altra struttura D3DX10_IMAGE_LOAD_INFO che si ottiene tramite l’istruzione D3DX10GetImageInfoFromFile. Questa conterrà il formato originale dell’immagine per permettere a DirectX di effettuare le giuste trasformazioni.

Per il momento utilizzate D3D10_USAGE_DEFAULT per l’usage e 0 per il CPUAccessFlags. Nel tutorial sull’accesso alla memoria spiegherò in dettaglio l’utilizzo di questi dettagli.

I filtri invece rappresentano l’algoritmo utilizzato quando si ridimensiona una immagine. Migliore sarà la qualità del filtro, migliore sarà la resa ma peggiori le performance (in questo caso solo al momento del caricamento).

 

  • D3DX10_FILTER_POINT
  • D3DX10_FILTER_LINEAR
  • D3DX10_FILTER_TRIANGLE
  • D3DX10_FILTER_BOX
  • D3DX10_FILTER_MIRROR_U
  • D3DX10_FILTER_MIRROR_V
  • D3DX10_FILTER_MIRROR_W
  • D3DX10_FILTER_MIRROR

 

Per mip (minus in parvis) si intende una tecnologia DirectX che consiste nell’inserire nella texture copie dell’immagine sempre più piccole (ogni livello ha dimensioni metà del precedente). Questo è utilizzato nel caso di oggetti distanti. Un oggetto distante non avrà bisogno della massima risoluzione texture possibile, quindi automaticamente DirectX utilizzerà un livello più basso risparmiando risorse. Tramite il load info sarà possibile specificare il numero di mip e le loro impostazioni.

Una volta caricata una texture questa resta in memoria a disposizione del device. Negli shader però non può essere utilizzata direttamente (cosa che invece avveniva in DirectX9) ma dovrà essere associata ad una “vista”. Per vista si intende un gestore che permette il passaggio di buffer verso gli shader.

D3D10_TEXTURE2D_DESC desc;

texture ->GetDesc( &desc );

D3D10_SHADER_RESOURCE_VIEW_DESC viewDesc;

ZeroMemory( & viewDesc, sizeof(viewDesc) );

viewDesc.Format = desc.Format;

viewDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;

viewDesc.Texture2D.MipLevels = desc.MipLevels;

ID3D10ShaderResourceView* textureView;

device->CreateShaderResourceView( texture, & viewDesc, &textureView);

Usando GetDesc si ottiene la descrizione della texture da cui poi creiamo la viewDesc (ci serviranno le informazioni sul formato, la dimensione ed il numero di livelli mips).

Sarà quindi la vista (nel nostro caso textureView) ad essere passata allo shader.

E’ possibile creare la risorsa in maniera più rapida.

D3DX10CreateShaderResourceViewFromFile(device, filePath, textureView);

Se poi vi serve la texture usate semplicemente GetResource

Sistema di coordinate texture

In DirectX una texture viene gestita non in pixel, ma in coordinate texture. Una immagine bidimensionale ha coordinate che variano da 0,0 (angolo alto a sinistra) ad 1,1 (angolo in basso a destra).

Il funzionamento è molto semplice.

Prendiamo un triangolo ed applichiamogli una zona dell’immagine. Innanzitutto scegliamo una zona triangolare qualsiasi dell’immagine e prendiamo i 3 vertici in coordinate texture (nell’esempio le 3 coppie sono 1-0 0-1 1-1). Queste 3 coppie di valori saranno passati al nostro buffer nel modo consueto creando una nuova riga di semantica.

La zona compresa tra i 3 punti sarà quindi posizionata sul triangolo. Non importa se il triangolo tagliato sull’immagine sarà diverso da quello 3D, l’immagine sarà deformata e piegata in modo da rispettare i 3 vertici. Quello selezionato nell’immagine sarà presente nel triangolo.

Definendo tutte le coordinate texture si potrà “mappare” l’oggetto ed applicare, quindi, la texture ad un intero modello 3D.

Le coordinate texture per una immagine variano da 0 ad 1. Cosa succede se le faccio variare da 0 a 2? Semplicemente superata la coordinata 1 la texture si ripeterà. In questo modo se ad esempio renderizziamo una parete composta da un rettangolo ci basterà usare coordinate texture da 0 a 10 per fare in modo che l’immagine si ripeta 10 volte su di essa. Per texture1D e 3D non cambia molto. Nel caso di texture1D avremo una sola coordinata che ci darà la posizione lungo l’unica dimensione. Nel caso di texture3D avremo 3 coordinate, la terza ci darà a che altezza della nostra pila di texture andare a prendere il pixel.

Nel prossimo tutorial renderizzeremo un modello 3D con texture.