<h2>TL;DR</h2>

<p>Yes, you can do it like that, you just have to divide the result by the probability of choosing the direction.</p>

<h2>Full Answer</h2>

<p>The topic of sampling in path tracers allowing materials with both reflection and refraction is actually a little bit more complex.</p>

<p>Let's start with some background first. If you allow BSDFs - not just BRDFs - in your path tracer, you have to integrate over the whole sphere instead of just the positive hemisphere. Monte Carlo samples can be generated by various strategies: for the direct illumination you can use BSDF and light sampling, for the indirect illumination the only meaningful strategy usually is the BSDF sampling. The sampling strategies themselves usually contain the decision about which hemisphere to sample (e.g. whether reflection or refraction is computed).</p>

<p>In the simplest version, the light sampling usually doesn't take care much about reflection or refraction. It samples the light sources or the environment map (if present) with respect to the light properties. You can improve sampling of environment maps by picking just the hemisphere in which the material has non-zero contribution, but the rest of the material properties is usually ignored. Note that for and ideally smooth Fresnel material the light sampling doesn't work.</p>

<p>For BSDF sampling, the situation is much more interesting. The case you described deals with an ideal Fresnel surface, where there are only two contributing directions (since Fresnel BSDF is in fact just a sum of two delta functions). You can easily split the integral into a sum of two parts - one reflection and one for refraction. Since, as you mentioned, we don’t want to go in both directions in a path tracer, we have to pick one. This means that we want to estimate the sum of numbers by picking just one of them. This can be done by discrete Monte Carlo estimation: pick one of the addends randomly and divide it by the probability of it being picked. In an ideal case you want to have the sampling probability proportional the the addends, but since we don't know their values (we wouldn't have to estimate the sum if we knew them), we just estimate them by neglecting some of the factors. In this case, we ignore the incoming light amount and use just the Fresnel reflectance/transmittance as our estimates.</p>

<p>The BSDF sampling routine for the case of smooth Fresnel surface is, therefore, to pick one of the directions randomly with probability proportional to the the Fresnel reflectance and, at some point, divide the result for that direction by probability of picking the direction. The estimator will look like:</p>

<p>$$
\frac
   {L_{i}\left(\omega_{i}\right)F\left(\theta_{i}\right)}
   {P\left(\omega_{i}\right)} =
\frac
   {L_{i}\left(\omega_{i}\right)F\left(\theta_{i}\right)}
   {F\left(\theta_{i}\right)} =
L_{i}\left(\omega_{i}\right)
$$</p>

<p>Where $\omega_{i}=\left( \phi_{i}, \theta_{i} \right)$ is the chosen incident light direction, $L_{i}\left(\omega_{i}\right)$ is the amount of incident radiance, $F\left(\theta_{i}\right)$ is either the Fresnel reflectance for the reflection case or 1 - Fresnel reflectance for the refraction case, $P\left(\omega_{i}\right)$ is the discrete probability of picking the direction and is equal to $F\left(\theta_{i}\right)$.</p>

<p>In case of more sophisticated BSDF models like those based on microfacet theory, the sampling is slightly more complex, but the idea of splitting the whole integral into a finite sum of sub-integrals and using discrete Monte Carlo afterwards can usually be applied too.</p>

CC BY-SA 3.0
2016-05-23T15:00:26.530Z
This is interesting but I'm confused by one point. Could you clarify what it means to "divide the result for that direction by probability of picking the direction"? If it is not a binary choice but a direction chosen from a continuous distribution, won't the probability be zero?
trichoplax is on Codidact now
CC BY-SA 3.0
2016-05-23T15:10:04.173Z
Thank you! This helps a lot. The method you describe will work for ideal Fresnel surfaces. And I just discovered Walter et. al. [2007] and Burley [2015], which can be used for rough BSDFs.
RichieSams
CC BY-SA 3.0
2016-05-23T16:37:09.823Z
@trichoplax: Yes it would, but in that paragraph I was describing the sampling technique just for a (dielectric) Fresnel BSDF - ideally smooth surface, which is a sum of two Dirac delta functions. In such case you are picking one of the directions with some discrete probability. In case of a non-delta (finite) BSDF, you generate directions according to a probability density function. Unfortunately, delta and non-delta cases have to be handled separately, which makes the code a little messy. More details on sampling microfacet BSDFs can be found, for example in the Walter et. al. [2007] paper.
ivokabel
CC BY-SA 3.0
2016-05-23T16:53:04.740Z
@RichieSams: Walter et. al. [2007] is basically still the state-of-the art for dielectric rough surfaces, but to make it work well you need a good sampling which was published just recently by Heitz and D'Eon the 2014 paper "Importance Sampling Microfacet-Based BSDFs using the
Distribution of Visible Normals". And note that it is a single-scattering model which neglects inter-reflections between microfacets making it visibly dark for higher roughness values. See my question "Compensation for energy loss in single-scattering microfacet BSDF models" for more details.
ivokabel
CC BY-SA 3.0
2016-05-23T18:22:23.363Z
Just wanted to point out that if you choose probability = fresnel() as the question suggested, then when you divide by the probability, you cancel out the Fresnel factor that would normally be multiplied in. So (in the discrete, two-Dirac case) you end up with the ray contribution not including any Fresnel factor at all. It's standard importance-sampling theory, but I thought I'd point that out as a potentially confusing issue.
Nathan Reed
CC BY-SA 3.0
2016-05-23T18:32:49.610Z
@Nathan, that's actually a very good point. I'm glad you mentioned it.
ivokabel
CC BY-SA 3.0
2016-05-24T11:27:33.883Z
@Nathan, I incorporated your notice into the answer.
ivokabel
CC BY-SA 3.0
2016-05-30T02:09:01.033Z
I got it to work! http://i.imgur.com/m1fYRdr.png
RichieSams
CC BY-SA 3.0
2016-05-30T12:34:54.060Z
@RichieSams: Cool, but does your glass attenuate light? If it doesn't, the object should not be visible under constant illumination I'm afraid.
ivokabel
CC BY-SA 3.0
2016-05-30T15:50:47.180Z
Currently, the BTDF just returns the surface Albedo, (which is float3(0.95) in this render). If I set it to float3(1.0), yes, it will disappear. Implementing Beer-Lambert is my next task.
RichieSams
CC BY-SA 3.0
2016-05-23T08:04:39.000Z
2016-05-24T11:25:59.273Z
2016-05-24T11:25:59.273Z
ivokabel
<p>I am trying to implement refraction and transmission in my path tracer and I'm a bit unsure on how to implement it. First, some background:</p>

<p>When light hits a surface, a portion of it will reflect, and a portion will be refracted:
<a href="https://i.sstatic.net/2oBo9.png" rel="noreferrer"><img src="https://i.sstatic.net/2oBo9.png" alt="enter image description here"></a></p>

<p>How much light reflects vs. refracts is given by the <a href="https://en.wikipedia.org/wiki/Fresnel_equations" rel="noreferrer">Fresnel Equations</a>
<a href="https://i.sstatic.net/cYrKH.png" rel="noreferrer"><img src="https://i.sstatic.net/cYrKH.png" alt="enter image description here"></a></p>

<p>In a recursive ray tracer, the simple implementation would be to shoot a ray for reflection and a ray for refraction, then do a weighted sum using the Fresnel.
$$\begin{align*}
R &amp;= Fresnel()\\
T &amp;= 1 - R\\
L_{\text{o}} &amp;= R \cdot L_{\text{i,reflection}} + T \cdot L_{\text{i,refraction}}
\end{align*}$$</p>

<p>However, in path tracing, we only choose one path. This is my question:</p>

<ul>
<li><strong>How do I choose whether to reflect or refract in a non-biased way</strong></li>
</ul>

<p>My first guess would be to randomly choose based on the Fresnel. Aka:</p>

<pre><code>float p = randf();
float fresnel = Fresnel();
if (p &lt;= fresnel) {
    // Reflect
} else {
    // Refract
}
</code></pre>

<p>Would this be correct? Or do I need to have some kind of correction factor? Since I'm not taking both paths.</p>

CC BY-SA 3.0
2016-05-30T01:46:15.387Z
russian roulette
v.oddou
<brdf><pathtracing><reflection><refraction>
Choosing Reflection or Refraction in Path Tracing
RichieSams
# Choosing Reflection or Refraction in Path Tracing

(Asked by: username_0 on 2016-05-23)

I am trying to implement refraction and transmission in my path tracer and I'm a bit unsure on how to implement it. First, some background:

When light hits a surface, a portion of it will reflect, and a portion will be refracted:
[![enter image description here](https://i.sstatic.net/2oBo9.png)](https://i.sstatic.net/2oBo9.png)

How much light reflects vs. refracts is given by the [Fresnel Equations](https://en.wikipedia.org/wiki/Fresnel_equations)
[![enter image description here](https://i.sstatic.net/cYrKH.png)](https://i.sstatic.net/cYrKH.png)

In a recursive ray tracer, the simple implementation would be to shoot a ray for reflection and a ray for refraction, then do a weighted sum using the Fresnel.
$$\begin{align\*}
R &= Fresnel()\\
T &= 1 - R\\
L\_{\text{o}} &= R \cdot L\_{\text{i,reflection}} + T \cdot L\_{\text{i,refraction}}
\end{align\*}$$

However, in path tracing, we only choose one path. This is my question:

* **How do I choose whether to reflect or refract in a non-biased way**

My first guess would be to randomly choose based on the Fresnel. Aka:

```
float p = randf();
float fresnel = Fresnel();
if (p <= fresnel) {
    // Reflect
} else {
    // Refract
}

```

Would this be correct? Or do I need to have some kind of correction factor? Since I'm not taking both paths.

**Tags:** brdf, pathtracing, reflection, refraction

> **Comments:**
> **username_1**: russian roulette  

---

## 1 answers

### Answer by username_2 on 2016-05-23. Score: 8 | Accepted answer

## TL;DR

Yes, you can do it like that, you just have to divide the result by the probability of choosing the direction.

## Full Answer

The topic of sampling in path tracers allowing materials with both reflection and refraction is actually a little bit more complex.

Let's start with some background first. If you allow BSDFs - not just BRDFs - in your path tracer, you have to integrate over the whole sphere instead of just the positive hemisphere. Monte Carlo samples can be generated by various strategies: for the direct illumination you can use BSDF and light sampling, for the indirect illumination the only meaningful strategy usually is the BSDF sampling. The sampling strategies themselves usually contain the decision about which hemisphere to sample (e.g. whether reflection or refraction is computed).

In the simplest version, the light sampling usually doesn't take care much about reflection or refraction. It samples the light sources or the environment map (if present) with respect to the light properties. You can improve sampling of environment maps by picking just the hemisphere in which the material has non-zero contribution, but the rest of the material properties is usually ignored. Note that for and ideally smooth Fresnel material the light sampling doesn't work.

For BSDF sampling, the situation is much more interesting. The case you described deals with an ideal Fresnel surface, where there are only two contributing directions (since Fresnel BSDF is in fact just a sum of two delta functions). You can easily split the integral into a sum of two parts - one reflection and one for refraction. Since, as you mentioned, we don’t want to go in both directions in a path tracer, we have to pick one. This means that we want to estimate the sum of numbers by picking just one of them. This can be done by discrete Monte Carlo estimation: pick one of the addends randomly and divide it by the probability of it being picked. In an ideal case you want to have the sampling probability proportional the the addends, but since we don't know their values (we wouldn't have to estimate the sum if we knew them), we just estimate them by neglecting some of the factors. In this case, we ignore the incoming light amount and use just the Fresnel reflectance/transmittance as our estimates.

The BSDF sampling routine for the case of smooth Fresnel surface is, therefore, to pick one of the directions randomly with probability proportional to the the Fresnel reflectance and, at some point, divide the result for that direction by probability of picking the direction. The estimator will look like:

$$
\frac
{L\_{i}\left(\omega\_{i}\right)F\left(\theta\_{i}\right)}
{P\left(\omega\_{i}\right)} =
\frac
{L\_{i}\left(\omega\_{i}\right)F\left(\theta\_{i}\right)}
{F\left(\theta\_{i}\right)} =
L\_{i}\left(\omega\_{i}\right)
$$

Where $\omega\_{i}=\left( \phi\_{i}, \theta\_{i} \right)$ is the chosen incident light direction, $L\_{i}\left(\omega\_{i}\right)$ is the amount of incident radiance, $F\left(\theta\_{i}\right)$ is either the Fresnel reflectance for the reflection case or 1 - Fresnel reflectance for the refraction case, $P\left(\omega\_{i}\right)$ is the discrete probability of picking the direction and is equal to $F\left(\theta\_{i}\right)$.

In case of more sophisticated BSDF models like those based on microfacet theory, the sampling is slightly more complex, but the idea of splitting the whole integral into a finite sum of sub-integrals and using discrete Monte Carlo afterwards can usually be applied too.

> **Comments:**
> **username_3**: This is interesting but I'm confused by one point. Could you clarify what it means to "divide the result for that direction by probability of picking the direction"? If it is not a binary choice but a direction chosen from a continuous distribution, won't the probability be zero?  
> **username_0**: Thank you! This helps a lot. The method you describe will work for ideal Fresnel surfaces. And I just discovered Walter et. al. [2007] and Burley [2015], which can be used for rough BSDFs.  
> **username_2**: @username_3: Yes it would, but in that paragraph I was describing the sampling technique just for a (dielectric) Fresnel BSDF - ideally smooth surface, which is a sum of two Dirac delta functions. In such case you are picking one of the directions with some discrete probability. In case of a non-delta (finite) BSDF, you generate directions according to a probability density function. Unfortunately, delta and non-delta cases have to be handled separately, which makes the code a little messy. More details on sampling microfacet BSDFs can be found, for example in the Walter et. al. [2007] paper.  
> **username_2**: @username_0: Walter et. al. [2007] is basically still the state-of-the art for dielectric rough surfaces, but to make it work well you need a good sampling which was published just recently by Heitz and D'Eon the 2014 paper "Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals". And note that it is a single-scattering model which neglects inter-reflections between microfacets making it visibly dark for higher roughness values. See my question "Compensation for energy loss in single-scattering microfacet BSDF models" for more details.  
> **username_4**: Just wanted to point out that if you choose probability = fresnel() as the question suggested, then when you divide by the probability, you cancel out the Fresnel factor that would normally be multiplied in. So (in the discrete, two-Dirac case) you end up with the ray contribution not including any Fresnel factor at all. It's standard importance-sampling theory, but I thought I'd point that out as a potentially confusing issue.  
> **username_2**: @username_4, that's actually a very good point. I'm glad you mentioned it.  
> **username_2**: @username_4, I incorporated your notice into the answer.  
> **username_0**: I got it to work! http://i.imgur.com/m1fYRdr.png  
> **username_2**: @username_0: Cool, but does your glass attenuate light? If it doesn't, the object should not be visible under constant illumination I'm afraid.  
> **username_0**: Currently, the BTDF just returns the surface Albedo, (which is float3(0.95) in this render). If I set it to float3(1.0), yes, it will disappear. Implementing Beer-Lambert is my next task.  

---

