Utils
random_on_hemisphere
We first generate a random unit vector
.1
vec3 on_unit_sphere = random_unit_vector();
Using the normal vector
,1 we just see if the dot product
1 is positive or not.
If it it positive, then this is the vector on correct hemisphere
, otherwise it is on the wrong one.
if (dot(on_unit_sphere, normal) > 0.0)
return on_unit_sphere;
else
return -on_unit_sphere;
Full function
.2
inline vec3 random_on_hemisphere(const vec3& normal) {
vec3 on_unit_sphere = random_unit_vector();
if (dot(on_unit_sphere, normal) > 0.0) // In the same hemisphere as the normal
return on_unit_sphere;
else
return -on_unit_sphere;
}
vec3 reflect(const vec3&, const vec&)
inline vec3 reflect(const vec3& v, const vec3& n) {
double d_mag = dot(v, unit_vector(n));
vec3 d = unit_vector(n) * d_mag;
vec3 b = -d;
return v + 2 * b;
}
vec3 refract(const vec3&,const vec3&, double)
According to snell's law
Where \(\theta\) and \(\theta^\prime\) are angles of incident ray
3 and refracted ray
3 against the normal vector
.1
And \(\eta\) and \(\eta^\prime\) are refractive indices of incident ray
3 and refracted ray
.3
If \(R^\prime\) is the refracted ray
3 then we can break it into components which are parallel or perpendicular to the normal vector
.1
Also notice
From the dot product
1
Since our \(\vec R\) and \(\vec n\) are unit vectors
.1
Therefore,
To find \(- \vec R \cdot \vec n\), we have
auto cos_theta = std::fmin(dot(-uv, n), 1.0);
And to solve rest, we have
vec3 r_out_perp = etai_over_etat * (uv + cos_theta*n);
Now for \(\vec R_\parallel\) we can use Pythagorus theorem
.
and for the direction, we have \(- \vec n\).
This is given by
vec3 r_out_parallel = -std::sqrt(std::fabs(1.0 - r_out_perp.length_squared())) * n;
Hence we have
inline vec3 refract(const vec3& uv, const vec3& n, double etai_over_etat) {
auto cos_theta = std::fmin(dot(-uv, n), 1.0);
vec3 r_out_perp = etai_over_etat * (uv + cos_theta*n);
vec3 r_out_parallel = -std::sqrt(std::fabs(1.0 - r_out_perp.length_squared())) * n;
return r_out_perp + r_out_parallel;
}