diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index e1b99fc409..e7e56f0e4c 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -65,23 +65,46 @@ namespace AZ { static constexpr char ShaderVariantAssetBuilderName[] = "ShaderVariantAssetBuilder"; - static void AddShaderAssetJobDependency( - AssetBuilderSDK::JobDescriptor& jobDescriptor, const AssetBuilderSDK::PlatformInfo& platformInfo, - const AZStd::string& shaderVariantListFilePath, const AZStd::string& shaderFilePath) + //! Adds source file dependencies for every place a referenced file may appear, and detects if one of + //! those possible paths resolves to the expected file. + //! @param currentFilePath - the full path to the file being processed + //! @param referencedParentPath - the path to a reference file, which may be relative to the @currentFilePath, or may be a full asset path. + //! @param sourceFileDependencies - new source file dependencies will be added to this list + //! @param foundSourceFile - if one of the source file dependencies is found, the highest priority one will be indicated here, otherwise this will be empty. + //! @return true if the referenced file was found and @foundSourceFile was set + bool LocateReferencedSourceFile( + AZStd::string_view currentFilePath, AZStd::string_view referencedParentPath, + AZStd::vector& sourceFileDependencies, + AZStd::string& foundSourceFile) { - AZStd::vector possibleDependencies = - AZ::RPI::AssetUtils::GetPossibleDepenencyPaths(shaderVariantListFilePath, shaderFilePath); + foundSourceFile.clear(); + + bool found = false; + + AZStd::vector possibleDependencies = RPI::AssetUtils::GetPossibleDepenencyPaths(currentFilePath, referencedParentPath); for (auto& file : possibleDependencies) { - AssetBuilderSDK::JobDependency jobDependency; - jobDependency.m_jobKey = ShaderAssetBuilder::ShaderAssetBuilderJobKey; - jobDependency.m_platformIdentifier = platformInfo.m_identifier; - jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; - jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; - jobDescriptor.m_jobDependencyList.push_back(jobDependency); + AssetBuilderSDK::SourceFileDependency sourceFileDependency; + sourceFileDependency.m_sourceFileDependencyPath = file; + sourceFileDependencies.push_back(sourceFileDependency); + + if (!found) + { + AZ::Data::AssetInfo sourceInfo; + AZStd::string watchFolder; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(found, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, file.c_str(), sourceInfo, watchFolder); + + if (found) + { + foundSourceFile = file; + } + } } + + return found; } + //! Returns true if @sourceFileFullPath starts with a valid asset processor scan folder, false otherwise. //! In case of true, it splits @sourceFileFullPath into @scanFolderFullPath and @filePathFromScanFolder. //! @sourceFileFullPath The full path to a source asset file. @@ -288,6 +311,9 @@ namespace AZ response.m_result = AssetBuilderSDK::CreateJobsResultCode::Failed; return; } + + AZStd::string foundShaderFile; + LocateReferencedSourceFile(variantListFullPath, shaderVariantList.m_shaderFilePath, response.m_sourceFileDependencyList, foundShaderFile); if (loadResult.m_code == LoadResult::Code::DeferredError || shouldExitEarlyFromProcessJob) { @@ -300,8 +326,16 @@ namespace AZ jobDescriptor.m_critical = false; jobDescriptor.m_jobKey = ShaderVariantAssetBuilderJobKey; jobDescriptor.SetPlatformIdentifier(info.m_identifier.data()); - - AddShaderAssetJobDependency(jobDescriptor, info, variantListFullPath, shaderVariantList.m_shaderFilePath); + + if (!foundShaderFile.empty()) + { + AssetBuilderSDK::JobDependency jobDependency; + jobDependency.m_jobKey = ShaderAssetBuilder::ShaderAssetBuilderJobKey; + jobDependency.m_platformIdentifier = info.m_identifier; + jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; + jobDependency.m_sourceFile.m_sourceFileDependencyPath = foundShaderFile; + jobDescriptor.m_jobDependencyList.push_back(jobDependency); + } if (loadResult.m_code == LoadResult::Code::DeferredError) { @@ -321,7 +355,7 @@ namespace AZ response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success; return; } - + for (const AssetBuilderSDK::PlatformInfo& info : request.m_enabledPlatforms) { AZ_TraceContext("For platform", info.m_identifier.data()); @@ -336,8 +370,16 @@ namespace AZ jobDescriptor.m_jobKey = GetShaderVariantTreeAssetJobKey(); jobDescriptor.SetPlatformIdentifier(info.m_identifier.data()); - - AddShaderAssetJobDependency(jobDescriptor, info, variantListFullPath, shaderVariantList.m_shaderFilePath); + + if (!foundShaderFile.empty()) + { + AssetBuilderSDK::JobDependency jobDependency; + jobDependency.m_jobKey = ShaderAssetBuilder::ShaderAssetBuilderJobKey; + jobDependency.m_platformIdentifier = info.m_identifier; + jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; + jobDependency.m_sourceFile.m_sourceFileDependencyPath = foundShaderFile; + jobDescriptor.m_jobDependencyList.push_back(jobDependency); + } jobDescriptor.m_jobParameters.emplace(ShaderSourceFilePathJobParam, shaderSourceFileFullPath); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index c635f94d56..0263f12245 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -714,6 +714,19 @@ "displayName": "Double-sided", "description": "Whether to render back-faces or just front-faces.", "type": "Bool" + }, + { + "id": "alphaAffectsSpecular", + "displayName": "Alpha affects specular", + "description": "How much the alpha value should also affect specular reflection. This should be 0.0 for materials where light can transmit through their physical surface (like glass), but 1.0 when alpha determines the very presence of a surface (like hair or grass)", + "type": "float", + "min": 0.0, + "max": 1.0, + "defaultValue": 0.0, + "connection": { + "type": "ShaderInput", + "id": "m_opacityAffectsSpecularFactor" + } } ], "uv": [ @@ -1669,4 +1682,3 @@ "UV1": "Unwrapped" } } - diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli index b6d6439268..3016adeadf 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_Common.azsli @@ -55,6 +55,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial float m_anisotropicFactor; // Base layer anisotropic strength of deviation: negative = Bi-Normal direction, positive = Tangent direction float m_opacityFactor; + float m_opacityAffectsSpecularFactor; Texture2D m_opacityMap; uint m_opacityMapUvIndex; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index a8b4075d51..b563a64b75 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -331,7 +331,8 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) { - alpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; // Increase opacity at grazing angles. + float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; // Increase opacity at grazing angles. + alpha = lerp(fresnelAlpha, alpha, MaterialSrg::m_opacityAffectsSpecularFactor); } PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); @@ -349,8 +350,13 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. // It's done this way because surface transparency doesn't really change specular response (eg, glass). + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - lightingOutput.m_diffuseColor.rgb += lightingOutput.m_specularColor.rgb; // add specular + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; } else if (o_opacity_mode == OpacityMode::TintedTransparent) { @@ -367,7 +373,12 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - lightingOutput.m_diffuseColor.rgb += lightingOutput.m_specularColor.rgb; // add specular + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + lightingOutput.m_specularColor.rgb = baseColor * (1.0 - lightingOutput.m_diffuseColor.w); } else @@ -415,4 +426,3 @@ ForwardPassOutput EnhancedPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : return OUT; } - diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index fd2c74dae0..0d3cf831aa 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -655,6 +655,19 @@ "displayName": "Double-sided", "description": "Whether to render back-faces or just front-faces.", "type": "Bool" + }, + { + "id": "alphaAffectsSpecular", + "displayName": "Alpha affects specular", + "description": "How much the alpha value should also affect specular reflection. This should be 0.0 for materials where light can transmit through their physical surface (like glass), but 1.0 when alpha determines the very presence of a surface (like hair or grass)", + "type": "float", + "min": 0.0, + "max": 1.0, + "defaultValue": 0.0, + "connection": { + "type": "ShaderInput", + "id": "m_opacityAffectsSpecularFactor" + } } ], "uv": [ @@ -1187,4 +1200,3 @@ "UV1": "Unwrapped" } } - diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Common.azsli index f339642a4d..e369042e9a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_Common.azsli @@ -50,6 +50,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial float4 m_pad2; // [GFX TODO][ATOM-14595] This is a workaround for a data stomping bug. Remove once it's fixed. float m_opacityFactor; + float m_opacityAffectsSpecularFactor; Texture2D m_opacityMap; uint m_opacityMapUvIndex; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl index 23e4ef0c10..698e9b5c54 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl @@ -259,7 +259,8 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent) { - alpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; // Increase opacity at grazing angles. + float fresnelAlpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; // Increase opacity at grazing angles. + alpha = lerp(fresnelAlpha, alpha, MaterialSrg::m_opacityAffectsSpecularFactor); } PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha); @@ -274,8 +275,13 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // For blended mode, we do (dest * alpha) + (source * 1.0). This allows the specular // to be added on top of the diffuse, but then the diffuse must be pre-multiplied. // It's done this way because surface transparency doesn't really change specular response (eg, glass). + lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - lightingOutput.m_diffuseColor.rgb += lightingOutput.m_specularColor.rgb; // add specular + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; } else if (o_opacity_mode == OpacityMode::TintedTransparent) { @@ -292,7 +298,12 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // m_diffuseColor.rgb (source) is added to that, and the final result is stored in render target 0. lightingOutput.m_diffuseColor.rgb *= lightingOutput.m_diffuseColor.w; // pre-multiply diffuse - lightingOutput.m_diffuseColor.rgb += lightingOutput.m_specularColor.rgb; // add specular + + // Add specular. m_opacityAffectsSpecularFactor controls how much the alpha masks out specular contribution. + float3 specular = lightingOutput.m_specularColor.rgb; + specular = lerp(specular, specular * lightingOutput.m_diffuseColor.w, MaterialSrg::m_opacityAffectsSpecularFactor); + lightingOutput.m_diffuseColor.rgb += specular; + lightingOutput.m_specularColor.rgb = baseColor * (1.0 - lightingOutput.m_diffuseColor.w); } else diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/AssetUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/AssetUtils.h index 86c381e2ec..9b177bacda 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/AssetUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Common/AssetUtils.h @@ -63,6 +63,7 @@ namespace AZ //! it's possible that b.json could be found in either MyGem/Assets/Foo/Bar/a.json or in MyGem/Assets/Bar/a.json. //! @param originatingSourceFilePath Path to a file that references referencedSourceFilePath. May be absolute or relative to asset-root. //! @param referencedSourceFilePath The referenced path as it appears in the originating file. May be relative to the originating file location or relative to asset-root. + //! @return the list of possible paths, ordered from highest priority to lowest priority AZStd::vector GetPossibleDepenencyPaths(const AZStd::string& originatingSourceFilePath, const AZStd::string& referencedSourceFilePath); // Definitions... diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 0cd0b7cff1..e5fb2068b1 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -66,16 +66,41 @@ namespace AZ BusDisconnect(); } - void AddPossibleJobDependencies(const char* jobKey, AZStd::string_view currentFilePath, AZStd::string_view referencedParentPath, AZStd::vector& jobDependencies) + //! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path. + //! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found. + //! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back + //! to the AssetBuilderSDK::CreateJobsResponse. + void AddPossibleDependencies( + AZStd::string_view currentFilePath, AZStd::string_view referencedParentPath, + AZStd::vector& sourceFileDependencies, + const char* jobKey, AZStd::vector& jobDependencies) { - AZStd::vector possibleDependencies = AssetUtils::GetPossibleDepenencyPaths(currentFilePath, referencedParentPath); + bool dependencyFileFound = false; + + AZStd::vector possibleDependencies = RPI::AssetUtils::GetPossibleDepenencyPaths(currentFilePath, referencedParentPath); for (auto& file : possibleDependencies) { - AssetBuilderSDK::JobDependency jobDependency; - jobDependency.m_jobKey = jobKey; - jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; - jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; - jobDependencies.push_back(jobDependency); + AssetBuilderSDK::SourceFileDependency sourceFileDependency; + sourceFileDependency.m_sourceFileDependencyPath = file; + sourceFileDependencies.push_back(sourceFileDependency); + + // The first path found is the highest priority, and will have a job dependency, as this is the one + // the builder will actually use + if (!dependencyFileFound) + { + AZ::Data::AssetInfo sourceInfo; + AZStd::string watchFolder; + AzToolsFramework::AssetSystemRequestBus::BroadcastResult(dependencyFileFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, file.c_str(), sourceInfo, watchFolder); + + if (dependencyFileFound) + { + AssetBuilderSDK::JobDependency jobDependency; + jobDependency.m_jobKey = jobKey; + jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; + jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; + jobDependencies.push_back(jobDependency); + } + } } } @@ -122,7 +147,7 @@ namespace AZ // We'll build up this one JobDescriptor and reuse it to register each of the platforms AssetBuilderSDK::JobDescriptor outputJobDescriptor; outputJobDescriptor.m_jobKey = JobKey; - + // Load the file so we can detect and report dependencies. // If the file is a .materialtype, report dependencies on the .shader files. // If the file is a .material, report a dependency on the .materialtype and parent .material file @@ -151,7 +176,9 @@ namespace AZ for (auto& shader : materialTypeSourceData.GetValue().m_shaderCollection) { - AddPossibleJobDependencies("Shader Asset", request.m_sourceFile, shader.m_shaderFilePath, outputJobDescriptor.m_jobDependencyList); + AddPossibleDependencies(request.m_sourceFile, shader.m_shaderFilePath, + response.m_sourceFileDependencyList, "Shader Asset", + outputJobDescriptor.m_jobDependencyList); } for (auto& functor : materialTypeSourceData.GetValue().m_materialFunctorSourceData) @@ -160,7 +187,9 @@ namespace AZ for (const MaterialFunctorSourceData::AssetDependency& dependency : dependencies) { - AddPossibleJobDependencies(dependency.m_jobKey.c_str(), request.m_sourceFile, dependency.m_sourceFilePath, outputJobDescriptor.m_jobDependencyList); + AddPossibleDependencies(request.m_sourceFile, dependency.m_sourceFilePath, + response.m_sourceFileDependencyList, + dependency.m_jobKey.c_str(), outputJobDescriptor.m_jobDependencyList); } } } @@ -195,7 +224,9 @@ namespace AZ // Register dependency on the parent material source file so we can load it and use it's data to build this variant material. // Note, we don't need a direct dependency on the material type because the parent material will depend on it. - AddPossibleJobDependencies(JobKey, request.m_sourceFile, parentMaterialPath, outputJobDescriptor.m_jobDependencyList); + AddPossibleDependencies(request.m_sourceFile, parentMaterialPath, + response.m_sourceFileDependencyList, + JobKey, outputJobDescriptor.m_jobDependencyList); } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp index 3cefa696c3..bb72df38d2 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Edit/Common/AssetUtils.cpp @@ -103,31 +103,16 @@ namespace AZ AZStd::vector GetPossibleDepenencyPaths(const AZStd::string& originatingSourceFilePath, const AZStd::string& referencedSourceFilePath) { - // We potentially add the parent dependency as both a direct path and a relative path rather than use AssetUtils::ResolvePathReference - // because there is no guarantee that the Asset Processor has seen the parent file yet (which ResolvePathReference requires). - // In that case, we have to add both possible locations because we don't know where it will show up. - AZStd::vector results; - // The first dependency we add is using the referencedSourceFilePath as a relative path. This gives relative paths priority over asset-root paths. + // Use the referencedSourceFilePath as a relative path starting at originatingSourceFilePath AZStd::string combinedPath = originatingSourceFilePath; AzFramework::StringFunc::Path::StripFullName(combinedPath); AzFramework::StringFunc::Path::Join(combinedPath.c_str(), referencedSourceFilePath.c_str(), combinedPath); results.push_back(combinedPath); - // If the parent file exists at the relative path, then there is no need to report a dependency on the asset-root path. - bool assetFound = false; - AZ::Data::AssetInfo sourceInfo; - AZStd::string watchFolder; - AzToolsFramework::AssetSystemRequestBus::BroadcastResult(assetFound, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, combinedPath.c_str(), sourceInfo, watchFolder); - - if (!assetFound) - { - // The parent file wasn't found at the relative path, so we need a dependency on the asset-root path in case the file - // exists there. Note, we still keep the relative path dependency above because we don't know whether it's missing because - // it doesn't exist, or just because the AP hasn't found it yet. - results.push_back(referencedSourceFilePath); - } + // Use the referencedSourceFilePath as a standard asset path + results.push_back(referencedSourceFilePath); return results; } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended_Alpha_Affects_Specular.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended_Alpha_Affects_Specular.material new file mode 100644 index 0000000000..dbaec36136 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/009_Opacity_Blended_Alpha_Affects_Specular.material @@ -0,0 +1,24 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardPBR.materialtype", + "parentMaterial": "", + "propertyLayoutVersion": 3, + "properties": { + "baseColor": { + "color": [ + 0.5906767249107361, + 1.0, + 0.11703670024871826, + 1.0 + ], + "textureMap": "Textures/Default/default_basecolor.tif" + }, + "opacity": { + "alphaSource": "Split", + "factor": 0.75, + "mode": "Blended", + "textureMap": "TestData/Textures/checker8x8_gray_512.png", + "alphaAffectsSpecular": 1.0 + } + } +}