 vec3 indirect_lighting(inout uint s){
     const material mat = getMaterial();
     const vec3 V = normalize(eye - P);
-    const vec3 R = reflect(-V, mat.normal);
-    const int samples = 64;
-    const float scaling = 1.0 / float(samples);
+    vec3 T, B;
+    findBasis(mat.normal, T, B);
     
+    const float samples = 6.0;
+    const float scaling = 1.0 / samples;
+
     vec3 light = vec3(0.0);
-    vec3 u, v;
-    cosHemiUV(mat.normal, u, v);
-    for(int i = 0; i < samples; ++i){
-        const vec3 L = cosHemi(mat.normal, u, v, s);
-        const vec3 radiance = environment_cubemap(L);
-        light += pbr_lighting(V, L, mat, radiance);
-    }
-
-    light *= scaling;
+    for(float x = 0.0; x < samples; ++x){
+        for(float y = 0.0; y < samples; ++y){
+            const vec2 X = vec2(stratRand(x, scaling, s), stratRand(y, scaling, s));
+            const vec3 N = GGXPDF(mat.roughness, X, T, B, mat.normal);
+            const vec3 L = reflect(-V, N);
+            const vec3 radiance = environment_cubemap(L);
+            light += pbr_lighting(V, L, mat, radiance);
+        }
+    }
+
+    light *= (scaling * scaling);
 
     return light;
 }

    const float metalness_multiplier = material_params[MID].metalness_multiplier;

    mat.albedo = pow(albedo.rgb, vec3(2.2));
    mat.roughness = clamp(albedo.a * roughness_multiplier + roughness_offset, 0.01, 0.99);
    mat.normal = normalize(TBN * normalize(normal.xyz * 2.0 - 1.0));
    mat.metalness = clamp(normal.a * metalness_multiplier + metalness_offset, 0.01, 0.99);

    return mat;
}

    vec3 sky = vec3(0.0);
    const material mat = getMaterial();
    sky += max(0.0, pow(dot(mat.normal, -sunDirection), 200.0)) * sunColor * 1000000.0;
    sky += mat.albedo;
    return sky;
}

