Rendering wolumetryczny

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

Krok 2 - Proste śledzenie promieni

Zajmiemy się teraz najważniejszą częścią naszego renderera - śledzeniem promieni. Problem ten jest dość skomplikowany i daje duże pole do popisu przy optymalizacji, jeśli operujemy na trójkątach. Jednak w naszym przypadku nie ma tu dużo do odkrycia - musimy przemieszczać się wzdłuż promienia, przeskakując o małe odległości i sprawdzając, czy w aktualnym punkcie znajduje się materia. Gęstość takiego próbkowania musi być dostatecznie duża, aby nie przeskoczyć jakiegoś obiektu.

Oczywiście nie możemy próbkować promienia w nieskończoność, więc ograniczamy śledzenie promienia do konkretnej odległości od kamery - tę odległość przechowuje zmienna farClipping. Możemy również szukać dopiero od pewnej odległości od kamery, ponieważ zwykle tak ustawiamy scenę, że pierwsze obiekty zaczynają pojawiać się dopiero w większej odległości od kamery. Dlatego przeszukiwanie przestrzeni zbyt blisko kamery niepotrzebnie wydłuża czas renderingu - i tak nic nie znajdziemy. Minimalną odległość od kamery przechowuje zmienna nearClipping. Musimy jednak pamiętać, że przycinanie bliskich obiektów ma sens jedynie wtedy, gdy śledzimy promienie główne. Z drugiej strony mamy promienie testujące, czy dany punkt jest w cieniu - wtedy nie możemy ograniczać obszaru przeszukiwania od dołu, bo obiekt rzucający cień na nasz punkt może być bardzo blisko. Dlatego funkcja śledząca promień przyjmuje jako parametr informację, czy korzystamy z near clippingu.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Vector SimpleRaytrace(Vector startPos, Vector ray, bool enableNearClipping)
{
    Vector current = startPos;
    if(enableNearClipping)
        current += nearClipping * ray;
    int howMany = (int)((farClipping - nearClipping) / step);
    for (int i = 0; i < howMany; ++i)
    {
        current += ray*step;
        if (world.GetPoint(current))
            return current;
    }
    return new Vector(double.NaN, double.NaN, double.NaN);
}

Wektor current przechwuje aktualnie testowany punkt; na początku przypisujemy tej zmiennej punkt, z którego zaczynamy przeszukiwanie (np. pozycję kamery), czyli startPos. Każdy kolejny punkt, który testujemy, jest odległy o step od poprzedniego. Kontynuujemy przeszukiwanie, dopóki nie znajdziemy punktu materii lub nie wyjdziemy poza obszar przeszukiwania ograniczony przez farClipping. Funkcja zwraca pozycję znalezionego punktu materialnego lub wektor o współrzędnych double.NaN, jeśli takiego punktu nie udało się znaleźć w zadanym przedziale.

Zmienna current przedstawiona na rysunku odnosi się do ostatniego sprawdzanego przez funkcję punktu, który okazuje się „zawierać” materię i zostanie zwrócony (w przypadku, gdy punkt rzeczywiście zostanie odnaleziony; w przeciwnym wypadku, jak mówiliśmy wcześniej, funkcja zwróciłaby wektor o współrzędnych double.NaN.

Wynik funkcji mówi nam po prostu, dokąd w przybliżeniu dojdzie promień światła. Na następnej stronie artykułu nieco poprawimy to przybliżenie.

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

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com