diff options
| -rwxr-xr-x | brdf.cginc | 26 | ||||
| -rw-r--r-- | data.cginc | 59 | ||||
| -rwxr-xr-x | lighting.cginc | 100 | ||||
| -rwxr-xr-x | pbr.cginc | 4 |
4 files changed, 103 insertions, 86 deletions
@@ -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 @@ -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 @@ -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, |
