Fasi di tessellazione

Il runtime Direct3D 11 supporta tre nuove fasi che implementano la tessellazione, che converte le superfici di suddivisione a dettaglio basso in primitive più dettagliate nella GPU. Riquadri di tessellazione (o suddivide) superfici ad ordine elevato in strutture adatte per il rendering.

Implementando la tessellazione nell'hardware, una pipeline grafica può valutare i dettagli inferiori (conteggio poligono inferiore) e eseguire il rendering in dettaglio più elevato. Anche se la tessellazione software può essere eseguita, la tessellazione implementata dall'hardware può generare un'incredibile quantità di dettagli visivi (incluso il supporto per il mapping di spostamento) senza aggiungere i dettagli visivi alle dimensioni del modello e alle frequenze di aggiornamento paralizzabili.

Vantaggi della tessellazione

Mosaico:

  • Salva un sacco di memoria e larghezza di banda, che consente a un'applicazione di eseguire il rendering di superfici dettagliate più elevate da modelli a bassa risoluzione. La tecnica di tessellazione implementata nella pipeline Direct3D 11 supporta anche il mapping di spostamento, che può produrre quantità straordinarie di dettagli di superficie.
  • Supporta tecniche di rendering scalabili, ad esempio livelli di dettaglio dipendenti continui o di visualizzazione, che possono essere calcolati al volo.
  • Migliora le prestazioni eseguendo calcoli costosi a frequenza inferiore (eseguendo calcoli su un modello di dettaglio inferiore). Ciò può includere la fusione di calcoli usando forme o destinazioni di modifica per animazioni realistiche o calcoli di fisica per il rilevamento delle collisioni o le dinamiche del corpo morbido.

La pipeline Direct3D 11 implementa la tessellazione nell'hardware, che carica il lavoro dalla CPU alla GPU. Ciò può causare miglioramenti delle prestazioni molto grandi se un'applicazione implementa un numero elevato di destinazioni di morphing e/o modelli di deformazione più sofisticati. Per accedere alle nuove funzionalità di tessellazione, è necessario conoscere alcune nuove fasi della pipeline.

Nuove fasi della pipeline

Tessellation usa la GPU per calcolare una superficie più dettagliata da una superficie costruita da patch quad, patch triangoli o isoline. Per approssimare la superficie elevata, ogni patch viene suddivisa in triangoli, punti o linee usando fattori di tessellazione. La pipeline Direct3D 11 implementa la tessellazione usando tre nuove fasi della pipeline:

  • Stage Hull-Shader : fase programmabile dello shader che produce una patch geometry (e costanti patch) che corrispondono a ogni patch di input (quad, triangolo o linea).
  • Fase tessellatore: una fase della pipeline di funzione fissa che crea un modello di campionamento del dominio che rappresenta la patch geometry e genera un set di oggetti più piccoli (triangoli, punti o linee) che connettono questi esempi.
  • Fase domain-Shader: fase dello shader programmabile che calcola la posizione del vertice corrispondente a ogni esempio di dominio.

Il diagramma seguente evidenzia le nuove fasi della pipeline Direct3D 11.

diagramma della pipeline direct3d 11 che evidenzia le fasi hull-shader, tessellator e domain-shader

Il diagramma seguente illustra la progressione attraverso le fasi di tessellazione. La progressione inizia con la superficie di suddivisione a basso dettaglio. La progressione evidenzia quindi la patch di input con la patch geometry corrispondente, gli esempi di dominio e i triangoli che connettono questi esempi. La progressione evidenzia infine i vertici corrispondenti a questi campioni.

diagramma della progressione della tessellazione

fase Hull-Shader

Uno shader dello scafo, richiamato una volta per patch, trasforma i punti di controllo di input che definiscono una superficie a basso ordine in punti di controllo che costituiscono una patch. Esegue anche alcuni calcoli per patch per fornire dati per la fase di tessellazione e la fase di dominio. A livello di scatola nera più semplice, la fase hull-shader sarebbe simile al diagramma seguente.

diagramma della fase di hull-shader

Uno shader dello scafo viene implementato con una funzione HLSL e ha le proprietà seguenti:

  • L'input shader è compreso tra 1 e 32 punti di controllo.
  • L'output dello shader è compreso tra 1 e 32 punti di controllo, indipendentemente dal numero di fattori di tessellazione. L'output dei punti di controllo da uno shader dello scafo può essere utilizzato dalla fase domain-shader. I dati costanti patch possono essere usati da uno shader di dominio; I fattori di tessellazione possono essere utilizzati dal domain shader e dalla fase di tessellazione.
  • I fattori di tessellazione determinano la quantità di suddivisione di ogni patch.
  • Lo shader dichiara lo stato richiesto dalla fase del tessellatore. Sono incluse informazioni quali il numero di punti di controllo, il tipo di viso di patch e il tipo di partizionamento da usare durante la tessellatura. Queste informazioni vengono visualizzate come dichiarazioni in genere nella parte anteriore del codice shader.
  • Se la fase dello hull-shader imposta qualsiasi fattore di tessellazione perimetrale su = 0 o NaN, la patch verrà eliminata. Di conseguenza, la fase del tessellatore potrebbe o non essere eseguita, lo shader di dominio non verrà eseguito e non verrà generato alcun output visibile per tale patch.

A livello più profondo, un hull-shader opera effettivamente in due fasi: una fase del punto di controllo e una fase costante patch, che vengono eseguite in parallelo dall'hardware. Il compilatore HLSL estrae il parallelismo in uno shader dello scafo e lo codifica in bytecode che guida l'hardware.

  • La fase del punto di controllo funziona una volta per ogni punto di controllo, lettura dei punti di controllo per una patch e generazione di un punto di controllo di output (identificato da un ControlPointID).
  • La fase costante della patch funziona una volta per patch per generare fattori di tessellazione perimetrale e altre costanti per patch. Internamente, molte fasi costanti patch possono essere eseguite contemporaneamente. La fase della costante patch ha accesso in sola lettura a tutti i punti di controllo di input e output.

Ecco un esempio di uno shader dello scafo:

[patchsize(12)]
[patchconstantfunc(MyPatchConstantFunc)]
MyOutPoint main(uint Id : SV_ControlPointID,
     InputPatch<MyInPoint, 12> InPts)
{
     MyOutPoint result;
     
     ...
     
     result = TransformControlPoint( InPts[Id] );

     return result;
}

Per un esempio che crea uno shader dello scafo, vedere Procedura: Creare uno shader di Hull.

Fase tessellatore

Il tessellatore è una fase a funzione fissa inizializzata associando uno shader dello scafo alla pipeline (vedere Procedura: Inizializzare la fase Tessellator). Lo scopo della fase tessellatore è suddividere un dominio (quad, tri o linea) in molti oggetti più piccoli (triangoli, punti o linee). Il tessellatore riquadri un dominio canonico in un sistema di coordinate normalizzato (zero-a-uno). Ad esempio, un dominio quad viene tessellato in un quadrato unità.

Il tessellatore opera una volta per patch usando i fattori di tessellazione (che specificano come il dominio verrà tessellato) e il tipo di partizionamento (che specifica l'algoritmo usato per tagliare una patch) passato dalla fase di hull-shader. Il tessellatore restituisce coordinate uv (e facoltativamente w) e la topologia di superficie alla fase di domain-shader.

Internamente, il tessellatore opera in due fasi:

  • La prima fase elabora i fattori di tessellazione, correzione di problemi di arrotondamento, gestione di fattori molto piccoli, riduzione e combinazione di fattori, usando aritmetica a 32 bit.
  • La seconda fase genera elenchi di topologie o punti in base al tipo di partizionamento selezionato. Si tratta dell'attività principale della fase tessellatore e usa frazioni a 16 bit con aritmetica a virgola fissa. L'aritmetica a punto fisso consente l'accelerazione hardware mantenendo la precisione accettabile. Ad esempio, data una patch a 64 metri, questa precisione può posizionare punti a una risoluzione di 2 mm.
Tipo di partizionamento Intervallo
fractional_odd [1...63]
fractional_even Intervallo TessFactor: [2..64]
numero intero Intervallo TessFactor: [1..64]
pow2 Intervallo TessFactor: [1..64]

fase Domain-Shader

Un domain shader calcola la posizione del vertice di un punto suddiviso nella patch di output. Un domain shader viene eseguito una volta per ogni punto di output della fase di tessellatore e ha accesso in sola lettura alle coordinate UV di output della fase tessellator, alla patch di output dello shader dello scafo e alle costanti dell'output dello shader dello scafo, come illustrato nel diagramma seguente.

diagramma della fase domain-shader

Le proprietà del domain shader includono:

  • Viene richiamato uno shader di dominio una volta per ogni coordinata di output dalla fase del tessellatore.
  • Un domain shader usa i punti di controllo di output dalla fase di hull-shader.
  • Un domain shader restituisce la posizione di un vertice.
  • Gli input sono gli output dello shader dello scafo, inclusi i punti di controllo, i dati costanti delle patch e i fattori di tessellazione. I fattori di tessellazione possono includere i valori usati dal tessellatore di funzioni fisse, nonché i valori non elaborati (prima di arrotondare per tessellazione intero, ad esempio), che facilita la geomorfiatura, ad esempio.

Al termine dello shader del dominio, la tessellazione viene completata e i dati della pipeline continuano alla fase successiva della pipeline (geometry shader, pixel shader e così via). Un shader geometry che prevede primitive con adiacency (ad esempio, 6 vertici per triangolo) non è valido quando la tessellazione è attiva (questo comporta un comportamento non definito, che il livello di debug si lamenta).

Ecco un esempio di domain shader:

void main( out    MyDSOutput result, 
           float2 myInputUV : SV_DomainPoint, 
           MyDSInput DSInputs,
           OutputPatch<MyOutPoint, 12> ControlPts, 
           MyTessFactors tessFactors)
{
     ...

     result.Position = EvaluateSurfaceUV(ControlPoints, myInputUV);
}

API per inizializzare le fasi di tessellazione

Tessellation viene implementata con due nuove fasi dello shader programmabile: uno shader dello scafo e un domain shader. Queste nuove fasi shader sono programmate con codice HLSL definito nel modello shader 5. Le nuove destinazioni shader sono: hs_5_0 e ds_5_0. Come tutte le fasi programmabili dello shader, il codice per l'hardware viene estratto dai shader compilati passati al runtime quando gli shader sono associati alla pipeline usando API come DSSetShader e HSSetShader. Tuttavia, prima di tutto, è necessario creare lo shader usando API, ad esempio CreateHullShader e CreateDomainShader.

Abilitare la tessellazione creando uno shader dello scafo e associandolo alla fase dello hull-shader (questo imposta automaticamente la fase del tessellatore). Per generare le posizioni del vertice finale dalle patch tessellate, sarà anche necessario creare uno shader di dominio e associarlo alla fase domain-shader. Dopo l'abilitazione della tessellazione, l'input dei dati alla fase dell'assembler di input deve essere dati di patch. Vale a dire, la topologia dell'assembler di input deve essere una topologia costante patch da D3D11_PRIMITIVE_TOPOLOGYimpostata con IASetPrimitiveTo topologia.

Per disabilitare la tessellazione, impostare lo shader dello scafo e il domain shader su NULL. Né la fase geometry-shader né la fase di output di flusso possono leggere i punti di output di hull-shader o i dati delle patch.

Procedura:

La documentazione contiene anche esempi per inizializzare le fasi di tessellazione.

Elemento Descrizione
Procedura: Creare uno shader di Hull
Creare uno shader dello scafo.
Procedura: Progettare uno shader di hull
Progettare uno shader dello scafo.
Procedura: Inizializzare la fase Tessellator
Inizializzare la fase di tessellazione.
Procedura: Creare un domain shader
Creare uno shader di dominio.
Procedura: Progettare uno shader di dominio
Creare uno shader di dominio.

Pipeline grafica