diff options
Diffstat (limited to 'brdf.cginc')
| -rw-r--r-- | brdf.cginc | 29 |
1 files changed, 19 insertions, 10 deletions
@@ -1,6 +1,7 @@ #ifndef __BRDF_INC #define __BRDF_INC +#include "pema99.cginc" #include "pbr.cginc" #include "lighting.cginc" #include "lysenko.cginc" @@ -184,14 +185,14 @@ float4 brdf(Pbr pbr, LightData data) { #if defined(FORWARD_BASE_PASS) { float remainder = 1.0f; - float2 dfg_uv = float2(data.common.NoV, pbr.roughness); + float2 dfg_uv = float2(pbr.roughness, data.common.NoV); #if defined(_CLEARCOAT) float cc_f0 = 0.04f; float Fcc = F_Schlick(data.common.NoV, cc_f0, 1.0f); float3 indirect_specular_cc = Fcc * data.indirect.specular_cc * pbr.cc_strength; specular += indirect_specular_cc; - remainder *= (1.0f - Fcc * pbr.cc_strength); + remainder -= Fcc * pbr.cc_strength; #endif #if defined(_CLOTH_SHEEN) @@ -201,19 +202,27 @@ float4 brdf(Pbr pbr, LightData data) { // Energy conservation for cloth is tricky with IBL. // A simple approximation is to use the Fresnel of the sheen layer. float Fcl = F_Schlick(data.common.NoV, 0.04, 1.0); - remainder *= (1.0f - Fcl * pbr.cl_strength); + remainder -= Fcl * pbr.cl_strength; #endif // Standard PBR IBL using split-sum approximation - float2 dfg = _DFG_LUT.Sample(bilinear_clamp_s, dfg_uv).rg; - float3 f0_spec = lerp(0.04f, pbr.albedo.xyz, pbr.metallic); + // Specular lobe + float2 dfg; + [branch] + if (textureExists(_DFG_LUT)) { + dfg = _DFG_LUT.SampleLevel(bilinear_clamp_s, dfg_uv, 0).rg; + } else { + dfg = float2(0, 1); + } + float3 f0_spec = lerp(f0, pbr.albedo.xyz, pbr.metallic); float3 ibl_specular_reflectance = f0_spec * dfg.x + dfg.y; float3 indirect_specular = data.indirect.specular * ibl_specular_reflectance; - specular += indirect_specular * remainder; - - // For energy conservation with the diffuse term, we use the view-dependent Fresnel. - float3 F = F_Schlick(data.common.NoV, f0_spec, 1.0f); - remainder *= (1.0f - F); + // surface reduction term lifted from here: + // UnityStandardBRDF.cginc :: BRDF1_Unity_PBS + float surface_reduction = 1.0f / (pbr.roughness * pbr.roughness + 1.0f); + const float F = F_Schlick(data.indirect.NoL, f0_spec, f90); + specular += surface_reduction * indirect_specular * F; + remainder -= F; // Diffuse is Lambertian, which is pre-integrated into the SH diffuse probe float3 indirect_diffuse = pbr.albedo.xyz * data.indirect.diffuse * remainder * (1.0 - pbr.metallic); |
