Hello! Welcome back.
In our last lesson, we explored the physics of refraction, establishing that Snell's Law () governs how the angle of a light ray changes when it crosses a boundary. This gave us the "what" and "why" of refraction.
Today, we move from the abstract law to concrete geometry. Our goal is to derive the formula for a refracted ray vector. Your ray tracer needs to compute a new 3D direction vector, not just an angle. A key engineering constraint in graphics is to do this efficiently. We'll leverage your linear algebra skills to construct a formula that relies only on vector operations like dot products, avoiding slow trigonometric functions like asin() or acos().
1. The Goal: From Angles to Vectors
Snell's Law gives us a relationship between angles, but our C++ code needs a direction vector (for transmitted/refracted ray) given an incident vector and a surface normal .
The core idea is to decompose the output vector into components that we can calculate. A common technique in vector geometry, which you've likely used in graphics and physics, is to break a vector down into components parallel and perpendicular to a known vector. In our case, the surface normal is the perfect reference.
Let's decompose into two orthogonal vectors:
- A component parallel to the normal .
- A component perpendicular to the normal (i.e., tangent to the surface).

As the diagram shows, we can write as:
Our task is to find expressions for and using our known quantities: , , , and . For this derivation, we will assume all vectors (, , ) are of unit length.
2. Deriving the Vector Formula
Let's tackle each component, and , one by one. The Scratchapixel article provides a fantastic, detailed walkthrough of this derivation. We'll summarize the key steps here.
Introduction to Shading (Reflection, Refraction and Fresnel)
This article provides an excellent, step-by-step geometric derivation of the refracted vector. We will follow its logic closely.
Please read the 'Refraction' section, starting from the heading 'Although how does it work in 3D space?' down to the final equation for T. Focus on how the vector T is decomposed and how Snell's law and trigonometric identities are used to arrive at the final vector form.
Let's walk through the derivation's logic:
Step 1: Expressing the Components with Trigonometry
From the diagram and basic trigonometry:
- The component is parallel to the normal but points inward. Its length is . So, .
- The component is perpendicular to the normal. Its length is . We need to find its direction.
Notice that the incident ray , the normal , and the refracted ray all lie in the same plane (the "plane of incidence"). This means must be in the same direction as the component of that is perpendicular to .
We can find this direction vector, let's call it , by taking and adding the part of it that is parallel to . The dot product gives us . So, the vector parallel to is .
Therefore, the tangential part is . This vector has length . To get a unit vector , we divide by its length:
Now we can write :
Step 2: Substituting and Simplifying with Snell's Law
Now we combine and and substitute what we know:
This looks complicated, but we can simplify it using Snell's Law: . Let's define the ratio .
Rearranging terms gives a common form of the equation:
Step 3: Eliminating Trigonometry
This is great, but it still contains and . We want to replace them with dot products.
-
is simple. Since and are unit vectors, . Note: To make sure the angle is acute, we often use if points towards the surface. We'll handle this detail in the implementation. For now, let's just use .
-
is trickier. We use the identity , so .
From Snell's law, we have .
We also know .
Putting it all together:
Substituting this back into our vector equation gives us the final formula, free of explicit angle calculations! The implementation in the PBR book and many other sources uses exactly this form.
Raytracing in 2D | Week 8 | 18.S191 MIT Fall 2020 | James Schloss
This video from a ray tracing course provides another walk-through of a similar derivation. Seeing it from a slightly different perspective can help solidify your understanding.
Watch from 15:15 to 21:26. The presenter, James Schloss, works through the math to arrive at the same vector equation. Notice how he also emphasizes the goal of replacing trigonometric functions with dot products (c) and the IOR ratio (r).
3. The Condition for Total Internal Reflection
Our derived formula for has an important side effect. Look at the term inside the square root:
What happens if this term, , is negative? We would be taking the square root of a negative number, which has no real solution.
This isn't a mathematical error; it's a signal of a physical phenomenon. This is precisely the condition for Total Internal Reflection (TIR) we discussed in the last lesson.
- This happens when .
- Since , this condition is more likely when moving from a dense to a less-dense medium (, so ).
- Since , . The condition becomes , or , which is exactly what we identified as the trigger for TIR in the previous lesson.
When our code calculates this term and finds it's negative, it knows that no refraction occurs, and it must compute a reflection vector instead.

Test your understanding!
A ray is traveling from glass () into air (). The angle of incidence is . Does total internal reflection occur?
Use the formula for the term inside the square root to decide.
- Calculate .
- Calculate .
- Calculate .
- Based on the sign of , determine if there is refraction or TIR.
Show answer
- Since is negative, total internal reflection occurs. There is no refracted ray.
Conclusion
You've now seen how to get from the abstract physics of Snell's Law to a concrete, computable vector equation. This is a perfect example of the blend of physics, math, and engineering that makes ray tracing so compelling.
Key Takeaways:
- The refracted ray vector can be derived by decomposing it into components parallel and perpendicular to the surface normal.
- By combining this geometric construction with Snell's Law and trigonometric identities, we can create a formula that depends only on the incident vector, the normal, and the ratio of refractive indices.
- The final formula avoids expensive trig functions like
acosorasin, using dot products instead, which is ideal for a high-performance C++ implementation. - The math itself provides a natural test for Total Internal Reflection: if the term inside the square root becomes negative, refraction is physically impossible, and the ray must reflect.
Next Steps
We have the complete mathematical toolkit. In the next lesson, we will implement the logic to handle the phenomenon of total internal reflection. We'll take our derived formula and the TIR check and write a robust refract function in C++. This will also involve some important practical details, like correctly handling cases where a ray enters versus exits an object by swapping the refractive indices and flipping the normal.