Auf einer der Folien aus PowerPoint "DirectX 11-Rendering in Battlefield 3" ist mir der folgende Code aufgefallen:
struct Light {
float3 pos; float sqrRadius;
float3 color; float invSqrRadius;
}
Ich verstehe nicht, warum sie den quadratischen Radius und sogar das inverse Quadrat (von dem ich glaube, dass es einfach ein Quadrat ist) speichern, anstatt einfach den Radius zu speichern? Wie verwenden sie diese Daten in ihren Berechnungen? Und was ist mit Kegel- und Linienlichtern? Diese Struktur muss nur für die Punktlichter sein, ich kann nicht sehen, dass sie für andere Typen funktioniert - es sind nicht genügend Daten vorhanden. Trotzdem würde ich gerne wissen, wie sie dieses Quadrat und invSquare verwenden.
UPDATE: Ok, ich habe es endlich verstanden.
Hier ist die klassische Lichtdämpfungsgleichung, die im Netz leicht zu finden ist:
float3 lightVector = lightPosition - surfacePosition;
float attenuation = saturate(1 - length(lightVector)/lightRadius);
Es ist relativ kostspielig, wie dies length(lightVector)
tatsächlich tut:
length(lightVector) = sqrt(dot(lightVector, lightVector);
Darüber hinaus ist die Aufteilung (/lightRadius)
auch recht kostspielig.
Anstatt die Lichtabschwächung auf diese Weise zu berechnen, können Sie sie folgendermaßen berechnen, was viel schneller wäre:
attenuation = saturate(1 - dot(lightVector, lightVector)*invRadiusSqr);
Dabei kann invRadiusSqr auf CPU-Ebene vorberechnet und als Shader-Konstante übergeben werden.
Darüber hinaus erhalten Sie als Ergebnis eine quadratische Lichtabschwächung (im ersten Fall nicht linear), was sogar noch besser ist, da IRL-Licht eine quadratische Abschwächung aufweist.
Vielen Dank für Ihre Hilfe!
Antworten:
Dies ist einfach eine Art Optimierung, da
invSqrRadius = 1/SqrRadius
anstelle der Berechnung des inversen quadratischen Radius für jedes Licht jedes Mal, wenn es einfach zwischengespeichert wird, der Grund dafür liegt, dass die Division normalerweise eine "langsame" Operation ist, zumindest im Vergleich zur Multiplikation.Diese Optimierung ist insbesondere relevant:
Was die Verwendung betrifft, bin ich mir nicht sicher, ob sie konkret implementiert wurden, aber
1/sqrRadius
dies wird lediglich für die Dämpfung, das Abfallen und das Keulen von Licht verwendet. Dies ist auch für die Ausrichtung und das Spotlight relevant. Der einzige Unterschied beim Spotlight besteht darin, dass Sie den Spotlight-Faktor nach dem Anwenden der Dämpfung berechnen müssen . In Bezug auf direktionales Licht wie Sonne hat es normalerweise keine Dämpfung oder Abnahme, daher würde ich davon ausgehen, dass es ignoriert wird.[EDIT] Nur um mehr auszuarbeiten, es sind keine irrelevanten Daten. Die Lichtbestrahlungsstärke kann mit der folgenden Gleichung berechnet werden:
Diese Gleichung erklärt, warum die empfangene Energiemenge mit der Quadratdistanz abnimmt.
Ein weiterer Punkt ist, dass Sie den Abstand zwischen dem Scheitelpunkt und dem Licht berechnen müssen, um den Lichtbeitrag für einen bestimmten Scheitelpunkt zu berechnen (es ist unwahrscheinlich, dass dieser Wert zwischengespeichert wird). Der Scheitelpunkt kann sich innerhalb oder außerhalb des Lichtbereichs befinden, der uns zum nächsten Punkt bringt wo
Radius Square
ist nützlich für das Keulen.Wenn Sie ein praktisches Beispiel für die Berechnung von Lichtabfall und -ausscheidung wünschen, ist dies besonders bei gekachelten Renderern hilfreich. Hier ein Beispiel .
quelle
invSqrRadius ist nicht 1 - sqrRadius; es ist 1 / sqrRadius.
Dies bedeutet, dass Sie mit invSqrRadius multiplizieren können, anstatt durch sqrRadius zu dividieren (da die Division in der Regel viel teurer ist als die Multiplikation).
quelle
Die anderen Antworten befassten sich mit dem umgekehrten quadratischen Radius, aber ich werde stattdessen den quadratischen Radius betrachten (welches Konzept3d angesprochen hat, aber ich glaube, es verdient eine weitere Diskussion).
Was für Quadrate nützlich sind, sind Entfernungsvergleiche. Wir wissen, dass die Berechnung des Abstands zwischen zwei Punkten eine Quadratwurzel erfordert und die Berechnung von Quadratwurzeln teuer ist. Wenn wir jedoch nur die Entfernungen vergleichen möchten (um herauszufinden, welche kleiner oder größer ist, und etwas Interessantes basierend auf der Ergebnis) können wir die Quadratwurzel werfen.
Wenn sqrt (x)> sqrt (y) ist, dann ist es auch so, dass x> y ist.
Für eine Leuchte entspricht der quadratische Radius dem Abstand zwischen dem Lichtmittelpunkt und der maximalen Ausdehnung - natürlich im Quadrat.
Für Beleuchtungsberechnungen kann dies für einen Early-Out-Fall verwendet werden. Wenn der Abstand zwischen dem Punkt, den Sie beleuchten, und dem Lichtmittelpunkt (Quadrat) größer als der Quadratradius ist, empfängt der Punkt kein Licht und Sie müssen den Rest Ihrer Berechnungen nicht ausführen. Dies ist daher nur eine Optimierung (eine ziemlich häufige) - wir können den Abstandsvergleich mit einem quadratischen Radius ohne teure Quadratwurzeln durchführen, und das zu einem Preis von nur einem Subtraktions- und Punktprodukt.
Ich weiß natürlich nicht, ob dies genau das ist , wofür BF3 es verwendet, aber ich würde erwarten, dass ich nicht zu weit von der Marke entfernt bin.
quelle