Question

So in my ray tracer that I'm building I've gotten refraction to work for spheres along with caustic effects, however the glass spheres don't look particularly good. I believe the refracted math is correct because the light appears to be bending in inverting the way you'd expect it to however it doesn't look like glass, it just looks like paper or something.

I've read that total internal reflection is responsible for much of what makes glass look like it does, however when I tested to see if any of my refracted rays go above the critical angle, none of them do, so my glass sphere has no total internal reflection. I'm not sure if this is normal or if I've done something wrong. I've posted my refraction code below so if anyone has any suggestions I'd love to hear them.

/*
 * Parameter 'dir' lets you know whether the ray is starting
 * from outside the sphere going in (0) or from in the sphere
 * going back out (1).
 */
void Ray::Refract(Intersection *hit, int dir)
{

    float n1, n2;
    if(dir == 0){ n1 = 1.0; n2 = hit->mat->GetRefract(); }
    if(dir == 1){ n1 = hit->mat->GetRefract(); n2 = 1.0; }

    STVector3 N = hit->normal/hit->normal.Length();
    if(dir == 1) N = -N;
    STVector3 V = D/D.Length();
    double c1 = -STVector3::Dot(N, V);
    double n = n1/n2;

    double c2 = sqrt(1.0f - (n*n)*(1.0f - (c1*c1))); 

    STVector3 Rr = (n * V) + (n * c1 - c2) * N;

    /*These are the parameters of the current ray being updated*/
    E = hit->point;  //Starting point
    D = Rr;          //Direction
}

This method is called during my main ray-tracing method RayTrace() which runs recursively. Here's a small section of it below that is in charge of refraction:

    if (hit->mat->IsRefractive())
    {    
        temp.Refract(hit, dir); //Temp is my ray that is being refracted
        dir++;
        result += RayTrace(temp, dir); //Result is the return RGB value.
    } 
Was it helpful?

Solution

You're right, you'll never get total internal reflection in a sphere (seen from the outside). That's because of symmetry: a ray inside a sphere will hit the surface at the same angle at both ends, meaning that, if it exceeds the critical angle at one end, it would have to exceed it at the other one as well (and so would not have been able to enter the sphere from the outside in the first place).

However, you'll still get a lot of partial reflection according to Fresnel's law. It doesn't look like your code accounts for that, which is probably why your glass looks fake. Try including that and see if it helps.

(Yes, it means that your rays will split in two whenever they hit a refractive surface. That happens in reality, so you'll just have to live with it. You can either trace both paths, or, if you're using a randomized ray tracing algorithm anyway, just sample one of them randomly with the appropriate weights.)

Ps. If you don't want to deal with stuff like light polarization, you may want to just use Schlick's approximation to the Fresnel equations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top