Merge remote-tracking branch 'upstream/development' into amzn-tommy/gitflow_211116_o3de2
Signed-off-by: Tommy Walton <waltont@amazon.com>
This commit is contained in:
@@ -61,6 +61,10 @@ class TestAutomation(EditorTestSuite):
|
||||
class AtomEditorComponents_HDRColorGradingAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_HDRColorGradingAdded as test_module
|
||||
|
||||
@pytest.mark.test_case_id("C32078116")
|
||||
class AtomEditorComponents_HDRiSkyboxAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_HDRiSkyboxAdded as test_module
|
||||
|
||||
@pytest.mark.test_case_id("C32078117")
|
||||
class AtomEditorComponents_LightAdded(EditorSharedTest):
|
||||
from Atom.tests import hydra_AtomEditorComponents_LightAdded as test_module
|
||||
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
"""
|
||||
Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
|
||||
class Tests:
|
||||
creation_undo = (
|
||||
"UNDO Entity creation success",
|
||||
"UNDO Entity creation failed")
|
||||
creation_redo = (
|
||||
"REDO Entity creation success",
|
||||
"REDO Entity creation failed")
|
||||
hdri_skybox_entity_creation = (
|
||||
"HDRi Skybox successfully created",
|
||||
"HDRi Skybox failed to be created")
|
||||
hdri_skybox_component = (
|
||||
"Entity has an HDRi Skybox component",
|
||||
"Entity failed to find HDRi Skybox component")
|
||||
cubemap_property_set = (
|
||||
"Cubemap property set on HDRi Skybox component",
|
||||
"Couldn't set Cubemap property on HDRi Skybox component")
|
||||
enter_game_mode = (
|
||||
"Entered game mode",
|
||||
"Failed to enter game mode")
|
||||
exit_game_mode = (
|
||||
"Exited game mode",
|
||||
"Couldn't exit game mode")
|
||||
is_visible = (
|
||||
"Entity is visible",
|
||||
"Entity was not visible")
|
||||
is_hidden = (
|
||||
"Entity is hidden",
|
||||
"Entity was not hidden")
|
||||
entity_deleted = (
|
||||
"Entity deleted",
|
||||
"Entity was not deleted")
|
||||
deletion_undo = (
|
||||
"UNDO deletion success",
|
||||
"UNDO deletion failed")
|
||||
deletion_redo = (
|
||||
"REDO deletion success",
|
||||
"REDO deletion failed")
|
||||
|
||||
|
||||
def AtomEditorComponents_HDRiSkybox_AddedToEntity():
|
||||
"""
|
||||
Summary:
|
||||
Tests the HDRi Skybox component can be added to an entity and has the expected functionality.
|
||||
|
||||
Test setup:
|
||||
- Wait for Editor idle loop.
|
||||
- Open the "Base" level.
|
||||
|
||||
Expected Behavior:
|
||||
The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components.
|
||||
Creation and deletion undo/redo should also work.
|
||||
|
||||
Test Steps:
|
||||
1) Create an HDRi Skybox with no components.
|
||||
2) Add an HDRi Skybox component to HDRi Skybox.
|
||||
3) UNDO the entity creation and component addition.
|
||||
4) REDO the entity creation and component addition.
|
||||
5) Enter/Exit game mode.
|
||||
6) Test IsHidden.
|
||||
7) Test IsVisible.
|
||||
8) Delete HDRi Skybox.
|
||||
9) UNDO deletion.
|
||||
10) REDO deletion.
|
||||
11) Look for errors.
|
||||
|
||||
:return: None
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
import azlmbr.legacy.general as general
|
||||
|
||||
from editor_python_test_tools.asset_utils import Asset
|
||||
from editor_python_test_tools.editor_entity_utils import EditorEntity
|
||||
from editor_python_test_tools.utils import Report, Tracer, TestHelper
|
||||
from Atom.atom_utils.atom_constants import AtomComponentProperties
|
||||
|
||||
with Tracer() as error_tracer:
|
||||
# Test setup begins.
|
||||
# Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level.
|
||||
TestHelper.init_idle()
|
||||
TestHelper.open_level("", "Base")
|
||||
|
||||
# Test steps begin.
|
||||
# 1. Create an HDRi Skybox with no components.
|
||||
hdri_skybox_entity = EditorEntity.create_editor_entity(
|
||||
AtomComponentProperties.hdri_skybox())
|
||||
Report.critical_result(Tests.hdri_skybox_entity_creation,
|
||||
hdri_skybox_entity.exists())
|
||||
|
||||
# 2. Add an HDRi Skybox component to HDRi Skybox.
|
||||
hdri_skybox_component = hdri_skybox_entity.add_component(
|
||||
AtomComponentProperties.hdri_skybox())
|
||||
Report.critical_result(
|
||||
Tests.hdri_skybox_component,
|
||||
hdri_skybox_entity.has_component(AtomComponentProperties.hdri_skybox()))
|
||||
|
||||
# 3. UNDO the entity creation and component addition.
|
||||
# -> UNDO component addition.
|
||||
general.undo()
|
||||
# -> UNDO naming entity.
|
||||
general.undo()
|
||||
# -> UNDO selecting entity.
|
||||
general.undo()
|
||||
# -> UNDO entity creation.
|
||||
general.undo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_undo, not hdri_skybox_entity.exists())
|
||||
|
||||
# 4. REDO the entity creation and component addition.
|
||||
# -> REDO entity creation.
|
||||
general.redo()
|
||||
# -> REDO selecting entity.
|
||||
general.redo()
|
||||
# -> REDO naming entity.
|
||||
general.redo()
|
||||
# -> REDO component addition.
|
||||
general.redo()
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.creation_redo, hdri_skybox_entity.exists())
|
||||
|
||||
|
||||
# 5. Set Cubemap Texture on HDRi Skybox component.
|
||||
skybox_cubemap_asset_path = os.path.join("LightingPresets", "default_iblskyboxcm.exr.streamingimage")
|
||||
skybox_cubemap_material_asset = Asset.find_asset_by_path(skybox_cubemap_asset_path, False)
|
||||
hdri_skybox_component.set_component_property_value(
|
||||
AtomComponentProperties.hdri_skybox('Cubemap Texture'), skybox_cubemap_material_asset.id)
|
||||
get_cubemap_property = hdri_skybox_component.get_component_property_value(
|
||||
AtomComponentProperties.hdri_skybox('Cubemap Texture'))
|
||||
Report.result(Tests.cubemap_property_set, get_cubemap_property == skybox_cubemap_material_asset.id)
|
||||
|
||||
|
||||
# 6. Enter/Exit game mode.
|
||||
TestHelper.enter_game_mode(Tests.enter_game_mode)
|
||||
general.idle_wait_frames(1)
|
||||
TestHelper.exit_game_mode(Tests.exit_game_mode)
|
||||
|
||||
# 7. Test IsHidden.
|
||||
hdri_skybox_entity.set_visibility_state(False)
|
||||
Report.result(Tests.is_hidden, hdri_skybox_entity.is_hidden() is True)
|
||||
|
||||
# 8. Test IsVisible.
|
||||
hdri_skybox_entity.set_visibility_state(True)
|
||||
general.idle_wait_frames(1)
|
||||
Report.result(Tests.is_visible, hdri_skybox_entity.is_visible() is True)
|
||||
|
||||
# 9. Delete hdri_skybox entity.
|
||||
hdri_skybox_entity.delete()
|
||||
Report.result(Tests.entity_deleted, not hdri_skybox_entity.exists())
|
||||
|
||||
# 10. UNDO deletion.
|
||||
general.undo()
|
||||
Report.result(Tests.deletion_undo, hdri_skybox_entity.exists())
|
||||
|
||||
# 11. REDO deletion.
|
||||
general.redo()
|
||||
Report.result(Tests.deletion_redo, not hdri_skybox_entity.exists())
|
||||
|
||||
# 12. Look for errors or asserts.
|
||||
TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0)
|
||||
for error_info in error_tracer.errors:
|
||||
Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}")
|
||||
for assert_info in error_tracer.asserts:
|
||||
Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from editor_python_test_tools.utils import Report
|
||||
Report.start_test(AtomEditorComponents_HDRiSkybox_AddedToEntity)
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace AzToolsFramework::EmbeddedPython
|
||||
{
|
||||
// When using embedded Python, some platforms need to explicitly load the python library.
|
||||
// For any modules that depend on 3rdParty::Python package, the AZ::Module should inherit this class.
|
||||
class PythonLoader
|
||||
{
|
||||
public:
|
||||
PythonLoader();
|
||||
~PythonLoader();
|
||||
|
||||
private:
|
||||
void* m_embeddedLibPythonHandle{ nullptr };
|
||||
};
|
||||
|
||||
} // namespace AzToolsFramework::EmbeddedPython
|
||||
@@ -47,6 +47,7 @@ set(FILES
|
||||
API/EntityCompositionRequestBus.h
|
||||
API/EntityCompositionNotificationBus.h
|
||||
API/EditorViewportIconDisplayInterface.h
|
||||
API/PythonLoader.h
|
||||
API/ViewPaneOptions.h
|
||||
API/ViewportEditorModeTrackerInterface.h
|
||||
Application/Ticker.h
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzToolsFramework/API/PythonLoader.h>
|
||||
|
||||
namespace AzToolsFramework::EmbeddedPython
|
||||
{
|
||||
PythonLoader::PythonLoader()
|
||||
{
|
||||
}
|
||||
|
||||
PythonLoader::~PythonLoader()
|
||||
{
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzToolsFramework/API/PythonLoader.h>
|
||||
#include <AzCore/Debug/Trace.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
namespace AzToolsFramework::EmbeddedPython
|
||||
{
|
||||
PythonLoader::PythonLoader()
|
||||
{
|
||||
constexpr char libPythonName[] = "libpython3.7m.so.1.0";
|
||||
if (m_embeddedLibPythonHandle = dlopen(libPythonName, RTLD_NOW | RTLD_GLOBAL);
|
||||
m_embeddedLibPythonHandle == nullptr)
|
||||
{
|
||||
char* err = dlerror();
|
||||
AZ_Error("PythonLoader", false, "Failed to load %s with error: %s\n", libPythonName, err ? err : "Unknown Error");
|
||||
}
|
||||
}
|
||||
|
||||
PythonLoader::~PythonLoader()
|
||||
{
|
||||
if (m_embeddedLibPythonHandle)
|
||||
{
|
||||
dlclose(m_embeddedLibPythonHandle);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AzToolsFramework::EmbeddedPython
|
||||
@@ -7,4 +7,5 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
AzToolsFramework/API/PythonLoader_Linux.cpp
|
||||
)
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../Common/Default/AzToolsFramework/API/PythonLoader_Default.cpp
|
||||
)
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../Common/Default/AzToolsFramework/API/PythonLoader_Default.cpp
|
||||
)
|
||||
|
||||
@@ -12,4 +12,5 @@
|
||||
|
||||
#ifdef AZ_COLLECTING_PARTIAL_SRGS
|
||||
#include <Atom/Feature/Common/Assets/ShaderResourceGroups/ViewSrg.azsli>
|
||||
#include <Terrain/Assets/Shaders/Terrain/ViewSrg.azsli> // Temporary until gem partial view srgs can be included automatically.
|
||||
#endif
|
||||
|
||||
@@ -199,6 +199,28 @@ namespace AZ
|
||||
{
|
||||
return m_indices.at(index);
|
||||
}
|
||||
|
||||
template<size_t Index, typename DataType>
|
||||
IndexType GetIndexForData(const DataType* data) const
|
||||
{
|
||||
if (data >= &AZStd::get<Index>(m_data).front() && data <= &AZStd::get<Index>(m_data).back())
|
||||
{
|
||||
return m_dataToIndices.at(data - &AZStd::get<Index>(m_data).front());
|
||||
}
|
||||
return NoFreeSlot;
|
||||
}
|
||||
|
||||
template<size_t Index, typename LambdaType>
|
||||
void ForEach(LambdaType lambda) const
|
||||
{
|
||||
for (auto& item : AZStd::get<Index>(m_data))
|
||||
{
|
||||
if (!lambda(item))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
using Fn = void(&)(AZStd::vector<Ts>& ...);
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace UnitTest
|
||||
{
|
||||
DestroyAllocator();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void CreateAllocator()
|
||||
@@ -60,6 +60,12 @@ namespace UnitTest
|
||||
|
||||
TEST_F(IndexedDataVectorTests, TestInsert)
|
||||
{
|
||||
enum Types
|
||||
{
|
||||
IntType = 0,
|
||||
DoubleType = 1,
|
||||
};
|
||||
|
||||
MultiIndexedDataVector<int, double> myVec;
|
||||
constexpr int NumToInsert = 5;
|
||||
|
||||
@@ -69,38 +75,48 @@ namespace UnitTest
|
||||
{
|
||||
auto index = myVec.GetFreeSlotIndex();
|
||||
indices.push_back(index);
|
||||
myVec.GetData<0>(index) = i;
|
||||
myVec.GetData<1>(index) = (double)i;
|
||||
myVec.GetData<IntType>(index) = i;
|
||||
myVec.GetData<DoubleType>(index) = (double)i;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < NumToInsert; ++i)
|
||||
{
|
||||
auto index = indices[i];
|
||||
EXPECT_EQ(i, myVec.GetData<0>(index));
|
||||
EXPECT_EQ((double)i, myVec.GetData<1>(index));
|
||||
EXPECT_EQ(i, myVec.GetData<IntType>(index));
|
||||
EXPECT_EQ((double)i, myVec.GetData<DoubleType>(index));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(IndexedDataVectorTests, TestSize)
|
||||
{
|
||||
enum Types
|
||||
{
|
||||
IntType = 0,
|
||||
};
|
||||
|
||||
MultiIndexedDataVector<int> myVec;
|
||||
constexpr int NumToInsert = 5;
|
||||
for (int i = 0; i < NumToInsert; ++i)
|
||||
{
|
||||
auto index = myVec.GetFreeSlotIndex();
|
||||
myVec.GetData<0>(index) = i;
|
||||
myVec.GetData<IntType>(index) = i;
|
||||
}
|
||||
EXPECT_EQ(NumToInsert, myVec.GetDataCount());
|
||||
EXPECT_EQ(NumToInsert, myVec.GetDataVector<0>().size());
|
||||
EXPECT_EQ(NumToInsert, myVec.GetDataVector<IntType>().size());
|
||||
|
||||
myVec.Clear();
|
||||
|
||||
EXPECT_EQ(0, myVec.GetDataCount());
|
||||
EXPECT_EQ(0, myVec.GetDataVector<0>().size());
|
||||
EXPECT_EQ(0, myVec.GetDataVector<IntType>().size());
|
||||
}
|
||||
|
||||
TEST_F(IndexedDataVectorTests, TestErase)
|
||||
{
|
||||
enum Types
|
||||
{
|
||||
IntType = 0,
|
||||
};
|
||||
|
||||
MultiIndexedDataVector<int> myVec;
|
||||
constexpr int NumToInsert = 200;
|
||||
AZStd::unordered_map<int, uint16_t> valueToIndex;
|
||||
@@ -109,7 +125,7 @@ namespace UnitTest
|
||||
{
|
||||
auto index = myVec.GetFreeSlotIndex();
|
||||
valueToIndex[i] = index;
|
||||
myVec.GetData<0>(index) = i;
|
||||
myVec.GetData<IntType>(index) = i;
|
||||
}
|
||||
|
||||
// erase every even number
|
||||
@@ -133,12 +149,21 @@ namespace UnitTest
|
||||
{
|
||||
int val = iter.first;
|
||||
uint16_t index = iter.second;
|
||||
EXPECT_EQ(val, myVec.GetData<0>(index));
|
||||
EXPECT_EQ(val, myVec.GetData<IntType>(index));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(IndexedDataVectorTests, TestManyTypes)
|
||||
{
|
||||
enum Types
|
||||
{
|
||||
IntType = 0,
|
||||
StringType = 1,
|
||||
DoubleType = 2,
|
||||
FloatType = 3,
|
||||
CharType = 4,
|
||||
};
|
||||
|
||||
MultiIndexedDataVector<int, AZStd::string, double, float, const char*> myVec;
|
||||
auto index = myVec.GetFreeSlotIndex();
|
||||
|
||||
@@ -148,16 +173,173 @@ namespace UnitTest
|
||||
constexpr float TestFloatVal = FLT_MAX;
|
||||
const char* TestConstPointerVal = "This is a C array.";
|
||||
|
||||
myVec.GetData<0>(index) = TestIntVal;
|
||||
myVec.GetData<1>(index) = TestStringVal;
|
||||
myVec.GetData<2>(index) = TestDoubleVal;
|
||||
myVec.GetData<3>(index) = TestFloatVal;
|
||||
myVec.GetData<4>(index) = TestConstPointerVal;
|
||||
myVec.GetData<IntType>(index) = TestIntVal;
|
||||
myVec.GetData<StringType>(index) = TestStringVal;
|
||||
myVec.GetData<DoubleType>(index) = TestDoubleVal;
|
||||
myVec.GetData<FloatType>(index) = TestFloatVal;
|
||||
myVec.GetData<CharType>(index) = TestConstPointerVal;
|
||||
|
||||
EXPECT_EQ(TestIntVal, static_cast<int>(myVec.GetData<IntType>(index)));
|
||||
EXPECT_EQ(TestStringVal, static_cast<AZStd::string>(myVec.GetData<StringType>(index)));
|
||||
EXPECT_EQ(TestDoubleVal, static_cast<double>(myVec.GetData<DoubleType>(index)));
|
||||
EXPECT_EQ(TestFloatVal, static_cast<float>(myVec.GetData<FloatType>(index)));
|
||||
EXPECT_STREQ(TestConstPointerVal, static_cast<const char*>(myVec.GetData<CharType>(index)));
|
||||
}
|
||||
|
||||
MultiIndexedDataVector<int32_t, float> CreateTestVector(AZStd::vector<uint16_t>& indices)
|
||||
{
|
||||
enum Types
|
||||
{
|
||||
IntType = 0,
|
||||
FloatType = 1,
|
||||
};
|
||||
|
||||
MultiIndexedDataVector<int32_t, float> myVec;
|
||||
constexpr int32_t Count = 10;
|
||||
int32_t startInt = 10;
|
||||
float startFloat = 2.0f;
|
||||
|
||||
// Create some initial values
|
||||
for (uint32_t i = 0; i < Count; ++i)
|
||||
{
|
||||
uint16_t index = myVec.GetFreeSlotIndex();
|
||||
indices.push_back(index);
|
||||
myVec.GetData<IntType>(index) = startInt;
|
||||
myVec.GetData<FloatType>(index) = startFloat;
|
||||
startInt += 1;
|
||||
startFloat += 1.0f;
|
||||
}
|
||||
|
||||
return myVec;
|
||||
}
|
||||
|
||||
void CheckIndexedData(MultiIndexedDataVector<int32_t, float>& data, AZStd::vector<uint16_t>& indices)
|
||||
{
|
||||
enum Types
|
||||
{
|
||||
IntType = 0,
|
||||
FloatType = 1,
|
||||
};
|
||||
|
||||
// For each index, get its data and make sure GetIndexForData returns the same
|
||||
// index used to retrieve the data
|
||||
for (uint32_t i = 0; i < data.GetDataCount(); ++i)
|
||||
{
|
||||
int32_t& intData = data.GetData<IntType>(indices.at(i));
|
||||
uint16_t indexForData = data.GetIndexForData<IntType>(&intData);
|
||||
EXPECT_EQ(indices.at(i), indexForData);
|
||||
|
||||
float& floatData = data.GetData<FloatType>(indices.at(i));
|
||||
indexForData = data.GetIndexForData<FloatType>(&floatData);
|
||||
EXPECT_EQ(indices.at(i), indexForData);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(IndexedDataVectorTests, GetIndexForDataSimple)
|
||||
{
|
||||
AZStd::vector<uint16_t> indices;
|
||||
MultiIndexedDataVector<int32_t, float> myVec = CreateTestVector(indices);
|
||||
CheckIndexedData(myVec, indices);
|
||||
}
|
||||
|
||||
TEST_F(IndexedDataVectorTests, GetIndexForDataComplex)
|
||||
{
|
||||
enum Types
|
||||
{
|
||||
IntType = 0,
|
||||
FloatType = 1,
|
||||
};
|
||||
|
||||
AZStd::vector<uint16_t> indices;
|
||||
MultiIndexedDataVector<int32_t, float> myVec = CreateTestVector(indices);
|
||||
|
||||
// remove every other value to shuffle the data around
|
||||
for (uint32_t i = 0; i < myVec.GetDataCount(); i += 2)
|
||||
{
|
||||
myVec.RemoveIndex(indices.at(i));
|
||||
}
|
||||
|
||||
int32_t startInt = 100;
|
||||
float startFloat = 20.0f;
|
||||
|
||||
// Add some data back in
|
||||
const size_t count = myVec.GetDataCount();
|
||||
for (uint32_t i = 0; i < count; i += 2)
|
||||
{
|
||||
uint16_t index = myVec.GetFreeSlotIndex();
|
||||
indices.at(i) = index;
|
||||
myVec.GetData<IntType>(index) = startInt;
|
||||
myVec.GetData<FloatType>(index) = startFloat;
|
||||
startInt += 1;
|
||||
startFloat += 1.0f;
|
||||
}
|
||||
|
||||
CheckIndexedData(myVec, indices);
|
||||
}
|
||||
|
||||
TEST_F(IndexedDataVectorTests, ForEach)
|
||||
{
|
||||
enum Types
|
||||
{
|
||||
IntType = 0,
|
||||
FloatType = 1,
|
||||
};
|
||||
|
||||
MultiIndexedDataVector<int32_t, float> myVec;
|
||||
constexpr int32_t Count = 10;
|
||||
int32_t startInt = 10;
|
||||
float startFloat = 2.0f;
|
||||
|
||||
AZStd::vector<uint16_t> indices;
|
||||
AZStd::set<int32_t> intValues;
|
||||
AZStd::set<float> floatValues;
|
||||
|
||||
// Create some initial values
|
||||
for (uint32_t i = 0; i < Count; ++i)
|
||||
{
|
||||
uint16_t index = myVec.GetFreeSlotIndex();
|
||||
indices.push_back(index);
|
||||
myVec.GetData<IntType>(index) = startInt;
|
||||
myVec.GetData<FloatType>(index) = startFloat;
|
||||
intValues.insert(startInt);
|
||||
floatValues.insert(startFloat);
|
||||
startInt += 1;
|
||||
startFloat += 1.0f;
|
||||
}
|
||||
|
||||
uint32_t visitCount = 0;
|
||||
myVec.ForEach<IntType>([&](int32_t value) -> bool
|
||||
{
|
||||
intValues.erase(value);
|
||||
++visitCount;
|
||||
return true; // keep iterating
|
||||
});
|
||||
|
||||
// All ints should have been visited and found in the set
|
||||
EXPECT_EQ(visitCount, Count);
|
||||
EXPECT_EQ(intValues.size(), 0);
|
||||
|
||||
visitCount = 0;
|
||||
myVec.ForEach<FloatType>([&](float value) -> bool
|
||||
{
|
||||
floatValues.erase(value);
|
||||
++visitCount;
|
||||
return true; // keep iterating
|
||||
});
|
||||
|
||||
// All floats should have been visited and found in the set
|
||||
EXPECT_EQ(visitCount, Count);
|
||||
EXPECT_EQ(floatValues.size(), 0);
|
||||
|
||||
visitCount = 0;
|
||||
myVec.ForEach<IntType>([&]([[maybe_unused]] int32_t value) -> bool
|
||||
{
|
||||
++visitCount;
|
||||
return false; // stop iterating
|
||||
});
|
||||
|
||||
// Since false is immediately returned, only one element should have been visited.
|
||||
EXPECT_EQ(visitCount, 1);
|
||||
|
||||
EXPECT_EQ(TestIntVal, static_cast<int>(myVec.GetData<0>(index)));
|
||||
EXPECT_EQ(TestStringVal, static_cast<AZStd::string>(myVec.GetData<1>(index)));
|
||||
EXPECT_EQ(TestDoubleVal, static_cast<double>(myVec.GetData<2>(index)));
|
||||
EXPECT_EQ(TestFloatVal, static_cast<float>(myVec.GetData<3>(index)));
|
||||
EXPECT_STREQ(TestConstPointerVal, static_cast<const char*>(myVec.GetData<4>(index)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,10 @@ namespace AZ
|
||||
//! It may return nullptr if this pass is independent with any views.
|
||||
ViewPtr GetView() const;
|
||||
|
||||
// Add a srg to srg list to be bound for this pass
|
||||
void BindSrg(const RHI::ShaderResourceGroup* srg);
|
||||
|
||||
|
||||
protected:
|
||||
explicit RenderPass(const PassDescriptor& descriptor);
|
||||
|
||||
@@ -95,9 +99,6 @@ namespace AZ
|
||||
// Clear the srg list
|
||||
void ResetSrgs();
|
||||
|
||||
// Add a srg to srg list to be bound for this pass
|
||||
void BindSrg(const RHI::ShaderResourceGroup* srg);
|
||||
|
||||
// Set srgs for pass's execution
|
||||
void SetSrgsForDraw(RHI::CommandList* commandList);
|
||||
void SetSrgsForDispatch(RHI::CommandList* commandList);
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Module/Module.h>
|
||||
#include <AzToolsFramework/API/PythonLoader.h>
|
||||
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
class AtomToolsFrameworkModule
|
||||
: public AZ::Module
|
||||
, public AzToolsFramework::EmbeddedPython::PythonLoader
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AtomToolsFrameworkModule, "{B58B7CA8-98C9-4DC8-8607-E094989BBBE2}", AZ::Module);
|
||||
|
||||
@@ -49,8 +49,14 @@ namespace AZ::Render
|
||||
RenderAABB(instance, renderActorSettings.m_staticAABBColor);
|
||||
}
|
||||
|
||||
// Render skeleton
|
||||
// Render simple line skeleton
|
||||
if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_LINESKELETON])
|
||||
{
|
||||
RenderLineSkeleton(instance, renderActorSettings.m_lineSkeletonColor);
|
||||
}
|
||||
|
||||
// Render advance skeleton
|
||||
if (renderFlags[EMotionFX::ActorRenderFlag::RENDER_SKELETON])
|
||||
{
|
||||
RenderSkeleton(instance, renderActorSettings.m_skeletonColor);
|
||||
}
|
||||
@@ -110,6 +116,29 @@ namespace AZ::Render
|
||||
return aabbRadius * 0.01f;
|
||||
}
|
||||
|
||||
float AtomActorDebugDraw::CalculateBoneScale(EMotionFX::ActorInstance* actorInstance, EMotionFX::Node* node)
|
||||
{
|
||||
// Get the transform data
|
||||
EMotionFX::TransformData* transformData = actorInstance->GetTransformData();
|
||||
const EMotionFX::Pose* pose = transformData->GetCurrentPose();
|
||||
|
||||
const size_t nodeIndex = node->GetNodeIndex();
|
||||
const size_t parentIndex = node->GetParentIndex();
|
||||
const AZ::Vector3 nodeWorldPos = pose->GetWorldSpaceTransform(nodeIndex).m_position;
|
||||
|
||||
if (parentIndex != InvalidIndex)
|
||||
{
|
||||
const AZ::Vector3 parentWorldPos = pose->GetWorldSpaceTransform(parentIndex).m_position;
|
||||
const AZ::Vector3 bone = parentWorldPos - nodeWorldPos;
|
||||
const float boneLength = bone.GetLengthEstimate();
|
||||
|
||||
// 10% of the bone length is the sphere size
|
||||
return boneLength * 0.1f;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::PrepareForMesh(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM)
|
||||
{
|
||||
// Check if we have already prepared for the given mesh
|
||||
@@ -145,7 +174,7 @@ namespace AZ::Render
|
||||
auxGeom->DrawAabb(aabb, aabbColor, RPI::AuxGeomDraw::DrawStyle::Line);
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor)
|
||||
void AtomActorDebugDraw::RenderLineSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor)
|
||||
{
|
||||
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
|
||||
|
||||
@@ -189,6 +218,42 @@ namespace AZ::Render
|
||||
auxGeom->DrawLines(lineArgs);
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor)
|
||||
{
|
||||
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
|
||||
|
||||
const EMotionFX::TransformData* transformData = instance->GetTransformData();
|
||||
const EMotionFX::Skeleton* skeleton = instance->GetActor()->GetSkeleton();
|
||||
const EMotionFX::Pose* pose = transformData->GetCurrentPose();
|
||||
const size_t numEnabled = instance->GetNumEnabledNodes();
|
||||
for (size_t i = 0; i < numEnabled; ++i)
|
||||
{
|
||||
EMotionFX::Node* joint = skeleton->GetNode(instance->GetEnabledNode(i));
|
||||
const size_t jointIndex = joint->GetNodeIndex();
|
||||
const size_t parentIndex = joint->GetParentIndex();
|
||||
|
||||
// check if this node has a parent and is a bone, if not skip it
|
||||
if (parentIndex == InvalidIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const AZ::Vector3 nodeWorldPos = pose->GetWorldSpaceTransform(jointIndex).m_position;
|
||||
const AZ::Vector3 parentWorldPos = pose->GetWorldSpaceTransform(parentIndex).m_position;
|
||||
const AZ::Vector3 bone = parentWorldPos - nodeWorldPos;
|
||||
const AZ::Vector3 boneDirection = bone.GetNormalizedEstimate();
|
||||
const AZ::Vector3 centerWorldPos = bone / 2 + nodeWorldPos;
|
||||
const float boneLength = bone.GetLengthEstimate();
|
||||
const float boneScale = CalculateBoneScale(instance, joint);
|
||||
const float parentBoneScale = CalculateBoneScale(instance, skeleton->GetNode(parentIndex));
|
||||
const float cylinderSize = boneLength - boneScale - parentBoneScale;
|
||||
|
||||
// Render the bone cylinder, the cylinder will be directed towards the node's parent and must fit between the spheres
|
||||
auxGeom->DrawCylinder(centerWorldPos, boneDirection, boneScale, cylinderSize, skeletonColor);
|
||||
auxGeom->DrawSphere(nodeWorldPos, boneScale, skeletonColor);
|
||||
}
|
||||
}
|
||||
|
||||
void AtomActorDebugDraw::RenderEMFXDebugDraw(EMotionFX::ActorInstance* instance)
|
||||
{
|
||||
RPI::AuxGeomDrawPtr auxGeom = m_auxGeomFeatureProcessor->GetDrawQueue();
|
||||
|
||||
@@ -37,9 +37,12 @@ namespace AZ::Render
|
||||
|
||||
private:
|
||||
|
||||
float CalculateBoneScale(EMotionFX::ActorInstance* actorInstance, EMotionFX::Node* node);
|
||||
float CalculateScaleMultiplier(EMotionFX::ActorInstance* instance) const;
|
||||
void PrepareForMesh(EMotionFX::Mesh* mesh, const AZ::Transform& worldTM);
|
||||
|
||||
void RenderAABB(EMotionFX::ActorInstance* instance, const AZ::Color& aabbColor);
|
||||
void RenderLineSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor);
|
||||
void RenderSkeleton(EMotionFX::ActorInstance* instance, const AZ::Color& skeletonColor);
|
||||
void RenderEMFXDebugDraw(EMotionFX::ActorInstance* instance);
|
||||
void RenderNormals(
|
||||
|
||||
+2
@@ -545,6 +545,7 @@ namespace EMStudio
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnLineSkeletonColorChangedCallback)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_skeletonColor, "Solid skeleton color",
|
||||
"Solid skeleton color.")
|
||||
->Attribute(AZ_CRC("AlphaChannel", 0xa0cab5cf), true)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &RenderOptions::OnSkeletonColorChangedCallback)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &RenderOptions::m_selectionColor, "Selection gizmo color",
|
||||
"Selection gizmo color")
|
||||
@@ -1268,6 +1269,7 @@ namespace EMStudio
|
||||
void RenderOptions::OnSkeletonColorChangedCallback() const
|
||||
{
|
||||
PluginOptionsNotificationsBus::Event(s_skeletonColorOptionName, &PluginOptionsNotificationsBus::Events::OnOptionChanged, s_skeletonColorOptionName);
|
||||
CopyToRenderActorSettings(EMotionFX::GetRenderActorSettings());
|
||||
}
|
||||
|
||||
void RenderOptions::OnSelectionColorChangedCallback() const
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Module/Module.h>
|
||||
|
||||
#include <AzToolsFramework/API/PythonLoader.h>
|
||||
|
||||
#include <PythonSystemComponent.h>
|
||||
#include <PythonReflectionComponent.h>
|
||||
#include <PythonMarshalComponent.h>
|
||||
@@ -18,6 +20,7 @@ namespace EditorPythonBindings
|
||||
{
|
||||
class EditorPythonBindingsModule
|
||||
: public AZ::Module
|
||||
, public AzToolsFramework::EmbeddedPython::PythonLoader
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(EditorPythonBindingsModule, "{851B9E35-4FD5-49B1-8207-E40D4BBA36CC}", AZ::Module);
|
||||
|
||||
@@ -9,12 +9,15 @@
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/Module/Module.h>
|
||||
|
||||
#include <AzToolsFramework/API/PythonLoader.h>
|
||||
|
||||
#include <PythonAssetBuilderSystemComponent.h>
|
||||
|
||||
namespace PythonAssetBuilder
|
||||
{
|
||||
class PythonAssetBuilderModule
|
||||
: public AZ::Module
|
||||
, public AzToolsFramework::EmbeddedPython::PythonLoader
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(PythonAssetBuilderModule, "{35C9457E-54C2-474C-AEBE-5A70CC1D435D}", AZ::Module);
|
||||
|
||||
@@ -89,61 +89,6 @@
|
||||
}
|
||||
],
|
||||
"settings": [
|
||||
{
|
||||
"id": "heightmapImage",
|
||||
"displayName": "Heightmap Image",
|
||||
"description": "Heightmap of the terrain. Controlled by the runtime.",
|
||||
"visibility": "Hidden",
|
||||
"type": "Image",
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_heightmapImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "detailMaterialIdImage",
|
||||
"displayName": "Detail Material Id Image",
|
||||
"description": "Texture containing detail material Ids and weights. Controlled by the runtime.",
|
||||
"visibility": "Hidden",
|
||||
"type": "Image",
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_detailMaterialIdImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "detailMaterialIdCenter",
|
||||
"displayName": "Detail Material Id Image Center",
|
||||
"description": "The center position of the detail material Id image. Controlled by the runtime.",
|
||||
"visibility": "Hidden",
|
||||
"type": "Vector2",
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_detailMaterialIdImageCenter"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "detailAabb",
|
||||
"displayName": "Detail material bounds in 2d",
|
||||
"description": "The 2d world space bounds of the detail id material. Controlled by the runtime.",
|
||||
"visibility": "Hidden",
|
||||
"type": "Vector4",
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_detailAabb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "detailHalfPixelUv",
|
||||
"displayName": "Detail texture half pixel uv size",
|
||||
"description": "Uv size of a half pixel in the detail material id texture. Controlled by the runtime.",
|
||||
"visibility": "Hidden",
|
||||
"type": "float",
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_detailHalfPixelUv"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "detailTextureMultiplier",
|
||||
"displayName": "Detail Texture UV Multiplier",
|
||||
@@ -177,178 +122,6 @@
|
||||
"id": "m_detailFadeLength"
|
||||
}
|
||||
}
|
||||
],
|
||||
"baseColor": [
|
||||
{
|
||||
"id": "color",
|
||||
"displayName": "Color",
|
||||
"description": "Color is displayed as sRGB but the values are stored as linear color.",
|
||||
"type": "Color",
|
||||
"defaultValue": [ 1.0, 1.0, 1.0 ],
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_baseColor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "factor",
|
||||
"displayName": "Factor",
|
||||
"description": "Strength factor for scaling the base color values. Zero (0.0) is black, white (1.0) is full color.",
|
||||
"type": "Float",
|
||||
"defaultValue": 1.0,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_baseColorFactor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "textureMap",
|
||||
"displayName": "Texture",
|
||||
"description": "Base color texture map",
|
||||
"type": "Image",
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_baseColorMap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "useTexture",
|
||||
"displayName": "Use Texture",
|
||||
"description": "Whether to use the texture.",
|
||||
"type": "Bool",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"id": "textureBlendMode",
|
||||
"displayName": "Texture Blend Mode",
|
||||
"description": "Selects the equation to use when combining Color, Factor, and Texture.",
|
||||
"type": "Enum",
|
||||
"enumValues": [ "Multiply", "LinearLight", "Lerp", "Overlay" ],
|
||||
"defaultValue": "Overlay",
|
||||
"connection": {
|
||||
"type": "ShaderOption",
|
||||
"id": "o_baseColorTextureBlendMode"
|
||||
}
|
||||
}
|
||||
],
|
||||
"normal": [
|
||||
{
|
||||
"id": "textureMap",
|
||||
"displayName": "Texture",
|
||||
"description": "Texture for defining surface normal direction.",
|
||||
"type": "Image",
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_normalMap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "useTexture",
|
||||
"displayName": "Use Texture",
|
||||
"description": "Whether to use the texture, or just rely on vertex normals.",
|
||||
"type": "Bool",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"id": "flipX",
|
||||
"displayName": "Flip X Channel",
|
||||
"description": "Flip tangent direction for this normal map.",
|
||||
"type": "Bool",
|
||||
"defaultValue": false,
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_flipNormalX"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "flipY",
|
||||
"displayName": "Flip Y Channel",
|
||||
"description": "Flip bitangent direction for this normal map.",
|
||||
"type": "Bool",
|
||||
"defaultValue": false,
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_flipNormalY"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "factor",
|
||||
"displayName": "Factor",
|
||||
"description": "Strength factor for scaling the values",
|
||||
"type": "Float",
|
||||
"defaultValue": 1.0,
|
||||
"min": 0.0,
|
||||
"softMax": 2.0,
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_normalFactor"
|
||||
}
|
||||
}
|
||||
],
|
||||
"roughness": [
|
||||
{
|
||||
"id": "textureMap",
|
||||
"displayName": "Texture",
|
||||
"description": "Texture for defining surface roughness.",
|
||||
"type": "Image",
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_roughnessMap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "useTexture",
|
||||
"description": "Whether to use the texture, or just default to the Factor value.",
|
||||
"type": "Bool",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"id": "factor",
|
||||
"displayName": "Factor",
|
||||
"description": "Controls the roughness value",
|
||||
"type": "Float",
|
||||
"defaultValue": 1.0,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_roughnessFactor"
|
||||
}
|
||||
}
|
||||
],
|
||||
"specularF0": [
|
||||
{
|
||||
"id": "textureMap",
|
||||
"displayName": "Texture",
|
||||
"description": "Texture for defining surface reflectance.",
|
||||
"type": "Image",
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_specularF0Map"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "useTexture",
|
||||
"displayName": "Use Texture",
|
||||
"description": "Whether to use the texture, or just default to the Factor value.",
|
||||
"type": "Bool",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"id": "factor",
|
||||
"displayName": "Factor",
|
||||
"description": "The default IOR is 1.5, which gives you 0.04 (4% of light reflected at 0 degree angle for dielectric materials). F0 values lie in the range 0-0.08, so that is why the default F0 slider is set on 0.5.",
|
||||
"type": "Float",
|
||||
"defaultValue": 0.5,
|
||||
"min": 0.0,
|
||||
"max": 1.0,
|
||||
"connection": {
|
||||
"type": "ShaderInput",
|
||||
"id": "m_specularF0Factor"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -364,39 +137,5 @@
|
||||
}
|
||||
],
|
||||
"functors": [
|
||||
{
|
||||
"type": "UseTexture",
|
||||
"args": {
|
||||
"textureProperty": "baseColor.textureMap",
|
||||
"useTextureProperty": "baseColor.useTexture",
|
||||
"dependentProperties": ["baseColor.textureBlendMode"],
|
||||
"shaderOption": "o_baseColor_useTexture"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "UseTexture",
|
||||
"args": {
|
||||
"textureProperty": "specularF0.textureMap",
|
||||
"useTextureProperty": "specularF0.useTexture",
|
||||
"shaderOption": "o_specularF0_useTexture"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "UseTexture",
|
||||
"args": {
|
||||
"textureProperty": "normal.textureMap",
|
||||
"useTextureProperty": "normal.useTexture",
|
||||
"dependentProperties": ["normal.factor", "normal.flipX", "normal.flipY"],
|
||||
"shaderOption": "o_normal_useTexture"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "UseTexture",
|
||||
"args": {
|
||||
"textureProperty": "roughness.textureMap",
|
||||
"useTextureProperty": "roughness.useTexture",
|
||||
"shaderOption": "o_roughness_useTexture"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
|
||||
ShaderResourceGroup ObjectSrg : SRG_PerObject
|
||||
{
|
||||
row_major float3x4 m_modelToWorld;
|
||||
|
||||
struct TerrainData
|
||||
{
|
||||
float2 m_uvMin;
|
||||
@@ -36,6 +34,8 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
|
||||
uint m_mapsInUse;
|
||||
};
|
||||
|
||||
row_major float3x4 m_modelToWorld;
|
||||
|
||||
TerrainData m_terrainData;
|
||||
|
||||
MacroMaterialData m_macroMaterialData[4];
|
||||
@@ -43,7 +43,7 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
|
||||
|
||||
Texture2D m_macroColorMap[4];
|
||||
Texture2D m_macroNormalMap[4];
|
||||
|
||||
|
||||
// The below shouldn't be in this SRG but needs to be for now because the lighting functions depend on them.
|
||||
|
||||
//! Reflection Probe (smallest probe volume that overlaps the object position)
|
||||
@@ -93,26 +93,10 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject
|
||||
|
||||
ShaderResourceGroup TerrainMaterialSrg : SRG_PerMaterial
|
||||
{
|
||||
Texture2D m_heightmapImage;
|
||||
Texture2D<uint4> m_detailMaterialIdImage;
|
||||
float2 m_detailMaterialIdImageCenter;
|
||||
float m_detailTextureMultiplier;
|
||||
float m_detailFadeDistance;
|
||||
float m_detailFadeLength;
|
||||
|
||||
float4 m_detailAabb;
|
||||
float m_detailHalfPixelUv;
|
||||
|
||||
Sampler HeightmapSampler
|
||||
{
|
||||
MinFilter = Linear;
|
||||
MagFilter = Linear;
|
||||
MipFilter = Point;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
AddressW = Clamp;
|
||||
};
|
||||
|
||||
Sampler m_sampler
|
||||
{
|
||||
AddressU = Wrap;
|
||||
@@ -123,15 +107,6 @@ ShaderResourceGroup TerrainMaterialSrg : SRG_PerMaterial
|
||||
MaxAnisotropy = 16;
|
||||
};
|
||||
|
||||
Sampler m_detailSampler
|
||||
{
|
||||
AddressU = Wrap;
|
||||
AddressV = Wrap;
|
||||
MinFilter = Point;
|
||||
MagFilter = Point;
|
||||
MipFilter = Point;
|
||||
};
|
||||
|
||||
// Base Color
|
||||
float3 m_baseColor;
|
||||
float m_baseColorFactor;
|
||||
@@ -153,11 +128,6 @@ ShaderResourceGroup TerrainMaterialSrg : SRG_PerMaterial
|
||||
}
|
||||
|
||||
option bool o_useTerrainSmoothing = false;
|
||||
option bool o_baseColor_useTexture = true;
|
||||
option bool o_specularF0_useTexture = true;
|
||||
option bool o_normal_useTexture = true;
|
||||
option bool o_roughness_useTexture = true;
|
||||
option TextureBlendMode o_baseColorTextureBlendMode = TextureBlendMode::Multiply;
|
||||
|
||||
struct VertexInput
|
||||
{
|
||||
@@ -240,12 +210,12 @@ float GetHeight(float2 origUv)
|
||||
if (o_useTerrainSmoothing)
|
||||
{
|
||||
float2 textureSize;
|
||||
TerrainMaterialSrg::m_heightmapImage.GetDimensions(textureSize.x, textureSize.y);
|
||||
height = SampleBSpline5Tap(TerrainMaterialSrg::m_heightmapImage, TerrainMaterialSrg::HeightmapSampler, uv, textureSize, rcp(textureSize));
|
||||
ViewSrg::m_heightmapImage.GetDimensions(textureSize.x, textureSize.y);
|
||||
height = SampleBSpline5Tap(ViewSrg::m_heightmapImage, ViewSrg::HeightmapSampler, uv, textureSize, rcp(textureSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
height = TerrainMaterialSrg::m_heightmapImage.SampleLevel(TerrainMaterialSrg::HeightmapSampler, uv, 0).r;
|
||||
height = ViewSrg::m_heightmapImage.SampleLevel(ViewSrg::HeightmapSampler, uv, 0).r;
|
||||
}
|
||||
|
||||
return ObjectSrg::m_terrainData.m_heightScale * (height - 0.5f);
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/Features/ColorManagement/TransformColor.azsli>
|
||||
|
||||
enum DetailTextureFlags
|
||||
{
|
||||
UseTextureBaseColor = 0x00000001, //0b0000'0000'0000'0000'0000'0000'0000'0001
|
||||
UseTextureNormal = 0x00000002, //0b0000'0000'0000'0000'0000'0000'0000'0010
|
||||
UseTextureMetallic = 0x00000004, //0b0000'0000'0000'0000'0000'0000'0000'0100
|
||||
UseTextureRoughness = 0x00000008, //0b0000'0000'0000'0000'0000'0000'0000'1000
|
||||
UseTextureOcclusion = 0x00000010, //0b0000'0000'0000'0000'0000'0000'0001'0000
|
||||
UseTextureHeight = 0x00000020, //0b0000'0000'0000'0000'0000'0000'0010'0000
|
||||
UseTextureSpecularF0 = 0x00000040, //0b0000'0000'0000'0000'0000'0000'0100'0000
|
||||
|
||||
FlipNormalX = 0x00010000, //0b0000'0000'0000'0001'0000'0000'0000'0000
|
||||
FlipNormalY = 0x00020000, //0b0000'0000'0000'0010'0000'0000'0000'0000
|
||||
|
||||
BlendModeMask = 0x000C0000, //0b0000'0000'0000'1100'0000'0000'0000'0000
|
||||
BlendModeLerp = 0x00000000, //0b0000'0000'0000'0000'0000'0000'0000'0000
|
||||
BlendModeLinearLight = 0x00040000, //0b0000'0000'0000'0100'0000'0000'0000'0000
|
||||
BlendModeMultiply = 0x00080000, //0b0000'0000'0000'1000'0000'0000'0000'0000
|
||||
BlendModeOverlay = 0x000C0000, //0b0000'0000'0000'1100'0000'0000'0000'0000
|
||||
};
|
||||
|
||||
struct DetailSurface
|
||||
{
|
||||
float3 m_color;
|
||||
float3 m_normal;
|
||||
float m_roughness;
|
||||
float m_specularF0;
|
||||
float m_metalness;
|
||||
float m_occlusion;
|
||||
float m_height;
|
||||
};
|
||||
|
||||
option bool o_debugDetailMaterialIds = false;
|
||||
|
||||
DetailSurface GetDefaultDetailSurface()
|
||||
{
|
||||
DetailSurface surface;
|
||||
|
||||
surface.m_color = float3(0.5, 0.5, 0.5);
|
||||
surface.m_normal = float3(0.0, 0.0, 1.0);
|
||||
surface.m_roughness = 1.0;
|
||||
surface.m_specularF0 = 0.5;
|
||||
surface.m_metalness = 0.0;
|
||||
surface.m_occlusion = 1.0;
|
||||
surface.m_height = 0.5;
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
// Detail material index getters
|
||||
uint GetDetailColorIndex(TerrainSrg::DetailMaterialData materialData)
|
||||
{
|
||||
return materialData.m_colorNormalImageIndices & 0x0000FFFF;
|
||||
}
|
||||
|
||||
uint GetDetailNormalIndex(TerrainSrg::DetailMaterialData materialData)
|
||||
{
|
||||
return materialData.m_colorNormalImageIndices >> 16;
|
||||
}
|
||||
|
||||
uint GetDetailRoughnessIndex(TerrainSrg::DetailMaterialData materialData)
|
||||
{
|
||||
return materialData.m_roughnessMetalnessImageIndices & 0x0000FFFF;
|
||||
}
|
||||
|
||||
uint GetDetailMetalnessIndex(TerrainSrg::DetailMaterialData materialData)
|
||||
{
|
||||
return materialData.m_roughnessMetalnessImageIndices >> 16;
|
||||
}
|
||||
|
||||
uint GetDetailSpecularF0Index(TerrainSrg::DetailMaterialData materialData)
|
||||
{
|
||||
return materialData.m_specularF0OcclusionImageIndices & 0x0000FFFF;
|
||||
}
|
||||
|
||||
uint GetDetailOcclusionIndex(TerrainSrg::DetailMaterialData materialData)
|
||||
{
|
||||
return materialData.m_specularF0OcclusionImageIndices >> 16;
|
||||
}
|
||||
|
||||
uint GetDetailHeightIndex(TerrainSrg::DetailMaterialData materialData)
|
||||
{
|
||||
return materialData.m_heightImageIndex & 0x0000FFFF;
|
||||
}
|
||||
|
||||
// Detail material value getters
|
||||
|
||||
float3 GetDetailColor(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
||||
{
|
||||
float3 color = materialData.m_baseColor;
|
||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureBaseColor) > 0)
|
||||
{
|
||||
color = TerrainSrg::m_detailTextures[GetDetailColorIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).rgb;
|
||||
}
|
||||
return color * materialData.m_baseColorFactor;
|
||||
}
|
||||
|
||||
float3 GetDetailNormal(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
||||
{
|
||||
float2 normal = float2(0.0, 0.0);
|
||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureNormal) > 0)
|
||||
{
|
||||
normal = TerrainSrg::m_detailTextures[GetDetailNormalIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).rg;
|
||||
}
|
||||
|
||||
// X and Y are inverted here to be consistent with SampleNormalXY in NormalInput.azsli.
|
||||
if(materialData.m_flags & DetailTextureFlags::FlipNormalX)
|
||||
{
|
||||
normal.y = -normal.y;
|
||||
}
|
||||
if(materialData.m_flags & DetailTextureFlags::FlipNormalY)
|
||||
{
|
||||
normal.x = -normal.x;
|
||||
}
|
||||
return GetTangentSpaceNormal(normal, materialData.m_normalFactor);
|
||||
}
|
||||
|
||||
float GetDetailRoughness(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
||||
{
|
||||
float roughness = materialData.m_roughnessScale;
|
||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureRoughness) > 0)
|
||||
{
|
||||
roughness = TerrainSrg::m_detailTextures[GetDetailRoughnessIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).r;
|
||||
roughness = materialData.m_roughnessBias + roughness * materialData.m_roughnessScale;
|
||||
}
|
||||
return roughness;
|
||||
}
|
||||
|
||||
float GetDetailMetalness(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
||||
{
|
||||
float metalness = 1.0;
|
||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureMetallic) > 0)
|
||||
{
|
||||
metalness = TerrainSrg::m_detailTextures[GetDetailMetalnessIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).r;
|
||||
}
|
||||
return metalness * materialData.m_metalFactor;
|
||||
}
|
||||
|
||||
float GetDetailSpecularF0(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
||||
{
|
||||
float specularF0 = 1.0;
|
||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureSpecularF0) > 0)
|
||||
{
|
||||
specularF0 = TerrainSrg::m_detailTextures[GetDetailSpecularF0Index(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).r;
|
||||
}
|
||||
return specularF0 * materialData.m_specularF0Factor;
|
||||
}
|
||||
|
||||
float GetDetailOcclusion(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
||||
{
|
||||
float occlusion = 1.0;
|
||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureOcclusion) > 0)
|
||||
{
|
||||
occlusion = TerrainSrg::m_detailTextures[GetDetailOcclusionIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).r;
|
||||
}
|
||||
return occlusion * materialData.m_occlusionFactor;
|
||||
}
|
||||
|
||||
float GetDetailHeight(TerrainSrg::DetailMaterialData materialData, float2 uv)
|
||||
{
|
||||
float height = materialData.m_heightFactor;
|
||||
if ((materialData.m_flags & DetailTextureFlags::UseTextureHeight) > 0)
|
||||
{
|
||||
height = TerrainSrg::m_detailTextures[GetDetailHeightIndex(materialData)].Sample(TerrainMaterialSrg::m_sampler, uv).r;
|
||||
height = materialData.m_heightOffset + height * materialData.m_heightFactor;
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
void GetDetailSurfaceForMaterial(inout DetailSurface surface, uint materialId, float2 uv)
|
||||
{
|
||||
TerrainSrg::DetailMaterialData detailMaterialData = TerrainSrg::m_detailMaterialData[materialId];
|
||||
|
||||
surface.m_color = GetDetailColor(detailMaterialData, uv);
|
||||
surface.m_normal = GetDetailNormal(detailMaterialData, uv);
|
||||
surface.m_roughness = GetDetailRoughness(detailMaterialData, uv);
|
||||
surface.m_specularF0 = GetDetailSpecularF0(detailMaterialData, uv);
|
||||
surface.m_metalness = GetDetailMetalness(detailMaterialData, uv);
|
||||
surface.m_occlusion = GetDetailOcclusion(detailMaterialData, uv);
|
||||
surface.m_height = GetDetailHeight(detailMaterialData, uv);
|
||||
}
|
||||
|
||||
void GetDebugDetailSurface(inout DetailSurface surface, uint material1, uint material2, float blend, float2 idUv)
|
||||
{
|
||||
float3 material1Color = float3(0.1, 0.1, 0.1);
|
||||
float3 material2Color = float3(0.1, 0.1, 0.1);
|
||||
|
||||
// Get a reasonably random hue for the material id
|
||||
if (material1 != 255)
|
||||
{
|
||||
float hue1 = (material1 * 25043 % 256) / 256.0;
|
||||
material1Color = HsvToRgb(float3(hue1, 1.0, 1.0));
|
||||
}
|
||||
if (material2 != 255)
|
||||
{
|
||||
float hue2 = (material2 * 25043 % 256) / 256.0;
|
||||
material2Color = HsvToRgb(float3(hue2, 1.0, 1.0));
|
||||
}
|
||||
|
||||
surface.m_color = lerp(material1Color, material2Color, blend);
|
||||
float seamBlend = 0.0;
|
||||
const float halfLineWidth = 1.0 / 2048.0;
|
||||
if (any(abs(idUv) % 1.0 < halfLineWidth) || any(abs(idUv) % 1.0 > 1.0 - halfLineWidth))
|
||||
{
|
||||
seamBlend = 1.0;
|
||||
}
|
||||
surface.m_color = lerp(surface.m_color, float3(0.0, 0.0, 0.0), seamBlend); // draw texture seams
|
||||
surface.m_color = pow(surface.m_color , 2.2);
|
||||
|
||||
surface.m_normal = float3(0.0, 0.0, 1.0);
|
||||
surface.m_roughness = 1.0;
|
||||
surface.m_specularF0 = 0.5;
|
||||
surface.m_metalness = 0.0;
|
||||
surface.m_occlusion = 1.0;
|
||||
surface.m_height = 0.5;
|
||||
}
|
||||
|
||||
bool GetDetailSurface(inout DetailSurface surface, float2 idUv, float2 uv)
|
||||
{
|
||||
uint4 material1 = TerrainSrg::m_detailMaterialIdImage.GatherRed(TerrainSrg::DetailSampler, idUv, 0).xyzw;
|
||||
uint4 material2 = TerrainSrg::m_detailMaterialIdImage.GatherGreen(TerrainSrg::DetailSampler, idUv, 0).xyzw;
|
||||
|
||||
const float maxBlendAmount = 0xFF;
|
||||
// convert integer of 0-255 to float of 0-1.
|
||||
float4 blends = float4(TerrainSrg::m_detailMaterialIdImage.GatherBlue(TerrainSrg::DetailSampler, idUv, 0).xyzw) / maxBlendAmount;
|
||||
|
||||
if (o_debugDetailMaterialIds)
|
||||
{
|
||||
GetDebugDetailSurface(surface, material1.x, material2.x, blends.x, idUv);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (material1.x == 0xFF)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
GetDetailSurfaceForMaterial(surface, material1.x, uv);
|
||||
return true;
|
||||
}
|
||||
@@ -7,8 +7,11 @@
|
||||
*/
|
||||
|
||||
#include <Atom/Features/SrgSemantics.azsli>
|
||||
|
||||
#include <viewsrg.srgi>
|
||||
#include <TerrainSrg.azsli>
|
||||
#include <TerrainCommon.azsli>
|
||||
#include <TerrainDetailHelpers.azsli>
|
||||
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
|
||||
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
|
||||
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
|
||||
@@ -17,7 +20,6 @@
|
||||
#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
|
||||
#include <Atom/Features/Shadow/DirectionalLightShadow.azsli>
|
||||
#include <Atom/Features/PBR/Decals.azsli>
|
||||
#include <Atom/Features/ColorManagement/TransformColor.azsli>
|
||||
|
||||
struct VSOutput
|
||||
{
|
||||
@@ -28,8 +30,6 @@ struct VSOutput
|
||||
float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV2;
|
||||
};
|
||||
|
||||
option bool o_debugDetailMaterialIds = false;
|
||||
|
||||
VSOutput TerrainPBR_MainPassVS(VertexInput IN)
|
||||
{
|
||||
VSOutput OUT;
|
||||
@@ -71,9 +71,9 @@ ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN)
|
||||
{
|
||||
// ------- Surface -------
|
||||
Surface surface;
|
||||
|
||||
// Position
|
||||
surface.position = IN.m_worldPosition.xyz;
|
||||
surface.vertexNormal = normalize(IN.m_normal);
|
||||
|
||||
float viewDistance = length(ViewSrg::m_worldPosition - surface.position);
|
||||
float detailFactor = saturate((viewDistance - TerrainMaterialSrg::m_detailFadeDistance) / max(TerrainMaterialSrg::m_detailFadeLength, EPSILON));
|
||||
float2 detailUv = IN.m_uv * TerrainMaterialSrg::m_detailTextureMultiplier;
|
||||
@@ -83,92 +83,80 @@ ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN)
|
||||
|
||||
// ------- Macro Color / Normal -------
|
||||
float3 macroColor = TerrainMaterialSrg::m_baseColor.rgb;
|
||||
[unroll] for (uint i = 0; i < 4 && (i < ObjectSrg::m_macroMaterialCount); ++i)
|
||||
|
||||
// There's a bug that shows up with an NVidia GTX 1660 Super card happening on driver versions as recent as 496.49 (10/26/21) in which
|
||||
// the IN.m_uv values will intermittently "flicker" to 0.0 after entering and exiting game mode.
|
||||
// (See https://github.com/o3de/o3de/issues/5014)
|
||||
// This bug has only shown up on PCs when using the DX12 RHI. It doesn't show up with Vulkan or when capturing frames with PIX or
|
||||
// RenderDoc. Our best guess is that it is a driver bug. The workaround is to use the IN.m_uv values in a calculation prior to the
|
||||
// point that we actually use them for macroUv below. The "if(any(!isnan(IN.m_uv)))" seems to be sufficient for the workaround. The
|
||||
// if statement will always be true, but just the act of reading these values in the if statement makes the values stable. Removing
|
||||
// the if statement causes the flickering to occur using the steps documented in the bug.
|
||||
if (any(!isnan(IN.m_uv)))
|
||||
{
|
||||
float2 macroUvMin = ObjectSrg::m_macroMaterialData[i].m_uvMin;
|
||||
float2 macroUvMax = ObjectSrg::m_macroMaterialData[i].m_uvMax;
|
||||
float2 macroUv = lerp(macroUvMin, macroUvMax, IN.m_uv);
|
||||
if (macroUv.x >= 0.0 && macroUv.x <= 1.0 && macroUv.y >= 0.0 && macroUv.y <= 1.0)
|
||||
[unroll] for (uint i = 0; i < 4 && (i < ObjectSrg::m_macroMaterialCount); ++i)
|
||||
{
|
||||
if ((ObjectSrg::m_macroMaterialData[i].m_mapsInUse & 1) > 0)
|
||||
float2 macroUvMin = ObjectSrg::m_macroMaterialData[i].m_uvMin;
|
||||
float2 macroUvMax = ObjectSrg::m_macroMaterialData[i].m_uvMax;
|
||||
float2 macroUv = lerp(macroUvMin, macroUvMax, IN.m_uv);
|
||||
if (macroUv.x >= 0.0 && macroUv.x <= 1.0 && macroUv.y >= 0.0 && macroUv.y <= 1.0)
|
||||
{
|
||||
macroColor = GetBaseColorInput(ObjectSrg::m_macroColorMap[i], TerrainMaterialSrg::m_sampler, macroUv, macroColor, true);
|
||||
if ((ObjectSrg::m_macroMaterialData[i].m_mapsInUse & 1) > 0)
|
||||
{
|
||||
macroColor = GetBaseColorInput(ObjectSrg::m_macroColorMap[i], TerrainMaterialSrg::m_sampler, macroUv, macroColor, true);
|
||||
}
|
||||
if ((ObjectSrg::m_macroMaterialData[i].m_mapsInUse & 2) > 0)
|
||||
{
|
||||
bool flipX = ObjectSrg::m_macroMaterialData[i].m_flipNormalX;
|
||||
bool flipY = ObjectSrg::m_macroMaterialData[i].m_flipNormalY;
|
||||
bool factor = ObjectSrg::m_macroMaterialData[i].m_normalFactor;
|
||||
macroNormal = GetNormalInputTS(ObjectSrg::m_macroNormalMap[i], TerrainMaterialSrg::m_sampler,
|
||||
macroUv, flipX, flipY, CreateIdentity3x3(), true, factor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ((ObjectSrg::m_macroMaterialData[i].m_mapsInUse & 2) > 0)
|
||||
{
|
||||
bool flipX = ObjectSrg::m_macroMaterialData[i].m_flipNormalX;
|
||||
bool flipY = ObjectSrg::m_macroMaterialData[i].m_flipNormalY;
|
||||
bool factor = ObjectSrg::m_macroMaterialData[i].m_normalFactor;
|
||||
macroNormal = GetNormalInputTS(ObjectSrg::m_macroNormalMap[i], TerrainMaterialSrg::m_sampler,
|
||||
macroUv, flipX, flipY, CreateIdentity3x3(), true, factor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float3 detailNormal = GetNormalInputTS(TerrainMaterialSrg::m_normalMap, TerrainMaterialSrg::m_sampler,
|
||||
detailUv, TerrainMaterialSrg::m_flipNormalX, TerrainMaterialSrg::m_flipNormalY, CreateIdentity3x3(), o_normal_useTexture, TerrainMaterialSrg::m_normalFactor);
|
||||
|
||||
detailNormal = ReorientTangentSpaceNormal(macroNormal, detailNormal);
|
||||
surface.normal = lerp(detailNormal, macroNormal, detailFactor);
|
||||
surface.normal = normalize(surface.normal);
|
||||
surface.vertexNormal = normalize(IN.m_normal);
|
||||
|
||||
|
||||
// ------- Base Color -------
|
||||
float3 detailColor = GetBaseColorInput(TerrainMaterialSrg::m_baseColorMap, TerrainMaterialSrg::m_sampler, detailUv, TerrainMaterialSrg::m_baseColor.rgb, o_baseColor_useTexture);
|
||||
float3 blendedColor = BlendBaseColor(lerp(detailColor, TerrainMaterialSrg::m_baseColor.rgb, detailFactor), macroColor, TerrainMaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture);
|
||||
|
||||
// ------- Debug detail materials using random colors -------
|
||||
// This assigns a random color to each material, turns off any kind of distance fading, and draws a black line at the texture edges.
|
||||
if (o_debugDetailMaterialIds)
|
||||
DetailSurface detailSurface = GetDefaultDetailSurface();
|
||||
float2 detailRegionMin = TerrainSrg::m_detailAabb.xy;
|
||||
float2 detailRegionMax = TerrainSrg::m_detailAabb.zw;
|
||||
float2 detailRegionUv = (surface.position.xy - detailRegionMin) / (detailRegionMax - detailRegionMin);
|
||||
bool hasDetailSurface = false;
|
||||
|
||||
// Check to make sure we're inside the detail texture's bounds and within where detail textures should be drawn.
|
||||
if (detailFactor < 1.0 && all(detailRegionUv > TerrainSrg::m_detailHalfPixelUv) && all(detailRegionUv < 1.0 - TerrainSrg::m_detailHalfPixelUv))
|
||||
{
|
||||
float2 detailRegionMin = TerrainMaterialSrg::m_detailAabb.xy;
|
||||
float2 detailRegionMax = TerrainMaterialSrg::m_detailAabb.zw;
|
||||
float2 detailRegionUv = (surface.position.xy - detailRegionMin) / (detailRegionMax - detailRegionMin);
|
||||
if (all(detailRegionUv > TerrainMaterialSrg::m_detailHalfPixelUv) && all(detailRegionUv < 1.0 - TerrainMaterialSrg::m_detailHalfPixelUv))
|
||||
{
|
||||
detailRegionUv += TerrainMaterialSrg::m_detailMaterialIdImageCenter - (0.5);
|
||||
|
||||
uint material1 = TerrainMaterialSrg::m_detailMaterialIdImage.GatherRed(TerrainMaterialSrg::m_detailSampler, detailRegionUv, 0).r;
|
||||
uint material2 = TerrainMaterialSrg::m_detailMaterialIdImage.GatherGreen(TerrainMaterialSrg::m_detailSampler, detailRegionUv, 0).r;
|
||||
float blend = float(TerrainMaterialSrg::m_detailMaterialIdImage.GatherBlue(TerrainMaterialSrg::m_detailSampler, detailRegionUv, 0).r) / 0xFF;
|
||||
|
||||
float3 material1Color = float3(0.1, 0.1, 0.1);
|
||||
float3 material2Color = float3(0.1, 0.1, 0.1);
|
||||
|
||||
// Get a reasonably random hue for the material id
|
||||
if (material1 != 255)
|
||||
{
|
||||
float hue1 = (material1 * 25043 % 256) / 256.0;
|
||||
material1Color = HsvToRgb(float3(hue1, 1.0, 1.0));
|
||||
}
|
||||
if (material2 != 255)
|
||||
{
|
||||
float hue2 = (material2 * 25043 % 256) / 256.0;
|
||||
material2Color = HsvToRgb(float3(hue2, 1.0, 1.0));
|
||||
}
|
||||
|
||||
blendedColor = lerp(material1Color, material2Color, blend);
|
||||
float seamBlend = 0.0;
|
||||
const float halfLineWidth = 1.0 / 2048.0;
|
||||
if (any(abs(detailRegionUv) % 1.0 < halfLineWidth) || any(abs(detailRegionUv) % 1.0 > 1.0 - halfLineWidth))
|
||||
{
|
||||
seamBlend = 1.0;
|
||||
}
|
||||
blendedColor = lerp(blendedColor, float3(0.0, 0.0, 0.0), seamBlend); // draw texture seams
|
||||
blendedColor = pow(blendedColor , 2.2);
|
||||
}
|
||||
detailRegionUv += TerrainSrg::m_detailMaterialIdImageCenter - (0.5);
|
||||
hasDetailSurface = GetDetailSurface(detailSurface, detailRegionUv, detailUv);
|
||||
}
|
||||
|
||||
// ------- Specular -------
|
||||
float specularF0Factor = GetSpecularInput(TerrainMaterialSrg::m_specularF0Map, TerrainMaterialSrg::m_sampler, detailUv, TerrainMaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
|
||||
specularF0Factor = lerp(specularF0Factor, 0.5, detailFactor);
|
||||
surface.SetAlbedoAndSpecularF0(blendedColor, specularF0Factor, 0.0);
|
||||
const float macroRoughness = 1.0;
|
||||
const float macroSpecularF0 = 0.5;
|
||||
const float macroMetalness = 0.0;
|
||||
|
||||
// ------- Roughness -------
|
||||
surface.roughnessLinear = GetRoughnessInput(TerrainMaterialSrg::m_roughnessMap, TerrainMaterialSrg::m_sampler, detailUv, TerrainMaterialSrg::m_roughnessFactor, 0.0, 1.0, o_roughness_useTexture);
|
||||
surface.roughnessLinear = lerp(surface.roughnessLinear, 1.0, detailFactor);
|
||||
surface.CalculateRoughnessA();
|
||||
if (hasDetailSurface)
|
||||
{
|
||||
float3 blendedColor = lerp(detailSurface.m_color, macroColor, detailFactor);
|
||||
float blendedSpecularF0 = lerp(detailSurface.m_specularF0, macroSpecularF0, detailFactor);
|
||||
surface.SetAlbedoAndSpecularF0(blendedColor, blendedSpecularF0, detailSurface.m_metalness * (1.0 - detailFactor));
|
||||
|
||||
surface.roughnessLinear = lerp(detailSurface.m_roughness, macroRoughness, detailFactor);
|
||||
surface.CalculateRoughnessA();
|
||||
|
||||
detailSurface.m_normal = ReorientTangentSpaceNormal(macroNormal, detailSurface.m_normal);
|
||||
surface.normal = lerp(detailSurface.m_normal, macroNormal, detailFactor);
|
||||
surface.normal = normalize(surface.normal);
|
||||
}
|
||||
else
|
||||
{
|
||||
surface.normal = macroNormal;
|
||||
surface.SetAlbedoAndSpecularF0(macroColor, macroSpecularF0, macroMetalness);
|
||||
surface.roughnessLinear = macroRoughness;
|
||||
surface.CalculateRoughnessA();
|
||||
}
|
||||
|
||||
// Clear Coat, Transmission (Not used for terrain)
|
||||
surface.clearCoat.InitializeToZero();
|
||||
@@ -184,6 +172,7 @@ ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN)
|
||||
|
||||
// Shadow, Occlusion
|
||||
lightingData.shadowCoords = IN.m_shadowCoords;
|
||||
lightingData.diffuseAmbientOcclusion = detailSurface.m_occlusion;
|
||||
|
||||
// Diffuse and Specular response
|
||||
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Atom/Features/SrgSemantics.azsli>
|
||||
|
||||
ShaderResourceGroupSemantic SRG_Terrain
|
||||
{
|
||||
FrequencyId = 7;
|
||||
};
|
||||
|
||||
ShaderResourceGroup TerrainSrg : SRG_Terrain
|
||||
{
|
||||
|
||||
Sampler DetailSampler
|
||||
{
|
||||
AddressU = Wrap;
|
||||
AddressV = Wrap;
|
||||
MinFilter = Point;
|
||||
MagFilter = Point;
|
||||
MipFilter = Point;
|
||||
};
|
||||
|
||||
struct DetailMaterialData
|
||||
{
|
||||
// Uv
|
||||
row_major float3x4 m_uvTransform;
|
||||
|
||||
float3 m_baseColor;
|
||||
|
||||
// Factor / Scale / Bias for input textures
|
||||
float m_baseColorFactor;
|
||||
|
||||
float m_normalFactor;
|
||||
float m_metalFactor;
|
||||
float m_roughnessScale;
|
||||
float m_roughnessBias;
|
||||
|
||||
float m_specularF0Factor;
|
||||
float m_occlusionFactor;
|
||||
float m_heightFactor;
|
||||
float m_heightOffset;
|
||||
|
||||
float m_heightBlendFactor;
|
||||
|
||||
// Flags
|
||||
uint m_flags; // see DetailTextureFlags
|
||||
|
||||
// Image indices
|
||||
uint m_colorNormalImageIndices;
|
||||
uint m_roughnessMetalnessImageIndices;
|
||||
|
||||
uint m_specularF0OcclusionImageIndices;
|
||||
uint m_heightImageIndex; // only first 16 bits used
|
||||
|
||||
// 16 byte aligned
|
||||
uint2 m_padding;
|
||||
};
|
||||
|
||||
Texture2D<uint4> m_detailMaterialIdImage;
|
||||
StructuredBuffer<DetailMaterialData> m_detailMaterialData;
|
||||
Texture2D m_detailTextures[]; // bindless array of all textures for detail materials
|
||||
|
||||
float2 m_detailMaterialIdImageCenter;
|
||||
float m_detailHalfPixelUv;
|
||||
float4 m_detailAabb;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AZ_COLLECTING_PARTIAL_SRGS
|
||||
#error Do not include this file directly. Include the main .srgi file instead.
|
||||
#endif
|
||||
|
||||
partial ShaderResourceGroup ViewSrg
|
||||
{
|
||||
Sampler HeightmapSampler
|
||||
{
|
||||
MinFilter = Linear;
|
||||
MagFilter = Linear;
|
||||
MipFilter = Point;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
AddressW = Clamp;
|
||||
};
|
||||
|
||||
Sampler DetailSampler
|
||||
{
|
||||
AddressU = Wrap;
|
||||
AddressV = Wrap;
|
||||
MinFilter = Point;
|
||||
MagFilter = Point;
|
||||
MipFilter = Point;
|
||||
};
|
||||
|
||||
struct DetailMaterialData
|
||||
{
|
||||
// Uv
|
||||
row_major float3x4 m_uvTransform;
|
||||
|
||||
float3 m_baseColor;
|
||||
|
||||
// Factor / Scale / Bias for input textures
|
||||
float m_baseColorFactor;
|
||||
|
||||
float m_normalFactor;
|
||||
float m_metalFactor;
|
||||
float m_roughnessScale;
|
||||
float m_roughnessBias;
|
||||
|
||||
float m_specularF0Factor;
|
||||
float m_occlusionFactor;
|
||||
float m_heightFactor;
|
||||
float m_heightOffset;
|
||||
|
||||
float m_heightBlendFactor;
|
||||
|
||||
// Flags
|
||||
uint m_flags; // see DetailTextureFlags
|
||||
|
||||
// Image indices
|
||||
uint m_colorNormalImageIndices;
|
||||
uint m_roughnessMetalnessImageIndices;
|
||||
|
||||
uint m_specularF0OcclusionImageIndices;
|
||||
uint m_heightImageIndex; // only first 16 bits used
|
||||
|
||||
// 16 byte aligned
|
||||
uint2 m_padding;
|
||||
};
|
||||
|
||||
Texture2D m_heightmapImage;
|
||||
Texture2D<uint4> m_detailMaterialIdImage;
|
||||
StructuredBuffer<DetailMaterialData> m_detailMaterialData;
|
||||
|
||||
Texture2D m_detailTextures[]; // bindless array of all textures for detail materials
|
||||
|
||||
float2 m_detailMaterialIdImageCenter;
|
||||
float m_detailHalfPixelUv;
|
||||
|
||||
float4 m_detailAabb;
|
||||
}
|
||||
@@ -31,6 +31,9 @@
|
||||
#include <Atom/RPI.Public/Image/AttachmentImagePool.h>
|
||||
#include <Atom/RPI.Public/Model/Model.h>
|
||||
#include <Atom/RPI.Public/Material/Material.h>
|
||||
#include <Atom/RPI.Public/Pass/PassFilter.h>
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
#include <Atom/RPI.Public/Pass/RasterPass.h>
|
||||
|
||||
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
|
||||
#include <Atom/RPI.Reflect/Buffer/BufferAssetCreator.h>
|
||||
@@ -50,18 +53,24 @@ namespace Terrain
|
||||
const char* TerrainDetailChars = "TerrainDetail";
|
||||
}
|
||||
|
||||
namespace MaterialInputs
|
||||
namespace ViewSrgInputs
|
||||
{
|
||||
// Terrain material
|
||||
static const char* const HeightmapImage("settings.heightmapImage");
|
||||
static const char* const DetailMaterialIdImage("settings.detailMaterialIdImage");
|
||||
static const char* const DetailCenter("settings.detailMaterialIdCenter");
|
||||
static const char* const DetailAabb("settings.detailAabb");
|
||||
static const char* const DetailHalfPixelUv("settings.detailHalfPixelUv");
|
||||
static const char* const HeightmapImage("m_heightmapImage");
|
||||
}
|
||||
|
||||
namespace TerrainSrgInputs
|
||||
{
|
||||
static const char* const DetailMaterialIdImage("m_detailMaterialIdImage");
|
||||
static const char* const DetailMaterialData("m_detailMaterialData");
|
||||
static const char* const DetailMaterialIdImageCenter("m_detailMaterialIdImageCenter");
|
||||
static const char* const DetailHalfPixelUv("m_detailHalfPixelUv");
|
||||
static const char* const DetailAabb("m_detailAabb");
|
||||
static const char* const DetailTextures("m_detailTextures");
|
||||
}
|
||||
|
||||
namespace DetailMaterialInputs
|
||||
{
|
||||
static const char* const BaseColorColor("baseColor.color");
|
||||
static const char* const BaseColorMap("baseColor.textureMap");
|
||||
static const char* const BaseColorUseTexture("baseColor.useTexture");
|
||||
static const char* const BaseColorFactor("baseColor.factor");
|
||||
@@ -72,8 +81,8 @@ namespace Terrain
|
||||
static const char* const RoughnessMap("roughness.textureMap");
|
||||
static const char* const RoughnessUseTexture("roughness.useTexture");
|
||||
static const char* const RoughnessFactor("roughness.factor");
|
||||
static const char* const RoughnessUpperBound("roughness.lowerBound");
|
||||
static const char* const RoughnessLowerBound("roughness.upperBound");
|
||||
static const char* const RoughnessLowerBound("roughness.lowerBound");
|
||||
static const char* const RoughnessUpperBound("roughness.upperBound");
|
||||
static const char* const SpecularF0Map("specularF0.textureMap");
|
||||
static const char* const SpecularF0UseTexture("specularF0.useTexture");
|
||||
static const char* const SpecularF0Factor("specularF0.factor");
|
||||
@@ -126,6 +135,9 @@ namespace Terrain
|
||||
|
||||
void TerrainFeatureProcessor::Activate()
|
||||
{
|
||||
EnableSceneNotification();
|
||||
CacheForwardPass();
|
||||
|
||||
Initialize();
|
||||
AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusConnect();
|
||||
|
||||
@@ -138,6 +150,13 @@ namespace Terrain
|
||||
|
||||
void TerrainFeatureProcessor::Initialize()
|
||||
{
|
||||
// Load indices for the View Srg.
|
||||
|
||||
auto viewSrgLayout = AZ::RPI::RPISystemInterface::Get()->GetViewSrgLayout();
|
||||
|
||||
m_heightmapPropertyIndex = viewSrgLayout->FindShaderInputImageIndex(AZ::Name(ViewSrgInputs::HeightmapImage));
|
||||
AZ_Error(TerrainFPName, m_heightmapPropertyIndex.IsValid(), "Failed to find view srg input constant %s.", ViewSrgInputs::HeightmapImage);
|
||||
|
||||
// Load the terrain material asynchronously
|
||||
const AZStd::string materialFilePath = "Materials/Terrain/DefaultPbrTerrain.azmaterial";
|
||||
m_materialAssetLoader = AZStd::make_unique<AZ::RPI::AssetUtils::AsyncAssetLoader>();
|
||||
@@ -166,6 +185,7 @@ namespace Terrain
|
||||
return;
|
||||
}
|
||||
OnTerrainDataChanged(AZ::Aabb::CreateNull(), TerrainDataChangedMask::HeightData);
|
||||
|
||||
}
|
||||
|
||||
void TerrainFeatureProcessor::Deactivate()
|
||||
@@ -173,6 +193,8 @@ namespace Terrain
|
||||
TerrainMacroMaterialNotificationBus::Handler::BusDisconnect();
|
||||
AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusDisconnect();
|
||||
AZ::RPI::MaterialReloadNotificationBus::Handler::BusDisconnect();
|
||||
|
||||
DisableSceneNotification();
|
||||
|
||||
m_patchModel = {};
|
||||
m_areaData = {};
|
||||
@@ -181,6 +203,7 @@ namespace Terrain
|
||||
m_macroMaterials.Clear();
|
||||
m_materialAssetLoader = {};
|
||||
m_materialInstance = {};
|
||||
|
||||
}
|
||||
|
||||
void TerrainFeatureProcessor::Render(const AZ::RPI::FeatureProcessor::RenderPacket& packet)
|
||||
@@ -339,9 +362,47 @@ namespace Terrain
|
||||
|
||||
uint16_t detailMaterialId = CreateOrUpdateDetailMaterial(material);
|
||||
materialRegion.m_materialsForSurfaces.push_back({ surfaceTag, detailMaterialId });
|
||||
m_detailMaterials.GetData(detailMaterialId).refCount++;
|
||||
m_dirtyDetailRegion.AddAabb(materialRegion.m_region);
|
||||
}
|
||||
|
||||
void TerrainFeatureProcessor::OnRenderPipelinePassesChanged([[maybe_unused]] AZ::RPI::RenderPipeline* renderPipeline)
|
||||
{
|
||||
CacheForwardPass();
|
||||
}
|
||||
|
||||
void TerrainFeatureProcessor::CheckDetailMaterialForDeletion(uint16_t detailMaterialId)
|
||||
{
|
||||
auto& detailMaterialData = m_detailMaterials.GetData(detailMaterialId);
|
||||
if (--detailMaterialData.refCount == 0)
|
||||
{
|
||||
uint16_t bufferIndex = detailMaterialData.m_detailMaterialBufferIndex;
|
||||
DetailMaterialShaderData& shaderData = m_detailMaterialShaderData.GetElement(bufferIndex);
|
||||
|
||||
for (uint16_t imageIndex :
|
||||
{
|
||||
shaderData.m_colorImageIndex,
|
||||
shaderData.m_normalImageIndex,
|
||||
shaderData.m_roughnessImageIndex,
|
||||
shaderData.m_metalnessImageIndex,
|
||||
shaderData.m_specularF0ImageIndex,
|
||||
shaderData.m_occlusionImageIndex,
|
||||
shaderData.m_heightImageIndex
|
||||
})
|
||||
{
|
||||
if (imageIndex != InvalidDetailImageIndex)
|
||||
{
|
||||
m_detailImageViews.at(imageIndex) = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::Magenta)->GetImageView();
|
||||
m_detailImageViewFreeList.push_back(imageIndex);
|
||||
m_detailImagesNeedUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_detailMaterialShaderData.Release(bufferIndex);
|
||||
m_detailMaterials.RemoveIndex(detailMaterialId);
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainFeatureProcessor::OnTerrainSurfaceMaterialMappingDestroyed(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag)
|
||||
{
|
||||
DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions);
|
||||
@@ -350,6 +411,8 @@ namespace Terrain
|
||||
{
|
||||
if (surface.m_surfaceTag == surfaceTag)
|
||||
{
|
||||
CheckDetailMaterialForDeletion(surface.m_detailMaterialId);
|
||||
|
||||
if (surface.m_surfaceTag != materialRegion.m_materialsForSurfaces.back().m_surfaceTag)
|
||||
{
|
||||
AZStd::swap(surface, materialRegion.m_materialsForSurfaces.back());
|
||||
@@ -373,13 +436,19 @@ namespace Terrain
|
||||
if (surface.m_surfaceTag == surfaceTag)
|
||||
{
|
||||
found = true;
|
||||
surface.m_detailMaterialId = materialId;
|
||||
if (surface.m_detailMaterialId != materialId)
|
||||
{
|
||||
++m_detailMaterials.GetData(materialId).refCount;
|
||||
CheckDetailMaterialForDeletion(surface.m_detailMaterialId);
|
||||
surface.m_detailMaterialId = materialId;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
++m_detailMaterials.GetData(materialId).refCount;
|
||||
materialRegion.m_materialsForSurfaces.push_back({ surfaceTag, materialId });
|
||||
}
|
||||
m_dirtyDetailRegion.AddAabb(materialRegion.m_region);
|
||||
@@ -398,138 +467,196 @@ namespace Terrain
|
||||
static constexpr uint16_t InvalidDetailMaterial = 0xFFFF;
|
||||
uint16_t detailMaterialId = InvalidDetailMaterial;
|
||||
|
||||
for (DetailMaterialData& detailMaterial : m_detailMaterials.GetDataVector())
|
||||
for (auto& detailMaterialData : m_detailMaterials.GetDataVector())
|
||||
{
|
||||
if (detailMaterial.m_assetId == material->GetAssetId())
|
||||
if (detailMaterialData.m_assetId == material->GetAssetId())
|
||||
{
|
||||
UpdateDetailMaterialData(detailMaterial, material);
|
||||
detailMaterialId = m_detailMaterials.GetIndexForData(&detailMaterial);
|
||||
detailMaterialId = m_detailMaterials.GetIndexForData(&detailMaterialData);
|
||||
UpdateDetailMaterialData(detailMaterialId, material);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (detailMaterialId == InvalidDetailMaterial)
|
||||
AZ_Assert(m_detailMaterialShaderData.GetSize() < 0xFF, "Only 255 detail materials supported.");
|
||||
|
||||
if (detailMaterialId == InvalidDetailMaterial && m_detailMaterialShaderData.GetSize() < 0xFF)
|
||||
{
|
||||
detailMaterialId = m_detailMaterials.GetFreeSlotIndex();
|
||||
UpdateDetailMaterialData(m_detailMaterials.GetData(detailMaterialId), material);
|
||||
auto& detailMaterialData = m_detailMaterials.GetData(detailMaterialId);
|
||||
detailMaterialData.m_detailMaterialBufferIndex = aznumeric_cast<uint16_t>(m_detailMaterialShaderData.Reserve());
|
||||
UpdateDetailMaterialData(detailMaterialId, material);
|
||||
}
|
||||
return detailMaterialId;
|
||||
}
|
||||
|
||||
void TerrainFeatureProcessor::UpdateDetailMaterialData(DetailMaterialData& materialData, MaterialInstance material)
|
||||
void TerrainFeatureProcessor::UpdateDetailMaterialData(uint16_t detailMaterialIndex, MaterialInstance material)
|
||||
{
|
||||
if (materialData.m_materialChangeId != material->GetCurrentChangeId())
|
||||
DetailMaterialData& materialData = m_detailMaterials.GetData(detailMaterialIndex);
|
||||
DetailMaterialShaderData& shaderData = m_detailMaterialShaderData.GetElement(materialData.m_detailMaterialBufferIndex);
|
||||
|
||||
if (materialData.m_materialChangeId == material->GetCurrentChangeId())
|
||||
{
|
||||
materialData = DetailMaterialData();
|
||||
DetailTextureFlags& flags = materialData.m_properties.m_flags;
|
||||
materialData.m_materialChangeId = material->GetCurrentChangeId();
|
||||
materialData.m_assetId = material->GetAssetId();
|
||||
|
||||
auto getIndex = [&](const char* const indexName) -> AZ::RPI::MaterialPropertyIndex
|
||||
{
|
||||
const AZ::RPI::MaterialPropertyIndex index = material->FindPropertyIndex(AZ::Name(indexName));
|
||||
AZ_Warning(TerrainFPName, index.IsValid(), "Failed to find shader input constant %s.", indexName);
|
||||
return index;
|
||||
};
|
||||
|
||||
auto applyProperty = [&](const char* const indexName, auto& ref) -> void
|
||||
{
|
||||
const auto index = getIndex(indexName);
|
||||
if (index.IsValid())
|
||||
{
|
||||
using TypeRefRemoved = AZStd::remove_cvref_t<decltype(ref)>;
|
||||
ref = material->GetPropertyValue(index).GetValue<TypeRefRemoved>();
|
||||
}
|
||||
};
|
||||
|
||||
auto applyFlag = [&](const char* const indexName, DetailTextureFlags flagToSet) -> void
|
||||
{
|
||||
const auto index = getIndex(indexName);
|
||||
if (index.IsValid())
|
||||
{
|
||||
bool flagValue = material->GetPropertyValue(index).GetValue<bool>();
|
||||
flags = DetailTextureFlags(flagValue ? flags | flagToSet : flags);
|
||||
}
|
||||
};
|
||||
|
||||
auto getEnumName = [&](const char* const indexName) -> const AZStd::string_view
|
||||
{
|
||||
const auto index = getIndex(indexName);
|
||||
if (index.IsValid())
|
||||
{
|
||||
uint32_t enumIndex = material->GetPropertyValue(index).GetValue<uint32_t>();
|
||||
const AZ::Name& enumName = material->GetMaterialPropertiesLayout()->GetPropertyDescriptor(index)->GetEnumName(enumIndex);
|
||||
return enumName.GetStringView();
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
using namespace DetailMaterialInputs;
|
||||
applyProperty(BaseColorMap, materialData.m_colorImage);
|
||||
applyFlag(BaseColorUseTexture, DetailTextureFlags::UseTextureBaseColor);
|
||||
applyProperty(BaseColorFactor, materialData.m_properties.m_baseColorFactor);
|
||||
|
||||
const AZStd::string_view& blendModeString = getEnumName(BaseColorBlendMode);
|
||||
if (blendModeString == "Multiply")
|
||||
{
|
||||
flags = DetailTextureFlags(flags | DetailTextureFlags::BlendModeMultiply);
|
||||
}
|
||||
else if (blendModeString == "LinearLight")
|
||||
{
|
||||
flags = DetailTextureFlags(flags | DetailTextureFlags::BlendModeLinearLight);
|
||||
}
|
||||
else if (blendModeString == "Lerp")
|
||||
{
|
||||
flags = DetailTextureFlags(flags | DetailTextureFlags::BlendModeLerp);
|
||||
}
|
||||
else if (blendModeString == "Overlay")
|
||||
{
|
||||
flags = DetailTextureFlags(flags | DetailTextureFlags::BlendModeOverlay);
|
||||
}
|
||||
|
||||
applyProperty(MetallicMap, materialData.m_metalnessImage);
|
||||
applyFlag(MetallicUseTexture, DetailTextureFlags::UseTextureMetallic);
|
||||
applyProperty(MetallicFactor, materialData.m_properties.m_metalFactor);
|
||||
|
||||
applyProperty(RoughnessMap, materialData.m_roughnessImage);
|
||||
applyFlag(RoughnessUseTexture, DetailTextureFlags::UseTextureRoughness);
|
||||
|
||||
if ((flags & DetailTextureFlags::UseTextureRoughness) > 0)
|
||||
{
|
||||
float lowerBound = 0.0;
|
||||
float upperBound = 1.0;
|
||||
applyProperty(RoughnessLowerBound, lowerBound);
|
||||
applyProperty(RoughnessUpperBound, upperBound);
|
||||
materialData.m_properties.m_roughnessBias = lowerBound;
|
||||
materialData.m_properties.m_roughnessScale = upperBound - lowerBound;
|
||||
}
|
||||
else
|
||||
{
|
||||
materialData.m_properties.m_roughnessBias = 0.0;
|
||||
applyProperty(RoughnessFactor, materialData.m_properties.m_roughnessScale);
|
||||
}
|
||||
|
||||
applyProperty(SpecularF0Map, materialData.m_specularF0Image);
|
||||
applyFlag(SpecularF0UseTexture, DetailTextureFlags::UseTextureSpecularF0);
|
||||
applyProperty(SpecularF0Factor, materialData.m_properties.m_specularF0Factor);
|
||||
|
||||
applyProperty(NormalMap, materialData.m_normalImage);
|
||||
applyFlag(NormalUseTexture, DetailTextureFlags::UseTextureNormal);
|
||||
applyProperty(NormalFactor, materialData.m_properties.m_normalFactor);
|
||||
applyFlag(NormalFlipX, DetailTextureFlags::FlipNormalX);
|
||||
applyFlag(NormalFlipY, DetailTextureFlags::FlipNormalY);
|
||||
|
||||
applyProperty(DiffuseOcclusionMap, materialData.m_occlusionImage);
|
||||
applyFlag(DiffuseOcclusionUseTexture, DetailTextureFlags::UseTextureOcclusion);
|
||||
applyProperty(DiffuseOcclusionFactor, materialData.m_properties.m_occlusionFactor);
|
||||
|
||||
applyProperty(HeightMap, materialData.m_heightImage);
|
||||
applyFlag(HeightUseTexture, DetailTextureFlags::UseTextureHeight);
|
||||
applyProperty(HeightFactor, materialData.m_properties.m_heightFactor);
|
||||
applyProperty(HeightOffset, materialData.m_properties.m_heightOffset);
|
||||
applyProperty(HeightBlendFactor, materialData.m_properties.m_heightBlendFactor);
|
||||
|
||||
return; // material hasn't changed, nothing to do
|
||||
}
|
||||
|
||||
materialData.m_materialChangeId = material->GetCurrentChangeId();
|
||||
materialData.m_assetId = material->GetAssetId();
|
||||
|
||||
DetailTextureFlags& flags = shaderData.m_flags;
|
||||
|
||||
auto getIndex = [&](const char* const indexName) -> AZ::RPI::MaterialPropertyIndex
|
||||
{
|
||||
const AZ::RPI::MaterialPropertyIndex index = material->FindPropertyIndex(AZ::Name(indexName));
|
||||
AZ_Warning(TerrainFPName, index.IsValid(), "Failed to find shader input constant %s.", indexName);
|
||||
return index;
|
||||
};
|
||||
|
||||
auto applyProperty = [&](const char* const indexName, auto& ref) -> void
|
||||
{
|
||||
const auto index = getIndex(indexName);
|
||||
if (index.IsValid())
|
||||
{
|
||||
// GetValue<T>() expects the actaul type, not a reference type, so the reference needs to be removed.
|
||||
using TypeRefRemoved = AZStd::remove_cvref_t<decltype(ref)>;
|
||||
ref = material->GetPropertyValue(index).GetValue<TypeRefRemoved>();
|
||||
}
|
||||
};
|
||||
|
||||
auto applyImage = [&](const char* const indexName, AZ::Data::Instance<AZ::RPI::Image>& ref, const char* const usingFlagName, DetailTextureFlags flagToSet, uint16_t& imageIndex) -> void
|
||||
{
|
||||
// Determine if an image exists and if its using flag allows it to be used.
|
||||
const auto index = getIndex(indexName);
|
||||
const auto useTextureIndex = getIndex(usingFlagName);
|
||||
bool useTextureValue = true;
|
||||
if (useTextureIndex.IsValid())
|
||||
{
|
||||
useTextureValue = material->GetPropertyValue(useTextureIndex).GetValue<bool>();
|
||||
}
|
||||
if (index.IsValid() && useTextureValue)
|
||||
{
|
||||
ref = material->GetPropertyValue(index).GetValue<AZ::Data::Instance<AZ::RPI::Image>>();
|
||||
}
|
||||
useTextureValue = useTextureValue && ref;
|
||||
flags = DetailTextureFlags(useTextureValue ? (flags | flagToSet) : (flags & ~flagToSet));
|
||||
|
||||
// Update queues to add/remove textures depending on if the image is used
|
||||
if (ref)
|
||||
{
|
||||
if (imageIndex == InvalidDetailImageIndex)
|
||||
{
|
||||
if (m_detailImageViewFreeList.size() > 0)
|
||||
{
|
||||
imageIndex = m_detailImageViewFreeList.back();
|
||||
m_detailImageViewFreeList.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
imageIndex = aznumeric_cast<uint16_t>(m_detailImageViews.size());
|
||||
m_detailImageViews.push_back();
|
||||
}
|
||||
}
|
||||
m_detailImageViews.at(imageIndex) = ref->GetImageView();
|
||||
m_detailImagesNeedUpdate = true;
|
||||
}
|
||||
else if (imageIndex != InvalidDetailImageIndex)
|
||||
{
|
||||
m_detailImageViews.at(imageIndex) = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::Magenta)->GetImageView();
|
||||
m_detailImageViewFreeList.push_back(imageIndex);
|
||||
m_detailImagesNeedUpdate = true;
|
||||
imageIndex = InvalidDetailImageIndex;
|
||||
}
|
||||
};
|
||||
|
||||
auto applyFlag = [&](const char* const indexName, DetailTextureFlags flagToSet) -> void
|
||||
{
|
||||
const auto index = getIndex(indexName);
|
||||
if (index.IsValid())
|
||||
{
|
||||
bool flagValue = material->GetPropertyValue(index).GetValue<bool>();
|
||||
flags = DetailTextureFlags(flagValue ? flags | flagToSet : flags);
|
||||
}
|
||||
};
|
||||
|
||||
auto getEnumName = [&](const char* const indexName) -> const AZStd::string_view
|
||||
{
|
||||
const auto index = getIndex(indexName);
|
||||
if (index.IsValid())
|
||||
{
|
||||
uint32_t enumIndex = material->GetPropertyValue(index).GetValue<uint32_t>();
|
||||
const AZ::Name& enumName = material->GetMaterialPropertiesLayout()->GetPropertyDescriptor(index)->GetEnumName(enumIndex);
|
||||
return enumName.GetStringView();
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
using namespace DetailMaterialInputs;
|
||||
applyImage(BaseColorMap, materialData.m_colorImage, BaseColorUseTexture, DetailTextureFlags::UseTextureBaseColor, shaderData.m_colorImageIndex);
|
||||
applyProperty(BaseColorFactor, shaderData.m_baseColorFactor);
|
||||
|
||||
const auto index = getIndex(BaseColorColor);
|
||||
if (index.IsValid())
|
||||
{
|
||||
AZ::Color baseColor = material->GetPropertyValue(index).GetValue<AZ::Color>();
|
||||
shaderData.m_baseColorRed = baseColor.GetR();
|
||||
shaderData.m_baseColorGreen = baseColor.GetG();
|
||||
shaderData.m_baseColorBlue = baseColor.GetB();
|
||||
}
|
||||
|
||||
const AZStd::string_view& blendModeString = getEnumName(BaseColorBlendMode);
|
||||
if (blendModeString == "Multiply")
|
||||
{
|
||||
flags = DetailTextureFlags(flags | DetailTextureFlags::BlendModeMultiply);
|
||||
}
|
||||
else if (blendModeString == "LinearLight")
|
||||
{
|
||||
flags = DetailTextureFlags(flags | DetailTextureFlags::BlendModeLinearLight);
|
||||
}
|
||||
else if (blendModeString == "Lerp")
|
||||
{
|
||||
flags = DetailTextureFlags(flags | DetailTextureFlags::BlendModeLerp);
|
||||
}
|
||||
else if (blendModeString == "Overlay")
|
||||
{
|
||||
flags = DetailTextureFlags(flags | DetailTextureFlags::BlendModeOverlay);
|
||||
}
|
||||
|
||||
applyImage(MetallicMap, materialData.m_metalnessImage, MetallicUseTexture, DetailTextureFlags::UseTextureMetallic, shaderData.m_metalnessImageIndex);
|
||||
applyProperty(MetallicFactor, shaderData.m_metalFactor);
|
||||
|
||||
applyImage(RoughnessMap, materialData.m_roughnessImage, RoughnessUseTexture, DetailTextureFlags::UseTextureRoughness, shaderData.m_roughnessImageIndex);
|
||||
|
||||
if ((flags & DetailTextureFlags::UseTextureRoughness) > 0)
|
||||
{
|
||||
float lowerBound = 0.0;
|
||||
float upperBound = 1.0;
|
||||
applyProperty(RoughnessLowerBound, lowerBound);
|
||||
applyProperty(RoughnessUpperBound, upperBound);
|
||||
shaderData.m_roughnessBias = lowerBound;
|
||||
shaderData.m_roughnessScale = upperBound - lowerBound;
|
||||
}
|
||||
else
|
||||
{
|
||||
shaderData.m_roughnessBias = 0.0;
|
||||
applyProperty(RoughnessFactor, shaderData.m_roughnessScale);
|
||||
}
|
||||
|
||||
applyImage(SpecularF0Map, materialData.m_specularF0Image, SpecularF0UseTexture, DetailTextureFlags::UseTextureSpecularF0, shaderData.m_specularF0ImageIndex);
|
||||
applyProperty(SpecularF0Factor, shaderData.m_specularF0Factor);
|
||||
|
||||
applyImage(NormalMap, materialData.m_normalImage, NormalUseTexture, DetailTextureFlags::UseTextureNormal, shaderData.m_normalImageIndex);
|
||||
applyProperty(NormalFactor, shaderData.m_normalFactor);
|
||||
applyFlag(NormalFlipX, DetailTextureFlags::FlipNormalX);
|
||||
applyFlag(NormalFlipY, DetailTextureFlags::FlipNormalY);
|
||||
|
||||
applyImage(DiffuseOcclusionMap, materialData.m_occlusionImage, DiffuseOcclusionUseTexture, DetailTextureFlags::UseTextureOcclusion, shaderData.m_occlusionImageIndex);
|
||||
applyProperty(DiffuseOcclusionFactor, shaderData.m_occlusionFactor);
|
||||
|
||||
applyImage(HeightMap, materialData.m_heightImage, HeightUseTexture, DetailTextureFlags::UseTextureHeight, shaderData.m_heightImageIndex);
|
||||
applyProperty(HeightFactor, shaderData.m_heightFactor);
|
||||
applyProperty(HeightOffset, shaderData.m_heightOffset);
|
||||
applyProperty(HeightBlendFactor, shaderData.m_heightBlendFactor);
|
||||
|
||||
m_updateDetailMaterialBuffer = true;
|
||||
}
|
||||
|
||||
void TerrainFeatureProcessor::CheckUpdateDetailTexture(const Aabb2i& newBounds, const Vector2i& newCenter)
|
||||
@@ -765,7 +892,7 @@ namespace Terrain
|
||||
{
|
||||
if (materialSurface.m_surfaceTag == surfaceType)
|
||||
{
|
||||
return materialSurface.m_detailMaterialId;
|
||||
return m_detailMaterials.GetData(materialSurface.m_detailMaterialId).m_detailMaterialBufferIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -801,6 +928,7 @@ namespace Terrain
|
||||
|
||||
// World size changed, so the whole height map needs updating.
|
||||
m_dirtyRegion = worldBounds;
|
||||
m_imagesNeedUpdate = true;
|
||||
}
|
||||
|
||||
int32_t xStart = aznumeric_cast<int32_t>(AZStd::ceilf(m_dirtyRegion.GetMin().GetX() / queryResolution));
|
||||
@@ -889,21 +1017,48 @@ namespace Terrain
|
||||
|
||||
m_macroNormalMapIndex = layout->FindShaderInputImageIndex(AZ::Name(ShaderInputs::MacroNormalMap));
|
||||
AZ_Error(TerrainFPName, m_macroNormalMapIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::MacroNormalMap);
|
||||
|
||||
m_heightmapPropertyIndex = m_materialInstance->GetMaterialPropertiesLayout()->FindPropertyIndex(AZ::Name(MaterialInputs::HeightmapImage));
|
||||
AZ_Error(TerrainFPName, m_heightmapPropertyIndex.IsValid(), "Failed to find material input constant %s.", MaterialInputs::HeightmapImage);
|
||||
|
||||
m_detailMaterialIdPropertyIndex = m_materialInstance->GetMaterialPropertiesLayout()->FindPropertyIndex(AZ::Name(MaterialInputs::DetailMaterialIdImage));
|
||||
AZ_Error(TerrainFPName, m_detailMaterialIdPropertyIndex.IsValid(), "Failed to find material input constant %s.", MaterialInputs::DetailMaterialIdImage);
|
||||
|
||||
m_detailCenterPropertyIndex = m_materialInstance->GetMaterialPropertiesLayout()->FindPropertyIndex(AZ::Name(MaterialInputs::DetailCenter));
|
||||
AZ_Error(TerrainFPName, m_detailCenterPropertyIndex.IsValid(), "Failed to find material input constant %s.", MaterialInputs::DetailCenter);
|
||||
|
||||
m_detailAabbPropertyIndex = m_materialInstance->GetMaterialPropertiesLayout()->FindPropertyIndex(AZ::Name(MaterialInputs::DetailAabb));
|
||||
AZ_Error(TerrainFPName, m_detailAabbPropertyIndex.IsValid(), "Failed to find material input constant %s.", MaterialInputs::DetailAabb);
|
||||
m_terrainSrg = {};
|
||||
for (auto& shaderItem : m_materialInstance->GetShaderCollection())
|
||||
{
|
||||
if (shaderItem.GetShaderAsset()->GetDrawListName() == AZ::Name("forward"))
|
||||
{
|
||||
const auto& shaderAsset = shaderItem.GetShaderAsset();
|
||||
m_terrainSrg = AZ::RPI::ShaderResourceGroup::Create(shaderItem.GetShaderAsset(), shaderAsset->GetSupervariantIndex(AZ::Name()), AZ::Name{"TerrainSrg"});
|
||||
AZ_Error(TerrainFPName, m_terrainSrg, "Failed to create Terrain shader resource group");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AZ_Error(TerrainFPName, m_terrainSrg, "Terrain Srg not found on any shader in the terrain material");
|
||||
|
||||
if (m_terrainSrg)
|
||||
{
|
||||
const AZ::RHI::ShaderResourceGroupLayout* terrainSrgLayout = m_terrainSrg->GetLayout();
|
||||
|
||||
m_detailMaterialIdPropertyIndex = terrainSrgLayout->FindShaderInputImageIndex(AZ::Name(TerrainSrgInputs::DetailMaterialIdImage));
|
||||
AZ_Error(TerrainFPName, m_detailMaterialIdPropertyIndex.IsValid(), "Failed to find view srg input constant %s.", TerrainSrgInputs::DetailMaterialIdImage);
|
||||
|
||||
m_detailHalfPixelUvPropertyIndex = m_materialInstance->GetMaterialPropertiesLayout()->FindPropertyIndex(AZ::Name(MaterialInputs::DetailHalfPixelUv));
|
||||
AZ_Error(TerrainFPName, m_detailHalfPixelUvPropertyIndex.IsValid(), "Failed to find material input constant %s.", MaterialInputs::DetailHalfPixelUv);
|
||||
m_detailCenterPropertyIndex = terrainSrgLayout->FindShaderInputConstantIndex(AZ::Name(TerrainSrgInputs::DetailMaterialIdImageCenter));
|
||||
AZ_Error(TerrainFPName, m_detailCenterPropertyIndex.IsValid(), "Failed to find view srg input constant %s.", TerrainSrgInputs::DetailMaterialIdImageCenter);
|
||||
|
||||
m_detailHalfPixelUvPropertyIndex = terrainSrgLayout->FindShaderInputConstantIndex(AZ::Name(TerrainSrgInputs::DetailHalfPixelUv));
|
||||
AZ_Error(TerrainFPName, m_detailHalfPixelUvPropertyIndex.IsValid(), "Failed to find view srg input constant %s.", TerrainSrgInputs::DetailHalfPixelUv);
|
||||
|
||||
m_detailAabbPropertyIndex = terrainSrgLayout->FindShaderInputConstantIndex(AZ::Name(TerrainSrgInputs::DetailAabb));
|
||||
AZ_Error(TerrainFPName, m_detailAabbPropertyIndex.IsValid(), "Failed to find view srg input constant %s.", TerrainSrgInputs::DetailAabb);
|
||||
|
||||
m_detailTexturesIndex = terrainSrgLayout->FindShaderInputImageUnboundedArrayIndex(AZ::Name(TerrainSrgInputs::DetailTextures));
|
||||
AZ_Error(TerrainFPName, m_detailTexturesIndex.IsValid(), "Failed to find view srg input constant %s.", TerrainSrgInputs::DetailTextures);
|
||||
|
||||
// Set up the gpu buffer for detail material data
|
||||
AZ::Render::GpuBufferHandler::Descriptor desc;
|
||||
desc.m_bufferName = "Detail Material Data";
|
||||
desc.m_bufferSrgName = TerrainSrgInputs::DetailMaterialData;
|
||||
desc.m_elementSize = sizeof(DetailMaterialShaderData);
|
||||
desc.m_srgLayout = terrainSrgLayout;
|
||||
m_detailMaterialDataBuffer = AZ::Render::GpuBufferHandler(desc);
|
||||
}
|
||||
|
||||
// Find any macro materials that have already been created.
|
||||
TerrainMacroMaterialRequestBus::EnumerateHandlers(
|
||||
@@ -987,7 +1142,7 @@ namespace Terrain
|
||||
auto objectSrg = AZ::RPI::ShaderResourceGroup::Create(shaderAsset, materialAsset->GetObjectSrgLayout()->GetName());
|
||||
if (!objectSrg)
|
||||
{
|
||||
AZ_Warning("TerrainFeatureProcessor", false, "Failed to create a new shader resource group, skipping.");
|
||||
AZ_Warning(TerrainFPName, false, "Failed to create a new shader resource group, skipping.");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1003,7 +1158,7 @@ namespace Terrain
|
||||
// set the shader option to select forward pass IBL specular if necessary
|
||||
if (!drawPacket.SetShaderOption(AZ::Name("o_meshUseForwardPassIBLSpecular"), AZ::RPI::ShaderOptionValue{ false }))
|
||||
{
|
||||
AZ_Warning("MeshDrawPacket", false, "Failed to set o_meshUseForwardPassIBLSpecular on mesh draw packet");
|
||||
AZ_Warning(TerrainFPName, false, "Failed to set o_meshUseForwardPassIBLSpecular on mesh draw packet");
|
||||
}
|
||||
const uint8_t stencilRef = AZ::Render::StencilRefs::UseDiffuseGIPass | AZ::Render::StencilRefs::UseIBLSpecularPass;
|
||||
drawPacket.SetStencilRef(stencilRef);
|
||||
@@ -1053,11 +1208,14 @@ namespace Terrain
|
||||
if (m_areaData.m_heightmapUpdated)
|
||||
{
|
||||
UpdateTerrainData();
|
||||
|
||||
const AZ::Data::Instance<AZ::RPI::Image> heightmapImage = m_areaData.m_heightmapImage; // cast StreamingImage to Image
|
||||
m_materialInstance->SetPropertyValue(m_heightmapPropertyIndex, heightmapImage);
|
||||
}
|
||||
|
||||
if (m_updateDetailMaterialBuffer)
|
||||
{
|
||||
m_updateDetailMaterialBuffer = false;
|
||||
m_detailMaterialDataBuffer.UpdateBuffer(m_detailMaterialShaderData.GetRawData(), aznumeric_cast<uint32_t>(m_detailMaterialShaderData.GetSize()));
|
||||
}
|
||||
|
||||
AZ::Vector3 cameraPosition = AZ::Vector3::CreateZero();
|
||||
for (auto& view : process.m_views)
|
||||
{
|
||||
@@ -1068,7 +1226,7 @@ namespace Terrain
|
||||
}
|
||||
}
|
||||
|
||||
if (m_dirtyDetailRegion.IsValid() || !cameraPosition.IsClose(m_previousCameraPosition))
|
||||
if (m_dirtyDetailRegion.IsValid() || !cameraPosition.IsClose(m_previousCameraPosition) || m_detailImagesNeedUpdate)
|
||||
{
|
||||
int32_t newDetailTexturePosX = aznumeric_cast<int32_t>(AZStd::roundf(cameraPosition.GetX() / DetailTextureScale));
|
||||
int32_t newDetailTexturePosY = aznumeric_cast<int32_t>(AZStd::roundf(cameraPosition.GetY() / DetailTextureScale));
|
||||
@@ -1091,8 +1249,6 @@ namespace Terrain
|
||||
m_dirtyDetailRegion = AZ::Aabb::CreateNull();
|
||||
|
||||
m_previousCameraPosition = cameraPosition;
|
||||
const AZ::Data::Instance<AZ::RPI::Image> detailTextureImage = m_detailTextureImage; // cast StreamingImage to Image
|
||||
m_materialInstance->SetPropertyValue(m_detailMaterialIdPropertyIndex, detailTextureImage);
|
||||
|
||||
AZ::Vector4 detailAabb = AZ::Vector4(
|
||||
m_detailTextureBounds.m_min.m_x * DetailTextureScale,
|
||||
@@ -1100,11 +1256,16 @@ namespace Terrain
|
||||
m_detailTextureBounds.m_max.m_x * DetailTextureScale,
|
||||
m_detailTextureBounds.m_max.m_y * DetailTextureScale
|
||||
);
|
||||
m_materialInstance->SetPropertyValue(m_detailAabbPropertyIndex, detailAabb);
|
||||
m_materialInstance->SetPropertyValue(m_detailHalfPixelUvPropertyIndex, 0.5f / DetailTextureSize);
|
||||
|
||||
AZ::Vector2 detailUvOffset = AZ::Vector2(float(newCenter.m_x) / DetailTextureSize, float(newCenter.m_y) / DetailTextureSize);
|
||||
m_materialInstance->SetPropertyValue(m_detailCenterPropertyIndex, detailUvOffset);
|
||||
|
||||
if (m_terrainSrg)
|
||||
{
|
||||
m_terrainSrg->SetConstant(m_detailAabbPropertyIndex, detailAabb);
|
||||
m_terrainSrg->SetConstant(m_detailHalfPixelUvPropertyIndex, 0.5f / DetailTextureSize);
|
||||
m_terrainSrg->SetConstant(m_detailCenterPropertyIndex, detailUvOffset);
|
||||
|
||||
m_detailMaterialDataBuffer.UpdateSrg(m_terrainSrg.get());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_areaData.m_heightmapUpdated || m_areaData.m_macroMaterialsUpdated)
|
||||
@@ -1195,6 +1356,15 @@ namespace Terrain
|
||||
sectorData.m_srg->Compile();
|
||||
}
|
||||
}
|
||||
|
||||
// Currently there seems to be a bug in unbounded image arrays where flickering can occur if this isn't updated every frame.
|
||||
if (m_terrainSrg/* && m_detailImagesUpdated*/)
|
||||
{
|
||||
AZStd::array_view<const AZ::RHI::ImageView*> imageViews(m_detailImageViews.data(), m_detailImageViews.size());
|
||||
[[maybe_unused]] bool result = m_terrainSrg->SetImageViewUnboundedArray(m_detailTexturesIndex, imageViews);
|
||||
AZ_Error(TerrainFPName, result, "Failed to set image view unbounded array into shader resource group.");
|
||||
m_detailImagesNeedUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& sectorData : m_sectorData)
|
||||
@@ -1236,10 +1406,30 @@ namespace Terrain
|
||||
}
|
||||
}
|
||||
|
||||
if (m_detailTextureImage && m_areaData.m_heightmapImage && m_imagesNeedUpdate)
|
||||
{
|
||||
m_imagesNeedUpdate = false;
|
||||
for (auto& view : process.m_views)
|
||||
{
|
||||
auto viewSrg = view->GetShaderResourceGroup();
|
||||
viewSrg->SetImage(m_heightmapPropertyIndex, m_areaData.m_heightmapImage);
|
||||
}
|
||||
if (m_terrainSrg)
|
||||
{
|
||||
m_terrainSrg->SetImage(m_detailMaterialIdPropertyIndex, m_detailTextureImage);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_materialInstance)
|
||||
{
|
||||
m_materialInstance->Compile();
|
||||
}
|
||||
|
||||
if (m_terrainSrg && m_forwardPass)
|
||||
{
|
||||
m_terrainSrg->Compile();
|
||||
m_forwardPass->BindSrg(m_terrainSrg->GetRHIShaderResourceGroup());
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainFeatureProcessor::InitializeTerrainPatch(uint16_t gridSize, float gridSpacing, PatchData& patchdata)
|
||||
@@ -1368,6 +1558,7 @@ namespace Terrain
|
||||
|
||||
void TerrainFeatureProcessor::OnMaterialReinitialized([[maybe_unused]] const MaterialInstance& material)
|
||||
{
|
||||
PrepareMaterialData();
|
||||
for (auto& sectorData : m_sectorData)
|
||||
{
|
||||
for (auto& drawPacket : sectorData.m_drawPackets)
|
||||
@@ -1375,6 +1566,8 @@ namespace Terrain
|
||||
drawPacket.Update(*GetParentScene());
|
||||
}
|
||||
}
|
||||
m_imagesNeedUpdate = true;
|
||||
m_detailImagesNeedUpdate = true;
|
||||
}
|
||||
|
||||
void TerrainFeatureProcessor::SetWorldSize([[maybe_unused]] AZ::Vector2 sizeInMeters)
|
||||
@@ -1438,6 +1631,27 @@ namespace Terrain
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainFeatureProcessor::CacheForwardPass()
|
||||
{
|
||||
auto rasterPassFilter = AZ::RPI::PassFilter::CreateWithPassClass<AZ::RPI::RasterPass>();
|
||||
rasterPassFilter.SetOwnerScene(GetParentScene());
|
||||
AZ::RHI::RHISystemInterface* rhiSystem = AZ::RHI::RHISystemInterface::Get();
|
||||
AZ::RHI::DrawListTag forwardTag = rhiSystem->GetDrawListTagRegistry()->AcquireTag(AZ::Name("forward"));
|
||||
AZ::RPI::PassSystemInterface::Get()->ForEachPass(rasterPassFilter,
|
||||
[&](AZ::RPI::Pass* pass) -> AZ::RPI::PassFilterExecutionFlow
|
||||
{
|
||||
auto* rasterPass = azrtti_cast<AZ::RPI::RasterPass*>(pass);
|
||||
|
||||
if (rasterPass && rasterPass->GetDrawListTag() == forwardTag)
|
||||
{
|
||||
m_forwardPass = rasterPass;
|
||||
return AZ::RPI::PassFilterExecutionFlow::StopVisitingPasses;
|
||||
}
|
||||
return AZ::RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
auto TerrainFeatureProcessor::Vector2i::operator+(const Vector2i& rhs) const -> Vector2i
|
||||
{
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
#include <Atom/RPI.Public/MeshDrawPacket.h>
|
||||
#include <Atom/RPI.Public/Material/MaterialReloadNotificationBus.h>
|
||||
#include <Atom/RPI.Public/Shader/ShaderSystemInterface.h>
|
||||
#include <Atom/Feature/Utils/GpuBufferHandler.h>
|
||||
#include <Atom/Feature/Utils/IndexedDataVector.h>
|
||||
#include <Atom/Feature/Utils/SparseVector.h>
|
||||
|
||||
namespace AZ::RPI
|
||||
{
|
||||
@@ -29,6 +31,7 @@ namespace AZ::RPI
|
||||
}
|
||||
class Material;
|
||||
class Model;
|
||||
class RenderPass;
|
||||
class StreamingImage;
|
||||
}
|
||||
|
||||
@@ -125,17 +128,19 @@ namespace Terrain
|
||||
UseTextureHeight = 0b0000'0000'0000'0000'0000'0000'0010'0000,
|
||||
UseTextureSpecularF0 = 0b0000'0000'0000'0000'0000'0000'0100'0000,
|
||||
|
||||
FlipNormalX = 0b0000'0000'0000'0000'0000'0000'1000'0000,
|
||||
FlipNormalY = 0b0000'0000'0000'0000'0000'0001'0000'0000,
|
||||
FlipNormalX = 0b0000'0000'0000'0001'0000'0000'0000'0000,
|
||||
FlipNormalY = 0b0000'0000'0000'0010'0000'0000'0000'0000,
|
||||
|
||||
BlendModeMask = 0b0000'0000'0000'0000'0000'0110'0000'0000,
|
||||
BlendModeMask = 0b0000'0000'0000'1100'0000'0000'0000'0000,
|
||||
BlendModeLerp = 0b0000'0000'0000'0000'0000'0000'0000'0000,
|
||||
BlendModeLinearLight = 0b0000'0000'0000'0000'0000'0010'0000'0000,
|
||||
BlendModeMultiply = 0b0000'0000'0000'0000'0000'0100'0000'0000,
|
||||
BlendModeOverlay = 0b0000'0000'0000'0000'0000'0110'0000'0000,
|
||||
BlendModeLinearLight = 0b0000'0000'0000'0100'0000'0000'0000'0000,
|
||||
BlendModeMultiply = 0b0000'0000'0000'1000'0000'0000'0000'0000,
|
||||
BlendModeOverlay = 0b0000'0000'0000'1100'0000'0000'0000'0000,
|
||||
};
|
||||
|
||||
struct DetailMaterialShaderProperties
|
||||
static constexpr uint16_t InvalidDetailImageIndex = 0xFFFF;
|
||||
|
||||
struct DetailMaterialShaderData
|
||||
{
|
||||
// Uv
|
||||
AZStd::array<float, 12> m_uvTransform
|
||||
@@ -145,30 +150,50 @@ namespace Terrain
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
};
|
||||
|
||||
float m_baseColorRed{ 1.0f };
|
||||
float m_baseColorGreen{ 1.0f };
|
||||
float m_baseColorBlue{ 1.0f };
|
||||
|
||||
// Factor / Scale / Bias for input textures
|
||||
float m_baseColorFactor{ 1.0f };
|
||||
|
||||
float m_normalFactor{ 1.0f };
|
||||
float m_metalFactor{ 1.0f };
|
||||
float m_roughnessScale{ 1.0f };
|
||||
|
||||
float m_roughnessBias{ 0.0f };
|
||||
|
||||
float m_specularF0Factor{ 1.0f };
|
||||
float m_occlusionFactor{ 1.0f };
|
||||
float m_heightFactor{ 1.0f };
|
||||
|
||||
float m_heightOffset{ 0.0f };
|
||||
|
||||
float m_heightBlendFactor{ 0.5f };
|
||||
|
||||
// Flags
|
||||
DetailTextureFlags m_flags{ 0 };
|
||||
|
||||
float m_padding; // 16 byte aligned
|
||||
// Image indices
|
||||
uint16_t m_colorImageIndex{ InvalidDetailImageIndex };
|
||||
uint16_t m_normalImageIndex{ InvalidDetailImageIndex };
|
||||
uint16_t m_roughnessImageIndex{ InvalidDetailImageIndex };
|
||||
uint16_t m_metalnessImageIndex{ InvalidDetailImageIndex };
|
||||
|
||||
uint16_t m_specularF0ImageIndex{ InvalidDetailImageIndex };
|
||||
uint16_t m_occlusionImageIndex{ InvalidDetailImageIndex };
|
||||
uint16_t m_heightImageIndex{ InvalidDetailImageIndex };
|
||||
|
||||
// 16 byte aligned
|
||||
uint16_t m_padding1;
|
||||
uint32_t m_padding2;
|
||||
uint32_t m_padding3;
|
||||
};
|
||||
|
||||
struct DetailMaterialData
|
||||
{
|
||||
AZ::Data::AssetId m_assetId;
|
||||
AZ::RPI::Material::ChangeId m_materialChangeId{AZ::RPI::Material::DEFAULT_CHANGE_ID};
|
||||
uint32_t refCount = 0;
|
||||
uint16_t m_detailMaterialBufferIndex{ 0xFFFF };
|
||||
|
||||
AZ::Data::Instance<AZ::RPI::Image> m_colorImage;
|
||||
AZ::Data::Instance<AZ::RPI::Image> m_normalImage;
|
||||
@@ -177,8 +202,6 @@ namespace Terrain
|
||||
AZ::Data::Instance<AZ::RPI::Image> m_specularF0Image;
|
||||
AZ::Data::Instance<AZ::RPI::Image> m_occlusionImage;
|
||||
AZ::Data::Instance<AZ::RPI::Image> m_heightImage;
|
||||
|
||||
DetailMaterialShaderProperties m_properties; // maps directly to shader
|
||||
};
|
||||
|
||||
struct DetailMaterialSurface
|
||||
@@ -217,6 +240,12 @@ namespace Terrain
|
||||
Aabb2i GetClamped(Aabb2i rhs) const;
|
||||
bool IsValid() const;
|
||||
};
|
||||
|
||||
struct DetailTextureLocation
|
||||
{
|
||||
uint16_t m_index;
|
||||
AZ::Data::Instance<AZ::RPI::Image> m_image;
|
||||
};
|
||||
|
||||
// AZ::RPI::MaterialReloadNotificationBus::Handler overrides...
|
||||
void OnMaterialReinitialized(const MaterialInstance& material) override;
|
||||
@@ -237,6 +266,9 @@ namespace Terrain
|
||||
void OnTerrainSurfaceMaterialMappingChanged(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) override;
|
||||
void OnTerrainSurfaceMaterialMappingRegionChanged(AZ::EntityId entityId, const AZ::Aabb& oldRegion, const AZ::Aabb& newRegion) override;
|
||||
|
||||
// AZ::RPI::SceneNotificationBus overrides...
|
||||
void OnRenderPipelinePassesChanged(AZ::RPI::RenderPipeline* renderPipeline) override;
|
||||
|
||||
void Initialize();
|
||||
void InitializeTerrainPatch(uint16_t gridSize, float gridSpacing, PatchData& patchdata);
|
||||
bool InitializePatchModel();
|
||||
@@ -249,7 +281,8 @@ namespace Terrain
|
||||
void TerrainSurfaceDataUpdated(const AZ::Aabb& dirtyRegion);
|
||||
|
||||
uint16_t CreateOrUpdateDetailMaterial(MaterialInstance material);
|
||||
void UpdateDetailMaterialData(DetailMaterialData& materialData, MaterialInstance material);
|
||||
void CheckDetailMaterialForDeletion(uint16_t detailMaterialId);
|
||||
void UpdateDetailMaterialData(uint16_t detailMaterialIndex, MaterialInstance material);
|
||||
void CheckUpdateDetailTexture(const Aabb2i& newBounds, const Vector2i& newCenter);
|
||||
void UpdateDetailTexture(const Aabb2i& updateArea, const Aabb2i& textureBounds, const Vector2i& centerPixel);
|
||||
uint16_t GetDetailMaterialForSurfaceTypeAndPosition(AZ::Crc32 surfaceType, const AZ::Vector2& position);
|
||||
@@ -271,6 +304,8 @@ namespace Terrain
|
||||
AZ::Outcome<AZ::Data::Asset<AZ::RPI::BufferAsset>> CreateBufferAsset(
|
||||
const void* data, const AZ::RHI::BufferViewDescriptor& bufferViewDescriptor, const AZStd::string& bufferName);
|
||||
|
||||
void CacheForwardPass();
|
||||
|
||||
// System-level parameters
|
||||
static constexpr float GridSpacing{ 1.0f };
|
||||
static constexpr int32_t GridSize{ 64 }; // number of terrain quads (vertices are m_gridSize + 1)
|
||||
@@ -281,6 +316,7 @@ namespace Terrain
|
||||
|
||||
AZStd::unique_ptr<AZ::RPI::AssetUtils::AsyncAssetLoader> m_materialAssetLoader;
|
||||
MaterialInstance m_materialInstance;
|
||||
AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> m_terrainSrg;
|
||||
|
||||
AZ::RHI::ShaderInputConstantIndex m_modelToWorldIndex;
|
||||
AZ::RHI::ShaderInputConstantIndex m_terrainDataIndex;
|
||||
@@ -288,11 +324,13 @@ namespace Terrain
|
||||
AZ::RHI::ShaderInputConstantIndex m_macroMaterialCountIndex;
|
||||
AZ::RHI::ShaderInputImageIndex m_macroColorMapIndex;
|
||||
AZ::RHI::ShaderInputImageIndex m_macroNormalMapIndex;
|
||||
AZ::RPI::MaterialPropertyIndex m_heightmapPropertyIndex;
|
||||
AZ::RPI::MaterialPropertyIndex m_detailMaterialIdPropertyIndex;
|
||||
AZ::RPI::MaterialPropertyIndex m_detailCenterPropertyIndex;
|
||||
AZ::RPI::MaterialPropertyIndex m_detailAabbPropertyIndex;
|
||||
AZ::RPI::MaterialPropertyIndex m_detailHalfPixelUvPropertyIndex;
|
||||
AZ::RHI::ShaderInputImageIndex m_heightmapPropertyIndex;
|
||||
AZ::RHI::ShaderInputImageIndex m_detailMaterialIdPropertyIndex;
|
||||
AZ::RHI::ShaderInputBufferIndex m_detailMaterialDataIndex;
|
||||
AZ::RHI::ShaderInputConstantIndex m_detailCenterPropertyIndex;
|
||||
AZ::RHI::ShaderInputConstantIndex m_detailAabbPropertyIndex;
|
||||
AZ::RHI::ShaderInputConstantIndex m_detailHalfPixelUvPropertyIndex;
|
||||
AZ::RHI::ShaderInputImageUnboundedArrayIndex m_detailTexturesIndex;
|
||||
|
||||
AZ::Data::Instance<AZ::RPI::Model> m_patchModel;
|
||||
AZ::Vector3 m_previousCameraPosition = AZ::Vector3(AZStd::numeric_limits<float>::max(), 0.0, 0.0);
|
||||
@@ -312,17 +350,26 @@ namespace Terrain
|
||||
TerrainAreaData m_areaData;
|
||||
AZ::Aabb m_dirtyRegion{ AZ::Aabb::CreateNull() };
|
||||
AZ::Aabb m_dirtyDetailRegion{ AZ::Aabb::CreateNull() };
|
||||
bool m_updateDetailMaterialBuffer{ false };
|
||||
|
||||
Aabb2i m_detailTextureBounds;
|
||||
Vector2i m_detailTextureCenter;
|
||||
AZ::Data::Instance<AZ::RPI::AttachmentImage> m_detailTextureImage;
|
||||
AZ::RPI::ShaderSystemInterface::GlobalShaderOptionUpdatedEvent::Handler m_handleGlobalShaderOptionUpdate;
|
||||
bool m_forceRebuildDrawPackets = false;
|
||||
bool m_forceRebuildDrawPackets{ false };
|
||||
bool m_imagesNeedUpdate{ false };
|
||||
|
||||
AZStd::vector<SectorData> m_sectorData;
|
||||
|
||||
AZ::Render::IndexedDataVector<MacroMaterialData> m_macroMaterials;
|
||||
AZ::Render::IndexedDataVector<DetailMaterialData> m_detailMaterials;
|
||||
AZ::Render::IndexedDataVector<DetailMaterialListRegion> m_detailMaterialRegions;
|
||||
AZ::Render::SparseVector<DetailMaterialShaderData> m_detailMaterialShaderData;
|
||||
AZ::Render::GpuBufferHandler m_detailMaterialDataBuffer;
|
||||
AZ::RPI::RenderPass* m_forwardPass;
|
||||
|
||||
AZStd::vector<const AZ::RHI::ImageView*> m_detailImageViews;
|
||||
AZStd::vector<uint16_t> m_detailImageViewFreeList;
|
||||
bool m_detailImagesNeedUpdate{ false };
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <${Name}ModuleInterface.h>
|
||||
#include <${Name}EditorSystemComponent.h>
|
||||
#include <AzToolsFramework/API/PythonLoader.h>
|
||||
|
||||
void Init${SanitizedCppName}Resources()
|
||||
{
|
||||
@@ -21,6 +22,7 @@ namespace ${SanitizedCppName}
|
||||
{
|
||||
class ${SanitizedCppName}EditorModule
|
||||
: public ${SanitizedCppName}ModuleInterface
|
||||
, public AzToolsFramework::EmbeddedPython::PythonLoader
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(${SanitizedCppName}EditorModule, "${ModuleClassId}", ${SanitizedCppName}ModuleInterface);
|
||||
|
||||
@@ -43,6 +43,6 @@ ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-linux
|
||||
ly_associate_package(PACKAGE_NAME azslc-1.7.34-rev1-linux TARGETS azslc PACKAGE_HASH 6d7dc671936c34ff70d2632196107ca1b8b2b41acdd021bfbc69a9fd56215c22)
|
||||
ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev5-linux TARGETS ZLIB PACKAGE_HASH 9be5ea85722fc27a8645a9c8a812669d107c68e6baa2ca0740872eaeb6a8b0fc)
|
||||
ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-linux TARGETS squish-ccr PACKAGE_HASH 85fecafbddc6a41a27c5f59ed4a5dfb123a94cb4666782cf26e63c0a4724c530)
|
||||
ly_associate_package(PACKAGE_NAME astc-encoder-3.2-rev1-linux TARGETS astc-encoder PACKAGE_HASH 2ba97a06474d609945f0ab4419af1f6bbffdd294ca6b869f5fcebec75c573c0f)
|
||||
ly_associate_package(PACKAGE_NAME astc-encoder-3.2-rev2-linux TARGETS astc-encoder PACKAGE_HASH 71549d1ca9e4d48391b92a89ea23656d3393810e6777879f6f8a9def2db1610c)
|
||||
ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-linux TARGETS ISPCTexComp PACKAGE_HASH 065fd12abe4247dde247330313763cf816c3375c221da030bdec35024947f259)
|
||||
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-linux TARGETS lz4 PACKAGE_HASH 5de3dbd3e2a3537c6555d759b3c5bb98e5456cf85c74ff6d046f809b7087290d)
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ ly_associate_package(PACKAGE_NAME libpng-1.6.37-mac
|
||||
ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-mac TARGETS libsamplerate PACKAGE_HASH b912af40c0ac197af9c43d85004395ba92a6a859a24b7eacd920fed5854a97fe)
|
||||
ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev5-mac TARGETS ZLIB PACKAGE_HASH b6fea9c79b8bf106d4703b67fecaa133f832ad28696c2ceef45fb5f20013c096)
|
||||
ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-mac TARGETS squish-ccr PACKAGE_HASH 155bfbfa17c19a9cd2ef025de14c5db598f4290045d5b0d83ab58cb345089a77)
|
||||
ly_associate_package(PACKAGE_NAME astc-encoder-3.2-rev1-mac TARGETS astc-encoder PACKAGE_HASH 96f6ea8c3e45ec7fe525230c7c53ca665c8300d8e28456cc19bb3159ce6f8dcc)
|
||||
ly_associate_package(PACKAGE_NAME astc-encoder-3.2-rev2-mac TARGETS astc-encoder PACKAGE_HASH 06f129d26995845824f1fb906a5135b2c71d44d66c768342af85fa28a175906f)
|
||||
ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-mac TARGETS ISPCTexComp PACKAGE_HASH 8a4e93277b8face6ea2fd57c6d017bdb55643ed3d6387110bc5f6b3b884dd169)
|
||||
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-mac TARGETS lz4 PACKAGE_HASH 891ff630bf34f7ab1d8eaee2ea0a8f1fca89dbdc63fca41ee592703dd488a73b)
|
||||
ly_associate_package(PACKAGE_NAME azslc-1.7.34-rev1-mac TARGETS azslc PACKAGE_HASH a9d81946b42ffa55c0d14d6a9249b3340e59a8fb8835e7a96c31df80f14723bc)
|
||||
|
||||
@@ -46,7 +46,7 @@ ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev2-windows
|
||||
ly_associate_package(PACKAGE_NAME Crashpad-0.8.0-rev1-windows TARGETS Crashpad PACKAGE_HASH d162aa3070147bc0130a44caab02c5fe58606910252caf7f90472bd48d4e31e2)
|
||||
ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev5-windows TARGETS ZLIB PACKAGE_HASH 8847112429744eb11d92c44026fc5fc53caa4a06709382b5f13978f3c26c4cbd)
|
||||
ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-windows TARGETS squish-ccr PACKAGE_HASH 5c3d9fa491e488ccaf802304ad23b932268a2b2846e383f088779962af2bfa84)
|
||||
ly_associate_package(PACKAGE_NAME astc-encoder-3.2-rev1-windows TARGETS astc-encoder PACKAGE_HASH 3addc6fc1a7eb0d6b7f3d530e962af967e6d92b3825ef485da243346357cf78e)
|
||||
ly_associate_package(PACKAGE_NAME astc-encoder-3.2-rev2-windows TARGETS astc-encoder PACKAGE_HASH 17249bfa438afb34e21449865d9c9297471174ae0cea9b2f9def2ee206038295)
|
||||
ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-windows TARGETS ISPCTexComp PACKAGE_HASH b6fa6ea28a2808a9a5524c72c37789c525925e435770f2d94eb2d387360fa2d0)
|
||||
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-windows TARGETS lz4 PACKAGE_HASH 4ea457b833cd8cfaf8e8e06ed6df601d3e6783b606bdbc44a677f77e19e0db16)
|
||||
ly_associate_package(PACKAGE_NAME azslc-1.7.34-rev1-windows TARGETS azslc PACKAGE_HASH 44eb2e0fc4b0f1c75d0fb6f24c93a5753655b84dbc3e6ad45389ed3b9cf7a4b0)
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
"CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-12 -DCMAKE_CXX_COMPILER=clang++-12 -DLY_PARALLEL_LINK_JOBS=4",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "all",
|
||||
"CTEST_OPTIONS": "-E (AutomatedTesting::Atom_TestSuite_Main|AutomatedTesting::PhysicsTests_Main|AutomatedTesting::PrefabTests|AutomatedTesting::TerrainTests_Main|Gem::EMotionFX.Editor.Tests) -L (SUITE_smoke|SUITE_main) -LE (REQUIRES_gpu) --no-tests=error",
|
||||
"CTEST_OPTIONS": "-E (AutomatedTesting::Atom_TestSuite_Main|AutomatedTesting::PrefabTests|AutomatedTesting::TerrainTests_Main|Gem::EMotionFX.Editor.Tests) -L (SUITE_smoke|SUITE_main) -LE (REQUIRES_gpu) --no-tests=error",
|
||||
"TEST_RESULTS": "True"
|
||||
}
|
||||
},
|
||||
@@ -96,7 +96,7 @@
|
||||
"CMAKE_OPTIONS": "-G 'Ninja Multi-Config' -DCMAKE_C_COMPILER=clang-12 -DCMAKE_CXX_COMPILER=clang++-12 -DLY_UNITY_BUILD=FALSE -DLY_PARALLEL_LINK_JOBS=4",
|
||||
"CMAKE_LY_PROJECTS": "AutomatedTesting",
|
||||
"CMAKE_TARGET": "all",
|
||||
"CTEST_OPTIONS": "-E (AutomatedTesting::Atom_TestSuite_Main|AutomatedTesting::PhysicsTests_Main|AutomatedTesting::PrefabTests|AutomatedTesting::TerrainTests_Main|Gem::EMotionFX.Editor.Tests) -L (SUITE_smoke|SUITE_main) -LE (REQUIRES_gpu) --no-tests=error",
|
||||
"CTEST_OPTIONS": "-E (AutomatedTesting::Atom_TestSuite_Main|AutomatedTesting::PrefabTests|AutomatedTesting::TerrainTests_Main|Gem::EMotionFX.Editor.Tests) -L (SUITE_smoke|SUITE_main) -LE (REQUIRES_gpu) --no-tests=error",
|
||||
"TEST_RESULTS": "True"
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user