<p>I just read <a href="https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf" rel="nofollow noreferrer">notes on moving frostbite to pbr</a> and I found the derivation of the method above. So I will just show the derivation here and quote some of the explanation.</p>

<p><a href="https://i.sstatic.net/76tsj.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/76tsj.png" alt="enter image description here"></a></p>

<blockquote>
  <p>One can notice an extra〈n·l〉in the LD term as well as a different
  weighting 1/(∑Ni〈n·l〉). These empirical terms have been introduce by
  Karis to allows to improve the reconstructed lighting integral which
  suffers from coarse hypothesis of separability of this integral. 
  There is no mathematical derivation for these terms, goal was to have
  an exact match with a constant L(l).</p>
</blockquote>

<p>So it turns out the pdf is weighted on the DFG term. As for dot(N,l), the term is introduced to minimize the error that is caused by split sum approximation. But I am actually still wondering what is the intuition on that empirical term.</p>

CC BY-SA 4.0
2018-07-24T09:09:34.783Z
2018-07-24T09:15:43.627Z
2018-07-24T09:15:43.627Z
kevinyu
<p>I am currently trying to understand IBL in Unreal Engine, and there are so much things that I don't understand about the formula. Unreal approximate the specular term of shading equation by doing split sum approximation.</p>

<p><a href="https://i.sstatic.net/77jXZ.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/77jXZ.png" alt="enter image description here"></a></p>

<p>This is how unreal pre-filter the environment map for specular-irradiance term.</p>

<pre><code>float3 PrefilterEnvMap(float Roughness, float3 R )
{
    float3 N = R;
    float3 V = R;
    float3 PrefilteredColor = 0;
    const uint NumSamples = 1024;
    for(uint i = 0; i &lt; NumSamples; i++ )
    {
        float2 Xi = Hammersley( i, NumSamples );
        float3 H = ImportanceSampleGGX( Xi, Roughness, N );
        float3 L = 2 * dot  ( V, H ) * H - V;
        float NoL =saturate( dot  ( N, L ) );
        if ( NoL &gt; 0 )
        {
            PrefilteredColor += EnvMap.SampleLevel( EnvMapSampler, L, 0 ).rgb * NoL;
            TotalWeight += NoL;
        }
    }
    return PrefilteredColor / TotalWeight;
}
</code></pre>

<p>My question is why does the total weight is the sum of saturate(dot(N,L)). My understanding on importance sampling is that we should divide our sample with the pdf we use to sample. In this case, from what I read at <a href="https://schuttejoe.github.io/post/ggximportancesamplingpart1/" rel="nofollow noreferrer">here</a> the pdf should be </p>

<p>$$p_i(wm, wo) = \frac{D(wm)(wm \cdot wg)}{4|wo \cdot wm|}$$</p>

<p>My reference on pbr in unreal engine is <a href="https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf" rel="nofollow noreferrer">here</a> and <a href="https://learnopengl.com/PBR/IBL/Specular-IBL" rel="nofollow noreferrer">here</a>.</p>

<shader><brdf><real-time><pbr><importance-sampling>
Importance Sampling in Unreal Engine Formula Derivation (Irradiance term)
kevinyu
# Importance Sampling in Unreal Engine Formula Derivation (Irradiance term)

(Asked by: username_0 on 2018-07-24)

I am currently trying to understand IBL in Unreal Engine, and there are so much things that I don't understand about the formula. Unreal approximate the specular term of shading equation by doing split sum approximation.

[![enter image description here](https://i.sstatic.net/77jXZ.png)](https://i.sstatic.net/77jXZ.png)

This is how unreal pre-filter the environment map for specular-irradiance term.

```
float3 PrefilterEnvMap(float Roughness, float3 R )
{
    float3 N = R;
    float3 V = R;
    float3 PrefilteredColor = 0;
    const uint NumSamples = 1024;
    for(uint i = 0; i < NumSamples; i++ )
    {
        float2 Xi = Hammersley( i, NumSamples );
        float3 H = ImportanceSampleGGX( Xi, Roughness, N );
        float3 L = 2 * dot  ( V, H ) * H - V;
        float NoL =saturate( dot  ( N, L ) );
        if ( NoL > 0 )
        {
            PrefilteredColor += EnvMap.SampleLevel( EnvMapSampler, L, 0 ).rgb * NoL;
            TotalWeight += NoL;
        }
    }
    return PrefilteredColor / TotalWeight;
}

```

My question is why does the total weight is the sum of saturate(dot(N,L)). My understanding on importance sampling is that we should divide our sample with the pdf we use to sample. In this case, from what I read at [here](https://schuttejoe.github.io/post/ggximportancesamplingpart1/) the pdf should be

$$p\_i(wm, wo) = \frac{D(wm)(wm \cdot wg)}{4|wo \cdot wm|}$$

My reference on pbr in unreal engine is [here](https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf) and [here](https://learnopengl.com/PBR/IBL/Specular-IBL).

**Tags:** shader, brdf, real-time, pbr, importance-sampling


---

## 1 answers

### Answer by username_0 on 2018-07-24. Score: 3 | Accepted answer

I just read [notes on moving frostbite to pbr](https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf) and I found the derivation of the method above. So I will just show the derivation here and quote some of the explanation.

[![enter image description here](https://i.sstatic.net/76tsj.png)](https://i.sstatic.net/76tsj.png)

> One can notice an extra〈n·l〉in the LD term as well as a different
> weighting 1/(∑Ni〈n·l〉). These empirical terms have been introduce by
> Karis to allows to improve the reconstructed lighting integral which
> suffers from coarse hypothesis of separability of this integral.
> There is no mathematical derivation for these terms, goal was to have
> an exact match with a constant L(l).

So it turns out the pdf is weighted on the DFG term. As for dot(N,l), the term is introduced to minimize the error that is caused by split sum approximation. But I am actually still wondering what is the intuition on that empirical term.


---

