2014-11-04 17 views
6

Piszę ray tracer. Do tej pory mam rozproszone, blinowe oświetlenie i odbicia. Coś poszło nie tak z moimi załamaniami i nie mam pojęcia co. Mam nadzieję, że ktoś może mi pomóc. enter image description hereŚledzenie promienia - błąd refrakcji

Mam dużą czerwoną rozproszoną kulę Blinna i małą refrakcyjną o współczynniku załamania n = 1,5.

Ten mały jest naprawdę spieprzony.

odpowiedni kod:

ReflectiveSurface::ReflectiveSurface(const Color& _n, const Color& _k) : 
F0(Color(((_n - 1)*(_n - 1) + _k * _k)/((_n + 1)*(_n + 1) + _k * _k))) {} 

Color ReflectiveSurface::F(const Point& N, const Point& V) const { 
    float cosa = fabs(N * V); 
    return F0 + (F0 * (-1) + 1) * pow(1 - cosa, 5); 
} 

Color ReflectiveSurface::getColor(const Incidence& incidence, const Scene& scene, int traceDepth) const { 
    Point reflectedDir = reflect(incidence.normal, incidence.direction); 
    Ray ray = Ray(incidence.point + reflectedDir * epsilon, reflectedDir); 
    return F(incidence.normal, incidence.direction) * scene.rayTrace(ray, traceDepth + 1); 
} 

Point ReflectiveSurface::reflect(const Point& N, const Point& V) const { 
    return V - N * (2 * (N * V)); 
} 

bool RefractiveSurface::refractionDir(Point& T, Point& N, const Point& V) const { 
    float cosa = -(N * V), cn = n; 
    if (cosa < 0) { cosa = -cosa; N = N * (-1); cn = 1/n; } 
    float disc = 1 - (1 - cosa * cosa)/cn/cn; 
    if (disc < 0) return false; 
    T = V/cn + N * (cosa/cn - sqrt(disc)); 
    return true; 
} 

RefractiveSurface::RefractiveSurface(float _n, const Color& _k) : ReflectiveSurface(Color(1, 1, 1) * _n, _k) {} 

Surface* RefractiveSurface::copy() { return new RefractiveSurface(*this); } 

Color RefractiveSurface::getColor(const Incidence& incidence, const Scene& scene, int traceDepth) const { 
    Incidence I = Incidence(incidence); 
    Color reflectedColor, refractedColor; 
    Point direction = reflect(I.normal, I.direction); 
    Ray reflectedRay = Ray(I.point + direction * epsilon, direction); 
    if (refractionDir(direction, I.normal, I.direction)) { 
     Ray refractedRay = Ray(I.point + direction * epsilon, direction); 
     Color colorF = F(I.normal, I.direction); 
     reflectedColor = colorF * scene.rayTrace(reflectedRay, traceDepth + 1); 
     refractedColor = (Color(1, 1, 1) - colorF) * scene.rayTrace(refractedRay, traceDepth + 1); 
    } 
    else { 
     reflectedColor = scene.rayTrace(reflectedRay, traceDepth + 1); 
    } 
    return reflectedColor + refractedColor; 
} 

Kod jest w każdym miejscu, ponieważ jest to praca domowa i nie wolno mi o dodatkowe nagłówki i muszę wysłać je w jednym pliku cpp, więc Musiałem oddzielić każdą klasę na deklarację, deklarację i wdrożenie w tym jednym pliku. Sprawia, że ​​wymiotuję, ale starałem się, aby był jak najbardziej czysty. Jest mnóstwo kodu, więc zawarłem tylko to, co uważałem za najbardziej powiązane. ReflectiveSurface to klasa nadrzędna RefractiveSurface. N jest normalną powierzchnią, V jest kierunkowym wektorem promienia tak normalnym, n jest współczynnikiem załamania. Struktura występowania utrzymuje punkt, wektor normalny i kierunek.

Wzory do zbliżenia Fersnel i załamania wektorem odpowiednio: enter image description here

można zobaczyć w kodzie, który używam epsilon * wartość kierunek ray uniknąć cienia trądziku spowodowanego przez pływaka niedokładności. Coś podobnego zdaje się jednak dziać w małej sferze. Kolejny zrzut ekranu: enter image description here

enter image description here

Jak widać, sfera nie pojawia się przezroczysta, ale nie dziedziczą kolor rozproszonego Sfery. Zwykle ma też jakieś białe piksele.

bez załamania:

enter image description here

+0

Jakiego rodzaju liczby dotyczą? Możliwe, że twoje wartości stają się zbyt małe, aby mogły być dokładnie reprezentowane przez 'float' i wynoszą zero. Czy mógłbyś/próbowałeś użyć zamiast tego 'double'? –

+0

Wygląda na to, że znajduje się w zakresie 20-100 dla dwóch wartości kolorów w pierwszych iteracjach, gdy pojawi się w trybie debugowania na końcu funkcji getColor, a następnie zostanie podzielony przez odległość^2 od kamery i nasycony. – PEC

+0

Wszyscy to myślimy. GWIAZDA ŚMIERCI –

Odpowiedz

1

Odpowiedź okazała się dość prosta, ale zajęło mi to 3 dni patrzenia na kod, aby złapać błąd. Mam klasę Surface, wywodzę się z niej z dwóch klas: RoughSurface (diffuse + blinn) i RelfectiveSurface. Następnie RefractiveSurace pochodzi z RefleciveSurface. Konstruktor ReflectiveSurface przyjmuje współczynnik załamania (n) i wartość ekstynkcji (k) jako parametry, ale ich nie przechowuje.(F0) jest wyliczany z nich podczas budowy, a następnie są one tracone. Natomiast refrakcja z drugiej strony wykorzystuje (n) w obliczaniu kąta refrakcji.

Old konstruktor:

RefractiveSurface::RefractiveSurface(float _n, const Color& _k) : 
    ReflectiveSurface(Color(1, 1, 1) * _n, _k) {} 

Nowy Konstruktor:

RefractiveSurface::RefractiveSurface(float _n, const Color& _k) : 
    ReflectiveSurface(Color(1, 1, 1) * _n, _k), n(_n) {} 

Jak widać, zapomniałem zapisać wartość (n) w przypadku RefractiveSurface w konstruktorze.

Mała czerwona kula za duży szklanej kuli oświetlony od dwóch stronach kamery:

enter image description here

Wygląda super w ruchu D

Dziękuję za poświęcony czas, chłopaki!. Muszę skończyć to zadanie domowe, a potem przerobię całą sprawę i zoptymalizuję to.

1

RefractiveSurface::refractionDir wykonuje normalny N przez (const) odniesienia, i może go odwrócić. To wydaje się niebezpieczne. Nie jest jasne, czy osoba dzwoniąca chce odwrócić tę wartość, ponieważ jest używana w dalszych obliczeniach kolorów.

Ponadto, refracted_color nie zawsze jest inicjowane (chyba że konstruktor koloru sprawi, że będzie czarny).

Spróbuj (tymczasowo) uprościć i zobacz, czy załamane promienie trafiają tam, gdzie oczekujesz. Usuń obliczenia Fresnela i komponent odbicia i po prostu ustaw refracted_color na wynik śladu załamanego promienia. Pomoże to ustalić, czy błąd jest w obliczeniach Fresnela, czy w geometrii zginania promienia.

Wskazówka do debugowania: Kolor pikseli, które niczego nie uderzają czymś innym niż czarny. Dzięki temu łatwo odróżnić chybienia od cieni (trądzik powierzchniowy).