summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-08-07 19:33:02 -0700
committeryum <yum.food.vr@gmail.com>2025-08-07 19:33:02 -0700
commit9393f117a139976b19adf9f5201dfc7023fb3c04 (patch)
treeead7a6a29507ccca4b456a5123742dcc05ccb715
parent8c6e9be61b2a7b1c5b9e5b61252090a4e2432ce2 (diff)
add clearcoat
-rw-r--r--3ner.shader30
-rw-r--r--brdf.cginc32
-rw-r--r--features.cginc4
-rw-r--r--globals.cginc4
-rw-r--r--lighting.cginc36
-rw-r--r--pbr.cginc13
6 files changed, 98 insertions, 21 deletions
diff --git a/3ner.shader b/3ner.shader
index 7b6fbac..1058d59 100644
--- a/3ner.shader
+++ b/3ner.shader
@@ -67,14 +67,22 @@ Shader "yum_food/3ner"
[HideInInspector] m_end_Tessellation("Tessellation", Float) = 0
//endex
-
[HideInInspector] m_start_Rendering_Options("Rendering Options", Float) = 0
- [Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull", Float) = 2
- [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4
- [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Source Blend", Float) = 1
- [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Destination Blend", Float) = 0
- [Enum(Off, 0, On, 1)] _ZWrite("ZWrite", Int) = 1
+ [HideInInspector] m_start_BRDF("BRDF", Float) = 0
+ _BRDF_Specular_Min_Denom("Specular minimum denominator", Float) = 0.000001
+ _Specular_AA_Variance("Specular AA Variance", Float) = 0.15
+ _Specular_AA_Threshold("Specular AA Threshold", Float) = 0.25
+
+ //ifex _Clearcoat_Enabled==0
+ [HideInInspector] m_start_Clearcoat("Clearcoat", Float) = 0
+ [ThryToggle(_CLEARCOAT)] _Clearcoat_Enabled("Enable", Float) = 0
+ _Clearcoat_Strength("Strength", Range(0, 1)) = 0
+ _Clearcoat_Roughness("Roughness", Range(0, 1)) = 0
+ [HideInInspector] m_end_Clearcoat("Clearcoat", Float) = 0
+ //endex
+
+ [HideInInspector] m_end_BRDF("BRDF", Float) = 0
[HideInInspector] m_start_blending ("Blending--{button_help:{text:Tutorial,action:{type:URL,data:https://www.poiyomi.com/rendering/blending},hover:Documentation}}", Float) = 0
[DoNotAnimate][Enum(Thry.BlendOp)]_BlendOp ("RGB Blend Op", Int) = 0
@@ -95,11 +103,11 @@ Shader "yum_food/3ner"
[DoNotAnimate][HideInInspector] m_end_alphaBlending ("Advanced Alpha Blending", Float) = 0
[HideInInspector] m_end_blending ("Blending", Float) = 0
- [HideInInspector] m_start_BRDF("BRDF", Float) = 0
- _BRDF_Specular_Min_Denom("Specular minimum denominator", Float) = 0.000001
- _Specular_AA_Variance("Specular AA Variance", Float) = 0.15
- _Specular_AA_Threshold("Specular AA Threshold", Float) = 0.25
- [HideInInspector] m_end_BRDF("BRDF", Float) = 0
+ [Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull", Float) = 2
+ [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4
+ [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Source Blend", Float) = 1
+ [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Destination Blend", Float) = 0
+ [Enum(Off, 0, On, 1)] _ZWrite("ZWrite", Int) = 1
[HideInInspector] m_end_Rendering_Options("Rendering Options", Float) = 0
}
diff --git a/brdf.cginc b/brdf.cginc
index 6ca8c8d..5294e5e 100644
--- a/brdf.cginc
+++ b/brdf.cginc
@@ -76,17 +76,31 @@ float4 brdf(Pbr pbr, LightData data) {
// Direct
if (true) {
+ float remainder = 1.0f;
+
+#if defined(_CLEARCOAT)
+ float cc_f0 = 0.04f;
+ float Fc = F_Schlick(data.direct.LoH, cc_f0, f90);
+ float Dc = D_GGX(pbr.cc_roughness, data.direct.NoH_cc);
+ float Gc = V_GGXSmith(pbr.cc_roughness, data.direct.NoL_cc, data.common.NoV_cc);
+ float FDGc = Fc * Dc * Gc;
+ float3 direct_specular_cc = FDGc * data.direct.color * data.direct.NoL_cc * pbr.cc_strength;
+ direct_specular_cc = max(0, direct_specular_cc);
+ specular += direct_specular_cc;
+ remainder -= Fc;
+#endif
+
float F = F_Schlick(data.direct.LoH, f0, f90);
float D = D_GGX(pbr.roughness, data.direct.NoH);
float G = V_GGXSmith(pbr.roughness, data.direct.NoL, data.common.NoV);
float FDG = F * D * G;
- float3 direct_specular = FDG * data.direct.color * data.direct.NoL * lerp(1.0f, pbr.albedo.xyz, pbr.metallic);
+ float3 direct_specular = FDG * remainder * data.direct.color * data.direct.NoL * lerp(1.0f, pbr.albedo.xyz, pbr.metallic);
direct_specular = max(0, direct_specular);
specular += direct_specular;
+ remainder -= F;
- float3 remainder = (1.0f - direct_specular);
float Fd = Fd_OrenNayar(pbr.roughness, data.common.NoV, data.direct.NoL, data.direct.LoV) / PI;
float3 direct_diffuse = Fd * remainder * (1.0f - pbr.metallic) * pbr.albedo.xyz * data.direct.color;
direct_diffuse = max(0, direct_diffuse);
@@ -95,14 +109,22 @@ float4 brdf(Pbr pbr, LightData data) {
// Indirect
if (true) {
- float F = F_Schlick(data.indirect.LoH, f0, f90);
- float G = V_GGXSmith(pbr.roughness, data.indirect.NoL, data.common.NoV);
+ float remainder = 1.0f;
+#if defined(_CLEARCOAT)
+ float cc_f0 = 0.04f;
+ float Fc = F_Schlick(data.indirect.LoH, cc_f0, f90);
+ float3 indirect_specular_cc = Fc * data.indirect.specular_cc * pbr.cc_strength;
+ specular += indirect_specular_cc;
+ remainder -= Fc;
+#endif
+ float F = F_Schlick(data.indirect.LoH, f0, f90);
float3 indirect_specular = F * data.indirect.specular;
specular += indirect_specular;
+ remainder -= F;
float Fd = 1.0f; // Lambertian divide is baked into SH
- float3 remainder = (1.0f - indirect_specular);
+ remainder -= indirect_specular;
float3 indirect_diffuse = Fd * remainder * pbr.albedo.xyz * data.indirect.diffuse;
diffuse += indirect_diffuse;
}
diff --git a/features.cginc b/features.cginc
index 4958d77..e6de1c1 100644
--- a/features.cginc
+++ b/features.cginc
@@ -15,4 +15,8 @@
#pragma shader_feature_local _TESSELLATION_HEIGHTMAP_DIRECTION_CONTROL
//endex
+//ifex _Clearcoat_Enabled==0
+#pragma shader_feature_local _CLEARCOAT
+//endex
+
#endif // __FEATURES_INC
diff --git a/globals.cginc b/globals.cginc
index b1db690..12e86c8 100644
--- a/globals.cginc
+++ b/globals.cginc
@@ -44,5 +44,9 @@ float _Tessellation_Frustum_Culling_Bias;
float _Tessellation_Falloff_Factor;
#endif // _TESSELLATION
+#if defined(_CLEARCOAT)
+float _Clearcoat_Strength;
+float _Clearcoat_Roughness;
+#endif // _CLEARCOAT
#endif // __GLOBALS_INC
diff --git a/lighting.cginc b/lighting.cginc
index db3c4ff..66b7220 100644
--- a/lighting.cginc
+++ b/lighting.cginc
@@ -16,7 +16,10 @@
struct LightCommon {
float3 V;
float3 N;
- float NoV;
+ float NoV;
+#if defined(_CLEARCOAT)
+ float NoV_cc;
+#endif
};
struct LightDirect {
@@ -25,6 +28,10 @@ struct LightDirect {
float3 H;
float NoH;
float NoL;
+#if defined(_CLEARCOAT)
+ float NoH_cc;
+ float NoL_cc;
+#endif
float LoH;
float LoV;
float double_LoV;
@@ -38,11 +45,17 @@ struct LightIndirect {
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;
@@ -78,9 +91,9 @@ float4 getDirectLightColorIntensity() {
return float4(_LightColor0.xyz / _LightColor0.w, _LightColor0.w);
}
-float3 getIndirectSpecular(v2f i, Pbr pbr, float3 view_dir, float3 reflect_dir) {
+float3 getIndirectSpecular(v2f i, float roughness, float3 view_dir, float3 reflect_dir) {
UnityGIInput data = InitialiseUnityGIInput(i.worldPos, view_dir);
- float3 env_refl = UnityGI_prefilteredRadiance(data, pbr.roughness_perceptual, reflect_dir);
+ float3 env_refl = UnityGI_prefilteredRadiance(data, roughness, reflect_dir);
return env_refl;
}
@@ -108,6 +121,9 @@ void GetLighting(v2f i, Pbr pbr, out LightData data) {
data.common.V = -view_dir;
data.common.N = pbr.normal;
data.common.NoV = saturate(dot(pbr.normal, data.common.V));
+#if defined(_CLEARCOAT)
+ data.common.NoV_cc = saturate(dot(i.normal, data.common.V));
+#endif
// Direct lighting
data.direct.dir = getDirectLightDirection(i);
@@ -115,6 +131,10 @@ void GetLighting(v2f i, Pbr pbr, out LightData data) {
data.direct.NoL = saturate(dot(pbr.normal, data.direct.dir));
data.direct.NoH = saturate(dot(pbr.normal, data.direct.H));
data.direct.LoH = saturate(dot(data.direct.dir, data.direct.H));
+#if defined(_CLEARCOAT)
+ data.direct.NoH_cc = saturate(dot(i.normal, data.direct.H));
+ data.direct.NoL_cc = saturate(dot(i.normal, data.direct.dir));
+#endif
float direct_LoV = dot(data.direct.dir, data.common.V);
data.direct.LoV = saturate(direct_LoV);
data.direct.double_LoV = saturate(2.0f * direct_LoV * direct_LoV - 1.0f);
@@ -127,13 +147,21 @@ void GetLighting(v2f i, Pbr pbr, out LightData data) {
data.indirect.H = normalize(data.common.V + data.indirect.dir);
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 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.direct.dir, data.common.V);
data.indirect.LoV = saturate(indirect_LoV);
data.indirect.double_LoV = saturate(2.0f * indirect_LoV * indirect_LoV - 1.0f);
data.indirect.diffuse = getIndirectDiffuse(i, pbr, data.indirect);
- data.indirect.specular = getIndirectSpecular(i, pbr, view_dir, data.indirect.dir);
+ data.indirect.specular = getIndirectSpecular(i, pbr.roughness_perceptual, view_dir, data.indirect.dir);
+#if defined(_CLEARCOAT)
+ data.indirect.specular_cc = getIndirectSpecular(i, pbr.cc_roughness, view_dir, dir_cc);
+#endif
}
#endif // __LIGHTING_INC
diff --git a/pbr.cginc b/pbr.cginc
index 1677ccc..746de9c 100644
--- a/pbr.cginc
+++ b/pbr.cginc
@@ -13,6 +13,10 @@ struct Pbr {
float roughness_perceptual;
float roughness;
float metallic;
+#if defined(_CLEARCOAT)
+ float cc_roughness;
+ float cc_strength;
+#endif
};
#define MIN_PERCEPTUAL_ROUGHNESS 5e-2f
@@ -22,6 +26,9 @@ struct Pbr {
void propagateSmoothness(inout Pbr pbr) {
pbr.roughness_perceptual = max(MIN_PERCEPTUAL_ROUGHNESS, 1.0f - pbr.smoothness);
pbr.roughness = max(MIN_ROUGHNESS, pbr.roughness_perceptual * pbr.roughness_perceptual);
+#if defined(_CLEARCOAT)
+ pbr.cc_roughness = max(MIN_ROUGHNESS, pbr.cc_roughness * pbr.cc_roughness);
+#endif
}
void apply_marble(float3 world_pos, inout float3 albedo) {
@@ -56,8 +63,12 @@ Pbr getPbr(v2f i) {
float4 metallic_gloss = _MetallicGlossMap.Sample(trilinear_repeat_s, i.uv0 * _MetallicGlossMap_ST.xy);
pbr.smoothness = metallic_gloss.a * _Glossiness;
pbr.metallic = metallic_gloss.r * _Metallic;
-
+#if defined(_CLEARCOAT)
+ pbr.cc_roughness = _Clearcoat_Roughness;
+ pbr.cc_strength = _Clearcoat_Strength;
+#endif
propagateSmoothness(pbr);
+
return pbr;
}