         float VdotH = clamp(dot(V, H), 0.0, 1.0);
 
         // Calculate the based on roughness
-        float pdf = D_ggx(NdotH, alpha2);
+        float pdf = D_ggx(NdotH, alpha2) * NdotH / (4 * VdotH);
         float lod = environment_map_lod(environment_map_size, SAMPLES, pdf);
 
         // Sample the environment map

    return vec3(cos(phi) * sin_theta, sin(phi) * sin_theta, cos_theta);
}

// http://www.trentreed.net/blog/physically-based-shading-and-image-based-lighting/
vec3 radiance(vec3 N, vec3 V, vec3 F0, float roughness)
{
    vec3 up_vec = abs(N.z) < 0.999 ? vec3(0, 0, 1) : vec3(1, 0, 0);


void main()
{

    surface s = read_geometry_buffer();

    mat4 inv_view_matrix = inverse(view_matrix); // TODO should be on the cpu
