1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
inline float GGXTerm (float NdotH, float roughness) { float a2 = roughness * roughness; float d = (NdotH * a2 - NdotH) * NdotH + 1.0f; return a2 /( (d * d + 1e-7f)*PI ); }
float ggx_anisotropic_ndf(float alpha_t, float alpha_b, float ToH, float BoH, float NoH) { vec3 v = vec3(alpha_b*ToH,alpha_t*BoH, alpha_t*alpha_b*NoH); float v2 = dot(v,v); float a2 = alpha_t*alpha_b; float w2 = a2/v2; return( a2*w2*w2*m_i_pi ); }
inline half3 FresnelTerm (half3 F0, half cosA) { half t = Pow5 (1 - cosA); return F0 + (1-F0) * t; }
inline float SmithJointGGXVisibilityTerm (float NdotL, float NdotV, float roughness) { #if 0
half a = roughness; half a2 = a * a;
half lambdaV = NdotL * sqrt((-NdotV * a2 + NdotV) * NdotV + a2); half lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
return 0.5f / (lambdaV + lambdaL + 1e-5f); #else float a = roughness; float lambdaV = NdotL * (NdotV * (1 - a) + a); float lambdaL = NdotV * (NdotL * (1 - a) + a);
#if defined(SHADER_API_SWITCH) return 0.5f / (lambdaV + lambdaL + 1e-4f); #else return 0.5f / (lambdaV + lambdaL + 1e-5f); #endif
#endif }
float CookTorranceBRDF(Surface surface,BRDF brdf,Light light){ float3 HalfDir=normalize(surface.viewDirection+light.direction); float NdotH=saturate(dot(HalfDir,surface.normal)); float LdotH=saturate(dot(light.direction,HalfDir)); float NdotV=saturate(dot(surface.normal,surface.viewDirection)); float NdotL=saturate(dot(surface.normal,light.direction)); float D=GGXTerm(NdotH,brdf.roughness); float F=FresnelTerm(brdf.specular,LdotH); float V = SmithJointGGXVisibilityTerm (LdotH, NdotV, brdf.roughness); float specularTerm=V*D*PI; specularTerm=max(0,specularTerm*LdotH); return specularTerm*F; }
|