Merge remote-tracking branch 'origin' into MultiplayerComponents

This commit is contained in:
karlberg
2021-06-02 14:57:00 -07:00
640 changed files with 17532 additions and 12712 deletions
+20 -3
View File
@@ -29,6 +29,9 @@ ly_add_target(
Gem::HttpRequestor
3rdParty::AWSNativeSDK::AWSClientAuth
3rdParty::AWSNativeSDK::Core
RUNTIME_DEPENDENCIES
Gem::AWSCore
Gem::HttpRequestor
)
ly_add_target(
@@ -44,13 +47,23 @@ ly_add_target(
AZ::AzCore
AZ::AzFramework
Gem::AWSCore
Gem::HttpRequestor
3rdParty::AWSNativeSDK::AWSClientAuth
3rdParty::AWSNativeSDK::Core
PUBLIC
Gem::AWSClientAuth.Static
RUNTIME_DEPENDENCIES
Gem::AWSCore
Gem::HttpRequestor
)
# Load the "Gem::AWSClientAuth" module in all types of applications.
ly_create_alias(NAME AWSClientAuth.Servers NAMESPACE Gem TARGETS Gem::AWSClientAuth)
ly_create_alias(NAME AWSClientAuth.Clients NAMESPACE Gem TARGETS Gem::AWSClientAuth)
if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME AWSClientAuth.Tools NAMESPACE Gem TARGETS Gem::AWSClientAuth)
ly_create_alias(NAME AWSClientAuth.Builders NAMESPACE Gem TARGETS Gem::AWSClientAuth)
endif()
################################################################################
# Tests
################################################################################
@@ -71,10 +84,14 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
3rdParty::AWSNativeSDK::AWSClientAuth
AZ::AzCore
AZ::AzFramework
Gem::AWSCore
Gem::AWSClientAuth.Static
AZ::AWSNativeSDKInit
Gem::AWSClientAuth.Static
Gem::AWSCore
Gem::HttpRequestor
RUNTIME_DEPENDENCIES
Gem::AWSCore
AZ::AWSNativeSDKInit
Gem::HttpRequestor
)
ly_add_googletest(
NAME Gem::AWSClientAuth.Tests
+11 -4
View File
@@ -45,6 +45,10 @@ ly_add_target(
Gem::AWSCore.Static
)
# clients and servers will use the above Gem::AWSCore module.
ly_create_alias(NAME AWSCore.Servers NAMESPACE Gem TARGETS Gem::AWSCore)
ly_create_alias(NAME AWSCore.Clients NAMESPACE Gem TARGETS Gem::AWSCore)
if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_target(
NAME AWSCore.Editor.Static STATIC
@@ -75,14 +79,12 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
INCLUDE_DIRECTORIES
PRIVATE
Include/Private
COMPILE_DEFINITIONS
PRIVATE
AWSCORE_EDITOR
BUILD_DEPENDENCIES
PRIVATE
AZ::AzCore
Gem::AWSCore.Static
Gem::AWSCore.Editor.Static
RUNTIME_DEPENDENCIES
Gem::AWSCore
)
ly_add_target(
@@ -99,6 +101,11 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
Gem::AWSCore.Editor.Static
)
ly_add_dependencies(AWSCore.Editor AWSCore.ResourceMappingTool)
# Builders and Tools (such as the Editor use AWSCore.Editor) use the .Editor module above.
ly_create_alias(NAME AWSCore.Tools NAMESPACE Gem TARGETS Gem::AWSCore.Editor)
ly_create_alias(NAME AWSCore.Builders NAMESPACE Gem TARGETS Gem::AWSCore.Editor)
endif()
################################################################################
@@ -11,15 +11,15 @@
#pragma once
#include <AWSCoreModule.h>
#include <AzCore/Module/Module.h>
namespace AWSCore
{
class AWSCoreEditorModule
: public AWSCoreModule
:public AZ::Module
{
public:
AZ_RTTI(AWSCoreEditorModule, "{C1C9B898-848B-4C2F-A7AA-69642D12BCB5}", AWSCoreModule);
AZ_RTTI(AWSCoreEditorModule, "{C1C9B898-848B-4C2F-A7AA-69642D12BCB5}", AZ::Module);
AZ_CLASS_ALLOCATOR(AWSCoreEditorModule, AZ::SystemAllocator, 0);
AWSCoreEditorModule();
@@ -38,6 +38,11 @@ namespace AWSCore
//! @return The path of AWS resource mapping config file
virtual AZStd::string GetResourceMappingConfigFilePath() const = 0;
//! GetResourceMappingConfigFolderPath
//! Get the path of AWS resource mapping config folder
//! @return The path of AWS resource mapping config folder
virtual AZStd::string GetResourceMappingConfigFolderPath() const = 0;
//! ReloadConfiguration
//! Reload AWSCore configuration without restarting application
virtual void ReloadConfiguration() = 0;
@@ -53,6 +53,7 @@ namespace AWSCore
// AWSCoreInternalRequestBus interface implementation
AZStd::string GetResourceMappingConfigFilePath() const override;
AZStd::string GetResourceMappingConfigFolderPath() const override;
AZStd::string GetProfileName() const override;
void ReloadConfiguration() override;
@@ -18,7 +18,7 @@ namespace AWSCore
class AWSCoreEditorManager
{
public:
static constexpr const char CLOUD_SERVICES_MENU_TEXT[] = "&Cloud services";
static constexpr const char AWS_MENU_TEXT[] = "&AWS";
AWSCoreEditorManager();
virtual ~AWSCoreEditorManager();
@@ -0,0 +1,53 @@
/*
* 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
namespace AWSCore
{
static constexpr const char NewToAWSUrl[] = "https://docs.o3de.org/docs/user-guide/gems/reference/aws/";
static constexpr const char AWSAndScriptCanvasUrl[] = "https://docs.o3de.org/docs/user-guide/components/reference/aws/";
static constexpr const char AWSAndComponentsUrl[] = "https://docs.o3de.org/docs/user-guide/components/reference/aws/";
static constexpr const char CallAWSResourcesUrl[] = "https://docs.o3de.org/docs/user-guide/components/reference/aws/";
static constexpr const char AWSCredentialConfigurationUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-core/configuring-credentials/";
static constexpr const char AWSClientAuthGemOverviewUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
static constexpr const char AWSClientAuthCDKAndResourcesUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
static constexpr const char AWSClientAuthScriptCanvasAndLuaUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
static constexpr const char AWSClientAuth3rdPartyAuthProviderUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
static constexpr const char AWSClientAuthCustomAuthProviderUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
static constexpr const char AWSClientAuthPlatformSpecificUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
static constexpr const char AWSClientAuthAPIReferenceUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/";
static constexpr const char AWSMetricsGemOverviewUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
static constexpr const char AWSMetricsSetupGemUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
static constexpr const char AWSMetricsScriptingUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
static constexpr const char AWSMetricsAPIReferenceUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
static constexpr const char AWSMetricsAdvancedTopicsUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
static constexpr const char AWSMetricsSettingsUrl[] =
"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/";
} // namespace AWSCore
@@ -0,0 +1,44 @@
/*
* 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
namespace AWSCore
{
static constexpr const char NewToAWSActionText[] = "Getting started with AWS?";
static constexpr const char AWSAndO3DEGlobalDocsText[] = "AWS & O3DE global docs";
static constexpr const char AWSAndScriptCanvasActionText[] = "AWS && ScriptCanvas";
static constexpr const char AWSAndComponentsActionText[] = "AWS & Components";
static constexpr const char CallAWSResourcesActionText[] = "Call AWS resources";
static constexpr const char AWSCredentialConfigurationActionText[] = "AWS credential configuration";
static constexpr const char AWSResourceMappingToolActionText[] = "AWS Resource Mapping Tool...";
static constexpr const char AWSClientAuthActionText[] = "Client Auth";
static constexpr const char AWSClientAuthGemOverviewActionText[] = "Gem Overview";
static constexpr const char AWSClientAuthCDKAndResourcesActionText[] = "CDK Application and Resource Mappings";
static constexpr const char AWSClientAuthScriptCanvasAndLuaActionText[] = "Script Canvas and Lua";
static constexpr const char AWSClientAuth3rdPartyAuthProviderActionText[] = "3rd Party developer Authentication Provider support";
static constexpr const char AWSClientAuthCustomAuthProviderActionText[] = "Custom developer Authentication Provider support";
static constexpr const char AWSClientAuthPlatformSpecificActionText[] = "Platform specific Callouts";
static constexpr const char AWSClientAuthAPIReferenceActionText[] = "API Reference";
static constexpr const char AWSMetricsActionText[] = "Metrics";
static constexpr const char AWSMetricsGemOverviewActionText[] = "Metrics Overview";
static constexpr const char AWSMetricsSetupGemActionText[] = "Setup Metrics Gem";
static constexpr const char AWSMetricsScriptingActionText[] = "Scripting with AWS Metrics";
static constexpr const char AWSMetricsAPIReferenceActionText[] = "C++ API with AWS Metrics Gem";
static constexpr const char AWSMetricsAdvancedTopicsActionText[] = "Advanced topics";
static constexpr const char AWSMetricsSettingsActionText[] = "Metrics Settings";
} // namespace AWSCore
@@ -35,29 +35,23 @@ namespace AWSCore
static constexpr const char AWSResourceMappingToolIsRunningText[] = "Resource Mapping Tool is running...";
static constexpr const char AWSResourceMappingToolLogWarningText[] =
"Failed to launch Resource Mapping Tool, please check <a href=\"file:///%s\">logs</a> for details.";
static constexpr const char AWSResourceMappingToolActionText[] = "AWS Resource Mapping Tool...";
static constexpr const char CredentialConfigurationActionText[] = "Credential Configuration";
static constexpr const char CredentialConfigurationUrl[] = "https://docs.aws.amazon.com/sdk-for-cpp/v1/developer-guide/credentials.html";
static constexpr const char NewToAWSActionText[] = "New to AWS?";
static constexpr const char NewToAWSUrl[] = "https://o3deorg.netlify.app/docs/user-guide/gems/reference/aws";
static constexpr const char AWSAndScriptCanvasActionText[] = "AWS && ScriptCanvas";
static constexpr const char AWSAndScriptCanvasUrl[] = "https://o3deorg.netlify.app/docs/user-guide/gems/reference/aws";
static constexpr const char AWSClientAuthActionText[] = "Client Auth";
static constexpr const char AWSMetricsActionText[] = "Metrics";
AWSCoreEditorMenu(const QString& text);
~AWSCoreEditorMenu();
private:
QAction* AddExternalLinkAction(const AZStd::string& name, const AZStd::string& url, const AZStd::string& icon = "");
void InitializeResourceMappingToolAction();
void InitializeAWSDocActions();
void InitializeAWSGlobalDocsSubMenu();
void InitializeAWSFeatureGemActions();
// AWSCoreEditorRequestBus interface implementation
void SetAWSClientAuthEnabled() override;
void SetAWSMetricsEnabled() override;
void SetAWSFeatureActionsEnabled(const AZStd::string actionText);
QMenu* SetAWSFeatureSubMenu(const AZStd::string& menuText);
// To improve experience, use process watcher to keep track of ongoing tool process
AZStd::unique_ptr<AzFramework::ProcessWatcher> m_resourceMappingToolWatcher;
@@ -15,7 +15,6 @@
namespace AWSCore
{
AWSCoreEditorModule::AWSCoreEditorModule()
: AWSCoreModule()
{
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
m_descriptors.insert(m_descriptors.end(), {
@@ -28,10 +27,9 @@ namespace AWSCore
*/
AZ::ComponentTypeList AWSCoreEditorModule::GetRequiredSystemComponents() const
{
AZ::ComponentTypeList requiredComponents = AWSCoreModule::GetRequiredSystemComponents();
requiredComponents.push_back(azrtti_typeid<AWSCoreEditorSystemComponent>());
return requiredComponents;
return AZ::ComponentTypeList{
azrtti_typeid<AWSCoreEditorSystemComponent>()
};
}
}
@@ -40,9 +40,7 @@ namespace AWSCore
}
#if !defined(AWSCORE_EDITOR)
// DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM
// The first parameter should be GemName_GemIdLower
// The second should be the fully qualified name of the class above
AZ_DECLARE_MODULE_CLASS(Gem_AWSCore, AWSCore::AWSCoreModule)
#endif
@@ -58,6 +58,19 @@ namespace AWSCore
return configFilePath;
}
AZStd::string AWSCoreConfiguration::GetResourceMappingConfigFolderPath() const
{
if (m_sourceProjectFolder.empty())
{
AZ_Warning(AWSCoreConfigurationName, false, ProjectSourceFolderNotFoundErrorMessage);
return "";
}
AZStd::string configFolderPath = AZStd::string::format(
"%s/%s", m_sourceProjectFolder.c_str(), AWSCoreResourceMappingConfigFolderName);
AzFramework::StringFunc::Path::Normalize(configFolderPath);
return configFolderPath;
}
void AWSCoreConfiguration::InitConfig()
{
InitSourceProjectFolderPath();
@@ -123,7 +136,7 @@ namespace AWSCore
auto profileNamePath = AZStd::string::format("%s%s",
AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreProfileNameKey);
m_settingsRegistry.Remove(profileNamePath);
m_profileName.clear();
m_profileName = AWSCoreDefaultProfileName;
auto resourceMappingConfigFileNamePath = AZStd::string::format("%s%s",
AZ::SettingsRegistryMergeUtils::OrganizationRootKey, AWSCoreResourceMappingConfigFileNameKey);
@@ -16,7 +16,7 @@
namespace AWSCore
{
AWSCoreEditorManager::AWSCoreEditorManager()
: m_awsCoreEditorMenu(new AWSCoreEditorMenu(CLOUD_SERVICES_MENU_TEXT))
: m_awsCoreEditorMenu(new AWSCoreEditorMenu(AWS_MENU_TEXT))
{
}
@@ -13,10 +13,13 @@
#include <AzCore/Debug/Trace.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/Jobs/JobFunction.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzFramework/Process/ProcessWatcher.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AWSCoreEditor_Traits_Platform.h>
#include <Editor/Constants/AWSCoreEditorMenuLinks.h>
#include <Editor/Constants/AWSCoreEditorMenuNames.h>
#include <Editor/UI/AWSCoreEditorMenu.h>
#include <Editor/UI/AWSCoreResourceMappingToolAction.h>
@@ -36,8 +39,8 @@ namespace AWSCore
: QMenu(text)
, m_resourceMappingToolWatcher(nullptr)
{
InitializeResourceMappingToolAction();
InitializeAWSDocActions();
InitializeResourceMappingToolAction();
this->addSeparator();
InitializeAWSFeatureGemActions();
@@ -58,6 +61,21 @@ namespace AWSCore
this->clear();
}
QAction* AWSCoreEditorMenu::AddExternalLinkAction(
const AZStd::string& name, const AZStd::string& url, const AZStd::string& icon)
{
QAction* linkAction = new QAction(QObject::tr(name.c_str()));
QObject::connect(linkAction, &QAction::triggered, this,
[url]() {
QDesktopServices::openUrl(QUrl(url.c_str()));
});
if (!icon.empty())
{
linkAction->setIcon(QIcon(icon.c_str()));
}
return linkAction;
}
void AWSCoreEditorMenu::InitializeResourceMappingToolAction()
{
#ifdef AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED
@@ -103,21 +121,21 @@ namespace AWSCore
void AWSCoreEditorMenu::InitializeAWSDocActions()
{
QAction* credentialConfiguration = new QAction(QObject::tr(CredentialConfigurationActionText));
QObject::connect(credentialConfiguration, &QAction::triggered, this, []() {
QDesktopServices::openUrl(QUrl(CredentialConfigurationUrl));
});
this->addAction(credentialConfiguration);
this->addAction(AddExternalLinkAction(NewToAWSActionText, NewToAWSUrl, ":/Notifications/link.svg"));
QAction* newToAWS = new QAction(QObject::tr(NewToAWSActionText));
QObject::connect(newToAWS, &QAction::triggered, this, []() {
QDesktopServices::openUrl(QUrl(NewToAWSUrl)); });
this->addAction(newToAWS);
InitializeAWSGlobalDocsSubMenu();
QAction* awsAndScriptCanvas = new QAction(QObject::tr(AWSAndScriptCanvasActionText));
QObject::connect(awsAndScriptCanvas, &QAction::triggered, this, []() {
QDesktopServices::openUrl(QUrl(AWSAndScriptCanvasUrl)); });
this->addAction(awsAndScriptCanvas);
this->addAction(AddExternalLinkAction(
AWSCredentialConfigurationActionText, AWSCredentialConfigurationUrl, ":/Notifications/link.svg"));
}
void AWSCoreEditorMenu::InitializeAWSGlobalDocsSubMenu()
{
QMenu* globalDocsMenu = this->addMenu(QObject::tr(AWSAndO3DEGlobalDocsText));
globalDocsMenu->addAction(AddExternalLinkAction(AWSAndScriptCanvasActionText, AWSAndScriptCanvasUrl, ":/Notifications/link.svg"));
globalDocsMenu->addAction(AddExternalLinkAction(AWSAndComponentsActionText, AWSAndComponentsUrl, ":/Notifications/link.svg"));
globalDocsMenu->addAction(AddExternalLinkAction(CallAWSResourcesActionText, CallAWSResourcesUrl, ":/Notifications/link.svg"));
}
void AWSCoreEditorMenu::InitializeAWSFeatureGemActions()
@@ -135,25 +153,67 @@ namespace AWSCore
void AWSCoreEditorMenu::SetAWSClientAuthEnabled()
{
SetAWSFeatureActionsEnabled(AWSClientAuthActionText);
// TODO: instead of creating submenu in core editor, aws feature gem should return submenu component directly
QMenu* subMenu = SetAWSFeatureSubMenu(AWSClientAuthActionText);
subMenu->addAction(AddExternalLinkAction(
AWSClientAuthGemOverviewActionText, AWSClientAuthGemOverviewUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSClientAuthCDKAndResourcesActionText, AWSClientAuthCDKAndResourcesUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSClientAuthScriptCanvasAndLuaActionText, AWSClientAuthScriptCanvasAndLuaUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSClientAuth3rdPartyAuthProviderActionText, AWSClientAuth3rdPartyAuthProviderUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSClientAuthCustomAuthProviderActionText, AWSClientAuthCustomAuthProviderUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSClientAuthPlatformSpecificActionText, AWSClientAuthPlatformSpecificUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSClientAuthAPIReferenceActionText, AWSClientAuthAPIReferenceUrl, ":/Notifications/link.svg"));
}
void AWSCoreEditorMenu::SetAWSMetricsEnabled()
{
SetAWSFeatureActionsEnabled(AWSMetricsActionText);
// TODO: instead of creating submenu in core editor, aws feature gem should return submenu component directly
QMenu* subMenu = SetAWSFeatureSubMenu(AWSMetricsActionText);
subMenu->addAction(AddExternalLinkAction(
AWSMetricsGemOverviewActionText, AWSMetricsGemOverviewUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSMetricsSetupGemActionText, AWSMetricsSetupGemUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSMetricsScriptingActionText, AWSMetricsScriptingUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSMetricsAPIReferenceActionText, AWSMetricsAPIReferenceUrl, ":/Notifications/link.svg"));
subMenu->addAction(AddExternalLinkAction(
AWSMetricsAdvancedTopicsActionText, AWSMetricsAdvancedTopicsUrl, ":/Notifications/link.svg"));
AZStd::string priorAlias = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devroot@");
AZStd::string configFilePath = priorAlias + "\\Gems\\AWSMetrics\\Code\\" + AZ::SettingsRegistryInterface::RegistryFolder;
AzFramework::StringFunc::Path::Normalize(configFilePath);
QAction* settingsAction = new QAction(QObject::tr(AWSMetricsSettingsActionText));
QObject::connect(settingsAction, &QAction::triggered, this,
[configFilePath](){
QDesktopServices::openUrl(QUrl::fromLocalFile(configFilePath.c_str()));
});
subMenu->addAction(settingsAction);
}
void AWSCoreEditorMenu::SetAWSFeatureActionsEnabled(const AZStd::string actionText)
QMenu* AWSCoreEditorMenu::SetAWSFeatureSubMenu(const AZStd::string& menuText)
{
auto actionList = this->actions();
for (QList<QAction*>::iterator itr = actionList.begin(); itr != actionList.end(); itr++)
{
if (QString::compare((*itr)->text(), actionText.c_str()) == 0)
if (QString::compare((*itr)->text(), menuText.c_str()) == 0)
{
(*itr)->setIcon(QIcon(QString(":/Notifications/checkmark.svg")));
(*itr)->setEnabled(true);
break;
QMenu* subMenu = new QMenu(QObject::tr(menuText.c_str()));
subMenu->setIcon(QIcon(QString(":/Notifications/checkmark.svg")));
this->insertMenu(*itr, subMenu);
this->removeAction(*itr);
return subMenu;
}
}
return nullptr;
}
} // namespace AWSCore
@@ -14,6 +14,7 @@
#include <AzCore/Utils/Utils.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AWSCoreInternalBus.h>
#include <Editor/UI/AWSCoreResourceMappingToolAction.h>
namespace AWSCore
@@ -108,17 +109,24 @@ namespace AWSCore
{
return "";
}
AZStd::string profileName = "default";
AWSCoreInternalRequestBus::BroadcastResult(profileName, &AWSCoreInternalRequests::GetProfileName);
AZStd::string configPath = "";
AWSCoreInternalRequestBus::BroadcastResult(configPath, &AWSCoreInternalRequests::GetResourceMappingConfigFolderPath);
if (m_isDebug)
{
return AZStd::string::format(
"%s debug %s --binaries_path %s --debug",
m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str());
"%s debug %s --binaries_path %s --debug --profile %s --config_path %s", m_enginePythonEntryPath.c_str(),
m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), profileName.c_str(), configPath.c_str());
}
else
{
return AZStd::string::format(
"%s %s --binaries_path %s",
m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str());
"%s %s --binaries_path %s --profile %s --config_path %s", m_enginePythonEntryPath.c_str(),
m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), profileName.c_str(), configPath.c_str());
}
}
@@ -85,7 +85,7 @@ TEST_F(AWSCoreEditorSystemComponentTest, NotifyMainWindowInitialized_HaveDummyMe
testMenuBar->addMenu("dummy menu");
AzToolsFramework::EditorEvents::Bus::Broadcast(&AzToolsFramework::EditorEvents::NotifyMainWindowInitialized, &testMainWindow);
EXPECT_TRUE(testMenuBar->actions().size() == 2);
EXPECT_TRUE(QString::compare(testMenuBar->actions()[1]->text(), AWSCoreEditorManager::CLOUD_SERVICES_MENU_TEXT) == 0);
EXPECT_TRUE(QString::compare(testMenuBar->actions()[1]->text(), AWSCoreEditorManager::AWS_MENU_TEXT) == 0);
}
TEST_F(AWSCoreEditorSystemComponentTest, NotifyMainWindowInitialized_HaveHelpMenuInMenuBar_ExpectedMenuGetsAddedAtFront)
@@ -95,5 +95,5 @@ TEST_F(AWSCoreEditorSystemComponentTest, NotifyMainWindowInitialized_HaveHelpMen
testMenuBar->addMenu(AWSCoreEditorSystemComponent::EDITOR_HELP_MENU_TEXT);
AzToolsFramework::EditorEvents::Bus::Broadcast(&AzToolsFramework::EditorEvents::NotifyMainWindowInitialized, &testMainWindow);
EXPECT_TRUE(testMenuBar->actions().size() == 2);
EXPECT_TRUE(QString::compare(testMenuBar->actions()[0]->text(), AWSCoreEditorManager::CLOUD_SERVICES_MENU_TEXT) == 0);
EXPECT_TRUE(QString::compare(testMenuBar->actions()[0]->text(), AWSCoreEditorManager::AWS_MENU_TEXT) == 0);
}
@@ -34,7 +34,8 @@ public:
MOCK_METHOD0(GetAWSCredentials, Aws::Auth::AWSCredentials());
};
class AWSDefaultCredentialHandlerMock : public AWSDefaultCredentialHandler
class AWSDefaultCredentialHandlerMock
: public AWSDefaultCredentialHandler
{
public:
void SetupMocks(
@@ -76,6 +77,7 @@ public:
// AWSCoreInternalRequestBus interface implementation
AZStd::string GetProfileName() const override { return m_profileName; }
AZStd::string GetResourceMappingConfigFilePath() const override { return ""; }
AZStd::string GetResourceMappingConfigFolderPath() const override { return ""; }
void ReloadConfiguration() override {}
std::shared_ptr<EnvironmentAWSCredentialsProviderMock> m_environmentCredentialsProviderMock;
@@ -14,6 +14,7 @@
#include <AWSCoreBus.h>
#include <AWSCoreEditor_Traits_Platform.h>
#include <Editor/Constants/AWSCoreEditorMenuNames.h>
#include <Editor/UI/AWSCoreEditorMenu.h>
#include <Editor/UI/AWSCoreEditorUIFixture.h>
#include <TestFramework/AWSCoreFixture.h>
@@ -35,6 +36,7 @@ class AWSCoreEditorMenuTest
{
AWSCoreEditorUIFixture::SetUp();
AWSCoreFixture::SetUp();
m_localFileIO->SetAlias("@devroot@", "dummy engine root");
}
void TearDown() override
@@ -77,12 +79,12 @@ TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_BroadcastFeatureGemsAreEnabled_C
QList<QAction*> actualActions = testMenu.actions();
for (QList<QAction*>::iterator itr = actualActions.begin(); itr != actualActions.end(); itr++)
{
if (QString::compare((*itr)->text(), AWSCoreEditorMenu::AWSClientAuthActionText) == 0)
if (QString::compare((*itr)->text(), AWSClientAuthActionText) == 0)
{
EXPECT_TRUE((*itr)->isEnabled());
}
if (QString::compare((*itr)->text(), AWSCoreEditorMenu::AWSMetricsActionText) == 0)
if (QString::compare((*itr)->text(), AWSMetricsActionText) == 0)
{
EXPECT_TRUE((*itr)->isEnabled());
}
@@ -119,6 +119,7 @@ public:
// AWSCoreInternalRequestBus interface implementation
AZStd::string GetProfileName() const override { return ""; }
AZStd::string GetResourceMappingConfigFilePath() const override { return m_normalizedConfigFilePath; }
AZStd::string GetResourceMappingConfigFolderPath() const override { return m_normalizedConfigFolderPath; }
void ReloadConfiguration() override { m_reloadConfigurationCounter++; }
AZStd::unique_ptr<AWSCore::AWSResourceMappingManager> m_resourceMappingManager;
@@ -48,11 +48,14 @@ class ConfigurationManager(object):
def configuration(self, new_configuration: ConfigurationManager) -> None:
self._configuration = new_configuration
def setup(self) -> None:
def setup(self, config_path: str) -> None:
logger.info("Setting up default configuration ...")
# TODO: remove config directory and files default setup once integrating with user input
try:
self._configuration.config_directory = file_utils.get_current_directory_path()
normalized_config_path: str = file_utils.normalize_file_path(config_path);
if normalized_config_path:
self._configuration.config_directory = normalized_config_path
else:
self._configuration.config_directory = file_utils.get_current_directory_path()
self._configuration.config_files = \
file_utils.find_files_with_suffix_under_directory(self._configuration.config_directory,
constants.RESOURCE_MAPPING_CONFIG_FILE_NAME_SUFFIX)
@@ -13,13 +13,16 @@ from argparse import (ArgumentParser, Namespace)
import logging
import sys
from utils import aws_utils
from utils import environment_utils
from utils import file_utils
# arguments setup
argument_parser: ArgumentParser = ArgumentParser()
argument_parser.add_argument('--binaries_path', help='Path to QT Binaries necessary for PySide.')
argument_parser.add_argument('--config_path', help='Path to resource mapping config directory.')
argument_parser.add_argument('--debug', action='store_true', help='Execute on debug mode to enable DEBUG logging level')
argument_parser.add_argument('--profile', default='default', help='Named AWS profile to use for querying AWS resources')
arguments: Namespace = argument_parser.parse_args()
# logging setup
@@ -70,9 +73,12 @@ if __name__ == "__main__":
except FileNotFoundError:
logger.warning("Failed to load style sheet for resource mapping tool")
logger.info("Initializing boto3 default session ...")
aws_utils.setup_default_session(arguments.profile)
logger.info("Initializing configuration manager ...")
configuration_manager: ConfigurationManager = ConfigurationManager()
configuration_manager.setup()
configuration_manager.setup(arguments.config_path)
logger.info("Initializing thread manager ...")
thread_manager: ThreadManager = ThreadManager()
@@ -43,7 +43,7 @@ class TestConfigurationManager(TestCase):
mock_find_files_with_suffix_under_directory: MagicMock,
mock_get_default_account_id: MagicMock,
mock_get_default_region: MagicMock) -> None:
TestConfigurationManager._expected_configuration_manager.setup()
TestConfigurationManager._expected_configuration_manager.setup("")
mock_get_current_directory_path.assert_called_once()
mock_check_path_exists.assert_called_once_with(TestConfigurationManager._expected_directory_path)
mock_find_files_with_suffix_under_directory.assert_called_once_with(
@@ -58,3 +58,29 @@ class TestConfigurationManager(TestCase):
TestConfigurationManager._expected_account_id
assert TestConfigurationManager._expected_configuration_manager.configuration.region == \
TestConfigurationManager._expected_region
@patch("utils.aws_utils.get_default_region", return_value=_expected_region)
@patch("utils.aws_utils.get_default_account_id", return_value=_expected_account_id)
@patch("utils.file_utils.find_files_with_suffix_under_directory", return_value=_expected_config_files)
@patch("utils.file_utils.check_path_exists", return_value=True)
@patch("utils.file_utils.normalize_file_path", return_value=_expected_directory_path)
def test_setup_get_configuration_setup_with_path_as_expected(self, mock_normalize_file_path: MagicMock,
mock_check_path_exists: MagicMock,
mock_find_files_with_suffix_under_directory: MagicMock,
mock_get_default_account_id: MagicMock,
mock_get_default_region: MagicMock) -> None:
TestConfigurationManager._expected_configuration_manager.setup(TestConfigurationManager._expected_directory_path)
mock_normalize_file_path.assert_called_once()
mock_check_path_exists.assert_called_once_with(TestConfigurationManager._expected_directory_path)
mock_find_files_with_suffix_under_directory.assert_called_once_with(
TestConfigurationManager._expected_directory_path, constants.RESOURCE_MAPPING_CONFIG_FILE_NAME_SUFFIX)
mock_get_default_account_id.assert_called_once()
mock_get_default_region.assert_called_once()
assert TestConfigurationManager._expected_configuration_manager.configuration.config_directory == \
TestConfigurationManager._expected_directory_path
assert TestConfigurationManager._expected_configuration_manager.configuration.config_files == \
TestConfigurationManager._expected_config_files
assert TestConfigurationManager._expected_configuration_manager.configuration.account_id == \
TestConfigurationManager._expected_account_id
assert TestConfigurationManager._expected_configuration_manager.configuration.region == \
TestConfigurationManager._expected_region
@@ -36,7 +36,7 @@ class TestViewManager(TestCase):
main_window_patcher: patch = patch("manager.view_manager.QMainWindow")
cls._mock_main_window = main_window_patcher.start()
window_icon_patcher: patch = patch("manager.view_manager.QPixmap")
window_icon_patcher: patch = patch("manager.view_manager.QIcon")
window_icon_patcher.start()
stacked_pages_patcher: patch = patch("manager.view_manager.QStackedWidget")
@@ -37,13 +37,12 @@ class TestAWSUtils(TestCase):
.build()
def setUp(self) -> None:
client_patcher: patch = patch("boto3.client")
self.addCleanup(client_patcher.stop)
self._mock_client: MagicMock = client_patcher.start()
session_patcher: patch = patch("boto3.session.Session")
self.addCleanup(session_patcher.stop)
self._mock_session: MagicMock = session_patcher.start()
self._mock_client: MagicMock = self._mock_session.return_value.client
aws_utils.setup_default_session("default")
def test_get_default_account_id_return_expected_account_id(self) -> None:
mocked_sts_client: MagicMock = self._mock_client.return_value
@@ -26,6 +26,8 @@ aws account, region, resources, etc.
_PAGINATION_MAX_ITEMS: int = 10
_PAGINATION_PAGE_SIZE: int = 10
default_session: boto3.session.Session = None
class AWSConstants(object):
CLOUDFORMATION_SERVICE_NAME: str = "cloudformation"
@@ -53,15 +55,20 @@ def _close_client_connection(client: BaseClient) -> None:
def _initialize_boto3_aws_client(service: str, region: str = "") -> BaseClient:
if region:
boto3_client: BaseClient = boto3.client(service, region_name=region)
boto3_client: BaseClient = default_session.client(service, region_name=region)
else:
boto3_client: BaseClient = boto3.client(service)
boto3_client: BaseClient = default_session.client(service)
boto3_client.meta.events.register(
f"after-call.{service}.*", lambda **kwargs: _close_client_connection(boto3_client)
)
return boto3_client
def setup_default_session(profile: str) -> None:
global default_session
default_session = boto3.session.Session(profile_name=profile)
def get_default_account_id() -> str:
sts_client: BaseClient = _initialize_boto3_aws_client(AWSConstants.STS_SERVICE_NAME)
try:
@@ -72,7 +79,7 @@ def get_default_account_id() -> str:
def get_default_region() -> str:
region: str = boto3.session.Session().region_name
region: str = default_session.region_name
if region:
return region
@@ -12,6 +12,8 @@
set(FILES
Include/Private/AWSCoreEditorSystemComponent.h
Include/Private/Editor/AWSCoreEditorManager.h
Include/Private/Editor/Constants/AWSCoreEditorMenuLinks.h
Include/Private/Editor/Constants/AWSCoreEditorMenuNames.h
Include/Private/Editor/UI/AWSCoreEditorMenu.h
Include/Private/Editor/UI/AWSCoreResourceMappingToolAction.h
Source/AWSCoreEditorSystemComponent.cpp
@@ -11,7 +11,5 @@
set(FILES
Include/Private/AWSCoreEditorModule.h
Include/Private/AWSCoreModule.h
Source/AWSCoreEditorModule.cpp
Source/AWSCoreModule.cpp
)
+13 -2
View File
@@ -23,6 +23,7 @@ ly_add_target(
PRIVATE
AZ::AzCore
AZ::AzFramework
PUBLIC
Gem::AWSCore
)
@@ -40,10 +41,19 @@ ly_add_target(
PRIVATE
AZ::AzCore
AZ::AzFramework
Gem::AWSCore
Gem::AWSMetrics.Static
RUNTIME_DEPENDENCIES
Gem::AWSCore
)
# Load the "Gem::AWSMetrics" module in all types of applications.
ly_create_alias(NAME AWSMetrics.Servers NAMESPACE Gem TARGETS Gem::AWSMetrics)
ly_create_alias(NAME AWSMetrics.Clients NAMESPACE Gem TARGETS Gem::AWSMetrics)
if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_create_alias(NAME AWSMetrics.Tools NAMESPACE Gem TARGETS Gem::AWSMetrics)
ly_create_alias(NAME AWSMetrics.Builders NAMESPACE Gem TARGETS Gem::AWSMetrics)
endif()
################################################################################
# Tests
################################################################################
@@ -63,8 +73,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
AZ::AzTest
AZ::AzCore
AZ::AzFramework
Gem::AWSCore
Gem::AWSMetrics.Static
RUNTIME_DEPENDENCIES
Gem::AWSCore
)
ly_add_googletest(
NAME Gem::AWSMetrics.Tests
@@ -111,8 +111,7 @@ class BatchProcessing:
self._events_firehose_delivery_stream = kinesisfirehose.CfnDeliveryStream(
self._stack,
id='EventsFirehoseDeliveryStream',
delivery_stream_name=f'{self._stack.stack_name}-EventsFirehoseDeliveryStream',
id=f'{self._stack.stack_name}-EventsFirehoseDeliveryStream',
delivery_stream_type='KinesisStreamAsSource',
kinesis_stream_source_configuration=kinesisfirehose.CfnDeliveryStream.KinesisStreamSourceConfigurationProperty(
kinesis_stream_arn=self._input_stream_arn,
@@ -327,7 +326,7 @@ class BatchProcessing:
@property
def delivery_stream_name(self) -> kinesisfirehose.CfnDeliveryStream.delivery_stream_name:
return self._events_firehose_delivery_stream.delivery_stream_name
return self._events_firehose_delivery_stream.ref
@property
def delivery_stream_role_arn(self) -> iam.Role.role_arn:
@@ -73,14 +73,14 @@ class DataIngestion:
api_id_output = core.CfnOutput(
self._stack,
id='RestApiId',
id='RESTApiId',
description='Service API Id for the analytics pipeline',
export_name=f"{application_name}:RestApiId",
value=self._rest_api.rest_api_id)
stage_output = core.CfnOutput(
self._stack,
id='DeploymentStage',
id='RESTApiStage',
description='Stage for the REST API deployment',
export_name=f"{application_name}:DeploymentStage",
value=self._rest_api.deployment_stage.stage_name)
+3
View File
@@ -44,3 +44,6 @@ ly_add_target(
PRIVATE
Gem::Achievements.Static
)
# we'll load the above "Gem::Achievements" module in clients only.
ly_create_alias(NAME Achievements.Clients NAMESPACE Gem TARGETS Gem::Achievements)
@@ -43,6 +43,10 @@ ly_add_target(
Gem::ImGui
)
# AssetMemoryAnalyzer is available in clients and servers.
ly_create_alias(NAME AssetMemoryAnalyzer.Clients NAMESPACE Gem TARGETS Gem::AssetMemoryAnalyzer)
ly_create_alias(NAME AssetMemoryAnalyzer.Servers NAMESPACE Gem TARGETS Gem::AssetMemoryAnalyzer)
################################################################################
# Tests
################################################################################
@@ -65,3 +69,4 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
NAME Gem::AssetMemoryAnalyzer.Tests
)
endif()
+5
View File
@@ -65,3 +65,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
NAME Gem::AssetValidation.Tests
)
endif()
# AssetValidation should be active in all clients plus tools
ly_create_alias(NAME AssetValidation.Clients NAMESPACE Gem TARGETS Gem::AssetValidation)
ly_create_alias(NAME AssetValidation.Tools NAMESPACE Gem TARGETS Gem::AssetValidation)
@@ -0,0 +1,10 @@
{
"gem_name": "ImageProcessingAtom",
"display_name": "Atom Image Processing",
"summary": "",
"canonical_tags": [
"Gem"
],
"user_tags": [
]
}
+10
View File
@@ -0,0 +1,10 @@
{
"gem_name": "AtomShader",
"display_name": "Atom Shader Builder",
"summary": "",
"canonical_tags": [
"Gem"
],
"user_tags": [
]
}
+10
View File
@@ -0,0 +1,10 @@
{
"gem_name": "Atom_Bootstrap",
"display_name": "Atom Bootstrap",
"summary": "",
"canonical_tags": [
"Gem"
],
"user_tags": [
]
}
+10
View File
@@ -0,0 +1,10 @@
{
"gem_name": "Atom_Component_DebugCamera",
"display_name": "Atom Debug Camera Component",
"summary": "",
"canonical_tags": [
"Gem"
],
"user_tags": [
]
}
@@ -469,7 +469,7 @@
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_depthFactor"
"id": "m_heightmapScale"
}
},
{
@@ -479,18 +479,7 @@
"type": "Image",
"connection": {
"type": "ShaderInput",
"id": "m_depthMap"
}
},
{
"id": "invert",
"displayName": "Invert",
"description": "Invert to depthmap if the texture is heightmap",
"type": "Bool",
"defaultValue": true,
"connection": {
"type": "ShaderInput",
"id": "m_depthInverted"
"id": "m_heightmap"
}
},
{
@@ -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,25 +935,25 @@
"parallax": [
{
"id": "textureMap",
"displayName": "Texture Map",
"description": "Depthmap to create parallax effect.",
"displayName": "Height Map",
"description": "Displacement height map to create parallax effect.",
"type": "Image",
"connection": {
"type": "ShaderInput",
"id": "m_depthMap"
"id": "m_heightmap"
}
},
{
"id": "useTexture",
"displayName": "Use Texture",
"description": "Whether to use the texture map.",
"description": "Whether to use the height map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
"description": "Depth texture map UV set",
"description": "Height map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -964,15 +964,15 @@
},
{
"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,
"softMax": 0.1,
"connection": {
"type": "ShaderInput",
"id": "m_depthFactor"
"id": "m_heightmapScale"
}
},
{
@@ -985,18 +985,7 @@
"softMax": 0.1,
"connection": {
"type": "ShaderInput",
"id": "m_depthOffset"
}
},
{
"id": "invert",
"displayName": "Invert",
"description": "Invert to depthmap if the texture is heightmap",
"type": "Bool",
"defaultValue": true,
"connection": {
"type": "ShaderInput",
"id": "m_depthInverted"
"id": "m_heightmapOffset"
}
},
{
@@ -1037,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": {
@@ -1074,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",
@@ -1084,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
},
@@ -1153,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",
@@ -1182,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 ]
},
@@ -1257,7 +1246,7 @@
{
"id": "enableDetailMaskTexture",
"displayName": " Use Texture",
"description": "Enable detail mask texture",
"description": "Enable detail blend mask",
"type": "Bool",
"defaultValue": true
},
@@ -1276,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",
@@ -1294,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",
@@ -1318,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
},
@@ -1337,8 +1326,8 @@
},
{
"id": "normalDetailMap",
"displayName": " Texture Map",
"description": "Detailed Normal Texture map",
"displayName": " Texture",
"description": "Detailed Normal map",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -1647,7 +1636,7 @@
{
"type": "Lua",
"args": {
"file": "StandardPBR_SubsurfaceState.lua"
"file": "EnhancedPBR_SubsurfaceState.lua"
}
},
{
@@ -108,7 +108,7 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial
// Callback function for ParallaxMapping.azsli
DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy)
{
return SampleDepthOrHeightMap(MaterialSrg::m_depthInverted, MaterialSrg::m_depthMap, MaterialSrg::m_sampler, uv, uv_ddx, uv_ddy);
return SampleDepthFromHeightmap(MaterialSrg::m_heightmap, MaterialSrg::m_sampler, uv, uv_ddx, uv_ddy);
}
COMMON_OPTIONS_PARALLAX()
@@ -116,7 +116,7 @@ COMMON_OPTIONS_PARALLAX()
bool ShouldHandleParallax()
{
// Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scattering is enabled.
return !o_enableSubsurfaceScattering && o_parallax_feature_enabled && o_useDepthMap;
return !o_enableSubsurfaceScattering && o_parallax_feature_enabled && o_useHeightmap;
}
bool ShouldHandleParallaxInDepthShaders()
@@ -84,7 +84,7 @@ PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace)
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor, MaterialSrg::m_depthOffset,
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth);
}
@@ -141,7 +141,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor, MaterialSrg::m_depthOffset,
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth, IN.m_position.w, displacementIsClipped);
@@ -88,7 +88,7 @@ PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace)
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor, MaterialSrg::m_depthOffset,
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth);
@@ -22,15 +22,14 @@
// You can optionally provide a prefix for the set of inputs which corresponds to a prefix string supplied by the .materialtype file. This is common for multi-layered material types.
#define COMMON_SRG_INPUTS_PARALLAX(prefix) \
Texture2D prefix##m_depthMap; \
float prefix##m_depthFactor; \
float prefix##m_depthOffset; \
bool prefix##m_depthInverted;
Texture2D prefix##m_heightmap; \
float prefix##m_heightmapScale; \
float prefix##m_heightmapOffset;
#define COMMON_OPTIONS_PARALLAX(prefix) \
option bool prefix##o_useDepthMap;
option bool prefix##o_useHeightmap;
void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float depthFactor, float depthOffset,
void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float heightmapScale, float heightmapOffset,
float4x4 objectWorldMatrix, float3x3 uvMatrix, float3x3 uvMatrixInverse,
inout float2 uv, inout float3 worldPosition, inout float depthNDC, inout float depthCS, out bool isClipped)
{
@@ -48,8 +47,8 @@ void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float dep
dirToCamera = ViewSrg::m_worldPosition.xyz - worldPosition;
}
ParallaxOffset tangentOffset = GetParallaxOffset( depthFactor,
depthOffset,
ParallaxOffset tangentOffset = GetParallaxOffset( heightmapScale,
-heightmapOffset,
uv,
dirToCamera,
tangent,
@@ -62,7 +61,7 @@ void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float dep
if(o_parallax_enablePixelDepthOffset)
{
PixelDepthOffset pdo = CalcPixelDepthOffset(depthFactor,
PixelDepthOffset pdo = CalcPixelDepthOffset(heightmapScale,
tangentOffset.m_offsetTS,
worldPosition,
tangent,
@@ -81,19 +80,19 @@ void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float dep
}
}
void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float depthFactor, float depthOffset,
void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float heightmapScale, float heightmapOffset,
float4x4 objectWorldMatrix, float3x3 uvMatrix, float3x3 uvMatrixInverse,
inout float2 uv, inout float3 worldPosition, inout float depthNDC, inout float depthCS)
{
bool isClipped;
GetParallaxInput(normal, tangent, bitangent, depthFactor, depthOffset, objectWorldMatrix, uvMatrix, uvMatrixInverse, uv, worldPosition, depthNDC, depthCS, isClipped);
GetParallaxInput(normal, tangent, bitangent, heightmapScale, heightmapOffset, objectWorldMatrix, uvMatrix, uvMatrixInverse, uv, worldPosition, depthNDC, depthCS, isClipped);
}
void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float depthFactor, float depthOffset,
void GetParallaxInput(float3 normal, float3 tangent, float3 bitangent, float heightmapScale, float heightmapOffset,
float4x4 objectWorldMatrix, float3x3 uvMatrix, float3x3 uvMatrixInverse,
inout float2 uv, inout float3 worldPosition, inout float depthNDC)
{
float depthCS;
GetParallaxInput(normal, tangent, bitangent, depthFactor, depthOffset, objectWorldMatrix, uvMatrix, uvMatrixInverse, uv, worldPosition, depthNDC, depthCS);
GetParallaxInput(normal, tangent, bitangent, heightmapScale, heightmapOffset, objectWorldMatrix, uvMatrix, uvMatrixInverse, uv, worldPosition, depthNDC, depthCS);
}
@@ -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",
@@ -1080,7 +1080,7 @@
{
"type": "Lua",
"args": {
"file": "StandardPBR_SubsurfaceState.lua"
"file": "EnhancedPBR_SubsurfaceState.lua"
}
},
{
File diff suppressed because it is too large Load Diff
@@ -379,7 +379,7 @@ float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy)
// layer1
{
if(o_layer1_o_useDepthMap)
if(o_layer1_o_useHeightmap)
{
float2 layerUv = uv;
if(MaterialSrg::m_parallaxUvIndex == 0)
@@ -387,16 +387,16 @@ float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy)
layerUv = mul(MaterialSrg::m_layer1_m_uvMatrix, float3(uv, 1.0)).xy;
}
layerDepthValues.r = SampleDepthOrHeightMap(MaterialSrg::m_layer1_m_depthInverted, MaterialSrg::m_layer1_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth;
layerDepthValues.r *= MaterialSrg::m_layer1_m_depthFactor;
layerDepthValues.r = SampleDepthFromHeightmap(MaterialSrg::m_layer1_m_heightmap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth;
layerDepthValues.r *= MaterialSrg::m_layer1_m_heightmapScale;
}
layerDepthValues.r -= MaterialSrg::m_layer1_m_depthOffset;
layerDepthValues.r -= MaterialSrg::m_layer1_m_heightmapOffset;
}
if(o_layer2_enabled)
{
if(o_layer2_o_useDepthMap)
if(o_layer2_o_useHeightmap)
{
float2 layerUv = uv;
if(MaterialSrg::m_parallaxUvIndex == 0)
@@ -404,17 +404,17 @@ float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy)
layerUv = mul(MaterialSrg::m_layer2_m_uvMatrix, float3(uv, 1.0)).xy;
}
layerDepthValues.g = SampleDepthOrHeightMap(MaterialSrg::m_layer2_m_depthInverted, MaterialSrg::m_layer2_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth;
layerDepthValues.g *= MaterialSrg::m_layer2_m_depthFactor;
layerDepthValues.g = SampleDepthFromHeightmap(MaterialSrg::m_layer2_m_heightmap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth;
layerDepthValues.g *= MaterialSrg::m_layer2_m_heightmapScale;
}
layerDepthValues.g -= MaterialSrg::m_layer2_m_depthOffset;
layerDepthValues.g -= MaterialSrg::m_layer2_m_heightmapOffset;
}
if(o_layer3_enabled)
{
if(o_layer3_o_useDepthMap)
if(o_layer3_o_useHeightmap)
{
float2 layerUv = uv;
if(MaterialSrg::m_parallaxUvIndex == 0)
@@ -422,11 +422,11 @@ float3 GetLayerDepthValues(float2 uv, float2 uv_ddx, float2 uv_ddy)
layerUv = mul(MaterialSrg::m_layer3_m_uvMatrix, float3(uv, 1.0)).xy;
}
layerDepthValues.b = SampleDepthOrHeightMap(MaterialSrg::m_layer3_m_depthInverted, MaterialSrg::m_layer3_m_depthMap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth;
layerDepthValues.b *= MaterialSrg::m_layer3_m_depthFactor;
layerDepthValues.b = SampleDepthFromHeightmap(MaterialSrg::m_layer3_m_heightmap, MaterialSrg::m_sampler, layerUv, uv_ddx, uv_ddy).m_depth;
layerDepthValues.b *= MaterialSrg::m_layer3_m_heightmapScale;
}
layerDepthValues.b -= MaterialSrg::m_layer3_m_depthOffset;
layerDepthValues.b -= MaterialSrg::m_layer3_m_heightmapOffset;
}
@@ -448,13 +448,13 @@ float3 ApplyBlendMaskToDepthValues(float3 blendMaskValues, float3 layerDepthValu
if(o_layer2_enabled)
{
float dropoffRange = MaterialSrg::m_layer2_m_depthOffset - zeroMaskDisplacement;
float dropoffRange = MaterialSrg::m_layer2_m_heightmapOffset - zeroMaskDisplacement;
layerDepthValues.g += dropoffRange * (1-blendMaskValues.r);
}
if(o_layer3_enabled)
{
float dropoffRange = MaterialSrg::m_layer3_m_depthOffset - zeroMaskDisplacement;
float dropoffRange = MaterialSrg::m_layer3_m_heightmapOffset - zeroMaskDisplacement;
layerDepthValues.b += dropoffRange * (1-blendMaskValues.g);
}
}
@@ -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,15 +38,25 @@
"displayName": "Emissive",
"description": "Properties to add light emission, independent of other lights in the scene."
},
{
"id": "clearCoat",
"displayName": "Clear Coat",
"description": "Properties for configuring gloss clear coat"
},
{
"id": "parallax",
"displayName": "Parallax Mapping",
"description": "Properties for parallax effect produced by depthmap."
"displayName": "Displacement",
"description": "Properties for parallax effect produced by a height map."
},
{
"id": "subsurfaceScattering",
"displayName": "Subsurface Scattering",
"description": "Properties for configuring subsurface scattering effects."
"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
@@ -71,7 +66,7 @@
},
{
"id": "general",
"displayName": "General",
"displayName": "General Settings",
"description": "General settings."
}
],
@@ -182,7 +177,7 @@
},
{
"id": "textureMap",
"displayName": "Texture Map",
"displayName": "Texture",
"description": "Base color texture map",
"type": "Image",
"connection": {
@@ -193,14 +188,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 +207,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 +233,7 @@
},
{
"id": "textureMap",
"displayName": "Texture Map",
"displayName": "Texture",
"description": "",
"type": "Image",
"connection": {
@@ -249,14 +244,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 +264,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 +275,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 +295,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 +309,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 +350,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 +361,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 +413,7 @@
{
"id": "influenceMap",
"displayName": " Influence Map",
"description": "Strength factor texture map",
"description": "Strength factor texture",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -428,14 +423,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 +455,7 @@
{
"id": "roughnessMap",
"displayName": " Roughness Map",
"description": "Roughness texture map",
"description": "Texture for defining surface roughness",
"type": "Image",
"connection": {
"type": "ShaderInput",
@@ -470,14 +465,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 +514,7 @@
{
"id": "normalMapUv",
"displayName": " UV",
"description": "Normal texture map UV set",
"description": "Normal map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -532,8 +527,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 +538,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 +594,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 +606,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 +617,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 +628,7 @@
{
"id": "textureMapUv",
"displayName": "UV",
"description": "Opacity texture map UV set",
"description": "Opacity map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -728,7 +723,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 +733,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 +765,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 +775,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 +845,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 +856,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,25 +876,25 @@
"parallax": [
{
"id": "textureMap",
"displayName": "Texture Map",
"description": "Depthmap to create parallax effect.",
"displayName": "Height Map",
"description": "Displacement height map to create parallax effect.",
"type": "Image",
"connection": {
"type": "ShaderInput",
"id": "m_depthMap"
"id": "m_heightmap"
}
},
{
"id": "useTexture",
"displayName": "Use Texture",
"description": "Whether to use the texture map.",
"description": "Whether to use the height map.",
"type": "Bool",
"defaultValue": true
},
{
"id": "textureMapUv",
"displayName": "UV",
"description": "Depth texture map UV set",
"description": "Height map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
@@ -910,15 +905,15 @@
},
{
"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,
"softMax": 0.1,
"connection": {
"type": "ShaderInput",
"id": "m_depthFactor"
"id": "m_heightmapScale"
}
},
{
@@ -931,18 +926,7 @@
"softMax": 0.1,
"connection": {
"type": "ShaderInput",
"id": "m_depthOffset"
}
},
{
"id": "invert",
"displayName": "Invert",
"description": "Invert to depthmap if the texture is heightmap",
"type": "Bool",
"defaultValue": true,
"connection": {
"type": "ShaderInput",
"id": "m_depthInverted"
"id": "m_heightmapOffset"
}
},
{
@@ -983,7 +967,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": {
@@ -992,183 +976,6 @@
}
}
],
"subsurfaceScattering": [
{
"id": "enableSubsurfaceScattering",
"displayName": "Subsurface Scattering",
"description": "Enable subsurface scattering feature, this will disable metallic and parallax mapping property due to incompatibility",
"type": "Bool",
"defaultValue": false,
"connection": {
"type": "ShaderOption",
"id": "o_enableSubsurfaceScattering"
}
},
{
"id": "subsurfaceScatterFactor",
"displayName": " Factor",
"description": "Strength factor for scaling percentage of subsurface scattering effect applied",
"type": "float",
"defaultValue": 1.0,
"min": 0.0,
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_subsurfaceScatteringFactor"
}
},
{
"id": "influenceMap",
"displayName": " Influence Map",
"description": "Use texture map to control the strength of subsurface scattering",
"type": "Image",
"connection": {
"type": "ShaderInput",
"id": "m_subsurfaceScatteringInfluenceMap"
}
},
{
"id": "useInfluenceMap",
"displayName": " Use Influence Map",
"description": "Whether to use the texture map as influence mask.",
"type": "Bool",
"defaultValue": true
},
{
"id": "influenceMapUv",
"displayName": " UV",
"description": "Influence map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
"connection": {
"type": "ShaderInput",
"id": "m_subsurfaceScatteringInfluenceMapUvIndex"
}
},
{
"id": "scatterColor",
"displayName": " Scatter color",
"description": "Color of volume light traveled through",
"type": "Color",
"defaultValue": [ 1.0, 0.27, 0.13 ]
},
{
"id": "scatterDistance",
"displayName": " Scatter distance",
"description": "How far light traveled inside the volume",
"type": "float",
"defaultValue": 8,
"min": 0.0,
"softMax": 20.0
},
{
"id": "quality",
"displayName": " Quality",
"description": "How much percent of sample will be used for each pixel, more samples improve quality and reduce artifacts, especially when the scatter distance is relatively large, but slow down computation time, 1.0 = full set 200 samples per pixel",
"type": "float",
"defaultValue": 0.4,
"min": 0.2,
"max": 1.0,
"connection": {
"type": "ShaderInput",
"id": "m_subsurfaceScatteringQuality"
}
},
{
"id": "transmissionMode",
"displayName": "Transmission",
"description": "Algorithm used for calculating transmission",
"type": "Enum",
"enumValues": [ "None", "ThickObject", "ThinObject" ],
"defaultValue": "None",
"connection": {
"type": "ShaderOption",
"id": "o_transmission_mode"
}
},
{
"id": "thickness",
"displayName": " Thickness",
"description": "Normalized global thickness, the maxima between this value (multiplied by thickness map if enabled) and thickness from shadow map (if applicable) will be used as final thickness of pixel",
"type": "float",
"defaultValue": 0.5,
"min": 0.0,
"max": 1.0
},
{
"id": "thicknessMap",
"displayName": " Thickness Map",
"description": "Use a greyscale texture for per pixel thickness",
"type": "Image",
"connection": {
"type": "ShaderInput",
"id": "m_transmissionThicknessMap"
}
},
{
"id": "useThicknessMap",
"displayName": " Use Thickness Map",
"description": "Whether to use the thickness map",
"type": "Bool",
"defaultValue": true
},
{
"id": "thicknessMapUv",
"displayName": " UV",
"description": "Thickness map UV set",
"type": "Enum",
"enumIsUv": true,
"defaultValue": "Tiled",
"connection": {
"type": "ShaderInput",
"id": "m_transmissionThicknessMapUvIndex"
}
},
{
"id": "transmissionTint",
"displayName": " Transmission Tint",
"description": "Color of the volume light travelling through",
"type": "Color",
"defaultValue": [ 1.0, 0.8, 0.6 ]
},
{
"id": "transmissionPower",
"displayName": " Power",
"description": "How much transmitted light scatter radially ",
"type": "float",
"defaultValue": 6.0,
"min": 0.0,
"softMax": 20.0
},
{
"id": "transmissionDistortion",
"displayName": " Distortion",
"description": "How much light direction distorted towards surface normal",
"type": "float",
"defaultValue": 0.1,
"min": 0.0,
"max": 1.0
},
{
"id": "transmissionAttenuation",
"displayName": " Attenuation",
"description": "How fast transmitted light fade with thickness",
"type": "float",
"defaultValue": 4.0,
"min": 0.0,
"softMax": 20.0
},
{
"id": "transmissionScale",
"displayName": " Scale",
"description": "Strength of transmission",
"type": "float",
"defaultValue": 3.0,
"min": 0.0,
"softMax": 20.0
}
],
"irradiance": [
// Note: this property group is used in the DiffuseGlobalIllumination pass and not by the main forward shader
{
@@ -1272,25 +1079,6 @@
"nitMinMax": [0.001, 100000.0]
}
},
{
// Preprocess & build parameter set for subsurface scattering and translucency
"type": "HandleSubsurfaceScatteringParameters",
"args": {
"mode": "subsurfaceScattering.transmissionMode",
"scale": "subsurfaceScattering.transmissionScale",
"power": "subsurfaceScattering.transmissionPower",
"distortion": "subsurfaceScattering.transmissionDistortion",
"attenuation": "subsurfaceScattering.transmissionAttenuation",
"tintColor": "subsurfaceScattering.transmissionTint",
"thickness": "subsurfaceScattering.thickness",
"enabled": "subsurfaceScattering.enableSubsurfaceScattering",
"scatterDistanceColor": "subsurfaceScattering.scatterColor",
"scatterDistanceIntensity": "subsurfaceScattering.scatterDistance",
"scatterDistanceShaderInput": "m_scatterDistance",
"parametersShaderInput": "m_transmissionParams",
"tintThickenssShaderInput": "m_transmissionTintThickness"
}
},
{
"type": "UseTexture",
"args": {
@@ -1375,12 +1163,6 @@
"file": "StandardPBR_Roughness.lua"
}
},
{
"type": "Lua",
"args": {
"file": "StandardPBR_SubsurfaceState.lua"
}
},
{
"type": "Lua",
"args": {
@@ -73,31 +73,12 @@ ShaderResourceGroup MaterialSrg : SRG_PerMaterial
MagFilter = Linear;
MipFilter = Linear;
};
// Parameters for subsurface scattering
float m_subsurfaceScatteringFactor;
float m_subsurfaceScatteringQuality;
float3 m_scatterDistance;
Texture2D m_subsurfaceScatteringInfluenceMap;
uint m_subsurfaceScatteringInfluenceMapUvIndex;
// Parameters for transmission
// Elements of m_transmissionParams:
// Thick object mode: (attenuation coefficient, power, distortion, scale)
// Thin object mode: (float3 scatter distance, scale)
float4 m_transmissionParams;
// (float3 TintColor, thickness)
float4 m_transmissionTintThickness;
Texture2D m_transmissionThicknessMap;
uint m_transmissionThicknessMapUvIndex;
}
// Callback function for ParallaxMapping.azsli
DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy)
{
return SampleDepthOrHeightMap(MaterialSrg::m_depthInverted, MaterialSrg::m_depthMap, MaterialSrg::m_sampler, uv, uv_ddx, uv_ddy);
return SampleDepthFromHeightmap(MaterialSrg::m_heightmap, MaterialSrg::m_sampler, uv, uv_ddx, uv_ddy);
}
@@ -106,7 +87,7 @@ COMMON_OPTIONS_PARALLAX()
bool ShouldHandleParallax()
{
// Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scattering is enabled.
return !o_enableSubsurfaceScattering && o_parallax_feature_enabled && o_useDepthMap;
return !o_enableSubsurfaceScattering && o_parallax_feature_enabled && o_useHeightmap;
}
bool ShouldHandleParallaxInDepthShaders()
@@ -86,7 +86,7 @@ PSDepthOutput MainPS(VSDepthOutput IN, bool isFrontFace : SV_IsFrontFace)
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor, MaterialSrg::m_depthOffset,
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth);
}
@@ -47,13 +47,6 @@ COMMON_OPTIONS_EMISSIVE()
// Alpha
#include "MaterialInputs/AlphaInput.azsli"
// Subsurface
#include "MaterialInputs/SubsurfaceInput.azsli"
// Transmission
#include "MaterialInputs/TransmissionInput.azsli"
// ---------- Vertex Shader ----------
struct VSInput
@@ -113,7 +106,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float3 tangents[UvSetCount] = { IN.m_tangent.xyz, IN.m_tangent.xyz };
float3 bitangents[UvSetCount] = { IN.m_bitangent.xyz, IN.m_bitangent.xyz };
if ((o_parallax_feature_enabled && !o_enableSubsurfaceScattering) || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture))
if (ShouldHandleParallax() || o_normal_useTexture || (o_clearCoat_enabled && o_clearCoat_normal_useTexture))
{
PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents);
}
@@ -124,13 +117,12 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
bool displacementIsClipped = false;
// Parallax mapping's non uniform uv transformations break screen space subsurface scattering, disable it when subsurface scatteirng is enabled
if(ShouldHandleParallax())
{
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor, MaterialSrg::m_depthOffset,
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depthNDC, IN.m_position.w, displacementIsClipped);
@@ -174,12 +166,8 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
// ------- Metallic -------
float metallic = 0;
if(!o_enableSubsurfaceScattering) // If subsurface scattering is enabled skip texture lookup for metallic, as this quantity won't be used anyway
{
float2 metallicUv = IN.m_uv[MaterialSrg::m_metallicMapUvIndex];
metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture);
}
float2 metallicUv = IN.m_uv[MaterialSrg::m_metallicMapUvIndex];
float metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture);
// ------- Specular -------
@@ -195,11 +183,6 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture);
surface.CalculateRoughnessA();
// ------- Subsurface -------
float surfaceScatteringFactor = 0.0f;
surface.transmission.InitializeToZero();
// ------- Lighting Data -------
LightingData lightingData;
@@ -271,7 +254,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
lightingData.FinalizeLighting();
if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent)
@@ -312,13 +295,6 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
lightingOutput.m_diffuseColor.rgb += lightingOutput.m_specularColor.rgb; // add specular
lightingOutput.m_specularColor.rgb = baseColor * (1.0 - lightingOutput.m_diffuseColor.w);
}
else
{
// Pack factor and quality, drawback: because of precision limit of float16 cannot represent exact 1, maximum representable value is 0.9961
uint factorAndQuality = dot(round(float2(saturate(surfaceScatteringFactor), MaterialSrg::m_subsurfaceScatteringQuality) * 255), float2(256, 1));
lightingOutput.m_diffuseColor.w = factorAndQuality * (o_enableSubsurfaceScattering ? 1.0 : -1.0);
lightingOutput.m_scatterDistance = MaterialSrg::m_scatterDistance;
}
return lightingOutput;
}
@@ -17,7 +17,7 @@ function GetMaterialPropertyDependencies()
end
function GetShaderOptionDependencies()
return {"o_parallax_feature_enabled", "o_useDepthMap"}
return {"o_parallax_feature_enabled", "o_useHeightmap"}
end
function Process(context)
@@ -25,7 +25,7 @@ function Process(context)
local useTexture = context:GetMaterialPropertyValue_bool("parallax.useTexture")
local enable = textureMap ~= nil and useTexture
context:SetShaderOptionValue_bool("o_parallax_feature_enabled", enable)
context:SetShaderOptionValue_bool("o_useDepthMap", enable)
context:SetShaderOptionValue_bool("o_useHeightmap", enable)
end
function ProcessEditor(context)
@@ -88,7 +88,7 @@ PSDepthOutput MainPS(VertexOutput IN, bool isFrontFace : SV_IsFrontFace)
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor, MaterialSrg::m_depthOffset,
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_heightmapScale, MaterialSrg::m_heightmapOffset,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, OUT.m_depth);
@@ -243,6 +243,13 @@
"Attachment": "LightListRemapped"
}
},
{
"LocalSlot": "InputLinearDepth",
"AttachmentRef": {
"Pass": "DepthPrePass",
"Attachment": "DepthLinear"
}
},
{
"LocalSlot": "DepthStencil",
"AttachmentRef": {
@@ -251,6 +251,13 @@
"Attachment": "LightListRemapped"
}
},
{
"LocalSlot": "InputLinearDepth",
"AttachmentRef": {
"Pass": "DepthPrePass",
"Attachment": "DepthLinear"
}
},
{
"LocalSlot": "DepthStencil",
"AttachmentRef": {
@@ -67,6 +67,12 @@
"ShaderInputName": "m_lightListRemapped",
"ScopeAttachmentUsage": "Shader"
},
{
"Name": "InputLinearDepth",
"SlotType": "Input",
"ShaderInputName": "m_linearDepthTexture",
"ScopeAttachmentUsage": "Shader"
},
// Input/Outputs
{
"Name": "DepthStencil",
@@ -32,6 +32,10 @@
"Name": "LightListRemapped",
"SlotType": "Input"
},
{
"Name": "InputLinearDepth",
"SlotType": "Input"
},
// Input/Outputs...
{
"Name": "DepthStencil",
@@ -91,6 +95,13 @@
"Attachment": "LightListRemapped"
}
},
{
"LocalSlot": "InputLinearDepth",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "InputLinearDepth"
}
},
// Input/Outputs...
{
"LocalSlot": "DepthStencil",
@@ -54,6 +54,7 @@ class LightingData
void Init(float3 positionWS, float3 normal, float roughnessLinear);
void CalculateMultiscatterCompensation(float3 specularF0, bool enabled);
void FinalizeLighting();
void FinalizeLighting(float3 transmissionTint);
};
@@ -80,10 +81,15 @@ void LightingData::CalculateMultiscatterCompensation(float3 specularF0, bool ena
multiScatterCompensation = GetMultiScatterCompensation(specularF0, brdf, enabled);
}
void LightingData::FinalizeLighting(float3 transmissionTint)
void LightingData::FinalizeLighting()
{
specularLighting *= specularOcclusion;
specularLighting += emissiveLighting;
}
void LightingData::FinalizeLighting(float3 transmissionTint)
{
FinalizeLighting();
// Transmitted light
if(o_transmission_mode != TransmissionMode::None)
@@ -75,7 +75,6 @@ struct PbrLightingOutput
float4 m_albedo;
float4 m_specularF0;
float4 m_normal;
float3 m_scatterDistance;
};
@@ -20,7 +20,7 @@
class Surface
{
ClearCoatSurfaceData clearCoat;
TransmissionSurfaceData transmission;
TransmissionSurfaceData transmission; // This is not actually used for Standard PBR, but must be present for common lighting code to compile
// ------- BasePbrSurfaceData -------
@@ -35,4 +35,5 @@ ShaderResourceGroup PassSrg : SRG_PerPass
Texture2D<uint4> m_tileLightData;
StructuredBuffer<uint> m_lightListRemapped;
Texture2D<float> m_linearDepthTexture;
}
@@ -58,7 +58,7 @@ DepthResult DepthResultAbsolute(float depth)
//! The client shader must define this function.
//! This allows the client shader to implement special depth map sampling, for example procedurally generating or blending depth maps.
//! In simple cases though, the implementation of GetDepth() can simply call SampleDepthOrHeightMap().
//! In simple cases though, the implementation of GetDepth() can simply call SampleDepthFromHeightmap().
//! @param uv the UV coordinates to use for sampling
//! @param uv_ddx will be set to ddx_fine(uv)
//! @param uv_ddy will be set to ddy_fine(uv)
@@ -66,13 +66,12 @@ DepthResult DepthResultAbsolute(float depth)
DepthResult GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy);
//! Convenience function that can be used to implement GetDepth().
//! @param isHeightmap indicates whether to sample the map is a height map rather than a depth map.
//! @return see struct DepthResult. In this case it will always contain a Code::Normalized result.
DepthResult SampleDepthOrHeightMap(bool isHeightmap, Texture2D map, sampler mapSampler, float2 uv, float2 uv_ddx, float2 uv_ddy)
DepthResult SampleDepthFromHeightmap(Texture2D map, sampler mapSampler, float2 uv, float2 uv_ddx, float2 uv_ddy)
{
DepthResult result;
result.m_resultCode = DepthResultCode_Normalized;
result.m_depth = abs((isHeightmap * 1.0) - map.SampleGrad(mapSampler, uv, uv_ddx, uv_ddy).r);
result.m_depth = 1.0 - map.SampleGrad(mapSampler, uv, uv_ddx, uv_ddy).r;
return result;
}
@@ -169,20 +168,20 @@ ParallaxOffset AdvancedParallaxMapping(float depthFactor, float depthOffset, flo
float2 ddx_uv = ddx_fine(uv);
float2 ddy_uv = ddy_fine(uv);
float depthSearchStart = -depthOffset;
float depthSearchStart = depthOffset;
float depthSearchEnd = depthSearchStart + depthFactor;
float inverseDepthFactor = 1.0 / depthFactor;
// This is the relative position at which we begin searching for intersection.
// It is adjusted according to the depthOffset, raising or lowering the whole surface by depthOffset units.
float3 parallaxOffset = dirToCameraTS.xyz * dirToCameraZInverse * depthOffset;
float3 parallaxOffset = -dirToCameraTS.xyz * dirToCameraZInverse * depthOffset;
// Get an initial heightmap sample to start the intersection search, starting at our initial parallaxOffset position.
float currentSample = GetNormalizedDepth(depthSearchStart, depthSearchEnd, inverseDepthFactor, uv + parallaxOffset.xy, ddx_uv, ddy_uv);
float prevSample;
// Note that when depthOffset < 0, we could actually narrow the search so that instead of going through the entire [depthSearchStart,depthSearchEnd] range
// Note that when depthOffset > 0, we could actually narrow the search so that instead of going through the entire [depthSearchStart,depthSearchEnd] range
// of the heightmap, we could go through the range [0,depthSearchEnd]. This would give more accurate results and fewer artifacts
// in case where the magnitude of depthOffset is significant. But for the sake of simplicity we currently search the whole range in all cases.
@@ -271,7 +270,7 @@ ParallaxOffset AdvancedParallaxMapping(float depthFactor, float depthOffset, flo
}
// Even though we do a bunch of clamping above when calling GetClampedDepth(), there are still cases where the parallax offset
// can be noticeably above the surface and still needs to be clamped here. The main case is when depthFactor==0 and depthOffset>1.
// can be noticeably above the surface and still needs to be clamped here. The main case is when depthFactor==0 and depthOffset<1.
if(parallaxOffset.z > 0.0)
{
parallaxOffset = float3(0,0,0);
@@ -371,13 +370,13 @@ ParallaxOffset CalculateParallaxOffset(float depthFactor, float depthOffset, flo
// @param dirToCameraTS - normalized direction to the camera, in tangent space.
// @param dirToLightTS - normalized direction to a light source, in tangent space, for self-shadowing (if enabled via o_parallax_shadow).
ParallaxOffset GetParallaxOffset( float depthFactor,
float depthOffset,
float2 uv,
float3 dirToCameraWS,
float3 tangentWS,
float3 bitangentWS,
float3 normalWS,
float3x3 uvMatrix)
float depthOffset,
float2 uv,
float3 dirToCameraWS,
float3 tangentWS,
float3 bitangentWS,
float3 normalWS,
float3x3 uvMatrix)
{
// Tangent space eye vector
float3 dirToCameraTS = normalize(WorldSpaceToTangent(dirToCameraWS, normalWS, tangentWS, bitangentWS));
@@ -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 <Atom/Features/SrgSemantics.azsli>
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<MaterialInfo> 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[];
}
@@ -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;
}
@@ -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<MeshInfo> 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[];
}
@@ -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;
}
@@ -64,3 +64,8 @@ ShaderResourceGroupSemantic SRG_RayTracingScene
{
FrequencyId = 1;
};
ShaderResourceGroupSemantic SRG_RayTracingMaterial
{
FrequencyId = 2;
};
@@ -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",
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bc9981393c88c6d30a0a5a6837e6f6246a9f550042b3c4be39dd34e479b90569
size 16793931
@@ -1,69 +0,0 @@
<ObjectStream version="3">
<Class name="TextureSettings" version="1" type="{980132FF-C450-425D-8AE0-BD96A8486177}">
<Class name="AZ::Uuid" field="PresetID" value="{46D9F30F-793C-4449-BCEF-12A396E61B2C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="SizeReduceLevel" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="bool" field="EngineReduce" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="EnableMipmap" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="bool" field="MaintainAlphaCoverage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
<Class name="AZStd::vector" field="MipMapAlphaAdjustments" type="{3349AACD-BE04-50BC-9478-528BF2ACFD55}">
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="unsigned int" field="element" value="50" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="MipMapGenEval" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="ImageProcessing::MipGenType" field="MipMapGenType" value="1" type="{8524F650-1417-44DA-BBB0-C707A7A1A709}"/>
<Class name="AZStd::map" field="PlatformSpecificOverrides" type="{74E4843B-0924-583D-8C6E-A37B09BD51FE}">
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="android" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}"/>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="ios" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="mac" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}">
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#1·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
<Class name="AZStd::pair" field="element" type="{FED51EB4-F646-51FF-9646-9852CF90F353}">
<Class name="AddressType" field="value1" value="AZStd::map({74E4843B-0924-583D-8C6E-A37B09BD51FE})::PlatformSpecificOverrides·0/AZStd::pair({CAC4E67F-D626-5452-A057-ACB57D53F549})#0·0/" version="1" type="{90752F2D-CBD3-4EE9-9CDD-447E797C8408}"/>
<Class name="any" field="value2" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"/>
</Class>
</Class>
</Class>
</Class>
<Class name="AZStd::pair" field="element" type="{CAC4E67F-D626-5452-A057-ACB57D53F549}">
<Class name="AZStd::string" field="value1" value="pc" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="DataPatch" field="value2" type="{BFF7A3F5-9014-4000-92C7-9B2BC7913DA9}">
<Class name="AZ::Uuid" field="m_targetClassId" value="{980132FF-C450-425D-8AE0-BD96A8486177}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="m_targetClassVersion" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::unordered_map" field="m_patch" type="{CEA836FC-77E0-5E46-BD0F-2E5A39D845E9}"/>
</Class>
</Class>
</Class>
<Class name="AZStd::string" field="OverridingPlatform" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</ObjectStream>
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:440bcb1579d4ad667c040bda914ed3121980526a94f23879a0c482c799fd5132
size 1310848
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cf4b22481726214c062ac27fb2d9d8a49e760a76d8fff03330ff9c5f9275a8da
size 1966208
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8b4c99faffc34988c268613948f2004f40e9bd51de915461a4cb74edc5e8bae6
size 134217920
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f7edea42ded8143764654f12c19e0c9b74c74afb21f435ebb59c0a4d203892a3
size 536871104
@@ -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...
@@ -23,6 +23,7 @@ set(FILES
Materials/Types/EnhancedPBR_ForwardPass_EDS.shader
Materials/Types/EnhancedPBR_Shadowmap_WithPS.azsl
Materials/Types/EnhancedPBR_Shadowmap_WithPS.shader
Materials/Types/EnhancedPBR_SubsurfaceState.lua
Materials/Types/Skin.azsl
Materials/Types/Skin.materialtype
Materials/Types/Skin.shader
@@ -61,7 +62,6 @@ set(FILES
Materials/Types/StandardPBR_ShaderEnable.lua
Materials/Types/StandardPBR_Shadowmap_WithPS.azsl
Materials/Types/StandardPBR_Shadowmap_WithPS.shader
Materials/Types/StandardPBR_SubsurfaceState.lua
Materials/Types/MaterialInputs/AlphaInput.azsli
Materials/Types/MaterialInputs/BaseColorInput.azsli
Materials/Types/MaterialInputs/ClearCoatInput.azsli
@@ -89,6 +89,8 @@
#include <ImGui/ImGuiPass.h>
#include <RayTracing/RayTracingAccelerationStructurePass.h>
#include <RayTracing/RayTracingPass.h>
#include <RayTracing/RayTracingPassData.h>
#include <DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.h>
#include <DiffuseProbeGrid/DiffuseProbeGridBlendIrradiancePass.h>
#include <DiffuseProbeGrid/DiffuseProbeGridBlendDistancePass.h>
@@ -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);
@@ -16,11 +16,14 @@
#include <Atom/RPI.Public/Pass/PassFilter.h>
#include <Atom/RPI.Public/Pass/RenderPass.h>
#include <Atom/RPI.Public/Pass/Specific/SwapChainPass.h>
#include <Atom/RPI.Public/ViewportContextManager.h>
#include <Atom/Utils/DdsFile.h>
#include <Atom/Utils/PpmFile.h>
#include <AtomCore/Serialization/Json/JsonUtils.h>
#include <AzCore/Jobs/JobFunction.h>
#include <AzCore/Jobs/JobCompletion.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/RTTI/BehaviorContext.h>
@@ -55,6 +58,43 @@ namespace AZ
FrameCaptureOutputResult PngFrameCaptureOutput(
const AZStd::string& outputFilePath, const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult)
{
AZStd::shared_ptr<AZStd::vector<uint8_t>> 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<AZStd::vector<uint8_t>>(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<ImageOutput> out = ImageOutput::create(outputFilePath.c_str());
if (out)
@@ -62,13 +102,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};
}
@@ -250,11 +290,7 @@ namespace AZ
bool FrameCaptureSystemComponent::CaptureScreenshot(const AZStd::string& filePath)
{
AzFramework::NativeWindowHandle windowHandle = nullptr;
AzFramework::WindowSystemRequestBus::BroadcastResult(
windowHandle,
&AzFramework::WindowSystemRequestBus::Events::GetDefaultWindowHandle);
AzFramework::NativeWindowHandle windowHandle = AZ::RPI::ViewportContextRequests::Get()->GetDefaultViewportContext()->GetWindowHandle();
if (windowHandle)
{
return CaptureScreenshotForWindow(filePath, windowHandle);
@@ -460,13 +496,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
@@ -12,7 +12,9 @@
#include <Atom/Feature/Material/MaterialAssignment.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <Material/MaterialAssignmentSerializer.h>
namespace AZ
{
@@ -22,6 +24,11 @@ namespace AZ
{
MaterialAssignmentId::Reflect(context);
if (auto jsonContext = azrtti_cast<JsonRegistrationContext*>(context))
{
jsonContext->Serializer<JsonMaterialAssignmentSerializer>()->HandlesType<MaterialAssignment>();
}
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->RegisterGenericType<MaterialAssignmentMap>();
@@ -0,0 +1,214 @@
/*
* 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 <Material/MaterialAssignmentSerializer.h>
#include <Atom/Feature/Material/MaterialAssignment.h>
namespace AZ
{
namespace Render
{
AZ_CLASS_ALLOCATOR_IMPL(JsonMaterialAssignmentSerializer, AZ::SystemAllocator, 0);
JsonSerializationResult::Result JsonMaterialAssignmentSerializer::Load(
void* outputValue, [[maybe_unused]] const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
AZ_Assert(
azrtti_typeid<AZ::Render::MaterialAssignment>() == outputValueTypeId,
"Unable to deserialize MaterialAssignment from json because the provided type is %s.",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ::Render::MaterialAssignment* materialAssignment = reinterpret_cast<AZ::Render::MaterialAssignment*>(outputValue);
AZ_Assert(materialAssignment, "Output value for JsonMaterialAssignmentSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::ReadField);
{
result.Combine(ContinueLoadingFromJsonObjectField(
&materialAssignment->m_materialAsset, azrtti_typeid<decltype(materialAssignment->m_materialAsset)>(), inputValue,
"MaterialAsset", context));
}
if (inputValue.HasMember("PropertyOverrides") && inputValue["PropertyOverrides"].IsObject())
{
// Attempt to load material property override values for a subset of types
for (const auto& inputPropertyPair : inputValue["PropertyOverrides"].GetObject())
{
const AZ::Name propertyName(inputPropertyPair.name.GetString());
if (!propertyName.IsEmpty())
{
AZStd::any propertyValue;
if (LoadAny<bool>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::u8>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::u16>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::u32>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::u64>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::s8>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::s16>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::s32>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::s64>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<float>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<double>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Vector2>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Vector3>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Vector4>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Color>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZStd::string>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Data::AssetId>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Data::Asset<AZ::RPI::ImageAsset>>(propertyValue, inputPropertyPair.value, context, result) ||
LoadAny<AZ::Data::Asset<AZ::RPI::StreamingImageAsset>>(propertyValue, inputPropertyPair.value, context, result))
{
materialAssignment->m_propertyOverrides[propertyName] = propertyValue;
}
}
}
}
return context.Report(
result,
result.GetProcessing() != JSR::Processing::Halted ? "Succesfully loaded MaterialAssignment information."
: "Failed to load MaterialAssignment information.");
}
JsonSerializationResult::Result JsonMaterialAssignmentSerializer::Store(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, [[maybe_unused]] const Uuid& valueTypeId,
JsonSerializerContext& context)
{
namespace JSR = AZ::JsonSerializationResult;
AZ_Assert(
azrtti_typeid<AZ::Render::MaterialAssignment>() == valueTypeId,
"Unable to Serialize MaterialAssignment because the provided type is %s.", valueTypeId.ToString<AZStd::string>().c_str());
const AZ::Render::MaterialAssignment* materialAssignment = reinterpret_cast<const AZ::Render::MaterialAssignment*>(inputValue);
AZ_Assert(materialAssignment, "Input value for JsonMaterialAssignmentSerializer can't be null.");
const AZ::Render::MaterialAssignment* defaultMaterialAssignmentInstance =
reinterpret_cast<const AZ::Render::MaterialAssignment*>(defaultValue);
outputValue.SetObject();
JSR::ResultCode result(JSR::Tasks::WriteValue);
{
AZ::ScopedContextPath subPathMaterialAsset(context, "m_materialAsset");
const AZ::Data::Asset<RPI::MaterialAsset>* materialAsset = &materialAssignment->m_materialAsset;
const AZ::Data::Asset<RPI::MaterialAsset>* defaultmaterialAsset =
defaultMaterialAssignmentInstance ? &defaultMaterialAssignmentInstance->m_materialAsset : nullptr;
result.Combine(ContinueStoringToJsonObjectField(
outputValue, "MaterialAsset", materialAsset, defaultmaterialAsset,
azrtti_typeid<decltype(materialAssignment->m_materialAsset)>(), context));
}
{
AZ::ScopedContextPath subPathPropertyOverrides(context, "m_propertyOverrides");
if (!materialAssignment->m_propertyOverrides.empty())
{
rapidjson::Value outputPropertyValueContainer;
outputPropertyValueContainer.SetObject();
// Attempt to extract and store material property override values for a subset of types
for (const auto& propertyPair : materialAssignment->m_propertyOverrides)
{
const AZ::Name& propertyName = propertyPair.first;
const AZStd::any& propertyValue = propertyPair.second;
if (!propertyName.IsEmpty() && !propertyValue.empty())
{
rapidjson::Value outputPropertyValue;
if (StoreAny<bool>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::u8>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::u16>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::u32>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::u64>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::s8>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::s16>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::s32>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::s64>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<float>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<double>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Vector2>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Vector3>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Vector4>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Color>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZStd::string>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Data::AssetId>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Data::Asset<AZ::RPI::ImageAsset>>(propertyValue, outputPropertyValue, context, result) ||
StoreAny<AZ::Data::Asset<AZ::RPI::StreamingImageAsset>>(
propertyValue, outputPropertyValue, context, result))
{
outputPropertyValueContainer.AddMember(
rapidjson::Value::StringRefType(propertyName.GetCStr()), outputPropertyValue,
context.GetJsonAllocator());
}
}
}
if (outputPropertyValueContainer.MemberCount() > 0)
{
outputValue.AddMember("PropertyOverrides", outputPropertyValueContainer, context.GetJsonAllocator());
}
}
}
return context.Report(
result,
result.GetProcessing() != JSR::Processing::Halted ? "Successfully stored MaterialAssignment information."
: "Failed to store MaterialAssignment information.");
}
template<typename T>
bool JsonMaterialAssignmentSerializer::LoadAny(
AZStd::any& propertyValue, const rapidjson::Value& inputPropertyValue, AZ::JsonDeserializerContext& context,
AZ::JsonSerializationResult::ResultCode& result)
{
if (inputPropertyValue.IsObject() && inputPropertyValue.HasMember("Value") && inputPropertyValue.HasMember("$type"))
{
// Requiring explicit type info to differentiate be=tween colors versus vectors and numeric types
const AZ::Uuid baseTypeId = azrtti_typeid<T>();
AZ::Uuid typeId = AZ::Uuid::CreateNull();
result.Combine(LoadTypeId(typeId, inputPropertyValue, context, &baseTypeId));
if (typeId == azrtti_typeid<T>())
{
T value = {};
result.Combine(ContinueLoadingFromJsonObjectField(&value, azrtti_typeid<T>(), inputPropertyValue, "Value", context));
propertyValue = value;
return true;
}
}
return false;
}
template<typename T>
bool JsonMaterialAssignmentSerializer::StoreAny(
const AZStd::any& propertyValue, rapidjson::Value& outputPropertyValue, AZ::JsonSerializerContext& context,
AZ::JsonSerializationResult::ResultCode& result)
{
if (propertyValue.is<T>())
{
outputPropertyValue.SetObject();
// Storing explicit type info to differentiate be=tween colors versus vectors and numeric types
rapidjson::Value typeValue;
result.Combine(StoreTypeId(typeValue, azrtti_typeid<T>(), context));
outputPropertyValue.AddMember("$type", typeValue, context.GetJsonAllocator());
T value = AZStd::any_cast<T>(propertyValue);
result.Combine(
ContinueStoringToJsonObjectField(outputPropertyValue, "Value", &value, nullptr, azrtti_typeid<T>(), context));
return true;
}
return false;
}
} // namespace Render
} // namespace AZ
@@ -0,0 +1,50 @@
/*
* 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 <AzCore/Memory/Memory.h>
#include <AzCore/Name/Name.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
namespace AZ
{
namespace Render
{
// Custom JSON serializer for material assignment objects containing AZStd::any property overrides,
// which aren't supported by the system
class JsonMaterialAssignmentSerializer : public BaseJsonSerializer
{
public:
AZ_RTTI(JsonMaterialAssignmentSerializer, "{3D33653E-4582-483F-91F5-BBCC347C3DF0}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
JsonSerializationResult::Result Load(
void* outputValue, const Uuid& outputValueTypeId, const rapidjson::Value& inputValue,
JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store(
rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue, const Uuid& valueTypeId,
JsonSerializerContext& context) override;
private:
template<typename T>
bool LoadAny(
AZStd::any& propertyValue, const rapidjson::Value& inputPropertyValue, AZ::JsonDeserializerContext& context,
AZ::JsonSerializationResult::ResultCode& result);
template<typename T>
bool StoreAny(
const AZStd::any& propertyValue, rapidjson::Value& outputPropertyValue, AZ::JsonSerializerContext& context,
AZ::JsonSerializationResult::ResultCode& result);
};
} // namespace Render
} // namespace AZ
@@ -710,27 +710,53 @@ namespace AZ
uint32_t rayTracingLod = aznumeric_cast<uint32_t>(modelLods.size() - 1);
const Data::Instance<RPI::ModelLod>& 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<RHI::Buffer*>(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<RPI::Material> 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<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetDescriptor().m_byteCount;
RHI::BufferViewDescriptor positionBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, positionBufferByteCount);
uint32_t normalBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[1].GetBuffer())->GetDescriptor().m_byteCount;
RHI::BufferViewDescriptor normalBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, normalBufferByteCount);
uint32_t tangentBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[2].GetBuffer())->GetDescriptor().m_byteCount;
RHI::BufferViewDescriptor tangentBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tangentBufferByteCount);
uint32_t bitangentBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[3].GetBuffer())->GetDescriptor().m_byteCount;
RHI::BufferViewDescriptor bitangentBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, bitangentBufferByteCount);
uint32_t uvBufferByteCount = const_cast<RHI::Buffer*>(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<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetBufferView(positionBufferDescriptor);
subMesh.m_normalFormat = NormalStreamFormat;
subMesh.m_normalVertexBufferView = streamBufferViews[1];
subMesh.m_normalShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[1].GetBuffer())->GetBufferView(normalBufferDescriptor);
subMesh.m_tangentFormat = TangentStreamFormat;
subMesh.m_tangentVertexBufferView = streamBufferViews[2];
subMesh.m_tangentShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[2].GetBuffer())->GetBufferView(tangentBufferDescriptor);
subMesh.m_bitangentFormat = BitangentStreamFormat;
subMesh.m_bitangentVertexBufferView = streamBufferViews[3];
subMesh.m_bitangentShaderBufferView = const_cast<RHI::Buffer*>(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<RHI::Buffer*>(streamBufferViews[4].GetBuffer())->GetBufferView(uvBufferDescriptor);
}
subMesh.m_indexBufferView = mesh.m_indexBufferView;
subMesh.m_indexShaderBufferView = const_cast<RHI::Buffer*>(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<AZ::Color>(propertyIndex);
subMesh.m_irradianceColor = material->GetPropertyValue<AZ::Color>(propertyIndex);
}
propertyIndex = material->FindPropertyIndex(AZ::Name("irradiance.factor"));
if (propertyIndex.IsValid())
{
irradianceColor *= material->GetPropertyValue<float>(propertyIndex);
subMesh.m_irradianceColor *= material->GetPropertyValue<float>(propertyIndex);
}
// base color
propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.color"));
if (propertyIndex.IsValid())
{
subMesh.m_baseColor = material->GetPropertyValue<AZ::Color>(propertyIndex);
}
propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.factor"));
if (propertyIndex.IsValid())
{
subMesh.m_baseColor *= material->GetPropertyValue<float>(propertyIndex);
}
// metallic
propertyIndex = material->FindPropertyIndex(AZ::Name("metallic.factor"));
if (propertyIndex.IsValid())
{
subMesh.m_metallicFactor = material->GetPropertyValue<float>(propertyIndex);
}
// roughness
propertyIndex = material->FindPropertyIndex(AZ::Name("roughness.factor"));
if (propertyIndex.IsValid())
{
subMesh.m_roughnessFactor = material->GetPropertyValue<float>(propertyIndex);
}
// textures
propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.textureMap"));
if (propertyIndex.IsValid())
{
Data::Instance<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(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<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(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<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(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<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(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<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetBufferView(vertexBufferDescriptor);
subMesh.m_normalVertexBufferView = streamBufferViews[1];
subMesh.m_normalShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[1].GetBuffer())->GetBufferView(vertexBufferDescriptor);
subMesh.m_indexBufferView = mesh.m_indexBufferView;
subMesh.m_indexShaderBufferView = const_cast<RHI::Buffer*>(mesh.m_indexBufferView.GetBuffer())->GetBufferView(indexBufferDescriptor);
subMesh.m_irradianceColor = irradianceColor;
subMeshes.push_back(subMesh);
}
@@ -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();
}
}
@@ -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<RPI::ShaderResourceGroupAsset> rayTracingMaterialSrgAsset =
RPI::AssetUtils::LoadAssetByProductPath<RPI::ShaderResourceGroupAsset>("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<uint32_t>(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<TransformServiceFeatureProcessor>();
AZStd::vector<MeshInfo> meshInfos;
meshInfos.reserve(m_subMeshCount);
uint32_t newMeshByteCount = m_subMeshCount * sizeof(MeshInfo);
if (m_meshInfoBuffer == nullptr)
{
AZStd::string uuidString = AZ::Uuid::CreateRandom().ToString<AZStd::string>();
// 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<uint32_t>(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<MaterialInfo> materialInfos;
materialInfos.reserve(m_subMeshCount);
uint32_t newMaterialByteCount = m_subMeshCount * sizeof(MaterialInfo);
if (m_materialInfoBuffer == nullptr)
{
AZStd::string uuidString = AZ::Uuid::CreateRandom().ToString<AZStd::string>();
// 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<uint32_t>(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<TransformServiceFeatureProcessor>();
AZStd::vector<MeshInfo> 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<const RHI::ImageView*> 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();
}
}
}
@@ -16,6 +16,7 @@
#include <Atom/RHI/RayTracingAccelerationStructure.h>
#include <Atom/RHI/RayTracingBufferPools.h>
#include <Atom/RHI/BufferView.h>
#include <Atom/RHI/ImageView.h>
#include <AzCore/Math/Color.h>
#include <AzCore/Math/Transform.h>
@@ -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<RHI::BufferView> m_positionShaderBufferView;
RHI::Format m_normalFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_normalVertexBufferView;
RHI::Ptr<RHI::BufferView> m_normalShaderBufferView;
RHI::Format m_tangentFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_tangentVertexBufferView;
RHI::Ptr<RHI::BufferView> m_tangentShaderBufferView;
RHI::Format m_bitangentFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_bitangentVertexBufferView;
RHI::Ptr<RHI::BufferView> m_bitangentShaderBufferView;
RHI::Format m_uvFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_uvVertexBufferView;
RHI::Ptr<RHI::BufferView> m_uvShaderBufferView;
// index buffer
RHI::IndexBufferView m_indexBufferView;
RHI::Ptr<RHI::BufferView> 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<RHI::RayTracingBlas> 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<const RHI::ImageView> m_baseColorImageView;
RHI::Ptr<const RHI::ImageView> m_normalImageView;
RHI::Ptr<const RHI::ImageView> m_metallicImageView;
RHI::Ptr<const RHI::ImageView> m_roughnessImageView;
};
using SubMeshVector = AZStd::vector<SubMesh>;
@@ -98,6 +154,9 @@ namespace AZ
//! Retrieves the RayTracingSceneSrg
Data::Instance<RPI::ShaderResourceGroup> GetRayTracingSceneSrg() const { return m_rayTracingSceneSrg; }
//! Retrieves the RayTracingMaterialSrg
Data::Instance<RPI::ShaderResourceGroup> GetRayTracingMaterialSrg() const { return m_rayTracingMaterialSrg; }
//! Retrieves the RayTracingTlas
const RHI::Ptr<RHI::RayTracingTlas>& GetTlas() const { return m_tlas; }
RHI::Ptr<RHI::RayTracingTlas>& GetTlas() { return m_tlas; }
@@ -118,14 +177,20 @@ namespace AZ
//! Retrieves the GPU buffer containing information for all ray tracing meshes.
const Data::Instance<RPI::Buffer> 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<RPI::Buffer> 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<RPI::ShaderResourceGroup> m_rayTracingSceneSrg;
// ray tracing material Srg
Data::Instance<RPI::ShaderResourceGroup> 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<float, 4> m_irradianceColor; // float4
AZStd::array<float, 9> 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<RPI::Buffer> 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<float, 4> 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<RPI::Buffer> 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;
};
}
}
@@ -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 <AzCore/Asset/AssetCommon.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <Atom/RHI/CommandList.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RHI/FrameScheduler.h>
#include <Atom/RHI/DispatchRaysItem.h>
#include <Atom/RHI/RHISystemInterface.h>
#include <Atom/RHI/PipelineState.h>
#include <Atom/RPI.Reflect/Pass/PassTemplate.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <Atom/RPI.Public/Base.h>
#include <Atom/RPI.Public/Pass/PassUtils.h>
#include <Atom/RPI.Public/RPIUtils.h>
#include <Atom/RPI.Public/RenderPipeline.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/View.h>
#include <RayTracing/RayTracingPass.h>
#include <RayTracing/RayTracingPassData.h>
#include <RayTracing/RayTracingFeatureProcessor.h>
namespace AZ
{
namespace Render
{
RPI::Ptr<RayTracingPass> RayTracingPass::Create(const RPI::PassDescriptor& descriptor)
{
RPI::Ptr<RayTracingPass> pass = aznew RayTracingPass(descriptor);
return pass;
}
RayTracingPass::RayTracingPass(const RPI::PassDescriptor& descriptor)
: RenderPass(descriptor)
, m_passDescriptor(descriptor)
{
RHI::Ptr<RHI::Device> 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<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
m_passData = RPI::PassUtils::GetPassData<RayTracingPassData>(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<RPI::ShaderResourceGroupAsset> 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<RPI::ShaderResourceGroupAsset> viewSrgAsset = m_rayGenerationShader->FindShaderResourceGroupAsset(RPI::SrgBindingSlot::View);
m_requiresViewSrg = viewSrgAsset.GetId().IsValid();
Data::Asset<RPI::ShaderResourceGroupAsset> 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<RPI::Shader> RayTracingPass::LoadShader(const RPI::AssetReference& shaderAssetReference)
{
Data::Asset<RPI::ShaderAsset> 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<RayTracingFeatureProcessor>();
if (!rayTracingFeatureProcessor)
{
return;
}
if (!m_rayTracingShaderTable)
{
RHI::Ptr<RHI::Device> 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<RayTracingFeatureProcessor>();
AZ_Assert(rayTracingFeatureProcessor, "RayTracingPass requires the RayTracingFeatureProcessor");
RPI::RenderPass::SetupFrameGraphDependencies(frameGraph);
frameGraph.SetEstimatedItemCount(1);
// TLAS
{
const RHI::Ptr<RHI::Buffer>& 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<uint32_t>(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<RayTracingFeatureProcessor>();
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<RHI::RayTracingShaderTableDescriptor> descriptor = AZStd::make_shared<RHI::RayTracingShaderTableDescriptor>();
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<RayTracingFeatureProcessor>();
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<RHI::ShaderResourceGroup*> shaderResourceGroups =
{
m_shaderResourceGroup->GetRHIShaderResourceGroup(),
rayTracingFeatureProcessor->GetRayTracingSceneSrg()->GetRHIShaderResourceGroup()
};
if (m_requiresViewSrg)
{
const AZStd::vector<RPI::ViewPtr>& 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<uint32_t>(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<RPI::ShaderAsset>& 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
@@ -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 <AzCore/Memory/SystemAllocator.h>
#include <Atom/RHI/RayTracingPipelineState.h>
#include <Atom/RHI/RayTracingShaderTable.h>
#include <Atom/RPI.Public/Pass/RenderPass.h>
#include <Atom/RPI.Public/Shader/Shader.h>
#include <Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h>
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<RayTracingPass> 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<RPI::ShaderAsset>& 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<RPI::Shader> 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<RPI::Shader> m_rayGenerationShader;
Data::Instance<RPI::Shader> m_missShader;
Data::Instance<RPI::Shader> m_closestHitShader;
RHI::Ptr<RHI::RayTracingPipelineState> m_rayTracingPipelineState;
RHI::ConstPtr<RHI::PipelineState> m_globalPipelineState;
RHI::Ptr<RHI::RayTracingShaderTable> m_rayTracingShaderTable;
bool m_requiresViewSrg = false;
bool m_requiresRayTracingMaterialSrg = false;
};
} // namespace RPI
} // namespace AZ

Some files were not shown because too many files have changed in this diff Show More