簡體   English   中英

光線追蹤-折射錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM