summaryrefslogtreecommitdiffstats
path: root/brdf.cginc
diff options
context:
space:
mode:
Diffstat (limited to 'brdf.cginc')
-rw-r--r--brdf.cginc29
1 files changed, 19 insertions, 10 deletions
diff --git a/brdf.cginc b/brdf.cginc
index 5a24307..d89558c 100644
--- a/brdf.cginc
+++ b/brdf.cginc
@@ -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);