Condividi tramite


Rendering da vertex buffer e buffer di indice (Direct3D 9)

I metodi di disegno indicizzati e non indicizzati sono supportati da Direct3D. I metodi indicizzati usano un singolo set di indici per tutti i componenti dei vertici. I dati dei vertici vengono archiviati nei buffer dei vertici e i dati degli indici vengono archiviati nei buffer degli indici. Di seguito sono elencati alcuni scenari comuni per la creazione di primitive che usano vertex buffer e buffer di indice.

Questi esempi confrontano l'uso di IDirect3DDevice9::DrawPrimitive e IDirect3DDevice9::DrawIndexedPrimitive

Scenario 1: Disegno di due triangoli senza indicizzazione

Si supponga di voler disegnare il quad illustrato nella figura seguente.

illustrazione di un quadrato costituito da due triangoli

Se si usa il tipo primitivo Elenco triangoli per eseguire il rendering dei due triangoli, ogni triangolo verrà archiviato come 3 singoli vertici, con un buffer di vertici simile all'illustrazione seguente.

diagramma di un buffer dei vertici che definisce tre vertici per due triangoli

La chiamata di disegno è molto semplice; a partire dalla posizione 0 all'interno del vertex buffer, disegnare due triangoli. Se il culling è abilitato, l'ordine dei vertici sarà importante. In questo esempio si presuppone lo stato predefinito di culling antiorario, quindi i triangoli visibili devono essere disegnati in senso orario. Il tipo primitivo Elenco triangoli legge semplicemente tre vertici in ordine lineare dal buffer per ogni triangolo, quindi questa chiamata disegna triangoli (0, 1, 2) e (3, 4, 5):

DrawPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
               0,                  // StartVertex
               2 );                // PrimitiveCount

Scenario 2: Disegno di due triangoli con indicizzazione

Come si noterà, il vertex buffer contiene dati duplicati in posizioni 0 e 4, 2 e 5. Questo ha senso perché i due triangoli condividono due vertici comuni. Questi dati duplicati sono sprecati e il vertex buffer può essere compresso usando un buffer di indici. Un buffer dei vertici più piccolo riduce la quantità di dati dei vertici che devono essere inviati alla scheda grafica. Ancora più importante, l'uso di un buffer di indice consente all'adattatore di archiviare i vertici in una cache dei vertici; se la primitiva disegnata contiene un vertice usato di recente, tale vertice può essere recuperato dalla cache invece di leggerlo dal vertex buffer, con un aumento delle prestazioni notevole.

Un buffer di indice indicizza nel buffer dei vertici, per cui ogni vertice univoco deve essere archiviato una sola volta nel buffer dei vertici. Il diagramma seguente illustra un approccio indicizzato allo scenario di disegno precedente.

diagramma di un buffer di indice per il buffer dei vertici precedente

Il buffer di indice archivia i valori di indice VB, che fanno riferimento a un vertice specifico all'interno del vertex buffer. Un vertex buffer può essere considerato come una matrice di vertici, quindi l'indice VB è semplicemente l'indice nel buffer dei vertici per il vertice di destinazione. Analogamente, un indice IB è un indice nel buffer degli indici. Ciò può generare confusione molto rapidamente se non si è attenti, quindi assicurarsi di avere chiaro il vocabolario in uso: i valori dell'indice VB indicizzano il vertex buffer, i valori dell'indice IB indicizzano il buffer di indice, e il buffer di indice stesso archivia i valori dell'indice VB.

La chiamata al disegno è mostrata di seguito. I significati di tutti gli argomenti vengono discussi a lungo per lo scenario di disegno successivo; Per il momento, tieni presente che questa chiamata indica di nuovo a Direct3D di eseguire il rendering di un elenco di triangoli contenente due triangoli, a partire dalla posizione 0 all'interno del buffer di indice. Questa chiamata disegnerà gli stessi due triangoli nello stesso ordine di prima, assicurando un corretto orientamento in senso orario:

   
DrawIndexedPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
                    0,                  // BaseVertexIndex
                    0,                  // MinIndex
                    4,                  // NumVertices
                    0,                  // StartIndex
                    2 );                // PrimitiveCount

Scenario 3: Disegno di un triangolo con indicizzazione

Fare finta di voler disegnare solo il secondo triangolo, ma si vuole usare lo stesso buffer dei vertici e lo stesso buffer di indice che vengono utilizzati per disegnare l'intero quad, come illustrato nel diagramma seguente.

diagramma del buffer di indice e del buffer dei vertici per il secondo triangolo

Per questa chiamata di disegno, il primo indice IB utilizzato è 3; questo valore è denominato StartIndex. L'indice VB più basso usato è 0; questo valore è denominato MinIndex. Anche se per disegnare il triangolo sono necessari solo tre vertici, questi tre vertici vengono distribuiti in quattro posizioni adiacenti nel vertex buffer; Il numero di posizioni all'interno del blocco contiguo di memoria del buffer dei vertici richiesto per la chiamata di disegno è denominato NumVertices e verrà impostato su 4 in questa chiamata. I valori MinIndex e NumVertices sono davvero solo suggerimenti per aiutare Direct3D a ottimizzare l'accesso alla memoria durante l'elaborazione dei vertici via software e possono semplicemente essere impostati per includere l'intero buffer dei vertici, a scapito delle prestazioni.

Ecco la chiamata di disegno per il caso a triangolo singolo; Il significato dell'argomento BaseVertexIndex verrà illustrato di seguito:

   
DrawIndexedPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
                    0,                  // BaseVertexIndex
                    0,                  // MinIndex
                    4,                  // NumVertices
                    3,                  // StartIndex
                    1 );                // PrimitiveCount

Scenario 4: Disegno di un triangolo con indicizzazione ad offset

BaseVertexIndex è un valore aggiunto in modo efficace a ogni indice VB archiviato nel buffer di indice. Ad esempio, se è stato passato un valore pari a 50 per BaseVertexIndex durante la chiamata precedente, questo sarebbe funzionalmente uguale all'uso del buffer di indice nel diagramma seguente per la durata della chiamata DrawIndexedPrimitive:

diagramma di un buffer di indice con un valore pari a 50 per basevertexindex

Questo valore viene raramente impostato su un valore diverso da 0, ma può essere utile se si desidera separare il buffer di indice dal vertex buffer: se quando si compila il buffer di indice per una determinata mesh la posizione della mesh all'interno del vertex buffer non è ancora nota, è sufficiente fingere che i vertici mesh si trovino all'inizio del vertex buffer; quando si tratta di effettuare la chiamata di disegno, è sufficiente passare la posizione iniziale effettiva come BaseVertexIndex.

Questa tecnica può essere usata anche quando si disegnano più istanze di una mesh usando un singolo buffer di indice; Ad esempio, se il buffer dei vertici conteneva due mesh con ordine di disegno identico ma vertici leggermente diversi (ad esempio colori diffusi o coordinate di trama diverse), entrambe le mesh potrebbero essere disegnate usando valori diversi per BaseVertexIndex. Prendendo ulteriormente questo concetto, è possibile usare un buffer di indice per disegnare più istanze di una mesh, ognuna contenuta in un buffer di vertici diverso, semplicemente eseguendo il ciclo del buffer dei vertici attivo e modificando BaseVertexIndex in base alle esigenze. Si noti che il valore BaseVertexIndex viene aggiunto automaticamente anche all'argomento MinIndex, che ha senso quando viene visualizzato come viene usato:

Supponiamo ora che vogliamo disegnare di nuovo solo il secondo triangolo del quad usando lo stesso indice di buffer; tuttavia, si utilizza un diverso buffer di vertici in cui il quad si trova in VB Index 50. L'ordine relativo dei vertici quad rimane invariato, ma solo la posizione iniziale all'interno del vertex buffer è diversa. Il buffer di indice e il vertex buffer sono simili al diagramma seguente.

diagramma del buffer di indice e del vertex buffer con un indice vb di 50

Ecco la chiamata di disegno appropriata, si noti che BaseVertexIndex è l'unico valore che è stato modificato rispetto allo scenario precedente.

   
DrawIndexedPrimitive( D3DPT_TRIANGLELIST, // PrimitiveType
                    50,                 // BaseVertexIndex
                    0,                  // MinIndex
                    4,                  // NumVertices
                    3,                  // StartIndex
                    1 );                // PrimitiveCount

di rendering delle primitive