Ray Tracing 005Adding a Sphere

Summary

  • Math foundations: sphere equation, vector dot-product, and solving intersection with a ray.
  • Added a function that returns whether the ray hit the sphere.
  • Added a function that returns the color red if the sphere was hit, and the blue-white background gradient otherwise.

The last chapter introduced a ray class. Now it's time to let the ray hit something: a sphere.

Note

The following math is probably much more verbose than it needs to be. I added these step-by-step details in case I need a refresher, and also to practice math typesetting at the same time. In future chapters I'll probably provide details for math I found particularly important and/or difficult to follow.

The equation of a sphere centered at the origin is (1)

x2+y2+z2=R2\begin{equation} x^2 + y^2 + z^2 = R^2 \end{equation}

which is essentially derived from Pythagoras' Theorem extended to three dimensions. (2)

For any (x,y,z)(x,y,z), if x2+y2+z2=R2x^2 + y^2 + z^2 = R^2, then (x,y,z)(x,y,z) is on the sphere, otherwise it's not.

The more general equation of a sphere centered at a point (x0,y0,z0)(x_0,y_0,z_0) is

(xβˆ’x0)2+(yβˆ’y0)2+(zβˆ’z0)2=R2\begin{equation} (x-x_0)^2 + (y-y_0)^2 + (z-z_0)^2 = R^2 \end{equation}

This can also be expressed as a dot-product:

(xyz)βˆ’(x0y0z0)=(xβˆ’x0yβˆ’y0zβˆ’z0)\begin{equation} \begin{pmatrix} x \\ y \\ z \end{pmatrix} - \begin{pmatrix} x_0 \\ y_0 \\ z_0 \end{pmatrix} = \begin{pmatrix} x-x_0 \\ y-y_0 \\ z-z_0 \end{pmatrix} \end{equation}
(xβˆ’x0yβˆ’y0zβˆ’z0)β‹…(xβˆ’x0yβˆ’y0zβˆ’z0)=(xβˆ’x0)2+(yβˆ’y0)2+(zβˆ’z0)2=R2\begin{equation} \begin{pmatrix} x-x_0 \\ y-y_0 \\ z-z_0 \end{pmatrix} \cdot \begin{pmatrix} x-x_0 \\ y-y_0 \\ z-z_0 \end{pmatrix} = (x-x_0)^2 + (y-y_0)^2 + (z-z_0)^2 = R^2 \end{equation}

For center C=(x0,y0,z0)C = (x_0,y_0,z_0) and a point P=(x,y,z)P = (x,y,z), we can also write:

(Pβˆ’C)β‹…(Pβˆ’C)=R2\begin{equation} \begin{pmatrix} P - C \end{pmatrix} \cdot \begin{pmatrix} P - C \end{pmatrix} = R^2 \end{equation}

The ray p(t)=A+tβˆ—Bp(t) = A + t*B intersects the sphere where p(t)=Pp(t) = P.

If the ray hits the sphere, there is a tt for which p(t)p(t) satisfies the sphere equation.

(p(t)βˆ’C)β‹…(p(t)βˆ’C)=R2\begin{equation} \begin{pmatrix} p(t) - C \end{pmatrix} \cdot \begin{pmatrix} p(t) - C \end{pmatrix} = R^2 \end{equation}
(A+tβˆ—Bβˆ’C)β‹…(A+tβˆ—Bβˆ’C)=R2\begin{equation} \begin{pmatrix} A + t*B - C \end{pmatrix} \cdot \begin{pmatrix} A + t*B - C \end{pmatrix} = R^2 \end{equation}

I'm looking for t, and A, B, C and R are constants. I can rearrange the equation as follows:

(tβˆ—B+(Aβˆ’C))β‹…(tβˆ—B+(Aβˆ’C))=R2\begin{equation} \begin{pmatrix} t*B + (A-C) \end{pmatrix} \cdot \begin{pmatrix} t*B + (A-C) \end{pmatrix} = R^2 \end{equation}

Let oc=(Aβˆ’C)oc = (A-C) and rearrange:

t2βˆ—(Bβ‹…B)+2βˆ—tβˆ—(Bβ‹…oc)+(ocβ‹…oc)=R2\begin{equation} t^2 * (B \cdot B) + 2 * t* (B \cdot oc) + (oc \cdot oc) = R^2 \end{equation}

Now let a=(BcdotB)a = (B cdot B) and rearrange:

aβˆ—t2+2βˆ—tβˆ—(Bβ‹…oc)+ocβ‹…ocβˆ’R2=0\begin{equation} a * t^2 + 2 * t * (B \cdot oc) + oc \cdot oc - R^2 = 0 \end{equation}

Let b=2βˆ—(Bβ‹…oc)b = 2 * (B \cdot oc):

aβˆ—t2+bβˆ—t+ocβ‹…ocβˆ’R2=0\begin{equation} a * t^2 + b * t + oc \cdot oc - R^2 = 0 \end{equation}

Then, let c=(occdotoc)βˆ’R2c = (oc cdot oc) - R^2 to arrive at the normal form:

aβˆ—t2+bβˆ—t+c=0\begin{equation} a * t^2 + b * t + c = 0 \end{equation}

This is a quadratic equation that can be solved for $t$ with the Quadratic Formula:

t=βˆ’bΒ±b2βˆ’4ac2a\begin{equation} t = \frac{-b \pm \sqrt{b^2 - 4ac} }{2a} \end{equation}

The square root portion of this equation can either be positive (meaning there are two real solutions), or zero (meaning there's one real solution), or negative (meaning there are no real solutions).

This relates directly to the geometry. If there are two real solutions, the ray intersects the squere at two points. If there's exactly one real solution, it touches the sphere at one point on the surface. If there are no real solutions, then the ray doesn't touch the sphere at all.

image/svg+xml

The new function hit_sphere() implements the math derived in this chapter. The only difference is that I only care about the root and whether it's greater than 0. I don't need a precise solution here. All rays that miss the sphere will result in the background gradient of the previous chapter.

The sphere is located in the center of the screen with a radius of 0.5. If the ray intersects this sphere, the color function will just return the color red for now.

Click to view C++ source code

Javascript and Canvas

Here's the example in Javascript.

Loading...

Figure RT005: Simple canvas image rendered with Javascript

Click to view Javascript source code

Links