Intro to ExPhotonMap - LuxRender Wiki
Luxrender GPL Physically Based Renderer

Intro to ExPhotonMap

Personal tools

From LuxRender Wiki

Jump to: navigation, search

Contents

Intro

Welcome the exphotonmap tutorial! Before we get started, please note that this tutorial assumes you already have some basic familiarity with LuxRender and your exporter of choice. Therefore detailed information about for example where to find a certain button will be skipped. This guide largely assumes you were using bidirectional path tracing before, and are curious about exphotonmap for its potential to render things a lot faster.

Examples

Bidir vs photon.jpg

Top: Bidirectional + Metropolis sampler. Bottom: Exphotonmap + low discrepancy sampler. Both rendered with halttime = 300

Pool scene 2min.jpg

Left: Exphotonmap + low discrepancy/hilbert sampler. Right: Bidirectional + Metropolis sampler. Both rendered with halttime = 120.

What exphotonmap is, and what it isn't

Exphotonmap is physically based, and consistent. It can simulate more or less all the optical phenomena supported by LuxRender, and given precise enough settings, should look basically correct. With that said, exphotonmap is biased, so it intentionally takes some shortcuts; how much this affects the rendered result depends on which render settings are being used.

Exphotonmap is not going to render your scene in a blink of an eye. Although when configured properly it will outrun path tracing and bidirectional path tracing by a long shot, it is still spectral progressive rendering.

Photon mapping explained

For a more technical introduction to photon mapping, please read the Wikipedia page. You can also read the documentation on PBRT's "improved photon mapping" plugin from which exphotonmap was derived.

In case those two documents seem too complicated or too long, here's a simple explanation in plain English that requires slightly less background on raytracing:

Path tracing algorithms (like LuxRender's path and bidirectional modes) rely on following a ray along a realistic light path through the scene, and repeating this again and again until a clean image results. This is accurate, but very, very slow. You could also do direct lighting (like LuxRender's direct mode), but that way you will not get any global illumination as reflected light will be ignored.

Photon mapping attempts to get around the problem via a two step process. During the first pass, the "light" or "photon" pass, it shoots rays from the light sources, and places a sort of marker where they land, called a "photon". Different types of markers are placed depending on how the ray wound up at that point (such as coming straight in from the light, bouncing off something else, refracting through glass, etc.) Once a predefined number of each kind of photons (markers) has been dropped, this pass ends and round two begins.

The second pass is (at least in LuxRender) a traditional raytracing pass, but instead of relying on hitting the lights themselves, it uses the "photons" it dropped as a big cheat-sheet of where all the light landed, and assumes hitting a "photon" equals hitting the light source it came from. So when a ray traced from the camera strikes a surface, it will look around where it landed, find the nearest photons and check how much light they show.

This is all a loose approximation of what happens, but you get the general idea. Now on to configuring it!

Parameters

Direct photons

The target number of direct light photons.

These are deposited where a light ray hits a surface directly after leaving the light source. You will need a lot of these, but they generally fill pretty quick. The default 1 million is fine in most cases.

Indirect photons

The target number of photons for soft indirect light.

These are deposited from light rays that bounced off another surface prior to landing. This map is the one that your global illumination solution will be computed from, for the most part. For most scenes 500,000-1,000,000 is recommended, although some scenes don't need that many and others need more. Light rays that bounced from a very glossy surface are considered reflection caustics, and are dealt with by the caustic photon map.

Caustic photons

Target number of photons for reflection and refraction caustics

These are left by light rays that passed through a glass material or bounced off a highly glossy surface prior to landing. In most cases, these are not common paths and hence they will fill slowly. Accurate caustics can still take over 1,000,000 caustic photons though, so be careful with the glass materials. If your scene contains no glass and mostly dull materials, this map will not be able to fill and LuxRender should give up on it after 15 seconds or so.

Radiance photons

Target number of final gather photons

These are kind of special, they are generic markers that will be used for the secondary rays during final gathering. In general, you want about the same number as you set for indirect photons.

Number of Photons Used/Max Photon Distance

These two work together, to help focus the search for photons when a ray from the camera hits something. Number of photons used is the maximum number of photons it will take to estimate the light contribution from that ray. Photons will only be taken into account if they are closer to the hit than the value set for Max photon distance. You can usually leave these settings at their default value.

Max depths

These are the maximum recursion depths for the photon pass and the rendering pass. They work pretty much the same as for any other integrator.

Final Gathering/Samples/Gather Angle

Final gathering will make LuxRender perform a more thorough (though also more biased) rendering pass. Instead of using the photon map directly, it will at each camera ray hit point shoot a set of secondary rays. It will then use the radiance photon map at these secondary hit points to estimate how much light reaches the camera ray's hit point, and use this to determine the overall light contribution for that camera ray.

Some photon contributions at those secondary hit points could in fact be impossible: the photons could be bouncing off in a completely different direction than towards the camera hit point. In order to filter out those photons they will be rejected if the angle between their direction and the direction to the camera hit point is too large. The "gather angle" parameter defines this value. 5-10 degrees is a good starting point for most scenes. Wider angles can allow fewer final gather samples, speeding up rendering, but increase bias: it will make some surfaces strangely (and incorrectly) bright. Too low values may reject too many photons leading to uneven lighting.

The last final gathering parameter, samples, is simply the number of secondary rays that will be fired at each intersection. The default is 32, although many scenes can get away with fewer, especially with higher gather angles.

If you increase the number of gather samples substantially you could decrease the gather angle somewhat in order to get a less blurry estimation. Gather angle vs samples is something of a balance between accuracy and speed, it can be adjusted how you like.

Rendering mode/Russian Roulette

This is the mode to use during the eye pass. It's usually best to stick with "directlighting" and let the photon maps handle caustics and GI, but you can use "path" tracing too if you so desire. Russian Roulette settings are the same as for other integrators.

Samplers

Generally, you should use either the low discrepancy or metropolis samplers. Metropolis is generally more efficient on scenes with a lot of glossy or glass/metal materials, low discrepancy is a better choice for a mainly matte scene, although it may require a large number of samples to properly handle blurred reflections.

Tuning it

Artifacts

After going for a spin with the default settings, you probably got a few strange artifacts. A very common one is a blotchy appearance to the phenomenon commonly called "ambient occlusion":

Amb-occlusion.jpg

This is caused by a lack of indirect photons, or too sloppy of final gather settings, but there is also something else you can do about it. You can bevel/chamfer the edge a bit, 5-10mm is enough. If the problem shows up with a creased edge on a subdivided model, try backing the crease amount off somewhat. Below is the same scene, with the same number of indirect and radiance photons, but with a bevel of 1cm (was rendered a bit longer though, hence the lower noise):

Bevel.jpg

Looks fairly clean, but the corner itself looks a bit funny, so in this case you'd want to to do a mix of both (more photons and a small bevel/chamfer). The default of 200k indirect and radiance photons is a bit short for tight detail like that, so if you have issues like that, either make the edge less tight, or add photons. You can also try lowering the gather angle, it can often help with lighting errors like this.

Another common problem you'll get looks like this:

Caustics.jpg

This is caused by not having nearly enough caustic photons. Sadly, these can take a while to shoot, since the odds of a ray shot from the light passing through a glass object then hitting something else aren't all that great. You can disable glass caustics entirely by setting the target amount for the caustic map to 0. You won't get "transparent shadows" this way though, all your glass will throw a shadow as though it was opaque. This can be (very) good time saver if you have glass objects that aren't terribly prominent in the scene.

If your scene has a severe lack of indirect lighting, such as a shape on a plane using only a blank "infinite" light, you may get an error that the indirect map failed, and then LuxRender will simply do a direct light render. It's best to forget the infinite light (use a blank environment) or enclose your scene in this case.

Final Gather samples vs Pixelsamples

Another important thing to remember is that final gather samples are set per-ray in LuxRender, rather than per-pixel as in some other engines. That means that if you use 32 pixelsamples and 16 final gather samples, you will wind up with an average of 512 final gather samples for each pixel. If you switch to 16 pixelsamples, you will only get 256 final gather samples per pixel (again, on average), which can lead to patchy lighting. To compensate, you can either increase the gather angle to smooth lighting out (may lead to noticeably incorrect lighting) or increase the number of final gather samples (will slow down the render). Or some combination of the two.

So if you are working on a motion graphics shot with some simple materials (like matte), you might want to use lower pixelsamples and higher final gather samples to better optimize your use of CPU time. On the flip side, if you are making a life-like animated film, you will probably need higher pixelsamples anyway to avoid monte-carlo noise on more difficult materials (probably 256 or 512 pixelsamples). So you can get away with dropping final gather samples down to 12-16 per ray, and using a tighter gather angle such as 5-6 degrees to help avoid incorrect lighting.

Materials

It is important to understand what happens with different kinds of materials so you know how to tune it properly. Indirect photons are needed for indirect diffuse bounces. These can be generated by matte types of materials and low specular (glossy) types of materials. Caustic photons are needed for highly specular surfaces (reflective caustics) such as mirror, metal, shinymetal, glass, and highly glossy items such as glossy with a low roughness parameter, or the carpaint material. Caustic photons are also needed for refractive caustics to generate those beautiful caustics from glass and water that we all love.

Wrapping up

It is important to always keep in mind that exphotonmap is biased. It will always be a bit fussy, and have the possibility of creating artifacts that will never disappear, no matter how long you render for. It will take a bit of coaxing to get it to produce an image with the quality of path or bidirectional, but it can be worth it for animations, or if you are on a tight deadline.

The following image was rendered to 32 samples per pixel using the following settings.
Low Discrepancy sampler [pixelsampler = hilbert, pixelsamples = 32].
Exphotonmap integrator [causticphotons = 2000000, maxphotondist = 0.1].
The rest of the Exphotonmap settings were the default settings.
Pool scene expm 32spp.jpg