enter title here (14 pt type size, uppercased, bold and centere
Transcription
enter title here (14 pt type size, uppercased, bold and centere
Non Photorealistic Rendering für Echtzeit-Applikationen Frank Kraus Sascha Siebert Hochschule Darmstadt Fachbereich Informatik Vertiefung aktueller Themen in der Computer Graphik ABSTRACT 1. Einleitung Dieses Paper soll eine Einführung in gängige Non Photorealistic Rendering – Effekte geben und diese im Hinblick auf Echtzeitfähigkeit sowie Bildqualität analysieren. Dabei wird insbesondere auf das Toon Shading eingegangen. Toon Shading setzt sich aus zwei unterschiedlichen Algorithmen zusammen. Die abgestuften Schattierungen werden dabei über einen Cel Shader realisiert. Der zweite Algorithmus beschäftigt sich mit dem Zeichnen der Objektränder. Non Photorealistic Rendering1 bezeichnet ein Verfahren zum Rendern von Grafiken, welches im Gegensatz zu Photorealistic Rendering keinen Anspruch auf eine möglichst realistische Darstellung erhebt. Im Gegensatz dazu steht hier oft der künstlerische Aspekt im Vordergrund. Neben Einsatzgebieten wie zum Beispiel Computerspielen und Grafikdemos wird NPR aber auch für andere Anwendungsgebiete wie dem CAD Bereich eingesetzt. Ein weiterer Bestandteil dieses Artikels sind Post-Effekte. Anhand ausgewählter Algorithmen werden diese Verfahren erklärt und Alternativen aufgezählt. In diesem Zusammenhang wird die Realisierung von BloomEffekten genauer untersucht. Als Basisapplikation für dieses Paper wurde eine Variante des beliebten Pong-Spiels aus dem Jahre 1972 implementiert, an dem die verschiedenen Grafikeffekte gezeigt werden. (a) (b) (c) (d) Abbildung 1.1 – NPR Effekte (a): photorealistisch (b): Toon Shading (c): Sketch Shading (d): Outlining Typische NPR-Effekte sind Toon-Shading, Strichzeichnungen sowie Outlining für den technischen Gebrauch. Diese werden in Abbildung 1.1 von links nach rechts dargestellt. Das erste Bild zeigt demgegenüber Photorealistic Rendering. Viele NPR-Effekte sind oft sehr rechenaufwändig. Für Anwendungsgebiete, die einen hohen Grad an Interaktion aufweisen und somit auf Echtzeitfähigkeit angewiesen sind, muss gewährleistet sein, dass trotz des Einsatzes Abbildung 0.1 – das klassische Pong 1 im Folgenden auch als NPR bezeichnet von NPR-Methoden diese Echtzeitfähigkeit nicht verloren geht. Dieses Paper will Methoden und Wege aufzeigen, wie NPR-Effekte unter Berücksichtigung dieser Anforderung effizient implementiert werden können. Dabei wird insbesondere auf Möglichkeiten zur Optimierung dieser Effekte eingegangen. Moderne Grafikkarten bieten programmierbare Shadereinheiten, auf denen man viele NPR-Effekte effizienter als auf der CPU berechnen kann. Anhand des Beispiels Toon-Shading sowie einiger ausgewählter Post-Effekte wird gezeigt, wie solche Verfahren sinnvoll und effizient auf moderner Grafikhardware implementiert werden können. Viele der genannten Optimierungsmöglichkeiten lassen sich im Allgemeinen auch auf andere NPR-Effekte anwenden. zwischen der Oberflächennormalen n an der Stelle des zu beleuchtenden Pixels und dem Richtungsvektor r vom beleuchteten Pixel zur Lichtquelle2 und der Entfernung zur Lichtquelle l. Die entfernungsabhängige Komponente l gibt dabei an, ab welcher Entfernung kein Licht mehr zu sehen ist. Die Pixelfarbe c wird durch Multiplikation des diffusen Anteils d mit der Intensität s berechnet. Für den Einsatz mehrerer Lichtquellen ist es notwendig, für jeden beleuchteten Pixel die Beleuchtungsberechnung anhand dieses Beleuchtungsmodells durchzuführen und die resultierenden Farben additiv zu Verknüpfen. Die Abstufung der Schattierung wird erreicht, indem man den errechneten Winkel zwischen Oberflächennormalen und Lichtvektor in verschiedene festgelegte Winkelstellungen einteilt. Bei mehreren Lichtquellen ist dieses Ergebnis allerdings unbefriedigend, da gerade im Überlappungsbereich der Lichtquellen sehr viele kleine abschattierte Bereiche entstehen (vgl. Abb. 2.1 (a)). 2. Toon-Shading Beim Toon-Shading geht es darum, die Szene comichaft darzustellen. Dazu gehört insbesondere eine abgestufte Schattierung (Cel-Shading) sowie die Darstellung von schwarzen Rändern um die Objekte. [THOMA02] zeigt ein Verfahren auf, wie Toon-Shading durch die Wahl eines geeigneten Beleuchtungsmodells einfach implementiert werden kann. Dieses Verfahren wird an dieser Stelle aufgegriffen und im Hinblick auf den Einsatz multipler Lichtquellen analysiert. 2.1. Cel-Shading Um eine abgestufte Schattierung zu ermöglichen, wird zunächst analog zu dem Photorealistic Rendering die Farbe der zu beleuchtenden Pixel mittels des Phongschen Reflektionsmodells berechnet. Formel #1 s= n⋅r ∗max0.0, l−length l/l c=d∗s Das phongsche Reflektionsmodell wird wie in Formel #1 zu sehen durch eine vereinfachte Version nachgebildet. Die Intensität des Lichtes s ist abhängig von dem Winkel (a) (b) Abbildung 2.1 – Cel Shading mit drei Lichtquellen Eine Alternative hierzu ist es, die Abstufung der Schattierung durch eine Einteilung der bereits fertig beleuchteten Pixel in verschiedene Intensitätsstufen durchzuführen. Die zugehörige Berechnung sieht folgendermaßen aus: Formel #2 Intensity = max ( color.r,color.g,color.b ) graduatedIntensity 1.0, wenn Intensity < 1.0 0.5, wenn Intensity < 0.75 0.0, wenn Intensity < 0.25 2 auch Lichtvektor genannt finalColor.r = color.r * ( graduatedIntensity / Intensity ) finalColor.g = color.g * ( graduatedIntensity / Intensity ) finalColor.b = color.b * ( graduatedIntensity / Intensity ) Abbildung 2.1 zeigt beide Verfahren gegenübergestellt. Zu erkennen ist, dass beim zweiten vorgestellten Verfahren (b) deutlich weniger Farbregionen entstehen, diese aber einen Farbverlauf ausweisen. Jede Farbe in einer solchen Region besitzt jedoch als Resultat der obigen Formeln die gleiche Intensität. Da die oben genannten Berechnungen für jedes Pixel durchgeführt werden müssen, sollte sehr auf die Perfomance des Cel-Shaders geachtet werden, da gerade bei hohen Auflösungen die Anzahl zu rendernder Pixel enorm ist. Der Flaschenhals bei diesem Verfahren stellt die Abstufung der Schattierung dar, da hier viele Fallunterscheidungen getroffen werden müssen. Aber gerade diese sind auf moderner Grafikhardware aufgrund des Pipelining-Konzepts ineffizient und sollten daher möglichst vermieden werden. Diese Fallunterscheidungen können jedoch durch ein einfaches aber effizientes Konzept vermieden werden. Hierzu wird anstelle der Fallunterscheidung eine eindimensionale Textur gesampelt. Diese Textur enthält von links nach rechts diejenigen Werte, die ansonsten über die Fallunterscheidungen bestimmt werden müssten, also im Endeffekt die gewünschten Abstufungen der Schattierung. Abbildung 2.2 zeigt eine solche Textur mit fünf verschiedenen Abstufungen für die Schattierung. Diese wird nun anhand der shading-Varibale aus der obigen Formel des vereinfachten PhongschenReflektionsmodells gesampelt. Zu beachten ist, dass diese Textur ohne Filterung gesampelt werden muss, da sonst interpolierte Wert entstehen können, welches hier zu unerwünschten Resultaten führen würde. Neben dem Geschwindigkeitsvorteil kann hier zusätzlich sehr einfach zur Laufzeit des Programms diese Textur verändert werden, um so andere Schattier-Effekte zu erzielen. Abbildung 2.2 – eindimensionale Textur zur Optimierung der Performance 2.2 Outlining Für die Darstellung der Objektränder wurden zwei verschiedene Verfahren analysiert und im Hinblick auf Bildqualität und Performance gegenübergestellt. 2.2.1 Wireframe Das erste Verfahren basiert auf der Idee, die Szene zwei mal zu rendern. Beim ersten Durchgang wird die Szene mittels Cel-Shading gerendert. In einem zweiten Durchgang wird nun die Szene im Wireframe-Modus über die alte Szene gezeichnet. Dabei werden die Vorderseiten nicht gezeichnet. Dies kann in modernen 3D-APIs durch Aktivierung von Backface-Culling und Einstellung des Drehsinns der Polygone realisiert werden. Der typische Drehsinn für die Vorderseiten ist gegen den Uhrzeigersinn. Abbildung 2.3 zeigt einen Würfel mit und ohne gezeichneten Vorderseiten. Abbildung 2.3 – Würfel mit Back- und Frontface Culling Durch den Z-Buffer werden nur diejenigen Linien angezeigt, die am Rand des Objekts beziehungsweise innerhalb des Objektes an so genannten Innenkanten liegen. Um die Kanten deutlicher zu visualisieren kann die Linienbreite in den meisten 3D APIs vergrößert werden. Abb. 2.4 – Outlines über Wireframe-Drawing Bei diesem Verfahren können an den Eckpunkten der Kanten ungewollte Lücken entstehen, was durch die Verdickung der Linien durch die Hardware verursacht wird. Dies wird in Abbildung 2.4 verdeutlicht. 2.2.2 Kantendetektion Eine Alternative zu dem Wireframe-Verfahren aus Kapitel 2.2.1 stellt eine Kantendetektion über eine Faltungsmatrix zum Beispiel mittels LaPlace dar. Diese sind jedoch in der Regel rechenaufwändig und werden stark von der gewählten Auflösung beeinflusst. Mit dem Einzug programmierbarer Grafikhardware ist es nun möglich, diese Berechnungen effektiv auf der Grafikkarte durchzuführen. Da es dem Pixel Shader jedoch nicht möglich ist, benachbarte Pixel abzufragen, bedient man sich eines einfachen aber effizienten Tricks : Abbildung 2.5 zeigt die Resultate des Laplace-Operators über die N8-Nachbarschaft. Um von Objekten nur die Objektränder und keine Kanten innerhalb der Objekte zu bekommen, wurden alle Objekte, die mit Kanten versehen werden sollen einfarbig und ohne Lichtberechnung gerendert. Die Anwendung des Laplace-Operators liefert auf diese Weise sehr schöne Konturen. Zu beachten ist, dass der Ergebniswert des Laplace-Operators für jeden Pixel noch mit dem ursprünglichen Farbwert der leeren Textur verglichen wird, und bei Ungleichheit dieser komplett auf Schwarz gesetzt wurde. Dies sorgt dafür, dass auch kleine Änderungen verursacht durch den Laplace-Operator mit voller Ausprägung gezeichnet werden und so die Linien dicker erscheinen. Es werden zwei Rendering-Durchgänge gemacht. Im ersten Durchgang wird die Szene wie üblich gerendert. Statt jedoch direkt auf den Bildschirm zu rendern, wird hier in eine Textur gerendert, die von nun an zur Nachbearbeitung genutzt werden kann. Im zweiten Durchgang wird diese Textur auf ein Quad gemappt, welches mittels orthographischer Projektion so platziert wird, dass sie den ganzen Viewport bedeckt. Würde für diesen Rendering-Vorgang die StandardPipeline verwendet, so wäre kein Unterschied zum normalen Rendern ohne den Umweg über die Textur ersichtlich. Über diesen Umweg ist es jetzt jedoch möglich, durch die Wahl eines programmierbaren Shaders auch die Nachbarpixel abzufragen, da diese jetzt in der Textur gespeichert werden. Hierzu muss man lediglich einen Offset auf die u und v-Texturkoordinaten addieren beziehungsweise subtrahieren. Dieser Offset ist abhängig von der Auflösung der Textur. Bei einer 1024*1024 Textur wäre er 1/1024. Durch alle Kombinationen von Additionen und Subtraktionen erhält man so die Texturkoordinaten der acht umliegenden Pixel. Mit diesen Informationen kann nun im Pixel-Shader sehr effizient der LaPlace-Operator implementiert werden. Eine zugehörige Faltungsmatrix für die N4-Nachbarschaft sieht folgendermaßen aus: Abbildung 2.5 – Einsatz des Laplace-Operators Das Verknüpfen von Original-Szene sowie der Kante Textur geschieht durch einfaches Alpha-Blending, wobei folgende Formel zum Einsatz kommt : Color = αAEdgeTexColor + (1 − αA)SceneColor Abbildung 2.6 zeigt das Ergebnis dieser Verknüpfung. Abbildung 2.6 – Einsatz des Blendings 2.2.3 Vergleich Bei dem Wireframe basierten Verfahren hängt aufgrund des zweiten Rendervorgangs die Geschwindigkeit von der Anzahl der Polygone in der Szene ab. Das zweite auf Kantendetektion basierte Verfahren demgegenüber ist nur abhängig von der gewählten Auflösung. Eine allgemeine Empfehlung kann nicht ausgesprochen werden, dar dies von der zugrunde liegenden Anwendung abhängig ist. In den meisten Fällen ist das Wireframe-Verfahren schneller. Es zeigt aber beim Einsatz von verdickten Linien wie bereits erwähnt eine schlechtere Bildqualität. Das Kantendetektionsverfahren hat den Nachteil, dass es aufgrund des Einsatzes des Laplace-Operators ungeeignet ist für die Detektion von Innenkanten. Will man auch Innenkanten erfassen, so sind andere Strategien notwendig. Ein gängiger Ansatz ist es, die Szene mit einem Shader zu Rendern, welcher als Farben die Normalen der Flächen rendert. Nun müssen nur noch Sprünge in den Steigungen der Normalen gefunden werden. Hierzu können wieder gängige Kantendetektoren, wie in [EBRAHIMI05] beschrieben, benutzt werden. Auch hier kann wieder der Laplace-Operator verwendet werden. Bei dem kantendetektionsbasierten Verfahren ist es recht einfach möglich, auf Kosten der Bildqualität eine schnellere Verarbeitungszeit zu erzielen, indem man einfach die Auflösung der Textur, in die gerendert wird, kleiner wählt als die Bildschirmauflösung. Beim Zeichnen der Textur über das normal gerenderte Bild nutzt man dabei die Filterverfahren zum Hochskalieren, die von der Grafikhardware zur Verfügung gestellt werden wie zum Beispiel dem bilinearen Filtering. Weiterhin ist es bei diesem Verfahren möglich, über eine Verkettung von Faltungsoperationen die Darstellung der Outlines zu verändern. Über eine Erosion beziehungsweise Dilatation lässt sich so zum Beispiel relativ einfach die Linienbreite verändern. 3. Post-Effekte Post-Effekte werden in der Computergrafik dazu verwendet, eine bereits gerenderte Szene nachzubearbeiten. Im Zusammenhang mit dem Zeichnen der Konturen im Kapitel 2.2.2 stellte das Verfahren zur Kantendetektion über den Laplace-Operator bereits einen Post Effekt dar. Das allgemeine Verfahren zur Erstellung von PostEffekten ist in der Regel immer gleich. Es wird das in Kapitel 2.2.2 beschriebene zweistufige Verfahren benutzt, um die Szene oder Teile der Szene nach der ersten Stufe ohne Post-Effekte in einer Textur vorrätig zu haben. Auf diese Textur können nun verschiedene Shader angewandt werden, welche für die Realisierung der Post-Effekte zuständig sind. In der zweiten Stufe der Verfahrens wird nun genau wie in Kapitel 2.2.2 beschrieben vorgegangen. Will man mehrere Post-Effekte miteinander kombinieren, so muss man jedoch hier anstatt direkt auf den Bildschirm zu rendern, wieder auf eine Textur rendern und diese dann dem nachfolgenden Shader verfügbar machen. Üblicherweise werden in diesen Shadern gängige Algorithmen aus der 2D-Bildverarbeitung eingesetzt. Dies umfasst insbesondere die Faltungsmatrizen, da sich diese im Pixelshader sehr einfach und effizient nachbilden lassen. Mit diesen Werkzeugen lassen sich nun auf einfache Art und Weise visuell beeindruckende Effekte erzielen. Im Folgenden werden zwei gängige Post-Effekte vorgestellt, welche ebenfalls in der zugrunde liegenden Anwendung eingesetzt werden. 3.1 Bloom Bloom bezeichnet den Effekt von sehr grellem, strahlendem Licht. Abbildung 3.1 soll dies verdeutlichen. Beim Blick auf eine helle Lichtquelle sind deren Konturen nicht mehr sichtbar, stattdessen wirkt der Körper verschwommen und einzelne Lichtstrahlen brechen heraus. Dies kann man mit Hilfe von Post Effekten sehr einfach und effizient nachbilden. Im Rahmen der zugrunde liegenden Anwendung soll dieser Effekt eingesetzt werden, um einen leuchtenden Schimmer um die Bälle, welche gleichzeitig den Lichtquellen in der Szene entsprechen, zu realisieren. Nebeneffekt durch die verringerte Auflösung ist das entstehen eines dezenten Flackerns der weichgezeichneten Regionen beim Bewegen der beleuchteten Objekte in der Szene. Dies liegt daran, dass die kleine Textur nicht 1:1 auf den Bildschirm gemappt werden kann und so bei einer Bewegung leichte Ruckler entstehen, welche den besagten Effekt verursachen. Abbildung 3.1 – Bloom Effekte in der Natur Das im folgenden vorgestellte Verfahren ist zwar in keinster Weise physikalisch korrekt, aber darum geht es beim NPR-Rendering auch nicht. Der erste Schritt zur Darstellung eines solchen Effekts ist es, nur die Lichtquellen auf eine separate Textur zu rendern. Anschließend wird diese mittels eines GaussFilters weichgezeichnet. Um den Effekt zu verstärken, kann diese Operation mehrmals angewandt werden. Das Ergebnis dieser Operation nach dreimaliger Anwendung der Gauss-Filterung zeigt Abbildung 3.2. Abbildung 3.3 – Ergebnis nach Blending Operation Abbildung 3.3 zeigt die Resultate dieses Blendings. Die Bloom-Textur wurde hier in einer Auflösung von 128*128 Pixeln erstellt, im Gegensatz zu einer Bildschirmauflösung von 1024*768 Pixeln. Abbildung 3.2 – Gauss Filterung auf 3 Lichtquellen Die so erstellte Textur wird nun additiv über die Szene nach folgender Formel geblendet : Color = αAEdgeTexColor + 1*SceneColor Um den Effekt weiterhin zu verstärken und gleichzeitig die Performance dieser Operationen deutlich zu steigern, empfiehlt es sich, die Auflösung der Textur deutlich kleiner zu wählen als die des Bildschirms. Die nötige Skalierung beim Blending sollte dabei durch bilineare Interpolation erfolgen. Auf diese Weise wirkt zum einem ein einzelner Durchgang beim Gauss-Filter auf ein größeres Gebiet und man spart sich unter Umständen einige Wiederholungen des Verfahrens. Zum anderen steigt die Geschwindigkeit allein durch die kleinere Auflösung drastisch an, da schon bei einer Halbierung der Auflösung nur noch 25% der Pixel-Shader Aufrufe gemacht werden. Ein weiterer Eine weitere Möglichkeit, einfache Bloom-Effekte sogar ohne Shader-Einatz realisieren zu können, wurde in [CORNO07] beschrieben. Hier werden alle Lichtquellen in eine separate Textur gerendert. Diese Textur wird dann anschließend in mehreren Zoom-Stufen überlagert und an die richtige Stelle in der Szene projiziert, wobei die vergrößerten Texturen mit einem festen alpha-Wert von zum Beispiel 0,2 gezeichnet werden, um einen sanften Farbübergang zu erzielen. Der Vorteil dieses Verfahrens ist zum einen, dass keine Shader dafür nötig sind, zum anderen ist es dem ersten Verfahren auch in der Geschwindigkeit überlegen, da das Nachbearbeiten wegfällt und lediglich mehrere Quads auf den Bildschirm gezeichnet werden müssen. Dafür ist man allerdings auch sehr eingeschränkt, was eine Weiterverarbeitung des Effekts angeht. Das erste Verfahren kann man durch geeignete Shader um Effekte wie ausbrechende Lichtstrahlen einfach erweitern, welches beim zweiten Verfahren nicht ohne weiteres möglich ist. Weiterhin wirkt der Effekt beim zweiten Verfahren in der Regel viel generischer (vgl. Abb. 3.4). Für die Darstellung der Lichter in der Szene selbst wurde daher das Shader-Basierte Verfahren gewählt. Abbildung 3.4 zeigt den Einsatz des Verfahrens ohne Shader auf GUI-Elemente. Texturkoordinaten für jeden Pixel gesampelt. Stattdessen wird ein Richtungsvektor auf die Texturkoordinaten addiert, welcher vom Kollisionspunkt in Richtung des darzustellenden Pixels verläuft und dessen Länge abhängig ist von der Entfernung des Pixels zum Kollisionspunkt. Pixel nahe am Kollisionspunkt werden durch einen größeren Offset beeinflusst als Pixel, die weiter vom Kollisionspunkt entfernt sind. Zusätzlich wurde die Länge der Richtungsvektoren noch über die Zeit verringert, um den Effekt mit der Zeit abzuschwächen. Abbildung 3.4 – Bloom Effekte ohne Shader Dieses Verfahren lässt sich durch wenige Handgriffe für eine ganze Reihe von Effekten einsetzen, wie zum Beispiel Hitzeflimmern, Implosionen, etc.. 3.2 Verzerrungs-Effekte Für die zugrunde liegende Anwendung wurde ein weiterer Post-Effekt implementiert, welcher eine Verzerrung verursacht, wenn zwei Bälle miteinander kollidieren. Abbildung 3.5 zeigt zwei Bälle vor und nach einer Kollision. 4. Resultate Auf Grundlage dieses Papers wurde eine kleine Anwendung programmiert, welche alle beschriebenen Effekte demonstriert. Als Erweiterung des klassischen Pong-Spiels wurden mehrere Bälle verwendet, welche jeweils eine Lichtquelle darstellen. Neben dem ToonShading sowie den Bloom-Effekten kam ein weiterer Post-Effekt zum Einsatz, welcher bei Ballkollisionen die in Abbildung 4.1 gezeigten Verzerrungen verursacht. Abbildung 3.5 – Verzerrung nach einer Kollision Hierzu wurde dem Shader einfach nach einer Kollision der Kollisionspunkt übergeben, welcher zunächst vom Weltkoordinatensystem in Texturkoordinaten auf der zugehörigen Textur aus Stufe 1 des zweistufigen Verfahrens transformiert werden muss. Um dies zu erreichen, genügt es, den Punkt in normalisierte Gerätekoordinaten zu transformieren (Intervall von -1 bis 1) und anschließend durch eine Addition um 1 und eine Division durch 2 in das Intervall zwischen 0 und 1 zu bringen. Um nun den Verzerrungs-Effekt zu realisieren, wird die Textur nicht wie üblich an den im Shader errechneten Abbildung 4.1 – Screenshot der Anwendung 5. Fazit NPR-Effekte werden heutzutage immer häufiger eingesetzt. Dies liegt zum großen Teil an den Innovationen der Grafikkartenhersteller. Mit dem Einzug programmierbarer Grafikhardware sind dem Programmierer fast keine Grenzen mehr gesetzt. Gerade Toon-Shading ist durch die gezeigten Algorithmen und Optimierungen heutzutage schon auf herkömmlichen Heim-PC-Systemen ohne große Hardwareanforderungen echtzeitfähig. Aufgrund dieser Eigenschaft ist es hervorragend zur Visualisierung von Computerspielen im comichaften Stil geeignet. Der Einsatz von Post-Effekten ist vor allem in der Spieleindustrie gerade bei aktuellen Computer- und Videospielen immer häufiger anzutreffen. Grund hierfür ist die einfache Implementierung dieser Effekte. Zwar gibt es auch andere Möglichkeiten, ähnliche Effekte auch ohne Shader zu erzielen, doch ist dies in der Regel zeitaufwändiger in der Herstellung und weniger flexibel. [FUMITO05] hat jedoch gezeigt, dass man auch heutzutage noch sehr beeindruckende echtzeitfähige Effekte auf Systemen ohne programmierbare Shadereinheiten mit sehr begrenzten Ressourcen erstellen kann. Literaturverzeichnis [EBRAHIMI05] “Edge and contour detection – Solution” von Prof. Touradj Ebrahimi, Dezember 2005 [THOMA02] “Non-Photorealistic Rendering Techniques for Real-Time Character Animation” Diplomarbeit von Jérome Thoma, Dezember 2002 [CORNO07] Dario Corno: NeHe -Homepage “http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=36“, Stand Mai 2007 [FUMITO05] The Making Of "Shadow Of The Colossus" Fumito Ueda, Hajime Sugiyama, Takuya Seki, Masanobu Tanaka, Dezember 2005