Aufgeschobene Schattierung - wie kombiniert man mehrere Lichter?

9

Ich beginne mit GLSL und habe eine einfache verzögerte Schattierung implementiert, die G-Puffer mit Positionen, Normalen und Albedo ausgibt.

Ich habe auch einen einfachen Punktlicht-Shader geschrieben.

Jetzt zeichne ich eine Kugel für das Punktlicht und die Ausgabe geht in einen Beleuchtungspuffer.

Das Problem ist, wie kombiniere ich die Ergebnisse des Beleuchtungspuffers beim Zeichnen mehrerer Lichter?

Wenn ich beispielsweise das zweite Licht mit dem Punktlicht-Shader zum Lichtpuffer zeichne, wie füge ich dem zweiten Licht im Lichtpuffer das erste Licht hinzu? Ich meine, Sie können nicht aus demselben Ausgabepuffer lesen und in diesen schreiben?

JBeurer
quelle

Antworten:

12

Additive Mischung, dh glBlendFunc (GL_ONE, GL_ONE) und glEnable (GL_BLEND).

Nathan Reed
quelle
Muss die Tiefenprüfung dafür deaktiviert werden?
woojoo666
1
@ woojoo666 Nein. Tatsächlich sollte es aktiviert werden, wenn der Tiefentest auf weniger gleich eingestellt ist, damit Oberflächen, die genau mit dem vorherigen Durchgang übereinstimmen, durchlaufen werden. Wenn der Tiefentest deaktiviert ist, akkumulieren Oberflächen fälschlicherweise Licht von dem, was sich dahinter befindet. :)
Nathan Reed
hmm, es scheint genau das zu sein. Wenn Sie das Mischen aktivieren, werden die Vorderflächen mit den Rückseiten gemischt, obwohl ich die Tiefenprüfung aktiviert habe. Muss ich auch etwas mit der Tiefenmaske machen?
woojoo666
hat ein bisschen mehr getestet, scheint eine Frage der Zeichnungsreihenfolge zu sein (das Zeichnen von vorne nach hinten führt dazu, dass die Tiefenprüfung korrekt funktioniert und das Mischen nur dann erfolgt, wenn die Gesichter äquiplanar sind, von hinten nach vorne wird alles zusammengemischt). Gibt es eine Möglichkeit, dies zu tun, ohne alles zu sortieren?
woojoo666
2
@ woojoo666 Aha, hört sich so an, als hättest du es selbst gelöst. Ja, Sie müssen die Tiefe in einem undurchsichtigen Durchgang festlegen, bevor Sie eine Mischung verwenden können. Es kann sich um einen Z-Prepass mit deaktivierten Farbschreibvorgängen handeln, oder eine andere übliche Methode besteht darin, Umgebungslicht in einem ersten Durchgang ohne Überblendung zu erzeugen und in späteren Durchgängen mit Überblendung Punkt- / Punktlichter hinzuzufügen.
Nathan Reed
2

Für meinen verzögerten Renderer aggregiere ich alle Lichter unter Verwendung der Informationen aus dem g-Puffer zu einem Lichtrenderziel und probiere dann das Renderziel auf Lichtintensität aus, während ich mein endgültiges Backbuffer-Bild erstelle.

Im Grunde genommen führe ich meine gesamte Spielgeometrie durch meinen Geometriepass, um die G-Puffer zu erstellen. Von dort füttere ich meinen Light Pass Shader mit den G-Puffern. Jedes Licht wird mit einem Vollbild-Quad durch den Pass geführt. Auf diese Weise kann mein Pixel-Shader die Lichtintensität für alle sichtbaren Oberflächen aus dem G-Puffer berechnen und sie dann zum Lichtrenderziel hinzufügen. Sie fügen einfach die Lichtintensität für jedes Licht zum Lichtpuffer hinzu, stellen jedoch sicher, dass Sie die Intensität von 0 auf 1 klemmen.

Alles, was Sie tun müssen, um verschiedene Arten von Lichtern (Punkt, Scheinwerfer, Parallel) zu handhaben, ist, den Lichtdurchgang robuster zu machen, indem Sie möglicherweise einen konstanten Puffer verwenden, um festzulegen, welche Beleuchtungsverfahren ausgeführt werden sollen.

KlashnikovKid
quelle
Ja, und die Frage ist: Wie fügt man dem Lichtrenderziel hinzu? Verwenden Sie Alpha-Blending, wie Nathan Reed vorgeschlagen hat? Denn soweit ich weiß, kann man nicht aus demselben Ausgabepuffer lesen und in diesen schreiben (der in diesem Fall der Lichtpuffer ist).
JBeurer
Ups, ja. Ich habe die Ausgabe-Fusion mit additiver Mischung erledigen lassen. Wenn Sie für das endgültige Bild abtasten, möchten Sie den Wert auf einen Wert festlegen, der für mich als maximal mögliche Lichtintensität gilt, die eine Oberfläche empfangen kann. Von dort aus können Sie Ihre Lichter einfach nach Bedarf skalieren.
KlashnikovKid
Wie gehen Sie mit Fällen um, in denen sich ein Licht hinter einer Wand befindet und keine Dinge auf der anderen Seite der Wand beleuchten sollten?
jjxtra
@PsychoDad Das ist die Domäne der Schatten, was ... ein komplizierteres Thema ist. :)
Nathan Reed
0

Es gibt wahrscheinlich eine bessere Antwort als diese, aber ich weiß, wenn Sie in Ihrem Shader den Code wiederholen, der für ein zweites Licht erforderlich ist, können Sie zwei Lichter auf einem einzelnen Objekt anstatt auf einem verarbeiten. Es erfordert viel Code für das zweite Licht und die Nähte sind etwas überflüssig, aber ich weiß, dass es funktioniert. Ich glaube jedoch, dass es eine elegantere Lösung geben könnte, wie jemand hoffentlich für Sie hervorheben wird.

CodeNeko
quelle
Nein, das funktioniert so nicht. Ich zeichne eine Kugel für jedes Punktlicht. Wenn das zweite Punktlicht nicht in der Einflusssphäre des ersten Lichts liegt, wird das zweite Licht einfach nicht gezeichnet. Ihre Methode würde funktionieren, wenn ich ein Vollbild-Quad für alle Punktlichter zeichne. Dies ist jedoch nicht der richtige Ansatz, da Vollbild-Quads für die globale Beleuchtung verwendet werden. Angenommen, ich habe 16 kleine Punktlichter, die mich zwingen würden, sie für jedes Pixel durchzugehen, selbst wenn das Pixel nicht von ihm beleuchtet wird. Und normalerweise würde ich sagen, dass jedes Pixel von einem oder zwei Lichtern beleuchtet wird. Und wenn ich 100 Lichter habe? NEIN
JBeurer
Der Hauptgrund, warum ich dies angegeben habe, ist, wenn Sie nur zwei oder wenige Lichter verwenden, kann es helfen. Insbesondere wenn Sie viele Objekte zerreißen, bedeutet die Verwendung einer Mischung, dass Sie die Szene für jedes Licht neu zeichnen müssen. Wenn Sie also viele Formen haben, z. B. eine Million oder zehn Millionen oder eine Milliarde, kostet jede Zeichnung viel mehr . Das Ausführen im Shader verursacht Probleme, wenn Sie viele Lichter möchten, aber das Mischen verursacht Probleme, wenn Sie viele Formen möchten. Wenn Sie viele von beiden haben, müssen Sie einen Mittelweg finden, aber normalerweise haben Sie ein paar Lichter und viele Objekte in Spielen.
CodeNeko
Nein, verzögerte Schattierung funktioniert so nicht. Ich muss die Szene nur einmal zeichnen und relevante Informationen in G-Buffer speichern. Dann eine Einflusssphäre für jedes Licht und mischen Sie es mit dem Lichtpuffer. Und schließlich kombiniere ich Lichtpuffer mit Farbpuffer und erhalte den endgültigen schattierten Farbpuffer. Der Umfang der Beleuchtungsberechnungen hängt nicht von der Komplexität der Szene ab. Dies ist in erster Linie der Hauptvorteil einer verzögerten Schattierung.
JBeurer
Ah, das macht viel mehr Sinn und wäre wesentlich besser.
CodeNeko