#ifndef __BRDF_INC #define __BRDF_INC #include "pbr.cginc" #include "lighting.cginc" #include "lysenko.cginc" #include "math.cginc" // Schlick "An Inexpensive BRDF Model for Physically-based Rendering". // Equation 24. // f0: Reflectance at normal incidence. Typically around 0.04. // f90: Reflectance at grazing incidence. Typically around 1.0. float F_Schlick(float LoH, float f0, float f90) { float term = 1.0f - LoH; float term2 = term * term; float term5 = term2 * term2 * term; return f0 + (f90 - f0) * term5; } float4 brdf(Pbr pbr, LightData data) { float3 specular = 0; float3 diffuse = 0; // Direct if (true) { float F = F_Schlick(data.direct.LoH, 0.04f, 1.0f); float D = D_GGX(pbr.roughness, data.direct.NoH, data.direct.H); float V = V_SmithGGXCorrelated_Fast(pbr.roughness, data.common.NoV, data.direct.NoL); float denom = 4.0f * data.common.NoV * data.direct.NoL; float FDV = denom > _BRDF_Specular_Min_Denom ? F * D * V / denom : 0.0f; specular += FDV * data.direct.color * data.direct.NoL; float Fd = Fd_OrenNayar(pbr.roughness, data.common.NoV, data.direct.NoL, data.direct.LoV); float3 remainder = (1.0f - F); diffuse += (Fd / PI) * remainder * pbr.albedo.xyz * data.direct.color; remainder *= (1.0f - (Fd / PI) * pbr.albedo); } // Indirect if (true) { float F = F_Schlick(data.indirect.LoH, 0.04f, 1.0f); specular += F * data.indirect.specular; float Fd = 1.0f; // Lambertian divide is baked into SH float3 remainder = (1.0f - F); diffuse += Fd * remainder * pbr.albedo.xyz * data.indirect.diffuse; remainder *= (1.0f - Fd * pbr.albedo); } return float4(diffuse + specular, 1); } #endif // __BRDF_INC