Rendering wolumetryczny

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

Krok 3 - Poszukiwanie dokładnego przecięcia promienia z powierzchnią

Jeśli założymy, że w naszym świecie istnieje granica pomiędzy materią a jej brakiem, czyli że materia ma swoją powierzchnię, możemy znacznie poprawić dokładność znalezionego przecięcia promienia ze światem za pomocą przeszukiwania binarnego.

1
2
3
4
5
6
7
8
9
10
11
12
Vector BinaryRaytrace(Vector prev, Vector current)
{
    for (int i = 0; i < binaryIters; ++i)
    {
        Vector mid = 0.5 * (prev + current);
        if (world.GetPoint(mid))
            current = mid;
        else
            prev = mid;
    }
    return 0.5 * (prev + current);
}

Powyższa funkcja przyjmuje dwa punkty jako argumenty. Drugi punkt (current) powinien znajdować się wewnątrz materii, a pierwszy (prev) na zewnątrz. Iterujemy wyszukiwanie binarne stałą liczbę razy (binaryIters) w celu znalezienia punktu leżącego na prostej przechodzącej przez punkty zadane jako argumenty funkcji, który z możliwie dużą dokładnością leży na powierzchni renderowanego obiektu, pomiędzy punktami wejściowymi. W praktyce, drugim punktem (current) będzie wynik funkcji prostego śledzenia promienia z poprzedniej strony, a pierwszym argumentem (prev) będzie poprzedni punkt sprawdzony przez ową funkcję, czyli ostatni, który jeszcze „nie zawierał” materii.

Na rysunku widać, jak śledzony jest promień oraz jak wynik prostego raytracingu z poprzedniej strony ma się do przeszukiwania binarnego zaprezentowanego przed chwilą.

Funkcji prostego śledzenia promienia i przeszukiwania binarnego, zwiększającego dokładność, będziemy używać za pośrednictwem dwóch innych funkcji:

- Collision - zwraca wartość boolowską, mówiącą nam, czy promień kolidował z obiektem.

1
2
3
4
5
bool Collision(Vector startPos, Vector ray, bool enableNearClipping)
{
    Vector r = SimpleRaytrace(startPos, ray, enableNearClipping);
    return !double.IsNaN(r.x);
}

- CollisionPoint - zwraca punkt przecięcia promienia z obiektem lub wektor o współrzędnych double.NaN<\span> (jeśli przecięcie nie zostało stwierdzone).

1
2
3
4
5
6
7
8
9
10
11
12
Vector CollisionPoint(Vector startPos, Vector ray, bool enableNearClipping)
{
    // Szukanie przecięcia promienia ze światem
    Vector p = SimpleRaytrace(startPos, ray, enableNearClipping);
 
    if (double.IsNaN(p.x))
        return p;
 
    // Szukanie dokładniej, binarnie, powierzchni obiektu
    Vector prev = p - step*ray;
    return BinaryRaytrace(prev, p);
}

5
Twoja ocena: Brak Ocena: 5 (1 ocena)

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com