blog logo

CHICIO CODING

Dirty clean code. Creative Stuff. Stuff.

How to calculate the reflection vector

In this post I will talk about reflection vector used in some lighting models, for example the Phong reflection model. I will show you how this vector is calculated.


In a previous post I talked about the Phong lighting model. I described all the different components contained inside it and how they try to describe and simulate different kind of light components. In particular you will remember that there's a specular component that try to simulated the light reflected in a specific direction: the reflection direction. In the shader implementation this direction has been calculated using a GLSL method reflect:

vec3 reflectionDirection = reflect(-lightDirection, normalInterp);

Easy, isn't it? But the most curios of you may asking: "How the f*$k this method calculate this reflection direction?" emoji-stuck_out_tongue_closed_eyes
We will suppose as in the previous post about the phong model that all vectors are normalized. Let's start from the beginning. The formula to calculate the reflection direction is:

R=2(N^L^)N^L^R = 2({\hat{N}}\cdot{\hat{L}}){\hat{N}} - {\hat{L}}

How is this formula obtained? Let's start from a picture that represents our reflection vector and the other vectors used in the calculation.

A representation of the reflection phenomenon with all the vectors involved
A representation of the reflection phenomenon with all the vectors involved

Before we start with the demonstration we also need to know what is the law of reflection:

The incident light ray L, the reflected ray R, and the normal N to the surface of the mirror all lie in the same plane. The angle of reflection ΘR\Theta_R is equal to the angle of incidence of light ΘL\Theta_L. Both angles are measured with respect to the normal to the mirror. The reflected ray and the incident ray are on the opposite sides of the normal.

Now we are ready for our demonstration emoji-sunglasses.
From the law of reflection reported above we know that:

ΘR=ΘL\Theta_R=\Theta_L

This equation could be rewritten as the dot product of the reflection direction with the normal equals the dot product of the incident light direction and the normal (remember that the dot product of two vector is equal to the cosine of the angle between them) . So we have:

R^N^=L^N^{\hat {R}} \cdot {\hat {N}} = {\hat {L}} \cdot {\hat {N}}

From the image above it's also evident for symmetry that:

U^=U^{\hat {U}^{\prime}} = -{\hat {U}^{\prime \prime}}

As you can see again from the image above, this two vectors could be easily calculated. In fact the first one is the difference between the reflection vector and the projection of it on the normal. The second one is the difference between the light incident vector and the projection of it on the normal. So for the reflection side we could write:

U^=R^N^=R^(R^N^)N^{\hat {U}^{\prime}} = {\hat {R}} - {\hat {N}^{\prime}} = {\hat {R}} - ({\hat {R}} \cdot {\hat {N}}){\hat {N}}

For the light side we could write:

U^=L^N^=L^(L^N^)N^{\hat {U}^{\prime \prime}} = {\hat {L}} - {\hat {N}^{\prime \prime}} = {\hat {L}} - ({\hat {L}} \cdot {\hat {N}}){\hat {N}}

As a consequence we obtain the following equation:

R^(R^N^)N^=(L^(L^N^)N^){\hat {R}} - ({\hat {R}} \cdot {\hat {N}}){\hat {N}} = -({\hat {L}} - ({\hat {L}} \cdot {\hat {N}}){\hat {N}})

Now we can see again from the image above that the vector projections N^{\hat {N}^{\prime}} and N^{\hat {N}^{\prime \prime}} are equals, that means we could change the previous equation by substituting the first one with the second one. So we obtain the following equation:

R^(L^N^)N^=(L^(L^N^)N^){\hat {R}} - ({\hat {L}} \cdot {\hat {N}}){\hat {N}} = -({\hat {L}} - ({\hat {L}} \cdot {\hat {N}}){\hat {N}})

Now we have all we need to calculate our R vector:

R^(L^N^)N^=(L^(L^N^)N^){\hat {R}} - ({\hat {L}} \cdot {\hat {N}}){\hat {N}} = -({\hat {L}} - ({\hat {L}} \cdot {\hat {N}}){\hat {N}}) R^=(L^N^)N^(L^(L^N^)N^){\hat {R}} = ({\hat {L}} \cdot {\hat {N}}){\hat {N}} - ({\hat {L}} - ({\hat {L}} \cdot {\hat {N}}){\hat {N}}) R^=(L^N^)N^L^+(L^N^)N^{\hat {R}} = ({\hat {L}} \cdot {\hat {N}}){\hat {N}} - {\hat {L}} + ({\hat {L}} \cdot {\hat {N}}){\hat {N}} R=2(N^L^)N^L^R = 2({\hat{N}}\cdot{\hat{L}}){\hat{N}} - {\hat{L}}

That's it!! We get our formula. Now you're ready to understand in detail the "magic" of the Phong lighting model emoji-relaxed.

Recent posts

Better organize tests and run them against multiple configuration with Xcode Test Plan
Better organize tests and run them against multiple configuration with Xcode Test Plan

Recently I added a lot of Unit and UI tests to RangeUISlider, one of my open source projects. Let's see how I grouped them and run them against multip...

Read More
Unit testing in Kotlin with JUnit 5 and MockK
Unit testing in Kotlin with JUnit 5 and MockK

I recently discovered MockK, a mocking library created for Kotlin. Let's see how it is possible to write modern unit tests with MockK + JUnit 5.

Read More
Spring Boot + Kotlin Rest client cheatsheet: RestTemplate and Webclient
Spring Boot + Kotlin Rest client cheatsheet: RestTemplate and Webclient

During the last months I worked a lot with Spring Boot backend applications. In this post I explain how you can consume a REST api from a Spring Boot ...

Read More