How to build a ray-traced voxel engine

2025-08-31

Note: This blog post is still a work in progress. Right now it's mostly ramblings of a madman, I'm still trying to organizing my thoughts about this.

All uppercase bolded variables are vectors in R3R^3.

Drawing

Let R(t)=Q+tD\mathbf{R}(t) = \mathbf{Q} + t\mathbf{D} be a ray originating at Q\mathbf{Q}, in the direction of D\mathbf{D}. We can describe a cube of radius rr centered at C\mathbf{C} with the equation

CP=r||\mathbf{C} - \mathbf{P}||_\infty = r

With P\mathbf{P} a vector in R3R^3. To be more specific: P\mathbf{P} is a point on the square if it satisfies the above equation for the given C\mathbf{C} and rr.

If we want to know if (and where) a ray R(t)\mathbf{R}(t) intersects a given cube. We can substitute P\mathbf{P} in for R(t)\mathbf{R}(t)

CR(t)=rCQ+tD=r\begin{align*} ||\mathbf{C} - \mathbf{R}(t)||_\infty &= r \\ ||\mathbf{C} - \mathbf{Q} + t\mathbf{D}||_\infty &= r \\ \end{align*}

But now by definition of the infinity norm, we can write

CQ+tD=max{CxQx+tDx,CyQy+tDy,CzQz+tDz}=r\begin{align*} ||\mathbf{C} - \mathbf{Q} + t\mathbf{D}||_\infty = \max\{&|C_x - Q_x + tD_x|,\\ &|C_y - Q_y + tD_y|,\\ &|C_z - Q_z + tD_z|\} = r \end{align*}

Here, since we're looking for a tt that will satisfy this equation, we can solve for it element-wise. That is, we can look at the expression for xx

CxQx+tDx=rCxQx+tDx=±rt=(QxCx±r)/Dx\begin{align*} |C_x - Q_x + tD_x| &= r \\ C_x - Q_x + tD_x &= \pm r \\ t &= (Q_x - C_x \pm r) / D_x \end{align*}

This gives us two values for tt which we can then plug back into the three expressions above. If either value tt^* is a maximum, then R(t)\mathbf{R}(t^*) a point on the square. We do this same process for the yy and zz expressions, finding six separate values for tt, and expecting zero, one, or two solutions.

See also