Rendering wolumetryczny

20.12.2010 - Adam Błaszkiewicz
TrudnośćTrudnośćTrudność

Krok 1 - Generowanie promieni głównych

Przez promienie główne rozumiemy promienie wystrzelone z kamery w stronę każdego piksela. Kamera zdefiniowana jest jako macierz transformująca widok z punktu $ \begin{bmatrix} 0 & 0 & 0 \end{bmatrix} $ w stronę dodatniej osi Z. Tak więc po pomnożeniu wektora $ \begin{bmatrix} 0 & 0 & 0 & 1 \end{bmatrix} $ przez taką macierz, otrzymamy pozycję kamery.

1
Vector cameraPos = new Vector() * transformation;

Natomiast jeśli przemnożymy wektor $ \begin{bmatrix} 0 & 0 & 1 & 0 \end{bmatrix} $ przez tę samą macierz, dostaniemy kierunek, w którym kamera jest skierowana.

Na początku wygenerujemy promienie główne dla wspomnianego wcześniej widoku ze środka układu współrzędnych, a następnie przemnożymy je przez macierz kamery, aby otrzymać właściwy już widok.

Obszar widziany przez kamerę ma kształt ostrosłupa o prostokątnej podstawie - kamera jest jego czubkiem. Właściwie, jego wysokość powinna być nieskończona, w ten sposób, że nigdy nie dotrzemy do podstawy. Wyobraźmy sobie, że w którymś miejscu przetniemy nasz ostrosłup płaszczyzną - możemy sobie wyobrazić, że to będzie ekran, na który powinien być rzutowany każdy punkt przestrzeni znajdujący się w ostrosłupie, wzdłuż prostej przechodzącej przez ten punkt i przez kamerę (wierzchołek ostrosłupa). Dla ułatwienia, przetniemy ostrosłup w odległości 1 od kamery.

Sam kształt ostrosłupa determinowany jest kątem widzenia kamery w pionie (ang. FOV - Field of view) oraz stosunkiem szerokości do wysokości ekranu (ang. Aspect ratio). Kąt widzenia w pionie jest oznaczony na rysunku jako $ \varphi $. Widać, że długość wektora $ v $ wynosi $ \tan{\frac{1}{2}\phi} $. Długość wektora $ u $ można obliczyć, mnożąc długość $ v $ przez stosunek szerokości do wysokości ekranu.

1
2
double fovYTan = Math.Tan(fov * 0.5); // Tangens z połowy kąta fi (kąta widzenia w pionie)
double fovXTan = fovYTan * sizeX / sizeY; // Tangens z połowy kąta widzenia w poziomie

Aby wygenerować promień, należy dodać do siebie $ w $ oraz przemnożone przez skalary z zakresu $ [-1,1] $ $ u $ i $ v $. Skalary dobieramy z zależności od tego, w który „piksel” celujemy. Następnie, jak wspomnieliśmy wcześniej, transformujemy wektor tak, aby był zgodny z orientacją kamery. Na końcu normalizujemy go (skalujemy tak, żeby miał długość $ 1 $).

1
2
3
4
5
6
7
// Obliczanie wektora od kamery do danego piksela
DirectionVector ray = new DirectionVector();
ray.z =  1.0;
ray.x =  (2.0 * x / sizeX - 1.0) * fovXTan;
ray.y = -(2.0 * y / sizeY - 1.0) * fovYTan;
ray *= transformation;
ray.Normalize();
5
Twoja ocena: Brak Ocena: 5 (1 ocena)

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com