diff --git a/TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Vulkan/None/1451_AxF_SVBRDF.png b/TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Vulkan/None/1451_AxF_SVBRDF.png index 59a315367ee..ee8f0d73692 100644 --- a/TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Vulkan/None/1451_AxF_SVBRDF.png +++ b/TestProjects/HDRP_Tests/Assets/ReferenceImages/Linear/WindowsEditor/Vulkan/None/1451_AxF_SVBRDF.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8bdf1ab6a1eadcb6d50029cae7e8099d64d50f777307b6298fd856c679abe7c0 -size 156437 +oid sha256:6bba19dc68f61b58aae5de4d46cb82e260c9eed2483851d9cf0d7456233e4c99 +size 261 diff --git a/com.unity.render-pipelines.high-definition/CHANGELOG.md b/com.unity.render-pipelines.high-definition/CHANGELOG.md index 83302d72722..fcb551ac2fd 100644 --- a/com.unity.render-pipelines.high-definition/CHANGELOG.md +++ b/com.unity.render-pipelines.high-definition/CHANGELOG.md @@ -677,6 +677,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Fix issue that caused sky to incorrectly render when using a custom projection matrix. - Fixed null reference exception when using depth pre/post pass in shadergraph with alpha clip in the material. - Appropriately constraint blend distance of reflection probe while editing with the inspector (case 1248931) +- Fixed AxF handling of roughness for Blinn-Phong type materials +- Fixed AxF UI errors when surface type is switched to transparent ### Changed - Improve MIP selection for decals on Transparents diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/AxF/AxFGUI.cs b/com.unity.render-pipelines.high-definition/Editor/Material/AxF/AxFGUI.cs index 2f6a862523d..6b8320c8a02 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/AxF/AxFGUI.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Material/AxF/AxFGUI.cs @@ -132,8 +132,13 @@ static public void SetupMaterialKeywordsAndPass(Material material) // Keywords for opt-out of decals and SSR: bool decalsEnabled = material.HasProperty(kEnableDecals) && material.GetFloat(kEnableDecals) > 0.0f; CoreUtils.SetKeyword(material, "_DISABLE_DECALS", decalsEnabled == false); - bool ssrEnabled = material.HasProperty(kEnableSSR) && material.GetFloat(kEnableSSR) > 0.0f; - CoreUtils.SetKeyword(material, "_DISABLE_SSR", ssrEnabled == false); + bool ssrEnabled = false; + if (material.GetSurfaceType() == SurfaceType.Transparent) + ssrEnabled = material.HasProperty(kReceivesSSRTransparent) ? material.GetFloat(kReceivesSSRTransparent) != 0 : false; + else + ssrEnabled = material.HasProperty(kReceivesSSR) ? material.GetFloat(kReceivesSSR) != 0 : false; + CoreUtils.SetKeyword(material, "_DISABLE_SSR", material.HasProperty(kReceivesSSR) && material.GetFloat(kReceivesSSR) == 0.0f); + CoreUtils.SetKeyword(material, "_DISABLE_SSR_TRANSPARENT", material.HasProperty(kReceivesSSRTransparent) && material.GetFloat(kReceivesSSRTransparent) == 0.0); CoreUtils.SetKeyword(material, "_ENABLE_GEOMETRIC_SPECULAR_AA", material.HasProperty(kEnableGeometricSpecularAA) && material.GetFloat(kEnableGeometricSpecularAA) > 0.0f); CoreUtils.SetKeyword(material, "_SPECULAR_OCCLUSION_NONE", material.HasProperty(kSpecularOcclusionMode) && material.GetFloat(kSpecularOcclusionMode) == 0.0f); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxF.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxF.hlsl index d5bfd477c54..1b3bac4efa5 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxF.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxF.hlsl @@ -1175,7 +1175,8 @@ PreLightData GetPreLightData(float3 viewWS_Clearcoat, PositionInputs posInput preLightData.iblPerceptualRoughness = PerceptualRoughnessBeckmannToGGX(preLightData.iblPerceptualRoughness); break; - // case 1: // @TODO: Support Blinn-Phong FGD? + case 1: //Phong + case 4: //Blinn-Phong : just approximate with Cook-Torrance which uses a Beckmann distribution case 2: GetPreIntegratedFGDCookTorranceAndLambert(NdotV_UnderCoat, preLightData.iblPerceptualRoughness, tempF0, preLightData.specularFGD, preLightData.diffuseFGD, specularReflectivity); preLightData.specularFGD *= GetPreIntegratedFGDCookTorranceSampleMutiplier(); @@ -1186,8 +1187,6 @@ PreLightData GetPreLightData(float3 viewWS_Clearcoat, PositionInputs posInput GetPreIntegratedFGDGGXAndLambert(NdotV_UnderCoat, preLightData.iblPerceptualRoughness, tempF0, preLightData.specularFGD, preLightData.diffuseFGD, specularReflectivity); break; - // case 4: // @TODO: Support Blinn-Phong FGD? - default: // Use GGX by default GetPreIntegratedFGDGGXAndLambert(NdotV_UnderCoat, preLightData.iblPerceptualRoughness, tempF0, preLightData.specularFGD, preLightData.diffuseFGD, specularReflectivity); break; @@ -1356,14 +1355,6 @@ PreLightData GetPreLightData(float3 viewWS_Clearcoat, PositionInputs posInput case 1: // BLINN-PHONG case 4: // PHONG; { - // According to https://computergraphics.stackexchange.com/questions/1515/what-is-the-accepted-method-of-converting-shininess-to-roughness-and-vice-versa - // float exponent = 2/roughness^4 - 2; - // - float exponent = PerceptualRoughnessToRoughness(preLightData.iblPerceptualRoughness); - float roughness = pow(max(0.0, 2.0 / (exponent + 2)), 1.0 / 4.0); - // todo_modes todo_pseudorefract: cant use undercoat like that - //float2 UV = LTCGetSamplingUV(NdotV_UnderCoat, RoughnessToPerceptualRoughness(roughness)); - float2 UV = LTCGetSamplingUV(NdotV_Clearcoat, RoughnessToPerceptualRoughness(roughness)); preLightData.ltcTransformSpecular = LTCSampleMatrix(UV, LTC_MATRIX_INDEX_COOK_TORRANCE); break; } @@ -1572,7 +1563,8 @@ float3 ComputeWard(float3 H, float LdotH, float NdotL, float NdotV, PreLightData float3 ComputeBlinnPhong(float3 H, float LdotH, float NdotL, float NdotV, PreLightData preLightData, BSDFData bsdfData) { - float2 exponents = exp2(bsdfData.roughness.xy); + // See AxFGetRoughnessFromSpecularLobeTexture in AxFData + float2 exponents = 2 * rcp(max(0.0001,(bsdfData.roughness.xy*bsdfData.roughness.xy))) - 2; // Evaluate normal distribution function float3 tsH = float3(dot(H, bsdfData.tangentWS), dot(H, bsdfData.biTangentWS), dot(H, bsdfData.normalWS)); diff --git a/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxF.shader b/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxF.shader index 7a1f5a3f2c7..c79b757d885 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxF.shader +++ b/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxF.shader @@ -142,7 +142,7 @@ Shader "HDRP/AxF" [ToggleUI] _SupportDecals("Support Decals", Float) = 1.0 [ToggleUI] _ReceivesSSR("Receives SSR", Float) = 1.0 - + [ToggleUI] _ReceivesSSRTransparent("Receives SSR Transparent", Float) = 0.0 [ToggleUI] _AddPrecomputedVelocity("AddPrecomputedVelocity", Float) = 0.0 } @@ -169,6 +169,7 @@ Shader "HDRP/AxF" #pragma shader_feature_local _DISABLE_DECALS #pragma shader_feature_local _DISABLE_SSR + #pragma shader_feature_local _DISABLE_SSR_TRANSPARENT #pragma shader_feature_local _ENABLE_GEOMETRIC_SPECULAR_AA #pragma shader_feature_local _ADD_PRECOMPUTED_VELOCITY diff --git a/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxFData.hlsl b/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxFData.hlsl index a2faf238a6b..5a58b7cdeed 100644 --- a/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxFData.hlsl +++ b/com.unity.render-pipelines.high-definition/Runtime/Material/AxF/AxFData.hlsl @@ -464,6 +464,29 @@ void ApplyDecalToSurfaceData(DecalSurfaceData decalSurfaceData, inout SurfaceDat #endif } +bool HasPhongTypeBRDF() +{ + uint type = ((_SVBRDF_BRDFType >> 1) & 7); + return type == 1 || type == 4; +} + +float2 AxFGetRoughnessFromSpecularLobeTexture(float2 specularLobe) +{ + // For Blinn-Phong, AxF encodes specularLobe.xy as log2(shiniExp_xy) so + // shiniExp = exp2(abs(specularLobe.xy)) + // A good fit for a corresponding Beckmann roughness is + // roughnessBeckmann^2 = 2 /(shiniExp + 2) + // See eg + // http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html + // http://simonstechblog.blogspot.com/2011/12/microfacet-brdf.html + + // We thus have + // roughnessBeckmann = sqrt(2) * rsqrt(exp2(abs(specularLobe.xy)) + 2); + // shiniExp = 2 * rcp(max(0.0001,(roughnessBeckmann*roughnessBeckmann))) - 2; + + return (HasPhongTypeBRDF() ? (sqrt(2) * rsqrt(exp2(abs(specularLobe)) + 2)) : specularLobe); +} + void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData) { #ifdef _DOUBLESIDED_ON @@ -479,8 +502,18 @@ void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs p InitTextureUVMapping(input, uvMapping); ZERO_INITIALIZE(SurfaceData, surfaceData); + float alpha = AXF_SAMPLE_SMP_TEXTURE2D(_SVBRDF_AlphaMap, sampler_SVBRDF_AlphaMap, uvMapping).x; + +#ifdef _ALPHATEST_ON + // TODOTODO: Move alpha test earlier and test. + float alphaCutoff = _AlphaCutoff; - float alpha = 1.0; + #if SHADERPASS == SHADERPASS_SHADOWS + GENERIC_ALPHA_TEST(alpha, _UseShadowThreshold ? _AlphaCutoffShadow : alphaCutoff); + #else + GENERIC_ALPHA_TEST(alpha, alphaCutoff); + #endif +#endif surfaceData.ambientOcclusion = 1.0; surfaceData.specularOcclusion = 1.0; @@ -494,7 +527,8 @@ void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs p surfaceData.diffuseColor = AXF_SAMPLE_SMP_TEXTURE2D(_SVBRDF_DiffuseColorMap, sampler_SVBRDF_DiffuseColorMap, uvMapping).xyz; surfaceData.specularColor = AXF_SAMPLE_SMP_TEXTURE2D(_SVBRDF_SpecularColorMap, sampler_SVBRDF_SpecularColorMap, uvMapping).xyz; - surfaceData.specularLobe.xy = _SVBRDF_SpecularLobeMapScale * AXF_SAMPLE_SMP_TEXTURE2D(_SVBRDF_SpecularLobeMap, sampler_SVBRDF_SpecularLobeMap, uvMapping).xy; + surfaceData.specularLobe.xy = _SVBRDF_SpecularLobeMapScale * AxFGetRoughnessFromSpecularLobeTexture( + AXF_SAMPLE_SMP_TEXTURE2D(_SVBRDF_SpecularLobeMap, sampler_SVBRDF_SpecularLobeMap, uvMapping).xy); // The AxF models include both a general coloring term that they call "specular color" while the f0 is actually another term, // seemingly always scalar: @@ -524,8 +558,6 @@ void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs p // Useless for SVBRDF, will be optimized out //SetFlakesSurfaceData(uvMapping, surfaceData); - alpha = AXF_SAMPLE_SMP_TEXTURE2D(_SVBRDF_AlphaMap, sampler_SVBRDF_AlphaMap, uvMapping).x; - //----------------------------------------------------------------------------- // _AXF_BRDF_TYPE_CAR_PAINT //----------------------------------------------------------------------------- @@ -604,17 +636,6 @@ void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs p // the handedness of the world space (tangentToWorld can be passed right handed while // Unity's WS is left handed, so this makes a difference here). -#ifdef _ALPHATEST_ON - // TODOTODO: Move alpha test earlier and test. - float alphaCutoff = _AlphaCutoff; - - #if SHADERPASS == SHADERPASS_SHADOWS - GENERIC_ALPHA_TEST(alpha, _UseShadowThreshold ? _AlphaCutoffShadow : alphaCutoff); - #else - GENERIC_ALPHA_TEST(alpha, alphaCutoff); - #endif -#endif - #if defined(_ENABLE_GEOMETRIC_SPECULAR_AA) // Specular AA for geometric curvature