Ray Tracing - Refraction Error

I am writing a ray tracer. So far I'm distracted, Blinn's coverage and thoughts. Something went wrong with my refractions, and I have no idea what. I hope someone can help me. enter image description here

I have a large red diffuse + Blinn sphere and a small refracting one with a refractive index of n = 1.5.

Little is simply contrived.

Relevant Code:

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; } 

The code is everywhere since this is homework, and I am not allowed to include additional headers, and I have to send it to one cpp file, so I had to separate each class before direct declaration, declaration and implementation in this single file. It makes me vomit, but I tried to keep it as clean as possible. There are tons of code, so I included only what, in my opinion, was the most related. ReflectiveSurface is the parent class of RefractiveSurface. N is the surface normal, V is the beam direction vector, this normal, n is the refractive index. The incidence structure has a point, a normal and a direction vector.

Formulas for the approximation of Fรถrsel and the refractive vector, respectively: enter image description here

In the code that I use, the epsilon * beam direction value can be seen to avoid shadow blackheads caused by float inaccuracies. However, something similar happens with a small sphere. Another screenshot: enter image description here

enter image description here

As you can see, the sphere does not look transparent, but inherits the color of the diffuse sphere. It also usually has a few white pixels.

Without refraction:

enter image description here

+6
source share
2 answers

The answer turned out to be quite simple, but it took me 3 days to look at the code to catch the error. I have a Surface class, I get two classes from it: RoughSurface (diffuse + blinn) and RelfectiveSurface. Then, RefractionSurace comes from RefleciveSurface. The ReflectiveSurface constructor accepts the refractive index (n) and the damping value (k) as parameters, but does not save them. (F0) is computed from them during construction, and then they are lost. RefractionSurface, on the other hand, uses (n) to calculate the angle of refraction.

Old constructor:

 RefractiveSurface::RefractiveSurface(float _n, const Color& _k) : ReflectiveSurface(Color(1, 1, 1) * _n, _k) {} 

New constructor:

 RefractiveSurface::RefractiveSurface(float _n, const Color& _k) : ReflectiveSurface(Color(1, 1, 1) * _n, _k), n(_n) {} 

As you can see, I forgot to save the value (n) for the RefractiveSurface in the constructor.

A small red sphere behind a large glass sphere illuminated on both sides of the camera:

enter image description here

It looks amazing on the move! D

Thanks for your time guys. Gotta finish this homework, then I rewrote it all and optimize it.

+1
source

RefractiveSurface::refractionDir accepts a normal N link (not const), and it can invert it. It seems dangerous. It is not clear that the caller wants him to be flipped, as he was used in the color calculations below.

In addition, refracted_color not always initialized (unless the color constructor makes it black).

Try to (temporarily) simplify and just see if the refracted rays go where you expect. Remove the Fresnel calculation and reflection components and simply set refracted_color to the result of the trace of the refracted ray. This will help determine if there is an error in the Fresnel calculation or in the geometry of the beam bend.

Debugging: color pixels that do not hit with anything other than black. This makes it easy to distinguish misses from shadows (surface acne).

+1
source

Source: https://habr.com/ru/post/977720/


All Articles