Displacement Mapping / Curved PN Triangles (Tessellation-Shader-Anwendungen) Hauptseminar SS 2011

Manuel Zimmermann 30. Juni 2011 Fakultät für Informatik und Mathematik Betreuer: Prof. Dr. Alfred Nischwitz

Inhaltsverzeichnis 1 Einleitung..........................................................................................................................................4 2 Grundlagen........................................................................................................................................5 2.1 Baryzentrische Koordinaten......................................................................................................5 2.2 Bézierkurve................................................................................................................................6 3 Tessellation-Shader............................................................................................................................7 3.1 Control Shader...........................................................................................................................8 3.2 Tessellator..................................................................................................................................9 3.3 Evaluation Shader......................................................................................................................9 3.4 Hardware Tessellation anhand eines Beispiels........................................................................10 4 Tessellation Shader-Anwendungen.................................................................................................12 4.1 Displacement Mapping............................................................................................................12 4.2 Curved PN Triangles................................................................................................................16 4.2.1 Bézierpatch für die Geometrie.........................................................................................17 Verwendung im Tessellation Shader....................................................................................18 4.2.2 Bézierpatch für die Normalenvektoren............................................................................19 Verwendung im Tessellation Shader....................................................................................21 4.2.3 Ergebnis der Curved PN-Triangles..................................................................................21 4.2.4 Crack-Free PN Triangles Using Adjacent Edge Normals (PN-AEN)..............................22 Eigene Implementierung von Crack-Free PN Triangles (PN-AEN)....................................23 4.3 Performancevergleich von Tessellation-Shader-Anwendungen..............................................24 5 Ausblick...........................................................................................................................................25

30.06.2011

Kurzbeschreibung: Seit OpenGL 4 und DirectX 11 stehen der 3D-Grafikprogrammierung neue Tessellation Shader zur Verfügung. Sowohl die Funktionsweise dieser Shader als auch typische Anwendungen, die sich mit diesen neuen Shadern realisieren lassen, werden in dieser Arbeit erörtert. So werden Techniken wie Curved Point-Normal Triangles und Displacement Mapping behandelt. Zusätzlich werden diese Techniken bezüglich ihrer Kosten gegenübergestellt.

Manuel Zimmermann

Seite 3 von 27

1 Einleitung

30.06.2011

1 Einleitung Seit jeher wird in der Computergrafik versucht, Modelle möglichst realitätsnah und somit mit einer hohen Detailtreue darzustellen. Um in der Echtzeitcomputergrafik eine ausreichend hohe Bildwiederholungsrate zu erreichen, werden häufig Ansätze wie Bump Mapping oder Parallax Occlusion

Mapping

verwendet.

Dabei

werden

feine

Strukturen

durch

entsprechende

Beleuchtungsverfahren simuliert, ohne dass sie im geometrischen Modell existieren. Diese Techniken haben Probleme mit Selbstverdeckung, Schattenwurf und teilweise auch mit Parallaxeffekten, besonders wenn man die Modelle in einem flachen Winkel betrachtet. Ein weiteres Problem ist, dass die Silhouette des Modells durch die Geometrie bestimmt ist, und somit

Abbildung 1: Bump Mapping, Parallax Occlusion Mapping und Detail Tessellation aus [AMD1 2010] Reliefwirkungen in Flächen durch gerade Silhouetten zunichte gemacht werden (vgl. Abbildung 1). Abhilfe schafft eine feinere Tesselierung der Geometrie, was bis zur Einführung der Tessellation Shader zu einem enormen Mehraufwand beim Rendern geführt hat (vgl. [Recker 2006]). Manuel Zimmermann

Seite 4 von 27

2 Grundlagen

30.06.2011

2 Grundlagen Für das Verständnis der in dieser Arbeit vorgestellten Themen werden Grundlagen benötigt, die im folgenden vorgestellt werden.

2.1 Baryzentrische Koordinaten „Baryzentrische Koordinaten (...) dienen in der linearen Algebra und in der Geometrie dazu, die Lage von Punkten in Bezug auf eine gegebene Strecke, ein gegebenes Dreieck, ein gegebenes Tetraeder oder allgemeiner ein gegebenes Simplex zu beschreiben“ [Wikipedia1 2011]. Sie werden im Tessellation Evaluation Shader bei der Tesselierung eines Dreiecks dazu verwendet, die relative Position eines neuen Vertices zu den Eckpunkten des ursprünglichen Dreiecks anzugeben.

Abbildung 2: Positionsbestimmung innerhalb eines Dreiecks mithilfe von Baryzentrischen Koordinaten aus [Wikipedia2 2011] Die Summe der Baryzentrischen Koordinaten (u,v,w) ergibt immer 1. Sofern die Position innerhalb des Dreiecks ist, nehmen auch u, v und w Werte ≥ 0 an. Um im Evaluation-Shader einen Vektor zu einer solchen Position zu ermitteln, werden die Komponenten der Baryzentrischen Koordinate auf die Vertexpositionsvektoren multipliziert. Der Punkt zwischen den oberen Ecken hat die Baryzentrische Koordinate (0.5,0.5,0). Die oberen Eckpunkte gehen somit in gleichen Teilen in die neue Position ein, der untere Eckpunkt hingegen hat keinen Einfluss auf den neuen Vektor. Der Vektor zu diesem Punkt wäre: P neu=u⋅P linksOben +v⋅P rechtsOben +w⋅P unten P neu=0.5⋅P linksOben+0.5⋅P rechtsOben+0.0⋅P unten

Manuel Zimmermann

Seite 5 von 27

(2.1.1)

2.2 Bézierkurve

30.06.2011

2.2 Bézierkurve Im Kapitel 4.2 Curved PN Triangles werden Bézierdreiecke verwendet. Um die Funktion eines solchen Bézierdreiecks zu verdeutlichen, wird eine Bézierkurve im zweidimensionalen erläutert. Relevant sind für diese Ausarbeitung sowohl quadratische als auch kubische Bézierkurven. Quadratische Bézierkurven besitzen zwischen ihren Eckpunkten einen Stützwert, kubische Bézierkurven besitzen hingegen zwei solcher Stützwerte (s. Abbildung 3).

Abbildung 3: quadratische und kubische Bézierkurve aus [Wikipedia3 2011] Sind sowohl die Eckpunkte als auch die Stützwerte gegeben, so lässt sich der zugehörige Kurvenverlauf mit folgenden Formeln berechnen: Quadratische Bézierkurve: C (t)=(1−t)2 P0 +2 t (1−t) P 1+t 2 P2 , t∈[0,1]

(2.2.1)

Kubische Bézierkurve: C (t)=(1−t )3 P 0+3t (1−t )2 P 1+3 t 2 (1−t )P 2+t 3 P 3, t∈[0,1]

(2.2.2)

Seien nun die Eckpunkte einer solchen Bézierkurve die ursprünglichen Vertices eines groben Modells, und die Seitenkante soll in vier gleichgroße Stücke unterteilt werden. So erhält man für die neu entstandenen Vertices die Positionen C(1/4), C(1/2) und C(3/4).

Manuel Zimmermann

Seite 6 von 27

3 Tessellation-Shader

30.06.2011

3 Tessellation-Shader Die Tessellation Shader sind in OpenGL seit Version 4.0 (Veröffentlichung: 11. März 2010) und in DirectX seit Version 11 (Veröffentlichung: 22. Oktober 2009) verfügbar.

Abbildung 5: DirectX 11 Pipeline aus [Constantin 2010]

Abbildung 4: OpenGL 4 Pipeline aus [Constantin 2010]

Die Funktionalität der neuen Tessellation Shader ist in OpenGL und in DirectX die selbe. Allerdings variiert die Benennung etwas: Der Control Shader in OpenGL wird in DirectX Hull Shader genannt, und der Evaluation Shader in OpenGL ist in DirectX der Domain Shader. In dieser Arbeit werden die Tessellation Shader anhand von OpenGL betrachtet. Für die Hardware Tessellation gibt es drei neue Shader. Zwei davon sind programmierbar während der mittlere, der Tessellator, ähnlich dem Rasterizer ein Fixed Function Shader ist (vgl. [Tessellation 2010])

Manuel Zimmermann

Seite 7 von 27

3.1 Control Shader

30.06.2011

3.1 Control Shader Der Control Shader ist optional. Er wird pro Primitive für jeden Patch einmal aufgerufen (Beispielsweise pro Dreieck 3x, pro Viereck 4x). In ihm wird festgelegt, wie fein ein Patch unterteilt werden soll. Es wird sowohl ein Outer als auch ein Inner Tessellation Level festgelegt. Das Outer Tessellation Level legt fest, in wie viele Teile eine Seitenkante des Patches unterteilt wird. Je nach verwendetem Patch müssen unterschiedlich viele Outer Tessellation Level festgelegt werden, bei einem Dreieck beispielsweise gl_TessLevelOuter[0] bis gl_TessLevelOuter[2]. Diese können Werte von 1 (keine feinere Tesselierung) bis 64 (maximale Tesselierung) annehmen. Werte über 64 werden als 64 interpretiert. Werte ≤ 0 eignen sich für Culling, da diese Patches nicht gerendert werden (vgl. [NVIDIA1 2010] S. 10). Das Inner Tessellation Level legt fest, wie viele ineinander verschachtelte neue Patches entstehen sollen. Auch hier wird mit dem Wert 1 keine feinere Tesselierung erzeugt. Der Wert 2 lässt im Patchinneren einen neuen entarteten Patch, einen Punkt, entstehen, der Wert 3 erzeugt den ersten vollwertigen neuen geschachtelten Patch, der Wert 4 erzeugt innerhalb des ersten geschachtelten Patch wieder einen entarteten Patch. Werte kleiner als 1 werden wie 1 behandelt, Werte größer als 64 wie 64. Die Auswirkungen der Tessellation Level sind in Abbildung 6 verständlich dargestellt. Die dickeren Begrenzungslinien rahmen die ursprünglichen vom OpenGL-Code übergebenen Dreiecke ein, die feineren Begrenzungslinien zeigen die durch die Tessellation Shader verfeinerten und somit neu erzeugten Dreiecke an. Neben den Einstellungen der Tessellation Level können auch die Positionen der Patchvertices verändert werden. Häufig werden die Vertexpositionen ähnlich dem Vertex Shader ausschließlich übergeben. Die Defaultwerte der TessellationLevel können alternativ vom OpenGL-Code aus gesetzt werden, wodurch der Control Shader nicht unbedingt nötig ist (vgl. [NVIDIA1 2010] S. 9).

Manuel Zimmermann

Seite 8 von 27

3.2 Tessellator

30.06.2011

Abbildung 6: Auswirkungen von TessellationLevel aus [Rideout 2010]

3.2 Tessellator Der Tessellator ist ein Fixed Function Shader und somit nicht programmierbar. Er lässt sich allerdings durch die im Tessellation Control Shader gesetzten Werte beeinflussen.

3.3 Evaluation Shader Der Evaluation Shader wird nach dem Tessellator durchlaufen und wird pro Patch für jeden Vertex einmal ausgeführt. In ihm lassen sich die neu erzeugten Vertices manipulieren, sowohl ihre Position als auch beispielsweise ihre Normalenvektoren. Um festzustellen, an welcher Position innerhalb des ursprünglichen Patches sich der neu entstandene Vertex befindet, gibt es die Variable gl_TessCoord. Bei Dreiecken wird die Position mithilfe von Baryzentrischen Koordinaten lokalisiert, bei Vierecken wird angegeben, wie weit der neu entstandene Vertex nach rechts und nach unten vom Originalpatch liegt. Beispiele Dreieck: vec3 gl_TessCoord(0.5, 0.5, 0); Der neue Vertex liegt genau zwischen dem ersten und zweiten ursprünglichen Patchvertex, gegenüber dem dritten Patchvertex (vgl. 2.2 Bézierkurve). Manuel Zimmermann

Seite 9 von 27

3.3 Evaluation Shader

30.06.2011

Beispiel Viereck: vec3 gl_TessCoord(0.3, 0.7, x); Verfolgt man den Vektor vom Vertex links oben nach rechts oben um 30% und ebenso den Vektor vom Vertex links unten nach rechts unten um 30%, und verfolgt die resultierenden Positionen um 70% von oben nach unten, so erreicht man die neue Vertexposition innerhalb des ursprünglichen Patches. Das dritte Vektorelement ist beim Viereck irrelevant.

3.4 Hardware Tessellation anhand eines Beispiels Die Funktionsweise der Tessellation Shader wird anhand des einfachen Beispiels aus [Rideout 2010] und dem zugehörigen Shadercode verdeutlicht. Ein Ikosaeder (Zwanzigflächer) wird im OpenGL-Code über ein Vertex Buffer Object (VBO) an die Rendering Pipeline übergeben. Der Mittelpunkt des Ikosaeders ist der Ursprung, und wie der Name es schon sagt besitzt er zwanzig Seitenflächen in Form von Dreiecken (s. Abbildung 7 links).

Abbildung 7: Ikosaeder mit TessellationLevel 1-6 Im VertexShader werden ausschließlich die Vertexpositionen weitergereicht. layout(vertices = 3) out; in vec3 vPosition[]; out vec3 tcPosition[]; uniform float TessLevelInner; uniform float TessLevelOuter; #define ID gl_InvocationID void main() { tcPosition[ID] = vPosition[ID]; if (ID == 0) { gl_TessLevelInner[0] = TessLevelInner; gl_TessLevelOuter[0] = TessLevelOuter; gl_TessLevelOuter[1] = TessLevelOuter; gl_TessLevelOuter[2] = TessLevelOuter; } }

Codebeispiel 1: Tessellation Control Shader aus [Rideout 2010] Im Tessellation Control Shader werden die Tessellation Level festgelegt. Da dieser Shader pro Patch

Manuel Zimmermann

Seite 10 von 27

3.4 Hardware Tessellation anhand eines Beispiels

30.06.2011

dreimal aufgerufen wird reicht es aus, den Tessellation Level nur einmal Werte zuzuweisen, beispielsweise beim Durchlauf für den ersten Vertex, wenn die InvocationID 0 ist. Außerdem werden die Vertexpositionen unverändert weitergereicht. Die Uniformvariablen für die Tessellation Level werden vom OpenGL-Code übergeben und können per Tastatureingabe verändert werden. layout(triangles, equal_spacing, ccw) in; in vec3 tcPosition[]; out vec3 tePosition; uniform mat4 Projection; uniform mat4 Modelview; void main() { vec3 p0 = gl_TessCoord.x * tcPosition[0]; vec3 p1 = gl_TessCoord.y * tcPosition[1]; vec3 p2 = gl_TessCoord.z * tcPosition[2]; tePosition = normalize(p0 + p1 + p2); }

gl_Position = Projection * Modelview * vec4(tePosition, 1);

Codebeispiel 2: Tessellation Evaluation Shader aus [Rideout 2010] Der Vektor gl_TessCoord beinhaltet in Baryzentrischen Koordinaten (vgl. Kapitel 2.1) die aktuelle Position innerhalb des ursprünglichen Dreiecks. Die Elemente dieses Vektors geben an, mit welchem Anteil die jeweiligen UrsprungsVertices in die neue Position eingehen. So geht beispielsweise bei gl_TessCoord == vec3(0.4, 0.5, 0.1) der erste Vertex (aus tcPosition[0]) mit 40% ein, der zweite Vertex mit 50% und der dritte Vertex mit 10% ein. Die Raumposition des neuen Vertices in der Dreiecksebene erhält man, indem man die Teilvektoren p0 bis p2 aufsummiert. In diesem Beispiel soll der Ikosaeder durch die feinere Tesselierung einer Kugel angenähert werden. Da die Ursprünglichen Ecken alle den Radius 1 vom Ursprung haben und die Summe der Teilvektoren in der jeweiligen Dreiecksebene liegt, muss der aufsummierte Vektor anschließend normalisiert werden. Auf diese Weise haben auch die neu erzeugten Vertices den Abstand 1 vom Ursprung. Nach dem Tessellation-Evaluation-Shader kann optional der Geometry Shader verwendet werden, um für jeden neu entstandenen Subpatch Verrechnungen durchzuführen. So kann beispielsweise für jeden Subpatch eine Flächennormale mithilfe des Kreuzproduktes zweier Seitenkanten berechnet werden. Abschließend wird im Fragment Shader dem jeweiligen Pixel eine Farbe zugeordnet.

Manuel Zimmermann

Seite 11 von 27

4 Tessellation Shader-Anwendungen

30.06.2011

4 Tessellation Shader-Anwendungen Wie in Kapitel 3 ersichtlich können dank der neuen Tessellation Shader Patches stark und effizient verfeinert werden. Das bietet die Möglichkeit, Modelle mit wenig Performanceeinbußen detaillierter zu rendern. Es ist zwar auch möglich schon im OpenGL-Code ein Modell beliebig fein an die Rendering Pipeline zu übergeben, allerdings müssen für die Modelldaten deutlich mehr Speicher bereitgestellt werden, und die Daten müssen vom Arbeitsspeicher an die Grafikkarte übertragen werden. Dieser Flaschenhals wird entlastet, indem stattdessen gröbere Modelle an die Grafikkarte übergeben und erst im Tessellation Shader verfeinert werden. Für diese Modellverfeinerung kommen häufig zwei Techniken zum Einsatz, die im Folgenden vorgestellt werden.

Abbildung 8: (a) grobes Modell, (b) geglättetes Modell (durch z.B. Curved PN Triangles), (c) detaillierteres Modell durch Displacement Mapping aus [NVIDIA2 2011]

4.1 Displacement Mapping Beim Displacement Mapping wird der Rendering Pipeline in einer Textur eine Heightmap übergeben. Aus dieser geht hervor, um welchen Wert Vertices entlang ihrer Normalen verschoben werden sollen.

Manuel Zimmermann

Seite 12 von 27

4.1 Displacement Mapping

30.06.2011

Abbildung 9: Prinzip des Displacement Mapping aus [Dmitriev 2011] Vor der Einführung der Tessellation Shader war Per Vertex Displacement Mapping sehr umständlich, da schon eine sehr fein tesselierte Oberfläche an die Rendering Pipeline übergeben werden musste (vgl. Abbildung 10).

Abbildung 10: Per Vertex Displacement Mapping vor Tessellation Shader aus [Szirmay 2006] Mithilfe der Tessellation Shader kann nun eine sehr grobe Oberflächenstruktur an die Rendering Pipeline übergeben werden. Mit dem Tessellator kann sie feiner tesselliert und anschließend jeder Vertex entsprechend den Texturwerten verschoben werden. Dies wird anhand eines einfachen Beispiels verdeutlicht.

Manuel Zimmermann

Seite 13 von 27

4.1 Displacement Mapping

30.06.2011

Abbildung 11: Displacement Mapping mit Tessellation Level 1, 10, 20 und 64 Als Modell dient eine planare Ebene bestehend aus acht Dreiecken. Diese werden mit dem Tessellator feiner unterteilt. Nach der Tesselierung wird für jeden Vertex (sowohl die Vertices des Eingangsmodells als auch die neu entstandenen Vertices) eine Positionsverschiebung entsprechend dem Texturwert an dem jeweiligen Vertex durchgeführt. Die Texel besitzen Werte von 0.0 (schwarz) bis 1.0 (weiß). Entsprechend den Texelwerten wird auf die Vertexposition ein Offset von 0.0 bis zu 0.1 Einheiten auf die y-Position addiert, also entlang der Normalenvektoren. Bei niedrigen Tessellation Leveln fällt auf, dass der Schriftzug eindeutig nicht lesbar ist, da viel zu wenige Vertices auf dem Schriftzug liegen. Bei maximaler Tessellierung hingegen ist der Schriftzug aufgrund der Geometrieveränderung gut lesbar. Als Normalenvektor wird für jeden neu entstandenen Patch eine Normale durch das Kreuzprodukt zweier Kanten berechnet. Das Resultat ist in Abbildung 11 zu sehen. Eine weitere Verbesserung wird erreicht, indem man das Displacement Mapping mit Normal Mapping kombiniert. Statt wie bei der Height Map eine Positionsveränderung wird hierbei pro Texel eine Normale gespeichert. Die Normal Map kann leicht aus der Height Map berechnet werden. Hierbei wird für jedes Texel (außer die Randtexel) die Steigung bezüglich ihrer benachbarten Texel berechnet und eine gemittelte Normale ermittelt. Manuel Zimmermann

Seite 14 von 27

4.1 Displacement Mapping

30.06.2011

Abbildung 12: Displacement Mapping kombiniert mit Normal Mapping Durch die Kombination von Displacement Mapping und Normal Mapping hat man zum einen durch das Displacement Mapping ein viel feineres und detaillierteres geometrisches Modell, zum anderen sind die Schattierungen durch das Normal-Mapping sehr gut. Man hat allerdings nicht die Nachteile wie bei Bump Mapping oder Parallax Occlusion Mapping, dass Silhouetten fehlerhaft sind oder Parallaxeffekte auftreten (vgl. Kapitel 1). Laut [Dmitriev 2011] (S. 3) lässt sich mit diesem Verfahren ohne merkliche optische Unterschiede ein bis zu 50fache Performancesteigerung erzielen (je nach Grafikkarte). Im Programmbeispiel PNPatches von NVIDIA wird bei eigenen Messungen mit dem vorab fein tesselierten Modell eine Bildwiederholrate von 16fps erzielt. Bei Verwendung des groben Modells in Kobination mit den Tessellation Shadern sowie Displacement Mapping und Normal Mapping wird eine Renderrate von 107fps erzielt, also fast das siebenfache. Zusätzlich ist die Variante mit Displacement-Mapping deutlich Speicherschonender, und in Verbindung mit Level Of Detail oder Culling können diese Resultate weiter verbessert werden.

Manuel Zimmermann

Seite 15 von 27

4.1 Displacement Mapping

30.06.2011

Abbildung 13: Monster grob, Displacement Map, Normal Map, Monster detailliert aus Programmbeispiel PNPatches von NVIDIA

4.2 Curved PN Triangles Die Theorie von Curved Point-Normal Triangles (kurz: Curved PN Triangles) wurde schon 2001 von Alex Vlachos et al. in [Vlachos 2001] veröffentlicht. Zu dieser Zeit war an effiziente Hardware Tessellation noch nicht zu denken, allerdings eignet sich das Verfahren auch um offline grobe und somit kantenreiche Modelle dahingehend zu verfeinern, dass sie geometrisch runder werden und durch die Beleuchtungsrechnung auch runder wirken. Für Curved PN Triangles werden Bézierpatches (s. Kapitel 2.2 Bézierkurve) verwendet, sowohl für die Geometrie, als auch für die Berechnung der Normalenvektoren. Für die Geometrie werden kubische Bézierpatches verwendet, für die Normalen hingegen quadratische Bézierpatches.

Manuel Zimmermann

Seite 16 von 27

4.2 Curved PN Triangles

30.06.2011

Abbildung 15: Kubischer Bézierpatch für die Geometrie aus [Vlachos 2001]

Abbildung 14: Quadratischer Bézierpatch für die Normalen aus [Vlachos 2001]

Curved PN Triangles haben als Grundlage ein grobes Modell, das pro Vertex genau einen Normalenvektor besitzt. Betrachtet man also zunächst nur ein Dreieck, so hat man für alle Eckpunkte sowohl die Raumkoordinate wie auch jeweils den Normalenvektor. Mit diesen Informationen lassen sich nun die Stützpunkte des Bézierpatches bestimmen. 4.2.1 Bézierpatch für die Geometrie Zunächst werden für jede Seitenkante zwei Stützpunkte berechnet. Für die Berechnung von b 210 wird die Kante von P1 nach P2 um 1/3 verfolgt. Da zusätzlich Oberflächeninformation in den neuen Stützwert eingehen soll, wird die Normale von b 300 mit eingerechnet. Dazu wird der Punkt ermittelt, der auf der Ebene, welche senkrecht zur Normalen N 1 und durch den Punkt P1 verläuft, liegt und den geringsten Abstand zum Punkt auf der Seitenkante hat (vgl. Abbildung 16). Für die Berechnung

Abbildung 16: Berechnung eines Stützwertes aus [Vlachos 2001] von b120 wird analog die Normale N2 verwendet. Es ergeben sich folgende Formeln:

Manuel Zimmermann

Seite 17 von 27

4.2 Curved PN Triangles

30.06.2011

b300 =P 1 b030 =P 2 b003 =P 3 wij =( P j−P i )⋅N i ∈ℝ ,'⋅' ist das Skalarprodukt b 210=(2 P 1+P 2 −w 12 N 1) /3 b 210=(2 P 2 +P 2−w21 N 2)/3 b 210=(2 P 2 +P 3−w 23 N 2)/3 b 210=(2 P 3+ P 2−w 32 N 3 )/3 b 210=(2 P 3+ P1−w31 N 3)/3 b 210=(2 P 1+P 3−w13 N 1)/3 E =(b 210 +b120 +b 021+b012 +b102 +b 201 )/6 V =( P1+ P 2+P 3)/3 b111 =E+( E−V ) /2

(4.2.1)

Berechnung der Geometriestützwerte aus [Vlachos 2001] Mit diesen Stützwerten lässt sich für jeden neuen Vertex innerhalb des groben Dreiecks eine neue Raumposition ermitteln: b( u , v , w)=b300 w3+b030 u3+b003 v3 +b 210 3 w 2 u+b 120 3 w u 2+b201 3 w 2 v +b 021 3 u2 v+b102 3 w v 2+b012 3 u v 2 +b111 6 w u v

(4.2.2)

Berechnung der Raumposition für neuen Vertex aus [Vlachos 2001] Verwendung im Tessellation Shader

Die Berechnung der Stützwerte wird im Control-Shader durchgeführt. Da es ausreicht, die Stützwerte pro Patch zu berechnen, wird der Outputvariablen der Qualifizierer 'patch out' vorangestellt, und die Berechnung wird nur bei einer InvocationID durchgeführt. … patch out vec3 b210; … void main() { if(ID==0){ … b210=(2.0*P1+P2-w(P1,P2,N1)*N1)/3.0; …

Codebeispiel 3: Ausschnitt aus Control Shader zur Berechnung der Geometrie-Stützwerte Nachdem der Tessellator durchlaufen wurde, wird im Evaluation Shader für jeden Vertex die neue Position im Raum berechnet, wobei sich die Raumposition der ursprünglichen Eckvertices mit der Manuel Zimmermann

Seite 18 von 27

4.2 Curved PN Triangles

30.06.2011

Formel 4.2.2 nicht ändert. … patch in vec3 b210; #define U gl_TessCoord.y #define V gl_TessCoord.z #define W gl_TessCoord.x … tePosition = b300 * pow(W,3.0) + b030 * pow(U,3.0) + b210 * 3.0 * pow(W,2.0) * U + b120 * + b201 * 3.0 * pow(W,2.0) * V + b021 * + b102 * 3.0 * W * pow(V,2.0) + b012 * + b111 * 6.0 * W * U * V; …

+ b003 * pow(V,3.0) 3.0 * W * pow(U,2.0) 3.0 * pow(U,2.0) * V 3.0 * U * pow(V,2.0)

Codebeispiel 4: Ausschnitt aus Evaluation Shader zur Berechnung der neuen Vertexpositionen Mit dieser Verfeinerung wird die Geometrie des anfangs groben Modells deutlich verfeinert. Allerdings ist die Schattierung durch die Beleuchtungsrechnung bisher noch unverändert, die Normalen der Eckpunkte werden lediglich linear interpoliert (s. Abbildung 17 (c) ).

Abbildung 17: (a) Grobes Modell, (b) mit Gouraud Shader gerendertes grobes Modell, (c) Geometrieverfeinerung angewendet auf grobes Modell, (d) sowohl Geometrie- als auch Normalen-Bézierpatch auf grobes Modell angewendet, aus [Vlachos 2001] 4.2.2 Bézierpatch für die Normalenvektoren Wie in Abbildung 17 zu sehen ist, verbessert die Verwendung eines Bézierpatch in Kombination mit feinerer Tessellierung vor allem die Silhouette des Modells. Um zusätzlich weichere Farbverläufe und somit einen runderen Eindruck durch die Beleuchtungsrechnung zu erhalten, wird ein weiterer Bézierpatch für die Normalenrechnung verwendet. Im Gegensatz zur Geometrie wird hierbei auf einen quadratischen Bézierpatch zurückgegriffen.

Manuel Zimmermann

Seite 19 von 27

4.2 Curved PN Triangles

30.06.2011

Abbildung 18: Abweichung von linearer Interpolation und realem Normalenverlauf aus [Vlachos 2001]

Abbildung 19: Berechnung eines Stützwertes des Normalen-Bézierpatches aus [Vlachos 2001]

Lineare Interpolation von Normalenvektoren ist wie in Abbildung 18 oben zu sehen teilweise nicht der Geometrie entsprechend. Wenn die Geometrie wie in der Abbildung wie eine sinusähnliche Kurve verläuft, so müsste der Normalenvektor zwischen Start- und Endpunkt wie in Abbildung 19 gespiegelt werden. Dieses Vorgehen würde dann keinen Sinn machen, wenn zwischen Start und Endpunkt ein hochfrequenter Geometrieverlauf vorliegen würde. Da die Geometrie allerdings durch einen kubischen Patch vorgegeben ist, passt diese Berechnung der Normaenstützwerte sehr gut zum Geometrieverlauf. Die Stützwerte für die Normalenvektoren lässt sich wie folgt berechnen: n 200 =N 1 n 020 =N 2 n 002= N 3 ( P −P i)⋅(N i+ N j ) vij =2 j ( P j −P i)⋅(P j− Pi ) n 110=h110 /∥h 110∥, h110 = N 1 +N 2−v 12 (P 2 −P 1) n 011=h011 /∥h 011∥, h011 =N 2+N 3−v 23 ( P3− P 2) n 101=h101 /∥h101∥, h101 =N 3+N 1−v 31( P1− P3 )

(4.2.3)

Berechnung der Normalenstützwerte aus [Vlachos 2001] Mit diesen Stützwerten lässt sich nun für jede Position im Dreieck ein Normalenvektor ermitteln:

Manuel Zimmermann

Seite 20 von 27

4.2 Curved PN Triangles

30.06.2011 b( u , v , w)=b300 w3+b030 u3+b 003 v 3 +b 210 3 w 2 u+b 120 3 w u 2+b201 3 w 2 v +b 021 3 u2 v+b102 3 w v 2+b012 3 u v 2 +b111 6 w u v

(4.2.4)

Berechnung der Normale für neuen Vertex aus [Vlachos 2001] Verwendung im Tessellation Shader

Der Bézierpatch für die Normanen wird analog zum Bézierpatch für die Geometrie verwendet. Zunächst werden die Stützpunkte im Control Shader berechnet. Auch hier werden die Stützwerte nur einmal pro Patch ermittelt. … patch out vec3 n110; … if (ID == 0) { … n110 = normalize( N1 + N2 - v(P1, P2, N1, N2) * (P2 - P1) ); …

Codebeispiel 5: Ausschnitt aus Control Shader zur Berechnung der Normalen-Stützwerte Um die Geschwindigkeit zu steigern, kann man die Berechnung der Stützpunkte auf verschiedene Threads verteilen, indem man sie bei unterschiedlichen InvocationID durchführt. Im Evaluation Shader kann anschließend für jeden Vertex der zugehörige Normalenvektor ermittelt werden. … patch in vec3 n110; #define U gl_TessCoord.y #define V gl_TessCoord.z #define W gl_TessCoord.x … teNormal = n200 * pow(W,2.0) + n020 * pow(U,2.0) + n002 * pow(V,2.0) + n110 * W * U + n011 * U * V + n101 * W * V; …

Codebeispiel 4: Ausschnitt aus Evaluation Shader zur Berechnung der neuen Vertexnormalen 4.2.3 Ergebnis der Curved PN-Triangles Wie in Abbildung 17 gut zu sehen ist kann ein grobes Modell mit diesem Verfahren optisch stark verbessert werden. Das Verfahren bietet sich an um grobe Modelle aus bestehenden Datensätzen, wie älteren Computerspielen, zu verwenden, ohne das Modell vorab überarbeiten zu müssen. Dadurch werden Kanten an Patchübergängen abgerundet und das Modell wirkt dadurch realistischer. Allerdings wird es mit diesem Verfahren nicht möglich sein, Details wie Manuel Zimmermann

Seite 21 von 27

4.2 Curved PN Triangles

30.06.2011

Muskelstränge die sich nicht aus den Modelldaten extrahieren lassen, zu erstellen. Dafür sind zusätzliche Daten wie beispielsweise eine Height- und eine Normalmap beim Displacement Mapping (vgl. Kapitel 4.1) nötig. 4.2.4 Crack-Free PN Triangles Using Adjacent Edge Normals (PN-AEN) Das vorgestellte Verfahren der Curved PN-Triangles funktioniert nur dann fehlerlos, wenn das Eingabemodell pro Vertex genau einen Normalenvektor besitzt. Werden hingegen für die angrenzenden Patches unterschiedliche Normalenvektoren für den gleichen Vertex verwendet, um beispielsweise scharfe Kanten zu erzeugen, so entstehen bei Verwendung von Curved PN Triangles Lücken im Modell. Das kommt daher, dass in die Stützpunktberechnung entlang einer Kante die Normalen der Vertices an den Kantenenden mit eingehen. Berechnet man die Stützwerte für benachbarte Primitive mit zwei unterschiedlichen Normalenvektoren, so ergibt sich für jede Primitive ein anderer Geometriestützwert, wodurch zwischen den Primitiven Lücken entstehen.

Abbildung 20: Lücken durch patchabhängige Normalen für einen Vertex aus [McDonald 2010] Schon in [Vlachos 2001] wurde diese Problematik angesprochen. Ein dort genannter Lösungsansatz ist, sehr schmale Patches an solchen Kanten einzufügen (vgl. Abbildung 21). Auf diese Weise kann weiterhin pro Vertex genau ein Normalenvektor verwendet werden, allerdings ist es dabei nötig, das Modell vorab zu modifizieren. In [McDonald 2010] wird hingegen ein Ansatz verfolgt, welcher wie auch das native Curved PN Triangle keine Vorverarbeitung der Modelldaten benötigt. Bei diesem PN-AEN-Ansatz werden für jede Kante in einem zusätzlichen Indexbuffer die Indices benachbarter Vertices gespeichert. Auf diese Weise kann im Shader auf die Normalenvektoren der benachbarten Vertices zugegriffen werden. Sofern sich diese nicht von den eigenen Normalenvektoren unterscheiden kann der Algorithmus der Curved PN Triangles unverändert angewendet werden. Manuel Zimmermann

Seite 22 von 27

4.2 Curved PN Triangles

30.06.2011

Abbildung 21: Problem von scharfen Kanten bei Curved PN Triangles aus [Vlachos 2001]

Abbildung 22: Index Buffer mit Information über benachbarte Kanten aus [McDonald 2010]

Wenn sich die Normalen der angrenzenden Kanten hingegen unterscheiden, berechnet man zunächst wie bisher die Stützpunkte. Anschließend werden die Stützpunkte, die entlang einer solchen Problemkante verlaufen, gemittelt. Dadurch haben die angrenzenden Patches wieder die gleichen Kantenstützpunkte für die Geometrie, und sind somit wieder lückenlos. Für die Normalenstützpunkte wird hingegen keine Anpassung vorgenommen. So entsteht bei der Beleuchtungsrechnung die Wirkung einer scharfen Kante (s. [McDonald 2010]). Eigene Implementierung von Crack-Free PN Triangles (PN-AEN)

Um die Auswirkungen des in [McDonald 2010] beschriebenen Algorithmus genauer zu untersuchen, wurde sowohl Curved PN Triangles als auch eine vereinfachte Form des Crack-Free PN Triangles implementiert. Als Modell dient eine einfache unten offene Pyramide. An der Spitze hat jedes Dreieck den Normalenvektor (0,1,0). Der Normalenvektor der unteren Vertices zeigt jeweils zu 70% entlang der Koordinatenachse auf die seine Fläche zeigt sowie 30% entlang der Koordinatenachse ihres direkten Nachbarn (bspw. Normalenvektor links unten: (-0.3, 0, 0.7) ).

Abbildung 23: Pyramide mit verschiedenen Normalenvektoren für die unteren Vertices, Curved PN Triangles (b und c) sowie Crack-Free PN Triangles (d und e) Wird der Algorithmus der Curved PN Triangles auf dieses Modell angewendet, so entstehen bei den Patchübergängen Lücken. Werden hingegen die Stützpunkte aneinanderliegender Kanten wie beim Algorithmus der Crack-Free PN Triangles gemittelt, so resultiert ein lückenloses Modell, bei dem

Manuel Zimmermann

Seite 23 von 27

4.2 Curved PN Triangles

30.06.2011

aber wie gewünscht sowohl geometrisch als auch durch die Beleuchtungsrechnung Kanten sichtbar sind.

4.3 Performancevergleich von Tessellation-Shader-Anwendungen Wie schon beschrieben ist es effizienter, ein grobes Modell mit Displacement Mapping zu kombinieren, anstatt ein vorab sehr feines Modell an die Rendering Pipeline zu übergeben. Welche Kosten bei den verschiedenen Techniken zusätzlich entstehen, ist der Tabelle in Abbildung 24 zu entnehmen. Flat Dicing, also die Verfeinerung ohne zusätzliche Vertexmanipulation ist nahezu kostenfrei, allerdings hat diese Technik allein keinen Nutzen, sondern stellt lediglich die Basis für Techniken wie beispielsweise das Displacement Mapping dar. Auch Curved PN Triangles sowie PN-AEN sind durch die gute Parallelisierbarkeit ebenso wie das Displacement Mapping sehr effizient zu nutzen.

Abbildung 24: Vergleich von verschiedenen Tessellation-Techniken aus [McDonald 2011] Ein großer Vorteil der Tessellation Shader ist die mittlerweile sehr große Anzahl von Rechenwerken auf Grafikkarten. Mit mehreren hundert Kernen können Berechnungen im Shader sehr stark parallelisiert werden. So können Vertexberechnung im Evaluation Shader ein verschiedene Threads aufgeteilt werden. Das ist auch der große Vorteil der Tessellation Shader gegenüber dem schon länger verfügbaren Geometry Shader. Auch mit ihm ist theoretisch eine Netzverfeinerung sowie eine Manipulation neu entstandener Vertices möglich. Allerdings wird das bei höheren Tessellation Leveln schnell unübersichtlich, und es fehlt die Parallelisierung, wodurch es sehr ineffizient wird (vgl. Abbildung 25).

Manuel Zimmermann

Seite 24 von 27

5 Ausblick

30.06.2011

Abbildung 25: Geometry Shader gegenüber Tessellation Shader aus [Tatarinov 2008]

5 Ausblick Durch die neuen Tessellation Shader stehen der 3D-Grafikprogrammierung neue Möglichkeiten zur Verfügung, Geometrie auf der Grafikkarte zu verfeinern und anschließend zu manipulieren. Die in dieser Arbeit vorgestellten Techniken diese Möglichkeiten zu nutzen sind nur zwei Ansätze, es gibt allerdings noch viele mehr. So wird beispielsweise in [Engel 2010] beschrieben, wie der für Beleuchtungsrechnung bekannte Phong Shader mithilfe feinerer Tesselierung erweitert werden kann, so dass auch die Silhouetten durch verbesserte Geometrie verbessert werden. Auch in der aktuellen Veröffentlichung [Engel 2011] werden einige Themen behandelt, die den Tessellator nutzen. Beispielsweise werden für dynamisch erzeugte Falten zur Darstellung von Emotionen die entsprechenden Bereiche ähnlich einer Displacement Map mit einer Wringkle Map verarbeitet. Daher darf man sich zukünftig auf viele Verbesserungen durch detailliertere Modelle im Bereich der Computergrafik freuen.

Manuel Zimmermann

Seite 25 von 27

5 Ausblick

30.06.2011

Literaturverzeichnis AMD1 2010: AMD Direct3D 11 Sample, Detail Tessellation 11, 2010, http://developer.amd.com/downloads/DetailTessellation11.zip Recker 2006: Ruth-Maria Recker, Displacement Mapping, 2006 Wikipedia1 2011: Wikipedia, Baryzentrische Koordinaten, Stand: 29.6.2011, http://de.wikipedia.org/wiki/Baryzentrische_Koordinaten Wikipedia2 2011: Wikipedia, Barycentric coordinate system (mathematics), Stand: 29.6.2011, http://en.wikipedia.org/wiki/Barycentric_coordinates_(mathematics) Wikipedia3 2011: Wikipedia, Bézierkurve, Stand: 29.6.2011, http://de.wikipedia.org/wiki/Bézierkurve Constantin 2010: Link Alexis Constantin, Real-Time GPU Tessellation, 2010 Tessellation 2010: Barthold Lichtenbelt et al., ARB_tessellation_shader, 2010, http://www.opengl.org/registry/specs/ARB/tessellation_shader.txt NVIDIA1 2010: , OpenGL 4.0 Tessellation For Professionnal Applications, 2010 Rideout 2010: Philip Rideout, Triangle Tessellation with OpenGL 4.0, 2010, http://prideout.net/blog/?p=48 NVIDIA2 2011: , DirectX 11 Tessellation, Stand: 29.6.2011, http://www.nvidia.com/object/tessellation.html Dmitriev 2011: Kirill Dmitriev, PN-Patches, 2011 Szirmay 2006: László Szirmay-Kalos, Tamás Umenhoffer, Displacement Mapping on the GPU State of the Art, 2006 Vlachos 2001: Alex Vlachos, Jörg Peters, Chas Boyd, Jason L. Mitchell , Curved PN triangles, 2001 McDonald 2010: John McDonald, Mark Kilgard, Crack-Free Point-Normal Triangles Using Adjacent Edge Normals, 2010 McDonald 2011: John McDonald, Tessellation on Any Budget, 2011 Tatarinov 2008: Andrei Tatarinov, Instanced Tessellation in DirectX10, 2008 Engel 2010: edited by Wolfgang Engel, GPU Pro, 2010 Engel 2011: edited by Wolfgang Engel, GPU Pro², 2011

Manuel Zimmermann

Seite 26 von 27

5 Ausblick

30.06.2011

Abbildungsverzeichnis Abbildung 1: Bump Mapping, Parallax Occlusion Mapping und Detail Tessellation aus [AMD1 2010].....................................................................................................................................................4 Abbildung 2: Positionsbestimmung innerhalb eines Dreiecks mithilfe von Baryzentrischen Koordinaten aus [Wikipedia2 2011].....................................................................................................5 Abbildung 3: quadratische und kubische Bézierkurve aus [Wikipedia3 2011]....................................6 Abbildung 4: OpenGL 4 Pipeline aus [Constantin 2010].....................................................................7 Abbildung 5: DirectX 11 Pipeline aus [Constantin 2010]....................................................................7 Abbildung 6: Auswirkungen von TessellationLevel aus [Rideout 2010].............................................9 Abbildung 7: Ikosaeder mit TessellationLevel 1-6.............................................................................10 Abbildung 8: (a) grobes Modell, (b) geglättetes Modell (durch z.B. Curved PN Triangles), (c) detaillierteres Modell durch Displacement Mapping aus [NVIDIA2 2011].................................12 Abbildung 9: Prinzip des Displacement Mapping aus [Dmitriev 2011]............................................13 Abbildung 10: Per Vertex Displacement Mapping vor Tessellation Shader aus [Szirmay 2006]......13 Abbildung 11: Displacement Mapping mit Tessellation Level 1, 10, 20 und 64...............................14 Abbildung 12: Displacement Mapping kombiniert mit Normal Mapping.........................................15 Abbildung 13: Monster grob, Displacement Map, Normal Map, Monster detailliert aus Programmbeispiel PNPatches von NVIDIA......................................................................................16 Abbildung 14: Quadratischer Bézierpatch für die Normalen aus [Vlachos 2001].............................17 Abbildung 15: Kubischer Bézierpatch für die Geometrie aus [Vlachos 2001]..................................17 Abbildung 16: Berechnung eines Stützwertes aus [Vlachos 2001]....................................................17 Abbildung 17: (a) Grobes Modell, (b) mit Gouraud Shader gerendertes grobes Modell, (c) Geometrieverfeinerung angewendet auf grobes Modell, (d) sowohl Geometrie- als auch Normalen-Bézierpatch auf grobes Modell angewendet, aus [Vlachos 2001]....................................19 Abbildung 18: Abweichung von linearer Interpolation und realem Normalenverlauf aus [Vlachos 2001]...................................................................................................................................................20 Abbildung 19: Berechnung eines Stützwertes des Normalen-Bézierpatches aus [Vlachos 2001].....20 Abbildung 20: Lücken durch patchabhängige Normalen für einen Vertex aus [McDonald 2010]....22 Abbildung 21: Problem von scharfen Kanten bei Curved PN Triangles aus [Vlachos 2001]...........23 Abbildung 22: Index Buffer mit Information über benachbarte Kanten aus [McDonald 2010]........23 Abbildung 23: Pyramide mit verschiedenen Normalenvektoren für die unteren Vertices, Curved PN Triangles (b und c) sowie Crack-Free PN Triangles (d und e)...........................................................23 Abbildung 24: Vergleich von verschiedenen Tessellation-Techniken aus [McDonald 2011]...........24 Abbildung 25: Geometry Shader gegenüber Tessellation Shader aus [Tatarinov 2008]....................25

Manuel Zimmermann

Seite 27 von 27