float Vis_SmithJointApprox(float Roughness, float NoV, float NoL) { float a = Roughness * Roughness; float Vis_SmithV = NoL * (NoV * (1.0 - a) + a); float Vis_SmithL = NoV * (NoL * (1.0 - a) + a); return 0.5 / (Vis_SmithV + Vis_SmithL); } Vector2 IntegrateBRDF(Vector2 Random, float Roughness, float NoV){ Vector3 V; V.x = sqrt(1.0 - NoV * NoV);// sin; V.y = 0; V.z = NoV;// # cos float A = 0; float B = 0; int NumSamples = 128; for (int i = 0;i < NumSamples;i++){ Vector2 E = Hammersley(i, NumSamples, Random); Vector3 H = ImportanceSampleGGX(E, Roughness); Vector3 L = H * (2 * V.dot(H)) - V; float NoL = saturate(L.z); float NoH = saturate(H.z); float VoH = saturate(V.dot(H)); if (NoL > 0){ float Vis = Vis_SmithJointApprox(Roughness, NoV, NoL); //#Incident light = NoL //#pdf = D * NoH / (4 * VoH) //#NoL * Vis / pdf float NoL_Vis_PDF = NoL * Vis * (4 * VoH / NoH); float Fc = pow(1 - VoH, 5); A += (1 - Fc) * NoL_Vis_PDF; B += Fc * NoL_Vis_PDF; } } return Vector2(A / NumSamples, B / NumSamples); }