diff --git a/Engine/Auto/Scripts/editor.lua b/Engine/Auto/Scripts/editor.lua index 74568e8e..e7645d41 100644 --- a/Engine/Auto/Scripts/editor.lua +++ b/Engine/Auto/Scripts/editor.lua @@ -62,8 +62,7 @@ project("Editor") if ENABLE_SPDLOG then defines { - -- TODO : Remove _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING after spdlog updates the format to the right version. - "SPDLOG_ENABLE", "SPDLOG_NO_EXCEPTIONS", "FMT_USE_NONTYPE_TEMPLATE_ARGS=0", "_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING", + "SPDLOG_ENABLE", "SPDLOG_NO_EXCEPTIONS", "SPDLOG_USE_STD_FORMAT", } includedirs { diff --git a/Engine/Auto/Scripts/engine.lua b/Engine/Auto/Scripts/engine.lua index d1869700..f6c8fb13 100644 --- a/Engine/Auto/Scripts/engine.lua +++ b/Engine/Auto/Scripts/engine.lua @@ -108,8 +108,7 @@ project("Engine") } defines { - -- TODO : Remove _SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING after spdlog updates the format to the right version. - "SPDLOG_ENABLE", "SPDLOG_NO_EXCEPTIONS", "FMT_USE_NONTYPE_TEMPLATE_ARGS=0", "_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING", + "SPDLOG_ENABLE", "SPDLOG_NO_EXCEPTIONS", "SPDLOG_USE_STD_FORMAT", } end diff --git a/Engine/BuiltInShaders/common/BRDF.sh b/Engine/BuiltInShaders/common/BRDF.sh index 05fd008c..189037e3 100644 --- a/Engine/BuiltInShaders/common/BRDF.sh +++ b/Engine/BuiltInShaders/common/BRDF.sh @@ -13,17 +13,36 @@ float DistributionGGX(float NdotH, float rough) { return a2 * CD_PI_INV * denom_inv * denom_inv; } -// Geometry -float Visibility(float NdotV, float NdotL, float rough) { - // Specular BRDF = (F * D * G) / (4 * NdotV * NdotL) - // = (F * D * (NdotV / (NdotV * (1 - K) + K)) * (NdotL / (NdotL * (1 - K) + K))) / (4 * NdotV * NdotL) - // = (F * D * (1 / (NdotV * (1 - K) + K)) * (1 / (NdotL * (1 - K) + K))) / 4 - // = F * D * Vis - // Vis = 1 / (NdotV * (1 - K) + K) / (NdotL * (1 - K) + K) / 4 +float Visibility_HighQuality(float NdotV, float NdotL, float rough) { + // BRDF = (F * D * G) / (4 * NdotV * NdotL) = F * D * V + // V = G / (4 * NdotV * NdotL) + // = 0.5 / (NdotL * sqrt(a2 + (1 - a2) * NdotV^2) + NdotV * sqrt(a2 + (1 - a2) * NdotL^2)) + + // rough = (rough + 1) / 2, by Disney + // a = rough^2 + float a2 = pow((rough + 1.0) * 0.5, 4); + float lambda_v = NdotL * sqrt(a2 + (1.0 - a2) * NdotV * NdotV); + float lambda_l = NdotV * sqrt(a2 + (1.0 - a2) * NdotL * NdotL); + + return 0.5 / (lambda_v + lambda_l); +} + +float Visibility_LowQuality(float NdotV, float NdotL, float rough) { + // BRDF = (F * D * G) / (4 * NdotV * NdotL) = F * D * V + // V = G / (4 * NdotV * NdotL) + // = 1 / ((NdotV * (2 - a) + a) * (NdotL * (2 - a) + a)) + + // rough = (rough + 1) / 2, by Disney + // a = rough^2 + float a = (rough + 1.0) * (rough + 1.0) * 0.25; + float g1_v_inv = NdotV * (2.0 - a) + a; + float g1_l_inv = NdotL * (2.0 - a) + a; - float f = rough + 1.0; - float k = f * f * 0.125; - float ggxV = 1.0 / (NdotV * (1.0 - k) + k); - float ggxL = 1.0 / (NdotL * (1.0 - k) + k); - return ggxV * ggxL * 0.25; + return 1.0 / (g1_v_inv * g1_l_inv); } + +// Geometry +float Visibility(float NdotV, float NdotL, float rough) { + // TODO : Wrap them in macros after we've collected enough approximate / exact formulas. + return Visibility_LowQuality(NdotV, NdotL, rough); +} \ No newline at end of file diff --git a/Engine/BuiltInShaders/common/Envirnoment.sh b/Engine/BuiltInShaders/common/Envirnoment.sh index 76b085d7..e3f24e4b 100644 --- a/Engine/BuiltInShaders/common/Envirnoment.sh +++ b/Engine/BuiltInShaders/common/Envirnoment.sh @@ -27,16 +27,14 @@ SAMPLER2D(s_texLUT, BRDF_LUT_SLOT); uniform vec4 u_iblStrength; -vec3 SampleEnvIrradiance(vec3 normal, float mip) { +vec3 SampleEnvIrradiance(vec3 normal) { // We use the HDR texture which in linear space. - vec3 cubeNormalDir = normalize(fixCubeLookup(normal, mip, 256.0)); - return textureCube(s_texCubeIrr, cubeNormalDir).xyz; + return textureCube(s_texCubeIrr, normal).xyz; } vec3 SampleEnvRadiance(vec3 reflectDir, float mip) { // We use the HDR texture which in linear space. - vec3 cubeReflectDir = normalize(fixCubeLookup(reflectDir, mip, 256.0)); - return textureCubeLod(s_texCubeRad, cubeReflectDir, mip).xyz; + return textureCubeLod(s_texCubeRad, reflectDir, mip).xyz; } vec2 SampleIBLSpecularBRDFLUT(float NdotV, float roughness) { @@ -57,11 +55,10 @@ vec3 GetIBL(Material material, vec3 vertexNormal, vec3 viewDir) { horizonOcclusion *= horizonOcclusion; float finalSpecularOcclusion = min(specularOcclusion, horizonOcclusion); - float mip = clamp(6.0 * material.roughness, 0.1, 6.0); - // Environment Prefiltered Irradiance - vec3 envIrradiance = SampleEnvIrradiance(material.normal, 0.0); + vec3 envIrradiance = SampleEnvIrradiance(material.normal); // Environment Specular Radiance + float mip = material.roughness * 6.0; vec3 envRadiance = SampleEnvRadiance(reflectDir, mip); // Environment Specular BRDF diff --git a/Engine/BuiltInShaders/common/LightSource.sh b/Engine/BuiltInShaders/common/LightSource.sh index 0ca00e5d..5faf3ada 100644 --- a/Engine/BuiltInShaders/common/LightSource.sh +++ b/Engine/BuiltInShaders/common/LightSource.sh @@ -12,6 +12,7 @@ uniform vec4 u_lightParams[LIGHT_LENGTH]; uniform mat4 u_lightViewProjs[4*3]; uniform vec4 u_clipFrustumDepth; uniform vec4 u_bias[3]; // [LIGHT_NUM] +uniform vec4 u_isCastShadow; SAMPLERCUBE(s_texCubeShadowMap_1, SHADOW_MAP_CUBE_FIRST_SLOT); SAMPLERCUBE(s_texCubeShadowMap_2, SHADOW_MAP_CUBE_SECOND_SLOT); @@ -185,7 +186,7 @@ vec3 CalculatePointLight(U_Light light, Material material, vec3 worldPos, vec3 v vec3 specularBRDF = Fre * NDF * Vis; vec3 KD = mix(vec3_splat(1.0) - Fre, vec3_splat(0.0), material.metallic); - float shadow = CalculatePointShadow(worldPos, light.position, light.range, lightIndex); + float shadow = CalculatePointShadow(worldPos, light.position, light.range, lightIndex) * u_isCastShadow.x; return (1 - shadow) * (KD * diffuseBRDF + specularBRDF) * radiance * NdotL; } @@ -237,7 +238,7 @@ vec3 CalculateSpotLight(U_Light light, Material material, vec3 worldPos, vec3 vi vec3 specularBRDF = Fre * NDF * Vis; vec3 KD = mix(1.0 - Fre, vec3_splat(0.0), material.metallic); - float shadow = CalculateSpotShadow(worldPos, material.normal, lightDir, light.lightViewProjOffset, lightIndex); + float shadow = CalculatePointShadow(worldPos, light.position, light.range, lightIndex) * u_isCastShadow.x; return (1.0 - shadow) * (KD * diffuseBRDF + specularBRDF) * radiance * NdotL; } @@ -310,7 +311,7 @@ vec3 CalculateDirectionalLight(U_Light light, Material material, vec3 worldPos, vec3 KD = mix(1.0 - Fre, vec3_splat(0.0), material.metallic); vec3 irradiance = light.color * light.intensity; - float shadow = CalculateCascadedDirectionalShadow(worldPos, material.normal, lightDir, csmDepth, light.lightViewProjOffset, lightIndex); + float shadow = CalculateCascadedDirectionalShadow(worldPos, material.normal, lightDir, csmDepth, light.lightViewProjOffset, lightIndex) * u_isCastShadow.x; return (1.0 - shadow) * (KD * diffuseBRDF + specularBRDF) * irradiance * NdotL; } diff --git a/Engine/BuiltInShaders/common/Material.sh b/Engine/BuiltInShaders/common/Material.sh index 6b587d1a..21067fa3 100644 --- a/Engine/BuiltInShaders/common/Material.sh +++ b/Engine/BuiltInShaders/common/Material.sh @@ -21,7 +21,7 @@ struct Material { }; uniform vec4 u_albedoColor; -uniform vec4 u_metallicRoughnessFactor; +uniform vec4 u_metallicRoughnessRefectanceFactor; uniform vec4 u_albedoUVOffsetAndScale; uniform vec4 u_alphaCutOff; @@ -110,15 +110,16 @@ Material GetMaterial(vec2 uv, vec3 normal, mat3 TBN) { material.roughness = orm.y; material.metallic = orm.z; #else - material.roughness = u_metallicRoughnessFactor.y; - material.metallic = u_metallicRoughnessFactor.x; + material.roughness = u_metallicRoughnessRefectanceFactor.y; + material.metallic = u_metallicRoughnessRefectanceFactor.x; #endif #if defined(EMISSIVEMAP) material.emissive = SampleEmissiveTexture(uv); #endif - material.F0 = mix(vec3_splat(0.04), material.albedo, material.metallic); + float refectance = u_metallicRoughnessRefectanceFactor.z; + material.F0 = mix(0.16 * refectance * refectance, material.albedo, material.metallic); return material; } diff --git a/Engine/BuiltInShaders/common/common.sh b/Engine/BuiltInShaders/common/common.sh index fe8c54ab..60444921 100644 --- a/Engine/BuiltInShaders/common/common.sh +++ b/Engine/BuiltInShaders/common/common.sh @@ -4,4 +4,12 @@ #define CD_PI 3.1415926536 #define CD_PI2 9.8696044011 #define CD_PI_INV 0.3183098862 -#define CD_PI_INV2 0.1013211836 \ No newline at end of file +#define CD_PI_INV2 0.1013211836 + +// https://baddogzz.github.io/2020/03/04/SGA-Pow-Opt/ +float pow_low(float x, float n) +{ + // 1.4427f --> 1/ln(2) + n = n * 1.4427 + 1.4427; + return exp2(x * n - n); +} diff --git a/Engine/BuiltInShaders/shaders/fs_PBR_postProcessing.sc b/Engine/BuiltInShaders/shaders/fs_postProcessing.sc similarity index 100% rename from Engine/BuiltInShaders/shaders/fs_PBR_postProcessing.sc rename to Engine/BuiltInShaders/shaders/fs_postProcessing.sc diff --git a/Engine/BuiltInShaders/shaders/vs_skeleton.sc b/Engine/BuiltInShaders/shaders/vs_skeleton.sc new file mode 100644 index 00000000..7b95f3bd --- /dev/null +++ b/Engine/BuiltInShaders/shaders/vs_skeleton.sc @@ -0,0 +1,12 @@ +$input a_position, a_indices + +#include "../common/common.sh" + +uniform mat4 u_boneMatrices[128]; + +void main() +{ + mat4 boneTransform = u_boneMatrices[a_indices[0]]; + vec4 localPosition = mul(boneTransform, vec4(a_position, 1.0)); + gl_Position = mul(u_modelViewProj, localPosition); +} \ No newline at end of file diff --git a/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp b/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp index eeba0b38..27887640 100644 --- a/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp +++ b/Engine/Source/Editor/ECWorld/ECWorldConsumer.cpp @@ -9,11 +9,13 @@ #include "Rendering/RenderContext.h" #include "Rendering/Resources/MeshResource.h" #include "Rendering/Resources/ResourceContext.h" +#include "Rendering/Resources/SkeletonResource.h" #include "Rendering/Resources/TextureResource.h" #include "Rendering/ShaderFeature.h" #include "Resources/ResourceBuilder.h" #include "Resources/ResourceLoader.h" #include "Resources/ShaderBuilder.h" +#include "Rendering/Utility/VertexLayoutUtility.h" #include "Scene/SceneDatabase.h" #include @@ -57,13 +59,17 @@ void ECWorldConsumer::Execute(const cd::SceneDatabase* pSceneDatabase) bool hasSkin = mesh.GetSkinIDCount() > 0U; if (hasSkin) { - engine::MaterialType* pMaterialType = m_pSceneWorld->GetAnimationMaterialType(); - AddSkinMesh(meshEntity, mesh, pMaterialType->GetRequiredVertexFormat()); - // TODO : Use a standalone .cdanim file to play animation. // Currently, we assume that imported SkinMesh will play animation automatically for testing. - AddAnimation(meshEntity, pSceneDatabase->GetAnimation(0), pSceneDatabase); - AddMaterial(meshEntity, nullptr, pMaterialType, pSceneDatabase); + //TODO : depens on skeleton to match animation + if (pSceneDatabase->GetAnimationCount() <= 1U) + { + engine::MaterialType* pMaterialType = m_pSceneWorld->GetAnimationMaterialType(); + AddSkinMesh(meshEntity, mesh, pMaterialType->GetRequiredVertexFormat(), pSceneDatabase); + AddAnimation(meshEntity, pSceneDatabase->GetAnimation(0), pSceneDatabase); + AddMaterial(meshEntity, nullptr, pMaterialType, pSceneDatabase); + AddSkeleton(meshEntity, pSceneDatabase); + } } else { @@ -185,9 +191,39 @@ void ECWorldConsumer::AddStaticMesh(engine::Entity entity, const cd::Mesh& mesh, staticMeshComponent.SetMeshResource(pMeshResource); } -void ECWorldConsumer::AddSkinMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat) +void ECWorldConsumer::AddSkinMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat, const cd::SceneDatabase* pSceneDatabase) { - AddStaticMesh(entity, mesh, vertexFormat); + assert(mesh.GetVertexCount() > 0 && mesh.GetPolygonCount() > 0); + + engine::World* pWorld = m_pSceneWorld->GetWorld(); + auto& nameComponent = pWorld->CreateComponent(entity); + std::string meshName(mesh.GetName()); + engine::StringCrc meshNameCrc(meshName); + nameComponent.SetName(cd::MoveTemp(meshName)); + + auto& collisionMeshComponent = pWorld->CreateComponent(entity); + collisionMeshComponent.SetType(engine::CollisonMeshType::AABB); + collisionMeshComponent.SetAABB(mesh.GetAABB()); + collisionMeshComponent.Build(); + + auto& staticMeshComponent = pWorld->CreateComponent(entity); + engine::MeshResource* pMeshResource = m_pResourceContext->AddMeshResource(meshNameCrc); + pMeshResource->SetMeshAsset(&mesh); + + //auto& skinMeshComponent = pWorld->CreateComponent(entity); + for (auto skinID : mesh.GetSkinIDs()) + { + pMeshResource->SetSkinAsset(&pSceneDatabase->GetSkin(skinID.Data())); + auto skeletonID = pSceneDatabase->GetSkin(skinID.Data()).GetSkeletonID(); + auto& skeleton = pSceneDatabase->GetSkeleton(skeletonID.Data()); + for (auto boneID : skeleton.GetBoneIDs()) + { + pMeshResource->AddBonesAsset(pSceneDatabase->GetBone(boneID.Data())); + } + } + + pMeshResource->UpdateVertexFormat(vertexFormat); + staticMeshComponent.SetMeshResource(pMeshResource); } void ECWorldConsumer::AddAnimation(engine::Entity entity, const cd::Animation& animation, const cd::SceneDatabase* pSceneDatabase) @@ -435,4 +471,18 @@ void ECWorldConsumer::AddParticleEmitter(engine::Entity entity, const cd::Mesh& particleEmitterComponent.Build(); } +void ECWorldConsumer::AddSkeleton(engine::Entity entity, const cd::SceneDatabase* pSceneDatabase) +{ + engine::World* pWorld = m_pSceneWorld->GetWorld(); + auto& SkeletonComponent = pWorld->CreateComponent(entity); + + auto& skeleton = pSceneDatabase->GetSkeleton(0); + std::string meshName(skeleton.GetName()); + engine::StringCrc meshNameCrc(meshName); + engine::SkeletonResource* pSkeletonResource = m_pResourceContext->AddSkeletonResource(meshNameCrc); + pSkeletonResource->SetSceneDataBase(pSceneDatabase); + SkeletonComponent.SetSkeletonAsset(pSkeletonResource); + +} + } \ No newline at end of file diff --git a/Engine/Source/Editor/ECWorld/ECWorldConsumer.h b/Engine/Source/Editor/ECWorld/ECWorldConsumer.h index 8359055a..fa05132b 100644 --- a/Engine/Source/Editor/ECWorld/ECWorldConsumer.h +++ b/Engine/Source/Editor/ECWorld/ECWorldConsumer.h @@ -66,7 +66,8 @@ class ECWorldConsumer final : public cdtools::IConsumer void AddLight(engine::Entity entity, const cd::Light& light); void AddTransform(engine::Entity entity, const cd::Transform& transform); void AddStaticMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat); - void AddSkinMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat); + void AddSkinMesh(engine::Entity entity, const cd::Mesh& mesh, const cd::VertexFormat& vertexFormat, const cd::SceneDatabase* pSceneDatabase); + void AddSkeleton(engine::Entity entity, const cd::SceneDatabase* pSceneDatabase); void AddAnimation(engine::Entity entity, const cd::Animation& animation, const cd::SceneDatabase* pSceneDatabase); void AddMaterial(engine::Entity entity, const cd::Material* pMaterial, engine::MaterialType* pMaterialType, const cd::SceneDatabase* pSceneDatabase); void AddBlendShape(engine::Entity entity, const cd::Mesh* pMesh, const cd::BlendShape& blendShape, const cd::SceneDatabase* pSceneDatabase); diff --git a/Engine/Source/Editor/EditorApp.cpp b/Engine/Source/Editor/EditorApp.cpp index e6a7c582..c7e0cfd2 100644 --- a/Engine/Source/Editor/EditorApp.cpp +++ b/Engine/Source/Editor/EditorApp.cpp @@ -103,6 +103,8 @@ void EditorApp::Init(engine::EngineInitArgs initArgs) InitECWorld(); m_pEditorImGuiContext->SetSceneWorld(m_pSceneWorld.get()); + // In order to avoid temporary handling of bugs + m_pSceneWorld->GetSceneDatabase()->GetMeshes().reserve(100); InitEngineRenderers(); @@ -382,7 +384,7 @@ void EditorApp::OnShaderHotModifiedCallback(const char* rootDir, const char* fil // Do nothing when a non-shader file is detected. return; } - m_pRenderContext->OnShaderHotModified(engine::StringCrc{ engine::Path::GetFileNameWithoutExtension(filePath) }); + m_pRenderContext->OnShaderHotModified(engine::Path::GetFileNameWithoutExtension(filePath)); } void EditorApp::UpdateMaterials() @@ -492,6 +494,14 @@ void EditorApp::InitEngineRenderers() AddEngineRenderer(cd::MoveTemp(pPBRSkyRenderer)); } + auto pSkeletonRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); + pSkeletonRenderer->SetSceneWorld(m_pSceneWorld.get()); + AddEngineRenderer(cd::MoveTemp(pSkeletonRenderer)); + + auto pAnimationRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); + pAnimationRenderer->SetSceneWorld(m_pSceneWorld.get()); + AddEngineRenderer(cd::MoveTemp(pAnimationRenderer)); + auto pSceneRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); m_pSceneRenderer = pSceneRenderer.get(); pSceneRenderer->SetSceneWorld(m_pSceneWorld.get()); @@ -516,14 +526,6 @@ void EditorApp::InitEngineRenderers() pTerrainRenderer->SetSceneWorld(m_pSceneWorld.get()); AddEngineRenderer(cd::MoveTemp(pTerrainRenderer)); - auto pSkeletonRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); - pSkeletonRenderer->SetSceneWorld(m_pSceneWorld.get()); - AddEngineRenderer(cd::MoveTemp(pSkeletonRenderer)); - - auto pAnimationRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); - pAnimationRenderer->SetSceneWorld(m_pSceneWorld.get()); - AddEngineRenderer(cd::MoveTemp(pAnimationRenderer)); - auto pWhiteModelRenderer = std::make_unique(m_pRenderContext->CreateView(), pSceneRenderTarget); m_pWhiteModelRenderer = pWhiteModelRenderer.get(); pWhiteModelRenderer->SetSceneWorld(m_pSceneWorld.get()); diff --git a/Engine/Source/Editor/Resources/ResourceBuilder.cpp b/Engine/Source/Editor/Resources/ResourceBuilder.cpp index d0de346b..0ba8b69d 100644 --- a/Engine/Source/Editor/Resources/ResourceBuilder.cpp +++ b/Engine/Source/Editor/Resources/ResourceBuilder.cpp @@ -297,6 +297,7 @@ TaskHandle ResourceBuilder::AddRadianceCubeMapBuildTask(const char* pInputFilePa } std::string pathWithoutExtension = std::filesystem::path(pOutputFilePath).replace_extension().generic_string(); + // TODO : mipCount should be affected by dstFaceSize, need to parameterize them in the future. std::vector radianceCommandArguments{"--input", pInputFilePath, "--filter", "radiance", "--lightingModel", "phongbrdf", "--excludeBase", "true", "--mipCount", "7", "--dstFaceSize", "256", diff --git a/Engine/Source/Editor/UILayers/AssetBrowser.cpp b/Engine/Source/Editor/UILayers/AssetBrowser.cpp index 023cd7ed..a688af0a 100644 --- a/Engine/Source/Editor/UILayers/AssetBrowser.cpp +++ b/Engine/Source/Editor/UILayers/AssetBrowser.cpp @@ -839,7 +839,7 @@ void AssetBrowser::ImportAssetFile(const char* pFilePath) std::filesystem::path absolutePath = CDPROJECT_RESOURCES_ROOT_PATH; absolutePath /= relativePath; - CD_INFO("Compile skybox textures to {0}.", absolutePath); + CD_INFO("Compile skybox textures to {0}.", absolutePath.generic_string()); std::string irrdianceOutput = absolutePath.generic_string() + "_irr.dds"; ResourceBuilder::Get().AddIrradianceCubeMapBuildTask(pFilePath, irrdianceOutput.c_str()); @@ -997,7 +997,6 @@ void AssetBrowser::ImportModelFile(const char* pFilePath) // Step 2 : Process generated cd::SceneDatabase ProcessSceneDatabase(pSceneDatabase, m_importOptions.ImportMesh, m_importOptions.ImportMaterial, m_importOptions.ImportTexture, m_importOptions.ImportCamera, m_importOptions.ImportLight); - // Step 3 : Convert cd::SceneDatabase to entities and components { ECWorldConsumer ecConsumer(pSceneWorld, pCurrentRenderContext); diff --git a/Engine/Source/Editor/UILayers/AssetBrowser.h b/Engine/Source/Editor/UILayers/AssetBrowser.h index 0538a566..da4349c8 100644 --- a/Engine/Source/Editor/UILayers/AssetBrowser.h +++ b/Engine/Source/Editor/UILayers/AssetBrowser.h @@ -51,7 +51,7 @@ struct AssetImportOptions bool ImportMaterial = true; bool ImportMesh = true; bool ImportTexture = true; - bool ImportAnimation = false; + bool ImportAnimation = true; }; struct AssetExportOptions diff --git a/Engine/Source/Editor/UILayers/EntityList.cpp b/Engine/Source/Editor/UILayers/EntityList.cpp index 2c5e2890..28a06cf4 100644 --- a/Engine/Source/Editor/UILayers/EntityList.cpp +++ b/Engine/Source/Editor/UILayers/EntityList.cpp @@ -285,6 +285,40 @@ void EntityList::AddEntity(engine::SceneWorld* pSceneWorld) particleForceFieldComponent.Build(); } + + else if (ImGui::MenuItem("PBR Demo")) + { + engine::Entity entity = AddNamedEntity("DirectionalLight"); + auto& lightComponent = CreateLightComponents(entity, cd::LightType::Directional, 4.0f, cd::Vec3f(1.0f, 1.0f, 1.0f), true); + lightComponent.SetDirection(cd::Direction(0.65f, -0.65f, 0.3f)); + lightComponent.SetCascadeNum(4); + lightComponent.SetIsCastShadow(false); + lightComponent.SetFrustumClips(cd::Vec4f(0.0f, 0.0f, 0.0f, 0.0f)); + lightComponent.SetShadowMapTexture(BGFX_INVALID_HANDLE); + + for (int horizontalIndex = 0 ; horizontalIndex < 7; ++horizontalIndex) + { + for (int verticalIndex = 0; verticalIndex < 7; ++verticalIndex) + { + engine::Entity entity = AddNamedEntity("Sphere"); + std::optional optMesh = cd::MeshGenerator::Generate(cd::Sphere(cd::Point(0.0f), 10.0f), 100U, 100U, pPBRMaterialType->GetRequiredVertexFormat()); + assert(optMesh.has_value()); + optMesh->SetName("Sphere"); + CreateShapeComponents(entity, cd::MoveTemp(optMesh.value()), pPBRMaterialType); + + auto* pTransformComponent = pSceneWorld->GetTransformComponent(entity); + cd::Transform transform = cd::Transform::Identity(); + transform.SetTranslation(cd::Vec3f(26.0f * (horizontalIndex - 4), 26.0f * (verticalIndex - 4), 0.0f)); + pTransformComponent->SetTransform(transform); + pTransformComponent->Build(); + + auto* pMaterialComponent = pSceneWorld->GetMaterialComponent(entity); + pMaterialComponent->SetFactor(cd::MaterialPropertyGroup::Metallic, horizontalIndex * (1.0f / 6.0f)); + pMaterialComponent->SetFactor(cd::MaterialPropertyGroup::Roughness, verticalIndex * (1.0f / 6.0f)); + } + } + + } } void EntityList::DrawEntity(engine::SceneWorld* pSceneWorld, engine::Entity entity) diff --git a/Engine/Source/Editor/UILayers/Inspector.cpp b/Engine/Source/Editor/UILayers/Inspector.cpp index 21352e6b..95158932 100644 --- a/Engine/Source/Editor/UILayers/Inspector.cpp +++ b/Engine/Source/Editor/UILayers/Inspector.cpp @@ -278,6 +278,21 @@ void UpdateComponentWidget(engine::SceneWorld* pScene ImGui::PopStyleVar(); } + // PBR + { + bool isOpen = ImGui::CollapsingHeader("PBR", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); + ImGui::Separator(); + if (isOpen) + { + ImGuiUtils::ImGuiFloatProperty("iblStrength", pMaterialComponent->GetIblStrengeth(), cd::Unit::None, 0.01f, 10.0f, false, 0.02f); + ImGuiUtils::ImGuiFloatProperty("Reflectance", pMaterialComponent->GetReflectance(), cd::Unit::None, 0.0f, 1.0f); + } + + ImGui::Separator(); + ImGui::PopStyleVar(); + } + // Cartoon { bool isOpen = ImGui::CollapsingHeader("Cartoon Material", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_Selected); @@ -309,31 +324,14 @@ void UpdateComponentWidget(engine::SceneWorld* pScene ImGui::PopStyleVar(); } - // Ambient - { - bool isOpen = ImGui::CollapsingHeader("Ambient", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); - ImGui::Separator(); - if (isOpen) - { - ImGuiUtils::ImGuiFloatProperty("iblStrength", pMaterialComponent->GetIblStrengeth(), cd::Unit::None, 0.01f, 10.0f, false, 0.02f); - } - - ImGui::Separator(); - ImGui::PopStyleVar(); - } - // Shaders { bool isOpen = ImGui::CollapsingHeader("Shader", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); ImGui::Separator(); - if (isOpen) + if (const engine::ShaderResource* pShaderResource = pMaterialComponent->GetShaderResource(); pShaderResource && isOpen) { - engine::RenderContext* pRenderContext = static_cast(ImGui::GetIO().BackendRendererUserData); - const engine::ShaderResource* pShaderResource = pMaterialComponent->GetShaderResource(); - ImGuiUtils::ImGuiStringProperty("Shader Program", pShaderResource->GetName()); ImGuiUtils::ImGuiStringProperty("Shader", pShaderResource->GetShaderInfo(0).name); if (engine::ShaderProgramType::Standard == pShaderResource->GetType()) @@ -715,6 +713,32 @@ void UpdateComponentWidget(engine::SceneWor ImGui::PopStyleVar(); } +template<> +void UpdateComponentWidget(engine::SceneWorld* pSceneWorld, engine::Entity entity) +{ + auto* pAnimationComponent = pSceneWorld->GetAnimationComponent(entity); + if (!pAnimationComponent) + { + return; + } + + bool isOpen = ImGui::CollapsingHeader("Animation Component", ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_DefaultOpen); + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); + ImGui::Separator(); + + if (isOpen) + { + ImGui::Separator(); + ImGuiUtils::ImGuiBoolProperty("play", pAnimationComponent->IsPlaying()); + ImGuiUtils::ImGuiEnumProperty("AnimationClip", pAnimationComponent->GetAnimationClip()); + ImGuiUtils::ImGuiFloatProperty("Factor", pAnimationComponent->GetBlendFactor(), cd::Unit::None, 0.0f, 1.0f, false, 0.01f); + ImGuiUtils::ImGuiFloatProperty("Time", pAnimationComponent->GetAnimationPlayTime(), cd::Unit::None); + ImGuiUtils::ImGuiFloatProperty("PlayBackSpeed", pAnimationComponent->GetPlayBackSpeed(), cd::Unit::None, 0.0f, 10.0f, false, 0.01f); + } + ImGui::Separator(); + ImGui::PopStyleVar(); +} + } namespace editor @@ -766,6 +790,7 @@ void Inspector::Update() details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); + details::UpdateComponentWidget(pSceneWorld, m_lastSelectedEntity); if (IsOpenFileBrowser()) { diff --git a/Engine/Source/Editor/UILayers/SkeletonView.cpp b/Engine/Source/Editor/UILayers/SkeletonView.cpp index fc488cf6..bdd21b3d 100644 --- a/Engine/Source/Editor/UILayers/SkeletonView.cpp +++ b/Engine/Source/Editor/UILayers/SkeletonView.cpp @@ -44,12 +44,17 @@ void SkeletonView::DrawBone(cd::SceneDatabase* pSceneDatabase, const cd::Bone& B void SkeletonView::DrawSkeleton(engine::SceneWorld* pSceneWorld) { cd::SceneDatabase* pSceneDatabase = pSceneWorld->GetSceneDatabase(); - if (0 == pSceneDatabase->GetBoneCount()) + if (0 == pSceneDatabase->GetSkeletonCount()) { return; } - const cd::Bone& rootBone = pSceneDatabase->GetBone(0); - DrawBone(pSceneDatabase, rootBone); + for (uint32_t skeletonIndex = 0; skeletonIndex < pSceneDatabase->GetSkeletonCount(); skeletonIndex++) + { + const cd::Skeleton& skeleton = pSceneDatabase->GetSkeleton(skeletonIndex); + auto rootBoneID = skeleton.GetRootBoneID(); + const cd::Bone& rootBone = pSceneDatabase->GetBone(rootBoneID.Data()); + DrawBone(pSceneDatabase, rootBone); + } } void SkeletonView::Update() @@ -63,11 +68,7 @@ void SkeletonView::Update() ImGui::End(); return; } - engine::AnimationComponent* pAnimationConponent = pSceneWorld->GetAnimationComponent(selectedEntity); - if (pAnimationConponent) - { - DrawSkeleton(pSceneWorld); - } + DrawSkeleton(pSceneWorld); ImGui::End(); } diff --git a/Engine/Source/Editor/UILayers/SkeletonView.h b/Engine/Source/Editor/UILayers/SkeletonView.h index 21252484..8f433088 100644 --- a/Engine/Source/Editor/UILayers/SkeletonView.h +++ b/Engine/Source/Editor/UILayers/SkeletonView.h @@ -2,6 +2,7 @@ #include "Scene/Bone.h" #include "Scene/SceneDatabase.h" +#include "Scene/Skeleton.h" namespace editor { diff --git a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h index be1e9312..9c8e2568 100644 --- a/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h +++ b/Engine/Source/Runtime/ECWorld/AllComponentsHeader.h @@ -13,6 +13,8 @@ #include "ECWorld/NameComponent.h" #include "ECWorld/SkyComponent.h" #include "ECWorld/StaticMeshComponent.h" +#include "ECWorld/SkeletonComponent.h" +#include "ECWorld/SkinMeshComponent.h" #include "ECWorld/TerrainComponent.h" #include "ECWorld/TransformComponent.h" #include "ECWorld/ParticleEmitterComponent.h" diff --git a/Engine/Source/Runtime/ECWorld/AnimationComponent.h b/Engine/Source/Runtime/ECWorld/AnimationComponent.h index 2430324a..0e214ee7 100644 --- a/Engine/Source/Runtime/ECWorld/AnimationComponent.h +++ b/Engine/Source/Runtime/ECWorld/AnimationComponent.h @@ -16,6 +16,17 @@ class Track; namespace engine { +enum class AnimationClip +{ + Idle, + Walking, + Running, + + Blend, + Switch, + Count, +}; + class AnimationComponent final { public: @@ -35,28 +46,51 @@ class AnimationComponent final const cd::Animation* GetAnimationData() const { return m_pAnimation; } void SetAnimationData(const cd::Animation* pAnimation) { m_pAnimation = pAnimation; } - + // TODO : use std::span to present pointer array. const cd::Track* GetTrackData() const { return m_pTrack; } void SetTrackData(const cd::Track* pTrack) { m_pTrack = pTrack; } void SetDuration(float duration) { m_duration = duration; } + float& GetDuration() { return m_duration; } float GetDuration() const { return m_duration; } void SetTicksPerSecond(float ticksPerSecond) { m_ticksPerSecond = ticksPerSecond; } + float& GetTicksPerSecond() { return m_ticksPerSecond; } float GetTicksPerSecond() const { return m_ticksPerSecond; } void SetBoneMatricesUniform(uint16_t uniform) { m_boneMatricesUniform = uniform; } + uint16_t& GetBoneMatrixsUniform() { return m_boneMatricesUniform; } uint16_t GetBoneMatrixsUniform() const { return m_boneMatricesUniform; } - void SetBoneMatrices(std::vector boneMatrices) { m_boneMatrices = cd::MoveTemp(boneMatrices); } - std::vector& GetBoneMatrices() { return m_boneMatrices; } - const std::vector& GetBoneMatrices() const { return m_boneMatrices; } + void SetAnimationPlayTime(float time) { m_animationPlayTime = time; } + float& GetAnimationPlayTime() { return m_animationPlayTime; } + float GetAnimationPlayTime() const { return m_animationPlayTime; } + + void SetPlayBackSpeed(float time) { m_playBackSpeed = time; } + float& GetPlayBackSpeed() { return m_playBackSpeed; } + float GetPlayBackSpeed() const { return m_playBackSpeed; } + + void SetAnimationClip(AnimationClip crtClip) { m_clip = crtClip; } + AnimationClip& GetAnimationClip() { return m_clip; } + const AnimationClip& GeAnimationClip() const { return m_clip; } + + void SetBlendFactor(float factor) { m_blendFactor = factor; } + float& GetBlendFactor() { return m_blendFactor; } + float GetBlendFactor() const { return m_blendFactor; } + + bool& IsPlaying() { return m_playAnimation; } private: + AnimationClip m_clip = AnimationClip::Idle; const cd::Animation* m_pAnimation = nullptr; const cd::Track* m_pTrack = nullptr; - + + float m_blendFactor; + float m_playBackSpeed; + bool m_playAnimation; + + float m_animationPlayTime; float m_duration; float m_ticksPerSecond; uint16_t m_boneMatricesUniform; diff --git a/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp b/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp index bb2c1c5a..36cddd2b 100644 --- a/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp +++ b/Engine/Source/Runtime/ECWorld/MaterialComponent.cpp @@ -154,8 +154,7 @@ void MaterialComponent::SetShaderResource(ShaderResource* pShaderResource) ShaderResource* MaterialComponent::GetShaderResource() const { - assert(!m_isShaderResourceDirty); - return m_pShaderResource; + return m_isShaderResourceDirty ? nullptr : m_pShaderResource; } TextureResource* MaterialComponent::GetTextureResource(cd::MaterialTextureType textureType) const diff --git a/Engine/Source/Runtime/ECWorld/MaterialComponent.h b/Engine/Source/Runtime/ECWorld/MaterialComponent.h index 0f7571f6..efc3a875 100644 --- a/Engine/Source/Runtime/ECWorld/MaterialComponent.h +++ b/Engine/Source/Runtime/ECWorld/MaterialComponent.h @@ -184,6 +184,10 @@ class MaterialComponent final float& GetIblStrengeth() { return m_iblStrength; } float GetIblStrengeth() const { return m_iblStrength; } + void SetReflectance(float reflectance) { m_reflectance = reflectance; } + float& GetReflectance() { return m_reflectance; } + float GetReflectance() const { return m_reflectance; } + void SetToonParameters(ToonParameters toonParameters) { m_toonParameters = toonParameters; } ToonParameters& GetToonParameters() { return m_toonParameters; } ToonParameters GetToonParameters() const { return m_toonParameters; } @@ -204,7 +208,8 @@ class MaterialComponent final bool m_twoSided; cd::BlendMode m_blendMode; float m_alphaCutOff; - float m_iblStrength = 0.5f; + float m_iblStrength = 1.0f; + float m_reflectance = 0.5f; ToonParameters m_toonParameters; std::map m_propertyGroups; }; diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp index a85a92d4..013f89fa 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.cpp +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.cpp @@ -35,6 +35,8 @@ SceneWorld::SceneWorld() m_pNameComponentStorage = m_pWorld->Register(); m_pSkyComponentStorage = m_pWorld->Register(); m_pStaticMeshComponentStorage = m_pWorld->Register(); + m_pSkinMeshComponentStorage = m_pWorld->Register(); + m_pSkeletonComponentStorage = m_pWorld->Register(); m_pParticleEmitterComponentStorage = m_pWorld->Register(); m_pParticleRibbonComponentStorage = m_pWorld->Register(); m_pParticleForceFieldComponentStorage = m_pWorld->Register(); diff --git a/Engine/Source/Runtime/ECWorld/SceneWorld.h b/Engine/Source/Runtime/ECWorld/SceneWorld.h index d2e8d3cc..5dd64340 100644 --- a/Engine/Source/Runtime/ECWorld/SceneWorld.h +++ b/Engine/Source/Runtime/ECWorld/SceneWorld.h @@ -38,6 +38,8 @@ class SceneWorld DEFINE_COMPONENT_STORAGE_WITH_APIS(Light); DEFINE_COMPONENT_STORAGE_WITH_APIS(Material); DEFINE_COMPONENT_STORAGE_WITH_APIS(Name); + DEFINE_COMPONENT_STORAGE_WITH_APIS(Skeleton); + DEFINE_COMPONENT_STORAGE_WITH_APIS(SkinMesh); DEFINE_COMPONENT_STORAGE_WITH_APIS(Sky); DEFINE_COMPONENT_STORAGE_WITH_APIS(StaticMesh); DEFINE_COMPONENT_STORAGE_WITH_APIS(ParticleEmitter); @@ -97,6 +99,8 @@ class SceneWorld DeleteLightComponent(entity); DeleteMaterialComponent(entity); DeleteNameComponent(entity); + DeleteSkeletonComponent(entity); + DeleteSkinMeshComponent(entity); DeleteSkyComponent(entity); DeleteStaticMeshComponent(entity); DeleteParticleEmitterComponent(entity); diff --git a/Engine/Source/Runtime/ECWorld/SkeletonComponent.cpp b/Engine/Source/Runtime/ECWorld/SkeletonComponent.cpp new file mode 100644 index 00000000..81b10cbc --- /dev/null +++ b/Engine/Source/Runtime/ECWorld/SkeletonComponent.cpp @@ -0,0 +1,38 @@ +#include "SkeletonComponent.h" +#include "Rendering/Resources/SkeletonResource.h" + +namespace engine +{ + +namespace details +{ + +} + +void SkeletonComponent::Reset() +{ + +} + +void SkeletonComponent::Build() +{ + +} + +void SkeletonComponent::SetSkeletonAsset(const SkeletonResource* pSkeletonResource) +{ + int boneCount = pSkeletonResource->GetBoneCount(); + m_pSkeletonResource = pSkeletonResource; + m_boneIBH = m_pSkeletonResource->GetIndexBufferHandle(); + m_boneVBH = m_pSkeletonResource->GetVertexBufferHandle(); + m_boneGlobalMatrices.resize(boneCount, cd::Matrix4x4::Identity()); + m_boneMatrices.resize(boneCount, cd::Matrix4x4::Identity()); +} + +void SkeletonComponent::SetBoneGlobalMatrix(uint32_t index, const cd::Matrix4x4& boneGlobalMatrix) +{ + m_boneGlobalMatrices[index] = boneGlobalMatrix; + m_boneIndex = index; +} + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/SkeletonComponent.h b/Engine/Source/Runtime/ECWorld/SkeletonComponent.h new file mode 100644 index 00000000..8ebe260e --- /dev/null +++ b/Engine/Source/Runtime/ECWorld/SkeletonComponent.h @@ -0,0 +1,79 @@ +#pragma once + +#include "Core/StringCrc.h" +#include "ECWorld/Entity.h" +#include "Scene/Bone.h" +#include + +namespace cd +{ + +class Skeleton; + +} + +namespace engine +{ + +class SkeletonComponent final +{ +public: + static constexpr StringCrc GetClassName() + { + constexpr StringCrc className("SkeletonComponent"); + return className; + } + +public: + SkeletonComponent() = default; + SkeletonComponent(const SkeletonComponent&) = default; + SkeletonComponent& operator=(const SkeletonComponent&) = default; + SkeletonComponent(SkeletonComponent&&) = default; + SkeletonComponent& operator=(SkeletonComponent&&) = default; + ~SkeletonComponent() = default; + + const SkeletonResource* GetSkeletonResource() const { return m_pSkeletonResource; } + void SetSkeletonAsset(const SkeletonResource* pSkeletonResource); + + void SetBoneMatricesUniform(uint16_t uniform) { m_boneMatricesUniform = uniform; } + uint16_t GetBoneMatrixsUniform() const { return m_boneMatricesUniform; } + + void SetBoneVBH(uint16_t boneVBH) { m_boneVBH = boneVBH; } + uint16_t GetBoneVBH() const { return m_boneVBH; } + + void SetBoneIBH(uint16_t boneIBH) { m_boneIBH = boneIBH; } + uint16_t GetBoneIBH() const { return m_boneIBH; } + + void SetBoneGlobalMatrix(uint32_t index, const cd::Matrix4x4& boneChangeMatrix); + const cd::Matrix4x4& GetBoneGlobalMatrix(uint32_t index) { return m_boneGlobalMatrices[index]; } + const std::vector& GetBoneGlobalMatrices() const { return m_boneGlobalMatrices; } + + void SetBoneMatrix(uint32_t index, const cd::Matrix4x4& changeMatrix) { m_boneMatrices[index] = changeMatrix * m_boneMatrices[index]; } + const cd::Matrix4x4& GetBoneMatrix(uint32_t index) { return m_boneMatrices[index]; } + + cd::Matrix4x4& GetRootMatrix() { return m_curRootMatrix; } + void SetRootMatrix(const cd::Matrix4x4& rootMatrix) { m_curRootMatrix = rootMatrix; } + + const cd::AnimationID& GetAnimation(uint32_t index) { return m_animationID[index]; } + void AddAnimationID(uint32_t animationID) { m_animationID.push_back(animationID); } + + void Reset(); + void Build(); + +private: + //input + uint32_t m_boneIndex = engine::INVALID_ENTITY; + const SkeletonResource* m_pSkeletonResource = nullptr; + //output + uint16_t m_boneVBH = UINT16_MAX; + uint16_t m_boneIBH = UINT16_MAX; + uint16_t m_boneMatricesUniform; + + cd::Matrix4x4 m_curRootMatrix = cd::Matrix4x4::Identity(); + std::vector m_boneGlobalMatrices; + std::vector m_boneMatrices; + std::vector m_animationID; + +}; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h index 67e4f7ed..5200232b 100644 --- a/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h +++ b/Engine/Source/Runtime/ECWorld/SkinMeshComponent.h @@ -31,18 +31,8 @@ class SkinMeshComponent final SkinMeshComponent& operator=(SkinMeshComponent&&) = default; ~SkinMeshComponent() = default; - uint16_t GetBonePositionBuffer() const { return m_boneVBH; } - uint16_t GetIndexBuffer() const { return m_boneIBH; } - void Reset(); void Build(); - -private: - //output - std::vector m_vertexBuffer; - std::vector m_indexBuffer; - uint16_t m_boneVBH = UINT16_MAX; - uint16_t m_boneIBH = UINT16_MAX; }; } \ No newline at end of file diff --git a/Engine/Source/Runtime/ECWorld/SkyComponent.h b/Engine/Source/Runtime/ECWorld/SkyComponent.h index c904d4c8..831f4141 100644 --- a/Engine/Source/Runtime/ECWorld/SkyComponent.h +++ b/Engine/Source/Runtime/ECWorld/SkyComponent.h @@ -79,7 +79,7 @@ class SkyComponent final private: SkyType m_type = SkyType::SkyBox; - float m_skyboxStrength = 0.5f; + float m_skyboxStrength = 0.75f; bool m_isAtmophericScatteringEnable = false; StringCrc m_ATMTransmittanceCrc; diff --git a/Engine/Source/Runtime/Log/Log.cpp b/Engine/Source/Runtime/Log/Log.cpp index f586d4ae..13506697 100644 --- a/Engine/Source/Runtime/Log/Log.cpp +++ b/Engine/Source/Runtime/Log/Log.cpp @@ -9,25 +9,10 @@ namespace engine { -std::shared_ptr Log::s_engineLogger; -std::shared_ptr Log::s_applicationLogger; +std::shared_ptr Log::s_pEngineLogger; +std::shared_ptr Log::s_pApplicationLogger; std::ostringstream Log::m_oss; -std::shared_ptr& Log::GetEngineLogger() -{ - return s_engineLogger; -} - -std::shared_ptr& Log::GetApplicationLogger() -{ - return s_applicationLogger; -} - -const std::ostringstream& Log::GetSpdOutput() -{ - return m_oss; -} - void Log::ClearBuffer() { m_oss.str(""); @@ -45,15 +30,15 @@ void Log::Init() { std::vector sinks{ consoleSink, fileSink, ossSink }; - s_engineLogger = std::make_shared("ENGINE", sinks.begin(), sinks.end()); - spdlog::register_logger(s_engineLogger); - s_engineLogger->set_level(spdlog::level::trace); - s_engineLogger->flush_on(spdlog::level::trace); + s_pEngineLogger = std::make_shared("ENGINE", sinks.begin(), sinks.end()); + spdlog::register_logger(s_pEngineLogger); + s_pEngineLogger->set_level(spdlog::level::trace); + s_pEngineLogger->flush_on(spdlog::level::trace); - s_applicationLogger = std::make_shared("EDITOR", sinks.begin(), sinks.end()); - spdlog::register_logger(s_applicationLogger); - s_applicationLogger->set_level(spdlog::level::trace); - s_applicationLogger->flush_on(spdlog::level::trace); + s_pApplicationLogger = std::make_shared("EDITOR", sinks.begin(), sinks.end()); + spdlog::register_logger(s_pApplicationLogger); + s_pApplicationLogger->set_level(spdlog::level::trace); + s_pApplicationLogger->flush_on(spdlog::level::trace); } } diff --git a/Engine/Source/Runtime/Log/Log.h b/Engine/Source/Runtime/Log/Log.h index d74557a3..2671df5d 100644 --- a/Engine/Source/Runtime/Log/Log.h +++ b/Engine/Source/Runtime/Log/Log.h @@ -5,9 +5,6 @@ #include "Math/Quaternion.hpp" #include -#include - -#include namespace engine { @@ -16,15 +13,15 @@ class Log { public: static void Init(); - static std::shared_ptr& GetEngineLogger(); - static std::shared_ptr& GetApplicationLogger(); + static std::shared_ptr GetEngineLogger() { return s_pEngineLogger; } + static std::shared_ptr GetApplicationLogger() { return s_pApplicationLogger; } - static const std::ostringstream& GetSpdOutput(); + static const std::ostringstream& GetSpdOutput() { return m_oss; } static void ClearBuffer(); private: - static std::shared_ptr s_engineLogger; - static std::shared_ptr s_applicationLogger; + static std::shared_ptr s_pEngineLogger; + static std::shared_ptr s_pApplicationLogger; // Note that m_oss will be cleared after OutputLog::AddSpdLog be called. static std::ostringstream m_oss; @@ -47,36 +44,55 @@ class Log #define CD_FATAL(...) ::engine::Log::GetApplicationLogger()->critical(__VA_ARGS__) // Runtime assert. -#define CD_ENGINE_ASSERT(x, ...) { if(!(x)) { ::engine::Log::GetEngineLogger()->error(__VA_ARGS__); } } -#define CD_ASSERT(x, ...) { if(!(x)) { ::engine::Log::GetApplicationLogger()->error(__VA_ARGS__); } } +#define CD_ENGINE_ASSERT(x, ...) { if(!(x)) { CD_FATAL(...); __debugbreak(); } } +#define CD_ASSERT(x, ...) { if(!(x)) { CD_FATAL(...); __debugbreak(); } } -inline std::ostream& operator<<(std::ostream& os, const cd::Vec2f& vec) +template<> +struct std::formatter : std::formatter { - return os << std::format("({0}, {1})", vec.x(), vec.y()); -} + auto format(const cd::Vec2f& vec, std::format_context& context) const + { + return formatter::format(std::format("vec2:({}, {})", vec.x(), vec.y()), context); + } +}; -inline std::ostream& operator<<(std::ostream& os, const cd::Vec3f& vec) +template<> +struct std::formatter : std::formatter { - return os << std::format("({0}, {1}, {2})", vec.x(), vec.y(), vec.z()); -} + auto format(const cd::Vec3f& vec, std::format_context& context) const + { + return formatter::format(std::format("vec3:({}, {}, {})", vec.x(), vec.y(), vec.z()), context); + } +}; -inline std::ostream& operator<<(std::ostream& os, const cd::Vec4f& vec) +template<> +struct std::formatter : std::formatter { - return os << std::format("({0}, {1}, {2}, {3})", vec.x(), vec.y(), vec.z(), vec.w()); -} + auto format(const cd::Vec4f& vec, std::format_context& context) const + { + return formatter::format(std::format("vec4:({}, {}, {}, {})", vec.x(), vec.y(), vec.z(), vec.w()), context); + } +}; -inline std::ostream& operator<<(std::ostream& os, const cd::Quaternion& quaternion) +template<> +struct std::formatter : std::formatter { - return os << std::format("Vector = ({0}, {1}, {2}), Scalar = {3}", quaternion.x(), quaternion.y(), quaternion.z(), quaternion.w()); -} + auto format(const cd::Quaternion& qua, std::format_context& context) const + { + return formatter::format(std::format("Vector = ({}, {}, {}), Scalar = {}", qua.x(), qua.y(), qua.z(), qua.w()), context); + } +}; #else +namespace engine +{ class Log { public: static void Init() {} }; +} #define CD_ENGINE_TRACE(...) #define CD_ENGINE_INFO(...) diff --git a/Engine/Source/Runtime/Path/Path.cpp b/Engine/Source/Runtime/Path/Path.cpp index 620efeb6..6befed26 100644 --- a/Engine/Source/Runtime/Path/Path.cpp +++ b/Engine/Source/Runtime/Path/Path.cpp @@ -53,11 +53,6 @@ std::filesystem::path Path::GetPlatformAppDataPath(const char* pRootPath) #endif } -std::string Path::Join(std::filesystem::path path) -{ - return path.generic_string(); -} - std::filesystem::path Path::GetEngineBuiltinShaderPath() { return std::filesystem::path(CDENGINE_BUILTIN_SHADER_PATH); diff --git a/Engine/Source/Runtime/Path/Path.h b/Engine/Source/Runtime/Path/Path.h index 3da9c42a..74cffb4d 100644 --- a/Engine/Source/Runtime/Path/Path.h +++ b/Engine/Source/Runtime/Path/Path.h @@ -31,9 +31,9 @@ class Path static std::string GetTerrainTextureOutputFilePath(const char* pInputFilePath, const char* extension); template - static std::string Join(std::filesystem::path path, Args... args) + static std::string Join(Args&&... args) { - return (std::filesystem::path{ cd::MoveTemp(path) } / Join(cd::MoveTemp(args)...)).generic_string(); + return (std::filesystem::path{ std::forward(args) } / ...).generic_string(); } static bool FileExists(const char* pFilePath); @@ -43,8 +43,6 @@ class Path static std::string GetExtension(const char* pFilePath); private: - static std::string Join(std::filesystem::path path); - static std::filesystem::path GetEngineBuiltinShaderPath(); static std::filesystem::path GetEngineResourcesPath(); static std::filesystem::path GetEditorResourcesPath(); diff --git a/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp b/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp index 7642b701..d1a91488 100644 --- a/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/AnimationRenderer.cpp @@ -5,14 +5,23 @@ #include "ECWorld/StaticMeshComponent.h" #include "ECWorld/TransformComponent.h" #include "Rendering/RenderContext.h" +#include "Rendering/Resources/MeshResource.h" #include "Rendering/Resources/ShaderResource.h" #include "Scene/Texture.h" #include +//#define VISUALIZE_BONE_WEIGHTS namespace engine { +namespace +{ + +constexpr const char* debugBoneIndex = "u_debugBoneIndex"; + +} + namespace details { @@ -138,7 +147,7 @@ void AnimationRenderer::Init() bgfx::setViewName(GetViewID(), "AnimationRenderer"); #ifdef VISUALIZE_BONE_WEIGHTS - m_pRenderContext->CreateUniform("u_debugBoneIndex", bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(debugBoneIndex, bgfx::UniformType::Vec4, 1); #endif } @@ -165,15 +174,15 @@ void AnimationRenderer::Render(float deltaTime) passedTime -= changeTime; } - constexpr StringCrc boneIndexUniform("u_debugBoneIndex"); - bgfx::setUniform(m_pRenderContext->GetUniform(boneIndexUniform), selectedBoneIndex, 1); + constexpr StringCrc boneIndexCrc(debugBoneIndex); + GetRenderContext()->FillUniform(boneIndexCrc, selectedBoneIndex, 1); #endif static float animationRunningTime = 0.0f; animationRunningTime += deltaTime; const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); - for (Entity entity : m_pCurrentSceneWorld->GetAnimationEntities()) + for (Entity entity : m_pCurrentSceneWorld->GetStaticMeshEntities()) { StaticMeshComponent* pMeshComponent = m_pCurrentSceneWorld->GetStaticMeshComponent(entity); if (!pMeshComponent) @@ -198,25 +207,6 @@ void AnimationRenderer::Render(float deltaTime) TransformComponent* pTransformComponent = m_pCurrentSceneWorld->GetTransformComponent(entity); bgfx::setTransform(pTransformComponent->GetWorldMatrix().begin()); - AnimationComponent* pAnimationComponent = m_pCurrentSceneWorld->GetAnimationComponent(entity); - - const cd::Animation* pAnimation = pAnimationComponent->GetAnimationData(); - float ticksPerSecond = pAnimation->GetTicksPerSecond(); - assert(ticksPerSecond > 1.0f); - float animationTime = details::CustomFModf(animationRunningTime * ticksPerSecond, pAnimation->GetDuration()); - - static std::vector boneMatrices; - boneMatrices.clear(); - for (uint16_t boneIndex = 0; boneIndex < 128; ++boneIndex) - { - boneMatrices.push_back(cd::Matrix4x4::Identity()); - } - - const cd::Bone& rootBone = pSceneDatabase->GetBone(0); - details::CalculateBoneTransform(boneMatrices, pSceneDatabase, animationTime, rootBone, - cd::Matrix4x4::Identity(), pTransformComponent->GetWorldMatrix().Inverse()); - bgfx::setUniform(bgfx::UniformHandle{pAnimationComponent->GetBoneMatrixsUniform()}, boneMatrices.data(), static_cast(boneMatrices.size())); - constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_CULL_CCW | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS; bgfx::setState(state); diff --git a/Engine/Source/Runtime/Rendering/PostProcessRenderer.cpp b/Engine/Source/Runtime/Rendering/PostProcessRenderer.cpp index ec9e26e5..1f569f38 100644 --- a/Engine/Source/Runtime/Rendering/PostProcessRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/PostProcessRenderer.cpp @@ -8,7 +8,7 @@ namespace engine void PostProcessRenderer::Init() { - AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("PostProcessProgram", "vs_fullscreen", "fs_PBR_postProcessing")); + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("PostProcessProgram", "vs_fullscreen", "fs_postProcessing")); GetRenderContext()->CreateUniform("s_lightingColor", bgfx::UniformType::Sampler); GetRenderContext()->CreateUniform("u_postProcessingParams", bgfx::UniformType::Vec4); diff --git a/Engine/Source/Runtime/Rendering/RenderContext.cpp b/Engine/Source/Runtime/Rendering/RenderContext.cpp index 10801ba1..6f10948f 100644 --- a/Engine/Source/Runtime/Rendering/RenderContext.cpp +++ b/Engine/Source/Runtime/Rendering/RenderContext.cpp @@ -187,10 +187,27 @@ ShaderResource* RenderContext::RegisterShaderProgram(const std::string& programN return pShaderResource; } -void RenderContext::OnShaderHotModified(StringCrc modifiedShaderNameCrc) +void RenderContext::OnShaderHotModified(std::string modifiedShaderName) { + // Delete all related compiled uber shader file. + // TODO : Need a file system to check is compiled file dirty. + for (const auto& entry : std::filesystem::recursive_directory_iterator(Path::GetShaderOutputDirectory())) + { + if (!entry.is_regular_file() || entry.path().extension() != Path::ShaderOutputExtension) + { + continue; + } + + std::string fileName = entry.path().filename().generic_string(); + if (fileName.find(modifiedShaderName) != std::string::npos) + { + std::filesystem::remove(entry.path()); + CD_ENGINE_TRACE("Delete obsolete file {}", fileName); + } + } + // Get all ShaderResource variants by shader name. - auto range = m_shaderResources.equal_range(modifiedShaderNameCrc); + auto range = m_shaderResources.equal_range(StringCrc{ modifiedShaderName }); for (auto it = range.first; it != range.second; ++it) { m_modifiedShaderResources.insert(it->second); diff --git a/Engine/Source/Runtime/Rendering/RenderContext.h b/Engine/Source/Runtime/Rendering/RenderContext.h index 9caf04c9..f75e9cad 100644 --- a/Engine/Source/Runtime/Rendering/RenderContext.h +++ b/Engine/Source/Runtime/Rendering/RenderContext.h @@ -76,7 +76,7 @@ class RenderContext const std::multimap& GetShaderResources() const { return m_shaderResources; } // Call back function bind to file watcher. - void OnShaderHotModified(StringCrc modifiedShaderNameCrc); + void OnShaderHotModified(std::string modifiedShaderName); void ClearModifiedShaderResources() { m_modifiedShaderResources.clear(); } std::set& GetModifiedShaderResources() { return m_modifiedShaderResources; } const std::set& GetModifiedShaderResources() const { return m_modifiedShaderResources; } diff --git a/Engine/Source/Runtime/Rendering/Resources/IResource.h b/Engine/Source/Runtime/Rendering/Resources/IResource.h index b33a6c8f..2181ba41 100644 --- a/Engine/Source/Runtime/Rendering/Resources/IResource.h +++ b/Engine/Source/Runtime/Rendering/Resources/IResource.h @@ -21,6 +21,7 @@ enum class ResourceType { Mesh, Shader, + Skeleton, Texture, }; diff --git a/Engine/Source/Runtime/Rendering/Resources/MeshResource.cpp b/Engine/Source/Runtime/Rendering/Resources/MeshResource.cpp index 98b3dbb1..6d13c3d7 100644 --- a/Engine/Source/Runtime/Rendering/Resources/MeshResource.cpp +++ b/Engine/Source/Runtime/Rendering/Resources/MeshResource.cpp @@ -74,6 +74,16 @@ void MeshResource::SetMeshAsset(const cd::Mesh* pMeshAsset) m_pMeshAsset = pMeshAsset; } +void MeshResource::SetSkinAsset(const cd::Skin* pSkinAsset) +{ + m_pSkinAsset.push_back(pSkinAsset); +} + +void MeshResource::AddBonesAsset(const cd::Bone& bone) +{ + m_pBonesAsset.push_back(&bone); +} + void MeshResource::UpdateVertexFormat(const cd::VertexFormat& vertexFormat) { // Set mesh asset at first so that MeshResource can analyze if it is suitable. @@ -175,8 +185,16 @@ void MeshResource::Reset() bool MeshResource::BuildVertexBuffer() { assert(m_pMeshAsset && m_vertexCount > 3U); + std::optional optVertexBuffer; + if (!m_pSkinAsset.empty()) + { + optVertexBuffer = cd::BuildVertexBufferForSkeletalMesh(*m_pMeshAsset, m_currentVertexFormat, *m_pSkinAsset[0], m_pBonesAsset); + } + else + { + optVertexBuffer = cd::BuildVertexBufferForStaticMesh(*m_pMeshAsset, m_currentVertexFormat); + } - std::optional optVertexBuffer = cd::BuildVertexBufferForStaticMesh(*m_pMeshAsset, m_currentVertexFormat); if (!optVertexBuffer.has_value()) { CD_ERROR("Failed to build mesh vertex buffer."); @@ -239,7 +257,6 @@ void MeshResource::SubmitVertexBuffer() { return; } - m_vertexBufferHandle = details::SubmitVertexBuffer(m_vertexBuffer, m_currentVertexFormat); } diff --git a/Engine/Source/Runtime/Rendering/Resources/MeshResource.h b/Engine/Source/Runtime/Rendering/Resources/MeshResource.h index 62f77bd3..45698d4c 100644 --- a/Engine/Source/Runtime/Rendering/Resources/MeshResource.h +++ b/Engine/Source/Runtime/Rendering/Resources/MeshResource.h @@ -8,7 +8,9 @@ namespace cd { +class Bone; class Mesh; +class Skin; } @@ -34,6 +36,12 @@ class MeshResource : public IResource const cd::Mesh* GetMeshAsset() const { return m_pMeshAsset; } void SetMeshAsset(const cd::Mesh* pMeshAsset); + + const cd::Skin* GetSkinAsset(int skinIndex) const { return m_pSkinAsset[skinIndex]; } + void SetSkinAsset(const cd::Skin* pSkinAsset); + + const std::vector GetBonesAsset() const { return m_pBonesAsset; } + void AddBonesAsset(const cd::Bone&); void UpdateVertexFormat(const cd::VertexFormat& vertexFormat); @@ -57,6 +65,8 @@ class MeshResource : public IResource private: // Asset const cd::Mesh* m_pMeshAsset = nullptr; + std::vector m_pSkinAsset; + std::vector m_pBonesAsset; uint32_t m_vertexCount = 0U; uint32_t m_polygonCount = 0U; uint32_t m_polygonGroupCount = 0U; diff --git a/Engine/Source/Runtime/Rendering/Resources/ResourceContext.cpp b/Engine/Source/Runtime/Rendering/Resources/ResourceContext.cpp index a8d43121..cd226707 100644 --- a/Engine/Source/Runtime/Rendering/Resources/ResourceContext.cpp +++ b/Engine/Source/Runtime/Rendering/Resources/ResourceContext.cpp @@ -3,6 +3,7 @@ #include "Base/NameOf.h" #include "MeshResource.h" #include "ShaderResource.h" +#include "SkeletonResource.h" #include "TextureResource.h" namespace engine @@ -37,6 +38,11 @@ ShaderResource* ResourceContext::AddShaderResource(StringCrc nameCrc) return static_cast(AddResourceImpl(nameCrc)); } +SkeletonResource* ResourceContext::AddSkeletonResource(StringCrc nameCrc) +{ + return static_cast(AddResourceImpl(nameCrc)); +} + TextureResource* ResourceContext::AddTextureResource(StringCrc nameCrc) { return static_cast(AddResourceImpl(nameCrc)); @@ -79,6 +85,10 @@ IResource* ResourceContext::AddResourceImpl(StringCrc nameCrc) { m_resources[resourceCrc] = std::make_unique(); } + else if constexpr (ResourceType::Skeleton == RT) + { + m_resources[resourceCrc] = std::make_unique(); + } auto* pResource = m_resources[resourceCrc].get(); pResource->SetName(nameCrc); diff --git a/Engine/Source/Runtime/Rendering/Resources/ResourceContext.h b/Engine/Source/Runtime/Rendering/Resources/ResourceContext.h index cc32afa7..9c320b4b 100644 --- a/Engine/Source/Runtime/Rendering/Resources/ResourceContext.h +++ b/Engine/Source/Runtime/Rendering/Resources/ResourceContext.h @@ -12,6 +12,7 @@ enum class ResourceType; class IResource; class MeshResource; class ShaderResource; +class SkeletonResource; class TextureResource; class ResourceContext @@ -30,6 +31,7 @@ class ResourceContext MeshResource* AddMeshResource(StringCrc nameCrc); ShaderResource* AddShaderResource(StringCrc nameCrc); + SkeletonResource* AddSkeletonResource(StringCrc nameCrc); TextureResource* AddTextureResource(StringCrc nameCrc); MeshResource* GetMeshResource(StringCrc nameCrc); ShaderResource* GetShaderResource(StringCrc nameCrc); diff --git a/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.cpp b/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.cpp new file mode 100644 index 00000000..7e511754 --- /dev/null +++ b/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.cpp @@ -0,0 +1,212 @@ +#include "SkeletonResource.h" + +#include "Log/Log.h" +#include "Rendering/Utility/VertexLayoutUtility.h" +#include "Utilities/MeshUtils.hpp" + +namespace details +{ + +void TraverseBone(const cd::Bone& bone, const cd::SceneDatabase* pSceneDatabase, std::byte* currentDataPtr, + std::byte* currentIndexPtr, uint32_t& vertexOffset, uint32_t& indexOffset) +{ + constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); + constexpr uint32_t indexDataSize = sizeof(uint16_t); + for (auto& child : bone.GetChildIDs()) + { + const cd::Bone& currBone = pSceneDatabase->GetBone(child.Data()); + cd::Vec3f translate = currBone.GetOffset().Inverse().GetTranslation(); + + uint16_t parentID = currBone.GetParentID().Data(); + uint16_t currBoneID = currBone.GetID().Data(); + uint16_t selectedBoneIndex[4] = { currBoneID, currBoneID, currBoneID, currBoneID }; + std::vector vertexBoneIndexes; + vertexBoneIndexes.resize(4, 0U); + vertexBoneIndexes[0] = currBoneID; + std::memcpy(¤tDataPtr[vertexOffset], translate.begin(), posDataSize); + vertexOffset += posDataSize; + std::memcpy(¤tDataPtr[vertexOffset], selectedBoneIndex, static_cast(4 * sizeof(uint16_t))); + vertexOffset += static_cast(4 * sizeof(uint16_t)); + std::memcpy(¤tIndexPtr[indexOffset], &parentID, indexDataSize); + indexOffset += indexDataSize; + std::memcpy(¤tIndexPtr[indexOffset], &currBoneID, indexDataSize); + indexOffset += indexDataSize; + + TraverseBone(currBone, pSceneDatabase, currentDataPtr, currentIndexPtr, vertexOffset, indexOffset); + } +} + +} + +namespace engine +{ + +SkeletonResource::SkeletonResource() = default; + +SkeletonResource::~SkeletonResource() +{ + // Collect garbage intermediatly. + //SetStatus(ResourceStatus::Garbage); + //Update(); +} + + +void SkeletonResource::Update() +{ + switch (GetStatus()) + { + case ResourceStatus::Loading: + { + if (m_pSceneDatabase) + { + m_boneCount = m_pSceneDatabase->GetBoneCount(); + SetStatus(ResourceStatus::Loaded); + } + break; + } + case ResourceStatus::Loaded: + { + if (m_boneCount > 0U) + { + SetStatus(ResourceStatus::Building); + } + SetStatus(ResourceStatus::Building); + break; + } + case ResourceStatus::Building: + { + BuildSkeletonBuffer(); + SetStatus(ResourceStatus::Built); + break; + } + case ResourceStatus::Built: + { + SubmitVertexBuffer(); + SubmitIndexBuffer(); + m_recycleCount = 0U; + SetStatus(ResourceStatus::Ready); + break; + } + case ResourceStatus::Ready: + { + // Release CPU data later to save memory. + constexpr uint32_t recycleDelayFrames = 30U; + if (m_recycleCount++ >= recycleDelayFrames) + { + FreeSkeletonData(); + SetStatus(ResourceStatus::Optimized); + } + break; + } + case ResourceStatus::Garbage: + { + DestroyVertexBufferHandle(); + DestroyIndexBufferHandle(); + // CPU data will destroy after deconstructor. + SetStatus(ResourceStatus::Destroyed); + break; + } + default: + break; + } +} + +void SkeletonResource::Reset() +{ + DestroyVertexBufferHandle(); + DestroyIndexBufferHandle(); + ClearSkeletonData(); + SetStatus(ResourceStatus::Loading); +} + +void SkeletonResource::BuildSkeletonBuffer() +{ + constexpr uint32_t indexTypeSize = static_cast(sizeof(uint16_t)); + constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); + m_currentVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::Position, cd::AttributeValueType::Float, 3); + m_currentVertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::BoneIndex, cd::AttributeValueType::Int16, 4U); + m_indexBuffer.resize((m_boneCount - 1) * 2 * indexTypeSize); + m_vertexBuffer.resize(m_boneCount * m_currentVertexFormat.GetStride()); + + uint32_t vbDataSize = 0U; + uint32_t ibDataSize = 0U; + + auto vbDataPtr = m_vertexBuffer.data(); + const cd::Point& position = m_pSceneDatabase->GetBone(0).GetTransform().GetTranslation(); + std::memcpy(&vbDataPtr[vbDataSize], position.begin(), posDataSize); + vbDataSize += posDataSize; + //std::vector vertexBoneIndexes; + uint16_t selectedBoneIndex[4] = { 0U, 0U, 0U, 0U }; + //vertexBoneIndexes.resize(4, 0U); + //vertexBoneIndexes[0] = 0U; + //uint16_t first = 0; + std::memcpy(&vbDataPtr[vbDataSize], selectedBoneIndex, static_cast(4 * sizeof(uint16_t))); + vbDataSize += static_cast(4 * sizeof(uint16_t)); + + details::TraverseBone(m_pSceneDatabase->GetBone(0), m_pSceneDatabase, m_vertexBuffer.data(), m_indexBuffer.data(), vbDataSize, ibDataSize); +} + +void SkeletonResource::SubmitVertexBuffer() +{ + if (m_vertexBufferHandle != UINT16_MAX) + { + return; + } + + bgfx::VertexLayout vertexLayout; + engine::VertexLayoutUtility::CreateVertexLayout(vertexLayout, m_currentVertexFormat.GetVertexAttributeLayouts()); + const bgfx::Memory* pVertexBufferRef = bgfx::makeRef(m_vertexBuffer.data(), static_cast(m_vertexBuffer.size())); + bgfx::VertexBufferHandle vertexBufferHandle = bgfx::createVertexBuffer(pVertexBufferRef, vertexLayout); + assert(bgfx::isValid(vertexBufferHandle)); + m_vertexBufferHandle = vertexBufferHandle.idx; +} + +void SkeletonResource::SubmitIndexBuffer() +{ + if (m_indexBufferHandle != UINT16_MAX) + { + return; + } + + const auto& indexBuffer = m_indexBuffer; + assert(!m_indexBuffer.empty()); + const bgfx::Memory* pIndexBufferRef = bgfx::makeRef(indexBuffer.data(), static_cast(indexBuffer.size())); + + bgfx::IndexBufferHandle indexBufferHandle = bgfx::createIndexBuffer(pIndexBufferRef); + assert(bgfx::isValid(indexBufferHandle)); + m_indexBufferHandle = indexBufferHandle.idx; +} + +void SkeletonResource::ClearSkeletonData() +{ + m_vertexBuffer.clear(); + m_indexBuffer.clear(); +} + +void SkeletonResource::FreeSkeletonData() +{ + //ClearSkeletonData(); + //VertexBuffer().swap(m_vertexBuffer); + //IndexBuffer().swap(m_indexBuffer); +} + +void SkeletonResource::DestroyVertexBufferHandle() +{ + if (m_vertexBufferHandle != UINT16_MAX) + { + bgfx::destroy(bgfx::VertexBufferHandle{ m_vertexBufferHandle }); + m_vertexBufferHandle = UINT16_MAX; + } +} + +void SkeletonResource::DestroyIndexBufferHandle() +{ + if (m_indexBufferHandle != UINT16_MAX) + { + bgfx::destroy(bgfx::IndexBufferHandle{ m_indexBufferHandle }); + m_indexBufferHandle = UINT16_MAX; + } + +} + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.h b/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.h new file mode 100644 index 00000000..08792546 --- /dev/null +++ b/Engine/Source/Runtime/Rendering/Resources/SkeletonResource.h @@ -0,0 +1,68 @@ +#pragma once + +#include "IResource.h" +#include "Scene/SceneDatabase.h" + +#include + +namespace cd +{ + +class Bone; + +} + +namespace engine +{ + +class SkeletonResource : public IResource +{ +public: + using VertexBuffer = std::vector; + using IndexBuffer = std::vector; + +public: + SkeletonResource(); + SkeletonResource(const SkeletonResource&) = default; + SkeletonResource& operator=(const SkeletonResource&) = default; + SkeletonResource(SkeletonResource&&) = default; + SkeletonResource& operator=(SkeletonResource&&) = default; + virtual ~SkeletonResource(); + + virtual void Update() override; + virtual void Reset() override; + + void SetSceneDataBase(const cd::SceneDatabase* pSceneDataBase) {m_pSceneDatabase = pSceneDataBase; m_boneCount = m_pSceneDatabase->GetBoneCount();} + + uint32_t GetBoneCount() const { return m_boneCount; } + uint16_t GetVertexBufferHandle() const { return m_vertexBufferHandle; } + uint16_t GetIndexBufferHandle() const { return m_indexBufferHandle; } + +private: + void BuildSkeletonBuffer(); + void SubmitVertexBuffer(); + void SubmitIndexBuffer(); + void ClearSkeletonData(); + void FreeSkeletonData(); + void DestroyVertexBufferHandle(); + void DestroyIndexBufferHandle(); + +private: + // Asset + const cd::SceneDatabase* m_pSceneDatabase; + uint32_t m_boneCount = 0U; + + // Runtime + cd::VertexFormat m_currentVertexFormat; + + // CPU + VertexBuffer m_vertexBuffer; + IndexBuffer m_indexBuffer; + uint32_t m_recycleCount = 0; + + // GPU + uint16_t m_vertexBufferHandle = UINT16_MAX; + uint16_t m_indexBufferHandle = UINT16_MAX; +}; + +} \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/ShadowMapRenderer.cpp b/Engine/Source/Runtime/Rendering/ShadowMapRenderer.cpp index 705aee72..198e87f4 100644 --- a/Engine/Source/Runtime/Rendering/ShadowMapRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/ShadowMapRenderer.cpp @@ -97,7 +97,7 @@ void ShadowMapRenderer::Render(float deltaTime) // Non-shadow-casting lights(include area lights) are excluded if (!lightComponent->IsCastShadow()) { - continue; + //continue; } // Render shadow map diff --git a/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp b/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp index 39a87fee..c638c607 100644 --- a/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/SkeletonRenderer.cpp @@ -2,6 +2,7 @@ #include "Core/StringCrc.h" #include "ECWorld/SceneWorld.h" +#include "ECWorld/SkinMeshComponent.h" #include "ECWorld/TransformComponent.h" #include "Rendering/RenderContext.h" #include "Rendering/Utility/VertexLayoutUtility.h" @@ -13,9 +14,136 @@ namespace engine namespace details { -constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); +float CustomFMod(float dividend, float divisor) +{ + if (divisor == 0.0f) + { + return 0.0f; + } + + int quotient = static_cast(dividend / divisor); + float result = dividend - static_cast(quotient) * divisor; + + if (result == 0.0f && dividend != 0.0f) + { + result = 0.0f; + } + if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) + { + result = -result; + } + return result; +} + +void CalculateTransform(std::vector& boneMatrices, const cd::SceneDatabase* pSceneDatabase, + float animationTime, const cd::Bone& bone, const char* clipName, SkeletonComponent* pSkeletonConponent, cd::Matrix4x4& curGlobalDeltaMatrix, float deltaTime, bool isPlaying) +{ + auto CalculateInterpolatedTranslation = [&animationTime](const cd::Track* pTrack) -> cd::Vec3f + { + if (1U == pTrack->GetTranslationKeyCount()) + { + const auto& firstKey = pTrack->GetTranslationKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetTranslationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetTranslationKeys()[keyIndex + 1]; + if (animationTime <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetTranslationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + } + + } + const auto& Key = pTrack->GetTranslationKeys()[pTrack->GetTranslationKeyCount() - 1]; + return Key.GetValue(); + }; + + auto CalculateInterpolatedRotation = [&animationTime](const cd::Track* pTrack) -> cd::Quaternion + { + if (1U == pTrack->GetRotationKeyCount()) + { + const auto& firstKey = pTrack->GetRotationKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetRotationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetRotationKeys()[keyIndex + 1]; + if (animationTime <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetRotationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Quaternion::SLerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate).Normalize(); + } + } + const auto& Key = pTrack->GetRotationKeys()[pTrack->GetTranslationKeyCount() - 1]; + return Key.GetValue(); + }; + + auto CalculateInterpolatedScale = [&animationTime](const cd::Track* pTrack) -> cd::Vec3f + { + if (1U == pTrack->GetScaleKeyCount()) + { + const auto& firstKey = pTrack->GetScaleKeys()[0]; + return firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetScaleKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetScaleKeys()[keyIndex + 1]; + if (animationTime <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetScaleKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (animationTime - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + return cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + } + } + + return cd::Vec3f::One(); + }; + static cd::Matrix4x4 transform = cd::Matrix4x4::Identity(); + + cd::Matrix4x4 curBoneGlobalMatrix = cd::Matrix4x4::Identity(); + if (const cd::Track* pTrack = pSceneDatabase->GetTrackByName((std::string(clipName) + bone.GetName()).c_str())) + { + if (0 == bone.GetID().Data()) + { + + transform = cd::Transform(CalculateInterpolatedTranslation(pTrack), + CalculateInterpolatedRotation(pTrack), + CalculateInterpolatedScale(pTrack)).GetMatrix(); + curBoneGlobalMatrix = transform; + pSkeletonConponent->SetBoneGlobalMatrix(bone.GetID().Data(), transform); + + } + else + { + curBoneGlobalMatrix = pSkeletonConponent->GetBoneGlobalMatrix(bone.GetParentID().Data()) * cd::Transform(CalculateInterpolatedTranslation(pTrack), + CalculateInterpolatedRotation(pTrack), + CalculateInterpolatedScale(pTrack)).GetMatrix(); + pSkeletonConponent->SetBoneGlobalMatrix(bone.GetID().Data(), curBoneGlobalMatrix); + } + } -constexpr size_t indexTypeSize = sizeof(uint16_t); + boneMatrices[bone.GetID().Data()] = curBoneGlobalMatrix * bone.GetOffset(); + for (cd::BoneID boneID : bone.GetChildIDs()) + { + const cd::Bone& childBone = pSceneDatabase->GetBone(boneID.Data()); + CalculateTransform(boneMatrices, pSceneDatabase, animationTime, childBone, clipName, pSkeletonConponent, curGlobalDeltaMatrix, deltaTime, isPlaying); + } +} cd::Vec3f CalculateBoneTranslate(const cd::Bone& bone, cd::Vec3f& translate, const cd::SceneDatabase* pSceneDatabase) { @@ -28,28 +156,147 @@ cd::Vec3f CalculateBoneTranslate(const cd::Bone& bone, cd::Vec3f& translate, con return translate; } -void TraverseBone(const cd::Bone& bone, const cd::SceneDatabase* pSceneDatabase, std::byte* currentDataPtr, - std::byte* currentIndexPtr, uint32_t& vertexOffset, uint32_t& indexOffset) +cd::Matrix4x4 CalculateInterpolationTransform(const cd::Track* pTrack, const float time) +{ + cd::Vec3f localTranslate = cd::Vec3f::Zero(); + cd::Quaternion localRotation = cd::Quaternion::Identity(); + cd::Vec3f localScale = cd::Vec3f::One(); + if (1U == pTrack->GetTranslationKeyCount()) + { + const auto& firstKey = pTrack->GetTranslationKeys()[0]; + localTranslate = firstKey.GetValue(); + } + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetTranslationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetTranslationKeys()[keyIndex + 1]; + if (time <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetTranslationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (time - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + localTranslate = cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + break; + } + const auto& translateKey = pTrack->GetTranslationKeys()[pTrack->GetTranslationKeyCount() - 1]; + localTranslate = translateKey.GetValue(); + } + + + if (1U == pTrack->GetRotationKeyCount()) + { + const auto& firstKey = pTrack->GetRotationKeys()[0]; + localRotation = firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetRotationKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetRotationKeys()[keyIndex + 1]; + if (time <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetRotationKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (time - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + localRotation = cd::Quaternion::SLerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate).Normalize(); + break; + } + const auto& rotationKey = pTrack->GetRotationKeys()[pTrack->GetTranslationKeyCount() - 1]; + localRotation = rotationKey.GetValue(); + } + + + if (1U == pTrack->GetScaleKeyCount()) + { + const auto& firstKey = pTrack->GetScaleKeys()[0]; + localScale = firstKey.GetValue(); + } + + for (uint32_t keyIndex = 0U; keyIndex < pTrack->GetScaleKeyCount() - 1; ++keyIndex) + { + const auto& nextKey = pTrack->GetScaleKeys()[keyIndex + 1]; + if (time <= nextKey.GetTime()) + { + const auto& currentKey = pTrack->GetScaleKeys()[keyIndex]; + float keyFrameDeltaTime = nextKey.GetTime() - currentKey.GetTime(); + float keyFrameRate = (time - currentKey.GetTime()) / keyFrameDeltaTime; + assert(keyFrameRate >= 0.0f && keyFrameRate <= 1.0f); + + localScale = cd::Vec3f::Lerp(currentKey.GetValue(), nextKey.GetValue(), keyFrameRate); + break; + } + localScale = cd::Vec3f::One(); + + } + return cd::Transform(localTranslate, localRotation, localScale).GetMatrix(); +} + +void BlendTwoPos(std::vector& boneMatrices, const cd::SceneDatabase* pSceneDatabase, + float blendTimeProgress, const cd::Bone& bone, const char* clipAName, const char* clipBName, SkeletonComponent* pSkeletonComponent, cd::Matrix4x4& curGlobalDeltaMatrix, const cd::Matrix4x4 rootBoonTransform, const float factor) { - constexpr uint32_t posDataSize = cd::Point::Size * sizeof(cd::Point::ValueType); - for (auto& child : bone.GetChildIDs()) + cd::Matrix4x4 localTransformA = cd::Matrix4x4::Identity(); + cd::Matrix4x4 localTransformB = cd::Matrix4x4::Identity(); + cd::Matrix4x4 curBoneGlobalMatrix = cd::Matrix4x4::Identity(); + float clipATime = pSceneDatabase->GetAnimation(0).GetDuration() * blendTimeProgress; + float clipBTime = pSceneDatabase->GetAnimation(1).GetDuration() * blendTimeProgress; + static float progress = 0.0f; + static cd::Matrix4x4 total = cd::Matrix4x4::Identity(); + static cd::Matrix4x4 lastMatrix = cd::Matrix4x4::Identity(); + const cd::Track* pTrackA = pSceneDatabase->GetTrackByName((std::string(clipAName) + bone.GetName()).c_str()); + if (const cd::Track* pTrackA = pSceneDatabase->GetTrackByName((std::string(clipAName) + bone.GetName()).c_str())) { - const cd::Bone& currBone = pSceneDatabase->GetBone(child.Data()); - const cd::Bone& parent = pSceneDatabase->GetBone(currBone.GetParentID().Data()); - cd::Vec3f translate = currBone.GetOffset().GetTranslation(); + localTransformA = CalculateInterpolationTransform(pTrackA, clipATime); + } + if (const cd::Track* pTrackB = pSceneDatabase->GetTrackByName((std::string(clipBName) + bone.GetName()).c_str())) + { + localTransformB = CalculateInterpolationTransform(pTrackB, clipBTime); + } - //const cd::Vec3f position = details::CalculateBoneTranslate(currBone, translate, pSceneDatabase); + cd::Vec3f translationBlend = cd::Vec3f::Lerp(localTransformA.GetTranslation(), localTransformB.GetTranslation(), factor); + cd::Quaternion rotationBlend = cd::Quaternion::SLerp(cd::Quaternion::FromMatrix(localTransformA.GetRotation()), cd::Quaternion::FromMatrix(localTransformB.GetRotation()), factor); + cd::Vec3f scaleBlend = cd::Vec3f::Lerp(localTransformA.GetScale(), localTransformB.GetScale(), factor); + cd::Matrix4x4 matrixBlend = cd::Transform(translationBlend, rotationBlend, scaleBlend).GetMatrix(); + cd::Matrix4x4 deltaGlobalTransform = cd::Matrix4x4::Identity(); + if (0 == bone.GetID().Data()) + { + //if (blendTimeProgress >= progress) + { + + curBoneGlobalMatrix = total * matrixBlend; - uint16_t parentID = currBone.GetParentID().Data(); - uint16_t currBoneID = currBone.GetID().Data(); - std::memcpy(¤tDataPtr[vertexOffset], translate.begin(), posDataSize); - vertexOffset += posDataSize; - std::memcpy(¤tIndexPtr[indexOffset], &parentID, indexTypeSize); - indexOffset += static_cast(indexTypeSize); - std::memcpy(¤tIndexPtr[indexOffset], &currBoneID, indexTypeSize); - indexOffset += static_cast(indexTypeSize); + pSkeletonComponent->SetRootMatrix(curBoneGlobalMatrix); + pSkeletonComponent->SetBoneGlobalMatrix(bone.GetID().Data(), curBoneGlobalMatrix); + lastMatrix = matrixBlend; - TraverseBone(currBone, pSceneDatabase, currentDataPtr, currentIndexPtr, vertexOffset, indexOffset); + } + /*else + { + const auto& srcTranslation = pTrackA->GetTranslationKeys()[0]; + const auto& srcRotation = pTrackA->GetRotationKeys()[0]; + const auto& srcSale = pTrackA->GetScaleKeys()[0]; + cd::Matrix4x4 srcTransform = cd::Transform(srcTranslation.GetValue(), srcRotation.GetValue(), srcSale.GetValue()).GetMatrix(); + cd::Matrix4x4 deltaTransform = pSkinmeshConponent->GetRootMatrix() * srcTransform.Inverse(); + total = deltaTransform; + deltaTransform = matrixBlend * srcTransform.Inverse(); + total = deltaTransform * total; + curBoneGlobalMatrix = total * pSkinmeshConponent->GetRootMatrix(); + pSkinmeshConponent->SetRootMatrix(curBoneGlobalMatrix); + pSkinmeshConponent->SetBoneGlobalMatrix(bone.GetID().Data(), curBoneGlobalMatrix); + }*/ + progress = blendTimeProgress; + } + else + { + curBoneGlobalMatrix = pSkeletonComponent->GetBoneGlobalMatrix(bone.GetParentID().Data()) * matrixBlend; + pSkeletonComponent->SetBoneGlobalMatrix(bone.GetID().Data(), curBoneGlobalMatrix); + } + boneMatrices[bone.GetID().Data()] = curBoneGlobalMatrix * bone.GetOffset(); + for (cd::BoneID boneID : bone.GetChildIDs()) + { + const cd::Bone& childBone = pSceneDatabase->GetBone(boneID.Data()); + BlendTwoPos(boneMatrices, pSceneDatabase, blendTimeProgress, childBone, clipAName, clipBName, pSkeletonComponent, curGlobalDeltaMatrix, rootBoonTransform, factor); } } @@ -57,8 +304,7 @@ void TraverseBone(const cd::Bone& bone, const cd::SceneDatabase* pSceneDatabase, void SkeletonRenderer::Init() { - AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("SkeletonProgram", "vs_AABB", "fs_AABB")); - + AddDependentShaderResource(GetRenderContext()->RegisterShaderProgram("SkeletonProgram", "vs_skeleton", "fs_AABB")); bgfx::setViewName(GetViewID(), "SkeletonRenderer"); } @@ -70,45 +316,18 @@ void SkeletonRenderer::UpdateView(const float* pViewMatrix, const float* pProjec void SkeletonRenderer::Build() { - const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); - const uint32_t vertexCount = pSceneDatabase->GetBoneCount(); - if (0 == vertexCount) - { - return; - } - - const cd::Bone& firstBone = pSceneDatabase->GetBone(0); - if (0 != firstBone.GetID().Data()) - { - CD_ENGINE_WARN("First BoneID is not 0"); - return; - } - - bgfx::setTransform(cd::Matrix4x4::Identity().begin()); - cd::VertexFormat vertexFormat; - vertexFormat.AddVertexAttributeLayout(cd::VertexAttributeType::Position, cd::AttributeValueType::Float, 3); +} - constexpr size_t indexTypeSize = sizeof(uint16_t); - m_indexBuffer.resize((vertexCount - 1) * 2 * indexTypeSize); - m_vertexBuffer.resize(vertexCount * vertexFormat.GetStride()); - uint32_t currentVertexOffset = 0U; - uint32_t currentIndexOffset = 0U; - std::byte* pCurrentVertexBuffer = m_vertexBuffer.data(); - const cd::Point& position = firstBone.GetTransform().GetTranslation(); - std::memcpy(&pCurrentVertexBuffer[currentVertexOffset], position.begin(), details::posDataSize); - currentVertexOffset += details::posDataSize; +void SkeletonRenderer::Render(float deltaTime) +{ - details::TraverseBone(firstBone, pSceneDatabase, m_vertexBuffer.data(), m_indexBuffer.data(), currentVertexOffset, currentIndexOffset); - bgfx::VertexLayout vertexLayout; - VertexLayoutUtility::CreateVertexLayout(vertexLayout, vertexFormat.GetVertexAttributeLayouts()); - m_boneVBH = bgfx::createVertexBuffer(bgfx::makeRef(m_vertexBuffer.data(), static_cast(m_vertexBuffer.size())), vertexLayout).idx; - m_boneIBH = bgfx::createIndexBuffer(bgfx::makeRef(m_indexBuffer.data(), static_cast(m_indexBuffer.size())), 0U).idx; + const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); -} + static float animationRunningTime = 0.0f; + static float playTime = 0.0f;//for replay one animation -void SkeletonRenderer::Render(float delataTime) -{ + //const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); for (const auto pResource : m_dependentShaderResources) { if (ResourceStatus::Ready != pResource->GetStatus() && @@ -125,24 +344,103 @@ void SkeletonRenderer::Render(float delataTime) { continue; } - if (!hasBuilt) + const cd::SceneDatabase* pSceneDatabase = m_pCurrentSceneWorld->GetSceneDatabase(); + SkeletonComponent* pSkeletonComponent = m_pCurrentSceneWorld->GetSkeletonComponent(entity); + const char* clipName; + float ticksPerSecond = 0.0f; + float duration = 0.0f; + + const SkeletonResource* pSkeletonResource = pSkeletonComponent->GetSkeletonResource(); + if (ResourceStatus::Ready != pSkeletonResource->GetStatus() && + ResourceStatus::Optimized != pSkeletonResource->GetStatus()) { - Build(); - hasBuilt = true; + continue; } - bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ m_boneVBH }); - bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ m_boneIBH }); + if (pAnimationComponent && pAnimationComponent->IsPlaying()) + { + animationRunningTime += deltaTime * pAnimationComponent->GetPlayBackSpeed(); + } + static cd::Matrix4x4 deltaRootTransform = cd::Matrix4x4::Identity(); + static std::vector globalDeltaBoneMatrix; + static std::vector boneMatrixA; + static std::vector boneMatrixB; + globalDeltaBoneMatrix.clear(); + boneMatrixA.clear(); + boneMatrixB.clear(); + globalDeltaBoneMatrix.resize(128, cd::Matrix4x4::Identity()); + boneMatrixA.resize(128, cd::Matrix4x4::Identity()); + boneMatrixB.resize(128, cd::Matrix4x4::Identity()); + if (engine::AnimationClip::Idle == pAnimationComponent->GetAnimationClip()) + { + cd::Matrix4x4 rootBone = cd::Matrix4x4::Identity(); + + clipName = pSceneDatabase->GetAnimation(0).GetName(); + duration = pSceneDatabase->GetAnimation(0).GetDuration(); + ticksPerSecond = pSceneDatabase->GetAnimation(0).GetTicksPerSecond(); + + float animationTime = details::CustomFMod(animationRunningTime, duration); + pAnimationComponent->SetAnimationPlayTime(animationTime); + + cd::Matrix4x4 curGlobalDeltaMatrix = cd::Matrix4x4::Identity(); + details::CalculateTransform(globalDeltaBoneMatrix, pSceneDatabase, animationTime, pSceneDatabase->GetBone(0), clipName, pSkeletonComponent, curGlobalDeltaMatrix, deltaTime * pAnimationComponent->GetPlayBackSpeed(), pAnimationComponent->IsPlaying()); + + } + else if (engine::AnimationClip::Walking == pAnimationComponent->GetAnimationClip()) + { + const cd::Animation& pAnimation = pSceneDatabase->GetAnimation(1); + clipName = pSceneDatabase->GetAnimation(1).GetName(); + duration = pSceneDatabase->GetAnimation(1).GetDuration(); + ticksPerSecond = pSceneDatabase->GetAnimation(1).GetTicksPerSecond(); + + float animationTime = details::CustomFMod(animationRunningTime, duration); + pAnimationComponent->SetAnimationPlayTime(animationTime); - constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS | + cd::Matrix4x4 curGlobalDeltaMatrix = cd::Matrix4x4::Identity(); + details::CalculateTransform(globalDeltaBoneMatrix, pSceneDatabase, animationTime, pSceneDatabase->GetBone(0), clipName, pSkeletonComponent, curGlobalDeltaMatrix, deltaTime * pAnimationComponent->GetPlayBackSpeed(), pAnimationComponent->IsPlaying()); + } + else if (engine::AnimationClip::Running == pAnimationComponent->GetAnimationClip()) + { + const cd::Animation& pAnimation = pSceneDatabase->GetAnimation(2); + clipName = pSceneDatabase->GetAnimation(2).GetName(); + duration = pSceneDatabase->GetAnimation(2).GetDuration(); + ticksPerSecond = pSceneDatabase->GetAnimation(1).GetTicksPerSecond(); + float animationTime = details::CustomFMod(animationRunningTime, duration); + + //details::CalculateTransform(globalDeltaBoneMatrix, pSceneDatabase, animationTime, pSceneDatabase->GetBone(0), clipName, pSkinMeshComponent, curBoneGlobalMatrix, cd::Matrix4x4::Identity()); + } + else if (engine::AnimationClip::Blend == pAnimationComponent->GetAnimationClip()) + { + float factor = pAnimationComponent->GetBlendFactor(); + float clipATime = pSceneDatabase->GetAnimation(0).GetDuration(); + float clipBTime = pSceneDatabase->GetAnimation(1).GetDuration(); + + float clipARunningTime = details::CustomFMod(animationRunningTime, clipATime); + float clipBRunningTime = details::CustomFMod(animationRunningTime, clipBTime); + const float blendSpeed = clipATime + (clipBTime - clipATime) * factor; + float clipASpeed = clipATime / blendSpeed; + pAnimationComponent->SetPlayBackSpeed(clipASpeed); + float clipBSpeed = clipBTime / blendSpeed; + float clipAProgress = clipARunningTime / clipATime; + + cd::Matrix4x4 curGlobalDeltaMatrix = cd::Matrix4x4::Identity(); + details::BlendTwoPos(globalDeltaBoneMatrix, pSceneDatabase, clipAProgress, pSceneDatabase->GetBone(0), pSceneDatabase->GetAnimation(0).GetName(), pSceneDatabase->GetAnimation(1).GetName(), pSkeletonComponent, curGlobalDeltaMatrix, deltaRootTransform, factor); + } + + bgfx::setTransform(cd::Matrix4x4::Identity().begin()); + + bgfx::setUniform(bgfx::UniformHandle{ pAnimationComponent->GetBoneMatrixsUniform() }, globalDeltaBoneMatrix.data(), static_cast(globalDeltaBoneMatrix.size())); + bgfx::setVertexBuffer(0, bgfx::VertexBufferHandle{ pSkeletonComponent->GetSkeletonResource()->GetVertexBufferHandle()}); + bgfx::setIndexBuffer(bgfx::IndexBufferHandle{ pSkeletonComponent->GetSkeletonResource()->GetIndexBufferHandle() }); + + constexpr uint64_t state = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA) | BGFX_STATE_PT_LINES; bgfx::setState(state); constexpr StringCrc programHandleIndex{ "SkeletonProgram" }; - GetRenderContext()->Submit(GetViewID(), programHandleIndex); + + //GetRenderContext()->Submit(GetViewID(), programHandleIndex); } - } - } \ No newline at end of file diff --git a/Engine/Source/Runtime/Rendering/SkeletonRenderer.h b/Engine/Source/Runtime/Rendering/SkeletonRenderer.h index 81632f97..4c576c7e 100644 --- a/Engine/Source/Runtime/Rendering/SkeletonRenderer.h +++ b/Engine/Source/Runtime/Rendering/SkeletonRenderer.h @@ -25,7 +25,6 @@ class SkeletonRenderer final : public Renderer std::vector m_indexBuffer; uint16_t m_boneVBH = UINT16_MAX; uint16_t m_boneIBH = UINT16_MAX; - bool hasBuilt = false; }; diff --git a/Engine/Source/Runtime/Rendering/TerrainRenderer.cpp b/Engine/Source/Runtime/Rendering/TerrainRenderer.cpp index 0b05e160..a2b2080d 100644 --- a/Engine/Source/Runtime/Rendering/TerrainRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/TerrainRenderer.cpp @@ -43,7 +43,7 @@ constexpr const char* cameraPos = "u_cameraPos"; constexpr const char* cameraNearFarPlane = "u_cameraNearFarPlane"; constexpr const char* albedoColor = "u_albedoColor"; -constexpr const char* metallicRoughnessFactor = "u_metallicRoughnessFactor"; +constexpr const char* metallicRoughnessRefectanceFactor = "u_metallicRoughnessRefectanceFactor"; constexpr const char* albedoUVOffsetAndScale = "u_albedoUVOffsetAndScale"; constexpr const char* alphaCutOff = "u_alphaCutOff"; constexpr const char* emissiveColor = "u_emissiveColor"; @@ -80,7 +80,7 @@ void TerrainRenderer::Init() GetRenderContext()->CreateUniform(albedoColor, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(emissiveColor, bgfx::UniformType::Vec4, 1); - GetRenderContext()->CreateUniform(metallicRoughnessFactor, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(metallicRoughnessRefectanceFactor, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(albedoUVOffsetAndScale, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(alphaCutOff, bgfx::UniformType::Vec4, 1); @@ -200,12 +200,13 @@ void TerrainRenderer::Render(float deltaTime) constexpr StringCrc albedoColorCrc(albedoColor); GetRenderContext()->FillUniform(albedoColorCrc, pMaterialComponent->GetFactor(cd::MaterialPropertyGroup::BaseColor), 1); - cd::Vec4f metallicRoughnessFactorData( + cd::Vec4f u_metallicRoughnessRefectanceFactorData( *(pMaterialComponent->GetFactor(cd::MaterialPropertyGroup::Metallic)), *(pMaterialComponent->GetFactor(cd::MaterialPropertyGroup::Roughness)), - 1.0f, 1.0f); - constexpr StringCrc mrFactorCrc(metallicRoughnessFactor); - GetRenderContext()->FillUniform(mrFactorCrc, metallicRoughnessFactorData.begin(), 1); + pMaterialComponent->GetReflectance(), + 1.0f); + constexpr StringCrc mrrFactorCrc(metallicRoughnessRefectanceFactor); + GetRenderContext()->FillUniform(mrrFactorCrc, u_metallicRoughnessRefectanceFactorData.begin(), 1); constexpr StringCrc emissiveColorCrc(emissiveColor); GetRenderContext()->FillUniform(emissiveColorCrc, pMaterialComponent->GetFactor(cd::MaterialPropertyGroup::Emissive), 1); diff --git a/Engine/Source/Runtime/Rendering/WorldRenderer.cpp b/Engine/Source/Runtime/Rendering/WorldRenderer.cpp index 404bb2e1..93ba41ab 100644 --- a/Engine/Source/Runtime/Rendering/WorldRenderer.cpp +++ b/Engine/Source/Runtime/Rendering/WorldRenderer.cpp @@ -24,37 +24,38 @@ namespace engine namespace { -constexpr const char* lutSampler = "s_texLUT"; -constexpr const char* cubeIrradianceSampler = "s_texCubeIrr"; -constexpr const char* cubeRadianceSampler = "s_texCubeRad"; +constexpr const char* lutSampler = "s_texLUT"; +constexpr const char* cubeIrradianceSampler = "s_texCubeIrr"; +constexpr const char* cubeRadianceSampler = "s_texCubeRad"; + +constexpr const char* lutTexture = "Textures/lut/ibl_brdf_lut.dds"; + +constexpr const char* cameraPos = "u_cameraPos"; +constexpr const char* iblStrength = "u_iblStrength"; +constexpr const char* albedoColor = "u_albedoColor"; +constexpr const char* emissiveColorAndFactor = "u_emissiveColorAndFactor"; +constexpr const char* metallicRoughnessRefectanceFactor = "u_metallicRoughnessRefectanceFactor"; -constexpr const char* lutTexture = "Textures/lut/ibl_brdf_lut.dds"; - -constexpr const char* cameraPos = "u_cameraPos"; -constexpr const char* iblStrength = "u_iblStrength"; -constexpr const char* albedoColor = "u_albedoColor"; -constexpr const char* emissiveColorAndFactor = "u_emissiveColorAndFactor"; -constexpr const char* metallicRoughnessFactor = "u_metallicRoughnessFactor"; - -constexpr const char* albedoUVOffsetAndScale = "u_albedoUVOffsetAndScale"; -constexpr const char* alphaCutOff = "u_alphaCutOff"; - -constexpr const char* lightCountAndStride = "u_lightCountAndStride"; -constexpr const char* lightParams = "u_lightParams"; - -constexpr const char* LightDir = "u_LightDir"; -constexpr const char* HeightOffsetAndshadowLength = "u_HeightOffsetAndshadowLength"; - -constexpr const char* lightViewProjs = "u_lightViewProjs"; -constexpr const char* cubeShadowMapSamplers[3] = { "s_texCubeShadowMap_1", "s_texCubeShadowMap_2" , "s_texCubeShadowMap_3" }; - -constexpr const char* cameraNearFarPlane = "u_cameraNearFarPlane"; -constexpr const char* cameraLookAt = "u_cameraLookAt"; -constexpr const char* clipFrustumDepth = "u_clipFrustumDepth"; - -constexpr const char* directionShadowMapTexture = "DirectionShadowMapTexture"; -constexpr const char* pointShadowMapTexture = "PointShadowMapTexture"; -constexpr const char* spotShadowMapTexture = "SpotShadowMapTexture"; +constexpr const char* albedoUVOffsetAndScale = "u_albedoUVOffsetAndScale"; +constexpr const char* alphaCutOff = "u_alphaCutOff"; + +constexpr const char* lightCountAndStride = "u_lightCountAndStride"; +constexpr const char* lightParams = "u_lightParams"; + +constexpr const char* LightDir = "u_LightDir"; +constexpr const char* HeightOffsetAndshadowLength = "u_HeightOffsetAndshadowLength"; + +constexpr const char* lightViewProjs = "u_lightViewProjs"; +constexpr const char* cubeShadowMapSamplers[3] = { "s_texCubeShadowMap_1", "s_texCubeShadowMap_2" , "s_texCubeShadowMap_3" }; + +constexpr const char* cameraNearFarPlane = "u_cameraNearFarPlane"; +constexpr const char* cameraLookAt = "u_cameraLookAt"; +constexpr const char* clipFrustumDepth = "u_clipFrustumDepth"; + +constexpr const char* IsCastShadow = "u_isCastShadow"; +constexpr const char* directionShadowMapTexture = "DirectionShadowMapTexture"; +constexpr const char* pointShadowMapTexture = "PointShadowMapTexture"; +constexpr const char* spotShadowMapTexture = "SpotShadowMapTexture"; constexpr uint64_t samplerFlags = BGFX_SAMPLER_U_CLAMP | BGFX_SAMPLER_V_CLAMP | BGFX_SAMPLER_W_CLAMP; constexpr uint64_t defaultRenderingState = BGFX_STATE_WRITE_MASK | BGFX_STATE_MSAA | BGFX_STATE_DEPTH_TEST_LESS; @@ -78,7 +79,7 @@ void WorldRenderer::Init() GetRenderContext()->CreateUniform(iblStrength, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(albedoColor, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(emissiveColorAndFactor, bgfx::UniformType::Vec4, 1); - GetRenderContext()->CreateUniform(metallicRoughnessFactor, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(metallicRoughnessRefectanceFactor, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(albedoUVOffsetAndScale, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(alphaCutOff, bgfx::UniformType::Vec4, 1); @@ -95,6 +96,7 @@ void WorldRenderer::Init() GetRenderContext()->CreateUniform(cameraNearFarPlane, bgfx::UniformType::Vec4, 1); GetRenderContext()->CreateUniform(clipFrustumDepth, bgfx::UniformType::Vec4, 1); + GetRenderContext()->CreateUniform(IsCastShadow, bgfx::UniformType::Vec4, 1); bgfx::setViewName(GetViewID(), "WorldRenderer"); } @@ -186,7 +188,8 @@ void WorldRenderer::Render(float deltaTime) // TODO : Temporary solution for CelluloidRenderer, remove it. if (pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetPBRMaterialType() && - pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetCelluloidMaterialType()) + pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetCelluloidMaterialType()&& + pMaterialComponent->GetMaterialType() != m_pCurrentSceneWorld->GetAnimationMaterialType()) { continue; } @@ -215,7 +218,7 @@ void WorldRenderer::Render(float deltaTime) // SkinMesh if(m_pCurrentSceneWorld->GetAnimationComponent(entity)) { - continue; + //continue; } // Transform @@ -310,12 +313,13 @@ void WorldRenderer::Render(float deltaTime) constexpr StringCrc albedoColorCrc(albedoColor); GetRenderContext()->FillUniform(albedoColorCrc, pMaterialComponent->GetFactor(cd::MaterialPropertyGroup::BaseColor), 1); - cd::Vec4f metallicRoughnessFactorData( + cd::Vec4f metallicRoughnessRefectanceFactorData( *(pMaterialComponent->GetFactor(cd::MaterialPropertyGroup::Metallic)), *(pMaterialComponent->GetFactor(cd::MaterialPropertyGroup::Roughness)), - 1.0f, 1.0f); - constexpr StringCrc mrFactorCrc(metallicRoughnessFactor); - GetRenderContext()->FillUniform(mrFactorCrc, metallicRoughnessFactorData.begin(), 1); + pMaterialComponent->GetReflectance(), + 1.0f); + constexpr StringCrc mrrFactorCrc(metallicRoughnessRefectanceFactor); + GetRenderContext()->FillUniform(mrrFactorCrc, metallicRoughnessRefectanceFactorData.begin(), 1); constexpr StringCrc emissiveColorCrc(emissiveColorAndFactor); GetRenderContext()->FillUniform(emissiveColorCrc, pMaterialComponent->GetFactor(cd::MaterialPropertyGroup::Emissive), 1); @@ -365,6 +369,19 @@ void WorldRenderer::Render(float deltaTime) { auto lightComponent = m_pCurrentSceneWorld->GetLightComponent(lightEntities[lightIndex]); cd::LightType lightType = lightComponent->GetType(); + + constexpr StringCrc CastShadowIntensityCrc(IsCastShadow); + if (lightComponent->IsCastShadow()) + { + cd::Vec4f vec4 = cd::Vec4f::One(); + GetRenderContext()->FillUniform(CastShadowIntensityCrc, &vec4); + } + else + { + cd::Vec4f vec4 = cd::Vec4f::Zero(); + GetRenderContext()->FillUniform(CastShadowIntensityCrc, &vec4); + } + //GetRenderContext()->FillUniform(CastShadowIntensityCrc, &lightComponent->IsCastShadow()); if (cd::LightType::Directional == lightType) { bgfx::TextureHandle blitDstShadowMapTexture = static_cast(lightComponent->GetShadowMapTexture());