Effizientes Rendern mit vielen Lichtquellen


10

Um eine Szene mit einer einzelnen Lichtquelle unter Verwendung von Phong-Schattierung zu rendern, kann die endgültige Farbe jedes in den Fragment-Shader übergebenen Fragments basierend auf den Umgebungs- / diffusen / spiegelnden Komponenten sowohl des Materials als auch der Lichtquelle berechnet werden.

Dies kann leicht erweitert werden, um mehrere Lichtquellen aufzunehmen, indem die Ergebnisse der Anwendung jeder einzelnen Lichtquelle auf das Fragment als solches addiert werden:

final_color = (0, 0, 0, 1)
for each light:
    final_color += apply_light(material, light)
final_color = clamp(final_color, (0,0,0,1), (1,1,1,1))

Bei einer sehr großen Anzahl von Lichtquellen ist dieser Prozess jedoch ziemlich langsam. Bei NLichtern erfordert dieser Ansatz Berechnungen für die Phong-Schattierung, die Npro Fragment durchgeführt werden müssen.

Gibt es einen besseren Ansatz zum Rendern von Szenen mit einer sehr großen Anzahl von Lichtquellen (Hunderte, Tausende usw.)?

Antworten:


15

Ja, aber Sie brauchen einen Paradigmenwechsel.

Was Sie gewohnt sind, nennt man Forward Rendering. Sie senden Ihre Geometrie und fahren dann sofort mit dem Schattierungsdurchlauf fort. Beim grundlegenden Vorwärts-Rendering können Sie entweder für jedes Licht eine Schleife innerhalb des Shaders erstellen oder einen Durchgang pro Licht ausführen und das Ergebnis zusammenmischen (mit additiver Überblendung).

Aber die Dinge haben sich ziemlich weiterentwickelt. Eingabe: Zurückgestelltes Rendern

Nun, da es so viele Varianten gibt, die sie alle im Detail beschreiben, wird eine Antwort hier mehr als akzeptabel sein. Hier beschreibe ich nur den Kern der verzögerten Schattierung. Es gibt viele andere Ressourcen, die Sie mit Google leicht finden können. Hoffentlich haben Sie nach dem Lesen die richtigen Schlüsselwörter, um das zu finden, was Sie brauchen.

Die Grundidee besteht darin, die Schattierung nach der Pipeline zu verschieben. Sie haben zwei Hauptschritte:

  1. Rendern Sie Ihre Geometrie und alle Informationen, die zum Schattieren erforderlich sind, in mehrere Renderziele. Dies bedeutet, dass Sie in einer Basisimplementierung normalerweise einen Tiefenpuffer haben, einen Puffer, der die Normalen Ihrer Geometrie und die Albedofarbe enthält. Sie werden bald feststellen, dass Sie andere Informationen zu den Materialien benötigen (z. B. Rauheit, "metallischer" Faktor usw.).

Dieses Bild aus Wikipedia zeigt drei Puffer (Farbe, Tiefe und Normalen)

Geben Sie hier die Bildbeschreibung ein

Auch hier variieren Menge, Art und Inhalt der verwendeten Puffer zwischen den verschiedenen Projekten erheblich. Sie finden den Puffersatz mit dem Namen GBuffers.

  1. Danach ist der Zeitpunkt, an dem die eigentliche Beleuchtung angewendet wird. Während des Beleuchtungsdurchlaufs für jedes Licht möchten Sie ein Lichtvolumen zeichnen, das von der Art des Lichts abhängt:
    • Für ein gerichtetes Licht rendern Sie ein Vollbild-Quad.
    • Für ein Punktlicht rendern Sie eine Kugel, bei der der Radius auf der Dämpfung Ihres Punktlichts basiert.
    • Für ein Spotlicht rendern Sie einen Kegel, dessen Abmessungen wiederum von den Eigenschaften Ihres Lichts abhängen.

Im Pixel-Shader dieses Durchgangs übergeben Sie Ihre GBuffers und führen Ihre Beleuchtung und Schattierung anhand der darin enthaltenen Informationen durch. Auf diese Weise verarbeiten Sie nur die Pixel, die von jedem der Lichter betroffen sind und im Vergleich zum klassischen Vorwärts-Rendering eine sinnvolle Beschleunigung aufweisen.

Es hat auch verschiedene Nachteile, insbesondere die Handhabung transparenter Objekte und einen höheren Verbrauch an Bandbreite und Videospeicher. Es ist aber auch schwieriger, verschiedene Modelle für Materialien zu handhaben.

Sie haben andere Nebeneffekte (da viele Informationen für die Nachbearbeitung bereitstehen) und sind auch ziemlich einfach zu implementieren. Aber das ist nicht mehr das Coolste für viele Lichter.

Neuere Techniken sind beispielsweise gekachelte Rendering- Techniken . Die Hauptidee davon ist, die Szene in "Kacheln" des Bildschirmbereichs zu unterteilen und jeder Kachel die Lichter zuzuweisen, die sie beeinflussen. Dies besteht sowohl aufgeschoben als auch vorwärts. Diese Techniken führen zu einigen Problemen, wenn Sie verschiedene Tiefendiskontinuitäten in einer Kachel haben, sind jedoch im Allgemeinen schneller als die klassische verzögerte und lösen verschiedene Probleme. Zu den Vorteilen gehört beispielsweise, dass Sie mit verzögerten Kacheln die GBuffers einmal pro beleuchtetem Fragment lesen und Pixel in derselben Kachel kohärent dieselben Lichter verarbeiten.

Eine weitere Entwicklung auf dieser Seite ist die Clustered-Schattierung, die konzeptionell den auf Kacheln basierenden Ansätzen ähnelt und anstelle von Bildschirmraumkacheln Cluster mit einer 3D-Ausdehnung aufweist. Diese Methode behandelt das Problem der Tiefendiskontinuitäten besser und bietet im Allgemeinen eine bessere Leistung als die gekachelten Methoden.

WICHTIGER HINWEIS: Ich habe die Grundlagen der verzögerten Schattierung beschrieben. Es gibt mehrere Variationen, Optimierungen und Verbesserungen. Ich empfehle Ihnen daher, mit einer einfachen Version zu experimentieren und dann einige Untersuchungen zu anderen Techniken durchzuführen, wie der oben erwähnten.


1
Hier sind zwei Quellcode-Ressourcen für Tiled und Clustered
RichieSams
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.