How to make a Photon Mapper : Whitted Ray Tracer

Hello there,

Today, we are going to see how to make the first part of our photon mapper. We are unfortunately not going to talk about photons, but only about normal ray tracing.

Whitted Ray Tracer without shadows
Whitted Ray Tracer without shadows

This is ugly !!! There is no shadow…

It is utterly wanted, shadows will be draw by photon mapping with opposite flux. We will see that in the next article.


In this chapter, we are going to see one implementation for a whitted ray tracer

Direct Lighting

Direct lighting equation could be exprimed by :

\displaystyle{L_o(\mathbf{x}, \vec{\omega_o}) = \sum_{i\in \{Lights\}}f_r(\mathbf{x}, \vec{\omega_i}, \vec{\omega_o})\frac{\phi_{Light}}{\Omega r^2}cos(\theta)}

The main difficult is to compute the solid angle \Omega .
For a simple isotropic spot light, the solid angle could be compute as :

\displaystyle{\Omega=\int_{0}^{angleCutOff}\int_{0}^{2\pi}sin(\theta)d\theta d\phi =-2\pi(cos(angleCutOff)-1)}

with :

  1. \Omega the solid angle.
  2. \phi_{Light} the total flux carried by the light.
  3. cos(\theta) the attenuation get by projected light area on lighted surface area.
  4. angleCutOff \in [0; pi].

Refraction and reflection

Both are drawn by normal ray tracing.


Now, we are going to see how our ray tracer works :

Shapes :

Shapes are bases of renderer. Without any shapes, you can’t have any render. We can have many differents shape, so, we can use one object approach for our shapes.


For each shapes, we obviously have a particular material. The material have to give us a brdf and can reflect radiance.

Storage Shapes

To have a better ray tracing algorithm, we could use a spatial structure like Kd-tree or other like one :


The main algorithm part is on the materials side. Below, a piece of code where I compute the reflected radiance for a lambertian material and a mirror. You could see that material part has access to other shape via the global variable world.


Lighting is a useful feature in a render. It’s thanks to lights that you can see the relief. A light carry a flux. Irradiance is the flux received by a surface.

So, our interface is :

Below a piece of code about computing irradiance :

The next time, we will see how to integrate a photon mapper to our photon mapper. If you want to have the complete code, you could get it here :

Bye my friends :).

How to make a Photon Mapper : Rendering Equation Debunked


Hi guys!

I have not written anything here since a long time, I had exams, professional mission in C++ with Qt and too many things to do. Don’t be afraid, activities in this blog will be start again soon.

In computer graphics, I didn’t do beautiful things, except a little ray tracer with photon mapping. I’m going to explain how to make a little photon mapper. Firstly, we’ll see the it on the CPU side, after we’ll try to implement it in the GPU side.

We will see several points :

  1. Explanations about rendering equations
  2. A raytracer
  3. A photon mapper
  4. A GPU side with Photons Volume

Perhaps, some chapters will be divided into several parts.

Rendering Equation :


The rendering equation is :

\displaystyle{L_o(\mathbf{x}, \vec{\omega_o}) = L_e(\mathbf{x}, \vec{\omega_o}) + \int_{\Omega}f_r(\mathbf{x}, \vec{\omega_i}, \vec{\omega_o})L_i(\mathbf{x}, \vec{\omega_i})(\vec{\omega_i}\cdot\vec{n}) d\omega_i =}
\displaystyle{L_e(\mathbf{x}, \vec{\omega_o}) + \int_{\Omega}f_r(\mathbf{x}, \vec{\omega_i}, \vec{\omega_o})dE_i(\vec{\omega_i}) =}
\displaystyle{L_e(\mathbf{x}, \vec{\omega_o}) + \int_{\Omega}f_r(\mathbf{x}, \vec{\omega_i}, \vec{\omega_o})\frac{d^2 \phi_i(\mathbf{x}, \vec{\omega_i})}{dA}}

What is it burried into this equation?

  1. L_o(\mathbf{x}, \vec{\omega_o}) is the outgoing radiance. It will be our pixel color in R, G, B space. It is exprimed in W\cdot sr^{-1}\cdot m^{-2}.
  2. L_e(\mathbf{x}, \vec{\omega_o}) is the emmited radiance. It should be zero for almost all materials, excepting those that emit light (fluorescent material or lights for examples).
  3. f_r(\mathbf{x}, \vec{\omega_i}, \vec{\omega_o}) is the Bidirectional Reflectance Distribution Function(aka BRDF). It defines how light is reflected on surface point \mathbf{x}. It is exprimed in sr^{-1}. Its integral over \Omega should be inferior or equal to one.
  4. L_i(\mathbf{x}, \vec{\omega_i}) is the incoming radiance. It is like the light received by \mathbf{x} in a direct or indirect way.
  5. (\vec{\omega_i}\cdot\vec{n}) is the lambert cosine law.
  6. d\omega_i is the differential solid angle. It is exprimed in sr.
  7. dE(\vec{\omega_i}) is differential irradiance. It is the radiant flux (or power) received by a surface per unit area. It is exprimed in W\cdot m^{-2}.
  8. \phi_i(\mathbf{x}, \vec{\omega_i}) is the radiant flux(or power) passing from \mathbf{x} and have for direction \omega_i. It could be seen as one of our photons. It is exprimed in R, G, B space as well. It is exprimed in W.
  9. dA is the area which received the radiant power.

Manipulate rendering equation for an approximation

This part is going to be a bit mathematical with “physical approximation :D”.

Simplification of irradiance

Zack Waters : Irradiance and flux
Zack Waters : Irradiance and flux

\displaystyle{dE_i=\frac{d^2 \phi_i}{dA}\rightarrow E_i=\frac{d\phi_i}{dA}}

Assuming the “floor” of the hemisphere is flat and photon hitting this floor is like hit \mathbf{x}, we have :

\displaystyle{E_i \simeq \sum \frac{\phi_i}{\pi r^2}\rightarrow E \simeq \sum_i \sum \frac{\phi_i}{\pi r^2} = \sum \frac{\phi}{\pi r^2}}.

So, to have a better approximation, you must have to reduce the hemisphere’s radius and increase the photons number.

The rendering equation simplified

\displaystyle{L_o(\mathbf{x}, \vec{\omega_o}) = L_e(\mathbf{x}, \vec{\omega_o}) + \int_{\Omega}f_r(\mathbf{x}, \vec{\omega_i}, \vec{\omega_o})L_i(\mathbf{x}, \vec{\omega_i})(\vec{\omega_i}\cdot\vec{n}) d\omega_i =}
\displaystyle{L_o(\mathbf{x}, \vec{\omega_o}) = L_e(\mathbf{x}, \vec{\omega_o}) + \frac{1}{\pi r^2}\sum f_r(\mathbf{x}, \vec{\omega_{photon}}, \vec{\omega_o})\phi(\mathbf{x}, \vec{\omega_{photon}})}

Direct Illumination

Direct illumination need an accurate quality, so, we will not use the simplified equation seen above but the real one. The main difficulty is to compute the solid angle. For example, a point light with power \phi_L :

\displaystyle{L_r = f_r(\mathbf{x}, \vec{\omega_i},\vec{\omega_o})(\vec{\omega_i}\cdot\vec{n})\frac{\phi_l}{4\pi r^2}}

We remind that E = \frac{I}{r^2} = \frac{\phi_l}{\Omega r^2} with \Omega the solid angle.

Photon tracing, reflection and refractions

The photon tracing is easy. Imagine you have a 1000W lamp, and you want to share all of its power into 1 000 photons, each photon should have a 1W power (We could say the colour of this photon is (1.0, 1.0, 1.0) in RGB normalized space). When photon hit a surface, you store it into the photon maps and reflect it with the BRDF :).

If you didn’t get it all, don’t be afraid, in our futur implementation, we are going to see how it works. We will probably not do any optimization, but it should be good :).

Bye my friends 🙂 !