Sto scrivendo un ray tracer. Finora ho diffuso, illuminazione Blinn e riflessioni. Qualcosa è andato storto con le mie rifrazioni e non ho idea di cosa. Spero che qualcuno possa darmi una mano. Ray tracing - bug di rifrazione
Ho una grande sfera rossa diffusa + Blinn e una piccola rifrangente con indice di rifrazione n = 1.5.
Il piccolo è davvero rovinato.
codice rilevante:
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;
}
Il codice è tutto il luogo, dal momento che questo è un lavoro e io non sono autorizzato a includere le intestazioni supplementari e devo inviarlo in in un file cpp, così Ho dovuto separare ogni classe in una dichiarazione, dichiarazione e implementazione in quel file. Mi fa vomitare ma ho cercato di mantenerlo il più pulito possibile. C'è un sacco di codice quindi ho incluso solo quello che pensavo fosse più relativo. ReflectiveSurface è la classe genitore di RefractiveSurface. N è la superficie normale, V è il vettore di direzione del raggio normale, n è l'indice di rifrazione. La struttura dell'incidenza contiene un punto, un vettore normale e un vettore di direzione.
Formule per il ravvicinamento Fersnel e la rifrazione vettore rispettivamente:
Si può vedere nel codice che uso un valore epsilon * direzione del raggio per evitare acne ombra causata dal galleggiante imprecisione. Qualcosa di simile sembra accadere alla piccola sfera, però. un'altra immagine:
Come si può vedere, la sfera non appare trasparente, ma lo fa ereditano il colore della sfera diffusa. Di solito ha anche alcuni pixel bianchi.
Senza rifrazione:
Che tipo di numeri sono coinvolti? È possibile che i tuoi valori stiano diventando troppo piccoli per essere rappresentati con precisione da 'float' e stanno andando a zero. Puoi/hai provato a usare 'double' invece? –
Sembra essere nell'intervallo 20-100 per i due valori di colore nelle prime iterazioni quando arriva in modalità debug alla fine della funzione getColor, e verrà quindi diviso per la distanza^2 dalla telecamera e saturato. – PEC
Lo stiamo pensando tutti. MORTE NERA –