Ich sehe ein paar weitreichende Ansätze, um Cel Shading zu machen:
- Vervielfältigung & Vergrößerung des Modells mit gespiegelten Normalen (für mich keine Option)
- Der Sobel-Filter / Fragment-Shader nähert sich der Kantenerkennung
- Der Schablonenpuffer nähert sich der Kantenerkennung
- Geometrie- (oder Vertex-) Shader-Ansätze, mit denen Flächen- und Kantennormalen berechnet werden
Habe ich Recht, wenn ich annehme, dass der geometriezentrierte Ansatz die größte Kontrolle über Beleuchtung und Liniendicke bietet, z. für Gelände, in dem Sie die Umrisslinie eines Hügels sehen könnten, der allmählich in eine Ebene übergeht?
Was ist, wenn ich auf meinen Geländeflächen keine Pixelbeleuchtung benötige? (Und ich werde wahrscheinlich nicht Zellen-basiertes Vertex- oder Textur-Map-basiertes Beleuchten / Shadowing verwenden.) Wäre es dann besser, wenn ich mich an den geometrietypischen Ansatz halte oder stattdessen einen Screen Space / Fragment-Ansatz wähle um die Dinge einfacher zu halten? Wenn ja, wie würde ich das "Einfärben" von Hügeln innerhalb der Netzsilhouette erhalten, anstatt nur den Umriss des gesamten Netzes (ohne "Einfärben" -Details in diesem Umriss? (AKA suggeriert Konturen , Falten ).
Ist es schließlich möglich, den Ansatz der gespiegelten Normalen mit einem Geometrie-Shader kostengünstig zu emulieren? Ich befürchte, dass ich jeden einzelnen Scheitelpunkt duplizieren und entsprechend skalieren könnte, aber wie würde ich mich dem Spiegeln von Normalen und einer deutlichen Färbung im Fragment-Shader nähern?
Was ich will - unterschiedliche Strichstärken mit aufdringlichen Linien innerhalb der Silhouette ...
Was ich nicht will ...
EDIT: Weitere Forschung hat Folgendes ergeben ...
Da ich selbst unter Berücksichtigung des distanzbasierten LoD eine enorme Anzahl von Scheitelpunkten im Gelände habe, sind weder Flipped-Normalals noch ein auf Geometrie-Shader basierender Ansatz (selbst bei kegelstumpfförmigem Culling) eine sinnvolle Option, da die Duplizierung und Skalierung aller Elemente mit einem hohen Rechenaufwand verbunden ist Hochgeladene Vertices.
Da ich keine pixelgenaue Beleuchtung in Form von Volltonschattierungen auf den Geländeoberflächen benötige, wird es auch weniger ratsam, Ansätze auf der Basis von Gesichtsnormalen zu berücksichtigen - andernfalls ist dies eine Voraussetzung für eine korrekte Oberflächenbeleuchtung sind natürlich recht teuer in der berechnung. Es ist jedoch wahr, dass sie das beste Maß an Kontrolle geben; Zum Beispiel die Möglichkeit, Kanten mit "künstlerischen" Strichen zu schattieren: Wunderschön, aber auch für eine sehr komplexe Spielumgebung nicht wirklich brauchbar.
Schablonenpuffer sind etwas, das ich lieber vermeiden möchte, da ich es vorziehen würde, alle Arbeiten in Shadern auszuführen. (Das obige Beispiel mit dem roten Umriss wurde mit einem Schablonenpuffer erstellt - old school.)
Dies hinterlässt Fragment-Shader-Bildraum-Ansätze. Die Komplexität der Berechnung wird auf die Anzahl der Fragmente und nicht auf die Anzahl der Scheitelpunkte reduziert (in meinem Fall sind dies 10 bis 100 Mal weniger Operationen als im Geometrie-Shader). Dies erfordert mehr als einen Renderdurchlauf, um einen g-Puffer (bestehend aus einem normalen Puffer und optional auch einem Tiefenpuffer) zu erzeugen, auf den wir Diskontinuitätsfilter anwenden können (z. B. Sobel-Operator). Tiefendiskontinuität ermöglicht suggestive Konturen und Falten. Mein einziges Manko bei diesem Ansatz ist die Unfähigkeit, die Breite der eingefärbten Kanten genauer zu steuern, obwohl ich mir sicher bin, dass dies mit dem richtigen Algorithmus im Fragment Shader möglich wäre.
Die Frage wird nun genauer: Wie genau würde ich in einem Fragment-Shader variable Kantenbreiten erzielen, insbesondere auf der äußeren Silhouette?