static inline t_color recursive_tracer(t_params p, t_ray *ray, t_objects *sp) { t_f64 inside; t_f64 facingratio; t_f64 fresneleffect; t_vec3f refldir; t_vec3f refdir; t_color reflection; t_color refrac; t_ray rx; if ((inside = dot_vec3f(&ray->dir, &p.nhit) > 0)) p.nhit = scale_vec3f(&p.nhit, -1); facingratio = -dot_vec3f(&ray->dir, &p.nhit); fresneleffect = mix(pow(1 - facingratio, 3), 1, .1); refldir = get_reflection_dir(&p.nhit, &ray->dir); rx = reflected_ray(ray, &refldir, &p.nhit, &p.phit); reflection = trace_ray(&rx, sp, ++p.depth); if (p.sphere->transparency > 0) { refdir = compute_ideal_refractions(ray, inside, p); rx = refracted_ray(ray, &refdir, &p.nhit, &p.phit); refrac = trace_ray(&rx, sp, ++p.depth); } return (defualt_glossy_shading(&reflection, &refrac, fresneleffect, p.sphere)); }
std::tuple<bool, double, Ray> a4_refract(const Point3D& hit, const Vector3D& direction, const Vector3D& n, double ni) { Ray refracted_ray(Point3D(0.0, 0.0, 0.0), Vector3D(0.0, 0.0, 0.0)); double R = 1.0; Vector3D normal = n; double cosI = direction.dot(normal); double n1, n2; if(cosI > 0) { // direction and normal are in the same direction so ray originates from inside primitive n1 = ni; n2 = 1.0; normal = -normal; } else { // Ray enters primitive from outside n1 = 1.0; n2 = ni; cosI = -cosI; } // Check for total internal reflection double nr = n1 / n2; double cosT = 1.0 - (nr * nr) * (1.0 - (cosI * cosI)); if(cosT >= 0) { cosT = sqrt(cosT); // Compute Fresnel coefficient double a = (n1 * cosI - n2 * cosT) / (n1 * cosI + n2 * cosT); double b = (n2 * cosI - n1 * cosT) / (n2 * cosI + n1 * cosT); R = ((a * a) + (b * b)) * 0.5; // Cast the refracted ray refracted_ray = Ray(hit - (1e-9) * normal, nr * direction + (nr * cosI - cosT) * normal); } return std::tuple<bool, double, Ray>(cosT < 0, R, refracted_ray); }