PhotonStudies
From Odwiki
Photon Case Studies
In mantra, a photon shader is applied to a surface for evaluting how photons (from lights) interact with the surface. When a photon arrives at a surface, the VEX GlobalVariables are set to
| P | The point on the surface being shaded |
| N | The surface normal at the point being shaded |
| Ng | The geometric normal |
| s,t | The parametric coordinates of the point being shaded |
| dPds, dPdt | The surface derivatives |
| I | The direction that the photon is travelling in |
| Cl | The light energy of the photon |
The photon shader doesn't set any global variables, but instead calls one or more of the following functions
| photon_store() | Stores the photon into the photon map |
| photon_diffuse() | Causes the photon to bounce as a diffuse photon |
| photon_specular() | Causes the photon to bounce as a specular photon |
| photon_transmit() | Causes the photon to bounce as a transmission photon |
If the photon bounces, then the next surface hit by the photon will have it's photon shader evaluated, at which point the photon may be stored or bounce again.
Once a photon bounces specularly (or transmission), it's considered to be a specular photon for the rest of its life. These specular photons are used to generate caustics. Diffuse photons can be used to simulate irradiance.
In order to get an even distribution of photons, a process known as RussianRoulette is used to determine what happens to the photon when it interacts with the surface. A Reflective Surface
Here, we explain how a photon shader would be written to model a reflective surface. The parameter Kr determines how reflective the surface is.
ph_reflective(vector Kr=.5)
{
int result;
vector nf, R;
nf = normalize(frontface(N, I));
result = photon_switch(0, Kr, 0);
if (result == PHOTON_STORE)
photon_store(P, nf, Cl, I);
else if (result == PHOTON_REFLECT)
{
R = normalize(reflect(I, nf));
photon_reflect(P, R, Cl);
}
}
The first part of this shader determines what happens to the photon. This is done using the photon_switch() function. The three arguments to the photon_switch function represent probabilities. The probability that there's a diffuse bounce, a specular bounce or that the photon is transmitted through the surface. In this case, the photon will either be stored in the map or reflected. The chance of being reflected is determined by the Kr parameter. So, if the Kr parameter were 1, no photons would be stored on the surface. This represents a perfect mirror. On the other hand, if Kr were 0, then no photons would ever bounce, that is it would be a perfect absorber of light.
Based on the result of the photon_switch(), we either store the photon, or send it on a specular bounce.
A Colored Reflective Surface
ph_reflective(vector Kr=.5; vector specular_color=1)
{
int result;
vector nf, R;
nf = normalize(frontface(N, I));
result = photon_switch(0, Kr, 0);
if (result == PHOTON_STORE)
photon_store(P, nf, Cl, I);
else if (result == PHOTON_REFLECT)
{
R = normalize(reflect(I, nf));
photon_reflect(P, R, Cl*specular_color);
}
}
This case is almost identical to the prior case, but instead of just sending the photon on its way, we adjust the energy of the photon based on the specular_color parameter. So, if the photon coming in is pure white {1,1,1}, and the specular_color is red {1,0,0}, if the photon bounces, it will be red instead of white. This would result in red caustics.



