[英]Ray tracing - refraction bug
我正在編寫光線追蹤器。 到目前為止,我有漫反射,布林照明和反射。 我的折射出現了問題,我也不知道該怎么辦。 我希望有人能幫助我。
我有一個大的紅色漫反射+布林球,還有一個折射率n = 1.5的小折射球。
小家伙真的搞砸了。
相關代碼:
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;
}
代碼無處不在,因為這是一項家庭作業,並且不允許我包含其他標頭,並且我必須將其發送到一個cpp文件中,因此我不得不將每個類都分離為正向聲明,聲明和實現。那一個文件。 它使我嘔吐,但我嘗試保持其清潔。 有大量的代碼,所以我只包括了我認為最相關的內容。 ReflectiveSurface是RefractiveSurface的父類。 N是表面法線,V是此法線的射線方向矢量,n是折射率。 入射結構包含一個點,一個法線和一個方向向量。
菲涅耳近似和折射矢量的公式分別為:
您可以在代碼中看到,我使用epsilon *射線方向值來避免由浮動不精確引起的陰影痤瘡。 不過,小領域似乎正在發生類似的情況。 另一個屏幕截圖:
如您所見,該球體看起來不是透明的,但它確實繼承了擴散球體的顏色。 通常也有一些白色像素。
無折射:
RefractiveSurface::refractionDir
通過(非常量)引用獲取正常N
,並且可以將其反轉。 這似乎很危險。 尚不清楚調用者是否希望翻轉I.normal,因為它被用於顏色計算的下層。
另外, refracted_color
並不總是初始化的(除非Color構造函數將其設為黑色)。
嘗試(暫時)簡化,然后看看折射的光線是否擊中了您期望的位置。 刪除菲涅耳計算和反射分量,然后將refracted_color
設置為折射光線的跟蹤結果。 這將有助於確定該錯誤是在菲涅耳計算中還是在彎曲射線的幾何中。
調試提示:用黑色以外的顏色給不會擊中像素的像素着色。 這樣可以很容易地將陰影和陰影(表面痤瘡)區別開來。
答案很簡單,但是花了我三天的時間盯着代碼才能發現錯誤。 我有一個Surface類,我從中派生了兩個類:RoughSurface(diffuse + blinn)和RelfectiveSurface。 然后,從RefleciveSurface派生RefractiveSurace。 ReflectiveSurface的構造函數將折光率(n)和消光值(k)作為參數,但不存儲它們。 (F0)是在構造過程中根據它們計算得出的,然后會丟失。 另一方面,RefractiveSurface在折射角計算中使用(n)。
舊構造函數:
RefractiveSurface::RefractiveSurface(float _n, const Color& _k) :
ReflectiveSurface(Color(1, 1, 1) * _n, _k) {}
新構造函數:
RefractiveSurface::RefractiveSurface(float _n, const Color& _k) :
ReflectiveSurface(Color(1, 1, 1) * _n, _k), n(_n) {}
如您所見,我忘記將RefractiveSurface的(n)值保存在構造函數中。
大玻璃球后面的紅色小球從相機的兩側照亮:
看起來很棒!D
伙計們,謝謝您的時間。 要完成這項作業,然后我將重寫整個內容並優化其中的內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.