\\ Home : Articoli : Stampa
Mesh
Di RobyDx (del 27/04/2007 @ 12:06:18, in Direct3D10, linkato 2957 volte)

 

Un oggetto 3D in DirectX10 è formato principalmente da 2 buffer, il vertex buffer e l’index buffer. Essendo questi oggetti sempre in coppia la SDK ci fornisce un oggetto che li gestisce entrambi: la ID3DX10Mesh.

Una mesh incapsula il vertex e l’index buffer e ci permette di fare molte operazioni in modo più semplice. Per chi viene da DirectX9 c’è da dire che purtroppo molte funzioni utili sono state rimosse, forse perché ritenute troppo restrittive in vista del nuovo approccio completamente orientato agli shader.

Per creare una mesh vuota si usa

ID3DX10Mesh *mesh;

D3DX10CreateMesh(device, semanticArray, semanticCount, PositionSemantic, VertexCount, FaceCount, Options, &mesh);

  • semanticArray: un array di D3D10_INPUT_ELEMENT_DESC, gli stessi utilizzati per definire l’inputLayout. La mesh in pratica si crea già pronta per supportare un nostro layer
  • semanticCount: il numero di elementi in semanticArray
  • PositionSemantic : una stringa che indica il nome del campo usato per la posizione.
  • VertexCount: numero di vertici
  • FaceCount: numero di facce (ricordate, 3 indici per ogni faccia)
  • Opzions: sono opzioni aggiuntive che sono D3DX10_MESH_32_BIT per indicare che vogliamo usare indici a 32 bit (per mesh con più di 65000 indici) e D3DX10_MESH_GS_ADJACENCY per far generare le informazioni necessarie per la gestione delle adiacenze nel geometry. Le opzioni possono essere concatenate con l’OR logico ( | ). Potete usare 0 per creare una mesh a 16 bit senza geometry.

Se il risultato della funzione è S_OK allora la mesh vuota è pronta.

Dovete ora impostare i dati.

mesh->SetVertexData( bufferIndex, data);

Con questa si riempie la mesh con l’array di vertici. In bufferIndex va il numero dello stream da riempire (in DirectX10 si possono usare più vertex buffer contemporaneamente, per mesh semplici c’è solo il primo indice che è zero). Il parametro data è invece l’array di vertici così come vengono passati al vertexbuffer.

Per passare gli indici invece si usa

mesh->SetIndexData(data,indexCount);

Dove data è l’array di indici e indexCount il numero di indici da leggere.

Dopo aver impostato i vertici e gli indici va usata l’istruzione

mesh->CommitToDevice();

Questa istruzione crea definitivamente la mesh che è ora pronta per il rendering. Prima però è necessario spiegare un altro dettaglio presente nella mesh: l’attribute buffer.

Vertex ed Index buffer non devono necessariamente contenere un solo oggetto ma potrebbero contenerne di diversi (una delle tecniche usate per ottimizzare è proprio quello di mettere tutta la grafica in pochi buffer). L’attribute buffer è un array di interi, uno per ogni triangolo della mesh, che serve per specificare a quale “subset” appartiene quel triangolo. Se ad esempio avete una scena con un tavolo ed una sedia in un unico buffer marcherete come 0 le facce del tavolo ed 1 quelle della sedia.

Per impostare gli attributi si usa, prima del commit, SetAttributeData.

In alternativa si può invece passare un array di D3DX10_ATTRIBUTE_RANGE che descrive le subset indicando dove iniziano e dove finiscono nei buffer nel vertex e nell’index buffer e l’ID di riferimento (di solito si ordinano da 0 in poi)

mesh->SetAttributeTable(attributes, attributeCount);

mesh->GenerateAttributeBufferFromTable();

Con questa funzione

Mesh->GenerateAdjacencyAndPointReps(epsilon);

Si generano le adiacenze e con questa istruzione si forza la creazione delle adiacenze, necessarie per il geometry.

mesh-> GenerateGSAdjacency();

Per renderizzare

Mesh->DrawSubset(index);

dove index è un intero che specifica quale attribute andare a renderizzare. Questa chiamata sostituisce i vari setbuffer e draw primitive, ma non vertex layout che dovrà essere inserito. Ovviamente ancora prima dovrete attivare l’effetto.

Nella classe mesh ci sono diverse utilità come GetFace GetVertices per leggere il numero di triangoli e vertici contenuti e funzioni di utilità che verranno trattate in seguito.

Vi lascio un demo molto particolare. Una grave mancanza di DirectX10 è il fatto che i file .x non possono essere più caricati. Per chi non avesse usato le versioni precedenti di DirectX, i file .x sono file contenenti oggetti 3D generati con programmi come 3Dstudio, Maya e simili.

Ebbene, vi ho preparato una classe in grado di caricare il vecchio formato .X utilizzando la possibilità di creare Device virtuali per DirectX9 ed utilizzare le vecchie funzioni di gestione delle mesh. Per maggiori approfondimenti consultate l'help di DirectX

Aggiornamento

Dopo gli aggiornamenti di DirectX occorre modificare lo shader in questo modo

BlendState SampleBlending
{
    BlendEnable[0] = FALSE; 
    RenderTargetWriteMask[0] = 0x0F;
};

technique10 Render
{
    pass P0
    {
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader(NULL);
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
        SetDepthStencilState( EnableDepth, 0 );
        SetBlendState( SampleBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    }
}

In questo modo disattiverete l'alphablending che altrimenti sarebbe attivo rendendo l'oggetto trasparente.  Modificate lo shader in questo modo.

Vi lascio al demo

Demo