diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index a2d962b64..71541eb66 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -10,6 +10,7 @@ #include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/RenderTask.h" +#include "Engine/Graphics/RenderTools.h" #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Renderer/RenderList.h" #include "Engine/Scripting/ManagedCLR/MCore.h" @@ -41,14 +42,8 @@ namespace { const Float3 normal = normals[i]; const Float3 tangent = tangents[i]; - - // Calculate bitangent sign - Float3 bitangent = Float3::Normalize(Float3::Cross(normal, tangent)); - byte sign = static_cast(Float3::Dot(Float3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0); - - // Set tangent frame - vb1[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign); - vb1[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0); + auto& v = vb1.Get()[i]; + RenderTools::CalculateTangentFrame(v.Normal, v.Tangent, normal, tangent); } } else @@ -56,23 +51,8 @@ namespace for (uint32 i = 0; i < vertexCount; i++) { const Float3 normal = normals[i]; - - // Calculate tangent - Float3 c1 = Float3::Cross(normal, Float3::UnitZ); - Float3 c2 = Float3::Cross(normal, Float3::UnitY); - Float3 tangent; - if (c1.LengthSquared() > c2.LengthSquared()) - tangent = c1; - else - tangent = c2; - - // Calculate bitangent sign - Float3 bitangent = Float3::Normalize(Float3::Cross(normal, tangent)); - byte sign = static_cast(Float3::Dot(Float3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0); - - // Set tangent frame - vb1[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign); - vb1[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0); + auto& v = vb1.Get()[i]; + RenderTools::CalculateTangentFrame(v.Normal, v.Tangent, normal); } } } diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp index 8bc938684..cc65e59d6 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp @@ -9,6 +9,7 @@ #include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/RenderTask.h" +#include "Engine/Graphics/RenderTools.h" #include "Engine/Level/Scene/Scene.h" #include "Engine/Renderer/RenderList.h" #include "Engine/Serialization/MemoryReadStream.h" @@ -389,9 +390,7 @@ bool UpdateMesh(SkinnedMesh* mesh, MArray* verticesObj, MArray* trianglesObj, MA Array vb; vb.Resize(vertexCount); for (uint32 i = 0; i < vertexCount; i++) - { - vb[i].Position = vertices[i]; - } + vb.Get()[i].Position = vertices[i]; if (normalsObj) { const auto normals = MCore::Array::GetAddress(normalsObj); @@ -400,42 +399,19 @@ bool UpdateMesh(SkinnedMesh* mesh, MArray* verticesObj, MArray* trianglesObj, MA const auto tangents = MCore::Array::GetAddress(tangentsObj); for (uint32 i = 0; i < vertexCount; i++) { - // Peek normal and tangent const Float3 normal = normals[i]; const Float3 tangent = tangents[i]; - - // Calculate bitangent sign - Float3 bitangent = Float3::Normalize(Float3::Cross(normal, tangent)); - byte sign = static_cast(Float3::Dot(Float3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0); - - // Set tangent frame - vb[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign); - vb[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0); + auto& v = vb.Get()[i]; + RenderTools::CalculateTangentFrame(v.Normal, v.Tangent, normal, tangent); } } else { for (uint32 i = 0; i < vertexCount; i++) { - // Peek normal const Float3 normal = normals[i]; - - // Calculate tangent - Float3 c1 = Float3::Cross(normal, Float3::UnitZ); - Float3 c2 = Float3::Cross(normal, Float3::UnitY); - Float3 tangent; - if (c1.LengthSquared() > c2.LengthSquared()) - tangent = c1; - else - tangent = c2; - - // Calculate bitangent sign - Float3 bitangent = Float3::Normalize(Float3::Cross(normal, tangent)); - byte sign = static_cast(Float3::Dot(Float3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0); - - // Set tangent frame - vb[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign); - vb[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0); + auto& v = vb.Get()[i]; + RenderTools::CalculateTangentFrame(v.Normal, v.Tangent, normal); } } } diff --git a/Source/Engine/Graphics/RenderTools.cpp b/Source/Engine/Graphics/RenderTools.cpp index a40bde11b..55f4df7d2 100644 --- a/Source/Engine/Graphics/RenderTools.cpp +++ b/Source/Engine/Graphics/RenderTools.cpp @@ -10,6 +10,7 @@ #include "Engine/Content/Assets/Model.h" #include "Engine/Content/Assets/SkinnedModel.h" #include "Engine/Core/Log.h" +#include "Engine/Core/Math/Packed.h" #include "Engine/Engine/Time.h" const Char* ToString(RendererType value) @@ -538,6 +539,33 @@ void RenderTools::ComputeCascadeUpdateFrequency(int32 cascadeIndex, int32 cascad } } +void RenderTools::CalculateTangentFrame(FloatR10G10B10A2& resultNormal, FloatR10G10B10A2& resultTangent, const Float3& normal) +{ + // Calculate tangent + const Float3 c1 = Float3::Cross(normal, Float3::UnitZ); + const Float3 c2 = Float3::Cross(normal, Float3::UnitY); + const Float3 tangent = c1.LengthSquared() > c2.LengthSquared() ? c1 : c2; + + // Calculate bitangent sign + const Float3 bitangent = Float3::Normalize(Float3::Cross(normal, tangent)); + const byte sign = static_cast(Float3::Dot(Float3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0); + + // Set tangent frame + resultNormal = Float1010102(normal * 0.5f + 0.5f, 0); + resultTangent = Float1010102(tangent * 0.5f + 0.5f, sign); +} + +void RenderTools::CalculateTangentFrame(FloatR10G10B10A2& resultNormal, FloatR10G10B10A2& resultTangent, const Float3& normal, const Float3& tangent) +{ + // Calculate bitangent sign + const Float3 bitangent = Float3::Normalize(Float3::Cross(normal, tangent)); + const byte sign = static_cast(Float3::Dot(Float3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0); + + // Set tangent frame + resultNormal = Float1010102(normal * 0.5f + 0.5f, 0); + resultTangent = Float1010102(tangent * 0.5f + 0.5f, sign); +} + int32 MipLevelsCount(int32 width, bool useMipLevels) { if (!useMipLevels) diff --git a/Source/Engine/Graphics/RenderTools.h b/Source/Engine/Graphics/RenderTools.h index 7e399ec4a..6ded26c8e 100644 --- a/Source/Engine/Graphics/RenderTools.h +++ b/Source/Engine/Graphics/RenderTools.h @@ -9,6 +9,7 @@ class Model; class SkinnedModel; struct RenderContext; +struct FloatR10G10B10A2; PACK_STRUCT(struct QuadShaderData { @@ -119,6 +120,9 @@ public: ComputeCascadeUpdateFrequency(cascadeIndex, cascadeCount, updateFrequency, updatePhrase, updateMaxCountPerFrame); return (frameIndex % updateFrequency == updatePhrase) || updateForce; } + + static void CalculateTangentFrame(FloatR10G10B10A2& resultNormal, FloatR10G10B10A2& resultTangent, const Float3& normal); + static void CalculateTangentFrame(FloatR10G10B10A2& resultNormal, FloatR10G10B10A2& resultTangent, const Float3& normal, const Float3& tangent); }; // Calculate mip levels count for a texture 1D