From 95135f4f2343fa73e4e793ec0923121019821985 Mon Sep 17 00:00:00 2001 From: hhhhkrx <155431265+hhhhkrx@users.noreply.github.com> Date: Fri, 20 Jun 2025 12:05:48 +0800 Subject: [PATCH] Fix Indirect Light Sheen/ClearCoat specularAO (#2744) * fix: pbr specularAO --- .../src/shaders/shadingPBR/BSDF.glsl | 6 ++++-- .../src/shaders/shadingPBR/FragmentPBR.glsl | 20 ++++++------------- .../shadingPBR/LightIndirectFunctions.glsl | 9 +++++++++ .../shaders/shadingPBR/LightIndirectPBR.glsl | 15 +++++++------- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/packages/shader-shaderlab/src/shaders/shadingPBR/BSDF.glsl b/packages/shader-shaderlab/src/shaders/shadingPBR/BSDF.glsl index 6a5904a1a..335c375d8 100644 --- a/packages/shader-shaderlab/src/shaders/shadingPBR/BSDF.glsl +++ b/packages/shader-shaderlab/src/shaders/shadingPBR/BSDF.glsl @@ -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); diff --git a/packages/shader-shaderlab/src/shaders/shadingPBR/FragmentPBR.glsl b/packages/shader-shaderlab/src/shaders/shadingPBR/FragmentPBR.glsl index fa1471ccc..4984aa78c 100644 --- a/packages/shader-shaderlab/src/shaders/shadingPBR/FragmentPBR.glsl +++ b/packages/shader-shaderlab/src/shaders/shadingPBR/FragmentPBR.glsl @@ -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; } diff --git a/packages/shader-shaderlab/src/shaders/shadingPBR/LightIndirectFunctions.glsl b/packages/shader-shaderlab/src/shaders/shadingPBR/LightIndirectFunctions.glsl index ca69a887a..599693674 100644 --- a/packages/shader-shaderlab/src/shaders/shadingPBR/LightIndirectFunctions.glsl +++ b/packages/shader-shaderlab/src/shaders/shadingPBR/LightIndirectFunctions.glsl @@ -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 \ No newline at end of file diff --git a/packages/shader-shaderlab/src/shaders/shadingPBR/LightIndirectPBR.glsl b/packages/shader-shaderlab/src/shaders/shadingPBR/LightIndirectPBR.glsl index 37eec9a46..3ada18cc6 100644 --- a/packages/shader-shaderlab/src/shaders/shadingPBR/LightIndirectPBR.glsl +++ b/packages/shader-shaderlab/src/shaders/shadingPBR/LightIndirectPBR.glsl @@ -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 }