Merge branch 'stabilization/2106' of https://github.com/aws-lumberyard/o3de into jckand/FoundationAutoStabilization
This commit is contained in:
@@ -13,13 +13,6 @@ add_subdirectory(asset_processor_tests)
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
## AP Python Tests ##
|
||||
ly_add_pytest(
|
||||
NAME AssetPipelineTests.AuxiliaryContent
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/auxiliary_content_tests/auxiliary_content_tests.py
|
||||
EXCLUDE_TEST_RUN_TARGET_FROM_IDE
|
||||
TEST_SUITE periodic
|
||||
)
|
||||
|
||||
ly_add_pytest(
|
||||
NAME AssetPipelineTests.BankInfoParser
|
||||
PATH ${CMAKE_CURRENT_LIST_DIR}/wwise_bank_dependency_tests/bank_info_parser_tests.py
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
-96
@@ -1,96 +0,0 @@
|
||||
"""
|
||||
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.
|
||||
|
||||
"""
|
||||
import pytest
|
||||
import ly_test_tools
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import subprocess
|
||||
import glob
|
||||
from ly_test_tools.builtin.helpers import *
|
||||
from ly_test_tools.environment.process_utils import *
|
||||
from ly_test_tools.o3de.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
project_list = ['AutomatedTesting']
|
||||
|
||||
@pytest.mark.system
|
||||
@pytest.mark.SUITE_periodic
|
||||
class TestAuxiliaryContent:
|
||||
@pytest.fixture(autouse=True)
|
||||
def setup_teardown(self, request, workspace, project):
|
||||
path_to_dev = workspace.paths.engine_root()
|
||||
os.chdir(path_to_dev)
|
||||
auxiliaryContentDirName = str.lower(project) + f"_{ASSET_PROCESSOR_PLATFORM_MAP[workspace.asset_processor_platform]}_paks"
|
||||
self.auxiliaryContentPath = os.path.join(path_to_dev, auxiliaryContentDirName)
|
||||
|
||||
def teardown():
|
||||
if (os.path.exists(self.auxiliaryContentPath)):
|
||||
shutil.rmtree(self.auxiliaryContentPath)
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@staticmethod
|
||||
def scanForLevelPak(path_toscan):
|
||||
files = glob.glob('{0}/**/level.pak'.format(path_toscan), recursive=True)
|
||||
return len(files)
|
||||
|
||||
@pytest.mark.parametrize('level', ['alldependencies'])
|
||||
@pytest.mark.parametrize('project', project_list)
|
||||
def test_CreateAuxiliaryContent_DontSkipLevelPaks(self, workspace, level):
|
||||
"""
|
||||
This test ensure that Auxiliary Content contain level.pak files
|
||||
|
||||
Test Steps:
|
||||
1. Run auxiliary content against project under test
|
||||
2. Validate auxiliary content exists
|
||||
3. Verifies that level.pak exists
|
||||
"""
|
||||
|
||||
path_to_dev = workspace.paths.engine_root()
|
||||
bin_path = workspace.paths.build_directory()
|
||||
|
||||
auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py')
|
||||
subprocess.check_call(['python', auxiliaryContentScriptPath,
|
||||
"--buildFolder={0}".format(bin_path),
|
||||
"--platforms=pc",
|
||||
f"--project-path={workspace.project}"])
|
||||
|
||||
assert os.path.exists(self.auxiliaryContentPath)
|
||||
assert not self.scanForLevelPak(self.auxiliaryContentPath) == 0
|
||||
|
||||
@pytest.mark.parametrize('level', ['alldependencies'])
|
||||
@pytest.mark.parametrize('project', project_list)
|
||||
def test_CreateAuxiliaryContent_SkipLevelPaks(self, workspace, level):
|
||||
"""
|
||||
This test ensure that Auxiliary Content contain no level.pak file
|
||||
|
||||
Test Steps:
|
||||
1. Run auxiliary content against project under test with skiplevelPaks flag
|
||||
2. Validate auxiliary content exists
|
||||
3. Validate level.pak was added to auxiliary content
|
||||
"""
|
||||
|
||||
path_to_dev = workspace.paths.engine_root()
|
||||
bin_path = workspace.paths.build_directory()
|
||||
|
||||
auxiliaryContentScriptPath = os.path.join(path_to_dev, 'BuildReleaseAuxiliaryContent.py')
|
||||
subprocess.check_call(['python', auxiliaryContentScriptPath,
|
||||
"--buildFolder={0}".format(bin_path),
|
||||
"--platforms=pc",
|
||||
"--skiplevelPaks",
|
||||
f"--project-path={workspace.project}"])
|
||||
assert os.path.exists(self.auxiliaryContentPath)
|
||||
|
||||
assert self.scanForLevelPak(self.auxiliaryContentPath) == 0
|
||||
@@ -4060,17 +4060,10 @@ void CCryEditApp::SetEditorWindowTitle(QString sTitleStr, QString sPreTitleStr,
|
||||
{
|
||||
if (MainWindow::instance() || m_pConsoleDialog)
|
||||
{
|
||||
QString platform = "";
|
||||
|
||||
#ifdef WIN64
|
||||
platform = "[x64]";
|
||||
#else
|
||||
platform = "[x86]";
|
||||
#endif //WIN64
|
||||
|
||||
if (sTitleStr.isEmpty())
|
||||
{
|
||||
sTitleStr = QObject::tr("Open 3D Engine Editor Beta %1 - Build %2").arg(platform).arg(LY_BUILD);
|
||||
sTitleStr = QObject::tr("O3DE Editor [Developer Preview]");
|
||||
}
|
||||
|
||||
if (!sPreTitleStr.isEmpty())
|
||||
|
||||
@@ -47,8 +47,6 @@ CEditorPreferencesPage_AWS::CEditorPreferencesPage_AWS()
|
||||
{
|
||||
m_settingsRegistry = AZStd::make_unique<AZ::SettingsRegistryImpl>();
|
||||
InitializeSettings();
|
||||
|
||||
// TODO Update with AWS svg.
|
||||
m_icon = QIcon(":/res/AWS_preferences_icon.svg");
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ namespace O3DE::ProjectManager
|
||||
return ProjectManagerScreen::CreateProject;
|
||||
}
|
||||
|
||||
// Called when pressing "Create New Project"
|
||||
void CreateProjectCtrl::NotifyCurrentScreen()
|
||||
{
|
||||
ScreenWidget* currentScreen = reinterpret_cast<ScreenWidget*>(m_stack->currentWidget());
|
||||
@@ -84,6 +85,11 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
currentScreen->NotifyCurrentScreen();
|
||||
}
|
||||
|
||||
// Gather the gems from the project template. When we will have multiple project templates, we need to re-gather them
|
||||
// on changing the template and let the user know that any further changes on top of the template will be lost.
|
||||
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
|
||||
m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true);
|
||||
}
|
||||
|
||||
void CreateProjectCtrl::HandleBackButton()
|
||||
@@ -151,9 +157,6 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
m_stack->setCurrentIndex(m_stack->currentIndex() + 1);
|
||||
|
||||
QString projectTemplatePath = m_newProjectSettingsScreen->GetProjectTemplatePath();
|
||||
m_gemCatalogScreen->ReinitForProject(projectTemplatePath + "/Template", /*isNewProject=*/true);
|
||||
|
||||
Update();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -89,17 +89,18 @@ namespace O3DE::ProjectManager
|
||||
return ProjectManagerScreen::UpdateProject;
|
||||
}
|
||||
|
||||
// Called when pressing "Edit Project Settings..."
|
||||
void UpdateProjectCtrl::NotifyCurrentScreen()
|
||||
{
|
||||
m_stack->setCurrentIndex(ScreenOrder::Settings);
|
||||
Update();
|
||||
|
||||
// Gather the available gems that will be shown in the gem catalog.
|
||||
m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false);
|
||||
}
|
||||
|
||||
void UpdateProjectCtrl::HandleGemsButton()
|
||||
{
|
||||
// The next page is the gem catalog. Gather the available gems that will be shown in the gem catalog.
|
||||
m_gemCatalogScreen->ReinitForProject(m_projectInfo.m_path, /*isNewProject=*/false);
|
||||
|
||||
m_stack->setCurrentWidget(m_gemCatalogScreen);
|
||||
Update();
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace AWSCore
|
||||
|
||||
bool UseAWSCredentials()
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Request body for the service API request.
|
||||
|
||||
@@ -25,20 +25,24 @@
|
||||
#include <AzCore/Module/ModuleManagerBus.h>
|
||||
#include <ResourceMapping/AWSResourceMappingUtils.h>
|
||||
|
||||
#include <QSysInfo>
|
||||
#include <QString>
|
||||
|
||||
|
||||
|
||||
namespace AWSCore
|
||||
{
|
||||
static constexpr const char* EngineVersionJsonKey = "O3DEVersion";
|
||||
constexpr const char* EngineVersionJsonKey = "O3DEVersion";
|
||||
|
||||
constexpr char EditorAWSPreferencesFileName[] = "editor_aws_preferences.setreg";
|
||||
constexpr char AWSAttributionSettingsPrefixKey[] = "/Amazon/AWS/Preferences";
|
||||
constexpr char AWSAttributionEnabledKey[] = "/Amazon/AWS/Preferences/AWSAttributionEnabled";
|
||||
constexpr char AWSAttributionDelaySecondsKey[] = "/Amazon/AWS/Preferences/AWSAttributionDelaySeconds";
|
||||
constexpr char AWSAttributionLastTimeStampKey[] = "/Amazon/AWS/Preferences/AWSAttributionLastTimeStamp";
|
||||
constexpr char AWSAttributionApiId[] = "xbzx78kvbk";
|
||||
constexpr char AWSAttributionApiId[] = "2zxvvmv8d7";
|
||||
constexpr char AWSAttributionChinaApiId[] = "";
|
||||
constexpr char AWSAttributionApiStage[] = "prod";
|
||||
const int AWSAttributionDefaultDelayInDays = 7;
|
||||
|
||||
AWSAttributionManager::AWSAttributionManager()
|
||||
{
|
||||
@@ -58,12 +62,11 @@ namespace AWSCore
|
||||
{
|
||||
if (ShouldGenerateMetric())
|
||||
{
|
||||
// 1. Gather metadata and assemble metric
|
||||
// Gather metadata and assemble metric
|
||||
AttributionMetric metric;
|
||||
UpdateMetric(metric);
|
||||
// 2. Identify region and chose attribution endpoint
|
||||
|
||||
// 3. Post metric
|
||||
// Post metric
|
||||
SubmitMetric(metric);
|
||||
}
|
||||
}
|
||||
@@ -104,8 +107,7 @@ namespace AWSCore
|
||||
AZ::u64 delayInSeconds = 0;
|
||||
if (!m_settingsRegistry->Get(delayInSeconds, AWSAttributionDelaySecondsKey))
|
||||
{
|
||||
AZ_Warning("AWSAttributionManager", false, "AWSAttribution delay key not found. Defaulting to delay to day");
|
||||
delayInSeconds = 86400;
|
||||
delayInSeconds = 86400 * AWSAttributionDefaultDelayInDays;
|
||||
m_settingsRegistry->Set(AWSAttributionDelaySecondsKey, delayInSeconds);
|
||||
}
|
||||
|
||||
@@ -243,7 +245,8 @@ namespace AWSCore
|
||||
metric.SetO3DEVersion(engineVersion);
|
||||
|
||||
AZStd::string platform = this->GetPlatform();
|
||||
metric.SetPlatform(platform, "");
|
||||
QString productName = QSysInfo::prettyProductName();
|
||||
metric.SetPlatform(platform, productName.toStdString().c_str());
|
||||
|
||||
AZStd::vector<AZStd::string> gemNames;
|
||||
GetActiveAWSGems(gemNames);
|
||||
@@ -256,6 +259,7 @@ namespace AWSCore
|
||||
void AWSAttributionManager::SubmitMetric(AttributionMetric& metric)
|
||||
{
|
||||
AWSCore::ServiceAPI::AWSAttributionRequestJob::Config* config = ServiceAPI::AWSAttributionRequestJob::GetDefaultConfig();
|
||||
// Identify region and chose attribution endpoint
|
||||
SetApiEndpointAndRegion(config);
|
||||
|
||||
ServiceAPI::AWSAttributionRequestJob* requestJob = ServiceAPI::AWSAttributionRequestJob::Create(
|
||||
@@ -266,7 +270,12 @@ namespace AWSCore
|
||||
UpdateLastSend();
|
||||
AZ_Printf("AWSAttributionManager", "AWSAttribution metric submit success");
|
||||
|
||||
}, {}, config);
|
||||
},
|
||||
[this](ServiceAPI::AWSAttributionRequestJob* failJob)
|
||||
{
|
||||
AZ_Error("AWSAttributionManager", false, "Metrics send error: %s", failJob->error.message.c_str());
|
||||
},
|
||||
config);
|
||||
|
||||
requestJob->parameters.metric = metric;
|
||||
requestJob->Start();
|
||||
|
||||
@@ -19,14 +19,16 @@
|
||||
|
||||
namespace AWSCore
|
||||
{
|
||||
constexpr char AWSAttributionMetricDefaultO3DEVersion[] = "1.1";
|
||||
|
||||
AttributionMetric::AttributionMetric(const AZStd::string& timestamp)
|
||||
: m_version("1.1")
|
||||
: m_version(AWSAttributionMetricDefaultO3DEVersion)
|
||||
, m_timestamp(timestamp)
|
||||
{
|
||||
}
|
||||
|
||||
AttributionMetric::AttributionMetric()
|
||||
: m_version("1.1")
|
||||
: m_version(AWSAttributionMetricDefaultO3DEVersion)
|
||||
{
|
||||
m_timestamp = AttributionMetric::GenerateTimeStamp();
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <AzCore/Module/ModuleManagerBus.h>
|
||||
|
||||
#include <TestFramework/AWSCoreFixture.h>
|
||||
#include <QSysInfo>
|
||||
#include <QString>
|
||||
|
||||
|
||||
using namespace AWSCore;
|
||||
@@ -405,6 +407,7 @@ namespace AWSAttributionUnitTest
|
||||
AZStd::string serializedMetricValue = metric.SerializeToJson();
|
||||
ASSERT_TRUE(serializedMetricValue.find("\"o3de_version\":\"1.0.0.0\"") != AZStd::string::npos);
|
||||
ASSERT_TRUE(serializedMetricValue.find(AZ::GetPlatformName(AZ::g_currentPlatform)) != AZStd::string::npos);
|
||||
ASSERT_TRUE(serializedMetricValue.find(QSysInfo::prettyProductName().toStdString().c_str()) != AZStd::string::npos);
|
||||
ASSERT_TRUE(serializedMetricValue.find("AWSCore.Editor") != AZStd::string::npos);
|
||||
ASSERT_TRUE(serializedMetricValue.find("AWSClientAuth") != AZStd::string::npos);
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@ AlphaSource_Packed = 0
|
||||
AlphaSource_Split = 1
|
||||
AlphaSource_None = 2
|
||||
|
||||
ForwardPassIndex = 1
|
||||
|
||||
function ConfigureAlphaBlending(shaderItem)
|
||||
shaderItem:GetRenderStatesOverride():SetDepthEnabled(true)
|
||||
shaderItem:GetRenderStatesOverride():SetDepthWriteMask(DepthWriteMask_Zero)
|
||||
@@ -58,15 +56,17 @@ end
|
||||
function Process(context)
|
||||
local opacityMode = context:GetMaterialPropertyValue_enum("opacity.mode")
|
||||
|
||||
local forwardPassEDS = context:GetShaderByTag("ForwardPass_EDS")
|
||||
|
||||
if(opacityMode == OpacityMode_Blended) then
|
||||
ConfigureAlphaBlending(context:GetShader(ForwardPassIndex))
|
||||
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent")
|
||||
ConfigureAlphaBlending(forwardPassEDS)
|
||||
forwardPassEDS:SetDrawListTagOverride("transparent")
|
||||
elseif(opacityMode == OpacityMode_TintedTransparent) then
|
||||
ConfigureDualSourceBlending(context:GetShader(ForwardPassIndex))
|
||||
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("transparent")
|
||||
ConfigureDualSourceBlending(forwardPassEDS)
|
||||
forwardPassEDS:SetDrawListTagOverride("transparent")
|
||||
else
|
||||
ResetAlphaBlending(context:GetShader(ForwardPassIndex))
|
||||
context:GetShader(ForwardPassIndex):SetDrawListTagOverride("") -- reset to default draw list
|
||||
ResetAlphaBlending(forwardPassEDS)
|
||||
forwardPassEDS:SetDrawListTagOverride("") -- reset to default draw list
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -74,7 +74,9 @@ function Process(context)
|
||||
shadowMapWithPS:SetEnabled(opacityMode == OpacityMode_Cutout)
|
||||
forwardPass:SetEnabled(opacityMode == OpacityMode_Cutout)
|
||||
|
||||
TrySetShaderEnabled(lowEndForwardEDS, (opacityMode == OpacityMode_Opaque) or (opacityMode == OpacityMode_Blended) or (opacityMode == OpacityMode_TintedTransparent))
|
||||
-- Only enable lowEndForwardEDS in Opaque mode, Transparent mode will be handled by forwardPassEDS. The transparent pass uses the "transparent" draw tag
|
||||
-- for both standard and low end pipelines, so this keeps both shaders from rendering to the transparent draw list.
|
||||
TrySetShaderEnabled(lowEndForwardEDS, opacityMode == OpacityMode_Opaque)
|
||||
TrySetShaderEnabled(lowEndForward, opacityMode == OpacityMode_Cutout)
|
||||
end
|
||||
|
||||
|
||||
+10
-6
@@ -226,7 +226,7 @@ float ProjectedShadow::GetVisibilityEsm()
|
||||
}
|
||||
|
||||
const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize;
|
||||
const Texture2DArray<float> expShadowmap = PassSrg::m_projectedExponentialShadowmap;
|
||||
const Texture2DArray<float> shadowmap = PassSrg::m_projectedExponentialShadowmap;
|
||||
|
||||
if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin &&
|
||||
m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin)
|
||||
@@ -243,10 +243,12 @@ float ProjectedShadow::GetVisibilityEsm()
|
||||
const float depth = PerspectiveDepthToLinear(
|
||||
m_shadowPosition.z,
|
||||
coefficients);
|
||||
const float expDepthInShadowmap = expShadowmap.Sample(
|
||||
const float occluder = shadowmap.Sample(
|
||||
PassSrg::LinearSampler,
|
||||
float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r;
|
||||
const float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap;
|
||||
|
||||
const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder);
|
||||
const float ratio = exp(exponent);
|
||||
// pow() mitigates light bleeding to shadows from near shadow casters.
|
||||
return saturate( pow(ratio, 8) );
|
||||
}
|
||||
@@ -265,7 +267,7 @@ float ProjectedShadow::GetVisibilityEsmPcf()
|
||||
}
|
||||
|
||||
const float invAtlasSize = ViewSrg::m_invShadowmapAtlasSize;
|
||||
const Texture2DArray<float> expShadowmap = PassSrg::m_projectedExponentialShadowmap;
|
||||
const Texture2DArray<float> shadowmap = PassSrg::m_projectedExponentialShadowmap;
|
||||
|
||||
if (m_shadowPosition.x >= 0 && m_shadowPosition.x * size < size - PixelMargin &&
|
||||
m_shadowPosition.y >= 0 && m_shadowPosition.y * size < size - PixelMargin)
|
||||
@@ -282,10 +284,12 @@ float ProjectedShadow::GetVisibilityEsmPcf()
|
||||
const float depth = PerspectiveDepthToLinear(
|
||||
m_shadowPosition.z,
|
||||
coefficients);
|
||||
const float expDepthInShadowmap = expShadowmap.Sample(
|
||||
const float occluder = shadowmap.Sample(
|
||||
PassSrg::LinearSampler,
|
||||
float3(atlasPosition.xy * invAtlasSize, atlasPosition.z)).r;
|
||||
float ratio = exp(-EsmExponentialShift * depth) * expDepthInShadowmap;
|
||||
|
||||
const float exponent = -ViewSrg::m_projectedShadows[m_shadowIndex].m_esmExponent * (depth - occluder);
|
||||
float ratio = exp(exponent);
|
||||
|
||||
static const float pcfFallbackThreshold = 1.04;
|
||||
if (ratio > pcfFallbackThreshold)
|
||||
|
||||
@@ -92,6 +92,8 @@ partial ShaderResourceGroup ViewSrg
|
||||
uint m_filteringSampleCount;
|
||||
float2 m_unprojectConstants;
|
||||
float m_bias;
|
||||
float m_esmExponent;
|
||||
float3 m_padding;
|
||||
};
|
||||
|
||||
StructuredBuffer<ProjectedShadow> m_projectedShadows;
|
||||
|
||||
@@ -56,7 +56,6 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
|
||||
return; // Early return if filter is disabled.
|
||||
}
|
||||
|
||||
float depth = 0.;
|
||||
switch (o_shadowmapLightType)
|
||||
{
|
||||
case ShadowmapLightType::Directional:
|
||||
@@ -68,9 +67,15 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
|
||||
// and it often causes light bleeding with ESM.
|
||||
// So this converts it to "depth" to emphasize the difference
|
||||
// within the frustum.
|
||||
depth = (depthInClip - distanceMin) / (1. - distanceMin);
|
||||
}
|
||||
const float depth = (depthInClip - distanceMin) / (1. - distanceMin);
|
||||
|
||||
// Todo: Expose Esm exponent slider for directional lights
|
||||
// This would remove the exp calculation below, collapsing it into a subtraction in DirectionalLightShadow.azsli
|
||||
// ATOM-15775
|
||||
const float outValue = exp(EsmExponentialShift * depth);
|
||||
PassSrg::m_outputShadowmap[dispatchId].r = outValue;
|
||||
break;
|
||||
}
|
||||
case ShadowmapLightType::Spot:
|
||||
{
|
||||
const float3 coefficients = float3(
|
||||
@@ -84,12 +89,9 @@ void MainCS(uint3 dispatchId: SV_DispatchThreadID)
|
||||
// and it often causes light bleeding with ESM.
|
||||
// So this converts it to a linear depth to emphasize the
|
||||
// difference like a orthogonal depth.
|
||||
depth = PerspectiveDepthToLinear(depthInClip, coefficients);
|
||||
}
|
||||
PassSrg::m_outputShadowmap[dispatchId].r = PerspectiveDepthToLinear(depthInClip, coefficients);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const float outValue = exp(EsmExponentialShift * depth);
|
||||
PassSrg::m_outputShadowmap[dispatchId].r = outValue;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -100,10 +100,13 @@ namespace AZ
|
||||
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
|
||||
//! Sets the shadowmap Pcf (percentage closer filtering) method.
|
||||
virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0;
|
||||
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
|
||||
virtual void SetEsmExponent(LightHandle handle, float exponent) = 0;
|
||||
|
||||
//! Sets all of the the disk data for the provided LightHandle.
|
||||
virtual void SetDiskData(LightHandle handle, const DiskLightData& data) = 0;
|
||||
|
||||
|
||||
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+2
@@ -82,6 +82,8 @@ namespace AZ
|
||||
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
|
||||
//! Sets the shadowmap Pcf (percentage closer filtering) method.
|
||||
virtual void SetPcfMethod(LightHandle handle, PcfMethod method) = 0;
|
||||
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
|
||||
virtual void SetEsmExponent(LightHandle handle, float exponent) = 0;
|
||||
//! Sets all of the the point data for the provided LightHandle.
|
||||
virtual void SetPointData(LightHandle handle, const PointLightData& data) = 0;
|
||||
};
|
||||
|
||||
@@ -343,6 +343,11 @@ namespace AZ
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method);
|
||||
}
|
||||
|
||||
void DiskLightFeatureProcessor::SetEsmExponent(LightHandle handle, float exponent)
|
||||
{
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, exponent);
|
||||
}
|
||||
|
||||
void DiskLightFeatureProcessor::UpdateShadow(LightHandle handle)
|
||||
{
|
||||
const DiskLightData& diskLight = m_diskLightData.GetData(handle.GetIndex());
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace AZ
|
||||
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
|
||||
void SetEsmExponent(LightHandle handle, float esmExponent) override;
|
||||
|
||||
void SetDiskData(LightHandle handle, const DiskLightData& data) override;
|
||||
|
||||
|
||||
@@ -192,9 +192,7 @@ namespace AZ
|
||||
OnShaderReloaded();
|
||||
}
|
||||
|
||||
void LightCullingTilePreparePass::OnShaderVariantReinitialized(
|
||||
const AZ::RPI::Shader&, const AZ::RPI::ShaderVariantId&,
|
||||
AZ::RPI::ShaderVariantStableId)
|
||||
void LightCullingTilePreparePass::OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant&)
|
||||
{
|
||||
OnShaderReloaded();
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace AZ
|
||||
// ShaderReloadNotificationBus overrides...
|
||||
void OnShaderReinitialized(const AZ::RPI::Shader& shader) override;
|
||||
void OnShaderAssetReinitialized(const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset) override;
|
||||
void OnShaderVariantReinitialized(const AZ::RPI::Shader& shader, const AZ::RPI::ShaderVariantId& shaderVariantId, AZ::RPI::ShaderVariantStableId shaderVariantStableId) override;
|
||||
void OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant& shaderVariant) override;
|
||||
|
||||
// Scope producer functions...
|
||||
void CompileResources(const RHI::FrameGraphCompileContext& context) override;
|
||||
|
||||
@@ -312,5 +312,10 @@ namespace AZ
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetPcfMethod, method);
|
||||
}
|
||||
|
||||
void PointLightFeatureProcessor::SetEsmExponent(LightHandle handle, float esmExponent)
|
||||
{
|
||||
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, esmExponent);
|
||||
}
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace AZ
|
||||
void SetPredictionSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
|
||||
void SetPcfMethod(LightHandle handle, PcfMethod method) override;
|
||||
void SetEsmExponent(LightHandle handle, float esmExponent) override;
|
||||
void SetPointData(LightHandle handle, const PointLightData& data) override;
|
||||
|
||||
const Data::Instance<RPI::Buffer> GetLightBuffer() const;
|
||||
|
||||
@@ -199,7 +199,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset)
|
||||
void MorphTargetDispatchItem::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset<RPI::ShaderAsset>& shaderAsset)
|
||||
{
|
||||
if (!Init())
|
||||
{
|
||||
@@ -207,7 +207,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void MorphTargetDispatchItem::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId)
|
||||
void MorphTargetDispatchItem::OnShaderVariantReinitialized(const RPI::ShaderVariant&)
|
||||
{
|
||||
if (!Init())
|
||||
{
|
||||
|
||||
@@ -72,8 +72,8 @@ namespace AZ
|
||||
|
||||
// ShaderInstanceNotificationBus::Handler overrides
|
||||
void OnShaderReinitialized(const RPI::Shader& shader) override;
|
||||
void OnShaderAssetReinitialized(const Data::Asset<AZ::RPI::ShaderAsset>& shaderAsset) override;
|
||||
void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
|
||||
void OnShaderAssetReinitialized(const Data::Asset<RPI::ShaderAsset>& shaderAsset) override;
|
||||
void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
|
||||
|
||||
RHI::DispatchItem m_dispatchItem;
|
||||
|
||||
|
||||
@@ -458,9 +458,13 @@ namespace AZ
|
||||
bool ProfilingCaptureSystemComponent::CaptureCpuProfilingStatistics(const AZStd::string& outputFilePath)
|
||||
{
|
||||
// Start the cpu profiling
|
||||
RHI::CpuProfiler::Get()->SetProfilerEnabled(true);
|
||||
bool wasEnabled = RHI::CpuProfiler::Get()->IsProfilerEnabled();
|
||||
if (!wasEnabled)
|
||||
{
|
||||
RHI::CpuProfiler::Get()->SetProfilerEnabled(true);
|
||||
}
|
||||
|
||||
const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath]()
|
||||
const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath, wasEnabled]()
|
||||
{
|
||||
JsonSerializerSettings serializationSettings;
|
||||
serializationSettings.m_keepDefaults = true;
|
||||
@@ -481,14 +485,22 @@ namespace AZ
|
||||
saveResult.GetError().c_str());
|
||||
AZ_Warning("ProfilingCaptureSystemComponent", false, captureInfo.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Printf("ProfilingCaptureSystemComponent", "Cpu profiling statistics was saved to file [%s]\n", outputFilePath.c_str());
|
||||
}
|
||||
|
||||
// Disable the profiler again
|
||||
RHI::CpuProfiler::Get()->SetProfilerEnabled(false);
|
||||
if (!wasEnabled)
|
||||
{
|
||||
RHI::CpuProfiler::Get()->SetProfilerEnabled(false);
|
||||
}
|
||||
|
||||
// Notify listeners that the pass' PipelineStatistics queries capture has finished.
|
||||
ProfilingCaptureNotificationBus::Broadcast(&ProfilingCaptureNotificationBus::Events::OnCaptureCpuProfilingStatisticsFinished,
|
||||
saveResult.IsSuccess(),
|
||||
captureInfo);
|
||||
|
||||
});
|
||||
|
||||
// Start the TickBus.
|
||||
|
||||
@@ -354,9 +354,9 @@ namespace AZ
|
||||
Init();
|
||||
}
|
||||
|
||||
void RayTracingPass::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId)
|
||||
void RayTracingPass::OnShaderVariantReinitialized(const RPI::ShaderVariant&)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
} // namespace RPI
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace AZ
|
||||
// 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;
|
||||
void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
|
||||
|
||||
// load the raytracing shaders and setup pipeline states
|
||||
void Init();
|
||||
|
||||
@@ -162,12 +162,21 @@ namespace AZ::Render
|
||||
|
||||
void ProjectedShadowFeatureProcessor::SetPcfMethod(ShadowId id, PcfMethod method)
|
||||
{
|
||||
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetPcfMethod().");
|
||||
ShadowData& shadowData = m_shadowData.GetElement<ShadowDataIndex>(id.GetIndex());
|
||||
shadowData.m_pcfMethod = method;
|
||||
|
||||
m_deviceBufferNeedsUpdate = true;
|
||||
}
|
||||
|
||||
void ProjectedShadowFeatureProcessor::SetEsmExponent(ShadowId id, float exponent)
|
||||
{
|
||||
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetEsmExponent().");
|
||||
ShadowData& shadowData = m_shadowData.GetElement<ShadowDataIndex>(id.GetIndex());
|
||||
shadowData.m_esmExponent = exponent;
|
||||
m_deviceBufferNeedsUpdate = true;
|
||||
}
|
||||
|
||||
void ProjectedShadowFeatureProcessor::SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method)
|
||||
{
|
||||
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetShadowFilterMethod().");
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace AZ::Render
|
||||
void SetFieldOfViewY(ShadowId id, float fieldOfViewYRadians) override;
|
||||
void SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size) override;
|
||||
void SetPcfMethod(ShadowId id, PcfMethod method);
|
||||
void SetEsmExponent(ShadowId id, float exponent);
|
||||
void SetShadowFilterMethod(ShadowId id, ShadowFilterMethod method) override;
|
||||
void SetSofteningBoundaryWidthAngle(ShadowId id, float boundaryWidthRadians) override;
|
||||
void SetPredictionSampleCount(ShadowId id, uint16_t count) override;
|
||||
@@ -73,6 +74,8 @@ namespace AZ::Render
|
||||
uint32_t m_filteringSampleCount = 0;
|
||||
AZStd::array<float, 2> m_unprojectConstants = { {0, 0} };
|
||||
float m_bias;
|
||||
float m_esmExponent = 87.0f;
|
||||
float m_padding[3];
|
||||
};
|
||||
|
||||
// CPU data used for constructing & updating ShadowData
|
||||
|
||||
@@ -65,9 +65,13 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId&, RPI::ShaderVariantStableId)
|
||||
void SkinnedMeshComputePass::OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant)
|
||||
{
|
||||
OnShaderReinitialized(shader);
|
||||
ComputePass::OnShaderVariantReinitialized(shaderVariant);
|
||||
if (m_skinnedMeshFeatureProcessor)
|
||||
{
|
||||
m_skinnedMeshFeatureProcessor->OnSkinningShaderReinitialized(m_shader);
|
||||
}
|
||||
}
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace AZ
|
||||
|
||||
// ShaderReloadNotificationBus::Handler overrides...
|
||||
void OnShaderReinitialized(const RPI::Shader& shader) override;
|
||||
void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
|
||||
void OnShaderVariantReinitialized(const RPI::ShaderVariant& shaderVariant) override;
|
||||
|
||||
SkinnedMeshFeatureProcessor* m_skinnedMeshFeatureProcessor = nullptr;
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Debug/EventTrace.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
@@ -87,6 +88,8 @@ namespace AZ
|
||||
|
||||
//! Enable/Disable the CpuProfiler
|
||||
virtual void SetProfilerEnabled(bool enabled) = 0;
|
||||
|
||||
virtual bool IsProfilerEnabled() const = 0 ;
|
||||
};
|
||||
|
||||
} // namespace RPI
|
||||
|
||||
@@ -102,6 +102,7 @@ namespace AZ
|
||||
void EndTimeRegion() final;
|
||||
void FlushTimeRegionMap(TimeRegionMap& timeRegionMap) final;
|
||||
void SetProfilerEnabled(bool enabled) final;
|
||||
bool IsProfilerEnabled() const final;
|
||||
|
||||
private:
|
||||
// Lazily create and register the local thread data
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI/FreeListAllocator.h>
|
||||
#include <Atom/RHI/PoolAllocator.h>
|
||||
#include <Atom/RHI/MemoryAllocation.h>
|
||||
@@ -160,6 +161,7 @@ namespace AZ
|
||||
template <class Traits>
|
||||
void MemorySubAllocator<Traits>::GarbageCollect()
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("RHI", "MemorySubAllocator: GarbageCollect");
|
||||
for (PageContext& pageContext : m_pageContexts)
|
||||
{
|
||||
pageContext.m_allocator.GarbageCollect();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI/Object.h>
|
||||
#include <AzCore/std/parallel/mutex.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
@@ -169,6 +170,7 @@ namespace AZ
|
||||
template <typename Traits>
|
||||
void ObjectCollector<Traits>::Collect(bool forceFlush)
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("DX12", "ObjectCollector: Collect");
|
||||
m_mutex.lock();
|
||||
if (m_pendingObjects.size())
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <Atom/RHI/CommandQueue.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI/Device.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -86,6 +87,7 @@ namespace AZ
|
||||
|
||||
void CommandQueue::FlushCommands()
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("RHI", "CommandQueue: FlushCommands");
|
||||
while (!m_isWorkQueueEmpty && !m_isQuitting)
|
||||
{
|
||||
AZStd::this_thread::yield();
|
||||
|
||||
@@ -186,6 +186,12 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
bool CpuProfilerImpl::IsProfilerEnabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
|
||||
void CpuProfilerImpl::RegisterThreadStorage()
|
||||
{
|
||||
AZStd::unique_lock<AZStd::mutex> lock(m_threadRegisterMutex);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI/Device.h>
|
||||
#include <Atom/RHI/MemoryStatisticsBus.h>
|
||||
|
||||
@@ -151,6 +152,7 @@ namespace AZ
|
||||
{
|
||||
if (ValidateIsInitialized() && ValidateIsInFrame())
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("RHI", "Device: EndFrame");
|
||||
EndFrameInternal();
|
||||
m_isInFrame = false;
|
||||
return ResultCode::Success;
|
||||
@@ -172,6 +174,7 @@ namespace AZ
|
||||
{
|
||||
if (ValidateIsInitialized() && ValidateIsNotInFrame())
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("RHI", "Device: CompileMemoryStatistics");
|
||||
MemoryStatisticsBuilder builder;
|
||||
builder.Begin(memoryStatistics, reportFlags);
|
||||
CompileMemoryStatisticsInternal(builder);
|
||||
|
||||
@@ -9,18 +9,19 @@
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#include <Atom/RHI/FrameGraph.h>
|
||||
#include <Atom/RHI/SwapChainFrameAttachment.h>
|
||||
#include <Atom/RHI/BufferFrameAttachment.h>
|
||||
#include <Atom/RHI/ImageFrameAttachment.h>
|
||||
#include <Atom/RHI/BufferScopeAttachment.h>
|
||||
#include <Atom/RHI/ImageScopeAttachment.h>
|
||||
#include <Atom/RHI/ResolveScopeAttachment.h>
|
||||
#include <Atom/RHI/SwapChain.h>
|
||||
#include <Atom/RHI/BufferPoolBase.h>
|
||||
#include <Atom/RHI/BufferScopeAttachment.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI/FrameGraph.h>
|
||||
#include <Atom/RHI/ImageFrameAttachment.h>
|
||||
#include <Atom/RHI/ImagePoolBase.h>
|
||||
#include <Atom/RHI/ImageScopeAttachment.h>
|
||||
#include <Atom/RHI/QueryPool.h>
|
||||
#include <Atom/RHI/ResolveScopeAttachment.h>
|
||||
#include <Atom/RHI/Scope.h>
|
||||
#include <Atom/RHI/SwapChain.h>
|
||||
#include <Atom/RHI/SwapChainFrameAttachment.h>
|
||||
#include <AzCore/Debug/EventTrace.h>
|
||||
#include <AzCore/std/sort.h>
|
||||
|
||||
@@ -76,6 +77,7 @@ namespace AZ
|
||||
|
||||
void FrameGraph::Clear()
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraph: Clear");
|
||||
for (Scope* scope : m_scopes)
|
||||
{
|
||||
scope->Deactivate();
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#include <Atom/RHI/FrameGraphExecuter.h>
|
||||
#include <Atom/RHI/Buffer.h>
|
||||
#include <Atom/RHI/FrameGraph.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI/FrameGraphExecuteGroup.h>
|
||||
#include <Atom/RHI/FrameGraphExecuter.h>
|
||||
#include <Atom/RHI/FrameGraph.h>
|
||||
#include <Atom/RHI/Image.h>
|
||||
#include <AzCore/Debug/EventTrace.h>
|
||||
|
||||
@@ -80,7 +81,7 @@ namespace AZ
|
||||
|
||||
void FrameGraphExecuter::End()
|
||||
{
|
||||
AZ_TRACE_METHOD();
|
||||
AZ_ATOM_PROFILE_FUNCTION("RHI", "FrameGraphExecuter: End");
|
||||
AZ_Assert(m_pendingGroups.empty(), "Pending contexts in queue.");
|
||||
m_groups.clear();
|
||||
EndInternal();
|
||||
|
||||
@@ -181,7 +181,10 @@ namespace AZ
|
||||
|
||||
m_compileRequest = compileRequest;
|
||||
|
||||
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompile);
|
||||
{
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: Compile: OnFrameCompile");
|
||||
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompile);
|
||||
}
|
||||
|
||||
FrameGraphCompileRequest frameGraphCompileRequest;
|
||||
frameGraphCompileRequest.m_frameGraph = m_frameGraph.get();
|
||||
@@ -193,7 +196,10 @@ namespace AZ
|
||||
const MessageOutcome outcome = m_frameGraphCompiler->Compile(frameGraphCompileRequest);
|
||||
if (outcome.IsSuccess())
|
||||
{
|
||||
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompileEnd, *m_frameGraph);
|
||||
{
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: Compile: OnFrameCompileEnd");
|
||||
FrameEventBus::Broadcast(&FrameEventBus::Events::OnFrameCompileEnd, *m_frameGraph);
|
||||
}
|
||||
|
||||
FrameGraphLogger::Log(*m_frameGraph, compileRequest.m_logVerbosity);
|
||||
|
||||
@@ -400,7 +406,11 @@ namespace AZ
|
||||
|
||||
m_scopeProducers.clear();
|
||||
m_scopeProducerLookup.clear();
|
||||
FrameEventBus::Event(m_device, &FrameEventBus::Events::OnFrameEnd);
|
||||
|
||||
{
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "FrameScheduler: EndFrame: OnFrameEnd");
|
||||
FrameEventBus::Event(m_device, &FrameEventBus::Events::OnFrameEnd);
|
||||
}
|
||||
|
||||
const AZStd::sys_time_t timeNowTicks = AZStd::GetTimeNowTicks();
|
||||
m_cpuTimingStatistics.m_frameToFrameTime = timeNowTicks - m_lastFrameEndTime;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI/Device.h>
|
||||
#include <Atom/RHI/Factory.h>
|
||||
#include <Atom/RHI/RHISystem.h>
|
||||
@@ -213,19 +214,23 @@ namespace AZ
|
||||
void RHISystem::FrameUpdate(FrameGraphCallback frameGraphCallback)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
|
||||
AZ_ATOM_PROFILE_FUNCTION("RHI", "RHISystem: FrameUpdate");
|
||||
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzRender, "main per-frame work");
|
||||
m_frameScheduler.BeginFrame();
|
||||
|
||||
|
||||
frameGraphCallback(m_frameScheduler);
|
||||
|
||||
/**
|
||||
* This exists as a hook to enable RHI sample tests, which are allowed to queue their
|
||||
* own RHI scopes to the frame scheduler. This happens prior to the RPI pass graph registration.
|
||||
*/
|
||||
RHISystemNotificationBus::Broadcast(&RHISystemNotificationBus::Events::OnFramePrepare, m_frameScheduler);
|
||||
|
||||
{
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RHI", "RHISystem :FrameUpdate: OnFramePrepare");
|
||||
RHISystemNotificationBus::Broadcast(&RHISystemNotificationBus::Events::OnFramePrepare, m_frameScheduler);
|
||||
}
|
||||
|
||||
RHI::MessageOutcome outcome = m_frameScheduler.Compile(m_compileRequest);
|
||||
if (outcome.IsSuccess())
|
||||
{
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <RHI/CommandList.h>
|
||||
#include <RHI/Conversions.h>
|
||||
#include <RHI/DescriptorContext.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <AzCore/Debug/EventTrace.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -179,6 +180,7 @@ namespace AZ
|
||||
|
||||
void CommandListAllocator::Collect()
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("DX12", "CommandListAllocator: Collect");
|
||||
for (uint32_t queueIdx = 0; queueIdx < RHI::HardwareQueueClassCount; ++queueIdx)
|
||||
{
|
||||
m_commandListSubAllocators[queueIdx].ForEach([](Internal::CommandListSubAllocator& commandListSubAllocator)
|
||||
|
||||
@@ -137,6 +137,7 @@ namespace AZ
|
||||
void CommandQueueContext::End()
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzRender);
|
||||
AZ_ATOM_PROFILE_FUNCTION("DX12", "CommandQueueContext: End");
|
||||
|
||||
QueueGpuSignals(m_frameFences[m_currentFrameIndex]);
|
||||
|
||||
@@ -150,7 +151,7 @@ namespace AZ
|
||||
|
||||
{
|
||||
AZ_PROFILE_SCOPE_IDLE(AZ::Debug::ProfileCategory::AzRender, "Wait and Reset Fence");
|
||||
AZ_ATOM_PROFILE_FUNCTION("RHI", "CommandQueueContext: Wait on Fences");
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("DX12", "CommandQueueContext: Wait on Fences");
|
||||
|
||||
FenceEvent event("FrameFence");
|
||||
m_frameFences[m_currentFrameIndex].Wait(event);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <RHI/Conversions.h>
|
||||
#include <RHI/Device.h>
|
||||
#include <RHI/Image.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI.Reflect/DX12/PlatformLimitsDescriptor.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -345,6 +346,7 @@ namespace AZ
|
||||
|
||||
void DescriptorContext::GarbageCollect()
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("DX12", "DescriptorContext: GarbageCollect");
|
||||
for (const auto& itr : m_platformLimitsDescriptor->m_descriptorHeapLimits)
|
||||
{
|
||||
for (uint32_t shaderVisibleIdx = 0; shaderVisibleIdx < PlatformLimitsDescriptor::NumHeapFlags; ++shaderVisibleIdx)
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace AZ
|
||||
|
||||
void StagingMemoryAllocator::GarbageCollect()
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("DX12", "StagingMemoryAllocator: GarbageCollect");
|
||||
m_mediumBlockAllocators.ForEach([](MemoryLinearSubAllocator& subAllocator)
|
||||
{
|
||||
subAllocator.GarbageCollect();
|
||||
|
||||
@@ -145,7 +145,7 @@ namespace AZ
|
||||
// ShaderReloadNotificationBus overrides...
|
||||
void OnShaderReinitialized(const Shader& shader) override;
|
||||
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
|
||||
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
|
||||
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Type>
|
||||
|
||||
@@ -24,6 +24,11 @@ namespace AZ
|
||||
|
||||
//! Connect to this EBus to get notifications whenever material objects reload.
|
||||
//! The bus address is the AssetId of the MaterialAsset or MaterialTypeAsset.
|
||||
//!
|
||||
//! Be careful when using the parameters provided by these functions. The bus ID is an AssetId, and it's possible for the system to have
|
||||
//! both *old* versions and *new reloaded* versions of the asset in memory at the same time, and they will have the same AssetId. Therefore
|
||||
//! your bus Handlers could receive Reinitialized messages from multiple sources. It may be necessary to check the memory addresses of these
|
||||
//! parameters against local members before using this data.
|
||||
class MaterialReloadNotifications
|
||||
: public EBusTraits
|
||||
{
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace AZ
|
||||
// ShaderReloadNotificationBus::Handler overrides...
|
||||
void OnShaderReinitialized(const Shader& shader) override;
|
||||
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
|
||||
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
|
||||
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
|
||||
|
||||
void LoadShader();
|
||||
PassDescriptor m_passDescriptor;
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace AZ
|
||||
// ShaderReloadNotificationBus overrides...
|
||||
void OnShaderReinitialized(const Shader& shader) override;
|
||||
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
|
||||
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
|
||||
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
void LoadShader();
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace AZ
|
||||
// ShaderReloadNotificationBus overrides...
|
||||
void OnShaderReinitialized(const AZ::RPI::Shader& shader) override;
|
||||
void OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset) override;
|
||||
void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) override;
|
||||
void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) override;
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
// Update shader variant from m_shader. It's called whenever shader, shader asset or shader variant were changed.
|
||||
|
||||
@@ -22,10 +22,16 @@ namespace AZ
|
||||
{
|
||||
class Shader;
|
||||
class ShaderAsset;
|
||||
class ShaderVariant;
|
||||
|
||||
/**
|
||||
* Connect to this EBus to get notifications whenever a Data::Instance<Shader> reloads its ShaderAsset.
|
||||
* The bus address is the AssetId of the ShaderAsset.
|
||||
* Connect to this EBus to get notifications whenever a shader system class reinitializes itself.
|
||||
* The bus address is the AssetId of the ShaderAsset, even when the thing being reinitialized is a ShaderVariant or other shader related class.
|
||||
*
|
||||
* Be careful when using the parameters provided by these functions. The bus ID is an AssetId, and it's possible for the system to have
|
||||
* both *old* versions and *new reloaded* versions of the asset in memory at the same time, and they will have the same AssetId. Therefore
|
||||
* your bus Handlers could receive Reinitialized messages from multiple sources. It may be necessary to check the memory addresses of these
|
||||
* parameters against local members before using this data.
|
||||
*/
|
||||
class ShaderReloadNotifications
|
||||
: public EBusTraits
|
||||
@@ -35,7 +41,7 @@ namespace AZ
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
|
||||
typedef Data::AssetId BusIdType;
|
||||
typedef Data::AssetId BusIdType;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ~ShaderReloadNotifications() {}
|
||||
@@ -47,7 +53,7 @@ namespace AZ
|
||||
virtual void OnShaderReinitialized(const Shader& shader) { AZ_UNUSED(shader); }
|
||||
|
||||
//! Called when a particular shader variant is reinitialized.
|
||||
virtual void OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId) { AZ_UNUSED(shader); AZ_UNUSED(shaderVariantId); AZ_UNUSED(shaderVariantStableId); }
|
||||
virtual void OnShaderVariantReinitialized(const ShaderVariant& shaderVariant) { AZ_UNUSED(shaderVariant); }
|
||||
};
|
||||
|
||||
typedef EBus<ShaderReloadNotifications> ShaderReloadNotificationBus;
|
||||
|
||||
@@ -23,10 +23,12 @@ namespace AZ
|
||||
//! the RHI::PipelineStateType of the parent Shader instance. For shaders on the raster
|
||||
//! pipeline, the RHI::DrawFilterTag is also provided.
|
||||
class ShaderVariant final
|
||||
: public Data::AssetBus::MultiHandler
|
||||
{
|
||||
friend class Shader;
|
||||
public:
|
||||
ShaderVariant() = default;
|
||||
virtual ~ShaderVariant();
|
||||
AZ_DEFAULT_COPY_MOVE(ShaderVariant);
|
||||
|
||||
//! Fills a pipeline state descriptor with settings provided by the ShaderVariant. (Note that
|
||||
@@ -54,12 +56,21 @@ namespace AZ
|
||||
bool IsRootVariant() const { return m_shaderVariantAsset->IsRootVariant(); }
|
||||
|
||||
ShaderVariantStableId GetStableId() const { return m_shaderVariantAsset->GetStableId(); }
|
||||
|
||||
const Data::Asset<ShaderAsset>& GetShaderAsset() const { return m_shaderAsset; }
|
||||
const Data::Asset<ShaderVariantAsset>& GetShaderVariantAsset() const { return m_shaderVariantAsset; }
|
||||
|
||||
private:
|
||||
// Called by Shader. Initializes runtime data from asset data. Returns whether the call succeeded.
|
||||
bool Init(
|
||||
const ShaderAsset& shaderAsset,
|
||||
Data::Asset<ShaderVariantAsset> shaderVariantAsset);
|
||||
const Data::Asset<ShaderAsset>& shaderAsset,
|
||||
const Data::Asset<ShaderVariantAsset>& shaderVariantAsset);
|
||||
|
||||
// AssetBus overrides...
|
||||
void OnAssetReloaded(Data::Asset<Data::AssetData> asset) override;
|
||||
|
||||
//! A reference to the shader asset that this is a variant of.
|
||||
Data::Asset<ShaderAsset> m_shaderAsset;
|
||||
|
||||
// Cached state from the asset to avoid an indirection.
|
||||
RHI::PipelineStateType m_pipelineStateType = RHI::PipelineStateType::Count;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <Atom/RHI/CommandList.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI/Factory.h>
|
||||
#include <Atom/RHI/FrameGraphInterface.h>
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
@@ -78,6 +79,7 @@ namespace AZ
|
||||
|
||||
void GpuQuerySystem::Update()
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("RPI", "GpuQuerySystem: Update");
|
||||
for (auto& queryPool : m_queryPoolArray)
|
||||
{
|
||||
if (queryPool)
|
||||
|
||||
@@ -242,8 +242,16 @@ namespace AZ
|
||||
// MaterialReloadNotificationBus overrides...
|
||||
void Material::OnMaterialAssetReinitialized(const Data::Asset<MaterialAsset>& materialAsset)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str());
|
||||
OnAssetReloaded(materialAsset);
|
||||
// It's important that we don't just pass materialAsset to Init() because when reloads occur,
|
||||
// it's possible for old Asset objects to hang around and report reinitialization, so materialAsset
|
||||
// might be stale data.
|
||||
|
||||
if (materialAsset.Get() == m_materialAsset.Get())
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str());
|
||||
|
||||
OnAssetReloaded(m_materialAsset);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
@@ -259,8 +267,6 @@ namespace AZ
|
||||
|
||||
void Material::OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset)
|
||||
{
|
||||
// TODO: I think we should make Shader handle OnShaderAssetReinitialized and treat it just like the shader reloaded.
|
||||
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str());
|
||||
// Note that it might not be strictly necessary to reinitialize the entire material, we might be able to get away with
|
||||
// just bumping the m_currentChangeId or some other minor updates. But it's pretty hard to know what exactly needs to be
|
||||
@@ -268,9 +274,9 @@ namespace AZ
|
||||
OnAssetReloaded(m_materialAsset);
|
||||
}
|
||||
|
||||
void Material::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& /*shaderVariantId*/, ShaderVariantStableId shaderVariantStableId)
|
||||
void Material::OnShaderVariantReinitialized(const ShaderVariant& shaderVariant)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s variant %u", this, shader.GetAsset().GetHint().c_str(), shaderVariantStableId.GetIndex());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s", this, shaderVariant.GetShaderVariantAsset().GetHint().c_str());
|
||||
|
||||
// Note that it would be better to check the shaderVariantId to see if that variant is relevant to this particular material before reinitializing it.
|
||||
// There could be hundreds or even thousands of variants for a shader, but only one of those variants will be used by any given material. So we could
|
||||
|
||||
@@ -241,9 +241,8 @@ namespace AZ
|
||||
LoadShader();
|
||||
}
|
||||
|
||||
void ComputePass::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& shaderVariantId, ShaderVariantStableId shaderVariantStableId)
|
||||
void ComputePass::OnShaderVariantReinitialized(const ShaderVariant&)
|
||||
{
|
||||
AZ_UNUSED(shader); AZ_UNUSED(shaderVariantId); AZ_UNUSED(shaderVariantStableId);
|
||||
LoadShader();
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace AZ
|
||||
LoadShader();
|
||||
}
|
||||
|
||||
void FullscreenTrianglePass::OnShaderVariantReinitialized(const Shader&, const ShaderVariantId&, ShaderVariantStableId)
|
||||
void FullscreenTrianglePass::OnShaderVariantReinitialized(const ShaderVariant&)
|
||||
{
|
||||
LoadShader();
|
||||
}
|
||||
|
||||
@@ -61,6 +61,11 @@ namespace AZ
|
||||
{
|
||||
const PassAttachmentBinding& binding = m_attachmentBindings[slotIndex];
|
||||
|
||||
if (!binding.m_attachment)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle the depth-stencil attachment. There should be only one.
|
||||
if (binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::DepthStencil)
|
||||
{
|
||||
@@ -98,6 +103,10 @@ namespace AZ
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!binding.m_attachment)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::RenderTarget
|
||||
|| binding.m_scopeAttachmentUsage == RHI::ScopeAttachmentUsage::DepthStencil)
|
||||
|
||||
@@ -124,12 +124,9 @@ namespace AZ
|
||||
RefreshShaderVariant();
|
||||
}
|
||||
|
||||
void PipelineStateForDraw::OnShaderVariantReinitialized(
|
||||
[[maybe_unused]] const Shader& shader,
|
||||
const ShaderVariantId& shaderVariantId,
|
||||
[[maybe_unused]] ShaderVariantStableId shaderVariantStableId)
|
||||
void PipelineStateForDraw::OnShaderVariantReinitialized(const ShaderVariant& shaderVariant)
|
||||
{
|
||||
if(shaderVariantId == m_shaderVariantId)
|
||||
if(shaderVariant.GetShaderVariantId() == m_shaderVariantId)
|
||||
{
|
||||
RefreshShaderVariant();
|
||||
}
|
||||
|
||||
@@ -282,24 +282,27 @@ namespace AZ
|
||||
|
||||
m_rhiSystem.FrameUpdate(
|
||||
[this](RHI::FrameGraphBuilder& frameGraphBuilder)
|
||||
{
|
||||
// Pass system's frame update, which includes the logic of adding scope producers, has to be added here since the scope producers only can be added to the frame
|
||||
// when frame started which cleans up previous scope producers.
|
||||
m_passSystem.FrameUpdate(frameGraphBuilder);
|
||||
{
|
||||
// Pass system's frame update, which includes the logic of adding scope producers, has to be added here since the
|
||||
// scope producers only can be added to the frame when frame started which cleans up previous scope producers.
|
||||
m_passSystem.FrameUpdate(frameGraphBuilder);
|
||||
|
||||
// Update View Srgs
|
||||
for (auto& scenePtr : m_scenes)
|
||||
{
|
||||
scenePtr->UpdateSrgs();
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "RPISystem: FrameEnd");
|
||||
m_dynamicDraw.FrameEnd();
|
||||
m_passSystem.FrameEnd();
|
||||
|
||||
// Update View Srgs
|
||||
for (auto& scenePtr : m_scenes)
|
||||
{
|
||||
scenePtr->UpdateSrgs();
|
||||
scenePtr->OnFrameEnd();
|
||||
}
|
||||
});
|
||||
|
||||
m_dynamicDraw.FrameEnd();
|
||||
m_passSystem.FrameEnd();
|
||||
|
||||
for (auto& scenePtr : m_scenes)
|
||||
{
|
||||
scenePtr->OnFrameEnd();
|
||||
}
|
||||
|
||||
m_renderTick++;
|
||||
|
||||
@@ -404,6 +404,7 @@ namespace AZ
|
||||
|
||||
{
|
||||
AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "WaitForSimulationCompletion");
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "WaitForSimulationCompletion");
|
||||
WaitAndCleanCompletionJob(m_simulationCompletion);
|
||||
}
|
||||
|
||||
@@ -420,12 +421,15 @@ namespace AZ
|
||||
|
||||
// Get active pipelines which need to be rendered and notify them frame started
|
||||
AZStd::vector<RenderPipelinePtr> activePipelines;
|
||||
for (auto& pipeline : m_pipelines)
|
||||
{
|
||||
if (pipeline->NeedsRender())
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "OnStartFrame");
|
||||
for (auto& pipeline : m_pipelines)
|
||||
{
|
||||
activePipelines.push_back(pipeline);
|
||||
pipeline->OnStartFrame(tickInfo);
|
||||
if (pipeline->NeedsRender())
|
||||
{
|
||||
activePipelines.push_back(pipeline);
|
||||
pipeline->OnStartFrame(tickInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,7 +448,7 @@ namespace AZ
|
||||
|
||||
|
||||
{
|
||||
AZ_PROFILE_SCOPE(Debug::ProfileCategory::AzRender, "Setup Views");
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Setup Views");
|
||||
|
||||
// Collect persistent views from all pipelines to be rendered
|
||||
AZStd::map<ViewPtr, RHI::DrawListMask> persistentViews;
|
||||
@@ -490,7 +494,6 @@ namespace AZ
|
||||
{
|
||||
const auto renderLambda = [this, &fp]()
|
||||
{
|
||||
AZ_PROFILE_SCOPE_DYNAMIC(Debug::ProfileCategory::AzRender, "renderJob - fp:%s", fp->RTTI_GetTypeName());
|
||||
fp->Render(m_renderPacket);
|
||||
};
|
||||
|
||||
@@ -526,12 +529,14 @@ namespace AZ
|
||||
// Add dynamic draw data for all the views
|
||||
if (m_dynamicDrawSystem)
|
||||
{
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "DynamicDraw SubmitDrawData");
|
||||
m_dynamicDrawSystem->SubmitDrawData(this, m_renderPacket.m_views);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzRender, "FinalizeDrawLists");
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "FinalizeDrawLists");
|
||||
if (jobPolicy == RHI::JobPolicy::Serial)
|
||||
{
|
||||
for (auto& view : m_renderPacket.m_views)
|
||||
@@ -542,7 +547,6 @@ namespace AZ
|
||||
else
|
||||
{
|
||||
AZ::JobCompletion* finalizeDrawListsCompletion = aznew AZ::JobCompletion();
|
||||
AZ_PROFILE_EVENT_BEGIN(Debug::ProfileCategory::AzRender, "StartFinalizeDrawListsJobs");
|
||||
for (auto& view : m_renderPacket.m_views)
|
||||
{
|
||||
const auto finalizeDrawListsLambda = [view]()
|
||||
@@ -559,11 +563,15 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
SceneNotificationBus::Event(GetId(), &SceneNotification::OnEndPrepareRender);
|
||||
{
|
||||
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene OnEndPrepareRender");
|
||||
SceneNotificationBus::Event(GetId(), &SceneNotification::OnEndPrepareRender);
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::OnFrameEnd()
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: OnFrameEnd");
|
||||
for (auto& pipeline : m_pipelines)
|
||||
{
|
||||
if (pipeline->NeedsRender())
|
||||
@@ -702,6 +710,7 @@ namespace AZ
|
||||
|
||||
void Scene::RebuildPipelineStatesLookup()
|
||||
{
|
||||
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: RebuildPipelineStatesLookup");
|
||||
m_pipelineStatesLookup.clear();
|
||||
|
||||
AZStd::queue<ParentPass*> parents;
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace AZ
|
||||
AZStd::unique_lock<decltype(m_variantCacheMutex)> lock(m_variantCacheMutex);
|
||||
m_shaderVariants.clear();
|
||||
}
|
||||
m_rootVariant.Init(shaderAsset, shaderAsset.GetRootVariant());
|
||||
m_rootVariant.Init(Data::Asset<ShaderAsset>{&shaderAsset, AZ::Data::AssetLoadBehavior::PreLoad}, shaderAsset.GetRootVariant());
|
||||
|
||||
if (m_pipelineLibraryHandle.IsNull())
|
||||
{
|
||||
@@ -154,7 +154,14 @@ namespace AZ
|
||||
{
|
||||
AZ_Assert(shaderVariantAsset, "Reloaded ShaderVariantAsset is null");
|
||||
const ShaderVariantStableId stableId = shaderVariantAsset->GetStableId();
|
||||
const ShaderVariantId& shaderVariantId = shaderVariantAsset->GetShaderVariantId();
|
||||
|
||||
// We make a copy of the updated variant because OnShaderVariantReinitialized must not be called inside
|
||||
// m_variantCacheMutex or deadlocks may occur.
|
||||
// Or if there is an error, we leave this object in its default state to indicate there was an error.
|
||||
// [GFX TODO] We really should have a dedicated message/event for this, but that will be covered by a future task where
|
||||
// we will merge ShaderReloadNotificationBus messages into one. For now, we just indicate the error by passing an empty ShaderVariant,
|
||||
// all our call sites don't use this data anyway.
|
||||
ShaderVariant updatedVariant;
|
||||
|
||||
if (isError)
|
||||
{
|
||||
@@ -165,7 +172,7 @@ namespace AZ
|
||||
return;
|
||||
}
|
||||
AZStd::unique_lock<decltype(m_variantCacheMutex)> lock(m_variantCacheMutex);
|
||||
m_shaderVariants.erase(stableId);
|
||||
m_shaderVariants.erase(stableId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -178,23 +185,26 @@ namespace AZ
|
||||
{
|
||||
ShaderVariant& shaderVariant = iter->second;
|
||||
|
||||
if (!shaderVariant.Init(*m_asset.Get(), shaderVariantAsset))
|
||||
if (!shaderVariant.Init(m_asset, shaderVariantAsset))
|
||||
{
|
||||
AZ_Error("Shader", false, "Failed to init shaderVariant with StableId=%u", shaderVariantAsset->GetStableId());
|
||||
m_shaderVariants.erase(stableId);
|
||||
}
|
||||
else
|
||||
{
|
||||
updatedVariant = shaderVariant;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//This is the first time the shader variant asset comes to life.
|
||||
ShaderVariant newVariant;
|
||||
newVariant.Init(*m_asset, shaderVariantAsset);
|
||||
m_shaderVariants.emplace(stableId, newVariant);
|
||||
updatedVariant.Init(m_asset, shaderVariantAsset);
|
||||
m_shaderVariants.emplace(stableId, updatedVariant);
|
||||
}
|
||||
}
|
||||
|
||||
//Even if there was an error, the interested parties should be notified.
|
||||
ShaderReloadNotificationBus::Event(m_asset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this, shaderVariantId, stableId);
|
||||
// [GFX TODO] It might make more sense to call OnShaderReinitialized here
|
||||
ShaderReloadNotificationBus::Event(m_asset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, updatedVariant);
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -203,10 +213,15 @@ namespace AZ
|
||||
// ShaderReloadNotificationBus overrides...
|
||||
void Shader::OnShaderAssetReinitialized(const Data::Asset<ShaderAsset>& shaderAsset)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Shader::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str());
|
||||
// When reloads occur, it's possible for old Asset objects to hang around and report reinitialization,
|
||||
// so we can reduce unnecessary reinitialization in that case.
|
||||
if (shaderAsset.Get() == m_asset.Get())
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Shader::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str());
|
||||
|
||||
Init(*m_asset.Get());
|
||||
ShaderReloadNotificationBus::Event(shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderReinitialized, *this);
|
||||
Init(*m_asset.Get());
|
||||
ShaderReloadNotificationBus::Event(shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderReinitialized, *this);
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -340,7 +355,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
ShaderVariant newVariant;
|
||||
newVariant.Init(*m_asset, shaderVariantAsset);
|
||||
newVariant.Init(m_asset, shaderVariantAsset);
|
||||
m_shaderVariants.emplace(shaderVariantStableId, newVariant);
|
||||
|
||||
return m_shaderVariants.at(shaderVariantStableId);
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/RPI.Public/Shader/ShaderVariant.h>
|
||||
#include <Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h>
|
||||
#include <Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h>
|
||||
|
||||
#include <Atom/RHI/DrawListTagRegistry.h>
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
|
||||
#include <Atom/RHI.Reflect/ShaderStageFunction.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -21,15 +23,26 @@ namespace AZ
|
||||
namespace RPI
|
||||
{
|
||||
bool ShaderVariant::Init(
|
||||
const ShaderAsset& shaderAsset,
|
||||
Data::Asset<ShaderVariantAsset> shaderVariantAsset)
|
||||
{
|
||||
m_pipelineStateType = shaderAsset.GetPipelineStateType();
|
||||
m_pipelineLayoutDescriptor = shaderAsset.GetPipelineLayoutDescriptor();
|
||||
const Data::Asset<ShaderAsset>& shaderAsset,
|
||||
const Data::Asset<ShaderVariantAsset>& shaderVariantAsset)
|
||||
{
|
||||
Data::AssetBus::MultiHandler::BusDisconnect();
|
||||
Data::AssetBus::MultiHandler::BusConnect(shaderAsset.GetId());
|
||||
Data::AssetBus::MultiHandler::BusConnect(shaderVariantAsset.GetId());
|
||||
|
||||
m_shaderAsset = shaderAsset;
|
||||
m_pipelineStateType = shaderAsset->GetPipelineStateType();
|
||||
m_pipelineLayoutDescriptor = shaderAsset->GetPipelineLayoutDescriptor();
|
||||
m_shaderVariantAsset = shaderVariantAsset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ShaderVariant::~ShaderVariant()
|
||||
{
|
||||
Data::AssetBus::MultiHandler::BusDisconnect();
|
||||
}
|
||||
|
||||
void ShaderVariant::ConfigurePipelineState(RHI::PipelineStateDescriptor& descriptor) const
|
||||
{
|
||||
descriptor.m_pipelineLayoutDescriptor = m_pipelineLayoutDescriptor;
|
||||
@@ -78,5 +91,25 @@ namespace AZ
|
||||
{
|
||||
return m_shaderVariantAsset->GetOutputContract();
|
||||
}
|
||||
|
||||
void ShaderVariant::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderVariant::OnAssetReloaded %s", this, asset.GetHint().c_str());
|
||||
|
||||
if (asset.GetAs<ShaderVariantAsset>())
|
||||
{
|
||||
Data::Asset<ShaderVariantAsset> shaderVariantAsset = { asset.GetAs<ShaderVariantAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
Init(m_shaderAsset, shaderVariantAsset);
|
||||
ShaderReloadNotificationBus::Event(m_shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this);
|
||||
}
|
||||
|
||||
if (asset.GetAs<ShaderAsset>())
|
||||
{
|
||||
Data::Asset<ShaderAsset> shaderAsset = { asset.GetAs<ShaderAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
Init(shaderAsset, m_shaderVariantAsset);
|
||||
ShaderReloadNotificationBus::Event(m_shaderAsset.GetId(), &ShaderReloadNotificationBus::Events::OnShaderVariantReinitialized, *this);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
|
||||
@@ -323,9 +323,8 @@ namespace AZ
|
||||
|
||||
void ShaderVariantAsyncLoader::Reset()
|
||||
{
|
||||
// [GFX TODO ATOM-14544] Idealy we want to be able to reset the ShaderVariantAsyncLoader but this is causing some problems that need to be worked out first.
|
||||
//Shutdown();
|
||||
//Init();
|
||||
Shutdown();
|
||||
Init();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -115,12 +115,19 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialAsset::OnMaterialTypeAssetReinitialized(const Data::Asset<MaterialTypeAsset>&)
|
||||
void MaterialAsset::OnMaterialTypeAssetReinitialized(const Data::Asset<MaterialTypeAsset>& materialTypeAsset)
|
||||
{
|
||||
// MaterialAsset doesn't need to reinitialize any of its own data when MaterialTypeAsset reinitializes,
|
||||
// because all it depends on is the MaterialTypeAsset reference, rather than the data inside it.
|
||||
// Ultimately it's the Material that cares about these changes, so we just forward any signal we get.
|
||||
MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset<MaterialAsset>{this, AZ::Data::AssetLoadBehavior::PreLoad});
|
||||
// When reloads occur, it's possible for old Asset objects to hang around and report reinitialization,
|
||||
// so we can reduce unnecessary reinitialization in that case.
|
||||
if (materialTypeAsset.Get() == m_materialTypeAsset.Get())
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnMaterialTypeAssetReinitialized %s", this, materialTypeAsset.GetHint().c_str());
|
||||
|
||||
// MaterialAsset doesn't need to reinitialize any of its own data when MaterialTypeAsset reinitializes,
|
||||
// because all it depends on is the MaterialTypeAsset reference, rather than the data inside it.
|
||||
// Ultimately it's the Material that cares about these changes, so we just forward any signal we get.
|
||||
MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset<MaterialAsset>{this, AZ::Data::AssetLoadBehavior::PreLoad});
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialAsset::ReinitializeMaterialTypeAsset(Data::Asset<Data::AssetData> asset)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -56,6 +57,16 @@ namespace AZ
|
||||
ImGuiTextFilter m_timedRegionFilter;
|
||||
|
||||
GroupRegionMap m_groupRegionMap;
|
||||
|
||||
// Pause cpu profiling. The profiler will show the statistics of the last frame before pause
|
||||
bool m_paused = false;
|
||||
|
||||
// Total frames need to be saved
|
||||
int m_captureFrameCount = 1;
|
||||
|
||||
AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause;
|
||||
|
||||
AZStd::string m_lastCapturedFilePath;
|
||||
};
|
||||
} // namespace Render
|
||||
}
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
|
||||
#include <Atom/Feature/Utils/ProfilingCaptureBus.h>
|
||||
#include <Atom/RPI.Public/RPISystemInterface.h>
|
||||
#include <AzCore/IO/SystemFile.h> // For AZ_MAX_PATH_LEN
|
||||
#include <AzCore/std/time.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -34,16 +37,42 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics)
|
||||
inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics)
|
||||
{
|
||||
// Cache the value to detect if it was changed by ImGui(user pressed 'x')
|
||||
const bool cachedShowCpuProfiler = keepDrawing;
|
||||
|
||||
const ImVec2 windowSize(640.0f, 480.0f);
|
||||
ImGui::SetNextWindowSize(windowSize, ImGuiCond_Once);
|
||||
bool captureToFile = false;
|
||||
if (ImGui::Begin("Cpu Profiler", &keepDrawing, ImGuiWindowFlags_None))
|
||||
{
|
||||
UpdateGroupRegionMap();
|
||||
m_paused = !AZ::RHI::CpuProfiler::Get()->IsProfilerEnabled();
|
||||
if (ImGui::Button(m_paused?"Resume":"Pause"))
|
||||
{
|
||||
m_paused = !m_paused;
|
||||
AZ::RHI::CpuProfiler::Get()->SetProfilerEnabled(!m_paused);
|
||||
}
|
||||
|
||||
// Update region map and cache the input cpu timing statistics when the profiling is not paused
|
||||
if (!m_paused)
|
||||
{
|
||||
UpdateGroupRegionMap();
|
||||
m_cpuTimingStatisticsWhenPause = currentCpuTimingStatistics;
|
||||
}
|
||||
|
||||
if (ImGui::Button("Capture"))
|
||||
{
|
||||
captureToFile = true;
|
||||
}
|
||||
|
||||
if (!m_lastCapturedFilePath.empty())
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(m_lastCapturedFilePath.c_str());
|
||||
}
|
||||
|
||||
const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics = m_cpuTimingStatisticsWhenPause;
|
||||
|
||||
const AZStd::sys_time_t ticksPerSecond = AZStd::GetTimeTicksPerSecond();
|
||||
|
||||
@@ -51,7 +80,7 @@ namespace AZ
|
||||
{
|
||||
// Note: converting to microseconds integer before converting to milliseconds float
|
||||
const float timeInMs = static_cast<float>((duration * 1000) / (ticksPerSecond / 1000)) / 1000.0f;
|
||||
ImGui::Text("%.1f ms", timeInMs);
|
||||
ImGui::Text("%.2f ms", timeInMs);
|
||||
};
|
||||
|
||||
const auto ShowRow = [ticksPerSecond, &ShowTimeInMs](const char* regionLabel, AZStd::sys_time_t duration)
|
||||
@@ -158,6 +187,20 @@ namespace AZ
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
if (captureToFile)
|
||||
{
|
||||
AZStd::sys_time_t timeNow = AZStd::GetTimeNowSecond();
|
||||
AZStd::string timeString;
|
||||
AZStd::to_string(timeString, timeNow);
|
||||
u64 currentTick = AZ::RPI::RPISystemInterface::Get()->GetCurrentTick();
|
||||
AZStd::string frameDataFilePath = AZStd::string::format("@user@/CpuProfiler/%s_%llu.json", timeString.c_str(), currentTick);
|
||||
char resolvedPath[AZ_MAX_PATH_LEN];
|
||||
AZ::IO::FileIOBase::GetInstance()->ResolvePath(frameDataFilePath.c_str(), resolvedPath, AZ_MAX_PATH_LEN);
|
||||
m_lastCapturedFilePath = resolvedPath;
|
||||
AZ::Render::ProfilingCaptureRequestBus::Broadcast(&AZ::Render::ProfilingCaptureRequestBus::Events::CaptureCpuProfilingStatistics,
|
||||
frameDataFilePath);
|
||||
}
|
||||
|
||||
// Toggle if the bool isn't the same as the cached value
|
||||
if (cachedShowCpuProfiler != keepDrawing)
|
||||
{
|
||||
|
||||
+7
@@ -143,6 +143,13 @@ namespace AZ
|
||||
|
||||
//! Sets the type of Pcf (percentage-closer filtering) to use.
|
||||
virtual void SetPcfMethod(PcfMethod method) = 0;
|
||||
|
||||
//! Gets the Esm exponent. Higher values produce a steeper falloff between light and shadow.
|
||||
virtual float GetEsmExponent() const = 0;
|
||||
|
||||
//! Sets the Esm exponent. Higher values produce a steeper falloff between light and shadow.
|
||||
virtual void SetEsmExponent(float exponent) = 0;
|
||||
|
||||
};
|
||||
|
||||
//! The EBus for requests to for setting and getting light component properties.
|
||||
|
||||
+3
@@ -66,6 +66,7 @@ namespace AZ
|
||||
float m_boundaryWidthInDegrees = 0.25f;
|
||||
uint16_t m_predictionSampleCount = 4;
|
||||
uint16_t m_filteringSampleCount = 12;
|
||||
float m_esmExponent = 87.0f;
|
||||
|
||||
// The following functions provide information to an EditContext...
|
||||
|
||||
@@ -124,6 +125,8 @@ namespace AZ
|
||||
//! Returns true if pcf boundary search is disabled.
|
||||
bool IsPcfBoundarySearchDisabled() const;
|
||||
|
||||
//! Returns true if exponential shadow maps are disabled.
|
||||
bool IsEsmDisabled() const;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -21,7 +21,7 @@ namespace AZ
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<AreaLightComponentConfig, ComponentConfig>()
|
||||
->Version(5) // ATOM-14637
|
||||
->Version(6) // ATOM-15654
|
||||
->Field("LightType", &AreaLightComponentConfig::m_lightType)
|
||||
->Field("Color", &AreaLightComponentConfig::m_color)
|
||||
->Field("IntensityMode", &AreaLightComponentConfig::m_intensityMode)
|
||||
@@ -41,7 +41,8 @@ namespace AZ
|
||||
->Field("Softening Boundary Width", &AreaLightComponentConfig::m_boundaryWidthInDegrees)
|
||||
->Field("Prediction Sample Count", &AreaLightComponentConfig::m_predictionSampleCount)
|
||||
->Field("Filtering Sample Count", &AreaLightComponentConfig::m_filteringSampleCount)
|
||||
->Field("Pcf Method", &AreaLightComponentConfig::m_pcfMethod);
|
||||
->Field("Pcf Method", &AreaLightComponentConfig::m_pcfMethod)
|
||||
->Field("Esm Exponent", &AreaLightComponentConfig::m_esmExponent)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -200,5 +201,11 @@ namespace AZ
|
||||
|
||||
return m_pcfMethod != PcfMethod::BoundarySearch;
|
||||
}
|
||||
|
||||
bool AreaLightComponentConfig::IsEsmDisabled() const
|
||||
{
|
||||
return !(m_shadowFilterMethod == ShadowFilterMethod::Esm || m_shadowFilterMethod == ShadowFilterMethod::EsmPcf);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+21
-3
@@ -84,7 +84,9 @@ namespace AZ::Render
|
||||
->Event("SetFilteringSampleCount", &AreaLightRequestBus::Events::SetFilteringSampleCount)
|
||||
->Event("GetPcfMethod", &AreaLightRequestBus::Events::GetPcfMethod)
|
||||
->Event("SetPcfMethod", &AreaLightRequestBus::Events::SetPcfMethod)
|
||||
|
||||
->Event("GetEsmExponent", &AreaLightRequestBus::Events::GetEsmExponent)
|
||||
->Event("SetEsmExponent", &AreaLightRequestBus::Events::SetEsmExponent)
|
||||
|
||||
->VirtualProperty("AttenuationRadius", "GetAttenuationRadius", "SetAttenuationRadius")
|
||||
->VirtualProperty("Color", "GetColor", "SetColor")
|
||||
->VirtualProperty("EmitsLightBothDirections", "GetEmitsLightBothDirections", "SetEmitsLightBothDirections")
|
||||
@@ -101,8 +103,9 @@ namespace AZ::Render
|
||||
->VirtualProperty("SofteningBoundaryWidthAngle", "GetSofteningBoundaryWidthAngle", "SetSofteningBoundaryWidthAngle")
|
||||
->VirtualProperty("PredictionSampleCount", "GetPredictionSampleCount", "SetPredictionSampleCount")
|
||||
->VirtualProperty("FilteringSampleCount", "GetFilteringSampleCount", "SetFilteringSampleCount")
|
||||
->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod");
|
||||
;
|
||||
->VirtualProperty("PcfMethod", "GetPcfMethod", "SetPcfMethod")
|
||||
->VirtualProperty("EsmExponent", "GetEsmExponent", "SetEsmExponent");
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,6 +317,7 @@ namespace AZ::Render
|
||||
m_lightShapeDelegate->SetPredictionSampleCount(m_configuration.m_predictionSampleCount);
|
||||
m_lightShapeDelegate->SetFilteringSampleCount(m_configuration.m_filteringSampleCount);
|
||||
m_lightShapeDelegate->SetPcfMethod(m_configuration.m_pcfMethod);
|
||||
m_lightShapeDelegate->SetEsmExponent(m_configuration.m_esmExponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -565,6 +569,20 @@ namespace AZ::Render
|
||||
}
|
||||
}
|
||||
|
||||
float AreaLightComponentController::GetEsmExponent() const
|
||||
{
|
||||
return m_configuration.m_esmExponent;
|
||||
}
|
||||
|
||||
void AreaLightComponentController::SetEsmExponent(float esmExponent)
|
||||
{
|
||||
m_configuration.m_esmExponent = esmExponent;
|
||||
if (m_lightShapeDelegate)
|
||||
{
|
||||
m_lightShapeDelegate->SetEsmExponent(esmExponent);
|
||||
}
|
||||
}
|
||||
|
||||
void AreaLightComponentController::CreateLightShapeDelegate()
|
||||
{
|
||||
switch (m_configuration.m_lightType)
|
||||
|
||||
+2
@@ -92,6 +92,8 @@ namespace AZ
|
||||
void SetFilteringSampleCount(uint32_t count) override;
|
||||
PcfMethod GetPcfMethod() const override;
|
||||
void SetPcfMethod(PcfMethod method) override;
|
||||
float GetEsmExponent() const override;
|
||||
void SetEsmExponent(float exponent) override;
|
||||
|
||||
void HandleDisplayEntityViewport(
|
||||
const AzFramework::ViewportInfo& viewportInfo,
|
||||
|
||||
@@ -175,5 +175,13 @@ namespace AZ::Render
|
||||
}
|
||||
}
|
||||
|
||||
void DiskLightDelegate::SetEsmExponent(float exponent)
|
||||
{
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), exponent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace AZ::Render
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace AZ
|
||||
void SetPredictionSampleCount(uint32_t count) override;
|
||||
void SetFilteringSampleCount(uint32_t count) override;
|
||||
void SetPcfMethod(PcfMethod method) override;
|
||||
void SetEsmExponent(float exponent) override;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
+13
-2
@@ -179,8 +179,19 @@ namespace AZ
|
||||
->EnumAttribute(PcfMethod::BoundarySearch, "Boundary search")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled);
|
||||
;
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsShadowPcfDisabled)
|
||||
->DataElement(
|
||||
Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_esmExponent, "Esm Exponent",
|
||||
"Exponent used by Esm shadows. "
|
||||
"Larger values increase the sharpness of the border between lit and unlit areas.")
|
||||
->Attribute(Edit::Attributes::Min, 50.0f)
|
||||
->Attribute(Edit::Attributes::Max, 5000.0f)
|
||||
->Attribute(AZ::Edit::Attributes::Decimals, 0)
|
||||
->Attribute(AZ::Edit::Attributes::SliderCurveMidpoint, 0.05f)
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShadows)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::IsEsmDisabled)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace AZ
|
||||
void SetPredictionSampleCount([[maybe_unused]] uint32_t count) override {};
|
||||
void SetFilteringSampleCount([[maybe_unused]] uint32_t count) override {};
|
||||
void SetPcfMethod([[maybe_unused]] PcfMethod method) override {};
|
||||
void SetEsmExponent([[maybe_unused]] float esmExponent) override{};
|
||||
|
||||
protected:
|
||||
void InitBase(EntityId entityId);
|
||||
|
||||
@@ -85,6 +85,8 @@ namespace AZ
|
||||
virtual void SetFilteringSampleCount(uint32_t count) = 0;
|
||||
//! Sets the Pcf (Percentage closer filtering) method to use.
|
||||
virtual void SetPcfMethod(PcfMethod method) = 0;
|
||||
//! Sets the Esm exponent to use. Higher values produce a steeper falloff between light and shadow.
|
||||
virtual void SetEsmExponent(float exponent) = 0;
|
||||
};
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -122,5 +122,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void SphereLightDelegate::SetEsmExponent(float esmExponent)
|
||||
{
|
||||
if (GetShadowsEnabled() && GetLightHandle().IsValid())
|
||||
{
|
||||
GetFeatureProcessor()->SetEsmExponent(GetLightHandle(), esmExponent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace AZ
|
||||
void SetPredictionSampleCount(uint32_t count) override;
|
||||
void SetFilteringSampleCount(uint32_t count) override;
|
||||
void SetPcfMethod(PcfMethod method) override;
|
||||
void SetEsmExponent(float esmExponent) override;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -286,9 +286,13 @@ namespace Blast
|
||||
|
||||
// Create damage and actor render managers
|
||||
m_damageManager = AZStd::make_unique<DamageManager>(blastMaterial, m_family->GetActorTracker());
|
||||
m_actorRenderManager = AZStd::make_unique<ActorRenderManager>(
|
||||
AZ::RPI::Scene::GetFeatureProcessorForEntity<AZ::Render::MeshFeatureProcessorInterface>(GetEntityId()),
|
||||
m_meshDataComponent, GetEntityId(), m_blastAsset->GetPxAsset()->getChunkCount(), AZ::Vector3(transform.GetUniformScale()));
|
||||
|
||||
if (m_meshDataComponent)
|
||||
{
|
||||
m_actorRenderManager = AZStd::make_unique<ActorRenderManager>(
|
||||
AZ::RPI::Scene::GetFeatureProcessorForEntity<AZ::Render::MeshFeatureProcessorInterface>(GetEntityId()),
|
||||
m_meshDataComponent, GetEntityId(), m_blastAsset->GetPxAsset()->getChunkCount(), AZ::Vector3(transform.GetUniformScale()));
|
||||
}
|
||||
|
||||
// Spawn the family
|
||||
m_family->Spawn(transform);
|
||||
@@ -540,7 +544,11 @@ namespace Blast
|
||||
|
||||
void BlastFamilyComponent::OnActorCreated([[maybe_unused]] const BlastFamily& family, const BlastActor& actor)
|
||||
{
|
||||
m_actorRenderManager->OnActorCreated(actor);
|
||||
if (m_actorRenderManager)
|
||||
{
|
||||
m_actorRenderManager->OnActorCreated(actor);
|
||||
}
|
||||
|
||||
m_solver->notifyActorCreated(*actor.GetTkActor().getActorLL());
|
||||
|
||||
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
|
||||
@@ -576,7 +584,11 @@ namespace Blast
|
||||
}
|
||||
|
||||
m_solver->notifyActorDestroyed(*actor.GetTkActor().getActorLL());
|
||||
m_actorRenderManager->OnActorDestroyed(actor);
|
||||
|
||||
if (m_actorRenderManager)
|
||||
{
|
||||
m_actorRenderManager->OnActorDestroyed(actor);
|
||||
}
|
||||
}
|
||||
|
||||
// Update positions of entities with render meshes corresponding to their right dynamic bodies.
|
||||
|
||||
@@ -826,7 +826,7 @@ enum class NetworkProperties
|
||||
#}
|
||||
{% macro DefineNetworkPropertyBehaviorReflection(Component, ReplicateFrom, ReplicateTo, ClassName) %}
|
||||
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
|
||||
{% if (Property.attrib['IsPublic'] | booleanTrue == true) and (Property.attrib['GenerateEventBindings'] | booleanTrue == true) -%}
|
||||
{% if (Property.attrib['IsPublic'] | booleanTrue == true) and (Property.attrib['ExposeToScript'] | booleanTrue == true) -%}
|
||||
// {{ UpperFirst(Property.attrib['Name']) }}: Replicate from {{ ReplicateFrom }} to {{ ReplicateTo }}
|
||||
{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
|
||||
->Method("Get{{ UpperFirst(Property.attrib['Name']) }}", [](AZ::EntityId id, int32_t index) -> {{ Property.attrib['Type'] }}
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
<Include File="Source/NetworkInput/NetworkInputMigrationVector.h"/>
|
||||
<Include File="AzNetworking/DataStructures/ByteBuffer.h"/>
|
||||
|
||||
<NetworkProperty Type="Multiplayer::ClientInputId" Name="LastInputId" Init="Multiplayer::ClientInputId{ 0 }" ReplicateFrom="Authority" ReplicateTo="Server" IsRewindable="false" IsPredictable="false" IsPublic="false" Container="Object" ExposeToEditor="false" GenerateEventBindings="false" />
|
||||
<NetworkProperty Type="Multiplayer::ClientInputId" Name="LastInputId" Init="Multiplayer::ClientInputId{ 0 }" ReplicateFrom="Authority" ReplicateTo="Server" IsRewindable="false" IsPredictable="false" IsPublic="false" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="false" />
|
||||
|
||||
<RemoteProcedure Name="SendClientInput" InvokeFrom="Autonomous" HandleOn="Authority" IsPublic="true" IsReliable="false" GenerateEventBindings="false" Description="Client to server move / input RPC">
|
||||
<Param Type="Multiplayer::NetworkInputArray" Name="inputArray" />
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
|
||||
<Include File="Multiplayer/MultiplayerTypes.h"/>
|
||||
|
||||
<NetworkProperty Type="AZ::Quaternion" Name="rotation" Init="AZ::Quaternion::CreateIdentity()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="AZ::Vector3" Name="translation" Init="AZ::Vector3::CreateZero()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="float" Name="scale" Init="1.0f" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="uint8_t" Name="resetCount" Init="0" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="false" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="NetEntityId" Name="parentEntityId" Init="InvalidNetEntityId" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="int32_t" Name="parentAttachmentBoneId" Init="-1" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="AZ::Quaternion" Name="rotation" Init="AZ::Quaternion::CreateIdentity()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="AZ::Vector3" Name="translation" Init="AZ::Vector3::CreateZero()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="float" Name="scale" Init="1.0f" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="uint8_t" Name="resetCount" Init="0" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="false" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="NetEntityId" Name="parentEntityId" Init="InvalidNetEntityId" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="int32_t" Name="parentAttachmentBoneId" Init="-1" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" ExposeToScript="false" GenerateEventBindings="true" />
|
||||
|
||||
<!--
|
||||
<ArchetypeProperty Type="bool" Name="snapToGround" Init="false" ExposeToEditor="true" />
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:056f3c42226567848b7b7bd959cde0dccdcf63a79700743e55436eae35520a28
|
||||
size 80
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5fc10f1dd377cc2663faaa6aa5503aadb8288179cddc46bb3379337167c150fc
|
||||
size 76
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:785988d40e9af3f1f6adccc10a5a6fa1f6a78b6f6bb10647acf0f3997cd14834
|
||||
size 80
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:76017bdaf559051a5ec6fb46a9132020ad54d35c1bdaf39511e52f0d3faeffe2
|
||||
size 87
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2b8efdd98b365874375ea80ee02c3b8e3d951aa5f74fe50fb0cfd2a431395b23
|
||||
size 85
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fa1ed0cda25890a36a3f2c9f4bd2cbfbb4cef0198258f1b33a0ad3fb804c860c
|
||||
size 91
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:38cff841ea29a428729b79667672d3825188b9eec74ce0be324c5a072958c63d
|
||||
size 68
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cc9ad675bca0b1446b9d3ad9b6bf53b1348f7dd96e00eb256744f82273b9f9da
|
||||
size 76
|
||||
@@ -1,173 +0,0 @@
|
||||
----------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- 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.
|
||||
--
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------
|
||||
Constraint =
|
||||
{
|
||||
Properties=
|
||||
{
|
||||
radius = 0.03,
|
||||
damping = 0,
|
||||
bNoSelfCollisions = 1,
|
||||
bUseEntityFrame=1,
|
||||
max_pull_force=0,
|
||||
max_bend_torque=0,
|
||||
bConstrainToLine=0,
|
||||
bConstrainToPlane=0,
|
||||
bConstrainFully=1,
|
||||
bNoRotation=0,
|
||||
Limits = {
|
||||
x_min = 0,
|
||||
x_max = 0,
|
||||
yz_min = 0,
|
||||
yz_max = 0,
|
||||
}
|
||||
},
|
||||
numUpdates = 0,
|
||||
|
||||
Editor=
|
||||
{
|
||||
Icon="Magnet.bmp",
|
||||
ShowBounds = 1,
|
||||
},
|
||||
}
|
||||
|
||||
function Constraint:OnReset()
|
||||
--Log("%s:OnReset() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
|
||||
-- tostring(self.idConstr), tostring(self.broken))
|
||||
|
||||
--if (self.idConstr) then
|
||||
--System.GetEntity(self.idEnt):SetPhysicParams(PHYSICPARAM_REMOVE_CONSTRAINT, { id=self.idConstr })
|
||||
--end
|
||||
|
||||
self.idEnt = nil
|
||||
self.idConstr = nil
|
||||
self.broken = nil
|
||||
self.numUpdates = 0
|
||||
self:SetFlags(ENTITY_FLAG_CLIENT_ONLY,0);
|
||||
end
|
||||
|
||||
function Constraint:Apply()
|
||||
--Log("%s:Apply() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
|
||||
-- tostring(self.idConstr), tostring(self.broken))
|
||||
|
||||
local ConstraintParams = {pivot={},frame0={},frame1={}};
|
||||
if self.idEnt then
|
||||
elseif (not self.broken) then
|
||||
local ents = Physics.SamplePhysEnvironment(self:GetPos(), self.Properties.radius);
|
||||
if (ents[1] and ents[6]) then
|
||||
CopyVector(ConstraintParams.pivot, self:GetPos());
|
||||
if self.Properties.bUseEntityFrame==1 then
|
||||
CopyVector(ConstraintParams.frame1, ents[1]:GetAngles());
|
||||
else
|
||||
CopyVector(ConstraintParams.frame1, self:GetAngles());
|
||||
end
|
||||
CopyVector(ConstraintParams.frame0, ConstraintParams.frame1);
|
||||
ConstraintParams.entity_part_id_1 = ents[2];
|
||||
ConstraintParams.phys_entity_id = ents[6];
|
||||
ConstraintParams.entity_part_id_2 = ents[5];
|
||||
ConstraintParams.xmin = self.Properties.Limits.x_min;
|
||||
ConstraintParams.xmax = self.Properties.Limits.x_max;
|
||||
ConstraintParams.yzmin = self.Properties.Limits.yz_min;
|
||||
ConstraintParams.yzmax = self.Properties.Limits.yz_max;
|
||||
ConstraintParams.ignore_buddy = self.Properties.bNoSelfCollisions;
|
||||
ConstraintParams.damping = self.Properties.damping;
|
||||
ConstraintParams.sensor_size = self.Properties.radius;
|
||||
ConstraintParams.max_pull_force = self.Properties.max_pull_force;
|
||||
ConstraintParams.max_bend_torque = self.Properties.max_bend_torque;
|
||||
ConstraintParams.line = self.Properties.bConstrainToLine;
|
||||
ConstraintParams.plane = self.Properties.bConstrainToPlane;
|
||||
ConstraintParams.no_rotation = self.Properties.bNoRotation;
|
||||
ConstraintParams.full = self.Properties.bConstrainFully;
|
||||
self.idConstr = ents[1]:SetPhysicParams(PHYSICPARAM_CONSTRAINT, ConstraintParams);
|
||||
self.idEnt = ents[1].id;
|
||||
else
|
||||
self:SetTimer(1,1);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Constraint:OnTimer()
|
||||
if (self.numUpdates < 10) then
|
||||
self:Apply();
|
||||
self.numUpdates = self.numUpdates+1;
|
||||
end
|
||||
end
|
||||
|
||||
function Constraint:OnLevelLoaded()
|
||||
--Log("%s:OnLevelLoaded() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
|
||||
-- tostring(self.idConstr), tostring(self.broken))
|
||||
|
||||
if ((not self.broken) and (not self.idConstr)) then
|
||||
self.numUpdates = 0
|
||||
self.idEnt = nil
|
||||
self.idConstr = nil
|
||||
self:Apply()
|
||||
end
|
||||
end
|
||||
|
||||
function Constraint:OnPropertyChange()
|
||||
self:OnReset()
|
||||
end
|
||||
|
||||
function Constraint:OnSpawn()
|
||||
self:OnReset()
|
||||
end
|
||||
|
||||
function Constraint:Event_ConstraintBroken(sender)
|
||||
--Log("%s:Event_ConstraintBroken() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
|
||||
-- tostring(self.idConstr), tostring(self.broken))
|
||||
|
||||
if self.idEnt then
|
||||
System.GetEntity(self.idEnt):SetPhysicParams(PHYSICPARAM_REMOVE_CONSTRAINT, { id=self.idConstr });
|
||||
self.idEnt = nil
|
||||
self.idConstr = nil
|
||||
end
|
||||
|
||||
self.broken = true
|
||||
self:KillTimer(1)
|
||||
|
||||
BroadcastEvent(self, "ConstraintBroken")
|
||||
end
|
||||
|
||||
function Constraint:OnSave( props )
|
||||
--Log("%s:OnSave() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
|
||||
-- tostring(self.idConstr), tostring(self.broken))
|
||||
|
||||
props.broken = self.broken
|
||||
props.idEnt = self.idEnt
|
||||
props.idConstr = self.idConstr
|
||||
end
|
||||
|
||||
function Constraint:OnLoad( props )
|
||||
self.broken = props.broken
|
||||
self.idEnt = props.idEnt
|
||||
self.idConstr = props.idConstr
|
||||
|
||||
--Log("%s:OnLoad() idEnt: %s idConstr: %s broken: %s", self:GetName(), tostring(self.idEnt),
|
||||
-- tostring(self.idConstr), tostring(self.broken))
|
||||
end
|
||||
|
||||
function Constraint:OnDestroy()
|
||||
end
|
||||
|
||||
Constraint.FlowEvents =
|
||||
{
|
||||
Inputs =
|
||||
{
|
||||
ConstraintBroken = { Constraint.Event_ConstraintBroken, "bool" },
|
||||
},
|
||||
Outputs =
|
||||
{
|
||||
ConstraintBroken = "bool",
|
||||
},
|
||||
}
|
||||
@@ -1,289 +0,0 @@
|
||||
----------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- 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.
|
||||
--
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------
|
||||
-- #Script.ReloadScript("scripts/default/entities/player/basicplayer.lua")
|
||||
|
||||
DeadBody =
|
||||
{
|
||||
type = "DeadBody",
|
||||
temp_ModelName = "",
|
||||
|
||||
DeadBodyParams =
|
||||
{
|
||||
max_time_step = 0.025,
|
||||
sleep_speed = 0.025,
|
||||
damping = 0.3,
|
||||
freefall_damping = 0.1,
|
||||
|
||||
lying_mode_ncolls = 4,
|
||||
lying_sleep_speed = 0.065,
|
||||
lying_damping = 1.5,
|
||||
},
|
||||
|
||||
PhysParams =
|
||||
{
|
||||
mass = 80,
|
||||
height = 1.8,
|
||||
eyeheight = 1.7,
|
||||
sphereheight = 1.2,
|
||||
radius = 0.45,
|
||||
stiffness_scale = 0,
|
||||
lod = 1,
|
||||
retain_joint_vel = 0,
|
||||
},
|
||||
|
||||
Properties =
|
||||
{
|
||||
soclasses_SmartObjectClass = "",
|
||||
bResting = 1,
|
||||
object_Model = "objects/characters/human/sdk_player/sdk_player.cdf",
|
||||
lying_damping = 1.5,
|
||||
bCollidesWithPlayers = 0,
|
||||
bPushableByPlayers = 0,
|
||||
Mass = 80,
|
||||
Stiffness = 0,
|
||||
MaxTimeStep = 0.025,
|
||||
bExtraStiff = 0,
|
||||
bNoFriendlyFire = 0,
|
||||
PoseAnim = "",
|
||||
|
||||
Buoyancy=
|
||||
{
|
||||
water_density = 1000,
|
||||
water_damping = 0,
|
||||
water_resistance = 1000,
|
||||
},
|
||||
|
||||
TacticalInfo =
|
||||
{
|
||||
bScannable = 0,
|
||||
LookupName = "",
|
||||
},
|
||||
},
|
||||
|
||||
Editor =
|
||||
{
|
||||
Icon = "DeadBody.bmp",
|
||||
IconOnTop = 1,
|
||||
},
|
||||
}
|
||||
|
||||
-------------------------------------------------------
|
||||
function DeadBody:OnLoad(table)
|
||||
self.temp_ModelName = table.temp_ModelName
|
||||
self.PhysParams = table.PhysParams
|
||||
self.DeadBodyParams = table.DeadBodyParams
|
||||
end
|
||||
|
||||
-------------------------------------------------------
|
||||
function DeadBody:OnSave(table)
|
||||
table.temp_ModelName = self.temp_ModelName
|
||||
table.PhysParams = self.PhysParams
|
||||
table.DeadBodyParams = self.DeadBodyParams
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
function DeadBody:OnReset()
|
||||
--self.temp_ModelName ="";
|
||||
--self:OnPropertyChange();
|
||||
|
||||
self.bScannable = self.Properties.TacticalInfo.bScannable;
|
||||
|
||||
-- no problem in repeatedly registering or unregistering
|
||||
if (self.bScannable==1) then
|
||||
Game.AddTacticalEntity(self.id, eTacticalEntity_Story);
|
||||
else
|
||||
Game.RemoveTacticalEntity(self.id, eTacticalEntity_Story);
|
||||
end
|
||||
|
||||
self:LoadCharacter(0,self.Properties.object_Model);
|
||||
--self:StartAnimation( 0,"cidle" );
|
||||
self:PhysicalizeThis();
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
function DeadBody:Server_OnInit()
|
||||
if (not CryAction.IsServer()) then
|
||||
DeadBody.OnPropertyChange( self );
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
function DeadBody:Client_OnInit()
|
||||
DeadBody.OnPropertyChange( self );
|
||||
|
||||
self:SetUpdatePolicy( ENTITY_UPDATE_PHYSICS_VISIBLE );
|
||||
--self:Activate(1);
|
||||
|
||||
-- self:RenderShadow( 1 ); -- enable rendering of player shadow
|
||||
-- self:SetShaderFloat("HeatIntensity",0,0,0);
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
function DeadBody:Server_OnDamageDead( hit )
|
||||
--printf("server on Damage DEAD %.2f %.2f",hit.impact_force_mul_final,hit.impact_force_mul);
|
||||
--System.Log("DeadBody hit part "..hit.ipart);
|
||||
if( hit.ipart ) then
|
||||
self:AddImpulse( hit.ipart, hit.pos, hit.dir, hit.impact_force_mul );
|
||||
else
|
||||
self:AddImpulse( -1, hit.pos, hit.dir, hit.impact_force_mul );
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
|
||||
function DeadBody:OnHit()
|
||||
BroadcastEvent( self,"Hit" );
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------
|
||||
|
||||
function DeadBody:OnPropertyChange()
|
||||
--System.LogToConsole("prev:"..self.temp_ModelName.." new:"..self.Properties.object_Model);
|
||||
|
||||
self.PhysParams.mass = self.Properties.Mass;
|
||||
|
||||
if (self.Properties.object_Model ~= self.temp_ModelName) then
|
||||
self.temp_ModelName = self.Properties.object_Model;
|
||||
self:LoadCharacter(0,self.Properties.object_Model);
|
||||
end
|
||||
self:PhysicalizeThis();
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
function DeadBody:PhysicalizeThis()
|
||||
local Properties = self.Properties;
|
||||
local status = 1;
|
||||
|
||||
self.PhysParams.retain_joint_vel = 0;
|
||||
if (Properties.PoseAnim ~= "") then
|
||||
self:StartAnimation( 0, Properties.PoseAnim, 0,0,1,1,1,0,1 );
|
||||
self.PhysParams.retain_joint_vel = 1; --this is just to retain the positions of non-physical bones
|
||||
end
|
||||
|
||||
local bPushableByPlayers = Properties.bPushableByPlayers;
|
||||
local bCollidesWithPlayers = Properties.bCollidesWithPlayers;
|
||||
|
||||
if (status == 1) then
|
||||
bPushableByPlayers = 0;
|
||||
bCollidesWithPlayers = 0;
|
||||
end
|
||||
|
||||
self.PhysParams.mass = Properties.Mass;
|
||||
self.PhysParams.stiffness_scale = Properties.Stiffness*(1-Properties.bExtraStiff*2);
|
||||
|
||||
self:Physicalize( 0, PE_ARTICULATED, self.PhysParams );
|
||||
|
||||
self:SetPhysicParams(PHYSICPARAM_SIMULATION, self.Properties );
|
||||
self:SetPhysicParams(PHYSICPARAM_BUOYANCY, self.Properties.Buoyancy );
|
||||
|
||||
if (Properties.lying_damping) then
|
||||
self.DeadBodyParams.lying_damping = Properties.lying_damping;
|
||||
end
|
||||
self.DeadBodyParams.max_time_step = Properties.MaxTimeStep;
|
||||
self:SetPhysicParams(PHYSICPARAM_SIMULATION, self.DeadBodyParams);
|
||||
self:SetPhysicParams(PHYSICPARAM_ARTICULATED, self.DeadBodyParams);
|
||||
|
||||
local flagstab = { flags_mask=geom_colltype_player, flags=geom_colltype_player*bCollidesWithPlayers };
|
||||
if (status == 1) then
|
||||
flagstab.flags_mask = geom_colltype_explosion + geom_colltype_ray + geom_colltype_foliage_proxy + geom_colltype_player;
|
||||
end
|
||||
self:SetPhysicParams(PHYSICPARAM_PART_FLAGS, flagstab);
|
||||
flagstab.flags_mask = pef_pushable_by_players;
|
||||
flagstab.flags = pef_pushable_by_players*bPushableByPlayers;
|
||||
self:SetPhysicParams(PHYSICPARAM_FLAGS, flagstab);
|
||||
if (Properties.bResting == 1) then
|
||||
self:AwakePhysics(0);
|
||||
else
|
||||
self:AwakePhysics(1);
|
||||
end
|
||||
self:EnableProceduralFacialAnimation(false);
|
||||
self:PlayFacialAnimation("death_pose_0"..random(1,5), true);
|
||||
-- small hack: we need one update to sync physics and animation, so here it is after physicalization
|
||||
-- (our OnUpdate function should just deactivate immediately.)
|
||||
--self:Activate(1);
|
||||
end
|
||||
|
||||
--function DeadBody:OnUpdate()
|
||||
--self:Activate(0);
|
||||
--end
|
||||
|
||||
function DeadBody:Event_Hide()
|
||||
self:Hide(1);
|
||||
end;
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function DeadBody:Event_UnHide()
|
||||
self:Hide(0);
|
||||
end;
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
function DeadBody:Event_Awake()
|
||||
self:AwakePhysics(1);
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
function DeadBody:Event_Hit(sender)
|
||||
BroadcastEvent(self, "Hit");
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
DeadBody.Server =
|
||||
{
|
||||
OnInit = DeadBody.Server_OnInit,
|
||||
-- OnShutDown = function( self ) end,
|
||||
OnDamage = DeadBody.Server_OnDamageDead,
|
||||
OnHit = DeadBody.OnHit,
|
||||
OnUpdate=DeadBody.OnUpdate,
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------------------------------
|
||||
DeadBody.Client =
|
||||
{
|
||||
OnInit = DeadBody.Client_OnInit,
|
||||
-- OnShutDown = DeadBody.Client_OnShutDown,
|
||||
OnDamage=DeadBody.Client_OnDamage,
|
||||
OnUpdate=DeadBody.OnUpdate,
|
||||
}
|
||||
|
||||
----------------------------------------------------------------------------------------------------
|
||||
function DeadBody:HasBeenScanned()
|
||||
self:ActivateOutput("Scanned", true);
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
DeadBody.FlowEvents =
|
||||
{
|
||||
Inputs =
|
||||
{
|
||||
Awake = { DeadBody.Event_Awake, "bool" },
|
||||
Hide = { DeadBody.Event_Hide, "bool" },
|
||||
UnHide = { DeadBody.Event_UnHide, "bool" },
|
||||
},
|
||||
Outputs =
|
||||
{
|
||||
Awake = "bool",
|
||||
Hit = "bool",
|
||||
Scanned = "bool",
|
||||
},
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
----------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- 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.
|
||||
--
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------
|
||||
-- Zero Gravity entity
|
||||
GravityBox =
|
||||
{
|
||||
Properties =
|
||||
{
|
||||
bActive = 1,
|
||||
BoxMin = { x=-10,y=-10,z=-10 },
|
||||
BoxMax = { x=10,y=10,z=10 },
|
||||
bUniform = 1,
|
||||
Gravity = { x=0,y=0,z=0 },
|
||||
FalloffInner = 0,
|
||||
},
|
||||
|
||||
Editor =
|
||||
{
|
||||
Icon = "GravitySphere.bmp",
|
||||
},
|
||||
_PhysTable = { Area={}, },
|
||||
}
|
||||
|
||||
-------------------------------------------------------
|
||||
function GravityBox:OnLoad(table)
|
||||
self.bActive = table.bActive
|
||||
if (self.bActive == 1) then
|
||||
self:PhysicalizeThis();
|
||||
else
|
||||
self:DestroyPhysics();
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------
|
||||
function GravityBox:OnSave(table)
|
||||
table.bActive = self.bActive
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravityBox:OnInit()
|
||||
self.bActive = self.Properties.bActive;
|
||||
if (self.bActive == 1) then
|
||||
self:PhysicalizeThis();
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- OnPropertyChange called only by the editor.
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravityBox:OnPropertyChange()
|
||||
if (self.bActive ~= self.Properties.bActive) then
|
||||
self.bActive = self.Properties.bActive;
|
||||
if (self.bActive == 1) then
|
||||
self:PhysicalizeThis();
|
||||
else
|
||||
self:DestroyPhysics();
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- OnReset called only by the editor.
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravityBox:OnReset()
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravityBox:PhysicalizeThis()
|
||||
if (self.bActive == 1) then
|
||||
local Properties = self.Properties;
|
||||
local Area = self._PhysTable.Area;
|
||||
Area.type = AREA_BOX;
|
||||
Area.box_min = Properties.BoxMin;
|
||||
Area.box_max = Properties.BoxMax;
|
||||
Area.uniform = Properties.bUniform;
|
||||
Area.falloffInner = Properties.FalloffInner;
|
||||
Area.gravity = Properties.Gravity;
|
||||
self:Physicalize( 0,PE_AREA,self._PhysTable );
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravityBox:Event_Activate()
|
||||
if (self.bActive ~= 1) then
|
||||
self.bActive = 1;
|
||||
self:PhysicalizeThis();
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravityBox:Event_Deactivate()
|
||||
if (self.bActive ~= 0) then
|
||||
self.bActive = 0;
|
||||
self:PhysicalizeThis();
|
||||
end
|
||||
end
|
||||
|
||||
GravityBox.FlowEvents =
|
||||
{
|
||||
Inputs =
|
||||
{
|
||||
Deactivate = { GravityBox.Event_Deactivate, "bool" },
|
||||
Activate = { GravityBox.Event_Activate, "bool" },
|
||||
},
|
||||
Outputs =
|
||||
{
|
||||
Deactivate = "bool",
|
||||
Activate = "bool",
|
||||
},
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
----------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- 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.
|
||||
--
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------
|
||||
-- Zero Gravity entity
|
||||
|
||||
GravitySphere =
|
||||
{
|
||||
Properties =
|
||||
{
|
||||
bActive = 1,
|
||||
Radius = 10,
|
||||
bUniform = 1,
|
||||
bEllipsoidal = 1,
|
||||
FalloffInner = 0,
|
||||
Gravity = { x=0,y=0,z=0 },
|
||||
Damping = 0,
|
||||
},
|
||||
|
||||
_PhysTable = { Area={}, },
|
||||
|
||||
Editor =
|
||||
{
|
||||
Icon = "GravitySphere.bmp",
|
||||
IconOnTop = 0,
|
||||
},
|
||||
}
|
||||
|
||||
-------------------------------------------------------
|
||||
function GravitySphere:OnLoad(table)
|
||||
self.bActive = table.bActive
|
||||
self:PhysicalizeThis();
|
||||
end
|
||||
|
||||
-------------------------------------------------------
|
||||
function GravitySphere:OnSave(table)
|
||||
table.bActive = self.bActive
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravitySphere:OnInit()
|
||||
self:OnReset();
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- OnPropertyChange called only by the editor.
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravitySphere:OnPropertyChange()
|
||||
self:DestroyPhysics();
|
||||
self.bActive = self.Properties.bActive;
|
||||
if (self.bActive ~= 0) then
|
||||
self:PhysicalizeThis();
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- OnReset called only by the editor.
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravitySphere:OnReset()
|
||||
self.bActive = self.Properties.bActive;
|
||||
self:PhysicalizeThis();
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravitySphere:PhysicalizeThis()
|
||||
--Log("GravitySphere:PhysicalizeThis");
|
||||
if (self.bActive == 1) then
|
||||
local Properties = self.Properties;
|
||||
local Area = self._PhysTable.Area;
|
||||
if (Properties.bEllipsoidal ~= 0) then
|
||||
Area.type = AREA_SPHERE;
|
||||
else
|
||||
Area.type = AREA_BOX;
|
||||
Area.box_min = {x = -Properties.Radius, y = -Properties.Radius, z = -Properties.Radius};
|
||||
Area.box_max = {x = Properties.Radius, y = Properties.Radius, z = Properties.Radius};
|
||||
end
|
||||
Area.radius = Properties.Radius;
|
||||
Area.uniform = Properties.bUniform;
|
||||
Area.falloffInner = Properties.FalloffInner;
|
||||
Area.gravity = Properties.Gravity;
|
||||
Area.damping = Properties.Damping;
|
||||
|
||||
self:Physicalize( 0,PE_AREA,self._PhysTable );
|
||||
|
||||
self:SetPhysicParams(PHYSICPARAM_FOREIGNDATA,{foreignData = ZEROG_AREA_ID});
|
||||
else
|
||||
self:DestroyPhysics();
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravitySphere:Event_Activate()
|
||||
if (self.bActive ~= 1) then
|
||||
self.bActive = 1;
|
||||
self:PhysicalizeThis();
|
||||
BroadcastEvent(self, "Activate");
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
function GravitySphere:Event_Deactivate()
|
||||
if (self.bActive ~= 0) then
|
||||
self.bActive = 0;
|
||||
self:PhysicalizeThis();
|
||||
BroadcastEvent(self, "Deactivate");
|
||||
end
|
||||
end
|
||||
|
||||
GravitySphere.FlowEvents =
|
||||
{
|
||||
Inputs =
|
||||
{
|
||||
Deactivate = { GravitySphere.Event_Deactivate, "bool" },
|
||||
Activate = { GravitySphere.Event_Activate, "bool" },
|
||||
},
|
||||
Outputs =
|
||||
{
|
||||
Deactivate = "bool",
|
||||
Activate = "bool",
|
||||
},
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
----------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- 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.
|
||||
--
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------
|
||||
GravityValve =
|
||||
{
|
||||
Properties =
|
||||
{
|
||||
bActive = 1,
|
||||
Strength = 10,
|
||||
Radius = 10,
|
||||
bSpline = 0,
|
||||
},
|
||||
|
||||
Server = {},
|
||||
Client = {},
|
||||
|
||||
_PhysTableCyl = { Area={}, },
|
||||
_PhysTableSph = { Area={}, },
|
||||
_PhysTableSpl = { Area={points={},}, },
|
||||
_Points = {},
|
||||
_Caps = {},
|
||||
|
||||
Editor =
|
||||
{
|
||||
Icon = "GravitySphere.bmp",
|
||||
ShowBounds = 1,
|
||||
},
|
||||
}
|
||||
|
||||
-------------------------------------------------------
|
||||
function GravityValve:OnLoad(table)
|
||||
self.bActive = table.bActive
|
||||
self._Points = table._Points
|
||||
self._Caps = table._Caps
|
||||
end
|
||||
|
||||
-------------------------------------------------------
|
||||
function GravityValve:OnSave(table)
|
||||
table.bActive = self.bActive
|
||||
table._Points = self._Points
|
||||
table._Caps = self._Caps
|
||||
end
|
||||
|
||||
function GravityValve:OnSpawn()
|
||||
self:SetActive( self.Properties.bActive )
|
||||
end
|
||||
|
||||
function GravityValve:OnDestroy()
|
||||
local Caps = self._Caps
|
||||
while table.getn(Caps)>0 do
|
||||
System.RemoveEntity( Caps[1] )
|
||||
table.remove( Caps, 1 )
|
||||
end
|
||||
end
|
||||
|
||||
-- OnPropertyChange called only by the editor
|
||||
function GravityValve:OnPropertyChange()
|
||||
self:NeedSetup()
|
||||
end
|
||||
|
||||
function GravityValve:OnReset()
|
||||
self:NeedSetup()
|
||||
end
|
||||
|
||||
function GravityValve:FillPoints()
|
||||
local MAX_POINTS = 50
|
||||
local prefix = self:GetName().."_p"
|
||||
local name
|
||||
local nPoints = 1
|
||||
local Points = self._Points
|
||||
|
||||
Points[1] = self
|
||||
|
||||
for i=1,MAX_POINTS do
|
||||
name = prefix..tostring(i)
|
||||
local ent = System.GetEntityByName( name )
|
||||
if not ent then break end
|
||||
Points[i+1] = ent
|
||||
nPoints = i+1
|
||||
Log("npoints "..nPoints);
|
||||
end
|
||||
|
||||
while table.getn(Points)>nPoints do
|
||||
Log("removed");
|
||||
table.remove(Points)
|
||||
end
|
||||
|
||||
for i=1, table.getn(Points) do
|
||||
Log(".. "..Points[i]:GetName())
|
||||
end
|
||||
end
|
||||
|
||||
function GravityValve:CreateCylinderArea( from, to, radius, strength )
|
||||
local Area = self._PhysTableCyl.Area
|
||||
local axis = DifferenceVectors( to, from )
|
||||
Area.type = AREA_CYLINDER
|
||||
Area.radius = radius
|
||||
Area.height = LengthVector( axis ) * .5
|
||||
Area.center = ScaleVector( SumVectors( to, from ), 0.5 )
|
||||
Area.axis = NormalizeVector( axis )
|
||||
Area.gravity = ScaleVector( Area.axis, strength )
|
||||
Area.uniform = 1
|
||||
Area.falloff = 0
|
||||
|
||||
return Area
|
||||
end
|
||||
|
||||
function GravityValve:CreateSphereArea( radius, gravity )
|
||||
local Area = self._PhysTableSph.Area
|
||||
Area.type = AREA_SPHERE
|
||||
Area.radius = radius
|
||||
Area.uniform = 1
|
||||
Area.falloff = 0
|
||||
Area.gravity = ScaleVector( gravity, 8 )
|
||||
|
||||
return Area
|
||||
end
|
||||
|
||||
function GravityValve:NeedSetup()
|
||||
self.bNeedSetup = 1
|
||||
self:Activate(1)
|
||||
end
|
||||
|
||||
function GravityValve:OnChange( index )
|
||||
self:NeedSetup()
|
||||
end
|
||||
|
||||
function GravityValve:OnUpdate()
|
||||
--Log("GV:OU "..self:GetName())
|
||||
if self.bNeedSetup then
|
||||
local wasActive = self.bActive
|
||||
self:SetActive(0)
|
||||
self:SetActive(wasActive)
|
||||
self.bNeedSetup = nil
|
||||
self:Activate(0)
|
||||
end
|
||||
end
|
||||
|
||||
GravityValve.Server.OnUpdate = GravityValve.OnUpdate
|
||||
GravityValve.Client.OnUpdate = GravityValve.OnUpdate
|
||||
|
||||
function GravityValve:SetActive( bActive )
|
||||
if bActive == self.bActive then return end
|
||||
self:FillPoints()
|
||||
local p, n
|
||||
local Points = self._Points
|
||||
local Caps = self._Caps
|
||||
n = table.getn(Points)
|
||||
--Log("GravityValve:SetActive "..tostring(bActive).." on valve "..self:GetName())
|
||||
if bActive == 1 then
|
||||
if (self.Properties.bSpline == 1) then
|
||||
|
||||
local Area = self._PhysTableSpl.Area;
|
||||
local splinePoints = self._PhysTableSpl.Area.points;
|
||||
|
||||
for p = 1, n do
|
||||
splinePoints[p] = {x=0,y=0,z=0};
|
||||
Points[p]:GetWorldPos(splinePoints[p]);
|
||||
--Log("Gravity Stream point "..p..":"..Vec2Str(splinePoints[p]));
|
||||
end
|
||||
|
||||
Area.type = AREA_SPLINE;
|
||||
Area.radius = self.Properties.Radius;
|
||||
--Area.uniform = 1;
|
||||
Area.falloff = 0;
|
||||
Area.gravity = {x=0,y=0,z=self.Properties.Strength};
|
||||
Area.damping = 2.0;
|
||||
|
||||
self:Physicalize(0, PE_AREA, self._PhysTableSpl);
|
||||
|
||||
self:SetPhysicParams(PHYSICPARAM_FOREIGNDATA,{foreignData = ZEROG_AREA_ID});
|
||||
else
|
||||
local params = {}
|
||||
params.class = "GravityStreamCap"
|
||||
params.orientation = {x=1,y=0,z=0}
|
||||
|
||||
for p = 2, n do
|
||||
self:CreateCylinderArea( Points[p-1]:GetPos(), Points[p]:GetPos(), self.Properties.Radius, self.Properties.Strength )
|
||||
Points[p]:Physicalize(0, PE_AREA, self._PhysTableCyl)
|
||||
|
||||
Points[p]:SetPhysicParams(PHYSICPARAM_FOREIGNDATA,{foreignData = ZEROG_AREA_ID});
|
||||
|
||||
if p > 2 then
|
||||
params.position = Points[p-1]:GetPos()
|
||||
local ent = System.SpawnEntity( params )
|
||||
table.insert( Caps, ent.id )
|
||||
self:CreateSphereArea( self.Properties.Radius, self._PhysTableCyl.Area.gravity )
|
||||
ent:Physicalize(0, PE_AREA, self._PhysTableSph)
|
||||
|
||||
ent:SetPhysicParams(PHYSICPARAM_FOREIGNDATA,{foreignData = ZEROG_AREA_ID});
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif bActive == 0 and self.bActive then
|
||||
|
||||
self:DestroyPhysics();
|
||||
|
||||
for p = 2, n do
|
||||
Points[p]:DestroyPhysics()
|
||||
end
|
||||
|
||||
self:OnDestroy()
|
||||
end
|
||||
self.bActive = bActive
|
||||
end
|
||||
|
||||
function GravityValve:Event_Enable()
|
||||
--Log("GravityValve: GetEnable")
|
||||
self:SetActive(1)
|
||||
end
|
||||
|
||||
function GravityValve:Event_Disable()
|
||||
--Log("GravityValve: GetDisable")
|
||||
self:SetActive(0)
|
||||
end
|
||||
|
||||
GravityValve.FlowEvents =
|
||||
{
|
||||
Inputs =
|
||||
{
|
||||
Disable = { GravityValve.Event_Disable, "bool" },
|
||||
Enable = { GravityValve.Event_Enable, "bool" },
|
||||
},
|
||||
Outputs =
|
||||
{
|
||||
Disable = "bool",
|
||||
Enable = "bool",
|
||||
},
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
----------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- 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.
|
||||
--
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------
|
||||
ParticlePhysics =
|
||||
{
|
||||
Properties =
|
||||
{
|
||||
object_Model = "Objects/default/primitive_box.cgf",
|
||||
|
||||
Particle =
|
||||
{
|
||||
mass = 50.0,
|
||||
radius = 1.0,
|
||||
air_resistance = 0.0,
|
||||
gravity = {x=0.0, y=0.0, z=-9.81},
|
||||
water_resistance = 0.5,
|
||||
water_gravity = {x=0.0, y=0.0, z=-9.81*0.8},
|
||||
min_bounce_vel = 1.5,
|
||||
accel_thrust = 0,
|
||||
accel_lift = 0,
|
||||
velocity = {x=0.0, y=0.0, z=0.0},
|
||||
thickness = 1.0,
|
||||
wspin = {x=0.0, y=0.0, z=0.0},
|
||||
normal = {x=0.0, y=0.0, z=1.0},
|
||||
pierceability = 15,
|
||||
constant_orientation = false,
|
||||
single_contact = true,
|
||||
no_roll = false,
|
||||
no_spin = true,
|
||||
no_path_alignment = false,
|
||||
collider_to_ignore = 0,
|
||||
material = "", -- this is supposed to be the surface type
|
||||
},
|
||||
},
|
||||
|
||||
Editor =
|
||||
{
|
||||
Icon = "physicsobject.bmp",
|
||||
IconOnTop = 1,
|
||||
},
|
||||
}
|
||||
|
||||
function ParticlePhysics:SetFromProperties()
|
||||
local Properties = self.Properties;
|
||||
|
||||
self:FreeSlot(0);
|
||||
|
||||
if (Properties.object_Model ~= "") then
|
||||
self:LoadObject(0, Properties.object_Model);
|
||||
end
|
||||
|
||||
NormalizeVector(Properties.Particle.normal);
|
||||
self:Physicalize(0, PE_PARTICLE, Properties);
|
||||
self:SetSlotPos(0, {0.0, 0.0, -Properties.Particle.thickness*0.5});
|
||||
end
|
||||
|
||||
function ParticlePhysics:OnSpawn()
|
||||
self:OnReset();
|
||||
end
|
||||
|
||||
function ParticlePhysics:OnPropertyChange()
|
||||
self:OnReset();
|
||||
end
|
||||
|
||||
function ParticlePhysics:OnReset()
|
||||
self:SetFromProperties();
|
||||
end
|
||||
@@ -1,188 +0,0 @@
|
||||
----------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- 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.
|
||||
--
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------
|
||||
Wind = {
|
||||
type = "WindController",
|
||||
Properties = {
|
||||
vVelocity={x=1.0,y=0.0,z=0.0},
|
||||
|
||||
fFadeTime = 1,--used only when the fog is triggered manually, with activate/deactivate events.
|
||||
},
|
||||
|
||||
Editor={
|
||||
Icon="Tornado.bmp",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
function Wind:OnInit()
|
||||
self.oldVelocity = {x=0.0,y=0.0,z=0.0};
|
||||
self.occupied = 0;
|
||||
self.lasttime = 0;
|
||||
|
||||
self:OnReset();
|
||||
|
||||
self:RegisterForAreaEvents(1);
|
||||
end
|
||||
|
||||
function Wind:OnPropertyChange()
|
||||
self:OnReset();
|
||||
end
|
||||
|
||||
function Wind:OnReset()
|
||||
self:RegisterForAreaEvents(1);
|
||||
end
|
||||
|
||||
function Wind:OnSave(tbl)
|
||||
tbl.bTriggered = self.bTriggered
|
||||
tbl.oldVelocity = self.oldVelocity
|
||||
tbl.fadeamt = self.fadeamt
|
||||
tbl.Who = self.Who
|
||||
end
|
||||
|
||||
function Wind:OnLoad(tbl)
|
||||
self.bTriggered = tbl.bTriggered
|
||||
self.oldVelocity = tbl.oldVelocity
|
||||
self.fadamt = tbl.fadeamt
|
||||
self.Who = tbl.Who
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- fade: 0-out 1-in
|
||||
function Wind:OnProceedFadeArea( player,areaId,fadeCoeff )
|
||||
self:Fade(fadeCoeff);
|
||||
end
|
||||
|
||||
function Wind:ResetValues()
|
||||
System.SetWind(self.oldVelocity);
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
function Wind:OnEnterArea( player,areaId )
|
||||
|
||||
if((player and (not player.actor:IsPlayer())) or self.occupied == 1) then
|
||||
return
|
||||
end
|
||||
|
||||
self.oldVelocity = System.GetWind();
|
||||
|
||||
self.occupied = 1;
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
function Wind:OnLeaveArea( player,areaId )
|
||||
|
||||
if(player and (not player.actor:IsPlayer())) then
|
||||
return
|
||||
end
|
||||
|
||||
self:ResetValues();
|
||||
|
||||
self.occupied = 0;
|
||||
end
|
||||
-----------------------------------------------------------------------------
|
||||
function Wind:OnShutDown()
|
||||
self:RegisterForAreaEvents(0);
|
||||
end
|
||||
|
||||
function Wind:Event_Enable( sender )
|
||||
|
||||
if(self.occupied == 0 ) then
|
||||
|
||||
if (self.fadeamt and self.fadeamt<1) then
|
||||
self:ResetValues();
|
||||
end
|
||||
|
||||
self:OnEnterArea( );
|
||||
|
||||
self.fadeamt = 0;
|
||||
self.lasttime = _time;
|
||||
self.exitfrom = nil;
|
||||
end
|
||||
|
||||
self:SetTimer(0, 1);
|
||||
|
||||
BroadcastEvent( self,"Enable" );
|
||||
end
|
||||
|
||||
function Wind:Event_Disable( sender )
|
||||
|
||||
if(self.occupied == 1 ) then
|
||||
|
||||
--self:OnLeaveArea( );
|
||||
self.occupied = 0;
|
||||
|
||||
self.fadeamt = 0;
|
||||
self.lasttime = _time;
|
||||
self.exitfrom = 1;
|
||||
end
|
||||
|
||||
self:SetTimer(0, 1);
|
||||
|
||||
BroadcastEvent( self,"Disable" );
|
||||
end
|
||||
|
||||
function Wind:OnTimer()
|
||||
|
||||
--System.Log("Ontimer ");
|
||||
|
||||
self:SetTimer(0, 1);
|
||||
|
||||
if (self.fadeamt) then
|
||||
|
||||
local delta = _time - self.lasttime;
|
||||
self.lasttime = _time;
|
||||
|
||||
self.fadeamt = self.fadeamt + (delta / self.Properties.fFadeTime);
|
||||
|
||||
if (self.fadeamt>=1) then
|
||||
|
||||
self.fadeamt = 1;
|
||||
self:KillTimer(0);
|
||||
end
|
||||
|
||||
----------------------------------------------
|
||||
--fade
|
||||
local fadeCoeff = self.fadeamt;
|
||||
|
||||
if (self.exitfrom) then
|
||||
fadeCoeff = 1 - fadeCoeff;
|
||||
end
|
||||
|
||||
fadeCoeff = math.sqrt( fadeCoeff );
|
||||
fadeCoeff = math.sqrt( fadeCoeff );
|
||||
|
||||
self:Fade(fadeCoeff);
|
||||
--self:OnProceedFadeArea( nil,0,self.fadeamt );
|
||||
else
|
||||
self:KillTimer(0);
|
||||
end
|
||||
end
|
||||
|
||||
function Wind:Fade(fadeCoeff)
|
||||
System.SetWind(LerpColors(self.oldVelocity, self.Properties.vVelocity, fadeCoeff));
|
||||
end
|
||||
|
||||
Wind.FlowEvents =
|
||||
{
|
||||
Inputs =
|
||||
{
|
||||
Disable = { Wind.Event_Disable, "bool" },
|
||||
Enable = { Wind.Event_Enable, "bool" },
|
||||
},
|
||||
Outputs =
|
||||
{
|
||||
Disable = "bool",
|
||||
Enable = "bool",
|
||||
},
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user