diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h index bb3bfe52e7..5a1c571a26 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/ModelLod.h @@ -14,6 +14,7 @@ #include #include +#include #include @@ -34,8 +35,6 @@ namespace AZ //! A map matches the UV shader inputs of this material to the custom UV names from the model. using MaterialModelUvOverrideMap = AZStd::unordered_map; - class UvStreamTangentBitmask; - class ModelLod final : public Data::InstanceData { @@ -175,54 +174,5 @@ namespace AZ AZStd::mutex m_callbackMutex; }; - - //! An encoded bitmask for tangent used by UV streams. - //! It contains the information about number of UV streams and which tangent/bitangent is used by each UV stream. - //! See m_mask for more details. - //! The mask will be passed through per draw SRG. - class UvStreamTangentBitmask - { - public: - //! Get the full mask including number of UVs and tangent/bitangent assignment to each UV. - uint32_t GetFullTangentBitmask() const; - - //! Get number of UVs that have tangent/bitangent assigned. - uint32_t GetUvStreamCount() const; - - //! Get tangent/bitangent assignment to the specified UV in the material. - //! @param uvIndex the index of the UV from the material, in default order as in the shader code. - uint32_t GetTangentAtUv(uint32_t uvIndex) const; - - //! Apply the tangent to the next UV, whose index is the same as GetUvStreamCount. - //! @param tangent the tangent/bitangent to be assigned. Ranged in [0, 0xF) - //! It comes from the model in order, e.g. 0 means the first available tangent stream from the model. - //! Specially, value 0xF(=UnassignedTangent) means generated tangent/bitangent will be used in shader. - //! If ranged out of definition, unassigned tangent will be applied. - void ApplyTangent(uint32_t tangent); - - //! Reset the bitmask to clear state. - void Reset(); - - //! The bit mask indicating generated tangent/bitangent will be used. - static constexpr uint32_t UnassignedTangent = 0b1111u; - - //! The variable name defined in the SRG shader code. - static constexpr const char* SrgName = "m_uvStreamTangentBitmask"; - private: - //! Mask composition: - //! The number of UV slots (highest 4 bits) + tangent mask (4 bits each) * 7 - //! e.g. 0x200000F0 means there are 2 UV streams, - //! the first UV stream uses 0th tangent stream (0x0), - //! the second UV stream uses the generated tangent stream (0xF). - uint32_t m_mask = 0; - - //! Bit size in the mask composition. - static constexpr uint32_t BitsPerTangent = 4; - static constexpr uint32_t BitsForUvIndex = 4; - - public: - //! Max UV slots available in this bit mask. - static constexpr uint32_t MaxUvSlots = (sizeof(m_mask) * CHAR_BIT - BitsForUvIndex) / BitsPerTangent; - }; } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/UvStreamTangentBitmask.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/UvStreamTangentBitmask.h new file mode 100644 index 0000000000..aa599bc27c --- /dev/null +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/UvStreamTangentBitmask.h @@ -0,0 +1,72 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +#include + +namespace AZ +{ + namespace RPI + { + //! An encoded bitmask for tangent used by UV streams. + //! It contains the information about number of UV streams and which tangent/bitangent is used by each UV stream. + //! See m_mask for more details. + //! The mask will be passed through per draw SRG. + class UvStreamTangentBitmask + { + public: + //! Get the full mask including number of UVs and tangent/bitangent assignment to each UV. + uint32_t GetFullTangentBitmask() const; + + //! Get number of UVs that have tangent/bitangent assigned. + uint32_t GetUvStreamCount() const; + + //! Get tangent/bitangent assignment to the specified UV in the material. + //! @param uvIndex the index of the UV from the material, in default order as in the shader code. + uint32_t GetTangentAtUv(uint32_t uvIndex) const; + + //! Apply the tangent to the next UV, whose index is the same as GetUvStreamCount. + //! @param tangent the tangent/bitangent to be assigned. Ranged in [0, 0xF) + //! It comes from the model in order, e.g. 0 means the first available tangent stream from the model. + //! Specially, value 0xF(=UnassignedTangent) means generated tangent/bitangent will be used in shader. + //! If ranged out of definition, unassigned tangent will be applied. + void ApplyTangent(uint32_t tangent); + + //! Reset the bitmask to clear state. + void Reset(); + + //! The bit mask indicating generated tangent/bitangent will be used. + static constexpr uint32_t UnassignedTangent = 0b1111u; + + //! The variable name defined in the SRG shader code. + static constexpr const char* SrgName = "m_uvStreamTangentBitmask"; + private: + //! Mask composition: + //! The number of UV slots (highest 4 bits) + tangent mask (4 bits each) * 7 + //! e.g. 0x200000F0 means there are 2 UV streams, + //! the first UV stream uses 0th tangent stream (0x0), + //! the second UV stream uses the generated tangent stream (0xF). + uint32_t m_mask = 0; + + //! Bit size in the mask composition. + static constexpr uint32_t BitsPerTangent = 4; + static constexpr uint32_t BitsForUvIndex = 4; + + public: + //! Max UV slots available in this bit mask. + static constexpr uint32_t MaxUvSlots = (sizeof(m_mask) * CHAR_BIT - BitsForUvIndex) / BitsPerTangent; + }; + } +} diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp index 1cf3866158..c6a1a51f39 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/ModelLod.cpp @@ -439,56 +439,5 @@ namespace AZ m_buffers.emplace_back(buffer); return static_cast(m_buffers.size() - 1); } - - uint32_t UvStreamTangentBitmask::GetFullTangentBitmask() const - { - return m_mask; - } - - uint32_t UvStreamTangentBitmask::GetUvStreamCount() const - { - return m_mask >> (sizeof(m_mask) * CHAR_BIT - BitsForUvIndex); - } - - uint32_t UvStreamTangentBitmask::GetTangentAtUv(uint32_t uvIndex) const - { - return (m_mask >> (BitsPerTangent * uvIndex)) & 0b1111u; - } - - void UvStreamTangentBitmask::ApplyTangent(uint32_t tangentIndex) - { - uint32_t currentSlot = GetUvStreamCount(); - if (currentSlot >= MaxUvSlots) - { - AZ_Error("UV Stream", false, "Reaching the max of avaiblable stream slots."); - return; - } - - if (tangentIndex > UnassignedTangent) - { - AZ_Warning( - "UV Stream", false, - "Tangent index must use %d bits as defined in UvStreamTangentIndex::m_flag. Unassigned index will be applied.", - BitsPerTangent); - tangentIndex = UnassignedTangent; - } - - uint32_t clearMask = 0b1111u << (BitsPerTangent * currentSlot); - clearMask = ~clearMask; - - // Clear the writing bits in case - m_mask &= clearMask; - - // Write the bits to the slot - m_mask |= (tangentIndex << (BitsPerTangent * currentSlot)); - - // Increase the index - m_mask += (1u << (sizeof(m_mask) * CHAR_BIT - BitsForUvIndex)); - } - - void UvStreamTangentBitmask::Reset() - { - m_mask = 0; - } } // namespace RPI } // namespace AZ diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/UvStreamTangentBitmask.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/UvStreamTangentBitmask.cpp new file mode 100644 index 0000000000..829207e406 --- /dev/null +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/UvStreamTangentBitmask.cpp @@ -0,0 +1,71 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include + +namespace AZ +{ + namespace RPI + { + uint32_t UvStreamTangentBitmask::GetFullTangentBitmask() const + { + return m_mask; + } + + uint32_t UvStreamTangentBitmask::GetUvStreamCount() const + { + return m_mask >> (sizeof(m_mask) * CHAR_BIT - BitsForUvIndex); + } + + uint32_t UvStreamTangentBitmask::GetTangentAtUv(uint32_t uvIndex) const + { + return (m_mask >> (BitsPerTangent * uvIndex)) & 0b1111u; + } + + void UvStreamTangentBitmask::ApplyTangent(uint32_t tangentIndex) + { + uint32_t currentSlot = GetUvStreamCount(); + if (currentSlot >= MaxUvSlots) + { + AZ_Error("UV Stream", false, "Reaching the max of avaiblable stream slots."); + return; + } + + if (tangentIndex > UnassignedTangent) + { + AZ_Warning( + "UV Stream", false, + "Tangent index must use %d bits as defined in UvStreamTangentIndex::m_flag. Unassigned index will be applied.", + BitsPerTangent); + tangentIndex = UnassignedTangent; + } + + uint32_t clearMask = 0b1111u << (BitsPerTangent * currentSlot); + clearMask = ~clearMask; + + // Clear the writing bits in case + m_mask &= clearMask; + + // Write the bits to the slot + m_mask |= (tangentIndex << (BitsPerTangent * currentSlot)); + + // Increase the index + m_mask += (1u << (sizeof(m_mask) * CHAR_BIT - BitsForUvIndex)); + } + + void UvStreamTangentBitmask::Reset() + { + m_mask = 0; + } + } +} diff --git a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp index 64f759d496..1ec14c6169 100644 --- a/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp +++ b/Gems/Atom/RPI/Code/Tests/Model/ModelTests.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include diff --git a/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake b/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake index 0d5c19758b..6242f3f140 100644 --- a/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake +++ b/Gems/Atom/RPI/Code/atom_rpi_public_files.cmake @@ -57,6 +57,7 @@ set(FILES Include/Atom/RPI.Public/Model/ModelLod.h Include/Atom/RPI.Public/Model/ModelLodUtils.h Include/Atom/RPI.Public/Model/ModelSystem.h + Include/Atom/RPI.Public/Model/UvStreamTangentBitmask.h Include/Atom/RPI.Public/Pass/AttachmentReadback.h Include/Atom/RPI.Public/Pass/ComputePass.h Include/Atom/RPI.Public/Pass/CopyPass.h @@ -136,6 +137,7 @@ set(FILES Source/RPI.Public/Model/ModelLod.cpp Source/RPI.Public/Model/ModelLodUtils.cpp Source/RPI.Public/Model/ModelSystem.cpp + Source/RPI.Public/Model/UvStreamTangentBitmask.cpp Source/RPI.Public/Pass/AttachmentReadback.cpp Source/RPI.Public/Pass/ComputePass.cpp Source/RPI.Public/Pass/CopyPass.cpp