summaryrefslogtreecommitdiffstats
path: root/brdf.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-03-16 19:35:38 -0700
committeryum <yum.food.vr@gmail.com>2026-03-16 19:35:38 -0700
commita0c233000c210273ca93c0444413fd45b1e6c928 (patch)
tree6928b8ded04f04dc670f049ccbdd673360c1b516 /brdf.cginc
parent11e9d97c5ac694773149d6059f90c670b9c00262 (diff)
Begin work on cloth (again)
Diffstat (limited to 'brdf.cginc')
-rwxr-xr-xbrdf.cginc67
1 files changed, 65 insertions, 2 deletions
diff --git a/brdf.cginc b/brdf.cginc
index 94e7858..d9443ed 100755
--- a/brdf.cginc
+++ b/brdf.cginc
@@ -39,8 +39,6 @@ float3 F_Schlick(float LoH, float3 f0, float f90) {
// tan^2(theta) = sin^2(theta) / cos^2(theta)
// = (1 - cos^2(theta)) / cos^2(theta)
// = -1 + 1 / cos^2(theta)
-// The `max(1e-4, _)` and `min(4096, _)` are hand picked to minimize the issue
-// of bloom making specular highlights flash as the camera moves.
float D_GGX(float roughness, float NoH) {
float r2 = roughness * roughness;
float NoH2 = NoH * NoH;
@@ -54,6 +52,14 @@ float D_GGX(float roughness, float NoH) {
return r2 / denom;
}
+float D_Estevez(float roughness, float NoH) {
+ float r_rcp = rcp(roughness);
+ float sin_theta = sqrt(1 - NoH * NoH);
+ float D = (2 + r_rcp) * pow(sin_theta, r_rcp) / TAU;
+
+ return D;
+}
+
// Hammon "PBR Diffuse Lighting for GGX+Smith Microsurfaces"
// Slide 84. Note that we remove the (4 * NoL * NoV) from the
// denominator of the specular lobe because of some cancellations.
@@ -64,6 +70,36 @@ float G_GGXSmith(float roughness, float NoL, float NoV) {
return rcp(denom);
}
+float L_Estevez(float r, float x) {
+ // Recover constants according to Table 1.
+ float interpolator = 1 - r * r;
+ float one_minus_i = 1 - interpolator;
+ float a = interpolator * 25.3245 + one_minus_i * 21.5473;
+ float b = interpolator * 3.32435 + one_minus_i * 3.82987;
+ float c = interpolator * 0.16801 + one_minus_i * 0.19823;
+ float d = interpolator * -1.27393 + one_minus_i * -1.97760;
+ float e = interpolator * -4.85967 + one_minus_i * -4.32054;
+
+ return a / (1 + b*pow(x, c)) + d*x + e;
+}
+
+float Lambda_Estevez(float cos_theta, float roughness) {
+ // Equation 3
+ float lambda = cos_theta < 0.5
+ ? exp(L_Estevez(roughness, cos_theta))
+ : exp(2 * L_Estevez(roughness, 0.5) - L_Estevez(roughness, 1 - cos_theta));
+ // Equation 4
+ return pow(lambda, 1 + 2 * pow(1 - cos_theta, 8));
+}
+
+// Estevez & Kulla "Production Friendly Microfacet Sheen BRDF"
+// Height-correlated Smith: G2 / (4 * NoL * NoV)
+float G_Estevez(float roughness, float NoL, float NoV) {
+ float lambda_l = Lambda_Estevez(NoL, roughness);
+ float lambda_v = Lambda_Estevez(NoV, roughness);
+ return 1.0 / ((1.0 + lambda_l + lambda_v) * 4.0 * NoL * NoV);
+}
+
float4 brdf(Pbr pbr, LightData data, out BrdfData bd) {
bd = (BrdfData)0;
float3 specular = 0;
@@ -124,6 +160,23 @@ float4 brdf(Pbr pbr, LightData data, out BrdfData bd) {
remainder *= saturate(1.0f - bd.direct_f_cc * pbr.cc_strength);
#endif
+#if defined(_CLOTH)
+ float3 cloth_f0 = _Cloth_Sheen.rgb;
+ bd.direct_f = F_Schlick(data.direct.LoH, cloth_f0, f90);
+ bd.direct_d = D_Estevez(pbr.roughness, data.direct.NoH);
+ bd.direct_g = G_Estevez(pbr.roughness, data.direct.NoL, data.common.NoV);
+
+ float3 direct_specular = (bd.direct_d * bd.direct_g) * bd.direct_f;
+ direct_specular *= data.direct.color * data.direct.NoL;
+ direct_specular *= remainder;
+ specular += direct_specular;
+
+ float Fd = Fd_Lambertian(data.direct.NoL) / PI;
+ float3 direct_diffuse = Fd * pbr.albedo.xyz * data.direct.color;
+ direct_diffuse *= remainder;
+ direct_diffuse = max(0, direct_diffuse);
+ diffuse += direct_diffuse;
+#else
bd.direct_f = F_Schlick(data.direct.LoH, f0_color, f90);
bd.direct_d = D_GGX(pbr.roughness, data.direct.NoH);
bd.direct_g = G_GGXSmith(pbr.roughness, data.direct.NoL, data.common.NoV);
@@ -143,6 +196,7 @@ float4 brdf(Pbr pbr, LightData data, out BrdfData bd) {
direct_diffuse *= remainder;
direct_diffuse = max(0, direct_diffuse);
diffuse += direct_diffuse;
+#endif
}
// Indirect
@@ -157,6 +211,14 @@ float4 brdf(Pbr pbr, LightData data, out BrdfData bd) {
remainder -= cc_specular_dfg;
#endif
+#if defined(_CLOTH)
+ float3 specular_dfg = _Cloth_Sheen.rgb * bd.ibl_dfg.zzz;
+ float3 indirect_specular = data.indirect.specular * specular_dfg;
+ specular += indirect_specular * remainder;
+
+ float3 indirect_diffuse = pbr.albedo.xyz * data.indirect.diffuse;
+ diffuse += indirect_diffuse * remainder;
+#else
float3 specular_dfg = bd.ibl_dfg.xxx * f0_color + bd.ibl_dfg.yyy; // filament 5.3.4.6
float3 indirect_specular = data.indirect.specular * specular_dfg;
@@ -165,6 +227,7 @@ float4 brdf(Pbr pbr, LightData data, out BrdfData bd) {
float3 indirect_diffuse = pbr.albedo.xyz * data.indirect.diffuse * (1.0 - pbr.metallic);
diffuse += indirect_diffuse * remainder;
+#endif
}
#endif