I'm reading through this article, and more specifically I'm trying to derive the equation that would explain the implementation the following shader (still in the same article):

#version 330 core
out vec4 FragColor;
in vec3 localPos;

uniform samplerCube environmentMap;
uniform float roughness;

const float PI = 3.14159265359;

float RadicalInverse_VdC(uint bits);
vec2 Hammersley(uint i, uint N);
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);

void main()
    vec3 N = normalize(localPos);    
    vec3 R = N;
    vec3 V = R;

    const uint SAMPLE_COUNT = 1024u;
    float totalWeight = 0.0;   
    vec3 prefilteredColor = vec3(0.0);     
    for(uint i = 0u; i < SAMPLE_COUNT; ++i)
        vec2 Xi = Hammersley(i, SAMPLE_COUNT);
        vec3 H  = ImportanceSampleGGX(Xi, N, roughness);
        vec3 L  = normalize(2.0 * dot(V, H) * H - V);

        float NdotL = max(dot(N, L), 0.0);
        if(NdotL > 0.0)
            prefilteredColor += texture(environmentMap, L).rgb * NdotL;
            totalWeight      += NdotL;
    prefilteredColor = prefilteredColor / totalWeight;

    FragColor = vec4(prefilteredColor, 1.0);

Which is my understanding suppose to implement the computation of the integral

$$ I = \int_{\Omega} L(\omega_i)d\omega_i $$

However I'm not entirely sure since NdotL is also used in the computation so I might be wrong.

It seems to me the idea is given $N$ to sample a random halfway vector $H$, and based on this we can construct, by reflection, the light direction vector $L$, which would be random as well by construction. The article also mentions that $H$ is sampled from a normal distribution.

But anyway suppose I have samples $H^{1} ,\ldots, H^{N}$ and therefore $L^{1},\ldots, L^{N}$ samples, the latter I suppose would define $\omega_{i}^{1} \ldots, \omega_{i}^{N}$ (solid angles).

By importance sampling

$$ I \approx \frac{1}{N} \sum_{j=1}^{N} \frac{L(\omega_i^{j})}{pdf(\omega_i^{j})} \;\;\;\; (1) $$

If what I wrote is correct than I don't know where the dot product and the normalization factor

$$ W = \sum_{j=1}^{N} N\cdot L^{j} $$

comes from, namely how do I go from $(1)$ to

$$ I \approx \frac{\sum_{j=1}^{N}L(\omega_i^{j}) N \cdot L^{j}} {\sum_{j=1}^{N} N \cdot L^{j}} $$

Update: I'm pretty sure many of you know this already, but the shader above is for a pre-filtered environment map. Which means in this context the actual integral should be given by

$$ I(N) = \int_{\Omega} L(\omega_i) N \cdot L d\omega $$

This explains the factor $N \cdot L$ in the shader, the distribution function used is the GGX distribution, I assume plugging this stuff together might give me the formula.

Just updating because it might give a better clue.

  • $\begingroup$ Looks wrong honestly, you cannot get to (1) by importance sampling in any sane manner that I can think of. They are using ggx sampling and do not divide by the pdf, but rather by some sum. Now if they are using a biased estimator of some form, then that's another matter, but I do not believe this was mentioned in the article. I am inclined to believe it's just wrong, try contacting the author. $\endgroup$
    – lightxbulb
    Commented May 24, 2019 at 22:15
  • $\begingroup$ They do mention in the article they divide on purpose for the total sum though. $\endgroup$ Commented May 24, 2019 at 22:27
  • $\begingroup$ Also if you, like me, think it's wrong... What would be the right montecarlo estimator then? $\endgroup$ Commented May 24, 2019 at 22:28
  • $\begingroup$ The shader is a cut and paste of the one shown at page 6 here: blog.selfshadow.com/publications/s2013-shading-course/karis/… . $\endgroup$ Commented May 24, 2019 at 22:57
  • $\begingroup$ "As shown in the code below, we have found weighting by coslk achieves better results1. 1This weighting is not present in Equation 7, which is left in a simpler form" - from the article you linked. They have not provided a reasoning beyond "achieves better results". Or at least I cannot find the part where they formally motivate this. $\endgroup$
    – lightxbulb
    Commented May 25, 2019 at 4:42


Your Answer

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