Wie kann ich Umrisse um 3D-Modelle zeichnen? Ich beziehe mich auf so etwas wie die Effekte in einem kürzlich erschienenen Pokemon-Spiel, die anscheinend einen einpixeligen Umriss haben:
3d
shaders
graphics
graphics-programming
mystisches Portal
quelle
quelle
Antworten:
Ich glaube nicht, dass eine der anderen Antworten hier den Effekt in Pokémon X / Y erzielen wird. Ich kann nicht genau wissen, wie es gemacht wird, aber ich habe einen Weg gefunden, der so ziemlich dem entspricht, was sie im Spiel machen.
In Pokémon X / Y werden Umrisse sowohl an den Konturkanten als auch an anderen Nicht-Konturkanten gezeichnet (wie in dem folgenden Screenshot, wo Raichus Ohren auf seinen Kopf treffen).
Wenn Sie sich Raichus Netz in Blender ansehen, sehen Sie, dass das Ohr (oben in Orange hervorgehoben) nur ein separates, nicht verbundenes Objekt ist, das den Kopf schneidet und eine abrupte Änderung der Oberflächennormalen bewirkt.
Darauf basierend habe ich versucht, den Umriss anhand der Normalen zu generieren, was ein Rendern in zwei Durchgängen erfordert:
Erster Durchgang : Rendern Sie das Modell (texturiert und cel-schattiert) ohne die Konturen und rendern Sie die Normalen des Kameraraums auf ein zweites Renderziel.
Zweiter Durchgang : Führen Sie einen Vollbild-Kantenerkennungsfilter über den Normalen des ersten Durchgangs aus.
Die ersten beiden Bilder unten zeigen die Ausgaben des ersten Durchgangs. Das dritte ist der Umriss für sich und das letzte ist das endgültige kombinierte Ergebnis.
Hier ist der OpenGL-Fragment-Shader, den ich im zweiten Durchgang für die Kantenerkennung verwendet habe. Es ist das Beste, was ich mir einfallen lassen konnte, aber es könnte einen besseren Weg geben. Es ist wahrscheinlich auch nicht sehr gut optimiert.
Und bevor ich den ersten Durchgang rendere, lösche ich das Renderziel der Normalen auf einen Vektor, der von der Kamera abgewandt ist:
Ich habe irgendwo gelesen (ich werde einen Link in den Kommentaren einfügen), dass der Nintendo 3DS eine Pipeline mit festen Funktionen anstelle von Shadern verwendet. Ich bin überzeugt, dass meine Methode nahe genug ist.
quelle
Dieser Effekt tritt besonders häufig in Spielen auf, in denen Cel-Shading-Effekte verwendet werden, kann jedoch unabhängig vom Cel-Shading-Stil angewendet werden.
Was Sie beschreiben, wird als "Feature Edge Rendering" bezeichnet und hebt im Allgemeinen die verschiedenen Konturen und Umrisse eines Modells hervor. Es gibt viele Techniken und viele Artikel zu diesem Thema.
Eine einfache Technik besteht darin, nur die Konturkante, den äußersten Umriss, zu rendern. Dies ist so einfach wie das Rendern des Originalmodells mit einem Schablonenschreibvorgang und das anschließende erneute Rendern im Thick-Wireframe-Modus, nur wenn kein Schablonenwert vorhanden war. Hier finden Sie ein Implementierungsbeispiel.
Dadurch werden jedoch die Innenkontur und die Knickkanten nicht hervorgehoben (wie in Ihren Bildern gezeigt). Um dies effektiv zu erreichen, müssen Sie im Allgemeinen Informationen über die Kanten des Netzes extrahieren (basierend auf Diskontinuitäten in den Flächennormalen auf beiden Seiten der Kante) und eine Datenstruktur aufbauen, die jede Kante darstellt.
Sie können dann Shader schreiben, um diese Kanten zu extrudieren oder auf andere Weise als reguläre Geometrie über Ihrem Basismodell (oder in Verbindung damit) zu rendern. Die Position einer Kante und die Normalen der angrenzenden Flächen relativ zum Ansichtsvektor werden verwendet, um zu bestimmen, ob eine bestimmte Kante gezeichnet werden kann.
Weitere Diskussionen, Details und Vorträge mit verschiedenen Beispielen finden Sie im Internet. Zum Beispiel:
quelle
dz/dx
dz/dy
Der einfachste Weg, dies zu tun, ist das Duplizieren des Modells und das Umkehren der Scheitelpunkt-Wicklungsreihenfolge, so dass das Modell von innen nach außen angezeigt wird (oder wenn Sie möchten, können Sie dies tun) Tun Sie dies in Ihrem Werkzeug zur Erstellung von 3D-Objekten, sagen Sie Blender, indem Sie die Oberflächennormalen spiegeln (dasselbe gilt für). Erweitern Sie dann das gesamte Duplikat geringfügig um seine Mitte und färben / texturieren Sie dieses Duplikat schließlich vollständig schwarz. Dies führt zu Umrissen um Ihr ursprüngliches Modell, wenn es sich um ein einfaches Modell wie einen Würfel handelt. Bei komplexeren Modellen mit konkaven Formen (wie in der Abbildung unten) muss das duplizierte Modell manuell so angepasst werden, dass es etwas "dicker" als das ursprüngliche Modell ist, z. B. eine Minkowski-Summein 3D. Sie können beginnen, indem Sie jeden Scheitelpunkt entlang seiner Normalen etwas nach außen schieben, um das Umrissnetz zu bilden, wie dies bei der Schrumpf- / Fett-Transformation von Blender der Fall ist.
Platz auf dem Bildschirm / Pixel - Shader - Ansätze sind in der Regel langsamer und schwieriger zu implementieren gut , aber OTOH nicht doppelt so hoch die Anzahl von Eckpunkten in Ihrer Welt. Wenn Sie also viel arbeiten, entscheiden Sie sich am besten für diesen Ansatz. Angesichts moderne Konsole und Desktop - Kapazität Geometrie für die Verarbeitung, würde mich nicht um einen Faktor 2 Sorgen überhaupt . Cartoon-Stil = mit Sicherheit Low Poly, daher ist das Duplizieren von Geometrie am einfachsten.
Sie können den Effekt zB in Blender selbst testen, ohne einen Code zu berühren. Die Umrisse sollten wie in der Abbildung unten aussehen. Beachten Sie, dass einige davon innerlich sind, z. B. unter dem Arm. Mehr dazu hier .
.
quelle
Für glatte Modelle (sehr wichtig) ist dieser Effekt ziemlich einfach. In Ihrem Fragment- / Pixel-Shader benötigen Sie die Normalen des zu schattierenden Fragments. Wenn es sehr nahe an der Senkrechten liegt (
dot(surface_normal,view_vector) <= .01
- möglicherweise müssen Sie mit dieser Schwelle spielen), färben Sie das Fragment schwarz anstatt der üblichen Farbe.Dieser Ansatz "verbraucht" einen kleinen Teil des Modells, um den Umriss zu erstellen. Dies kann oder kann nicht sein, was Sie wollen. Es ist sehr schwierig, anhand des Pokemon-Bildes zu erkennen, ob dies getan wird. Es hängt davon ab, ob Sie erwarten, dass der Umriss in einer Silhouette des Charakters enthalten ist, oder ob der Umriss die Silhouette einschließen soll (was eine andere Technik erfordert).
Das Highlight wird sich auf jedem Teil der Oberfläche befinden, auf dem der Übergang von der Vorderseite zur Rückseite erfolgt, einschließlich der "Innenkanten" (wie die Beine des grünen Pokémon oder dessen Kopf). Einige andere Techniken würden diesen keine Konturen hinzufügen ).
Objekte mit harten, nicht glatten Kanten (wie ein Würfel) erhalten bei diesem Ansatz an den gewünschten Stellen keine Hervorhebung. Dies bedeutet, dass dieser Ansatz in einigen Fällen überhaupt nicht in Frage kommt. Ich habe keine Ahnung, ob Pokemon-Modelle alle glatt sind oder nicht.
quelle
Am häufigsten habe ich dies durch einen zweiten Render-Pass für Ihr Modell gesehen. Duplizieren Sie es im Wesentlichen, drehen Sie die Normalen um und verschieben Sie sie in einen Vertex-Shader. Skalieren Sie im Shader jeden Scheitelpunkt entlang seiner Normalen. Zeichnen Sie im Pixel- / Fragment-Shader Schwarz. Dadurch erhalten Sie sowohl externe als auch interne Konturen, z. B. um die Lippen, die Augen usw. Dies ist eigentlich ein recht billiger Zeichnungsaufruf, wenn nichts anderes in der Regel billiger als die Nachbearbeitung der Linie, abhängig von der Anzahl der Modelle und ihrer Komplexität. Guilty Gear Xrd verwendet diese Methode, da die Linienstärke einfach über die Scheitelpunktfarbe gesteuert werden kann.
Die zweite Möglichkeit, innere Linien zu machen, habe ich aus demselben Spiel gelernt. Richten Sie in Ihrer UV-Karte Ihre Textur entlang der u- oder v-Achse aus, insbesondere in Bereichen, in denen Sie eine innere Linie wünschen. Zeichnen Sie eine schwarze Linie entlang einer der beiden Achsen und verschieben Sie die UV-Koordinaten in diese Linie hinein oder aus dieser heraus, um die innere Linie zu erstellen.
Eine bessere Erklärung finden Sie im Video von GDC: https://www.youtube.com/watch?v=yhGjCzxJV3E
quelle
Eine Möglichkeit, einen Umriss zu erstellen, besteht darin, die normalen Vektoren unserer Modelle zu verwenden. Normale Vektoren sind Vektoren, die senkrecht zu ihrer Oberfläche stehen (von der Oberfläche weg zeigen). Der Trick dabei ist, dein Charaktermodell in zwei Teile zu teilen. Die Scheitelpunkte, die der Kamera zugewandt sind, und die Scheitelpunkte, die der Kamera abgewandt sind. Wir werden sie FRONT und BACK nennen.
Für den Umriss nehmen wir unsere BACK-Eckpunkte und verschieben sie leicht in Richtung ihrer normalen Vektoren. Stellen Sie sich das so vor, als würde der Teil unseres Charakters, der von der Kamera abgewandt ist, etwas dicker. Nachdem wir das erledigt haben, weisen wir ihnen eine Farbe unserer Wahl zu und wir haben einen schönen Umriss.
Zeile 41: Die Einstellung "Front aussortieren" weist den Shader an, ein Aussortieren an den nach vorne gerichteten Scheitelpunkten durchzuführen. Dies bedeutet, dass wir in diesem Durchgang alle nach vorne gerichteten Eckpunkte ignorieren. Wir haben die RÜCKSEITE, die wir ein wenig manipulieren wollen.
Zeilen 51-53: Die Mathematik zum Verschieben von Eckpunkten entlang ihrer normalen Vektoren.
Zeile 54: Stellen Sie die Scheitelpunktfarbe auf die Farbe Ihrer Wahl ein, die in den Shadereigenschaften definiert ist.
Nützlicher Link: http://wiki.unity3d.com/index.php/Silhouette-Outlined_Diffuse
Aktualisieren
ein anderes Beispiel
quelle
Eine der besten Möglichkeiten besteht darin, Ihre Szene auf einer Framebuffer- Textur zu rendern und diese Textur dann zu rendern, während Sie eine Sobel-Filterung für jedes Pixel durchführen. Dies ist eine einfache Technik zur Kantenerkennung. Auf diese Weise können Sie die Szene nicht nur pixelig machen (indem Sie eine niedrige Auflösung für die Framebuffer-Textur festlegen), sondern auch auf alle Pixelwerte zugreifen, damit Sobel funktioniert.
quelle