PhotonStudies

From Odwiki

Jump to: navigation, search

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.

© 2009 od[force].net | advertise