Tessellationsphasen

Die Direct3D 11-Runtime unterstützt drei neue Phasen, die tessellation implementieren, wodurch Unterteilungsflächen mit geringer Detailgenauigkeit in Grundtypen mit höherem Detail auf der GPU konvertiert werden. Tessellationkacheln (oder zerlegt) hohe Oberflächen in geeignete Strukturen zum Rendern.

Durch die Implementierung von Tessellation in Hardware kann eine Grafikpipeline Modelle mit geringerer Detailgenauigkeit (niedrigere Polygonanzahl) auswerten und mit höherer Detailgenauigkeit rendern. Während softwaretessellation möglich ist, kann die von Hardware implementierte Tessellation eine unglaubliche Menge an visuellen Details generieren (einschließlich Unterstützung für die Verdrängungszuordnung), ohne die visuellen Details zu den Modellgrößen hinzuzufügen und die Aktualisierungsraten zu lähmen.

Vorteile von Tessellation

Tessellation:

  • Spart viel Arbeitsspeicher und Bandbreite, sodass eine Anwendung detailliertere Oberflächen aus Modellen mit niedriger Auflösung rendern kann. Die tessellationstechnik, die in der Direct3D 11-Pipeline implementiert wurde, unterstützt auch die Verdrängungszuordnung, wodurch atemberaubende Mengen an Oberflächendetails erzeugt werden können.
  • Unterstützt skalierbare Renderingverfahren, z. B. fortlaufende oder ansichtsabhängige Detailebenen, die im laufenden Betrieb berechnet werden können.
  • Verbessert die Leistung, indem teure Berechnungen mit niedrigerer Häufigkeit durchgeführt werden (Berechnungen für ein Modell mit geringerer Detailgenauigkeit). Dies kann das Mischen von Berechnungen mit Mischformen oder Morphzielen für realistische Animationen oder physikologische Berechnungen zur Kollisionserkennung oder Weichkörperdynamik umfassen.

Die Direct3D 11-Pipeline implementiert tessellation in hardware, wodurch die Arbeit von der CPU auf die GPU geladen wird. Dies kann zu sehr großen Leistungsverbesserungen führen, wenn eine Anwendung eine große Anzahl von Morphzielen und/oder anspruchsvollere Skinning/Deformationsmodelle implementiert. Um auf die neuen Tessellationsfeatures zuzugreifen, müssen Sie sich über einige neue Pipelinephasen informieren.

Neue Pipelinephasen

Tessellation verwendet die GPU, um eine detailliertere Oberfläche aus einer Oberfläche zu berechnen, die aus Quad-Patches, Dreieckspatches oder Isolinien erstellt wurde. Um die hochgeordnete Oberfläche anzunähern, wird jeder Patch mithilfe von Tessellationsfaktoren in Dreiecke, Punkte oder Linien unterteilt. Die Direct3D 11-Pipeline implementiert die Tessellation mithilfe von drei neuen Pipelinestufen:

  • Hull-Shader Stage : Eine programmierbare Shaderstufe, die einen Geometriepatch (und Patchkonstanten) erzeugt, die jedem Eingabepatch (Quad, Dreieck oder Linie) entsprechen.
  • Tessellatorphase : Eine Pipelinephase mit festen Funktionen, die ein Stichprobenmuster der Domäne erstellt, das den Geometriepatch darstellt, und einen Satz kleinerer Objekte (Dreiecke, Punkte oder Linien) generiert, die diese Beispiele verbinden.
  • Domain-Shader Stage : Eine programmierbare Shaderstufe, die die Vertexposition berechnet, die den einzelnen Domänenbeispielen entspricht.

Das folgende Diagramm zeigt die neuen Phasen der Direct3D 11-Pipeline.

Diagramm der direct3d 11-Pipeline, die die Phasen Hull-Shader, Tessellator und Domänenshader hervor hebt

Das folgende Diagramm zeigt den Fortschritt durch die Tessellationsphasen. Der Fortschritt beginnt mit der Unterteilungsoberfläche mit geringen Details. Der nächste Fortschritt hebt den Eingabepatch mit dem entsprechenden Geometriepatch, Domänenbeispielen und Dreiecken hervor, die diese Beispiele verbinden. Der Fortschritt hebt schließlich die Scheitelpunkte hervor, die diesen Beispielen entsprechen.

Diagramm des Tessellationsverlaufs

Hull-Shader Phase

Ein Hull-Shader, der einmal pro Patch aufgerufen wird, transformiert Eingabesteuerungspunkte, die eine Oberfläche mit niedriger Ordnung definieren, in Steuerungspunkte, aus denen ein Patch besteht. Außerdem werden einige Berechnungen pro Patch durchgeführt, um Daten für die Tessellationsphase und die Domänenphase bereitzustellen. Auf der einfachsten Blackbox-Ebene würde die Rumpf-Shader-Stufe ungefähr wie das folgende Diagramm aussehen.

Diagramm der Hull-Shader-Phase

Ein Hull-Shader wird mit einer HLSL-Funktion implementiert und weist die folgenden Eigenschaften auf:

  • Die Shadereingabe liegt zwischen 1 und 32 Kontrollpunkten.
  • Die Shaderausgabe liegt zwischen 1 und 32 Kontrollpunkten, unabhängig von der Anzahl der Tessellationsfaktoren. Die Ausgabe von Steuerelementpunkten aus einem Hull-Shader kann von der Domain-Shader-Phase verwendet werden. Patchkonstantendaten können von einem Domänenshader genutzt werden. Tessellationsfaktoren können vom Domänen-Shader und der Tessellationsphase genutzt werden.
  • Tessellationsfaktoren bestimmen, wie viel die einzelnen Patches unterteilt werden sollen.
  • Der Shader deklariert den zustand, der für die tessellator-Phase erforderlich ist. Dies umfasst Informationen wie die Anzahl der Kontrollpunkte, den Typ des Patchfaces und den Typ der Partitionierung, die beim Tesselling verwendet werden soll. Diese Informationen werden als Deklarationen normalerweise an der Vorderseite des Shadercodes angezeigt.
  • Wenn die Hull-Shader-Stufe einen beliebigen Randtessellationsfaktor auf = 0 oder NaN festlegt, wird der Patch gekullt. Infolgedessen kann die Tessellatorphase ausgeführt werden oder nicht, der Domänen-Shader wird nicht ausgeführt, und für diesen Patch wird keine sichtbare Ausgabe erzeugt.

Auf einer tieferen Ebene arbeitet ein Hull-Shader tatsächlich in zwei Phasen: einer Kontrollpunktphase und einer Patchkonstantenphase, die parallel von der Hardware ausgeführt werden. Der HLSL-Compiler extrahiert die Parallelität in einem Hull-Shader und codiert ihn in Bytecode, der die Hardware antreibt.

  • Die Steuerungspunktphase wird für jeden Kontrollpunkt einmal ausgeführt, liest die Steuerungspunkte für einen Patch und generiert einen Ausgabesteuerungspunkt (identifiziert durch eine ControlPointID).
  • Die Patchkonstantephase wird einmal pro Patch ausgeführt, um Edgetessellationsfaktoren und andere Patchkonstanten zu generieren. Intern können viele Patchkonstantenphasen gleichzeitig ausgeführt werden. Die Patchkonstantenphase hat schreibgeschützten Zugriff auf alle Eingabe- und Ausgabesteuerungspunkte.

Hier sehen Sie ein Beispiel für einen Hull-Shader:

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

     return result;
}

Ein Beispiel zum Erstellen eines Hull-Shaders finden Sie unter Vorgehensweise: Erstellen eines Hull-Shaders.

Tessellator-Phase

Der Tessellator ist eine Phase mit festen Funktionen, die initialisiert wird, indem ein Hull-Shader an die Pipeline gebunden wird (siehe Vorgehensweise: Initialisieren der Tessellatorphase). Der Zweck der Tessellatorphase besteht darin, eine Domäne (Quad, Tri oder Linie) in viele kleinere Objekte (Dreiecke, Punkte oder Linien) zu unterteilen. Der Tessellator kachelt eine kanonische Domäne in einem normalisierten Koordinatensystem (null zu eins). Beispielsweise wird eine Quad-Domäne zu einem Einheitsquadrat tesselliert.

Der Tessellator arbeitet einmal pro Patch unter Verwendung der Tessellationsfaktoren (die angeben, wie fein die Domäne tesselliert wird) und den Partitionierungstyp (der den Algorithmus angibt, der zum Aufschneiden eines Patches verwendet wird), die aus der Hull-Shader-Phase übergeben werden. Der Tessellator gibt uv -Koordinaten (und optional w) und die Oberflächentopologie an die Domänen-Shader-Phase aus.

Intern arbeitet der Tessellator in zwei Phasen:

  • Die erste Phase verarbeitet die Tessellationsfaktoren, das Beheben von Rundungsproblemen, die Behandlung sehr kleiner Faktoren, reduzierende und kombinierende Faktoren unter Verwendung von 32-Bit-Gleitkommaarithmetik.
  • In der zweiten Phase werden Punkt- oder Topologielisten basierend auf dem ausgewählten Partitionierungstyp generiert. Dies ist die Kernaufgabe der Tessellatorphase und verwendet 16-Bit-Fraktionen mit Festpunktarithmetik. Die Fixpunktarithmetik ermöglicht die Hardwarebeschleunigung bei akzeptabler Genauigkeit. Bei einem 64 Meter breiten Patch kann diese Genauigkeit beispielsweise Punkte mit einer Auflösung von 2 mm platzieren.
Partitionierungstyp Bereich
fractional_odd [1...63]
fractional_even TessFactor-Bereich: [2..64]
integer TessFactor-Bereich: [1..64]
pow2 TessFactor-Bereich: [1..64]

Domain-Shader Phase

Ein Domänenshader berechnet die Scheitelpunktposition eines unterteilten Punkts im Ausgabepatch. Ein Domänenshader wird einmal pro Ausgabepunkt der Tessellatorphase ausgeführt und verfügt über schreibgeschützten Zugriff auf die UV-Koordinaten der Ausgabe der Tessellatorstufe, den Hull-Shaderausgabepatch und die Ausgabepatchkonstanten des Hull-Shaders, wie im folgenden Diagramm dargestellt.

Diagramm der Domänen-Shader-Phase

Zu den Eigenschaften des Domänenshaders gehören:

  • Ein Domänenshader wird einmal pro Ausgabekoordinate aus der Tessellatorphase aufgerufen.
  • Ein Domänenshader nutzt Ausgabesteuerungspunkte aus der Hull-Shader-Phase.
  • Ein Domänen-Shader gibt die Position eines Scheitelpunkts aus.
  • Eingaben sind die Hull-Shaderausgaben, einschließlich Kontrollpunkte, Patchkonstantendaten und Tessellationsfaktoren. Die Tessellationsfaktoren können die vom festen Funktionstesellator verwendeten Werte sowie die Rohwerte (z. B. vor der Rundung durch ganzzahlige Tessellation) umfassen, was z. B. geomorphing erleichtert.

Nachdem der Domänen-Shader abgeschlossen ist, ist die Tessellation abgeschlossen, und die Pipelinedaten werden mit der nächsten Pipelinephase fortgesetzt (Geometrie-Shader, Pixel-Shader usw.). Ein Geometrie-Shader, der Primitiven mit Adjazenz erwartet (z. B. 6 Scheitelpunkte pro Dreieck), ist ungültig, wenn tessellation aktiv ist (dies führt zu einem nicht definierten Verhalten, über das sich die Debugebene beschwert).

Hier sehen Sie ein Beispiel für einen Domänenshader:

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

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

APIs zum Initialisieren von Tessellationsphasen

Tessellation wird mit zwei neuen programmierbaren Shaderstufen implementiert: einem Hull-Shader und einem Domänenshader. Diese neuen Shaderphasen werden mit HLSL-Code programmiert, der im Shadermodell 5 definiert ist. Die neuen Shaderziele sind: hs_5_0 und ds_5_0. Wie alle programmierbaren Shaderphasen wird Code für die Hardware aus kompilierten Shadern extrahiert, die an die Runtime übergeben werden, wenn Shader mithilfe von APIs wie DSSetShader und HSSetShader an die Pipeline gebunden werden. Zunächst muss der Shader jedoch mithilfe von APIs wie CreateHullShader und CreateDomainShader erstellt werden.

Aktivieren Sie die Tessellation, indem Sie einen Hull-Shader erstellen und ihn an die Hull-Shader-Phase binden (dadurch wird automatisch die Tessellatorphase eingerichtet). Um die endgültigen Vertexpositionen aus den tessellierten Patches zu generieren, müssen Sie auch einen Domänenshader erstellen und ihn an die Domänenshaderphase binden. Sobald tessellation aktiviert ist, müssen die Dateneingaben für die Eingabe-Assembler-Phase Patchdaten sein. Das heißt, die Topologie des Eingabeassens muss eine Patchkonstantentopologie aus D3D11_PRIMITIVE_TOPOLOGY mit IASetPrimitiveTopology festgelegt sein.

Um die Tessellation zu deaktivieren, legen Sie den Hull-Shader und den Domänen-Shader auf NULL fest. Weder die Geometrie-Shader-Phase noch die Stream-Ausgabephase können Hull-Shader-Ausgabepunkte oder Patchdaten lesen.

Vorgehensweise:

Die Dokumentation enthält auch Beispiele für die Initialisierung der Tessellationsphasen.

Element BESCHREIBUNG
Vorgehensweise: Erstellen eines Hull-Shaders
Erstellen Sie einen Hull-Shader.
Vorgehensweise: Entwerfen eines Hull-Shaders
Entwerfen sie einen Rumpf-Shader.
Vorgehensweise: Initialisieren der Tessellatorphase
Initialisieren Sie die Tessellationsphase.
Vorgehensweise: Erstellen eines Domänenshaders
Erstellen Sie einen Domänenshader.
Vorgehensweise: Entwerfen eines Domänenshaders
Erstellen Sie einen Domänenshader.

Grafikpipeline