diff --git a/AutomatedTesting/surfacetypemateriallibrary.physmaterial b/AutomatedTesting/surfacetypemateriallibrary.physmaterial
index 434d673998..481cd2fbfa 100644
--- a/AutomatedTesting/surfacetypemateriallibrary.physmaterial
+++ b/AutomatedTesting/surfacetypemateriallibrary.physmaterial
@@ -4,17 +4,152 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
index 1010ae3473..7b33359023 100644
--- a/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
+++ b/Code/Framework/AzCore/AzCore/Component/ComponentApplication.cpp
@@ -77,6 +77,27 @@
#endif // defined(AZ_ENABLE_DEBUG_TOOLS)
#include
+#include
+
+static void PrintEntityName(const AZ::ConsoleCommandContainer& arguments)
+{
+ if (arguments.empty())
+ {
+ return;
+ }
+
+ const auto entityIdStr = AZStd::string(arguments.front());
+ const auto entityIdValue = AZStd::stoull(entityIdStr);
+
+ AZStd::string entityName;
+ AZ::ComponentApplicationBus::BroadcastResult(
+ entityName, &AZ::ComponentApplicationBus::Events::GetEntityName, AZ::EntityId(entityIdValue));
+
+ AZ_Printf("Entity Debug", "EntityId: %" PRIu64 ", Entity Name: %s", entityIdValue, entityName.c_str());
+}
+
+AZ_CONSOLEFREEFUNC(
+ PrintEntityName, AZ::ConsoleFunctorFlags::Null, "Parameter: EntityId value, Prints the name of the entity to the console");
namespace AZ
{
diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
index d5f02c957c..559f7ce460 100644
--- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
+++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp
@@ -29,7 +29,7 @@ namespace AzFramework
AZ_CVAR(float, ed_cameraSystemOrbitDollyScrollSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemOrbitDollyCursorSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemScrollTranslateSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
- AZ_CVAR(float, ed_cameraSystemMinOrbitDistance, 6.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
+ AZ_CVAR(float, ed_cameraSystemMinOrbitDistance, 10.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 50.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemLookSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(float, ed_cameraSystemTranslateSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
@@ -37,7 +37,6 @@ namespace AzFramework
AZ_CVAR(float, ed_cameraSystemPanSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(bool, ed_cameraSystemPanInvertX, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(bool, ed_cameraSystemPanInvertY, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
- AZ_CVAR(float, ed_cameraSystemLookDeadzone, 2.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
AZ_CVAR(
AZ::CVarFixedString, ed_cameraSystemTranslateForwardKey, "keyboard_key_alphanumeric_W", nullptr, AZ::ConsoleFunctorFlags::Null, "");
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
index e4507227b5..d7de634c11 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.cpp
@@ -303,6 +303,45 @@ namespace AzToolsFramework
return true;
}
+ bool PrefabLoader::SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath)
+ {
+ AZ_Assert(absolutePath.IsAbsolute(), "SaveTemplateToFile requires an absolute path for saving the initial prefab file.");
+
+ const auto& domAndFilepath = StoreTemplateIntoFileFormat(templateId);
+ if (!domAndFilepath)
+ {
+ return false;
+ }
+
+ // Verify that the absolute path provided to this matches the relative path saved in the template.
+ // Otherwise, the saved prefab won't be able to be loaded.
+ auto relativePath = GenerateRelativePath(absolutePath);
+ if (relativePath != domAndFilepath->second)
+ {
+ AZ_Error(
+ "Prefab", false,
+ "PrefabLoader::SaveTemplateToFile - "
+ "Failed to save template '%s' to location '%.*s'."
+ "Error: Relative path '%.*s' for location didn't match template name.",
+ domAndFilepath->second.c_str(), AZ_STRING_ARG(absolutePath.Native()), AZ_STRING_ARG(relativePath.Native()));
+ return false;
+ }
+
+ auto outcome = AzFramework::FileFunc::WriteJsonFile(domAndFilepath->first, absolutePath);
+ if (!outcome.IsSuccess())
+ {
+ AZ_Error(
+ "Prefab", false,
+ "PrefabLoader::SaveTemplateToFile - "
+ "Failed to save template '%s' to location '%.*s'."
+ "Error: %s",
+ domAndFilepath->second.c_str(), AZ_STRING_ARG(absolutePath.Native()), outcome.GetError().c_str());
+ return false;
+ }
+ m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, false);
+ return true;
+ }
+
bool PrefabLoader::SaveTemplateToString(TemplateId templateId, AZStd::string& output)
{
const auto& domAndFilepath = StoreTemplateIntoFileFormat(templateId);
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
index aed24e153e..3722e14a97 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoader.h
@@ -72,6 +72,16 @@ namespace AzToolsFramework
*/
bool SaveTemplate(TemplateId templateId) override;
+ /**
+ * Saves a Prefab Template to the provided absolute source path, which needs to match the relative path in the template.
+ * Converts Prefab Template form into .prefab form by collapsing nested Template info
+ * into a source path and patches.
+ * @param templateId Id of the template to be saved
+ * @param absolutePath Absolute path to save the file to
+ * @return bool on whether the operation succeeded or not
+ */
+ bool SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath) override;
+
/**
* Saves a Prefab Template into the provided output string.
* Converts Prefab Template form into .prefab form by collapsing nested Template info
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
index d71fbff80f..0e551cee6b 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabLoaderInterface.h
@@ -60,6 +60,16 @@ namespace AzToolsFramework
*/
virtual bool SaveTemplate(TemplateId templateId) = 0;
+ /**
+ * Saves a Prefab Template to the provided absolute source path, which needs to match the relative path in the template.
+ * Converts Prefab Template form into .prefab form by collapsing nested Template info
+ * into a source path and patches.
+ * @param templateId Id of the template to be saved
+ * @param absolutePath Absolute path to save the file to
+ * @return bool on whether the operation succeeded or not
+ */
+ virtual bool SaveTemplateToFile(TemplateId templateId, AZ::IO::PathView absolutePath) = 0;
+
/**
* Saves a Prefab Template into the provided output string.
* Converts Prefab Template form into .prefab form by collapsing nested Template info
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
index 9dd5199ea2..fadcc1b81f 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
@@ -64,7 +64,7 @@ namespace AzToolsFramework
m_prefabUndoCache.Destroy();
}
- PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath)
+ PrefabOperationResult PrefabPublicHandler::CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath)
{
EntityList inputEntityList, topLevelEntities;
AZ::EntityId commonRootEntityId;
@@ -76,6 +76,8 @@ namespace AzToolsFramework
return findCommonRootOutcome;
}
+ AZ_Assert(absolutePath.IsAbsolute(), "CreatePrefab requires an absolute path for saving the initial prefab file.");
+
InstanceOptionalReference instanceToCreate;
{
// Initialize Undo Batch object
@@ -144,7 +146,8 @@ namespace AzToolsFramework
// Create the Prefab
instanceToCreate = prefabEditorEntityOwnershipInterface->CreatePrefab(
- entities, AZStd::move(instancePtrs), filePath, commonRootEntityOwningInstance);
+ entities, AZStd::move(instancePtrs), m_prefabLoaderInterface->GenerateRelativePath(absolutePath),
+ commonRootEntityOwningInstance);
if (!instanceToCreate)
{
@@ -254,7 +257,7 @@ namespace AzToolsFramework
}
// Save Template to file
- m_prefabLoaderInterface->SaveTemplate(instanceToCreate->get().GetTemplateId());
+ m_prefabLoaderInterface->SaveTemplateToFile(instanceToCreate->get().GetTemplateId(), absolutePath);
return AZ::Success();
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
index 7e2357dd44..e68a3e0b1e 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h
@@ -46,7 +46,7 @@ namespace AzToolsFramework
void UnregisterPrefabPublicHandlerInterface();
// PrefabPublicInterface...
- PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) override;
+ PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath) override;
PrefabOperationResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) override;
PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override;
PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h
index 0750c4d264..2e9152fd1b 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicInterface.h
@@ -46,10 +46,10 @@ namespace AzToolsFramework
* Create a prefab out of the entities provided, at the path provided.
* Automatically detects descendants of entities, and discerns between entities and child instances.
* @param entityIds The entities that should form the new prefab (along with their descendants).
- * @param filePath The path for the new prefab file.
+ * @param filePath The absolute path for the new prefab file.
* @return An outcome object; on failure, it comes with an error message detailing the cause of the error.
*/
- virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView filePath) = 0;
+ virtual PrefabOperationResult CreatePrefab(const AZStd::vector& entityIds, AZ::IO::PathView absolutePath) = 0;
/**
* Instantiate a prefab from a prefab file.
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
index 61d4433c0e..021b97a7dd 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp
@@ -333,8 +333,7 @@ namespace AzToolsFramework
}
}
- auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(
- selectedEntities, s_prefabLoaderInterface->GenerateRelativePath(prefabFilePath.data()));
+ auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, prefabFilePath.data());
if (!createPrefabOutcome.IsSuccess())
{
diff --git a/Code/Tools/Android/ProjectBuilder/build.gradle.in b/Code/Tools/Android/ProjectBuilder/build.gradle.in
index 66f58294ab..5980984516 100644
--- a/Code/Tools/Android/ProjectBuilder/build.gradle.in
+++ b/Code/Tools/Android/ProjectBuilder/build.gradle.in
@@ -15,14 +15,14 @@ android {
${SIGNING_CONFIGS}
compileSdkVersion sdkVer
buildToolsVersion buildToolsVer
-
+ ndkVersion ndkPlatformVer
lintOptions {
abortOnError false
checkReleaseBuilds false
}
defaultConfig {
- minSdkVersion ndkPlatformVer
+ minSdkVersion minSdkVer
targetSdkVersion sdkVer
${NATIVE_CMAKE_SECTION_DEFAULT_CONFIG}
}
diff --git a/Code/Tools/Android/ProjectBuilder/local.properties.in b/Code/Tools/Android/ProjectBuilder/local.properties.in
index 559ea67bcb..4e82cb2940 100644
--- a/Code/Tools/Android/ProjectBuilder/local.properties.in
+++ b/Code/Tools/Android/ProjectBuilder/local.properties.in
@@ -16,6 +16,5 @@
# For customization when using a Version Control System, please read the
# header note.
# ${GENERATION_TIMESTAMP}
-ndk.dir=${ANDROID_NDK_PATH}
sdk.dir=${ANDROID_SDK_PATH}
${CMAKE_DIR_LINE}
diff --git a/Code/Tools/Android/ProjectBuilder/root.build.gradle.in b/Code/Tools/Android/ProjectBuilder/root.build.gradle.in
index 782a1f26b5..dfce99c3c7 100644
--- a/Code/Tools/Android/ProjectBuilder/root.build.gradle.in
+++ b/Code/Tools/Android/ProjectBuilder/root.build.gradle.in
@@ -12,10 +12,9 @@ buildscript {
repositories {
google()
jcenter()
-
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.6.4'
+ classpath 'com.android.tools.build:gradle:${ANDROID_GRADLE_PLUGIN_VERSION}'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -26,14 +25,14 @@ allprojects {
repositories {
google()
jcenter()
-
}
}
subprojects {
ext {
+ minSdkVer = ${MIN_SDK_VER}
sdkVer = ${SDK_VER}
- ndkPlatformVer = ${NDK_PLATFORM_VER}
+ ndkPlatformVer = '${NDK_VERSION}'
buildToolsVer = '${SDK_BUILD_TOOL_VER}'
lyEngineRoot = '${LY_ENGINE_ROOT}'
}
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype
index 3696188514..79c4ca3cc3 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype
@@ -13,11 +13,6 @@
"displayName": "Metallic",
"description": "Properties for configuring whether the surface is metallic or not."
},
- {
- "id": "anisotropy",
- "displayName": "Anisotropic Material Response",
- "description": "How much is this material response anisotropic."
- },
{
"id": "roughness",
"displayName": "Roughness",
@@ -28,46 +23,11 @@
"displayName": "Specular Reflectance f0",
"description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces."
},
- {
- "id": "clearCoat",
- "displayName": "Clear Coat",
- "description": "Properties for configuring gloss clear coat"
- },
{
"id": "normal",
"displayName": "Normal",
"description": "Properties related to configuring surface normal."
},
- {
- "id": "opacity",
- "displayName": "Opacity",
- "description": "Properties for configuring the materials transparency."
- },
- {
- "id": "uv",
- "displayName": "UVs",
- "description": "Properties for configuring UV transforms."
- },
- {
- "id": "occlusion",
- "displayName": "Occlusion",
- "description": "Properties for baked textures that represent geometric occlusion of light."
- },
- {
- "id": "emissive",
- "displayName": "Emissive",
- "description": "Properties to add light emission, independent of other lights in the scene."
- },
- {
- "id": "parallax",
- "displayName": "Parallax Mapping",
- "description": "Properties for parallax effect produced by depthmap."
- },
- {
- "id": "subsurfaceScattering",
- "displayName": "Subsurface Scattering",
- "description": "Properties for configuring subsurface scattering effects."
- },
{
"id": "detailLayerGroup",
"displayName": "Detail Layer",
@@ -78,6 +38,46 @@
"displayName": "Detail Layer UV",
"description": "Properties for modifying detail layer UV."
},
+ {
+ "id": "anisotropy",
+ "displayName": "Anisotropic Material Response",
+ "description": "How much is this material response anisotropic."
+ },
+ {
+ "id": "occlusion",
+ "displayName": "Occlusion",
+ "description": "Properties for baked textures that represent geometric occlusion of light."
+ },
+ {
+ "id": "emissive",
+ "displayName": "Emissive",
+ "description": "Properties to add light emission, independent of other lights in the scene."
+ },
+ {
+ "id": "subsurfaceScattering",
+ "displayName": "Subsurface Scattering",
+ "description": "Properties for configuring subsurface scattering effects."
+ },
+ {
+ "id": "clearCoat",
+ "displayName": "Clear Coat",
+ "description": "Properties for configuring gloss clear coat"
+ },
+ {
+ "id": "parallax",
+ "displayName": "Displacement",
+ "description": "Properties for parallax effect produced by a height map."
+ },
+ {
+ "id": "opacity",
+ "displayName": "Opacity",
+ "description": "Properties for configuring the materials transparency."
+ },
+ {
+ "id": "uv",
+ "displayName": "UVs",
+ "description": "Properties for configuring UV transforms."
+ },
{
// Note: this property group is used in the DiffuseGlobalIllumination pass and not by the main forward shader
"id": "irradiance",
@@ -86,7 +86,7 @@
},
{
"id": "general",
- "displayName": "General",
+ "displayName": "General Settings",
"description": "General settings."
}
],
@@ -197,7 +197,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "Base color texture map",
"type": "Image",
"connection": {
@@ -208,14 +208,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Base color texture map UV set",
+ "description": "Base color map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -227,7 +227,7 @@
{
"id": "textureBlendMode",
"displayName": "Texture Blend Mode",
- "description": "Selects the equation to use when combining Color, Factor, and Texture Map.",
+ "description": "Selects the equation to use when combining Color, Factor, and Texture.",
"type": "Enum",
"enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ],
"defaultValue": "Multiply",
@@ -253,7 +253,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "",
"type": "Image",
"connection": {
@@ -264,14 +264,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Metallic texture map UV set",
+ "description": "Metallic map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -284,8 +284,8 @@
"roughness": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface roughness.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface roughness.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -295,14 +295,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -315,7 +315,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "lowerBound",
"displayName": "Lower Bound",
- "description": "The roughness value that corresponds to black in the texture map.",
+ "description": "The roughness value that corresponds to black in the texture.",
"type": "Float",
"defaultValue": 0.0,
"min": 0.0,
@@ -329,7 +329,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "upperBound",
"displayName": "Upper Bound",
- "description": "The roughness value that corresponds to white in the texture map.",
+ "description": "The roughness value that corresponds to white in the texture.",
"type": "Float",
"defaultValue": 1.0,
"min": 0.0,
@@ -409,8 +409,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface reflectance.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface reflectance.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -420,14 +420,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Specular reflection texture map UV set",
+ "description": "Specular reflection map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -472,7 +472,7 @@
{
"id": "influenceMap",
"displayName": " Influence Map",
- "description": "Strength factor texture map",
+ "description": "Strength factor texture",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -482,14 +482,14 @@
{
"id": "useInfluenceMap",
"displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "influenceMapUv",
"displayName": " UV",
- "description": "Strength factor texture map UV set",
+ "description": "Strength factor map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -514,7 +514,7 @@
{
"id": "roughnessMap",
"displayName": " Roughness Map",
- "description": "Roughness texture map",
+ "description": "Texture for defining surface roughness",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -524,14 +524,14 @@
{
"id": "useRoughnessMap",
"displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the roughness value.",
+ "description": "Whether to use the texture, or just default to the roughness value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "roughnessMapUv",
"displayName": " UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -573,7 +573,7 @@
{
"id": "normalMapUv",
"displayName": " UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -586,8 +586,8 @@
"normal": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface normal direction.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface normal direction.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -597,14 +597,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just rely on vertex normals.",
+ "description": "Whether to use the texture, or just rely on vertex normals.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -653,7 +653,7 @@
{
"id": "mode",
"displayName": "Opacity Mode",
- "description": "Opacity mode for this texture.",
+ "description": "Indicates the general approach how transparency is to be applied.",
"type": "Enum",
"enumValues": [ "Opaque", "Cutout", "Blended", "TintedTransparent" ],
"defaultValue": "Opaque",
@@ -665,7 +665,7 @@
{
"id": "alphaSource",
"displayName": "Alpha Source",
- "description": "Source texture of alpha value.",
+ "description": "Indicates whether to get the opacity texture from the Base Color map (Packed) or from a separate greyscale texture (Split).",
"type": "Enum",
"enumValues": [ "Packed", "Split", "None" ],
"defaultValue": "Packed",
@@ -676,8 +676,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface opacity.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface opacity.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -687,7 +687,7 @@
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Opacity texture map UV set",
+ "description": "Opacity map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -782,7 +782,7 @@
{
"id": "diffuseTextureMap",
"displayName": "Diffuse AO",
- "description": "Texture map for defining occlusion area for diffuse ambient lighting.",
+ "description": "Texture for defining occlusion area for diffuse ambient lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -792,14 +792,14 @@
{
"id": "diffuseUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Diffuse AO texture map.",
+ "description": "Whether to use the Diffuse AO map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "diffuseTextureMapUv",
"displayName": " UV",
- "description": "Diffuse AO texture map UV set.",
+ "description": "Diffuse AO map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -824,7 +824,7 @@
{
"id": "specularTextureMap",
"displayName": "Specular Cavity",
- "description": "Texture map for defining occlusion area for specular lighting.",
+ "description": "Texture for defining occlusion area for specular lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -834,14 +834,14 @@
{
"id": "specularUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Specular Cavity texture map.",
+ "description": "Whether to use the Specular Cavity map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "specularTextureMapUv",
"displayName": " UV",
- "description": "Specular Cavity texture map UV set.",
+ "description": "Specular Cavity map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -904,8 +904,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining emissive area.",
+ "displayName": "Texture",
+ "description": "Texture for defining emissive area.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -915,14 +915,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Emissive texture map UV set",
+ "description": "Emissive map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -935,8 +935,8 @@
"parallax": [
{
"id": "textureMap",
- "displayName": "Heightmap",
- "description": "Displacement heightmap to create parallax effect.",
+ "displayName": "Height Map",
+ "description": "Displacement height map to create parallax effect.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -946,14 +946,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the heightmap.",
+ "description": "Whether to use the height map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Heightmap UV set",
+ "description": "Height map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -964,8 +964,8 @@
},
{
"id": "factor",
- "displayName": "Heightmap Scale",
- "description": "The total height of the heightmap in local model units.",
+ "displayName": "Height Map Scale",
+ "description": "The total height of the height map in local model units.",
"type": "Float",
"defaultValue": 0.05,
"min": 0.0,
@@ -1026,7 +1026,7 @@
{
"id": "showClipping",
"displayName": "Show Clipping",
- "description": "Highlight areas where the heightmap is clipped by the mesh surface.",
+ "description": "Highlight areas where the height map is clipped by the mesh surface.",
"type": "Bool",
"defaultValue": false,
"connection": {
@@ -1063,7 +1063,7 @@
{
"id": "influenceMap",
"displayName": " Influence Map",
- "description": "Use texture map to control the strength of subsurface scattering",
+ "description": "Texture for controlling the strength of subsurface scattering",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1073,7 +1073,7 @@
{
"id": "useInfluenceMap",
"displayName": " Use Influence Map",
- "description": "Whether to use the texture map as influence mask.",
+ "description": "Whether to use the influence map.",
"type": "Bool",
"defaultValue": true
},
@@ -1142,7 +1142,7 @@
{
"id": "thicknessMap",
"displayName": " Thickness Map",
- "description": "Use a greyscale texture for per pixel thickness",
+ "description": "Texture for controlling per pixel thickness",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1171,7 +1171,7 @@
{
"id": "transmissionTint",
"displayName": " Transmission Tint",
- "description": "Color of the volume light travelling through",
+ "description": "Color of the volume light traveling through",
"type": "Color",
"defaultValue": [ 1.0, 0.8, 0.6 ]
},
@@ -1246,7 +1246,7 @@
{
"id": "enableDetailMaskTexture",
"displayName": " Use Texture",
- "description": "Enable detail mask texture",
+ "description": "Enable detail blend mask",
"type": "Bool",
"defaultValue": true
},
@@ -1265,7 +1265,7 @@
{
"id": "textureMapUv",
"displayName": "Detail Map UVs",
- "description": "Which UV set to use for detail map texture sampling",
+ "description": "Which UV set to use for detail map sampling",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1283,8 +1283,8 @@
},
{
"id": "baseColorDetailMap",
- "displayName": " Texture Map",
- "description": "Detailed Base Color Texture map",
+ "displayName": " Texture",
+ "description": "Detailed Base Color Texture",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1307,7 +1307,7 @@
{
"id": "enableNormals",
"displayName": "Enable Normal",
- "description": "Enable detail normal texture to be used for fine detail normal such as scratches and small dents",
+ "description": "Enable detail normal map to be used for fine detail normal such as scratches and small dents",
"type": "Bool",
"defaultValue": false
},
@@ -1326,8 +1326,8 @@
},
{
"id": "normalDetailMap",
- "displayName": " Texture Map",
- "description": "Detailed Normal Texture map",
+ "displayName": " Texture",
+ "description": "Detailed Normal map",
"type": "Image",
"connection": {
"type": "ShaderInput",
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype
index f8c49d579c..9ead0376bb 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype
@@ -23,6 +23,16 @@
"displayName": "Normal",
"description": "Properties related to configuring surface normal."
},
+ {
+ "id": "detailLayerGroup",
+ "displayName": "Detail Layer",
+ "description": "Properties for Fine Details Layer."
+ },
+ {
+ "id": "detailUV",
+ "displayName": "Detail Layer UV",
+ "description": "Properties for modifying detail layer UV."
+ },
{
"id": "occlusion",
"displayName": "Occlusion",
@@ -38,19 +48,9 @@
"displayName": "Wrinkle Layers",
"description": "Properties for wrinkle maps to support morph animation, using vertex color blend weights."
},
- {
- "id": "detailLayerGroup",
- "displayName": "Detail Layer",
- "description": "Properties for Fine Details Layer."
- },
- {
- "id": "detailUV",
- "displayName": "Detail Layer UV",
- "description": "Properties for modifying detail layer UV."
- },
{
"id": "general",
- "displayName": "General",
+ "displayName": "General Settings",
"description": "General settings."
}
],
@@ -150,7 +150,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "Base color texture map",
"type": "Image",
"connection": {
@@ -161,14 +161,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Base color texture map UV set",
+ "description": "Base color map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Unwrapped",
@@ -180,7 +180,7 @@
{
"id": "textureBlendMode",
"displayName": "Texture Blend Mode",
- "description": "Selects the equation to use when combining Color, Factor, and Texture Map.",
+ "description": "Selects the equation to use when combining Color, Factor, and Texture.",
"type": "Enum",
"enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ],
"defaultValue": "Multiply",
@@ -193,8 +193,8 @@
"roughness": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface roughness.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface roughness.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -204,14 +204,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Unwrapped",
@@ -224,7 +224,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "lowerBound",
"displayName": "Lower Bound",
- "description": "The roughness value that corresponds to black in the texture map.",
+ "description": "The roughness value that corresponds to black in the texture.",
"type": "Float",
"defaultValue": 0.0,
"min": 0.0,
@@ -238,7 +238,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "upperBound",
"displayName": "Upper Bound",
- "description": "The roughness value that corresponds to white in the texture map.",
+ "description": "The roughness value that corresponds to white in the texture.",
"type": "Float",
"defaultValue": 1.0,
"min": 0.0,
@@ -279,8 +279,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface reflectance.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface reflectance.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -290,14 +290,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Specular reflection texture map UV set",
+ "description": "Specular reflection map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Unwrapped",
@@ -321,8 +321,8 @@
"normal": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface normal direction.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface normal direction.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -332,14 +332,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just rely on vertex normals.",
+ "description": "Whether to use the texture, or just rely on vertex normals.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Unwrapped",
@@ -388,7 +388,7 @@
{
"id": "diffuseTextureMap",
"displayName": "Diffuse AO",
- "description": "Texture map for defining occlusion area for diffuse ambient lighting.",
+ "description": "Texture for defining occlusion area for diffuse ambient lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -398,14 +398,14 @@
{
"id": "diffuseUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Diffuse AO texture map.",
+ "description": "Whether to use the Diffuse AO map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "diffuseTextureMapUv",
"displayName": " UV",
- "description": "Diffuse AO texture map UV set.",
+ "description": "Diffuse AO map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -430,7 +430,7 @@
{
"id": "specularTextureMap",
"displayName": "Specular Cavity",
- "description": "Texture map for defining occlusion area for specular lighting.",
+ "description": "Texture for defining occlusion area for specular lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -440,14 +440,14 @@
{
"id": "specularUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Specular Cavity texture map.",
+ "description": "Whether to use the Specular Cavity map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "specularTextureMapUv",
"displayName": " UV",
- "description": "Specular Cavity texture map UV set.",
+ "description": "Specular Cavity map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -498,7 +498,7 @@
{
"id": "influenceMap",
"displayName": " Influence Map",
- "description": "Use texture map to control the strength of subsurface scattering",
+ "description": "Texture for controlling the strength of subsurface scattering",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -508,7 +508,7 @@
{
"id": "useInfluenceMap",
"displayName": " Use Influence Map",
- "description": "Whether to use the texture map as influence mask.",
+ "description": "Whether to use the influence map.",
"type": "Bool",
"defaultValue": true
},
@@ -577,7 +577,7 @@
{
"id": "thicknessMap",
"displayName": " Thickness Map",
- "description": "Use a greyscale texture for per pixel thickness",
+ "description": "Texture for controlling per pixel thickness",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -606,7 +606,7 @@
{
"id": "transmissionTint",
"displayName": " Transmission Tint",
- "description": "Color of the volume light travelling through",
+ "description": "Color of the volume light traveling through",
"type": "Color",
"defaultValue": [ 1.0, 0.8, 0.6 ]
},
@@ -792,7 +792,7 @@
{
"id": "enableDetailMaskTexture",
"displayName": " Use Texture",
- "description": "Enable detail mask texture",
+ "description": "Enable detail blend mask",
"type": "Bool",
"defaultValue": true
},
@@ -811,7 +811,7 @@
{
"id": "textureMapUv",
"displayName": "Detail Map UVs",
- "description": "Which UV set to use for detail map texture sampling",
+ "description": "Which UV set to use for detail map sampling",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Unwrapped",
@@ -829,8 +829,8 @@
},
{
"id": "baseColorDetailMap",
- "displayName": " Texture Map",
- "description": "Detailed Base Color Texture map",
+ "displayName": " Texture",
+ "description": "Detailed Base Color Texture",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -853,7 +853,7 @@
{
"id": "enableNormals",
"displayName": "Enable Normal",
- "description": "Enable detail normal texture to be used for fine detail normal such as scratches and small dents",
+ "description": "Enable detail normal map to be used for fine detail normal such as scratches and small dents",
"type": "Bool",
"defaultValue": false
},
@@ -872,8 +872,8 @@
},
{
"id": "normalDetailMap",
- "displayName": " Texture Map",
- "description": "Detailed Normal Texture map",
+ "displayName": " Texture",
+ "description": "Detailed Normal map",
"type": "Image",
"connection": {
"type": "ShaderInput",
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype
index ca6cb77b0a..c07eac3d47 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype
@@ -26,7 +26,7 @@
},
{
"id": "general",
- "displayName": "General",
+ "displayName": "General Settings",
"description": "General settings."
},
//##############################################################################################
@@ -57,11 +57,6 @@
"displayName": "Layer 1: Normal",
"description": "Properties related to configuring surface normal."
},
- {
- "id": "layer1_clearCoat",
- "displayName": "Layer 1: Clear Coat",
- "description": "Properties for configuring gloss clear coat"
- },
{
"id": "layer1_occlusion",
"displayName": "Layer 1: Occlusion",
@@ -72,6 +67,11 @@
"displayName": "Layer 1: Emissive",
"description": "Properties to add light emission, independent of other lights in the scene."
},
+ {
+ "id": "layer1_clearCoat",
+ "displayName": "Layer 1: Clear Coat",
+ "description": "Properties for configuring gloss clear coat"
+ },
{
"id": "layer1_parallax",
"displayName": "Layer 1: Displacement",
@@ -110,11 +110,6 @@
"displayName": "Layer 2: Normal",
"description": "Properties related to configuring surface normal."
},
- {
- "id": "layer2_clearCoat",
- "displayName": "Layer 2: Clear Coat",
- "description": "Properties for configuring gloss clear coat"
- },
{
"id": "layer2_occlusion",
"displayName": "Layer 2: Occlusion",
@@ -125,6 +120,11 @@
"displayName": "Layer 2: Emissive",
"description": "Properties to add light emission, independent of other lights in the scene."
},
+ {
+ "id": "layer2_clearCoat",
+ "displayName": "Layer 2: Clear Coat",
+ "description": "Properties for configuring gloss clear coat"
+ },
{
"id": "layer2_parallax",
"displayName": "Layer 2: Displacement",
@@ -163,11 +163,6 @@
"displayName": "Layer 3: Normal",
"description": "Properties related to configuring surface normal."
},
- {
- "id": "layer3_clearCoat",
- "displayName": "Layer 3: Clear Coat",
- "description": "Properties for configuring gloss clear coat"
- },
{
"id": "layer3_occlusion",
"displayName": "Layer 3: Occlusion",
@@ -178,6 +173,11 @@
"displayName": "Layer 3: Emissive",
"description": "Properties to add light emission, independent of other lights in the scene."
},
+ {
+ "id": "layer3_clearCoat",
+ "displayName": "Layer 3: Clear Coat",
+ "description": "Properties for configuring gloss clear coat"
+ },
{
"id": "layer3_parallax",
"displayName": "Layer 3: Displacement",
@@ -428,7 +428,7 @@
{
"id": "showClipping",
"displayName": "Show Clipping",
- "description": "Highlight areas where the heightmap is clipped by the mesh surface.",
+ "description": "Highlight areas where the height map is clipped by the mesh surface.",
"type": "Bool",
"defaultValue": false,
"connection": {
@@ -550,7 +550,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "Base color texture map",
"type": "Image",
"connection": {
@@ -561,14 +561,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Base color texture map UV set",
+ "description": "Base color map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -580,7 +580,7 @@
{
"id": "textureBlendMode",
"displayName": "Texture Blend Mode",
- "description": "Selects the equation to use when combining Color, Factor, and Texture Map.",
+ "description": "Selects the equation to use when combining Color, Factor, and Texture.",
"type": "Enum",
"enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ],
"defaultValue": "Multiply",
@@ -606,7 +606,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "",
"type": "Image",
"connection": {
@@ -617,14 +617,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Metallic texture map UV set",
+ "description": "Metallic map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -637,8 +637,8 @@
"layer1_roughness": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface roughness.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface roughness.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -648,14 +648,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -668,7 +668,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "lowerBound",
"displayName": "Lower Bound",
- "description": "The roughness value that corresponds to black in the texture map.",
+ "description": "The roughness value that corresponds to black in the texture.",
"type": "Float",
"defaultValue": 0.0,
"min": 0.0,
@@ -682,7 +682,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "upperBound",
"displayName": "Upper Bound",
- "description": "The roughness value that corresponds to white in the texture map.",
+ "description": "The roughness value that corresponds to white in the texture.",
"type": "Float",
"defaultValue": 1.0,
"min": 0.0,
@@ -723,8 +723,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface reflectance.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface reflectance.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -734,14 +734,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Specular reflection texture map UV set",
+ "description": "Specular reflection map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -754,8 +754,8 @@
"layer1_normal": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface normal direction.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface normal direction.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -765,14 +765,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just rely on vertex normals.",
+ "description": "Whether to use the texture, or just rely on vertex normals.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -841,7 +841,7 @@
{
"id": "influenceMap",
"displayName": " Influence Map",
- "description": "Strength factor texture map",
+ "description": "Strength factor texture",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -851,14 +851,14 @@
{
"id": "useInfluenceMap",
"displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "influenceMapUv",
"displayName": " UV",
- "description": "Strength factor texture map UV set",
+ "description": "Strength factor map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -883,7 +883,7 @@
{
"id": "roughnessMap",
"displayName": " Roughness Map",
- "description": "Roughness texture map",
+ "description": "Texture for defining surface roughness",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -893,14 +893,14 @@
{
"id": "useRoughnessMap",
"displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the roughness value.",
+ "description": "Whether to use the texture, or just default to the roughness value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "roughnessMapUv",
"displayName": " UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -942,7 +942,7 @@
{
"id": "normalMapUv",
"displayName": " UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -956,7 +956,7 @@
{
"id": "diffuseTextureMap",
"displayName": "Diffuse AO",
- "description": "Texture map for defining occlusion area for diffuse ambient lighting.",
+ "description": "Texture for defining occlusion area for diffuse ambient lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -966,14 +966,14 @@
{
"id": "diffuseUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Diffuse AO texture map.",
+ "description": "Whether to use the Diffuse AO map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "diffuseTextureMapUv",
"displayName": " UV",
- "description": "Diffuse AO texture map UV set.",
+ "description": "Diffuse AO map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -998,7 +998,7 @@
{
"id": "specularTextureMap",
"displayName": "Specular Cavity",
- "description": "Texture map for defining occlusion area for specular lighting.",
+ "description": "Texture for defining occlusion area for specular lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1008,14 +1008,14 @@
{
"id": "specularUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Specular Cavity texture map.",
+ "description": "Whether to use the Specular Cavity map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "specularTextureMapUv",
"displayName": " UV",
- "description": "Specular Cavity texture map UV set.",
+ "description": "Specular Cavity map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1078,8 +1078,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining emissive area.",
+ "displayName": "Texture",
+ "description": "Texture for defining emissive area.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1089,14 +1089,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Emissive texture map UV set",
+ "description": "Emissive map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1109,8 +1109,8 @@
"layer1_parallax": [
{
"id": "textureMap",
- "displayName": "Heightmap",
- "description": "Displacement heightmap, which can be used for layer blending and/or a parallax effect.",
+ "displayName": "Height Map",
+ "description": "Displacement height map, which can be used for layer blending and/or a parallax effect.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1120,14 +1120,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the heightmap.",
+ "description": "Whether to use the height map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "factor",
"displayName": "Scale",
- "description": "The total height of the heightmap in local model units.",
+ "description": "The total height of the height map in local model units.",
"type": "Float",
"defaultValue": 0.05,
"min": 0.0,
@@ -1245,7 +1245,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "Base color texture map",
"type": "Image",
"connection": {
@@ -1256,14 +1256,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Base color texture map UV set",
+ "description": "Base color map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1275,7 +1275,7 @@
{
"id": "textureBlendMode",
"displayName": "Texture Blend Mode",
- "description": "Selects the equation to use when combining Color, Factor, and Texture Map.",
+ "description": "Selects the equation to use when combining Color, Factor, and Texture.",
"type": "Enum",
"enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ],
"defaultValue": "Multiply",
@@ -1301,7 +1301,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "",
"type": "Image",
"connection": {
@@ -1312,14 +1312,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Metallic texture map UV set",
+ "description": "Metallic map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1332,8 +1332,8 @@
"layer2_roughness": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface roughness.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface roughness.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1343,14 +1343,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1363,7 +1363,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "lowerBound",
"displayName": "Lower Bound",
- "description": "The roughness value that corresponds to black in the texture map.",
+ "description": "The roughness value that corresponds to black in the texture.",
"type": "Float",
"defaultValue": 0.0,
"min": 0.0,
@@ -1377,7 +1377,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "upperBound",
"displayName": "Upper Bound",
- "description": "The roughness value that corresponds to white in the texture map.",
+ "description": "The roughness value that corresponds to white in the texture.",
"type": "Float",
"defaultValue": 1.0,
"min": 0.0,
@@ -1418,8 +1418,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface reflectance.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface reflectance.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1429,14 +1429,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Specular reflection texture map UV set",
+ "description": "Specular reflection map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1449,8 +1449,8 @@
"layer2_normal": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface normal direction.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface normal direction.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1460,14 +1460,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just rely on vertex normals.",
+ "description": "Whether to use the texture, or just rely on vertex normals.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1536,7 +1536,7 @@
{
"id": "influenceMap",
"displayName": " Influence Map",
- "description": "Strength factor texture map",
+ "description": "Strength factor texture",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1546,14 +1546,14 @@
{
"id": "useInfluenceMap",
"displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "influenceMapUv",
"displayName": " UV",
- "description": "Strength factor texture map UV set",
+ "description": "Strength factor map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1578,7 +1578,7 @@
{
"id": "roughnessMap",
"displayName": " Roughness Map",
- "description": "Roughness texture map",
+ "description": "Texture for defining surface roughness",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1588,14 +1588,14 @@
{
"id": "useRoughnessMap",
"displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the roughness value.",
+ "description": "Whether to use the texture, or just default to the roughness value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "roughnessMapUv",
"displayName": " UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1637,7 +1637,7 @@
{
"id": "normalMapUv",
"displayName": " UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1651,7 +1651,7 @@
{
"id": "diffuseTextureMap",
"displayName": "Diffuse AO",
- "description": "Texture map for defining occlusion area for diffuse ambient lighting.",
+ "description": "Texture for defining occlusion area for diffuse ambient lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1661,14 +1661,14 @@
{
"id": "diffuseUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Diffuse AO texture map.",
+ "description": "Whether to use the Diffuse AO map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "diffuseTextureMapUv",
"displayName": " UV",
- "description": "Diffuse AO texture map UV set.",
+ "description": "Diffuse AO map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1693,7 +1693,7 @@
{
"id": "specularTextureMap",
"displayName": "Specular Cavity",
- "description": "Texture map for defining occlusion area for specular lighting.",
+ "description": "Texture for defining occlusion area for specular lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1703,14 +1703,14 @@
{
"id": "specularUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Specular Cavity texture map.",
+ "description": "Whether to use the Specular Cavity map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "specularTextureMapUv",
"displayName": " UV",
- "description": "Specular Cavity texture map UV set.",
+ "description": "Specular Cavity map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1773,8 +1773,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining emissive area.",
+ "displayName": "Texture",
+ "description": "Texture for defining emissive area.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1784,14 +1784,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Emissive texture map UV set",
+ "description": "Emissive map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1804,8 +1804,8 @@
"layer2_parallax": [
{
"id": "textureMap",
- "displayName": "Heightmap",
- "description": "Displacement heightmap, which can be used for layer blending and/or a parallax effect.",
+ "displayName": "Height Map",
+ "description": "Displacement height map, which can be used for layer blending and/or a parallax effect.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1815,14 +1815,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the heightmap.",
+ "description": "Whether to use the height map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "factor",
"displayName": "Scale",
- "description": "The total height of the heightmap in local model units.",
+ "description": "The total height of the height map in local model units.",
"type": "Float",
"defaultValue": 0.05,
"min": 0.0,
@@ -1940,7 +1940,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "Base color texture map",
"type": "Image",
"connection": {
@@ -1951,14 +1951,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Base color texture map UV set",
+ "description": "Base color map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -1970,7 +1970,7 @@
{
"id": "textureBlendMode",
"displayName": "Texture Blend Mode",
- "description": "Selects the equation to use when combining Color, Factor, and Texture Map.",
+ "description": "Selects the equation to use when combining Color, Factor, and Texture.",
"type": "Enum",
"enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ],
"defaultValue": "Multiply",
@@ -1996,7 +1996,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "",
"type": "Image",
"connection": {
@@ -2007,14 +2007,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Metallic texture map UV set",
+ "description": "Metallic map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -2027,8 +2027,8 @@
"layer3_roughness": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface roughness.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface roughness.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -2038,14 +2038,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -2058,7 +2058,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "lowerBound",
"displayName": "Lower Bound",
- "description": "The roughness value that corresponds to black in the texture map.",
+ "description": "The roughness value that corresponds to black in the texture.",
"type": "Float",
"defaultValue": 0.0,
"min": 0.0,
@@ -2072,7 +2072,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "upperBound",
"displayName": "Upper Bound",
- "description": "The roughness value that corresponds to white in the texture map.",
+ "description": "The roughness value that corresponds to white in the texture.",
"type": "Float",
"defaultValue": 1.0,
"min": 0.0,
@@ -2113,8 +2113,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface reflectance.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface reflectance.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -2124,14 +2124,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Specular reflection texture map UV set",
+ "description": "Specular reflection map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -2144,8 +2144,8 @@
"layer3_normal": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface normal direction.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface normal direction.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -2155,14 +2155,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just rely on vertex normals.",
+ "description": "Whether to use the texture, or just rely on vertex normals.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -2231,7 +2231,7 @@
{
"id": "influenceMap",
"displayName": " Influence Map",
- "description": "Strength factor texture map",
+ "description": "Strength factor texture",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -2241,14 +2241,14 @@
{
"id": "useInfluenceMap",
"displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "influenceMapUv",
"displayName": " UV",
- "description": "Strength factor texture map UV set",
+ "description": "Strength factor map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -2273,7 +2273,7 @@
{
"id": "roughnessMap",
"displayName": " Roughness Map",
- "description": "Roughness texture map",
+ "description": "Texture for defining surface roughness",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -2283,14 +2283,14 @@
{
"id": "useRoughnessMap",
"displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the roughness value.",
+ "description": "Whether to use the texture, or just default to the roughness value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "roughnessMapUv",
"displayName": " UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -2332,7 +2332,7 @@
{
"id": "normalMapUv",
"displayName": " UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -2346,7 +2346,7 @@
{
"id": "diffuseTextureMap",
"displayName": "Diffuse AO",
- "description": "Texture map for defining occlusion area for diffuse ambient lighting.",
+ "description": "Texture for defining occlusion area for diffuse ambient lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -2356,14 +2356,14 @@
{
"id": "diffuseUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Diffuse AO texture map.",
+ "description": "Whether to use the Diffuse AO map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "diffuseTextureMapUv",
"displayName": " UV",
- "description": "Diffuse AO texture map UV set.",
+ "description": "Diffuse AO map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -2388,7 +2388,7 @@
{
"id": "specularTextureMap",
"displayName": "Specular Cavity",
- "description": "Texture map for defining occlusion area for specular lighting.",
+ "description": "Texture for defining occlusion area for specular lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -2398,14 +2398,14 @@
{
"id": "specularUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Specular Cavity texture map.",
+ "description": "Whether to use the Specular Cavity map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "specularTextureMapUv",
"displayName": " UV",
- "description": "Specular Cavity texture map UV set.",
+ "description": "Specular Cavity map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -2468,8 +2468,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining emissive area.",
+ "displayName": "Texture",
+ "description": "Texture for defining emissive area.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -2479,14 +2479,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Emissive texture map UV set",
+ "description": "Emissive map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -2499,8 +2499,8 @@
"layer3_parallax": [
{
"id": "textureMap",
- "displayName": "Heightmap",
- "description": "Displacement heightmap, which can be used for layer blending and/or a parallax effect.",
+ "displayName": "Height Map",
+ "description": "Displacement height map, which can be used for layer blending and/or a parallax effect.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -2510,14 +2510,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the heightmap.",
+ "description": "Whether to use the height map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "factor",
"displayName": "Scale",
- "description": "The total height of the heightmap in local model units.",
+ "description": "The total height of the height map in local model units.",
"type": "Float",
"defaultValue": 0.05,
"min": 0.0,
diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype
index 183cddd4cb..658aaeeee9 100644
--- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype
+++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype
@@ -23,26 +23,11 @@
"displayName": "Specular Reflectance f0",
"description": "The constant f0 represents the specular reflectance at normal incidence (Fresnel 0 Angle). Used to adjust reflectance of non-metal surfaces."
},
- {
- "id": "clearCoat",
- "displayName": "Clear Coat",
- "description": "Properties for configuring gloss clear coat"
- },
{
"id": "normal",
"displayName": "Normal",
"description": "Properties related to configuring surface normal."
},
- {
- "id": "opacity",
- "displayName": "Opacity",
- "description": "Properties for configuring the materials transparency."
- },
- {
- "id": "uv",
- "displayName": "UVs",
- "description": "Properties for configuring UV transforms."
- },
{
"id": "occlusion",
"displayName": "Occlusion",
@@ -53,16 +38,31 @@
"displayName": "Emissive",
"description": "Properties to add light emission, independent of other lights in the scene."
},
- {
- "id": "parallax",
- "displayName": "Parallax Mapping",
- "description": "Properties for parallax effect produced by depthmap."
- },
{
"id": "subsurfaceScattering",
"displayName": "Subsurface Scattering",
"description": "Properties for configuring subsurface scattering effects."
},
+ {
+ "id": "clearCoat",
+ "displayName": "Clear Coat",
+ "description": "Properties for configuring gloss clear coat"
+ },
+ {
+ "id": "parallax",
+ "displayName": "Displacement",
+ "description": "Properties for parallax effect produced by a height map."
+ },
+ {
+ "id": "opacity",
+ "displayName": "Opacity",
+ "description": "Properties for configuring the materials transparency."
+ },
+ {
+ "id": "uv",
+ "displayName": "UVs",
+ "description": "Properties for configuring UV transforms."
+ },
{
// Note: this property group is used in the DiffuseGlobalIllumination pass, it is not read by the StandardPBR shader
"id": "irradiance",
@@ -71,7 +71,7 @@
},
{
"id": "general",
- "displayName": "General",
+ "displayName": "General Settings",
"description": "General settings."
}
],
@@ -182,7 +182,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "Base color texture map",
"type": "Image",
"connection": {
@@ -193,14 +193,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Base color texture map UV set",
+ "description": "Base color map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -212,7 +212,7 @@
{
"id": "textureBlendMode",
"displayName": "Texture Blend Mode",
- "description": "Selects the equation to use when combining Color, Factor, and Texture Map.",
+ "description": "Selects the equation to use when combining Color, Factor, and Texture.",
"type": "Enum",
"enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ],
"defaultValue": "Multiply",
@@ -238,7 +238,7 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
+ "displayName": "Texture",
"description": "",
"type": "Image",
"connection": {
@@ -249,14 +249,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Metallic texture map UV set",
+ "description": "Metallic map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -269,8 +269,8 @@
"roughness": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface roughness.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface roughness.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -280,14 +280,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -300,7 +300,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "lowerBound",
"displayName": "Lower Bound",
- "description": "The roughness value that corresponds to black in the texture map.",
+ "description": "The roughness value that corresponds to black in the texture.",
"type": "Float",
"defaultValue": 0.0,
"min": 0.0,
@@ -314,7 +314,7 @@
// Note that "factor" is mutually exclusive with "lowerBound"/"upperBound". These are swapped by a lua functor.
"id": "upperBound",
"displayName": "Upper Bound",
- "description": "The roughness value that corresponds to white in the texture map.",
+ "description": "The roughness value that corresponds to white in the texture.",
"type": "Float",
"defaultValue": 1.0,
"min": 0.0,
@@ -355,8 +355,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface reflectance.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface reflectance.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -366,14 +366,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Specular reflection texture map UV set",
+ "description": "Specular reflection map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -418,7 +418,7 @@
{
"id": "influenceMap",
"displayName": " Influence Map",
- "description": "Strength factor texture map",
+ "description": "Strength factor texture",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -428,14 +428,14 @@
{
"id": "useInfluenceMap",
"displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the Factor value.",
+ "description": "Whether to use the texture, or just default to the Factor value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "influenceMapUv",
"displayName": " UV",
- "description": "Strength factor texture map UV set",
+ "description": "Strength factor map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -460,7 +460,7 @@
{
"id": "roughnessMap",
"displayName": " Roughness Map",
- "description": "Roughness texture map",
+ "description": "Texture for defining surface roughness",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -470,14 +470,14 @@
{
"id": "useRoughnessMap",
"displayName": " Use Texture",
- "description": "Whether to use the texture map, or just default to the roughness value.",
+ "description": "Whether to use the texture, or just default to the roughness value.",
"type": "Bool",
"defaultValue": true
},
{
"id": "roughnessMapUv",
"displayName": " UV",
- "description": "Roughness texture map UV set",
+ "description": "Roughness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -519,7 +519,7 @@
{
"id": "normalMapUv",
"displayName": " UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -532,8 +532,8 @@
"normal": [
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface normal direction.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface normal direction.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -543,14 +543,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map, or just rely on vertex normals.",
+ "description": "Whether to use the texture, or just rely on vertex normals.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Normal texture map UV set",
+ "description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -599,7 +599,7 @@
{
"id": "mode",
"displayName": "Opacity Mode",
- "description": "Opacity mode for this texture.",
+ "description": "Indicates the general approach how transparency is to be applied.",
"type": "Enum",
"enumValues": [ "Opaque", "Cutout", "Blended", "TintedTransparent" ],
"defaultValue": "Opaque",
@@ -611,7 +611,7 @@
{
"id": "alphaSource",
"displayName": "Alpha Source",
- "description": "Source texture of alpha value.",
+ "description": "Indicates whether to get the opacity texture from the Base Color map (Packed) or from a separate greyscale texture (Split).",
"type": "Enum",
"enumValues": [ "Packed", "Split", "None" ],
"defaultValue": "Packed",
@@ -622,8 +622,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining surface opacity.",
+ "displayName": "Texture",
+ "description": "Texture for defining surface opacity.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -633,7 +633,7 @@
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Opacity texture map UV set",
+ "description": "Opacity map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -728,7 +728,7 @@
{
"id": "diffuseTextureMap",
"displayName": "Diffuse AO",
- "description": "Texture map for defining occlusion area for diffuse ambient lighting.",
+ "description": "Texture for defining occlusion area for diffuse ambient lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -738,14 +738,14 @@
{
"id": "diffuseUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Diffuse AO texture map.",
+ "description": "Whether to use the Diffuse AO map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "diffuseTextureMapUv",
"displayName": " UV",
- "description": "Diffuse AO texture map UV set.",
+ "description": "Diffuse AO map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -770,7 +770,7 @@
{
"id": "specularTextureMap",
"displayName": "Specular Cavity",
- "description": "Texture map for defining occlusion area for specular lighting.",
+ "description": "Texture for defining occlusion area for specular lighting.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -780,14 +780,14 @@
{
"id": "specularUseTexture",
"displayName": " Use Texture",
- "description": "Whether to use the Specular Cavity texture map.",
+ "description": "Whether to use the Specular Cavity map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "specularTextureMapUv",
"displayName": " UV",
- "description": "Specular Cavity texture map UV set.",
+ "description": "Specular Cavity map UV set.",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -850,8 +850,8 @@
},
{
"id": "textureMap",
- "displayName": "Texture Map",
- "description": "Texture map for defining emissive area.",
+ "displayName": "Texture",
+ "description": "Texture for defining emissive area.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -861,14 +861,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the texture map.",
+ "description": "Whether to use the texture.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Emissive texture map UV set",
+ "description": "Emissive map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -881,8 +881,8 @@
"parallax": [
{
"id": "textureMap",
- "displayName": "Heightmap",
- "description": "Displacement heightmap to create parallax effect.",
+ "displayName": "Height Map",
+ "description": "Displacement height map to create parallax effect.",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -892,14 +892,14 @@
{
"id": "useTexture",
"displayName": "Use Texture",
- "description": "Whether to use the heightmap.",
+ "description": "Whether to use the height map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
- "description": "Heightmap UV set",
+ "description": "Height map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -910,8 +910,8 @@
},
{
"id": "factor",
- "displayName": "Heightmap Scale",
- "description": "The total height of the heightmap in local model units.",
+ "displayName": "Height Map Scale",
+ "description": "The total height of the height map in local model units.",
"type": "Float",
"defaultValue": 0.05,
"min": 0.0,
@@ -972,7 +972,7 @@
{
"id": "showClipping",
"displayName": "Show Clipping",
- "description": "Highlight areas where the heightmap is clipped by the mesh surface.",
+ "description": "Highlight areas where the height map is clipped by the mesh surface.",
"type": "Bool",
"defaultValue": false,
"connection": {
@@ -1009,7 +1009,7 @@
{
"id": "influenceMap",
"displayName": " Influence Map",
- "description": "Use texture map to control the strength of subsurface scattering",
+ "description": "Texture for controlling the strength of subsurface scattering",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1019,7 +1019,7 @@
{
"id": "useInfluenceMap",
"displayName": " Use Influence Map",
- "description": "Whether to use the texture map as influence mask.",
+ "description": "Whether to use the influence map.",
"type": "Bool",
"defaultValue": true
},
@@ -1088,7 +1088,7 @@
{
"id": "thicknessMap",
"displayName": " Thickness Map",
- "description": "Use a greyscale texture for per pixel thickness",
+ "description": "Texture for controlling per pixel thickness",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1117,7 +1117,7 @@
{
"id": "transmissionTint",
"displayName": " Transmission Tint",
- "description": "Color of the volume light travelling through",
+ "description": "Color of the volume light traveling through",
"type": "Color",
"defaultValue": [ 1.0, 0.8, 0.6 ]
},
diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingMaterialSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingMaterialSrg.azsli
new file mode 100644
index 0000000000..40faba24f9
--- /dev/null
+++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingMaterialSrg.azsli
@@ -0,0 +1,48 @@
+/*
+* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+* its licensors.
+*
+* For complete copyright and license terms please see the LICENSE at the root of this
+* distribution (the "License"). All use of this software is governed by the License,
+* or, if provided, by the license below or the license accompanying this file. Do not
+* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*
+*/
+
+#include
+
+ShaderResourceGroup RayTracingMaterialSrg : SRG_RayTracingMaterial
+{
+ Sampler LinearSampler
+ {
+ AddressU = Wrap;
+ AddressV = Wrap;
+ MinFilter = Linear;
+ MagFilter = Linear;
+ MipFilter = Linear;
+ MaxAnisotropy = 16;
+ };
+
+ // material info structured buffer
+ struct MaterialInfo
+ {
+ float4 m_baseColor;
+ float m_metallicFactor;
+ float m_roughnessFactor;
+ uint m_textureFlags;
+ uint m_textureStartIndex;
+ };
+
+ // hit shaders can retrieve the MaterialInfo for a mesh hit using: RayTracingMaterialSrg::m_materialInfo[InstanceIndex()]
+ StructuredBuffer m_materialInfo;
+
+ // texture flag bits indicating if optional textures are present
+ #define TEXTURE_FLAG_BASECOLOR 1
+ #define TEXTURE_FLAG_NORMAL 2
+ #define TEXTURE_FLAG_METALLIC 4
+ #define TEXTURE_FLAG_ROUGHNESS 8
+
+ // unbounded array of Material textures
+ Texture2D m_materialTextures[];
+}
\ No newline at end of file
diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingMaterialUtils.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingMaterialUtils.azsli
new file mode 100644
index 0000000000..d6dd77f4fa
--- /dev/null
+++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingMaterialUtils.azsli
@@ -0,0 +1,69 @@
+/*
+* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+* its licensors.
+*
+* For complete copyright and license terms please see the LICENSE at the root of this
+* distribution (the "License"). All use of this software is governed by the License,
+* or, if provided, by the license below or the license accompanying this file. Do not
+* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*
+*/
+
+struct TextureData
+{
+ float4 m_baseColor;
+ float3 m_normal;
+ float m_metallic;
+ float m_roughness;
+};
+
+TextureData GetHitTextureData(RayTracingMaterialSrg::MaterialInfo materialInfo, float2 uv)
+{
+ TextureData textureData = (TextureData)0;
+
+ uint textureIndex = materialInfo.m_textureStartIndex;
+
+ // base color
+ if (materialInfo.m_textureFlags & TEXTURE_FLAG_BASECOLOR)
+ {
+ textureData.m_baseColor = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+ }
+ else
+ {
+ textureData.m_baseColor = materialInfo.m_baseColor;
+ }
+
+ // normal
+ if (materialInfo.m_textureFlags & TEXTURE_FLAG_NORMAL)
+ {
+ textureData.m_normal = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+ }
+ else
+ {
+ textureData.m_normal = float3(0.0f, 0.0f, 1.0f);
+ }
+
+ // metallic
+ if (materialInfo.m_textureFlags & TEXTURE_FLAG_METALLIC)
+ {
+ textureData.m_metallic = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+ }
+ else
+ {
+ textureData.m_metallic = materialInfo.m_metallicFactor;
+ }
+
+ // roughness
+ if (materialInfo.m_textureFlags & TEXTURE_FLAG_ROUGHNESS)
+ {
+ textureData.m_roughness = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+ }
+ else
+ {
+ textureData.m_roughness = materialInfo.m_roughnessFactor;
+ }
+
+ return textureData;
+}
+
\ No newline at end of file
diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli
index fdf7ba92de..b8c97ef421 100644
--- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli
+++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli
@@ -136,18 +136,35 @@ ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
uint m_indexOffset;
uint m_positionOffset;
uint m_normalOffset;
+ uint m_tangentOffset;
+ uint m_bitangentOffset;
+ uint m_uvOffset;
+ float m_padding0[2];
+
float4 m_irradianceColor;
float3x3 m_worldInvTranspose;
+ float m_padding1;
+
+ uint m_bufferFlags;
+ uint m_bufferStartIndex;
};
-
+
+ // hit shaders can retrieve the MeshInfo for a mesh hit using: RayTracingSceneSrg::m_meshInfo[InstanceIndex()]
StructuredBuffer m_meshInfo;
- // unbounded array of Index, VertexPosition, and VertexNormal buffers
- // each mesh has three entries in this array starting at its InstanceIndex() * BUFFER_COUNT_PER_MESH
- #define BUFFER_COUNT_PER_MESH 3
- #define MESH_INDEX_BUFFER_OFFSET 0
- #define MESH_POSITION_BUFFER_OFFSET 1
- #define MESH_NORMAL_BUFFER_OFFSET 2
-
+ // buffer array index offsets for buffers that are always present for each mesh
+ #define MESH_INDEX_BUFFER_OFFSET 0
+ #define MESH_POSITION_BUFFER_OFFSET 1
+ #define MESH_NORMAL_BUFFER_OFFSET 2
+ #define MESH_TANGENT_BUFFER_OFFSET 3
+ #define MESH_BITANGENT_BUFFER_OFFSET 4
+
+ // buffer flag bits indicating if optional buffers are present
+ #define MESH_BUFFER_FLAG_UV 1
+
+ // Unbounded array of mesh stream buffers:
+ // - Index, Position, Normal, Tangent, and Bitangent stream buffers are always present
+ // - Optional stream buffers such as UV are indicated in the MeshInfo.m_bufferFlags field
+ // - Buffers for a particular mesh start at MeshInfo.m_bufferStartIndex
ByteAddressBuffer m_meshBuffers[];
}
\ No newline at end of file
diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli
new file mode 100644
index 0000000000..f858b9a11a
--- /dev/null
+++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli
@@ -0,0 +1,126 @@
+/*
+* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+* its licensors.
+*
+* For complete copyright and license terms please see the LICENSE at the root of this
+* distribution (the "License"). All use of this software is governed by the License,
+* or, if provided, by the license below or the license accompanying this file. Do not
+* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*
+*/
+
+// returns the normalized camera view ray into the scene for this raytracing dispatch thread
+float3 GetViewRayDirection(float4x4 viewProjectionInverseMatrix)
+{
+ float2 pixel = ((float2)DispatchRaysIndex().xy + float2(0.5f, 0.5f)) / (float2)DispatchRaysDimensions();
+ float2 ndc = pixel * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f);
+ return normalize(mul(viewProjectionInverseMatrix, float4(ndc, 0.0f, 1.0f)).xyz);
+}
+
+// returns the vertex indices for the primitive hit by the ray
+// Note: usable only in a raytracing Hit shader
+uint3 GetHitIndices(RayTracingSceneSrg::MeshInfo meshInfo)
+{
+ // compute the array index of the index buffer for this mesh in the m_meshBuffers unbounded array
+ uint meshIndexBufferArrayIndex = meshInfo.m_bufferStartIndex + MESH_INDEX_BUFFER_OFFSET;
+
+ // compute the offset into the index buffer for this primitve of the mesh
+ uint offsetBytes = meshInfo.m_indexOffset + (PrimitiveIndex() * 12);
+
+ // load the indices for this primitive from the index buffer
+ return RayTracingSceneSrg::m_meshBuffers[meshIndexBufferArrayIndex].Load3(offsetBytes);
+}
+
+// returns the interpolated vertex data for the primitive hit by the ray
+// Note: usable only in a raytracing hit shader
+struct VertexData
+{
+ float3 m_position;
+ float3 m_normal;
+ float3 m_tangent;
+ float3 m_bitangent;
+ float2 m_uv;
+};
+
+VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, float2 builtInBarycentrics)
+{
+ // retrieve the poly indices
+ uint3 indices = GetHitIndices(meshInfo);
+
+ // compute barycentrics
+ float3 barycentrics = float3((1.0f - builtInBarycentrics.x - builtInBarycentrics.y), builtInBarycentrics.x, builtInBarycentrics.y);
+
+ // compute the vertex data using barycentric interpolation
+ VertexData vertexData = (VertexData)0;
+ for (uint i = 0; i < 3; ++i)
+ {
+ // position
+ {
+ // array index of the position buffer for this mesh in the m_meshBuffers unbounded array
+ uint meshVertexPositionArrayIndex = meshInfo.m_bufferStartIndex + MESH_POSITION_BUFFER_OFFSET;
+
+ // offset into the position buffer for this vertex
+ uint positionOffset = meshInfo.m_positionOffset + (indices[i] * 12);
+
+ // load the position data
+ vertexData.m_position += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexPositionArrayIndex].Load3(positionOffset)) * barycentrics[i];
+ }
+
+ // normal
+ {
+ // array index of the normal buffer for this mesh in the m_meshBuffers unbounded array
+ uint meshVertexNormalArrayIndex = meshInfo.m_bufferStartIndex + MESH_NORMAL_BUFFER_OFFSET;
+
+ // offset into the normal buffer for this vertex
+ uint normalOffset = meshInfo.m_normalOffset + (indices[i] * 12);
+
+ // load the normal data
+ vertexData.m_normal += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexNormalArrayIndex].Load3(normalOffset)) * barycentrics[i];
+ }
+
+ // tangent
+ {
+ // array index of the tangent buffer for this mesh in the m_meshBuffers unbounded array
+ uint meshVertexTangentArrayIndex = meshInfo.m_bufferStartIndex + MESH_TANGENT_BUFFER_OFFSET;
+
+ // offset into the tangent buffer for this vertex
+ uint tangentOffset = meshInfo.m_tangentOffset + (indices[i] * 12);
+
+ // load the tangent data
+ vertexData.m_tangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexTangentArrayIndex].Load3(tangentOffset)) * barycentrics[i];
+ }
+
+ // bitangent
+ {
+ // array index of the bitangent buffer for this mesh in the m_meshBuffers unbounded array
+ uint meshVertexBitangentArrayIndex = meshInfo.m_bufferStartIndex + MESH_BITANGENT_BUFFER_OFFSET;
+
+ // offset into the bitangent buffer for this vertex
+ uint bitangentOffset = meshInfo.m_bitangentOffset + (indices[i] * 12);
+
+ // load the bitangent data
+ vertexData.m_bitangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexBitangentArrayIndex].Load3(bitangentOffset)) * barycentrics[i];
+ }
+
+ // optional streams begin after MESH_BITANGENT_BUFFER_OFFSET
+ uint optionalBufferOffset = MESH_BITANGENT_BUFFER_OFFSET + 1;
+
+ // UV
+ if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_UV)
+ {
+ // array index of the UV buffer for this mesh in the m_meshBuffers unbounded array
+ uint meshVertexUVArrayIndex = meshInfo.m_bufferStartIndex + optionalBufferOffset++;
+
+ // offset into the UV buffer for this vertex
+ uint uvOffset = meshInfo.m_uvOffset + (indices[i] * 8);
+
+ // load the UV data
+ vertexData.m_uv += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexUVArrayIndex].Load2(uvOffset)) * barycentrics[i];
+ }
+ }
+
+ vertexData.m_normal = normalize(vertexData.m_normal);
+
+ return vertexData;
+}
\ No newline at end of file
diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/SrgSemantics.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/SrgSemantics.azsli
index c134a9d293..6d1b05d797 100644
--- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/SrgSemantics.azsli
+++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/SrgSemantics.azsli
@@ -64,3 +64,8 @@ ShaderResourceGroupSemantic SRG_RayTracingScene
{
FrequencyId = 1;
};
+
+ShaderResourceGroupSemantic SRG_RayTracingMaterial
+{
+ FrequencyId = 2;
+};
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing.azshader
index 804b534277..746ae357ee 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_dx12_0.azshadervariant
index b3bee56bfd..841c5defe3 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_null_0.azshadervariant
index d9b2f17848..39eacb4ade 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_vulkan_0.azshadervariant
index cf39160d3f..597b239218 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracing_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit.azshader
index c4a83a26dc..0f42cd04d6 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant
index fb5b740f04..49bc94767a 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_null_0.azshadervariant
index b7bdabeb4e..d9d30c99f7 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant
index 1eeeffa8be..e2f2a13ca3 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingclosesthit_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingcommon_raytracingglobalsrg.azsrg b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingcommon_raytracingglobalsrg.azsrg
index c9fa0f4e1c..35d7050294 100644
--- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingcommon_raytracingglobalsrg.azsrg
+++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingcommon_raytracingglobalsrg.azsrg
@@ -44,8 +44,14 @@
"field": "element",
"typeName": "ShaderResourceGroupLayout",
"typeId": "{1F92C651-9B83-4379-AB5C-5201F1B2C278}",
- "version": 6,
+ "version": 7,
"Objects": [
+ {
+ "field": "m_name",
+ "typeName": "Name",
+ "typeId": "{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}",
+ "value": ""
+ },
{
"field": "m_staticSamplers",
"typeName": "AZStd::vector",
@@ -3338,8 +3344,14 @@
"field": "element",
"typeName": "ShaderResourceGroupLayout",
"typeId": "{1F92C651-9B83-4379-AB5C-5201F1B2C278}",
- "version": 6,
+ "version": 7,
"Objects": [
+ {
+ "field": "m_name",
+ "typeName": "Name",
+ "typeId": "{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}",
+ "value": ""
+ },
{
"field": "m_staticSamplers",
"typeName": "AZStd::vector",
@@ -6632,8 +6644,14 @@
"field": "element",
"typeName": "ShaderResourceGroupLayout",
"typeId": "{1F92C651-9B83-4379-AB5C-5201F1B2C278}",
- "version": 6,
+ "version": 7,
"Objects": [
+ {
+ "field": "m_name",
+ "typeName": "Name",
+ "typeId": "{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}",
+ "value": ""
+ },
{
"field": "m_staticSamplers",
"typeName": "AZStd::vector",
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss.azshader
index 4f0cea1bfe..77a0f94f97 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss.azshader differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_dx12_0.azshadervariant
index 839efa7278..c144350c7f 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_dx12_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_null_0.azshadervariant
index 5f08825487..c369381fe9 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_null_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_vulkan_0.azshadervariant
index a5b0e842ef..13fd579d9b 100644
Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridraytracingmiss_vulkan_0.azshadervariant differ
diff --git a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/PaperMill_E_3k.exr b/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/PaperMill_E_3k.exr
deleted file mode 100644
index 0fcbcc4746..0000000000
--- a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/PaperMill_E_3k.exr
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:bc9981393c88c6d30a0a5a6837e6f6246a9f550042b3c4be39dd34e479b90569
-size 16793931
diff --git a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/PaperMill_E_3k.exr.assetinfo b/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/PaperMill_E_3k.exr.assetinfo
deleted file mode 100644
index 16cb0dd668..0000000000
--- a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/PaperMill_E_3k.exr.assetinfo
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/exampleBrdf_lut.dds b/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/exampleBrdf_lut.dds
deleted file mode 100644
index f2b2ce550d..0000000000
--- a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/exampleBrdf_lut.dds
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:440bcb1579d4ad667c040bda914ed3121980526a94f23879a0c482c799fd5132
-size 1310848
diff --git a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/exampleDiffuseHDR_cm.dds b/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/exampleDiffuseHDR_cm.dds
deleted file mode 100644
index 9585c25dd1..0000000000
--- a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/exampleDiffuseHDR_cm.dds
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:cf4b22481726214c062ac27fb2d9d8a49e760a76d8fff03330ff9c5f9275a8da
-size 1966208
diff --git a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/exampleSpecularHDR_cm.dds b/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/exampleSpecularHDR_cm.dds
deleted file mode 100644
index a35fac45fb..0000000000
--- a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/exampleSpecularHDR_cm.dds
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8b4c99faffc34988c268613948f2004f40e9bd51de915461a4cb74edc5e8bae6
-size 134217920
diff --git a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/example_iblskyboxcm.dds b/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/example_iblskyboxcm.dds
deleted file mode 100644
index a89dfdbd3d..0000000000
--- a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/example_iblskyboxcm.dds
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:f7edea42ded8143764654f12c19e0c9b74c74afb21f435ebb59c0a4d203892a3
-size 536871104
diff --git a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/papermill_license.txt b/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/papermill_license.txt
deleted file mode 100644
index 83cfe08ab9..0000000000
--- a/Gems/Atom/Feature/Common/Assets/Textures/sampleEnvironment/papermill_license.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-The papermill 'Image base lighting' (IBL) images are modified from the following:
-
-http://www.hdrlabs.com/sibl/archive.html
-'Papermill Ruins E'
-
-All sIBL-sets on this page, including the images within, are licensed under the Creative Commons Attribution-Noncommercial-Share Alike 3.0 License.
-
-Creative Commons License: http://creativecommons.org/licenses/by-nc-sa/3.0/us/
-
-Remember: Do what you want with them, but always mention where you got them from...
\ No newline at end of file
diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp
index 16f20d7178..00c55cbade 100644
--- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp
@@ -89,6 +89,8 @@
#include
#include
+#include
+#include
#include
#include
#include
@@ -128,6 +130,7 @@ namespace AZ
SMAAFeatureProcessor::Reflect(context);
PostProcessFeatureProcessor::Reflect(context);
ImGuiPassData::Reflect(context);
+ RayTracingPassData::Reflect(context);
LightingPreset::Reflect(context);
ModelPreset::Reflect(context);
@@ -271,6 +274,9 @@ namespace AZ
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurChildPass"), &Render::ReflectionScreenSpaceBlurChildPass::Create);
passSystem->AddPassCreator(Name("ReflectionCopyFrameBufferPass"), &Render::ReflectionCopyFrameBufferPass::Create);
+ // Add RayTracing pas
+ passSystem->AddPassCreator(Name("RayTracingPass"), &Render::RayTracingPass::Create);
+
// setup handler for load pass template mappings
m_loadTemplatesHandler = RPI::PassSystemInterface::OnReadyLoadTemplatesEvent::Handler([this]() { this->LoadPassTemplateMappings(); });
RPI::PassSystemInterface::Get()->ConnectEvent(m_loadTemplatesHandler);
diff --git a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp
index 90499be8b8..f8c1258fc0 100644
--- a/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/FrameCaptureSystemComponent.cpp
@@ -21,6 +21,8 @@
#include
#include
+#include
+#include
#include
#include
@@ -55,6 +57,43 @@ namespace AZ
FrameCaptureOutputResult PngFrameCaptureOutput(
const AZStd::string& outputFilePath, const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult)
{
+ AZStd::shared_ptr> buffer = readbackResult.m_dataBuffer;
+
+ // convert bgra to rgba by swapping channels
+ const int numChannels = AZ::RHI::GetFormatComponentCount(readbackResult.m_imageDescriptor.m_format);
+ if (readbackResult.m_imageDescriptor.m_format == RHI::Format::B8G8R8A8_UNORM)
+ {
+ buffer = AZStd::make_shared>(readbackResult.m_dataBuffer->size());
+ AZStd::copy(readbackResult.m_dataBuffer->begin(), readbackResult.m_dataBuffer->end(), buffer->begin());
+
+ AZ::JobCompletion jobCompletion;
+ const int numThreads = 8;
+ const int numPixelsPerThread = buffer->size() / numChannels / numThreads;
+ for (int i = 0; i < numThreads; ++i)
+ {
+ int startPixel = i * numPixelsPerThread;
+
+ AZ::Job* job = AZ::CreateJobFunction(
+ [&, startPixel, numPixelsPerThread]()
+ {
+ for (int pixelOffset = 0; pixelOffset < numPixelsPerThread; ++pixelOffset)
+ {
+ if (startPixel * numChannels + numChannels < buffer->size())
+ {
+ AZStd::swap(
+ buffer->data()[(startPixel + pixelOffset) * numChannels],
+ buffer->data()[(startPixel + pixelOffset) * numChannels + 2]
+ );
+ }
+ }
+ }, true, nullptr);
+
+ job->SetDependent(&jobCompletion);
+ job->Start();
+ }
+ jobCompletion.StartAndWaitForCompletion();
+ }
+
using namespace OIIO;
AZStd::unique_ptr out = ImageOutput::create(outputFilePath.c_str());
if (out)
@@ -62,13 +101,13 @@ namespace AZ
ImageSpec spec(
readbackResult.m_imageDescriptor.m_size.m_width,
readbackResult.m_imageDescriptor.m_size.m_height,
- AZ::RHI::GetFormatComponentCount(readbackResult.m_imageDescriptor.m_format)
+ numChannels
);
spec.attribute("png:compressionLevel", r_pngCompressionLevel);
if (out->open(outputFilePath.c_str(), spec))
{
- out->write_image(TypeDesc::UINT8, readbackResult.m_dataBuffer->data());
+ out->write_image(TypeDesc::UINT8, buffer->data());
out->close();
return FrameCaptureOutputResult{FrameCaptureResult::Success, AZStd::nullopt};
}
@@ -460,13 +499,23 @@ namespace AZ
#if defined(OPEN_IMAGE_IO_ENABLED)
else if (extension == "png")
{
- AZStd::string folderPath;
- AzFramework::StringFunc::Path::GetFolderPath(m_outputFilePath.c_str(), folderPath);
- AZ::IO::SystemFile::CreateDir(folderPath.c_str());
+ if (readbackResult.m_imageDescriptor.m_format == RHI::Format::R8G8B8A8_UNORM ||
+ readbackResult.m_imageDescriptor.m_format == RHI::Format::B8G8R8A8_UNORM)
+ {
+ AZStd::string folderPath;
+ AzFramework::StringFunc::Path::GetFolderPath(m_outputFilePath.c_str(), folderPath);
+ AZ::IO::SystemFile::CreateDir(folderPath.c_str());
- const auto frameCaptureResult = PngFrameCaptureOutput(m_outputFilePath, readbackResult);
- m_result = frameCaptureResult.m_result;
- m_latestCaptureInfo = frameCaptureResult.m_errorMessage.value_or("");
+ const auto frameCaptureResult = PngFrameCaptureOutput(m_outputFilePath, readbackResult);
+ m_result = frameCaptureResult.m_result;
+ m_latestCaptureInfo = frameCaptureResult.m_errorMessage.value_or("");
+ }
+ else
+ {
+ m_latestCaptureInfo = AZStd::string::format(
+ "Can't save image with format %s to a png file", RHI::ToString(readbackResult.m_imageDescriptor.m_format));
+ m_result = FrameCaptureResult::UnsupportedFormat;
+ }
}
#endif
else
diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
index 117b177f05..4aaa0be132 100644
--- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
@@ -710,27 +710,53 @@ namespace AZ
uint32_t rayTracingLod = aznumeric_cast(modelLods.size() - 1);
const Data::Instance& modelLod = modelLods[rayTracingLod];
- // setup a stream layout and shader input contract for the position and normal streams
+ // setup a stream layout and shader input contract for the vertex streams
static const char* PositionSemantic = "POSITION";
static const char* NormalSemantic = "NORMAL";
- static const RHI::Format StreamFormat = RHI::Format::R32G32B32_FLOAT;
+ static const char* TangentSemantic = "TANGENT";
+ static const char* BitangentSemantic = "BITANGENT";
+ static const char* UVSemantic = "UV";
+ static const RHI::Format PositionStreamFormat = RHI::Format::R32G32B32_FLOAT;
+ static const RHI::Format NormalStreamFormat = RHI::Format::R32G32B32_FLOAT;
+ static const RHI::Format TangentStreamFormat = RHI::Format::R32G32B32_FLOAT;
+ static const RHI::Format BitangentStreamFormat = RHI::Format::R32G32B32_FLOAT;
+ static const RHI::Format UVStreamFormat = RHI::Format::R32G32_FLOAT;
RHI::InputStreamLayoutBuilder layoutBuilder;
- layoutBuilder.AddBuffer()->Channel(PositionSemantic, StreamFormat);
- layoutBuilder.AddBuffer()->Channel(NormalSemantic, StreamFormat);
+ layoutBuilder.AddBuffer()->Channel(PositionSemantic, PositionStreamFormat);
+ layoutBuilder.AddBuffer()->Channel(NormalSemantic, NormalStreamFormat);
+ layoutBuilder.AddBuffer()->Channel(UVSemantic, UVStreamFormat);
+ layoutBuilder.AddBuffer()->Channel(TangentSemantic, TangentStreamFormat);
+ layoutBuilder.AddBuffer()->Channel(BitangentSemantic, BitangentStreamFormat);
RHI::InputStreamLayout inputStreamLayout = layoutBuilder.End();
RPI::ShaderInputContract::StreamChannelInfo positionStreamChannelInfo;
positionStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(PositionSemantic));
- positionStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(StreamFormat);
+ positionStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(PositionStreamFormat);
RPI::ShaderInputContract::StreamChannelInfo normalStreamChannelInfo;
normalStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(NormalSemantic));
- normalStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(StreamFormat);
+ normalStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(NormalStreamFormat);
+
+ RPI::ShaderInputContract::StreamChannelInfo tangentStreamChannelInfo;
+ tangentStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(TangentSemantic));
+ tangentStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(TangentStreamFormat);
+
+ RPI::ShaderInputContract::StreamChannelInfo bitangentStreamChannelInfo;
+ bitangentStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(BitangentSemantic));
+ bitangentStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(BitangentStreamFormat);
+
+ RPI::ShaderInputContract::StreamChannelInfo uvStreamChannelInfo;
+ uvStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(UVSemantic));
+ uvStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(UVStreamFormat);
+ uvStreamChannelInfo.m_isOptional = true;
RPI::ShaderInputContract shaderInputContract;
shaderInputContract.m_streamChannels.emplace_back(positionStreamChannelInfo);
shaderInputContract.m_streamChannels.emplace_back(normalStreamChannelInfo);
+ shaderInputContract.m_streamChannels.emplace_back(tangentStreamChannelInfo);
+ shaderInputContract.m_streamChannels.emplace_back(bitangentStreamChannelInfo);
+ shaderInputContract.m_streamChannels.emplace_back(uvStreamChannelInfo);
// setup the raytracing data for each sub-mesh
const size_t meshCount = modelLod->GetMeshes().size();
@@ -739,26 +765,6 @@ namespace AZ
{
const RPI::ModelLod::Mesh& mesh = modelLod->GetMeshes()[meshIndex];
- // retrieve vertex/index buffers
- RPI::ModelLod::StreamBufferViewList streamBufferViews;
- [[maybe_unused]] bool result = modelLod->GetStreamsForMesh(inputStreamLayout, streamBufferViews, nullptr, shaderInputContract, meshIndex);
- AZ_Assert(result, "Failed to retrieve mesh stream buffer views");
-
- // note that the element count is the size of the entire buffer, even though this mesh may only
- // occupy a portion of the vertex buffer. This is necessary since we are accessing it using
- // a ByteAddressBuffer in the raytracing shaders and passing the byte offset to the shader in a constant buffer.
- uint32_t vertexBufferByteCount = const_cast(streamBufferViews[0].GetBuffer())->GetDescriptor().m_byteCount;
- RHI::BufferViewDescriptor vertexBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, vertexBufferByteCount);
-
- const RHI::IndexBufferView& indexBufferView = mesh.m_indexBufferView;
- uint32_t indexElementSize = indexBufferView.GetIndexFormat() == RHI::IndexFormat::Uint16 ? 2 : 4;
- uint32_t indexElementCount = (uint32_t)indexBufferView.GetBuffer()->GetDescriptor().m_byteCount / indexElementSize;
- RHI::BufferViewDescriptor indexBufferDescriptor;
- indexBufferDescriptor.m_elementOffset = 0;
- indexBufferDescriptor.m_elementCount = indexElementCount;
- indexBufferDescriptor.m_elementSize = indexElementSize;
- indexBufferDescriptor.m_elementFormat = indexBufferView.GetIndexFormat() == RHI::IndexFormat::Uint16 ? RHI::Format::R16_UINT : RHI::Format::R32_UINT;
-
// retrieve the material
Data::Instance material = mesh.m_material;
@@ -769,31 +775,163 @@ namespace AZ
material = materialAssignment.m_materialInstance;
}
- AZ::Color irradianceColor(1.0f, 1.0f, 1.0f, 1.0f);
+ // retrieve vertex/index buffers
+ RPI::ModelLod::StreamBufferViewList streamBufferViews;
+ [[maybe_unused]] bool result = modelLod->GetStreamsForMesh(
+ inputStreamLayout,
+ streamBufferViews,
+ nullptr,
+ shaderInputContract,
+ meshIndex,
+ materialAssignment.m_matModUvOverrides,
+ material->GetAsset()->GetMaterialTypeAsset()->GetUvNameMap());
+ AZ_Assert(result, "Failed to retrieve mesh stream buffer views");
+
+ // note that the element count is the size of the entire buffer, even though this mesh may only
+ // occupy a portion of the vertex buffer. This is necessary since we are accessing it using
+ // a ByteAddressBuffer in the raytracing shaders and passing the byte offset to the shader in a constant buffer.
+ uint32_t positionBufferByteCount = const_cast(streamBufferViews[0].GetBuffer())->GetDescriptor().m_byteCount;
+ RHI::BufferViewDescriptor positionBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, positionBufferByteCount);
+
+ uint32_t normalBufferByteCount = const_cast(streamBufferViews[1].GetBuffer())->GetDescriptor().m_byteCount;
+ RHI::BufferViewDescriptor normalBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, normalBufferByteCount);
+
+ uint32_t tangentBufferByteCount = const_cast(streamBufferViews[2].GetBuffer())->GetDescriptor().m_byteCount;
+ RHI::BufferViewDescriptor tangentBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tangentBufferByteCount);
+
+ uint32_t bitangentBufferByteCount = const_cast(streamBufferViews[3].GetBuffer())->GetDescriptor().m_byteCount;
+ RHI::BufferViewDescriptor bitangentBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, bitangentBufferByteCount);
+
+ uint32_t uvBufferByteCount = const_cast(streamBufferViews[4].GetBuffer())->GetDescriptor().m_byteCount;
+ RHI::BufferViewDescriptor uvBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, uvBufferByteCount);
+
+ const RHI::IndexBufferView& indexBufferView = mesh.m_indexBufferView;
+ uint32_t indexElementSize = indexBufferView.GetIndexFormat() == RHI::IndexFormat::Uint16 ? 2 : 4;
+ uint32_t indexElementCount = (uint32_t)indexBufferView.GetBuffer()->GetDescriptor().m_byteCount / indexElementSize;
+ RHI::BufferViewDescriptor indexBufferDescriptor;
+ indexBufferDescriptor.m_elementOffset = 0;
+ indexBufferDescriptor.m_elementCount = indexElementCount;
+ indexBufferDescriptor.m_elementSize = indexElementSize;
+ indexBufferDescriptor.m_elementFormat = indexBufferView.GetIndexFormat() == RHI::IndexFormat::Uint16 ? RHI::Format::R16_UINT : RHI::Format::R32_UINT;
+
+ // set the SubMesh data to pass to the RayTracingFeatureProcessor, starting with vertex/index data
+ RayTracingFeatureProcessor::SubMesh subMesh;
+ subMesh.m_positionFormat = PositionStreamFormat;
+ subMesh.m_positionVertexBufferView = streamBufferViews[0];
+ subMesh.m_positionShaderBufferView = const_cast(streamBufferViews[0].GetBuffer())->GetBufferView(positionBufferDescriptor);
+
+ subMesh.m_normalFormat = NormalStreamFormat;
+ subMesh.m_normalVertexBufferView = streamBufferViews[1];
+ subMesh.m_normalShaderBufferView = const_cast(streamBufferViews[1].GetBuffer())->GetBufferView(normalBufferDescriptor);
+
+ subMesh.m_tangentFormat = TangentStreamFormat;
+ subMesh.m_tangentVertexBufferView = streamBufferViews[2];
+ subMesh.m_tangentShaderBufferView = const_cast(streamBufferViews[2].GetBuffer())->GetBufferView(tangentBufferDescriptor);
+
+ subMesh.m_bitangentFormat = BitangentStreamFormat;
+ subMesh.m_bitangentVertexBufferView = streamBufferViews[3];
+ subMesh.m_bitangentShaderBufferView = const_cast(streamBufferViews[3].GetBuffer())->GetBufferView(bitangentBufferDescriptor);
+
+ if (uvBufferByteCount > 0)
+ {
+ subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::UV;
+ subMesh.m_uvFormat = UVStreamFormat;
+ subMesh.m_uvVertexBufferView = streamBufferViews[4];
+ subMesh.m_uvShaderBufferView = const_cast(streamBufferViews[4].GetBuffer())->GetBufferView(uvBufferDescriptor);
+ }
+
+ subMesh.m_indexBufferView = mesh.m_indexBufferView;
+ subMesh.m_indexShaderBufferView = const_cast(mesh.m_indexBufferView.GetBuffer())->GetBufferView(indexBufferDescriptor);
+
+ // add material data
if (material)
{
+ // irradiance color
RPI::MaterialPropertyIndex propertyIndex = material->FindPropertyIndex(AZ::Name("irradiance.color"));
if (propertyIndex.IsValid())
{
- irradianceColor = material->GetPropertyValue(propertyIndex);
+ subMesh.m_irradianceColor = material->GetPropertyValue(propertyIndex);
}
propertyIndex = material->FindPropertyIndex(AZ::Name("irradiance.factor"));
if (propertyIndex.IsValid())
{
- irradianceColor *= material->GetPropertyValue(propertyIndex);
+ subMesh.m_irradianceColor *= material->GetPropertyValue(propertyIndex);
+ }
+
+ // base color
+ propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.color"));
+ if (propertyIndex.IsValid())
+ {
+ subMesh.m_baseColor = material->GetPropertyValue(propertyIndex);
+ }
+
+ propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.factor"));
+ if (propertyIndex.IsValid())
+ {
+ subMesh.m_baseColor *= material->GetPropertyValue(propertyIndex);
+ }
+
+ // metallic
+ propertyIndex = material->FindPropertyIndex(AZ::Name("metallic.factor"));
+ if (propertyIndex.IsValid())
+ {
+ subMesh.m_metallicFactor = material->GetPropertyValue(propertyIndex);
+ }
+
+ // roughness
+ propertyIndex = material->FindPropertyIndex(AZ::Name("roughness.factor"));
+ if (propertyIndex.IsValid())
+ {
+ subMesh.m_roughnessFactor = material->GetPropertyValue(propertyIndex);
+ }
+
+ // textures
+ propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.textureMap"));
+ if (propertyIndex.IsValid())
+ {
+ Data::Instance image = material->GetPropertyValue>(propertyIndex);
+ if (image.get())
+ {
+ subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::BaseColor;
+ subMesh.m_baseColorImageView = image->GetImageView();
+ }
+ }
+
+ propertyIndex = material->FindPropertyIndex(AZ::Name("normal.textureMap"));
+ if (propertyIndex.IsValid())
+ {
+ Data::Instance image = material->GetPropertyValue>(propertyIndex);
+ if (image.get())
+ {
+ subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::Normal;
+ subMesh.m_normalImageView = image->GetImageView();
+ }
+ }
+
+ propertyIndex = material->FindPropertyIndex(AZ::Name("metallic.textureMap"));
+ if (propertyIndex.IsValid())
+ {
+ Data::Instance image = material->GetPropertyValue>(propertyIndex);
+ if (image.get())
+ {
+ subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::Metallic;
+ subMesh.m_metallicImageView = image->GetImageView();
+ }
+ }
+
+ propertyIndex = material->FindPropertyIndex(AZ::Name("roughness.textureMap"));
+ if (propertyIndex.IsValid())
+ {
+ Data::Instance image = material->GetPropertyValue>(propertyIndex);
+ if (image.get())
+ {
+ subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::Roughness;
+ subMesh.m_roughnessImageView = image->GetImageView();
+ }
}
}
- RayTracingFeatureProcessor::SubMesh subMesh;
- subMesh.m_vertexFormat = StreamFormat;
- subMesh.m_positionVertexBufferView = streamBufferViews[0];
- subMesh.m_positionShaderBufferView = const_cast(streamBufferViews[0].GetBuffer())->GetBufferView(vertexBufferDescriptor);
- subMesh.m_normalVertexBufferView = streamBufferViews[1];
- subMesh.m_normalShaderBufferView = const_cast(streamBufferViews[1].GetBuffer())->GetBufferView(vertexBufferDescriptor);
- subMesh.m_indexBufferView = mesh.m_indexBufferView;
- subMesh.m_indexShaderBufferView = const_cast(mesh.m_indexBufferView.GetBuffer())->GetBufferView(indexBufferDescriptor);
- subMesh.m_irradianceColor = irradianceColor;
subMeshes.push_back(subMesh);
}
diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp
index 2bb2fa2ac2..92cd41b4e8 100644
--- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp
@@ -115,11 +115,11 @@ namespace AZ
}
}
- // update and compile the RayTracingSceneSrg
+ // update and compile the RayTracingSceneSrg and RayTracingMaterialSrg
// Note: the timing of this update is very important, it needs to be updated after the TLAS is allocated so it can
// be set on the RayTracingSceneSrg for this frame, and the ray tracing mesh data in the RayTracingSceneSrg must
// exactly match the TLAS. Any mismatch in this data may result in a TDR.
- rayTracingFeatureProcessor->UpdateRayTracingSceneSrg();
+ rayTracingFeatureProcessor->UpdateRayTracingSrgs();
}
}
diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp
index 7c13daea3b..10c7c2d378 100644
--- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp
@@ -71,6 +71,13 @@ namespace AZ
AZ_Assert(rayTracingSceneSrgAsset.IsReady(), "Failed to load RayTracingSceneSrg asset");
m_rayTracingSceneSrg = RPI::ShaderResourceGroup::Create(rayTracingSceneSrgAsset);
+
+ // load the RayTracingMaterialSrg asset
+ Data::Asset rayTracingMaterialSrgAsset =
+ RPI::AssetUtils::LoadAssetByProductPath("shaderlib/atom/features/raytracing/raytracingmaterialsrg_raytracingmaterialsrg.azsrg", RPI::AssetUtils::TraceLevel::Error);
+ AZ_Assert(rayTracingMaterialSrgAsset.IsReady(), "Failed to load RayTracingMaterialSrg asset");
+
+ m_rayTracingMaterialSrg = RPI::ShaderResourceGroup::Create(rayTracingMaterialSrgAsset);
}
void RayTracingFeatureProcessor::SetMesh(const ObjectId objectId, const SubMeshVector& subMeshes)
@@ -104,7 +111,7 @@ namespace AZ
RHI::RayTracingBlasDescriptor blasDescriptor;
blasDescriptor.Build()
->Geometry()
- ->VertexFormat(subMesh.m_vertexFormat)
+ ->VertexFormat(subMesh.m_positionFormat)
->VertexBuffer(subMesh.m_positionVertexBufferView)
->IndexBuffer(subMesh.m_indexBufferView)
;
@@ -124,6 +131,7 @@ namespace AZ
m_subMeshCount += aznumeric_cast(subMeshes.size());
m_meshInfoBufferNeedsUpdate = true;
+ m_materialInfoBufferNeedsUpdate = true;
}
void RayTracingFeatureProcessor::RemoveMesh(const ObjectId objectId)
@@ -142,6 +150,7 @@ namespace AZ
}
m_meshInfoBufferNeedsUpdate = true;
+ m_materialInfoBufferNeedsUpdate = true;
}
void RayTracingFeatureProcessor::SetMeshTransform(const ObjectId objectId, const AZ::Transform transform, const AZ::Vector3 nonUniformScale)
@@ -162,14 +171,14 @@ namespace AZ
m_meshInfoBufferNeedsUpdate = true;
}
- void RayTracingFeatureProcessor::UpdateRayTracingSceneSrg()
+ void RayTracingFeatureProcessor::UpdateRayTracingSrgs()
{
if (!m_tlas->GetTlasBuffer())
{
return;
}
- if (m_rayTracingSceneSrg->IsQueuedForCompile())
+ if (m_rayTracingSceneSrg->IsQueuedForCompile() || m_rayTracingMaterialSrg->IsQueuedForCompile())
{
//[GFX TODO][ATOM-14792] AtomSampleViewer: Reset scene and feature processors before switching to sample
return;
@@ -178,7 +187,148 @@ namespace AZ
// update the mesh info buffer with the latest ray tracing enabled meshes
UpdateMeshInfoBuffer();
+ // update the material info buffer with the latest ray tracing enabled meshes
+ UpdateMaterialInfoBuffer();
+
// update the RayTracingSceneSrg
+ UpdateRayTracingSceneSrg();
+
+ // update the RayTracingMaterialSrg
+ UpdateRayTracingMaterialSrg();
+ }
+
+ void RayTracingFeatureProcessor::UpdateMeshInfoBuffer()
+ {
+ if (m_meshInfoBufferNeedsUpdate && (m_subMeshCount > 0))
+ {
+ TransformServiceFeatureProcessor* transformFeatureProcessor = GetParentScene()->GetFeatureProcessor();
+
+ AZStd::vector meshInfos;
+ meshInfos.reserve(m_subMeshCount);
+
+ uint32_t newMeshByteCount = m_subMeshCount * sizeof(MeshInfo);
+
+ if (m_meshInfoBuffer == nullptr)
+ {
+ AZStd::string uuidString = AZ::Uuid::CreateRandom().ToString();
+
+ // allocate the MeshInfo structured buffer
+ RPI::CommonBufferDescriptor desc;
+ desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
+ desc.m_bufferName = AZStd::string::format("RayTracingMeshInfo_%s", uuidString.c_str());
+ desc.m_byteCount = newMeshByteCount;
+ desc.m_elementSize = sizeof(MeshInfo);
+ m_meshInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
+ }
+ else if (m_meshInfoBuffer->GetBufferSize() < newMeshByteCount)
+ {
+ // resize for the new sub-mesh count
+ m_meshInfoBuffer->Resize(newMeshByteCount);
+ }
+
+ // keep track of the start index of the buffers for each mesh, this is put into the MeshInfo
+ // entry for each mesh so it knows where to find the start of its buffers in the unbounded array
+ uint32_t bufferStartIndex = 0;
+
+ for (const auto& mesh : m_meshes)
+ {
+ AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first));
+ AZ::Transform noScaleTransform = meshTransform;
+ noScaleTransform.ExtractUniformScale();
+ AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform);
+ rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose();
+
+ const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes;
+ for (const auto& subMesh : subMeshes)
+ {
+ MeshInfo meshInfo;
+ meshInfo.m_indexOffset = subMesh.m_indexBufferView.GetByteOffset();
+ meshInfo.m_positionOffset = subMesh.m_positionVertexBufferView.GetByteOffset();
+ meshInfo.m_normalOffset = subMesh.m_normalVertexBufferView.GetByteOffset();
+ meshInfo.m_tangentOffset = subMesh.m_tangentVertexBufferView.GetByteOffset();
+ meshInfo.m_bitangentOffset = subMesh.m_bitangentVertexBufferView.GetByteOffset();
+
+ if (RHI::CheckBitsAll(subMesh.m_bufferFlags, RayTracingSubMeshBufferFlags::UV))
+ {
+ meshInfo.m_uvOffset = subMesh.m_uvVertexBufferView.GetByteOffset();
+ }
+
+ subMesh.m_irradianceColor.StoreToFloat4(meshInfo.m_irradianceColor.data());
+ rotationMatrix.StoreToRowMajorFloat9(meshInfo.m_worldInvTranspose.data());
+ meshInfo.m_bufferFlags = subMesh.m_bufferFlags;
+ meshInfo.m_bufferStartIndex = bufferStartIndex;
+
+ // add the count of buffers present in this subMesh to the start index for the next subMesh
+ // note that the Index, Position, Normal, Tangent, and Bitangent buffers are always counted since they are guaranteed
+ static const uint32_t RayTracingSubMeshFixedStreamCount = 5;
+ bufferStartIndex += (RayTracingSubMeshFixedStreamCount + RHI::CountBitsSet(aznumeric_cast(meshInfo.m_bufferFlags)));
+
+ meshInfos.emplace_back(meshInfo);
+ }
+ }
+
+ m_meshInfoBuffer->UpdateData(meshInfos.data(), newMeshByteCount);
+ m_meshInfoBufferNeedsUpdate = false;
+ }
+ }
+
+ void RayTracingFeatureProcessor::UpdateMaterialInfoBuffer()
+ {
+ if (m_materialInfoBufferNeedsUpdate && (m_subMeshCount > 0))
+ {
+ AZStd::vector materialInfos;
+ materialInfos.reserve(m_subMeshCount);
+
+ uint32_t newMaterialByteCount = m_subMeshCount * sizeof(MaterialInfo);
+
+ if (m_materialInfoBuffer == nullptr)
+ {
+ AZStd::string uuidString = AZ::Uuid::CreateRandom().ToString();
+
+ // allocate the MaterialInfo structured buffer
+ RPI::CommonBufferDescriptor desc;
+ desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
+ desc.m_bufferName = AZStd::string::format("RayTracingMaterialInfo_%s", uuidString.c_str());
+ desc.m_byteCount = newMaterialByteCount;
+ desc.m_elementSize = sizeof(MaterialInfo);
+ m_materialInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
+ }
+ else if (m_materialInfoBuffer->GetBufferSize() < newMaterialByteCount)
+ {
+ // resize for the new sub-mesh count
+ m_materialInfoBuffer->Resize(newMaterialByteCount);
+ }
+
+ // keep track of the start index of the textures for each mesh, this is put into the MaterialInfo
+ // entry for each mesh so it knows where to find the start of its textures in the unbounded array
+ uint32_t textureStartIndex = 0;
+
+ for (const auto& mesh : m_meshes)
+ {
+ const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes;
+ for (const auto& subMesh : subMeshes)
+ {
+ MaterialInfo materialInfo;
+ subMesh.m_baseColor.StoreToFloat4(materialInfo.m_baseColor.data());
+ materialInfo.m_metallicFactor = subMesh.m_metallicFactor;
+ materialInfo.m_roughnessFactor = subMesh.m_roughnessFactor;
+ materialInfo.m_textureFlags = subMesh.m_textureFlags;
+ materialInfo.m_textureStartIndex = textureStartIndex;
+
+ // add the count of textures present in this subMesh to the start index for the next subMesh
+ textureStartIndex += RHI::CountBitsSet(aznumeric_cast(materialInfo.m_textureFlags));
+
+ materialInfos.emplace_back(materialInfo);
+ }
+ }
+
+ m_materialInfoBuffer->UpdateData(materialInfos.data(), newMaterialByteCount);
+ m_materialInfoBufferNeedsUpdate = false;
+ }
+ }
+
+ void RayTracingFeatureProcessor::UpdateRayTracingSceneSrg()
+ {
const RHI::ShaderResourceGroupLayout* srgLayout = m_rayTracingSceneSrg->GetLayout();
RHI::ShaderInputImageIndex imageIndex;
RHI::ShaderInputBufferIndex bufferIndex;
@@ -272,11 +422,18 @@ namespace AZ
const SubMeshVector& subMeshes = mesh.second.m_subMeshes;
for (const auto& subMesh : subMeshes)
{
- // add the index, position, and normal buffers for this sub-mesh to the mesh buffer list, this will
- // go into the shader as an unbounded array in the Srg
+ // add the stream buffers for this sub-mesh to the mesh buffer list,
+ // this is sent to the shader as an unbounded array in the Srg
meshBuffers.push_back(subMesh.m_indexShaderBufferView.get());
meshBuffers.push_back(subMesh.m_positionShaderBufferView.get());
meshBuffers.push_back(subMesh.m_normalShaderBufferView.get());
+ meshBuffers.push_back(subMesh.m_tangentShaderBufferView.get());
+ meshBuffers.push_back(subMesh.m_bitangentShaderBufferView.get());
+
+ if (RHI::CheckBitsAll(subMesh.m_bufferFlags, RayTracingSubMeshBufferFlags::UV))
+ {
+ meshBuffers.push_back(subMesh.m_uvShaderBufferView.get());
+ }
}
}
@@ -287,58 +444,53 @@ namespace AZ
m_rayTracingSceneSrg->Compile();
}
- void RayTracingFeatureProcessor::UpdateMeshInfoBuffer()
+ void RayTracingFeatureProcessor::UpdateRayTracingMaterialSrg()
{
- if (m_meshInfoBufferNeedsUpdate && (m_subMeshCount > 0))
+ const RHI::ShaderResourceGroupLayout* srgLayout = m_rayTracingMaterialSrg->GetLayout();
+ RHI::ShaderInputImageIndex imageIndex;
+ RHI::ShaderInputBufferIndex bufferIndex;
+ RHI::ShaderInputConstantIndex constantIndex;
+
+ bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_materialInfo"));
+ m_rayTracingMaterialSrg->SetBufferView(bufferIndex, m_materialInfoBuffer->GetBufferView());
+
+ if (m_subMeshCount)
{
- TransformServiceFeatureProcessor* transformFeatureProcessor = GetParentScene()->GetFeatureProcessor();
-
- AZStd::vector meshInfos;
- meshInfos.reserve(m_subMeshCount);
-
- uint32_t newMeshByteCount = m_subMeshCount * sizeof(MeshInfo);
-
- if (m_meshInfoBuffer == nullptr)
- {
- // allocate the MeshInfo structured buffer
- RPI::CommonBufferDescriptor desc;
- desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
- desc.m_bufferName = "RayTracingMeshInfo";
- desc.m_byteCount = newMeshByteCount;
- desc.m_elementSize = sizeof(MeshInfo);
- m_meshInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
- }
- else if (m_meshInfoBuffer->GetBufferSize() < newMeshByteCount)
- {
- // resize for the new sub-mesh count
- m_meshInfoBuffer->Resize(newMeshByteCount);
- }
-
+ AZStd::vector materialTextures;
for (const auto& mesh : m_meshes)
{
- AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first));
- AZ::Transform noScaleTransform = meshTransform;
- noScaleTransform.ExtractUniformScale();
- AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform);
- rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose();
-
- const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes;
+ const SubMeshVector& subMeshes = mesh.second.m_subMeshes;
for (const auto& subMesh : subMeshes)
{
- MeshInfo meshInfo;
- meshInfo.m_indexOffset = subMesh.m_indexBufferView.GetByteOffset();
- meshInfo.m_positionOffset = subMesh.m_positionVertexBufferView.GetByteOffset();
- meshInfo.m_normalOffset = subMesh.m_normalVertexBufferView.GetByteOffset();
- subMesh.m_irradianceColor.StoreToFloat4(meshInfo.m_irradianceColor.data());
- rotationMatrix.StoreToRowMajorFloat9(meshInfo.m_worldInvTranspose.data());
+ // add the baseColor, normal, metallic, and roughness images for this sub-mesh to the material texture list,
+ // this is sent to the shader as an unbounded array in the Srg
+ if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::BaseColor))
+ {
+ materialTextures.push_back(subMesh.m_baseColorImageView.get());
+ }
- meshInfos.emplace_back(meshInfo);
+ if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::Normal))
+ {
+ materialTextures.push_back(subMesh.m_normalImageView.get());
+ }
+
+ if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::Metallic))
+ {
+ materialTextures.push_back(subMesh.m_metallicImageView.get());
+ }
+
+ if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::Roughness))
+ {
+ materialTextures.push_back(subMesh.m_roughnessImageView.get());
+ }
}
}
- m_meshInfoBuffer->UpdateData(meshInfos.data(), newMeshByteCount);
- m_meshInfoBufferNeedsUpdate = false;
+ RHI::ShaderInputImageUnboundedArrayIndex textureUnboundedArrayIndex = srgLayout->FindShaderInputImageUnboundedArrayIndex(AZ::Name("m_materialTextures"));
+ m_rayTracingMaterialSrg->SetImageViewUnboundedArray(textureUnboundedArrayIndex, materialTextures);
}
+
+ m_rayTracingMaterialSrg->Compile();
}
}
}
diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h
index f317f1c096..90a9383ae6 100644
--- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h
+++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h
@@ -16,6 +16,7 @@
#include
#include
#include
+#include
#include
#include
@@ -23,6 +24,28 @@ namespace AZ
{
namespace Render
{
+ static const uint32_t RayTracingGlobalSrgBindingSlot = 0;
+ static const uint32_t RayTracingSceneSrgBindingSlot = 1;
+ static const uint32_t RayTracingMaterialSrgBindingSlot = 2;
+
+ enum class RayTracingSubMeshBufferFlags : uint32_t
+ {
+ None = 0,
+
+ UV = AZ_BIT(0)
+ };
+ AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::Render::RayTracingSubMeshBufferFlags);
+
+ enum class RayTracingSubMeshTextureFlags : uint32_t
+ {
+ None = 0,
+ BaseColor = AZ_BIT(0),
+ Normal = AZ_BIT(1),
+ Metallic = AZ_BIT(2),
+ Roughness = AZ_BIT(3)
+ };
+ AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::Render::RayTracingSubMeshTextureFlags);
+
//! This feature processor manages ray tracing data for a Scene
class RayTracingFeatureProcessor
: public RPI::FeatureProcessor
@@ -42,20 +65,53 @@ namespace AZ
//! Contains data for a single sub-mesh
struct SubMesh
{
- // vertex/index buffer data
- RHI::Format m_vertexFormat = RHI::Format::Unknown;
+ // vertex streams
+ RHI::Format m_positionFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_positionVertexBufferView;
RHI::Ptr m_positionShaderBufferView;
+
+ RHI::Format m_normalFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_normalVertexBufferView;
RHI::Ptr m_normalShaderBufferView;
+
+ RHI::Format m_tangentFormat = RHI::Format::Unknown;
+ RHI::StreamBufferView m_tangentVertexBufferView;
+ RHI::Ptr m_tangentShaderBufferView;
+
+ RHI::Format m_bitangentFormat = RHI::Format::Unknown;
+ RHI::StreamBufferView m_bitangentVertexBufferView;
+ RHI::Ptr m_bitangentShaderBufferView;
+
+ RHI::Format m_uvFormat = RHI::Format::Unknown;
+ RHI::StreamBufferView m_uvVertexBufferView;
+ RHI::Ptr m_uvShaderBufferView;
+
+ // index buffer
RHI::IndexBufferView m_indexBufferView;
RHI::Ptr m_indexShaderBufferView;
+ // vertex buffer usage flags
+ RayTracingSubMeshBufferFlags m_bufferFlags = RayTracingSubMeshBufferFlags::None;
+
// color of the bounced light from this sub-mesh
- AZ::Color m_irradianceColor;
+ AZ::Color m_irradianceColor = AZ::Color(1.0f);
// ray tracing Blas
RHI::Ptr m_blas;
+
+ // material data
+ AZ::Color m_baseColor = AZ::Color(0.0f);
+ float m_metallicFactor = 0.0f;
+ float m_roughnessFactor = 0.0f;
+
+ // material texture usage flags
+ RayTracingSubMeshTextureFlags m_textureFlags = RayTracingSubMeshTextureFlags::None;
+
+ // material textures
+ RHI::Ptr m_baseColorImageView;
+ RHI::Ptr m_normalImageView;
+ RHI::Ptr m_metallicImageView;
+ RHI::Ptr m_roughnessImageView;
};
using SubMeshVector = AZStd::vector;
@@ -98,6 +154,9 @@ namespace AZ
//! Retrieves the RayTracingSceneSrg
Data::Instance GetRayTracingSceneSrg() const { return m_rayTracingSceneSrg; }
+ //! Retrieves the RayTracingMaterialSrg
+ Data::Instance GetRayTracingMaterialSrg() const { return m_rayTracingMaterialSrg; }
+
//! Retrieves the RayTracingTlas
const RHI::Ptr& GetTlas() const { return m_tlas; }
RHI::Ptr& GetTlas() { return m_tlas; }
@@ -118,14 +177,20 @@ namespace AZ
//! Retrieves the GPU buffer containing information for all ray tracing meshes.
const Data::Instance GetMeshInfoBuffer() const { return m_meshInfoBuffer; }
- //! Updates the RayTracingSceneSrg, called after the TLAS is allocated in the RayTracingAccelerationStructurePass
- void UpdateRayTracingSceneSrg();
+ //! Retrieves the GPU buffer containing information for all ray tracing materials.
+ const Data::Instance GetMaterialInfoBuffer() const { return m_materialInfoBuffer; }
+
+ //! Updates the RayTracingSceneSrg and RayTracingMaterialSrg, called after the TLAS is allocated in the RayTracingAccelerationStructurePass
+ void UpdateRayTracingSrgs();
private:
AZ_DISABLE_COPY_MOVE(RayTracingFeatureProcessor);
void UpdateMeshInfoBuffer();
+ void UpdateMaterialInfoBuffer();
+ void UpdateRayTracingSceneSrg();
+ void UpdateRayTracingMaterialSrg();
// flag indicating if RayTracing is enabled, currently based on device support
bool m_rayTracingEnabled = false;
@@ -143,6 +208,9 @@ namespace AZ
// ray tracing scene Srg
Data::Instance m_rayTracingSceneSrg;
+ // ray tracing material Srg
+ Data::Instance m_rayTracingMaterialSrg;
+
// current revision number of ray tracing data
uint32_t m_revision = 0;
@@ -158,18 +226,43 @@ namespace AZ
// structure for data in the m_meshInfoBuffer, shaders that use the buffer must match this type
struct MeshInfo
{
- uint32_t m_indexOffset;
- uint32_t m_positionOffset;
- uint32_t m_normalOffset;
+ uint32_t m_indexOffset;
+ uint32_t m_positionOffset;
+ uint32_t m_normalOffset;
+ uint32_t m_tangentOffset;
+ uint32_t m_bitangentOffset;
+ uint32_t m_uvOffset;
+ float m_padding0[2];
+
AZStd::array m_irradianceColor; // float4
AZStd::array m_worldInvTranspose; // float3x3
+ float m_padding1;
+
+ RayTracingSubMeshBufferFlags m_bufferFlags = RayTracingSubMeshBufferFlags::None;
+ uint32_t m_bufferStartIndex = 0;
};
// buffer containing a MeshInfo for each sub-mesh
Data::Instance m_meshInfoBuffer;
- // flag indicating we need to update the mesh info GPU buffer
+ // structure for data in the m_materialInfoBuffer, shaders that use the buffer must match this type
+ struct MaterialInfo
+ {
+ AZStd::array m_baseColor; // float4
+ float m_metallicFactor = 0.0f;
+ float m_roughnessFactor = 0.0f;
+ RayTracingSubMeshTextureFlags m_textureFlags = RayTracingSubMeshTextureFlags::None;
+ uint32_t m_textureStartIndex = 0;
+ };
+
+ // buffer containing a MaterialInfo for each sub-mesh
+ Data::Instance m_materialInfoBuffer;
+
+ // flag indicating we need to update the meshInfo buffer
bool m_meshInfoBufferNeedsUpdate = false;
+
+ // flag indicating we need to update the materialInfo buffer
+ bool m_materialInfoBufferNeedsUpdate = false;
};
}
}
diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp
new file mode 100644
index 0000000000..988870cc0e
--- /dev/null
+++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.cpp
@@ -0,0 +1,362 @@
+/*
+* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+* its licensors.
+*
+* For complete copyright and license terms please see the LICENSE at the root of this
+* distribution (the "License"). All use of this software is governed by the License,
+* or, if provided, by the license below or the license accompanying this file. Do not
+* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace AZ
+{
+ namespace Render
+ {
+ RPI::Ptr RayTracingPass::Create(const RPI::PassDescriptor& descriptor)
+ {
+ RPI::Ptr pass = aznew RayTracingPass(descriptor);
+ return pass;
+ }
+
+ RayTracingPass::RayTracingPass(const RPI::PassDescriptor& descriptor)
+ : RenderPass(descriptor)
+ , m_passDescriptor(descriptor)
+ {
+ RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice();
+ if (device->GetFeatures().m_rayTracing == false)
+ {
+ // raytracing is not supported on this platform
+ SetEnabled(false);
+ return;
+ }
+
+ Init();
+ }
+
+ RayTracingPass::~RayTracingPass()
+ {
+ RPI::ShaderReloadNotificationBus::MultiHandler::BusDisconnect();
+ }
+
+ void RayTracingPass::Init()
+ {
+ RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice();
+
+ m_passData = RPI::PassUtils::GetPassData(m_passDescriptor);
+ if (m_passData == nullptr)
+ {
+ AZ_Error("PassSystem", false, "RayTracingPass [%s]: Invalid RayTracingPassData", GetPathName().GetCStr());
+ return;
+ }
+
+ // ray generation shader
+ m_rayGenerationShader = LoadShader(m_passData->m_rayGenerationShaderAssetReference);
+ if (m_rayGenerationShader == nullptr)
+ {
+ AZ_Error("PassSystem", false, "RayTracingPass [%s]: Failed to load RayGeneration shader [%s]", GetPathName().GetCStr(), m_passData->m_rayGenerationShaderAssetReference.m_filePath.data());
+ return;
+ }
+
+ auto shaderVariant = m_rayGenerationShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
+ RHI::PipelineStateDescriptorForRayTracing rayGenerationShaderDescriptor;
+ shaderVariant.ConfigurePipelineState(rayGenerationShaderDescriptor);
+
+ // closest hit shader
+ m_closestHitShader = LoadShader(m_passData->m_closestHitShaderAssetReference);
+ if (m_closestHitShader == nullptr)
+ {
+ AZ_Error("PassSystem", false, "RayTracingPass [%s]: Failed to load ClosestHit shader [%s]", GetPathName().GetCStr(), m_passData->m_closestHitShaderAssetReference.m_filePath.data());
+ return;
+ }
+
+ shaderVariant = m_closestHitShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
+ RHI::PipelineStateDescriptorForRayTracing closestHitShaderDescriptor;
+ shaderVariant.ConfigurePipelineState(closestHitShaderDescriptor);
+
+ // miss shader
+ m_missShader = LoadShader(m_passData->m_missShaderAssetReference);
+ if (m_missShader == nullptr)
+ {
+ AZ_Error("PassSystem", false, "RayTracingPass [%s]: Failed to load Miss shader [%s]", GetPathName().GetCStr(), m_passData->m_missShaderAssetReference.m_filePath.data());
+ return;
+ }
+
+ shaderVariant = m_missShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
+ RHI::PipelineStateDescriptorForRayTracing missShaderDescriptor;
+ shaderVariant.ConfigurePipelineState(missShaderDescriptor);
+
+ // retrieve global pipeline state
+ m_globalPipelineState = m_rayGenerationShader->AcquirePipelineState(rayGenerationShaderDescriptor);
+ AZ_Assert(m_globalPipelineState, "Failed to acquire ray tracing global pipeline state");
+
+ // create global srg
+ Data::Asset globalSrgAsset = m_rayGenerationShader->FindShaderResourceGroupAsset(RayTracingGlobalSrgBindingSlot);
+ AZ_Error("PassSystem", globalSrgAsset.GetId().IsValid(), "RayTracingPass [%s] Failed to find RayTracingGlobalSrg asset", GetPathName().GetCStr());
+ AZ_Error("PassSystem", globalSrgAsset.IsReady(), "RayTracingPass [%s] asset is not loaded for shader", GetPathName().GetCStr());
+
+ m_shaderResourceGroup = RPI::ShaderResourceGroup::Create(globalSrgAsset);
+ AZ_Assert(m_shaderResourceGroup, "RayTracingPass [%s]: Failed to create RayTracingGlobalSrg", GetPathName().GetCStr());
+ RPI::PassUtils::BindDataMappingsToSrg(m_passDescriptor, m_shaderResourceGroup.get());
+
+ // check to see if the shader requires the View and RayTracingMaterial Srgs
+ Data::Asset viewSrgAsset = m_rayGenerationShader->FindShaderResourceGroupAsset(RPI::SrgBindingSlot::View);
+ m_requiresViewSrg = viewSrgAsset.GetId().IsValid();
+
+ Data::Asset rayTracingMaterialSrgAsset = m_rayGenerationShader->FindShaderResourceGroupAsset(RayTracingMaterialSrgBindingSlot);
+ m_requiresRayTracingMaterialSrg = rayTracingMaterialSrgAsset.GetId().IsValid();
+
+ // build the ray tracing pipeline state descriptor
+ RHI::RayTracingPipelineStateDescriptor descriptor;
+ descriptor.Build()
+ ->PipelineState(m_globalPipelineState.get())
+ ->MaxPayloadSize(m_passData->m_maxPayloadSize)
+ ->MaxAttributeSize(m_passData->m_maxAttributeSize)
+ ->MaxRecursionDepth(m_passData->m_maxRecursionDepth)
+ ->ShaderLibrary(rayGenerationShaderDescriptor)
+ ->RayGenerationShaderName(AZ::Name(m_passData->m_rayGenerationShaderName.c_str()))
+ ->ShaderLibrary(missShaderDescriptor)
+ ->MissShaderName(AZ::Name(m_passData->m_missShaderName.c_str()))
+ ->ShaderLibrary(closestHitShaderDescriptor)
+ ->ClosestHitShaderName(AZ::Name(m_passData->m_closestHitShaderName.c_str()))
+ ->HitGroup(AZ::Name("HitGroup"))
+ ->ClosestHitShaderName(AZ::Name(m_passData->m_closestHitShaderName.c_str()));
+
+ // create the ray tracing pipeline state object
+ m_rayTracingPipelineState = RHI::Factory::Get().CreateRayTracingPipelineState();
+ m_rayTracingPipelineState->Init(*device.get(), &descriptor);
+
+ // make sure the shader table rebuilds if we're hotreloading
+ m_rayTracingRevision = 0;
+
+ RPI::ShaderReloadNotificationBus::MultiHandler::BusDisconnect();
+ RPI::ShaderReloadNotificationBus::MultiHandler::BusConnect(m_passData->m_rayGenerationShaderAssetReference.m_assetId);
+ RPI::ShaderReloadNotificationBus::MultiHandler::BusConnect(m_passData->m_closestHitShaderAssetReference.m_assetId);
+ RPI::ShaderReloadNotificationBus::MultiHandler::BusConnect(m_passData->m_missShaderAssetReference.m_assetId);
+ }
+
+ Data::Instance RayTracingPass::LoadShader(const RPI::AssetReference& shaderAssetReference)
+ {
+ Data::Asset shaderAsset;
+ if (shaderAssetReference.m_assetId.IsValid())
+ {
+ shaderAsset = RPI::FindShaderAsset(shaderAssetReference.m_assetId, shaderAssetReference.m_filePath);
+ }
+
+ if (!shaderAsset.GetId().IsValid())
+ {
+ AZ_Error("PassSystem", false, "RayTracingPass [%s]: Failed to load shader asset [%s]", GetPathName().GetCStr(), shaderAssetReference.m_filePath.data());
+ return nullptr;
+ }
+
+ return RPI::Shader::FindOrCreate(shaderAsset);
+ }
+
+ void RayTracingPass::FrameBeginInternal(FramePrepareParams params)
+ {
+ RPI::Scene* scene = m_pipeline->GetScene();
+ RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor();
+ if (!rayTracingFeatureProcessor)
+ {
+ return;
+ }
+
+ if (!m_rayTracingShaderTable)
+ {
+ RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice();
+ RHI::RayTracingBufferPools& rayTracingBufferPools = rayTracingFeatureProcessor->GetBufferPools();
+
+ m_rayTracingShaderTable = RHI::Factory::Get().CreateRayTracingShaderTable();
+ m_rayTracingShaderTable->Init(*device.get(), rayTracingBufferPools);
+ }
+
+ RPI::RenderPass::FrameBeginInternal(params);
+ }
+
+ void RayTracingPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
+ {
+ RPI::Scene* scene = m_pipeline->GetScene();
+ RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor();
+ AZ_Assert(rayTracingFeatureProcessor, "RayTracingPass requires the RayTracingFeatureProcessor");
+
+ RPI::RenderPass::SetupFrameGraphDependencies(frameGraph);
+ frameGraph.SetEstimatedItemCount(1);
+
+ // TLAS
+ {
+ const RHI::Ptr& rayTracingTlasBuffer = rayTracingFeatureProcessor->GetTlas()->GetTlasBuffer();
+ if (rayTracingTlasBuffer)
+ {
+ AZ::RHI::AttachmentId tlasAttachmentId = rayTracingFeatureProcessor->GetTlasAttachmentId();
+ if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(tlasAttachmentId) == false)
+ {
+ [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(tlasAttachmentId, rayTracingTlasBuffer);
+ AZ_Assert(result == RHI::ResultCode::Success, "Failed to import ray tracing TLAS buffer with error %d", result);
+ }
+
+ uint32_t tlasBufferByteCount = aznumeric_cast(rayTracingFeatureProcessor->GetTlas()->GetTlasBuffer()->GetDescriptor().m_byteCount);
+ RHI::BufferViewDescriptor tlasBufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tlasBufferByteCount);
+
+ RHI::BufferScopeAttachmentDescriptor desc;
+ desc.m_attachmentId = tlasAttachmentId;
+ desc.m_bufferViewDescriptor = tlasBufferViewDescriptor;
+ desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
+
+ frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite);
+ }
+ }
+ }
+
+ void RayTracingPass::CompileResources(const RHI::FrameGraphCompileContext& context)
+ {
+ RPI::Scene* scene = m_pipeline->GetScene();
+ RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor();
+ AZ_Assert(rayTracingFeatureProcessor, "RayTracingPass requires the RayTracingFeatureProcessor");
+
+ if (m_shaderResourceGroup != nullptr)
+ {
+ BindPassSrg(context, m_shaderResourceGroup);
+ m_shaderResourceGroup->Compile();
+ }
+
+ uint32_t rayTracingRevision = rayTracingFeatureProcessor->GetRevision();
+ if (m_rayTracingRevision != rayTracingRevision)
+ {
+ // scene changed, need to rebuild the shader table
+ m_rayTracingRevision = rayTracingRevision;
+
+ AZStd::shared_ptr descriptor = AZStd::make_shared();
+
+ if (rayTracingFeatureProcessor->GetSubMeshCount())
+ {
+ // build the ray tracing shader table descriptor
+ RHI::RayTracingShaderTableDescriptor* descriptorBuild = descriptor->Build(AZ::Name("RayTracingShaderTable"), m_rayTracingPipelineState)
+ ->RayGenerationRecord(AZ::Name(m_passData->m_rayGenerationShaderName.c_str()))
+ ->MissRecord(AZ::Name(m_passData->m_missShaderName.c_str()));
+
+ // add a hit group for each mesh to the shader table
+ for (uint32_t i = 0; i < rayTracingFeatureProcessor->GetSubMeshCount(); ++i)
+ {
+ descriptorBuild->HitGroupRecord(AZ::Name("HitGroup"));
+ }
+ }
+
+ m_rayTracingShaderTable->Build(descriptor);
+ }
+ }
+
+ void RayTracingPass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
+ {
+ RPI::Scene* scene = m_pipeline->GetScene();
+ RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor();
+ AZ_Assert(rayTracingFeatureProcessor, "RayTracingPass requires the RayTracingFeatureProcessor");
+
+ if (!rayTracingFeatureProcessor ||
+ !rayTracingFeatureProcessor->GetTlas()->GetTlasBuffer() ||
+ !rayTracingFeatureProcessor->GetSubMeshCount() ||
+ !m_rayTracingShaderTable)
+ {
+ return;
+ }
+
+ RHI::DispatchRaysItem dispatchRaysItem;
+
+ // calculate thread counts if this is a full screen raytracing pass
+ if (m_passData->m_makeFullscreenPass)
+ {
+ RPI::PassAttachment* outputAttachment = nullptr;
+
+ if (GetOutputCount() > 0)
+ {
+ outputAttachment = GetOutputBinding(0).m_attachment.get();
+ }
+ else if (GetInputOutputCount() > 0)
+ {
+ outputAttachment = GetInputOutputBinding(0).m_attachment.get();
+ }
+
+ AZ_Assert(outputAttachment != nullptr, "[RayTracingPass '%s']: A fullscreen RayTracing pass must have a valid output or input/output.", GetPathName().GetCStr());
+ AZ_Assert(outputAttachment->GetAttachmentType() == RHI::AttachmentType::Image, "[RayTracingPass '%s']: The output of a fullscreen RayTracing pass must be an image.", GetPathName().GetCStr());
+
+ RHI::Size imageSize = outputAttachment->m_descriptor.m_image.m_size;
+
+ dispatchRaysItem.m_width = imageSize.m_width;
+ dispatchRaysItem.m_height = imageSize.m_height;
+ dispatchRaysItem.m_depth = imageSize.m_depth;
+ }
+ else
+ {
+ dispatchRaysItem.m_width = m_passData->m_threadCountX;
+ dispatchRaysItem.m_height = m_passData->m_threadCountY;
+ dispatchRaysItem.m_depth = m_passData->m_threadCountZ;
+ }
+
+ // bind RayTracingGlobal, RayTracingScene, and View Srgs
+ // [GFX TODO][ATOM-15610] Add RenderPass::SetSrgsForRayTracingDispatch
+ AZStd::vector shaderResourceGroups =
+ {
+ m_shaderResourceGroup->GetRHIShaderResourceGroup(),
+ rayTracingFeatureProcessor->GetRayTracingSceneSrg()->GetRHIShaderResourceGroup()
+ };
+
+ if (m_requiresViewSrg)
+ {
+ const AZStd::vector& views = m_pipeline->GetViews(m_passData->m_pipelineViewTag);
+ if (views.size() > 0)
+ {
+ shaderResourceGroups.push_back(views[0]->GetRHIShaderResourceGroup());
+ }
+ }
+
+ if (m_requiresRayTracingMaterialSrg)
+ {
+ shaderResourceGroups.push_back(rayTracingFeatureProcessor->GetRayTracingMaterialSrg()->GetRHIShaderResourceGroup());
+ }
+
+ dispatchRaysItem.m_shaderResourceGroupCount = aznumeric_cast(shaderResourceGroups.size());
+ dispatchRaysItem.m_shaderResourceGroups = shaderResourceGroups.data();
+ dispatchRaysItem.m_rayTracingPipelineState = m_rayTracingPipelineState.get();
+ dispatchRaysItem.m_rayTracingShaderTable = m_rayTracingShaderTable.get();
+ dispatchRaysItem.m_globalPipelineState = m_globalPipelineState.get();
+
+ // submit the DispatchRays item
+ context.GetCommandList()->Submit(dispatchRaysItem);
+ }
+
+ void RayTracingPass::OnShaderReinitialized([[maybe_unused]] const RPI::Shader& shader)
+ {
+ Init();
+ }
+
+ void RayTracingPass::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset& shaderAsset)
+ {
+ Init();
+ }
+
+ void RayTracingPass::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId)
+ {
+ Init();
+ }
+ } // namespace RPI
+} // namespace AZ
diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h
new file mode 100644
index 0000000000..6ad082e894
--- /dev/null
+++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPass.h
@@ -0,0 +1,82 @@
+/*
+* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+* its licensors.
+*
+* For complete copyright and license terms please see the LICENSE at the root of this
+* distribution (the "License"). All use of this software is governed by the License,
+* or, if provided, by the license below or the license accompanying this file. Do not
+* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*
+*/
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace AZ
+{
+ namespace Render
+ {
+ struct RayTracingPassData;
+
+ //! This pass executes a raytracing shader as specified in the PassData.
+ class RayTracingPass
+ : public RPI::RenderPass
+ , private RPI::ShaderReloadNotificationBus::MultiHandler
+ {
+ AZ_RPI_PASS(RayTracingPass);
+
+ public:
+ AZ_RTTI(RayTracingPass, "{7A68A36E-956A-4258-93FE-38686042C4D9}", RPI::RenderPass);
+ AZ_CLASS_ALLOCATOR(RayTracingPass, SystemAllocator, 0);
+ virtual ~RayTracingPass();
+
+ //! Creates a RayTracingPass
+ static RPI::Ptr Create(const RPI::PassDescriptor& descriptor);
+
+ protected:
+ RayTracingPass(const RPI::PassDescriptor& descriptor);
+
+ // Pass overrides
+ void FrameBeginInternal(FramePrepareParams params) override;
+
+ // Scope producer functions
+ void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
+ void CompileResources(const RHI::FrameGraphCompileContext& context) override;
+ void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
+
+ // ShaderReloadNotificationBus::Handler overrides
+ void OnShaderReinitialized(const RPI::Shader& shader) override;
+ void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override;
+ void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
+
+ // load the raytracing shaders and setup pipeline states
+ void Init();
+
+ // helper for loading a shader from a shader asset reference
+ Data::Instance LoadShader(const RPI::AssetReference& shaderAssetReference);
+
+ // pass data
+ RPI::PassDescriptor m_passDescriptor;
+ const RayTracingPassData* m_passData = nullptr;
+
+ // revision number of the ray tracing TLAS when the shader table was built
+ uint32_t m_rayTracingRevision = 0;
+
+ // raytracing shaders, pipeline states, and shader table
+ Data::Instance m_rayGenerationShader;
+ Data::Instance m_missShader;
+ Data::Instance m_closestHitShader;
+ RHI::Ptr m_rayTracingPipelineState;
+ RHI::ConstPtr m_globalPipelineState;
+ RHI::Ptr m_rayTracingShaderTable;
+ bool m_requiresViewSrg = false;
+ bool m_requiresRayTracingMaterialSrg = false;
+ };
+ } // namespace RPI
+} // namespace AZ
diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPassData.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPassData.h
new file mode 100644
index 0000000000..bc15a8372c
--- /dev/null
+++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingPassData.h
@@ -0,0 +1,73 @@
+/*
+* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
+* its licensors.
+*
+* For complete copyright and license terms please see the LICENSE at the root of this
+* distribution (the "License"). All use of this software is governed by the License,
+* or, if provided, by the license below or the license accompanying this file. Do not
+* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*
+*/
+#pragma once
+
+#include
+#include
+
+namespace AZ
+{
+ namespace Render
+ {
+ //! Custom data for the RayTracingPass, specified in the PassRequest.
+ struct RayTracingPassData
+ : public RPI::RenderPassData
+ {
+ AZ_RTTI(RayTracingPassData, "{26C2E2FD-D30A-4142-82A3-0167BC94B3EE}", RPI::RenderPassData);
+ AZ_CLASS_ALLOCATOR(RayTracingPassData, SystemAllocator, 0);
+
+ RayTracingPassData() = default;
+ virtual ~RayTracingPassData() = default;
+
+ static void Reflect(ReflectContext* context)
+ {
+ if (auto* serializeContext = azrtti_cast(context))
+ {
+ serializeContext->Class()
+ ->Version(1)
+ ->Field("RayGenerationShaderAsset", &RayTracingPassData::m_rayGenerationShaderAssetReference)
+ ->Field("RayGenerationShaderName", &RayTracingPassData::m_rayGenerationShaderName)
+ ->Field("ClosestHitShaderAsset", &RayTracingPassData::m_closestHitShaderAssetReference)
+ ->Field("ClosestHitShaderName", &RayTracingPassData::m_closestHitShaderName)
+ ->Field("MissShaderAsset", &RayTracingPassData::m_missShaderAssetReference)
+ ->Field("MissShaderName", &RayTracingPassData::m_missShaderName)
+ ->Field("MaxPayloadSize", &RayTracingPassData::m_maxPayloadSize)
+ ->Field("MaxAttributeSize", &RayTracingPassData::m_maxAttributeSize)
+ ->Field("MaxRecursionDepth", &RayTracingPassData::m_maxRecursionDepth)
+ ->Field("Thread Count X", &RayTracingPassData::m_threadCountX)
+ ->Field("Thread Count Y", &RayTracingPassData::m_threadCountY)
+ ->Field("Thread Count Z", &RayTracingPassData::m_threadCountZ)
+ ->Field("Make Fullscreen Pass", &RayTracingPassData::m_makeFullscreenPass)
+ ;
+ }
+ }
+
+ RPI::AssetReference m_rayGenerationShaderAssetReference;
+ AZStd::string m_rayGenerationShaderName;
+ RPI::AssetReference m_closestHitShaderAssetReference;
+ AZStd::string m_closestHitShaderName;
+ RPI::AssetReference m_missShaderAssetReference;
+ AZStd::string m_missShaderName;
+
+ uint32_t m_maxPayloadSize = 64;
+ uint32_t m_maxAttributeSize = 32;
+ uint32_t m_maxRecursionDepth = 1;
+
+ uint32_t m_threadCountX = 1;
+ uint32_t m_threadCountY = 1;
+ uint32_t m_threadCountZ = 1;
+
+ bool m_makeFullscreenPass = false;
+ };
+ } // namespace RPI
+} // namespace AZ
+
diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake
index 4f98046adb..76b71e5fae 100644
--- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake
+++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake
@@ -250,6 +250,9 @@ set(FILES
Source/RayTracing/RayTracingFeatureProcessor.cpp
Source/RayTracing/RayTracingAccelerationStructurePass.cpp
Source/RayTracing/RayTracingAccelerationStructurePass.h
+ Source/RayTracing/RayTracingPass.cpp
+ Source/RayTracing/RayTracingPass.h
+ Source/RayTracing/RayTracingPassData.h
Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp
Source/ReflectionProbe/ReflectionProbe.cpp
Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h
index 9baf80bae0..c8b406f94b 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Edit/Material/MaterialSourceData.h
@@ -32,7 +32,7 @@ namespace AZ
//! In the source data, properties and UV names are loaded separately.
//! However, treating UV names as a special property group can greatly simplify the editor code.
//! See MaterialInspector::AddUvNamesGroup() for more details.
- static constexpr const char UvGroupName[] = "UvNames";
+ static constexpr const char UvGroupName[] = "uvSets";
class MaterialAsset;
diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Base.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Base.h
index c376112290..52b75c4157 100644
--- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Base.h
+++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Base.h
@@ -59,7 +59,10 @@ namespace AZ
static constexpr uint32_t Draw = 0;
static constexpr uint32_t Object = 1;
static constexpr uint32_t Material = 2;
+ static constexpr uint32_t SubPass = 3;
static constexpr uint32_t Pass = 4;
+ static constexpr uint32_t View = 5;
+ static constexpr uint32_t Scene = 6;
};
}
}
diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp
index 6fb3edfa22..896d9f8043 100644
--- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp
+++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -24,6 +25,11 @@
namespace AtomToolsFramework
{
+ AZ_CVAR(
+ AZ::Color, ed_cameraSystemOrbitPointColor, AZ::Color::CreateFromRgba(255, 255, 255, 255), nullptr, AZ::ConsoleFunctorFlags::Null,
+ "");
+ AZ_CVAR(float, ed_cameraSystemOrbitPointSize, 0.5f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
+
// debug
void DrawPreviewAxis(AzFramework::DebugDisplayRequests& display, const AZ::Transform& transform, const float axisLength)
{
@@ -73,7 +79,8 @@ namespace AtomToolsFramework
if (auto viewportContext = RetrieveViewportContext(GetViewportId()))
{
- auto handleCameraChange = [this, viewportContext](const AZ::Matrix4x4&) {
+ auto handleCameraChange = [this, viewportContext](const AZ::Matrix4x4&)
+ {
if (!m_updatingTransform)
{
UpdateCameraFromTransform(m_targetCamera, viewportContext->GetCameraTransform());
@@ -137,7 +144,10 @@ namespace AtomToolsFramework
}
else if (m_cameraMode == CameraMode::Animation)
{
- const auto smootherStepFn = [](const float t) { return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f); };
+ const auto smootherStepFn = [](const float t)
+ {
+ return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f);
+ };
const float transitionT = smootherStepFn(m_animationT);
const AZ::Transform current = AZ::Transform::CreateFromQuaternionAndTranslation(
@@ -169,8 +179,9 @@ namespace AtomToolsFramework
{
if (const float alpha = AZStd::min(-m_camera.m_lookDist / 5.0f, 1.0f); alpha > AZ::Constants::FloatEpsilon)
{
- debugDisplay.SetColor(1.0f, 1.0f, 1.0f, alpha);
- debugDisplay.DrawWireSphere(m_camera.m_lookAt, 0.5f);
+ const AZ::Color orbitPointColor = ed_cameraSystemOrbitPointColor;
+ debugDisplay.SetColor(orbitPointColor.GetR(), orbitPointColor.GetG(), orbitPointColor.GetB(), alpha);
+ debugDisplay.DrawWireSphere(m_camera.m_lookAt, ed_cameraSystemOrbitPointSize);
}
}
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h
index c71d500d8c..7f36d3fabc 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Include/Atom/Document/MaterialDocumentRequestBus.h
@@ -33,7 +33,7 @@ namespace AZ
namespace MaterialEditor
{
//! UVs are processed in a property group but will be handled differently.
- static constexpr const char UvGroupName[] = "UvNames";
+ static constexpr const char UvGroupName[] = "uvSets";
class MaterialDocumentRequests
: public AZ::EBusTraits
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp
index 301fd69025..2242d3af1b 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocument.cpp
@@ -819,10 +819,10 @@ namespace MaterialEditor
// is implemented.
AtomToolsFramework::DynamicPropertyConfig propertyConfig;
propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Asset;
- propertyConfig.m_id = "details.materialType";
+ propertyConfig.m_id = "overview.materialType";
propertyConfig.m_nameId = "materialType";
propertyConfig.m_displayName = "Material Type";
- propertyConfig.m_groupName = "Details";
+ propertyConfig.m_groupName = "Overview";
propertyConfig.m_description = "The material type defines the layout, properties, default values, shader connections, and other "
"data needed to create and edit a derived material.";
propertyConfig.m_defaultValue = AZStd::any(materialTypeAsset);
@@ -834,10 +834,10 @@ namespace MaterialEditor
propertyConfig = {};
propertyConfig.m_dataType = AtomToolsFramework::DynamicPropertyType::Asset;
- propertyConfig.m_id = "details.parentMaterial";
+ propertyConfig.m_id = "overview.parentMaterial";
propertyConfig.m_nameId = "parentMaterial";
propertyConfig.m_displayName = "Parent Material";
- propertyConfig.m_groupName = "Details";
+ propertyConfig.m_groupName = "Overview";
propertyConfig.m_description =
"The parent material provides an initial configuration whose properties are inherited and overriden by a derived material.";
propertyConfig.m_defaultValue = AZStd::any(parentMaterialAsset);
@@ -860,7 +860,7 @@ namespace MaterialEditor
propertyConfig.m_id = MaterialPropertyId(UvGroupName, shaderInput).GetCStr();
propertyConfig.m_nameId = shaderInput;
propertyConfig.m_displayName = shaderInput;
- propertyConfig.m_groupName = "UV Names";
+ propertyConfig.m_groupName = "UV Sets";
propertyConfig.m_description = shaderInput;
propertyConfig.m_defaultValue = uvName;
propertyConfig.m_originalValue = uvName;
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp
index 706d365027..560c82be9b 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp
@@ -79,8 +79,8 @@ namespace MaterialEditor
if (!m_documentId.IsNull() && isOpen)
{
- // Create the top group for displaying details about the material
- AddDetailsGroup();
+ // Create the top group for displaying overview info about the material
+ AddOverviewGroup();
// Create groups for displaying editable UV names
AddUvNamesGroup();
// Create groups for displaying editable properties
@@ -105,25 +105,25 @@ namespace MaterialEditor
return property && AtomToolsFramework::ArePropertyValuesEqual(property->GetValue(), property->GetConfig().m_parentValue);
}
- void MaterialInspector::AddDetailsGroup()
+ void MaterialInspector::AddOverviewGroup()
{
const AZ::RPI::MaterialTypeSourceData* materialTypeSourceData = nullptr;
MaterialDocumentRequestBus::EventResult(
materialTypeSourceData, m_documentId, &MaterialDocumentRequestBus::Events::GetMaterialTypeSourceData);
- const AZStd::string groupNameId = "details";
- const AZStd::string groupDisplayName = "Details";
+ const AZStd::string groupNameId = "overview";
+ const AZStd::string groupDisplayName = "Overview";
const AZStd::string groupDescription = materialTypeSourceData->m_description;
auto& group = m_groups[groupNameId];
AtomToolsFramework::DynamicProperty property;
MaterialDocumentRequestBus::EventResult(
- property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("details.materialType"));
+ property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("overview.materialType"));
group.m_properties.push_back(property);
property = {};
MaterialDocumentRequestBus::EventResult(
- property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("details.parentMaterial"));
+ property, m_documentId, &MaterialDocumentRequestBus::Events::GetProperty, AZ::Name("overview.parentMaterial"));
group.m_properties.push_back(property);
// Passing in same group as main and comparison instance to enable custom value comparison for highlighting modified properties
@@ -139,7 +139,7 @@ namespace MaterialEditor
MaterialDocumentRequestBus::EventResult(materialAsset, m_documentId, &MaterialDocumentRequestBus::Events::GetAsset);
const AZStd::string groupNameId = UvGroupName;
- const AZStd::string groupDisplayName = "UV Names";
+ const AZStd::string groupDisplayName = "UV Sets";
const AZStd::string groupDescription = "UV set names in this material, which can be renamed to match those in the model.";
auto& group = m_groups[groupNameId];
diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h
index 4080430ff5..65d095f42f 100644
--- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h
+++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.h
@@ -52,7 +52,7 @@ namespace MaterialEditor
bool CompareInstanceNodeProperties(
const AzToolsFramework::InstanceDataNode* source, const AzToolsFramework::InstanceDataNode* target) const;
- void AddDetailsGroup();
+ void AddOverviewGroup();
void AddUvNamesGroup();
void AddPropertiesGroup();
diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp
index 3192900ca4..229606a238 100644
--- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp
+++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp
@@ -184,7 +184,7 @@ namespace AZ
void MaterialPropertyInspector::AddUvNamesGroup()
{
const AZStd::string groupNameId = AZ::RPI::UvGroupName;
- const AZStd::string groupDisplayName = "UV Names";
+ const AZStd::string groupDisplayName = "UV Sets";
const AZStd::string groupDescription = "UV set names in this material, which can be renamed to match those in the model.";
auto& group = m_groups[groupNameId];
diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja
index 8cf1eeeb58..79fbb4a99e 100644
--- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja
+++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Header.jinja
@@ -383,6 +383,8 @@ namespace {{ Component.attrib['Namespace'] }}
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Client', true)|indent(8) -}}
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Autonomous', false)|indent(8) -}}
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Autonomous', true)|indent(8) -}}
+ {{ DeclareNetworkPropertyAccessors(Component, 'Autonomous', 'Authority', false)|indent(8) -}}
+ {{ DeclareNetworkPropertyAccessors(Component, 'Autonomous', 'Authority', true)|indent(8) -}}
{{ DeclareArchetypePropertyGetters(Component)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', true)|indent(8) -}}
@@ -456,7 +458,6 @@ namespace {{ Component.attrib['Namespace'] }}
{% endif %}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Server', false)|indent(8) -}}
- {{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Autonomous', false)|indent(8) -}}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', false)|indent(8) -}}
{{ DeclareArchetypePropertyGetters(Component)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) -}}
@@ -481,8 +482,6 @@ namespace {{ Component.attrib['Namespace'] }}
//! @}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Server', true)|indent(8) -}}
- {{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Autonomous', true)|indent(8) -}}
- {{ DeclareNetworkPropertyGetters(Component, 'Autonomous', 'Authority', true)|indent(8) -}}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', true)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', true)|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Authority', 'Client', false)|indent(8) -}}
diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja
index 0feff5c07c..5cfd0bfc4d 100644
--- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja
+++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja
@@ -796,12 +796,27 @@ enum class NetworkProperties
AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }} failed. Entity '%s' (id: %s) is missing {{ ClassName }}, be sure to add {{ ClassName }} to this entity.", entity->GetName().c_str(), id.ToString().c_str())
return {{ Property.attrib['Type'] }}();
}
+{% if (ReplicateTo == 'Autonomous') or (ReplicateFrom == 'Autonomous' and ReplicateTo == 'Authority') %}
+ // {{ UpperFirst(Property.attrib['Name']) }} is only sent and received between contoller objects (ie Authority, Autonomous); we must go through the controller in order to get this property
+ {{ ClassName }}Controller* controller = static_cast<{{ ClassName }}Controller*>(networkComponent->GetController());
+ if (!controller)
+ {
+ AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }} method failed. Entity '%s' (id: %s) {{ ClassName }} is missing the network controller. This property is replicated to autonomous network entities, because this entity doesn't have a controller, it must not be automonous. Please check your network context before attempting to get {{ UpperFirst(Property.attrib['Name']) }}.", entity->GetName().c_str(), id.ToString().c_str())
+ return {{ Property.attrib['Type'] }}();
+ }
+{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
+ return controller->Get{{ UpperFirst(Property.attrib['Name']) }}(index);
+{% else %}
+ return controller->Get{{ UpperFirst(Property.attrib['Name']) }}();
+{% endif %}
+{% else %}
{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
return networkComponent->Get{{ UpperFirst(Property.attrib['Name']) }}(index);
{% else %}
return networkComponent->Get{{ UpperFirst(Property.attrib['Name']) }}();
{% endif %}
+{% endif %}
})
{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
->Method("Set{{ UpperFirst(Property.attrib['Name']) }}", [](AZ::EntityId id, int32_t index, const {{ Property.attrib['Type'] }}& value) -> void
@@ -1480,12 +1495,8 @@ namespace {{ Component.attrib['Namespace'] }}
}
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Server', false, ComponentBaseName)|indent(4) -}}
-{{ DefineNetworkPropertyGets(Component, 'Authority', 'Autonomous', false, ComponentBaseName)|indent(4) -}}
-{{ DefineNetworkPropertyGets(Component, 'Autonomous', 'Authority', false, ComponentBaseName)|indent(4) -}}
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Client', false, ComponentBaseName)|indent(4) -}}
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Server', true, ComponentBaseName)|indent(4) -}}
-{{ DefineNetworkPropertyGets(Component, 'Authority', 'Autonomous', true, ComponentBaseName)|indent(4) -}}
-{{ DefineNetworkPropertyGets(Component, 'Autonomous', 'Authority', true, ComponentBaseName)|indent(4) -}}
{{ DefineNetworkPropertyGets(Component, 'Authority', 'Client', true, ComponentBaseName)|indent(4) }}
{{ DefineArchetypePropertyGets(Component, ClassType, ComponentBaseName)|indent(4) -}}
{{ DefineRpcInvocations(Component, ComponentBaseName, 'Server', 'Authority', false)|indent(4) -}}
diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
index ef8627fe54..0818f605df 100644
--- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
+++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp
@@ -438,19 +438,16 @@ namespace Multiplayer
m_connAcquiredEvent.Signal(datum);
}
+ // Hosts will spawn a new default player prefab for the user that just connected
if (GetAgentType() == MultiplayerAgentType::ClientServer
|| GetAgentType() == MultiplayerAgentType::DedicatedServer)
{
- PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast(sv_defaultPlayerSpawnAsset).c_str()), 1);
- INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity());
-
- NetworkEntityHandle controlledEntity;
- if (entityList.size() > 0)
+ NetworkEntityHandle controlledEntity = SpawnDefaultPlayerPrefab();
+ if (controlledEntity.Exists())
{
- controlledEntity = entityList[0];
controlledEntity.GetNetBindComponent()->SetOwningConnectionId(connection->GetConnectionId());
}
-
+
if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
{
connection->SetUserData(new ServerToClientConnectionData(connection, *this, controlledEntity));
@@ -522,6 +519,17 @@ namespace Multiplayer
}
}
m_agentType = multiplayerType;
+
+ // Spawn the default player for this host since the host is also a player (not a dedicated server)
+ if (m_agentType == MultiplayerAgentType::ClientServer)
+ {
+ NetworkEntityHandle controlledEntity = SpawnDefaultPlayerPrefab();
+ if (NetBindComponent* controlledEntityNetBindComponent = controlledEntity.GetNetBindComponent())
+ {
+ controlledEntityNetBindComponent->SetAllowAutonomy(true);
+ }
+ }
+
AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType));
}
@@ -629,6 +637,19 @@ namespace Multiplayer
}
}
+ NetworkEntityHandle MultiplayerSystemComponent::SpawnDefaultPlayerPrefab()
+ {
+ PrefabEntityId playerPrefabEntityId(AZ::Name(static_cast(sv_defaultPlayerSpawnAsset).c_str()), 1);
+ INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity());
+
+ NetworkEntityHandle controlledEntity;
+ if (entityList.size() > 0)
+ {
+ controlledEntity = entityList[0];
+ }
+ return controlledEntity;
+ }
+
void host([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
{
Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer;
diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h
index db83c50fb5..e8e05a9d4c 100644
--- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h
+++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h
@@ -104,7 +104,8 @@ namespace Multiplayer
void OnConsoleCommandInvoked(AZStd::string_view command, const AZ::ConsoleCommandContainer& args, AZ::ConsoleFunctorFlags flags, AZ::ConsoleInvokedFrom invokedFrom);
void ExecuteConsoleCommandList(AzNetworking::IConnection* connection, const AZStd::fixed_vector& commands);
-
+ NetworkEntityHandle SpawnDefaultPlayerPrefab();
+
AZ_CONSOLEFUNC(MultiplayerSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dumps stats for the current multiplayer session");
AzNetworking::INetworkInterface* m_networkInterface = nullptr;
diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp
index dda3f18ad4..eaf89f3489 100644
--- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp
+++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp
@@ -402,8 +402,12 @@ namespace Multiplayer
const AZ::Transform& transform
)
{
- INetworkEntityManager::EntityList returnList;
-
+ EntityList returnList;
+ if (!AZ::Data::AssetManager::IsReady())
+ {
+ return returnList;
+ }
+
auto spawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(prefabEntryId.m_prefabName);
// Required for sync-instantiation. Todo: keep the reference in NetworkSpawnableLibrary
auto netSpawnableAsset = AZ::Data::AssetManager::Instance().GetAsset(spawnableAssetId, AZ::Data::AssetLoadBehavior::PreLoad);
diff --git a/Gems/PhysX/Code/CMakeLists.txt b/Gems/PhysX/Code/CMakeLists.txt
index b0318af9f2..d281270ce4 100644
--- a/Gems/PhysX/Code/CMakeLists.txt
+++ b/Gems/PhysX/Code/CMakeLists.txt
@@ -128,6 +128,9 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
AUTOMOC
FILES_CMAKE
physx_editor_shared_files.cmake
+ COMPILE_DEFINITIONS
+ PUBLIC
+ PHYSX_ENABLE_MULTI_THREADING
INCLUDE_DIRECTORIES
PRIVATE
.
diff --git a/Gems/PythonAssetBuilder/Code/CMakeLists.txt b/Gems/PythonAssetBuilder/Code/CMakeLists.txt
index 4af266f56d..73fa90ab67 100644
--- a/Gems/PythonAssetBuilder/Code/CMakeLists.txt
+++ b/Gems/PythonAssetBuilder/Code/CMakeLists.txt
@@ -13,24 +13,11 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS)
return()
endif()
-set(static_files pythonassetbuilder_common_files.cmake)
-set(editor_files pythonassetbuilder_editor_files.cmake)
-set(shared_files pythonassetbuilder_shared_files.cmake)
-set(static_dependencies
- 3rdParty::Python
- Gem::EditorPythonBindings.Static
- AZ::AssetBuilderSDK
-)
-set(editor_dependencies
- Gem::EditorPythonBindings.Static
- AZ::AssetBuilderSDK
-)
-
ly_add_target(
NAME PythonAssetBuilder.Static STATIC
NAMESPACE Gem
FILES_CMAKE
- ${static_files}
+ pythonassetbuilder_common_files.cmake
PLATFORM_INCLUDE_FILES
Source/Platform/Common/${PAL_TRAIT_COMPILER_ID}/pythonassetbuilder_static_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake
INCLUDE_DIRECTORIES
@@ -43,7 +30,9 @@ ly_add_target(
PRIVATE
AZ::AzCore
PUBLIC
- ${static_dependencies}
+ 3rdParty::Python
+ Gem::EditorPythonBindings.Static
+ AZ::AssetBuilderSDK
AZ::AzToolsFramework
)
@@ -52,8 +41,8 @@ ly_add_target(
NAMESPACE Gem
FILES_CMAKE
- ${editor_files}
- ${shared_files}
+ pythonassetbuilder_editor_files.cmake
+ pythonassetbuilder_shared_files.cmake
PLATFORM_INCLUDE_FILES
Source/Platform/Common/${PAL_TRAIT_COMPILER_ID}/pythonassetbuilder_static_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake
INCLUDE_DIRECTORIES
@@ -64,7 +53,8 @@ ly_add_target(
Include
BUILD_DEPENDENCIES
PRIVATE
- ${editor_dependencies}
+ Gem::EditorPythonBindings.Static
+ AZ::AssetBuilderSDK
RUNTIME_DEPENDENCIES
Gem::EditorPythonBindings.Editor
)
diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp
index b93844b989..21d1fc5264 100644
--- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp
+++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Spawning/SpawnNodeable.cpp
@@ -118,7 +118,7 @@ namespace ScriptCanvas::Nodeables::Spawning
AZ::Vector3 rotationCopy = rotation;
AZ::Quaternion rotationQuat = AZ::Quaternion::CreateFromEulerAnglesDegrees(rotationCopy);
- entityTransform->SetWorldTM(AZ::Transform(translation, rotationQuat, AZ::Vector3(scale, scale, scale)));
+ entityTransform->SetWorldTM(AZ::Transform(translation, rotationQuat, scale));
}
};
diff --git a/README.md b/README.md
index e0442adc16..0c59837a62 100644
--- a/README.md
+++ b/README.md
@@ -118,11 +118,6 @@ If you have the Git credential manager core or other credential helpers installe
```
python\get_python.bat
```
-
-1. While still within the repo folder, register the engine with this command:
- ```
- scripts\o3de.bat register --this-engine
- ```
1. Configure the source into a solution using this command line, replacing and <3rdParty cache path> to a path you've created:
```
@@ -146,7 +141,11 @@ If you have the Git credential manager core or other credential helpers installe
1. This will compile after some time and binaries will be available in the build path you've specified
-### Setting up new projects
+### Setting up new projects
+1. While still within the repo folder, register the engine with this command:
+ ```
+ scripts\o3de.bat register --this-engine
+ ```
1. Setup new projects using the `o3de create-project` command. In the 0.5 branch, the project directory must be a subdirectory in the repo folder.
```
\scripts\o3de.bat create-project --project-path
@@ -160,10 +159,10 @@ If you have the Git credential manager core or other credential helpers installe
cmake -B -S -G "Visual Studio 16" -DLY_3RDPARTY_PATH=<3rdParty cache path>
// For the 0.5 branch, you must build a new Editor for each project:
- cmake --build --target Editor --config profile -- /m
+ cmake --build --target .GameLauncher Editor --config profile -- /m
// For all other branches, just build the project:
- cmake --build --target --config profile -- /m
+ cmake --build --target .GameLauncher --config profile -- /m
```
For a tutorial on project configuration, see [Creating Projects Using the Command Line](https://docs.o3de.org/docs/welcome-guide/get-started/project-config/creating-projects-using-cli) in the documentation.
diff --git a/cmake/Platform/Common/RuntimeDependencies_common.cmake b/cmake/Platform/Common/RuntimeDependencies_common.cmake
index d9d0fe4c7f..4ae914744f 100644
--- a/cmake/Platform/Common/RuntimeDependencies_common.cmake
+++ b/cmake/Platform/Common/RuntimeDependencies_common.cmake
@@ -105,7 +105,7 @@ function(ly_get_runtime_dependencies ly_RUNTIME_DEPENDENCIES ly_TARGET)
set(skip_imported TRUE)
endif()
endif()
- if(target_type MATCHES "(INTERFACE_LIBRARY|STATIC_LIBRARY)")
+ if(target_type MATCHES "(STATIC_LIBRARY)")
# No need to copy these dependencies since the outputs are not used at runtime
set(skip_imported TRUE)
endif()
diff --git a/cmake/Tools/Platform/Android/android_support.py b/cmake/Tools/Platform/Android/android_support.py
index 6443077457..75e0cd2970 100755
--- a/cmake/Tools/Platform/Android/android_support.py
+++ b/cmake/Tools/Platform/Android/android_support.py
@@ -10,7 +10,9 @@
#
import imghdr
+import configparser
import datetime
+import fnmatch
import logging
import os
import json
@@ -33,6 +35,13 @@ if ROOT_DEV_PATH not in sys.path:
from cmake.Tools import common
+ANDROID_GRADLE_PLUGIN_COMPATIBILITY_MAP = {
+ '4.2.0': {'min_gradle_version': '6.7.1',
+ 'sdk_build': '30.0.2',
+ 'default_ndk': '21.4.7075529',
+ 'min_cmake_version': '3.20'}
+}
+
APP_NAME = 'app'
ANDROID_MANIFEST_FILE = 'AndroidManifest.xml'
ANDROID_LIBRARIES_JSON_FILE = 'android_libraries.json'
@@ -86,83 +95,93 @@ PYTHON_SCRIPT = 'python.cmd' if platform.system() == 'Windows' else 'python.sh'
ANDROID_LAUNCHER_NAME_PATTERN = "{project_name}.GameLauncher"
+
class AndroidProjectManifestEnvironment(object):
"""
- This class manages the environment for the AndroidManifiest.xml template file, based on project settings and environments
+ This class manages the environment for the AndroidManifest.xml template file, based on project settings and environments
that were passed in or calculated from the command line arguments.
"""
- def __init__(self, engine_root, project_path, android_sdk_version_number, android_ndk_platform_number, is_test:bool):
+ def __init__(self, engine_root, project_path, android_sdk_version_number, is_test:bool):
"""
Initialize the object with the project specific parameters and values for the game project
:param engine_root: The path where the engine is located
:param project_path: The path were the project is located
:param android_sdk_version_number: The android SDK platform version
- :param android_ndk_platform_number: The android NDK platform version
:param is_test: Indicates if theAzTestRunner application should be run
"""
- if is_test:
- # The AzTestRunner project.json is located under {engine_root}/Code/Tools/AzTestRunner/Platform/Android/android_project.json
- project_properties_path = engine_root / 'Code' / 'Tools' / 'AzTestRunner' / 'Platform' / 'Android' / 'android_project.json'
- else:
- # The project.json file is located under the game name folder
- project_properties_path = project_path / 'project.json'
- # Read and parse the project.json file into a dictionary to process the specific attributes needed for the manifest template
- project_properties_content = project_properties_path.resolve(strict=True)\
- .read_text(encoding=common.DEFAULT_TEXT_READ_ENCODING,
- errors=common.ENCODING_ERROR_HANDLINGS)
- self.project_path = project_path
+ try:
+ if is_test:
+ # The AzTestRunner project.json is located under {engine_root}/Code/Tools/AzTestRunner/Platform/Android/android_project.json
+ project_properties_path = engine_root / 'Code' / 'Tools' / 'AzTestRunner' / 'Platform' / 'Android' / 'android_project.json'
+ assert project_properties_path.is_file(), f'Missing required android settings file {project_properties_path.resolve()}'
+ project_properties_content = project_properties_path.read_text(encoding=common.DEFAULT_TEXT_READ_ENCODING,
+ errors=common.ENCODING_ERROR_HANDLINGS)
+ project_json = json.loads(project_properties_content)
- # Extract the key attributes we need to process and build up our environment table
- project_json = json.loads(project_properties_content)
+ android_settings = project_json['android_settings']
- project_name = project_json.get('project_name')
- if not project_name:
- raise common.LmbrCmdError(f"Missing required 'project_name' from project.json for project at '{str(project_path)}'")
- product_name = project_json.get('product_name', project_name)
+ else:
+ # O3DE projects have both a project.json and an android_project.json files (unless its internal)
+ project_properties_path = project_path / 'project.json'
+ assert project_properties_path.is_file(), f'Missing required project settings file {project_properties_path.resolve()}'
+ project_properties_content = project_properties_path.read_text(encoding=common.DEFAULT_TEXT_READ_ENCODING,
+ errors=common.ENCODING_ERROR_HANDLINGS)
+ project_json = json.loads(project_properties_content)
- game_project_android_settings = project_json['android_settings']
+ android_project_properties_path = project_path / 'Platform' / 'Android' / 'android_project.json'
+ if android_project_properties_path.is_file():
+ android_project_properties_content = android_project_properties_path.read_text(encoding=common.DEFAULT_TEXT_READ_ENCODING,
+ errors=common.ENCODING_ERROR_HANDLINGS)
+ android_project_json = json.loads(android_project_properties_content)
+ android_settings = android_project_json['android_settings']
+ else:
+ android_settings = project_json['android_settings']
- package_name = game_project_android_settings["package_name"]
+ self.project_path = project_path
- package_path = package_name.replace('.', '/')
+ project_name = project_json['project_name']
+ product_name = project_json.get('product_name', project_name)
+ package_name = android_settings["package_name"]
+ package_path = package_name.replace('.', '/')
- project_activity = f'{TEST_RUNNER_PROJECT}Activity' if is_test else f'{project_name}Activity'
+ project_activity = f'{TEST_RUNNER_PROJECT}Activity' if is_test else f'{project_name}Activity'
- # Multiview options require special processing
- multi_window_options = AndroidProjectManifestEnvironment.process_android_multi_window_options(game_project_android_settings)
+ # Multiview options require special processing
+ multi_window_options = AndroidProjectManifestEnvironment.process_android_multi_window_options(android_settings)
- self.internal_dict = {
- 'ANDROID_PACKAGE': package_name,
- 'ANDROID_PACKAGE_PATH': package_path,
- 'ANDROID_VERSION_NUMBER': game_project_android_settings["version_number"],
- "ANDROID_VERSION_NAME": game_project_android_settings["version_name"],
- "ANDROID_SCREEN_ORIENTATION": game_project_android_settings["orientation"],
- 'ANDROID_APP_NAME': TEST_RUNNER_PROJECT if is_test else product_name, # external facing name
- 'ANDROID_PROJECT_NAME': TEST_RUNNER_PROJECT if is_test else project_name, # internal facing name
- 'ANDROID_PROJECT_ACTIVITY': project_activity,
- 'ANDROID_LAUNCHER_NAME': TEST_RUNNER_PROJECT if is_test else ANDROID_LAUNCHER_NAME_PATTERN.format(project_name=project_name),
- 'ANDROID_CONFIG_CHANGES': multi_window_options['ANDROID_CONFIG_CHANGES'],
- 'ANDROID_APP_PUBLIC_KEY': game_project_android_settings.get('app_public_key', 'NoKey'),
- 'ANDROID_APP_OBFUSCATOR_SALT': game_project_android_settings.get('app_obfuscator_salt', ''),
- 'ANDROID_USE_MAIN_OBB': game_project_android_settings.get('use_main_obb', 'false'),
- 'ANDROID_USE_PATCH_OBB': game_project_android_settings.get('use_patch_obb', 'false'),
- 'ANDROID_ENABLE_KEEP_SCREEN_ON': game_project_android_settings.get('enable_keep_screen_on', 'false'),
- 'ANDROID_DISABLE_IMMERSIVE_MODE': game_project_android_settings.get('disable_immersive_mode', 'false'),
- 'ANDROID_MIN_SDK_VERSION': android_ndk_platform_number,
- 'ANDROID_TARGET_SDK_VERSION': android_sdk_version_number,
- 'ICONS': game_project_android_settings.get('icons', None),
- 'SPLASH_SCREEN': game_project_android_settings.get('splash_screen', None),
+ self.internal_dict = {
+ 'ANDROID_PACKAGE': package_name,
+ 'ANDROID_PACKAGE_PATH': package_path,
+ 'ANDROID_VERSION_NUMBER': android_settings["version_number"],
+ "ANDROID_VERSION_NAME": android_settings["version_name"],
+ "ANDROID_SCREEN_ORIENTATION": android_settings["orientation"],
+ 'ANDROID_APP_NAME': TEST_RUNNER_PROJECT if is_test else product_name, # external facing name
+ 'ANDROID_PROJECT_NAME': TEST_RUNNER_PROJECT if is_test else project_name, # internal facing name
+ 'ANDROID_PROJECT_ACTIVITY': project_activity,
+ 'ANDROID_LAUNCHER_NAME': TEST_RUNNER_PROJECT if is_test else ANDROID_LAUNCHER_NAME_PATTERN.format(project_name=project_name),
+ 'ANDROID_CONFIG_CHANGES': multi_window_options['ANDROID_CONFIG_CHANGES'],
+ 'ANDROID_APP_PUBLIC_KEY': android_settings.get('app_public_key', 'NoKey'),
+ 'ANDROID_APP_OBFUSCATOR_SALT': android_settings.get('app_obfuscator_salt', ''),
+ 'ANDROID_USE_MAIN_OBB': android_settings.get('use_main_obb', 'false'),
+ 'ANDROID_USE_PATCH_OBB': android_settings.get('use_patch_obb', 'false'),
+ 'ANDROID_ENABLE_KEEP_SCREEN_ON': android_settings.get('enable_keep_screen_on', 'false'),
+ 'ANDROID_DISABLE_IMMERSIVE_MODE': android_settings.get('disable_immersive_mode', 'false'),
+ 'ANDROID_TARGET_SDK_VERSION': android_sdk_version_number,
+ 'ICONS': android_settings.get('icons', None),
+ 'SPLASH_SCREEN': android_settings.get('splash_screen', None),
- 'ANDROID_MULTI_WINDOW': multi_window_options['ANDROID_MULTI_WINDOW'],
- 'ANDROID_MULTI_WINDOW_PROPERTIES': multi_window_options['ANDROID_MULTI_WINDOW_PROPERTIES'],
+ 'ANDROID_MULTI_WINDOW': multi_window_options['ANDROID_MULTI_WINDOW'],
+ 'ANDROID_MULTI_WINDOW_PROPERTIES': multi_window_options['ANDROID_MULTI_WINDOW_PROPERTIES'],
- 'SAMSUNG_DEX_KEEP_ALIVE': multi_window_options['SAMSUNG_DEX_KEEP_ALIVE'],
- 'SAMSUNG_DEX_LAUNCH_WIDTH': multi_window_options['SAMSUNG_DEX_LAUNCH_WIDTH'],
- 'SAMSUNG_DEX_LAUNCH_HEIGHT': multi_window_options['SAMSUNG_DEX_LAUNCH_HEIGHT']
- }
+ 'SAMSUNG_DEX_KEEP_ALIVE': multi_window_options['SAMSUNG_DEX_KEEP_ALIVE'],
+ 'SAMSUNG_DEX_LAUNCH_WIDTH': multi_window_options['SAMSUNG_DEX_LAUNCH_WIDTH'],
+ 'SAMSUNG_DEX_LAUNCH_HEIGHT': multi_window_options['SAMSUNG_DEX_LAUNCH_HEIGHT']
+ }
+ except KeyError as e:
+ raise common.LmbrCmdError(f"Missing key from android project settings for project at {project_path}:'{e}' ")
def __getitem__(self, item):
return self.internal_dict.get(item)
@@ -306,6 +325,7 @@ asset_deploy_type={asset_type}
android_sdk_path={android_sdk_path}
embed_assets_in_apk={embed_assets_in_apk}
is_unit_test={is_unit_test}
+android_gradle_plugin={android_gradle_plugin_version}
"""
NATIVE_CMAKE_SECTION_ANDROID_FORMAT = """
@@ -425,26 +445,28 @@ class AndroidProjectGenerator(object):
Class the manages the process to generate an android project folder in order to build with gradle/android studio
"""
- def __init__(self, engine_root, build_dir, android_ndk_path, android_sdk_path, android_sdk_version, android_ndk_platform,
- project_path, third_party_path, cmake_version, override_cmake_path, override_gradle_path, override_ninja_path,
- android_sdk_build_tool_version, include_assets_in_apk, asset_mode, asset_type, signing_config, is_test_project=False,
+ def __init__(self, engine_root, build_dir, android_sdk_path, build_tool, android_sdk_platform, android_native_api_level, android_ndk,
+ project_path, third_party_path, cmake_version, override_cmake_path, override_gradle_path, gradle_version, gradle_plugin_version,
+ override_ninja_path, include_assets_in_apk, asset_mode, asset_type, signing_config, is_test_project=False,
overwrite_existing=True):
"""
Initialize the object with all the required parameters needed to create an Android Project. The parameters should be verified before initializing this object
-
+
:param engine_root: The engine root that contains the engine
:param build_dir: The target folder under the where the android project folder will be created
- :param android_ndk_path: The path to the ANDROID_NDK used for building the native android code
:param android_sdk_path: The path to the ANDROID_SDK used for building the android java code
- :param android_sdk_version: The android platform version number to use for the Android SDK related builds
- :param android_ndk_platform: The android platform version number to use for the Android NDK related builds
+ :param build_tool: The android SDK build-tool version.
+ :param android_sdk_platform: The android sdk platform version number to use for the Android SDK related builds
+ :param android_native_api_level:The android native API level (ANDROID_NATIVE_API_LEVEL) to set
+ :param android_ndk: The android ndk version number to use for the native builds
:param project_path: The path to the project
:param third_party_path: The required path to the lumberyard 3rd party path
:param cmake_version: The version number of cmake that will be used by gradle
:param override_cmake_path: The override path to cmake if it does not exists in the system path
:param override_gradle_path: The override path to gradle if it does not exists in the system path
+ :param gradle_version: The detected version of gradle being used
+ :param gradle_plugin_version: The android gradle plugin version
:param override_ninja_path: The override path to ninja if it does not exists in the system path
- :param android_sdk_build_tool_version: The preferred android SDK build-tool version. Will default to the first one detected in the android sdk path
:param include_assets_in_apk:
:param asset_mode:
:param asset_type:
@@ -458,17 +480,16 @@ class AndroidProjectGenerator(object):
self.build_dir = build_dir
- self.android_ndk_path = android_ndk_path
-
self.android_sdk_path = android_sdk_path
self.android_project_builder_path = self.engine_root / 'Code/Tools/Android/ProjectBuilder'
- self.android_sdk_version = android_sdk_version
+ self.android_sdk_platform = android_sdk_platform
+ self.android_sdk_build_tool_version = build_tool.version
- self.android_sdk_build_tool_version = android_sdk_build_tool_version
-
- self.android_ndk_platform = android_ndk_platform
+ self.android_ndk = android_ndk
+ self.android_ndk_version = android_ndk.version
+ self.android_native_api_level = android_native_api_level
self.project_path = project_path
@@ -480,6 +501,10 @@ class AndroidProjectGenerator(object):
self.override_gradle_path = override_gradle_path
+ self.gradle_version = gradle_version
+
+ self.gradle_plugin_version = gradle_plugin_version
+
self.override_ninja_path = override_ninja_path
self.include_assets_in_apk = include_assets_in_apk
@@ -511,8 +536,10 @@ class AndroidProjectGenerator(object):
project_names.extend(self.create_lumberyard_app(project_names))
root_gradle_env = {
- 'SDK_VER': self.android_sdk_version,
- 'NDK_PLATFORM_VER': self.android_ndk_platform,
+ 'ANDROID_GRADLE_PLUGIN_VERSION': str(self.gradle_plugin_version),
+ 'SDK_VER': self.android_sdk_platform,
+ 'MIN_SDK_VER': self.android_sdk_platform,
+ 'NDK_VERSION': self.android_ndk_version,
'SDK_BUILD_TOOL_VER': self.android_sdk_build_tool_version,
'LY_ENGINE_ROOT': common.normalize_path_for_settings(self.engine_root)
}
@@ -557,7 +584,7 @@ class AndroidProjectGenerator(object):
if self.override_gradle_path:
gradle_wrapper_cmd = [self.override_gradle_path]
else:
- gradle_wrapper_cmd = ['gradle.bat' if platform.system() == 'Windows' else 'gradle']
+ gradle_wrapper_cmd = ['gradle']
gradle_wrapper_cmd.extend(['wrapper', '-p', str(self.build_dir.resolve())])
@@ -580,7 +607,8 @@ class AndroidProjectGenerator(object):
asset_type='',
android_sdk_path=str(self.android_sdk_path),
embed_assets_in_apk=True,
- is_unit_test=True)
+ is_unit_test=True,
+ android_gradle_plugin_version=self.gradle_plugin_version)
else:
platform_settings_content = PLATFORM_SETTINGS_FORMAT.format(generation_timestamp=str(datetime.datetime.now().strftime("%c")),
platform='android',
@@ -589,16 +617,28 @@ class AndroidProjectGenerator(object):
asset_type=self.asset_type,
android_sdk_path=str(self.android_sdk_path),
embed_assets_in_apk=str(self.include_assets_in_apk),
- is_unit_test=False)
+ is_unit_test=False,
+ android_gradle_plugin_version=self.gradle_plugin_version)
platform_settings_file = self.build_dir / 'platform.settings'
+
+ # Check if there already exists the build folder and a 'platform.settings' file. If there is an android gradle
+ # plugin version set and it is different than the one configured here, we will always overwrite it since
+ # there could be significant differences from one plug-in to the next
+ if platform_settings_file.is_file():
+ config = configparser.ConfigParser()
+ config.read([str(platform_settings_file.resolve(strict=True))])
+ if config.has_option('android', 'android_gradle_plugin'):
+ exist_agp_version = config.get('android', 'android_gradle_plugin')
+ if exist_agp_version != self.gradle_plugin_version:
+ self.overwrite_existing = True
+
platform_settings_file.open('w').write(platform_settings_content)
def create_default_local_properties(self):
"""
Create the default 'local.properties' file in the build folder
"""
- template_android_ndk_path = common.normalize_path_for_settings(self.android_ndk_path, True)
template_android_sdk_path = common.normalize_path_for_settings(self.android_sdk_path, True)
if self.override_cmake_path:
# The cmake dir references the base cmake folder, not the executable path itself, so resolve to the base folder
@@ -608,7 +648,6 @@ class AndroidProjectGenerator(object):
local_properties_env = {
"GENERATION_TIMESTAMP": str(datetime.datetime.now().strftime("%c")),
- "ANDROID_NDK_PATH": template_android_ndk_path,
"ANDROID_SDK_PATH": template_android_sdk_path,
"CMAKE_DIR_LINE": f'cmake.dir={template_cmake_path}' if template_cmake_path else ''
}
@@ -626,8 +665,7 @@ class AndroidProjectGenerator(object):
# before we can process it.
android_libraries_substitution_table = {
"ANDROID_SDK_HOME": common.normalize_path_for_settings(self.android_sdk_path, False),
- "ANDROID_NDK_HOME": common.normalize_path_for_settings(self.android_ndk_path, False),
- "ANDROID_SDK_VERSION": "android-".format(self.android_sdk_version)
+ "ANDROID_SDK_VERSION": f"android-{self.android_sdk_platform}"
}
android_libraries_template_json_path = self.android_project_builder_path / ANDROID_LIBRARIES_JSON_FILE
@@ -717,7 +755,7 @@ class AndroidProjectGenerator(object):
template_engine_root = common.normalize_path_for_settings(self.engine_root)
template_third_party_path = common.normalize_path_for_settings(self.third_party_path)
- template_ndk_path = common.normalize_path_for_settings(self.android_ndk_path)
+ template_ndk_path = common.normalize_path_for_settings(os.path.join(self.android_sdk_path, self.android_ndk.location))
gradle_build_env = dict()
@@ -733,7 +771,6 @@ class AndroidProjectGenerator(object):
gradle_build_env['OVERRIDE_JAVA_SOURCESET'] = OVERRIDE_JAVA_SOURCESET_STR.format(absolute_azandroid_path=absolute_azandroid_path)
-
gradle_build_env['OPTIONAL_JNI_SRC_LIB_SET'] = ', "outputs/native-lib"'
for native_config in BUILD_CONFIGURATIONS:
@@ -755,7 +792,7 @@ class AndroidProjectGenerator(object):
cmake_argument_list.append('"-DLY_TEST_PROJECT=1"')
cmake_argument_list.extend([
- f'"-DANDROID_NATIVE_API_LEVEL={self.android_ndk_platform}"',
+ f'"-DANDROID_NATIVE_API_LEVEL={self.android_native_api_level}"',
f'"-DLY_NDK_DIR={template_ndk_path}"',
'"-DANDROID_STL=c++_shared"',
'"-Wno-deprecated"',
@@ -835,8 +872,7 @@ class AndroidProjectGenerator(object):
dest_src_main_path.mkdir(parents=True)
az_android_package_env = AndroidProjectManifestEnvironment(engine_root=self.engine_root,
project_path=self.project_path,
- android_sdk_version_number=self.android_sdk_version,
- android_ndk_platform_number=self.android_ndk_platform,
+ android_sdk_version_number=self.android_sdk_platform,
is_test=self.is_test_project)
self.create_file_from_project_template(src_template_file=ANDROID_MANIFEST_FILE,
template_env=az_android_package_env,
@@ -1304,218 +1340,7 @@ class AndroidProjectGenerator(object):
self.new = new
-ANDROID_PLATFORM_PATTERN = re.compile(r'([\w\d]*-)?(\d+\d*)') # Regex to handle android platform naming for both SDKs and NDKs
-
-
-def validate_android_platform_input(input_android_platform, platform_variable_type, min_version, max_version):
- """
- Helper tool to support android platform number inputs and perform min/max version validation
-
- :param input_android_platform: The inpuit argument to evaluate
- :param platform_variable_type: The type of platform version to validate (android sdk / android ndk)
- :param min_version: The minimum version to validate against
- :param max_version: The maximum version to validate against
- :return: The int version of the extracted platform number from the input
- """
- # Validate the platform number's format and against the supported versions
- platform_number_match = ANDROID_PLATFORM_PATTERN.search(input_android_platform)
- if not platform_number_match or not platform_number_match.group(2) or (platform_number_match.group(1) and platform_number_match.group(1) != 'android-'):
- raise common.LmbrCmdError(f"Invalid {platform_variable_type} version value ({input_android_platform}). It must be "
- f"either 'XX' or android-'XX' where 'XX' is a platform number.",
- common.ERROR_CODE_INVALID_PARAMETER)
-
- android_platform_number = int(platform_number_match.group(2))
- if android_platform_number < min_version:
- raise common.LmbrCmdError(f"Invalid {platform_variable_type} version value ({input_android_platform}) is less than the minimum "
- f"supported version ({min_version}).",
- common.ERROR_CODE_INVALID_PARAMETER)
- if android_platform_number > max_version:
- raise common.LmbrCmdError(f"Invalid {platform_variable_type} version value ({input_android_platform}) is greater than the maximum "
- f"supported version ({max_version}).",
- common.ERROR_CODE_INVALID_PARAMETER)
- return android_platform_number
-
-
ANDROID_SDK_ENV_NAME = 'ANDROID_SDK'
-ANDROID_SDK_MIN_PLATFORM = 28
-ANDROID_SDK_MAX_PLATFORM = 29
-
-
-def verify_android_sdk(android_sdk_platform, argument_name, override_android_sdk_path=None, preferred_sdk_build_tools_ver=None):
- """
- Verify the android sdk and the requested platform platform against the android sdk path
-
- :param android_sdk_platform: The android sdk platform to use (e.g. '28' or 'android-28')
- :param argument_name: The name of the argument for descriptive errors to present
- :param override_android_sdk_path: The location of the android SDK path if not set through the environment variable
- :param preferred_sdk_build_tools_ver: Option prefered built tool version under the android SDK if available. Will fallback to the first one discovered
- :returns tuple of the verified android sdk platform number, path to the Android SDK path and the build tool version
- """
- android_sdk_platform_number = validate_android_platform_input(input_android_platform=android_sdk_platform,
- platform_variable_type='android sdk',
- min_version=ANDROID_SDK_MIN_PLATFORM,
- max_version=ANDROID_SDK_MAX_PLATFORM)
-
- # Get the candidate android sdk path from either the override argument or the system environment variable
- if override_android_sdk_path:
- check_android_sdk_path = override_android_sdk_path
- else:
- check_android_sdk_path = os.environ.get(ANDROID_SDK_ENV_NAME)
- if not check_android_sdk_path:
- raise common.LmbrCmdError(f"Android SDK path not set. Make sure that either the '{ANDROID_SDK_ENV_NAME}' environment is "
- f"set or it is passed in through the {argument_name} argument")
-
- # The android sdk folder structure is expected to have a 'platforms' sub folder based on the android sdk-platform number
- check_android_sdk_path = pathlib.Path(check_android_sdk_path)
- android_sdk_platforms_path = check_android_sdk_path / 'platforms'
- if not android_sdk_platforms_path.is_dir():
- raise common.LmbrCmdError(f"Invalid Android SDK path '{str(check_android_sdk_path)}': Missing 'platforms' directory.")
-
- # Collect the available platform numbers from the platforms subdirectory
- validated_android_platforms = []
- for dir_item in android_sdk_platforms_path.iterdir():
- if not dir_item.is_dir():
- continue
- check_file = dir_item / 'package.xml'
- if check_file.is_file():
- validated_android_platforms.append(dir_item.name)
-
- if not validated_android_platforms:
- raise common.LmbrCmdError(f"Invalid Android SDK path '{str(check_android_sdk_path)}': Unable to find any android platforms.")
-
- # Normalize the android_sdk argument to fit the same folder name pattern
- android_sdk_platform_name = f'android-{android_sdk_platform_number}'
- if android_sdk_platform_name not in validated_android_platforms:
- raise common.LmbrCmdError(f"Android SDK platform {android_sdk_platform_name} is not a valid for the android SDK located under '{str(check_android_sdk_path)}'")
-
- # Enumerate through the build tools under android sdk
- android_sdk_build_tools_dir = check_android_sdk_path / 'build-tools'
- if not android_sdk_build_tools_dir.is_dir():
- raise common.LmbrCmdError(f"Invalid Android SDK path '{str(check_android_sdk_path)}': Unable to find any built-tools folder.")
- supported_build_tools = [str(build_tool.name) for build_tool in android_sdk_build_tools_dir.iterdir() if build_tool.is_dir()]
- if not supported_build_tools:
- raise common.LmbrCmdError(f"Invalid Android SDK path '{str(check_android_sdk_path)}': Unable to find any built-tools.")
- if preferred_sdk_build_tools_ver:
- if preferred_sdk_build_tools_ver in supported_build_tools:
- validated_build_tool = preferred_sdk_build_tools_ver
- else:
- validated_build_tool = supported_build_tools[0]
- logging.warning("Unable to locate android sdk build tool version {preferred_sdk_build_tools_ver}. Defaulting to version {validated_build_tool}")
-
- else:
- validated_build_tool = supported_build_tools[0]
-
- return android_sdk_platform_number, check_android_sdk_path, validated_build_tool
-
-
-ANDROID_NDK_ENV_NAME = 'ANDROID_NDK'
-ANDROID_NDK_MIN_PLATFORM = 21
-ANDROID_NDK_MAX_PLATFORM = 29
-ANDROID_NDK_SOURCE_PROPERTIES_REVISION_PATTERN = re.compile(r'Pkg.Revision\s*=\s*(\d+.\d+.\d+)')
-
-
-def verify_android_ndk(android_ndk_platform, argument_name, override_android_ndk_path=None):
- """
- Verify the android ndk and requested platform against the android ndk path
-
- :param android_ndk_platform: The android ndk platform to use (e.g. '21' or 'android-21')
- :param argument_name: The name of the argument for descriptive errors to present
- :param override_android_ndk_path: The location of the android NDK path if not set through the environment variable
- :returns tuple of the verified android ndk platform number and the Path to the Android SDK path and the
- """
-
- android_ndk_platform_number = validate_android_platform_input(input_android_platform=android_ndk_platform,
- platform_variable_type='android ndk',
- min_version=ANDROID_NDK_MIN_PLATFORM,
- max_version=ANDROID_NDK_MAX_PLATFORM)
-
- # Get the candidate android ndk path from either the override argument or the system environment variable
- if override_android_ndk_path:
- check_android_ndk_path = str(override_android_ndk_path)
- else:
- check_android_ndk_path = os.environ.get(ANDROID_NDK_ENV_NAME)
- if not check_android_ndk_path:
- raise common.LmbrCmdError(f"Android NDK path not set. Make sure that either the {ANDROID_NDK_ENV_NAME} environment "
- f"is set or it is passed in through the {argument_name} argument")
- check_android_ndk_path = pathlib.Path(check_android_ndk_path)
-
- # Validate the android ndk path
-
- # Determine the NDK revision by reading the source.properties file
- ndk_source_properties_file = check_android_ndk_path / 'source.properties'
- if not ndk_source_properties_file.is_file():
- raise common.LmbrCmdError(f"Invalid Android NDK path '{str(check_android_ndk_path)}'. Missing 'source.properties' file.",
- common.ERROR_CODE_INVALID_PARAMETER)
- ndk_source_properties_file_content = ndk_source_properties_file.read_text(encoding=common.DEFAULT_TEXT_READ_ENCODING,
- errors=common.ENCODING_ERROR_HANDLINGS)
-
- ndk_revision_match = ANDROID_NDK_SOURCE_PROPERTIES_REVISION_PATTERN.search(ndk_source_properties_file_content)
- if not ndk_revision_match:
- raise common.LmbrCmdError(f"Invalid Android NDK path '{str(check_android_ndk_path)}'. Unable to extract version from 'source.properties' file.",
- common.ERROR_CODE_INVALID_PARAMETER)
- ndk_revision_number = LooseVersion(ndk_revision_match.group(1))
- logging.info(f"Detected Android NDK Revision {str(ndk_revision_number)}")
-
- # Collect the supported android platforms from the required 'platforms' folder under the ndk path
- android_ndk_platforms_path = check_android_ndk_path / 'platforms'
- if not android_ndk_platforms_path.is_dir():
- raise common.LmbrCmdError(f"Invalid Android NDK path '{str(check_android_ndk_path)}'. Missing 'platforms' folder.",
- common.ERROR_CODE_INVALID_PARAMETER)
-
- validated_android_platforms = []
- for dir_item in android_ndk_platforms_path.iterdir():
- if not dir_item.is_dir():
- continue
- api_version_match = ANDROID_PLATFORM_PATTERN.search(dir_item.name)
- if not api_version_match or api_version_match.group(1) != 'android-':
- continue
-
- check_lib_path = dir_item / 'arch-arm64/usr/lib'
- if check_lib_path.is_dir():
- validated_android_platforms.append(dir_item.name)
-
- # For NDK revisions 19 and up, there is a mapping file for version numbers that map to other version.
- platforms_map_aliases = {}
- if ndk_revision_number >= LooseVersion('19.0.0'):
- platforms_map_file = check_android_ndk_path / 'meta/platforms.json'
- if platforms_map_file.exists():
- with open(platforms_map_file, 'r') as platforms_map_file_handle:
- platforms_map_file_json = json.load(platforms_map_file_handle)
- platforms_map_aliases = platforms_map_file_json['aliases']
- elif validated_android_platforms:
- # Revisions before 19 does not have a mapping file for API versions, they fall back to the previous one
- # So we need to make a mapping file that does the same
- platforms_map_aliases = {}
- validated_android_platforms.sort()
- max_supported_api_number = int(ANDROID_PLATFORM_PATTERN.search(validated_android_platforms[-1]).group(2))
- for validated_android_platform in validated_android_platforms:
- current_api_version = int(ANDROID_PLATFORM_PATTERN.search(validated_android_platform).group(2))
- next_api_version = current_api_version + 1
- while f'android-{next_api_version}' not in validated_android_platforms and next_api_version <= max_supported_api_number:
- platforms_map_aliases[str(next_api_version)] = current_api_version
- next_api_version += 1
-
- # Go through the aliases and add to the validated platforms if it is mapped to an existing platform
- for alias_key, alias_value in platforms_map_aliases.items():
- if not ANDROID_PLATFORM_PATTERN.search(f'android-{alias_key}'):
- # Skip any non android-XX (XX = number) aliases
- continue
- aliased_platform_key = f'android-{alias_value}'
- if aliased_platform_key in validated_android_platforms:
- validated_android_platforms.append(f'android-{alias_key}')
-
- if not validated_android_platforms:
- raise common.LmbrCmdError(f"Invalid Android NDK path {str(check_android_ndk_path)}")
-
- # Verify the ndk platform against the ndk path
- android_ndk_platform_name = f'android-{android_ndk_platform_number}'
- if android_ndk_platform_name not in validated_android_platforms:
- raise common.LmbrCmdError(f"Android NDK platform {android_ndk_platform_name} is not a valid for the Android NDK located under '{str(check_android_ndk_path)}'")
-
- return android_ndk_platform_number, check_android_ndk_path
-
-
-ADB_TARGET = 'adb.exe' if platform.system() == 'Windows' else 'adb'
def resolve_adb_tool(android_sdk_path):
@@ -1528,9 +1353,16 @@ def resolve_adb_tool(android_sdk_path):
if isinstance(android_sdk_path, str):
android_sdk_path = pathlib.Path(android_sdk_path)
- check_adb_target = android_sdk_path / 'platform-tools' / ADB_TARGET
- if not check_adb_target.exists():
- raise common.LmbrCmdError(f"Invalid Android SDK path '{str(android_sdk_path)}': Unable to locate '{ADB_TARGET}'.")
+ file_found = False
+ for executable_path_ext in common.PLATFORM_EXECUTABLE_EXTENSIONS:
+ check_adb_target = android_sdk_path / 'platform-tools' / f'adb{executable_path_ext}'
+ if check_adb_target.is_file():
+ file_found = True
+ break
+
+ if not file_found:
+ raise common.LmbrCmdError(f"Invalid Android SDK path '{str(android_sdk_path)}': Unable to locate 'adb'.")
+
return check_adb_target
@@ -1633,3 +1465,196 @@ class AdbTool(common.CommandLineExec):
else:
adb_params = arguments
return super().popen(adb_params, cwd)
+
+
+class AndroidGradlePluginInfo(object):
+
+ def __init__(self, android_gradle_plugin_version):
+
+ if android_gradle_plugin_version not in ANDROID_GRADLE_PLUGIN_COMPATIBILITY_MAP.keys():
+ raise common.LmbrCmdError(f"Android Gradle Plugin version {android_gradle_plugin_version} is not supported. "
+ f"Only the following version(s) are supported: {','.join(ANDROID_GRADLE_PLUGIN_COMPATIBILITY_MAP.keys())}")
+
+ details = ANDROID_GRADLE_PLUGIN_COMPATIBILITY_MAP[android_gradle_plugin_version]
+ self.default_sdk_build_tools_version = LooseVersion(details.get('sdk_build'))
+
+ self.default_ndk_version = LooseVersion(details.get('default_ndk'))
+
+ self.min_gradle_version = LooseVersion(details.get('min_gradle_version'))
+
+ self.min_cmake_version = LooseVersion(details.get('min_cmake_version'))
+
+ max_cmake_version_number = details.get('max_cmake_version')
+ self.max_cmake_version = None if max_cmake_version_number is None else LooseVersion(max_cmake_version_number)
+
+
+class AndroidSDKResolver(object):
+ """
+ Class that manages the Android SDK tool to validate, install packages (e.g. built tools, sdk platforms, ndk, etc)
+ """
+
+ class InstalledPackage(object):
+ def __init__(self, installed_package_components):
+ assert len(installed_package_components) == 4, '4 sections expected for installed package components (path, version, description, location)'
+ self.path = installed_package_components[0]
+ self.version = LooseVersion(installed_package_components[1])
+ self.description = installed_package_components[2]
+ self.location = installed_package_components[3]
+
+ class AvailablePackage(object):
+ def __init__(self, available_package_components):
+ assert len(available_package_components) == 3, '3 sections expected for installed package components (path, version, description)'
+ self.path = available_package_components[0]
+ self.version = LooseVersion(available_package_components[1])
+ self.description = available_package_components[2]
+
+ class AvailableUpdate(object):
+ def __init__(self, available_update_components):
+ assert len(available_update_components) == 3, '3 sections expected for installed package components (path, version, available)'
+ self.path = available_update_components[0]
+ self.version = LooseVersion(available_update_components[1])
+ self.available = available_update_components[2]
+
+ def __init__(self, android_sdk_path):
+
+ self.android_sdk_path = android_sdk_path or os.environ.get(ANDROID_SDK_ENV_NAME)
+ if not self.android_sdk_path:
+ raise common.LmbrCmdError(f"Android SDK path not set or it was not passed into the command to generate the android project")
+ if not os.path.isdir(self.android_sdk_path):
+ raise common.LmbrCmdError(f"Android SDK path {self.android_sdk_path} is not valid")
+ if platform.system() == 'Windows':
+ self.sdk_manager_path = pathlib.Path(self.android_sdk_path) / 'tools' / 'bin' / 'sdkmanager.bat'
+ else:
+ raise common.LmbrCmdError(f"This tool is not supported on the current platform {platform.system()}")
+ if not self.sdk_manager_path.is_file():
+ raise common.LmbrCmdError(f"Android SDK path {self.android_sdk_path} is not valid or complete. Missing {self.sdk_manager_path}")
+
+ self.sdk_manager = common.CommandLineExec(str(self.sdk_manager_path.resolve()))
+
+ self.installed_packages = {}
+ self.available_packages = {}
+ self.available_updates = {}
+ self.refresh_sdk_installation()
+
+ def refresh_sdk_installation(self):
+ """
+ Utilize the sdk_manager command line tool from the Android SDK to collect / refresh the list of
+ installed, available, and updateable packages that are managed by the android SDK.
+ """
+ self.installed_packages = {}
+ self.available_packages = {}
+ self.available_updates = {}
+
+ def _factory_installed_package(package_map, item_components):
+ package_map[item_components[0]] = AndroidSDKResolver.InstalledPackage(item_components)
+
+ def _factory_available_package(package_map, item_components):
+ package_map[item_components[0]] = AndroidSDKResolver.AvailablePackage(item_components)
+
+ def _factory_available_update(package_map, item_components):
+ package_map[item_components[0]] = AndroidSDKResolver.AvailableUpdate(item_components)
+
+ # Use the SDK manager to collect the available and installed packages
+ result_code, result_stdout, result_stderr = self.sdk_manager.exec(['--list'], capture_stdout=True, suppress_stderr=True)
+
+ current_append_map = None
+ current_item_factory = None
+ for package_item in result_stdout.split('\n'):
+ package_item_stripped = package_item.strip()
+ if not package_item_stripped:
+ continue
+ if '|' not in package_item_stripped:
+ if package_item_stripped.upper() == 'INSTALLED PACKAGES:':
+ current_append_map = self.installed_packages
+ current_item_factory = _factory_installed_package
+ elif package_item_stripped.upper() == 'AVAILABLE PACKAGES:':
+ current_append_map = self.available_packages
+ current_item_factory = _factory_available_package
+ elif package_item_stripped.upper() == 'AVAILABLE UPDATES:':
+ current_append_map = self.available_updates
+ current_item_factory = _factory_available_update
+ else:
+ current_append_map = None
+ current_item_factory = None
+ continue
+ item_parts = [split.strip() for split in package_item_stripped.split('|')]
+ if len(item_parts) < 3:
+ continue
+ elif item_parts[1].upper() in ('VERSION', 'INSTALLED', '-------'):
+ continue
+ elif current_append_map is None:
+ continue
+ if current_append_map is not None and current_item_factory is not None:
+ current_item_factory(current_append_map, item_parts)
+
+ def is_package_installed(self, search_package_path):
+ """
+ Check if a package path to see if its a package that is installed. The path can use wildcard '*'s
+ The function will return a list of the results that match the package paths, ordered by the newest version first
+ """
+ def _package_sort(package):
+ return package.version
+ package_detail_result_list = []
+ for installed_package_path, installed_package_details in self.installed_packages.items():
+ if fnmatch.fnmatch(installed_package_path, search_package_path):
+ package_detail_result_list.append(installed_package_details)
+ package_detail_result_list.sort(reverse=True, key=_package_sort)
+ return package_detail_result_list
+
+ def is_package_available(self, search_package_path):
+ """
+ Check if a package path to see if its an available package to install. The path can use wildcard '*'s
+ The function will return a list of the results that match the package paths, ordered by the newest version first
+ """
+ def _package_sort(package):
+ return package.version
+ package_detail_result_list = []
+ for available_package_path, available_package_details in self.available_packages.items():
+ if fnmatch.fnmatch(available_package_path, search_package_path):
+ package_detail_result_list.append(available_package_details)
+ package_detail_result_list.sort(reverse=True, key=_package_sort)
+ return package_detail_result_list
+
+ def install_package(self, package_install_path, package_description):
+ """
+ Install a package based on the path of an available android sdk package
+ """
+
+ # Skip installation if the package is already installed
+ package_result_list = self.is_package_installed(package_install_path)
+ if package_result_list:
+ installed_package_detail = package_result_list[0]
+ logging.info(f"{installed_package_detail.description} (version {installed_package_detail.version}) Detected")
+ return installed_package_detail
+
+ # Make sure the package name is available
+ package_result_list = self.is_package_available(package_install_path)
+ if not package_result_list:
+ raise common.LmbrCmdError(f"Invalid Android SDK Package {package_description}: Bad package path {package_install_path}")
+
+ # Reverse sort and pick the first item, which should be the latest (if the install path contains wildcards)
+ def _available_sort(item):
+ return item.path
+
+ package_result_list.sort(reverse=True, key=_available_sort)
+
+ available_package_to_install = package_result_list[0] # For multiple hits, resolve to the first item which will be the latest version
+
+ # Perform the package installation
+ logging.info(f"Installing {available_package_to_install.description} ...")
+ result_code, result_stdout, result_stderr = self.sdk_manager.exec(['--install', available_package_to_install.path], capture_stdout=True, suppress_stderr=True)
+ if result_code != 0:
+ raise common.LmbrCmdError(f"Error installing package {available_package_to_install.path}: \n{result_stderr}")
+
+ # Refresh the tracked SDK Contents
+ self.refresh_sdk_installation()
+
+ # Get the package details to verify
+ package_result_list = self.is_package_installed(package_install_path)
+ if package_result_list:
+ installed_package_detail = package_result_list[0]
+ logging.info(f"{installed_package_detail.description} (version {installed_package_detail.version}) Installed")
+ return installed_package_detail
+ else:
+ raise common.LmbrCmdError(f"Error installing package {available_package_to_install.path}: \n{result_stderr}")
+
diff --git a/cmake/Tools/Platform/Android/generate_android_project.py b/cmake/Tools/Platform/Android/generate_android_project.py
index 9a0e2760f5..d25b62dde8 100755
--- a/cmake/Tools/Platform/Android/generate_android_project.py
+++ b/cmake/Tools/Platform/Android/generate_android_project.py
@@ -27,7 +27,7 @@ from cmake.Tools import common
from cmake.Tools.Platform.Android import android_support
GRADLE_ARGUMENT_NAME = '--gradle-install-path'
-GRADLE_MIN_VERSION = LooseVersion('4.10.1')
+GRADLE_MIN_VERSION = LooseVersion('6.5')
GRADLE_MAX_VERSION = LooseVersion('7.0.0')
GRADLE_VERSION_REGEX = re.compile(r"Gradle\s(\d+.\d+.?\d*)")
GRADLE_EXECUTABLE = 'gradle.bat' if platform.system() == 'Windows' else 'gradle'
@@ -48,9 +48,9 @@ def verify_gradle(override_gradle_path=None):
CMAKE_ARGUMENT_NAME = '--cmake-install-path'
-CMAKE_MIN_VERSION = LooseVersion('3.17.0')
+CMAKE_MIN_VERSION = LooseVersion('3.19.0')
CMAKE_VERSION_REGEX = re.compile(r'cmake version (\d+.\d+.?\d*)')
-CMAKE_EXECUTABLE = 'cmake.exe' if platform.system() == 'Windows' else 'cmake'
+CMAKE_EXECUTABLE = 'cmake'
def verify_cmake(override_cmake_path=None):
@@ -69,7 +69,7 @@ def verify_cmake(override_cmake_path=None):
NINJA_ARGUMENT_NAME = '--ninja-install-path'
NINJA_VERSION_REGEX = re.compile(r'(\d+.\d+.?\d*)')
-NINJA_EXECUTABLE = 'ninja.exe' if platform.system() == 'Windows' else 'ninja'
+NINJA_EXECUTABLE = 'ninja'
def verify_ninja(override_ninja_path=None):
@@ -78,7 +78,7 @@ def verify_ninja(override_ninja_path=None):
"""
return common.verify_tool(override_tool_path=override_ninja_path,
tool_name='ninja',
- tool_filename='ninja.exe' if platform.system() == 'Windows' else 'ninja',
+ tool_filename='ninja',
argument_name=NINJA_ARGUMENT_NAME,
tool_version_argument='--version',
tool_version_regex=NINJA_VERSION_REGEX,
@@ -103,13 +103,21 @@ def build_optional_signing_profile(store_file, store_password, key_alias, key_pa
ANDROID_SDK_ARGUMENT_NAME = '--android-sdk-path'
-ANDROID_SDK_PLATFORM_ARGUMENT_NAME = '--android-sdk-version'
+ANDROID_SDK_PLATFORM_ARGUMENT_NAME = '--android-sdk-platform'
ANDROID_SDK_PREFERRED_TOOL_VER = '--android-sdk-build-tool-version'
+ANDROID_NATIVE_API_LEVEL = '--android-native-api-level'
+
+
+MIN_ANDROID_SDK_PLATFORM = 28 # The minimum platform/api level that is supported for the SDK Platform
+MIN_NATIVE_API_LEVEL = 24 # The minimum Native API level that is supported for the NDK
+
-ANDROID_NDK_ARGUMENT_NAME = '--android-ndk-path'
ANDROID_NDK_PLATFORM_ARGUMENT_NAME = '--android-ndk-version'
+ANDROID_GRADLE_PLUGIN_ARGUMENT_NAME = '--gradle-plugin-version'
+ANDROID_GRADLE_MIN_PLUGIN_VERSION = LooseVersion("4.2.0")
+
# Constants for asset-related options for APK generation
INCLUDE_APK_ASSETS_ARGUMENT_NAME = "--include-apk-assets"
ASSET_MODE_ARGUMENT_NAME = "--asset-mode"
@@ -147,6 +155,7 @@ def main(args):
parser = argparse.ArgumentParser(description="Prepare the android studio subfolder")
+ # Required Arguments
parser.add_argument('--engine-root',
help='The path to the engine root. Defaults to the current working directory.',
default=os.getcwd())
@@ -160,32 +169,42 @@ def main(args):
help='The path to the 3rd Party root directory',
required=True)
- parser.add_argument(ANDROID_NDK_ARGUMENT_NAME,
- help='The path to the android NDK',
- required=True)
-
parser.add_argument(ANDROID_SDK_ARGUMENT_NAME,
help='The path to the android SDK',
required=True)
- parser.add_argument(ANDROID_SDK_PLATFORM_ARGUMENT_NAME,
- help='The android SDK version',
+ parser.add_argument('-g', '--project-path',
+ help='The project path to generate an android project',
required=True)
+ parser.add_argument(ANDROID_SDK_PLATFORM_ARGUMENT_NAME,
+ help=f'The android SDK platform number version to use for the APK. (Minimum {MIN_ANDROID_SDK_PLATFORM})',
+ type=int,
+ default=-1)
+
+ parser.add_argument(ANDROID_NATIVE_API_LEVEL,
+ help=f'The android native API level to use for the APK. If not set, this will default to the android SDK platform. (Minimum {MIN_ANDROID_SDK_PLATFORM})',
+ type=int,
+ default=-1)
+
+ # Override arguments
parser.add_argument(ANDROID_SDK_PREFERRED_TOOL_VER,
- help='The preferred android sdk build version (i.e. 28.0.3). Will default to the first one detected under the android sdk',
- default=None,
+ help='The android SDK build tools version.',
required=False)
parser.add_argument(ANDROID_NDK_PLATFORM_ARGUMENT_NAME,
help='The android NDK version',
- required=True)
+ required=False)
parser.add_argument(GRADLE_ARGUMENT_NAME,
help=f'The path to installed gradle. The version of gradle must fall in between {str(GRADLE_MIN_VERSION)} and {str(GRADLE_MAX_VERSION)}.',
default=None,
required=False)
+ parser.add_argument(ANDROID_GRADLE_PLUGIN_ARGUMENT_NAME,
+ help=f'The version of the android gradle plugin to use. Defaults to the minimum version ({ANDROID_GRADLE_MIN_PLUGIN_VERSION})',
+ default=str(ANDROID_GRADLE_MIN_PLUGIN_VERSION))
+
parser.add_argument(CMAKE_ARGUMENT_NAME,
help=f'The path to cmake build tool if not installed on the system path. The version of cmake must be at least version {str(CMAKE_MIN_VERSION)}.',
default=None,
@@ -196,9 +215,6 @@ def main(args):
default=None,
required=False)
- parser.add_argument('-g', '--project-path',
- help='The project path to generate an android project')
-
# Asset Options
parser.add_argument(INCLUDE_APK_ASSETS_ARGUMENT_NAME,
action='store_true',
@@ -207,11 +223,11 @@ def main(args):
parser.add_argument(ASSET_MODE_ARGUMENT_NAME,
choices=ALL_ASSET_MODES,
default=ASSET_MODE_LOOSE,
- help='Asset Mode (vfs|pak|loose) to use when including assets into the APK')
+ help=f'Asset Mode (vfs|pak|loose) to use when including assets into the APK. (Defaults to {ASSET_MODE_LOOSE})')
parser.add_argument(ASSET_TYPE_ARGUMENT_NAME,
default=DEFAULT_ASSET_TYPE,
- help='Asset Type to use when including assets into the APK')
+ help=f'Asset Type to use when including assets into the APK. (Defaults to {DEFAULT_ASSET_TYPE})')
parser.add_argument('--debug',
action='store_true',
@@ -260,16 +276,81 @@ def main(args):
ninja_version, override_ninja_path = verify_ninja(override_ninja_path=parsed_args.get_argument(NINJA_ARGUMENT_NAME))
logging.info("Detected Ninja version %s", str(ninja_version))
- # Verify the android sdk path and sdk version
- verified_android_sdk_platform, verified_android_sdk_path, android_sdk_build_tool_ver = android_support.verify_android_sdk(android_sdk_platform=parsed_args.get_argument(ANDROID_SDK_PLATFORM_ARGUMENT_NAME),
- argument_name=ANDROID_SDK_ARGUMENT_NAME,
- override_android_sdk_path=parsed_args.get_argument(ANDROID_SDK_ARGUMENT_NAME),
- preferred_sdk_build_tools_ver=parsed_args.get_argument(ANDROID_SDK_PREFERRED_TOOL_VER))
+ # Get the android sdk platform version to use from the arguments, but also handle the deprecated argument name
+ android_sdk_platform_version = parsed_args.get_argument(ANDROID_SDK_PLATFORM_ARGUMENT_NAME)
- # Verify the android ndk path and ndk version
- verified_android_ndk_platform, verified_android_ndk_path = android_support.verify_android_ndk(android_ndk_platform=parsed_args.get_argument(ANDROID_NDK_PLATFORM_ARGUMENT_NAME),
- argument_name=ANDROID_NDK_ARGUMENT_NAME,
- override_android_ndk_path=parsed_args.get_argument(ANDROID_NDK_ARGUMENT_NAME))
+ # Get the gradle plugin details and validate against the current environment
+ android_gradle_plugin_version = parsed_args.get_argument(ANDROID_GRADLE_PLUGIN_ARGUMENT_NAME)
+ android_gradle_plugin = android_support.AndroidGradlePluginInfo(android_gradle_plugin_version)
+ logging.info(f"Generating Android Gradle Plugin version {android_gradle_plugin_version} based project")
+
+ if gradle_version < android_gradle_plugin.min_gradle_version:
+ raise common.LmbrCmdError(f"The current version of gradle ({gradle_version}) does not satisfy the minimum version "
+ f"({android_gradle_plugin.min_gradle_version}) needed for the android gradle plugin "
+ f"({android_gradle_plugin_version}). Please upgrade your gradle.")
+ if cmake_version < android_gradle_plugin.min_cmake_version:
+ raise common.LmbrCmdError(f"The current version of cmake ({cmake_version}) does not satisfy the minimum version "
+ f"({android_gradle_plugin.min_cmake_version}) needed for the android gradle plugin "
+ f"({android_gradle_plugin_version}). Please upgrade your cmake.")
+ if android_gradle_plugin.max_cmake_version and cmake_version > android_gradle_plugin.max_cmake_version:
+ raise common.LmbrCmdError(f"The current version of cmake ({cmake_version}) exceeds the maximum version "
+ f"({android_gradle_plugin.max_cmake_version}) of the android gradle plugin "
+ f"({android_gradle_plugin_version}).")
+
+ # Use the SDK Resolver to make sure the build tools and ndk
+ android_sdk = android_support.AndroidSDKResolver(android_sdk_path=parsed_args.get_argument(ANDROID_SDK_ARGUMENT_NAME))
+
+ # If no SDK platform is provided, check for any installed one
+ if android_sdk_platform_version < 0:
+ android_sdk_platform_version = MIN_ANDROID_SDK_PLATFORM
+ installed_android_sdk_platforms = android_sdk.is_package_installed('platforms;*')
+ if installed_android_sdk_platforms:
+ # If there are installed platforms, check the most recent one
+ latest_platform_version = -1
+ for installed_android_sdk_platform in installed_android_sdk_platforms:
+ platform_number_match = re.match(r'platforms;android-([0-9]*)', installed_android_sdk_platform.path)
+ if not platform_number_match:
+ continue
+ check_platform_version = int(platform_number_match.group(1))
+ if check_platform_version > latest_platform_version:
+ latest_platform_version = check_platform_version
+ if latest_platform_version >= MIN_ANDROID_SDK_PLATFORM:
+ android_sdk_platform_version = latest_platform_version
+ else:
+ if android_sdk_platform_version < MIN_ANDROID_SDK_PLATFORM:
+ raise common.LmbrCmdError(f"Invalid argument for {ANDROID_SDK_PLATFORM_ARGUMENT_NAME} ({android_sdk_platform_version}). Must be greater than the minimum value supported {MIN_ANDROID_SDK_PLATFORM}.")
+
+ # Get the android native api level from the arguments. Default to the sdk platform version if not provided
+ android_native_api_level = parsed_args.get_argument(ANDROID_NATIVE_API_LEVEL)
+ if android_native_api_level < 0:
+ android_native_api_level = android_sdk_platform_version
+ else:
+ if android_native_api_level < MIN_NATIVE_API_LEVEL:
+ raise common.LmbrCmdError(f"Invalid argument for {ANDROID_NATIVE_API_LEVEL} ({android_native_api_level}). Must be greater than the minimum value supported {MIN_NATIVE_API_LEVEL}.")
+
+ # Check and make sure that the requested sdk platform exists, download if necessary
+ platform_package_name = f"platforms;android-{android_sdk_platform_version}"
+ android_sdk.install_package(package_install_path=platform_package_name,
+ package_description=f'Android SDK Platform {android_sdk_platform_version}')
+
+ # Make sure we have the extra android packages "market_apk_expansion" and "market_licensing" which is needed by the APK
+ android_sdk.install_package(package_install_path='extras;google;market_apk_expansion',
+ package_description='Google APK Expansion Library')
+
+ android_sdk.install_package(package_install_path='extras;google;market_licensing',
+ package_description='Google Play Licensing Library')
+
+ # Install either the requested SDK build tools or the default one for the android gradle plugin version
+ build_tools_version = parsed_args.get_argument(ANDROID_SDK_PREFERRED_TOOL_VER) or android_gradle_plugin.default_sdk_build_tools_version
+ build_tools_package_name = f'build-tools;{build_tools_version}'
+ build_tools_package = android_sdk.install_package(package_install_path=build_tools_package_name,
+ package_description='Android SDK Build Tools')
+
+ # Install either the requested NDK version or the default one for the android gradle plugin version
+ android_ndk_version = parsed_args.get_argument(ANDROID_NDK_PLATFORM_ARGUMENT_NAME) or android_gradle_plugin.default_ndk_version
+ android_ndk_package_name = f'ndk;{android_ndk_version}'
+ android_ndk_package = android_sdk.install_package(package_install_path=android_ndk_package_name,
+ package_description='Android NDK')
# Verify the engine root path and project path
verified_project_path, verified_engine_root = common.verify_project_and_engine_root(project_root=parsed_args.project_path,
@@ -277,10 +358,9 @@ def main(args):
is_test_project = parsed_args.unit_test
# Verify the 3rd Party Root Path
- third_party_path = pathlib.Path(parsed_args.third_party_path) / '3rdParty.txt'
- if not third_party_path.is_file():
- raise common.LmbrCmdError("Invalid --third-party-path '{}'. Make sure it exists and contains "
- "3rdParty.txt".format(parsed_args.third_party_path),
+ third_party_path = pathlib.Path(parsed_args.third_party_path)
+ if not third_party_path.is_dir():
+ raise common.LmbrCmdError(f"Invalid --third-party-path '{parsed_args.third_party_path}'.",
common.ERROR_CODE_INVALID_PARAMETER)
third_party_path = third_party_path.parent
@@ -293,23 +373,23 @@ def main(args):
logging.debug("Engine Root : %s", str(verified_engine_root.resolve()))
logging.debug("Build Path : %s", str(build_dir.resolve()))
- logging.debug("Android NDK Path : %s", str(verified_android_ndk_path.resolve()))
- logging.debug("Android SDK Path : %s", str(verified_android_sdk_path.resolve()))
# Prepare the generator and execute
generator = android_support.AndroidProjectGenerator(engine_root=verified_engine_root,
- project_path=verified_project_path,
build_dir=build_dir,
- android_sdk_path=verified_android_sdk_path,
- android_ndk_path=verified_android_ndk_path,
- android_sdk_version=verified_android_sdk_platform,
- android_ndk_platform=verified_android_ndk_platform,
+ android_sdk_path=android_sdk.android_sdk_path,
+ build_tool=build_tools_package,
+ android_sdk_platform=android_sdk_platform_version,
+ android_native_api_level=android_native_api_level,
+ android_ndk=android_ndk_package,
+ project_path=verified_project_path,
third_party_path=third_party_path,
cmake_version=cmake_version,
override_cmake_path=override_cmake_path,
override_gradle_path=override_gradle_path,
+ gradle_version=gradle_version,
+ gradle_plugin_version=android_gradle_plugin_version,
override_ninja_path=override_ninja_path,
- android_sdk_build_tool_version=android_sdk_build_tool_ver,
include_assets_in_apk=parsed_args.get_argument(INCLUDE_APK_ASSETS_ARGUMENT_NAME),
asset_mode=parsed_args.get_argument(ASSET_MODE_ARGUMENT_NAME),
asset_type=parsed_args.get_argument(ASSET_TYPE_ARGUMENT_NAME),
diff --git a/cmake/Tools/Platform/Android/unit_test_generate_android_project.py b/cmake/Tools/Platform/Android/unit_test_generate_android_project.py
index 5598942046..0cd0f16eaf 100755
--- a/cmake/Tools/Platform/Android/unit_test_generate_android_project.py
+++ b/cmake/Tools/Platform/Android/unit_test_generate_android_project.py
@@ -170,117 +170,3 @@ def test_verify_ninja(tmpdir, from_override, version_str, expected_result):
finally:
subprocess.check_output = orig_check_output
-
-TEST_VALIDATE_VERSION_MIN = 19
-TEST_VALIDATE_VERSION_MAX = 21
-
-
-@pytest.mark.parametrize(
- "test_input, expected", [
- pytest.param('20', 20),
- pytest.param('android-20', 20),
- pytest.param('bad-21', "android-'XX'"),
- pytest.param('10', "minimum"),
- pytest.param('30', "maximum")
- ]
-)
-def test_validate_android_platform_input(test_input, expected):
- try:
- result = android_support.validate_android_platform_input(input_android_platform=test_input,
- platform_variable_type='test',
- min_version=TEST_VALIDATE_VERSION_MIN,
- max_version=TEST_VALIDATE_VERSION_MAX)
- assert isinstance(expected, int)
- assert result == expected
- except Exception as e:
- assert expected in str(e)
-
-
-def test_verify_android_sdk_success(tmpdir):
-
- test_android_path = 'android_sdk'
- sdk_version_number = 28
- sdk_version = f'android-{sdk_version_number}'
-
- tmpdir.ensure(f'{test_android_path}/platforms/{sdk_version}/package.xml')
-
- tmpdir.ensure(f'{test_android_path}/build-tools/28.0.3/package.xml')
- tmpdir.ensure(f'{test_android_path}/build-tools/29.0.3/package.xml')
-
- input_sdk_path = tmpdir.join(test_android_path).realpath()
- argument_name = '--android-sdk'
-
- requested_build_tool_version = '29.0.3'
-
- result_sdk_version, result_sdk_path, result_build_tool_version = android_support.verify_android_sdk(android_sdk_platform=sdk_version,
- argument_name=argument_name,
- override_android_sdk_path=input_sdk_path,
- preferred_sdk_build_tools_ver=requested_build_tool_version)
- assert result_sdk_version == sdk_version_number
- assert result_sdk_path == input_sdk_path
- assert result_build_tool_version == requested_build_tool_version
-
- sdk_version_number_only = str(sdk_version_number)
- result_sdk_version, result_sdk_path, result_build_tool_version = android_support.verify_android_sdk(android_sdk_platform=sdk_version_number_only,
- argument_name=argument_name,
- override_android_sdk_path=input_sdk_path)
- assert result_sdk_version == sdk_version_number
- assert result_sdk_path == input_sdk_path
- assert result_build_tool_version == '28.0.3'
-
- requested_build_tool_version = '30.0.3'
- result_sdk_version, result_sdk_path, result_build_tool_version = android_support.verify_android_sdk(android_sdk_platform=sdk_version,
- argument_name=argument_name,
- override_android_sdk_path=input_sdk_path,
- preferred_sdk_build_tools_ver=requested_build_tool_version)
- assert result_sdk_version == sdk_version_number
- assert result_sdk_path == input_sdk_path
- assert result_build_tool_version == '28.0.3'
-
-
-@pytest.mark.parametrize(
- "desired_ndk_version_number, available_ndk_revisions, pkg_revision, mappings, expect_error", [
- pytest.param(21, [21, 22, 24], '15.2.4203891', None, False, id='preNdk19ExactMatch'),
- pytest.param(23, [21, 22, 24], '15.2.4203891', None, False, id='preNdk19FallbackMatch'),
- pytest.param(22, [21, 22, 24], '19.2.4203891', {'23': 21}, False, id='postNdk19ExactMatch'),
- pytest.param(23, [21, 22, 24], '21.2.4203891', {'23': 21}, False, id='postNdk19MappingMatch'),
- pytest.param(android_support.ANDROID_NDK_MIN_PLATFORM-1, [21, 22, 24], '15.2.4203891', None, True, id='preNdk19BelowMinVer'),
- pytest.param(android_support.ANDROID_NDK_MAX_PLATFORM+1, [21, 22, 24], '15.2.4203891', None, True, id='preNdk19AboveMaxVer'),
- pytest.param(25, [21, 22, 24], '19.2.4203891', {'23': 21}, True, id='postNdk19NoMatch')
- ]
-)
-def test_verify_android_ndk_success(tmpdir, desired_ndk_version_number, available_ndk_revisions, pkg_revision, mappings, expect_error):
-
- test_android_path = 'android_ndk'
- for ndk_number in available_ndk_revisions:
- tmpdir.ensure(f'{test_android_path}/platforms/android-{ndk_number}/arch-arm64/usr/lib/libc.so')
-
- tmpdir.ensure(f'{test_android_path}/source.properties')
- test_ndk_source_properties_file = tmpdir / test_android_path / 'source.properties'
- test_ndk_source_properties_file.write_text(f'Pkg.Desc = Android NDK\nPkg.Revision = {pkg_revision}\n', encoding='ASCII')
-
- if mappings:
- platform_mapping = {
- # min and max are arbitrary for now since we dont use it during evaluation, but if we do, parameterize it here as well
- "min": 16, #
- "max": 29,
- "aliases": {}
- }
- for key, value in mappings.items():
- platform_mapping['aliases'][key] = value
- tmpdir.ensure(f'{test_android_path}/meta/platforms.json')
- platform_mapping_file = tmpdir / test_android_path / 'meta/platforms.json'
- platform_mapping_file.write_text(json.dumps(platform_mapping), encoding='ASCII')
-
- input_ndk_path = tmpdir.join(test_android_path).realpath()
-
- try:
- android_ndk_platform_number, android_ndk_path = android_support.verify_android_ndk(android_ndk_platform=str(desired_ndk_version_number),
- argument_name="--android-ndk",
- override_android_ndk_path=input_ndk_path)
- assert not expect_error
- assert android_ndk_platform_number == desired_ndk_version_number
- assert android_ndk_path == input_ndk_path
- except Exception:
- assert expect_error
-
diff --git a/cmake/Tools/common.py b/cmake/Tools/common.py
index c6a3e89e67..9c0d31cd53 100755
--- a/cmake/Tools/common.py
+++ b/cmake/Tools/common.py
@@ -55,6 +55,7 @@ ENGINE_ROOT_CHECK_FILE = 'engine.json'
HASH_CHUNK_SIZE = 200000
+
class LmbrCmdError(Exception):
"""
Wrapper class to the general exception class where will absorb and prevent the printing of stack.
@@ -244,6 +245,19 @@ def load_template_file(template_file_path, template_env):
raise FileNotFoundError(f"Invalid file path. Cannot find template file located at {str(template_file_path)}")
+# Determine the possible file extensions for executable files based on the host platform
+PLATFORM_EXECUTABLE_EXTENSIONS = [''] # Files without extensions are always considered
+
+if platform.system() == 'Windows':
+ # Windows manages its executable extensions through the %PATHEXT% environment variable
+ path_extensions_str = os.environ.get('PATHEXT', default='.EXE;.COM;.BAT;.CMD')
+ PLATFORM_EXECUTABLE_EXTENSIONS.extend([pathext.lower() for pathext in path_extensions_str.split(';')])
+elif platform.system() == 'Linux':
+ PLATFORM_EXECUTABLE_EXTENSIONS = ['', '.out']
+else:
+ PLATFORM_EXECUTABLE_EXTENSIONS = ['']
+
+
def verify_tool(override_tool_path, tool_name, tool_filename, argument_name, tool_version_argument, tool_version_regex, min_version, max_version):
"""
Support method to validate a required system tool needed for the build either through an installed tool in the
@@ -270,12 +284,21 @@ def verify_tool(override_tool_path, tool_name, tool_filename, argument_name, too
elif not isinstance(override_tool_path, pathlib.Path):
raise LmbrCmdError(f"Invalid {tool_name} path argument. '{override_tool_path}' must be a string or Path",
ERROR_CODE_INVALID_PARAMETER)
- check_tool_path = override_tool_path / tool_filename
- if not check_tool_path.is_file():
- check_tool_path = pathlib.Path(override_tool_path) / 'bin' / tool_filename
+ file_found = False
+ for executable_path_ext in PLATFORM_EXECUTABLE_EXTENSIONS:
+ check_tool_filename = f'{tool_filename}{executable_path_ext}'
- if not check_tool_path.is_file():
+ check_tool_path = override_tool_path / check_tool_filename
+ if check_tool_path.is_file():
+ file_found = True
+ break
+ check_tool_path = override_tool_path / 'bin' / check_tool_filename
+ if check_tool_path.is_file():
+ file_found = True
+ break
+
+ if not file_found:
raise LmbrCmdError(f"Invalid {tool_name} path argument. '{override_tool_path}' is not a valid {tool_name} path",
ERROR_CODE_INVALID_PARAMETER)
resolved_override_tool_path = str(check_tool_path.resolve())
@@ -284,7 +307,7 @@ def verify_tool(override_tool_path, tool_name, tool_filename, argument_name, too
else:
resolved_override_tool_path = None
tool_source = tool_name
- tool_desc = "installed gradle in the system path"
+ tool_desc = f"installed {tool_name} in the system path"
# Extract the version and verify
version_output = subprocess.check_output([tool_source, tool_version_argument],
@@ -296,10 +319,10 @@ def verify_tool(override_tool_path, tool_name, tool_filename, argument_name, too
result_version = LooseVersion(str(version_match.group(1)).strip())
if min_version and result_version < min_version:
- raise LmbrCmdError(f"The {tool_desc} does not meet the minimum version of gradle required ({str(min_version)}).",
+ raise LmbrCmdError(f"The {tool_desc} does not meet the minimum version of {tool_name} required ({str(min_version)}).",
ERROR_CODE_ENVIRONMENT_ERROR)
elif max_version and result_version > max_version:
- raise LmbrCmdError(f"The {tool_desc} exceeds maximum version of gradle supported ({str(max_version)}).",
+ raise LmbrCmdError(f"The {tool_desc} exceeds maximum version of {tool_name} supported ({str(max_version)}).",
ERROR_CODE_ENVIRONMENT_ERROR)
return result_version, resolved_override_tool_path
diff --git a/scripts/build/Platform/Android/build_config.json b/scripts/build/Platform/Android/build_config.json
index adaa417380..b871670cd0 100644
--- a/scripts/build/Platform/Android/build_config.json
+++ b/scripts/build/Platform/Android/build_config.json
@@ -141,10 +141,8 @@
"COMMAND":"gradle_windows.cmd",
"PARAMETERS": {
"CONFIGURATION":"profile",
- "OUTPUT_DIRECTORY":"build\\android_gradle",
+ "OUTPUT_DIRECTORY":"build\\ad_grd",
"GAME_PROJECT": "AutomatedTesting",
- "ANDROID_NDK_PLATFORM": "21",
- "ANDROID_SDK_PLATFORM": "29",
"SIGN_APK": "false",
"GRADLE_BUILD_CMD": "build",
"ADDITIONAL_GENERATE_ARGS": ""
@@ -158,8 +156,6 @@
"CONFIGURATION":"profile",
"OUTPUT_DIRECTORY":"build\\android_unittest",
"GAME_PROJECT": "AutomatedTesting",
- "ANDROID_NDK_PLATFORM": "21",
- "ANDROID_SDK_PLATFORM": "29",
"SIGN_APK": "true",
"GRADLE_BUILD_CMD": "assemble",
"ADDITIONAL_GENERATE_ARGS": "--unit-test"
diff --git a/scripts/build/Platform/Android/gradle_windows.cmd b/scripts/build/Platform/Android/gradle_windows.cmd
index 56423af95a..dd5285bdbf 100644
--- a/scripts/build/Platform/Android/gradle_windows.cmd
+++ b/scripts/build/Platform/Android/gradle_windows.cmd
@@ -17,20 +17,12 @@ IF NOT EXIST "%LY_3RDPARTY_PATH%" (
GOTO :error
)
-IF NOT EXIST "%GRADLE_HOME%" (
+IF NOT EXIST "%GRADLE_BUILD_HOME%" (
REM This is the default for developers
- SET GRADLE_HOME=C:\Gradle\gradle-5.6.4
+ SET GRADLE_BUILD_HOME=C:\Gradle\gradle-7.0
)
-IF NOT EXIST "%GRADLE_HOME%" (
- ECHO [ci_build] FAIL: GRADLE_HOME=%GRADLE_HOME%
- GOTO :error
-)
-
-IF NOT EXIST "%CMAKE_HOME%" (
- SET CMAKE_HOME=%LY_3RDPARTY_PATH%/CMake/3.19.1/Windows/
-)
-IF NOT EXIST "%CMAKE_HOME%" (
- ECHO [ci_build] FAIL: CMAKE_HOME=%CMAKE_HOME%
+IF NOT EXIST "%GRADLE_BUILD_HOME%" (
+ ECHO [ci_build] FAIL: GRADLE_BUILD_HOME=%GRADLE_BUILD_HOME%
GOTO :error
)
@@ -50,20 +42,9 @@ ECHO Ninja wasnt in the call path, add the value set by LY_NINJA_PATH
SET PATH=%PATH%;%LY_NINJA_PATH%
:ninja_on_path
-IF NOT EXIST "%LY_ANDROID_SDK%" (
- SET LY_ANDROID_SDK=!LY_3RDPARTY_PATH!/android-sdk/platform-29
-)
-IF NOT EXIST "%LY_ANDROID_SDK%" (
- ECHO [ci_build] FAIL: LY_ANDROID_SDK=!LY_ANDROID_SDK!
- GOTO :error
-)
-IF NOT EXIST "%LY_ANDROID_NDK%" (
- set LY_ANDROID_NDK=!LY_3RDPARTY_PATH!/android-ndk/r21d
-)
-IF NOT EXIST "%LY_ANDROID_NDK%" (
- ECHO [ci_build] LY_ANDROID_NDK=!LY_ANDROID_NDK!
- GOTO :error
+IF NOT "%ANDROID_GRADLE_PLUGIN%" == "" (
+ set ANDROID_GRADLE_PLUGIN_OPTION=--gradle-plugin-version=%ANDROID_GRADLE_PLUGIN%
)
IF NOT EXIST %OUTPUT_DIRECTORY% (
@@ -154,11 +135,11 @@ IF "%GENERATE_SIGNED_APK%"=="true" (
ECHO Using keystore file at %CI_ANDROID_KEYSTORE_FILE_ABS%
)
- ECHO [ci_build] %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_HOME% --cmake-install-path=%CMAKE_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-ndk-path=%LY_ANDROID_NDK% --android-sdk-path=%LY_ANDROID_SDK% --android-ndk-version=%ANDROID_NDK_PLATFORM% --android-sdk-version=%ANDROID_SDK_PLATFORM% --signconfig-store-file %CI_ANDROID_KEYSTORE_FILE_ABS% --signconfig-store-password %CI_ANDROID_KEYSTORE_PASSWORD% --signconfig-key-alias %CI_ANDROID_KEYSTORE_ALIAS% --signconfig-key-password %CI_ANDROID_KEYSTORE_PASSWORD% %OPTIONAL_TEST_FLAG% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
- CALL %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_HOME% --cmake-install-path=%CMAKE_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-ndk-path=%LY_ANDROID_NDK% --android-sdk-path=%LY_ANDROID_SDK% --android-ndk-version=%ANDROID_NDK_PLATFORM% --android-sdk-version=%ANDROID_SDK_PLATFORM% --signconfig-store-file %CI_ANDROID_KEYSTORE_FILE_ABS% --signconfig-store-password %CI_ANDROID_KEYSTORE_PASSWORD% --signconfig-key-alias %CI_ANDROID_KEYSTORE_ALIAS% --signconfig-key-password %CI_ANDROID_KEYSTORE_PASSWORD% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
+ ECHO [ci_build] %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_BUILD_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-sdk-path=%ANDROID_HOME% %ANDROID_GRADLE_PLUGIN_OPTION% --signconfig-store-file %CI_ANDROID_KEYSTORE_FILE_ABS% --signconfig-store-password %CI_ANDROID_KEYSTORE_PASSWORD% --signconfig-key-alias %CI_ANDROID_KEYSTORE_ALIAS% --signconfig-key-password %CI_ANDROID_KEYSTORE_PASSWORD% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
+ CALL %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_BUILD_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-sdk-path=%ANDROID_HOME% %ANDROID_GRADLE_PLUGIN_OPTION% --signconfig-store-file %CI_ANDROID_KEYSTORE_FILE_ABS% --signconfig-store-password %CI_ANDROID_KEYSTORE_PASSWORD% --signconfig-key-alias %CI_ANDROID_KEYSTORE_ALIAS% --signconfig-key-password %CI_ANDROID_KEYSTORE_PASSWORD% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
) ELSE (
- ECHO [ci_build] %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_HOME% --cmake-install-path=%CMAKE_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-ndk-path=%LY_ANDROID_NDK% --android-sdk-path=%LY_ANDROID_SDK% --android-ndk-version=%ANDROID_NDK_PLATFORM% --android-sdk-version=%ANDROID_SDK_PLATFORM% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
- CALL %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_HOME% --cmake-install-path=%CMAKE_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% --android-ndk-path=%LY_ANDROID_NDK% --android-sdk-path=%LY_ANDROID_SDK% --android-ndk-version=%ANDROID_NDK_PLATFORM% --android-sdk-version=%ANDROID_SDK_PLATFORM% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
+ ECHO [ci_build] %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% %GRADLE_OVERRIDE_OPTION% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% %ANDROID_GRADLE_PLUGIN_OPTION% --android-sdk-path=%ANDROID_HOME% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
+ CALL %PYTHON% cmake\Tools\Platform\Android\generate_android_project.py --engine-root=. --build-dir=%OUTPUT_DIRECTORY% -g %GAME_PROJECT% --gradle-install-path=%GRADLE_BUILD_HOME% --ninja-install-path=%LY_NINJA_PATH% --third-party-path=%LY_3RDPARTY_PATH% %ANDROID_GRADLE_PLUGIN_OPTION% --android-sdk-path=%ANDROID_HOME% %ADDITIONAL_GENERATE_ARGS% --overwrite-existing
)
REM Validate the android project generation
diff --git a/scripts/build/Platform/Android/pipeline.json b/scripts/build/Platform/Android/pipeline.json
index ed10e7022d..551374a027 100644
--- a/scripts/build/Platform/Android/pipeline.json
+++ b/scripts/build/Platform/Android/pipeline.json
@@ -1,7 +1,7 @@
{
"ENV": {
- "GRADLE_HOME": "C:/Gradle/gradle-5.6.4",
- "NODE_LABEL": "windows-047e5cdf",
+ "GRADLE_HOME": "C:/Gradle/gradle-7.0",
+ "NODE_LABEL": "windows-b3c8994f1",
"LY_3RDPARTY_PATH": "C:/ly/3rdParty",
"TIMEOUT": 30,
"WORKSPACE": "D:/workspace",