光线追踪 - 折射bug

时间:2014-11-04 16:52:07

标签: c++ graphics raytracing

我正在写一个光线追踪器。到目前为止,我有漫反射,Blinn照明和反射。我的折射出了点问题,我不知道是什么。我希望有人可以帮助我。 enter image description here

我有一个大的红色漫反射+ 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

你可以在代码中看到我使用epsilon * ray方向值来避免浮动不精确引起的阴影痤疮。但是,类似的东西似乎正在发生在小球体上。 另一个截图: enter image description here

enter image description here

正如您所看到的,球体看起来并不透明,但它确实继承了漫反射球体的颜色。它通常也有一些白色像素。

没有折射:

enter image description here

2 个答案:

答案 0 :(得分:1)

RefractiveSurface::refractionDir采用正常N by(非常量)引用,它可能会将其反转。这似乎很危险。目前还不清楚调用者是否希望将I.normal翻转,因为它会用于进一步降低颜色计算。

此外,refracted_color并不总是初始化(除非Color构造函数使其变黑)。

尝试(暂时)简化并观察折射光线是否达到预期的位置。删除菲涅耳计算和反射分量,然后将refracted_color设置为折射光线轨迹的结果。这将有助于确定错误是在菲涅耳计算中还是弯曲射线的几何形状。

调试提示:为不使用黑色以外的任何东西打击的像素着色。这样可以很容易地将未命中与阴影(表面痤疮)区分开来。

答案 1 :(得分:1)

答案结果非常简单,但是我花了3天的时间盯着代码来捕捉错误。我有一个Surface类,我从它派生出两个类:RoughSurface(diffuse + blinn)和RelfectiveSurface。然后,RefractiveSurace派生自RefleciveSurface。 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)值。

从相机两侧照亮的大玻璃球后面的小红球:

enter image description here

它在运动中看起来很棒!D

谢谢你的时间,伙计们。要完成这个作业,然后我会重写整个事情并优化它的地狱。