informa
4 min read
News

In-depth: Photon mapping

In this reprinted #altdevblogaday in-depth piece, game programmer Simon Yeung offers an introduction to photon mapping, an important global illuminination technique.
[In this reprinted #altdevblogaday in-depth piece, game programmer Simon Yeung offers an introduction to photon mapping, an important global illuminination technique.] In this generation of computer graphics, global illumination (GI) is an important technique that calculates indirect lighting within a scene. Photon mapping is one of the GI techniques that uses particle tracing to compute images in offline rendering. Photon mapping is an easy to implement technique, so I choose to learn it. My target is to bake light maps, storing indirect diffuse lighting information using the photon map. Photon mapping consists of two passes: the photon map pass and the render pass, which will be described below. Photon map pass In this pass, photons will be casted into the scene from the position of the light source. Each photon stores a packet of energy. When a photon hits a surface of the scene, the photon will either be reflected (either diffusely or specularly), transmitted,  or absorbed, which is determined by Russian roulette.
Photons are traced in the scene to simulate the light transportation
This hit event represents the incoming energy of that surface and will be stored in a k-d tree (known as photon map) for looking up in the render pass. Each hit event would store the photon energy, the incoming direction, and the hit position. However, it is more convenient to store radiance than storing energy in photons because when using punctual light source (e.g. point light), it is hard to compute the energy emits given the light source radiance. So I use the method described in Physically Based Rendering, a weight of radiance is stored in each photon:
When a photon hits a surface, the probability of being reflected in a new random direction used in Russian roulette is:
This probability equation is chosen because the photon will have a higher chance of being reflected if it is brighter. If the photon is reflected, its radiance will be updated to:
Render pass In render pass, the direct and indirect lighting is computed separately. The direction lighting is computed using ray tracing.
Direct light only
The indirect lighting is computed by sampling from the photon map. When calculating the indirect lighting in a given position (in this case, the shading pixel), we can locate N nearby photons in photon map to estimate the incoming radiance using kernel density estimation. A kernel function needs to satisfy the conditions:
I use the Simpson's kernel (also known as Silverman's second order kernel) suggested in the book Physically Based Rendering:
Then the density can be computed using a kernel estimator for N samples within a distance d (i.e. the distance of the photon that is the furthest away in the N samples):
Then the reflected radiance at the shading position can be computed with:
However, the result shows some circular artifact:
Using the photon map directly for indirect diffuselight would show artifacts
To tackle this problem, either we can increase the number of photons to a very high number, or we can perform a final gather step. In the final gather step, we shoot a number of final gather rays from the pixel that we are shading in random direction over the hemisphere of the shading point.
Final gather rays are casted from every shading position
When a final gather ray hits another surface, then the photon map is queried just like before and the reflected radiance from this surface will be the incoming radiance of the shading pixel. Using Monte Carlo integration, the reflected radiance at the shading pixel can be calculated by sampling the final gather rays. Here is the final result:
Direct light + Indirect light, with final gather
Indirect light only, with final gather
Conclusion In this post, the steps to implement a photon map is briefly described. It is a two pass approach with the photon map pass building a photon map as kd-tree representing the indirect lighting data, and the render pass use the photon map to compute the final image. In the next part, I will describe how to make use of the photon map to bake light maps for real time application. References [This piece was reprinted from #AltDevBlogADay, a shared blog initiative started by @mike_acton devoted to giving game developers of all disciplines a place to motivate each other to write regularly about their personal game development passions.]

Latest Jobs

Treyarch

Playa Vista, California
6.20.22
Audio Engineer

Digital Extremes

London, Ontario, Canada
6.20.22
Communications Director

High Moon Studios

Carlsbad, California
6.20.22
Senior Producer

Build a Rocket Boy Games

Edinburgh, Scotland
6.20.22
Lead UI Programmer
More Jobs   

CONNECT WITH US

Register for a
Subscribe to
Follow us

Game Developer Account

Game Developer Newsletter

@gamedevdotcom

Register for a

Game Developer Account

Gain full access to resources (events, white paper, webinars, reports, etc)
Single sign-on to all Informa products

Register
Subscribe to

Game Developer Newsletter

Get daily Game Developer top stories every morning straight into your inbox

Subscribe
Follow us

@gamedevdotcom

Follow us @gamedevdotcom to stay up-to-date with the latest news & insider information about events & more