Hello! Welcome back to your ray tracing journey.
In the last lesson, we made our renderer much more robust by adding a recursion depth limit. This prevents infinite bounces and gives us control over the trade-off between performance and image quality. Our ray tracer can now simulate complex light paths without crashing.
So far, our only material simulates diffuse (or matte) surfaces. Now, we'll add the ability to render shiny, mirror-like objects. To do that, we need to calculate precisely how a ray of light reflects off a surface. This lesson is dedicated to the vector mathematics behind this phenomenon.
Our learning outcome is to derive the reflection formula for a vector about a normal. This is a fundamental concept in computer graphics, and your strong background in linear algebra will be a great asset here.
1. The Core Idea: Decomposing the Incident Vector
Imagine a light ray with direction vector v hitting a surface with a normal vector n. We want to find the direction of the reflected ray, which we'll call r.

This diagram illustrates the core problem: given an incoming vector v (labeled e-hat) and a surface normal n, we need to find the reflected vector r.
The key to solving this is to break down the incoming vector v into two separate components:
- A component that is parallel to the normal n.
- A component that is perpendicular to the normal n.
Your experience with vector projections will be very useful here. This decomposition is a powerful technique used throughout physics and graphics.
Vector reflection at a surface
The article 'Vector reflection at a surface' provides an excellent refresher on using the dot product to decompose a vector. This will be the foundation for our derivation.
Please read the 'Prerequisites' and 'DotProduct' sections. Focus on how a vector b is split into b∥ (parallel to a) and b⊥ (perpendicular to a). Notice the formula for each component.
As the article explains, if n is a unit vector, we can decompose our incoming vector v as follows:
- The component of v parallel to n is: v∥ = (v ⋅ n) n
- The component of v perpendicular to n is: v⊥ = v - v∥
Therefore, any vector v can be written as the sum of its parallel and perpendicular parts relative to n:
2. Deriving the Reflection Formula
Now, let's think about what happens during a perfect reflection.
- The part of the motion that is parallel to the surface (v⊥) is unaffected. The ray continues along the surface with the same "sideways" motion.
- The part of the motion that is perpendicular to the surface (v∥) gets inverted. The ray was going "in", and now it's going "out".
So, the reflected vector r can be constructed by keeping the perpendicular component and flipping the sign of the parallel component:
Geometric construction of the reflection vector. You can see that r is formed by adding -v∥ to v⊥.
This gives us a clear geometric picture. Now, let's substitute the formulas for our components back in to get a single equation for r in terms of v and n.
We start with:
We know that v⊥ = v - v∥, so we can substitute that in:
Finally, we substitute the formula for the parallel component, v∥ = (v ⋅ n) n:
This is it! This is the reflection formula we will use in our ray tracer. It elegantly captures the physics of reflection using basic vector operations. Note that this formula assumes n is a unit vector, which is standard practice for normals.
3. Visualizing the Derivation
Reading a derivation is one thing; seeing it animated helps build a stronger intuition. The following videos walk through the same logic, though sometimes with slightly different conventions or intermediate steps. Watching them will help generalize your understanding.
First, let's watch a clear, visual derivation that uses vector projections.
Math for Game Developers - Vector Reflections
The video 'Math for Game Developers - Vector Reflections' by Jorge Rodriguez provides a great step-by-step visual construction of the reflected vector.
Watch from 07:19 to 10:57. The presenter derives the formula by projecting the incident vector onto the normal and then using vector subtraction. Notice that his final formula, V - 2*Vp, is conceptually identical to our v - 2*v_parallel.
A Quick Note on Vector Conventions
You may have noticed that different resources draw the incident vector differently.
- In ray tracing, the incoming ray vector v typically points towards the surface.
- In some physics or game-dev contexts, the vector v points away from the point of impact.
This choice affects the sign of the dot product (v ⋅ n) and can lead to slightly different-looking, but equivalent, formulas. The next video is particularly helpful because it explicitly addresses this difference.
The video 'The Reflection Vector' by Mike, the Mathematician, offers another derivation and then clearly explains the difference between the 'mathematical' and 'physical' reflection conventions.
Watch from 02:30 to 05:16. First, he derives a formula, and then he explains how to adapt it for the 'physical' case used in graphics, where the incident ray comes 'in'. This distinction is crucial for correctly interpreting formulas from different sources.
For our ray tracer, we will stick to the convention where the ray direction v points into the surface, and the normal n points out. Therefore, our formula remains:
Test your understanding!
Let's use a 2D example. A ray is traveling down and to the right, with direction vector v = (0.707, -0.707). It hits a flat horizontal surface whose normal is n = (0, 1). What is the reflected vector r?
Show answer
-
Calculate the dot product:
v ⋅ n = (0.707)(0) + (-0.707)(1) = -0.707 -
Plug into the formula:
r = v - 2(v ⋅ n) n
r = (0.707, -0.707) - 2(-0.707) * (0, 1)
r = (0.707, -0.707) - (-1.414) * (0, 1)
r = (0.707, -0.707) + (0, 1.414)
r = (0.707, 0.707)
The reflected vector points up and to the right. The x-component is unchanged, and the y-component is inverted, which is exactly what we expect for a reflection off a horizontal surface.
Conclusion
In this lesson, we went back to the mathematical foundations to understand specular reflection. You've seen how a few simple vector operations—the dot product, vector scaling, and vector subtraction—can be combined to produce a physically accurate reflection.
Key Takeaways:
- The reflection of a vector v about a normal n can be found by decomposing v into its parallel (v∥) and perpendicular (v⊥) components relative to n.
- The reflection flips the parallel component while preserving the perpendicular component: r = v⊥ - v∥.
- This simplifies to the final, computationally efficient reflection formula: r = v - 2(v ⋅ n) n.
- This formula relies on n being a unit vector and assumes the convention where v points toward the surface.
Next Steps
With this formula derived and understood, we are now ready to implement it. In the next lesson, we will create a new metal material class in C++. We will add a reflect function that implements this formula and use it within the material's scatter method to create beautiful, shiny surfaces in our scenes.