In this blog post I will show you how to ray trace a torus. I will assume that you already know how to ray trace simple shapes like spheres and cubes. I will also assume some basic familiarity with shading and ray tracing in general.
Obtaining torus equation
Before we start I must introduce some terminology. I will use to denote torus major radius (the distance from the center of the tube to the center of the torus), and to denote torus minor radius (the radius of the tube).
Let us consider torus centered at point with radiuses and . Torus can be defined as a set of points for which certain function returns zero:
Our task will be to find a suitable definition of function that properly describes torus .
We will start by looking at the intersection of torus with plane: Every point on the circumference of the right circle satisfies equation:
Now imagine that we are taking some point on the circumference and we are rotating it around axis. This way point becomes a set of points in 3D space:
Torus can be obtained by rotating all points on the circumference of the circle. In other words points on the surface of a torus satisfy equations:
This equations can be simplified by removal of variable into:
And this is exactly what we were looking for, a suitable definition for our function . After a bit of renaming (, ) we can write our final equation:
Solving torus equation
Given ray definition:
where is the ray origin (starting point) and is a unit vector () that represents the ray direction, we will try to find all positive () solutions to the equation:
Notice that for a particular ray this equation can have 0, 1, 2, 3 or 4 solutions:
We will start by substituting variables by point components in the formula of function :
And then we expand them to their full definition:
After long and tedious calculations and a lot of grouping and simplifications we finally get:
Since our equation is just a polynomial of 4th degree, we may use one of the standard algorithms to solve it. In my demo application I used algorithm from Graphic Gems book, freely available at GitHub. But you are free to use any other algorithm. In particular Numerical Recipes in C book is a good source of numerical algorithms.
Roots3And4.c file from Graphic Gems (called
in my demo app) is sparsely
documented. If you want to know how finding roots of 4th
degree polynomial actually works please
read section from Wikipedia about
but use second definition of the resolvent cubic described in this Wikipedia article.
With a bit of effort you should be able to follow and understand source
code of the solver then.
Currently we can only render tori centered at point and laying on plane. To obtain tori located at arbitrary points and/or in arbitrary positions, we must apply matrix transformations to the ray just before computing intersections with the torus surface. For example from the viewer point of view the results of the following operations are the same: translating ray by vector , translating torus by vector . In my demo app this transformation is done in
RayTracer.js#rotationEndmethod. For more details please see Ray Tracing from the Ground Up book.
Due to limited accuracy of the floating point computations artifacts may be seen when we use huge numerical values for torus radiuses. For the best results we should keep . If you need huge tori in your scenes please use ray transformation technique described in point (1) to scale small tori as needed.
From performance point of view rendering a torus by solving its equation is slow. Rendering may be speed up considerably if we manage to avoid solving the equation altogether e.g. by using triangle meshes.
As a part of preparations to write this post I created a simple demo app that ray traces a torus:
Source code can be downloaded from this GitHub repository.
npm install command may take a while to finish, so please be patient.
Also notice that you have to had both
on you local machine to make this work.
You can install them by executing: