From eb1529d4401cc4d385ef8bc806a186890999fed6 Mon Sep 17 00:00:00 2001 From: yum Date: Fri, 28 Feb 2025 15:17:43 -0800 Subject: add basic clearcoat lobe --- 2ner.shader | 8 ++++++++ features.cginc | 4 ++++ filamented.cginc | 3 +-- globals.cginc | 5 +++++ yum_brdf.cginc | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) diff --git a/2ner.shader b/2ner.shader index e02cef6..8bf7934 100644 --- a/2ner.shader +++ b/2ner.shader @@ -81,6 +81,14 @@ Shader "yum_food/2ner" [HideInInspector] m_end_Metallic("Metallics", Float) = 0 //endex + //ifex _Clearcoat_Enabled==0 + [HideInInspector] m_start_Clearcoat("Clearcoat", Float) = 0 + [ThryToggle(_CLEARCOAT)]_Clearcoat_Enabled("Enable", Float) = 0 + _Clearcoat_Strength("Strength", Range(0, 1)) = 1 + _Clearcoat_Roughness("Roughness", Range(0.089, 1)) = 0.089 + [HideInInspector] m_end_Clearcoat("Clearcoat", Float) = 0 + //endex + [HideInInspector] m_gimmicks("Gimmicks", Float) = 0 //ifex _Outlines_Enabled==0 [HideInInspector] m_start_Outlines("Outlines", Float) = 0 diff --git a/features.cginc b/features.cginc index 3a18b8b..64c0480 100644 --- a/features.cginc +++ b/features.cginc @@ -37,6 +37,10 @@ #pragma shader_feature_local _QUANTIZE_SPECULAR //endex +//ifex _Clearcoat_Enabled==0 +#pragma shader_feature_local _CLEARCOAT +//endex + //ifex _Metallics_Enabled==0 #pragma shader_feature_local _METALLICS //endex diff --git a/filamented.cginc b/filamented.cginc index 9edfca5..fac3fef 100644 --- a/filamented.cginc +++ b/filamented.cginc @@ -241,7 +241,7 @@ float3 PrefilteredDFG_LUT(float lod, float NoV) { return UNITY_SAMPLE_TEX2D(_DFG, float2(NoV, lod)); } -float3 specularDFG(const float3 dfg, const float f0) { +float3 specularDFG(const float3 dfg, const float3 f0) { return lerp(dfg.xxx, dfg.yyy, f0); } @@ -355,7 +355,6 @@ inline half3 UnityGI_prefilteredRadiance(const UnityGIInput data, glossIn.reflUVW = r; #ifdef UNITY_SPECCUBE_BOX_PROJECTION - // we will tweak reflUVW in glossIn directly (as we pass it to Unity_GlossyEnvironment twice for probe0 and pr obe1), so keep original to pass into BoxProjectedCubemapDirection half3 originalReflUVW = glossIn.reflUVW; glossIn.reflUVW = BoxProjectedCubemapDirection(originalReflUVW, data.worldPos, data.probePosition[0], data.boxMin[0], data.boxMax[0]); diff --git a/globals.cginc b/globals.cginc index 043c1a9..cfde8a1 100644 --- a/globals.cginc +++ b/globals.cginc @@ -81,6 +81,11 @@ sampler2D _MetallicGlossMap; float4 _MetallicGlossMap_ST; #endif +#if defined(_CLEARCOAT) +float _Clearcoat_Strength; +float _Clearcoat_Roughness; +#endif + #if defined(OUTLINE_PASS) float _Outlines_Enabled_Dynamic; float4 _Outline_Color; diff --git a/yum_brdf.cginc b/yum_brdf.cginc index 52bc495..ab1730b 100644 --- a/yum_brdf.cginc +++ b/yum_brdf.cginc @@ -44,6 +44,22 @@ float3 specularLobe(YumPbr pbr, float f0, return (D * V) * F * PI; } +#if defined(_CLEARCOAT) +// Add a clearcoat specular lobe function +float3 clearcoatLobe(float roughness, float f0, + float3 h, float LoH, float NoH_mesh, float NoV_mesh, float NoL_mesh) +{ + const float F = F_Schlick(f0, LoH); + + // Normal distribution function with clearcoat roughness + float D = D_GGX(roughness, NoH_mesh, h); + // Geometric shadowing + float V = V_SmithGGXCorrelated_Fast(roughness, NoV_mesh, NoL_mesh); + + return (D * V) * F * PI; +} +#endif // _CLEARCOAT + float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) { const float3 h = normalize(light.view_dir + light.dir); const float LoH = saturate(dot(light.dir, h)); @@ -73,13 +89,49 @@ float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) { const float3 E = specularDFG(dfg, f0); const float3 energy_compensation = energyCompensation(dfg, f0); +#if defined(_CLEARCOAT) + // Clearcoat parameters + const float clearcoat_strength = _Clearcoat_Strength; + const float clearcoat_roughness = max(0.089, _Clearcoat_Roughness); + const float clearcoat_perceptual_roughness = sqrt(clearcoat_roughness); + + // IoR of 1.5 -> reflectance of 0.04 + const float clearcoat_f0 = 0.04; + + // Use cc normal for clearcoat instead of detail normal + const float3 cc_normal = i.normal; + const float NoV_cc = max(1E-4, dot(cc_normal, light.view_dir)); + const float NoH_cc = saturate(dot(cc_normal, h)); + const float NoL_cc = saturate(dot(cc_normal, light.dir)); +#if defined(_WRAPPED_LIGHTING) + const float NoL_cc_wrapped = saturate((NoL_cc + light.wrapped) / (1.0 + light.wrapped)); +#else + const float NoL_cc_wrapped = NoL_cc; +#endif + + // Calculate clearcoat DFG terms with cc normal + const float3 clearcoat_dfg = PrefilteredDFG_LUT(clearcoat_perceptual_roughness, NoV_cc); + const float clearcoat_E = specularDFG(clearcoat_dfg, clearcoat_f0); + const float clearcoat_energy_compensation = energyCompensation(clearcoat_dfg, clearcoat_f0); +#endif // _CLEARCOAT + float3 direct; { + // Base layer float3 Fd = diffuseLobe(pbr.albedo, pbr.roughness_perceptual, LoH, NoL, NoV, f90); Fd *= (1.0 - pbr.metallic) * light.attenuation; float3 Fr = specularLobe(pbr, f0, h, LoH, NoH, NoV, NoL_wrapped_s); + +#if defined(_CLEARCOAT) + float Fcr = clearcoatLobe(clearcoat_roughness, clearcoat_f0, h, LoH, NoH_cc, NoV_cc, NoL_cc_wrapped); + Fcr *= clearcoat_strength * clearcoat_energy_compensation; + float clearcoat_factor = 1.0 - clearcoat_strength * F_Schlick(clearcoat_f0, NoV_cc); + float3 color = (Fd * NoL_wrapped_d + Fr * energy_compensation * NoL_wrapped_s) * clearcoat_factor + + Fcr * NoL_cc_wrapped; +#else float3 color = Fd * NoL_wrapped_d + Fr * energy_compensation * NoL_wrapped_s; +#endif // _CLEARCOAT direct = color * light.direct; } @@ -88,7 +140,14 @@ float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) { { float3 Fr = E * light.specular * energy_compensation; float3 Fd = pbr.albedo * light.diffuse * (1.0 - E) * (1.0 - pbr.metallic) * pbr.ao; + +#if defined(_CLEARCOAT) + float Fcr = clearcoat_E * light.specular * clearcoat_energy_compensation * clearcoat_strength; + float clearcoat_factor = 1.0 - clearcoat_strength * F_Schlick(clearcoat_f0, NoV_cc); + indirect = (Fr + Fd) * clearcoat_factor + Fcr; +#else indirect = Fr + Fd; +#endif // _CLEARCOAT } return float4(direct + indirect, pbr.albedo.a); -- cgit v1.2.3