/*
- * 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.
#include <dali-toolkit-test-suite-utils.h>
#include <dali-toolkit/dali-toolkit.h>
#include <dali/devel-api/common/map-wrapper.h>
+#include <dali/public-api/common/vector-wrapper.h>
#include <stdlib.h>
#include <iostream>
#include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
#include <dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h>
+#include <dali-scene3d/public-api/loader/node-definition.h>
+
#include <dali/devel-api/actors/camera-actor-devel.h>
using namespace Dali;
* 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
gResourceReadyCalled = true;
}
+void ApplyAllMaterialPropertyRecursively(Scene3D::ModelNode modelNode, const std::vector<KeyValuePair>& 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
END_TEST;
}
+
+int UtcDaliModelMaterialUniformChange(void)
+{
+ ToolkitTestApplication application;
+
+ static std::vector<UniformData> 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<Vector4>("uColorFactor", expectBaseColorFactor), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckUniformValue<float>("uBaseColorTextureTransformAvailable", expectTransformValid), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckUniformValue<float>(Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), expectMaxLOD), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckUniformValue<float>(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<Vector4>("uColorFactor", expectBaseColorFactor), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckUniformValue<float>("uBaseColorTextureTransformAvailable", expectTransformValid), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckUniformValue<float>(Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), expectMaxLOD), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckUniformValue<float>(Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), expectIblFactor), true, TEST_LOCATION);
+
+ END_TEST;
+}
\ No newline at end of file
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,
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<typename T>
+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()
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);
}