X

Ray Sphere Intersection

To perform a ray-sphere intersection test we need:

  • A ray with a known point of origin \mathbf{o}, and direction vector \mathbf{d}.
  • a sphere with a known centre at a point \mathbf{c} and a known radius r

Contents

Mathematical Formulation

Given the above mentioned sphere, a point \mathbf{p} lies on the surface of the sphere if

(\mathbf{p} - \mathbf{c}) \cdot{(\mathbf{p} - \mathbf{c})} = r^2

Given a ray with a point of origin \mathbf{o}, and a direction vector \mathbf{d}:

ray(t) = \mathbf{o} + t\mathbf{d}, \; \; t \geq 0

we can find the t at which the ray intersects the sphere by setting ray(t) equal to \mathbf{p}

(\mathbf{o} + t\mathbf{d} - \mathbf{c})\cdot (\mathbf{o} + t\mathbf{d} - \mathbf{c}) = r^2

To solve for t we first expand the above into a more recognisable quadratic equation form

(\mathbf{d}\cdot\mathbf{d})t^2 + 2(\mathbf{o} - \mathbf{c})\cdot\mathbf{d}t +  (\mathbf{o} - \mathbf{c})\cdot (\mathbf{o} - \mathbf{c}) - r^2 = 0

or

At2 + Bt + C = 0

where

  • A = \mathbf{d}\cdot\mathbf{d}
  • B = 2(\mathbf{o} - \mathbf{c})\cdot\mathbf{d}
  • C = (\mathbf{o} - \mathbf{c})\cdot (\mathbf{o} - \mathbf{c}) - r^2

which can be solved using a standard quadratic formula.

Note that in the absence of positive, real, roots, the ray does not intersect the sphere.

Practical Simplification

In a renderer, we often differentiate between world space and object space. In the object space of a sphere it is centred at origin, meaning that if we first transform the ray from world space into object space, the mathematical solution presented above can be simplified significantly.

If a sphere is centred at origin, a point \mathbf{p} lies on a sphere of radius r2 if

\mathbf{p}\cdot \mathbf{p} = r^2

and we can find the t at which the (transformed) ray intersects the sphere by

(\mathbf{o} + t\mathbf{d})\cdot (\mathbf{o} + t\mathbf{d}) = r^2

According to the reasoning above, we expand the above quadratic equation into the general form

At2 + Bt + C = 0

which now has coefficients:

  • A = \mathbf{d}\cdot \mathbf{d}
  • B = 2(\mathbf{d}\cdot\mathbf{o})
  • C = \mathbf{o}\cdot \mathbf{o} - r^2

Solving the Quadratic Equation

There are two possible solutions to the quadratic equation:

t_0 = \frac{-B -\sqrt{B^2 - 4AC}}{2A}
t_1 = \frac{-B +\sqrt{B^2 - 4AC}}{2A}

Firstly, if the discriminant is negative, i.e. (B2 − 4AC) < 0, we know that there are no real roots, and consequently we also know that the ray has missed the sphere.


To avoid poor numeric precision when B \approx \sqrt{B^2 - 4AC} t0 and t1 can be rewritten:

t_0 = \frac{q}{A}
t_1 = \frac{C}{q}

where

q = \left \{\begin{matrix} \frac{-B + \sqrt{B^2 - 4AC}}{2} & : &\;B < 0 \\ \frac{-B - \sqrt{B^2 - 4AC}}{2} & : &\;otherwise\end{matrix}\right.

External Links

Example Code

The following C++ code snippet is an example how the simplified version of the ray/sphere intersection described above might be implemented. Note that it assumes the ray has already been transformed into object space, and be aware that the code below is not necessarily the most efficient implementation available!

bool SpherePrimitive::intersect(const Ray& ray, float* t)
{
    //Compute A, B and C coefficients
    float a = dot(ray.d, ray.d);
    float b = 2 * dot(ray.d, ray.o);
    float c = dot(ray.o, ray.o) - (r * r);

    //Find discriminant
    float disc = b * b - 4 * a * c;
    
    // if discriminant is negative there are no real roots, so return 
    // false as ray misses sphere
    if (disc < 0)
        return false;

    // compute q as described above
    float distSqrt = sqrtf(disc);
    float q;
    if (b < 0)
        q = (-b - distSqrt)/2.0;
    else
        q = (-b + distSqrt)/2.0;

    // compute t0 and t1
    float t0 = q / a;
    float t1 = c / q;

    // make sure t0 is smaller than t1
    if (t0 > t1)
    {
        // if t0 is bigger than t1 swap them around
        float temp = t0;
        t0 = t1;
        t1 = temp;
    }

    // if t1 is less than zero, the object is in the ray's negative direction
    // and consequently the ray misses the sphere
    if (t1 < 0)
        return false;

    // if t0 is less than zero, the intersection point is at t1
    if (t0 < 0)
    {
        t = t1;
        return true;
    }
    // else the intersection point is at t0
    else
    {
        t = t0;
        return true;
    }
}




The Society

The CGSociety is the most respected and accessible global organization for creative digital artists. The CGS supports artists at every level by offering a range of services to connect, inform, educate and promote digital artists worldwide

Contact | Privacy | Advertising | About CGS