I was taking a look at Smallpt (http://www.kevinbeason.com/smallpt), more specifically at the Russian Roulette part. Actually, RR is used in two places along the code: first, to determine ray termination; and second, for the rendering of dielectrics.

That is the code for the ray termination case (expanded code version):

// p = maximum reflectance
// fr = BRDF
double p = fr.x > fr.y && fr.x > fr.z ? fr.x : fr.y > fr.z ? fr.y : fr.z; 

if ( ++depth > 5 ) 
    if ( erand48(Xi) < p )
        fr = fr * ( 1 / p ); 
        return obj.emission;

After five bounces, RR is used to determine if the ray path continues or not. If it continues, the BRDF is scaled to compensate for it. This is Ok for me.

RR is also used in a second code segment to select between refraction or transmission during the rendering of dielectrics (expanded code version):

double Re = R0 + ( 1 - R0 ) * cost * cost * cost * cost * cost;
double Tr = 1 - Re;
double P = .25 + .5 * Re;
double RP = Re / P;
double TP = Tr / ( 1 - P );
Vec Lo; // output radiance

if ( depth > 2 )
    if ( erand48(Xi) < P )
        Lo = radiance(reflRay,depth,Xi) * RP;
        Lo = radiance(Ray(x,tdir),depth,Xi) * TP;
    Lo = radiance(reflRay,depth,Xi) * Re + radiance(Ray(x,tdir),depth,Xi) * Tr;

According to the code above, the path branches recursively if the ray has bounced up to two times. After two bounces, however, RR is used to select the path to be followed. This is also Ok for me.

What is a bit confusing is the fact that the radiance returned by both possible non-branching paths (refraction and transmission) is scaled. I understand that there are different probabilities regarding reflection and transmission. However, if for instance Re = 0.3 and Tr = 0.7, and 100 rays strike the surface, about 30% of the rays will be reflected and 70% of will be transmitted due RR. In this case, I understand that there is no path termination neither energy loss, so there wouldn't be anything to compensate for.

Thus, my first two questions are: why are these radiances scaled? Should they be scaled, or would it work without scaling at all?

My third question is related to the scaling factors: Why the author has used P, RP and TP instead of Re and Tr?

Any indication of a good reading about this topic is also very welcome!!

Thank you!


1 Answer 1


The reflected and transmitted values need to be scaled because they are not sampled proportionally to their contribution. You'll notice how the decision whether to reflect or transmit is made based on P, not Re.

About why that scaling has been done in the first place, only the author can give you the definitive answer. My guess is that this is done to prevent extreme values that would come from tiny probabilities. Imagine that Re is 0.001 and is used without scaling. Then only one in 1000 rays would reflect, and the contribution of that ray would be multiplied by 1000. At a render with, say, 64 rays per pixel, this would leave very visible artefacts, as not every pixel would get a reflected ray. The scaling from this code snipped on the other hand makes sure that the ray budget is more evenly distributed between reflection and transmission and that each potential path taken is guaranteed at least 25% or the rays.

For further reading about path tracing, there is no better and comprehensive resource than www.pbrt.org - both the book and the source code are worth reading.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.