我正在编写一个光线追踪器。到目前为止,我已经实现了漫反射、Blinn光照和反射。但是我的折射出了问题,我不知道怎么回事。希望有人能帮助我。
![enter image description here](https://istack.dev59.com/IThu9.webp)
我有一个大的红色漫反射+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](https://istack.dev59.com/xqnfc.webp)
![enter image description here](https://istack.dev59.com/gQLaN.webp)
无折射时的效果:
![enter image description here](https://istack.dev59.com/GRyO1.webp)