我正在写一个光线追踪器。到目前为止,我有漫射、Blinn 照明和反射。我的折射出了点问题,我不知道是什么。我希望有人能帮助我。
我有一个大的红色漫反射球 + 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是这条法线的光线方向 vector ,n是折射率。关联结构包含一个点、一个法线和一个方向 vector 。
Fersnel 近似和折射 vector 的公式分别为:
你可以在代码中看到,我使用了一个 epsilon * 射线方向值来避免由 float 不精确引起的阴影痤疮。不过,小球体似乎也发生了类似的事情。 另一个截图:
如您所见,球体看起来并不透明,但它确实继承了漫反射球体的颜色。它通常也有一些白色像素。
没有折射:
最佳答案
RefractiveSurface::refractionDir
通过(非常量)引用获取正常的 N
,并且它可能会反转它。这看起来很危险。不清楚调用者是否希望翻转 I.normal,因为它用于进一步向下的颜色计算。
此外,refracted_color
并不总是被初始化(除非 Color 构造函数将其设为黑色)。
尝试(暂时)简化并查看折射光线是否到达您预期的位置。移除菲涅耳计算和反射分量,并将 refracted_color
设置为折射光线的追踪结果。这将有助于确定错误是在菲涅尔计算中还是在弯曲光线的几何结构中。
调试提示:用黑色以外的其他颜色为没有碰到任何东西的像素着色。这样可以轻松区分未命中和阴影(表面粉刺)。
关于c++ - 光线追踪 - 折射错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26740643/