Refactor BRDF roughness input to be squared

This commit is contained in:
2026-06-25 08:46:44 +02:00
parent 3cd04b74b7
commit 2f3ce50cef
2 changed files with 13 additions and 15 deletions
+9 -12
View File
@@ -12,19 +12,18 @@ float3 Diffuse_Lambert(float3 diffuseColor)
// GGX / Trowbridge-Reitz
// [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"]
float D_GGX(float roughness, float NoH)
float D_GGX(float roughnessSq, float NoH)
{
float a = roughness * roughness;
float a2 = a * a;
float a2 = roughnessSq * roughnessSq;
float d = (NoH * a2 - NoH) * NoH + 1;
return a2 / (PI * d * d);
}
// Tuned to match behavior of V_Smith
// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
float V_Schlick(float roughness, float NoV, float NoL)
float V_Schlick(float roughnessSq, float NoV, float NoL)
{
float k = Square(roughness) * 0.5;
float k = roughnessSq * 0.5;
float visSchlickV = NoV * (1 - k) + k;
float visSchlickL = NoL * (1 - k) + k;
return 0.25 / (visSchlickV * visSchlickL);
@@ -32,10 +31,9 @@ float V_Schlick(float roughness, float NoV, float NoL)
// Smith term for GGX
// [Smith 1967, "Geometrical shadowing of a random rough surface"]
float V_Smith(float roughness, float NoV, float NoL)
float V_Smith(float roughnessSq, float NoV, float NoL)
{
float a = Square(roughness);
float a2 = a * a;
float a2 = roughnessSq * roughnessSq;
float visSmithV = NoV + sqrt(NoV * (NoV - NoV * a2) + a2);
float visSmithL = NoL + sqrt(NoL * (NoL - NoL * a2) + a2);
return rcp(visSmithV * visSmithL);
@@ -43,11 +41,10 @@ float V_Smith(float roughness, float NoV, float NoL)
// Appoximation of joint Smith term for GGX
// [Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"]
float V_SmithJointApprox(float roughness, float NoV, float NoL)
float V_SmithJointApprox(float roughnessSq, float NoV, float NoL)
{
float a = Square(roughness);
float visSmithV = NoL * (NoV * (1 - a) + a);
float visSmithL = NoV * (NoL * (1 - a) + a);
float visSmithV = NoL * (NoV * (1 - roughnessSq) + roughnessSq);
float visSmithL = NoV * (NoL * (1 - roughnessSq) + roughnessSq);
return 0.5 * rcp(visSmithV + visSmithL);
}
+4 -3
View File
@@ -33,9 +33,10 @@ LightSample StandardShading(GBufferSample gBuffer, float energy, float3 L, float
lighting.Specular = 0;
#else
float3 specularColor = GetSpecularColor(gBuffer);
float roughnessSq = Square(gBuffer.Roughness);
float3 F = F_Schlick(specularColor, VoH);
float D = D_GGX(gBuffer.Roughness, NoH) * energy;
float Vis = V_SmithJointApprox(gBuffer.Roughness, NoV, NoL);
float D = D_GGX(roughnessSq, NoH) * energy;
float Vis = V_SmithJointApprox(roughnessSq, NoV, NoL);
// TODO: apply energy compensation to specular (1.0 + specularColor * (1.0 / PreIntegratedGF.y - 1.0))
lighting.Specular = (D * Vis) * F;
#endif
@@ -67,7 +68,7 @@ LightSample FoliageShading(GBufferSample gBuffer, float energy, float3 L, float3
float3 subsurfaceColor = gBuffer.CustomData.rgb;
float wrapNoL = saturate((-dot(N, L) + 0.5f) / 2.25);
float VoL = dot(V, L);
float scatter = D_GGX(0.36, saturate(-VoL));
float scatter = D_GGX(Square(0.36), saturate(-VoL));
lighting.Transmission = subsurfaceColor * (wrapNoL * scatter);
#endif
return lighting;