Na jednym ze slajdów z „DirectX 11 Rendering in Battlefield 3” PowerPoint zauważyłem następujący kod:
struct Light {
float3 pos; float sqrRadius;
float3 color; float invSqrRadius;
}
Nie rozumiem, dlaczego mieliby przechowywać kwadratowy promień, a nawet odwrotny kwadrat (który moim zdaniem jest po prostu promieniem 1-kwadratowym) zamiast po prostu przechowywać promień? Jak wykorzystują te dane w swoich obliczeniach? A co z lampkami stożkowymi i liniowymi? Ta struktura musi być tylko dla świateł punktowych, nie widzę, aby działała dla innych typów - nie ma wystarczającej ilości danych. Nadal chciałbym wiedzieć, jak używają tego kwadratu i invSquare.
AKTUALIZACJA: Ok, w końcu to rozumiem.
Oto klasyczne równanie tłumienia światła, które można łatwo znaleźć w sieci:
float3 lightVector = lightPosition - surfacePosition;
float attenuation = saturate(1 - length(lightVector)/lightRadius);
Jest to stosunkowo kosztowne, ponieważ length(lightVector)
faktycznie robi to:
length(lightVector) = sqrt(dot(lightVector, lightVector);
ponadto operacja podziału (/lightRadius)
jest również dość kosztowna.
Zamiast obliczać tłumienie światła w ten sposób, możesz obliczyć go w następujący sposób, co byłoby znacznie szybsze:
attenuation = saturate(1 - dot(lightVector, lightVector)*invRadiusSqr);
gdzie invRadiusSqr można wstępnie obliczyć na poziomie procesora i przekazać jako stałą modułu cieniującego.
Ponadto uzyskuje się w ten sposób kwadratowe tłumienie światła (zamiast liniowego w poprzednim przypadku), co jest jeszcze lepsze, ponieważ światło IRL wykazuje kwadratowy spadek światła.
Dziękuję wszystkim za pomoc!
Odpowiedzi:
Jest to po prostu rodzaj optymalizacji, biorąc pod uwagę, że
invSqrRadius = 1/SqrRadius
zamiast obliczać odwrotny kwadratowy promień dla każdego światła za każdym razem, gdy po prostu buforuje je, przyczyną jest to, że podział jest zwykle operacją „powolną”, przynajmniej w porównaniu do mnożenia.Ta optymalizacja jest szczególnie istotna:
Jeśli chodzi o sposób jego wykorzystania, nie jestem pewien ich konkretnej implementacji, ale jeśli chodzi o
1/sqrRadius
to, jest on po prostu używany do tłumienia światła, wypadania i ubijania. Ma to również znaczenie dla kierunkowego i punktowego, jedyną różnicą w przypadku reflektora jest to, że należy obliczyć współczynnik reflektora po zastosowaniu tłumienia . Jeśli chodzi o światła kierunkowe, takie jak słońce, zwykle nie ma on żadnego tłumienia ani spadku, więc sądzę, że zostanie zignorowany.[EDYCJA] Żeby rozwinąć więcej, nie są to nieistotne dane. Lekkie natężenie napromienienia można obliczyć za pomocą następującego równania:
To równanie wyjaśnia, dlaczego ilość otrzymanej energii spada z kwadratową odległością.
Kolejnym punktem jest to, że musisz obliczyć odległość między wierzchołkiem a światłem, aby obliczyć udział światła w określonym wierzchołku (ta wartość nie jest buforowana), wierzchołek może znajdować się w zasięgu światła lub poza nim, co prowadzi nas do następnego punktu gdzie
Radius Square
jest przydatny do uboju.Jeśli potrzebujesz praktycznego przykładu do obliczania lekkiego spadku i wygaszania, jest to szczególnie przydatne w przypadku odroczonych rendererów opartych na kafelkach, oto jeden przykład .
źródło
invSqrRadius nie jest 1 - sqrRadius; to 1 / sqrRadius.
Oznacza to, że możesz pomnożyć przez invSqrRadius, zamiast dzielić przez sqrRadius (ponieważ dzielenie jest zwykle znacznie droższe niż mnożenie)
źródło
Inne odpowiedzi tutaj dotyczyły odwrotnego promienia kwadratowego, ale zamiast tego przyjrzę się kwadratowemu promieniu (która koncepcja dotknęła, ale uważam, że zasługuje na dalszą dyskusję).
Kwadraty są przydatne do porównań odległości. Wiemy, że obliczanie odległości między dwoma punktami wymaga pierwiastka kwadratowego, a pierwiastki kwadratowe są drogie do obliczenia, ale jeśli wszystko, co chcemy zrobić, to porównać odległości (aby znaleźć, która jest mniejsza lub większa, i zrobić coś interesującego na podstawie wynik) możemy wyrzucić pierwiastek kwadratowy.
Jeśli sqrt (x)> sqrt (y), to również przypadek, że x> y.
W przypadku światła kwadratowy promień jest taki sam, jak odległość między środkiem światła i jego maksymalnym zasięgiem - oczywiście kwadrat.
W przypadku obliczeń oświetleniowych można to wykorzystać w przypadku wczesnego wyjścia. Jeśli odległość między oświetlanym punktem a środkiem (kwadratem) światła jest większa niż promień kwadratu, punkt nie odbiera światła i nie musisz uruchamiać reszty obliczeń. Jest to zatem tylko optymalizacja (dość powszechna) - możemy użyć kwadratu promienia, aby wykonać porównanie odległości bez drogich pierwiastków kwadratowych, a kosztem jest tylko odjęcie i kropka.
Oczywiście nie wiem, czy właśnie do tego używa go BF3, ale spodziewałbym się, że nie jestem zbyt daleko od celu.
źródło