
Dieses Wochenende hatte ich zwischen den Kursen etwas Freizeit
(der Autor erhielt zum Zeitpunkt des Artikels einen Master of Science) und entschied mich, wieder Shader zu erstellen, indem ich diesen Postprozess-Scan-Effekt erfand. Ich stellte mir vor, dass es im Spiel als eine Art Distanz-Scan-Effekt verwendet wird. Wir verwenden auch einige einfache Rauschverzerrungen, um den Effekt etwas interessanter aussehen zu lassen.
In diesem Artikel werde ich Ihnen erklären, wie Sie diesen Effekt auf UE4 implementieren. Es gibt verschiedene Möglichkeiten, wie Sie diesen Effekt erzeugen können. Eine dieser Methoden wurde von mir gewählt.
Sie können Bilder in einer neuen Registerkarte öffnen, um sie in höherer Auflösung anzuzeigen.
Hauptkomponenten
Die Hauptidee dieses Effekts besteht darin, eine Version des Szenen-Renderings mit
dem Sobel-Operator zu erstellen und diese dann mit dem üblichen SphereMask-basierten Szenen-Rendering zu mischen, das wir animieren, um einen Scan-Effekt zu erstellen.
Dieser Effekt besteht aus 3 Hauptkomponenten:
- Skalierbares SphereMask-Feld
- Sobel-Edge-Funktion (Ich werde nicht erklären, wie diese Funktion funktioniert, da es sich um ein separates Thema handelt, aber ich werde auf den von mir verwendeten Code verweisen)
- Überlagern Sie die projizierte Textur im Weltraster
Skalierbares SphereMask-Feld
In diesem Teil geht es darum, wie wir eine skalierbare SphereMask erstellen. Zu diesem Zweck übertragen wir die Position der Blaupause auf den Satz von Materialparametern. Anschließend verwenden wir sie wie folgt

Verbinden Sie das Ergebnis des
Clamp- Knotens mit dem
Emissionsausgang Ihres Materials, und Sie werden so etwas sehen

„TexLoc“ ist ein
Vektor3 , der den Ort der
Kugelquelle bestimmt. In meinem Fall wird er aus einer Reihe von Materialparametern gelesen, sodass er beispielsweise aus dem Spiel selbst gelesen werden kann, um die Position des Spielers zu bestimmen.
Der oben angegebene Satz von Knotenparametern erstellt ein Feld mit einem Kugelradius von 1024 Einheiten. Ich habe es nur verwendet, um das Ergebnis im Vorschaufenster anzuzeigen. Wenn Sie mehr über die Arbeit mit Remote-Funktionen erfahren und deren Verwendung verstehen möchten, empfehlen
wir Ihnen dringend,
die Inigo Quilez-Website zu besuchen .
Jetzt verwenden wir die
Zeit , um die Kugel mit einem festgelegten Zeitintervall zu skalieren.

Dies gibt uns das folgende Ergebnis
Frac (Zeit) gibt uns im Grunde eine konstante Periode, die weiter 0-1.0-1.0-1 geht. Wir multiplizieren die Zeit mit 0,25, um die Skalierungsgeschwindigkeit zu steuern, und multiplizieren dann das Ergebnis mit dem Radius der Kugel, was zu einer Änderung des Radius von 0 auf 1024 führt und uns eine animierte Maske gibt.
Dies ist ein gutes Ergebnis, aber dies ist nicht das, was wir von dem Effekt erwarten. Wir brauchen einen Skalierungsring. Dies kann leicht mit einfachen Berechnungen durchgeführt werden.

Dies gibt uns das, was wir wollen, einen wachsenden Ring mit einem guten Gradientenschwund, der gesteuert werden kann.

Die mathematischen Operationen im Block Edge_Mask wählen grundsätzlich die Position in der Gradientenmaske aus. In diesem Fall beträgt der Wert 0,5 und bestimmen die Kante der Maske aus der aktuellen Position mit einer bestimmten Breite, wodurch wir einen Ring erhalten können. Ich werde nicht auf die technischen Details des Erhaltens der Maskenkanten eingehen, höchstwahrscheinlich werde ich in einem der folgenden Beiträge darüber sprechen.
Wie Sie sehen können, haben Sie die volle Kontrolle über die Breite des Rings ohne einen skalaren Parameter, und wenn wir wollten, könnten wir sogar die Dämpfung der Kanten steuern, aber wir brauchen dies in diesem Effekt nicht.
Der nächste Schritt besteht darin, mithilfe von Rauschen eine visuell interessante Version des Rings zu erstellen.
Dazu verwenden wir den Knoten
Vector Noise , der Teil von UE4 ist. Sie können hier darüber lesen oder eine Rauschtextur verwenden, die World Aligned UV-Koordinaten enthält.
In meinem Shader habe ich den Parameter Function im
Knoten Vector Noise auf Cellnoise gesetzt. Sie können auch mit anderen Typen dieses Parameters experimentieren, um Ihren eigenen einzigartigen Effekt zu erzielen.

Das Ergebnis sieht wie folgt aus

Dies ist die erste Phase, in der unser Shader abgeschlossen ist. Anschließend werden wir die Implementierung der Sobel-Edge-Funktion in Betracht ziehen.
Sobel-Edge-Funktion
Es gibt viele verschiedene Optionen für diese Funktion, von denen einige optimierter sind als andere. Ich werde das Wesentliche nicht erläutern, da dies ein separates Thema ist. Eine regelmäßige Google-Suche mit den Schlüsselwörtern "Sobel Edge" oder "Sobel Operator" bietet Ihnen jedoch viele Optionen . Oder verwenden Sie den Artikel auf dem
Hub von
Gepard_vvk -
Algorithmen zum Auswählen von
Bildkonturen .
Die Hauptidee des Sobel-Operators lautet: Wir nehmen das
RenderTarget der Szene (stellen Sie sich vor, es ist eine Textur, die das enthält, was Sie gerade in Ihrem Ansichtsfenster sehen) und vergleichen jedes Pixel mit allen benachbarten Pixeln um es herum. Als nächstes vergleichen wir den Helligkeitsunterschied. Wenn der Unterschied über einem bestimmten Schwellenwert liegt, markieren wir ihn als Kante. Dabei erhalten wir eine schwarz-weiße
RenderTarget-Texturmaske , bei der eine Maske an den Kanten angepasst wird.
Der folgende Code ist ein einfaches Beispiel für die Sobel-Operatorfunktion, die
RebelMoogle auf der Shadertoy-Website erstellt hat (höchstwahrscheinlich ist diese Option nicht vollständig optimiert, sodass Sie eine andere Implementierung ausprobieren können). Wir werden sie in UE4 in unserem Material neu erstellen.
void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord.xy / iResolution.xy; vec3 TL = texture(iChannel0, uv + vec2(-1, 1)/ iResolution.xy).rgb; vec3 TM = texture(iChannel0, uv + vec2(0, 1)/ iResolution.xy).rgb; vec3 TR = texture(iChannel0, uv + vec2(1, 1)/ iResolution.xy).rgb; vec3 ML = texture(iChannel0, uv + vec2(-1, 0)/ iResolution.xy).rgb; vec3 MR = texture(iChannel0, uv + vec2(1, 0)/ iResolution.xy).rgb; vec3 BL = texture(iChannel0, uv + vec2(-1, -1)/ iResolution.xy).rgb; vec3 BM = texture(iChannel0, uv + vec2(0, -1)/ iResolution.xy).rgb; vec3 BR = texture(iChannel0, uv + vec2(1, -1)/ iResolution.xy).rgb; vec3 GradX = -TL + TR - 2.0 * ML + 2.0 * MR - BL + BR; vec3 GradY = TL + 2.0 * TM + TR - BL - 2.0 * BM - BR; fragColor.r = length(vec2(GradX.r, GradY.r)); fragColor.g = length(vec2(GradX.g, GradY.g)); fragColor.b = length(vec2(GradX.b, GradY.b)); }
In UE4 sieht es so aus

Ein
kurzer Hinweis zur Implementierung der Funktion:
Stellen Sie sicher, dass Ihre
SceneTexture- Knoten für die Verwendung von
PostProcessInput0 konfiguriert
sind
Zwei
benutzerdefinierte Knoten
GradX und
GradY konfigurieren sie auf ähnliche Weise
GradX :
return -TL + TR - 2.0 * ML + 2.0 * MR - BL + BR;
GradY :
return TL + 2.0 * TM + TR - BL - 2.0 * BM - BR;
Dies muss nicht in
Custom erfolgen , ich habe es nur zur Vereinfachung verwendet, da sonst zu viele Knoten vorhanden wären und sich Spaghetti bilden würden.
Wenn Sie das Ergebnis der Funktion in eine
emittierende Materialausgabe einstecken, sehen Sie Folgendes

Wir multiplizieren das Ergebnis auch mit dem regulären
Vektor3 , um die Kanten jeder gewünschten Farbe zu erhalten.

Infolgedessen ändert sich die Farbe der Kante.

Gitterstruktur-Überlagerungswelt
Der einfachste Teil: Wir verwenden einfach die Textur des Gitters und projizieren es auf der ganzen Welt. Dann kombinieren wir es mit der Sobel-Edge-Funktion, um einen coolen Effekt zu erzielen.

Wenn Sie das Ergebnis der Funktion mit dem
Emissionsausgang verbinden , werden Sie sehen

Alles zusammenfügen
Jetzt werden wir alle drei Teile für unseren Post-Effekt zusammenfügen!
Zunächst kombinieren wir die Funktionen Sobel-Edge und World-Aligned-Grid und fügen sie zusammen

Dann erstellen wir einen
SceneTexture- Knoten und fügen das Ergebnis von Sobel-Edge und World-Aligned-Grid hinzu.
Dann interpolieren wir zwischen der normalen und der hinzugefügten Szene und verwenden dabei das Ergebnis der Ringmaske, die wir im ersten Teil erstellt haben

Und voila, wir haben es geschafft. Das Endergebnis wird ungefähr so aussehen. Sie können natürlich die Parameter anpassen und versuchen, ihre Werte zu ändern, um interessantere Optionen zu erhalten.

Ich hoffe, Sie finden diese Informationen hilfreich, alles Gute :)
Ein Beispielprojekt mit diesem Shader finden Sie auf
github .