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

∣∣C−P∣∣∞=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)

∣∣C−R(t)∣∣∞=r∣∣C−Q+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

∣∣C−Q+tD∣∣∞=max⁡{∣Cx−Qx+tDx∣,∣Cy−Qy+tDy∣,∣Cz−Qz+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

∣Cx−Qx+tDx∣=rCx−Qx+tDx=±rt=(Qx−Cx±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 t∗t^* 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