diff --git a/package/Shaders/Common/BRDF.hlsli b/package/Shaders/Common/BRDF.hlsli new file mode 100644 index 0000000000..8f1faf4489 --- /dev/null +++ b/package/Shaders/Common/BRDF.hlsli @@ -0,0 +1,216 @@ +#ifndef __BRDF_DEPENDENCY_HLSL__ +#define __BRDF_DEPENDENCY_HLSL__ + +#include "Common/Math.hlsli" + +namespace BRDF +{ + // N = Normal of the macro surface + // H = Normal of the micro surface (halfway vector between L and V) + // L = Light direction from surface point to light + // V = View direction from surface point to camera + + // D = Distribution (Microfacet NDF) + // F = Fresnel + // Vis = Visibility (Self-shadowing and masking) + // Specular BRDF = D * Vis * F + + // Diffuse BRDFs + float Diffuse_Lambert() + { + return 1.0 / Math::PI; + } + + // [Burley 2012, "Physically-Based Shading at Disney"] + float3 Diffuse_Burley(float roughness, float NdotV, float NdotL, float VdotH) + { + float FD90 = 0.5 + 2.0 * VdotH * VdotH * roughness; + float FdV = 1.0 + (FD90 - 1.0) * pow(1.0 - NdotV, 5.0); + float FdL = 1.0 + (FD90 - 1.0) * pow(1.0 - NdotL, 5.0); + return (1.0 / Math::PI) * (FdV * FdL); + } + + // [Gotanda 2012, "Beyond a Simple Physically Based Blinn-Phong Model in Real-Time"] + float3 Diffuse_OrenNayar(float roughness, float3 N, float3 V, float3 L, float NdotV, float NdotL) + { + float a = roughness * roughness * 0.25; + float A = 1.0 - 0.5 * (a / (a + 0.33)); + float B = 0.45 * (a / (a + 0.09)); + + float gamma = dot(V - N * NdotV, L - N * NdotL) / (sqrt(saturate(1.0 - NdotV * NdotV)) * sqrt(saturate(1.0 - NdotL * NdotL))); + + float2 cos_alpha_beta = NdotV < NdotL ? float2(NdotV, NdotL) : float2(NdotL, NdotV); + float2 sin_alpha_beta = sqrt(saturate(1.0 - cos_alpha_beta * cos_alpha_beta)); + float C = sin_alpha_beta.x * sin_alpha_beta.y / (1e-6 + cos_alpha_beta.y); + + return (1 / Math::PI) * (A + B * max(0.0, gamma) * C); + } + + // [Gotanda 2014, "Designing Reflectance Models for New Consoles"] + float3 Diffuse_Gotanda(float roughness, float NdotV, float NdotL, float VdotL) + { + float a = roughness * roughness; + float a2 = a * a; + float F0 = 0.04; + float Cosri = VdotL - NdotV * NdotL; + float Fr = (1 - (0.542026 * a2 + 0.303573 * a) / (a2 + 1.36053)) * (1 - pow(1 - NdotV, 5 - 4 * a2) / (a2 + 1.36053)) * ((-0.733996 * a2 * a + 1.50912 * a2 - 1.16402 * a) * pow(1 - NdotV, 1 + rcp(39 * a2 * a2 + 1)) + 1); + float Lm = (max(1 - 2 * a, 0) * (1 - pow(1 - NdotL, 5)) + min(2 * a, 1)) * (1 - 0.5 * a * (NdotL - 1)) * NdotL; + float Vd = (a2 / ((a2 + 0.09) * (1.31072 + 0.995584 * NdotV))) * (1 - pow(1 - NdotL, (1 - 0.3726732 * NdotV * NdotV) / (0.188566 + 0.38841 * NdotV))); + float Bp = Cosri < 0 ? 1.4 * NdotV * NdotL * Cosri : Cosri; + float Lr = (21.0 / 20.0) * (1 - F0) * (Fr * Lm + Vd + Bp); + return (1 / Math::PI) * Lr; + } + + // [ Chan 2018, "Material Advances in Call of Duty: WWII" ] + float3 Diffuse_Chan(float roughness, float NdotV, float NdotL, float VdotH, float NdotH) + { + float a = roughness * roughness; + float a2 = a * a; + float g = saturate((1.0 / 18.0) * log2(2 * rcp(a2) - 1)); + + float F0 = VdotH + pow(1 - VdotH, 5); + float FdV = 1 - 0.75 * pow(1 - NdotV, 5); + float FdL = 1 - 0.75 * pow(1 - NdotL, 5); + + float Fd = lerp(F0, FdV * FdL, saturate(2.2 * g - 0.5)); + + float Fb = ((34.5 * g - 59) * g + 24.5) * VdotH * exp2(-max(73.2 * g - 21.2, 8.9) * sqrt(NdotH)); + + return (1 / Math::PI) * (Fd + Fb); + } + + // Specular BRDFs + // [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"] + float3 F_Schlick(float3 specularColor, float VdotH) + { + float Fc = pow(1 - VdotH, 5); + return Fc + (1 - Fc) * specularColor; + } + + float3 F_Schlick(float3 F0, float3 F90, float VdotH) + { + float Fc = pow(1 - VdotH, 5); + return F0 + (F90 - F0) * Fc; + } + + // [Kutz et al. 2021, "Novel aspects of the Adobe Standard Material" ] + float3 F_AdobeF82(float3 F0, float3 F82, float VdotH) + { + const float Fc = pow(1 - VdotH, 5); + const float K = 49.0 / 46656.0; + float3 b = (K - K * F82) * (7776.0 + 9031.0 * F0); + return saturate(F0 + Fc * ((1 - F0) - b * (VdotH - VdotH * VdotH))); + } + + // [Beckmann 1963, "The scattering of electromagnetic waves from rough surfaces"] + float D_Beckmann(float roughness, float NdotH) + { + float NdotH2 = NdotH * NdotH; + float a = roughness * roughness; + float a2 = a * a; + return exp((NdotH2 - 1.0) / (a2 * NdotH2)) / (Math::PI * a2 * NdotH2 * NdotH2); + } + + // [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"] + float D_GGX(float roughness, float NdotH) + { + float NdotH2 = NdotH * NdotH; + float a = roughness * roughness; + float a2 = a * a; + float d = NdotH2 * (a2 - 1.0) + 1.0; + return (a2 / (Math::PI * d * d)); + } + + // [Burley 2012, "Physically-Based Shading at Disney"] + float D_AnisoGGX(float alphaX, float alphaY, float NdotH, float XdotH, float YdotH) + { + float d = XdotH * XdotH / (alphaX * alphaX) + YdotH * YdotH / (alphaY * alphaY) + NdotH * NdotH; + return rcp(Math::PI * alphaX * alphaY * d * d); + } + + // [Estevez et al. 2017, "Production Friendly Microfacet Sheen BRDF"] + float D_Charlie(float roughness, float NdotH) + { + float invAlpha = pow(roughness, -4); + float cos2h = NdotH * NdotH; + float sin2h = max(1.0 - cos2h, 1e-5); + return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / Math::TAU; + } + + // Smith term for GGX + // [Smith 1967, "Geometrical shadowing of a random rough surface"] + float Vis_Smith(float roughness, float NdotV, float NdotL) + { + float a = roughness * roughness; + float a2 = a * a; + float Vis_SmithV = NdotV + sqrt(a2 + (1.0 - a2) * NdotV * NdotV); + float Vis_SmithL = NdotL + sqrt(a2 + (1.0 - a2) * NdotL * NdotL); + return rcp(Vis_SmithV * Vis_SmithL); + } + + // Appoximation of joint Smith term for GGX + // [Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"] + float Vis_SmithJointApprox(float roughness, float NdotV, float NdotL) + { + float a = roughness * roughness; + float Vis_SmithV = NdotL * (NdotV * (1.0 + a) + a); + float Vis_SmithL = NdotV * (NdotL * (1.0 + a) + a); + return rcp(Vis_SmithV + Vis_SmithL) * 0.5; + } + + float Vis_SmithJoint(float roughness, float NdotV, float NdotL) + { + float a = roughness * roughness; + float a2 = a * a; + float Vis_SmithV = NdotL * sqrt(a2 + (1.0 - a2) * NdotV * NdotV); + float Vis_SmithL = NdotV * sqrt(a2 + (1.0 - a2) * NdotL * NdotL); + return rcp(Vis_SmithV + Vis_SmithL) * 0.5; + } + + float Vis_SmithJointAniso(float alphaX, float alphaY, float NdotL, float NdotV, float XdotL, float YdotL, float XdotV, float YdotV) + { + float Vis_SmithV = NdotL * length(float3(alphaX * XdotV, alphaY * YdotV, NdotV)); + float Vis_SmithL = NdotV * length(float3(alphaX * XdotL, alphaY * YdotL, NdotL)); + return rcp(Vis_SmithV + Vis_SmithL) * 0.5; + } + + // [Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF"] + float Vis_Charlie_L(float x, float r) + { + r = saturate(r); + r = 1.0 - (1.0 - r) * (1.0 - r); + float a = lerp(25.3245 , 21.5473 , r); + float b = lerp( 3.32435, 3.82987, r); + float c = lerp( 0.16801, 0.19823, r); + float d = lerp(-1.27393, -1.97760, r); + float e = lerp(-4.85967, -4.32054, r); + + return a * rcp((1 + b * pow(x, c)) + d * x + e); + } + + float Vis_Charlie(float roughness, float NdotV, float NdotL) + { + float visV = NdotV < 0.5 ? exp(Vis_Charlie_L(NdotV, roughness)) : exp(2.0 * Vis_Charlie_L(0.5, roughness) - Vis_Charlie_L(1.0 - NdotV, roughness)); + float visL = NdotL < 0.5 ? exp(Vis_Charlie_L(NdotL, roughness)) : exp(2.0 * Vis_Charlie_L(0.5, roughness) - Vis_Charlie_L(1.0 - NdotL, roughness)); + return rcp(((1.0 + visV + visL) * (4.0 * NdotL * NdotV))); + } + + // [Neubelt et al. 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"] + float Vis_Neubelt(float NdotV, float NdotL) + { + return rcp(4.0 * (NdotL + NdotV - NdotL * NdotV)); + } + + // [Lazarov 2013, "Getting More Physical in Call of Duty: Black Ops II"] + float2 EnvBRDFApproxLazarov(float roughness, float NdotV) + { + const float4 c0 = { -1, -0.0275, -0.572, 0.022 }; + const float4 c1 = { 1, 0.0425, 1.04, -0.04 }; + float4 r = roughness * c0 + c1; + float a004 = min(r.x * r.x, exp2(-9.28 * NdotV)) * r.x + r.y; + float2 AB = float2(-1.04, 1.04) * a004 + r.zw; + return AB; + } +} + +#endif // __BRDF_DEPENDENCY_HLSL__ \ No newline at end of file diff --git a/package/Shaders/Common/PBR.hlsli b/package/Shaders/Common/PBR.hlsli index 4139f89e7a..24205e1f6d 100644 --- a/package/Shaders/Common/PBR.hlsli +++ b/package/Shaders/Common/PBR.hlsli @@ -1,6 +1,7 @@ #ifndef __PBR_DEPENDENCY_HLSL__ #define __PBR_DEPENDENCY_HLSL__ +#include "Common/BRDF.hlsli" #include "Common/Color.hlsli" #include "Common/Math.hlsli" #include "Common/SharedData.hlsli" @@ -149,58 +150,19 @@ namespace PBR return saturate(pow(NdotV + ao, exp2(-16.0 * roughness - 1.0)) - 1.0 + ao); } - // [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"] - float3 GetFresnelFactorSchlick(float3 specularColor, float VdotH) - { - float Fc = pow(1 - VdotH, 5); - return Fc + (1 - Fc) * specularColor; - } - - // [Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"] - float GetVisibilityFunctionSmithJointApprox(float roughness, float NdotV, float NdotL) - { - float a = roughness * roughness; - float visSmithV = NdotL * (NdotV * (1 - a) + a); - float visSmithL = NdotV * (NdotL * (1 - a) + a); - return 0.5 * rcp(visSmithV + visSmithL); - } - - // [Neubelt et al. 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886"] - float GetVisibilityFunctionNeubelt(float NdotV, float NdotL) - { - return rcp(4 * (NdotL + NdotV - NdotL * NdotV)); - } - - // [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"] - float GetNormalDistributionFunctionGGX(float roughness, float NdotH) - { - float a2 = pow(roughness, 4); - float d = max((NdotH * a2 - NdotH) * NdotH + 1, 1e-5); - return a2 / (Math::PI * d * d); - } - - // [Estevez et al. 2017, "Production Friendly Microfacet Sheen BRDF"] - float GetNormalDistributionFunctionCharlie(float roughness, float NdotH) - { - float invAlpha = pow(roughness, -4); - float cos2h = NdotH * NdotH; - float sin2h = max(1.0 - cos2h, 1e-5); - return (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / Math::TAU; - } - #if defined(GLINT) float3 GetSpecularDirectLightMultiplierMicrofacetWithGlint(float noise, float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, float glintH, float logDensity, float microfacetRoughness, float densityRandomization, Glints::GlintCachedVars glintCache, out float3 F) { - float D = GetNormalDistributionFunctionGGX(roughness, NdotH); + float D = BRDF::D_GGX(roughness, NdotH); [branch] if (logDensity > 1.1) { - float D_max = GetNormalDistributionFunctionGGX(roughness, 1); + float D_max = BRDF::D_GGX(roughness, 1); D = Glints::SampleGlints2023NDF(noise, logDensity, microfacetRoughness, densityRandomization, glintCache, glintH, D, D_max).x; } - float G = GetVisibilityFunctionSmithJointApprox(roughness, NdotV, NdotL); - F = GetFresnelFactorSchlick(specularColor, VdotH); + float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL); + F = BRDF::F_Schlick(specularColor, VdotH); return D * G * F; } @@ -208,96 +170,22 @@ namespace PBR float3 GetSpecularDirectLightMultiplierMicrofacet(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, out float3 F) { - float D = GetNormalDistributionFunctionGGX(roughness, NdotH); - float G = GetVisibilityFunctionSmithJointApprox(roughness, NdotV, NdotL); - F = GetFresnelFactorSchlick(specularColor, VdotH); + float D = BRDF::D_GGX(roughness, NdotH); + float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL); + F = BRDF::F_Schlick(specularColor, VdotH); return D * G * F; } float3 GetSpecularDirectLightMultiplierMicroflakes(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH) { - float D = GetNormalDistributionFunctionCharlie(roughness, NdotH); - float G = GetVisibilityFunctionNeubelt(NdotV, NdotL); - float3 F = GetFresnelFactorSchlick(specularColor, VdotH); + float D = BRDF::D_Charlie(roughness, NdotH); + float G = BRDF::Vis_Neubelt(NdotV, NdotL); + float3 F = BRDF::F_Schlick(specularColor, VdotH); return D * G * F; } - float GetDiffuseDirectLightMultiplierLambert() - { - return 1 / Math::PI; - } - - // [Burley 2012, "Physically-Based Shading at Disney"] - float3 GetDiffuseDirectLightMultiplierBurley(float roughness, float NdotV, float NdotL, float VdotH) - { - float Fd90 = 0.5 + 2 * VdotH * VdotH * roughness; - float FdV = 1 + (Fd90 - 1) * pow(1 - NdotV, 5); - float FdL = 1 + (Fd90 - 1) * pow(1 - NdotL, 5); - return (1 / Math::PI) * FdV * FdL; - } - - // [Oren et al. 1994, "Generalization of Lambert’s Reflectance Model"] - float3 GetDiffuseDirectLightMultiplierOrenNayar(float roughness, float3 N, float3 V, float3 L, float NdotV, float NdotL) - { - float a = roughness * roughness * 0.25; - float A = 1.0 - 0.5 * (a / (a + 0.33)); - float B = 0.45 * (a / (a + 0.09)); - - float gamma = dot(V - N * NdotV, L - N * NdotL) / (sqrt(saturate(1.0 - NdotV * NdotV)) * sqrt(saturate(1.0 - NdotL * NdotL))); - - float2 cos_alpha_beta = NdotV < NdotL ? float2(NdotV, NdotL) : float2(NdotL, NdotV); - float2 sin_alpha_beta = sqrt(saturate(1.0 - cos_alpha_beta * cos_alpha_beta)); - float C = sin_alpha_beta.x * sin_alpha_beta.y / (1e-6 + cos_alpha_beta.y); - - return (1 / Math::PI) * (A + B * max(0.0, gamma) * C); - } - - // [Gotanda 2014, "Designing Reflectance Models for New Consoles"] - float3 GetDiffuseDirectLightMultiplierGotanda(float roughness, float NdotV, float NdotL, float VdotL) - { - float a = roughness * roughness; - float a2 = a * a; - float F0 = 0.04; - float Cosri = VdotL - NdotV * NdotL; - float Fr = (1 - (0.542026 * a2 + 0.303573 * a) / (a2 + 1.36053)) * (1 - pow(1 - NdotV, 5 - 4 * a2) / (a2 + 1.36053)) * ((-0.733996 * a2 * a + 1.50912 * a2 - 1.16402 * a) * pow(1 - NdotV, 1 + rcp(39 * a2 * a2 + 1)) + 1); - float Lm = (max(1 - 2 * a, 0) * (1 - pow(1 - NdotL, 5)) + min(2 * a, 1)) * (1 - 0.5 * a * (NdotL - 1)) * NdotL; - float Vd = (a2 / ((a2 + 0.09) * (1.31072 + 0.995584 * NdotV))) * (1 - pow(1 - NdotL, (1 - 0.3726732 * NdotV * NdotV) / (0.188566 + 0.38841 * NdotV))); - float Bp = Cosri < 0 ? 1.4 * NdotV * NdotL * Cosri : Cosri; - float Lr = (21.0 / 20.0) * (1 - F0) * (Fr * Lm + Vd + Bp); - return (1 / Math::PI) * Lr; - } - - // [Chan 2018, "Material Advances in Call of Duty: WWII"] - float3 GetDiffuseDirectLightMultiplierChan(float roughness, float NdotV, float NdotL, float VdotH, float NdotH) - { - float a = roughness * roughness; - float a2 = a * a; - float g = saturate((1.0 / 18.0) * log2(2 * rcp(a2) - 1)); - - float F0 = VdotH + pow(1 - VdotH, 5); - float FdV = 1 - 0.75 * pow(1 - NdotV, 5); - float FdL = 1 - 0.75 * pow(1 - NdotL, 5); - - float Fd = lerp(F0, FdV * FdL, saturate(2.2 * g - 0.5)); - - float Fb = ((34.5 * g - 59) * g + 24.5) * VdotH * exp2(-max(73.2 * g - 21.2, 8.9) * sqrt(NdotH)); - - return (1 / Math::PI) * (Fd + Fb); - } - - // [Lazarov 2013, "Getting More Physical in Call of Duty: Black Ops II"] - float2 GetEnvBRDFApproxLazarov(float roughness, float NdotV) - { - const float4 c0 = { -1, -0.0275, -0.572, 0.022 }; - const float4 c1 = { 1, 0.0425, 1.04, -0.04 }; - float4 r = roughness * c0 + c1; - float a004 = min(r.x * r.x, exp2(-9.28 * NdotV)) * r.x + r.y; - float2 AB = float2(-1.04, 1.04) * a004 + r.zw; - return AB; - } - float HairIOR() { const float n = 1.55; @@ -354,14 +242,14 @@ namespace PBR // R Mp = HairGaussian(B[0], ThetaH - Alpha[0]); Np = 0.25 * cosHalfPhi; - Fp = GetFresnelFactorSchlick(specularColor, sqrt(saturate(0.5 + 0.5 * VdotL))).x; + Fp = BRDF::F_Schlick(specularColor, sqrt(saturate(0.5 + 0.5 * VdotL))).x; S += (Mp * Np) * (Fp * lerp(1, backlit, saturate(-VdotL))); // TT Mp = HairGaussian(B[1], ThetaH - Alpha[1]); a = (1.55f / hairIOR) * rcp(n_prime); h = cosHalfPhi * (1 + a * (0.6 - 0.8 * cosPhi)); - f = GetFresnelFactorSchlick(specularColor, cosThetaD * sqrt(saturate(1 - h * h))).x; + f = BRDF::F_Schlick(specularColor, cosThetaD * sqrt(saturate(1 - h * h))).x; Fp = (1 - f) * (1 - f); Tp = pow(surfaceProperties.BaseColor, 0.5 * sqrt(1 - (h * a) * (h * a)) / cosThetaD); Np = exp(-3.65 * cosPhi - 3.98); @@ -369,7 +257,7 @@ namespace PBR // TRT Mp = HairGaussian(B[2], ThetaH - Alpha[2]); - f = GetFresnelFactorSchlick(specularColor, cosThetaD * 0.5f).x; + f = BRDF::F_Schlick(specularColor, cosThetaD * 0.5f).x; Fp = (1 - f) * (1 - f) * f; Tp = pow(surfaceProperties.BaseColor, 0.8 / cosThetaD); Np = exp(17 * cosPhi - 16.78); @@ -435,7 +323,7 @@ namespace PBR else #endif { - diffuse += lightProperties.LightColor * satNdotL * GetDiffuseDirectLightMultiplierLambert(); + diffuse += lightProperties.LightColor * satNdotL * BRDF::Diffuse_Lambert(); float3 F; #if defined(GLINT) @@ -446,7 +334,7 @@ namespace PBR specular += GetSpecularDirectLightMultiplierMicrofacet(surfaceProperties.Roughness, surfaceProperties.F0, satNdotL, satNdotV, satNdotH, satVdotH, F) * lightProperties.LightColor * satNdotL; #endif - float2 specularBRDF = GetEnvBRDFApproxLazarov(surfaceProperties.Roughness, satNdotV); + float2 specularBRDF = BRDF::EnvBRDFApproxLazarov(surfaceProperties.Roughness, satNdotV); specular *= 1 + surfaceProperties.F0 * (1 / (specularBRDF.x + specularBRDF.y) - 1); #if !defined(LANDSCAPE) && !defined(LODLANDSCAPE) @@ -464,7 +352,7 @@ namespace PBR float forwardScatter = exp2(saturate(-VdotL) * subsurfacePower - subsurfacePower); float backScatter = saturate(satNdotL * surfaceProperties.Thickness + (1.0 - surfaceProperties.Thickness)) * 0.5; float subsurface = lerp(backScatter, 1, forwardScatter) * (1.0 - surfaceProperties.Thickness); - transmission += surfaceProperties.SubsurfaceColor * subsurface * lightProperties.LightColor * GetDiffuseDirectLightMultiplierLambert(); + transmission += surfaceProperties.SubsurfaceColor * subsurface * lightProperties.LightColor * BRDF::Diffuse_Lambert(); } else if ((PBRFlags & Flags::TwoLayer) != 0) { @@ -489,7 +377,7 @@ namespace PBR diffuse *= layerAttenuation; specular *= layerAttenuation; - coatDiffuse += lightProperties.CoatLightColor * coatNdotL * GetDiffuseDirectLightMultiplierLambert(); + coatDiffuse += lightProperties.CoatLightColor * coatNdotL * BRDF::Diffuse_Lambert(); specular += coatSpecular * surfaceProperties.CoatStrength; } #endif @@ -544,7 +432,7 @@ namespace PBR } #endif - float2 specularBRDF = GetEnvBRDFApproxLazarov(surfaceProperties.Roughness, NdotV); + float2 specularBRDF = BRDF::EnvBRDFApproxLazarov(surfaceProperties.Roughness, NdotV); specularLobeWeight = surfaceProperties.F0 * specularBRDF.x + specularBRDF.y; diffuseLobeWeight *= (1 - specularLobeWeight); @@ -553,11 +441,11 @@ namespace PBR #if !defined(LANDSCAPE) && !defined(LODLANDSCAPE) [branch] if ((PBRFlags & Flags::TwoLayer) != 0) { - float2 coatSpecularBRDF = GetEnvBRDFApproxLazarov(surfaceProperties.CoatRoughness, NdotV); + float2 coatSpecularBRDF = BRDF::EnvBRDFApproxLazarov(surfaceProperties.CoatRoughness, NdotV); float3 coatSpecularLobeWeight = surfaceProperties.CoatF0 * coatSpecularBRDF.x + coatSpecularBRDF.y; coatSpecularLobeWeight *= 1 + surfaceProperties.CoatF0 * (1 / (coatSpecularBRDF.x + coatSpecularBRDF.y) - 1); - float3 coatF = GetFresnelFactorSchlick(surfaceProperties.CoatF0, NdotV); + float3 coatF = BRDF::F_Schlick(surfaceProperties.CoatF0, NdotV); float3 layerAttenuation = 1 - coatF * surfaceProperties.CoatStrength; diffuseLobeWeight *= layerAttenuation; @@ -596,7 +484,7 @@ namespace PBR const float wetnessF0 = 0.02; float NdotV = saturate(abs(dot(N, V)) + 1e-5); - float2 specularBRDF = GetEnvBRDFApproxLazarov(roughness, NdotV); + float2 specularBRDF = BRDF::EnvBRDFApproxLazarov(roughness, NdotV); float3 specularLobeWeight = wetnessF0 * specularBRDF.x + specularBRDF.y; // Horizon specular occlusion