Pixie supports global illumination and photon mapping. The mechanism for global illumination is very similar to the new extensions introduced with PrMan 11.
The rib fragment above causes one global photon map to be saved into global.gpm. You can attach different photon maps to different objects. You can also use causticmap instead of globalmap to create a caustics photon map. The only difference between them is that the caustic photon map only contains photons that hit a reflective / refractive (specular) object. To look up a previously created photon map, you can use the photonmap shading language command:
color photonmap(string map,point P,normal N,...);
where map is the name of the photonmap (e.g.: global.gpm), P is the lookup point and N is the lookup normal. The following optional parameters can also be passed:
uniform float estimator | The number of photons to use for lookup |
uniform float maxRadius | The maximum lookup radius |
Caustics can be generated by directly visualizing the caustics photon maps that Pixie generates. Notice that since these photon maps are visualized directly, they need to have lots of photons. Figures below demonstrate this effect. Corresponding RIB files can be found in $PIXIEHOME$/examples/ex2.
Pixie can compute occlusion and/or irradiance values sparsely and interpolate them for the final rendering. This allows fast and accurate diffuse interreflections without noise. The following two shading language commands can be used:
color indirectdiffuse(point P,normal
N,floatnumSamples,...);
float occlusion(point P,normal N,float numSamples,...);
indirectdiffuse command computes diffuse interreflection. It will either interpolate using the previous diffuse interreflection samples nearby, or compute a new sample. occlusion computes the coverage (i.e.: the fraction of the hemisphere that does not see anything) using the same method. The only difference between them is that indirectdiffuse shades the rays that are shot for computing a sample whereas occlusion doesn't. This makes occlusion faster than indirectdiffuse. The following optional parameters can be pass to both of these commands:
uniform float minR | The closest distance between samples |
uniform float maxR | The farthest distance between samples |
varying float occlusion | The occlusion value (output) |
varying color irradiance | The irradiance value (output) |
Notice that you can obtain the occlusion value from indirectdiffuse and vice-versa:
float oc;
vector ic;
ic =indirectdiffuse(P,N,256,"occlusion",oc);}
Since in a single pass, the renderer will be forced to do some extrapolation, the generated image may have blocky artifacts. These can be avoided by doing another pass using the irradiance cache computed by the previous pass. The figures below demonstrate the extrapolation artifacts and the image computed after a second pass:
The image on the left is computed in the first pass and suffers from blocky artifacts due to extrapolation. The image on the right is computed in the second pass. This scene contains only one light source shader: ambientocclusion (available in the shaders directory). Corresponding RIB file can be found in $PIXIEHOME$/examples/ex1.
Figures below further demonstrate the global illumination capabilities of Pixie.
These images were created using irradiance caching via indirectdiffuse. This scene contains only one light source shader: ambientindirect (available in the shaders directory). Corresponding RIB file can be found in $PIXIEHOME$/examples/ex3.