From c799d2969c05fa5bffbb92dd1069ac03b6902c38 Mon Sep 17 00:00:00 2001 From: Eunki Hong Date: Sat, 6 Jan 2024 01:01:50 +0900 Subject: [PATCH] Fix bug that IBLFactor / Roughness not works well when we change material There was some bug when we change Material info, uMaxLOD and uIblIntensity does not applied what primitive has. This is because Material's SetUniform API overwrite the value of those uniform. This patch make we ensure the order of uniform register, so let we use correct LOD and IBL intensity. Change-Id: Ic14b7f9b6c0e443ac17188a8968ac71a7c6328d6 Signed-off-by: Eunki Hong --- .../src/dali-scene3d/utc-Dali-Model.cpp | 110 ++++++++++++++++++++- .../internal/model-components/material-impl.cpp | 59 +++++++---- .../model-components/model-primitive-impl.cpp | 2 +- 3 files changed, 148 insertions(+), 23 deletions(-) diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp index 0962643..e8a372c 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,8 @@ #include #include +#include + #include using namespace Dali; @@ -72,7 +75,7 @@ const char* TEST_DLI_EXERCISE_FILE_NAME = TEST_RESOURCE_DIR "/exercis * These textures are based off version of Wave engine sample * Take from https://github.com/WaveEngine/Samples * - * Copyright (c) 2023 Wave Coorporation + * Copyright (c) 2024 Wave Coorporation * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -121,6 +124,39 @@ void OnResourceReady(Control control) gResourceReadyCalled = true; } +void ApplyAllMaterialPropertyRecursively(Scene3D::ModelNode modelNode, const std::vector& materialPropertyValues) +{ + if(!modelNode) + { + return; + } + + for(uint32_t primitiveIndex = 0u; primitiveIndex < modelNode.GetModelPrimitiveCount(); ++primitiveIndex) + { + Scene3D::ModelPrimitive primitive = modelNode.GetModelPrimitive(primitiveIndex); + if(primitive) + { + Scene3D::Material material = primitive.GetMaterial(); + if(material) + { + for(const auto& keyValuePair : materialPropertyValues) + { + if(keyValuePair.first.type == Property::Key::Type::INDEX) + { + material.SetProperty(keyValuePair.first.indexKey, keyValuePair.second); + } + } + } + } + } + + for(uint32_t childIndex = 0u; childIndex < modelNode.GetChildCount(); ++childIndex) + { + Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(modelNode.GetChildAt(childIndex)); + ApplyAllMaterialPropertyRecursively(childNode, materialPropertyValues); + } +} + } // namespace // Negative test case for a method @@ -1817,3 +1853,73 @@ int UtcDaliModelBlendShapeMotionDataByName(void) END_TEST; } + +int UtcDaliModelMaterialUniformChange(void) +{ + ToolkitTestApplication application; + + static std::vector customUniforms = + { + UniformData("uColorFactor", Property::Type::VECTOR4), + UniformData("uBaseColorTextureTransformAvailable", Property::Type::FLOAT), + UniformData(Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), Property::Type::FLOAT), + UniformData(Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), Property::Type::FLOAT), + }; + + TestGraphicsController& graphics = application.GetGraphicsController(); + graphics.AddCustomUniforms(customUniforms); + + auto& gl = application.GetGlAbstraction(); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + + gResourceReadyCalled = false; + model.ResourceReadySignal().Connect(&OnResourceReady); + + float expectIblFactor = 0.5f; + model.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE, expectIblFactor); + DALI_TEST_EQUALS(model.GetImageBasedLightScaleFactor(), expectIblFactor, TEST_LOCATION); + + DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION); + application.GetScene().Add(model); + + application.SendNotification(); + application.Render(); + + // Wait 3 task. (Load 1 model + Load 2 IBL) + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(3), true, TEST_LOCATION); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION); + DALI_TEST_EQUALS(model.GetImageBasedLightScaleFactor(), expectIblFactor, TEST_LOCATION); + + // Check uniform values before change material value + Vector4 expectBaseColorFactor = Vector4(1.000f, 0.766f, 0.336f, 1.0f); // Defined at AnimatedCube.gltf + float expectTransformValid = 0.0f; ///< Note : This value will be true when gltf have BaseColorTexture, and use KHR_texture_transform extension. + float expectMaxLOD = 5.0f; ///< Note : The number of LOD what TEST_SPECULAR_TEXTURE file has is 5. + + tet_printf("Check uniform value result\n"); + DALI_TEST_EQUALS(gl.CheckUniformValue("uColorFactor", expectBaseColorFactor), true, TEST_LOCATION); + DALI_TEST_EQUALS(gl.CheckUniformValue("uBaseColorTextureTransformAvailable", expectTransformValid), true, TEST_LOCATION); + DALI_TEST_EQUALS(gl.CheckUniformValue(Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), expectMaxLOD), true, TEST_LOCATION); + DALI_TEST_EQUALS(gl.CheckUniformValue(Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), expectIblFactor), true, TEST_LOCATION); + + // Change all materials in Model. + expectBaseColorFactor = Color::BLUE; + + Scene3D::ModelNode rootModelNode = model.GetModelRoot(); + DALI_TEST_CHECK(rootModelNode); + ApplyAllMaterialPropertyRecursively(rootModelNode, {{Dali::Scene3D::Material::Property::BASE_COLOR_FACTOR, expectBaseColorFactor}}); + + application.SendNotification(); + application.Render(); + + tet_printf("Check whether uniform values are not changed instead what we change now\n"); + DALI_TEST_EQUALS(gl.CheckUniformValue("uColorFactor", expectBaseColorFactor), true, TEST_LOCATION); + DALI_TEST_EQUALS(gl.CheckUniformValue("uBaseColorTextureTransformAvailable", expectTransformValid), true, TEST_LOCATION); + DALI_TEST_EQUALS(gl.CheckUniformValue(Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), expectMaxLOD), true, TEST_LOCATION); + DALI_TEST_EQUALS(gl.CheckUniformValue(Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), expectIblFactor), true, TEST_LOCATION); + + END_TEST; +} \ No newline at end of file diff --git a/dali-scene3d/internal/model-components/material-impl.cpp b/dali-scene3d/internal/model-components/material-impl.cpp index 3b35ffd..baebb4a 100644 --- a/dali-scene3d/internal/model-components/material-impl.cpp +++ b/dali-scene3d/internal/model-components/material-impl.cpp @@ -61,6 +61,8 @@ static constexpr uint32_t ALPHA_CUTOFF_FLAG = Scene3D::Lo static constexpr std::string_view THREE_TEX_KEYWORD = "THREE_TEX"; static constexpr std::string_view GLTF_CHANNELS_KEYWORD = "GLTF_CHANNELS"; +static constexpr Vector3 IBL_BASIS(1.0f, -1.0f, 1.0f); + enum TextureIndex { BASE_COLOR, @@ -73,6 +75,23 @@ enum TextureIndex TEXTURE_TYPE_NUMBER, }; +/** + * @brief Helper API to register uniform property only if don't register before. + * + * @tparam T Type of uniform value. + * @param[in] renderer The renderer what we want to check / register property. + * @param[in] uniformName The name of uniform. + * @param[in] defaultUniformValue The default value if renderer don't register given uniform before. + */ +template +void RegisterUniformIfNotDefinedBefore(Renderer renderer, const std::string_view& uniformName, const T& defaultUniformValue) +{ + if(renderer.GetPropertyIndex(uniformName.data()) == Property::INVALID_INDEX) + { + renderer.RegisterProperty(uniformName, defaultUniformValue); + } +} + } // unnamed namespace MaterialPtr Material::New() @@ -694,32 +713,32 @@ void Material::SetRendererUniform(Dali::Renderer renderer) renderer.RegisterProperty("uSpecularFactor", mTextureInformations[TextureIndex::SPECULAR].mFactor.x); renderer.RegisterProperty("uSpecularColorFactor", Vector3(mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor)); - // No requirement to use texture transform for runtime generated models. - renderer.RegisterProperty("uBaseColorTextureTransformAvailable", 0.0f); - renderer.RegisterProperty("uNormalTextureTransformAvailable", 0.0f); - renderer.RegisterProperty("uNormalRoughnessTextureTransformAvailable", 0.0f); - renderer.RegisterProperty("uMetalRoughnessTextureTransformAvailable", 0.0f); - renderer.RegisterProperty("uOcclusionTextureTransformAvailable", 0.0f); - renderer.RegisterProperty("uEmissiveTextureTransformAvailable", 0.0f); - - renderer.RegisterProperty("uBaseColorTextureTransform", Matrix3::IDENTITY); - renderer.RegisterProperty("uNormalRoughnessTextureTransform", Matrix3::IDENTITY); - renderer.RegisterProperty("uNormalTextureTransform", Matrix3::IDENTITY); - renderer.RegisterProperty("uMetalRoughnessTextureTransform", Matrix3::IDENTITY); - renderer.RegisterProperty("uOcclusionTextureTransform", Matrix3::IDENTITY); - renderer.RegisterProperty("uEmissiveTextureTransform", Matrix3::IDENTITY); - float opaque = mIsOpaque ? 1.0f : 0.0f; float mask = mIsMask ? 1.0f : 0.0f; renderer.RegisterProperty("uOpaque", opaque); renderer.RegisterProperty("uMask", mask); renderer.RegisterProperty("uAlphaThreshold", mAlphaCutoff); - renderer.RegisterProperty("uCubeMatrix", Matrix::IDENTITY); - - renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), 6.f); - renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), 1.0f); - renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblYDirectionUniformName().data(), Vector3(1.0f, -1.0, 1.0)); + // Setup default uniform values what we might need. + RegisterUniformIfNotDefinedBefore(renderer, "uBaseColorTextureTransformAvailable", 0.0f); + RegisterUniformIfNotDefinedBefore(renderer, "uNormalTextureTransformAvailable", 0.0f); + RegisterUniformIfNotDefinedBefore(renderer, "uNormalRoughnessTextureTransformAvailable", 0.0f); + RegisterUniformIfNotDefinedBefore(renderer, "uMetalRoughnessTextureTransformAvailable", 0.0f); + RegisterUniformIfNotDefinedBefore(renderer, "uOcclusionTextureTransformAvailable", 0.0f); + RegisterUniformIfNotDefinedBefore(renderer, "uEmissiveTextureTransformAvailable", 0.0f); + + RegisterUniformIfNotDefinedBefore(renderer, "uBaseColorTextureTransform", Matrix3::IDENTITY); + RegisterUniformIfNotDefinedBefore(renderer, "uNormalRoughnessTextureTransform", Matrix3::IDENTITY); + RegisterUniformIfNotDefinedBefore(renderer, "uNormalTextureTransform", Matrix3::IDENTITY); + RegisterUniformIfNotDefinedBefore(renderer, "uMetalRoughnessTextureTransform", Matrix3::IDENTITY); + RegisterUniformIfNotDefinedBefore(renderer, "uOcclusionTextureTransform", Matrix3::IDENTITY); + RegisterUniformIfNotDefinedBefore(renderer, "uEmissiveTextureTransform", Matrix3::IDENTITY); + + RegisterUniformIfNotDefinedBefore(renderer, "uCubeMatrix", Matrix::IDENTITY); + + RegisterUniformIfNotDefinedBefore(renderer, Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName(), 1.0f); + RegisterUniformIfNotDefinedBefore(renderer, Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName(), 1.0f); + RegisterUniformIfNotDefinedBefore(renderer, Scene3D::Loader::NodeDefinition::GetIblYDirectionUniformName(), IBL_BASIS); Scene3D::Loader::RendererState::Apply(mRendererState, renderer); } diff --git a/dali-scene3d/internal/model-components/model-primitive-impl.cpp b/dali-scene3d/internal/model-components/model-primitive-impl.cpp index 12bbf6e..1adf514 100644 --- a/dali-scene3d/internal/model-components/model-primitive-impl.cpp +++ b/dali-scene3d/internal/model-components/model-primitive-impl.cpp @@ -549,9 +549,9 @@ void ModelPrimitive::UpdateRendererUniform() { if(mMaterial) { + GetImplementation(mMaterial).SetRendererUniform(mRenderer); mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightScaleFactorName().data(), mIblScaleFactor); mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightMaxLodUniformName().data(), static_cast(mSpecularMipmapLevels)); - GetImplementation(mMaterial).SetRendererUniform(mRenderer); } } -- 2.7.4