Merge branch 'main' into MultiplayerPipeline

This commit is contained in:
pereslav
2021-04-27 21:23:22 +01:00
547 changed files with 12849 additions and 46765 deletions
@@ -15,9 +15,9 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from ActorSplitsAfterDamage import Tests
def run():
from ActorSplitsAfterDamage import run as internal_run
from editor_python_test_tools.utils import Constants
def ActorSplitsAfterCapsuleDamage():
from ActorSplitsAfterDamage import base_run as internal_run
from BlastUtils import Constants
def CapsuleDamage(target_id, position0):
position1 = azlmbr.object.construct('Vector3', position0.x + 1.0, position0.y, position0.z)
@@ -30,4 +30,8 @@ def run():
if __name__ == "__main__":
run()
import ImportPathHelper as imports
imports.init()
from editor_python_test_tools.utils import Report
Report.start_test(ActorSplitsAfterCapsuleDamage)
@@ -22,7 +22,7 @@ class Tests():
# fmt: on
def run():
def ActorSplitsAfterCollision():
"""
Summary:
@@ -60,8 +60,8 @@ def run():
import azlmbr.legacy.general as general
import azlmbr.bus
from editor_python_test_tools.utils import CollisionHandler
from editor_python_test_tools.utils import BlastNotificationHandler
from BlastUtils import CollisionHandler
from BlastUtils import BlastNotificationHandler
# Constants
TIMEOUT = 2.0
@@ -107,4 +107,8 @@ def run():
if __name__ == "__main__":
run()
import ImportPathHelper as imports
imports.init()
from editor_python_test_tools.utils import Report
Report.start_test(ActorSplitsAfterCollision)
@@ -20,7 +20,7 @@ class Tests():
# fmt: on
def run(damage_func):
def base_run(damage_func):
"""
Summary:
@@ -56,7 +56,7 @@ def run(damage_func):
import azlmbr.legacy.general as general
import azlmbr.bus
from editor_python_test_tools.utils import BlastNotificationHandler
from BlastUtils import BlastNotificationHandler
# Constants
TIMEOUT = 2.0
@@ -15,9 +15,9 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from ActorSplitsAfterDamage import Tests
def run():
from ActorSplitsAfterDamage import run as internal_run
from editor_python_test_tools.utils import Constants
def ActorSplitsAfterImpactSpreadDamage():
from ActorSplitsAfterDamage import base_run as internal_run
from BlastUtils import Constants
def ImpactSpreadDamage(target_id, position):
azlmbr.destruction.BlastFamilyDamageRequestBus(azlmbr.bus.Event, "Impact Spread Damage", target_id,
@@ -28,4 +28,8 @@ def run():
if __name__ == "__main__":
run()
import ImportPathHelper as imports
imports.init()
from editor_python_test_tools.utils import Report
Report.start_test(ActorSplitsAfterImpactSpreadDamage)
@@ -15,9 +15,9 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from ActorSplitsAfterDamage import Tests
def run():
from ActorSplitsAfterDamage import run as internal_run
from editor_python_test_tools.utils import Constants
def ActorSplitsAfterRadialDamage():
from ActorSplitsAfterDamage import base_run as internal_run
from BlastUtils import Constants
def RadialDamage(target_id, position):
azlmbr.destruction.BlastFamilyDamageRequestBus(azlmbr.bus.Event, "Radial Damage", target_id,
@@ -28,4 +28,8 @@ def run():
if __name__ == "__main__":
run()
import ImportPathHelper as imports
imports.init()
from editor_python_test_tools.utils import Report
Report.start_test(ActorSplitsAfterRadialDamage)
@@ -15,9 +15,9 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from ActorSplitsAfterDamage import Tests
def run():
from ActorSplitsAfterDamage import run as internal_run
from editor_python_test_tools.utils import Constants
def ActorSplitsAfterShearDamage():
from ActorSplitsAfterDamage import base_run as internal_run
from BlastUtils import Constants
def ShearDamage(target_id, position):
normal = azlmbr.object.construct('Vector3', 1.0, 0.0, 0.0)
@@ -29,4 +29,8 @@ def run():
if __name__ == "__main__":
run()
import ImportPathHelper as imports
imports.init()
from editor_python_test_tools.utils import Report
Report.start_test(ActorSplitsAfterShearDamage)
@@ -15,9 +15,9 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from ActorSplitsAfterDamage import Tests
def run():
from ActorSplitsAfterDamage import run as internal_run
from editor_python_test_tools.utils import Constants
def ActorSplitsAfterStressDamage():
from ActorSplitsAfterDamage import base_run as internal_run
from BlastUtils import Constants
def StressDamage(target_id, position):
force = azlmbr.object.construct('Vector3', 0.0, 0.0, -100.0) # Should be enough to break `brittle` objects
@@ -28,4 +28,8 @@ def run():
if __name__ == "__main__":
run()
import ImportPathHelper as imports
imports.init()
from editor_python_test_tools.utils import Report
Report.start_test(ActorSplitsAfterStressDamage)
@@ -15,9 +15,9 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from ActorSplitsAfterDamage import Tests
def run():
from ActorSplitsAfterDamage import run as internal_run
from editor_python_test_tools.utils import Constants
def ActorSplitsAfterTriangleDamage():
from ActorSplitsAfterDamage import base_run as internal_run
from BlastUtils import Constants
def TriangleDamage(target_id, position):
# Some points that form a triangle that contains the given position
@@ -32,4 +32,8 @@ def run():
if __name__ == "__main__":
run()
import ImportPathHelper as imports
imports.init()
from editor_python_test_tools.utils import Report
Report.start_test(ActorSplitsAfterTriangleDamage)
@@ -170,7 +170,7 @@ endif()
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_pytest(
NAME AutomatedTesting::BlastTests
TEST_SUITE periodic
TEST_SUITE main
TEST_SERIAL TRUE
PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py
TIMEOUT 3600
@@ -178,6 +178,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
Legacy::Editor
AZ::AssetProcessor
AutomatedTesting.Assets
COMPONENT Blast
)
endif()
@@ -7,25 +7,10 @@ distribution (the "License"). All use of this software is governed by the Licens
or, if provided, by the license below or the license accompanying this file. Do not
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Hydra script that creates an entity and attaches Atom components to it for test verification.
"""
# This module does a bulk test and update of many components at once.
# Each test case is listed below in the format:
# "Test Case ID: Test Case Title (URL)"
# C32078130: Tone Mapper (https://testrail.agscollab.com/index.php?/cases/view/32078130)
# C32078129: Light (https://testrail.agscollab.com/index.php?/cases/view/32078129)
# C32078131: Radius Weight Modifier (https://testrail.agscollab.com/index.php?/cases/view/32078131)
# C32078127: PostFX Layer (https://testrail.agscollab.com/index.php?/cases/view/32078127)
# C32078126: Point Light (https://testrail.agscollab.com/index.php?/cases/view/32078126)
# C32078125: Physical Sky (https://testrail.agscollab.com/index.php?/cases/view/32078125)
# C32078115: Global Skylight (IBL) (https://testrail.agscollab.com/index.php?/cases/view/32078115)
# C32078121: Exposure Control (https://testrail.agscollab.com/index.php?/cases/view/32078121)
# C32078120: Directional Light (https://testrail.agscollab.com/index.php?/cases/view/32078120)
# C32078119: DepthOfField (https://testrail.agscollab.com/index.php?/cases/view/32078119)
# C32078118: Decal (https://testrail.agscollab.com/index.php?/cases/view/32078118)
# C32078117: Area Light (https://testrail.agscollab.com/index.php?/cases/view/32078117)
import os
import sys
@@ -41,10 +26,6 @@ sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "P
import editor_python_test_tools.hydra_editor_utils as hydra
from editor_python_test_tools.utils import TestHelper
from editor_python_test_tools.editor_test_helper import EditorTestHelper
EditorTestHelper = EditorTestHelper(log_prefix="AtomEditorComponents")
def run():
@@ -151,28 +132,6 @@ def run():
# Wait for Editor idle loop before executing Python hydra scripts.
TestHelper.init_idle()
# Create a new level.
new_level_name = "tmp_level" # Specified in TestAllComponentsBasicTests.py
heightmap_resolution = 512
heightmap_meters_per_pixel = 1
terrain_texture_resolution = 412
use_terrain = False
# Return codes are ECreateLevelResult defined in CryEdit.h
return_code = general.create_level_no_prompt(
new_level_name, heightmap_resolution, heightmap_meters_per_pixel, terrain_texture_resolution, use_terrain)
if return_code == 1:
general.log(f"{new_level_name} level already exists")
elif return_code == 2:
general.log("Failed to create directory")
elif return_code == 3:
general.log("Directory length is too long")
elif return_code != 0:
general.log("Unknown error, failed to create level")
else:
general.log(f"{new_level_name} level created successfully")
EditorTestHelper.after_level_load(bypass_viewport_resize=True)
# Delete all existing entities initially
search_filter = azlmbr.entity.SearchFilter()
all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter)
@@ -209,7 +168,7 @@ def run():
entity_obj, ["Capsule Shape"], area_light))
# Decal Component
material_asset_path = os.path.join("Materials", "decal", "aiirship_nose_number_decal.material")
material_asset_path = os.path.join("Materials", "basic_grey.material")
material_asset = asset.AssetCatalogRequestBus(
bus.Broadcast, "GetAssetIdByPath", material_asset_path, math.Uuid(), False)
ComponentTests(
@@ -263,9 +222,12 @@ def run():
# Radius Weight Modifier Component
ComponentTests("Radius Weight Modifier")
# Spot Light Component
# Light Component
ComponentTests("Light")
# Display Mapper Component
ComponentTests("Display Mapper")
if __name__ == "__main__":
run()
@@ -13,32 +13,207 @@ import logging
import os
import pytest
import ly_test_tools.environment.file_system as file_system
import editor_python_test_tools.hydra_test_utils as hydra
logger = logging.getLogger(__name__)
EDITOR_TIMEOUT = 60
EDITOR_TIMEOUT = 120
TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts")
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("level", ["tmp_level"])
@pytest.mark.parametrize("level", ["auto_test"])
class TestAtomEditorComponents(object):
@pytest.fixture(autouse=True)
def setup_teardown(self, request, workspace, project, level):
# Cleanup our temp level
file_system.delete(
[os.path.join(workspace.paths.engine_root(), project, "Levels", "AtomLevels", level)], True, True)
def teardown():
# Cleanup our temp level
file_system.delete(
[os.path.join(workspace.paths.engine_root(), project, "Levels", "AtomLevels", level)], True, True)
request.addfinalizer(teardown)
@pytest.mark.test_case_id(
"C32078117", # Area Light
"C32078130", # Display Mapper
"C32078129", # Light
"C32078131", # Radius Weight Modifier
"C32078127", # PostFX Layer
"C32078126", # Point Light
"C32078125", # Physical Sky
"C32078115", # Global Skylight (IBL)
"C32078121", # Exposure Control
"C32078120", # Directional Light
"C32078119", # DepthOfField
"C32078118") # Decal
def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform):
cfg_args = [level]
# It requires at least one test
def test_Dummy(self, request, editor, level, workspace, project, launcher_platform):
pass
expected_lines = [
# Area Light Component
"Area Light Entity successfully created",
"Area Light_test: Component added to the entity: True",
"Area Light_test: Component removed after UNDO: True",
"Area Light_test: Component added after REDO: True",
"Area Light_test: Entered game mode: True",
"Area Light_test: Entity enabled after adding required components: True",
"Area Light_test: Entity is hidden: True",
"Area Light_test: Entity is shown: True",
"Area Light_test: Entity deleted: True",
"Area Light_test: UNDO entity deletion works: True",
"Area Light_test: REDO entity deletion works: True",
# Decal Component
"Decal Entity successfully created",
"Decal_test: Component added to the entity: True",
"Decal_test: Component removed after UNDO: True",
"Decal_test: Component added after REDO: True",
"Decal_test: Entered game mode: True",
"Decal_test: Exit game mode: True",
"Decal Settings|Decal Settings|Material: SUCCESS",
"Decal_test: Entity is hidden: True",
"Decal_test: Entity is shown: True",
"Decal_test: Entity deleted: True",
"Decal_test: UNDO entity deletion works: True",
"Decal_test: REDO entity deletion works: True",
# DepthOfField Component
"DepthOfField Entity successfully created",
"DepthOfField_test: Component added to the entity: True",
"DepthOfField_test: Component removed after UNDO: True",
"DepthOfField_test: Component added after REDO: True",
"DepthOfField_test: Entered game mode: True",
"DepthOfField_test: Exit game mode: True",
"DepthOfField_test: Entity disabled initially: True",
"DepthOfField_test: Entity enabled after adding required components: True",
"DepthOfField Controller|Configuration|Camera Entity: SUCCESS",
"DepthOfField_test: Entity is hidden: True",
"DepthOfField_test: Entity is shown: True",
"DepthOfField_test: Entity deleted: True",
"DepthOfField_test: UNDO entity deletion works: True",
"DepthOfField_test: REDO entity deletion works: True",
# Directional Light Component
"Directional Light Entity successfully created",
"Directional Light_test: Component added to the entity: True",
"Directional Light_test: Component removed after UNDO: True",
"Directional Light_test: Component added after REDO: True",
"Directional Light_test: Entered game mode: True",
"Directional Light_test: Exit game mode: True",
"Directional Light Controller|Configuration|Shadow|Camera: SUCCESS",
"Directional Light_test: Entity is hidden: True",
"Directional Light_test: Entity is shown: True",
"Directional Light_test: Entity deleted: True",
"Directional Light_test: UNDO entity deletion works: True",
"Directional Light_test: REDO entity deletion works: True",
# Exposure Control Component
"Exposure Control Entity successfully created",
"Exposure Control_test: Component added to the entity: True",
"Exposure Control_test: Component removed after UNDO: True",
"Exposure Control_test: Component added after REDO: True",
"Exposure Control_test: Entered game mode: True",
"Exposure Control_test: Exit game mode: True",
"Exposure Control_test: Entity disabled initially: True",
"Exposure Control_test: Entity enabled after adding required components: True",
"Exposure Control_test: Entity is hidden: True",
"Exposure Control_test: Entity is shown: True",
"Exposure Control_test: Entity deleted: True",
"Exposure Control_test: UNDO entity deletion works: True",
"Exposure Control_test: REDO entity deletion works: True",
# Global Skylight (IBL) Component
"Global Skylight (IBL) Entity successfully created",
"Global Skylight (IBL)_test: Component added to the entity: True",
"Global Skylight (IBL)_test: Component removed after UNDO: True",
"Global Skylight (IBL)_test: Component added after REDO: True",
"Global Skylight (IBL)_test: Entered game mode: True",
"Global Skylight (IBL)_test: Exit game mode: True",
"Global Skylight (IBL) Controller|Configuration|Diffuse Image: SUCCESS",
"Global Skylight (IBL) Controller|Configuration|Specular Image: SUCCESS",
"Global Skylight (IBL)_test: Entity is hidden: True",
"Global Skylight (IBL)_test: Entity is shown: True",
"Global Skylight (IBL)_test: Entity deleted: True",
"Global Skylight (IBL)_test: UNDO entity deletion works: True",
"Global Skylight (IBL)_test: REDO entity deletion works: True",
# Physical Sky Component
"Physical Sky Entity successfully created",
"Physical Sky component was added to entity",
"Entity has a Physical Sky component",
"Physical Sky_test: Component added to the entity: True",
"Physical Sky_test: Component removed after UNDO: True",
"Physical Sky_test: Component added after REDO: True",
"Physical Sky_test: Entered game mode: True",
"Physical Sky_test: Exit game mode: True",
"Physical Sky_test: Entity is hidden: True",
"Physical Sky_test: Entity is shown: True",
"Physical Sky_test: Entity deleted: True",
"Physical Sky_test: UNDO entity deletion works: True",
"Physical Sky_test: REDO entity deletion works: True",
# Point Light Component
"Point Light Entity successfully created",
"Point Light_test: Component added to the entity: True",
"Point Light_test: Component removed after UNDO: True",
"Point Light_test: Component added after REDO: True",
"Point Light_test: Entered game mode: True",
"Point Light_test: Exit game mode: True",
"Point Light_test: Entity is hidden: True",
"Point Light_test: Entity is shown: True",
"Point Light_test: Entity deleted: True",
"Point Light_test: UNDO entity deletion works: True",
"Point Light_test: REDO entity deletion works: True",
# PostFX Layer Component
"PostFX Layer Entity successfully created",
"PostFX Layer_test: Component added to the entity: True",
"PostFX Layer_test: Component removed after UNDO: True",
"PostFX Layer_test: Component added after REDO: True",
"PostFX Layer_test: Entered game mode: True",
"PostFX Layer_test: Exit game mode: True",
"PostFX Layer_test: Entity is hidden: True",
"PostFX Layer_test: Entity is shown: True",
"PostFX Layer_test: Entity deleted: True",
"PostFX Layer_test: UNDO entity deletion works: True",
"PostFX Layer_test: REDO entity deletion works: True",
# Radius Weight Modifier Component
"Radius Weight Modifier Entity successfully created",
"Radius Weight Modifier_test: Component added to the entity: True",
"Radius Weight Modifier_test: Component removed after UNDO: True",
"Radius Weight Modifier_test: Component added after REDO: True",
"Radius Weight Modifier_test: Entered game mode: True",
"Radius Weight Modifier_test: Exit game mode: True",
"Radius Weight Modifier_test: Entity is hidden: True",
"Radius Weight Modifier_test: Entity is shown: True",
"Radius Weight Modifier_test: Entity deleted: True",
"Radius Weight Modifier_test: UNDO entity deletion works: True",
"Radius Weight Modifier_test: REDO entity deletion works: True",
# Light Component
"Light Entity successfully created",
"Light_test: Component added to the entity: True",
"Light_test: Component removed after UNDO: True",
"Light_test: Component added after REDO: True",
"Light_test: Entered game mode: True",
"Light_test: Exit game mode: True",
"Light_test: Entity is hidden: True",
"Light_test: Entity is shown: True",
"Light_test: Entity deleted: True",
"Light_test: UNDO entity deletion works: True",
"Light_test: REDO entity deletion works: True",
# Display Mapper Component
"Display Mapper Entity successfully created",
"Display Mapper_test: Component added to the entity: True",
"Display Mapper_test: Component removed after UNDO: True",
"Display Mapper_test: Component added after REDO: True",
"Display Mapper_test: Entered game mode: True",
"Display Mapper_test: Exit game mode: True",
"Display Mapper_test: Entity is hidden: True",
"Display Mapper_test: Entity is shown: True",
"Display Mapper_test: Entity deleted: True",
"Display Mapper_test: UNDO entity deletion works: True",
"Display Mapper_test: REDO entity deletion works: True",
]
unexpected_lines = [
"failed to open",
"Traceback (most recent call last):",
]
hydra.launch_and_validate_results(
request,
TEST_DIRECTORY,
editor,
"hydra_AtomEditorComponents_AddedToEntity.py",
timeout=EDITOR_TIMEOUT,
expected_lines=expected_lines,
unexpected_lines=unexpected_lines,
halt_on_unexpected=True,
null_renderer=True,
cfg_args=cfg_args,
)
@@ -9,211 +9,14 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
"""
import logging
import os
import pytest
import ly_test_tools.environment.file_system as file_system
import editor_python_test_tools.hydra_test_utils as hydra
logger = logging.getLogger(__name__)
EDITOR_TIMEOUT = 60
TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts")
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
@pytest.mark.parametrize("level", ["tmp_level"])
@pytest.mark.parametrize("level", ["auto_test"])
class TestAtomEditorComponents(object):
@pytest.fixture(autouse=True)
def setup_teardown(self, request, workspace, project, level):
# Cleanup our temp level
file_system.delete(
[os.path.join(workspace.paths.engine_root(), project, "Levels", "AtomLevels", level)], True, True)
def teardown():
# Cleanup our temp level
file_system.delete(
[os.path.join(workspace.paths.engine_root(), project, "Levels", "AtomLevels", level)], True, True)
request.addfinalizer(teardown)
@pytest.mark.test_case_id(
"C32078130", # Tone Mapper
"C32078129", # Light
"C32078131", # Radius Weight Modifier
"C32078127", # PostFX Layer
"C32078126", # Point Light
"C32078125", # Physical Sky
"C32078115", # Global Skylight (IBL)
"C32078121", # Exposure Control
"C32078120", # Directional Light
"C32078119", # DepthOfField
"C32078118") # Decal
def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform):
cfg_args = [level]
expected_lines = [
# Area Light Component
"Area Light Entity successfully created",
"Area Light_test: Component added to the entity: True",
"Area Light_test: Component removed after UNDO: True",
"Area Light_test: Component added after REDO: True",
"Area Light_test: Entered game mode: True",
"Area Light_test: Entity enabled after adding required components: True",
"Area Light_test: Entity is hidden: True",
"Area Light_test: Entity is shown: True",
"Area Light_test: Entity deleted: True",
"Area Light_test: UNDO entity deletion works: True",
"Area Light_test: REDO entity deletion works: True",
# Decal Component
"Decal Entity successfully created",
"Decal_test: Component added to the entity: True",
"Decal_test: Component removed after UNDO: True",
"Decal_test: Component added after REDO: True",
"Decal_test: Entered game mode: True",
"Decal_test: Exit game mode: True",
"Decal Settings|Decal Settings|Material: SUCCESS",
"Decal_test: Entity is hidden: True",
"Decal_test: Entity is shown: True",
"Decal_test: Entity deleted: True",
"Decal_test: UNDO entity deletion works: True",
"Decal_test: REDO entity deletion works: True",
# DepthOfField Component
"DepthOfField Entity successfully created",
"DepthOfField_test: Component added to the entity: True",
"DepthOfField_test: Component removed after UNDO: True",
"DepthOfField_test: Component added after REDO: True",
"DepthOfField_test: Entered game mode: True",
"DepthOfField_test: Exit game mode: True",
"DepthOfField_test: Entity disabled initially: True",
"DepthOfField_test: Entity enabled after adding required components: True",
"DepthOfField Controller|Configuration|Camera Entity: SUCCESS",
"DepthOfField_test: Entity is hidden: True",
"DepthOfField_test: Entity is shown: True",
"DepthOfField_test: Entity deleted: True",
"DepthOfField_test: UNDO entity deletion works: True",
"DepthOfField_test: REDO entity deletion works: True",
# Directional Light Component
"Directional Light Entity successfully created",
"Directional Light_test: Component added to the entity: True",
"Directional Light_test: Component removed after UNDO: True",
"Directional Light_test: Component added after REDO: True",
"Directional Light_test: Entered game mode: True",
"Directional Light_test: Exit game mode: True",
"Directional Light Controller|Configuration|Shadow|Camera: SUCCESS",
"Directional Light_test: Entity is hidden: True",
"Directional Light_test: Entity is shown: True",
"Directional Light_test: Entity deleted: True",
"Directional Light_test: UNDO entity deletion works: True",
"Directional Light_test: REDO entity deletion works: True",
# Exposure Control Component
"Exposure Control Entity successfully created",
"Exposure Control_test: Component added to the entity: True",
"Exposure Control_test: Component removed after UNDO: True",
"Exposure Control_test: Component added after REDO: True",
"Exposure Control_test: Entered game mode: True",
"Exposure Control_test: Exit game mode: True",
"Exposure Control_test: Entity disabled initially: True",
"Exposure Control_test: Entity enabled after adding required components: True",
"Exposure Control_test: Entity is hidden: True",
"Exposure Control_test: Entity is shown: True",
"Exposure Control_test: Entity deleted: True",
"Exposure Control_test: UNDO entity deletion works: True",
"Exposure Control_test: REDO entity deletion works: True",
# Global Skylight (IBL) Component
"Global Skylight (IBL) Entity successfully created",
"Global Skylight (IBL)_test: Component added to the entity: True",
"Global Skylight (IBL)_test: Component removed after UNDO: True",
"Global Skylight (IBL)_test: Component added after REDO: True",
"Global Skylight (IBL)_test: Entered game mode: True",
"Global Skylight (IBL)_test: Exit game mode: True",
"Global Skylight (IBL) Controller|Configuration|Diffuse Image: SUCCESS",
"Global Skylight (IBL) Controller|Configuration|Specular Image: SUCCESS",
"Global Skylight (IBL)_test: Entity is hidden: True",
"Global Skylight (IBL)_test: Entity is shown: True",
"Global Skylight (IBL)_test: Entity deleted: True",
"Global Skylight (IBL)_test: UNDO entity deletion works: True",
"Global Skylight (IBL)_test: REDO entity deletion works: True",
# Physical Sky Component
"Physical Sky Entity successfully created",
"Physical Sky component was added to entity",
"Entity has a Physical Sky component",
"Physical Sky_test: Component added to the entity: True",
"Physical Sky_test: Component removed after UNDO: True",
"Physical Sky_test: Component added after REDO: True",
"Physical Sky_test: Entered game mode: True",
"Physical Sky_test: Exit game mode: True",
"Physical Sky_test: Entity is hidden: True",
"Physical Sky_test: Entity is shown: True",
"Physical Sky_test: Entity deleted: True",
"Physical Sky_test: UNDO entity deletion works: True",
"Physical Sky_test: REDO entity deletion works: True",
# Point Light Component
"Point Light Entity successfully created",
"Point Light_test: Component added to the entity: True",
"Point Light_test: Component removed after UNDO: True",
"Point Light_test: Component added after REDO: True",
"Point Light_test: Entered game mode: True",
"Point Light_test: Exit game mode: True",
"Point Light_test: Entity is hidden: True",
"Point Light_test: Entity is shown: True",
"Point Light_test: Entity deleted: True",
"Point Light_test: UNDO entity deletion works: True",
"Point Light_test: REDO entity deletion works: True",
# PostFX Layer Component
"PostFX Layer Entity successfully created",
"PostFX Layer_test: Component added to the entity: True",
"PostFX Layer_test: Component removed after UNDO: True",
"PostFX Layer_test: Component added after REDO: True",
"PostFX Layer_test: Entered game mode: True",
"PostFX Layer_test: Exit game mode: True",
"PostFX Layer_test: Entity is hidden: True",
"PostFX Layer_test: Entity is shown: True",
"PostFX Layer_test: Entity deleted: True",
"PostFX Layer_test: UNDO entity deletion works: True",
"PostFX Layer_test: REDO entity deletion works: True",
# Radius Weight Modifier Component
"Radius Weight Modifier Entity successfully created",
"Radius Weight Modifier_test: Component added to the entity: True",
"Radius Weight Modifier_test: Component removed after UNDO: True",
"Radius Weight Modifier_test: Component added after REDO: True",
"Radius Weight Modifier_test: Entered game mode: True",
"Radius Weight Modifier_test: Exit game mode: True",
"Radius Weight Modifier_test: Entity is hidden: True",
"Radius Weight Modifier_test: Entity is shown: True",
"Radius Weight Modifier_test: Entity deleted: True",
"Radius Weight Modifier_test: UNDO entity deletion works: True",
"Radius Weight Modifier_test: REDO entity deletion works: True",
# Light Component
"Light Entity successfully created",
"Light_test: Component added to the entity: True",
"Light_test: Component removed after UNDO: True",
"Light_test: Component added after REDO: True",
"Light_test: Entered game mode: True",
"Light_test: Exit game mode: True",
"Light_test: Entity is hidden: True",
"Light_test: Entity is shown: True",
"Light_test: Entity deleted: True",
"Light_test: UNDO entity deletion works: True",
"Light_test: REDO entity deletion works: True",
]
unexpected_lines = [
"failed to open",
"Traceback (most recent call last):",
]
hydra.launch_and_validate_results(
request,
TEST_DIRECTORY,
editor,
"hydra_AtomEditorComponents_AddedToEntity.py",
timeout=EDITOR_TIMEOUT,
expected_lines=expected_lines,
unexpected_lines=unexpected_lines,
halt_on_unexpected=True,
null_renderer=True,
cfg_args=cfg_args,
)
# It requires at least one test
def test_Dummy(self, request, editor, level, workspace, project, launcher_platform):
pass
@@ -41,7 +41,7 @@ class TestDynamicSliceInstanceSpawner(object):
return console
@pytest.mark.test_case_id("C28851763")
@pytest.mark.SUITE_main
@pytest.mark.SUITE_sandbox
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
def test_DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks(self, request, editor, level, workspace, project,
launcher_platform):
@@ -36,8 +36,13 @@ class TestEmptyInstanceSpawner(object):
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True)
@pytest.mark.test_case_id("C28851762")
# Main suite needs at least one test
@pytest.mark.SUITE_main
def test_EmptyInstanceSpawner_Dummy(self, request, editor, level, workspace, project, launcher_platform):
pass
@pytest.mark.test_case_id("C28851762")
@pytest.mark.SUITE_sandbox
def test_EmptyInstanceSpawner_EmptySpawnerWorks(self, request, editor, level, launcher_platform):
cfg_args = [level]
@@ -269,6 +269,8 @@ class TestAutomation(TestAutomationBase):
from . import C18977601_Material_FrictionCombinePriority as test_module
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(
reason="Something with the CryRenderer disabling is causing this test to fail now.")
@revert_physics_config
def test_C13895144_Ragdoll_ChangeLevel(self, request, workspace, editor, launcher_platform):
from . import C13895144_Ragdoll_ChangeLevel as test_module
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -78,7 +78,7 @@ namespace Physics
float m_minimumMovementDistance = 0.001f; //!< To avoid jittering, the controller will not attempt to move distances below this.
float m_maximumSpeed = 100.0f; //!< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped.
AZStd::string m_colliderTag; //!< Used to identify the collider associated with the character controller.
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig = nullptr; //!< The shape to use when creating the character controller.
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig; //!< The shape to use when creating the character controller.
AZStd::vector<AZStd::shared_ptr<Physics::Shape>> m_colliders; //!< The list of colliders to attach to the character controller.
};
@@ -55,7 +55,7 @@ namespace AzPhysics
//! Flag to determine if the body is part of the simulation.
//! When true the body will be affected by any forces, collisions, and found with scene queries.
bool m_simulating = true;
bool m_simulating = false;
//! Helper functions for setting user data.
//! @param userData Can be a pointer to any type as internally will be cast to a void*. Object lifetime not managed by the SimulatedBody.
@@ -46,6 +46,7 @@ namespace AzPhysics
->Field("orientation", &SimulatedBodyConfiguration::m_orientation)
->Field("scale", &SimulatedBodyConfiguration::m_scale)
->Field("entityId", &SimulatedBodyConfiguration::m_entityId)
->Field("startSimulationEnabled", &SimulatedBodyConfiguration::m_startSimulationEnabled)
;
}
}
@@ -39,6 +39,7 @@ namespace AzPhysics
AZ::Vector3 m_position = AZ::Vector3::CreateZero();
AZ::Quaternion m_orientation = AZ::Quaternion::CreateIdentity();
AZ::Vector3 m_scale = AZ::Vector3::CreateOne();
bool m_startSimulationEnabled = true;
// Entity/object association.
AZ::EntityId m_entityId = AZ::EntityId(AZ::EntityId::InvalidEntityId);
@@ -52,6 +52,11 @@ namespace Physics
}
}
RagdollConfiguration::RagdollConfiguration()
{
m_startSimulationEnabled = false; //ragdolls do not start enabled.
}
void RagdollConfiguration::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
@@ -24,6 +24,8 @@
namespace Physics
{
using ParentIndices = AZStd::vector<size_t>;
class RagdollNodeConfiguration
: public AzPhysics::RigidBodyConfiguration
{
@@ -46,7 +48,7 @@ namespace Physics
AZ_RTTI(RagdollConfiguration, "{7C96D332-61D8-4C58-A2BF-707716D38D14}", AzPhysics::SimulatedBodyConfiguration);
static void Reflect(AZ::ReflectContext* context);
RagdollConfiguration() = default;
RagdollConfiguration();
explicit RagdollConfiguration(const RagdollConfiguration& settings) = default;
RagdollNodeConfiguration* FindNodeConfigByName(const AZStd::string& nodeName) const;
@@ -56,6 +58,8 @@ namespace Physics
AZStd::vector<RagdollNodeConfiguration> m_nodes;
CharacterColliderConfiguration m_colliders;
RagdollState m_initialState;
ParentIndices m_parentIndices;
};
/// Represents a single rigid part of a ragdoll.
@@ -79,7 +83,7 @@ namespace Physics
{
public:
AZ_CLASS_ALLOCATOR(Ragdoll, AZ::SystemAllocator, 0);
AZ_RTTI(Ragdoll, "{01F09602-80EC-4693-A0E7-C2719239044B}", AzPhysics::SimulatedBody);
AZ_RTTI(Physics::Ragdoll, "{01F09602-80EC-4693-A0E7-C2719239044B}", AzPhysics::SimulatedBody);
virtual ~Ragdoll() = default;
/// Inserts the ragdoll into the physics simulation.
@@ -63,7 +63,7 @@ AZ_POP_DISABLE_WARNING
#include <UI/PropertyEditor/Model/AssetCompleterModel.h>
#include <UI/PropertyEditor/View/AssetCompleterListView.h>
#include <UI/PropertyEditor/ThumbnailDropDown.h>
#include <UI/PropertyEditor/ThumbnailPropertyCtrl.h>
namespace AzToolsFramework
{
@@ -93,15 +93,11 @@ namespace AzToolsFramework
setAcceptDrops(true);
m_thumbnail = new Thumbnailer::ThumbnailWidget(this);
m_thumbnail->setFixedSize(QSize(24, 24));
m_thumbnail = new ThumbnailPropertyCtrl(this);
m_thumbnail->setFixedSize(QSize(40, 24));
m_thumbnail->setVisible(false);
m_thumbnailDropDown = new ThumbnailDropDown(this);
m_thumbnailDropDown->setFixedSize(QSize(40, 24));
m_thumbnailDropDown->setVisible(false);
connect(m_thumbnailDropDown, &ThumbnailDropDown::clicked, this, &PropertyAssetCtrl::OnEditButtonClicked);
connect(m_thumbnail, &ThumbnailPropertyCtrl::clicked, this, &PropertyAssetCtrl::OnThumbnailClicked);
m_editButton = new QToolButton(this);
m_editButton->setAutoRaise(true);
@@ -112,7 +108,6 @@ namespace AzToolsFramework
connect(m_editButton, &QToolButton::clicked, this, &PropertyAssetCtrl::OnEditButtonClicked);
pLayout->addWidget(m_thumbnail);
pLayout->addWidget(m_thumbnailDropDown);
pLayout->addWidget(m_browseEdit);
pLayout->addWidget(m_editButton);
@@ -188,6 +183,17 @@ namespace AzToolsFramework
}
}
void PropertyAssetCtrl::OnThumbnailClicked()
{
const AZ::Data::AssetId assetID = GetCurrentAssetID();
if (m_thumbnailCallback)
{
AZ_Error("Asset Property", m_editNotifyTarget, "No notification target set for edit callback.");
m_thumbnailCallback->Invoke(m_editNotifyTarget, assetID, GetCurrentAssetType());
return;
}
}
void PropertyAssetCtrl::OnCompletionModelReset()
{
if (!m_completerIsActive)
@@ -1091,10 +1097,10 @@ namespace AzToolsFramework
void PropertyAssetCtrl::UpdateThumbnail()
{
m_thumbnail->setVisible(m_showThumbnail);
m_thumbnailDropDown->setVisible(m_showThumbnailDropDown);
if (m_showThumbnail || m_showThumbnailDropDown)
if (m_showThumbnail)
{
m_thumbnail->ShowDropDownArrow(m_showThumbnailDropDownButton);
const AZ::Data::AssetId assetID = GetCurrentAssetID();
if (assetID.IsValid())
{
@@ -1112,17 +1118,12 @@ namespace AzToolsFramework
{
m_thumbnail->SetThumbnailKey(thumbnailKey, Thumbnailer::ThumbnailContext::DefaultContext);
}
if (m_showThumbnailDropDown)
{
m_thumbnailDropDown->SetThumbnailKey(thumbnailKey, Thumbnailer::ThumbnailContext::DefaultContext);
}
return;
}
}
}
m_thumbnail->ClearThumbnail();
m_thumbnailDropDown->ClearThumbnail();
}
void PropertyAssetCtrl::SetClearButtonEnabled(bool enable)
@@ -1156,14 +1157,19 @@ namespace AzToolsFramework
return m_showThumbnail;
}
void PropertyAssetCtrl::SetShowThumbnailDropDown(bool enable)
void PropertyAssetCtrl::SetShowThumbnailDropDownButton(bool enable)
{
m_showThumbnailDropDown = enable;
m_showThumbnailDropDownButton = enable;
}
bool PropertyAssetCtrl::GetShowThumbnailDropDown() const
bool PropertyAssetCtrl::GetShowThumbnailDropDownButton() const
{
return m_showThumbnailDropDown;
return m_showThumbnailDropDownButton;
}
void PropertyAssetCtrl::SetThumbnailCallback(EditCallbackType* editNotifyCallback)
{
m_thumbnailCallback = editNotifyCallback;
}
const AZ::Uuid& AssetPropertyHandlerDefault::GetHandledType() const
@@ -1277,23 +1283,21 @@ namespace AzToolsFramework
}
else if (attrib == AZ_CRC_CE("Thumbnail"))
{
bool showThumbnail = false;
if (attrValue->Read<bool>(showThumbnail))
{
GUI->SetShowThumbnail(showThumbnail);
}
GUI->SetShowThumbnail(true);
}
else if (attrib == AZ_CRC_CE("ThumbnailWithDropDown"))
else if (attrib == AZ_CRC_CE("ThumbnailCallback"))
{
PropertyAssetCtrl::EditCallbackType* func = azdynamic_cast<PropertyAssetCtrl::EditCallbackType*>(attrValue->GetAttribute());
if (func)
{
GUI->SetShowThumbnailDropDown(true);
GUI->SetEditNotifyCallback(func);
GUI->SetShowThumbnail(true);
GUI->SetShowThumbnailDropDownButton(true);
GUI->SetThumbnailCallback(func);
}
else
{
GUI->SetEditNotifyCallback(nullptr);
GUI->SetShowThumbnailDropDownButton(false);
GUI->SetThumbnailCallback(nullptr);
}
}
}
@@ -45,7 +45,7 @@ namespace AzToolsFramework
{
class AssetCompleterModel;
class AssetCompleterListView;
class ThumbnailDropDown;
class ThumbnailPropertyCtrl;
namespace Thumbnailer
{
@@ -95,8 +95,7 @@ namespace AzToolsFramework
void OnAssetIDChanged(AZ::Data::AssetId newAssetID);
protected:
ThumbnailDropDown* m_thumbnailDropDown = nullptr;
Thumbnailer::ThumbnailWidget* m_thumbnail = nullptr;
ThumbnailPropertyCtrl* m_thumbnail = nullptr;
QPushButton* m_errorButton = nullptr;
QToolButton* m_editButton = nullptr;
@@ -157,8 +156,8 @@ namespace AzToolsFramework
bool m_showProductAssetName = true;
bool m_showThumbnail = false;
bool m_showThumbnailDropDown = false;
bool m_showThumbnailDropDownButton = false;
EditCallbackType* m_thumbnailCallback = nullptr;
// ! Default suffix used in the field's placeholder text when a default value is set.
const char* m_DefaultSuffix = " (default)";
@@ -209,8 +208,9 @@ namespace AzToolsFramework
void SetShowThumbnail(bool enable);
bool GetShowThumbnail() const;
void SetShowThumbnailDropDown(bool enable);
bool GetShowThumbnailDropDown() const;
void SetShowThumbnailDropDownButton(bool enable);
bool GetShowThumbnailDropDownButton() const;
void SetThumbnailCallback(EditCallbackType* editNotifyCallback);
void SetSelectedAssetID(const AZ::Data::AssetId& newID);
void SetCurrentAssetType(const AZ::Data::AssetType& newType);
@@ -222,6 +222,7 @@ namespace AzToolsFramework
void UpdateAssetDisplay();
void OnLineEditFocus(bool focus);
virtual void OnEditButtonClicked();
void OnThumbnailClicked();
void OnCompletionModelReset();
void OnAutocomplete(const QModelIndex& index);
void OnTextChange(const QString& text);
@@ -19,12 +19,14 @@ AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // 4251: 'QRawFon
#include <QPainter>
#include <UI/UICore/AspectRatioAwarePixmapWidget.hxx>
#include <Thumbnails/ThumbnailWidget.h>
#include <QApplication>
AZ_POP_DISABLE_WARNING
#include "ThumbnailDropDown.h"
#include "ThumbnailPropertyCtrl.h"
namespace AzToolsFramework
{
ThumbnailDropDown::ThumbnailDropDown(QWidget* parent)
ThumbnailPropertyCtrl::ThumbnailPropertyCtrl(QWidget* parent)
: QWidget(parent)
{
QHBoxLayout* pLayout = new QHBoxLayout();
@@ -37,6 +39,7 @@ namespace AzToolsFramework
m_dropDownArrow = new AspectRatioAwarePixmapWidget(this);
m_dropDownArrow->setPixmap(QPixmap(":/stylesheet/img/triangle0.png"));
m_dropDownArrow->setFixedSize(QSize(8, 24));
ShowDropDownArrow(false);
m_emptyThumbnail = new QLabel(this);
m_emptyThumbnail->setPixmap(QPixmap(":/stylesheet/img/line.png"));
@@ -51,19 +54,33 @@ namespace AzToolsFramework
setLayout(pLayout);
}
void ThumbnailDropDown::SetThumbnailKey(Thumbnailer::SharedThumbnailKey key, const char* contextName)
void ThumbnailPropertyCtrl::SetThumbnailKey(Thumbnailer::SharedThumbnailKey key, const char* contextName)
{
m_key = key;
m_emptyThumbnail->setVisible(false);
m_thumbnail->SetThumbnailKey(key, contextName);
}
void ThumbnailDropDown::ClearThumbnail()
void ThumbnailPropertyCtrl::ClearThumbnail()
{
m_emptyThumbnail->setVisible(true);
m_thumbnail->ClearThumbnail();
}
bool ThumbnailDropDown::event(QEvent* e)
void ThumbnailPropertyCtrl::ShowDropDownArrow(bool visible)
{
if (visible)
{
setFixedSize(QSize(40, 24));
}
else
{
setFixedSize(QSize(24, 24));
}
m_dropDownArrow->setVisible(visible);
}
bool ThumbnailPropertyCtrl::event(QEvent* e)
{
if (isEnabled())
{
@@ -77,7 +94,7 @@ namespace AzToolsFramework
return QWidget::event(e);
}
void ThumbnailDropDown::paintEvent(QPaintEvent* e)
void ThumbnailPropertyCtrl::paintEvent(QPaintEvent* e)
{
QPainter p(this);
QRect targetRect(QPoint(), QSize(40, 24));
@@ -85,17 +102,32 @@ namespace AzToolsFramework
QWidget::paintEvent(e);
}
void ThumbnailDropDown::enterEvent(QEvent* e)
void ThumbnailPropertyCtrl::enterEvent(QEvent* e)
{
m_dropDownArrow->setPixmap(QPixmap(":/stylesheet/img/triangle0_highlighted.png"));
if (!m_thumbnailEnlarged && m_key)
{
QPoint position = mapToGlobal(pos() - QPoint(185, 0));
QSize size(180, 180);
m_thumbnailEnlarged.reset(new Thumbnailer::ThumbnailWidget());
m_thumbnailEnlarged->setFixedSize(size);
m_thumbnailEnlarged->move(position);
m_thumbnailEnlarged->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
m_thumbnailEnlarged->SetThumbnailKey(m_key);
m_thumbnailEnlarged->show();
}
QWidget::enterEvent(e);
}
void ThumbnailDropDown::leaveEvent(QEvent* e)
void ThumbnailPropertyCtrl::leaveEvent(QEvent* e)
{
m_dropDownArrow->setPixmap(QPixmap(":/stylesheet/img/triangle0.png"));
if (m_thumbnailEnlarged)
{
m_thumbnailEnlarged.reset();
}
QWidget::leaveEvent(e);
}
}
#include "UI/PropertyEditor/moc_ThumbnailDropDown.cpp"
#include "UI/PropertyEditor/moc_ThumbnailPropertyCtrl.cpp"
@@ -30,17 +30,20 @@ namespace AzToolsFramework
class ThumbnailWidget;
}
class ThumbnailDropDown : public QWidget
//! Used by PropertyAssetCtrl to display thumbnail preview of the asset as well as additional drop-down actions
class ThumbnailPropertyCtrl : public QWidget
{
Q_OBJECT
public:
explicit ThumbnailDropDown(QWidget* parent = nullptr);
explicit ThumbnailPropertyCtrl(QWidget* parent = nullptr);
//! Call this to set what thumbnail widget will display
void SetThumbnailKey(Thumbnailer::SharedThumbnailKey key, const char* contextName = "Default");
//! Remove current thumbnail
void ClearThumbnail();
void ShowDropDownArrow(bool visible);
bool event(QEvent* e) override;
Q_SIGNALS:
@@ -52,7 +55,9 @@ namespace AzToolsFramework
void leaveEvent(QEvent* e) override;
private:
Thumbnailer::SharedThumbnailKey m_key;
Thumbnailer::ThumbnailWidget* m_thumbnail = nullptr;
QScopedPointer<Thumbnailer::ThumbnailWidget> m_thumbnailEnlarged;
QLabel* m_emptyThumbnail = nullptr;
AspectRatioAwarePixmapWidget* m_dropDownArrow = nullptr;
};
@@ -417,8 +417,8 @@ set(FILES
UI/PropertyEditor/GrowTextEdit.cpp
UI/PropertyEditor/MultiLineTextEditHandler.h
UI/PropertyEditor/MultiLineTextEditHandler.cpp
UI/PropertyEditor/ThumbnailDropDown.h
UI/PropertyEditor/ThumbnailDropDown.cpp
UI/PropertyEditor/ThumbnailPropertyCtrl.h
UI/PropertyEditor/ThumbnailPropertyCtrl.cpp
UI/Slice/SlicePushWidget.cpp
UI/Slice/SlicePushWidget.hxx
UI/Slice/SliceOverridesNotificationWindow.cpp
@@ -1,187 +1,64 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or
* a third party where indicated.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates, or
* a third party where indicated.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "EditorDefs.h"
#include "PropertyMotionCtrl.h"
// Qt
#include <QHBoxLayout>
#include <QLabel>
#include <QToolButton>
// AzToolsFramework
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
MotionPropertyCtrl::MotionPropertyCtrl(QWidget *pParent)
: QWidget(pParent)
QWidget* MotionPropertyWidgetHandler::CreateGUI(QWidget* pParent)
{
m_motionLabel = new QLabel;
m_pBrowseButton = new QToolButton;
m_pBrowseButton->setIcon(QIcon(":/reflectedPropertyCtrl/img/file_browse.png"));
m_pApplyButton = new QToolButton;
m_pApplyButton->setIcon(QIcon(":/reflectedPropertyCtrl/img/apply.png"));
m_pApplyButton->setFocusPolicy(Qt::StrongFocus);
m_pBrowseButton->setFocusPolicy(Qt::StrongFocus);
QHBoxLayout *pLayout = new QHBoxLayout(this);
pLayout->setContentsMargins(0, 0, 0, 0);
pLayout->addWidget(m_motionLabel, 1);
pLayout->addWidget(m_pBrowseButton);
pLayout->addWidget(m_pApplyButton);
connect(m_pBrowseButton, &QAbstractButton::clicked, this, &MotionPropertyCtrl::OnBrowseClicked);
connect(m_pApplyButton, &QAbstractButton::clicked, this, &MotionPropertyCtrl::OnApplyClicked);
};
MotionPropertyCtrl::~MotionPropertyCtrl()
{
}
void MotionPropertyCtrl::SetValue(const CReflectedVarMotion &motion)
{
m_motion = motion;
SetLabelText(motion.m_motion);
}
CReflectedVarMotion MotionPropertyCtrl::value() const
{
return m_motion;
}
void MotionPropertyCtrl::OnBrowseClicked()
{
static AZ::Data::AssetType emotionFXMotionAssetType("{00494B8E-7578-4BA2-8B28-272E90680787}"); // from MotionAsset.h in EMotionFX Gem
// Request the AssetBrowser Dialog and set a type filter
AssetSelectionModel selection = AssetSelectionModel::AssetTypeSelection(emotionFXMotionAssetType);
selection.SetSelectedAssetId(m_motion.m_assetId);
AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection);
if (selection.IsValid())
{
auto product = azrtti_cast<const ProductAssetBrowserEntry*>(selection.GetResult());
if (product != nullptr)
{
m_motion.m_motion = product->GetRelativePath();
m_motion.m_assetId = product->GetAssetId();
SetLabelText(m_motion.m_motion);
emit ValueChanged(m_motion);
}
}
}
// TODO: Might be able to delete this function
void MotionPropertyCtrl::OnApplyClicked()
{
#if 0
CUIEnumerations &roGeneralProxy = CUIEnumerations::GetUIEnumerationsInstance();
QStringList cSelectedMotions;
size_t nTotalMotions(0);
size_t nCurrentMotion(0);
QString combinedString = GetIEditor()->GetResourceSelectorHost()->GetGlobalSelection("motion");
SplitString(combinedString, cSelectedMotions, ',');
nTotalMotions = cSelectedMotions.size();
for (nCurrentMotion = 0; nCurrentMotion < nTotalMotions; ++nCurrentMotion)
{
QString& rstrCurrentAnimAction = cSelectedMotions[nCurrentMotion];
if (!rstrCurrentAnimAction.isEmpty())
{
m_motion.m_motion = rstrCurrentAnimAction.toLatin1().data();
SetLabelText(m_motion.m_motion);
emit ValueChanged(m_motion);
}
}
#endif
}
QWidget* MotionPropertyCtrl::GetFirstInTabOrder()
{
return m_pBrowseButton;
}
QWidget* MotionPropertyCtrl::GetLastInTabOrder()
{
return m_pApplyButton;
}
void MotionPropertyCtrl::UpdateTabOrder()
{
setTabOrder(m_pBrowseButton, m_pApplyButton);
}
void MotionPropertyCtrl::SetLabelText(const AZStd::string& motion)
{
if (!motion.empty())
{
AZStd::string filename;
if (AzFramework::StringFunc::Path::GetFileName(motion.c_str(), filename))
{
m_motionLabel->setText(filename.c_str());
}
else
{
m_motionLabel->setText(motion.c_str());
}
}
else
{
m_motionLabel->setText("");
}
}
QWidget* MotionPropertyWidgetHandler::CreateGUI(QWidget *pParent)
{
MotionPropertyCtrl* newCtrl = aznew MotionPropertyCtrl(pParent);
connect(newCtrl, &MotionPropertyCtrl::ValueChanged, newCtrl, [newCtrl]()
{
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
});
AzToolsFramework::PropertyAssetCtrl* newCtrl = aznew AzToolsFramework::PropertyAssetCtrl(pParent);
connect(
newCtrl, &AzToolsFramework::PropertyAssetCtrl::OnAssetIDChanged, this, [newCtrl]([[maybe_unused]] AZ::Data::AssetId newAssetId) {
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(
&AzToolsFramework::PropertyEditorGUIMessages::Bus::Handler::OnEditingFinished, newCtrl);
});
return newCtrl;
}
void MotionPropertyWidgetHandler::ConsumeAttribute(MotionPropertyCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName)
void MotionPropertyWidgetHandler::ConsumeAttribute(
[[maybe_unused]] AzToolsFramework::PropertyAssetCtrl* GUI, [[maybe_unused]] AZ::u32 attrib,
[[maybe_unused]] AzToolsFramework::PropertyAttributeReader* attrValue, [[maybe_unused]] const char* debugName)
{
Q_UNUSED(GUI);
Q_UNUSED(attrib);
Q_UNUSED(attrValue);
Q_UNUSED(debugName);
}
void MotionPropertyWidgetHandler::WriteGUIValuesIntoProperty(size_t index, MotionPropertyCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node)
void MotionPropertyWidgetHandler::WriteGUIValuesIntoProperty(
[[maybe_unused]] size_t index, [[maybe_unused]] AzToolsFramework::PropertyAssetCtrl* GUI, property_t& instance,
[[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
{
Q_UNUSED(index);
Q_UNUSED(node);
CReflectedVarMotion val = GUI->value();
CReflectedVarMotion val;
val.m_motion = GUI->GetCurrentAssetHint();
val.m_assetId = GUI->GetSelectedAssetID();
instance = static_cast<property_t>(val);
}
bool MotionPropertyWidgetHandler::ReadValuesIntoGUI(size_t index, MotionPropertyCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node)
bool MotionPropertyWidgetHandler::ReadValuesIntoGUI(
[[maybe_unused]] size_t index, [[maybe_unused]] AzToolsFramework::PropertyAssetCtrl* GUI, const property_t& instance,
[[maybe_unused]] AzToolsFramework::InstanceDataNode* node)
{
Q_UNUSED(index);
Q_UNUSED(node);
CReflectedVarMotion val = instance;
GUI->SetValue(val);
static const AZ::Data::AssetType emotionFXMotionAssetType(
"{00494B8E-7578-4BA2-8B28-272E90680787}"); // from MotionAsset.h in EMotionFX Gem
GUI->blockSignals(true);
GUI->SetSelectedAssetID(instance.m_assetId);
GUI->SetCurrentAssetType(emotionFXMotionAssetType);
GUI->blockSignals(false);
return false;
}
#include <Controls/ReflectedPropertyControl/moc_PropertyMotionCtrl.cpp>
@@ -1,92 +1,67 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#ifndef CRYINCLUDE_EDITOR_UTILS_PROPERTYMOTIONCTRL_H
#define CRYINCLUDE_EDITOR_UTILS_PROPERTYMOTIONCTRL_H
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/base.h>
#include <AzCore/Memory/SystemAllocator.h>
#include "ReflectedVar.h"
#include <QWidget>
#include <QPointer>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/base.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
#include <QPointer>
#include <QWidget>
#endif
class QToolButton;
class QLabel;
class QHBoxLayout;
namespace AzToolsFramework
{
class PropertyAssetCtrl;
}
class MotionPropertyCtrl
: public QWidget
class MotionPropertyWidgetHandler : QObject,
public AzToolsFramework::PropertyHandler<CReflectedVarMotion, AzToolsFramework::PropertyAssetCtrl>
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(MotionPropertyCtrl, AZ::SystemAllocator, 0);
MotionPropertyCtrl(QWidget* pParent = nullptr);
virtual ~MotionPropertyCtrl();
CReflectedVarMotion value() const;
QWidget* GetFirstInTabOrder();
QWidget* GetLastInTabOrder();
void UpdateTabOrder();
signals:
void ValueChanged(CReflectedVarMotion value);
public slots:
void SetValue(const CReflectedVarMotion& motion);
protected slots:
void OnBrowseClicked();
void OnApplyClicked();
private:
void SetLabelText(const AZStd::string& motion);
QToolButton* m_pBrowseButton;
QToolButton* m_pApplyButton;
QLabel* m_motionLabel;
CReflectedVarMotion m_motion;
};
class MotionPropertyWidgetHandler
: QObject
, public AzToolsFramework::PropertyHandler < CReflectedVarMotion, MotionPropertyCtrl >
{
public:
AZ_CLASS_ALLOCATOR(MotionPropertyWidgetHandler, AZ::SystemAllocator, 0);
virtual AZ::u32 GetHandlerName(void) const override { return AZ_CRC("Motion", 0xf5fea1e8); }
virtual bool IsDefaultHandler() const override { return true; }
virtual QWidget* GetFirstInTabOrder(MotionPropertyCtrl* widget) override { return widget->GetFirstInTabOrder(); }
virtual QWidget* GetLastInTabOrder(MotionPropertyCtrl* widget) override { return widget->GetLastInTabOrder(); }
virtual void UpdateWidgetInternalTabbing(MotionPropertyCtrl* widget) override { widget->UpdateTabOrder(); }
virtual AZ::u32 GetHandlerName(void) const override
{
return AZ_CRC("Motion", 0xf5fea1e8);
}
virtual bool IsDefaultHandler() const override
{
return true;
}
virtual QWidget* GetFirstInTabOrder(AzToolsFramework::PropertyAssetCtrl* widget) override
{
return widget->GetFirstInTabOrder();
}
virtual QWidget* GetLastInTabOrder(AzToolsFramework::PropertyAssetCtrl* widget) override
{
return widget->GetLastInTabOrder();
}
virtual void UpdateWidgetInternalTabbing(AzToolsFramework::PropertyAssetCtrl* widget) override
{
widget->UpdateTabOrder();
}
virtual QWidget* CreateGUI(QWidget* pParent) override;
virtual void ConsumeAttribute(MotionPropertyCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
virtual void WriteGUIValuesIntoProperty(size_t index, MotionPropertyCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
virtual bool ReadValuesIntoGUI(size_t index, MotionPropertyCtrl* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
virtual void ConsumeAttribute(
AzToolsFramework::PropertyAssetCtrl* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue,
const char* debugName) override;
virtual void WriteGUIValuesIntoProperty(
size_t index, AzToolsFramework::PropertyAssetCtrl* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
virtual bool ReadValuesIntoGUI(
size_t index, AzToolsFramework::PropertyAssetCtrl* GUI, const property_t& instance,
AzToolsFramework::InstanceDataNode* node) override;
};
#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYMOTIONCTRL_H
+4 -1
View File
@@ -2428,7 +2428,10 @@ void EditorViewportWidget::SetDefaultCamera()
return;
}
ResetToViewSourceType(ViewSourceType::None);
gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam("Dof_Active", 0.0f);
if (gEnv->p3DEngine)
{
gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam("Dof_Active", 0.0f);
}
GetViewManager()->SetCameraObjectId(m_cameraObjectId);
SetName(m_defaultViewName);
SetViewTM(m_defaultViewTM);
+34 -20
View File
@@ -139,7 +139,10 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE
// Make sure we unload any unused CGFs before exporting so that they don't end up in
// the level data.
pEditor->Get3DEngine()->FreeUnusedCGFResources();
if (pEditor->Get3DEngine())
{
pEditor->Get3DEngine()->FreeUnusedCGFResources();
}
CCryEditDoc* pDocument = pEditor->GetDocument();
@@ -282,7 +285,7 @@ void CGameExporter::ExportVisAreas(const char* pszGamePath, EEndian eExportEndia
SHotUpdateInfo exportInfo;
I3DEngine* p3DEngine = pEditor->Get3DEngine();
if (eExportEndian == GetPlatformEndian()) // skip second export, this data is common for PC and consoles
if (p3DEngine && (eExportEndian == GetPlatformEndian())) // skip second export, this data is common for PC and consoles
{
std::vector<struct IStatObj*>* pTempBrushTable = NULL;
std::vector<_smart_ptr<IMaterial>>* pTempMatsTable = NULL;
@@ -367,25 +370,28 @@ void CGameExporter::ExportLevelData(const QString& path, bool bExportMission)
QString missionFileName;
QString currentMissionFileName;
I3DEngine* p3DEngine = pEditor->Get3DEngine();
for (int i = 0; i < pDocument->GetMissionCount(); i++)
if (p3DEngine)
{
CMission* pMission = pDocument->GetMission(i);
QString name = pMission->GetName();
name.replace(' ', '_');
missionFileName = QStringLiteral("Mission_%1.xml").arg(name);
XmlNodeRef missionDescNode = missionsNode->newChild("Mission");
missionDescNode->setAttr("Name", pMission->GetName().toUtf8().data());
missionDescNode->setAttr("File", missionFileName.toUtf8().data());
missionDescNode->setAttr("CGFCount", p3DEngine->GetLoadedObjectCount());
int nProgressBarRange = m_numExportedMaterials / 10 + p3DEngine->GetLoadedObjectCount();
missionDescNode->setAttr("ProgressBarRange", nProgressBarRange);
if (pMission == pCurrentMission)
for (int i = 0; i < pDocument->GetMissionCount(); i++)
{
currentMissionFileName = missionFileName;
CMission* pMission = pDocument->GetMission(i);
QString name = pMission->GetName();
name.replace(' ', '_');
missionFileName = QStringLiteral("Mission_%1.xml").arg(name);
XmlNodeRef missionDescNode = missionsNode->newChild("Mission");
missionDescNode->setAttr("Name", pMission->GetName().toUtf8().data());
missionDescNode->setAttr("File", missionFileName.toUtf8().data());
missionDescNode->setAttr("CGFCount", p3DEngine->GetLoadedObjectCount());
int nProgressBarRange = m_numExportedMaterials / 10 + p3DEngine->GetLoadedObjectCount();
missionDescNode->setAttr("ProgressBarRange", nProgressBarRange);
if (pMission == pCurrentMission)
{
currentMissionFileName = missionFileName;
}
}
}
@@ -413,7 +419,10 @@ void CGameExporter::ExportLevelData(const QString& path, bool bExportMission)
XmlNodeRef missionNode = rootAction->createNode("Mission");
pCurrentMission->Export(missionNode, objectsNode);
missionNode->setAttr("CGFCount", p3DEngine->GetLoadedObjectCount());
if (p3DEngine)
{
missionNode->setAttr("CGFCount", p3DEngine->GetLoadedObjectCount());
}
//if (!CFileUtil::OverwriteFile( path+currentMissionFileName ))
// return;
@@ -483,6 +492,11 @@ void CGameExporter::ExportLevelInfo(const QString& path)
//////////////////////////////////////////////////////////////////////////
void CGameExporter::ExportMapInfo(XmlNodeRef& node)
{
if (!GetIEditor()->Get3DEngine())
{
return;
}
XmlNodeRef info = node->newChild("LevelInfo");
IEditor* pEditor = GetIEditor();
+5 -2
View File
@@ -212,8 +212,11 @@ void CMission::SyncContent(bool bRetrieve, bool bIgnoreObjects, [[maybe_unused]]
else
{
// Save time of day.
m_timeOfDay = XmlHelpers::CreateXmlNode("TimeOfDay");
GetIEditor()->Get3DEngine()->GetTimeOfDay()->Serialize(m_timeOfDay, false);
if (GetIEditor()->Get3DEngine())
{
m_timeOfDay = XmlHelpers::CreateXmlNode("TimeOfDay");
GetIEditor()->Get3DEngine()->GetTimeOfDay()->Serialize(m_timeOfDay, false);
}
if (!bIgnoreObjects)
{
+1
View File
@@ -138,6 +138,7 @@ bool CLevelShaderCache::SaveBuffer(QString& textBuffer)
void CLevelShaderCache::Update()
{
IRenderer* pRenderer = gEnv->pRenderer;
if (pRenderer)
{
QString buf;
char* str = NULL;
+1 -1
View File
@@ -13,6 +13,7 @@ add_subdirectory(SceneAPI) # Needs to go before AssetProcessor since it provides
add_subdirectory(AssetProcessor)
add_subdirectory(AWSNativeSDKInit)
add_subdirectory(AzTestRunner)
add_subdirectory(CrashHandler)
add_subdirectory(CryCommonTools)
add_subdirectory(CryXML)
add_subdirectory(HLSLCrossCompiler)
@@ -21,7 +22,6 @@ add_subdirectory(News)
add_subdirectory(PythonBindingsExample)
add_subdirectory(RC)
add_subdirectory(RemoteConsole)
add_subdirectory(CrashHandler)
add_subdirectory(ShaderCacheGen)
add_subdirectory(DeltaCataloger)
add_subdirectory(SerializeContextTools)
+3 -5
View File
@@ -32,11 +32,11 @@ ly_add_target(
PRIVATE
${pal_dir}
BUILD_DEPENDENCIES
PUBLIC
AZ::CrashSupport
PRIVATE
3rdParty::Crashpad
AZ::AzCore
AZ::AzFramework
AZ::CrashSupport
)
string(REPLACE "." ";" version_list "${LY_VERSION_STRING}")
@@ -67,11 +67,9 @@ ly_add_target(
PRIVATE
Uploader/include/Uploader
BUILD_DEPENDENCIES
PRIVATE
AZ::AzCore
AZ::CrashSupport
PUBLIC
3rdParty::Crashpad::Handler
AZ::CrashSupport
)
add_subdirectory(Tools)
@@ -19,6 +19,6 @@ ly_add_target(
PUBLIC
include
BUILD_DEPENDENCIES
PRIVATE
PUBLIC
AZ::AzCore
)
+3 -7
View File
@@ -21,13 +21,13 @@ ly_add_target(
tools_crash_handler_files.cmake
Platform/${PAL_PLATFORM_NAME}/tools_crash_handler_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
PUBLIC
.
BUILD_DEPENDENCIES
PUBLIC
AZ::CrashHandler
PRIVATE
3rdParty::Qt::Core
AZ::CrashHandler
AZ::CrashSupport
AZ::AzToolsFramework
)
@@ -41,18 +41,14 @@ ly_add_target(
Platform/${PAL_PLATFORM_NAME}/tools_crash_uploader_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
.
Uploader
BUILD_DEPENDENCIES
PRIVATE
3rdParty::Qt::Core
3rdParty::Qt::Gui
3rdParty::Qt::Widgets
3rdParty::Crashpad
3rdParty::Crashpad::Handler
AZ::CrashUploaderSupport
AZ::AzQtComponents
AZ::CrashSupport
TARGET_PROPERTIES
Qt5_NO_LINK_QTMAIN TRUE
)
@@ -138,7 +138,7 @@ namespace O3de
if (!logFileReader->Open(thisFile))
{
#if defined(AZ_PLATFORM_WINDOWS)
LOG(ERROR) << "Failed to open " << base::UTF16ToUTF8(thisFile.BaseName().value());
LOG(ERROR) << "Failed to open " << base::WideToUTF8(thisFile.BaseName().value());
#else
LOG(ERROR) << "Failed to open " << thisFile.BaseName().value();
#endif
@@ -149,7 +149,7 @@ namespace O3de
if (start_offset < 0)
{
#if defined(AZ_PLATFORM_WINDOWS)
LOG(ERROR) << "Failed to get offset for " << base::UTF16ToUTF8(thisFile.BaseName().value());
LOG(ERROR) << "Failed to get offset for " << base::WideToUTF8(thisFile.BaseName().value());
#else
LOG(ERROR) << "Failed to get offset for " << thisFile.BaseName().value();
#endif
@@ -162,7 +162,7 @@ namespace O3de
std::string fileNameKey{ "attachment_" };
#if defined(AZ_PLATFORM_WINDOWS)
fileNameKey += base::UTF16ToUTF8(thisFile.BaseName().value());
fileNameKey += base::WideToUTF8(thisFile.BaseName().value());
#else
fileNameKey += thisFile.BaseName().value();
#endif
@@ -13,6 +13,7 @@
#pragma once
#include <Atom/Features/SrgSemantics.azsli>
#include <viewsrg.srgi>
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
#include "MaterialInputs/BaseColorInput.azsli"
@@ -10,7 +10,6 @@
*
*/
#include <viewsrg.srgi>
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include "./EnhancedPBR_Common.azsli"
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
@@ -10,11 +10,25 @@
*
*/
#include <viewsrg.srgi>
#include "EnhancedPBR_Common.azsli"
// SRGs
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
// Pass Output
#include <Atom/Features/PBR/ForwardSubsurfacePassOutput.azsli>
// Utility
#include <Atom/Features/ColorManagement/TransformColor.azsli>
#include <Atom/Features/PBR/AlphaUtils.azsli>
// Custom Surface & Lighting
#include <Atom/Features/PBR/Lighting/EnhancedLighting.azsli>
// Decals
#include <Atom/Features/PBR/Decals.azsli>
// ---------- Material Parameters ----------
@@ -39,6 +53,8 @@ COMMON_OPTIONS_DETAIL_MAPS()
#include "MaterialInputs/TransmissionInput.azsli"
// ---------- Vertex Shader ----------
struct VSInput
{
// Base fields (required by the template azsli file)...
@@ -67,8 +83,6 @@ struct VSOutput
float2 m_detailUv[UvSetCount] : UV3;
};
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/LightingModel.azsli>
#include <Atom/Features/Vertex/VertexHelper.azsli>
VSOutput EnhancedPbr_ForwardPassVS(VSInput IN)
@@ -94,6 +108,9 @@ VSOutput EnhancedPbr_ForwardPassVS(VSInput IN)
return OUT;
}
// ---------- Pixel Shader ----------
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth)
{
// ------- Tangents & Bitangets -------
@@ -144,6 +161,9 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
}
}
Surface surface;
surface.position = IN.m_worldPosition;
// ------- Alpha & Clip -------
float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex];
@@ -172,7 +192,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms.
float detailLayerNormalFactor = MaterialSrg::m_detail_normal_factor * detailLayerBlendFactor;
float3 normal = GetDetailedNormalInputWS(
surface.normal = GetDetailedNormalInputWS(
isFrontFace, IN.m_normal,
tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_normalFactor, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, uvMatrix, o_normal_useTexture,
tangents[MaterialSrg::m_detail_allMapsUvIndex], bitangents[MaterialSrg::m_detail_allMapsUvIndex], MaterialSrg::m_detail_normal_texture, MaterialSrg::m_sampler, detailUv, detailLayerNormalFactor, MaterialSrg::m_detail_normal_flipX, MaterialSrg::m_detail_normal_flipY, MaterialSrg::m_detailUvMatrix, o_detail_normal_useTexture);
@@ -196,26 +216,19 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
metallic = GetMetallicInput(MaterialSrg::m_metallicMap, MaterialSrg::m_sampler, metallicUv, MaterialSrg::m_metallicFactor, o_metallic_useTexture);
}
// ------- Roughness -------
float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex];
float roughness = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor,
MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture);
// ------- Specular -------
float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex];
float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
// ------- Emissive -------
surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic);
float2 emissiveUv = IN.m_uv[MaterialSrg::m_emissiveMapUvIndex];
float3 emissive = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture);
// ------- Roughness -------
// ------- Occlusion -------
float diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture);
float specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture);
float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex];
surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor,
MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture);
surface.CalculateRoughnessA();
// ------- Subsurface -------
@@ -226,33 +239,99 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float2 transmissionUv = IN.m_uv[MaterialSrg::m_transmissionThicknessMapUvIndex];
float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness);
surface.transmission.tint = transmissionTintThickness.rgb;
surface.transmission.thickness = transmissionTintThickness.w;
surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams;
// ------- Anisotropy -------
if (o_enableAnisotropy)
{
// Convert the angle from [0..1] = [0 .. 180 degrees] to radians [0 .. PI]
const float anisotropyAngle = MaterialSrg::m_anisotropicAngle * PI;
const float anisotropyFactor = MaterialSrg::m_anisotropicFactor;
surface.anisotropy.Init(surface.normal, tangents[0], bitangents[0], anisotropyAngle, anisotropyFactor, surface.roughnessA);
}
// ------- Lighting Data -------
LightingData lightingData;
// Light iterator
lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData);
lightingData.Init(surface.position, surface.normal, surface.roughnessLinear);
// Directional light shadow coordinates
lightingData.shadowCoords = IN.m_shadowCoords;
// ------- Occlusion -------
lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture);
lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture);
// ------- Emissive -------
float2 emissiveUv = IN.m_uv[MaterialSrg::m_emissiveMapUvIndex];
lightingData.emissiveLighting = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture);
// ------- Clearcoat -------
float clearCoatFactor = 0.0;
float clearCoatRoughness = 0.0;
float3 clearCoatNormal = float3(0.0, 0.0, 0.0);
// TODO: Clean up the double uses of these clear coat flags
if(o_clearCoat_enabled && o_clearCoat_feature_enabled)
// [GFX TODO][ATOM-14603]: Clean up the double uses of these clear coat flags
if(o_clearCoat_feature_enabled)
{
float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, IN.m_uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture,
MaterialSrg::m_clearCoatRoughnessMap, IN.m_uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture,
MaterialSrg::m_clearCoatNormalMap, IN.m_uv[MaterialSrg::m_clearCoatNormalMapUvIndex], IN.m_normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength,
uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex],
MaterialSrg::m_sampler, isFrontFace,
clearCoatFactor, clearCoatRoughness, clearCoatNormal);
if(o_clearCoat_enabled)
{
float3x3 uvMatrix = MaterialSrg::m_clearCoatNormalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
GetClearCoatInputs(MaterialSrg::m_clearCoatInfluenceMap, IN.m_uv[MaterialSrg::m_clearCoatInfluenceMapUvIndex], MaterialSrg::m_clearCoatFactor, o_clearCoat_factor_useTexture,
MaterialSrg::m_clearCoatRoughnessMap, IN.m_uv[MaterialSrg::m_clearCoatRoughnessMapUvIndex], MaterialSrg::m_clearCoatRoughness, o_clearCoat_roughness_useTexture,
MaterialSrg::m_clearCoatNormalMap, IN.m_uv[MaterialSrg::m_clearCoatNormalMapUvIndex], IN.m_normal, o_clearCoat_normal_useTexture, MaterialSrg::m_clearCoatNormalStrength,
uvMatrix, tangents[MaterialSrg::m_clearCoatNormalMapUvIndex], bitangents[MaterialSrg::m_clearCoatNormalMapUvIndex],
MaterialSrg::m_sampler, isFrontFace,
surface.clearCoat.factor, surface.clearCoat.roughness, surface.clearCoat.normal);
}
// manipulate base layer f0 if clear coat is enabled
// modify base layer's normal incidence reflectance
// for the derivation of the following equation please refer to:
// https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification
float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0));
surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor);
}
// Diffuse and Specular response (used in IBL calculations)
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
lightingData.diffuseResponse = 1.0 - lightingData.specularResponse;
if(o_clearCoat_feature_enabled)
{
// Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04
lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor);
}
// ------- Multiscatter -------
lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation);
// ------- Lighting Calculation -------
// Convert the angle from [0..1] = [0 .. 180 degrees] to radians [0 .. PI]
const float2 anisotropy = float2(MaterialSrg::m_anisotropicAngle * PI, MaterialSrg::m_anisotropicFactor);
// Apply Decals
ApplyDecals(lightingData.tileIterator, surface);
PbrLightingOutput lightingOutput = PbrLighting(IN,
baseColor, metallic, roughness, specularF0Factor,
normal, IN.m_tangent, IN.m_bitangent, anisotropy,
emissive, diffuseAmbientOcclusion, specularOcclusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode);
// Apply Direct Lighting
ApplyDirectLighting(surface, lightingData);
// Apply Image Based Lighting (IBL)
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent)
{
alpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; // Increase opacity at grazing angles.
}
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);
// ------- Opacity -------
@@ -50,5 +50,5 @@
]
},
"DrawList" : "forward"
}
"DrawList" : "forwardWithSubsurfaceOutput"
}
@@ -49,5 +49,5 @@
]
},
"DrawList" : "forward"
"DrawList" : "forwardWithSubsurfaceOutput"
}
@@ -11,7 +11,6 @@
*/
#include <scenesrg.srgi>
#include <viewsrg.srgi>
#include "EnhancedPBR_Common.azsli"
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
@@ -10,11 +10,24 @@
*
*/
#include <viewsrg.srgi>
#include "Skin_Common.azsli"
// SRGs
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
// Pass Output
#include <Atom/Features/PBR/ForwardSubsurfacePassOutput.azsli>
// Utility
#include <Atom/Features/ColorManagement/TransformColor.azsli>
#include <Atom/Features/PBR/AlphaUtils.azsli> // TODO: Remove this after OpacityMode is removed from LightingModel
// Custom Surface & Lighting
#include <Atom/Features/PBR/Lighting/SkinLighting.azsli>
// Decals
#include <Atom/Features/PBR/Decals.azsli>
// ---------- Material Parameters ----------
@@ -53,6 +66,8 @@ option bool o_blendMask_isBound;
#include "MaterialInputs/TransmissionInput.azsli"
// ---------- Vertex Shader ----------
struct VSInput
{
// Base fields (required by the template azsli file)...
@@ -89,8 +104,6 @@ struct VSOutput
float4 m_blendMask : UV8;
};
#include <Atom/Features/PBR/AlphaUtils.azsli> // TODO: Remove this after OpacityMode is removed from LightingModel
#include <Atom/Features/PBR/LightingModel.azsli>
#include <Atom/Features/Vertex/VertexHelper.azsli>
VSOutput SkinVS(VSInput IN)
@@ -131,6 +144,9 @@ VSOutput SkinVS(VSInput IN)
return OUT;
}
// ---------- Pixel Shader ----------
float3 ApplyBaseColorWrinkleMap(bool shouldApply, float3 baseColor, Texture2D map, sampler mapSampler, float2 uv, float factor)
{
if (shouldApply)
@@ -177,6 +193,9 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
PrepareGeneratedTangent(IN.m_normal, IN.m_worldPosition, isFrontFace, IN.m_uv, UvSetCount, tangents, bitangents, startIndex);
}
Surface surface;
surface.position = IN.m_worldPosition;
// ------- Detail Layer Setup -------
// When the detail maps and the detail blend mask are on the same UV, they both use the transformed detail UVs because they are 'attached' to each other
@@ -212,19 +231,18 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture4, normalMapSample, MaterialSrg::m_wrinkle_normal_texture4, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_blendMask.a);
}
float3 normalWS;
if(o_detail_normal_useTexture)
{
float3 normalTS = GetTangentSpaceNormal(normalMapSample, uvMatrix, MaterialSrg::m_normalFactor);
bool applyOverlay = true;
normalWS = ApplyNormalMapOverlayWS(applyOverlay, IN.m_normal, normalTS, tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex],
surface.normal = ApplyNormalMapOverlayWS(applyOverlay, IN.m_normal, normalTS, tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex],
MaterialSrg::m_detail_normal_texture, MaterialSrg::m_sampler, IN.m_detailUv, MaterialSrg::m_detail_normal_flipX, MaterialSrg::m_detail_normal_flipY,
detailLayerNormalFactor, tangents[MaterialSrg::m_detail_allMapsUvIndex], bitangents[MaterialSrg::m_detail_allMapsUvIndex], MaterialSrg::m_detailUvMatrix);
}
else
{
normalWS = GetWorldSpaceNormal(normalMapSample, IN.m_normal, tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex],
surface.normal = GetWorldSpaceNormal(normalMapSample, IN.m_normal, tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex],
uvMatrix, MaterialSrg::m_normalFactor);
}
@@ -265,23 +283,29 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
baseColor = ApplyTextureOverlay(o_detail_baseColor_useTexture, baseColor, MaterialSrg::m_detail_baseColor_texture, MaterialSrg::m_sampler, IN.m_detailUv, detailLayerBaseColorFactor);
// ------- Roughness -------
float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex];
float roughness = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor,
MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture);
// ------- Occlusion -------
float diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture);
float specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture);
if(o_wrinkleLayers_enabled && o_wrinkleLayers_showBlendMaskValues && o_blendMask_isBound)
{
// Overlay debug colors to highlight the different blend weights coming from the vertex color stream.
if(o_wrinkleLayers_count > 0) { baseColor = lerp(baseColor, float3(1,0,0), IN.m_blendMask.r); }
if(o_wrinkleLayers_count > 1) { baseColor = lerp(baseColor, float3(0,1,0), IN.m_blendMask.g); }
if(o_wrinkleLayers_count > 2) { baseColor = lerp(baseColor, float3(0,0,1), IN.m_blendMask.b); }
if(o_wrinkleLayers_count > 3) { baseColor = lerp(baseColor, float3(1,1,1), IN.m_blendMask.a); }
}
// ------- Specular -------
float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex];
float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor);
// ------- Roughness -------
float2 roughnessUv = IN.m_uv[MaterialSrg::m_roughnessMapUvIndex];
surface.roughnessLinear = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor,
MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture);
surface.CalculateRoughnessA();
// ------- Subsurface -------
float2 subsurfaceUv = IN.m_uv[MaterialSrg::m_subsurfaceScatteringInfluenceMapUvIndex];
@@ -291,29 +315,49 @@ PbrLightingOutput SkinPS_Common(VSOutput IN)
float2 transmissionUv = IN.m_uv[MaterialSrg::m_transmissionThicknessMapUvIndex];
float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness);
surface.transmission.tint = transmissionTintThickness.rgb;
surface.transmission.thickness = transmissionTintThickness.w;
surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams;
// ------- Lighting Data -------
LightingData lightingData;
// Light iterator
lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData);
lightingData.Init(surface.position, surface.normal, surface.roughnessLinear);
// Directional light shadow coordinates
lightingData.shadowCoords = IN.m_shadowCoords;
// Diffuse and Specular response (used in IBL calculations)
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
lightingData.diffuseResponse = 1.0 - lightingData.specularResponse;
// ------- Occlusion -------
lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture);
lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture);
// ------- Lighting Calculation -------
if(o_wrinkleLayers_enabled && o_wrinkleLayers_showBlendMaskValues && o_blendMask_isBound)
{
// Overlay debug colors to highlight the different blend weights coming from the vertex color stream.
if(o_wrinkleLayers_count > 0) { baseColor = lerp(baseColor, float3(1,0,0), IN.m_blendMask.r); }
if(o_wrinkleLayers_count > 1) { baseColor = lerp(baseColor, float3(0,1,0), IN.m_blendMask.g); }
if(o_wrinkleLayers_count > 2) { baseColor = lerp(baseColor, float3(0,0,1), IN.m_blendMask.b); }
if(o_wrinkleLayers_count > 3) { baseColor = lerp(baseColor, float3(1,1,1), IN.m_blendMask.a); }
}
surface.clearCoat.factor = 0.0;
surface.clearCoat.roughness = 0.0;
surface.clearCoat.normal = float3(0.0, 0.0, 0.0);
float metallic = 0;
float3 emissive = float3(0,0,0);
float2 anisotropy = float2(0,0);
float clearCoatFactor = 0.0;
float clearCoatRoughness = 0.0;
float3 clearCoatNormal = float3(0.0, 0.0, 0.0);
float alpha = 1;
// Apply Decals
ApplyDecals(lightingData.tileIterator, surface);
PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor,
normalWS, tangents[0], bitangents[0], anisotropy,
emissive, diffuseAmbientOcclusion, specularOcclusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode);
// Apply Direct Lighting
ApplyDirectLighting(surface, lightingData);
// Apply Image Based Lighting (IBL)
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData);
// ------- Preparing output -------
@@ -42,5 +42,5 @@
]
},
"DrawList" : "forward"
"DrawList" : "forwardWithSubsurfaceOutput"
}
@@ -13,6 +13,7 @@
#pragma once
#include <Atom/Features/SrgSemantics.azsli>
#include <viewsrg.srgi>
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
#include "MaterialInputs/BaseColorInput.azsli"
@@ -10,10 +10,23 @@
*
*/
// SRGs
#include <viewsrg.srgi>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
// Pass Output
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
// Utility
#include <Atom/Features/ColorManagement/TransformColor.azsli>
#include <Atom/Features/PBR/AlphaUtils.azsli>
// Custom Surface & Lighting
#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
// Decals
#include <Atom/Features/PBR/Decals.azsli>
// ---------- Material Parameters ----------
@@ -47,6 +60,9 @@ DEFINE_LAYER_OPTIONS(o_layer3_)
#include "MaterialInputs/TransmissionInput.azsli"
#include "StandardMultilayerPBR_Common.azsli"
// ---------- Vertex Shader ----------
struct VSInput
{
// Base fields (required by the template azsli file)...
@@ -83,8 +99,6 @@ struct VSOutput
float3 m_blendMask : UV7;
};
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/LightingModel.azsli>
#include <Atom/Features/Vertex/VertexHelper.azsli>
VSOutput ForwardPassVS(VSInput IN)
@@ -115,6 +129,9 @@ VSOutput ForwardPassVS(VSInput IN)
return OUT;
}
// ---------- Pixel Shader ----------
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth)
{
depth = IN.m_position.z;
@@ -144,14 +161,14 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
if(o_debugDrawMode == DebugDrawMode::BlendMaskValues)
{
float3 blendMaskValues = GetBlendMaskValues(IN.m_uv[MaterialSrg::m_blendMaskUvIndex], IN.m_blendMask);
return MakeDebugOutput(IN, blendMaskValues);
return DebugOutput(blendMaskValues);
}
if(o_debugDrawMode == DebugDrawMode::DepthMaps)
{
GetDepth_Setup(IN.m_blendMask);
float depth = GetDepth(IN.m_uv[MaterialSrg::m_parallaxUvIndex], float2(0,0), float2(0,0));
return MakeDebugOutput(IN, float3(depth,depth,depth));
return DebugOutput(float3(depth,depth,depth));
}
// ------- Parallax -------
@@ -179,6 +196,9 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
}
}
Surface surface;
surface.position = IN.m_worldPosition;
// ------- Setup the per-layer UV transforms -------
float2 uvLayer1[UvSetCount];
@@ -222,7 +242,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float3 normalTS = ReorientTangentSpaceNormal(layer1_normalTS, layer2_normalTS);
normalTS = ReorientTangentSpaceNormal(normalTS, layer3_normalTS);
// [GFX TODO][ATOM-14591]: This will only work if the normal maps all use the same UV stream. We would need to add support for having them in different UV streams.
float3 normalWS = normalize(TangentSpaceToWorld(normalTS, IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex]));
surface.normal = normalize(TangentSpaceToWorld(normalTS, IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex]));
// ------- Base Color -------
@@ -244,14 +264,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float layer3_metallic = GetMetallicInput(MaterialSrg::m_layer3_m_metallicMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_metallicMapUvIndex], MaterialSrg::m_layer3_m_metallicFactor, o_layer3_o_metallic_useTexture);
metallic = BlendLayers(layer1_metallic, layer2_metallic, layer3_metallic, blendMaskValues);
}
// ------- Roughness -------
float layer1_roughness = GetRoughnessInput(MaterialSrg::m_layer1_m_roughnessMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_roughnessMapUvIndex], MaterialSrg::m_layer1_m_roughnessFactor, MaterialSrg::m_layer1_m_roughnessLowerBound, MaterialSrg::m_layer1_m_roughnessUpperBound, o_layer1_o_roughness_useTexture);
float layer2_roughness = GetRoughnessInput(MaterialSrg::m_layer2_m_roughnessMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_roughnessMapUvIndex], MaterialSrg::m_layer2_m_roughnessFactor, MaterialSrg::m_layer2_m_roughnessLowerBound, MaterialSrg::m_layer2_m_roughnessUpperBound, o_layer2_o_roughness_useTexture);
float layer3_roughness = GetRoughnessInput(MaterialSrg::m_layer3_m_roughnessMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_roughnessMapUvIndex], MaterialSrg::m_layer3_m_roughnessFactor, MaterialSrg::m_layer3_m_roughnessLowerBound, MaterialSrg::m_layer3_m_roughnessUpperBound, o_layer3_o_roughness_useTexture);
float roughness = BlendLayers(layer1_roughness, layer2_roughness, layer3_roughness, blendMaskValues);
// ------- Specular -------
float layer1_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer1_m_specularF0Map, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_specularF0MapUvIndex], MaterialSrg::m_layer1_m_specularF0Factor, o_layer1_o_specularF0_useTexture);
@@ -259,24 +272,16 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float layer3_specularF0Factor = GetSpecularInput(MaterialSrg::m_layer3_m_specularF0Map, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_specularF0MapUvIndex], MaterialSrg::m_layer3_m_specularF0Factor, o_layer3_o_specularF0_useTexture);
float specularF0Factor = BlendLayers(layer1_specularF0Factor, layer2_specularF0Factor, layer3_specularF0Factor, blendMaskValues);
// ------- Emissive -------
float3 layer1_emissive = GetEmissiveInput(MaterialSrg::m_layer1_m_emissiveMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_emissiveMapUvIndex], MaterialSrg::m_layer1_m_emissiveIntensity, MaterialSrg::m_layer1_m_emissiveColor.rgb, o_layer1_o_emissiveEnabled, o_layer1_o_emissive_useTexture);
float3 layer2_emissive = GetEmissiveInput(MaterialSrg::m_layer2_m_emissiveMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_emissiveMapUvIndex], MaterialSrg::m_layer2_m_emissiveIntensity, MaterialSrg::m_layer2_m_emissiveColor.rgb, o_layer2_o_emissiveEnabled, o_layer2_o_emissive_useTexture);
float3 layer3_emissive = GetEmissiveInput(MaterialSrg::m_layer3_m_emissiveMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_emissiveMapUvIndex], MaterialSrg::m_layer3_m_emissiveIntensity, MaterialSrg::m_layer3_m_emissiveColor.rgb, o_layer3_o_emissiveEnabled, o_layer3_o_emissive_useTexture);
float3 emissive = BlendLayers(layer1_emissive, layer2_emissive, layer3_emissive, blendMaskValues);
surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic);
// ------- Occlusion -------
float layer1_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer1_m_diffuseOcclusionFactor, o_layer1_o_diffuseOcclusion_useTexture);
float layer2_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer2_m_diffuseOcclusionFactor, o_layer2_o_diffuseOcclusion_useTexture);
float layer3_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer3_m_diffuseOcclusionFactor, o_layer3_o_diffuseOcclusion_useTexture);
float diffuseAmbientOcclusion = BlendLayers(layer1_diffuseAmbientOcclusion, layer2_diffuseAmbientOcclusion, layer3_diffuseAmbientOcclusion, blendMaskValues);
// ------- Roughness -------
float layer1_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer1_m_specularOcclusionFactor, o_layer1_o_specularOcclusion_useTexture);
float layer2_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer2_m_specularOcclusionFactor, o_layer2_o_specularOcclusion_useTexture);
float layer3_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer3_m_specularOcclusionFactor, o_layer3_o_specularOcclusion_useTexture);
float specularOcclusion = BlendLayers(layer1_specularOcclusion, layer2_specularOcclusion, layer3_specularOcclusion, blendMaskValues);
float layer1_roughness = GetRoughnessInput(MaterialSrg::m_layer1_m_roughnessMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_roughnessMapUvIndex], MaterialSrg::m_layer1_m_roughnessFactor, MaterialSrg::m_layer1_m_roughnessLowerBound, MaterialSrg::m_layer1_m_roughnessUpperBound, o_layer1_o_roughness_useTexture);
float layer2_roughness = GetRoughnessInput(MaterialSrg::m_layer2_m_roughnessMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_roughnessMapUvIndex], MaterialSrg::m_layer2_m_roughnessFactor, MaterialSrg::m_layer2_m_roughnessLowerBound, MaterialSrg::m_layer2_m_roughnessUpperBound, o_layer2_o_roughness_useTexture);
float layer3_roughness = GetRoughnessInput(MaterialSrg::m_layer3_m_roughnessMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_roughnessMapUvIndex], MaterialSrg::m_layer3_m_roughnessFactor, MaterialSrg::m_layer3_m_roughnessLowerBound, MaterialSrg::m_layer3_m_roughnessUpperBound, o_layer3_o_roughness_useTexture);
surface.roughnessLinear = BlendLayers(layer1_roughness, layer2_roughness, layer3_roughness, blendMaskValues);
surface.CalculateRoughnessA();
// ------- Subsurface -------
@@ -287,14 +292,46 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
float2 transmissionUv = IN.m_uv[MaterialSrg::m_transmissionThicknessMapUvIndex];
float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness);
surface.transmission.tint = transmissionTintThickness.rgb;
surface.transmission.thickness = transmissionTintThickness.w;
surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams;
// ------- Lighting Data -------
LightingData lightingData;
// Light iterator
lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData);
lightingData.Init(surface.position, surface.normal, surface.roughnessLinear);
// Directional light shadow coordinates
lightingData.shadowCoords = IN.m_shadowCoords;
// ------- Emissive -------
float3 layer1_emissive = GetEmissiveInput(MaterialSrg::m_layer1_m_emissiveMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_emissiveMapUvIndex], MaterialSrg::m_layer1_m_emissiveIntensity, MaterialSrg::m_layer1_m_emissiveColor.rgb, o_layer1_o_emissiveEnabled, o_layer1_o_emissive_useTexture);
float3 layer2_emissive = GetEmissiveInput(MaterialSrg::m_layer2_m_emissiveMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_emissiveMapUvIndex], MaterialSrg::m_layer2_m_emissiveIntensity, MaterialSrg::m_layer2_m_emissiveColor.rgb, o_layer2_o_emissiveEnabled, o_layer2_o_emissive_useTexture);
float3 layer3_emissive = GetEmissiveInput(MaterialSrg::m_layer3_m_emissiveMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_emissiveMapUvIndex], MaterialSrg::m_layer3_m_emissiveIntensity, MaterialSrg::m_layer3_m_emissiveColor.rgb, o_layer3_o_emissiveEnabled, o_layer3_o_emissive_useTexture);
lightingData.emissiveLighting = BlendLayers(layer1_emissive, layer2_emissive, layer3_emissive, blendMaskValues);
// ------- Occlusion -------
float layer1_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer1_m_diffuseOcclusionFactor, o_layer1_o_diffuseOcclusion_useTexture);
float layer2_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer2_m_diffuseOcclusionFactor, o_layer2_o_diffuseOcclusion_useTexture);
float layer3_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer3_m_diffuseOcclusionFactor, o_layer3_o_diffuseOcclusion_useTexture);
lightingData.diffuseAmbientOcclusion = BlendLayers(layer1_diffuseAmbientOcclusion, layer2_diffuseAmbientOcclusion, layer3_diffuseAmbientOcclusion, blendMaskValues);
float layer1_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer1_m_specularOcclusionFactor, o_layer1_o_specularOcclusion_useTexture);
float layer2_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer2_m_specularOcclusionFactor, o_layer2_o_specularOcclusion_useTexture);
float layer3_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer3_m_specularOcclusionFactor, o_layer3_o_specularOcclusion_useTexture);
lightingData.specularOcclusion = BlendLayers(layer1_specularOcclusion, layer2_specularOcclusion, layer3_specularOcclusion, blendMaskValues);
// ------- Clearcoat -------
float clearCoatFactor = 0.0f;
float clearCoatRoughness = 0.0f;
float3 clearCoatNormal = float3(0.0, 0.0, 0.0);
if(o_clearCoat_feature_enabled)
{
// --- Layer 1 ---
float layer1_clearCoatFactor = 0.0f;
float layer1_clearCoatRoughness = 0.0f;
float3 layer1_clearCoatNormal = float3(0.0, 0.0, 0.0);
@@ -310,6 +347,8 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
layer1_clearCoatFactor, layer1_clearCoatRoughness, layer1_clearCoatNormal);
}
// --- Layer 2 ---
float layer2_clearCoatFactor = 0.0f;
float layer2_clearCoatRoughness = 0.0f;
float3 layer2_clearCoatNormal = float3(0.0, 0.0, 0.0);
@@ -325,6 +364,8 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
layer2_clearCoatFactor, layer2_clearCoatRoughness, layer2_clearCoatNormal);
}
// --- Layer 3 ---
float layer3_clearCoatFactor = 0.0f;
float layer3_clearCoatRoughness = 0.0f;
float3 layer3_clearCoatNormal = float3(0.0, 0.0, 0.0);
@@ -340,22 +381,58 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
layer3_clearCoatFactor, layer3_clearCoatRoughness, layer3_clearCoatNormal);
}
clearCoatFactor = BlendLayers(layer1_clearCoatFactor, layer2_clearCoatFactor, layer3_clearCoatFactor, blendMaskValues);
clearCoatRoughness = BlendLayers(layer1_clearCoatRoughness, layer2_clearCoatRoughness, layer3_clearCoatRoughness, blendMaskValues);
// --- Blend Layers ---
surface.clearCoat.factor = BlendLayers(layer1_clearCoatFactor, layer2_clearCoatFactor, layer3_clearCoatFactor, blendMaskValues);
surface.clearCoat.roughness = BlendLayers(layer1_clearCoatRoughness, layer2_clearCoatRoughness, layer3_clearCoatRoughness, blendMaskValues);
// [GFX TODO][ATOM-14592] This is not the right way to blend the normals. We need to use ReorientTangentSpaceNormal(), and that requires GetClearCoatInputs() to return the normal in TS instead of WS.
clearCoatNormal = BlendLayers(layer1_clearCoatNormal, layer2_clearCoatNormal, layer3_clearCoatNormal, blendMaskValues);
clearCoatNormal = normalize(clearCoatNormal);
surface.clearCoat.normal = BlendLayers(layer1_clearCoatNormal, layer2_clearCoatNormal, layer3_clearCoatNormal, blendMaskValues);
surface.clearCoat.normal = normalize(surface.clearCoat.normal);
// manipulate base layer f0 if clear coat is enabled
// modify base layer's normal incidence reflectance
// for the derivation of the following equation please refer to:
// https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification
float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0));
surface.specularF0 = lerp(surface.specularF0, f0 * f0, surface.clearCoat.factor);
}
// Diffuse and Specular response (used in IBL calculations)
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
lightingData.diffuseResponse = 1.0 - lightingData.specularResponse;
if(o_clearCoat_feature_enabled)
{
// Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04
lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor);
}
// ------- Multiscatter -------
lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation);
// ------- Lighting Calculation -------
const float2 anisotropy = 0.0; // Does not affect calculations unless 'o_enableAnisotropy' is enabled
// Apply Decals
ApplyDecals(lightingData.tileIterator, surface);
PbrLightingOutput lightingOutput = PbrLighting(IN,
baseColor, metallic, roughness, specularF0Factor,
normalWS, tangents[0], bitangents[0], anisotropy,
emissive, diffuseAmbientOcclusion, specularOcclusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode);
// Apply Direct Lighting
ApplyDirectLighting(surface, lightingData);
// Apply Image Based Lighting (IBL)
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent)
{
alpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; // Increase opacity at grazing angles.
}
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);
// ------- Opacity -------
@@ -375,7 +452,6 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
// Pack factor and quality, drawback: because of precision limit of float16 cannot represent exact 1, maximum representable value is 0.9961
uint factorAndQuality = dot(round(float2(saturate(surfaceScatteringFactor), MaterialSrg::m_subsurfaceScatteringQuality) * 255), float2(256, 1));
lightingOutput.m_diffuseColor.w = factorAndQuality * (o_enableSubsurfaceScattering ? 1.0 : -1.0);
lightingOutput.m_scatterDistance = MaterialSrg::m_scatterDistance;
}
@@ -394,7 +470,6 @@ ForwardPassOutputWithDepth ForwardPassPS(VSOutput IN, bool isFrontFace : SV_IsFr
OUT.m_specularF0 = lightingOutput.m_specularF0;
OUT.m_albedo = lightingOutput.m_albedo;
OUT.m_normal = lightingOutput.m_normal;
OUT.m_scatterDistance = lightingOutput.m_scatterDistance;
OUT.m_depth = depth;
return OUT;
}
@@ -412,7 +487,6 @@ ForwardPassOutput ForwardPassPS_EDS(VSOutput IN, bool isFrontFace : SV_IsFrontFa
OUT.m_specularF0 = lightingOutput.m_specularF0;
OUT.m_albedo = lightingOutput.m_albedo;
OUT.m_normal = lightingOutput.m_normal;
OUT.m_scatterDistance = lightingOutput.m_scatterDistance;
return OUT;
}
@@ -13,6 +13,7 @@
#pragma once
#include <Atom/Features/SrgSemantics.azsli>
#include <viewsrg.srgi>
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
#include "MaterialInputs/BaseColorInput.azsli"
@@ -10,7 +10,6 @@
*
*/
#include <viewsrg.srgi>
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include "./StandardPBR_Common.azsli"
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
@@ -10,11 +10,25 @@
*
*/
#include <viewsrg.srgi>
#include "StandardPBR_Common.azsli"
// SRGs
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
// Pass Output
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
// Utility
#include <Atom/Features/ColorManagement/TransformColor.azsli>
#include <Atom/Features/PBR/AlphaUtils.azsli>
// Custom Surface & Lighting
#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
// Decals
#include <Atom/Features/PBR/Decals.azsli>
// ---------- Material Parameters ----------
@@ -38,6 +52,8 @@ COMMON_OPTIONS_PARALLAX()
#include "MaterialInputs/TransmissionInput.azsli"
// ---------- Vertex Shader ----------
struct VSInput
{
// Base fields (required by the template azsli file)...
@@ -66,8 +82,6 @@ struct VSOutput
float2 m_uv[UvSetCount] : UV1;
};
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/LightingModel.azsli>
#include <Atom/Features/Vertex/VertexHelper.azsli>
VSOutput StandardPbr_ForwardPassVS(VSInput IN)
@@ -85,6 +99,9 @@ VSOutput StandardPbr_ForwardPassVS(VSInput IN)
return OUT;
}
// ---------- Pixel Shader ----------
PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float depth)
{
// ------- Tangents & Bitangets -------
@@ -112,7 +129,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
{
float3x3 uvMatrix = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3();
float3x3 uvMatrixInverse = MaterialSrg::m_parallaxUvIndex == 0 ? MaterialSrg::m_uvMatrixInverse : CreateIdentity3x3();
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor,
GetParallaxInput(IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex], MaterialSrg::m_depthFactor,
ObjectSrg::GetWorldMatrix(), uvMatrix, uvMatrixInverse,
IN.m_uv[MaterialSrg::m_parallaxUvIndex], IN.m_worldPosition, depth);
@@ -130,7 +147,6 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
Surface surface;
surface.position = IN.m_worldPosition.xyz;
// ------- Alpha & Clip -------
float2 baseColorUv = IN.m_uv[MaterialSrg::m_baseColorMapUvIndex];
@@ -162,9 +178,9 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
// ------- Specular -------
float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex];
float specularF0 = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
float specularF0Factor = GetSpecularInput(MaterialSrg::m_specularF0Map, MaterialSrg::m_sampler, specularUv, MaterialSrg::m_specularF0Factor, o_specularF0_useTexture);
surface.SetAlbedoAndSpecularF0(baseColor, specularF0, metallic);
surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic);
// ------- Roughness -------
@@ -175,25 +191,8 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
// ------- Subsurface -------
float2 subsurfaceUv = IN.m_uv[MaterialSrg::m_subsurfaceScatteringInfluenceMapUvIndex];
float surfaceScatteringFactor = GetSubsurfaceInput(MaterialSrg::m_subsurfaceScatteringInfluenceMap, MaterialSrg::m_sampler, subsurfaceUv, MaterialSrg::m_subsurfaceScatteringFactor);
// ------- Transmission -------
float2 transmissionUv = IN.m_uv[MaterialSrg::m_transmissionThicknessMapUvIndex];
float4 transmissionTintThickness = GeTransmissionInput(MaterialSrg::m_transmissionThicknessMap, MaterialSrg::m_sampler, transmissionUv, MaterialSrg::m_transmissionTintThickness);
surface.transmission.tint = transmissionTintThickness.rgb;
surface.transmission.thickness = transmissionTintThickness.w;
surface.transmission.transmissionParams = MaterialSrg::m_transmissionParams;
// ------- Anisotropy -------
if (o_enableAnisotropy)
{
const float anisotropyAngle = 0.0f;
const float anisotropyFactor = 0.0f;
surface.anisotropy.Init(surface.normal, tangents[0], bitangents[0], anisotropyAngle, anisotropyFactor, surface.roughnessA);
}
float surfaceScatteringFactor = 0.0f;
surface.transmission.InitializeToZero();
// ------- Lighting Data -------
@@ -250,9 +249,9 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float
lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor);
}
// Multiscatter compensation factor
lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation);
// ------- Multiscatter -------
lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation);
// ------- Lighting Calculation -------
@@ -312,8 +311,8 @@ ForwardPassOutputWithDepth StandardPbr_ForwardPassPS(VSOutput IN, bool isFrontFa
OUT.m_specularF0 = lightingOutput.m_specularF0;
OUT.m_albedo = lightingOutput.m_albedo;
OUT.m_normal = lightingOutput.m_normal;
OUT.m_scatterDistance = lightingOutput.m_scatterDistance;
OUT.m_depth = depth;
return OUT;
}
@@ -330,7 +329,6 @@ ForwardPassOutput StandardPbr_ForwardPassPS_EDS(VSOutput IN, bool isFrontFace :
OUT.m_specularF0 = lightingOutput.m_specularF0;
OUT.m_albedo = lightingOutput.m_albedo;
OUT.m_normal = lightingOutput.m_normal;
OUT.m_scatterDistance = lightingOutput.m_scatterDistance;
return OUT;
}
@@ -11,7 +11,6 @@
*/
#include <scenesrg.srgi>
#include <viewsrg.srgi>
#include "StandardPBR_Common.azsli"
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
@@ -148,22 +148,6 @@
},
"LoadAction": "Clear"
}
},
{
"Name": "ScatterDistanceOutput",
"SlotType": "Output",
"ScopeAttachmentUsage": "RenderTarget",
"LoadStoreAction": {
"ClearValue": {
"Value": [
0.0,
0.0,
0.0,
0.0
]
},
"LoadAction": "Clear"
}
}
],
"ImageAttachments": [
@@ -258,23 +242,6 @@
"AssetRef": {
"FilePath": "Textures/BRDFTexture.attimage"
}
},
{
"Name": "ScatterDistanceImage",
"SizeSource": {
"Source": {
"Pass": "Parent",
"Attachment": "SwapChainOutput"
}
},
"MultisampleSource": {
"Pass": "This",
"Attachment": "DepthStencilInputOutput"
},
"ImageDescriptor": {
"Format": "R11G11B10_FLOAT",
"SharedQueueMask": "Graphics"
}
}
],
"Connections": [
@@ -319,13 +286,6 @@
"Pass": "This",
"Attachment": "BRDFTexture"
}
},
{
"LocalSlot": "ScatterDistanceOutput",
"AttachmentRef": {
"Pass": "This",
"Attachment": "ScatterDistanceImage"
}
}
]
}
@@ -0,0 +1,158 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PassAsset",
"ClassData": {
"PassTemplate": {
"Name": "ForwardSubsurfaceMSAAPassTemplate",
"PassClass": "RasterPass",
"Slots": [
// Inputs...
{
"Name": "BRDFTextureInput",
"ShaderInputName": "m_brdfMap",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader"
},
{
"Name": "DirectionalLightShadowmap",
"ShaderInputName": "m_directionalLightShadowmap",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ImageViewDesc": {
"IsArray": 1
}
},
{
"Name": "ExponentialShadowmapDirectional",
"ShaderInputName": "m_directionalLightExponentialShadowmap",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ImageViewDesc": {
"IsArray": 1
}
},
{
"Name": "ProjectedShadowmap",
"ShaderInputName": "m_projectedShadowmaps",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ImageViewDesc": {
"IsArray": 1
}
},
{
"Name": "ExponentialShadowmapProjected",
"ShaderInputName": "m_projectedExponentialShadowmap",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ImageViewDesc": {
"IsArray": 1
}
},
{
"Name": "TileLightData",
"SlotType": "Input",
"ShaderInputName": "m_tileLightData",
"ScopeAttachmentUsage": "Shader"
},
{
"Name": "LightListRemapped",
"SlotType": "Input",
"ShaderInputName": "m_lightListRemapped",
"ScopeAttachmentUsage": "Shader"
},
// Input/Outputs...
{
"Name": "DepthStencilInputOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "DepthStencil"
},
{
"Name": "DiffuseOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
},
{
"Name": "SpecularOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
},
{
"Name": "AlbedoOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
},
{
"Name": "SpecularF0Output",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
},
{
"Name": "NormalOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
},
// Outputs...
{
"Name": "ScatterDistanceOutput",
"SlotType": "Output",
"ScopeAttachmentUsage": "RenderTarget",
"LoadStoreAction": {
"ClearValue": {
"Value": [
0.0,
0.0,
0.0,
0.0
]
},
"LoadAction": "Clear"
}
}
],
"ImageAttachments": [
{
"Name": "BRDFTexture",
"Lifetime": "Imported",
"AssetRef": {
"FilePath": "Textures/BRDFTexture.attimage"
}
},
{
"Name": "ScatterDistanceImage",
"SizeSource": {
"Source": {
"Pass": "Parent",
"Attachment": "SwapChainOutput"
}
},
"MultisampleSource": {
"Pass": "This",
"Attachment": "DepthStencilInputOutput"
},
"ImageDescriptor": {
"Format": "R11G11B10_FLOAT",
"SharedQueueMask": "Graphics"
}
}
],
"Connections": [
{
"LocalSlot": "BRDFTextureInput",
"AttachmentRef": {
"Pass": "This",
"Attachment": "BRDFTexture"
}
},
{
"LocalSlot": "ScatterDistanceOutput",
"AttachmentRef": {
"Pass": "This",
"Attachment": "ScatterDistanceImage"
}
}
]
}
}
}
@@ -127,6 +127,106 @@
}
}
},
{
"Name": "ForwardSubsurfaceMSAAPass",
"TemplateName": "ForwardSubsurfaceMSAAPassTemplate",
"Connections": [
// Inputs...
{
"LocalSlot": "DirectionalLightShadowmap",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "DirectionalShadowmap"
}
},
{
"LocalSlot": "ExponentialShadowmapDirectional",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "DirectionalESM"
}
},
{
"LocalSlot": "ProjectedShadowmap",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "ProjectedShadowmap"
}
},
{
"LocalSlot": "ExponentialShadowmapProjected",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "ProjectedESM"
}
},
{
"LocalSlot": "TileLightData",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "TileLightData"
}
},
{
"LocalSlot": "LightListRemapped",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "LightListRemapped"
}
},
// Input/Outputs...
{
"LocalSlot": "DepthStencilInputOutput",
"AttachmentRef": {
"Pass": "Parent",
"Attachment": "DepthStencil"
}
},
{
"LocalSlot": "DiffuseOutput",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Attachment": "DiffuseOutput"
}
},
{
"LocalSlot": "SpecularOutput",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Attachment": "SpecularOutput"
}
},
{
"LocalSlot": "AlbedoOutput",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Attachment": "AlbedoOutput"
}
},
{
"LocalSlot": "SpecularF0Output",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Attachment": "SpecularF0Output"
}
},
{
"LocalSlot": "NormalOutput",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Attachment": "NormalOutput"
}
}
],
"PassData": {
"$type": "RasterPassData",
"DrawListTag": "forwardWithSubsurfaceOutput",
"PipelineViewTag": "MainCamera",
"PassSrgAsset": {
"FilePath": "shaderlib/atom/features/pbr/forwardpasssrg.azsli:PassSrg"
}
}
},
{
"Name": "DiffuseGlobalIlluminationPass",
"TemplateName": "DiffuseGlobalIlluminationPassTemplate",
@@ -320,7 +420,7 @@
{
"LocalSlot": "Input",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Pass": "ForwardSubsurfaceMSAAPass",
"Attachment": "ScatterDistanceOutput"
}
}
@@ -48,6 +48,10 @@
"Name": "ForwardMSAAPassTemplate",
"Path": "Passes/ForwardMSAA.pass"
},
{
"Name": "ForwardSubsurfaceMSAAPassTemplate",
"Path": "Passes/ForwardSubsurfaceMSAA.pass"
},
{
"Name": "MainPipeline",
"Path": "Passes/MainPipeline.pass"
@@ -12,7 +12,6 @@
#pragma once
// TODO: Move this to LightingModel.azsli
option enum class OpacityMode {Opaque, Cutout, Blended, TintedTransparent} o_opacity_mode;
void CheckClipping(float alpha, float opacityFactor)
@@ -1,7 +1,23 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
// ------------------------------------------------------------------------------
// NOTE: The following must be included or defined before including this file:
// - Surface - LightingData
// ---------------------------------------------------------------------------------
#include <Atom/Features/PBR/LightingOptions.azsli>
#include <Atom/Features/PBR/Surface.azsli>
// Analytical integation (approximation) of diffusion profile over radius, could be replaced by other pre integrated kernels
// such as sum of Gaussian
@@ -12,23 +12,27 @@
#pragma once
// ------------------------------------------------------------------------------
// NOTE: The following must be included or defined before including this file:
// - Surface
// ---------------------------------------------------------------------------------
#include <Atom/Features/MatrixUtility.azsli>
#include <Atom/Features/Decals/DecalTextureUtil.azsli>
#include <Atom/Features/LightCulling/LightCullingTileIterator.azsli>
#include <Atom/Features/PBR/Surface.azsli>
void ApplyDecal(uint currDecalIndex, inout Surface surface);
void ApplyDecals(inout LightCullingTileIterator tileIterator, inout Surface surface)
{
tileIterator.LoadAdvance();
while( !tileIterator.IsDone() )
{
uint currDecalIndex = tileIterator.GetValue();
while( !tileIterator.IsDone() )
{
uint currDecalIndex = tileIterator.GetValue();
tileIterator.LoadAdvance();
ApplyDecal(currDecalIndex, surface);
ApplyDecal(currDecalIndex, surface);
}
}
@@ -44,13 +48,13 @@ float GetDecalAttenuation(float3 surfNormal, float3 decalUp, float decalAngleAtt
void ApplyDecal(uint currDecalIndex, inout Surface surface)
{
ViewSrg::Decal decal = ViewSrg::m_decals[currDecalIndex];
ViewSrg::Decal decal = ViewSrg::m_decals[currDecalIndex];
float3x3 decalRot = MatrixFromQuaternion(decal.m_quaternion);
float3 localPos = surface.position - decal.m_position;
float3 localPos = surface.position - decal.m_position;
localPos = mul(localPos, decalRot);
float3 decalUVW = localPos * rcp(decal.m_halfSize);
if(decalUVW.x >= -1.0f && decalUVW.x <= 1.0f &&
decalUVW.y >= -1.0f && decalUVW.y <= 1.0f &&
@@ -70,25 +74,23 @@ void ApplyDecal(uint currDecalIndex, inout Surface surface)
switch(textureArrayIndex)
{
case 0:
baseMap = ViewSrg::m_decalTextureArray0.Sample(PassSrg::LinearSampler, decalUV);
baseMap = ViewSrg::m_decalTextureArray0.Sample(PassSrg::LinearSampler, decalUV);
break;
case 1:
baseMap = ViewSrg::m_decalTextureArray1.Sample(PassSrg::LinearSampler, decalUV);
baseMap = ViewSrg::m_decalTextureArray1.Sample(PassSrg::LinearSampler, decalUV);
break;
case 2:
baseMap = ViewSrg::m_decalTextureArray2.Sample(PassSrg::LinearSampler, decalUV);
baseMap = ViewSrg::m_decalTextureArray2.Sample(PassSrg::LinearSampler, decalUV);
break;
case 3:
baseMap = ViewSrg::m_decalTextureArray3.Sample(PassSrg::LinearSampler, decalUV);
baseMap = ViewSrg::m_decalTextureArray3.Sample(PassSrg::LinearSampler, decalUV);
break;
case 4:
baseMap = ViewSrg::m_decalTextureArray4.Sample(PassSrg::LinearSampler, decalUV);
baseMap = ViewSrg::m_decalTextureArray4.Sample(PassSrg::LinearSampler, decalUV);
break;
}
float opacity = baseMap.a * decal.m_opacity * GetDecalAttenuation(surface.normal, decalRot[2], decal.m_angleAttenuation);
surface.albedo = lerp(surface.albedo, baseMap.rgb, opacity);
}
float opacity = baseMap.a * decal.m_opacity * GetDecalAttenuation(surface.normal, decalRot[2], decal.m_angleAttenuation);
surface.albedo = lerp(surface.albedo, baseMap.rgb, opacity);
}
}
@@ -17,7 +17,6 @@ struct ForwardPassOutput
float4 m_albedo : SV_Target2; //!< RGB = Surface albedo pre-multiplied by other factors that will be multiplied later by diffuse GI, A = specularOcclusion
float4 m_specularF0 : SV_Target3; //!< RGB = Specular F0, A = roughness
float4 m_normal : SV_Target4; //!< RGB10 = EncodeNormalSignedOctahedron(worldNormal), A2 = multiScatterCompensationEnabled
float3 m_scatterDistance : SV_Target5;
};
struct ForwardPassOutputWithDepth
@@ -29,6 +28,5 @@ struct ForwardPassOutputWithDepth
float4 m_albedo : SV_Target2;
float4 m_specularF0 : SV_Target3;
float4 m_normal : SV_Target4;
float3 m_scatterDistance : SV_Target5;
float m_depth : SV_Depth;
};
@@ -0,0 +1,34 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
struct ForwardPassOutput
{
// m_diffuseColor.a should be encoded with subsurface scattering's strength factor and quality factor if enabled
float4 m_diffuseColor : SV_Target0;
float4 m_specularColor : SV_Target1;
float4 m_albedo : SV_Target2;
float4 m_specularF0 : SV_Target3;
float4 m_normal : SV_Target4;
float3 m_scatterDistance : SV_Target5;
};
struct ForwardPassOutputWithDepth
{
// m_diffuseColor.a should be encoded with subsurface scattering's strength factor and quality factor if enabled
float4 m_diffuseColor : SV_Target0;
float4 m_specularColor : SV_Target1;
float4 m_albedo : SV_Target2;
float4 m_specularF0 : SV_Target3;
float4 m_normal : SV_Target4;
float3 m_scatterDistance : SV_Target5;
float m_depth : SV_Depth;
};
@@ -0,0 +1,115 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
// Include options first
#include <Atom/Features/PBR/LightingOptions.azsli>
// Then include custom surface and lighting data types
#include <Atom/Features/PBR/Lighting/LightingData.azsli>
#include <Atom/Features/PBR/Surfaces/EnhancedSurface.azsli>
#include <Atom/Features/PBR/LightingUtils.azsli>
#include <Atom/Features/PBR/Microfacet/Brdf.azsli>
// Then define the Diffuse and Specular lighting functions
float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight)
{
float3 diffuse;
if(o_enableSubsurfaceScattering)
{
// Use diffuse brdf contains double Fresnel (enter/exit surface) terms if subsurface scattering is enabled
diffuse = NormalizedDisneyDiffuse(surface.albedo, surface.normal, lightingData.dirToCamera, dirToLight, surface.roughnessLinear);
}
else
{
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
}
if(o_clearCoat_feature_enabled)
{
// Attenuate diffuse term by clear coat's fresnel term to account for energy loss
float HdotV = saturate(dot(normalize(dirToLight + lightingData.dirToCamera), lightingData.dirToCamera));
diffuse *= 1.0 - (FresnelSchlick(HdotV, 0.04) * surface.clearCoat.factor);
}
diffuse *= lightIntensity;
return diffuse;
}
float3 GetSpecularLighting(Surface surface, LightingData lightingData, const float3 lightIntensity, const float3 dirToLight)
{
float3 specular;
if (o_enableAnisotropy)
{
specular = AnisotropicGGX( lightingData.dirToCamera, dirToLight, surface.normal, surface.anisotropy.tangent, surface.anisotropy.bitangent, surface.anisotropy.anisotropyFactors,
surface.specularF0, lightingData.NdotV, lightingData.multiScatterCompensation );
}
else
{
specular = SpecularGGX(lightingData.dirToCamera, dirToLight, surface.normal, surface.specularF0, lightingData.NdotV, surface.roughnessA2, lightingData.multiScatterCompensation);
}
if(o_clearCoat_feature_enabled)
{
float3 halfVector = normalize(dirToLight + lightingData.dirToCamera);
float NdotH = saturate(dot(surface.clearCoat.normal, halfVector));
float NdotL = saturate(dot(surface.clearCoat.normal, dirToLight));
float HdotL = saturate(dot(halfVector, dirToLight));
// HdotV = HdotL due to the definition of half vector
float3 clearCoatF = FresnelSchlick(HdotL, 0.04) * surface.clearCoat.factor;
float clearCoatRoughness = max(surface.clearCoat.roughness * surface.clearCoat.roughness, 0.0005f);
float3 clearCoatSpecular = ClearCoatGGX(NdotH, HdotL, NdotL, surface.clearCoat.normal, clearCoatRoughness, clearCoatF );
specular = specular * (1.0 - clearCoatF) * (1.0 - clearCoatF) + clearCoatSpecular;
}
specular *= lightIntensity;
return specular;
}
// Then include everything else
#include <Atom/Features/PBR/Lights/Lights.azsli>
#include <Atom/Features/PBR/Lights/Ibl.azsli>
struct PbrLightingOutput
{
float4 m_diffuseColor;
float4 m_specularColor;
float4 m_albedo;
float4 m_specularF0;
float4 m_normal;
float3 m_scatterDistance;
};
PbrLightingOutput GetPbrLightingOutput(Surface surface, LightingData lightingData, float alpha)
{
PbrLightingOutput lightingOutput;
lightingOutput.m_diffuseColor = float4(lightingData.diffuseLighting, alpha);
lightingOutput.m_specularColor = float4(lightingData.specularLighting, 1.0);
// albedo, specularF0, roughness, and normals for later passes (specular IBL, Diffuse GI, SSR, AO, etc)
lightingOutput.m_specularF0 = float4(surface.specularF0, surface.roughnessLinear);
lightingOutput.m_albedo.rgb = surface.albedo * lightingData.diffuseResponse * lightingData.diffuseAmbientOcclusion;
lightingOutput.m_albedo.a = lightingData.specularOcclusion;
lightingOutput.m_normal.rgb = EncodeNormalSignedOctahedron(surface.normal);
lightingOutput.m_normal.a = o_specularF0_enableMultiScatterCompensation ? 1.0f : 0.0f;
return lightingOutput;
}
@@ -0,0 +1,106 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
// Include options first
#include <Atom/Features/PBR/LightingOptions.azsli>
// Then include custom surface and lighting data types
#include <Atom/Features/PBR/Lighting/LightingData.azsli>
#include <Atom/Features/PBR/Surfaces/SkinSurface.azsli>
#include <Atom/Features/PBR/LightingUtils.azsli>
#include <Atom/Features/PBR/Microfacet/Brdf.azsli>
// Then define the Diffuse and Specular lighting functions
float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight)
{
float3 diffuse;
if(o_enableSubsurfaceScattering)
{
// Use diffuse brdf contains double Fresnel (enter/exit surface) terms if subsurface scattering is enabled
diffuse = NormalizedDisneyDiffuse(surface.albedo, surface.normal, lightingData.dirToCamera, dirToLight, surface.roughnessLinear);
}
else
{
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
}
if(o_clearCoat_feature_enabled)
{
// Attenuate diffuse term by clear coat's fresnel term to account for energy loss
float HdotV = saturate(dot(normalize(dirToLight + lightingData.dirToCamera), lightingData.dirToCamera));
diffuse *= 1.0 - (FresnelSchlick(HdotV, 0.04) * surface.clearCoat.factor);
}
diffuse *= lightIntensity;
return diffuse;
}
float3 GetSpecularLighting(Surface surface, LightingData lightingData, const float3 lightIntensity, const float3 dirToLight)
{
float3 specular = SpecularGGX(lightingData.dirToCamera, dirToLight, surface.normal, surface.specularF0, lightingData.NdotV, surface.roughnessA2, lightingData.multiScatterCompensation);
if(o_clearCoat_feature_enabled)
{
float3 halfVector = normalize(dirToLight + lightingData.dirToCamera);
float NdotH = saturate(dot(surface.clearCoat.normal, halfVector));
float NdotL = saturate(dot(surface.clearCoat.normal, dirToLight));
float HdotL = saturate(dot(halfVector, dirToLight));
// HdotV = HdotL due to the definition of half vector
float3 clearCoatF = FresnelSchlick(HdotL, 0.04) * surface.clearCoat.factor;
float clearCoatRoughness = max(surface.clearCoat.roughness * surface.clearCoat.roughness, 0.0005f);
float3 clearCoatSpecular = ClearCoatGGX(NdotH, HdotL, NdotL, surface.clearCoat.normal, clearCoatRoughness, clearCoatF );
specular = specular * (1.0 - clearCoatF) * (1.0 - clearCoatF) + clearCoatSpecular;
}
specular *= lightIntensity;
return specular;
}
// Then include everything else
#include <Atom/Features/PBR/Lights/Lights.azsli>
#include <Atom/Features/PBR/Lights/Ibl.azsli>
struct PbrLightingOutput
{
float4 m_diffuseColor;
float4 m_specularColor;
float4 m_albedo;
float4 m_specularF0;
float4 m_normal;
float3 m_scatterDistance;
};
PbrLightingOutput GetPbrLightingOutput(Surface surface, LightingData lightingData)
{
PbrLightingOutput lightingOutput;
lightingOutput.m_diffuseColor = float4(lightingData.diffuseLighting, 1.0f);
lightingOutput.m_specularColor = float4(lightingData.specularLighting, 1.0f);
// albedo, specularF0, roughness, and normals for later passes (specular IBL, Diffuse GI, SSR, AO, etc)
lightingOutput.m_specularF0 = float4(surface.specularF0, surface.roughnessLinear);
lightingOutput.m_albedo.rgb = surface.albedo * lightingData.diffuseResponse * lightingData.diffuseAmbientOcclusion;
lightingOutput.m_albedo.a = lightingData.specularOcclusion;
lightingOutput.m_normal.rgb = EncodeNormalSignedOctahedron(surface.normal);
lightingOutput.m_normal.a = o_specularF0_enableMultiScatterCompensation ? 1.0f : 0.0f;
return lightingOutput;
}
@@ -19,6 +19,50 @@
#include <Atom/Features/PBR/Lighting/LightingData.azsli>
#include <Atom/Features/PBR/Surfaces/StandardSurface.azsli>
#include <Atom/Features/PBR/LightingUtils.azsli>
#include <Atom/Features/PBR/Microfacet/Brdf.azsli>
// Then define the Diffuse and Specular lighting functions
float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight)
{
float3 diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
if(o_clearCoat_feature_enabled)
{
// Attenuate diffuse term by clear coat's fresnel term to account for energy loss
float HdotV = saturate(dot(normalize(dirToLight + lightingData.dirToCamera), lightingData.dirToCamera));
diffuse *= 1.0 - (FresnelSchlick(HdotV, 0.04) * surface.clearCoat.factor);
}
diffuse *= lightIntensity;
return diffuse;
}
float3 GetSpecularLighting(Surface surface, LightingData lightingData, const float3 lightIntensity, const float3 dirToLight)
{
float3 specular = SpecularGGX(lightingData.dirToCamera, dirToLight, surface.normal, surface.specularF0, lightingData.NdotV, surface.roughnessA2, lightingData.multiScatterCompensation);
if(o_clearCoat_feature_enabled)
{
float3 halfVector = normalize(dirToLight + lightingData.dirToCamera);
float NdotH = saturate(dot(surface.clearCoat.normal, halfVector));
float NdotL = saturate(dot(surface.clearCoat.normal, dirToLight));
float HdotL = saturate(dot(halfVector, dirToLight));
// HdotV = HdotL due to the definition of half vector
float3 clearCoatF = FresnelSchlick(HdotL, 0.04) * surface.clearCoat.factor;
float clearCoatRoughness = max(surface.clearCoat.roughness * surface.clearCoat.roughness, 0.0005f);
float3 clearCoatSpecular = ClearCoatGGX(NdotH, HdotL, NdotL, surface.clearCoat.normal, clearCoatRoughness, clearCoatF );
specular = specular * (1.0 - clearCoatF) * (1.0 - clearCoatF) + clearCoatSpecular;
}
specular *= lightIntensity;
return specular;
}
// Then include everything else
#include <Atom/Features/PBR/Lights/Lights.azsli>
#include <Atom/Features/PBR/Lights/Ibl.azsli>
@@ -31,7 +75,6 @@ struct PbrLightingOutput
float4 m_albedo;
float4 m_specularF0;
float4 m_normal;
float4 m_clearCoatNormal;
float3 m_scatterDistance;
};
@@ -50,11 +93,17 @@ PbrLightingOutput GetPbrLightingOutput(Surface surface, LightingData lightingDat
lightingOutput.m_normal.rgb = EncodeNormalSignedOctahedron(surface.normal);
lightingOutput.m_normal.a = o_specularF0_enableMultiScatterCompensation ? 1.0f : 0.0f;
// layout: (packedNormal.x, packedNormal.y, strength factor, clear coat roughness (not base material's roughness))
lightingOutput.m_clearCoatNormal = float4(EncodeNormalSphereMap(surface.clearCoat.normal), o_clearCoat_feature_enabled ? surface.clearCoat.factor : 0.0, surface.clearCoat.roughness);
return lightingOutput;
}
PbrLightingOutput DebugOutput(float3 color)
{
PbrLightingOutput output = (PbrLightingOutput)0;
float defaultNormal = float3(0.0f, 0.0f, 1.0f);
output.m_diffuseColor = float4(color.rgb, 1.0f);
output.m_normal.rgb = EncodeNormalSignedOctahedron(defaultNormal);
return output;
}
@@ -1,205 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Atom/Features/PBR/LightingOptions.azsli>
#include <viewsrg.srgi>
#include <scenesrg.srgi>
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
#include <Atom/RPI/Math.azsli>
#include <Atom/RPI/TangentSpace.azsli>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
#include <Atom/Features/PBR/Decals.azsli>
// VSInput, VSOutput, ObjectSrg must be defined before including this file.
// DEPRECATED: Please use the VertexHelper(...) function in VertexHelper.azsli instead.
//! @param skipShadowCoords can be useful for example when PixelDepthOffset is enable, because the pixel shader will have to run before the final world position is known
void PbrVsHelper(in VSInput IN, inout VSOutput OUT, float3 worldPosition, bool skipShadowCoords = false)
{
OUT.m_worldPosition = worldPosition;
OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(OUT.m_worldPosition, 1.0));
float4x4 objectToWorld = ObjectSrg::GetWorldMatrix();
float3x3 objectToWorldIT = ObjectSrg::GetWorldMatrixInverseTranspose();
ConstructTBN(IN.m_normal, IN.m_tangent, IN.m_bitangent, objectToWorld, objectToWorldIT, OUT.m_normal, OUT.m_tangent, OUT.m_bitangent);
// directional light shadow
const uint shadowIndex = ViewSrg::m_shadowIndexDirectionalLight;
if (o_enableShadows && !skipShadowCoords && shadowIndex < SceneSrg::m_directionalLightCount)
{
DirectionalLightShadow::GetShadowCoords(
shadowIndex,
worldPosition,
OUT.m_shadowCoords);
}
}
// DEPRECATED: Please use the functions in StandardLighting.azsli instead.
// For an example on how to use those functions, see StandardPBR_forwardPass.azsl
PbrLightingOutput PbrLighting( VSOutput IN,
float3 baseColor,
float metallic,
float roughness,
float specularF0Factor,
float3 normal,
float3 vtxTangent,
float3 vtxBitangent,
float2 anisotropy, // angle and factor
float3 emissive,
float diffuseAmbientOcclusion,
float specularOcclusion,
float4 transmissionTintThickness,
float4 transmissionParams,
float clearCoatFactor,
float clearCoatRoughness,
float3 clearCoatNormal,
float alpha,
OpacityMode opacityMode)
{
float3 worldPosition = IN.m_worldPosition;
float4 position = IN.m_position;
float3 shadowCoords[ViewSrg::MaxCascadeCount] = IN.m_shadowCoords;
// ______________________________________________________________________________________________
// Surface
Surface surface;
surface.position = worldPosition;
surface.normal = normal;
surface.roughnessLinear = roughness;
surface.transmission.tint = transmissionTintThickness.rgb;
surface.transmission.thickness = transmissionTintThickness.w;
surface.transmission.transmissionParams = transmissionParams;
surface.clearCoat.factor = clearCoatFactor;
surface.clearCoat.roughness = clearCoatRoughness;
surface.clearCoat.normal = clearCoatNormal;
surface.CalculateRoughnessA();
surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic);
surface.anisotropy.Init(normal, vtxTangent, vtxBitangent, anisotropy.x, anisotropy.y, surface.roughnessA);
// ______________________________________________________________________________________________
// LightingData
LightingData lightingData;
// Light iterator
lightingData.tileIterator.Init(position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData);
lightingData.Init(surface.position, surface.normal, surface.roughnessLinear);
lightingData.emissiveLighting = emissive;
lightingData.diffuseAmbientOcclusion = diffuseAmbientOcclusion;
lightingData.specularOcclusion = specularOcclusion;
// Directional light shadow coordinates
lightingData.shadowCoords = shadowCoords;
// manipulate base layer f0 if clear coat is enabled
if(o_clearCoat_feature_enabled)
{
// modify base layer's normal incidence reflectance
// for the derivation of the following equation please refer to:
// https://google.github.io/filament/Filament.md.html#materialsystem/clearcoatmodel/baselayermodification
float3 f0 = (1.0 - 5.0 * sqrt(surface.specularF0)) / (5.0 - sqrt(surface.specularF0));
surface.specularF0 = lerp(surface.specularF0, f0 * f0, clearCoatFactor);
}
// Diffuse and Specular response (used in IBL calculations)
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
lightingData.diffuseResponse = 1.0 - lightingData.specularResponse;
if(o_clearCoat_feature_enabled)
{
// Clear coat layer has fixed IOR = 1.5 and transparent => F0 = (1.5 - 1)^2 / (1.5 + 1)^2 = 0.04
lightingData.diffuseResponse *= 1.0 - (FresnelSchlickWithRoughness(lightingData.NdotV, float3(0.04, 0.04, 0.04), surface.clearCoat.roughness) * surface.clearCoat.factor);
}
// Multiscatter compensation factor
lightingData.CalculateMultiscatterCompensation(surface.specularF0, o_specularF0_enableMultiScatterCompensation);
// ______________________________________________________________________________________________
// Lighting
// Apply Decals
ApplyDecals(lightingData.tileIterator, surface);
// Apply Direct Lighting
ApplyDirectLighting(surface, lightingData);
// Apply Image Based Lighting (IBL)
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
if (o_opacity_mode == OpacityMode::Blended || o_opacity_mode == OpacityMode::TintedTransparent)
{
alpha = FresnelSchlickWithRoughness(lightingData.NdotV, alpha, surface.roughnessLinear).x; // Increase opacity at grazing angles.
}
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);
return lightingOutput;
}
//! Populates a PbrLightingOutput struct with values that can be used to render a simple debug color in the PBR pipeline.
//! Note that this will not give you a the exact color screen pixels since it is used in the PBR pipeline, it may
//! still have lighting or other affects applied on top of it. But this is still a convenient way to quickly get some
//! colors on screen.
//! @param IN the pixel shader input structure
//! @param debugColor the color to be drawn
//! @param normalWS world space normal vector
//! @return a PbrLightingOutput as returned by the main PbrLighting() function
PbrLightingOutput MakeDebugOutput(VSOutput IN, float3 debugColor, float3 normalWS)
{
// We happen to set this up initially using baseColor, but we could consider adding an option to use
// emissive instead to avoid depending on scene lighting.
const float3 baseColor = debugColor;
const float metallic = 0;
const float roughness = 1;
const float specularF0Factor = 0.5;
const float3 normal = normalWS;
const float3 emissive = {0,0,0};
const float occlusion = 1;
const float clearCoatFactor = 0.0f;
const float clearCoatRoughness = 0.0f;
const float3 clearCoatNormal = {0,0,0};
const float4 transmissionTintThickness = {0,0,0,0};
const float4 transmissionParams = {0,0,0,0};
const float2 anisotropy = 0.0; // Does not affect calculations unless 'o_enableAnisotropy' is enabled
const float alpha = 1.0;
PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor,
normal, IN.m_tangent, IN.m_bitangent, anisotropy,
emissive, occlusion, occlusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque);
return lightingOutput;
}
//! Same as above, using the vertex normal
PbrLightingOutput MakeDebugOutput(VSOutput IN, float3 debugColor)
{
return MakeDebugOutput(IN, debugColor, normalize(IN.m_normal));
}
@@ -16,71 +16,9 @@
#include <Atom/Features/PBR/BackLighting.azsli>
#include <Atom/Features/PBR/Hammersley.azsli>
#include <Atom/Features/PBR/LightingUtils.azsli>
#include <Atom/Features/PBR/Surface.azsli>
#include <Atom/Features/PBR/Microfacet/Brdf.azsli>
option bool o_area_light_validation = false;
float3 GetDiffuseLighting(Surface surface, LightingData lightingData, float3 lightIntensity, float3 dirToLight)
{
float3 diffuse;
if(o_enableSubsurfaceScattering)
{
// Use diffuse brdf contains double Fresnel (enter/exit surface) terms if subsurface scattering is enabled
diffuse = NormalizedDisneyDiffuse(surface.albedo, surface.normal, lightingData.dirToCamera, dirToLight, surface.roughnessLinear);
}
else
{
diffuse = DiffuseLambertian(surface.albedo, surface.normal, dirToLight);
}
if(o_clearCoat_feature_enabled)
{
// Attenuate diffuse term by clear coat's fresnel term to account for energy loss
float HdotV = saturate(dot(normalize(dirToLight + lightingData.dirToCamera), lightingData.dirToCamera));
diffuse *= 1.0 - (FresnelSchlick(HdotV, 0.04) * surface.clearCoat.factor);
}
diffuse *= lightIntensity;
return diffuse;
}
float3 GetSpecularLighting(Surface surface, LightingData lightingData, const float3 lightIntensity, const float3 dirToLight)
{
float3 specular;
if (o_enableAnisotropy)
{
//AnisotropicGGX( float3 dirToCamera, float3 dirToLight, float3 normal, float3 tangent, float3 bitangent, float2 anisotropyFactors,
// float3 specularF0, float NdotV, float multiScatterCompensation )
specular = AnisotropicGGX( lightingData.dirToCamera, dirToLight, surface.normal, surface.anisotropy.tangent, surface.anisotropy.bitangent, surface.anisotropy.anisotropyFactors,
surface.specularF0, lightingData.NdotV, lightingData.multiScatterCompensation );
}
else
{
specular = SpecularGGX(lightingData.dirToCamera, dirToLight, surface.normal, surface.specularF0, lightingData.NdotV, surface.roughnessA2, lightingData.multiScatterCompensation);
}
if(o_clearCoat_feature_enabled)
{
float3 halfVector = normalize(dirToLight + lightingData.dirToCamera);
float NdotH = saturate(dot(surface.clearCoat.normal, halfVector));
float NdotL = saturate(dot(surface.clearCoat.normal, dirToLight));
float HdotL = saturate(dot(halfVector, dirToLight));
// HdotV = HdotL due to the definition of half vector
float3 clearCoatF = FresnelSchlick(HdotL, 0.04) * surface.clearCoat.factor;
float clearCoatRoughness = max(surface.clearCoat.roughness * surface.clearCoat.roughness, 0.0005f);
float3 clearCoatSpecular = ClearCoatGGX(NdotH, HdotL, NdotL, surface.clearCoat.normal, clearCoatRoughness, clearCoatF );
specular = specular * (1.0 - clearCoatF) * (1.0 - clearCoatF) + clearCoatSpecular;
}
specular *= lightIntensity;
return specular;
}
//! Adjust the intensity of specular light based on the radius of the light source and roughness of the surface to approximate energy conservation.
float GetIntensityAdjustedByRadiusAndRoughness(float roughnessA, float radius, float distance2)
@@ -18,7 +18,6 @@
* rather than transmit.
**/
#include <Atom/Features/PBR/Surface.azsli>
#include <Atom/RPI/Math.azsli>
#include "Ggx.azsli"
#include "Fresnel.azsli"
@@ -81,9 +80,6 @@ float3 DiffuseTitanfall(float roughnessA, float3 albedo, float3 normal, float3 d
}
// ------- Specular Lighting -------
//! Computes specular response from surfaces with microgeometry. The common form for microfacet
@@ -1,68 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
// //! The surface struct should contain all the info for a pixel that can be
// //! passed onto the rendering logic for shading.
// //! Note that metallic workflow can be supported by first converting to these physical properties first.
// struct Surface
// {
// float3 position;
// float3 normal;
// float3 tangentAniso; //! surface space tangent for anisotropic use
// float3 bitangentAniso; //! surface space bitangent for anisotropic use
// float2 anisotropyFactors; //! anisotory factors along the tangent and the bitangent directions
// float3 albedo;
// float3 specularF0; //!< actual fresnel f0 spectral value of the surface (as opposed to a "factor")
// float3 multiScatterCompensation; //!< the constant scaling term to approximate multiscattering contribution in specular BRDF
// float roughnessLinear; //!< perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use
// float roughnessA; //!< actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations
// float thickness; //!< pre baked local thickness, used for transmission
// float4 transmissionParams; //!< parameters: thick mode->(attenuation coefficient, power, distortion, scale), thin mode: (float3 scatter distance, scale)
// float clearCoatFactor; //!< clear coat strength factor
// float clearCoatRoughness; //!< clear coat linear roughness (not base layer one)
// float3 clearCoatNormal; //!< normal used for top layer clear coat
// };
//
// //! Calculate and fill the data required for fast directional anisotropty surface response.
// //! Assumption: the normal and roughnessA surface properties were filled and are valid
// //! Notice that since the newly created surface tangent and bitangent will be rotated
// //! according to the anisotropy direction and should not be used for other purposes uness
// //! rotated back.
// void CalculateSurfaceDirectionalAnisotropicData(
// inout Surface surface, float2 anisotropyAngleAndFactor,
// float3 vtxTangent, float3 vtxBitangent )
// {
// const float anisotropyAngle = anisotropyAngleAndFactor.x;
// const float anisotropyFactor = anisotropyAngleAndFactor.y;
//
// surface.anisotropyFactors = max( 0.01,
// float2( surface.roughnessA * (1.0 + anisotropyFactor),
// surface.roughnessA * (1.0 - anisotropyFactor) )
// );
//
// if (anisotropyAngle > 0.01)
// {
// // Base rotation according to anisotropic main direction
// float aniSin, aniCos;
// sincos(anisotropyAngle, aniSin, aniCos);
//
// // Rotate the vertex tangent to get new aligned to surface normal tangent
// vtxTangent = aniCos * vtxTangent - aniSin * vtxBitangent;
// }
//
// // Now create the new surface base according to the surface normal
// // If rotation was required it was already applied to the tangent, hence to the bitangent
// surface.bitangentAniso = normalize(cross(surface.normal, vtxTangent));
// surface.tangentAniso = cross(surface.bitangentAniso, surface.normal);
// }
@@ -43,7 +43,7 @@ class BasePbrSurfaceData
void CalculateRoughnessA();
//! Sets albedo and specularF0 using metallic workflow
void SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0, float metallic);
void SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic);
};
// ------- Functions -------
@@ -63,6 +63,9 @@ void BasePbrSurfaceData::ApplySpecularAA()
float kernelRoughnessA2 = min(2.0 * variance , varianceThresh );
float filteredRoughnessA2 = saturate ( roughnessA2 + kernelRoughnessA2 );
roughnessA2 = filteredRoughnessA2;
roughnessA = sqrt(roughnessA2);
roughnessLinear = sqrt(roughnessA);
}
void BasePbrSurfaceData::CalculateRoughnessA()
@@ -82,9 +85,9 @@ void BasePbrSurfaceData::CalculateRoughnessA()
}
}
void BasePbrSurfaceData::SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0, float metallic)
void BasePbrSurfaceData::SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic)
{
float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * inSpecularF0;
float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * specularF0Factor;
// Compute albedo and specularF0 based on metalness
albedo = lerp(baseColor, float3(0.0f, 0.0f, 0.0f), metallic);
@@ -17,4 +17,13 @@ class ClearCoatSurfaceData
float factor; //!< clear coat strength factor
float roughness; //!< clear coat linear roughness (not base layer one)
float3 normal; //!< normal used for top layer clear coat
void InitializeToZero();
};
void ClearCoatSurfaceData::InitializeToZero()
{
factor = 0.0f;
roughness = 0.0f;
normal = float3(0.0f, 0.0f, 0.0f);
}
@@ -0,0 +1,90 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Atom/Features/PBR/Surfaces/AnisotropicSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/BasePbrSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/ClearCoatSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli>
class Surface
{
AnisotropicSurfaceData anisotropy;
ClearCoatSurfaceData clearCoat;
TransmissionSurfaceData transmission;
// ------- BasePbrSurfaceData -------
float3 position; //!< Position in world-space
float3 normal; //!< Normal in world-space
float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value
float3 specularF0; //!< Fresnel f0 spectral value of the surface
float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use
float roughnessA; //!< Actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations
float roughnessA2; //!< Alpha roughness ^ 2 (i.e. roughnessA * roughnessA), used in GGX, cached here for perfromance
//! Applies specular anti-aliasing to roughnessA2
void ApplySpecularAA();
//! Calculates roughnessA and roughnessA2 after roughness has been set
void CalculateRoughnessA();
//! Sets albedo and specularF0 using metallic workflow
void SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic);
};
// Specular Anti-Aliasing technique from this paper:
// http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
void Surface::ApplySpecularAA()
{
// Constants for formula below
const float screenVariance = 0.25f;
const float varianceThresh = 0.18f;
// Specular Anti-Aliasing
float3 dndu = ddx_fine( normal );
float3 dndv = ddy_fine( normal );
float variance = screenVariance * (dot( dndu , dndu ) + dot( dndv , dndv ));
float kernelRoughnessA2 = min(2.0 * variance , varianceThresh );
float filteredRoughnessA2 = saturate ( roughnessA2 + kernelRoughnessA2 );
roughnessA2 = filteredRoughnessA2;
}
void Surface::CalculateRoughnessA()
{
// The roughness value in microfacet calculations (called "alpha" in the literature) does not give perceptually
// linear results. Disney found that squaring the roughness value before using it in microfacet equations causes
// the user-provided roughness parameter to be more perceptually linear. We keep both values available as some
// equations need roughnessLinear (i.e. IBL sampling) while others need roughnessA (i.e. GGX equations).
// See Burley's Disney PBR: https://pdfs.semanticscholar.org/eeee/3b125c09044d3e2f58ed0e4b1b66a677886d.pdf
roughnessA = max(roughnessLinear * roughnessLinear, MinRoughnessA);
roughnessA2 = roughnessA * roughnessA;
if(o_applySpecularAA)
{
ApplySpecularAA();
}
}
void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic)
{
float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * specularF0Factor;
// Compute albedo and specularF0 based on metalness
albedo = lerp(baseColor, float3(0.0f, 0.0f, 0.0f), metallic);
specularF0 = lerp(dielectricSpecularF0, baseColor, metallic);
}
@@ -0,0 +1,86 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Atom/Features/PBR/Surfaces/AnisotropicSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/BasePbrSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/ClearCoatSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli>
class Surface
{
ClearCoatSurfaceData clearCoat;
TransmissionSurfaceData transmission;
// ------- BasePbrSurfaceData -------
float3 position; //!< Position in world-space
float3 normal; //!< Normal in world-space
float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value
float3 specularF0; //!< Fresnel f0 spectral value of the surface
float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use
float roughnessA; //!< Actual roughness value ( a.k.a. "alpha roughness") to be used in microfacet calculations
float roughnessA2; //!< Alpha roughness ^ 2 (i.e. roughnessA * roughnessA), used in GGX, cached here for perfromance
//! Applies specular anti-aliasing to roughnessA2
void ApplySpecularAA();
//! Calculates roughnessA and roughnessA2 after roughness has been set
void CalculateRoughnessA();
//! Sets albedo and specularF0 using metallic workflow
void SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor);
};
// Specular Anti-Aliasing technique from this paper:
// http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA.pdf
void Surface::ApplySpecularAA()
{
// Constants for formula below
const float screenVariance = 0.25f;
const float varianceThresh = 0.18f;
// Specular Anti-Aliasing
float3 dndu = ddx_fine( normal );
float3 dndv = ddy_fine( normal );
float variance = screenVariance * (dot( dndu , dndu ) + dot( dndv , dndv ));
float kernelRoughnessA2 = min(2.0 * variance , varianceThresh );
float filteredRoughnessA2 = saturate ( roughnessA2 + kernelRoughnessA2 );
roughnessA2 = filteredRoughnessA2;
}
void Surface::CalculateRoughnessA()
{
// The roughness value in microfacet calculations (called "alpha" in the literature) does not give perceptually
// linear results. Disney found that squaring the roughness value before using it in microfacet equations causes
// the user-provided roughness parameter to be more perceptually linear. We keep both values available as some
// equations need roughnessLinear (i.e. IBL sampling) while others need roughnessA (i.e. GGX equations).
// See Burley's Disney PBR: https://pdfs.semanticscholar.org/eeee/3b125c09044d3e2f58ed0e4b1b66a677886d.pdf
roughnessA = max(roughnessLinear * roughnessLinear, MinRoughnessA);
roughnessA2 = roughnessA * roughnessA;
if(o_applySpecularAA)
{
ApplySpecularAA();
}
}
void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor)
{
albedo = baseColor;
specularF0 = MaxDielectricSpecularF0 * specularF0Factor;
}
@@ -17,10 +17,8 @@
#include <Atom/Features/PBR/Surfaces/ClearCoatSurfaceData.azsli>
#include <Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli>
class Surface //: BasePbrSurfaceData
class Surface
{
//BasePbrSurfaceData pbr;
AnisotropicSurfaceData anisotropy;
ClearCoatSurfaceData clearCoat;
TransmissionSurfaceData transmission;
@@ -41,7 +39,7 @@ class Surface //: BasePbrSurfaceData
void CalculateRoughnessA();
//! Sets albedo and specularF0 using metallic workflow
void SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0, float metallic);
void SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic);
};
@@ -80,9 +78,9 @@ void Surface::CalculateRoughnessA()
}
}
void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float inSpecularF0, float metallic)
void Surface::SetAlbedoAndSpecularF0(float3 baseColor, float specularF0Factor, float metallic)
{
float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * inSpecularF0;
float3 dielectricSpecularF0 = MaxDielectricSpecularF0 * specularF0Factor;
// Compute albedo and specularF0 based on metalness
albedo = lerp(baseColor, float3(0.0f, 0.0f, 0.0f), metallic);
@@ -17,4 +17,13 @@ class TransmissionSurfaceData
float3 tint;
float thickness; //!< pre baked local thickness, used for transmission
float4 transmissionParams; //!< parameters: thick mode->(attenuation coefficient, power, distortion, scale), thin mode: (float3 scatter distance, scale)
void InitializeToZero();
};
void TransmissionSurfaceData::InitializeToZero()
{
tint = float3(0.0f, 0.0f, 0.0f);
thickness = 0.0f;
transmissionParams = float4(0.0f, 0.0f, 0.0f, 0.0f);
}
@@ -13,7 +13,9 @@
#pragma once
// ------------------------------------------------------------------------------
// NOTE: VSInput, VSOutput, ObjectSrg must be defined before including this file.
// NOTE: The following must be included or defined before including this file:
// - VSInput - ObjectSrg
// - VSOutput - PassSrg
// ---------------------------------------------------------------------------------
// Options
@@ -23,8 +25,6 @@
#include <viewsrg.srgi>
#include <scenesrg.srgi>
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
// Math
#include <Atom/RPI/Math.azsli>
@@ -33,7 +33,6 @@
// Shadow Coords
#include <Atom/Features/Shadow/DirectionalLightShadow.azsli>
//! @param skipShadowCoords can be useful for example when PixelDepthOffset is enable, because the pixel shader will have to run before the final world position is known
void VertexHelper(in VSInput IN, inout VSOutput OUT, float3 worldPosition, bool skipShadowCoords = false)
{
@@ -140,6 +140,7 @@ set(FILES
Passes/Forward.pass
Passes/ForwardCheckerboard.pass
Passes/ForwardMSAA.pass
Passes/ForwardSubsurfaceMSAA.pass
Passes/FullscreenCopy.pass
Passes/FullscreenOutputOnly.pass
Passes/ImGui.pass
@@ -164,6 +165,7 @@ set(FILES
Passes/MSAAResolveDepth.pass
Passes/OpaqueParent.pass
Passes/PostProcessParent.pass
Passes/ProjectedShadowmaps.pass
Passes/RayTracingAccelerationStructure.pass
Passes/ReflectionComposite.pass
Passes/ReflectionCopyFrameBuffer.pass
@@ -190,7 +192,6 @@ set(FILES
Passes/SMAAConvertToPerceptualColor.pass
Passes/SMAAEdgeDetection.pass
Passes/SMAANeighborhoodBlending.pass
Passes/ProjectedShadowmaps.pass
Passes/SsaoCompute.pass
Passes/SsaoHalfRes.pass
Passes/SsaoParent.pass
@@ -229,14 +230,15 @@ set(FILES
ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli
ShaderLib/Atom/Features/PBR/ForwardPassOutput.azsli
ShaderLib/Atom/Features/PBR/ForwardPassSrg.azsli
ShaderLib/Atom/Features/PBR/ForwardSubsurfacePassOutput.azsli
ShaderLib/Atom/Features/PBR/Hammersley.azsli
ShaderLib/Atom/Features/PBR/LightingModel.azsli
ShaderLib/Atom/Features/PBR/LightingOptions.azsli
ShaderLib/Atom/Features/PBR/LightingUtils.azsli
ShaderLib/Atom/Features/PBR/Surface.azsli
ShaderLib/Atom/Features/PBR/TransparentPassSrg.azsli
ShaderLib/Atom/Features/PBR/Lighting/DualSpecularLighting.azsli
ShaderLib/Atom/Features/PBR/Lighting/EnhancedLighting.azsli
ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli
ShaderLib/Atom/Features/PBR/Lighting/SkinLighting.azsli
ShaderLib/Atom/Features/PBR/Lighting/StandardLighting.azsli
ShaderLib/Atom/Features/PBR/Lights/CapsuleLight.azsli
ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli
@@ -248,6 +250,8 @@ set(FILES
ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli
ShaderLib/Atom/Features/PBR/Lights/PolygonLight.azsli
ShaderLib/Atom/Features/PBR/Lights/QuadLight.azsli
ShaderLib/Atom/Features/PBR/Lights/SimplePointLight.azsli
ShaderLib/Atom/Features/PBR/Lights/SimpleSpotLight.azsli
ShaderLib/Atom/Features/PBR/Microfacet/Brdf.azsli
ShaderLib/Atom/Features/PBR/Microfacet/Fresnel.azsli
ShaderLib/Atom/Features/PBR/Microfacet/Ggx.azsli
@@ -255,6 +259,8 @@ set(FILES
ShaderLib/Atom/Features/PBR/Surfaces/BasePbrSurfaceData.azsli
ShaderLib/Atom/Features/PBR/Surfaces/ClearCoatSurfaceData.azsli
ShaderLib/Atom/Features/PBR/Surfaces/DualSpecularSurface.azsli
ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli
ShaderLib/Atom/Features/PBR/Surfaces/SkinSurface.azsli
ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli
ShaderLib/Atom/Features/PBR/Surfaces/TransmissionSurfaceData.azsli
ShaderLib/Atom/Features/PostProcessing/Aces.azsli
@@ -270,9 +276,12 @@ set(FILES
ShaderLib/Atom/Features/Shadow/BicubicPcfFilters.azsli
ShaderLib/Atom/Features/Shadow/DirectionalLightShadow.azsli
ShaderLib/Atom/Features/Shadow/JitterTablePcf.azsli
ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli
ShaderLib/Atom/Features/Shadow/Shadow.azsli
ShaderLib/Atom/Features/Shadow/ShadowmapAtlasLib.azsli
ShaderLib/Atom/Features/Shadow/ProjectedShadow.azsli
ShaderLib/Atom/Features/Vertex/VertexHelper.azsli
ShaderResourceGroups/RayTracingSceneSrg.azsli
ShaderResourceGroups/RayTracingSceneSrgAll.azsli
ShaderResourceGroups/SceneSrg.azsli
ShaderResourceGroups/SceneSrgAll.azsli
ShaderResourceGroups/SceneTimeSrg.azsli
@@ -1,6 +1,6 @@
{
"description": "",
"materialType": "Materials/Types/StandardPBR.materialtype",
"materialType": "Materials/Types/EnhancedPBR.materialtype",
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
@@ -9,8 +9,8 @@
"influenceMap": "TestData/Textures/checker8x8_512.png",
"scatterColor": [
1.0,
0.19937437772750855,
0.07179369777441025,
0.20000000298023225,
0.07058823853731156,
1.0
],
"scatterDistance": 40.0,
@@ -1,11 +1,12 @@
{
"description": "",
"materialType": "Materials/Types/StandardPBR.materialtype",
"materialType": "Materials/Types/EnhancedPBR.materialtype",
"parentMaterial": "",
"propertyLayoutVersion": 3,
"properties": {
"subsurfaceScattering": {
"enableSubsurfaceScattering": true,
"enableTransmission": true,
"scatterDistance": 64.6464614868164,
"subsurfaceScatterFactor": 1.0,
"thicknessMap": "TestData/Textures/checker8x8_512.png",
@@ -14,9 +14,12 @@
#include "AutoBrick_Common.azsli"
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
#include <Atom/Features/ColorManagement/TransformColor.azsli>
#include <Atom/Features/ParallaxMapping.azsli>
#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
#include <Atom/Features/PBR/Decals.azsli>
struct VSInput
{
@@ -38,7 +41,6 @@ struct VSOutput
float2 m_uv : UV1;
};
#include <Atom/Features/PBR/LightingModel.azsli>
#include <Atom/Features/Vertex/VertexHelper.azsli>
VSOutput AutoBrick_ForwardPassVS(VSInput IN)
@@ -129,8 +131,6 @@ float GetDepth(float2 uv, float2 uv_ddx, float2 uv_ddy)
ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN)
{
ForwardPassOutput OUT;
float3x3 identityUvMatrix =
{ 1,0,0,
0,1,0,
@@ -164,23 +164,62 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN)
GetSurfaceShape(IN.m_uv, surfaceDepth, surfaceNormal);
const float3 normal = TangentSpaceToWorld(surfaceNormal, normalize(IN.m_normal), normalize(IN.m_tangent), normalize(IN.m_bitangent));
const float diffuseAmbientOcclusion = 1.0f - surfaceDepth * AutoBrickSrg::m_aoFactor;
const float specularOcclusion = 1;
const float metallic = 0;
const float roughness = 1;
const float specularF0Factor = 0.5;
const float3 emissive = {0,0,0};
const float clearCoatFactor = 0.0;
const float clearCoatRoughness = 0.0;
const float3 clearCoatNormal = {0,0,0};
const float4 transmissionTintThickness = {0,0,0,0};
const float4 transmissionParams = {0,0,0,0};
const float2 anisotropy = 0.0;
const float alpha = 1.0;
// ------- Surface -------
PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor,
normal, IN.m_tangent, IN.m_bitangent, anisotropy,
emissive, diffuseAmbientOcclusion, specularOcclusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque);
Surface surface;
// Position, Normal, Roughness
surface.position = IN.m_worldPosition.xyz;
surface.normal = normalize(normal);
surface.roughnessLinear = 1.0f;
surface.CalculateRoughnessA();
// Albedo, SpecularF0
const float metallic = 0.0f;
const float specularF0Factor = 0.5f;
surface.SetAlbedoAndSpecularF0(baseColor, specularF0Factor, metallic);
// Clear Coat, Transmission
surface.clearCoat.InitializeToZero();
surface.transmission.InitializeToZero();
// ------- LightingData -------
LightingData lightingData;
// Light iterator
lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData);
lightingData.Init(surface.position, surface.normal, surface.roughnessLinear);
// Shadow
lightingData.shadowCoords = IN.m_shadowCoords;
lightingData.diffuseAmbientOcclusion = 1.0f - surfaceDepth * AutoBrickSrg::m_aoFactor;
// Diffuse and Specular response
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
lightingData.diffuseResponse = 1.0f - lightingData.specularResponse;
const float alpha = 1.0f;
// ------- Lighting Calculation -------
// Apply Decals
ApplyDecals(lightingData.tileIterator, surface);
// Apply Direct Lighting
ApplyDirectLighting(surface, lightingData);
// Apply Image Based Lighting (IBL)
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);
// ------- Output -------
ForwardPassOutput OUT;
OUT.m_diffuseColor = lightingOutput.m_diffuseColor;
OUT.m_diffuseColor.w = -1; // Subsurface scattering is disabled
@@ -188,7 +227,6 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN)
OUT.m_specularF0 = lightingOutput.m_specularF0;
OUT.m_albedo = lightingOutput.m_albedo;
OUT.m_normal = lightingOutput.m_normal;
OUT.m_scatterDistance = float3(0,0,0);
return OUT;
}
@@ -12,10 +12,13 @@
#include <viewsrg.srgi>
#include <Atom/Features/PBR/DefaultObjectSrg.azsli>
#include <Atom/Features/PBR/ForwardPassSrg.azsli>
#include <Atom/Features/PBR/ForwardPassOutput.azsli>
#include <Atom/Features/PBR/AlphaUtils.azsli>
#include <Atom/Features/SrgSemantics.azsli>
#include <Atom/Features/ColorManagement/TransformColor.azsli>
#include <Atom/Features/PBR/Lighting/StandardLighting.azsli>
#include <Atom/Features/PBR/Decals.azsli>
ShaderResourceGroup MinimalPBRSrg : SRG_PerMaterial
{
@@ -42,7 +45,6 @@ struct VSOutput
float3 m_shadowCoords[ViewSrg::MaxCascadeCount] : UV3;
};
#include <Atom/Features/PBR/LightingModel.azsli>
#include <Atom/Features/Vertex/VertexHelper.azsli>
VSOutput MinimalPBR_MainPassVS(VSInput IN)
@@ -58,26 +60,60 @@ VSOutput MinimalPBR_MainPassVS(VSInput IN)
ForwardPassOutput MinimalPBR_MainPassPS(VSOutput IN)
{
ForwardPassOutput OUT;
const float3 baseColor = MinimalPBRSrg::m_baseColor;
const float metallic = MinimalPBRSrg::m_metallic;
const float roughness = MinimalPBRSrg::m_roughness;
const float specularF0Factor = 0.5;
const float3 normal = normalize(IN.m_normal);
const float3 emissive = {0,0,0};
const float occlusion = 1;
const float clearCoatFactor = 0.0;
const float clearCoatRoughness = 0.0;
const float3 clearCoatNormal = {0,0,0};
const float4 transmissionTintThickness = {0,0,0,0};
const float4 transmissionParams = {0,0,0,0};
const float2 anisotropy = 0.0; // Does not affect calculations unless 'o_enableAnisotropy' is enabled
const float alpha = 1.0;
// ------- Surface -------
PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor,
normal, IN.m_tangent, IN.m_bitangent, anisotropy,
emissive, occlusion, occlusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque);
Surface surface;
// Position, Normal, Roughness
surface.position = IN.m_worldPosition.xyz;
surface.normal = normalize(IN.m_normal);
surface.roughnessLinear = MinimalPBRSrg::m_roughness;
surface.CalculateRoughnessA();
// Albedo, SpecularF0
const float specularF0Factor = 0.5f;
surface.SetAlbedoAndSpecularF0(MinimalPBRSrg::m_baseColor, specularF0Factor, MinimalPBRSrg::m_metallic);
// Clear Coat, Transmission
surface.clearCoat.InitializeToZero();
surface.transmission.InitializeToZero();
// ------- LightingData -------
LightingData lightingData;
// Light iterator
lightingData.tileIterator.Init(IN.m_position, PassSrg::m_lightListRemapped, PassSrg::m_tileLightData);
lightingData.Init(surface.position, surface.normal, surface.roughnessLinear);
// Shadow, Occlusion
lightingData.shadowCoords = IN.m_shadowCoords;
// Diffuse and Specular response
lightingData.specularResponse = FresnelSchlickWithRoughness(lightingData.NdotV, surface.specularF0, surface.roughnessLinear);
lightingData.diffuseResponse = 1.0f - lightingData.specularResponse;
const float alpha = 1.0f;
// ------- Lighting Calculation -------
// Apply Decals
ApplyDecals(lightingData.tileIterator, surface);
// Apply Direct Lighting
ApplyDirectLighting(surface, lightingData);
// Apply Image Based Lighting (IBL)
ApplyIBL(surface, lightingData);
// Finalize Lighting
lightingData.FinalizeLighting(surface.transmission.tint);
PbrLightingOutput lightingOutput = GetPbrLightingOutput(surface, lightingData, alpha);
// ------- Output -------
ForwardPassOutput OUT;
OUT.m_diffuseColor = lightingOutput.m_diffuseColor;
OUT.m_diffuseColor.w = -1; // Subsurface scattering is disabled
@@ -85,7 +121,6 @@ ForwardPassOutput MinimalPBR_MainPassPS(VSOutput IN)
OUT.m_specularF0 = lightingOutput.m_specularF0;
OUT.m_albedo = lightingOutput.m_albedo;
OUT.m_normal = lightingOutput.m_normal;
OUT.m_scatterDistance = float3(0,0,0);
return OUT;
}
@@ -41,7 +41,6 @@ namespace AZ
BuilderComponent::~BuilderComponent()
{
AZ::Component::~Component();
AZ::Interface<AzFramework::AtomActiveInterface>::Unregister(this);
}
@@ -98,7 +98,7 @@ namespace AZ
->Attribute(AZ::Edit::Attributes::DefaultAsset, &EditorMaterialComponentSlot::GetDefaultAssetId)
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &EditorMaterialComponentSlot::GetLabel)
->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true)
->Attribute("ThumbnailWithDropDown", &EditorMaterialComponentSlot::OpenPopupMenu)
->Attribute("ThumbnailCallback", &EditorMaterialComponentSlot::OpenPopupMenu)
;
}
}
@@ -53,16 +53,20 @@ namespace AZ
->Attribute(AZ::Edit::Attributes::ViewportIcon, "editor/icons/components/viewport/component_placeholder.png")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c))
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo<RPI::ModelAsset>::Uuid())
->ClassElement(AZ::Edit::ClassElements::Group, "Cubemap")
->ClassElement(AZ::Edit::ClassElements::Group, "Cubemap Bake")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &EditorReflectionProbeComponent::m_useBakedCubemap, "Use Baked Cubemap", "Selects between a cubemap that captures the environment at location in the scene or a preauthored cubemap")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::OnUseBakedCubemapChanged)
->UIElement(AZ::Edit::UIHandlers::Button, "Bake Reflection Probe", "Bake Reflection Probe")
->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
->Attribute(AZ::Edit::Attributes::ButtonText, "Bake Reflection Probe")
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::BakeReflectionProbe)
->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting)
->ClassElement(AZ::Edit::ClassElements::Group, "Cubemap")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &EditorReflectionProbeComponent::m_useBakedCubemap, "Use Baked Cubemap", "Selects between a cubemap that captures the environment at location in the scene or a preauthored cubemap")
->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorReflectionProbeComponent::OnUseBakedCubemapValidate)
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::OnUseBakedCubemapChanged)
->DataElement(AZ::Edit::UIHandlers::MultiLineEdit, &EditorReflectionProbeComponent::m_bakedCubeMapRelativePath, "Baked Cubemap Path", "Baked Cubemap Path")
->Attribute(AZ::Edit::Attributes::ReadOnly, true)
->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting)
@@ -188,6 +192,16 @@ namespace AZ
return false;
}
AZ::Outcome<void, AZStd::string> EditorReflectionProbeComponent::OnUseBakedCubemapValidate([[maybe_unused]] void* newValue, [[maybe_unused]] const AZ::Uuid& valueType)
{
if (!m_controller.m_featureProcessor)
{
return AZ::Failure(AZStd::string("This Reflection Probe entity is hidden, it must be visible in order to change the cubemap type."));
}
return AZ::Success();
}
AZ::u32 EditorReflectionProbeComponent::OnUseBakedCubemapChanged()
{
// save setting to the configuration
@@ -47,6 +47,9 @@ namespace AZ
void DisplayEntityViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
private:
// validation
AZ::Outcome<void, AZStd::string> OnUseBakedCubemapValidate(void* newValue, const AZ::Uuid& valueType);
// change notifications
AZ::u32 OnUseBakedCubemapChanged();
AZ::u32 OnAuthoredCubemapChanged();
-7
View File
@@ -30,9 +30,7 @@ ly_add_target(
Include
BUILD_DEPENDENCIES
PRIVATE
AZ::AzCore
AZ::CrashHandler
AZ::CrashSupport
)
ly_add_target(
@@ -46,10 +44,5 @@ ly_add_target(
Include
BUILD_DEPENDENCIES
PRIVATE
#3rdParty::Crashpad
#3rdParty::Crashpad::Handler
AZ::AzCore
AZ::CrashUploaderSupport
#AZ::CrashHandler
AZ::CrashSupport
)
@@ -443,9 +443,12 @@ namespace DebugDraw
AZ::TransformBus::EventResult(sphereElement.m_worldLocation, sphereElement.m_targetEntityId, &AZ::TransformBus::Events::GetWorldTranslation);
}
ColorB lyColor(sphereElement.m_color.ToU32());
Vec3 worldLocation(AZVec3ToLYVec3(sphereElement.m_worldLocation));
gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(worldLocation, sphereElement.m_radius, lyColor, true);
if (gEnv->pRenderer)
{
ColorB lyColor(sphereElement.m_color.ToU32());
Vec3 worldLocation(AZVec3ToLYVec3(sphereElement.m_worldLocation));
gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(worldLocation, sphereElement.m_radius, lyColor, true);
}
}
removeExpiredDebugElementsFromVector(m_activeSpheres);
@@ -303,7 +303,8 @@ namespace EMotionFX
if (GetFinalNode() == nodeToRemove)
{
SetFinalNodeId(AnimGraphNodeId::InvalidId);
m_finalNodeId = AnimGraphNodeId::InvalidId;
m_finalNode = nullptr;
}
// call it for all children
@@ -68,6 +68,8 @@ namespace EMotionFX
&actorSettings,
"");
assetData->ReleaseEMotionFXData();
if (!assetData->m_emfxActor)
{
AZ_Error("EMotionFX", false, "Failed to initialize actor asset %s", asset.ToString<AZStd::string>().c_str());
@@ -77,7 +79,6 @@ namespace EMotionFX
assetData->m_emfxActor->SetIsOwnedByRuntime(true);
// Note: Render actor depends on the mesh asset, so we need to manually create it after mesh asset has been loaded.
return static_cast<bool>(assetData->m_emfxActor);
}
@@ -90,6 +90,7 @@ namespace EMotionFX
}
}
assetData->ReleaseEMotionFXData();
AZ_Error("EMotionFX", assetData->m_emfxAnimGraph, "Failed to initialize anim graph asset %s", asset.GetHint().c_str());
return static_cast<bool>(assetData->m_emfxAnimGraph);
}
@@ -36,6 +36,12 @@ namespace EMotionFX
: AZ::Data::AssetData(id)
{}
void ReleaseEMotionFXData()
{
m_emfxNativeData.clear();
m_emfxNativeData.shrink_to_fit();
}
AZStd::vector<AZ::u8> m_emfxNativeData;
};
@@ -47,6 +47,7 @@ namespace EMotionFX
assetData->m_emfxMotion->SetIsOwnedByRuntime(true);
}
assetData->ReleaseEMotionFXData();
AZ_Error("EMotionFX", assetData->m_emfxMotion, "Failed to initialize motion asset %s", asset.GetHint().c_str());
return (assetData->m_emfxMotion);
}
@@ -232,6 +232,7 @@ namespace EMotionFX
// Set motion set's motion load callback, so if EMotion FX queries back for a motion,
// we can pull the one managed through an AZ::Asset.
assetData->m_emfxMotionSet->SetCallback(aznew CustomMotionSetCallback(asset));
assetData->ReleaseEMotionFXData();
return true;
}
@@ -39,7 +39,6 @@
#include "Rendering/LightComponent.h"
#include "Rendering/HighQualityShadowComponent.h"
#include "Rendering/MeshComponent.h"
#include "Rendering/FogVolumeComponent.h"
#include "Rendering/GeomCacheComponent.h"
#include "Ai/NavigationComponent.h"
#include "Scripting/TagComponent.h"
@@ -241,7 +240,6 @@ namespace LmbrCentral
StereoRendererComponent::CreateDescriptor(),
NavigationSystemComponent::CreateDescriptor(),
GeometrySystemComponent::CreateDescriptor(),
FogVolumeComponent::CreateDescriptor(),
RandomTimedSpawnerComponent::CreateDescriptor(),
GeometryCacheComponent::CreateDescriptor(),
SphereShapeDebugDisplayComponent::CreateDescriptor(),
@@ -34,7 +34,6 @@
#include "Rendering/EditorEnvProbeComponent.h"
#include "Rendering/EditorHighQualityShadowComponent.h"
#include "Rendering/EditorMeshComponent.h"
#include "Rendering/EditorFogVolumeComponent.h"
#include "Rendering/EditorGeomCacheComponent.h"
#include "Scripting/EditorLookAtComponent.h"
#include "Scripting/EditorRandomTimedSpawnerComponent.h"
@@ -104,7 +103,6 @@ namespace LmbrCentral
EditorCommentComponent::CreateDescriptor(),
EditorNavigationAreaComponent::CreateDescriptor(),
EditorNavigationSeedComponent::CreateDescriptor(),
EditorFogVolumeComponent::CreateDescriptor(),
EditorRandomTimedSpawnerComponent::CreateDescriptor(),
EditorGeometryCacheComponent::CreateDescriptor(),
EditorSpawnerComponent::CreateDescriptor(),

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