float4 ApplyCookTorrance(float3 InNormal, float3 InWorld) { float3 PixelToEye = normalize(EyePos - InWorld); float3 HalfVector = normalize(LightVector + PixelToEye); float NdotH = max(0.0f, dot(InNormal, HalfVector)); float3 RoughnessParams = {0.5f, 0.5f, 0.5f}; //Start the "D" term, use Blinn Gaussian float Alpha = acos(NdotH); float C = RoughnessParams.x; float m = RoughnessParams.y; float D = C * exp(-(pow(Alpha / m, 2.0f))); //Start the "G" term float NdotV = dot(InNormal, PixelToEye); float VdotH = dot(HalfVector, PixelToEye); float NdotL = dot(LightVector, InNormal); float G1 = 2 * NdotH * NdotV / NdotH; float G2 = 2 * NdotH * NdotL / NdotH; float G = min(1.0f, max(0.0f, min(G1, G2))); //Start the fresnel term. Use the approximation from //http://developer.nvidia.com/docs/IO/3035/ATT/FresnelReflection.pdf float R0 = RoughnessParams.z; float F = R0 + (1.0f - R0) * pow(1.0f - NdotL, 5.0); float4 DiffuseColor = {1.0f, 1.0f, 1.0f, 1.0f}; return DiffuseColor * F * D * G / (NdotL * NdotV); }