2014-11-04 88 views
6

我在寫射線追蹤器。到目前爲止,我有漫反射,布林照明和反射。我的折射出現問題,我不知道是什麼。我希望有人能幫助我。 enter image description here射線追蹤 - 折射錯誤

我有一個很大的紅色diffuse + Blinn球體和一個折射率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是折射率。發生結構包含一個點,一個法線和一個方向向量。

公式爲Fersnel近似和分別折射向量: enter image description here

可以在我使用的ε*射線方向上的值,以避免由浮子不精確陰影粉刺代碼中看到。不過,類似的事情似乎也發生在小球體上。 另一張截圖: ​​

enter image description here

正如你所看到的,球沒有出現透明的,但它確實繼承漫球體的顏色。它通常也有一些白色像素。

無折射:

enter image description here

+0

涉及什麼樣的數字?有可能你的數值變得太小,無法用「float」來準確表示,並且將變爲零。你可以/你嘗試過使用'double'嗎? – 2014-11-04 16:56:37

+0

在開始的幾次迭代中,當它在getColor函數的末尾以調試模式到達時,似乎處於20-100範圍內,然後將與攝像機的距離^ 2相除,飽和。 – PEC 2014-11-04 17:05:52

+0

我們都在想。死星 – 2014-11-05 17:58:02

回答

1

答案結果非常簡單,但我花了3天的時間盯着代碼來捕捉錯誤。我有一個Surface類,我從它派生了兩個類:RoughSurface(diffuse + blinn)和RelfectiveSurface。然後,RefractiveSurace來自RefleciveSurface。 ReflectiveSurface的構造函數以折射率(n)和消光值(k)爲參數,但不存儲它們。(F0)在施工期間由它們計算,然後它們丟失。另一方面,折射表面在折射角計算中使用(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)的值。從背後攝像頭的兩邊點燃大玻璃球

紅色的小球:

enter image description here

它看起來運動d

謝謝您的時間,你們真棒!要完成這個作業,然後我會重寫整個事情並優化它。

1

RefractiveSurface::refractionDir取正常N通過(非const)參考,並且它可以倒轉。這看起來很危險。目前尚不清楚調用者是否需要翻轉正常值,因爲它用於進一步降低顏色計算。

此外,refracted_color並不總是初始化(除非Color構造函數使其變爲黑色)。

嘗試(暫時)簡化,看看折射光線是否達到您的預期。除去菲涅耳計算和反射分量,只需設置refracted_color即可得到折射光線的結果。這將有助於確定錯誤是在菲涅耳計算中還是在彎曲射線的幾何中。

一個調試提示:使用除黑色以外的其他東西不使用任何東西的像素着色。這可以很容易地區分陰影(表面痤瘡)的缺失。