# Rendering multi BRDF materials

## Recommended Posts

hick18    102
In regard to ray tracing, and using a path tracing algorithm, how do you go about selecting paths to trace?

-If I have a mirror, I can just sample the materials BRDF to generate the new ray direction
-If I have a transparent material, I can just sample the materials BTDF to generate the new ray direction
-If I have glass, which will exhibit a BRDF and a BTDF, then I now have 2 directions to trace, but path tracing uses only one. For this I could use the fresnel equations to generate probabilities over which to chose based on the incident angle

But what if I have a semi transparent plastic material? Which would consist of 2 BRDFs and a BTDF. One BRDF for the almost specular/high glossy reflection and the other for diffuse reflection.

##### Share on other sites
macnihilist    377
You can sample your paths (almost) like you want, as long as you weight them correctly (with 1/p) and you don't completely ignore any possible path. The worst thing that can happen is that your path tracing gets very inefficient. (But even then you can expect it to converge to the exact solution eventually.)

For example if your BSDF has 3 components you can choose one of the components with probability 1/3 and then weight the path *3.
In general you should try to pick a component with a probability proportional to the contribution you expect (importance sampling), in order not to waste samples. Your third example does exactly this. Importance sampling is a science in itself, especially for glossy surfaces. But a strategy that is relatively easy to implement (besides uniform sampling) is to pick a component proportional to the hemispherical (directional) reflectance of the component.

If you are after layered materials like plastic you should be aware that they are usually modeled by a Fresnel layer 'above' the diffuse component. So only light that penetrates into the subsrate (i.e. light that is not reflected specularly) has a change to be scattered diffusely. You cannot simply treat these as independent components, but have to blend them according to the angle of incidence.

I hope this helps at least a bit -- unfortunately the details are too complex to explain here. If you really want to dive into path tracing and global illumination I'd recommend the book 'Physically Based Rendering'.

##### Share on other sites
hick18    102
[quote]For example if your BSDF has 3 components you can choose one of the components with probability 1/3 and then weight the path *3.[/quote]

Wouldnt that make that paths result be 3 times brighter? Or is it it a rough approximation for the contribution of the other 2 paths, which if this process is done many times, will then converge?

##### Share on other sites
macnihilist    377
[quote name='hick18' timestamp='1305749381' post='4812709']
[quote]For example if your BSDF has 3 components you can choose one of the components with probability 1/3 and then weight the path *3.[/quote]

Wouldnt that make that paths result be 3 times brighter? Or is it it a rough approximation for the contribution of the other 2 paths, which if this process is done many times, will then converge?
[/quote]

No, it should come out exactly right. Consider a surface that just reflects 50% and transmits 50%. You have two components 'reflect .5' and 'transmit .5'. If you hit the surface you first sample a component, let's say with probability 1/2 for each. Then you sample a new direction, attenuate the throughput of the path according to the BRDF (the component) and continue. Let's say we had done this with 4 paths that carry '1 radiance' on average:
Without 1/p:
2 pick reflection: .5*1 + .5*1 gets reflected => '1 radiance' accumulated for reflection, divide by 4 paths => 1/4 radiance reflected
2 pick transmission: [...] => 1/4 radiance transmitted.

With 1/p:
Well, it's easy to see that if you multiply each result by 2 (1/p) you get the correct answer: 1/2 reflected, 1/2 transmitted.

If you have time you can work this out on paper with different reflection/transmission ratios and probabilities. It should always come out right in the long run as long as you don't completely forget one component (i.e. assign it a probability of 0).

##### Share on other sites
hick18    102
I guess my problem is when you have all these pdfs floating about, and how to plug them all in.

Take for example a material with 2 BRDFs, a specular reflection and a phong diffuse. If the material was something like somewhat shiny plastic then I could use say 50/50 ratio for each, and so with path tracing having the pdf for each be 0.5.

But if I was going to extend that to incorporate global illumination, and instead sample some direction in the hemisphere for the diffuse BRDF, with a cos distribution, then now I have another pdf. Where does this second pdf plug in?

##### Share on other sites
macnihilist    377
[quote name='hick18' timestamp='1305827589' post='4813099']
But if I was going to extend that to incorporate global illumination, and instead sample some direction in the hemisphere for the diffuse BRDF, with a cos distribution, then now I have another pdf. Where does this second pdf plug in?
[/quote]

You just multiply the pdf of all decissions that lead to the new path. (This is only valid if they are independent, but they usually are.)

The code at a path vertex typically looks like this:
1. Sample new direction
1.1. Select BSDF component according to pdf_component
1.2. Sample direction wi according to pdf_fr
1.3. pdf = pdf_fr * pdf_component;
2. Attenuate throughput
2.1. Evaluate BRDF-component for sampled wi: fr = brdf_comp(wo,wi)
2.2. throughput *= fr/pdf * dot(n,wi)
3. shoot ray to get next vertex

Lines 82-91 of [url="https://github.com/mmp/pbrt-v2/blob/master/src/integrators/path.cpp#L82"]PBRT's path.cpp[/url] do exactly this, although the actual sampling is hidden in BSDF::Sample_f.
EDIT: Ah ok, I just looked at [url="https://github.com/mmp/pbrt-v2/blob/master/src/core/reflection.cpp#L513"]Sample_f[/url] and they do things a bit differently. They sample the direction from ONE component, but evaluate ALL with that single direction for the attenuation and consequently also use the sum of ALL pdf as the resulting pdf. I guess this is more efficient, but a bit harder to implement. In the end both methods should converge to the same result. Sorry if that confuses you only more -- one more reason to heed the advice below.

Again: I'd recommend you read a good book on the topic or at least look at PBRT's source code. The devil is the details here and it's not easy to explain the interrelationships correctly in a forum.