Echtzeitfähige Simulation von Wasser auf Grafikhardware
Transcription
Echtzeitfähige Simulation von Wasser auf Grafikhardware
Technische Universität München Fakultät für Informatik Diplomarbeit Echtzeitfähige Simulation von Wasser auf Grafikhardware Thomas Schiwietz Aufgabensteller: Prof. Dr. Rüdiger Westermann Betreuer: Dipl.-Inf. Jens Krüger Abgabedatum: Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 2 von 99 Ich versichere hiermit, dass ich diese Diplomarbeit selbständig verfasst und nur die angegebenen Quellen und Hilfsmittel verwendet habe. Datum Unterschrift Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 3 von 99 Echtzeitfähige Simulation von Wasser auf Grafikhardware 1. Einleitung..........................................................................................5 1.1. Das Potential moderner Grafikkarten............................................... 5 1.1.1. 1.1.2. 1.1.3. 1.2. Die feste Pipeline herkömmlicher Grafikkarten ..................................... 5 Freie Programmierbarkeit durch Vertex- und Pixel-Shader................... 6 Neue Anwendungsfelder für Grafikkarten mit Shadern ......................... 7 Ziele dieser Diplomarbeit................................................................... 8 2. Simulation von Wasseroberflächen ...............................................9 2.1. Die Wellengleichung .......................................................................... 9 2.1.1. 2.1.2. 2.1.3. 2.1.4. 2.1.5. 2.1.6. 2.2. Modellierung des Lichts .................................................................. 19 2.2.1. 2.2.2. 2.2.3. 2.2.4. 2.3. Die partielle Differentialgleichung.......................................................... 9 Diskretisierung der Differentialgleichung ............................................. 11 Diskretisierung der Membran .............................................................. 13 Numerische Stabilität .......................................................................... 14 Dämpfung ........................................................................................... 15 Einschläge von Objekten auf die Wasseroberfläche ........................... 16 Berechnung der Normalen der Wasseroberfläche .............................. 19 Lichtfarbe und Lichtintensität (Phong-Illumination-Model)................... 22 Lichtreflexion ....................................................................................... 25 Lichtbrechung...................................................................................... 28 Implementierung .............................................................................. 31 2.3.1. 2.3.2. 2.3.3. Lösung der Wellengleichung in Grafikhardware.................................. 31 Zweidimensionale Darstellung ............................................................ 33 Dreidimensionale Darstellung ............................................................. 35 3. Simulation von Fluiden..................................................................37 3.1. Die inkompressiblen Navier-Stokes-Gleichungen ........................ 37 3.2. Diskretisierung ................................................................................. 42 3.2.1. 3.2.2. 3.2.3. 3.2.4. 3.2.5. 3.3. Das Gebiet .......................................................................................... 42 Hindernisse ......................................................................................... 44 Die Zeit, das Stabilitätskriterium.......................................................... 45 Die Impulsgleichung............................................................................ 46 Die Kontinuitätsgleichung.................................................................... 49 Der Algorithmus ............................................................................... 50 3.3.1. 3.3.2. 3.3.3. Die Berechnung der Diffusion und Konvektion.................................... 50 Die Berechnung des Drucks................................................................ 51 Der gesamte Algorithmus.................................................................... 54 Echtzeitfähige Simulation von Wasser auf Grafikhardware 3.4. Implementierung .............................................................................. 55 3.4.1. 3.4.2. 3.4.3. 3.4.4. 3.4.5. 3.4.6. 3.4.7. 3.5. Texturen .............................................................................................. 55 Vertex-Buffer ....................................................................................... 57 Die Shader-Programme ...................................................................... 59 Die Rendering Pipeline ....................................................................... 62 Ein Beispiel Shader in HLSL: ImpulseF .............................................. 64 Visualisierung...................................................................................... 69 Geschwindigkeitsmessungen.............................................................. 76 Simulierte Probleme......................................................................... 79 3.5.1. 3.5.2. 3.5.3. 3.5.4. 3.5.5. 3.6. Seite 4 von 99 Nischenströmung ................................................................................ 79 Kármánsche Wirbelstraße................................................................... 81 Stufenströmung................................................................................... 83 Strömung über ein Auto ...................................................................... 85 tum3D-Logo ........................................................................................ 86 Erweiterungen .................................................................................. 87 3.6.1. 3.6.2. 3.6.3. 3.6.4. 3.6.5. 3.6.6. 3.6.7. Visualisierung...................................................................................... 87 Stromfunktion ...................................................................................... 87 Hinderniseditor .................................................................................... 88 Numerische Fehler.............................................................................. 88 Freie Randwertprobleme..................................................................... 89 Temperatur (Energietransport)............................................................ 89 Dreidimensionale Navier-Stokes-Gleichungen.................................... 90 4. Fazit .................................................................................................92 Literaturverzeichnis .............................................................................93 Abbildungsverzeichnis ........................................................................95 Stichwortverzeichnis ...........................................................................97 Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 5 von 99 1. Einleitung 1.1. Das Potential moderner Grafikkarten In den letzten Jahren gab es große Fortschritte in der Entwicklung der Grafikkarten. Neben immer höheren Dreiecksdurchsatzraten, reicht auch der Video-Speicher schon fast an die gleiche Größenordnung wie der Hauptspeicher des Systems heran. Die interessantesten Neuerungen sind seit den letzten Kartengenerationen vor allem die so genannten Vertex- und Pixel-Shader. Shader sind freiprogrammierbare Prozessoren, die Teil der GPU (Graphical Processing Unit) sind. Bisher war die GPU fest verdrahtet, was zur Folge hatte, dass der eingehende Datenstrom aus Vektorund Texturdaten fest vorgegebene Wege durchlief. 1.1.1. Die feste Pipeline herkömmlicher Grafikkarten Die wesentlichen Stationen der festen Pipeline sehen typischerweise wie folgt aus: In der Geometrieverarbeitungsstufe werden auf die dreidimensionalen Vektoren die Welt- und Kameramatrix multipliziert und schließlich auf ein zweidimensionales Raster, den Bildschirmspeicher, projiziert. Im Anschluss wird die zweidimensionale Geometrie gerastert. Pro Pixel werden Texturzugriffe und Lichtberechnungen durchgeführt, die nur sehr eingeschränkt programmierbar sind. Dazu stehen wenige einfache Operationen wie Addition oder Multiplikation zweier Texturen zur Verfügung. Abbildung 1: Schematischer Aufbau der Hardware Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 6 von 99 1.1.2. Freie Programmierbarkeit durch Vertex- und Pixel-Shader Mit Hilfe der Shader kann die GPU einer modernen Grafikkarte frei programmiert werden. Es gibt zwei Arten von Shader, zum Einen die Vertex-Shader, die die Geometrieverarbeitung programmierbar machen, und zum Anderen die Pixel-Shader, die die Rasterung der Pixel, der einzelnen Fragmente, programmierbar machen. Vertex-Shader sind auf die Berechnung geometrischer Funktionen spezialisiert. Dazu zählen beispielsweise mathematische Operationen wie das Produkt aus Matrix und Vektor, Skalarprodukte, Vektorprodukte, Längenbestimmung und Normalisierung von Vektoren. Ebenso können viele trigonometrische Funktionen wie Sinus, Cosinus oder die Exponentialfunktion berechnet werden. Im Gegensatz zum Hauptprozessor stehen für die meisten dieser Operationen eigene Hardwarebausteine zur Verfügung, die die Ausführung in einem Takt vollziehen können. Typische Einsatzgebiete von Vertex-Shadern sind neben der freien Verformung von Geometrien, Beleuchtungsund Schattenberechnungen. Pixel-Shader sind dazu da, Texturdaten zu laden und zu verarbeiten. Als Ergebnis eines Pixel-Shaders werden eine Farbe und ein Tiefenwert zurückgegeben, die ein Bildpunkt annehmen soll. Moderne Grafikkarten können bis zu acht Texturen pro Dreieck auslesen und verarbeiten. In den Texturen können Grafiken, Lichtverteilungen, Oberflächennormalen oder beliebige Daten abgespeichert werden, die zur Berechnung einer realistischen Oberfläche notwendig sind. Durch die freie Programmierbarkeit der Pixel-Shader können die Texturen an jeder Stelle ausgelesen und mit Hilfe von Registern, wie man es auf dem Hauptprozessor gewohnt ist, zwischengespeichert werden. Darauf können alle grundlegenden mathematischen Operationen angewendet werden um so beispielsweise aufwändige Lichtmodelle, wie das PhongShading-Model, im Pixel-Shader zu berechnen. Abbildung 2: Aufbau einer Grafikkarte Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 7 von 99 1.1.3. Neue Anwendungsfelder für Grafikkarten mit Shadern Eigentlich wurden die Vertex- und Pixel-Shader dazu entwickelt, flexible geometrische Modelle zu programmieren und schwer darstellbare Oberflächen optisch wiederzugeben, wie zum Beispiel Rost, der sich im Lauf der Zeit in eine Autotür frisst. In der Spieleindustrie werden diese Eigenschaften ausgenutzt. Die flexible Programmierbarkeit der Shader lässt sich auch zweckentfremden, um beliebige mathematische Probleme von der Grafikkarte berechnen zu lassen. Sobald man das Ziel eines Renderingpasses nicht mehr auf die Bildschirmausgabe, sondern auf eine Textur im Video-Speicher setzt, lassen sich die Texturwerte als Variablen eines Arrays verwenden. Durch Hintereinanderausführung mehrerer Renderingpasses können Texturen in mehreren Stufen als Lese- und Schreibziele verwendet werden. In den Projekten dieser Diplomarbeit wurde diese Fähigkeit der Pixel-Shader ausgenutzt. Abhängig von der GPU lassen sich Texturen mit Fließkommawerten nach dem IEEE float – Standard anlegen und für sehr genaue Berechnung verwenden. Zurzeit unterstützen die großen Kartenhersteller Fließkommatexturen zwischen 16- und 32-bit pro Komponente. Dies reicht zwar nicht an die Genauigkeit der 64-bit Fließkommaeinheit im Hauptprozessor heran, lässt sich aber für erste Versuche verwenden. Bevor man diese Idee weiterverfolgt, stellt sich die Frage, aus welchem Grund man denn eine Grafikkarte zur Berechnung von grafikfremden Problemen verwenden sollte. Die Antwort liegt in der hohen Verarbeitungsgeschwindigkeit der Grafikkarten. Durch ihre vektorrechnerähnliche Struktur sind Shader Parallelrechner, die einerseits Operationen auf Vektoren mit vier Komponenten parallel ausführen können und andererseits selbst mehrfach auf der Grafikkarte vorhanden sind. Aktuelle Karten besitzen teilweise bis zu acht Pixel-Shader-Einheiten, die parallel geschaltet sind. Neben der parallelen Auslegung der Shader-Einheiten ist die sehr schnelle Anbindung zum Video-Speicher der Grafikkarten ein Geschwindigkeitsvorteil gegenüber der CPU. Im Video-Speicher werden Geometrie-Daten, Texturen und ShaderProgramme, sowie der Bildschirmspeicher abgelegt, der das Ausgabebild für den Monitor liefert (siehe Abbildung 2). Auf alle diese Daten kann ohne Umweg über den System-Bus sehr schnell zugegriffen werden. Bei der Initialisierung eines Programms kann man – soweit schon verfügbar – alle notwendigen Daten vom Hauptspeicher in den Video-Speicher kopieren, damit der System-Bus zur Laufzeit durch Datentransfer nicht mehr belastet wird. Wenn neben einer mathematischen Berechnung anschließend eine Visualisierung der Ergebnisse ansteht, werden unnötige Bustransfers über das System vermieden. Neben den oben genannten Vorteilen hält das hohe Tempo der Weiterentwicklung der Karten weiter an, was künftig zu weiteren Geschwindigkeitszunahmen führen wird. Etwa zweimal im Jahr stellen die großen Grafikkartenhersteller ihre neue GPUGeneration vor, die ihre Vorgänger meist deutlich übertrifft. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 8 von 99 1.2. Ziele dieser Diplomarbeit Im Rahmen dieser Diplomarbeit werden zwei Anwendungsbeispiele zur numerischen Simulation von Wasser und Fluiden auf Grafikhardware vorgestellt. Das Ziel besteht darin, die gesamten numerischen Berechnungen von der Grafikkarte durchführen zu lassen. Bei Initialisierung der Programme werden alle notwendigen Daten in den Video-Speicher kopiert und zur Laufzeit darf die CPU nur ShaderProgramme auf der GPU aufrufen. Arbeitslos ist die CPU trotzdem nicht, weil sie sich um die Nachrichten-, Maus- und Fensterverwaltung des Programms kümmern muss. Die numerische Berechnung erfolgt aber ausschließlich auf der GPU. Als erstes Teilprojekt geht es um die Umsetzung der allgemeinen Wellengleichung zur Simulation von Wasseroberflächen. Hierbei wird ein membranartiges Gitternetz simuliert, das zum Beispiel von Regentropfen ausgelenkt wird und anschließend nach den Gesetzen der Wellengleichung ausschwingt. Neben der Berechnung der Wellen werden Lichtberechnungen durchgeführt, die die optische Qualität steigern. Im Rahmen dieser Diplomarbeit wurde nur eine explizite Lösung der Wellengleichung implementiert. Im zweiten Teilprojekt geht es um die Simulation von Strömungen. Dazu werden die inkompressiblen Navier-Stokes-Gleichungen diskretisiert und auf der Grafikkarte berechnet. Aus Performancegründen wird nur der zweidimensionale Fall betrachtet, eine Erweiterung ins Dreidimensionale ist aber relativ einfach zu programmieren. Beide Projekte basieren gänzlich auf Pixel-Shader Programmen. Vertex-Shader Programme zur Geometrieverarbeitung werden nicht benötigt, weil alle Berechnungen auf zweidimensionalen Arrays bzw. Texturen ausgeführt werden. Das Ziel der beiden Projekte lag in erster Linie darin, die Möglichkeiten und die Geschwindigkeit moderner Grafikkarten mit Shadern auszuloten. Es geht nicht um eine numerisch exakte Lösung, die mit einer Implementierung auf der CPU oder FPU mithalten kann. Dazu fehlen vor allem Fließkommaformate mit hoher Genauigkeit. Es ging darum zu zeigen, dass Grafikkarten heutzutage in der Lage sind mathematische Probleme in sehr hoher Geschwindigkeit zu berechnen – wenn auch nicht mit der Genauigkeit von FPUs. Allerdings entwickeln die Hersteller ihre Karten im ungebremsten Wettbewerb stetig weiter, so dass es nur eine Frage der Zeit ist, bis dieses Problem vernachlässigbar ist. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 9 von 99 2. Simulation von Wasseroberflächen Im Folgenden wird ein Algorithmus zur Lösung der allgemeinen Wellengleichung auf Grafikhardware vorgestellt. Der hier gewählte Ansatz simuliert eine Wasseroberfläche, die man sich wie eine Membran vorstellen kann. Sie kann durch Regentropfen oder Gegenstände, die ins Wasser geworfen werden, ausgelenkt werden. Durch die Gesetze der Wellengleichungen beginnt daraufhin diese Membran zu schwingen, wobei sich charakteristische Wellen ausbreiten, wie man es von realem Wasser kennt. Dieser Ansatz simuliert kein Volumen, sondern nur eine Oberfläche. Die Membran ist also unendlich dünn und „darunter“ ist nichts. Außerdem werden hier nur stille Gewässer simuliert, Strömungen werden im nächsten Teilprojekt im Kapitel 3 ab Seite 37 behandelt. 2.1. Die Wellengleichung 2.1.1. Die partielle Differentialgleichung Ausgangspunkt ist die zweidimensionale Poisson-Gleichung, die eine Vielzahl von physikalischen Problemen beschreibt, je nach dem, wie die rechte Seite der PoissonGleichung f ( x, y ) gewählt wird. Neben der Temperaturverteilung in isotropen Medien im Gleichgewichtszustand oder das erzeugte elektrische Potential durch eine Ladungsverteilung, kann auch eine Membran damit berechnet werden. ∂ 2 u ( x , y ) ∂ 2 u ( x, y ) = f ( x, y ) + ∂y 2 ∂x 2 In [10], [11], [12] und [13] finden sich Herleitungen aus den Wärmegesetzen, numerische Lösungsverfahren und zahlreiche Anwendungsbeispiele. Um eine Membran zu simulieren, benötigt man als rechte Seite die zweite partielle Ableitung nach der Zeit t. ∂2 y ∂2 y ∂2 y c 2 + 2 = 2 ∂z ∂t ∂x 2 Die allgemeine Wellengleichung beschreibt, wie sich die Membran in einem bestimmten, unendlich kleinen Punkt verhält. Die Nachbarn eines Punktes nehmen dabei unmittelbaren Einfluss auf die Auslenkung, da durch die Oberflächenspannung benachbarte Punkte zusammengehalten werden. Wenn also ein Punkt durch den Einschlag eines Regentropfens oder eines Steines nach unten ausgelenkt wird, so beeinflusst das auch seine Nachbarn, die dann auch heruntergezogen werden. Im nächsten Iterationsschritt pflanzt sich diese Entwicklung fort und es entstehen Wellenbewegungen. Durch die gegenseitige Ausgleichung der horizontalen Kräfte, kann sich ein Punkt der Membran nur auf und ab bewegen, jedoch niemals seitwärts. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 10 von 99 Um die partielle Differentialgleichung lösen zu können benötigt man Anfangswerte und Randbedingungen. Eine gültige Ausgangslage ist eine ruhende Membran, die an jedem Ort nicht ausgelenkt ist. Hier wurde ein Wasserbecken simuliert, so dass für die Randbedingung gilt, dass die Wellen am Rand in das Becken zurück reflektiert werden. Zunächst zur Erklärung der Variablen. Die geometrischen Achsen verlaufen so, dass die z-Achse die Tiefe in den Raum repräsentiert und die y-Achse die Höhe. Die Membran erstreckt sich über die x- und z-Achse und kann entlang der y-Achse nach oben und unten ausgelenkt werden. Abbildung 3: Membran und Koordinatenachsen Über die Variable t, die die Zeit darstellt, lässt sich die gesamte Simulation schneller oder langsamer ablaufen lassen. Im Gegensatz zur Zeit t bestimmt die Wellengeschwindigkeit c, wie schnell sich die Wellen über die Membran ausbreiten. Der Unterschied zwischen t und c liegt darin, dass die Zeit t ein globaler Parameter ist und sich auf die gesamte Membran auswirkt. Dagegen kann die Wellengeschwindigkeit c als lokaler Parameter aufgefasst werden. Durch Anpassung von c kann man an unterschiedlichen Stellen unterschiedliche Medien entsprechend ihrer Durchflussgeschwindigkeit bzw. Wasserdurchlässigkeit simulieren. Im Allgemeinen kann die Wellengleichung nicht in analytischer Form gelöst werden. Deswegen wird sie im folgenden Abschnitt durch ein geeignetes numerisches Verfahren diskretisiert. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 11 von 99 2.1.2. Diskretisierung der Differentialgleichung Um die Wellengleichung zu diskretisieren werden finite Differenzenverfahren angewendet. Mit Hilfe der Taylor-Formel lassen sich für partielle Ableitungen verschiedener Ordnungen finite Differenzen bestimmen. Als Grundlage dient die Taylor-Formel, wobei R das Restglied der eigentlich unendlichen Reihe darstellt. f ' (a) f (n ) (x − a ) + L + (x − a )n + Rn+1 (x − a ) f ( x) = f (a) + 1! n! Dieses Polynom approximiert die Funktion f(x) in der Umgebung von x = a. Drei verschiedene Differenzenverfahren ergeben sich durch Umformungen aus der Taylor-Formel, um partielle Ableitungen erster Ordnung zu diskretisieren. Die kontinuierlichen Variablen x, y und z werden zu diskreten Variablen i, j und k transformiert. ∂y ∂h i , j y i +1, j − y i , j + O(∆h) ∆ h y i , j − y i −1, j + O(∆h) = ∆h y i +1, j − y i −1, j + O(∆h) 2∆h Hier sind die finiten Differenzen entlang der i-Achse dargestellt. Völlig analog gelten sie auch für die j-Achse. Die erste Variante ist eine so genannte Vorwärtsdifferenz. Die aktuelle Position wird vom rechten Nachbarpunkt subtrahiert und durch den Gitterpunktabstand h dividiert, weil man sich eine Einheit auf dem Gitter bewegt. Den Fehlerterm O(∆h) kann man vernachlässigen. Analog verhält sich die Rückwärtsdifferenz. Zur Diskretisierung der Wellengleichung werden Zentraldifferenzen verwendet, die hier als dritte Möglichkeit aufgeführt sind. Die Zentraldifferenz subtrahiert den „linken“ Punkt vom „Rechten“ und dividiert anschließend durch den doppelten Gitterpunktabstand h, weil hier die zweifache Distanz beschritten wird. Für die Wellengleichung benötigt man die finiten Differenzen für die zweiten partiellen Ableitungen. Aus der Taylor-Formel ergibt sich folgender Term für die Zentraldifferenz: y − 2 y i , j + y i −1, j ∂2 y 2 = i +1, j + O(∆h) 2 2 (∆h ) ∂h i , j Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 12 von 99 2 ∂2 y ∂2 y 2 ∂ y Eingesetzt in die Wellengleichung = c 2 + 2 ergibt sich: ∂t 2 ∂z ∂x y it,+j1 − 2 y it, j + y it,−j1 (∆t )2 y it+1, j − 2 y it, j + y it−1, j y it, j +1 − 2 y it, j + y it, j −1 =c + 2 2 ( ) ( ) x z ∆ ∆ 2 Unter der Annahme eines regulären Gitters mit konstantem Gitterabstand h über beide Achsen ergibt sich mit ∆x = ∆z = h : y it,+j1 − 2 y it, j + y it,−j1 (∆t )2 y it+1, j − 2 y it, j + y it−1, j y it, j +1 − 2 y it, j + y it, j −1 =c + 2 2 ( ) ( ) h h ∆ ∆ 2 y it,+j1 − 2 y it, j + yit,−j1 = c 2 (∆t ) (∆h ) 2 2 (y t i +1, j + y it−1, j + y it, j +1 + y it, j −1 − 4 y it, j ) Gesucht ist die Lösung von y it,+j1 , dem Höhenwert der Membran an einem diskreten Punkt i,j zum Zeitpunkt t+1: y t +1 i, j = c 2 (∆t ) (∆h ) 2 2 (y t i +1, j +y t i −1, j +y t i , j +1 +y t i , j −1 ) 2 c 2 (∆t ) + 2 − 4 (∆h )2 t y i , j − y it,−j1 Aus dieser Diskretisierung wird ersichtlich, dass hier nur die unmittelbaren Nachbarpunkte Einfluss auf die neue Höhe eines Punktes haben und keine weiter entfernten Punkte. Abbildung 4: Einfluss der Nachbarpunkte in der diskreten Wellengleichung Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 13 von 99 Aus dem Zeitschritt t werden die umliegenden Nachbarn aufaddiert und je nach Wahl der Konstanten c, ∆t und ∆h die Höhe des Punktes selbst subtrahiert. Im letzten Term wird die Höhe des Punktes schließlich aus dem vorherigen Zeitschritt subtrahiert. Weitere Informationen finden sich in [2]. Eine Shader-basierte Implementierung ist jetzt kein Problem mehr, da nur auf Nachbarpunkte zugegriffen werden muss und sich die arithmetischen Funktionen auf Addition, Subtraktionen und Multiplikationen beschränken. Diese Funktionalität stellen Pixel-Shader zur Verfügung. 2.1.3. Diskretisierung der Membran Wie oben schon angedeutet kann die Membran durch ein reguläres Gitter modelliert werden, das sich als Array oder Textur abspeichern lässt. Zwischen den einzelnen Gitterpunkten ist der Abstand h konstant für beide Achsen, x und z. Man kann diesen Abstand h als 1 annehmen und somit die Diskretisierung nochmals vereinfachen. Genauso kann man die Zeit ∆t auf 1 setzen. Jedem Gitterpunkt ist eine Höhe y zugeordnet, die die Auslenkung der Membran bestimmt. Insgesamt ist das Gitter N x N Punkte groß, wobei das Gitter nicht zwingend quadratisch sein muss. Zur Initialisierung werden alle Höhenwerte der Membran auf 0 gesetzt, womit die Wasseroberfläche als ruhig angenommen wird und sich in beide Richtungen, nach oben und unten bzw. in positiver und negativer y-Richtung, auslenken kann. Abbildung 5: Diskretes Gitter zur Modellierung der Membran Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 14 von 99 2.1.4. Numerische Stabilität So einfach das oben beschriebene Verfahren auch ist, es hat einen entscheidenden Nachteil: es ist numerisch instabil. Numerische Instabilität bedeutet, dass sich bei der Durchführung der Berechnungen Fehler aufsummieren, und sich somit im Laufe der Zeit Überschwinger zu nicht mehr endenden Oszillationen aufschaukeln. Wenn es so weit kommt, sind die Ergebnisse nicht mehr brauchbar. Das oben beschriebene Verfahren ist ein explizites Verfahren. Bei einem expliziten Verfahren liegen alle Eingabewerte bereits vor. In diesem Fall sind das die Höhenwerte aus dem letzten bzw. vorletzten Zeitschritt. Es gibt nur eine Gleichung und eine Unbekannte, nämlich den neuen Höhenwert. Die Lösung lässt sich sehr schnell und einfach explizit durch Auswerten der Formel berechnen, aber darin liegt eine Fehlerquelle. Nur für einen sehr eingeschränkten Parameterbereich von c, ∆t und ∆h liefert das Verfahren vernünftige Ergebnisse. Zur numerisch stabilen Lösung der Wellengleichung ist ein implizites Verfahren notwendig. Um aus der expliziten Formel eine Implizite zu machen, wird nach dem Crank-Nicholson-Verfahren der Höhenwert zum Zeitpunkt t mit dem Höhenwert zum Zeitpunkt t+1 gemittelt. y t i, j (y = t +1 i, j + yit, j ) 2 Weitere Erläuterungen zum Crank-Nicholson-Verfahren finden sich in [10], [11], [12] und [13]. Eingesetzt in die explizite Formel ergibt sich: yit,+j1 − 2 yit, j + yit,−j1 (∆t )2 ( ) ( ) ( ) ( ) ( yit++11, j + yit+1, j + yit−+11, j + yit−1, j + yit,+j1+1 + yit, j +1 + yit,+j1−1 + yit, j −1 − 4 yit,+j1 + yit, j =c 2 2(∆h ) 2 ) Um diese Gleichung nach yit,+j1 lösen, braucht man die umliegenden Werte von y zum Zeitpunkt t+1. Mit Hilfe eines Gleichungssystems kann man diese Formel berechnen. Das Lösen von Gleichungssystemen geht über den Rahmen dieser Diplomarbeit hinaus und wird nicht weiter betrachtet. In [7] wird ein implizites Lösungsverfahren vorgestellt. Damit das explizite Verfahren vernünftige Ergebnisse liefert, müssen die Konstanten c, ∆t und ∆h sorgfältig gewählt werden und folgende Stabilitätsbedingung erfüllen. 1 c 2 (∆t ) ≤ 2 2 (∆h ) 2 Weitere Informationen zur Stabilitätsbedingung finden sich in [2]. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 15 von 99 Wenn man diese Bedingung beachtet, liefert das explizite Verfahren brauchbare Werte. Allerdings kommen die Wellen, sobald sie einmal in Gang gebracht wurden, nie wieder zur Ruhe. Deshalb ist eine zusätzliche Dämpfung notwendig. 2.1.5. Dämpfung Um permanente Wellen zu vermeiden, die sich aus dem expliziten Verfahren ergeben, bedarf es einer Dämpfung der Wellengleichung. Positiver Nebeneffekt der Dämpfung ist, dass man damit auch Ufer, an denen die Wellenbewegung abflacht, oder Inseln im See simulieren kann. Der einfachste Ansatz ist die Einführung einer Dämpfungskonstante d, die den gesamten Term abdämpft. y t +1 i, j 2 c 2 (∆t )2 t c 2 (∆t ) t t t y i +1, j + y i −1, j + y i , j +1 + y i , j −1 + 2 − 4 =d (∆h )2 (∆h )2 ( ) t y i , j − y it,−j1 Der Wertebereich für d liegt zwischen 0 und 1. In der Praxis haben sich bereits Dämpfungskoeffizienten von 0.95 als ausreichend erwiesen um permanente Wellen zu vermeiden. Für Ufer oder Inseln kann man den Dämpfungskoeffizienten ortsabhängig machen: di,j. In der Implementierung wurde eine zweidimensionale Exponentialfunktion bzw. Gauss-Glocke als Dämpfung verwendet. 2 2 d i , j = e − r ⋅((i −0.5 ) + ( j −0.5 ) ) Den Radius der Funktion bestimmt der Parameter r. Die Verschiebung von i und j um 0.5 legt das Zentrum der Auswölbung in die Mitte des Feldes mit i, j ∈ [0;1] . Durch diese Dämpfungsfunktion werden die Wellen zum Rand abgebremst, so dass ein Ufer simuliert werden kann. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 16 von 99 Abbildung 6: Dämpfungsfunktion in der Wasserdemo 2.1.6. Einschläge von Objekten auf die Wasseroberfläche Bis jetzt ist die Membran noch in ihrer Ausgangslage, der x-z-Ebene. Damit sich Wellen bilden können, muss zuerst ein Einschlag auf die Membran erfolgen, der sie auslenkt. Je nach Form des Objekts, das ins Wasser fällt, wird ein bestimmtes Volumen an Wasser mit der Form des Objekts verdrängt. Der einfache Versuch nur einzelne Punkte der Membran auszulenken scheitert an der hohen Unstetigkeit mit den umliegenden Punkten. Durch die explizite Lösung der Wellengleichung breiten sich die Unstetigkeiten über die Membran aus und der Realismus der Simulation geht verloren. Mit einem impliziten Verfahren treten solche Probleme nicht auf. Im Folgenden werden nur Einschläge von Regentropfen bzw. relativ runden Objekten untersucht, da sich die Einschläge runder Objekte wieder gut mit einer zweidimensionalen Exponentialfunktion beschreiben lassen. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 17 von 99 Um unterschiedlich große Objekte zu simulieren, wie zum Beispiel Regentropfen oder größere, runde Steine, kommt diesmal neben dem Einschlagsradius auch noch die Einschlagstiefe a ins Spiel. 2 2 d i , j = a ⋅ e −r⋅((i −0.5 ) +( j −0.5 ) ) Zusammen mit dem Einschlagsradius r bestimmt die Einschlagstiefe a die Charakteristik des Einschlags. Kleiner Radius mit hoher Tiefe simuliert zum Beispiel kleine, schwere Metallkugeln, die mit großer Kraft ins Wasser geworfen werden. Regentropfen haben einen kleinen Einschlagsradius mit geringer Einschlagstiefe. Einen großen Radius und geringe Tiefe verursachen Schlauchboote, die ins Wasser gelassen werden. Die Parameter i und j bestimmen, wie gehabt, die Einschlagsstelle auf der Membran. Je nach Zusammenspiel der Parameter entstehen durch Berechnung der Wellengleichung auch unterschiedliche Ausbreitungsformen der Wellen. Bei geringer Einschlagstiefe entsteht meist nur eine einzelne Welle, die sich über die Membran ausbreitet. Bei anderen Parameterkombinationen können sehr viele und große Wellen entstehen. Abbildung 7: Regentropfeneinschläge und Wellenausbreitung Echtzeitfähige Simulation von Wasser auf Grafikhardware Abbildung 8: Große Einschläge und Wellenausbreitung Seite 18 von 99 Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 19 von 99 2.2. Modellierung des Lichts Nachdem die geometrische Wellenausbreitung berechnet ist, geht es nun darum, die optische Darstellung zu verbessern. Dazu werden verschiedene Aspekte des Lichts nachmodelliert. Als erstes werden die Lichtfarbe und -intensität nach dem Phong-Illumination-Model berechnet. Je nach Position der Lichtquelle werden damit bestimmte Wellenkämme und -täler beleuchtet. Das Lichtmodell ist zwar sehr einfach, sorgt aber für eine täuschend echte Beleuchtung der Szene. Im zweiten Schritt werden Lichtreflexionen berechnet. Lichtstrahlen, die aus der Umgebung kommen, werden an der Wasseroberfläche reflektiert und treffen im Auge des Betrachters ein. Die Reflexion sorgt für eine große Verbesserung der optischen Qualität. Als letztes wird die Lichtbrechung berechnet. Lichtstrahlen, die auf die Wasseroberfläche auftreffen, werden teilweise reflektiert und teilweise gebrochen. Unter Lichtbrechung versteht man die Ablenkung der Lichtrichtung an der Oberfläche zu einem Medium mit unterschiedlicher optischer Dichte. Alle drei Lichtaspekte erfordern die Oberflächennormalen des Wassers in jeder diskreten Gitterzelle. Dies wird zuerst untersucht. 2.2.1. Berechnung der Normalen der Wasseroberfläche Gegeben ist das reguläre, diskrete Gitter mit den aktuellen Höhenwerten der Auslenkung. Die Frage ist, wie man aus den Höhenwerten Oberflächennormalen berechnen kann. Wie aus den obigen Bildern ersichtlich, wird das Gitter stets in Form von Dreiecken dargestellt. Zwei Dreiecke bilden ein Quadrat, dessen Ecken Höhenwerte aus den Wellenberechnungen zugeordnet sind. Die Berechnung der Normalen eines Dreiecks ergibt sich direkt aus dem Vektorprodukt der Dreiecksschenkel v1 und v2. n f = v1 × v 2 Anschließend muss man die Normale normalisieren, so dass ihre Länge 1 wird. Mit den Dreiecksnormalen kann man zunächst nicht viel anfangen, da man die Normalen auf einem Höhenpunkt benötigt. Sie wird Vertexnormale oder Vektornormale genannt. Da an jedem Höhenpunkt mehrere Dreiecke anliegen, kann man deren Dreiecksnormalen zusammenaddieren und mit ihrem Winkel in diesem Punkt gewichten. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 20 von 99 Abbildung 9: Berechnung einer Dreiecksnormalen Dieses Verfahren ist zu aufwändig für Echtzeitanwendungen, weil die Normalen durch Wellenbewegung für jedes Bild und für jeden Punkt neu berechnet werden müssen. Man braucht eine einfachere Methode. Zur Vereinfachung der Berechnung wird angenommen, dass jeder Punkt v genau zu vier umliegenden Dreiecken gehört. Von v gehen vier Vektoren v1...4 zu den direkten Nachbarpunkten. Abbildung 10: Nachbarschaftsbeziehung Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 21 von 99 Zur Erinnerung: das Gitter erstreckt sich in x-z-Ebene und der y-Wert entspricht der Höhe. Als zweite Annäherung an die Normale, geht man davon aus, dass alle vier Dreiecksnormalen den gleichen Anteil zur Normale von v beitragen. Falsch wird die Annahme, sobald die Höhenwerte weit auseinander liegen, weil dann die Winkel um v nicht mehr in der Nähe von 90° sind. Um eine möglichst einfache und schnell berechenbare Formel zu erhalten, wird dieser Fehler in Kauf genommen. Mit den obigen Vereinfachungen berechnet man die Normale von v aus dem Mittelwert der umliegenden Dreiecksnormalen. nv = (n1 + n2 + n3 + n 4 ) 4 Die Dreiecksnormalen n1...4 werden wie oben beschrieben aus dem Vektorprodukt ihrer beiden Dreiecksschenkel berechnet. Als weitere Vereinfachung kann man den Gitterabstand h als 1 annehmen, wodurch die x- und z-Komponenten der Vektoren v1…4 zu Werten aus {-1; 0; 1} werden. 1 v1 = y1 − y 0 ; 0 0 v 2 = y 2 − y 0 ; 1 −1 v3 = y 3 − y 0 ; 0 0 v 4 = y 4 − y 0 ; −1 Eingesetzt in die Kreuzprodukte ergibt das: − y1 + y0 1 n1 = v1 × v2 = ; − y + y 0 2 y3 − y 0 n 3 = v3 × v4 = 1 ; y −y 0 4 In nv = y3 − y0 1 n 2 = v 2 × v3 = ; − y + y 0 2 − y1 + y 0 1 n4 = v4 × v1 = ; y −y 0 4 (n1 + n2 + n3 + n 4 ) eingesetzt ergibt sich für die Normale in v: 4 − y1 + y 0 + y 3 − y 0 + y 3 − y 0 − y1 + y 0 2( y 3 − y1 ) 1 1 4 nv = 4 = 4 4 − y2 + y0 − y2 + y0 + y4 − y0 + y 4 − y0 2( y 4 − y 2 ) Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 22 von 99 Da die Länge der Normalen sowieso noch normalisiert werden muss, kann man auf die Koeffizienten verzichten und man kommt auf diese einfache Formel zur Berechnung der Normalen, die nur auf benachbarte Höhenwerte zugreift: y 3 − y1 nv = 2 y − y 2 4 Ausführlichere Darstellungen zur Berechnung der Vertexnormalen in Höhenfeldern sind in [2] ausgeführt. 2.2.2. Lichtfarbe und Lichtintensität (Phong-Illumination-Model) Da nun die Normalen der Oberfläche bekannt sind, kann man berechnen, wie viel Licht von einer Quelle auf einen Oberflächenpunkt trifft. Das Phong-IlluminationModel vereinfacht den komplexen Strahlenverlauf des Lichts auf eine elementare Formel. Auf eine Oberfläche mit der Oberflächennormale N trifft unter einem bestimmten Winkel α ein Lichtstrahl L. Je nach den Eigenschaften der Oberfläche wird dieser Lichtstrahl unter dem gleichen Ausfallswinkel an der Oberfläche reflektiert. Oftmals wird anstatt des Reflexionsvektors R der so genannten Halbvektor H als Näherung verwendet. Der Betrachtungsvektor V bestimmt den Winkel unter dem der Betrachter auf die Oberfläche blickt. Abbildung 11: Phong-Illumination-Model Drei Komponenten hat dem Phong-Modell zufolge das Licht, das in [16] erstmals vorgestellt wurde: das Umgebungslicht, diffuse Lichtreflexion und spekulare Reflexion. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 23 von 99 Ambient Das Umgebungslicht einer Szene wird durch einen konstanten Ambient-Anteil im Licht modelliert. Anstatt den komplexen Strahlenverlauf des Lichts zu berechnen, der sich nur durch eine globale Beleuchtung modellieren lässt, wird pro Oberfläche eine Farbe CAmbient(Rot, Grün, Blau) definiert, die sie emittieren soll. Mittels des Koeffizienten KAmbient, der zwischen 0 und 1 liegt, wird die Intensität der Farbe gewichtet. Ambient = K Ambient ⋅ C Ambient (R, G , B ) Sowohl die Farbe als auch der Koeffizient des Umgebungslichts sind Eigenschaften des Oberflächenmaterials und können pro Oberfläche unterschiedlich definiert werden. Die Bestimmung der Farbe und des Koeffizienten unterliegen keinen physikalischen Gesetzen. Sie werden meist empirisch festgelegt. Diffuse Reflexion Die diffuse Reflexion des Lichts beschreibt die Lichtintensität in Abhängigkeit von der Richtung des Lichteinfalls und der Oberfläche. Die Lichtintensität hängt vom Winkel α zwischen dem Lichtvektor L und der Oberflächennormale N ab. Bei einem Winkel von 0° wird das Licht maximal reflektiert und es entsteht die größte Lichtreflexion. Je größer der Winkel wird, desto weniger Licht wird reflektiert. Wenn der Winkel größer als 90° ist, dann liegt Lichtquelle hinter der Oberfläche, und sie wird gar nicht von beleuchtet. Die Lichtfarbe CDiffuse(Rot, Grün, Blau) sowie der Koeffizient KDiffuse sind wieder Materialkonstanten. Diffuse = K Diffuse ⋅ C Diffuse (R, G, B ) ⋅ cos(α ) Wenn die beiden Vektoren L und N normalisiert sind, so kann der Cosinus durch ein Skalarprodukt ausgerechnet werden. Wenn mehrere Lichtquellen modelliert werden sollen, dann wird die Beleuchtung wesentlich realistischer, wenn man noch den Abstand der Lichtquellen von der Oberfläche hinzunimmt. Dies erfolgt durch einen weiteren Koeffizienten im Term, der nach den physikalischen Gesetzen mit dem quadrierten Inversen des Abstandes eingeht. Spekulare Reflexion (Glanzlichter) Während das Umgebungslicht und der diffuse Lichtanteil unabhängig von der Position des Betrachters sind, entstehen Glanzlichter, wenn der Betrachter in die Reflexion des Lichts an der Oberfläche blickt. Je kleiner der Winkel zwischen Betrachtervektor und Reflexionsvektor des Lichts ist, desto größer sind der reflektierte Lichtanteil und damit das Glanzlicht. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 24 von 99 Nach Phong ist der Übergang nicht linear. Stattdessen wird die Intensitätsabnahme durch cos n ( β ) bestimmt, wobei β ist der Winkel zwischen Betrachtungsvektor V und Reflexionsvektor R ist. Der Parameter n ist eine materialspezifische Konstante ist. 1,2000 1,0000 0,8000 cos β cos2 β cos64 β 0,6000 0,4000 0,2000 1,5463 1,4358 1,3254 1,2149 1,1045 0,9940 0,8836 0,7731 0,6627 0,5522 0,4418 0,3313 0,2209 0,1104 0,0000 0,0000 Abbildung 12: Materialspezifische Konstante n Für n = 1 ergibt sich eine weiche Intensitätsabnahme, während bei großen n scharfe Glanzlichter ergeben. Wie schon beim diffusen Lichtanteil kann der Winkel β durch ein Skalarprodukt von V und R berechnet werden, wenn beide Vektoren normalisiert sind. Die Farbe des Glanzlichtes einer Oberfläche wird durch CSpecular(Rot, Grün, Blau) festgelegt und ihre Intensität durch KSpecular. Specular = K Sepcular ⋅ C Specular (R, G, B ) ⋅ cos n (β ) Alle drei Terme zusammengenommen ergeben das Phong-Illumination-Model. C Phong = K Ambient ⋅ C Ambient + K Diffuse ⋅ C Diffuse ⋅ cos(α ) + K Sepcular ⋅ C Specular ⋅ cos n (β ) CPhong bestimmt die Lichtfarbe und die Lichtintensität am gesuchten Oberflächenpunkt. Eine detaillierte Beschreibung und andere, komplexere Lichtmodelle kann in [4] nachgelesen werden. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 25 von 99 2.2.3. Lichtreflexion Sowohl im Phong-Illumination-Model als auch bei der Berechung von Spiegelungen der Umgebung im Wasser wird der Reflexionsvektor R eines eintreffenden Strahles V an einer Oberfläche mit der Normale N benötigt. Abbildung 14: Reflexionsvektor Um den Reflexionsvektor R zu bestimmen müssen der Betrachtungsvektor V und die Oberflächennormale N normalisiert sein. Wie in [4] beschrieben, kann man den Reflexionsvektor durch geometrische Überlegungen herleiten: Die Projektion von V auf N ist N · cos α. Im linken Dreieck ist N · cos α = V + S. Um vom Ursprung zu R zu gelangen folgt man erst dem Vektor V und dann den beiden Vektoren S, die aus Symmetriegründen gleich sein müssen. R =V + 2⋅S Setzt man S = N ⋅ cos α − V in R ein ergibt sich: R = V + 2 ⋅ ( N ⋅ cosα − V ) R = V + 2 ⋅ N ⋅ cosα − 2 ⋅ V R = 2 ⋅ N ⋅ cosα − V Den Winkel α kann man durch ein Skalarprodukt ausdrücken, wenn die Vektoren normalisiert sind und es ergibt sich schließlich folgende Formel für den Reflexionsvektor. R = 2 ⋅ (V • N ) ⋅ N − V Im Blinn-Phong-Illumination-Model (siehe [17]) wird auf die explizite Berechnung des Reflexionsvektors verzichtet um die Berechnung möglichst schnell zu machen. Für den spekularen Lichtanteil wird der Winkel zwischen dem Betrachtervektor V und dem Reflexionsvektor des Lichts R benötigt. Anstatt R wird der so genannte Halbvektor H verwendet, der zwar nur eine grobe Näherung an den Reflexionsvektor ist, aber dafür sehr schnell berechenbar ist: L +V H= L +V Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 26 von 99 Abbildung 13: Regentropfeneinschläge von oben mit Phong-Beleuchtung Cube Mapping Um Spiegelungen der umgebenden Landschaft auf der Wasseroberfläche zu berechnen, wird der Reflexionsvektor R als Index in eine so genannte Cube Map verwendet werden. Cube-Maps bestehen aus sechs Texturen, die an die Innenseiten eines Würfels angebracht sind. Sie werden dazu benutzt, die umgebende Landschaft um einen Betrachtungspunkt darzustellen, der genau in der Mitte des Würfels liegt. Jede Seitenfläche enthält eine Bild der Szene mit einem Sichtwinkel von 90° in horizontaler und vertikaler Achse. Wenn man alle sechs Seitenflächen auf die Innenseiten eines Würfels setzt, ergibt sich ein kontinuierliches 360° Panoramabild über alle Achsen um den Szenenmittelpunkt. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 27 von 99 Abbildung 15: Sechs Seiten einer Cube-Map Um Reflexionen aus der umgebenden Szene zu simulieren, wird der Reflexionsvektor als Index in die Cube Map verwendet. Dazu wird in Richtung der längsten der drei Vektorkomponenten U, V, W eine der sechs Seitenflächen ausgewählt und mit den anderen beiden innerhalb dieser Textur ein konkretes Pixel adressiert. Sei W ist längste Komponente, dann werden die zweidimensionalen Texturkoordinaten U’ und V’ in eine der Seitentexturen mit einer Projektion berechnet: U ' = U /W V ' = V /W Auf diese Weise erhält man Spiegelungen der umgebenden Landschaft auf der Wasseroberfläche. Ausführlichere Beschreibungen finden sich in [3], [4], [15] und [18]. Abbildung 16: Reflexion der Umgebung im Wasser Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 28 von 99 2.2.4. Lichtbrechung Ein Teil des Lichts, der auf eine Wasseroberfläche trifft, wird reflektiert, ein anderer Teil gelangt unter die Wasseroberfläche. Beim Medienwechsel zwischen Luft und Wasser kommt es zur Lichtbrechung. Der Lichtstrahl wird von seiner ursprünglichen Richtung an der Wasseroberfläche abgelenkt. In der nachfolgenden Abbildung wird die Berechnung des Brechungsvektors, manchmal auch Refraktionsvektor genannt, aufgezeigt. Abbildung 17: Brechungsvektor Das Verhältnis zwischen dem Eintreffwinkel des Lichts α auf der Wasseroberfläche und β, dem Brechungswinkel unter Wasser, wird Brechungsindex ηr genannt. ηr = sin β sin α Gegeben sind der einfallende Lichtvektor L, die Oberflächennormale N in einem Punkt und der Brechungsindex ηr. Aus geometrischen Überlegungen ergibt sich der Brechungsvektor zu: B = sin β ⋅ M − cos β ⋅ N Der Einheitsvektor M steht senkrecht auf der Oberflächennormalen N und liegt in der Ebene, die N und L aufspannen. Wie aus obiger Abbildung ersichtlich, zeigt S in die gleiche Richtung wie M. Um M zu berechnen muss S mit sin α skaliert werden. Echtzeitfähige Simulation von Wasser auf Grafikhardware M = Seite 29 von 99 N ⋅ cos α − L sin α Eingesetzt in B = sin β ⋅ M − cos β ⋅ N ergibt sich: B= Mit η r = sin β ⋅ (N ⋅ cosα − L ) − cos β ⋅ N sin α sin β ergibt sich für B: sin α B = (η r ⋅ cos α − cos β ) ⋅ N − η r L Durch das Skalarprodukt (N · L) kann cos α bestimmt werden, cos β kann über Phythagoras berechnet werden: cos β = 1 − sin 2 β Die Quadrierung von η r = sin β ergibt nach sin2 β aufgelöst: sin α sin 2 β = η r ⋅ sin 2 α 2 Eingesetzt in die Formel für cos β und zugleich sin2 α durch Phythagoras ersetzt erhält man: ( cos β = 1 − sin 2 β = 1 − η r2 sin 2 α = 1 − η r2 1 − ( N ⋅ L ) 2 ) Der Brechungsvektor B = (η r ⋅ cosα − cos β ) ⋅ N − η r L ist somit: ( ) 2 B = η r ⋅ ( N ⋅ L ) − 1 − η r2 1 − ( N ⋅ L ) ⋅ N − η r L In der nachfolgenden Tabelle sind einige Brechungsindizes ηr für verschiedene Medien aufgeführt. Medium Diamant Schwefelkohlenstoff Kanadabalsam Benzol Quarzglas Wasser Brechungsindex ηr 2,4173 1,6277 1,5420 1,5014 1,4584 1,3330 Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 30 von 99 In dieser Implementierung wurde die Länge des Refraktionsvektors nicht weiter verwendet. In Abhängigkeit von der Länge können Intensitätsabnahmen oder Farbfrequenzverschiebungen modelliert werden. Mit Hilfe der Lichtbrechung gelingen die typischen Verzerrungen, die man beobachten kann, wenn durch klares Wasser auf den Grund blickt. Wenn man im Hallenbad in ein tiefes Becken schaut und das Wasser ruhig ist, sieht das Becken meist nicht so tief aus wie es eigentlich ist. Dieser Effekt beruht auf der Lichtbrechung. Weitere Ausführungen zur Lichtbrechung findet man in [4] und [19]. Abbildung 18: Lichtbrechung Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 31 von 99 2.3. Implementierung 2.3.1. Lösung der Wellengleichung in Grafikhardware Wie schon weiter oben angedeutet, werden bei der Implementierung nur PixelShader Programme verwendet. Die Berechnung der Höhenwerte erfolgt in Arrays bzw. Texturen auf Pixel- bzw. Fragment-Basis und nicht in Vektoren, die in VertexShader Programmen verarbeitet werden. Zum Berechnen der Wellengleichung in Grafikhardware werden zwei Texturen benötigt, die die Höheninformation für die Zeitpunkte t+1, t und t-1 speichern. Zwei Texturen sind deshalb ausreichend, weil man als Eingabe für die Wellengleichung die Texturen zu den Zeitpunkten t und t-1 benötigt und das Ergebnis für den Zeitschritt t+1 in der Textur t-1 ersetzten kann. Es werden keine umliegenden Punkte aus t-1 benötigt. Des Weiteren ist eine Dämpfungstextur d notwendig, die die Dämpfungskoeffizienten pro Punkt speichert. Abbildung 19: Texturen und Funktionsweise des Wellen-Pixel-Shaders Die Arbeitsweise läuft nach diesem Schema ab: Die Wellentexturen t und t-1 sowie die Dämpfungstextur d wird als Parameter an den Wellen-Shader übergeben, genauso wie die Konstanten c, ∆t und ∆h. Mit der diskretisierten Form der Wellengleichung errechnet der Shader Punkt für Punkt die neuen Höhenwerte zum Zeitpunkt t+1 aus. Die Ergebnisse speichert er in der Textur t-1. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 32 von 99 Sobald ein Shader-Pass abgeschlossen ist, werden die Labels der Wellentexturen geändert: Die soeben berechnete Textur t-1 als Textur t, und die ehemalige Textur t als Textur t-1 deklariert. So ist kein Umkopieren von Texturen notwendig. Um die gesamte Textur beim Rendern zu erreichen, wird ein Quadrat über die Fläche in einem Vertex-Buffer aufgespannt. Damit jeder Pixel der Texturen genau einmal bearbeitet wird, werden die Welt- und Kameramatrix auf die Einheitsmatrix und die Projektionsmatrix wird auf eine orthogonale Projektion gesetzt. So wird auf zweidimensionaler Pixelebene gearbeitet. Einige Worte zum Texturformat: Die drei Texturen benötigen jeweils nur eine Komponente. Wenn man das Programm auf minimalen Video-Speicherplatz optimieren will, kann man die Texturen t, t ± 1 und d in eine Textur mit vier Komponenten speichern, wobei eine frei bleibt. Die Shader werden dadurch aber komplizierter. Neben der Anzahl der Komponenten ist noch die Frage nach dem Datentyp von Bedeutung. Es bieten sich 32-bit-float-Texturen an, da man hier uneingeschränkt positive und negative Fließkommazahlen verwenden kann. Alternativ können auch 16bit-float-Texturen verwendet werden, mit denen man je nach GPU schneller, aber auch ungenauer, rechnen kann. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 33 von 99 2.3.2. Zweidimensionale Darstellung Als einfache Möglichkeit der Darstellung bietet sich die direkte Draufsicht auf die Wassermembran an, wie es in Abbildung 18 dargestellt ist. Hierzu wird die aktuelle Wellentextur t+1 in ein Rechteck auf dem Bildschirm hineingerendert. Als weitere Eingabeparameter müssen für die Lichtreflexionen und Lichtbrechungen, auch Refraktionen genannt, die beiden entsprechenden Cube-Maps als Parameter mit übergeben werden. Das Demoprogramm Water2D demonstriert diese Vorgehensweise. Abbildung 20: Funktionsweise des Licht-Pixel-Shaders Die Demo Water2D wurde auf einem Rechner mit einer ATI Radeon 9700 Pro Grafikkarte geschrieben, weil das zur Entwicklungszeit die einzige Karte mit Unterstützung für den Pixel-Shader 2.0 Standard war. Zu den kompatiblen Karten zählen alle ATI Radeon Modelle ab 9500. Die sonstige Rechnerausstattung entspricht dem aktuellen Stand der Dinge. Der Hauptprozessor ist ein AMD Athlon mit 1,2 GHz und der Hauptspeicher ist 512 MB groß. Da das Programm unter DirectX 9.0 geschrieben wurde, wurde als Betriebssystem Windows XP Professional verwendet. Die Geschwindigkeit ist allerdings vom verwendeten Rechensystem unabhängig, da es hier nur auf die Leistung der Grafikkarte ankommt. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 34 von 99 Im unten stehenden Diagramm wurden mit verschiedenen Gittergrößen und Bildschirmauflösungen Geschwindigkeitsmessungen durchgeführt. Die Messgröße ist hierbei Bilder pro Sekunde bzw. Frames per Second im Englischen. In einem Bild werden die gesamten Berechnungen der Wellengleichung und des Lichts inklusive Reflexion und Refraktion durchgeführt. Geschwindigkeitsmessungen Bilder pro Sekunde 250 200 1024x768 800x600 640x480 150 100 50 0 64 128 256 512 Gittergöße Abbildung 21: Geschwindigkeitsmessungen der Demo Water2D Mit der Gittergröße ist die Seitenlänge des Quadrats gemeint. Um also die Anzahl der Gitterpunkte zu erhalten, muss die Gittergröße quadriert werden. Während die Framerate bei der höchsten Bildschirmauflösung zwischen dem größten und kleinsten Gitter nur um 15% sinkt, obwohl 64-mal mehr Gitterpunkte verarbeitet werden müssen zeigt, dass die Berechnung der Wellengleichung verhältnismäßig schnell von statten geht, dahingegen die Lichtberechnungen den größten Teil der Rechenzeit ausmachen. Diese werden nämlich pro Punkt im Framebuffer ausgerechnet und sind daher sehr stark abhängig von der Bildschirmauflösung. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 35 von 99 2.3.3. Dreidimensionale Darstellung Neben der zweidimensionalen Draufsicht auf das Wasser, stellt die dreidimensionale Darstellung des Wassers eine interessante Erweiterung der bisherigen Überlegungen dar. Damit die Berechnungen weiterhin vollständig in Grafikhardware und ohne Hauptprozessor durchgeführt werden können, müssen die Höhenwerte aus der Wellentextur an die Geometrieeinheit des Grafikprozessors weitergeleitet und in Punkte umgesetzt werden. Abbildung 22: Displacement Mapping Dieses Verfahren nennt sich Displacement Mapping. Einem Gitter, das in x-y-Ebene liegt, werden pro Vektor Texturkoordinaten mitgegeben an welcher Stelle eine Displacement Map ausgelesen werden soll. In diesem Fall würde die jeweils aktuelle Wellentextur als Displacement Map übergeben werden. Ein Vertex-ShaderProgramm greift pro Vektor darauf zu und verschiebt jeden Vektor um den jeweiligen Höhenwert. Anschließend werden im Vertex-Shader das Phong-Illumination-Model, Lichtreflexionen sowie Lichtbrechungen berechnet. Das Demoprogramm Water3D verwendet Displacement Mapping nach dem DirectX 9.0 Standard. Auf einer Radeon 9700 Pro Karte – momentan die einzige Karte, die Displacement Mapping unterstützt – erzielt man ca. 22 Bilder pro Sekunde, wenn man eine Gittergröße von 64 mal 64 Zellen verwendet. Die Anzahl der Bilder pro Sekunde hängt hier nur von der Gittergröße ab, die Bildschirmauflösung spielt keine Rolle. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 36 von 99 Bilder pro Sekunde Geschwindigkeitsmessungen 80 70 60 50 40 30 20 10 0 32 64 128 256 Gittergröße Abbildung 23: Geschwindigkeitsmessungen der Demo Water2D Für kleine Gittergrößen liegt die Geschwindigkeit im akzeptablen Rahmen, während größere Felder in Echtzeitanwendungen nicht zu gebrauchen sind. Die Hardwareunterstützung wird sich wahrscheinlich in den nächsten Generationen der Grafikkarten verbessern. Abbildung 24: Water3D mit 64² Gitterzellen, Phong-Beleuchtung und Lichtreflexion Im Vertex-Shader 3.0 Standard, den noch keine Grafikkarte unterstützt, wird es eine Technik namens Vertex-Texturing geben, womit in Vertex-Shader-Programmen Texturzugriffe erlaubt werden. Dies ist eine weitere Variante eine dreidimensionale Darstellung zu implementieren, die vollständig in Grafikhardware abläuft. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 37 von 99 3. Simulation von Fluiden Was versteht man eigentlich unter einem Fluid? Ein Fluid ist flüssige oder gasförmige Materie, die sich entlang von Strömungen sowie durch Diffusion ausbreitet und verwirbelt. Wenn man beispielsweise etwas Milch in den Kaffee gibt und kurz umrührt, kann man beobachten, wie die Milch im Kaffee wolkenähnliche Gebilde formt. Wissenschaftliche Anwendungen der Berechnung von Fluiden kommen vor allem aus dem Bereich des Bauingenieurwesens und des Maschinenbaus. So werden zum Beispiel beim Bau von Staudämmen Wasserverwirbelungen berechnet, denen der Damm Stand halten muss. Beim Brückenbau ist es wichtig Luftverwirbelungen zu kalkulieren, um sicher zu gehen, dass die Brücke nicht durch Turbulenzen einstürzt. Im Maschinenbauwesen spielen Fluide beispielsweise im Fahrzeugbau eine Rolle. In der Windkanalsimulation werden Luftströmungen berechnet, um das Fahrzeug möglichst windschnittig zu machen. Die exakte mathematische und physikalische Beschreibung dieses Naturphänomens liefern die so genannten Navier-Stokes-Gleichungen. Im vorherigen Teilprojekt ging es um die Simulation einer Membran. Das Strömungsmodell dagegen kann auch dazu verwendet werden Strömungen in dreidimensionalen Volumen zu berechnen. Wegen der begrenzten Rechenkapazität wird aber auch hier nur eine zweidimensionale Berechnung implementiert. Diese zweidimensionale Ebene kann man sich als eine einzelne Schicht eines dreidimensionalen Volumens vorstellen. Der Fokus liegt im folgenden Kapitel auf der Impuls- und der Kontinuitätsgleichung. Weitere Navier-Stokes-Gleichungen werden im Kapitel Erweiterungen auf Seite 87 kurz angesprochen, aber nicht im Detail diskutiert oder implementiert. 3.1. Die inkompressiblen Navier-Stokes-Gleichungen Das folgende Gleichungssystem beschreibt laminare, inkompressible, instationäre Fluide. Laminare Fluide kann man sich als Strömungsschichten vorstellen, die sich gegeneinander reiben und so Energie austauschen. Abbildung 25: Laminare Strömungen Im Gegensatz dazu haben turbulente Strömungen kaum Reibung, sondern die Teilchen können chaotisch die Schichten wechseln. Für diesen Fall kann das Reynoldsgleichungssystem verwendet werden. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 38 von 99 Inkompressible Fluide können – vereinfacht gesagt – nicht zusammengedrückt werden. Das gilt für Wasser, solange es nicht zum Kochen gebracht wird und in Dampf übergeht. Luft ist andererseits ein kompressibles Medium, wie man beispielsweise an der Erhitzung beim Aufpumpen eines Fahrradreifens beobachten kann. Instationäre Probleme verändern mit der Zeit ihren Zustand. Im Kapitel Simulierte Probleme ab Seite 79 werden sowohl stationäre Probleme wie die Nischenströmung und auch instationäre Probleme wie die Wirbelstraße vorgestellt. Die Navier-Stokes-Gleichungen werden hier in der dimensionslosen Darstellung verwendet. Für die Herleitung der dimensionslosen und dimensionsbehafteten NavierStokes-Gleichungen sei auf [6] verwiesen. Dimensionslos bedeutet, dass alle Größen der Gleichung keine physikalischen Einheiten tragen. Eine Ausnahme ist nur die Reynoldszahl. Durch diese Darstellung konnte man zeigen, dass sich Strömungen unabhängig ihres tatsächlichen Ausmaßes ähnlich verhalten. So erzeugt ein Tropfen Milch in einer Tasse Kaffee das gleiche Strömungsverhalten, wie ein runder Meteor, der in den Ozean fällt. Impulsgleichung und Kontinuitätsgleichung Die folgende Beschreibung wurde in starker Anlehnung an das Buch „Numerische Simulation in der Strömungsmechanik“ [6] verfasst. In diesem Buch findet man noch viele weitere Details, sowie weiterführende Thematiken. Für Strömungen werden Richtungsvektoren benötigt, die besagen, in welche Richtung die Strömung an jeder Stelle fließt. Im zweidimensionalen Fall besteht ein Richtungsvektor aus zwei Komponenten u und v. Pro Richtungskomponente gibt es eine partielle Differentialgleichung, die Impulsgleichung genannt wird: ( ) ∂u ∂p 1 ∂ 2 u ∂ 2 u ∂ u 2 ∂ (uv ) − − + gx + = + ∂y ∂t ∂x Re ∂x 2 ∂y 2 ∂x ( ) ∂v ∂p 1 ∂ 2 v ∂ 2 v ∂ (uv ) ∂ v 2 − − + gy + = + ∂x ∂y ∂t ∂y Re ∂x 2 ∂y 2 Zur Massenerhaltung wurde die so genannte Kontinuitätsgleichung hergeleitet, die die Divergenzfreiheit garantiert: ∂u ∂v + =0 ∂x ∂y Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 39 von 99 Die beiden Gleichungen werden auf einem rechteckigen, zunächst kontinuierlichem, Gebiet Ω := [0, a ]× [0, b] ⊂ R 2 gelöst. Dabei sind die gesuchten Größen in den Gleichungen: u: die Geschwindigkeitskomponente des Fluids in x-Richtung v: die Geschwindigkeitskomponente des Fluids in y-Richtung p: der Druck gx, gy: die äußeren Kräfte, die auf das Gebiet einwirken. Das können zum Beispiel Erdanziehungskräfte oder Corilis-Kräfte sein t: die Zeit Re: Nach dem englischen Physiker Reynolds benannt, beschreibt die Zähigkeit bzw. die Viskosität des Fluids. Je kleiner sie ist, desto zäher ist das Fluid. Je größer sie ist, desto turbulenter ist das Fluid. Zum besseren Verständnis der Gleichungen ein paar kurze Erläuterungen zu den einzelnen Termen. Anfangsbedingungen Aus den obigen Differentialgleichungen ergibt sich ein Anfangswert-RandwertProblem. Zu Beginn der Simulation ist das Gebiet Ω mit Anfangswerten vorbelegt, die die Kontinuitätsgleichung erfüllen. Die Geschwindkeitskomponenten u und v werden mit u0 und v0 initialisiert, der Druck p mit p0. Zeit ∂u ∂v und zum Tragen. ∂t ∂t Unter diskreten Bedingungen lässt sich der Term folgendermaßen auffassen: aus einem gegeben Zeitschritt werden die neuen Geschwindigkeitskomponenten u und v zu einem späteren Zeitpunkt berechnet, die dann wiederum als Eingabe für den nächsten Schritt fungieren können. Der zeitliche Verlauf der Simulation kommt in den Termen Divergenzfreiheit ∂u ∂v + = 0 wird gefordert, dass die Geschwindigkeitsvekto∂x ∂y ren überall divergenzfrei sein müssen. Die Divergenzen müssen deswegen Null sein, damit die Massenerhaltung gewährleistet ist. Divergenzfreiheit bedeutet, dass in einem Gebiet Ω genau soviel Masse hineinfließt wie herausfließt, damit die Masse im Gebiet Ω immer gleich bleibt. In Kontinuitätsgleichung Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 40 von 99 Druck ∂p ∂p und werden die Vektoren an Rändern und an Hindernissen ∂y ∂x umso mehr abgelenkt, je senkrechter sie auf die Hindernisse treffen. Würde an Hindernissen kein Druck entstehen, würden in der Strömung mit geschwemmt werden. Der Druck ist eine Gegenkraft gegen den Strom. Hinter Hindernissen können sich je nach Viskosität des Fluids Wirbel bilden. Durch den Druck Diffusion 1 ∂ 2u ∂ 2u 1 ∂ 2v ∂ 2v 2 + 2 und kommt der diffusive Anteil der + Re ∂x 2 ∂y 2 ∂y Re ∂x Strömung zum Tragen. Unter Diffusion versteht man den gleichmäßigen Energieaustausch benachbarter Teilchen. Physikalisch entsteht die Diffusion durch Oberflächenkräfte, die zwischen den einzelnen Fluidelementen wirken. In den Termen In diesem Fall bedeutet das, dass die Richtung und Länge jedes Geschwindigkeitsvektors von seinen Nachbarvektoren beeinflusst wird. Lässt man die Diffusion alleine voranschreiten, ergibt sich im Laufe der Zeit ein homogenes Bild der Geschwindigkeitsvektoren. Die Diffusionsausbreitung ist unabhängig von der Richtung der Vektoren. Sie ist in alle Richtungen gleich groß, egal in welche Richtungen die Vektoren zeigen, da sich nur benachbarte Fluidelemente reiben. Konvektion (Advektion) ( ) ( ) ∂ u 2 ∂ (uv ) ∂ (uv ) ∂ v 2 − − und − , manchmal auch advektive ∂x ∂y ∂x ∂y Terme genannt, beschreiben den Fluss im Geschwindigkeitsfeld. Mit Hilfe dieses Terms werden Objekte entlang der Strömung bewegt. Dazu zählen nicht nur Partikel, die im Strom mitgetragen werden, sondern auch die Geschwindigkeit selbst. Geschwindigkeit wird in sich selbst fort getragen. Die konvektiven Terme − Dieser Term beschreibt den eigentlichen Strom. Die physikalische Herleitung dieser Terme erfolgt aus den Kräften, die zwischen den Massen der Fluidelemente wirken. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 41 von 99 Randbedingungen An den Rändern des Gebiets Ω müssen Randbedingungen gewählt werden, da man zwangsweise auf einem endlichen Gebiet rechnen muss. Es sind verschiedene Bedingungen denkbar, in dieser Simulation betrachten wir diese Vier: Haftbedingung (no-slip): Die Geschwindigkeit ist am Rand Null. Anschaulich haftet das Fluid am Rand. Rutschbedingung (free-slip): Die Geschwindigkeit senkrecht zum Rand ist Null, genauso wie die Normalableitung der Geschwindigkeit parallel zur Wand Null ist. Ausströmbedingung (outflow): Auf den Randbereich werden die unmittelbaren Nachbarn im Fluid senkrecht zum Rand gesetzt. Dadurch ändert sich die Geschwindigkeit senkrecht zum Rand nicht. Einströmbedingung (inflow): Die Geschwindigkeit wird am Rand fest vorgeben. Alle Einströmungen in dieser Simulation fließen vom linken Rand in das Innere des Gebiets ein. Eine Variante der Einströmbedingung ist die Bandbedingung. Im Kapitel Simulierte Probleme ab Seite 79 wird darauf näher eingegangen. Randwerte müssen auch an eventuellen Hindernissen, die im Gebiet Ω liegen, gesetzt werden. Siehe hierzu Kapitel 3.2.2 auf Seite 44. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 42 von 99 3.2. Diskretisierung Aus den obigen kontinuierlichen Navier-Stokes-Gleichungen muss eine diskretisierte Form abgeleitet werden, denn eine geschlossene, analytische Lösung der NavierStokes-Gleichungen ist im Allgemeinen nicht möglich. Bevor die Diskretisierung der Gleichungen betrachtet werden kann, muss erst das zugrunde liegende Gebiet Ω diskretisiert werden. Mit der Diskretisierung der Zeit kann letztendlich die Impulsgleichung und die Kontinuitätsgleichung diskretisiert werden. 3.2.1. Das Gebiet Das Gebiet Ω := [0, a ]× [0, b] ⊂ R 2 wird in imax Spalten und jmax Zeilen eingeteilt. Die Seitenlängen einer einzelnen Zelle δx und δy ergeben sich zu δx = a / imax und δy = a / jmax . Um die Randbedingung setzen zu können, müssen Randzellen, die das Gebiet umgeben, hinzugefügt werden. So ergibt sich ein Feld mit der Gesamtgröße von [imax+2] x [jmax+2] Zellen. Abbildung 26: Diskretisiertes Gebiet mit Randzellen Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 43 von 99 Damit die Navier-Stokes-Gleichungen im Diskreten numerisch stabil bleiben, werden die Geschwindigkeitskomponenten u und v, sowie der Druck p in einem so genannten Staggered Grid gespeichert. Zu Deutsch ein versetztes Gitter. Hier werden die drei Werte in einem jeweils um eine halbe Zelle zueinander versetztem Gitter abgespeichert. Die Idee dazu stammt aus der Finiten-Volumen-Technik. Hier werden die Geschwindigkeiten an alle Seitenwände jedes Würfels gesetzt um den Massenfluss zwischen Volumenzellen bei der Berechnung der Kontinuitätsgleichung zu bestimmen. Das Staggered Grid gewährleistet auch im Zweidimensionalen, dass der Druck nicht oszilliert. In [6] wird erklärt, warum das so ist. Neben dem Staggered Grid gibt es Diskretisierungen des Gebiets auf regulären Gittern. Bei einem Collcated Grid werden alle Werte im Zellenmittelpunkt gespeichert. Allerdings sind dann spezielle Interpolationsmethoden notwendig. Im Staggered Grid hingegen können alle Größen linear interpoliert werden. Wenn man die drei Gitter übereinander legt, kann man die Lage und Abstände der drei Komponenten zueinander sehen. Der Druck p liegt in der Mitte einer Zelle. Die xKomponente u der Geschwindigkeit liegt in der Mitte der senkrechten Zellenränder und die y-Komponente v der Geschwindigkeit liegt in der Mitte der waagrechten Zellenränder. Aus dem versetzten Gitter ergeben sich noch ein paar Besonderheiten am Rand des Gebiets, weil nicht alle Komponenten auf dem Rand des Gebiets Ω zu liegen kommen. Auf den senkrechten Rändern gibt es keine y-Komponente und auf den waagrechten Rändern gibt es keine x-Komponente. Die fehlenden Werte für die Ränder werden in die zusätzlichen Randzellen abgespeichert. Abbildung 27: Staggered Grid Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 44 von 99 3.2.2. Hindernisse Nach der bisherigen Beschreibung wird das Fluid in einem rechteckigen Gebiet berechnet. Für realistische Simulationen werden aber meist irreguläre Geometrien bzw. Topologien benötigt. Dazu wird ein weiteres Bitfeld verwendet, das mit einer Eins angibt, dass es sich bei dieser Zelle um eine Hinderniszelle, und bei einer Null um eine Fluidzelle handelt. Die Navier-Stokes-Gleichungen werden fortan nur noch in den Fluidzellen berechnet. Abbildung 28: Weiße Fluidzellen, graue Hinderniszellen, ungültige Zellen in Rot Je feiner man das Gitter wählt, desto genauer lassen sich bestimmte Geometrien darstellen. Genauso wie am Rand des Gebiets, müssen bei Hinderniszellen die Randbereiche nach einer entsprechenden Randbedingung gesetzt werden. Hier wird für die Randbedingung an Hinderniszellen stets die Haftbedingung verwendet. Das Fluid bleibt an den Hindernissen haften. Im Prinzip erfolgt das Setzen der Randwerte analog zum äußeren Rand. Jede Hinderniszelle wird daraufhin überprüft, an welcher Seite sie an eine Fluidzelle angrenzt. Dabei sind nur die waagrechten und senkrechten Nachbarn von Bedeutung, die diagonal angrenzenden Felder spielen keine Rolle. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 45 von 99 Wenn sie nur an eine Fluidzelle angrenzt, ist das Vorgehen einfach, da nur die Komponente aus der Fluidzelle negiert in die Hinderniszelle eingetragen werden muss. Durch die Negation ergibt sich in der linearen Interpolation zwischen Fluid- und Hinderniszelle eine Geschwindigkeit von Null am Rand – das Fluid haftet. Wenn zwei Fluidzellen an das Hindernis angrenzen, die übereck liegen, ergibt sich ebenfalls eine eindeutige Lösung. Durch das Staggered Grid grenzt jeweils nur eine der beiden Geschwindigkeitskomponenten an die Hinderniszelle an, und diese können negiert eingetragen werden. Nicht mehr eindeutig bestimmbare Randwerte kommen dann zustande, wenn eine Hinderniszelle zwischen zwei Fluidzellen liegt. Das ist insbesondere der Fall, wenn sie an drei oder mehr Fluidzellen angrenzen. In Abbildung 28 sind gültige Hinderniszellen in grau dargestellt, ungültige in Rot. Solche Zellen müssen eliminiert werden, bevor die Berechnung der Navier-Stokes-Gleichungen stattfinden kann. Ein explizites Setzen der Randwerte an Hinderniszellen ist bei der Berechnung der UV-Werte, sowie bei der Berechnung des Drucks p notwendig. 3.2.3. Die Zeit, das Stabilitätskriterium Das Zeitkontinuum wird durch diskrete Zeitpunkte ti ersetzt und die Geschwindigkeit und der Druck werden nur an diesen Zeitpunkten berechnet. Der Abstand zwischen zwei Zeitpunkten ti und ti+1 wird durch ein geeignet gewähltes ∆t gesetzt. Entweder setzt man ∆t am Anfang der Simulation auf einen festen Wert, oder es wird je nach Strömungsgeschwindigkeit und Reynoldszahl dynamisch gewählt. ∆t ist ein entscheidender Stabilitätsfaktor für die diskretisierten Navier-Stokes-Gleichungen und darf nie zu groß gesetzt werden. Andernfalls können Oszillationen entstehen, die die Berechnung unbrauchbar machen. Die Stabilitätsbedingungen heißen Courant-Friedrichs-Levi-Bedingungen (CFL). −1 Re 1 1 δx δy 2 + 2 , ∆t = τ min , 2 δx δy u max vmax Es muss zu jedem Zeitpunkt gewährleistet sein, dass ein Geschwindigkeitsvektor nie weiter als in seine Nachbarzellen zeigt. Wird ein Vektor zu lang, so muss ∆t entsprechend kleiner gesetzt werden, damit die Bedingung erfüllt ist. Damit das für alle Vektoren im Feld gilt, werden die längsten Komponenten umax und vmax bestimmt. Dies wird in den hinteren beiden Teilen der Minimumsbildung ausgedrückt. Die zweite Schranke für ∆t ergibt sich aus der Reynoldszahl und der Zellengröße des Gitters im ersten Teil der obigen Gleichung. Der Faktor τ ∈ ]0,1] ist ein Sicherheitsfaktor, der das berechnete ∆t weiter absenken kann. In der Praxis kommt es vor, dass eine Simulation trotzdem oszillieren kann, auch wenn das Minimum korrekt berechnet worden ist. So kann ∆t weiter nach unten korrigiert werden. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 46 von 99 Neben der Bestimmung von ∆t muss auch für jeden Term festgelegt werden, zu welchem Zeitpunkt man ihn auswertet. Bei den Impulsgleichungen werden die Terme auf der linken Seite, also die Geschwindigkeit nach der Zeit und der Druck zum Zeitpunkt n+1 ausgewertet. Die Terme auf der rechten Seite werden alle zum Zeitpunkt n berechnet. Andere Festlegungen für die Zeitpunkte der einzelnen Terme sind auch denkbar, aber praktikabel ist nur diese. Daraus ergibt sich für die Terme auf der rechten Seite ein explizites Lösungsverfahren, während die Terme auf der linken Seite, im Besonderen der Druck, implizit gelöst werden. 3.2.4. Die Impulsgleichung Für die Diskretisierung werden finite Differenzenverfahren verwendet, wie sie auch schon bei der Wassersimulation in Kapitel 2 verwendet wurden. Als Besonderheit sei bei den konvektiven Termen auf den Zusatzterm α hingewiesen, der die numerische Stabilität sichert. Die Zeitableitungen ∂v ∂u und werden mit einer Vorwärtsdifferenz ausgedrückt: ∂t ∂t u ∂u ∂t := i, j v ∂v ∂t := i, j ( n +1) − u (n ) δt ( n +1) − v (n ) δt Die erste Impulsgleichung für die x-Komponente u wird an den Mittelpunkten der senkrechten Zellenkanten diskretisiert. Den konvektiven Term − ( ) ∂ u 2 ∂ (uv ) ersetzt man durch − ∂x ∂y ( ) ∂ u2 1 ui , j + ui +1, j : = ∂x 2 i , j δx α und 2 ui −1, j + ui , j − 2 2 + 1 ui , j + ui +1, j (ui , j − ui +1, j ) ui −1, j + ui , j (ui −1, j − ui , j ) − δx 2 2 2 2 ∂ (uv ) 1 (vi , j + vi +1, j )(ui , j + ui , j +1 ) (vi , j −1 + vi +1, j −1 )(ui , j −1 + ui , j ) + : = − ∂y 2 2 2 2 i , j δy α 1 vi , j + vi +1, j (ui , j − ui , j +1 ) (vi , j −1 + vi +1, j −1 ) (ui , j −1 − ui , j ) − δy 2 2 2 2 Echtzeitfähige Simulation von Wasser auf Grafikhardware Der diffusive Term Seite 47 von 99 1 ∂ 2u ∂ 2u wird durch folgenden Term ausgedrückt: + Re ∂x 2 ∂y 2 ui +1, j − 2ui , j + u i −1, j ∂ 2u 2 := (δx )2 ∂x i , j ui , j +1 − 2ui , j + u i , j −1 ∂ 2u 2 := (δy )2 ∂y i , j Bleibt als letztes noch der Druck, der durch eine Vorwärtsdifferenz diskretisiert wird: pi +1, j − pi , j ∂p ∂x := δx i, j Die Variablen i und j laufen, bedingt durch das Staggered Grid, im Bereich i = 1,..., imax − 1 j = 1,..., jmax Vollkommen analog wird die Impulsgleichung für die y-Komponente v diskretisiert. Die Konvektion − ( ) ∂ (uv ) ∂ v 2 wird durch − ∂x ∂y 1 (ui , j + ui , j +1 )(vi , j + vi +1, j ) (ui −1, j + ui −1, j +1 )(vi −1, j + vi , j ) ∂ (uv ) + : = − ∂x δ 2 2 2 2 x i, j α 1 ui , j + ui , j +1 (vi , j − vi +1, j ) (ui −1, j + ui −1, j +1 )(vi −1, j − vi , j ) − δx 2 2 2 2 und ( ) 2 ∂ v2 1 vi , j + vi , j +1 vi , j −1 + vi , j − ∂y := δy 2 2 i, j α ersetzt. 2 + 1 vi , j + vi , j +1 (vi , j − vi , j +1 ) vi , j −1 + vi , j (vi , j −1 − vi , j ) − δy 2 2 2 2 Echtzeitfähige Simulation von Wasser auf Grafikhardware Die Diffusion Seite 48 von 99 1 ∂ 2v ∂ 2v wird durch + Re ∂x 2 ∂y 2 vi +1, j − 2vi , j + vi −1, j ∂ 2v 2 := (δy )2 ∂x i , j vi , j +1 − 2vi , j + vi , j −1 ∂ 2v : = 2 (δy )2 ∂y i , j ersetzt. Abschließend wird der Druck durch pi , j +1 − pi , j ∂p : = ∂y δy i, j diskretisiert. Der Bereich für die Variablen i und j liegt für die y-Komponente i = 1,..., imax j = 1,..., jmax − 1 Der Faktor α liegt hierbei im Bereich zwischen 0 und 1. Mit α = 0 wird der zweite Teil der Gleichungen ausgeblendet, womit man eine Zentraldifferenz erhält. Mit α = 1 erhält man die Doner-Cell-Diskretisierung. Nähere Informationen hierzu gibt es in [6]. Nach [20] muss α folgende Gleichung erfüllen: α ≥ max ui , j i, j δt δt , vi , j δx δy In der Praxis verwendet man meist den konstanten Wert 0.5. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 49 von 99 3.2.5. Die Kontinuitätsgleichung Die Bedingung der Divergenzfreiheit wird durch ui , j − ui −1, j ∂u : = ∂x δx i, j vi , j − vi , j −1 ∂v ∂y := δy i, j diskretisiert und i, j sind im Bereich i = 1,..., imax j = 1,..., jmax Mit Hilfe der Kontinuitätsgleichung wird im Kapitel 3.3.2 auf Seite 51 die rechte der Seite der Poisson-Gleichung für den Druck p berechnet. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 50 von 99 3.3. Der Algorithmus Nachdem die kontinuierlichen Navier-Stokes-Gleichungen diskretisiert wurden, fehlt noch ein Algorithmus, der das ganze berechnet. Außerdem wird hier auf die Problematik der Druckberechnung näher eingegangen, denn dieser wird nach obiger Zeitdiskretisierung zum Zeitpunkt n+1 benötigt. Nach der Initialisierung der Felder U, V und P mit den Anfangswerten, beginnt die äußere Zeitschleife, die genau einen Zeitschritt von tn auf tn+1 berechnet. Innerhalb dieser Schleife werden die neuen Geschwindigkeitsvektoren U und V sowie der neue Druck P zum Zeitpunkt tn+1 berechnet. In dieser Implementierung ist die Zeitschleife eine Endlosschleife, sie kann aber jederzeit durch den Benutzer unterbrochen werden bzw. neu gestartet werden. 3.3.1. Die Berechnung der Diffusion und Konvektion Die Impulsgleichungen werden zuerst so umgestellt, dass auf der linken Seite nur noch u bzw. v zum Zeitpunkt n+1 vorkommen. Mit den Variablen F und G werden fortan die u,v-Werte zum Zeitpunkt n, die sich aus der Addition der diffusiven und konvektiven Anteile, sowie der äußeren Einflusskraft g berechnen. ( ) 1 ∂ 2u ∂ 2 u ∂ u 2 ∂ (uv ) + 2 − − + g x ; Fi , j = ui , j + ∂t Re ∂x 2 ∂y i , j ∂x i , j ∂y i , j i, j Wieder durch das Staggered Grid bedingt ergeben sich diese Laufindizes für i und j i ∈ [1; imax − 1], j ∈ [1; jmax ] Analog ergibt sich für G: ( ) 1 ∂ 2v ∂ 2 v ∂ (uv ) ∂ v2 ; − + Gi , j = vi , j + ∂t 2 + 2 − g y ∂y Re ∂x ∂ x ∂ y i, j i, j i, j i, j Mit i,j im Bereich i ∈ [1; imax ], j ∈ [1; jmax − 1] Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 51 von 99 In dieser Schreibweise ergeben sich für die u,v-Werte zum Zeitpunkt n+1 folgende diskretisierte Impulsgleichungen: ui(,nj+1) = Fi ,(nj ) − δt (n+1) pi +1, j − pi(,nj+1) ) ( δx i ∈ [1; i max − 1]; j ∈ [1; j max ] vi(,nj+1) = Gi(,nj) − δt (n+1) ( pi, j+1 − pi(,nj+1) ) δy i ∈ [1; i max ]; j ∈ [1; j max − 1] Der Druck ist die letzte Komponente, die noch berechnet werden muss, bevor der Algorithmus komplett ist. 3.3.2. Die Berechnung des Drucks Der rechenintensivste Teil der Strömungssimulation ist die Berechnung des Drucks. Zunächst benötigt man die rechte Seite der Druckgleichung, damit der Druck bestimmt werden kann. Die rechte Seite ergibt sich aus der Kontinuitätsgleichung und den F-G-Werten aus dem vorherigen Abschnitt: rs = (n ) (n ) (n ) (n ) 1 Fi , j − Fi −1, j Gi , j − Gi , j −1 + δt δx δy Die linke Seite dieser so genanten Poisson-Gleichung ergibt sich aus der Diskretisierung des Drucks wie folgt: pi(+n1+,1j) − 2 pi(,nj+1) + pi(−n1+,1j) (δx )2 + pi(,nj++11) − 2 pi(,nj+1) + pi(,nj+−11) (δy )2 (n ) (n ) (n ) (n ) 1 Fi , j − Fi −1, j Gi , j − Gi , j −1 = + δt δx δy Wie aus obiger Formel ersichtlich, benötigt man den Druck im Zeitpunkt n+1. Das läuft auf ein Gleichungssystem hinaus, das mit einem geeigneten Lösungsverfahren berechnet werden muss. Eine Gausselimination wäre denkbar, aber da die Matrix eine Bandmatrix mit fünf Bändern ist, sind iterative Verfahren besser geeignet. Sie lösen das Gleichungssystem sehr viel schneller, auch wenn der Restfehler erst nach mehreren Iterationen gering wird. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 52 von 99 Gauss-Seidel-Verfahren Der erste Versuch einen Gleichungssystemlöser zu implementieren war das GaussSeidel-Verfahren auf der GPU zu programmieren. Bei diesem Verfahren werden bei der Berechnung der Drucks p an der Stelle (i,j) benachbarte Werte benötigt. Dieses Verfahren funktioniert nur, wenn das Feld linear von links oben nach rechts unten abgearbeitet wird, weil bei der Berechnung des Drucks in Zelle (i,j) der linke und der obere Werte von p schon aus der aktuellen Iteration stammen muss, während der rechte und untere Werte von p noch aus der letzten Iteration kommt. In einer Software-Lösung ist diese Abarbeitungsfolge kein Problem, in Grafikhardware hat man darüber keine Kontrolle. Abbildung 29: Gauss-Seidel-Verfahren Abgesehen von der Abarbeitungsfolge kann man überhaupt nicht auf bereits geschriebene Elemente zugreifen, weil intern alle Daten erst in eine Schattentextur geschrieben und erst am Ende des Passes sichtbar werden. Aus diesen Gründen ist das Gauss-Seidel-Verfahren auf Grafikhardware in dieser Form nicht umsetzbar. Einen anderen Ansatz um das das Gauss-Seidel-Verfahren dennoch von der GPU berechnen zu lassen wird in [7] vorgestellt. Für diese Zwecke ist es allerdings nicht effizient umzusetzen. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 53 von 99 Konjugierte Gradienten-Verfahren Im zweiten Anlauf wurde ein konjugiertes Gradienten Verfahren verwendet, das im Rahmen des clFramework implementiert wurde. Wie auch das Gauss-SeidelVerfahren wird es in [7] genau beschrieben. Abgesehen von der manchmal auftretenden Divergenz des Verfahrens, wird der Druck schon mit sehr wenigen Iterationen brauchbar angenähert. Um möglichst viel Geschwindigkeit aus dem Programm herauszuholen, wurden meist nur zwei Iterationen verwendet. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 54 von 99 3.3.3. Der gesamte Algorithmus Jetzt sind alle Teile, die zur Berechnung der Navier-Stokes-Gleichungen notwendig sind, vorhanden und können nach folgendem Schema berechnet werden. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Setze Zeit t:=0 Belege die Felder U,V und P überall mit den Initialwerten u0, v0, p0 Wiederhole (Zeitschleife) Berechne ∆t nach den Stabilitätsbedingungen Setze Randwerte für U und V am äußeren Rand Setze Randwerte für U und V an den Hinderniszellen Berechne F und G Setze Randwerte für F und G am äußeren Rand Setze Randwerte für F und G an den Hinderniszellen Berechne die rechte Seite der Druckgleichung Setze it:=0 Solange it < itermax oder residuum < eps Setze Randwerte für den Druck am äußeren Rand Setze Randwerte für den Druck an den Hinderniszellen Führe eine Druck-Iteration durch It++ Aktualisiere U und V über F, G und P t = t + ∆t Die Anzahl der Iterationen, die zur Berechnung des Drucks verwendet werden, sind an zwei Abbruchkriterien gekoppelt. Zum einen kann eine maximale Anzahl von Iterationen itermax vorgegeben werden. Zum anderen kann nach jeder Iteration ein Residuum berechnet werden, das bestimmt, wie weit die aktuelle Lösung von der richtigen Lösung entfernt ist. Erst wenn das Residuum unter eine gewisse EpsilonSchranke fällt, wird die Schleife verlassen. Die Epsilon-Schranke kann hierbei beliebig klein gewählt werden. Eine Epsilon-Schranke von ca. 10-4 ist ein üblicher Wert. Durch das verwendete konjugierte Gradienten-Verfahren wird dieses Residuum aber meist nicht erreicht. Das Abbruchkriterium wird im Normalfall durch das Überschreiten der maximalen Anzahl der Iterationen erfüllt. Somit ist die theoretische Diskretisierung abgeschlossen. Im nächsten Kapitel geht es um die Umsetzung des obigen Algorithmus auf der GPU. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 55 von 99 3.4. Implementierung In diesem Abschnitt geht es um die konkrete Umsetzung des obigen Algorithmus auf der Grafikkarte. Als Grafik-API wurde DirectX 9.0 von Microsoft verwendet. In dieser Version wurde eine neue Hochsprache, die High-Level-Shader-Language (HLSL), integriert, mit Hilfe derer man Vertex- und Pixel-Shader-Programme auf hohem Abstraktionsniveau entwickeln kann. Bisher musste man Shader in Assembler programmieren. Wie schon im ersten Teilprojekt in Kapitel 2 wurde die Umsetzung ausschließlich mit Pixel-Shader Programmen auf Fragmentbasis implementiert. Vertex-Shader Programme in der Geometrieverarbeitung wurden nicht benötigt. Zunächst wird beschrieben, wie die Daten der Felder gespeichert werden. Danach werden Vertex-Buffer besprochen, mit denen man gezielte Bereiche der Felder bzw. Texturen von der GPU bearbeiten kann. Anschließend folgt ein kurzer Abschnitt über die Shader-Programme, insbesondere über den BoundaryUV-Shader, der eine Sonderstellung einnimmt. Mit Hilfe dieser Einzelteile können dann die Renderingstufen betrachtet werden. Abschließend folgen Geschwindigkeitsmessungen. 3.4.1. Texturen Zur Speicherung der einzelnen Komponenten im Gebiet Ω werden vier Texturen verwendet. Ihre Größe hängt alleine von der Anzahl der simulierten Zellen ab. Ein Randpixel wird automatisch hinzugefügt. Auch wenn man zunächst durch das Staggered Grid eine komplizierte Speicherung und Adressierung der einzelnen Texturelemente vermuten möchte, ergibt sich die korrekte Adressierung schlicht aus der Diskretisierung und man kann alle vier Texturen gleich groß anlegen, auch wenn bei manchen Komponenten nicht alle Zellen benötigt werden. Das Texturformat ist immer ein 32-Bit Fließkommaformat mit einer oder vier Komponente und die Größe ist immer [imax+2] x [jmax+2] Texel bzw. Zellen. Die erste Textur ist die UVFG-Textur, die pro Zelle in der x-y-Komponente den Geschwindigkeitsvektor UV, und in der z-w-Komponente, die FG-Werte aus der Impulsgleichung hält. x u y v = z f w i, j g i, j In den folgenden zwei Texturen mit je einer Komponente werden die rechte Seite der Druckgleichung und der Druck berechnet. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 56 von 99 (x )i , j = (rs )i , j (x )i , j = ( p )i , j Als letztes fehlt noch eine Ablage für die Hindernisinformationen. Dazu wird die Obstacles-Textur verwendet. x fluid | obstacle shape y z = right − shift w i , j top − shift i , j In der x-Komponente steht ein binärer Wert, der anzeigt, ob es sich hier um eine Hinderniszelle oder um eine Fluidzelle handelt. Eine Eins bedeutet, dass diese Zelle ein Hindernis ist, andernfalls ist es eine Fluidzelle. Der Shape-Wert in der yKomponente erhielt seinen Namen deswegen, weil er genau die Randzellen von Hindernissen vorberechnet und hier Nachbarschaftsrelationen ablegt. Shape-Zellen sind also Hinderniszellen, die an eine oder mehrere Fluidzellen angrenzen. Im Shape-Wert werden die acht möglichen Nachbarn der Zelle betrachtet, welche Fluidzellen bzw. Hinderniszellen sind, und in einem Bitfeld abgespeichert. An dieser Stelle sei nochmals darauf hingewiesen, dass eine Hinderniszelle maximal an zwei Fluidzellen angrenzen darf, und diese dürfen auch nicht gegenüberliegen, weil sich sonst die Randbedingung für diese Hinderniszellen nicht mehr eindeutig festlegen lässt. Die anderen beiden Werte right-shift und top-shift sind Hilfsvariablen. Beim Setzen der Randbedingungen an einer Hinderniszelle (i,j) müssen je nach Shape gegebenenfalls auch die Zellen (i-1,j) oder (i,j+1) verändert werden. Diese Notwendigkeit ist auf das Staggered Grid zurückzuführen. Da in einem Pixel-Shader-Programm aber nur die Zelle (i,j) verändert werden kann, werden beim Berechnen von (i,j) die ShiftWerte überprüft, ob sich eine Zelle rechts (i+1,j) oder oberhalb (i,j-1) befindet. Entsprechend ihres Shift-Wertes werden dann die Randbedingungen umgesetzt. Eine zusätzliche vierte Textur speichert die Informationen für den Partikelverfolger, der im Kapitel 3.4.6 auf Seite 69 näher erläutert wird. Hier wird nur eine Komponente benötigt, die die Dichte der Partikel in einer Zelle festhält. Der Wertebereich liegt zwischen Null und Eins. (x )i , j = ( particle density )i , j Für jede der hier vorgestellten Texturen gibt es eine Schattentextur, die im Hauptspeicher des Rechners liegt. Vor jedem Reset des Direct3D-Device werden die Texturen in ihre entsprechenden Schattentexturen im Hauptspeicher kopiert und beim Wiederaufbau aus ihnen wieder zurückkopiert. So ist gewährleistet, dass die Simulation beim Vergrößern des Fensters nicht verloren geht. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 57 von 99 3.4.2. Vertex-Buffer Durch die Randbedingungen und das Staggered Grid müssen in den einzelnen Schritten des Algorithmus verschiedene Bereiche der Textur beschrieben werden. Auf Grund der aktuellen Implementierung der GPUs werden in Shader bei Verzweigungen im Code immer alle Äste ausgeführt – wobei nur der richtige Ast seine Ergebnisse zurückschreiben darf. Verzweigungen kosten also sehr viel Rechenzeit und sollten vermieden werden. Um zum Beispiel die Randbedingungen zu setzen, müsste ein Shader beim Durchlaufen der gesamten Textur jedes Mal abprüfen, ob er sich gerade am Rand befindet oder nicht, und es würden pro Pixel die Bedingungen berechnet, auch wenn sie nicht in die Textur geschrieben werden. Ein Ausweg um keine unnötigen Operationen zu berechnen sind Vertex-Buffer, die nur bestimmte Bereiche der Textur überdecken. Dazu wird ein Quadrat, das nur einen bestimmten Teil der Textur überdeckt, über vier Vektoren in einem Vertex-Buffer abgelegt. Sie dienen als Schablone, auf welchen Bereichen die Shader-Programme die Texturen bearbeiten sollen. Der Vertex-Buffer Full überdeckt die gesamte Textur inklusive Rand. Wichtiger ist der Vertex-Buffer Inner, der von den meisten Shadern verwendet wird. Der äußere Rand wird bei diesem Vertex-Buffer nicht verändert. Beispiele sind das Setzen der Hindernisrandbedingungen im UV-Feld und die Berechnung von F und G. Für das Setzen der äußeren Randbedingungen im FG-Feld werden spezielle VertexBuffer benutzt, in der folgenden Abbildung bläulich dargestellt. Es gibt je einen für die vier Ränder, wobei jeweils der Eckrandwert nicht überschrieben wird: Top0, Bottom0, Left0, Right0. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 58 von 99 Abbildung 30: Vertex-Buffer Full, Inner (grau), Top0, Bottom0, Left0, Right0 Für die äußeren Randbedingungen im UV-Feld benötigt man im Staggered Grid noch einen weiteren Satz von rechteckigen Bereichen. Die Top1-, Bottom1-, Right1- und Left1-Vertex-Buffer entsprechen den die Top0-, Bottom0-, Right0- und Left0-VertexBuffer mit dem Unterschied, dass jeweils die Eckzelle enthalten ist. Des Weiteren sind noch zwei Vertex-Buffer notwendig, die sich am rechten und unteren Rand jeweils eine Zelle weiter innen im Feld befinden. Diese sind wegen des Staggered Grids notwendig, da sich der rechte Rand für die U-Komponente eine Zelle im Inneren befindet. Analog ist der Rand für die V-Komponente die zweit-unterste Zelle. Ihre Namen sind dementsprechend Right12 und Bottom12. Als letzen Vertex-Buffer benötigt man noch einen für die Darstellung im Framebuffer. Er kann beliebig gewählt werden. Je nach dem, ob man die Randbereiche anzeigen lassen will oder nicht, verschiebt man die Texturkoordinaten entsprechend nach innen. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 59 von 99 Abbildung 31: Randbedingungen im Staggered Grid 3.4.3. Die Shader-Programme Ein limitierender Faktor bei der Erstellung von Shader-Programmen ist die derzeitig maximale Länge von 64 Instruktionen bei Pixel-Shader Programmen. Bei VertexShadern liegt die Zahl höher, aber für diese Problematik können nur Pixel-ShaderProgramme verwendet werden, da immer auf Felder operiert wird. Die Limitierung der Shader-Länge stammt aus dem Pixel-Shader 2.0 Standard. Erst mit dem PixelShader 3.0 Standard dürfen auch Pixel-Shader-Programme länger sein. Doch momentan gibt es keine Grafikkarte, die schon jetzt diesen Standard unterstützt. Daraus ergibt sich, wie man im nächsten Abschnitt sehen kann, oftmals eine Aufteilung eines logischen Verarbeitungsschritts in mehrere einzelne Shader. Die Berechnung von F und G ist in zwei getrennte Shader-Programme aufgeteilt, die jeweils fast an das 64-Instruktionslimit stoßen. Wenn längere Shader-Programme möglich wären, würde viel Overhead wegfallen, der bei jedem Shader-Programm am Anfang steht. Zum Beispiel entfiele das Auslesen der Textur an den Nachbarstellen. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 60 von 99 Die Shader-Programme sind logisch sortiert in mehrere Dateien aufgeteilt: Impulse.hlsl o Setzen der Randbedingungen im UV-Feld o Berechnung von FG o Setzen der Randbedingungen im FG-Feld o Einfügen von Geschwindigkeit mit der Maus o Update von UV mit FG und Druck Poisson.hlsl o Berechnung der rechten Seite der Poisson-Gleichung o Setzen der Druckrandbedingungen Obstacles.hlsl o Einfügen und Entfernen von Hinderniszellen o Berechnung der Shape- und Shift-Vorberechnungen für Hinderniszellen o Löschen illegaler Hinderniszellen o Importieren von Grafiken als Hinderniskarte Particles.hlsl o Einfügen von Partikeln mit der Maus o Partikeldiffusion o Partikelverfolgung o Einfügen von Partikelpinseln aus Grafiken View2D.hlsl o Darstellung der Geschwindigkeit UV als Farbkodierung o Darstellung der Partikel als Grauwerte o Darstellung der Hindernisse mit Blau o Darstellung des Drucks im roten Farbkanal o Berechnung und Darstellung der Wirbelstärke Zusätzlich enthalten die Klassen aus dem clFramework für den iterativen Gleichungsystemlöser weitere Shader-Programme zur Berechnung des Drucks. Ein besonderer Shader ist der BoundaryUV-Shader, der die Bedingung am äußeren Rand im UV-Geschwindigkeitsfeld berechnet. Während alle anderen ShaderProgramme im Verzeichnis shaders/ als statische Programme abgelegt sind, wird der BoundaryUV-Shader dynamisch zur Laufzeit erzeugt. Für jeden der vier Ränder Oben, Rechts, Unten und Links kann entweder eine Haftbedingung, eine Rutschbedingung oder eine Ausströmbedingung gewählt werden. Des Weiteren kann ein Simulationstyp gewählt werden, der eine Einströmbedingung in einem bestimmten Teilbereich der Ränder setzt. Folgende Simulationen sind definiert: Driven Cavity: Zieht am oberen Rand ein Band mit der Geschwindigkeit 1.0 nach rechts. Diese Bedingung wird für die Nischenströmung benötigt. Waterfall: Definiert am linken Rand ab der Hälfte bis zum oberen Rand ein Einströmen mit der Initialgeschwindigkeit UV0. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 61 von 99 Ocean: Setzt an allen Rändern die Geschwindigkeit fest auf UV0. Dieses Profil wird beispielsweise bei der Wirbelstraße oder der Stufenströmung benötigt. Inject: Definiert ein Einspritzen in das Feld von der linken Seite. Dazu wird am linken Rand in der Mitte die Geschwindigkeit fest auf UV0 gesetzt. Nur wenn der Benutzer diese Bedingung explizit ändert, ergibt sich ein neuer Pfad durch die relativ aufwändige Verzweigung. Diese ist deswegen so aufwändig, weil es sehr viele mögliche Fälle gibt. Der dynamische Shader soll es nun möglich machen, nur den Pfad im Shader ausführen zu lassen, der gerade vom Benutzer gewählt wurde. In der Implementierung stehen alle möglichen Fälle als Text- bzw. Stringbausteine im Shader-Quellcode zur Verfügung, die je nach Benutzereingabe selektiert und zusammengesetzt werden. Anschließend wird dieser neue Shader übersetzt. Dieser Prozess findet nur statt, wenn der Benutzer die Randbedingung bzw. den Simulationstyp ändert. In der laufenden Simulation wird der kompilierte Shader ausgeführt. Abbildung 32: Dynamischer Zusammenbau des BoundaryUV-Shaders Durch den dynamischen Shader entsteht keine einzige Verzweigung und die Abarbeitung ist sehr schnell. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 62 von 99 3.4.4. Die Rendering Pipeline Die Rendering Pipeline folgt dem vorgestellten Pseudo-Algorithmus aus Kapitel 3.3.3 auf Seite 54. Jede einzelne Render-Funktion beschreibt mit Hilfe seines PixelShader-Programms eine der vier Texturen. Die Aufrufe der einzelnen Funktionen erfolgt über DirectX, die Ausführung der konkreten Rechenoperationen erfolgt auf der Grafikkarte. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Setze Zeit t:=0 RenderUVFGPRSReset Wiederhole (Zeitschleife) ∆t = RenderDeltaT RenderImpulseUVBoundaryOuter RenderImpulseUVBoundaryObstaclesShape RenderImpulseUVBoundaryObstaclesShift RenderImpulseF RenderImpulseG RenderImpulseFGBoundary RenderPressureRightSide Setze it:=0 PressureSolveInitialize Solange it < itermax oder residuum < eps RenderPressureBoundary residuum = RenderPressureSolveIteration it++ RenderImpulseUVFGP Particlessiehe Kapitel 3.4.6 auf Seite 69 t = t + ∆t Im folgenden C-Quellcode wird exemplarisch an RenderImpulseUVBoundaryObstaclesShape gezeigt, wie der Aufruf eines Shader-Programms von DirectX aus erfolgt. Zunächst wird das Ziel der Shader-Berechnungen über RenderToSurface (Zeile 3) die UVFG-Textur festgelegt. Anschließend werden mit der SetFloat-Methode (ab Zeile 9) alle nötigen Konstanten an das Shader-Programm übergeben. Im nächsten Abschnitt werden sie genauer beschrieben. Nun folgen die Eingabetexturen ab Zeile 34. Für die Berechnung von F werden die UVFG-Textur, die zugleich auch das Schreibziel des Shader-Programms ist, und die Hindernistextur übergeben. Über SetTechnique in Zeile 41 wird ein konkretes Shader-Programm ausgewählt, das ausgeführt werden soll, in diesem Fall ImpulseF. Da eine Technique aus mehreren Passes bestehen kann, wird in der nachfolgenden Schleife (ab Zeile 46) über die Anzahl der Passes gelaufen und der jeweilige Pass selektiert (Zeile 48). Echtzeitfähige Simulation von Wasser auf Grafikhardware 1 2 3 4 5 6 Seite 63 von 99 HRESULT CMyD3DApplication::RenderImpulseF() { if (SUCCEEDED(m_pRenderToSurface->BeginScene( m_pSurfUVFG, NULL))) { HRESULT hr; 7 8 9 10 // set texture step hr = m_pShaderImpulse->SetFloat("tsx", m_vTS.x); hr = m_pShaderImpulse->SetFloat("tsy", m_vTS.y); 11 12 13 14 15 16 // set dx, dy hr = m_pShaderImpulse->SetFloat("dx4", 1.0f / (4.0f * m_vDArea.x)); hr = m_pShaderImpulse->SetFloat("dy4", 1.0f / (4.0f * m_vDArea.y)); 17 18 19 20 // set 1/dx², 1/dy² hr = m_pShaderImpulse->SetFloat("rdx2", m_vRD2Area.x); hr = m_pShaderImpulse->SetFloat("rdy2", m_vRD2Area.y); 21 22 23 // set 1 / Reynolds hr = m_pShaderImpulse->SetFloat("Re", 1.0f / m_fRe); 24 25 26 // set alpha hr = m_pShaderImpulse->SetFloat("alpha", m_fAlpha); 27 28 29 // set dt hr = m_pShaderImpulse->SetFloat("dt", m_fDT); 30 31 32 // set GX hr = m_pShaderImpulse->SetFloat("gx", m_vG.x); 33 34 35 36 37 38 // set textures hr = m_pShaderImpulse->SetTexture("tUVFG", m_pTexUVFG); hr = m_pShaderImpulse->SetTexture("tObstacles", m_pTexObstacles); 39 40 41 // setup technique hr = m_pShaderImpulse->SetTechnique("ImpulseF"); 42 44 45 46 47 48 UINT cPasses,iPass; m_pShaderImpulse->Begin(&cPasses, 0); for (iPass = 0; iPass < cPasses; iPass++) { hr = m_pShaderImpulse->Pass(iPass); 49 // render using inner vertex-buffer m_pd3dDevice->SetStreamSource( 0, m_pVBInner, 0, sizeof(CUSTOMVERTEX) ); 50 51 52 53 m_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); 53 54 m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 ); 55 56 57 } Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 64 von 99 m_pShaderImpulse->End(); 58 59 // done rendering to texture m_pRenderToSurface->EndScene(0); 60 61 62 return S_OK; 63 64 } 65 66 return S_FALSE; 67 68 } Im Inneren der Schleife folgt jetzt die Wahl des Vertex-Buffer in SetStreamSource in Zeile 51. Damit wird festgelegt, welcher Bereich der Textur beschrieben werden soll. Mit pVBInner wird der innere Bereich des Gebiets Ω ohne Rand bearbeitet. Der eigentliche Start des Shader-Programms erfolgt dann in Zeile 55 mit dem Aufruf von DrawPrimitive, das den Vertex-Buffer rendert und den Pixel-Shader ausführt. Abschließend kommen noch Aufräumarbeiten ab Zeile 58 um das Shader-Programm und die Szene zu beenden. 3.4.5. Ein Beispiel Shader in HLSL: ImpulseF Hier wird beispielhaft der ImpulseF-Shader im Quellcode gezeigt, um einen Eindruck zu bekommen, wie die High-Level-Shader-Language (HLSL) aussieht. Dieses Programm berechnet die Variable F, wie sie in der Diskretisierung beschrieben ist. In den Zeilen 1 – 13 werden die Variablen definiert, die vom DirectX-C-Programm an das Shader-Programm übergeben werden. Texturkoordinaten werden immer auf [0;1] normalisiert, deswegen muss dem Shader mitgeteilt werden wie groß der Abstand zu Nachbarpixeln ist, damit er auf sie zugreifen kann. Die Variablen tsx und tsy (Zeile 1 und 2) enthalten diese Werte wobei tsx = 1 / (Zellenanzahl in x-Richtung) und tsy = 1 / (Zellenanzahl in y-Richtung) sind. Alle Variablen, die vorberechenbar sind, werden als weitere Konstanten übergeben, um im Shader keine Rechenzeit zu verschwenden. Für die Berechnung der Diffusion werden die Variablen rdx2 und rdy2 (Zeile 4 und 5) vorbestimmt. rdx 2 = 1 ; (δx )2 rdy 2 = 1 (δy )2 Alle weiteren Konstanten Re, dt, gx, alpha (Zeile 7 – 10) und die Texturen (Zeile 12 und 13) werden unverändert an den Shader übergeben. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 65 von 99 Die Struktur vertex2pixel in Zeile 17 – 21 definiert das Datenübergabeformat vom Vertex-Shader zum Pixel-Shader. Vertex-Shader werden hier nicht gebraucht, weil in der Geometrieverarbeitung keine Besonderheiten notwendig sind. In diesem Fall wird automatisch die Fixed-Function-Pipeline verwendet. Essentiell ist hier die Texturkoordinate, die zwischen den Vertices bilinear interpoliert wird. Jeder Pixel, der bearbeitet wird, kennt somit seine Texturposition. Um auf Texturen zugreifen zu können, braucht man für jede einen sampler (ab Zeile 23 und 33), der die Textur und den Zugriffsmodus festlegt. MinFilter und MagFilter bestimmen, ob die Textur nur an einem Punkt ausgelesen werden soll, oder ob man bilineare Interpolation wünscht. Im Falle von Fließkommatexturen, wie sie hier immer verwendet werden, wird hardwareseitig nur das Punktauslesen unterstützt. Lineare Interpolation ist nicht definiert. AddressU und AddressV bestimmen das Verhalten am Rand der Textur. Falls die Texturkoordinaten außerhalb [0;1] liegen sollten, bestimmen diese Parameter, an welcher Stelle die Textur ausgelesen werden soll. Clamp setzt negative Werte auf Null und Werte größer Eins auf Eins zurück. Mirror spiegelt Koordinaten außerhalb des Bereichs ins Innere zurück und Wrap macht die Textur periodisch. 1 2 float float tsx; tsy; // texture step x // texture step y float float rdx2; rdy2; // 1 / (dx*dx) // 1 / (dy*dy) float float float float Re; dt; gx; alpha; // Reynolds number // Delta t // forces from outside 3 4 5 6 7 8 9 10 11 12 13 texture tUVFG; texture tObstacles; 14 15 ////////////////////////////////////////////////////////// 16 17 18 19 20 21 struct vertex2pixel { float4 Position float2 TexCoord }; : POSITION; : TEXCOORD0; 22 23 24 25 sampler PointSamplerUVFG = sampler_state { Texture = (tUVFG); 26 MinFilter MagFilter AddressU AddressV 27 28 29 30 31 32 }; = = = = Point; Point; Clamp; Clamp; Echtzeitfähige Simulation von Wasser auf Grafikhardware 33 34 35 Seite 66 von 99 sampler PointSamplerObstacles = sampler_state { Texture = (tObstacles); 36 MinFilter MagFilter AddressU AddressV 37 38 39 40 41 = = = = Point; Point; Clamp; Clamp; }; 42 44 45 46 ////////////////////////////////////////////////////////// // ImpulseF ////////////////////////////////////////////////////////// 47 48 49 50 51 float4 ImpulseFPixelShader(vertex2pixel v) : COLOR0 { // get current position float2 uv = v.TexCoord; 52 53 53 54 // sample seven surrounding texels float4 topcenter = tex2D(PointSamplerUVFG, float2(uv.x, uv.y - tsy)); 55 56 float4 topright = tex2D(PointSamplerUVFG, float2(uv.x + tsx, uv.y - tsy)); float4 centerleft = tex2D(PointSamplerUVFG, float2(uv.x - tsx, uv.y)); float4 center = tex2D(PointSamplerUVFG, uv); float4 centerright = tex2D(PointSamplerUVFG, float2(uv.x + tsx, uv.y)); 57 58 59 60 61 62 63 64 65 66 67 68 float4 bottomcenter = tex2D(PointSamplerUVFG, float2(uv.x, uv.y + tsy)); 69 70 71 // sample obstacles float4 obst = tex2D(PointSamplerObstacles, uv); 72 73 74 float4 obstright = tex2D(PointSamplerObstacles, float2(uv.x + tsx, uv.y)); 75 76 77 // copy U value to F center.z = center.x; 78 79 80 81 82 83 84 85 // if this and the cell to the right are fluid cells if ((obst.x + obstright.x) == 0) { // compute F // du² / dx float fd = center.x + centerright.x; float bd = center.x + centerleft.x; 86 87 88 89 90 float du2dx = ( (fd * fd) - (bd * bd) + alpha * Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 67 von 99 ( 91 abs(fd) * (center.x - centerright.x) - abs(bd) * (centerleft.x - center.x) 92 93 94 95 ) ) * dx4; 96 97 98 // duv / dy fd = center.y + centerright.y; bd = topcenter.y + topright.y; 99 100 101 102 float duvdy = ( 103 fd * (center.x + bottomcenter.x) - bd * (topcenter.x + center.x) + alpha * ( abs(fd) * (center.x - bottomcenter.x) - abs(bd) * (topcenter.x - center.x) ) ) * dy4; 104 105 106 107 108 109 110 111 112 113 114 115 116 // wave (diffusion) float wave = Re * ((centerright.x - 2*center.x + centerleft.x) * rdx2 + (bottomcenter.x - 2*center.x + topcenter.x ) * rdy2); 117 118 119 120 121 122 123 // F center.z += dt * (wave - du2dx - duvdy + gx); 124 125 126 } 127 128 return center; 129 130 } 131 132 133 134 135 136 137 138 139 technique ImpulseF { pass P0 { VertexShader = NULL; PixelShader = compile ps_2_0 ImpulseFPixelShader(); } } Der Einsprungspunkt für ein High-Level-Shader-Programm ist eine so genannte Technique (Zeile 132). In ihr können mehrere Passes (Zeile 134) definiert werden, die jeweils ein Vertex-Programm und ein Pixel-Programm ausführen. In diesem Fall gibt es nur einen Pass ohne Vertex-Programm. Das Pixel-Programm wird mit einem bestimmten Profil übersetzt ps_2_0; das bedeutet: Pixel-Shader 2.0 Standard. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 68 von 99 In ImpulseFPixelShader (Zeile 48) werden zunächst die Texturkoordinaten zwischengespeichert (Zeile 51) und anschließend alle Nachbarpunkte der aktuellen Position in die Konstantenregister kopiert, da sie öfters gebraucht werden (Zeile 53 – 68). Außerdem werden die Hindernistextur an der aktuellen Position und ein Texel weiter rechts ausgelesen (Zeile 71 – 74). Nur wenn beide keine Hinderniszellen sind, muss F neu berechnet werden, sonst wird F einfach mit U überschrieben (Zeile 77 und 80). Wie in Kapitel 3.2.4 auf Seite 46 beschrieben wird jetzt der diskretisierte F-Term der ∂u 2 ∂uv Impulsgleichung berechnet. Die beiden konvektiven Terme und werden in ∂y ∂x den Zeilen 84 – 97 und 100 – 113 berechnet. Die Diffusion wird in den Zeilen 118 – 122 bestimmt und abschließend wird alles in Zeile 125 zusammenaddiert und zurückgegeben. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 69 von 99 3.4.6. Visualisierung Die Lösung der Navier-Stokes-Gleichungen liegt nun zum Zeitpunkt n+1 vor. Zur Visualisierung stehen insgesamt fünf verschiedene Ansichten bereit: Geschwindigkeitsfeld: Zeigt eine Farbkodierung der Richtungsvektoren Partikel: Zeigt Bahnlinien von Partikel, die in die Strömung ausgesetzt werden Hindernisse: Zeigt die Hindernisse im Gebiet Ω an, um sie zu editieren Druck: Zeigt die aktuelle Druckverteilung an Rotation: Stellt die Verteilung der Wirbelstärke dar Geschwindigkeitsfeld Als Visualisierungstechnik kommt für das Geschwindigkeitsfeld eine einfache Farbkodierung der Richtungsvektoren zum Einsatz. Im roten Farbanteil wird die x-Komponente und im grünen Anteil die y-Komponente eines Vektors dargestellt. Dabei wird der Nullvektor in die Mitte der beiden Farbanteile gelegt, da die Werte positiv und negativ werden können. Mit einem Rot- und Grünanteil von 0.5 wird der Nullvektor repräsentiert. Je länger der Vektor, desto weiter zeigt er an den Rand des Quadrats. Abbildung 33: Farbkodierung der Richtungsvektoren Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 70 von 99 Für den Nullvektor ergibt sich grünliches Gelbbraun. Vektoren nach rechts werden durch orange Farbe gekennzeichnet, Vektoren nach links unten durch Grün und Vektoren nach links oben durch Schwarz. Abbildung 34: Einströmung von links nach rechts mit Wirbelbildung Im Demoprogramm gibt es die Möglichkeit die Vektoren vor der Darstellung normalisieren zu lassen. Hier sieht man an den Stellen, wo alle Farben in einer Singularität zusammentreffen, die Wirbelzentren. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 71 von 99 Partikelverfolgung Eine andere Möglichkeit die Strömung sichtbar zu machen ist die Partikelverfolgung. Hier werden einzelne Partikel an eine bestimmte Stelle im Gebiet Ω eingesetzt und durch die Strömung fort getragen. Es werden nicht nur einzelne Partikel betrachtet, sondern eine Partikelverteilung, die an jeder Stelle im Gebiet Ω eine bestimmte Intensität hat. In der Demo können diese Partikel einfach mit der linken Maustaste eingesetzt werden. Mit dem Mausrad kann die Größe des Radius verändert werden in dem neue Partikel hinzugefügt werden. So können auf einmal sehr viele oder sehr wenige neue Partikel eingesetzt werden. Sei p ∈ Ω die zweidimensionale Position eines einzelnen Partikels im Gebiet Ω. Pro Zeitschritt wird die Gitterzelle (i, j ) bestimmt, in der p liegt. Dazu wird im einfachsten Fall (i, j ) = ( p x / δx, p y / δy ) berechnet, wobei δx und δy die Zellenabmaße sind. Eine bilineare Interpolation zu den umliegenden vier Gitterzellen kann verwendet werden um genauere Ergebnisse zu erzielen. Die Gitterzelle (i, j ) wird benötigt um den entu sprechenden Geschwindigkeitsvektor UVi , j = ausgelesen. v i, j In einer Vorwärtsverfolgung wird UVi,j auf die Position p addieren, um die neue Position des Partikels im nächsten Zeitschritt zu bestimmmen. Aus technischen Gründen ist die Vorwärtsverfolgung auf der Grafikkarte nicht mit vernünftiger Performance berechenbar, so dass eine Rückwärtsverfolgung implementiert wurde. In der Rückwärtsverfolgung wird ausgehend von der aktuellen Zelle (i, j ) der Geschwindigkeitsvektors in umgekehrter Richtung –UVi,j verfolgt und die Zelle (i ' , j ') bestimmt, auf die (i ' , j ') = (i − ui , j − v j ) zeigt. Auch hier kann wieder eine bilineare Interpolation angewendet werden um genauere Ergebnisse zu erhalten. Die an Stelle (i' , j ') gefundenen Partikel werden in die Zelle (i, j ) kopiert. Die Rückwärtsverfolgung ist wesentlich ungenauer als die Vorwärtsverfolgung, da ja auch mehrere Geschwindigkeitsvektoren in die gleiche Zielzelle zeigen könnten. Dieser Fall wird nicht berücksichtigt, dafür ist die Berechnung sehr schnell. Zusätzlich zur Verfolgung diffundieren die Partikel. Die Diffusionsrate kann im Einstellungsdialog des Programms festgelegt werden. Mathematisch funktioniert die Diffusion genauso, wie sie bei der Impulsgleichung beschrieben worden ist. So breiten sich je nach Diffusionsrate die Partikel unabhängig von der Strömung aus. Die Partikel werden in der Standardeinstellung des Programms durch Grauwerte visualisiert, die von der jeweiligen Intensität an jeder Stelle abhängen. Je mehr Intensität an einem Ort vorliegt, desto weißer wird dieser Bereich dargestellt. Je weniger, desto dunkler wird die Darstellung. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 72 von 99 Abbildung 35: Partikelverfolgung Um verschiedene Materialien zu simulieren, können die Partikel eingefärbt werden. Dazu werden eindimensionale Paletten verwendet, die auf zwei Arten indiziert werden können: Intensitätsindizierung: Der Index in die Paletten ist die Partikelintensität. Diese Indizierung eignet sich für Materialien, die in dichterem Zustand anderes Licht aussenden, als im undichteren Zustand. Wie in Abbildung 36 zeigt, kann damit zum Beispiel Feuer dargestellt werden. Im dichtesten Zustand weiß, ändert es mit Abnahme der Intensität seine Farbe zu gelb über rot nach schwarz. Abbildung 36: Partikel mit Feuerpalette Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 73 von 99 Indizierung über die Partikelposition: Die y-Komponente der Partikelposition wird als Index in die Palette verwendet. Damit können statische Farbverläufe von Medien simuliert werden. Beide Indizierungsarten können im Demoprogramm parallel angewendet werden, wie es in Abbildung 37 dargestellt ist. Abbildung 37: Intensitätspalette und Positionspalette Neben dem Einfügen von Partikeln mit der linken Maustaste, kann ein Pinsel bzw. Stempel aus einer Grafikdatei geladen werden. An jedem Punkt der Grafik wird der Mittelwert über die drei Farbkomponenten Rot, Grün und Blau zu einer Graustufe gemittelt. Mit gedrückter Shift-Taste und einem Klick auf die linke Maustaste, wird dieses Graubild als Partikelpinsel an der Mausposition eingefügt. Im Bild unten wurde das tum3D Logo als Partikelpinsel verwendet. Abbildung 38: Partikelpinsel Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 74 von 99 Druck Da die Druckwerte positiv und negativ werden können, wird die gleiche Visualisierungstechnik wie beim Geschwindigkeitsfeld angewandt, mit dem Unterschied, dass hier nur eine Dimension benötigt wird. Ein Druck von Null wird mit 0.5 im Rotkanal kodiert, also ein mittelhelles Rot. Großer positiver Druck wird als helles Rot dargestellt, großer negativer Druck als Dunkelrot bis Schwarz. Abbildung 39: Beispiel einer Druckverteilung Rotation (Wirbelstärke) Diese Darstellung stellt die Wirbel im Geschwindigkeitsfeld dar. Dazu werden lila Farben benutzt, die die Stärke und Richtung der Wirbel visualisiert. Wie beim Druck werden positive und negative Wirbelstärke durch helles Lila bzw. Schwarz dargestellt, während Wirbelfreiheit durch einen Mittelwert angezeigt wird. Die Wirbelstärke ζ kann direkt aus einem gegebenen Geschwindigkeitsfeld berechnet werden. ζ (x, y ) := ∂u ∂v − ∂y ∂x Nach der Diskretisierung ergibt sich folgende Formel. ζ (i, j ) := ui , j +1 − ui , j δy − vi +1, j − vi , j δx Die Berechnung von ζ erfolgt nur, falls die entsprechend Ansicht auch ausgewählt ist. Abbildung 40: Rotation der Wirbelstrasse Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 75 von 99 Hinderniseditor Die Hindernisse werden als blaue Pixel dargestellt. Mit der linken Maustaste können neue Hinderniszellen hinzugefügt werden und mit der rechten Maustaste wieder entfernt werden. Wie bei der Partikelverfolgung kann hier mit dem Mausrad die Größe des Pinsels verändert werden. Da der Hinderniseditor neben den diesen elementaren Einfüge- und Löschoperationen keine weitere Funktionalität bietet, wurde eine Import-Funktion implementiert, mit der man beliebige Bilder als Hinderniskarte einlesen kann. Das Bild muss dabei in einem der folgenden Formate vorliegen: JPEG (*.jpg) Portable Network Graphics (*.png) Truevision Targa (*.tga) Windows Bitmap (*.bmp) Um aus beliebigen Bildern eine gültige Hindernistextur zu erzeugen, werden alle sehr dunklen bis schwarzen Pixel ignoriert. D.h. hier bleiben die Fluidzellen erhalten, wohingegen die farbigen Bereiche des Bildes als Hinderniszellen interpretiert werden. Falls sich beim Setzen von neuen Hindernissen ungültige Hinderniszellen ergeben (siehe Kapitel 3.2.2 auf Seite 44), werden diese als weiße Punkte dargestellt. Durch erneutes Hinzufügen oder Entfernen von Hinderniszellen müssen die ungültigen Zellen unbedingt beseitigt werden, da sonst die Simulation nicht funktioniert. Abbildung 41: Hindernisse mit ungültigen Zellen Overlay Texturen Um die optische Qualität zu steigern, können beliebige Bilder als Overlay Texturen geladen werden, die über jede Ansicht gelegt werden. So können beispielsweise die blauen Hinderniszellen mit einem farbigen Bild überklebt werden, um den optischen Eindruck zu verbessern. Overlay Texturen müssen nicht von der gleichen Größe sein wie das diskretisierte Gebiet. Durch scharfe Overlay Texturen werden die kantigen Ränder an Hinderniszellen zu glatten Rändern, wie es in Abbildung 42 zu sehen ist. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 76 von 99 Abbildung 42: Overlay Texturen 3.4.7. Geschwindigkeitsmessungen Die Rechengeschwindigkeit wurde auf einem System mit AMD Athlon 1,2 GHz Prozessor und einer ATI Radeon 9700 Pro gemessen. Als Betriebssystem kam wieder Windows XP Professional zum Einsatz. Wie schon bei den Geschwindigkeitsmessungen des Wasserprogramms aus Kapitel 2, wurde das Programm mit verschiedenen Parameterkombinationen gemessen. Neben der Abhängigkeit von der Bildschirmauflösung, spielt diesmal auch die gerade ausgewählte Visualisierungstechnik eine entscheidende Rolle für die Geschwindigkeit. Da die Visualisierung als eigener Software-Layer realisiert wurde, kann man die benötigte Rechenzeit in zwei Komponenten aufteilen. Zum einen benötigt die eigentliche Berechnung der Navier-Stokes-Gleichungen einen festen Rechenaufwand, der im Wesentlichen nur von der Anzahl der Gitterzellen abhängt. Dies allerdings der Hauptfaktor in der gesamten Leistungsbilanz. Zum anderen benötigt jede Visualisierungstechnik unterschiedlich viel zusätzliche Rechenzeit. In der folgenden Auflistung sind die Visualisierungstechniken nach ihrem Leistungsbedarf in absteigender Reihenfolge sortiert. Jeweils in Klammern daneben ist der entsprechende Geschwindigkeitsfaktor in Bezug auf die schnellste Visualisierungstechnik, die Darstellung des Drucks, angegeben. 1. 2. 3. 4. 5. Druck Hinderniseditor Partikel Wirbelstärke Geschwindigkeitsfeld ( 100 % ) ( 98 % ) ( 97 % ) ( 76 % ) ( 66 % ) Die obigen Geschwindigkeitsfaktoren wurden auf einem Gitter von 128 mal 128 Zellen bei einer Bildschirmauflösung von 1024 mal 768 Bildpunkten gemacht. Es wurde immer die Gesamtleistung betrachtet, also inklusive Berechnung der Navier-StokesGleichungen und nicht nur die Visualisierungstechnik alleine. Bei anderen Gitterauflösungen und anderen Bildschirmauflösungen ergeben sich andere Faktoren, aber die Reihenfolge bleibt immer gleich. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 77 von 99 Die Visualisierung des Geschwindigkeitsfeldes benötigt deshalb so viel Rechenzeit, weil in jedem Punkt auf dem Bildschirm eine bilineare Interpolation auf dem Geschwindigkeitsfeld durchgeführt wird. Deswegen ist diese Visualisierung stark von der gewählten Bildschirmauflösung abhängig. Die Wirbelstärke wird während der Berechnung der Navier-Stokes-Gleichungen nicht explizit bestimmt, sondern erst in der Visualisierungsschicht. Deswegen ist diese Darstellung verhältnismäßig langsam. Partikel-, Hindernis- und Druckvisualisierung sind deswegen so schnell, weil nichts weiter berechnet werden muss. Aus den entsprechenden Texturen werden lediglich die notwendigen Texel ausgelesen und in den Bildschirmspeicher kopiert. Nach dieser Erläuterung zur Visualisierungsschicht folgen nun konkrete Messungen der Bilder pro Sekunde bzw. Frames per Second unter verschiedenen Gitterauflösungen und Bildschirmauflösungen. Es wurde jeweils eine Tabelle pro Visualisierungstechnik erstellt. Da sich die Bilder pro Sekunde bei der Visualisierung von Partikeln, Hindernissen und Druck nur sehr gering unterscheiden, wurde hier auf separate Diagramme verzichtet. Geschwindigkeitsfeld Bilder pro Sekunde 80 70 60 50 640x480 40 800x600 30 1024x768 20 10 0 64 128 256 Gittergröße Abbildung 43: Geschwindigkeit bei Visualisierung des Geschwindigkeitsfelds Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 78 von 99 Bilder pro Sekunde Wirbelstärke 90 80 70 60 50 40 30 20 10 0 640x480 800x600 1024x768 64 128 256 Gittergröße Abbildung 44: Geschwindigkeit bei Visualisierung der Wirbelstärke Bilder pro Sekunde Partikel, Hinderniseditor, Druck 100 90 80 70 60 50 40 30 20 10 0 640x480 800x600 1024x768 64 128 256 Gittergröße Abbildung 45: Geschwindigkeit von Partikeln, Druck oder Hindernissen Um die Abhängigkeit von der Bildschirmauflösung zu lösen, kann jede Ansicht zuerst in eine Zwischentextur visualisiert werden, die die gleiche Auflösung wie das diskretisierte Gebiet hat. Diese Textur wird anschließend auf den Bildschirm gezeichnet. Bei steilen Änderungen in den Partikelpaletten entstehen mit dieser Methode Artefakte, auf der anderen Seite bringt es manchmal eine Performacesteigerung von bis zu 10%. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 79 von 99 3.5. Simulierte Probleme 3.5.1. Nischenströmung Als Nischenströmung bezeichnet man das Strömungsverhalten, wenn ein geradliniger Strom über eine Nische bzw. Ausbuchtung fließt. In der Realität kommt dieses Phänomen zum Beispiel bei einem Bach vor, der über eine Bodenunebenheit fließt. Folgende Abbildung stellt das Problem anschaulich dar. Abbildung 46: Nischenströmung In der Demo wird nur die Nische selbst simuliert, nicht der Strom, der darüber fließt. Als Bedingungen für den linken, rechten und unteren Rand werden Haftbedingungen gesetzt und zur Simulation des Flusses am oberen Rand eine so genannte Bandbedingung (Driven Cavity). Dazu wird ein Einheitsvektor nach rechts gesetzt. Das Gebiet kann quadratisch sein, muss es aber nicht. Zusätzliche Hindernisse können ebenfalls eingefügt werden, um die Nische mit einer realistischeren Kontur zu versehen. Als Anfangsbedingung für die Geschwindigkeit und den Druck innerhalb der Nische wird jeweils Null gewählt. So ist das gesamte Gebiet anfangs in Ruhe, bis auf die Bandbedingung am oberen Rand. Die Verwirbelung, die in der Nische entsteht, hängt von der Reynoldszahl des Fluids ab. Je größer sie wird, desto weiter verschiebt sich der Wirbel in die rechte obere Ecke, und es bildet sich nach einiger Zeit ein weiterer Wirbel in der linken unteren Ecke der Nische. Bei kleineren Reynoldszahlen bleibt das untere Drittel der Nische immer in Ruhe und es bilden sich keine weiteren Wirbel. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 80 von 99 Abbildung 47: Vektorfeld einer Nischenströmung mit hoher Reynoldszahl Abbildung 48: Partikelverfolgung in der Nischenströmung Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 81 von 99 3.5.2. Kármánsche Wirbelstraße Die Kármánsche Wirbelstraße ist die Simulation, die man in jedem Buch über Strömungsmechanik findet. Hier wird ein von linken Seite einströmendes Fluid simuliert, das auf ein Hindernis, wie zum Beispiel einen Balken, trifft. Mit hoher Reynoldszahl (Re ≈ 10000) entstehen hinter dem Hindernis Verwirbelungen, die man als Kármánsche Wirbelstraße bezeichnet. Abbildung 49: Kármánsche Wirbelstraße Die Breite des Gebiets wurde in dieser Simulation vier Mal so groß gewählt wie die Höhe. Als Einströmungsbedingung am linken Rand nimmt man wiederum einen Einheitsvektor, der nach rechts zeigt. Am oberen und unteren Rand, sowie am unteren Rand wählt man ebenfalls einen Einheitsvektor mit der gleichen Richtung wie am linken Rand. Diese Art von Randbedingung nennt man auch Ozeanbedingung, weil dadurch ein unendliches Feld simuliert wird. Als Besonderheit sei darauf hingewiesen, dass der Initialvektor für das Geschwindigkeitsfeld UV0 auch ein Einheitsvektor nach rechts sein muss, damit die Simulation funktioniert. Mit anderen Worten: Es muss das gesamte Gebiet inklusive Rand mit dem Initialvektor UV0 belegt werden, der kein Nullvektor sein darf. Die nachfolgende Abbildung zeigt das Geschwindigkeitsfeld in der Kármánsche Wirbelstraße. Bei der Simulation über einen schrägen Balken bilden sich sofort Verwirbelungen. Die Strömung ist über die Zeit periodisch. Abbildung 50: Strömung über einen schrägen Balken mit hoher Reynoldszahl Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 82 von 99 Wenn man in dieses Geschwindigkeitsfeld Partikel injiziert, dann kommt folgendes Bild zustande. Abbildung 51: Partikelverfolgung über den schrägen Balken Hier wurden die Partikel gelb eingefärbt, und eine Overlay Texture verwendet, die in der rechten unteren Ecke das tum3D-Logo einblendet. Dieses Logo ist im Gegensatz zu dem Balken kein Hindernis. Wählt man als Hindernis statt des schrägen Balkens einen Kreis, so bildet sich die Wirbelstraße nicht sofort aus. Bei kleinen Reynoldszahlen schließen sich die Stromlinien hinter dem Hindernis gleich wieder, ohne dass es zu Verwirbelungen kommt. Bei hohen Reynoldszahlen bildet sich hinter dem Hindernis zunächst ein Rückstrom, von dem sich erst nach einiger Zeit Wirbel ablösen und davon treiben. Abbildung 52: Simulation eines Flusses (Partikelverfolgung) Abbildung 52 zeigt die Simulation eines Flusses, der sich um verschiedene Steine herumschlängelt. Hierzu wurden die Partikel bläulich eingefärbt und als Hindernisund Overlay-Textur eine Fläche mit ein paar Steinen verwendet. Hinter jedem kleinen Steine bildet sich eine kleine Kármánsche Wirbelstraße. Das zugehörige Geschwindigkeitsfeld ist in Abbildung 53 dargestellt. Abbildung 53: Simulation eines Flusses (Geschwindigkeitsfeld) Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 83 von 99 3.5.3. Stufenströmung Bei der Stufenströmung befindet sich in der linken unteren Ecke ein Hindernis und darüber strömt das Fluid mit dem Initalvektor UV0 ein. Für UV0 wurde ein Einheitsvektor nach rechts gewählt. Wie schon bei der Kármánsche Wirbelstraße werden auch hier an allen Rändern die Ozeanrandbedingung gesetzt. Abbildung 54: Strömung über eine Stufe Die Gebietsgröße kann für diese Simulation beliebig gewählt werden. In der hier vorgestellten Simulation wurde ein Breiten-Höhen-Verhältnis von zwei zu eins mit 128 mal 64 Gitterzellen verwendet. Je größer die Reynoldszahl ist, desto lang gestreckter wird der Wirbel, der sich rechts hinter der Stufe bildet. Je kleiner sie ist, desto näher bleibt der Wirbel an der Schwelle. In den folgenden Abbildungen wurde als Overlay Texture ein natürlicher Felsen eingezeichnet um so einen Wasserfall zu simulieren. Dementsprechend wurden die Partikel blau gefärbt um Wasser darzustellen. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 84 von 99 Abbildung 55: Stufenströmung mit Re = 1000 (Geschwindigkeitsfeld) Die obige Abbildung wurde mit einer Reynoldszahl von 1000 berechnet. An den gelben Bereichen kann man erkennen, wie die Strömung nach rechts unten zeigt. In den grünen Bereichen am unteren Bildrand erkennt man den Rückstrom nach rechts. Abbildung 56 zeigt die Partikelverfolgung im Wasserfall. Abbildung 56: Stufenströmung mit Re = 1000 (Partikelverfolgung) Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 85 von 99 3.5.4. Strömung über ein Auto Bei der Fahrzeugentwicklung sind Tests der Windschnittigkeit neuer Autos sehr wichtig. Der Treibstoffverbrauch hängt direkt mit dem Luftwiderstand des Fahrzeugs zusammen. Um diese Tests durchzuführen, werden Prototypen oder kleinere Modelle in Windkanäle gestellt und von Luft aus Windmaschinen umströmt. In praktischen Experimenten werden Rauch- oder Staubpartikel in die Strömung injiziert um die Strömung sichtbar zu machen. Mit Hilfe der Navier-Stokes-Gleichungen können Windkanale durch Simulationen am Computer ersetzt werden. Für dieses Anwendungsbeispiel wird ein Gebiet wie bei der Kármánsche Wirbelstraße erzeugt (siehe Seite 81): Die Initialvektoren UV0 werden auf den Einheitsvektor nach rechts gesetzt, an den Ränder herrscht eine Ozeanrandbedingung und die Reynoldszahl wird auf 10000 gesetzt. Als Overlay Textur wurde die Seitenansicht eines Autos über die Hindernisse gelegt (Quelle [21]). Abbildung 57: Auto im Windkanal (Geschwindigkeitsfeld) An der Motorhaube und Windschutzscheibe ist durch die rote Farbe ersichtlich, wie sich die Vektoren den Weg über das Auto bahnen. Hinter dem Auto entstehen starke Verwirbelungen. Bei diesen Simulationen geht es immer um die relative Geschwindigkeit zwischen Fluid und Hindernis. D.h. es ist egal, ob das Auto steht und Wind auf das Auto bläst, oder ob das Auto in Fahrt und die Luft in Ruhe ist: Das Strömungsbild ist in beiden Fällen identisch. Abbildung 58: Auto im Windkanal (Geschwindigkeitsfeld) Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 86 von 99 3.5.5. tum3D-Logo In der letzten Simulation geht nicht um eine wissenschaftliche Simulation, sondern um Strömung um das Logo des Lehrstuhls. Hier wurde ein Gebiet mit 128 mal 128 Gitterzellen und einem Initialvektor UV0 nach oben definiert. Als Hindernis und Overlay Textur wurde das tum3D Logo in die Mitte des Gebiets gesetzt. Die Partikel wurden mit einer Feuerpalette eingefärbt. Abbildung 59: tum3D-Logo (Geschwindigkeitsfeld) Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 87 von 99 3.6. Erweiterungen In diesem Abschnitt werden mögliche Erweiterungen zu der bisher vorgestellten Simulation aufgezeigt. Neben weiteren Visualisierungstechniken können auch physikalische Phänomene wie die Temperatur berechnet werden. Die Simulation von Fluiden, die sich erst in ein Gebiet ausbreiten, bezeichnet man als freie Randwertprobleme. Im Abschnitt zu numerischen Fehlern geht es um die Minimierung der Rechenfehler. Abschließend wird eine Erweiterung der Navier-Stokes-Gleichungen ins DreiDimensionale vorgestellt. 3.6.1. Visualisierung Die Farbkodierung der Geschwindigkeitsvektoren ist nicht besonders intuitiv verständlich. Die Partikelverfolgung gibt dem Betrachter einen wesentlich besseren Eindruck, wie die Strömungsverhältnisse sind. Eine bessere Visualisierungstechnik wären zum Beispiel kleine Pfeile, die in die Richtung des Vektors zeigen und durch ihre Länge die Vektorlänge wiedergeben. Mit einer Exportfunktion für Geschwindigkeitsfelder könnte man sie in anderen Visualisierungstools wie AVS anzeigen und nachbearbeiten. Andersherum könnten gegebene Geschwindigkeitsfelder durch eine Importfunktion weiter simuliert werden. Für den Druck und die Rotation könnten Isolinien die Anschaulichkeit steigern. 3.6.2. Stromfunktion Neben der Wirbelstärke (siehe Kapitel 3.4.6 auf Seite 69) kann auch die Stromfunktion ψ berechnet werden, die die Stromlinien des Geschwindigkeitsfeldes mit ψ ( x, y ) = const bestimmt. Im Kontinuierlichen ist sie wie folgt definiert: ∂ψ ( x, y ) := −v, ∂x ∂ψ ( x, y ) := u ∂y In der Diskretisierung ergibt sich eine Startzeile ψ i ,0 = ψ i −1,0 − vi , 0δx, i = 1,..., imax und eine Formel für den Rest des Gebiets ψ i , j = ψ i , j −1 − ui , j δy, i = 1,..., imax , j = 1,..., jmax Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 88 von 99 Wie aus letzter Formel ersichtlich, kommt man mit dieser Formel in ähnliche Probleme wie bei der Berechnung des Gauss-Seidel-Verfahrens. Das ψi,j benötigt den bereits aktualisierten Wert ψi,j-1 und das ist technisch auf der Grafikhardware nicht möglich. Hier müsste man erst nach neuen Wegen suchen, um die Stromfunktion zu berechnen. 3.6.3. Hinderniseditor Der Hinderniseditor ist sehr rudimentär gehalten. Er unterstützt nur die wesentlichen Funktionen um Hinderniszellen einzufügen und zu löschen. In einem komfortablen Hinderniseditor sollte auch die Pinselform wählbar sein, wie zum Bespiel Rechtecke. Außerdem wären einfache Zeichenfunktionen sehr nützlich: Funktionen, mit der man Linien ziehen kann oder Füllfunktion, mit der Bereich mit leeren bzw. Hinderniszellen ausgefüllt werden können. 3.6.4. Numerische Fehler Auf Grund der begrenzten Anzahl von Instruktionen im Pixel-Shader, wurden die meisten Shader auf Speicherplatz optimiert, damit so wenige Rendering-Passes benötigt werden wie möglich. Dieses Vorgehen begünstigt numerische Fehler, die durch eine bestimmte Reihenfolge der mathematischen Operationen verursacht werden. Die Rechenfehler resultieren zum einen aus der begrenzten Bitbreite eines Fließkommawortes. Reelle Zahlen sind unendlich genau, aber das lässt sich im Rechner nicht darstellen und deshalb müssen sie ab einer bestimmten Stelle abgeschnitten werden. Bei der mathematischen Operation mit zwei Zahlen, bei der eine sehr klein und die andere sehr groß ist, können sich Auslöschungen von Bits und damit große Rechenfehler ergeben. Als illustrierendes Beispiel sei auf den Code aus Kapitel 3.4.5 auf Seite 64 verwiesen. Bei der Berechnung des diffusiven Anteils wird ein so genannter Stern ausgewertet: 118 119 120 float wave = Re * ((centerright.x - 2*center.x + centerleft.x) * rdx2 + (bottomcenter.x - 2*center.x + topcenter.x ) * rdy2); Diese Berechnung ist numerisch fehlerfrei, wenn man sie folgendermaßen ausdrückt: 118 119 120 121 122 float wave = Re * ((centerright.x centerleft.x (bottomcenter.x topcenter.x - center.x + center.x) * rdx2 + center.x + center.x) * rdy2); Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 89 von 99 In der unteren Version bleiben alle beteiligten Zwischenergebnisse immer in etwa gleich groß. Das ist eine wesentliche Vorraussetzung um Auslöschungen von Bits in Fließkommazahlen zu vermeiden. Hier sei auf einschlägige Literatur zur Numerik auf Computern hingewiesen, die sich umfassend mit dieser Thematik befasst. Wenn die Länge der Shader-Programme im Pixel-Shader 3.0 Standard nicht mehr auf 64 Befehle beschränkt ist, sollte man nicht nur zusammengehörige ShaderProgramme zusammenfassen, sondern auch die mathematischen Operationen auf numerische Korrektheit überprüfen. 3.6.5. Freie Randwertprobleme Mit freien Randwerten definiert man noch eine weitere Unterscheidung zwischen verschiedenen Zelltypen. Bisher gab es entweder Fluidzellen oder Hinderniszellen. Hier kommt noch eine dritte hinzu: eine leere Zelle. Fluide können sich nun in leere Zellen ausbreiten bzw. Zellen verlassen. Damit lassen sich dann zum Beispiel Wassertropfen, die in ein Becken fallen simulieren. Die Ausbreitung eines Fluids wird mit Hilfe eines Partikelverfolgers realisiert. In jede Zelle des Gitters, in der sich anfangs das Fluid befinden soll, wird eine feste Menge an Partikeln gesetzt. In der Praxis sind das meist 9 oder 16 Partikel. Zu Beginn des Algorithmus werden diese Partikel mit der Partikelverfolgung auf dem aktuellen Geschwindigkeitsfeld bewegt. Dadurch gelangen einige der Partikel in Zellen, in denen vorher noch kein Fluid war, und umgekehrt kann eine Zelle leer werden, wenn sie alle Partikel verlassen haben. Die Partikel zeigen jetzt an, in welchen Zellen Fluid ist und in welchen nicht. Jetzt kann der so genannte Freirand bestimmt werden. Das sind die Fluidzellen, die an eine oder mehrere leere Zellen angrenzen. An diesem Freirand müssen wieder für die Geschwindigkeitsfelder UV und FG sowie für den Druck Randwerte gesetzt werden. Nun wird die Impulsgleichung in den Fluidzellen wie gehabt ausgewertet und die Schleife beginnt von vorne mit der Partikelverfolgung. 3.6.6. Temperatur (Energietransport) In vielen technischen Anwendungen ist bei der Simulation von Strömungen die Temperatur ein wichtiger Faktor. Man denke beispielsweise an die Wettervorhersage, wo Wolkenströmungen entscheidend durch die Temperatur beeinflusst werden. Jedes Fluid besitzt thermodynamische Eigenschaften. Die Temperatur eines Fluids wirkt sich auf die Dichte des Mediums aus. Durch Erwärmung dehnt sich das Fluid aus, und es steigt auf, weil es leichter wird. So entstehen thermische Auftriebskräfte, die sich auf das Geschwindigkeitsfeld auswirken. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 90 von 99 Die Temperatur korrekt in die Gleichung einzubeziehen ist unter exakten Bedingungen äußerst schwierig, weshalb man sich auf eine Approximation beschränken kann; zum Beispiel die Boussinesq-Appromixation. Dabei wird als Vereinfachung angenommen, dass die Dichte im Fluid konstant ist, außer bei den Termen der Auftriebskräfte. Dadurch können die inkompressiblen Navier-Stokes-Gleichungen beibehalten werden. Sie werden lediglich durch die Terme der Auftriebskräfte erweitert. Ein interessantes Beispiel ist das Heizen einer Wand: In dem rechteckigen Gebiet Ω wird ein ruhendes Fluid gesetzt mit UV = 0. Durch das Heizen einer der vier Seitenwände beginnt nun das Fluid in Bewegung zu geraten. So entsteht ein Wirbel im Gebiet. 3.6.7. Dreidimensionale Navier-Stokes-Gleichungen Wegen der nicht ausreichenden Rechenkraft ist es heute zwar noch nicht möglich die Navier-Stokes-Gleichungen im Dreidimensionalen in Echtzeit zu berechnen, aber in den kommenden Jahren dürfte auch das durchführbar werden. Erst in der dreidimensionalen Simulation lassen sich die meisten Naturphänomene realistisch nachrechnen, wie zum Beispiel der Luftstrom um ein Auto im Windkanal. Neben der aufwändigen Berechnung der Navier-Stokes-Gleichungen, müssen hier auch aufwändigere Visualisierungstechniken verwendet werden. Um ein dreidimensionales Strömungsvolumen darzustellen, braucht man einen Volumenrenderer. Alternativ können auch nur einzelne Scheiben des Volumens betrachtet werden, allerdings ist diese Darstellung nicht besonders anschaulich. Im Dreidimensionalen ergeben sich drei Impulsgleichungen in dimensionsloser Darstellung. ( ) ∂u ∂p 1 ∂ 2 u ∂ 2 u ∂ 2 u ∂ u 2 ∂(uv ) ∂ (uw) − + = + + − − + gx ∂t ∂x Re ∂x 2 ∂y 2 ∂z 2 ∂x ∂y ∂z ( ) ∂v ∂p 1 ∂ 2 v ∂ 2 v ∂ 2 v ∂ (uv ) ∂ v 2 ∂ (vw) − + = + + − − + gy ∂t ∂y Re ∂x 2 ∂y 2 ∂z 2 ∂x ∂y ∂z ( ) ∂w ∂p 1 ∂ 2 w ∂ 2 w ∂ 2 w ∂ (uw) ∂ (vw) ∂ w 2 − + = + + − − + gz ∂t ∂z Re ∂x 2 ∂y 2 ∂z 2 ∂x ∂y ∂z Dementsprechend ergibt sich folgende Kontinuitätsgleichung: ∂u ∂v ∂w + + =0 ∂x ∂y ∂z Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 91 von 99 Die Variable w bezeichnet hierbei die Geschwindigkeitskomponente in Richtung der z-Achse. Die Behandlung der Ränder muss auf die Seitenflächen des Volumens übertragen werden, wobei prinzipiell die gleichen Bedingungen wie im zweidimensionale Fall verwendet werden: Haft-, Rutsch-, Einström- und Ausströmbedingung. Das gilt auch für Hindernisse im Raum, bei denen jetzt noch mehr Fallunterscheidungen für die Nachbarschaftsbeziehungen abgearbeitet werden müssen. Die Diskretisierung erfolgt analog zum zweidimensionalen Fall, allerdings um eine Komponente erweitert. Statt nur die F-G-Terme zu berechnen müssen hier die F-G-H-Terme ausgewertet werden, die folgendermaßen aussehen: δt (n+1) (δp ) δx δt v (n+1) = G (n ) − (δp (n+1) ) δy δt w (n+1) = H (n ) − (δp (n+1) ) δz u (n+1) = F (n ) − Zur Berechnung des Drucks ergibt sich im Dreidimensionalen folgende PoissonGleichung: ∂ 2 p (n+1) ∂ 2 p (n +1) ∂ 2 p (n+1) 1 ∂F (n ) ∂G (n ) ∂H (n ) + + = + + ∂y ∂z ∂t ∂x ∂x 2 ∂y 2 ∂z 2 Dies sollte nur eine Idee geben, wie die dreidimensionalen Navier-StokesGleichungen aussehen. Für weitere Informationen siehe [6]. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 92 von 99 4. Fazit Die beiden Teilprojekte Simulation von Wasseroberflächen und Simulation von Fluiden haben gezeigt, dass moderne Grafikhardware eine Alternative zu teuren Rechenanlagen sein kann, um aufwändige Simulation zu berechnen. Gerade durch die sehr schnelle Weiterentwicklung der Grafikkarten ist in Zukunft noch sehr viel Potential in diesem Forschungszweig. Während vor ein paar Jahren Grafikkarten nicht viel mehr als Dreiecke mit Texturen überziehen und beleuchten konnten, hat sich die neue Generation der Chips von ihrem Dasein als Spezialbaustein für ein bestimmtes Anwendungsgebiet zu GeneralPurpose-Bausteinen entwickelt. Auch wenn es Algorithmen gibt, die sich gar nicht oder nur sehr schlecht auf die Grafikkarte portieren lassen, ist eine Vielzahl von Problemen auf Grafikhardware schneller zu berechnen als auf herkömmlichen CPUs. Gerade Operationen auf Vektoren und Matrizen sind ein Spezialgebiet der GPUs. Mit Pixel-Shader Programmen sind Berechnungen mit Arrays sehr schnell durchführbar. Mit der Unterstützung der Pixel-Shader 3.0 und Vertex-Shader 3.0 Standards in Hardware ist die nächste große Evolutionsstufe schon absehbar. Die Instruktionssets werden vereinheitlicht, Längenbeschränkungen der Programme werden über 65536 Befehle verschoben und echte Sprünge werden möglich. Damit können dann auch Schleifen aller Art programmiert werden. Diese Generation der Grafikkarten wird völlig neue Anwendungsgebiete für GPUs eröffnen. Wie man im Erweiterungen auf Seite 87 lesen kann, gibt es noch zahlreiche Dinge, um die man die beiden Projekte erweitern kann. Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 93 von 99 Literaturverzeichnis [1] Deloura Mark A., "Game Programming Gems 1", Charles River Media, Inc, 2000, Hingham Massachusetts, ISBN 1-58450-049-2 "Fractal Terrain Generation - Midpoint displacement", Jason Shankel, S. 503 – 507 "Improved Environment-mapped reflection using glossy prefiltering and the fresnel term", Anis Ahmad, S. 581 – 585 "Refraction mapping for liquids in containers", Alex Vlachos and Jason L. Mitchell, S. 594 – 599 [2] Treflia Dante, "Game Programming Gems 3", Charles River Media, Inc, 2002, Hingham Massachusetts, ISBN 1-58450-233-9 "Fast Heightfield Normal Calculation", Jason Shankel, S. 344 – 348 “Interactive Simulation of Water Surfaces”, Miguel Gomez, S.187 – 194 [3] LaMothe Andre, "Beginning Direct3D Game Programming", Prima Publishing, Inc, 2001, Roseville, California 95661, ISBN 0-7615-3191-2 "Cubic Environment Mapping", Wolfgang F. Engel, S. 175 - 182 [4] Foley, van Dam, Feiner, Hughes, “Computer Graphics: Principles and Practice”, Addison-Wesley Publishing Company, 1990, ISBN 0-201-121107 [5] Stam Jos, „Real-Time Fluid Dynamics for Games“, Alias wavefront, Toronto, GDC 2003 [6] Griebel Michael, Dornseifer Thomas, Neunhoeffer Tilman, „Numerische Simulation in der Strömungsmechanik – Eine praxisorientierte Einführung“, vieweg Verlagsgesellschaft mbH, Braunschweig/Wiesbaden 1995, ISBN 3-528-06761-6 [7] Krüger Jens, Westermann Rüdiger, “Linear Algebra Operators for GPU Implementation of Numerical Algorithms”, 2003 [8] Stoer Josef, “Numerische Mathematik”, Springer-Verlag, 1999, ISBN 3540-66154-9 [9] Lomax, Pulliam, Zingg, “Fundamentals of Computational Fluid Dynamics (Scientific Computation)”, Springer-Verlag, 2001, ISBN 3-540-41607-2 [10] Tveito Aslak, Winther Ragnar, „Einführung in partielle Differentialgleichungen. Ein numerischer Zugang“, Springer-Verlag, 2002, ISBN 3-540-424040 [11] Hungerbühler Norbert, “Einführung in partielle Differentialgleichungen“, vdf Hochschulverlag AG, Zürich, 1996, ISBN 3-7281-2303-X Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 94 von 99 [12] van Kann J. J. I. M., „Numerik partieller Differentialgleichungen für Ingenieure“, ISBN 3-519-02968-5 [13] Fedkiw Ron, Osher Stanley, „Level Set Methods and Dynamic Implicit Surfaces”, Springer Heidelberg US, 2002, ISBN 0387954821 [14] Schneider Jens, Westermann Rüdiger, “Towards Real-Time Simulation of Water Surfaces”, 2001 [15] Mircosoft, DirectX 9.0 SDK, 2002, http://www.microsoft.com/DirectX [16] Bui-Tuong Phong, “Illumination for Computer Generated Pictures”, CACM, 1975, 331 – 317 [17] Blinn, J.F., “Models of Light Reflection for Computer Synthesized Pictures”, SIGGRAPH 77, 192-198 [18] nVidia, 2002, “Cube Maps”, http://developer.nvidia.com [19] Hammer, Hammer, “Physikalische Formeln und Tabellen”, Lindauer Verlag, München, 1994, ISBN 3-87488-064-8 [20] Hirt, C., Nichols, B. & Romero, “SOLA – A Numerical Solution Algorithm for Transient Fluid Flows”, Technical Report, Los Alamos Scientific Lab. Rep. LA-5852 [21] Bild eines Mercedes: http://www.oeamtc.at/netautor/data/auto/webuse/ mercedes_ekl2002seitl_4.jpg Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 95 von 99 Abbildungsverzeichnis Abbildung 1: Schematischer Aufbau der Hardware .................................................... 5 Abbildung 2: Aufbau einer Grafikkarte........................................................................ 6 Abbildung 3: Membran und Koordinatenachsen....................................................... 10 Abbildung 4: Einfluss der Nachbarpunkte in der diskreten Wellengleichung ............ 12 Abbildung 5: Diskretes Gitter zur Modellierung der Membran .................................. 13 Abbildung 6: Dämpfungsfunktion in der Wasserdemo.............................................. 16 Abbildung 7: Regentropfeneinschläge und Wellenausbreitung ................................ 17 Abbildung 8: Große Einschläge und Wellenausbreitung .......................................... 18 Abbildung 9: Berechnung einer Dreiecksnormalen................................................... 20 Abbildung 10: Nachbarschaftsbeziehung ................................................................. 20 Abbildung 11: Phong-Illumination-Model .................................................................. 22 Abbildung 12: Materialspezifische Konstante n ........................................................ 24 Abbildung 14: Reflexionsvektor ................................................................................ 25 Abbildung 13: Regentropfeneinschläge von oben mit Phong-Beleuchtung .............. 26 Abbildung 15: Sechs Seiten einer Cube-Map ........................................................... 27 Abbildung 16: Reflexion der Umgebung im Wasser ................................................. 27 Abbildung 17: Brechungsvektor................................................................................ 28 Abbildung 18: Lichtbrechung .................................................................................... 30 Abbildung 19: Texturen und Funktionsweise des Wellen-Pixel-Shaders.................. 31 Abbildung 20: Funktionsweise des Licht-Pixel-Shaders ........................................... 33 Abbildung 21: Geschwindigkeitsmessungen der Demo Water2D............................. 34 Abbildung 22: Displacement Mapping ...................................................................... 35 Abbildung 23: Geschwindigkeitsmessungen der Demo Water2D............................. 36 Abbildung 24: Water3D mit 64² Gitterzellen, Phong-Beleuchtung und Lichtreflexion 36 Abbildung 25: Laminare Strömungen ....................................................................... 37 Abbildung 26: Diskretisiertes Gebiet mit Randzellen ................................................ 42 Abbildung 27: Staggered Grid .................................................................................. 43 Abbildung 28: Weiße Fluidzellen, graue Hinderniszellen, ungültige Zellen in Rot .... 44 Abbildung 29: Gauss-Seidel-Verfahren .................................................................... 52 Abbildung 30: Vertex-Buffer Full, Inner (grau), Top0, Bottom0, Left0, Right0........... 58 Abbildung 31: Randbedingungen im Staggered Grid ............................................... 59 Abbildung 32: Dynamischer Zusammenbau des BoundaryUV-Shaders .................. 61 Abbildung 33: Farbkodierung der Richtungsvektoren............................................... 69 Abbildung 34: Einströmung von links nach rechts mit Wirbelbildung........................ 70 Abbildung 35: Partikelverfolgung .............................................................................. 72 Abbildung 36: Partikel mit Feuerpalette .................................................................... 72 Abbildung 37: Intensitätspalette und Positionspalette .............................................. 73 Abbildung 38: Partikelpinsel ..................................................................................... 73 Abbildung 39: Beispiel einer Druckverteilung ........................................................... 74 Abbildung 40: Rotation der Wirbelstrasse................................................................. 74 Abbildung 41: Hindernisse mit ungültigen Zellen...................................................... 75 Abbildung 42: Overlay Texturen ............................................................................... 76 Abbildung 43: Geschwindigkeit bei Visualisierung des Geschwindigkeitsfelds ........ 77 Abbildung 44: Geschwindigkeit bei Visualisierung der Wirbelstärke......................... 78 Abbildung 45: Geschwindigkeit von Partikeln, Druck oder Hindernissen.................. 78 Abbildung 46: Nischenströmung............................................................................... 79 Abbildung 47: Vektorfeld einer Nischenströmung mit hoher Reynoldszahl .............. 80 Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 96 von 99 Abbildung 48: Partikelverfolgung in der Nischenströmung ....................................... 80 Abbildung 49: Kármánsche Wirbelstraße ................................................................. 81 Abbildung 50: Strömung über einen schrägen Balken mit hoher Reynoldszahl ....... 81 Abbildung 51: Partikelverfolgung über den schrägen Balken ................................... 82 Abbildung 52: Simulation eines Flusses (Partikelverfolgung) ................................... 82 Abbildung 53: Simulation eines Flusses (Geschwindigkeitsfeld) .............................. 82 Abbildung 54: Strömung über eine Stufe.................................................................. 83 Abbildung 55: Stufenströmung mit Re = 1000 (Geschwindigkeitsfeld) ..................... 84 Abbildung 56: Stufenströmung mit Re = 1000 (Partikelverfolgung) .......................... 84 Abbildung 57: Auto im Windkanal (Geschwindigkeitsfeld) ........................................ 85 Abbildung 58: Auto im Windkanal (Geschwindigkeitsfeld) ........................................ 85 Abbildung 59: tum3D-Logo (Geschwindigkeitsfeld) .................................................. 86 Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 97 von 99 Stichwortverzeichnis Ableitungen, partiell ..........................11 Advektion..........................................40 Ähnlichkeit ........................................38 Ambient-Anteil ..................................23 Anfangsbedingungen........................39 Anfangswert-Randwert-Problem.......39 ATI Radeon 9700 .............................33 Auftriebskraft ....................................89 Auslenkung.........................................9 Auslöschungen .................................88 Bandmatrix .......................................51 Betrachtungsvektor...........................24 Bilder pro Sekunde .....................34, 77 Bildschirm Auflösung ......................................76 Speicher........................................77 Boussinesq-Appromixation ...............90 Brechungsindex................................28 clFramework ...............................53, 60 Collcated Grid...................................43 Courant-Friedrichs-Levi-Bedingungen ......................................................45 Cube-Maps .................................26, 33 Dämpfung .........................................15 Dämpfungstextur ..............................31 Differentialgleichung .........................38 Differenzenverfahren, finite.........11, 46 Diffusion................................40, 50, 71 Rate ..............................................71 Direct3D-Device ...............................56 DirectX..................................55, 62, 64 Displacement Mapping .....................35 Divergenz .........................................53 Divergenzfreiheit...................38, 39, 49 Doner-Cell-Diskretisierung................48 Dreiecksdurchsatzraten ......................5 Dreiecksnormale...............................19 Druck ..............................39, 40, 69, 74 Randbedingung.............................60 Druckrandwerte ................................89 Durchflussgeschwindigkeit ...............10 Einflusskraft ......................................50 Einschlag ..........................................16 Radius .......................................... 17 Tiefe ............................................. 17 Epsilon-Schranke............................. 54 Explizites Verfahren....................14, 46 Exponentialfunktion ......................... 15 Fehlerterm ....................................... 11 Fixed-Function-Pipeline ................... 65 Fluid................................................. 37 Element ........................................ 40 inkompressibel ............................. 37 instationär..................................... 37 laminar ......................................... 37 Zelle ............................44, 45, 56, 89 Framebuffer ..................................... 58 Freie Randwertprobleme ................. 89 Gausselimination ............................. 51 Gauss-Seidel-Verfahren .......52, 53, 88 Geometrieeinheit ............................. 35 Geschwindigkeit Feld ...................................69, 74, 77 Messung..................................55, 76 Geschwindigkeitsfeld ..................87, 89 Gitter Auflösung ..................................... 76 regulär .....................................12, 13 versetzt ........................................ 43 Zelle ............................................. 76 Gleichungssystem ........................... 51 GPU................................................... 5 Grafik-API ........................................ 55 Graphical Processing Unit ................. 5 Halbvektor ....................................... 25 Hauptspeicher.................................... 5 High-Level-Shader-Language.............. ..........................................55, 64, 67 Hindernis ......44, 56, 69, 75, 79, 81, 83 Bitfeld ........................................... 56 Editor.......................................75, 88 Information ................................... 56 Randbedingung.......................44, 56 Shape-Wert .............................56, 60 Shift-Wert ................................56, 60 Textur ......................................68, 75 Zelle ....44, 45, 56, 60, 68, 75, 88, 89 Echtzeitfähige Simulation von Wasser auf Grafikhardware Seite 98 von 99 Implizites Verfahren..........................14 Impulsgleichung.................................... .................. 37, 38, 42, 46, 50, 68, 90 Instabilität, numerische.....................14 Interpolation, bilinear ..................65, 77 Isolinien ............................................87 Iterationsschritt ...................................9 Phong-Illumination-Model .................... ....................................19, 22, 25, 35 Pixel-Shader .......................5, 6, 59, 88 Pixel-Shader 2.0 Standard....33, 59, 67 Pixel-Shader 3.0 Standard....59, 89, 92 Pixel-Shader-Einheiten ...................... 7 Poisson-Gleichung..................9, 49, 51 Konjugierte Gradienten-Verfahren........ ................................................53, 54 Konstantenregister ...........................68 Kontinuitätsgleichung ........................... ..............................37, 38, 42, 49, 51 Konvektion..................................40, 50 Randbedingung ............................... 41 Ausströmbedingung ..................... 41 Einströmbedingung ...................... 41 Haftbedingung.........................41, 79 Rutschbedingung ......................... 41 Rechenfehler ................................... 88 Rechengeschwindigkeit ................... 76 Reflexionsvektor .............................. 25 Rendering Pipeline .......................... 62 Residuum ........................................ 54 Reynoldsgleichungssystem ............. 37 Reynoldszahl ............38, 45, 79, 81, 83 Rotation ......................................69, 74 Rückwärtsdifferenz .......................... 11 Rückwärtsverfolgung ....................... 71 Licht Anteil, diffuse ................................23 Berechnung...................................34 Brechung.....................19, 28, 33, 35 Farbe.......................................19, 24 Intensität .................................19, 24 Quelle......................................19, 22 Reflexionen .......................19, 33, 35 Refraktion......................................33 Strahl.......................................19, 28 Vektor............................................23 Massenerhaltung ........................38, 39 Membran ............................................9 Microsoft ...........................................55 Navier-Stokes-Gleichungen.................. ................... 8, 37, 38, 42, 44, 45, 54, ....................................76, 87, 90, 91 dimensionsbehaftet.......................38 dimensionslos ...............................38 Diskretisierung ..............................42 Nischenströmung........................60, 79 Numerische Fehler ...........................88 Oberflächenkräfte .............................40 Oberflächennormale ...................19, 23 Oberflächenspannung ........................9 Oszillationen .....................................45 Parallelrechner ...................................7 Partikel .....................60, 69, 73, 77, 89 Diffusion ........................................60 Pinsel ......................................60, 73 Verfolgung.............56, 60, 71, 87, 89 Schattentextur.............................52, 56 Shader ......................................... 5, 32 Shader-Länge .................................. 59 Shader-Quellcode............................ 61 Simulation, numerische ..................... 8 Simulationstyp ................................. 61 Driven Cavity...........................60, 79 Inject ............................................ 61 Ocean ...............................61, 81, 83 Waterfall ....................................... 60 Stabilitätsbedingung ........................ 45 Stabilitätsfaktor ................................ 45 Staggered Grid .................................... ............43, 45, 47, 50, 55, 56, 57, 58 Strahlenverlauf................................. 22 Stromfunktion................................... 87 Stromlinien....................................... 87 Strömung ..................................... 8, 37 Stufenströmung ..........................61, 83 Taylor-Formel .................................. 11 Technique ........................................ 67 Temperatur ...................................... 89 Textur .............................31, 55, 57, 92 Echtzeitfähige Simulation von Wasser auf Grafikhardware Überschwinger..................................14 Ufer...................................................15 Vektornormale ..................................19 Vertex-Buffer ..............................55, 57 Vertexnormale ..................................19 Vertex-Shader ........................6, 58, 59 Vertex-Shader 3.0 Standard .............92 Video-Speicher ...................................5 Viskosität ..........................................39 Visualisierung ...................................77 Visualisierungstechnik .......................... ..............................69, 74, 76, 77, 87 Volumenrenderer..............................90 Vorwärtsdifferenz..................11, 46, 47 Vorwärtsverfolgung...........................71 Wasser ...............................................9 Durchlässigkeit..............................10 Seite 99 von 99 Membran ...................................... 33 Oberfläche.............................8, 9, 13 Water2D .......................................... 33 Water3D .....................................33, 35 Wellen................................................ 9 Bewegungen .................................. 9 Geschwindigkeit ........................... 10 Gleichung ....................................... 8 Kämme......................................... 19 Shader ......................................... 31 Textur ......................................31, 33 Wirbel .............................................. 74 Stärke................................74, 77, 87 Straße .....................................38, 61 Straße, Kármánsche ...............81, 85 Zähigkeit .......................................... 39 Zeit..............................................39, 45 Zentraldifferenz................................ 11