Fix Indirect Light Sheen/ClearCoat specularAO (#2744)

* fix: pbr specularAO
This commit is contained in:
hhhhkrx
2025-06-20 12:05:48 +08:00
committed by GitHub
parent ac262f3915
commit 95135f4f23
4 changed files with 27 additions and 23 deletions

View File

@@ -21,8 +21,7 @@ struct SurfaceData{
vec3 emissiveColor;
float metallic;
float roughness;
float diffuseAO;
float specularAO;
float ambientOcclusion;
float f0;
float opacity;
float IOR;
@@ -79,6 +78,7 @@ struct BSDFData{
vec3 specularColor;
float roughness;
vec3 envSpecularDFG;
float diffuseAO;
#ifdef MATERIAL_ENABLE_CLEAR_COAT
vec3 clearCoatSpecularColor;
@@ -434,6 +434,8 @@ void initBSDFData(SurfaceData surfaceData, out BSDFData bsdfData){
bsdfData.roughness = max(MIN_PERCEPTUAL_ROUGHNESS, min(roughness + getAARoughnessFactor(surfaceData.normal), 1.0));
bsdfData.envSpecularDFG = envBRDFApprox(bsdfData.specularColor, bsdfData.roughness, surfaceData.dotNV);
bsdfData.diffuseAO = surfaceData.ambientOcclusion;
#ifdef MATERIAL_ENABLE_CLEAR_COAT
bsdfData.clearCoatRoughness = max(MIN_PERCEPTUAL_ROUGHNESS, min(surfaceData.clearCoatRoughness + getAARoughnessFactor(surfaceData.clearCoatNormal), 1.0));
bsdfData.clearCoatSpecularColor = vec3(0.04);

View File

@@ -221,7 +221,7 @@ SurfaceData getSurfaceData(Varyings v, vec2 aoUV, bool isFrontFacing){
#ifdef MATERIAL_HAS_NORMALTEXTURE
surfaceData.normal = getNormalByNormalTexture(tbn, material_NormalTexture, material_NormalIntensity, uv, isFrontFacing);
#endif
#endif
#endif
surfaceData.dotNV = saturate( dot(surfaceData.normal, surfaceData.viewDir) );
@@ -265,7 +265,7 @@ SurfaceData getSurfaceData(Varyings v, vec2 aoUV, bool isFrontFacing){
surfaceData.anisotropicN = getAnisotropicBentNormal(surfaceData);
#endif
//Iridescence
// Iridescence
#ifdef MATERIAL_ENABLE_IRIDESCENCE
surfaceData.iridescenceFactor = material_IridescenceInfo.x;
surfaceData.iridescenceIOR = material_IridescenceInfo.y;
@@ -310,21 +310,13 @@ SurfaceData getSurfaceData(Varyings v, vec2 aoUV, bool isFrontFacing){
#endif
#endif
// AO
float diffuseAO = 1.0;
float specularAO = 1.0;
// Ambient Occlusion
#ifdef MATERIAL_HAS_OCCLUSION_TEXTURE
diffuseAO = ((texture2D(material_OcclusionTexture, aoUV)).r - 1.0) * material_OcclusionIntensity + 1.0;
surfaceData.ambientOcclusion = ((texture2D(material_OcclusionTexture, aoUV)).r - 1.0) * material_OcclusionIntensity + 1.0;
#else
surfaceData.ambientOcclusion = 1.0;
#endif
#if defined(MATERIAL_HAS_OCCLUSION_TEXTURE) && defined(SCENE_USE_SPECULAR_ENV)
specularAO = saturate( pow( surfaceData.dotNV + diffuseAO, exp2( - 16.0 * surfaceData.roughness - 1.0 ) ) - 1.0 + diffuseAO );
#endif
surfaceData.diffuseAO = diffuseAO;
surfaceData.specularAO = specularAO;
return surfaceData;
}

View File

@@ -43,4 +43,13 @@ vec3 getLightProbeRadiance(SurfaceData surfaceData, vec3 normal, float roughness
#endif
}
float evaluateSpecularOcclusion(float dotNV, float diffuseAO, float roughness){
float specularAOFactor = 1.0;
#if defined(MATERIAL_HAS_OCCLUSION_TEXTURE) && defined(SCENE_USE_SPECULAR_ENV)
specularAOFactor = saturate( pow(dotNV + diffuseAO, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + diffuseAO );
#endif
return specularAOFactor;
}
#endif

View File

@@ -48,8 +48,7 @@ void evaluateDiffuseIBL(Varyings varyings, SurfaceData surfaceData, BSDFData bsd
vec3 irradiance = scene_EnvMapLight.diffuse * scene_EnvMapLight.diffuseIntensity;
irradiance *= PI;
#endif
diffuseColor += surfaceData.diffuseAO * irradiance * BRDF_Diffuse_Lambert( bsdfData.diffuseColor );
diffuseColor += bsdfData.diffuseAO * irradiance * BRDF_Diffuse_Lambert( bsdfData.diffuseColor );
}
float evaluateClearCoatIBL(Varyings varyings, SurfaceData surfaceData, BSDFData bsdfData, inout vec3 specularColor){
@@ -57,7 +56,8 @@ float evaluateClearCoatIBL(Varyings varyings, SurfaceData surfaceData, BSDFData
#ifdef MATERIAL_ENABLE_CLEAR_COAT
vec3 clearCoatRadiance = getLightProbeRadiance(surfaceData, surfaceData.clearCoatNormal, bsdfData.clearCoatRoughness);
specularColor += surfaceData.specularAO * clearCoatRadiance * surfaceData.clearCoat * envBRDFApprox(bsdfData.clearCoatSpecularColor, bsdfData.clearCoatRoughness, surfaceData.clearCoatDotNV);
float specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.clearCoatRoughness);
specularColor += specularAO * clearCoatRadiance * surfaceData.clearCoat * envBRDFApprox(bsdfData.clearCoatSpecularColor, bsdfData.clearCoatRoughness, surfaceData.clearCoatDotNV);
radianceAttenuation -= surfaceData.clearCoat * F_Schlick(surfaceData.f0, surfaceData.clearCoatDotNV);
#endif
@@ -72,16 +72,17 @@ void evaluateSpecularIBL(Varyings varyings, SurfaceData surfaceData, BSDFData bs
#else
vec3 speculaColor = bsdfData.specularColor;
#endif
outSpecularColor += surfaceData.specularAO * radianceAttenuation * radiance * envBRDFApprox(speculaColor, bsdfData.roughness, surfaceData.dotNV);
float specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.roughness);
outSpecularColor += specularAO * radianceAttenuation * radiance * envBRDFApprox(speculaColor, bsdfData.roughness, surfaceData.dotNV);
}
void evaluateSheenIBL(Varyings varyings, SurfaceData surfaceData, BSDFData bsdfData, float radianceAttenuation, inout vec3 diffuseColor, inout vec3 specularColor){
#ifdef MATERIAL_ENABLE_SHEEN
diffuseColor *= bsdfData.sheenScaling;
specularColor *= bsdfData.sheenScaling;
vec3 reflectance = surfaceData.specularAO * radianceAttenuation * bsdfData.approxIBLSheenDG * surfaceData.sheenColor;
float specularAO = evaluateSpecularOcclusion(surfaceData.dotNV, bsdfData.diffuseAO, bsdfData.sheenRoughness) ;
vec3 reflectance = specularAO * radianceAttenuation * bsdfData.approxIBLSheenDG * surfaceData.sheenColor;
specularColor += reflectance;
#endif
}