Sun
04
May 2008
Piszemy Deferred Shading... Pierwsze co przychodzi do głowy, to zapisywanie do G-buforów pozycji i wektora normalnego w przestrzeni kamery jako pełne (x,y,z). Żeby oszczędzić komponentów, można je spakować. Zakładając, że wszystkie widoczne ścianki są zwrócone przodem do kamery, jako wektor normalny wystarczy zapisać tylko (x,y), a trzecią składową odzyskać ze wzoru:
Normal.z = - sqrt(1 - Normal.x*Normal.x - Normal.y*Normal.y);
Długo szukałem działającego wzoru na kodowanie pozycji jako pojedyncza odległość/głębokość, więc tym chętniej się nim podzielę. Są tutaj różne szkoły. Można zapisywać głębokość z/w, można odległość od kamery, można też odległość od bliskiej płaszczyzny przycinania. U mnie sprawdziło się takie rozwiązanie:
// Kodowanie - VS: Out.ViewPos = mul(float4(In.Pos, 1), (float4x3)WorldView); // Kodowanie - PS: G1.b = length(In.ViewPos); // Dekodowanie - VS: Out.EyeVec = float3(In.Pos.x * AspectRatio, In.Pos.y, TanFovY); // Dekodowanie - PS: Pos = normalize(In.EyeVec) * G1.b;
Gdzie podczas dekodowania: Pos.xy to pozycja wierzchołków fullscreen quada w przestrzeni rzutowania -1..1, TanFovY to tangens kąta widzenia pionowego w radianach używanego w macierzy rzutowania tan(FovY), AspectRatio to stosunek szerokości do wysokości widoku.
Trzeba jeszcze pamiętać, że jeśli tekstura G-bufora nie jest w formacie zmiennoprzecinkowym (jak u mnie A16B16G16R16F), to zapisywane wartości trzeba jakoś skalować do przedziału 0..1.
Comments | #algorithms #rendering Share