notJustCode.it
 
\\ Home : Articoli
Geometry Instancing
Di robydx (del 02/07/2007 @ 22:12:06, in Direct3D10, linkato 2701 volte)

Tutto ciò che appariva come funzionalità avanzata in DirectX9, appare come una funzionalità standard in DirectX10. Un esempio è il geometry instancing, una delle ultime funzionalità ad apparire in Direct3D9.

Tramite il geometry instancing possiamo caricare un soldato ed in un'unica istruzione di draw, mandarne a video migliaia di copie, ognuna con caratteristiche di posizione, colore o texture differenti l'uno dall'altro.

La cosa più interessante è la totale gestione in memoria video del processo, permettendo delle prestazioni impensabili normalmente. Infatti ogni volta che si esegue una istruzione di draw ci sono dati che passano dalla RAM alla scheda video o tra zone diverse di quest'ultima: sarà direttamente la GPU ad operare la moltiplicazione dei vertici e degli indici dell'oggetto.

Il geometry instancing prevede l'utilizzo di 2 vertex buffer: il primo contenente i vertici dell'oggetto, il secondo contenente un array di strutture dati specifiche per ogni copia. Ad esempio se vogliamo rappresentare 1000 oggetti, ognuno con posizione e colore diverso, dovremo creare una struttura contenente posizione e colore e crearne un array di 1000 elementi. La funzionalità geometry instancing non farà altro che fondere ogni vertice con ogni elemento del secondo buffer. Nel vertex shader troveremo una struttura di input che sarà la somma dei 2 buffer. Dal punto di vista dello shader sarà quindi sufficiente prevedere dei dati extra da utilizzare per modificare la posizione ed il colore dell'oggetto. Per prima cosa è necessario creare un buffer per contenere i dati

ID3D10Buffer* instanceBuffer;

this->stride=stride;
this->offset=0;
this->vertexCount=vertexCount;
D3D10_BUFFER_DESC bd;
bd.Usage = D3D10_USAGE_DYNAMIC;
bd.ByteWidth = stride * elementCount;
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;

D3D10_SUBRESOURCE_DATA InitData;
InitData.pSysMem = data;

device->CreateBuffer( &bd, &InitData, &instanceBuffer);

 

Come vedete è simile a quanto usato per il vertex buffer. Per poter utilizzare l'instancing occorre creare un layout appropriato

D3D10_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{ "EXTRADATA", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D10_INPUT_PER_INSTANCE_DATA, 1 },
};

Nell' instancing il layout è formato dalla somma dei due formati vertici. Il secondo buffer è descritto dalla seconda parte dell'array. Si può notare infatti che l'indice è impostato ad 1 e non a 0 (perchè sarà estratto dal secondo buffer), l'offset è a zero (perchè si conta l'offset del buffer, non totale del vertice) e si imposta il tipo ad Instance_Data. L'ultimo valore, instance_repetition, va impostato ad 1.

Ora quello che si dovrò fare in fase di rendering è passare i 2 vertex buffer contemporaneamente (quello con i dati e quello con i dati per l'instancing).

 

device->IASetInputLayout(this->layout);
device->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D10Buffer* buffers[2]={vertexBuffer,instanceVertexBuffer};
UINT strideA[2]={stride,instanceStride};
UINT offsetA[2]={0,0};

device->IASetVertexBuffers(0,2,buffers,strideA,offsetA);
device->IASetIndexBuffer(indexBuffer,DXGI_FORMAT_R16_UINT,0);
device->DrawIndexedInstanced(FaceCount*3,istanceCount,0,0,0);

 In questo esempio vedete come ho eseguito il rendering. Ho creato un array con due buffer e li ho passati al device insieme ai due stride ed i due offset. Nel mio esempio avrò uno stride di 20 byte per il primo vertex buffer (POSITION e TEXCOORD) e 16 per il secondo (EXTRADATA). Successivamente passo l'indexbuffer ed utilizzo l'istruzione DrawIndexedInstanced per mandare il rendering (gli si passa alla funzione il numero degli indici ed il numero di istance ossia quante copie dell'oggetto volete). Con la funzione DrawIndexedInstance potrete renderizzare oggetti da un minimo di zero ad un massimo pari al numero di elementi nel buffer dell'instance.

Nello shader non noterete differenza

struct VS_INPUT
{
float4 Pos : POSITION;
float2 tex:TEXCOORD;
float4 posIstance:EXTRADATA;
};

 

Ogni vertice del primo buffer sarà combinato con ogni vertice (anche se in realtà sono dati anche se gestiti come vertici). Quindi se abbiamo un cubo e 1000 vettori posizione otterremo 8 (vertici del cubo) * 1000 = 8000 vertici e quindi 8000 chiamate allo shader con tutte le combinazioni. Nello shader ad esempio potremo utilizzare il vettore per spostare il cubo in modo da assegnare ad ognuno una posizione diversa. Passando 4 float4 avrete una intera matrice. Potete passare quanti dati volete.

Nella struttura di input potete utilizzare un campo non definito nei due buffer con sintatti SV_InstanceID

uint indice:SV_InstanceID

Questo campo contiene l'indice dell'instanza che stiamo renderizzando (che varierà quindi da 0 a 999 nell'esempio).

 

Vi lascio al demo che renderizza fino a 1000 cubi contemporaneamente.

Demo

Articolo Articolo  Storico Storico Stampa Stampa
I commenti sono disabilitati.
"La logica ti porterà dal punto A al punto B. L'immaginazione ti porterà ovunque"

Albert Einstein


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 1100 persone collegate
Sono state visualizzate  pagine

22/11/2024 @ 16:28:14
script eseguito in 31 ms