2011-10-26

Błędy numeryczne

Ich występowanie jest szczególnie uciążliwe dla takich obiektów jak sfera i torus. Podejrzewam, że podobne problemy mogą dotyczyć wszystkiego co nie jest płaskie, czyli trójkąta. Patrząc na kod historycznie kod trójkąta (intersekcja, normalna, mapowanie tekstury, mapowanie wypukłości) nie zmienił się ani trochę od samego początku. Nie ma w nim żadnego względnego porównywania względem błędu, a porównanie bezwzględne jest dla wartości z zakresu 0...1.

Z błędami numerycznymi jako takimi można sobie radzić dobierając gdzie trzeba porównania z pożądaną precyzją. Problem zaczyna się kiedy odległości pomiędzy obiektami są bardzo małe albo bardzo duże lub same obiekty są bardzo małe albo bardzo duże. Z pierwszym możemy sobie poradzić normalizując scenę do żądanych rozmiarów np. AABB o wymiarze $\pm 1$. Z drugim możemy sobie poradzić skalując obiekt odpowiednio do współrzędnych lokalnych. W obu przypadkach stabilizujemy wartości na których liczymy i tym samym błąd.

Ciągle pozostaje jednak problem kiedy odległości pomiędzy obiektami różnią się od siebie znacznie. Wtedy po normalizacji sceny odległości pomiędzy nimi mogą stać się mniejsze od precyzji co może wywołać błędy numeryczne. I to chyba będzie waży argument w moim przypadku przenieść obliczenia na double z powrotem. Na razie ten problem zostawiam sobie na później.

Dodatkowo dla sfery i torusa tuż po wyliczeniu wynikowej intersekcji sprawdzamy, czy normalna i promień padający tworzą kąt mniejszy od 90 stopni. Pozwala to nam zapobiegać błędom numerycznym kiedy promień jest prawie prostopadły do powierzchni. Takie błędy lepiej uciąć u źródeł niż dodawać w wielu miejscach kod na ich korekcje.

Kolejna poprawka dotyczyła kontroli argumentów dla funkcji o ograniczonej dziedzinie (pierwiastkowanie, odwrotne funkcje trygonometryczne). Jeśli przekraczają one dziedzinę nieznacznie są do niej zaokrąglane np. -0.000001 do 0 dla pierwiastkowania.

Kolejna poprawka dotyczyła ścisłego kontrolowania współrzędnych UV, co okazało się szczególnie istotnie dla torusa, gdzie błąd może znacznie przekroczyć wartości 0...1.

W ogóle torus to wyjątkowo trudny obiekt. Bardzo niestabilny numerycznie. Wydaje mi się, że w przyszłości wszelkie powierzchnie wyższego rzędu będą służyć tylko do generacji siatki trójkątów. Są one niestabilnie numerycznie i każda nowa rzecz jaką dodawałem do raytracera wymagała jakiś specjalnych działań by wszystko zaczęło dobrze działać.

Kolejna poprawka tym razem na kod sfery dotyczy parametry m2. Generalnie powinien się on zawierać w granicach od 0 do 1. Ale jeśli promień nadchodzi z bardzo daleka niekoniecznie okazuje się to być prawdą. Musimy go z zadaną precyzją przyciąć do wartości 0...1.

I kolejna poprawka tym razem na torus i sferę. Najpierw wyliczamy czy promień uderza w AABB i od razu znajdujemy do niego odległość. Następnie przesuwamy promień na granicę lokalnego AABB wykorzystując tą odległość. Dzięki temu błędy dla promieni nadchodzących z daleka zostały znacznie zredukowane. To także powinno zmniejszyć błędy numeryczne liczenia intersekcji torusa i go ustabilizować pozwalając na jego korygowanie niezależnie jak pada promień.

Jak widać większość błędów kręci się wokół sfery i torusa.

Brak komentarzy:

Prześlij komentarz