Diablo Immortal verbessert die Bildqualität mit Hardware-Raytracing

Diablo Immortal ist ein kostenloses Multiplayer-Action-Rollenspiel (ARPG), das gemeinsam von Blizzard Entertainment und NetEase entwickelt wurde. Diablo Immortal, ein neues Kapitel in der Diablo-Reihe, wurde 2022 veröffentlicht. Das Spiel schließt die Lücke zwischen Diablo 2 und Diablo 3 und bietet ein neues Abenteuer rund um die Fragmente des Weltsteins. Die Spieler erkunden den Kontinent Sanctuary und kämpfen gegen Dämonen und korrumpierte Mächte.

Dank der Innovationen bei der mobilen GPU-Architektur und der Fortschritte bei der Hardwarebeschleunigung wird die Ray-Tracing-Technologie nach und nach von Computern auf Mobilgeräte übertragen und wird zu einem der Haupttreiber für High-Fidelity-Grafik-Rendering. Die Berechnung physikalisch realistischer dynamischer Reflexionen ist rechenintensiv. Eine spezielle Hardwareeinheit macht dies jedoch auf stromsparenden mobilen Plattformen möglich. Durch die Echtzeit-Verfolgung des Lichtverlaufs durch die Szene simuliert die Technologie das Reflexionsverhalten komplexer Oberflächen wie Spiegel, Metalle und Flüssigkeiten. Raytracing überwindet die räumlichen Einschränkungen und Approximationsfehler herkömmlicher Rasterisierungsschemata und unterstützt die globale, konsistente Darstellung dynamischer Lichtquellen, Objekte außerhalb des Bildschirms und mehrstufiger Reflexionen.

Hardware-Raytracing auf Mobilgeräten

Die Hardware-Raytracing-Technologie umfasst hauptsächlich zwei Implementierungsparadigmen: Raytracing-Pipeline und Ray-Abfrage.

Die Raytracing-Pipeline erstellt eine vollständige Pipeline über spezielle Shader-Phasen (Ray-Generierung / Intersection / Closest-Hit-Shader). Obwohl eine präzise Kontrolle der Interaktion von Strahlen möglich ist, erfordert die Ray-Tracing-Pipeline eine unabhängige Pipelinekonfiguration, was die Entwicklungskomplexität erhöht.

Bei der Ray-Abfrage hingegen können Ray-Abfragen direkt von traditionellen Berechnungs- oder Fragment-Shadern initiiert werden. Dies macht sie zu einer Kerntechnologie für mobiles Raytracing. Da separate Pipelines nicht mehr erforderlich sind, vereinfacht die Ray-Abfrage nicht nur den Entwicklungsprozess erheblich, sondern bietet auch drei weitere Vorteile:

  1. Bietet Kompatibilität mit heterogenen Computing-Umgebungen und nicht vollständiger Raytracing-Hardware
  2. Unterstützt die On-Demand-Auslösung von Raytracing in jeder Schattierungsphase
  3. Durch die reduzierte Ressourcennutzung werden die Bandbreiten- und Leistungseinschränkungen von Mobilplattformen erfüllt und eine praktikable Grundlage für erweiterte Effekte wie dynamische globale Beleuchtung und Echtzeitreflexionen in mobilen Spielen geschaffen.

In Diablo Immortal wird Vulkan verwendet, um die Hardware-Raytracing-Funktionen der GPU zu nutzen. Das Spiel berechnet den Weg von Lichtstrahlen durch die Szene in Echtzeit und berücksichtigt komplexe Materialeigenschaften, um bahnbrechende Echtzeit-Reflexionseffekte auf Android-Geräten zu erzielen.

Abbildung 1 Szene mit aktivierter raytracingbasierter Reflexion.
Abbildung 2. Szene ohne raytracingfähige Reflexion.

Beschleunigungsstruktur

Die Beschleunigungsstruktur ist der Kern des Hardware-Raytracings. Die Beschleunigungsstruktur verbessert die Effizienz von Ray-Intersection-Tests durch eine hierarchische Datenorganisation erheblich.

Das System hat in der Regel zwei Ebenen: die Top-Level-Beschleunigungsstruktur (TLAS) und die Bottom-Level-Beschleunigungsstruktur (BLAS):

  • TLAS übernimmt die Rolle des Szenenmanagers. Durch Aufzeichnen der räumlichen Transformationsmatrix (einschließlich Position, Drehung und Skalierung) aller BLAS-Instanzen ermöglicht TLAS die globale Organisation dynamischer Szenen. Mit TLAS können Entwickler beispielsweise Hunderte von Instanzen desselben Baummodells an verschiedenen Positionen und Posen in der Szene platzieren. So müssen sie nur die Transformationsmatrix des sich bewegenden Objekts in jedem Frame aktualisieren, anstatt die Geometrie neu zu erstellen.
  • BLAS als Basiseinheit: BLAS ist für die effiziente Codierung der geometrischen Details eines einzelnen 3D‑Objekts verantwortlich. Es erstellt eine räumliche Indexstruktur über den Bounding Volume Hierarchy (BVH)-Algorithmus, damit irrelevante Bereiche bei der Ray-Erkennung schnell übersprungen werden können.

Dieses hierarchische Design ermöglicht es der Raytracing-Pipeline, eine effiziente Erkennungskette von Ray ==> TLAS (Körniges Sieb – Objektinstanz) ==> BLAS (exakte Schnittmenge) zu bilden.

Die Trennung von dynamischen und statischen Modellen ist der Schlüssel zur Minimierung der Kosten für die Erstellung von Beschleunigungsstrukturen:

  • Statisches Modell: Die BLAS muss nur einmal in der Initialisierungsphase erstellt werden und kann beim anschließenden Laden der Szene direkt wiederverwendet werden. Um Ladeverzögerungen bei groß angelegten Szenen zu vermeiden, kann die asynchrone Vorab-Rendering-Technologie des Framings verwendet werden, um die BLAS-Aufgabe auf mehrere Frames zu verteilen.
  • Dynamisches Modell
    • Skelettbasierte Animation: Die Skinned-Vertex-Daten müssen in jedem Frame parallel vom Compute-Shader berechnet werden, um einen neuen Vertex-Buffer zu generieren und dann die inkrementelle Aktualisierung des entsprechenden BLAS auszulösen. Dadurch wird eine vollständige Rekonstruktion vermieden, um die Leistung zu verbessern.
    • Transformation starrer Körper: Wenn nur Verschiebungs-, Dreh- oder Zoomtransformationen erforderlich sind, müssen Sie BLAS nicht ändern. Aktualisieren Sie einfach die Welttransformationsmatrix in TLAS und lösen Sie dann den schnellen Aktualisierungsprozess für TLAS aus.

Die regelmäßige Rekonstruktion ist für die Effizienz der Beschleunigungsstruktur beim Raytracing dynamischer Szenen unerlässlich. Wenn sich die geometrische Topologie dynamischer Objekte erheblich ändert, z. B. durch Verformung oder großflächige Verschiebung von Eckpunkten, funktioniert die ursprüngliche räumliche Aufteilung möglicherweise nicht mehr. Dies beeinträchtigt die Leistung der Kollisionserkennung bei der Ray-Tracing-Durchsuchung. Daher muss alle N Frames eine vollständige Rekonstruktion statt eines inkrementellen Updates der hochdynamischen BLAS/TLAS ausgelöst werden.

Um die Leistung des Raytracing-Renderings zu optimieren, sollten Sie eine dynamische TLAS-Konstruktionsstrategie basierend auf dem sichtbaren Bereich des Charakters verwenden: Nur die Modelle innerhalb des aktiven Radiusgrenzwerts des Charakters werden in die TLAS aufgenommen, um den Hauptaufwand der Berechnung von Strahlüberschneidungen zu reduzieren.

Raytracing-Reflexionen

Raytracing-Reflexionen haben gegenüber traditionellen Techniken wie Screen-Space-Reflexionen (SSR) und planaren Reflexionen (einfache Oberflächen, die eine Szene in einer Dimension projizieren) mehrere Vorteile. Bei der Raytracing-Reflexion wird der Lichtweg physikalisch simuliert, dynamische Objekte innerhalb und außerhalb der Szene werden genau erfasst, natürliche Reflexionen von gekrümmten und nicht ebenen Oberflächen werden unterstützt und es sind mehrere Lichtreflexionseffekte wie Spiegel möglich. Im Gegensatz dazu ist SSR auf die auf dem Bildschirm sichtbaren Informationen beschränkt und flache, ebene Reflexionen neigen in komplexen Szenen zu visuellen Fehlern oder Verzerrungen.

Abbildung 3 Die Spiegelung der Flügel im Pool.
Abbildung 4 Die Reflexion des Monsters.

Die Raytracing-Reflexion ähnelt im Prinzip der herkömmlichen SSR: Bei der Raytracing-Reflexion werden auf Pixelebene Strahlen in Richtung der Sichtlinie emittiert und die Schnittmenge der Strahlen mit den Szenenobjekten berechnet. Der von der Ray Query API zurückgegebene Schnittpunkt enthält geometrische Informationen (einschließlich Instanz-ID, Geometrieindex und Primitive-Index) und Rasterisierungsparameter (Baryzentrische Koordinaten) auf Dreiecksebene, aber keine Pixelfarbdaten. Bei der typischen Lösung werden alle Textur- und Materialparameter der Szene mithilfe der Bindless-Ressourcenbindungstechnologie in ein globales Indexarray vorkompiliert. Anhand der geometrischen IDs, die von der Ray-Abfrage zurückgegeben werden, können die physikalischen Eigenschaften des entsprechenden Materials (z. B. Normal- und Rauheitskarte) abgerufen und dann mit der Interpolation baryzentrischer Koordinaten kombiniert werden, um die Informationen zur Oberflächenschattierung zu berechnen. Der tatsächliche Farbwert der Schnittstelle kann dann durch Rasterung rekonstruiert werden.

Bei der Implementierung stellte das Diablo Immortal-Team jedoch zwei erhebliche technische Probleme fest:

  1. Das Beleuchtungsmodell musste vereinheitlicht werden, was mit den verschiedenen Schattierungssystemen im Verlauf des Projekts in Konflikt stand und zu einer Abweichung zwischen dem Glanzmaterial und dem Originalmaterial geführt hätte.
  2. Die Vielfalt der Vertex-Formate führt zu einer Verringerung der Effizienz der Anweisungsverzweigung in der Rasterisierungsphase, was bei dem knappen Leistungsbudget des Mobilgeräts ein großes Problem darstellt.

Das Diablo Immortal-Team hat den Sichtbarkeitsbuffer eingeführt, um die Geometrieverarbeitung von Schattierungsberechnungen zu trennen:

  • Ray-Tracing-Phase: Informationen zu Ray-Treffern auf Pixelebene werden in Echtzeit über die Ray-Abfrage erfasst. Die 3D-Speicherort-ID (InstanceID mit PrimitiveIndex) des Schnittpunkts wird in eine kompakte Sichtbarkeits-ID codiert und in den Bildschirmbereichs-Puffer geschrieben.
  • Farbphase: Ähnlich wie bei den Operationen von Vertex- und Pixel-Shadern werden die geometrischen IDs im Sichtbarkeitsbuffer dynamisch analysiert, die Vertex-Eigenschaften (z. B. UVs und Normalen) und physikalisch basierten Materialkarten des ursprünglichen Modells abgerufen und schließlich die mit dem Materialtyp verknüpften Schattierungsberechnungen durchgeführt.

Mit dieser Lösung können Art-Assets mit dem System für raytracingbasierte Reflexionen verbunden werden, ohne dass Vertex-Formate oder Shader geändert werden müssen.

Spezifische Rendering-Schritte

Ray-Abfragepass

Entspricht der Raytracing-Phase und generiert einen Sichtbarkeitsbuffer für Bildschirmreflexionen:

  • Color0
    • Format: R32G32UInt
    • R = Dreiecks-ID, G = baryzentrische Koordinaten
Abbildung 5 Sichtbarkeitspuffer.
  • Tiefe:
    • Format: Depth32F
    • D = EncodeAsFloat(InstanceIdx, GeometryIdx)
    • Die Material-ID der Kreuzung wird in 32-Bit-Gleitkomma codiert und für die nächste Stufe der Erkennungstechnik für die Tiefencodierung des Materials in den Tiefenbuffer geschrieben.
Abbildung 6 Codierte Tiefe.

Im Vergleich zu Compute Shadern hat die Ray-Abfrage im Pixel-Shader folgende Vorteile:

  • Pipeline-Integration: Die Pipeline wird direkt in vorhandene Pipeline für vorwärts-/verzögertes Rendering eingebettet, um die Kontinuität des Rendering-Pipeline-Status aufrechtzuerhalten.
  • Optimierung der mobilen Bandbreite: Bei der mobilen kachelbasierten Architektur kann die verlustfreie On-Chip-Komprimierung ausgelöst werden, wenn Ray-Trefferdaten in RenderTarget geschrieben werden. Dadurch wird die Speicherbandbreitennutzung im Vergleich zur herkömmlichen Compute-Shader-Ausgabe in den Puffer reduziert.
  • Kontrolle der Strahlenanzahl: Nicht reflektierende Bereiche können in einer Vorkalkulationsphase in Kombination mit einem Stencil-Test markiert und abgelehnt werden.

Karte/Ticket beheben

In der Farbgebungsphase (siehe Raytracing-Reflexionen) konnte das Diablo Immortal-Team durch die Verwendung der Hardwareeinheit für den Tiefentest und die Farbgebung von Materialien in aufeinanderfolgenden Batches eine schnelle Identifizierung erzielen.

Für jedes Material wird ein Vollbild-Zeichnen-Pass ausgegeben. Der Vertex-Shader rekonstruiert die codierte Kennung des aktuellen Materials dynamisch. Bei diesem Test wird die Kennung mit den codierten Werten im Tiefenbuffer verglichen. Nur Pixel, deren codierte Werte genau übereinstimmen, werden beibehalten, also Pixel, die zur aktuellen Materialinstanz gehören. Die beibehaltenen Pixel führen den entsprechenden Material-Shader aus.

Als Nächstes wird im Pixel-Shader eine hochpräzise Materialwiedergabe implementiert:

  • Dekodierung von Geometriedaten: Hier werden die Dreiecks-ID (MeshID + PrimitiveID) und die baryzentrischen Koordinaten aus dem Sichtbarkeitsbuffer extrahiert und die Vertice-Attribute (Position, UV, Normale usw.) des entsprechenden Dreiecks werden dynamisch aus dem Vertice-Buffer geladen. Da jedes Modell als unabhängiges Material schattiert wird, sind erweiterte Funktionen wie die Bindung nicht erforderlich.
  • Oberflächenparameter-Rekonstruktion: Die UV-Koordinaten an der Schnittstelle werden mithilfe der baryzentrischen Koordinateninterpolation berechnet. Die Software-Rasterisierung wird durchgeführt, um die Karte anhand der interpolierten UVs zu bemustern.
  • Wiederverwendung von Schattierungsberechnungen: Vorhandener Shadercode wird direkt wiederverwendet, um dieselbe Materiallogik wie in der Haupt-Rendering-Pipeline beizubehalten.
Abbildung 7 Geklärte Reflexion.

Schließlich machen die Modelle, die tatsächlich an der Reflexionsberechnung teilnehmen, nur einen sehr kleinen Teil der Szene aus. Die von der GPU zurückgegebenen Identifikationsdaten des Reflexionsmodells können asynchron gelesen werden, um die Modelle/Materialien zu entfernen, die nicht an der Reflexion teilnehmen. Dadurch wird die Anzahl der Draw-Aufrufe in der Schattierungsphase effektiv reduziert (ein Draw-Aufruf erfolgt, wenn Materialien und ein Mesh zur Darstellung an die GPU gesendet werden).

Physikbasierte Spiegelreflexion

Um realistische Reflexionen zu erzielen, werden reflektierende Oberflächen je nach Rauheit in eine von drei Kategorien eingeteilt:

  1. Keine Reflexion: Reflexionsberechnungen für diese Oberflächen können übersprungen werden, um Ressourcen zu sparen. Ist die Oberfläche sehr rau, wird die Reflexion unscharf und schwach, sodass der Beitrag nicht offensichtlich ist.
  2. Spiegelung: Wie bei einem glatten Spiegel ist das reflektierte Bild klar und nicht verschwommen. Richten Sie die Linie direkt in Richtung der Reflexion aus der Sichtlinie.
  3. Glänzende Reflexion: Die Reflexion mit einer bestimmten Oberflächenrauheit wird anhand von GGX-Wichtigkeitsstichproben simuliert, wobei sowohl die Recheneffizienz als auch die physikalische Genauigkeit berücksichtigt werden können. Die Reflexion weicht beim Ausstrahlen der Linie in die Hauptrichtung der sphärischen Reflexion ab, was die Abtastleistung des Highlights verbessert.

Um eine brauchbare Bildqualität bei begrenztem Stromverbrauch zu erreichen, hat das Diablo Immortal-Team eine Lösung mit 1 SPP + Denoiser verwendet. Das Diablo Immortal-Team hat also ein Sample pro Pixel aufgenommen und dann einen Algorithmus zur zeitlichen/räumlichen Rauschunterdrückung verwendet, um das große Rauschen zu glätten,das durch die niedrige Abtastrate verursacht wird.

Das Diablo Immortal-Team entschied sich für den Reflexions-Entferner in AMD FidelityFX Denoiser, einen Hochleistungs-Entferner, der für Raytracing-Reflexionen und Screen-Space-Reflexionen optimiert ist. Der Hauptvorteil des Reflexions-Rauschunterdrückers ist sein raumzeitlicher Hybrid-Rauschunterdrückungsalgorithmus: Durch die Verschmelzung des aktuellen Frames und der bisherigen Frame-Daten (basierend auf der Bewegungskompensation) in Kombination mit räumlichen Filtertechniken (z. B. varianzbasierter Randretentionsfilter) eliminiert der Reflexions-Rauschunterdrücker effektiv Rauschen und liefert bei sehr niedriger Abtastrate glatte Reflexionseffekte.

Um sich an die Eigenschaften selbst entwickelter Renderpipelines anzupassen und die strengen Leistungseinschränkungen von Mobilgeräten zu erfüllen, hat das Diablo Immortal-Team bei der Integration des AMD FidelityFX Reflection Denoisers gezielte Optimierungen und Architekturanpassungen vorgenommen.

High-Fidelity-Raytracing mit Vulkan

Diablo Immortal läuft auf einer Vielzahl von Vulkan-kompatiblen Android-Geräten, bei denen das Diablo Immortal-Team innovative Raytracing-Funktionen der GPU-Hardware nutzte. Vulkan hat den Entwicklungsaufwand und die Entwicklungszeit reduziert und so die Bereitstellung hochwertiger Diablo Immortal-Inhalte und -Gameplay-Elemente für Android-Nutzer ermöglicht.