summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbrdf.cginc26
-rw-r--r--data.cginc59
-rwxr-xr-xlighting.cginc100
-rwxr-xr-xpbr.cginc4
4 files changed, 103 insertions, 86 deletions
diff --git a/brdf.cginc b/brdf.cginc
index da3fcd6..254adc3 100755
--- a/brdf.cginc
+++ b/brdf.cginc
@@ -70,10 +70,6 @@ float4 brdf(Pbr pbr, LightData data) {
float3 specular = 0;
float3 diffuse = 0;
- // TODO parameterize
- float f0 = 0.04f;
- const float f90 = 1.0f;
-
//#define FURNACE_TEST_DIRECT
#if defined(FURNACE_TEST_DIRECT)
// Create the conditions for the standard BRDF furnace test.
@@ -86,6 +82,9 @@ float4 brdf(Pbr pbr, LightData data) {
data.direct.LoH = 1;
#endif
+ // TODO parameterize
+ float f0 = 0.04f;
+ const float f90 = 1.0f;
float2 dfg_uv = float2(data.common.NoV, pbr.roughness_perceptual);
float3 dfg;
[branch]
@@ -107,8 +106,8 @@ float4 brdf(Pbr pbr, LightData data) {
} else {
cc_dfg = float3(1, 1, 1);
}
- float cc_Ess = max(cc_dfg.y, 1e-4f);
- float cc_energy_comp = 1.0f + cc_f0 * (1.0f / cc_dfg.xxx - 1.0f);
+ float3 cc_f0_color = lerp(cc_f0, pbr.albedo.xyz, pbr.metallic);
+ float3 cc_energy_comp = 1.0f + cc_f0_color * (1.0f / (cc_dfg.xxx + cc_dfg.yyy) - 1.0f);
#endif
// Direct
@@ -153,14 +152,23 @@ float4 brdf(Pbr pbr, LightData data) {
// Indirect
#if !defined(FURNACE_TEST_DIRECT) && (defined(FORWARD_BASE_PASS) || defined(OUTLINES_PASS))
{
+ float3 remainder = 1.0f;
+#if defined(_CLEARCOAT)
+ float3 cc_specular_dfg = cc_dfg.xxx * cc_f0_color + cc_dfg.yyy; // filament 5.3.4.6
+ float3 cc_indirect_specular = data.indirect.specular_cc * cc_specular_dfg;
+ cc_indirect_specular *= cc_energy_comp;
+ specular += cc_indirect_specular;
+ remainder -= cc_specular_dfg;
+#endif
+
float3 specular_dfg = dfg.xxx * f0_color + dfg.yyy; // filament 5.3.4.6
float3 indirect_specular = data.indirect.specular * specular_dfg;
indirect_specular *= energy_comp;
- specular += indirect_specular;
+ specular += indirect_specular * remainder;
float3 indirect_diffuse = pbr.albedo.xyz * data.indirect.diffuse * (1.0 - pbr.metallic);
- diffuse += indirect_diffuse;
+ diffuse += indirect_diffuse * remainder;
}
#endif
@@ -175,7 +183,9 @@ float4 brdf(Pbr pbr, LightData data) {
}
#endif
+ diffuse *= data.common.ao;
specular *= data.common.spec_ao;
+
#if defined(_EMISSIONS) && defined(FORWARD_BASE_PASS)
float3 emission = pbr.emission;
#else
diff --git a/data.cginc b/data.cginc
index 34eacd6..e0fcd77 100644
--- a/data.cginc
+++ b/data.cginc
@@ -20,9 +20,6 @@ struct Pbr {
#if defined(_EMISSIONS) && defined(FORWARD_BASE_PASS)
float3 emission;
#endif
-#if defined(_AMBIENT_OCCLUSION)
- float ao;
-#endif
#if defined(_BENT_NORMALS)
float3 bent_normal;
#endif
@@ -33,4 +30,60 @@ struct Pbr {
#endif
};
+struct LightCommon {
+ float3 V;
+ float3 N;
+ float NoV;
+ float ao;
+ float spec_ao;
+#if defined(_CLEARCOAT)
+ float NoV_cc;
+#endif
+};
+
+struct LightDirect {
+ float3 dir;
+
+ float3 H;
+ float NoH;
+ float NoL;
+#if defined(_CLEARCOAT)
+ float NoH_cc;
+ float NoL_cc;
+#endif
+ float LoH;
+ float LoV;
+ float double_LoV;
+
+ float3 color;
+};
+
+struct LightIndirect {
+ float3 dir;
+
+ float3 H;
+ float NoH;
+ float NoL;
+ float LoH;
+ float LoV;
+ float double_LoV;
+
+ float3 specular;
+#if defined(_CLEARCOAT)
+ float3 specular_cc;
+#endif
+ float3 diffuse;
+
+ float3 L00;
+ float3 L01r;
+ float3 L01g;
+ float3 L01b;
+};
+
+struct LightData {
+ LightCommon common;
+ LightDirect direct;
+ LightIndirect indirect;
+};
+
#endif // __DATA_INC
diff --git a/lighting.cginc b/lighting.cginc
index 1f3afe6..9ea2052 100755
--- a/lighting.cginc
+++ b/lighting.cginc
@@ -14,64 +14,6 @@
#include "pbr.cginc"
#include "poi.cginc"
-struct LightCommon {
- float3 V;
- float3 N;
- float NoV;
- float spec_ao;
-#if defined(_CLEARCOAT)
- float NoV_cc;
-#endif
-};
-
-struct LightDirect {
- float3 dir;
-
- float3 H;
- float NoH;
- float NoL;
-#if defined(_CLEARCOAT)
- float NoH_cc;
- float NoL_cc;
-#endif
- float LoH;
- float LoV;
- float double_LoV;
-
- float3 color;
-};
-
-struct LightIndirect {
- float3 dir;
-
- float3 H;
- float NoH;
- float NoL;
-#if defined(_CLEARCOAT)
- float LoH_cc;
-#endif
- float LoH;
- float LoV;
- float double_LoV;
-
- float3 specular;
-#if defined(_CLEARCOAT)
- float3 specular_cc;
-#endif
- float3 diffuse;
-
- float3 L00;
- float3 L01r;
- float3 L01g;
- float3 L01b;
-};
-
-struct LightData {
- LightCommon common;
- LightDirect direct;
- LightIndirect indirect;
-};
-
float3 getDirectLightDirection(v2f i) {
#if defined(POINT) || defined(POINT_COOKIE) || defined(SPOT)
return normalize((_WorldSpaceLightPos0 - i.worldPos).xyz);
@@ -194,12 +136,6 @@ float4 getIndirectDiffuse(v2f i, Pbr pbr, inout LightData light) {
#endif
#endif
-#if defined(_BRIGHTNESS_CLAMP) && (defined(FORWARD_BASE_PASS) || defined(OUTLINES_PASS))
- float3 diffuse_hsv = RGBtoHSV(diffuse.xyz);
- diffuse_hsv.z = clamp(diffuse_hsv.z, _Brightness_Clamp_Min, _Brightness_Clamp_Max);
- diffuse.xyz = HSVtoRGB(diffuse_hsv);
-#endif
-
#if defined(_SHADOWS)
float3x3 mat = float3x3(
light.indirect.L01r,
@@ -225,11 +161,15 @@ float4 getIndirectDiffuse(v2f i, Pbr pbr, inout LightData light) {
diffuse.xyz *= shadow_color;
#endif
+ return diffuse;
+}
+
+float getAO(v2f i) {
+ float ao = 1;
#if defined(_AMBIENT_OCCLUSION)
- diffuse.xyz *= pbr.ao;
+ ao = saturate(lerp(1.0, _OcclusionMap.Sample(bilinear_repeat_s, i.uv01.xy).r, _OcclusionStrength));
#endif
-
- return diffuse;
+ return ao;
}
float getSpecularAO(v2f i, Pbr pbr, LightData data, float3 reflect_dir) {
@@ -237,7 +177,7 @@ float getSpecularAO(v2f i, Pbr pbr, LightData data, float3 reflect_dir) {
#if defined(_AMBIENT_OCCLUSION) || defined(_BENT_NORMALS)
float ao_vis = 1.0;
#if defined(_AMBIENT_OCCLUSION)
- ao_vis = pbr.ao;
+ ao_vis = data.common.ao;
#endif
#if defined(_BENT_NORMALS)
float3 spec_ao_normal = pbr.bent_normal;
@@ -262,6 +202,7 @@ float getSpecularAO(v2f i, Pbr pbr, LightData data, float3 reflect_dir) {
horizon_fade *= horizon_fade;
spec_ao *= horizon_fade;
#endif
+
return spec_ao;
}
@@ -307,9 +248,10 @@ void GetLighting(v2f i, Pbr pbr, out LightData data) {
data.indirect.NoL = saturate(dot(pbr.normal, data.indirect.dir));
data.indirect.NoH = saturate(dot(pbr.normal, data.indirect.H));
#if defined(_CLEARCOAT)
- float3 dir_cc = reflect(data.common.V, i.normal);
+ float3 cc_reflect_dir = reflect(-data.common.V, i.normal);
+ float3 cc_dominant_dir = getSpecularDominantDirection(i.normal, cc_reflect_dir, pbr.cc_roughness);
+ float3 dir_cc = normalize(cc_dominant_dir);
float3 H_cc = normalize(data.common.V + dir_cc);
- data.indirect.LoH_cc = saturate(dot(dir_cc, H_cc));
#endif
data.indirect.LoH = saturate(dot(data.indirect.dir, data.indirect.H));
float indirect_LoV = dot(data.indirect.dir, data.common.V);
@@ -319,15 +261,31 @@ void GetLighting(v2f i, Pbr pbr, out LightData data) {
data.indirect.diffuse = getIndirectDiffuse(i, pbr, data);
data.indirect.specular = getIndirectSpecular(i, pbr.roughness_perceptual, view_dir, data.indirect.dir);
+ data.common.ao = getAO(i);
data.common.spec_ao = getSpecularAO(i, pbr, data, reflect_dir);
#if defined(_CLEARCOAT)
- data.indirect.specular_cc = getIndirectSpecular(i, saturate(sqrt(pbr.cc_roughness)), view_dir, dir_cc);
+ data.indirect.specular_cc = getIndirectSpecular(i, pbr.cc_roughness_perceptual, view_dir, dir_cc);
#if defined(_CLEARCOAT_MASK)
float cc_mask = _Clearcoat_Mask.Sample(bilinear_clamp_s, i.uv01.xy).r;
data.indirect.specular_cc *= cc_mask;
#endif
#endif
+
+#if defined(_BRIGHTNESS_CLAMP)
+ float3 tmpHSV = RGBtoHSV(data.direct.color);
+ tmpHSV[2] = clamp(tmpHSV[2], _Brightness_Clamp_Min, _Brightness_Clamp_Max);
+ data.direct.color = HSVtoRGB(tmpHSV);
+
+ tmpHSV = RGBtoHSV(data.indirect.diffuse);
+ tmpHSV[2] = clamp(tmpHSV[2], _Brightness_Clamp_Min, _Brightness_Clamp_Max);
+ data.indirect.diffuse = HSVtoRGB(tmpHSV);
+
+ // No minimum for specular lighting. It would look awful.
+ tmpHSV = RGBtoHSV(data.indirect.specular);
+ tmpHSV[2] = clamp(tmpHSV[2], 0, _Brightness_Clamp_Max);
+ data.indirect.specular = HSVtoRGB(tmpHSV);
+#endif
}
#endif // __LIGHTING_INC
diff --git a/pbr.cginc b/pbr.cginc
index ab84c73..d79d58d 100755
--- a/pbr.cginc
+++ b/pbr.cginc
@@ -198,10 +198,6 @@ Pbr getPbr(v2f i) {
#endif
propagateSmoothness(pbr);
-#if defined(_AMBIENT_OCCLUSION)
- pbr.ao = saturate(lerp(1.0, _OcclusionMap.Sample(bilinear_repeat_s, i.uv01.xy).r, _OcclusionStrength));
-#endif
-
#if defined(_EMISSIONS) && defined(FORWARD_BASE_PASS)
float3 emission_tint = _EmissionColor;
float3 emission_color = _EmissionMap.Sample(trilinear_repeat_s,