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. Ś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:
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:
Jak widać, sfera nie pojawia się przezroczysta, ale nie dziedziczą kolor rozproszonego Sfery. Zwykle ma też jakieś białe piksele.
bez załamania:
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'? –
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
Wszyscy to myślimy. GWIAZDA ŚMIERCI –