Reputation: 1
I'm following the steps in the book 'Ray Tracing in a weekend' and I'm having some problems with the section 11.3 Total internal reflection. When I try create the image I get this result:
This is the code for the intersection with the sphere, it returns an intersection with the sphere or null:
std::optional<Intersection> Sphere::intersect(const Ray& r, double tMin, double tMax) const {
vec o_c = this->center- r.origin();
auto a = r.direction().length_squared() ()
auto b = dot(r.direction(), o_c);
auto c = o_c.length_squared() - radius * radius;
auto d = b * b - a * c;
// at^2 + tb + c = 0 not real solution
if (d < 0) {
return std::nullopt;
}
// Verify root in [tMin, tMax]
double dSqrt = std::sqrt(d);
double root = (b - dSqrt) / a;
if (root < tMin || root > tMax) {
root = (b + dSqrt) / a;
if (root < tMin || root > tMax) return std::nullopt;
}
Intersection i;
i.t = root;
i.point = r(i.t);
i.normal = unit_vector(i.point - center);
i.material = material;
return i;
};
This is the code for the refraction:
inline vec refraction(const vec& v, const vec& normal, double refraction_index) {
vec rparal{ .0, .0, .0 };
vec rperp{ .0, .0, .0 };
bool front_face = (dot(v, normal) < 0);
double ri = front_face ? 1.0 / refraction_index : refraction_index;
vec outward_normal = front_face ? normal : -normal;
double cos_tita = fmin(dot(-v, outward_normal ), 1.0);
double sen_tita = sqrt(1 - cos_tita * cos_tita);
if (ri * sen_tita > 1) {
return reflect(v, outward_normal);
}
rperp = ri * (v + (dot(-v, outward_normal) * outward_normal));
rparal = (-sqrt(abs(1 - rperp.length_squared()))) * outward_normal;
return rparal + rperp;
};
And this is the code for the color_ray:
color color_ray(const Ray& r, int deep, const Geometry& g) {
if (deep <= 0)
return color(0, 0, 0);
auto i = g.intersect(r, 0.001, infinity);
if (i) {
color intensity;
// Check if the material is reflective
if (i->material->reflective) {
vec reflectedVector = reflect(unit_vector(r.direction()), i->normal) +
(i->material->coef_Reflective * vec::random_Unit_vector());
Ray reflected_Ray = Ray(i->point, reflectedVector);
intensity = i->material->DifuseColor * color_ray(reflected_Ray, deep - 1, g);
// Check if the material is refractive
} else if (i->material->refractive) {
vec refractedVector = refraction(unit_vector(r.direction()), i->normal,
i->material>refraction_index);
Ray refracted_Ray = Ray(i->point, refractedVector);
intensity = color_ray(refracted_Ray , deep - 1, g);
} else {
intensity = i->material->DifuseColor * color_ray(Ray(i->point, i->normal + vec::randomUnitVector()), deep - 1, g);
}
return intensity;
}
vec unit_direction = unit_vector(r.direction());
auto a = 0.5 * (unit_direction .y() + 1);
return (1.0 - a) * color(1.0, 1.0, 1.0) + a * color(0.5, 0.7, 1.0);
};
I should get the following image as a result:
Let me know if you need more information, any help is appreciated :)
Upvotes: 0
Views: 72
Reputation: 1
Well, I found the solution, the problem was in
rparal = (-sqrt(abs(1 - rperp.length_squared()))) * outward_normal;
I deleted the parenthesis and I changed 'abs' for 'fabs' and that solved the problem.
rparal = -sqrt(fabs(1 - rperp.length_squared())) * outward_normal;
Here is the new image generated: New image without problem
Upvotes: 0