Wie der Rahmen von Rise of the Tomb Raider gerendert wird


Rise of the Tomb Raider (2015) ist die Fortsetzung des hervorragenden Neustarts von Tomb Raider (2013). Persönlich finde ich beide Teile interessant, weil sie sich von der stagnierenden Originalserie entfernt und die Geschichte von Lara erneut erzählt haben. In diesem Spiel steht wie im Prequel die Handlung im Mittelpunkt und bietet faszinierende Mechaniken für Handwerk, Jagd und Klettern / Forschung.

Tomb Raider verwendete die von Crystal Dynamics entwickelte Crystal Engine, die auch in Deus Ex: Human Revolution verwendet wurde . Die Fortsetzung verwendete eine neue Engine namens Foundation, die zuvor für Lara Croft und den Temple of Osiris (2014) entwickelt wurde. Sein Rendering kann allgemein als Fliesenmotor mit vorläufigem Beleuchtungsdurchlauf beschrieben werden, und später werden wir herausfinden, was dies bedeutet. Mit der Engine können Sie zwischen den Renderern DX11 und DX12 wählen. Ich habe mich aus den unten diskutierten Gründen für Letzteres entschieden. Um den Rahmen zu erfassen, wurde Renderdoc 1.2 auf dem Geforce 980 Ti verwendet. Das Spiel enthält alle Funktionen und Dekorationen.

Analysierter Rahmen



Um Spoiler zu vermeiden, werde ich sagen, dass die Bösen in diesem Rahmen Lara jagen, weil sie nach einem Artefakt sucht, nach dem sie suchen. Dieser Interessenkonflikt kann nicht ohne Waffen gelöst werden. Lara schlich sich nachts in die feindliche Basis. Ich habe einen Rahmen mit atmosphärischer und kontrastreicher Beleuchtung gewählt, in dem sich der Motor zeigen kann.

Tiefenvorschuss


Hier wird die für viele Spiele übliche Optimierung durchgeführt - ein kleiner vorläufiger Durchgang der Tiefe (ca. 100 Draw Calls). Das Spiel rendert die größten Objekte (und nicht diejenigen, die mehr Platz auf dem Bildschirm beanspruchen), um die Funktionen des Early-Z-Videoprozessors zu nutzen. Lesen Sie mehr darüber in einem Intel-Artikel . Kurz gesagt, GPUs können die Ausführung eines Pixel-Shaders vermeiden, wenn sie feststellen können, dass er vom vorherigen Pixel überlappt wird. Dies ist eine relativ kostengünstige Passage, bei der der Z-Puffer mit Tiefenwerten vorgefüllt wird.

Zu diesem Zeitpunkt entdeckte ich eine interessante Detailgenauigkeitstechnik (LOD) namens „Fizzle“ oder „Checkerboard“. Dies ist eine übliche Methode, um Objekte in einiger Entfernung schrittweise anzuzeigen oder auszublenden, damit sie später entweder durch ein Netz mit geringerer Qualität ersetzt oder vollständig ausgeblendet werden können. Schau dir diesen Truck an. Es scheint, als würde es zweimal gerendert, aber tatsächlich wird es mit einer hohen LOD und einer niedrigen LOD an derselben Position gerendert. Jede der Ebenen rendert die Pixel, die die andere nicht gerendert hat. Die erste LOD hat 182.226 Eckpunkte und die zweite LOD hat 47.250. In großer Entfernung sind sie nicht zu unterscheiden, aber eine davon ist dreimal billiger. In diesem Frame verschwindet LOD 0 fast vollständig und LOD 1 wird fast vollständig gerendert. Nach dem vollständigen Verschwinden von LOD 0 wird nur LOD 1 gerendert.


LOD 0


LOD 1


Die pseudozufällige Textur und der Wahrscheinlichkeitskoeffizient ermöglichen es uns, Pixel zu verwerfen, die den Schwellenwert nicht überschritten haben. Diese Textur wird in ROTR verwendet. Man könnte sich fragen, warum Alpha-Blending nicht verwendet wird. Alpha-Blending hat viele Nachteile im Vergleich zum Fizzle-Fading.

  1. Bequemlichkeit für den vorläufigen Durchgang der Tiefen: Dank der Darstellung eines undurchsichtigen Objekts mit darin eingebrachten Löchern können wir den vorläufigen Durchgang rendern und Early-Z verwenden. Objekte mit Alpha-Überblendung in einem so frühen Stadium werden aufgrund von Sortierproblemen nicht in den Tiefenpuffer gerendert.
  2. Zusätzliche Shader erforderlich : Wenn ein verzögerter Renderer verwendet wird, enthält der Shader von undurchsichtigen Objekten keine Beleuchtung. Wenn Sie ein undurchsichtiges Objekt durch ein transparentes ersetzen müssen, benötigen Sie eine separate Option für die Beleuchtung. Zusätzlich zur Erhöhung des Speicherbedarfs und der Komplexität aufgrund mindestens eines zusätzlichen Shaders für alle undurchsichtigen Objekte müssen diese genau sein, um zu vermeiden, dass sich Objekte vorwärts bewegen. Dies ist aus vielen Gründen kompliziert, aber alles hängt davon ab, dass das Rendern jetzt in einem anderen Codepfad erfolgt.
  3. Größere Neuzeichnungen : Durch Alpha-Blending können große Neuzeichnungen erstellt werden. Bei einer bestimmten Komplexität von Objekten kann ein großer Teil der Bandbreite erforderlich sein, um die LOD zu schattieren.
  4. Z-Konflikte : Z-Konflikte sind ein Flickereffekt, wenn zwei Polygone in sehr geringer Tiefe zueinander gerendert werden. In diesem Fall werden sie aufgrund der Ungenauigkeit der Gleitkommaberechnungen nacheinander gerendert. Wenn wir zwei aufeinanderfolgende LODs rendern, eine nach und nach ausblenden und die zweite anzeigen, können sie einen Z-Konflikt verursachen, da sie sehr nahe beieinander liegen. Es gibt immer Möglichkeiten, dies zu umgehen, beispielsweise ein Polygon einem anderen vorzuziehen, aber ein solches System ist komplex.
  5. Z-Buffer-Effekte : Viele Effekte wie SSAO verwenden nur den Tiefenpuffer. Wenn wir transparente Objekte am Ende der Pipeline gerendert haben, als die Umgebungsokklusion bereits abgeschlossen war, konnten wir dies nicht berücksichtigen.

Der Nachteil dieser Technik ist, dass sie schlechter aussieht als Alpha-Blending, aber ein gutes Rauschmuster, Unschärfe nach Sprudeln oder vorübergehendes Anti-Aliasing kann sie fast vollständig verbergen. In dieser Hinsicht macht ROTR nichts besonders Ungewöhnliches.

Normaler Pass


Crystal Dynamics verwendet in seinen Spielen ein eher ungewöhnliches Beleuchtungsmuster, das wir im Beleuchtungsgang behandeln werden. Im Moment genügt es zu sagen, dass die Engine keinen G-Puffer-Durchgang hat. Zumindest in dem Maße, wie es in anderen Spielen bekannt ist. In dieser Passage übertragen die Objekte nur Informationen über die Tiefe und Normalen an die Ausgabe. Normalen werden im Renderziel des Formats RGBA16_SNORM im Weltraum aufgezeichnet. Es ist merkwürdig, dass diese Engine das Z-up-Schema verwendet, nicht das Y-up (die Z-Achse ist nach oben gerichtet, nicht die Y-Achse), das in anderen Modellierungs-Engines / -Paketen häufiger verwendet wird. Der Alpha-Kanal enthält Glanz, der dann als exp2(glossiness * 12 + 1.0) entpackt exp2(glossiness * 12 + 1.0) . Der Glanzwert kann auch negativ sein, da das Vorzeichen als Flag verwendet wird, das angibt, ob die Oberfläche metallisch ist. Dies kann von selbst bemerkt werden, da alle dunklen Farben im Alphakanal mit Metallobjekten zusammenhängen.

R.G.B.
Normal.xNormal.yNormal.zGlanz + Metallizität


Normal


Glanz / Metallizität

Vorteile der Abreise


Denken Sie daran, dass wir im Abschnitt „Tiefenvorbereitung“ über das Einsparen von Pixelkosten gesprochen haben. Ich werde ein wenig zurückgehen, um es zu veranschaulichen. Nehmen Sie das folgende Bild auf. Dadurch wird der detaillierte Teil des Berges zum normalen Puffer. Renderdoc hat freundlicherweise die Pixel, die den Tiefentest bestanden haben, mit Grün und diejenigen, die ihn nicht bestanden haben, mit Rot hervorgehoben (sie werden nicht gerendert). Die Gesamtzahl der Pixel, die ohne diesen vorläufigen Durchgang gerendert würden, entspricht ungefähr 104518 (berechnet in Photoshop). Die Gesamtzahl der tatsächlich gerenderten Pixel beträgt 23858 (berechnet von Renderdoc). Sparen Sie ca. 77%! Wie wir sehen, kann dieser vorläufige Durchgang bei intelligenter Verwendung einen großen Gewinn bringen und erfordert nur etwa hundert Draw Calls.

Aufzeichnen von Multithread-Befehlen


Es ist erwähnenswert, dass ich mich für den DX12-Renderer entschieden habe - das Aufzeichnen von Multithread-Befehlen. In früheren APIs wie DX11 wird das Rendern normalerweise in einem einzelnen Thread ausgeführt. Der Grafiktreiber erhielt Rendering-Befehle vom Spiel und übertrug ständig GPU-Anfragen, aber das Spiel wusste nicht, wann dies passieren würde. Dies führt zu Ineffizienz, da der Treiber irgendwie erraten muss, was die Anwendung versucht, und nicht auf mehrere Threads skaliert. Neuere APIs wie DX12 übergeben die Kontrolle an einen Entwickler, der entscheiden kann, wie und wann Befehle geschrieben werden sollen. Obwohl Renderdoc nicht zeigen kann, wie die Aufnahme durchgeführt wird, werden Sie feststellen, dass sieben Farbdurchgänge als Farbdurchlauf N gekennzeichnet sind und jeder von ihnen in ein Paar ExecuteCommandList: Reset / Close eingeschlossen ist. Es markiert den Anfang und das Ende der Befehlsliste. Die Liste umfasst ungefähr 100-200 Draw Calls. Dies bedeutet nicht, dass sie mit mehreren Streams aufgezeichnet wurden, sondern weist darauf hin.

Fußspuren im Schnee


Wenn Sie sich Lara ansehen, können Sie sehen, dass sie beim Bewegen vor dem Screenshot Spuren im Schnee hinterlassen hat. In jedem Frame wird ein Compute-Shader ausgeführt, der Verformungen in bestimmten Bereichen aufzeichnet und diese basierend auf Art und Höhe der Oberfläche anwendet. Hier wird nur die normale Karte auf den Schnee angewendet (d. H. Die Geometrie ändert sich nicht), aber in einigen Bereichen, in denen der Schnee dicker ist, wird die Verformung tatsächlich durchgeführt! Sie können auch sehen, wie der Schnee an seinen Platz "fällt" und die von Lara hinterlassenen Spuren füllt. Diese Technik wird in der GPU Pro 7 ausführlicher beschrieben. Die Schneekettetextur ist eine Art Höhenkarte, die Laras Bewegungen verfolgt und an den Rändern festgeklebt wird, damit der Sampling-Shader diese Faltung nutzen kann.

Atlas der Schatten


Beim Erstellen der Schattenzuordnung wird ein ziemlich gängiger Ansatz verwendet: Packen Sie so viele Schattenkarten wie möglich in eine gemeinsame Schattenstruktur. Ein solcher Schattenatlas ist eigentlich eine riesige 16-Bit-Textur mit einer Größe von 16384 × 8196. Auf diese Weise können Sie die Schattenkarten im Atlas sehr flexibel wiederverwenden und skalieren. In dem Rahmen, den wir analysieren, werden 8 Schattenkarten im Atlas aufgezeichnet. Vier von ihnen beziehen sich auf die Hauptquelle der gerichteten Beleuchtung (der Mond, weil es nachts passiert), weil sie kaskadierende Schattenkarten verwenden - eine ziemlich Standardtechnik von Fernschatten für die gerichtete Beleuchtung, die ich bereits etwas früher erklärt habe . Interessanterweise sind bei der Erfassung dieses Rahmens auch mehrere Projektions- und Scheinwerferquellen enthalten. Die Tatsache, dass 8 Schattenkarten in diesem Rahmen aufgezeichnet werden, bedeutet nicht, dass nur 8 Quellen für das Werfen von Schattenlicht darin enthalten sind. Das Spiel kann Schattenberechnungen zwischenspeichern, dh Beleuchtung, die weder die Position der Quelle noch die Geometrie im Bereich geändert hat, sollte ihre Schattenkarte nicht aktualisieren.


Es scheint, dass das Rendern von Schattenkarten auch vom Schreiben von Multithread-Befehlen in die Liste profitiert. In diesem Fall wurden bis zu 19 Befehlslisten zum Rendern von Schattenkarten geschrieben.

Schatten von gerichteter Beleuchtung

Schatten von gerichteter Beleuchtung werden vor dem Durchgang der Beleuchtung berechnet und später abgetastet. Ich weiß nicht, was passieren würde, wenn die Szene mehrere gerichtete Lichtquellen hätte.


Umgebungsokklusion


Für Umgebungsokklusion können Sie mit ROTR entweder HBAO oder eine Variante von HBAO + verwenden (diese Technik wurde ursprünglich von NVIDIA veröffentlicht). Es gibt verschiedene Variationen dieses Algorithmus, daher werde ich die in ROTR gefundene betrachten. Zunächst wird der Tiefenpuffer in 16 Texturen unterteilt, von denen jede 1/16 aller Tiefenwerte enthält. Die Trennung wird so durchgeführt, dass jede Textur einen Wert aus einem 4 × 4-Block der in der folgenden Abbildung gezeigten ursprünglichen Textur enthält. Die erste Textur enthält alle rot markierten Werte (1), die zweite enthält die blau markierten Werte (2) usw. Wenn Sie mehr über diese Technik erfahren möchten, finden Sie hier einen Artikel von Louis Bavoil , der auch einer der Autoren des Artikels über HBAO war.


Der nächste Schritt berechnet die Umgebungsokklusion für jede Textur, wodurch wir 16 AO-Texturen erhalten. Eine Umgebungsokklusion wird wie folgt erzeugt: Der Tiefenpuffer wird mehrmals abgetastet, wobei die Position neu erstellt und das Berechnungsergebnis für jede der Proben akkumuliert wird. Jede Umgebungsokklusionstextur wird unter Verwendung unterschiedlicher Abtastkoordinaten berechnet, dh in einem 4 × 4-Pixelblock erzählt jedes Pixel seinen eigenen Teil der Geschichte. Dies erfolgt aus Leistungsgründen. Jedes Pixel tastet den Tiefenpuffer bereits 32 Mal ab, und für den vollen Effekt sind 16 × 32 = 512 Abtastwerte erforderlich, was selbst für die leistungsstärksten GPUs eine Pleite ist. Dann rekombinieren sie zu einer Vollbild-Textur, die sich als ziemlich verrauscht herausstellt. Um die Ergebnisse unmittelbar danach zu glätten, wird ein Vollbild-Unschärfe-Durchgang durchgeführt. Wir haben in Shadow of Mordor eine sehr ähnliche Lösung gesehen.

Bild

HBAO Teile

Bild

Voller HBAO mit Lärm

Bild

Volle horizontale HBAO-Unschärfe

Bild

Bereit HBAO

Pre-Pass für gekachelte Beleuchtung


Light Prepass ist eine eher ungewöhnliche Technik. Die meisten Entwicklungsteams verwenden eine Kombination aus verzögerter + direkter Beleuchtungsberechnung (mit Variationen, z. B. mit Kachel, Cluster) oder vollständig direkt für einige Effekte des Bildschirmbereichs. Die Vorbeleuchtungstechnik ist so ungewöhnlich, dass sie eine Erklärung verdient. Wenn das Konzept der traditionellen verzögerten Beleuchtung darin besteht, die Eigenschaften von Materialien von der Beleuchtung zu trennen, ist die Idee, die Beleuchtung von den Eigenschaften der Materialien zu trennen, der Eckpfeiler des vorläufigen Durchgangs der Beleuchtung. Obwohl diese Formulierung etwas albern aussieht, besteht der Unterschied zur herkömmlichen verzögerten Beleuchtung darin, dass wir alle Materialeigenschaften (wie Albedo, Spiegelfarbe, Rauheit, Metallizität, Mikrookklusion, Emissionsgrad) in einem riesigen G-Puffer speichern und später als verwenden Eingabedaten für nachfolgende Beleuchtungsdurchläufe. Herkömmliche verzögerte Beleuchtung kann den Durchsatz stark belasten. Je komplexer die Materialien sind, desto mehr Informationen und Operationen werden im G-Puffer benötigt. Im vorläufigen Beleuchtungsdurchlauf akkumulieren wir jedoch zunächst die gesamte Beleuchtung separat unter Verwendung der Mindestdatenmenge und wenden sie dann in nachfolgenden Durchgängen auf die Materialien an. In diesem Fall reicht die Beleuchtung nur für Normalen, Rauheit und Metallität aus. Shader (hier werden zwei Durchgänge verwendet) geben Daten in drei RGBA16F-Renderzielformaten aus. Eine enthält diffuse Beleuchtung, die zweite enthält spiegelnde Beleuchtung und die dritte enthält Umgebungsbeleuchtung. Zu diesem Zeitpunkt werden alle Schattendaten berücksichtigt. Es ist merkwürdig, dass im ersten Durchgang (diffuse + Spiegelbeleuchtung) für einen Vollbilddurchgang ein Viereck aus zwei Dreiecken verwendet wird und in anderen Effekten ein Vollbilddreieck verwendet wird (warum dies wichtig ist, erfahren Sie hier ). Unter diesem Gesichtspunkt ist der gesamte Rahmen nicht ganzheitlich.

Bild

Diffuse Beleuchtung

Bild

Spiegelbeleuchtung

Bild

Umgebungsbeleuchtung

Fliesenoptimierung

Fliesenbeleuchtung ist eine Optimierungstechnik, mit der eine große Anzahl von Lichtquellen gerendert werden kann. ROTR teilt den Bildschirm in 16 × 16 Kacheln auf und speichert dann Informationen darüber, welche Quellen jede Kachel schneiden. Das heißt, Beleuchtungsberechnungen werden nur für die Quellen durchgeführt, die sich auf die Kacheln beziehen. Zu Beginn des Frames wird eine Folge von Computer-Shadern gestartet, die bestimmen, welche Quellen sich auf die Kacheln beziehen. In der Beleuchtungsphase bestimmt jedes Pixel, in welcher Kachel es sich befindet, und durchläuft jede Lichtquelle in der Kachel, wobei alle Beleuchtungsberechnungen durchgeführt werden. Wenn die Quellen effizient mit Kacheln verknüpft sind, können Sie viel Rechenaufwand und den größten Teil der Bandbreite einsparen und die Produktivität steigern.

Tiefenzoom

Tiefenbasiertes Upsampling ist eine interessante Technik, die in diesem und den folgenden Durchgängen nützlich ist. Manchmal können rechenintensive Algorithmen nicht mit voller Auflösung gerendert werden, daher werden sie mit einer niedrigeren Auflösung gerendert und dann vergrößert. In unserem Fall wird die Umgebungsbeleuchtung in halber Auflösung berechnet, dh nach den Berechnungen muss die Beleuchtung korrekt neu erstellt werden. In der einfachsten Form werden 4 Pixel mit niedriger Auflösung aufgenommen und interpoliert, um etwas zu erhalten, das dem Originalbild ähnelt. Dies funktioniert für reibungslose Übergänge, sieht aber bei Diskontinuitäten nicht gut aus, da wir dort nicht verwandte Werte mischen, die im Bildschirmbereich benachbart sein können, im Weltraum jedoch voneinander entfernt sind. Bei Lösungen für dieses Problem werden normalerweise mehrere Tiefenpufferproben genommen und mit der Tiefenprobe verglichen, die wir neu erstellen möchten. Wenn die Probe zu weit entfernt ist, berücksichtigen wir sie bei der Rekonstruktion nicht. Ein solches Schema funktioniert gut, bedeutet jedoch, dass der Erholungs-Shader sehr bandbreitenintensiv ist.

ROTR macht einen schwierigen Schritt mit dem frühen Verwerfen von Schablonen. Nach dem Übergeben der Normalen ist der Tiefenpuffer vollständig gefüllt, sodass die Engine einen Vollbilddurchlauf durchführt und alle unterbrochenen Pixel im Schablonenpuffer markiert. Wenn es an der Zeit ist, den Umgebungslichtpuffer neu zu erstellen, verwendet die Engine zwei Shader: Einer ist sehr einfach für Bereiche ohne Tiefenlücken, der andere ist komplexer für Pixel mit Lücken. Frühe Schablonen verwerfen Pixel, wenn sie nicht zu der entsprechenden Region gehören, d. H. Es gibt Kosten nur in den erforderlichen Regionen. Die folgenden Bilder sind viel klarer:

Bild

Umgebungsbeleuchtung mit halber Auflösung

Bild

Skalierung der Tiefen des Innenraums

Bild

Umgebungsbeleuchtung in voller Auflösung, keine Rippen

Bild

Skalieren der Rippentiefen

Bild

Bereit Umgebungsbeleuchtung

Bild

Ansicht mit halber Auflösung

Bild

Eine Nahaufnahme des neu erstellten Bildes

Nach dem vorläufigen Durchgang der Beleuchtung wird die Geometrie auf das Förderband übertragen. Nur dieses Mal tastet jedes Objekt Beleuchtungstexturen, Umgebungsokklusionstexturen und andere Eigenschaften von Materialien ab, die wir nicht von Anfang an in den G-Puffer geschrieben haben. Dies ist gut, da die Bandbreite hier erheblich gespart wird, da Sie nicht eine Reihe von Texturen lesen müssen, um sie in einen großen G-Puffer zu schreiben, und sie dann erneut lesen / dekodieren müssen. Der offensichtliche Nachteil dieses Ansatzes besteht darin, dass die gesamte Geometrie erneut übertragen werden muss und die Textur des vorläufigen Durchgangs der Beleuchtung an sich eine große Belastung für den Durchsatz darstellt. Ich habe mich gefragt, warum ich nicht ein helleres Format verwenden soll, zum Beispiel R11G11B10F, um vorläufige Passbeleuchtungstexturen zu verwenden, aber der Alphakanal enthält zusätzliche Informationen, sodass dies unmöglich wäre. Wie dem auch sei, dies ist eine interessante technische Lösung. Zu diesem Zeitpunkt ist die gesamte undurchsichtige Geometrie bereits gerendert und beleuchtet. Beachten Sie, dass es lichtemittierende Objekte wie den Himmel und den Laptop-Bildschirm enthält.


Reflexionen


Diese Szene ist kein gutes Beispiel für die Demonstration von Reflexionen, deshalb habe ich eine andere gewählt. Der Reflection Shader ist eine ziemlich komplizierte Kombination von Zyklen, die auf zwei Teile reduziert werden kann: einer tastet kubische Karten ab und der andere führt SSR (Screen Space Reflection - Berechnung von Reflexionen im Screen Space) durch; All dies erfolgt in einem Durchgang und wird am Ende unter Berücksichtigung des Koeffizienten gemischt, der bestimmt, ob die SSR Reflexion erfasst (wahrscheinlich ist der Koeffizient nicht binär, sondern ein Wert im Intervall [0, 1]). SSR funktioniert bei vielen Spielen auf übliche Weise - es zeichnet wiederholt den Tiefenpuffer nach und versucht, den besten Schnittpunkt zwischen dem von der schattierten Oberfläche reflektierten Strahl und einer anderen Oberfläche irgendwo auf dem Bildschirm zu finden. SSR arbeitet mit der Mip-Kette der zuvor reduzierten Skala des aktuellen HDR-Puffers und nicht mit dem gesamten Puffer.

Es gibt auch Korrekturfaktoren wie die Helligkeit der Reflexion sowie die eigentümliche Fresnel-Textur, die vor dieser Passage basierend auf den Normalen und der Rauheit berechnet wurde. Ich bin mir nicht ganz sicher, aber nach dem Studium des Assembler-Codes scheint es mir, dass ROTR SSR nur für glatte Oberflächen berechnen kann. Der Motor hat nach der SSR-Phase keine Unschärfekette, die in anderen Motoren vorhanden ist, und es gibt nicht einmal eine Möglichkeit, den Tiefenpuffer mithilfe von Strahlen zu verfolgen, die je nach Rauheit variieren . Im Allgemeinen erhalten rauere Oberflächen Reflexionen von kubischen Karten oder überhaupt nicht. Wenn SSR funktioniert, ist seine Qualität jedoch sehr hoch und stabil, unter Berücksichtigung der Tatsache, dass es sich im Laufe der Zeit nicht ansammelt und keine räumliche Unschärfe für SSR durchgeführt wird. Alpha-Daten unterstützen auch SSR (in einigen Tempeln können Sie sehr schöne Reflexionen im Wasser sehen) und dies ist eine gute Ergänzung, die Sie nicht oft sehen.

Bild

Reflexionen zu

Bild

Reflexionspuffer

Bild

Reflexionen nach

Beleuchteter Nebel



In unserer Szene ist Nebel schlecht dargestellt, weil er den Hintergrund verdunkelt und daher von Partikeln erzeugt wird, so dass wir das Beispiel wieder mit Reflexionen verwenden. Der Nebel ist relativ einfach, aber sehr effektiv. Es gibt zwei Modi: global, die allgemeine Farbe des Nebels und die Farbe der nach innen gerichteten Streuung, die aus der kubischen Karte erhalten wird. Vielleicht wurde die kubische Karte wieder aus den kubischen Reflexionskarten entnommen oder neu erstellt. In beiden Modi wird die Verdünnung des Nebels aus der globalen Verdünnungstextur entnommen, in der die Verdünnungskurven für verschiedene Effekte gepackt sind. In einem solchen Schema ist es bemerkenswert, dass es einen sehr kostengünstigen beleuchteten Nebel ergibt, d.h. Streuung nach innen gerichteter Veränderungen im Raum, wodurch die Illusion entsteht, dass Nebel mit entferntem Licht in Wechselwirkung tritt. Dieser Ansatz kann auch für die nach innen gerichtete atmosphärische Streuung in der Nähe des Himmels verwendet werden.

Bild

Nebel zu

Bild

Nebel danach

Volumenbeleuchtung


In den frühen Phasen des Rahmens werden mehrere Vorgänge ausgeführt, um die volumetrische Beleuchtung vorzubereiten. Zwei Puffer werden von der CPU auf die GPU kopiert: Lichtquellenindizes und Lichtquellendaten. Beide werden von einem Computer-Shader gelesen, der eine 40 x 23 x 16 3D-Textur der Kameraansicht ausgibt, die die Anzahl der Lichtquellen enthält, die diesen Bereich durchqueren. Die Textur ist 40 × 23, da jede Kachel 32 × 32 Pixel (1280/32 = 40, 720/32 = 22,5) einnimmt und 16 die Anzahl der Pixel in der Tiefe ist. Die Textur enthält nicht alle Lichtquellen, sondern nur diejenigen, die als voluminös markiert sind (es gibt drei in unserer Szene). Wie wir weiter unten sehen werden, gibt es andere gefälschte volumetrische Effekte, die durch flache Texturen erzeugt werden. Die angezeigte Textur hat eine höhere Auflösung - 160x90x64. Nach dem Bestimmen der Anzahl der Lichtquellen pro Kachel und ihres Index werden drei Rechen-Shader nacheinander ausgeführt, wobei die folgenden Operationen ausgeführt werden:

  1. Der erste Durchgang bestimmt die Lichtmenge, die in Form einer Pyramide der Sichtbarkeit in die Zelle innerhalb des Volumens eintritt. Jede Zelle sammelt den Einfluss aller Lichtquellen, als hätten sie Schwebeteilchen, die auf Licht reagieren und einen Teil davon an die Kamera zurückgeben.
  2. Der zweite Durchgang verwischt die Beleuchtung mit einem kleinen Radius. Dies ist wahrscheinlich erforderlich, um ein Flackern beim Bewegen der Kamera zu vermeiden, da die Auflösung sehr niedrig ist.
  3. Der dritte Durchgang umgeht die Volumentextur von vorne nach hinten, fügt schrittweise den Einfluss jeder Quelle hinzu und gibt die fertige Textur. Tatsächlich simuliert es die Gesamtmenge der einfallenden Beleuchtung entlang des Strahls bis zu einer bestimmten Entfernung. , , . .

, 3D-, , . , — , HDR-. 16 .

Bild



Bild




PureHair , . - , . , . Tomb Raider TressFX, Crystal Dynamics . 7 . . :

  1. ( motion blur)
  2. 1×1 ()
  3. 122 (Triangle Strip) ( — ). , . 7 , . , , . « ».
  4. / quad , , . , , .
  5. 4, ( « »)

, AMD , . 1, , 3, , , , ; , Renderdoc - . , , , , .

Bild



Bild



Bild



-


, . , ( ). , ! HDR-, , , .. - , - (, ).


, , , , , , .. HDR- , . , 40 . , . , , ( , , ). , -, , .. , , , . , «» , . , . , .

Bild



Bild

-

Bild

1

Bild

2

Bild

3

Bild


Bild



Bild

-


ROTR . , -, . , . (luminance) ROTR , . 64×64, (20, 12, 1) 256 . ( ):

 for(int i = 0; i < 16; ++i) { uint2 iCoord = CalculateCoord(threadID, i, j); // Obtain coordinate float3 hdrValue = Load(hdrTexture, iCoord.xyz); // Read HDR float maxHDRValue = max3(hdrValue); // Find max component float minHDRValue = min3(hdrValue); // Find min component float clampedAverage = max(0.0, (maxHDRValue + minHDRValue) / 2.0); float logAverage = log(clampedAverage); // Natural logarithm sumLogAverage += logAverage; } 

64 (256 , 16 ). , , ( 64×64 , , , ). ; 16 , , ( 0) . 240 , . 64 , , . .

, . 64 , , , . , .

. , ROTR (Photographic Tonemapping), was die Verwendung logarithmischer Mittel anstelle der üblichen Mittel erklärt. Die Tonwertkorrekturformel im Shader (nach der Belichtung) kann wie folgt erweitert werden:



Eine kurze Erklärung finden Sie hier . Ich konnte nicht herausfinden, warum eine zusätzliche Division durch Lm notwendig ist, weil sie den Einfluss der Multiplikation aufhebt. In jedem Fall ist whitePoint 1.0, sodass der Vorgang in diesem Frame nicht viel bewirkt. Das Bild ändert nur die Verschlusszeit. Die Werte des LDR-Intervalls sind nicht einmal begrenzt! Es tritt während der Farbkorrektur auf, wenn der Farbwürfel indirekt Werte über 1,0 begrenzt.

Bild

Exposition gegenüber

Bild

Belichtung nach

Linseneffekt


(Lens Flares) . 1xN ( N — , , 28). - , - , , . , .


Dann wird jedes Element als einfache ebene ausgerichtete Ebenen gerendert, die von Lichtquellen emittiert werden. Wenn der Alpha-Wert kleiner als 0,01 ist, wird der Position der Wert NaN zugewiesen, damit dieses Partikel nicht rastert. Sie sind ein bisschen wie der Bloom-Effekt und fügen Glühen hinzu, aber dieser Effekt selbst wird später erzeugt.

Bild

Linse flackert auf

Bild

Linseneffektelemente

Bild

Linseneffekte nach

Blüte


Bloom : HDR-, , , . . , . 7 : 2 , 1 , 4 .

  1. target (mip 1). . , mip- , 0.02.
  2. mip mip 2, 3, 4 5.
  3. mip 5. , . , .
  4. — . 3 , mip N mip N + 1, , . bloom , .
  5. mip 1 HDR-, bloom.

Bild

Bloom


MIP 1 Bloom


MIP 2 Bloom


MIP 3 Bloom


MIP 4 Bloom

Bild

MIP 5 Bloom


MIP 5 Bloom


MIP 4 Bloom


MIP 3 Bloom

Bild

MIP 2 Bloom


MIP 1 Bloom


Bloom

, . , ; , , 16. : , float32 float16! . , .

FXAA


ROTR (), FXAA (Fast Approximate AA) SSAA (Super Sampling AA). temporal AA, AAA- . , FXAA , SSAA , «» , .

Motion Blur


, Motion blur ( ) , Shadows of Mordor . . , , , , . , , . , , . : -, , , -, . , .

Bild

Motion Blur


Motion Blur


Motion Blur, 1


Motion Blur, 2


Motion Blur, 3


Motion Blur, 4


Motion Blur, 5


Motion Blur, 6


Motion Blur,


Motion Blur,


, .

  1. :
  2. :
  3. : , , , ,

UI


UI — . UI -. ROTR . , 3D UI; HDR- sRGB- , (-) .


, , . . Crystal Dynamics , . Renderdoc. PC . , , — , DX12. , .

Source: https://habr.com/ru/post/de436500/


All Articles