Condividi tramite


Rendering da vertex buffer e index buffer (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 vertex buffer e i dati dell'indice vengono archiviati nei buffer di indice. Di seguito sono elencati alcuni scenari comuni per disegnare primitive che usano vertex buffer e index buffer.

Questi esempi confrontano l'uso di IDirect3DDevice9::D rawPrimitive e IDirect3DDevice9::D rawIndexedPrimitive

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, ottenendo un buffer di vertici simile alla figura 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 in senso 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 nelle posizioni 0 e 4, 2 e 5. Questo ha senso perché i due triangoli condividono due vertici comuni. Questi dati duplicati sono sprecate e il buffer dei vertici può essere compresso usando un buffer di indice. 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 anziché leggerlo dal buffer dei vertici, con un aumento delle prestazioni notevole.

Un buffer di indice "indici" nel buffer dei vertici in modo che ogni vertice univoco debba 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 vertex buffer 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 di indice. Ciò può generare confusione molto rapidamente se non si è attenti, quindi assicurarsi di essere chiari sul vocabolario in uso: indice di indice VB nel vertex buffer, indice IB index nel buffer di indice e il buffer di indice stesso archivia i valori di indice VB Index.

La chiamata di disegno è illustrata 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 dell'indice. Questa chiamata disegnerà gli stessi due triangoli nello stesso ordine di prima, assicurando un orientamento orario appropriato:

   
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 il buffer di indice usati 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 sono necessari solo tre vertici per disegnare il triangolo, questi tre vertici vengono distribuiti in quattro posizioni adiacenti nel buffer dei vertici; Il numero di posizioni all'interno del blocco contiguo di memoria del buffer dei vertici richiesto per la chiamata di disegno viene chiamato NumVertices e verrà impostato su 4 in questa chiamata. I valori MinIndex e NumVertices sono solo suggerimenti per ottimizzare l'accesso alla memoria direct3D durante l'elaborazione dei vertici software e possono semplicemente essere impostati per includere l'intero buffer dei vertici al prezzo delle prestazioni.

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

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

Scenario 4: Disegno di un triangolo con indicizzazione 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, tale valore 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 particolare 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 contiene due mesh con un ordine di disegno identico ma vertici leggermente diversi (forse diversi colori diffusi o coordinate di trama), entrambe le mesh possono essere disegnate usando valori diversi per BaseVertexIndex. Prendendo questo concetto ulteriormente, è 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 anche il valore BaseVertexIndex viene aggiunto automaticamente all'argomento MinIndex, che ha senso quando viene visualizzato come viene usato:

Fingere ora che vogliamo di nuovo disegnare solo il secondo triangolo del quad usando lo stesso buffer di indice di prima; tuttavia, viene usato un buffer di vertici diverso 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 buffer dei vertici avranno un aspetto simile al diagramma seguente.

diagramma del buffer di indice e del vertex buffer con un indice vb pari a 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

Rendering di primitive