Erweiterung der Unity 5-Rendering-Pipeline: Befehlspuffer

In Unity 5 haben wir viele für den Benutzer sichtbare Grafikfunktionen hinzugefügt (neuer Standard-Shader, globale Beleuchtung in Echtzeit, Reflexionssonden, neuer Lightmapping-Workflow usw.), aber wir haben auch an der internen Wiedergabe gearbeitet. Neben typischen Dingen wie „Optimierung“ ( z. B. Multithread-Lichtkulling) un d „Konsistenzsteigerung“ (z. B. konsistenter zwischen Linear- und Gamma-Farbräumen) haben wir auch untersucht, wie wir die Erwe iterbarkeit verbessern können.
Intern und in der Beta-Testgruppe haben wir verschiedene Ansätze diskutiert. Viele Ideen wurden herumgeworfen: mehr Skript-Callbacks, das Zusammenstellen kleiner "Hier ist eine Liste von Dingen, die zu tun sind"-Puffer, die Möglichkeit, komplette Rendering-Pipelines von Grund auf zu erstellen, eine Art visuelle Baum-/Graph-Rendering-Pipeline-Konstruktionstools und so weiter. Für Unity 5 haben wir uns auf die Möglichkeit festgelegt, "Liste der zu erledigenden Dinge"-Puffer zu erstellen, die wir "Befehlspuffer" nannten.
Ein Befehlspuffer in der Grafik ist eine Liste von Befehlen, die auf niedriger Ebene ausgeführt werden müssen. 3D Rendering APIs wie Direct3D oder OpenGL konstruieren beispielsweise normalerweise einen Befehlspuffer, der dann von der GPU ausgeführt wird. Der Multithread-Renderer von Unity erstellt auch einen Befehlspuffer zwischen einem aufrufenden Thread und dem "Worker-Thread", der Befehle an die Rendering API sendet.
In unserem Fall ist die Idee sehr ähnlich, aber die "Befehle" sind etwas höher. Anstatt Dinge wie "internes GPU-Register X auf den Wert Y setzen" zu enthalten, lauten die Befehle "Dieses Mesh mit diesem Material zeichnen" usw.
Sie können aus Ihren Skripten Befehlspuffer erstellen und ihnen Rendering-Befehle hinzufügen („Renderziel festlegen, Mesh zeichnen, ...“). Dann können diese Befehlspuffer so eingestellt werden, dass sie an verschiedenen Stellen während des Kamera-Renderings ausgeführt werden.
Sie könnten beispielsweise einige zusätzliche Objekte in einen verzögerten Shading-G-Puffer rendern, nachdem alle regulären Objekte erledigt sind. Oder rendern Sie einige Wolken direkt nach der Skybox-Zeichnung, aber vor allem. Oder rendern Sie benutzerdefinierte Lichter (Volumenlichter, Negativlichter usw.) in einen verzögerten Schattenlichtpuffer, nachdem alle regulären Lichter erledigt sind. Und so weiter; wir denken, es gibt viele interessante Möglichkeiten, sie zu nutzen.
Sehen Sie sich die Seiten CommandBuffer und CameraEvent in der Dokumentation der Scripting API an.
Ok, ok.
Wir könnten zum Beispiel unscharfe Brechungen machen:

Nachdem opake Objekte und Skybox gerendert wurden, wird das aktuelle Bild in ein temporäres Renderziel kopiert, unscharf dargestellt und als globale Shader-Eigenschaft eingerichtet. Der Shader auf dem Glasobjekt mustert dann dieses unscharfe Bild aus, wobei die UV-Koordinaten auf einer normalen Karte basieren, um die Refraktion zu simulieren. Dies ist ähnlich wie bei Shadern GrabPass, aber Sie können auch benutzerdefiniertere Dinge tun (in diesem Fall Unschärfe).
Ein weiterer Anwendungsfall: Individuelles Deferred Lights. Hier sind kugel- und rohrförmige Leuchten:

Nachdem ein normaler verzögerter Shading-Lichtdurchlauf durchgeführt wurde, wird für jede benutzerdefinierte Beleuchtung eine Kugel mit einem Shader gezeichnet, der die Beleuchtung berechnet und dem Beleuchtungspuffer hinzufügt.
Noch ein Beispiel: Aufgeschobene Aufkleber.

Die Idee ist: Nachdem der G-Puffer fertig ist, zeichnen Sie jede „Form“ des Decals (eine Box) und modifizieren Sie die G-Puffer-Inhalte. Das ist sehr ähnlich wie die Beleuchtung bei verzögerter Schattierung, aber statt die Beleuchtung zu akkumulieren, modifizieren wir die G-Puffer-Texturen.

Jedes Decal ist hier als Box implementiert und beeinflusst jede Geometrie innerhalb des Boxvolumens.
Hier ist ein kleiner Unity (5.0 Beta 22)-Projektordner, der alles oben zeigt: RenderingCommandBuffers50b22.zip.
Sie sehen, dass alle oben aufgeführten Fälle nicht einmal komplex zu implementieren sind – die Skripts bestehen aus etwa hundert Codezeilen.
Ich finde das aufregend. Ich freue mich schon darauf, zu sehen, was ihr alle damit macht!
