Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions features/Hair Specular/Shaders/Hair/Hair.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ namespace Hair
};

float hairIOR = 1.55;
float3 specularColor = HairF0();
float3 F0 = HairF0();

float3 Tp;
float Mp, Np, Fp, a, h, f;
Expand All @@ -151,22 +151,22 @@ namespace Hair
// R
Mp = Hair_g(B[0], ThetaH - Alpha[0]);
Np = 0.25 * cosHalfPhi;
Fp = BRDF::F_Schlick(specularColor, sqrt(saturate(0.5 + 0.5 * VdotL))).x;
Fp = BRDF::F_Schlick(F0, sqrt(saturate(0.5 + 0.5 * VdotL))).x;
R = (Mp * Np) * (Fp * lerp(1, backlit, saturate(-VdotL)));

// TT
Mp = Hair_g(B[1], ThetaH - Alpha[1]);
a = (1.55f / hairIOR) * rcp(n_prime);
h = cosHalfPhi * (1 + a * (0.6 - 0.8 * cosPhi));
f = BRDF::F_Schlick(specularColor, cosThetaD * sqrt(saturate(1 - h * h))).x;
f = BRDF::F_Schlick(F0, cosThetaD * sqrt(saturate(1 - h * h))).x;
Fp = (1 - f) * (1 - f);
Tp = pow(abs(baseColor), 0.5 * sqrt(1 - (h * a) * (h * a)) / cosThetaD);
Np = exp(-3.65 * cosPhi - 3.98);
TT = (Mp * Np) * (Fp * Tp) * backlit;

// TRT
Mp = Hair_g(B[2], ThetaH - Alpha[2]);
f = BRDF::F_Schlick(specularColor, cosThetaD * 0.5f).x;
f = BRDF::F_Schlick(F0, cosThetaD * 0.5f).x;
Fp = (1 - f) * (1 - f) * f;
Tp = pow(abs(baseColor), 0.8 / cosThetaD);
Np = exp(17 * cosPhi - 16.78);
Expand Down
4 changes: 2 additions & 2 deletions package/Shaders/Common/BRDF.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ namespace BRDF

// Specular BRDFs
// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
float3 F_Schlick(float3 specularColor, float VdotH)
float3 F_Schlick(float3 F0, float VdotH)
{
float Fc = pow(1 - VdotH, 5);
return Fc + (1 - Fc) * specularColor;
return Fc + (1 - Fc) * F0;
}

float3 F_Schlick(float3 F0, float3 F90, float VdotH)
Expand Down
9 changes: 5 additions & 4 deletions package/Shaders/Common/LightingEval.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -180,16 +180,17 @@ void EvaluateWetnessLighting(float3 wetnessNormal, DirectContext context, float
float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL);
float3 F = BRDF::F_Schlick(wetnessF0, VdotH);

F *= wetnessStrength;
// Separate physical Fresnel from effective contribution weighted by strength
float3 wetnessF = F * wetnessStrength;

float3 wetnessSpecular = D * G * F * NdotL * lightColor;
float3 wetnessSpecular = D * G * wetnessF * NdotL * lightColor;

# if !defined(TRUE_PBR)
wetnessSpecular *= Color::PBRLightingCompensation * Color::PBRLightingScale; // Compensate for GGX on traditional specular
# endif

lightingOutput.diffuse *= 1 - F;
lightingOutput.specular *= 1 - F;
lightingOutput.diffuse *= 1 - wetnessF;
lightingOutput.specular *= 1 - wetnessF;
lightingOutput.specular += wetnessSpecular;
}

Expand Down
30 changes: 15 additions & 15 deletions package/Shaders/Common/PBR.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
namespace PBR
{
#if defined(GLINT)
float3 GetSpecularDirectLightMultiplierMicrofacetWithGlint(float noise, float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, float glintH,
float3 SpecularMicrofacetWithGlint(float noise, float roughness, float3 F0, float NdotL, float NdotV, float NdotH, float VdotH, float glintH,
float logDensity, float microfacetRoughness, float densityRandomization, Glints::GlintCachedVars glintCache,
out float3 F)
{
Expand All @@ -23,7 +23,7 @@ namespace PBR
D = Glints::SampleGlints2023NDF(noise, logDensity, microfacetRoughness, densityRandomization, glintCache, glintH, D, D_max).x;
}
float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL);
F = BRDF::F_Schlick(specularColor, VdotH);
F = BRDF::F_Schlick(F0, VdotH);

return D * G * F;
}
Expand Down Expand Up @@ -57,30 +57,30 @@ namespace PBR
};

float hairIOR = HairIOR();
float specularColor = IORToF0(hairIOR);
float F0 = IORToF0(hairIOR);

float3 Tp;
float Mp, Np, Fp, a, h, f;
float ThetaH = NdotL + NdotV;
// R
Mp = HairGaussian(B[0], ThetaH - Alpha[0]);
Np = 0.25 * cosHalfPhi;
Fp = BRDF::F_Schlick(specularColor, sqrt(saturate(0.5 + 0.5 * VdotL))).x;
Fp = BRDF::F_Schlick(F0, sqrt(saturate(0.5 + 0.5 * VdotL))).x;
S += (Mp * Np) * (Fp * lerp(1, backlit, saturate(-VdotL)));

// TT
Mp = HairGaussian(B[1], ThetaH - Alpha[1]);
a = (1.55f / hairIOR) * rcp(n_prime);
h = cosHalfPhi * (1 + a * (0.6 - 0.8 * cosPhi));
f = BRDF::F_Schlick(specularColor, cosThetaD * sqrt(saturate(1 - h * h))).x;
f = BRDF::F_Schlick(F0, cosThetaD * sqrt(saturate(1 - h * h))).x;
Fp = (1 - f) * (1 - f);
Tp = pow(abs(material.BaseColor), 0.5 * sqrt(1 - (h * a) * (h * a)) / cosThetaD);
Np = exp(-3.65 * cosPhi - 3.98);
S += (Mp * Np) * (Fp * Tp) * backlit;

// TRT
Mp = HairGaussian(B[2], ThetaH - Alpha[2]);
f = BRDF::F_Schlick(specularColor, cosThetaD * 0.5f).x;
f = BRDF::F_Schlick(F0, cosThetaD * 0.5f).x;
Fp = (1 - f) * (1 - f) * f;
Tp = pow(abs(material.BaseColor), 0.8 / cosThetaD);
Np = exp(17 * cosPhi - 16.78);
Expand Down Expand Up @@ -152,22 +152,22 @@ namespace PBR
else
#endif
{
float3 F;
float3 F; // Fresnel reflectance at current (V,H) angle
#if defined(GLINT)
float3 specular = GetSpecularDirectLightMultiplierMicrofacetWithGlint(material.Noise, material.Roughness, material.F0, satNdotL, satNdotV, satNdotH, satVdotH, mul(tbnTr, H).x,
float3 Fr = SpecularMicrofacetWithGlint(material.Noise, material.Roughness, material.F0, satNdotL, satNdotV, satNdotH, satVdotH, mul(tbnTr, H).x,
material.GlintLogMicrofacetDensity, material.GlintMicrofacetRoughness, material.GlintDensityRandomization, material.GlintCache, F);
#else
float3 specular = GetSpecularDirectLightMultiplierMicrofacet(material.Roughness, material.F0, satNdotL, satNdotV, satNdotH, satVdotH, F);
float3 Fr = SpecularMicrofacet(material.Roughness, material.F0, satNdotL, satNdotV, satNdotH, satVdotH, F);
#endif
float3 kD = 1 - F;

lightingOutput.diffuse += detailedLightColor * satNdotL * BRDF::Diffuse_Lambert() * kD;
lightingOutput.specular += specular * detailedLightColor * satNdotL;
lightingOutput.specular += Fr * detailedLightColor * satNdotL;

#if !defined(LANDSCAPE) && !defined(LODLANDSCAPE)
[branch] if ((PBRFlags & Flags::Fuzz) != 0)
{
float3 fuzzSpecular = GetSpecularDirectLightMultiplierMicroflakes(material.Roughness, material.FuzzColor, satNdotL, satNdotV, satNdotH, satVdotH) * detailedLightColor * satNdotL;
float3 fuzzSpecular = SpecularMicroflakes(material.Roughness, material.FuzzColor, satNdotL, satNdotV, satNdotH, satVdotH) * detailedLightColor * satNdotL;
lightingOutput.specular = lerp(lightingOutput.specular, fuzzSpecular, material.FuzzWeight);
}

Expand All @@ -194,14 +194,14 @@ namespace PBR
}

float3 coatF;
float3 coatSpecular = GetSpecularDirectLightMultiplierMicrofacet(material.CoatRoughness, material.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, coatF) * context.coatLightColor * coatNdotL;
float3 coatFr = SpecularMicrofacet(material.CoatRoughness, material.CoatF0, coatNdotL, coatNdotV, coatNdotH, coatVdotH, coatF);

float3 layerAttenuation = 1 - coatF * material.CoatStrength;
lightingOutput.diffuse *= layerAttenuation;
lightingOutput.specular *= layerAttenuation;

lightingOutput.coatDiffuse += context.coatLightColor * coatNdotL * BRDF::Diffuse_Lambert();
lightingOutput.specular += coatSpecular * material.CoatStrength;
lightingOutput.specular += coatFr * context.coatLightColor * coatNdotL * material.CoatStrength;
}
#endif
}
Expand Down Expand Up @@ -242,8 +242,8 @@ namespace PBR
float2 specularBRDF = BRDF::EnvBRDF(material.Roughness, NdotV);
lobeWeights.specular = material.F0 * specularBRDF.x + specularBRDF.y;

float3 kD = 1 - lobeWeights.specular;
lobeWeights.diffuse *= kD;
// Energy conservation: diffuse receives only what specular does not reflect
lobeWeights.diffuse *= 1 - lobeWeights.specular;

#if !defined(LANDSCAPE) && !defined(LODLANDSCAPE)
[branch] if ((PBRFlags & Flags::TwoLayer) != 0)
Expand Down
36 changes: 17 additions & 19 deletions package/Shaders/Common/PBRMath.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -57,37 +57,37 @@ namespace PBR
static const uint LandTile5HasGlint = (1 << 17);
}

/// @brief Calculate specular reflection using GGX microfacet model
/// @param roughness Surface roughness [0,1]
/// @param specularColor F0 reflectance at normal incidence
/// @brief Evaluate GGX microfacet specular BRDF (D * Vis * F)
/// @param roughness Perceptual roughness [0,1]
/// @param F0 Reflectance at normal incidence
/// @param NdotL Dot product of normal and light direction
/// @param NdotV Dot product of normal and view direction
/// @param NdotH Dot product of normal and half vector
/// @param VdotH Dot product of view and half vector
/// @param F Output Fresnel term
/// @return Specular BRDF term (D * G * F)
float3 GetSpecularDirectLightMultiplierMicrofacet(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH, out float3 F)
/// @param F Output Fresnel reflectance at current angle
/// @return Specular BRDF value (D * Vis * F)
float3 SpecularMicrofacet(float roughness, float3 F0, float NdotL, float NdotV, float NdotH, float VdotH, out float3 F)
{
float D = BRDF::D_GGX(roughness, NdotH);
float G = BRDF::Vis_SmithJointApprox(roughness, NdotV, NdotL);
F = BRDF::F_Schlick(specularColor, VdotH);
F = BRDF::F_Schlick(F0, VdotH);

return D * G * F;
}

/// @brief Calculate specular reflection using Charlie microflake model (for sheen/fabric)
/// @param roughness Surface roughness [0,1]
/// @param specularColor F0 reflectance at normal incidence
/// @brief Evaluate Charlie microflake specular BRDF for sheen/fabric (D * Vis * F)
/// @param roughness Perceptual roughness [0,1]
/// @param F0 Reflectance at normal incidence
/// @param NdotL Dot product of normal and light direction
/// @param NdotV Dot product of normal and view direction
/// @param NdotH Dot product of normal and half vector
/// @param VdotH Dot product of view and half vector
/// @return Specular BRDF term (D * G * F)
float3 GetSpecularDirectLightMultiplierMicroflakes(float roughness, float3 specularColor, float NdotL, float NdotV, float NdotH, float VdotH)
/// @return Specular BRDF value (D * Vis * F)
float3 SpecularMicroflakes(float roughness, float3 F0, float NdotL, float NdotV, float NdotH, float VdotH)
{
float D = BRDF::D_Charlie(roughness, NdotH);
float G = BRDF::Vis_Neubelt(NdotV, NdotL);
float3 F = BRDF::F_Schlick(specularColor, VdotH);
float3 F = BRDF::F_Schlick(F0, VdotH);

return D * G * F;
}
Expand Down Expand Up @@ -132,7 +132,6 @@ namespace PBR
/// @return Wetness specular color contribution
float3 GetWetnessDirectLightSpecularInput(float3 N, float3 V, float3 L, float3 lightColor, float roughness)
{
const float wetnessStrength = 1;
const float wetnessF0 = 0.02;

float3 H = normalize(V + L);
Expand All @@ -141,10 +140,10 @@ namespace PBR
float NdotH = saturate(dot(N, H));
float VdotH = saturate(dot(V, H));

float3 wetnessF;
float3 wetnessSpecular = GetSpecularDirectLightMultiplierMicrofacet(roughness, wetnessF0, NdotL, NdotV, NdotH, VdotH, wetnessF) * lightColor * NdotL;
float3 F;
float3 Fr = SpecularMicrofacet(roughness, wetnessF0, NdotL, NdotV, NdotH, VdotH, F);

return wetnessSpecular * wetnessStrength;
return Fr * lightColor * NdotL;
}

/// @brief Calculate wetness specular lobe weight for indirect lighting
Expand All @@ -154,14 +153,13 @@ namespace PBR
/// @return Wetness specular lobe weight
float3 GetWetnessIndirectSpecularLobeWeight(float3 N, float3 V, float roughness)
{
const float wetnessStrength = 1;
const float wetnessF0 = 0.02;

float NdotV = saturate(abs(dot(N, V)) + EPSILON_DOT_CLAMP);
float2 specularBRDF = BRDF::EnvBRDF(roughness, NdotV);
float3 specularLobeWeight = wetnessF0 * specularBRDF.x + specularBRDF.y;

return specularLobeWeight * wetnessStrength;
return specularLobeWeight;
}
}

Expand Down
Loading
Loading