Die Geschichte der Entwicklung von The Light Remake. Teil 1





Grüße Leser! Mein Name ist Sergey, ich bin ein Indie-Computerspielentwickler. Ich habe bereits mehrere Indie-Projekte in meinem Portfolio, von denen einige auf Steam selbst veröffentlicht wurden. Das 2012 erschienene Spiel Light oder The Light war mein erster Stift und Pionier in der Welt der Spieleentwicklung. Das Projekt wurde kostenlos verteilt, aber die öffentliche Reaktion und das Feedback der Spieler haben mich ernsthaft motiviert, weiter zu arbeiten. "Das Licht" ist für mich so etwas wie eine philosophische Parabel über die Menschheit und ihr Schicksal geworden. Die Handlung ist abstrakt und verfolgt keine spezifischen Ziele. Sie ist lediglich eine Gelegenheit, über ein breites Thema nachzudenken.



Da das ursprüngliche Spiel es nie bis zur Veröffentlichung auf Steam geschafft hat, habe ich beschlossen, diese Lücke zu schließen, und im Juni 2019 begann eine umfassende Überarbeitung des Projekts, damit es dem Gameplay und der Optik entspricht und als vollwertiges Spiel betrachtet werden kann.







Worüber reden wir?



Dieser Artikel konzentriert sich speziell auf das "Light" -Projekt und auf die Arbeit im Zusammenhang mit der Portierung des Spiels auf eine neuere Version der Unity-Engine. Dies impliziert viele technische Nuancen. Der Artikel wird in zwei Teilen präsentiert.



Teil 1



Die ursprüngliche Version des Spiels wurde bereits 2012 auf Unity 4.2 erstellt. Damals wurde in meinem Informationsfeld noch nicht über PBR-Materialien, Reflextests und andere Methoden gesprochen, die derzeit relevant sind. Grundlegende Shader in Unity waren sehr einfach und nicht sehr realistisch. Natürlich war es möglich, viele zusätzliche Elemente wie Fresnel-Reflexionen hinzuzufügen, aber dann war die Shader-Programmierung für mich ein Geheimnis hinter sieben Siegeln. Die wichtigsten verwendeten Shader waren Normal Bumped Specular und AlphaTest Diffuse für Objekte mit Transparenz (Baumblätter, lockige Metallgitter).



Es gab keine Riltime-Schatten, fast die gesamte Beleuchtung war in Textur eingebrannt und die Auflösung dieser Schatten war stellenweise sehr niedrig. Durch das Backen des Lichts über alles andere wurde der Bump-Effekt des Bumped Specular-Shaders auf nahezu Null reduziert, sodass die Objekte bei näherer Betrachtung eher wie flacher Karton aussehen.



Das Bild wurde durch Nachwirkungen auf die Kamera, insbesondere Bloom und Color Correction, erheblich verändert. Sie fügten Farbe und Abwechslung hinzu, obwohl sie stellenweise zu aufdringlich waren.







Zum Zeitpunkt der Erstellung dieses Projekts hatte ich noch vage Vorstellungen über Optimierung, Batching (Kombination zu einem Netz), Okklusion - Keulen (Abschneiden unsichtbarer Objekte) usw. Aber aufgrund der Tatsache, dass die Szene technisch nicht mit etwas Kompliziertem beladen war, keine Riltime-Beleuchtung, Gras mit einem Alphakanal usw. hatte. - Das Spiel kam ziemlich optimiert heraus und funktionierte gut auf schwacher Hardware, was ein angenehmes Bild für 2012 ergab.



Nach 7 Jahren betrachten Sie jede Ihrer Kreationen mit anderen Augen. Die Technologien haben sich stark weiterentwickelt, die Werkzeuge haben sich geändert, die neuesten Versionen der Unity-Engine unterscheiden sich erheblich von ihren Vorgängern. In Verbindung mit all dem ist die Übertragung des Projekts von Version 4 auf Version 2017 (ich habe mich aus mehreren Gründen entschlossen, damit aufzuhören) eine ziemlich lange und mühsame Arbeit. Angesichts der Tatsache, dass das ursprüngliche Projekt nicht als vollwertiges Spiel bezeichnet werden konnte (die meisten Aktionen im Spiel wurden mit einem Skript mit Triggerfunktion ausgeführt), war es außerdem erforderlich, die gesamte Logik von Grund auf neu zu schreiben, mit Objekten zu interagieren, Inventar, Menüsystem, System Speichern, Erfolge, Einstellungen usw. Im Allgemeinen erwartete mich eine sehr große Menge an Arbeit!



Start. Shader und Licht



Das erste, was beim Öffnen eines Projekts in einer neuen Engine demoralisierend ist, ist, dass das gesamte Bild beschädigt ist. Viele Shader und Post-Effekte, die aus Quellen von Drittanbietern importiert wurden, funktionieren nicht mehr. Die Shader, die weiterhin funktionieren, sehen etwas anders aus. Die Beleuchtung in der Szene ändert sich, Lichtkarten fliegen ab, alles muss neu berechnet werden.







Neuer Standart



Es wurde beschlossen, zunächst alte Shader durch einen neuen PBR-Standart zu ersetzen. Im vorherigen ArtikelBei der Entwicklung von 35 MM habe ich bereits einen neuen Typ von PBR-Shadern (Physically Based Rendering) erwähnt, der ein korrektes physisches Rendering impliziert. Der neue Materialstandard hat nicht mehr den üblichen o.Gloss und o.Specular aus den Vorgängerversionen, hier haben wir eine Karte der Metallizität (o.Metallic) und der Glätte. Es gibt auch mehr Steckplätze für Texturen verschiedener Kategorien. Zum Beispiel haben wir die Möglichkeit, eine Okklusionskarte für weiche Schattierungen hinzuzufügen. Dieser Effekt ist sehr nützlich, da Sie damit Volumen und Schattierungen in Bereichen des Modells hervorheben können, in denen weniger Licht vorhanden ist. Ohne diese Karte und Lichtkarte - die Textur - sehen Objekte flach und unrealistisch aus.







Es gibt die gleiche Detailalbedo und Detailnormal - diese Karten fügen Details zu unseren vorhandenen Texturen hinzu. Sie können beispielsweise eine zusätzliche normale Karte mit kleinen Rissen platzieren und diese durch Anpassen des Einflussgrades tönen. Infolgedessen wird die ursprüngliche Bump-Textur mit niedriger Auflösung detaillierter angezeigt. Für einige Materialien habe ich diese Technik verwendet, während andere unverändert blieben.







Vegetation



Nachdem ich die Grundmaterialien ausgetauscht hatte, ging ich zur Vegetation über. Der ursprüngliche Build des Spiels verwendete einen Standard-Alpha-Test-Shader ohne Spekulanten und eine normale Karte. Natürlich hat mir dieser Zustand im Jahr 2019 nicht gepasst. Sie können eine fertige Lösung im Internet kaufen oder finden. Es gibt ganze Pakete mit Shadern und fertigen Modellen mit vielen Funktionen, Nachahmung des Schwankens im Wind usw. Aber traditionell versuche ich, solche Probleme selbst herauszufinden und zu experimentieren. Das ist so etwas wie ein sportliches Interesse. Mein neuer Vegetable Shader basiert auf der Toon Ramp- Referenz aus dem Unity-Tutorial.



Mit dem vorgestellten LightingRamp-Beleuchtungsmodell konnte die Schatten-Silhouette sowohl auf der beleuchteten Seite des Polygons als auch auf der gegenüberliegenden Seite gezeichnet werden. Dies ahmte die Fähigkeit des Laubes nach, Lichtdurchlässigkeit zu übertragen.







Ein ähnlicher Shader kann auch zum Rendern transparenter Stoffe wie Vorhänge verwendet werden.







Leider ergab das automatische Rendern der Rückseite des Polygons mit der Cull Off-Methode in diesem Modus kein sehr korrektes Ergebnis, sodass die Rückseite manuell im Editor hinzugefügt werden musste. Als nächstes wurde die Normal- und Spiegelkarte dem Shader hinzugefügt. Ich konnte das PBR-Shader-Beleuchtungsmodell nicht verwenden und die Reflexionssonden anschließen, aber mit Hilfe von Masken und der Emissionskarte habe ich die Nachahmung der Umgebungsokklusion hinzugefügt. Und schließlich war es äußerst notwendig, das Ganze wiederzubeleben und der Vegetation Bewegung zu geben. Mit der Vertex-Funktion und der gleichen Maske werden die gewünschten Bereiche der Laubplatten zum Leben erweckt. Der Scheitelpunktversatz basiert auf dem Beispiel Normale Extrusion mit Scheitelpunktmodifikator aus dem Unity- Handbuch .







Sie können die Geschwindigkeit und Amplitude einstellen. Übrigens hat sich in diesen Experimenten die neue Funktion zum Verwalten der globalen Variablen von Shadern als nützlich erwiesen ... Sie können allen erforderlichen Shadern aus dem Skript einfach jede Variable oder Textur zuweisen.







Scheinen



Die Herangehensweise an das Beleuchtungsgerät in der Szene wurde erheblich geändert. Im Original wurde alles Licht in Lichtkarten eingebrannt, und das Rendern funktionierte im Vorwärtsmodus. Ein wichtiger Aspekt des Remakes war die Verwendung von Echtzeitlicht, um die Tageszeit ändern zu können. Der Rendermodus wurde in Zurückgestellt geändert. Das Hauptlicht (Sonne) wurde im gemischten Modus verwendet, gerichtetes Licht und Schatten wurden in Echtzeit gezeichnet und die globale Beleuchtung wurde in Texturen eingebrannt. Dies ermöglichte es, das Lichtniveau und die Richtung zu ändern, behielt aber gleichzeitig den Effekt einer weichen globalen Beleuchtung und Reflexionen bei, die dem Bild immer zusätzlichen Realismus verleihen. Lightmap-Texturen wurden nicht für alle Objekte gebacken, hauptsächlich für große und mehr oder weniger einfache. Kleine und komplexe Sweeps blieben dynamisch und wurden entweder mit Lichtsonden hervorgehoben,Reflexionstests oder nur einfaches Umgebungslicht (das in den Hauptbeleuchtungseinstellungen angegeben ist). Das Backen erfolgte mit einem Progressive Lightmapper.















Tag und Nacht



Um die Tageszeit zu ändern, wurde ein Skybox-Shader mit zwei Texturen erstellt: Tag und Nacht. Beide Optionen wurden durch eine Versatzfunktion ergänzt, um die Wolkenbewegung zu simulieren. Die Nachthimmel-Texturen und das anomale Leuchten für die Szene des Fluges der Kampfraketen wurden ebenfalls hinzugefügt. All diese Schande wurde durch ein spezielles Skript kontrolliert, das die Skybox und die Sonne drehte. An bestimmten Positionen der Sonne änderte sich die Farbe der Skybox, die Texturen wurden mit der Lerp-Methode gemischt und der Nachthimmel und die Sterne wurden reibungslos enthüllt. Die Wirkung des Glühens des Himmels nach dem Abschuss der Raketen wurde ebenfalls auf einer separaten Ebene hinzugefügt.







Zur Optimierung bei minimalem Lichtniveau (ca. 0,1-0,2) wurden die Schatten sanft ausgeschaltet. Um die Zeit zu ändern, mussten einige weitere wichtige Punkte berücksichtigt werden. Auf der Bühne befanden sich Partikel - Pappelflusen. Ihr Material reagierte nicht auf Licht (zu diesem Zeitpunkt hatte ich noch keinen geeigneten Shader gefunden), daher musste die Farbe des Flusenmaterials je nach Tageszeit mit einem Skript geändert werden.



Beim Ändern der Uhrzeit hat das Skript außerdem die gewünschte Farbe für den Global Fog-Nacheffekt angepasst, da der Nebel tagsüber wie ein hellgrau-blauer Dunst aussehen und nachts einen dunkleren, fast schwarzen Ton haben sollte.







Modelle und neue Inhalte



Der Hauptteil der Lage und Grundmodelle: Das Modell des Hauptgebäudes, Bäume, Bänke, Laternenpfähle blieb original. Viele andere Requisiten wurden ganz oder teilweise überarbeitet. Das Modell der Petroleumlampe wurde überarbeitet, ein neuer Dieselgenerator mit separaten animierbaren Elementen wurde erstellt, ein neues Modell eines Kinoprojektors usw.















Gebäude in der Nähe, die zuvor nicht betreten werden konnten, wurden neu gestaltet und dem Spieler zur Verfügung gestellt. Die Innenausstattung des Hauptgebäudes wurde ebenfalls geändert. Zusätzlich zur Überarbeitung des alten Inhalts wurde ein neues hinzugefügt, beispielsweise ein PAZ-Busmodell, ein Spielautomat, ein Getränkeautomat, ein Puzzle - eine Schalttafel, eine hermetische Tür im Keller, Inventargegenstände usw. Ein Teil des Inhalts wurde unabhängig erstellt, ein Teil der Modelle wurde ausgelagert.







Für fast alle Objekte, für die Lightmaps gebacken wurden, wurde manuell ein UV2-Scan erstellt, wobei die Fragmente aus wirtschaftlichen Gründen optimal angeordnet wurden. Beispielsweise nahmen bei Gebäuden alle schwer zugänglichen Bereiche (z. B. Decken und Wände der oberen Stockwerke), die der Spieler praktisch nicht sieht, nur minimalen Platz auf dem Scan ein.



Effekte und benutzerdefinierte Shader.



Wasser







Bei jedem neuen Projekt möchte ich die Nuancen berücksichtigen, für die wir zuvor unsere Augen geschlossen haben. Das Gesamtbild wird aus separaten Details erstellt und selbst nicht sehr wichtige Elemente können die Wahrnehmung beeinflussen. Außerdem ist es eine Art Herausforderung - jedes Mal etwas zu verbessern, mit dem ich bereits gearbeitet habe. Es ist besonders befriedigend, selbst Lösungen zu finden, anstatt vorgefertigte Assets zu verwenden. In allen vorherigen Projekten habe ich mit Wasser gearbeitet. In der Regel war es ein ziemlich einfacher Vertex-Shader, der nicht auf den Player und die Beleuchtung in der Szene reagierte. Es basierte auf Mirror Reflection aus dem Unity Wiki, einem Beispiel für eine Spiegelimplementierung.







Die Oberfläche war aufgrund der Verschiebung der Eckpunkte (Nachahmung von Wellen) dynamisch, aber immer zu eintönig und etwas langweilig. Durch Versuch und Irrtum für das Light-Projekt gelang es mir, eine Oberflächenversion eines ähnlichen Shaders zu erstellen, der wie ein Beispiel: eine spiegelnde Reflexionstextur aus einem Spiegelskript empfangen, Scheitelpunkte verformen kann, um Wellen zu simulieren, einen Bildschirm in eine Grabpass-Textur schreiben kann, um unter Wasser Brechungen zu erzeugen, weiche Alpha-Kanten aufweist beim Überschneiden mit der Geometrie (Tiefenüberblendung). Für den Effekt der Reaktion auf den Spieler werden Informationen über die Koordinaten der Position des Spielers an den Shader weitergegeben. Am Koordinatenpunkt wird ein dynamischer Punkt gezeichnet, der Spritzer simuliert, wenn sich das Zeichen direkt in der Wassersäule befindet. Das Wichtigste, was der Surface Shader zuließ, war, Licht von jeder Lichtquelle zu empfangen. Auf diese Weise scheint das Wasser greifbarer,volumetrische Substanz und ermöglicht es Ihnen, mit Lichteffekten damit zu spielen.







Ätzmittel



Ein weiteres wichtiges Detail war die Erzeugung des Ätzeffekts - Lichtreflexionen, die auf die Oberfläche fallen. In der Dunkelheit der wasserüberfluteten Kellertunnel war diese Technik unerlässlich. Der Effekt wurde mit einem Projektorobjekt und einem leuchtenden Material mit einer animierten Textur erstellt. Der Shader mischt 2 ätzende Texturen, die in verschiedene Richtungen verschoben werden, was zu einem dynamischen Effekt führt. Um Geld zu sparen, verwende ich in den meisten meiner Shader normalerweise Texturmasken mit 4 Kanälen (RGBA) - jeweils für einen bestimmten Zweck. Der R-Kanal kann eine Grundtextur haben, der G-Kanal hat weichere Lichtpunkte und der B-Kanal hat eine Rauschtextur, um das Ätzmuster zu verzerren.







Die Wasseroberfläche hat einen Collider mit einem speziellen Tag. Sobald der Charakter ins Wasser kommt, erkennt das Skript dies mithilfe der Raycast-Methode und schaltet die Ätzung reibungslos ein. In diesem Fall werden auch verschiedene Bedingungen dargelegt, z. B. das Vorhandensein eines Feuerzeugs, einer Taschenlampe oder einer Petroleumlampe in der Nähe der Hände.







Partikel



Ein interessanter Effekt wurde für kleine Partikel in der Luft implementiert, die im Licht sichtbar sind. Die Idee selbst wurde vom Homesick-Projekt inspiriert, bei dem ich einmal etwas Ähnliches gesehen habe. In einem bestimmten Abstand haben die Partikel eine regelmäßige Textur, ähnlich der Textur von Pappelflusen. Wenn sich die Kamera nähert, ändert sich die Textur im Shader reibungslos in die zweite Version, was an den Defokussierungseffekt erinnert. In der Dynamik sieht es ganz gut aus und die Partikel wirken greifbarer.







Wie oben erwähnt, verwenden fast alle Basisflächen in der Szene eine modifizierte Version des Standart PBR-Shaders. Einige haben Masken mit unterschiedlichen Spot-Optionen hinzugefügt, um zusätzliche Details zu Albedo-Texturen zu erhalten. Es wurde eine Punktmaske hinzugefügt, um Regenpfützen auf Oberflächen wie Asphalt oder Pflastersteinen zu simulieren. Der Bodenfliesen-Shader im Hauptgebäude verfügt über eine zusätzliche Karte für Reflexionen, die vom Spiegel-Skript ähnlich wie eine Wasseroberfläche gerendert werden. Zur Optimierung werden nur einfache und große Objekte in das Rendern von Reflexionen einbezogen, und in einem bestimmten Abstand wird das Rendern von Reflexionen deaktiviert.



Nebel / Rauch



Ein wichtiges Detail, das ich bei der Erstellung des Remakes berücksichtigen wollte, ist der dynamische Nebel und die Wirkung der Beleuchtung, insbesondere das Licht einer Laterne. In früheren Arbeiten war der Haupt-Shader für Rauch und Nebel die Standard-Partikelmischung und ihre Modifikationen. Dies ist ein Vertex-Shader, der in Bezug auf die Leistung gut ist, aber überhaupt nicht auf Licht reagiert. Die Anzeige von Nebel mit einem solchen Material ist im Schatten und im Licht immer gleich, es kann nicht mit einer Laterne beleuchtet werden und es sieht nicht immer attraktiv und natürlich aus. In den unterirdischen Katakomben, die ich mir vorgestellt hatte, sollte der Dunst durch eine Laterne aus der Dunkelheit hervorgehoben werden, die durch dynamisches Licht hervorgehoben wurde. Um dieses Problem zu lösen, wurde ein Shader aus einem freien Asset verwendet . Der Shader kann sich keiner hohen Leistung rühmen, hat aber seine Aufgabe optisch perfekt gemeistert.







Abziehbilder



Ein weiterer wichtiger Punkt war die Suche nach einem geeigneten Shader für die Abziehbilder. Das Spiel plante viele Arten von Graffiti, die meistens mit dem alten Abziehbild-System-Plugin (seit der alten Version von Unity 4.6) installiert wurden. Für Graffiti, Inschriften und Schilder wurde ein großer Atlas von 4096 x 4096 erstellt. Bilder auf Abziehbildern sind durchscheinend und werden im transparenten Alpha-Modus gerendert. Bei dynamischer Beleuchtung sehen sie daher nicht immer angemessen aus, da der Standard-Alpha-Shader keine Schatten empfangen kann.



Um das Problem zu lösen, wurde ein spezieller Zwei-Pass-Shader erstellt. Der erste Durchgang zeichnet die dunklen Teile des Bildes, der zweite die hellen Teile mit der Mischmethode DstColor One. Ich verstehe die Zeichenmethode möglicherweise nicht ganz richtig, daher werde ich auf detaillierte Erklärungen verzichten, aber ich habe es geschafft, das gewünschte Ergebnis zu erzielen: Im Schatten ist das Bild in der Dunkelheit vergraben, und im Licht erscheint es und spielt sogar mit Farben. Der Two-Pass-Shader hatte keinen Einfluss auf die Leistung, da das Decal-System zunächst alle Decals zu einem großen Netz kombiniert. Wahrscheinlich gibt es bessere Möglichkeiten, aber diese Option passt perfekt zu mir.











Erde / Gras



Ein weiterer Zwei-Pass-Shader wurde für die Bodenoberfläche erstellt. Das Gebiet am Standort wird durch die Geometrie in 3d max. Für das Rendern des Grases wurde jedoch ein zusätzliches Gelände geschaffen. Ich musste die Geländehöhen manuell an den richtigen Stellen anpassen, um sie an das Gelände anzupassen. Dann wurde das Rendern des Geländes selbst abgeschaltet und mehrere Varianten der vorbereiteten Grasmaschen wurden mit einem Pinsel auf die Oberfläche aufgetragen. Das einheimische Gras auf dem Gelände ist in Bezug auf die Leistung furchtbar schwer in der Szene, da es nicht stapelt und jedes Element einen zusätzlichen Ziehungsaufruf erzeugt (vielleicht korrigiert mich jemand, wenn ich falsch liege), aber diese Methode ist in Bezug auf die Arbeit äußerst praktisch. Die Dichte des Grases ist nicht hoch und an den Stellen, an denen dies nicht der Fall ist, ist die Einfachheit der Oberfläche sehr auffällig. In diesem Zusammenhang habe ich als Experiment einen Zwei-Pass-Shader verwendet.das wurde oben erwähnt. Der erste Durchgang ist eine reguläre undurchsichtige Geometrie, der zweite ist ein leicht erhöhtes Duplikat der Oberfläche im Alpha-Testmodus. Grob gesagt wird zusätzlich eine Kopie der Boden- / Grasoberfläche mit harter Transparenz gezeichnet und die Eckpunkte nach oben verschoben. Diese Methode ergänzt das flache Gras etwas und erzeugt die Illusion von zusätzlichen Details und Volumen.







Licht außerhalb des Fensters An



einigen Stellen außerhalb der Fenster des Hauptgebäudes wurden einseitige durchscheinende Sprites platziert, um Glanzlichter zu simulieren. Außerdem hat der Global Fog-Posteffekt einen hellweißen Nebelparameter, der aktiviert wird, wenn sich der Held tiefer in das Gebäude hineinbewegt. Das heißt, wenn sich der Charakter in den dunklen Korridoren des Gehäuses befindet, erhält die Umgebung draußen sanft einen weißlichen Schimmer. Dies erzeugt einen ziemlich schönen künstlerischen Effekt und ermöglicht es Ihnen, den nahen und fernen Plan hervorzuheben.







Damit ist der erste Teil des Artikels abgeschlossen. Link zum zweiten Teil. Vielen Dank für Ihre Aufmerksamkeit!



All Articles