[dali_2.2.35] Merge branch 'devel/master' 63/295863/1
authorRichard Huang <r.huang@samsung.com>
Fri, 14 Jul 2023 11:36:36 +0000 (12:36 +0100)
committerRichard Huang <r.huang@samsung.com>
Fri, 14 Jul 2023 11:36:36 +0000 (12:36 +0100)
Change-Id: If963b00d724dbfdf9f173d13515fff3682a3eebe

45 files changed:
automated-tests/src/dali-scene3d-internal/utc-Dali-GlbLoaderImpl.cpp
automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp
automated-tests/src/dali-scene3d-internal/utc-Dali-MaterialImpl.cpp
automated-tests/src/dali-scene3d/CMakeLists.txt
automated-tests/src/dali-scene3d/utc-Dali-Light.cpp
automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp [deleted file]
automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionOption.cpp [deleted file]
automated-tests/src/dali-scene3d/utc-Dali-ShaderManager.cpp [new file with mode: 0644]
automated-tests/src/dali-scene3d/utc-Dali-ShaderOption.cpp [new file with mode: 0644]
automated-tests/src/dali-toolkit-internal/dali-toolkit-test-utils/toolkit-text-utils.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-actor-utils.h
dali-scene3d/dali-scene3d.h
dali-scene3d/internal/common/light-observer.h
dali-scene3d/internal/controls/model/model-impl.cpp
dali-scene3d/internal/controls/model/model-impl.h
dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp
dali-scene3d/internal/controls/scene-view/scene-view-impl.h
dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag
dali-scene3d/internal/loader/gltf2-util.cpp
dali-scene3d/internal/loader/gltf2-util.h
dali-scene3d/internal/model-components/material-impl.cpp
dali-scene3d/internal/model-components/material-impl.h
dali-scene3d/internal/model-components/model-node-impl.cpp
dali-scene3d/internal/model-components/model-node-impl.h
dali-scene3d/internal/model-components/model-primitive-impl.cpp
dali-scene3d/internal/model-components/model-primitive-impl.h
dali-scene3d/public-api/file.list
dali-scene3d/public-api/loader/node-definition.cpp
dali-scene3d/public-api/loader/node-definition.h
dali-scene3d/public-api/loader/scene-definition.cpp
dali-scene3d/public-api/loader/shader-definition-factory.cpp [deleted file]
dali-scene3d/public-api/loader/shader-definition-factory.h [deleted file]
dali-scene3d/public-api/loader/shader-definition.h
dali-scene3d/public-api/loader/shader-manager.cpp [new file with mode: 0644]
dali-scene3d/public-api/loader/shader-manager.h [new file with mode: 0644]
dali-scene3d/public-api/loader/shader-option.cpp [moved from dali-scene3d/public-api/loader/shader-definition-option.cpp with 73% similarity]
dali-scene3d/public-api/loader/shader-option.h [moved from dali-scene3d/public-api/loader/shader-definition-option.h with 80% similarity]
dali-scene3d/public-api/model-motion/motion-data.h
dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h
dali-scene3d/public-api/model-motion/motion-index/motion-transform-index.h
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h
dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index f3d8a93..14f5864 100644 (file)
@@ -22,7 +22,7 @@
 #include <dali-scene3d/public-api/loader/load-result.h>
 #include <dali-scene3d/public-api/loader/resource-bundle.h>
 #include <dali-scene3d/public-api/loader/scene-definition.h>
-#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
+#include <dali-scene3d/public-api/loader/shader-manager.h>
 #include <dali-test-suite-utils.h>
 #include <string_view>
 
@@ -123,10 +123,6 @@ int UtcDaliGlbLoaderFailedToLoad(void)
 int UtcDaliGlbLoaderFailedToParse(void)
 {
   Context ctx;
-
-  ShaderDefinitionFactory sdf;
-  sdf.SetResources(ctx.resources);
-
   DALI_TEST_EQUAL(ctx.loader.LoadModel(TEST_RESOURCE_DIR "/invalid.glb", ctx.loadResult), false);
 
   DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
@@ -135,7 +131,6 @@ int UtcDaliGlbLoaderFailedToParse(void)
   DALI_TEST_EQUAL(0, ctx.resources.mEnvironmentMaps.size());
   DALI_TEST_EQUAL(0, ctx.resources.mMaterials.size());
   DALI_TEST_EQUAL(0, ctx.resources.mMeshes.size());
-  DALI_TEST_EQUAL(0, ctx.resources.mShaders.size());
   DALI_TEST_EQUAL(0, ctx.resources.mSkeletons.size());
 
   DALI_TEST_EQUAL(0, ctx.cameras.size());
@@ -149,9 +144,6 @@ int UtcDaliGlbLoaderFailedToParse(void)
 int UtcDaliGlbLoaderSuccess1(void)
 {
   Context                 ctx;
-  ShaderDefinitionFactory sdf;
-  sdf.SetResources(ctx.resources);
-
   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/BoxAnimated.glb", ctx.loadResult);
 
   DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size());
index 1f274d0..adf95eb 100644 (file)
@@ -22,7 +22,7 @@
 #include <dali-scene3d/public-api/loader/load-result.h>
 #include <dali-scene3d/public-api/loader/resource-bundle.h>
 #include <dali-scene3d/public-api/loader/scene-definition.h>
-#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
+#include <dali-scene3d/public-api/loader/shader-manager.h>
 #include <dali-test-suite-utils.h>
 #include <string_view>
 
@@ -125,9 +125,6 @@ int UtcDaliGltfLoaderFailedToParse(void)
 {
   Context ctx;
 
-  ShaderDefinitionFactory sdf;
-  sdf.SetResources(ctx.resources);
-
   DALI_TEST_EQUAL(ctx.loader.LoadModel(TEST_RESOURCE_DIR "/invalid.gltf", ctx.loadResult), false);
 
   DALI_TEST_EQUAL(0, ctx.scene.GetRoots().size());
@@ -136,7 +133,6 @@ int UtcDaliGltfLoaderFailedToParse(void)
   DALI_TEST_EQUAL(0, ctx.resources.mEnvironmentMaps.size());
   DALI_TEST_EQUAL(0, ctx.resources.mMaterials.size());
   DALI_TEST_EQUAL(0, ctx.resources.mMeshes.size());
-  DALI_TEST_EQUAL(0, ctx.resources.mShaders.size());
   DALI_TEST_EQUAL(0, ctx.resources.mSkeletons.size());
 
   DALI_TEST_EQUAL(0, ctx.cameras.size());
@@ -193,7 +189,7 @@ int UtcDaliGltfLoaderSuccess1(void)
       nullptr,
       MaterialDefinition::ALBEDO | MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
         MaterialDefinition::NORMAL | MaterialDefinition::SPECULAR | MaterialDefinition::SPECULAR_COLOR |
-        (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
+        MaterialDefinition::GLTF_CHANNELS | (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
       0,
       Color::WHITE,
       1.f,
@@ -306,7 +302,7 @@ int UtcDaliGltfLoaderSuccess1(void)
           },
         },
         {
-          MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
+          MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS,
           {
             "AnimatedCube_MetallicRoughness.png",
             SamplerFlags::Encode(FilterMode::NEAREST_MIPMAP_LINEAR, FilterMode::NEAREST, WrapMode::CLAMP_TO_EDGE, WrapMode::MIRRORED_REPEAT),
@@ -448,7 +444,6 @@ int UtcDaliGltfLoaderSuccess1(void)
     ++iMesh;
   }
 
-  DALI_TEST_EQUAL(2u, ctx.resources.mShaders.size());
   DALI_TEST_EQUAL(0u, ctx.resources.mSkeletons.size());
 
   DALI_TEST_EQUAL(6u, ctx.cameras.size());
@@ -462,8 +457,6 @@ int UtcDaliGltfLoaderSuccess1(void)
 int UtcDaliGltfLoaderSuccess2(void)
 {
   Context                 ctx;
-  ShaderDefinitionFactory sdf;
-  sdf.SetResources(ctx.resources);
 
   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/AnimatedCubeStride.gltf", ctx.loadResult);
 
@@ -577,9 +570,6 @@ int UtcDaliGltfLoaderSuccessShort(void)
 int UtcDaliGltfLoaderMRendererTest(void)
 {
   Context ctx;
-
-  ShaderDefinitionFactory sdf;
-  sdf.SetResources(ctx.resources);
   auto& resources = ctx.resources;
 
   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/MRendererTest.gltf", ctx.loadResult);
@@ -592,6 +582,7 @@ int UtcDaliGltfLoaderMRendererTest(void)
 
   DALI_TEST_EQUAL(scene.GetNodeCount(), 1u);
 
+  Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
   ViewProjection viewProjection;
   Transforms     xforms{
     MatrixStack{},
@@ -599,6 +590,7 @@ int UtcDaliGltfLoaderMRendererTest(void)
   NodeDefinition::CreateParams nodeParams{
     resources,
     xforms,
+    shaderManager,
   };
 
   Customization::Choices choices;
@@ -649,6 +641,7 @@ int UtcDaliGltfLoaderAnimationLoadingTest(void)
   auto& roots = scene.GetRoots();
   DALI_TEST_EQUAL(roots.size(), 1u);
 
+  Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
   ViewProjection viewProjection;
   Transforms     xforms{
     MatrixStack{},
@@ -656,6 +649,7 @@ int UtcDaliGltfLoaderAnimationLoadingTest(void)
   NodeDefinition::CreateParams nodeParams{
     resources,
     xforms,
+    shaderManager,
   };
 
   Customization::Choices choices;
@@ -690,8 +684,6 @@ int UtcDaliGltfLoaderImageFromBufferView(void)
 {
   Context ctx;
 
-  ShaderDefinitionFactory sdf;
-  sdf.SetResources(ctx.resources);
   auto& resources = ctx.resources;
 
   ctx.loader.LoadModel(TEST_RESOURCE_DIR "/EnvironmentTest_b.gltf", ctx.loadResult);
@@ -700,6 +692,7 @@ int UtcDaliGltfLoaderImageFromBufferView(void)
   auto& roots = scene.GetRoots();
   DALI_TEST_EQUAL(roots.size(), 1u);
 
+  Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
   ViewProjection viewProjection;
   Transforms     xforms{
     MatrixStack{},
@@ -707,6 +700,7 @@ int UtcDaliGltfLoaderImageFromBufferView(void)
   NodeDefinition::CreateParams nodeParams{
     resources,
     xforms,
+    shaderManager,
   };
 
   Customization::Choices choices;
@@ -749,6 +743,7 @@ int UtcDaliGltfLoaderUint8Indices(void)
   auto& roots = scene.GetRoots();
   DALI_TEST_EQUAL(roots.size(), 1u);
 
+  Scene3D::Loader::ShaderManagerPtr shaderManager = new Scene3D::Loader::ShaderManager();
   ViewProjection viewProjection;
   Transforms     xforms{
     MatrixStack{},
@@ -756,6 +751,7 @@ int UtcDaliGltfLoaderUint8Indices(void)
   NodeDefinition::CreateParams nodeParams{
     resources,
     xforms,
+    shaderManager,
   };
 
   Customization::Choices choices;
index 34a82b2..e3bc2d2 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-scene3d/internal/model-components/material-impl.h>
-#include <dali-scene3d/public-api/loader/shader-definition-option.h>
+#include <dali-scene3d/public-api/loader/shader-option.h>
 
 using namespace Dali;
 using namespace Dali::Toolkit;
@@ -96,20 +96,14 @@ int UtcDaliMaterialImplSetGetTextureInformation(void)
   DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
   GetImplementation(material).UpdateMaterialData();
 
-  std::vector<std::string> defines;
-  defines.push_back(Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Scene3D::Loader::ShaderDefinitionOption::Type::THREE_TEXTURE).data());
-  defines.push_back(Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Scene3D::Loader::ShaderDefinitionOption::Type::GLTF_CHANNELS).data());
-  defines.push_back(Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Scene3D::Loader::ShaderDefinitionOption::Type::BASE_COLOR_TEXTURE).data());
-  defines.push_back(Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Scene3D::Loader::ShaderDefinitionOption::Type::METALLIC_ROUGHNESS_TEXTURE).data());
-  defines.push_back(Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Scene3D::Loader::ShaderDefinitionOption::Type::NORMAL_TEXTURE).data());
+  Scene3D::Loader::ShaderOption option;
+  option.AddOption(Scene3D::Loader::ShaderOption::Type::THREE_TEXTURE);
+  option.AddOption(Scene3D::Loader::ShaderOption::Type::GLTF_CHANNELS);
+  option.AddOption(Scene3D::Loader::ShaderOption::Type::BASE_COLOR_TEXTURE);
+  option.AddOption(Scene3D::Loader::ShaderOption::Type::METALLIC_ROUGHNESS_TEXTURE);
+  option.AddOption(Scene3D::Loader::ShaderOption::Type::NORMAL_TEXTURE);
 
-  std::string fragmentShader = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
-  for(const auto& define : defines)
-  {
-    Scene3D::Loader::ShaderDefinition::ApplyDefine(fragmentShader, define);
-  }
-
-  DALI_TEST_EQUALS(fragmentShader, GetImplementation(material).GetFragmentShader(), TEST_LOCATION);
+  DALI_TEST_EQUALS(option.GetOptionHash(), GetImplementation(material).GetShaderOption().GetOptionHash(), TEST_LOCATION);
 
   Scene3D ::Internal ::Material ::TextureInformation occlusion;
   Dali ::Texture                                     occlusiontexture = Dali ::Texture ::New(TextureType ::TEXTURE_2D, Pixel ::RGBA8888, 100, 100);
@@ -176,18 +170,12 @@ int UtcDaliMaterialImplSetGetTextureInformation(void)
   DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
   GetImplementation(material).UpdateMaterialData();
 
-  defines.push_back(Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Scene3D::Loader::ShaderDefinitionOption::Type::OCCLUSION).data());
-  defines.push_back(Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Scene3D::Loader::ShaderDefinitionOption::Type::EMISSIVE).data());
-  defines.push_back(Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Scene3D::Loader::ShaderDefinitionOption::Type::SPECULAR).data());
-  defines.push_back(Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Scene3D::Loader::ShaderDefinitionOption::Type::SPECULAR_COLOR).data());
-
-  fragmentShader = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
-  for(const auto& define : defines)
-  {
-    Scene3D::Loader::ShaderDefinition::ApplyDefine(fragmentShader, define);
-  }
+  option.AddOption(Scene3D::Loader::ShaderOption::Type::OCCLUSION);
+  option.AddOption(Scene3D::Loader::ShaderOption::Type::EMISSIVE);
+  option.AddOption(Scene3D::Loader::ShaderOption::Type::SPECULAR);
+  option.AddOption(Scene3D::Loader::ShaderOption::Type::SPECULAR_COLOR);
 
-  DALI_TEST_EQUALS(fragmentShader, GetImplementation(material).GetFragmentShader(), TEST_LOCATION);
+  DALI_TEST_EQUALS(option.GetOptionHash(), GetImplementation(material).GetShaderOption().GetOptionHash(), TEST_LOCATION);
 
   END_TEST;
 }
index 1eed33c..1cb9f3c 100755 (executable)
@@ -36,8 +36,8 @@ SET(TC_SOURCES
   utc-Dali-ResourceBundle.cpp
   utc-Dali-SceneDefinition.cpp
   utc-Dali-ShaderDefinition.cpp
-  utc-Dali-ShaderDefinitionFactory.cpp
-  utc-Dali-ShaderDefinitionOption.cpp
+  utc-Dali-ShaderManager.cpp
+  utc-Dali-ShaderOption.cpp
   utc-Dali-StringCallback.cpp
   utc-Dali-Utils.cpp
   utc-Dali-ViewProjection.cpp
index 2ac5bcb..01bb4b0 100644 (file)
@@ -24,6 +24,7 @@
 #include <dali-scene3d/public-api/controls/model/model.h>
 #include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
 #include <dali-scene3d/public-api/light/light.h>
+#include <dali/public-api/object/property.h>
 #include <toolkit-event-thread-callback.h>
 
 using namespace Dali;
@@ -212,7 +213,7 @@ int UtcDaliLightOnScene01(void)
 int UtcDaliLightAdd01(void)
 {
   ToolkitTestApplication application;
-  Scene3D::SceneView sceneView = Scene3D::SceneView::New();
+  Scene3D::SceneView     sceneView = Scene3D::SceneView::New();
   sceneView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
   sceneView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
   sceneView.SetProperty(Dali::Actor::Property::WIDTH_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT);
@@ -238,20 +239,22 @@ int UtcDaliLightAdd01(void)
 
   Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u);
   DALI_TEST_CHECK(renderer);
+  Shader shader = renderer.GetShader();
+  DALI_TEST_CHECK(shader);
 
   DALI_TEST_EQUALS(1u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  auto countPropertyIndex = renderer.GetPropertyIndex("uLightCount");
-  DALI_TEST_CHECK(countPropertyIndex != DALI_KEY_INVALID);
-  DALI_TEST_EQUALS(1, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
-  auto colorPropertyIndex = renderer.GetPropertyIndex("uLightColor[0]");
-  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), renderer.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
-  auto directionPropertyIndex = renderer.GetPropertyIndex("uLightDirection[0]");
-  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), renderer.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
+  auto countPropertyIndex = shader.GetPropertyIndex("uLightCount");
+  DALI_TEST_CHECK(countPropertyIndex != Dali::Property::INVALID_INDEX);
+  DALI_TEST_EQUALS(1, shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  auto colorPropertyIndex = shader.GetPropertyIndex("uLightColor[0]");
+  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), shader.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
+  auto directionPropertyIndex = shader.GetPropertyIndex("uLightDirection[0]");
+  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), shader.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
 
   light.Enable(false);
 
   DALI_TEST_EQUALS(0u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  DALI_TEST_EQUALS(0, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  DALI_TEST_EQUALS(0, shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
 
   END_TEST;
 }
@@ -290,20 +293,22 @@ int UtcDaliLightAdd02(void)
 
   Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u);
   DALI_TEST_CHECK(renderer);
+  Shader shader = renderer.GetShader();
+  DALI_TEST_CHECK(shader);
 
   DALI_TEST_EQUALS(1u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  auto countPropertyIndex = renderer.GetPropertyIndex("uLightCount");
+  auto countPropertyIndex = shader.GetPropertyIndex("uLightCount");
   DALI_TEST_CHECK(countPropertyIndex != DALI_KEY_INVALID);
-  DALI_TEST_EQUALS(1, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
-  auto colorPropertyIndex = renderer.GetPropertyIndex("uLightColor[0]");
-  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), renderer.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
-  auto directionPropertyIndex = renderer.GetPropertyIndex("uLightDirection[0]");
-  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), renderer.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(1, shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  auto colorPropertyIndex = shader.GetPropertyIndex("uLightColor[0]");
+  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), shader.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
+  auto directionPropertyIndex = shader.GetPropertyIndex("uLightDirection[0]");
+  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), shader.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
 
   light.Enable(false);
 
   DALI_TEST_EQUALS(0u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  DALI_TEST_EQUALS(0, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  DALI_TEST_EQUALS(0, shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
 
   END_TEST;
 }
@@ -340,11 +345,13 @@ int UtcDaliLightAdd03(void)
 
   Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u);
   DALI_TEST_CHECK(renderer);
+  Shader shader = renderer.GetShader();
+  DALI_TEST_CHECK(shader);
 
   DALI_TEST_EQUALS(0u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  auto countPropertyIndex = renderer.GetPropertyIndex("uLightCount");
+  auto countPropertyIndex = shader.GetPropertyIndex("uLightCount");
   DALI_TEST_CHECK(countPropertyIndex != DALI_KEY_INVALID);
-  DALI_TEST_EQUALS(0, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  DALI_TEST_EQUALS(0, shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
 
   light.Enable(true);
 
@@ -352,11 +359,11 @@ int UtcDaliLightAdd03(void)
   application.Render();
 
   DALI_TEST_EQUALS(1u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  DALI_TEST_EQUALS(1, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
-  auto colorPropertyIndex = renderer.GetPropertyIndex("uLightColor[0]");
-  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), renderer.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
-  auto directionPropertyIndex = renderer.GetPropertyIndex("uLightDirection[0]");
-  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), renderer.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(1, shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  auto colorPropertyIndex = shader.GetPropertyIndex("uLightColor[0]");
+  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), shader.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
+  auto directionPropertyIndex = shader.GetPropertyIndex("uLightDirection[0]");
+  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), shader.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
 
   light.Enable(false);
 
@@ -364,7 +371,7 @@ int UtcDaliLightAdd03(void)
   application.Render();
 
   DALI_TEST_EQUALS(0u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  DALI_TEST_EQUALS(0, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  DALI_TEST_EQUALS(0, shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
 
   END_TEST;
 }
@@ -404,19 +411,21 @@ int UtcDaliLightAdd04(void)
 
   Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u);
   DALI_TEST_CHECK(renderer);
+  Shader shader = renderer.GetShader();
+  DALI_TEST_CHECK(shader);
 
   DALI_TEST_EQUALS(2u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  auto countPropertyIndex = renderer.GetPropertyIndex("uLightCount");
+  auto countPropertyIndex = shader.GetPropertyIndex("uLightCount");
   DALI_TEST_CHECK(countPropertyIndex != DALI_KEY_INVALID);
-  DALI_TEST_EQUALS(2, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
-  auto colorPropertyIndex1 = renderer.GetPropertyIndex("uLightColor[0]");
-  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), renderer.GetCurrentProperty<Vector3>(colorPropertyIndex1), 0.01f, TEST_LOCATION);
-  auto directionPropertyIndex1 = renderer.GetPropertyIndex("uLightDirection[0]");
-  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), renderer.GetCurrentProperty<Vector3>(directionPropertyIndex1), 0.01f, TEST_LOCATION);
-  auto colorPropertyIndex2 = renderer.GetPropertyIndex("uLightColor[1]");
-  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), renderer.GetCurrentProperty<Vector3>(colorPropertyIndex2), 0.01f, TEST_LOCATION);
-  auto directionPropertyIndex2 = renderer.GetPropertyIndex("uLightDirection[1]");
-  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, -1.0f), renderer.GetCurrentProperty<Vector3>(directionPropertyIndex2), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(2, shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  auto colorPropertyIndex1 = shader.GetPropertyIndex("uLightColor[0]");
+  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), shader.GetCurrentProperty<Vector3>(colorPropertyIndex1), 0.01f, TEST_LOCATION);
+  auto directionPropertyIndex1 = shader.GetPropertyIndex("uLightDirection[0]");
+  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), shader.GetCurrentProperty<Vector3>(directionPropertyIndex1), 0.01f, TEST_LOCATION);
+  auto colorPropertyIndex2 = shader.GetPropertyIndex("uLightColor[1]");
+  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), shader.GetCurrentProperty<Vector3>(colorPropertyIndex2), 0.01f, TEST_LOCATION);
+  auto directionPropertyIndex2 = shader.GetPropertyIndex("uLightDirection[1]");
+  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, -1.0f), shader.GetCurrentProperty<Vector3>(directionPropertyIndex2), 0.01f, TEST_LOCATION);
 
   light1.Enable(false);
 
@@ -424,11 +433,11 @@ int UtcDaliLightAdd04(void)
   application.Render();
 
   DALI_TEST_EQUALS(1u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  DALI_TEST_EQUALS(1, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  DALI_TEST_EQUALS(1, shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
 
   // After light1 is disable, shader uniforms of lights are reordered.
-  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), renderer.GetCurrentProperty<Vector3>(colorPropertyIndex1), 0.01f, TEST_LOCATION);
-  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, -1.0f), renderer.GetCurrentProperty<Vector3>(directionPropertyIndex1), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), shader.GetCurrentProperty<Vector3>(colorPropertyIndex1), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, -1.0f), shader.GetCurrentProperty<Vector3>(directionPropertyIndex1), 0.01f, TEST_LOCATION);
 
   END_TEST;
 }
@@ -476,23 +485,22 @@ int UtcDaliLightAdd05(void)
 
   Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u);
   DALI_TEST_CHECK(renderer);
-
-  std::vector<int32_t> enableAnswers;
-  enableAnswers.assign(maxLightCount, 1);
+  Shader shader = renderer.GetShader();
+  DALI_TEST_CHECK(shader);
 
   DALI_TEST_EQUALS(maxLightCount, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  auto countPropertyIndex = renderer.GetPropertyIndex("uLightCount");
+  auto countPropertyIndex = shader.GetPropertyIndex("uLightCount");
   DALI_TEST_CHECK(countPropertyIndex != DALI_KEY_INVALID);
-  DALI_TEST_EQUALS(static_cast<int32_t>(maxLightCount), renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  DALI_TEST_EQUALS(static_cast<int32_t>(maxLightCount), shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
   for(uint32_t i = 0; i < maxLightCount; ++i)
   {
     std::string colorStringKey     = std::string("uLightColor[") + std::to_string(i) + "]";
-    auto        colorPropertyIndex = renderer.GetPropertyIndex(colorStringKey);
-    DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), renderer.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
+    auto        colorPropertyIndex = shader.GetPropertyIndex(colorStringKey);
+    DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), shader.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
 
     std::string directionStringKey     = std::string("uLightDirection[") + std::to_string(i) + "]";
-    auto        directionPropertyIndex = renderer.GetPropertyIndex(directionStringKey);
-    DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), renderer.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
+    auto        directionPropertyIndex = shader.GetPropertyIndex(directionStringKey);
+    DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), shader.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
   }
 
   lightList[2].Enable(false);
@@ -501,11 +509,12 @@ int UtcDaliLightAdd05(void)
   application.Render();
 
   DALI_TEST_EQUALS(maxLightCount, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  DALI_TEST_EQUALS(static_cast<int32_t>(maxLightCount), renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  DALI_TEST_EQUALS(static_cast<int32_t>(maxLightCount), shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
   for(uint32_t i = 0; i < maxLightCount; ++i)
   {
+    tet_printf("i : %d\n", i);
     Vector3 color, direction;
-    if(i == 2)
+    if(i == maxLightCount - 1)
     {
       color     = Vector3(1.0f, 0.0f, 0.0f);
       direction = Vector3(0.0f, 0.0f, -1.0f);
@@ -516,12 +525,12 @@ int UtcDaliLightAdd05(void)
       direction = Vector3(1.0f, 0.0f, 0.0f);
     }
     std::string colorStringKey     = std::string("uLightColor[") + std::to_string(i) + "]";
-    auto        colorPropertyIndex = renderer.GetPropertyIndex(colorStringKey);
-    DALI_TEST_EQUALS(color, renderer.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
+    auto        colorPropertyIndex = shader.GetPropertyIndex(colorStringKey);
+    DALI_TEST_EQUALS(color, shader.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
 
     std::string directionStringKey     = std::string("uLightDirection[") + std::to_string(i) + "]";
-    auto        directionPropertyIndex = renderer.GetPropertyIndex(directionStringKey);
-    DALI_TEST_EQUALS(direction, renderer.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
+    auto        directionPropertyIndex = shader.GetPropertyIndex(directionStringKey);
+    DALI_TEST_EQUALS(direction, shader.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
   }
 
   for(uint32_t i = 0; i < lightList.size(); ++i)
@@ -569,23 +578,24 @@ int UtcDaliLightModelAddAndRemove(void)
 
   Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u);
   DALI_TEST_CHECK(renderer);
+  Shader shader = renderer.GetShader();
+  DALI_TEST_CHECK(shader);
 
   DALI_TEST_EQUALS(1u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  auto countPropertyIndex = renderer.GetPropertyIndex("uLightCount");
+  auto countPropertyIndex = shader.GetPropertyIndex("uLightCount");
   DALI_TEST_CHECK(countPropertyIndex != DALI_KEY_INVALID);
-  DALI_TEST_EQUALS(1, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
+  DALI_TEST_EQUALS(1, shader.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
 
-  auto colorPropertyIndex = renderer.GetPropertyIndex("uLightColor[0]");
-  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), renderer.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
-  auto directionPropertyIndex = renderer.GetPropertyIndex("uLightDirection[0]");
-  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), renderer.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
+  auto colorPropertyIndex = shader.GetPropertyIndex("uLightColor[0]");
+  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 1.0f), shader.GetCurrentProperty<Vector3>(colorPropertyIndex), 0.01f, TEST_LOCATION);
+  auto directionPropertyIndex = shader.GetPropertyIndex("uLightDirection[0]");
+  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f), shader.GetCurrentProperty<Vector3>(directionPropertyIndex), 0.01f, TEST_LOCATION);
 
   DALI_TEST_EQUALS(1u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
 
   model.Unparent();
 
   DALI_TEST_EQUALS(1u, sceneView.GetActivatedLightCount(), TEST_LOCATION);
-  DALI_TEST_EQUALS(0, renderer.GetProperty<int32_t>(countPropertyIndex), TEST_LOCATION);
 
   END_TEST;
 }
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionFactory.cpp
deleted file mode 100644 (file)
index 0a269a5..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// Enable debug log for test coverage
-#define DEBUG_ENABLED 1
-
-// Disable this UTC until shader definition factory refactorize
-#define ENABLE_SHADER_DEFINITION_FACTORY_UTC 0
-
-#include <dali-test-suite-utils.h>
-#include <set>
-#include <string_view>
-#include "dali-scene3d/public-api/loader/node-definition.h"
-#include "dali-scene3d/public-api/loader/resource-bundle.h"
-#include "dali-scene3d/public-api/loader/shader-definition-factory.h"
-
-using namespace Dali;
-using namespace Dali::Scene3D::Loader;
-
-namespace
-{
-#if ENABLE_SHADER_DEFINITION_FACTORY_UTC
-MaterialDefinition& NewMaterialDefinition(ResourceBundle& resources)
-{
-  resources.mMaterials.push_back({});
-  return resources.mMaterials.back().first;
-}
-
-MeshDefinition& NewMeshDefinition(ResourceBundle& resources)
-{
-  resources.mMeshes.push_back({});
-  return resources.mMeshes.back().first;
-}
-
-void ClearMeshesAndMaterials(ResourceBundle& resources)
-{
-  resources.mMaterials.clear();
-  resources.mMeshes.clear();
-}
-#endif
-
-struct Context
-{
-  ResourceBundle          resources;
-  ShaderDefinitionFactory factory;
-
-  Context()
-  {
-    factory.SetResources(resources);
-  }
-};
-
-#if ENABLE_SHADER_DEFINITION_FACTORY_UTC
-struct ShaderParameters
-{
-  MeshDefinition&     meshDef;
-  MaterialDefinition& materialDef;
-  NodeDefinition&     nodeDef;
-};
-
-struct Permutation
-{
-  using ConfigureFn = void (*)(ShaderParameters&);
-
-  ConfigureFn configureFn;
-
-  std::set<std::string> defines;
-  RendererState::Type   rendererStateSet   = 0;
-  RendererState::Type   rendererStateClear = 0;
-};
-
-struct PermutationSet
-{
-  std::vector<const Permutation*> permutations;
-  Index                           shaderIdx;
-};
-#endif
-
-} // namespace
-
-int UtcDaliShaderDefinitionFactoryProduceShaderInvalid(void)
-{
-  Context ctx;
-
-  NodeDefinition                              nodeDef;
-  std::unique_ptr<NodeDefinition::Renderable> renderable = std::unique_ptr<NodeDefinition::Renderable>(new NodeDefinition::Renderable());
-  nodeDef.mRenderables.push_back(std::move(renderable));
-
-  DALI_TEST_CHECK(ctx.resources.mShaders.empty());
-
-  END_TEST;
-}
-
-int UtcDaliShaderDefinitionFactoryProduceShader(void)
-{
-#if ENABLE_SHADER_DEFINITION_FACTORY_UTC
-  Context ctx;
-  ctx.resources.mMaterials.push_back({});
-  ctx.resources.mMeshes.push_back({});
-
-  Permutation permutations[]{
-    {
-      [](ShaderParameters& p) {},
-      {},
-      RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE | RendererState::CULL_BACK,
-    },
-    {
-      [](ShaderParameters& p) {
-        p.materialDef.mFlags |= MaterialDefinition::TRANSPARENCY;
-      },
-      {"THREE_TEX"},
-      RendererState::ALPHA_BLEND,
-      RendererState::DEPTH_WRITE,
-    },
-    {[](ShaderParameters& p) {
-       p.materialDef.mFlags |= MaterialDefinition::ALBEDO;
-       p.materialDef.mTextureStages.push_back({MaterialDefinition::ALBEDO, {}});
-     },
-     {"THREE_TEX", "BASECOLOR_TEX"}},
-    {[](ShaderParameters& p) {
-       p.materialDef.mTextureStages.push_back({MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS, {}});
-     },
-     {"THREE_TEX", "METALLIC_ROUGHNESS_TEX"}},
-    {[](ShaderParameters& p) {
-       p.materialDef.mFlags |= MaterialDefinition::NORMAL;
-       p.materialDef.mTextureStages.push_back({MaterialDefinition::NORMAL, {}});
-     },
-     {"THREE_TEX", "NORMAL_TEX"}},
-    {[](ShaderParameters& p) {
-       p.materialDef.mFlags |= MaterialDefinition::SUBSURFACE;
-     },
-     {"SSS"}},
-    {[](ShaderParameters& p) {
-       p.materialDef.SetAlphaCutoff(.5f);
-     },
-     {"ALPHA_TEST"}},
-    {[](ShaderParameters& p) {
-       p.materialDef.SetAlphaCutoff(1.f);
-     },
-     {"ALPHA_TEST"}},
-    {[](ShaderParameters& p) {
-       p.materialDef.mFlags |= MaterialDefinition::GLTF_CHANNELS;
-     },
-     {"GLTF_CHANNELS"}},
-    {[](ShaderParameters& p) {
-       p.meshDef.mJoints0.mBlob.mOffset  = 0;
-       p.meshDef.mWeights0.mBlob.mOffset = 0;
-     },
-     {"SKINNING"}},
-    {[](ShaderParameters& p) {
-       p.meshDef.mFlags |= MeshDefinition::FLIP_UVS_VERTICAL;
-     },
-     {"FLIP_V"}},
-    {
-      [](ShaderParameters& p) {
-        p.meshDef.mBlendShapes.push_back({});
-      },
-    },
-    {[](ShaderParameters& p) {
-       p.meshDef.mBlendShapes.back().deltas.mBlob.mOffset = 0;
-     },
-     {"MORPH_POSITION", "MORPH"}},
-    {[](ShaderParameters& p) {
-       p.meshDef.mBlendShapes.back().normals.mBlob.mOffset = 0;
-     },
-     {"MORPH_NORMAL", "MORPH"}},
-    {[](ShaderParameters& p) {
-       p.meshDef.mBlendShapes.back().tangents.mBlob.mOffset = 0;
-     },
-     {"MORPH_TANGENT", "MORPH"}},
-    {[](ShaderParameters& p) {
-       auto& blendShapes = p.meshDef.mBlendShapes;
-       DALI_ASSERT_ALWAYS(!blendShapes.empty() &&
-                          (blendShapes.back().deltas.mBlob.mOffset != MeshDefinition::INVALID ||
-                           blendShapes.back().normals.mBlob.mOffset != MeshDefinition::INVALID ||
-                           blendShapes.back().tangents.mBlob.mOffset != MeshDefinition::INVALID));
-       p.meshDef.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0;
-     },
-     {"MORPH_VERSION_2_0"}},
-
-    {[](ShaderParameters& p) {
-       p.materialDef.mFlags |= MaterialDefinition::OCCLUSION;
-     },
-
-     {"OCCLUSION"}},
-
-    {[](ShaderParameters& p) {
-       p.meshDef.mColors.mBlob.mOffset = 0;
-     },
-     {"COLOR_ATTRIBUTE"}},
-    {[](ShaderParameters& p) {
-       p.meshDef.mTangentType = Property::VECTOR4;
-     },
-     {"VEC4_TANGENT"}},
-  };
-
-  PermutationSet permSets[]{
-    // default
-    {{&permutations[0]}, 0},
-
-    // alpha
-    {{&permutations[0], &permutations[1]}, 1},
-
-    // three-texture setups
-    {{&permutations[0], &permutations[2]}, 2},
-    {{&permutations[0], &permutations[3]}, 2},
-    {{&permutations[0], &permutations[4]}, 2},
-    {{&permutations[0], &permutations[2], &permutations[3]}, 2},
-    {{&permutations[0], &permutations[3], &permutations[4]}, 2},
-    {{&permutations[0], &permutations[4], &permutations[2]}, 2},
-    {{&permutations[0], &permutations[2], &permutations[3], &permutations[4]}, 2},
-
-    // subsurface scattering
-    {{&permutations[0], &permutations[5]}, 3},
-
-    // alpha test
-    {{&permutations[0], &permutations[6]}, 4},
-    {{&permutations[0], &permutations[7]}, 4},
-
-    // glTF channels
-    {{&permutations[0], &permutations[8]}, 5},
-
-    // skinning
-    {{&permutations[0], &permutations[9]}, 6},
-
-    // flip uvs
-    {{&permutations[0], &permutations[10]}, 7},
-
-    // morphing
-    {{&permutations[0], &permutations[11], &permutations[12]}, 8},
-    {{&permutations[0], &permutations[11], &permutations[13]}, 9},
-    {{&permutations[0], &permutations[11], &permutations[14]}, 10},
-    {{&permutations[0], &permutations[11], &permutations[12], &permutations[13]}, 11},
-    {{&permutations[0], &permutations[11], &permutations[13], &permutations[14]}, 12},
-    {{&permutations[0], &permutations[11], &permutations[14], &permutations[12]}, 13},
-    {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14]}, 14},
-
-    {{&permutations[0], &permutations[11], &permutations[12], &permutations[15]}, 15},
-    {{&permutations[0], &permutations[11], &permutations[13], &permutations[15]}, 16},
-    {{&permutations[0], &permutations[11], &permutations[14], &permutations[15]}, 17},
-    {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[15]}, 18},
-    {{&permutations[0], &permutations[11], &permutations[13], &permutations[14], &permutations[15]}, 19},
-    {{&permutations[0], &permutations[11], &permutations[14], &permutations[12], &permutations[15]}, 20},
-    {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14], &permutations[15]}, 21},
-
-    // etc.
-    {{&permutations[0], &permutations[1], &permutations[2]}, 1},
-    {{&permutations[0], &permutations[1], &permutations[3]}, 1},
-    {{&permutations[0], &permutations[1], &permutations[2], &permutations[3]}, 1},
-
-    // occlusion
-    {{&permutations[0], &permutations[16]}, 22},
-  };
-
-  for(auto& ps : permSets)
-  {
-    static int tc = 0;
-    tet_printf("Test %d's tc\n", ++tc);
-    auto modelRenderable          = new ModelRenderable();
-    modelRenderable->mMeshIdx     = 0;
-    modelRenderable->mMaterialIdx = 0;
-
-    NodeDefinition                              nodeDef;
-    std::unique_ptr<NodeDefinition::Renderable> renderable;
-    renderable.reset(modelRenderable);
-    nodeDef.mRenderables.push_back(std::move(renderable));
-
-    auto&            meshDef     = NewMeshDefinition(ctx.resources);
-    auto&            materialDef = NewMaterialDefinition(ctx.resources);
-    ShaderParameters sp{meshDef, materialDef, nodeDef};
-
-    std::set<std::string> defines;
-    RendererState::Type   rendererState = 0;
-    for(auto p : ps.permutations)
-    {
-      p->configureFn(sp);
-      defines.insert(p->defines.begin(), p->defines.end());
-      rendererState = (rendererState | p->rendererStateSet) & ~p->rendererStateClear;
-    }
-
-    for(auto& renderable : nodeDef.mRenderables)
-    {
-      auto shaderIdx = ctx.factory.ProduceShader(*renderable);
-      DALI_TEST_EQUAL(ps.shaderIdx, shaderIdx);
-
-      auto& shaderDef = ctx.resources.mShaders[shaderIdx].first;
-      DALI_TEST_EQUAL(shaderDef.mRendererState, rendererState);
-
-      uint32_t definesUnmatched = shaderDef.mDefines.size();
-      for(auto& define : shaderDef.mDefines)
-      {
-        auto iFind = defines.find(define);
-        if(iFind != defines.end())
-        {
-          defines.erase(iFind);
-          --definesUnmatched;
-        }
-        else
-        {
-          break;
-        }
-      }
-      if(!defines.empty())
-      {
-        std::ostringstream oss;
-        oss << "Need to check below defines :\n";
-        for(auto& it : defines)
-        {
-          oss << it << "\n";
-        }
-        tet_printf("%s\n", oss.str().c_str());
-      }
-
-      DALI_TEST_CHECK(defines.empty());
-      DALI_TEST_EQUAL(0, definesUnmatched);
-
-      auto uMaxLOD = shaderDef.mUniforms["uMaxLOD"];
-      DALI_TEST_EQUAL(uMaxLOD.GetType(), Property::FLOAT);
-
-      auto uCubeMatrix = shaderDef.mUniforms["uCubeMatrix"];
-      DALI_TEST_EQUAL(uCubeMatrix.GetType(), Property::MATRIX);
-    }
-
-    ClearMeshesAndMaterials(ctx.resources);
-  }
-#else
-  DALI_TEST_CHECK(true);
-#endif
-
-  END_TEST;
-}
\ No newline at end of file
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionOption.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionOption.cpp
deleted file mode 100644 (file)
index 0f320a8..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2023 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <dali-test-suite-utils.h>
-#include <dali-toolkit/dali-toolkit.h>
-#include <string_view>
-#include "dali-scene3d/public-api/loader/shader-definition-option.h"
-
-using namespace Dali;
-using namespace Dali::Toolkit;
-
-void shader_definition_option_startup(void)
-{
-  test_return_value = TET_UNDEF;
-}
-
-void shader_definition_option_cleanup(void)
-{
-  test_return_value = TET_PASS;
-}
-
-int UtcDaliShaderDefinitionOptionInit(void)
-{
-  Scene3D::Loader::ShaderDefinitionOption option;
-  DALI_TEST_EQUALS(option.GetOptionHash(), 0u, TEST_LOCATION);
-  END_TEST;
-}
-
-int UtcDaliShaderDefinitionOptionSetTransparency(void)
-{
-  Scene3D::Loader::ShaderDefinitionOption option;
-  DALI_TEST_EQUALS(option.GetOptionHash(), 0u, TEST_LOCATION);
-
-  option.SetTransparency();
-  DALI_TEST_NOT_EQUALS(option.GetOptionHash(), static_cast<uint64_t>(0u), 0.1f, TEST_LOCATION);
-
-  END_TEST;
-}
-
-int UtcDaliShaderDefinitionOptionAddOption(void)
-{
-  Scene3D::Loader::ShaderDefinitionOption option;
-  DALI_TEST_EQUALS(option.GetOptionHash(), 0u, TEST_LOCATION);
-
-  Scene3D::Loader::ShaderDefinitionOption::Type types[19] = {
-    Scene3D::Loader::ShaderDefinitionOption::Type::GLTF_CHANNELS,
-    Scene3D::Loader::ShaderDefinitionOption::Type::THREE_TEXTURE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::BASE_COLOR_TEXTURE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::METALLIC_ROUGHNESS_TEXTURE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::NORMAL_TEXTURE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::OCCLUSION,
-    Scene3D::Loader::ShaderDefinitionOption::Type::EMISSIVE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::ALPHA_TEST,
-    Scene3D::Loader::ShaderDefinitionOption::Type::SUBSURFACE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::SPECULAR,
-    Scene3D::Loader::ShaderDefinitionOption::Type::SPECULAR_COLOR,
-    Scene3D::Loader::ShaderDefinitionOption::Type::SKINNING,
-    Scene3D::Loader::ShaderDefinitionOption::Type::FLIP_UVS_VERTICAL,
-    Scene3D::Loader::ShaderDefinitionOption::Type::COLOR_ATTRIBUTE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::VEC4_TANGENT,
-    Scene3D::Loader::ShaderDefinitionOption::Type::MORPH_POSITION,
-    Scene3D::Loader::ShaderDefinitionOption::Type::MORPH_NORMAL,
-    Scene3D::Loader::ShaderDefinitionOption::Type::MORPH_TANGENT,
-    Scene3D::Loader::ShaderDefinitionOption::Type::MORPH_VERSION_2_0};
-
-  uint64_t hash = 0u;
-  for(uint32_t i = 0; i < 19; ++i)
-  {
-    hash |= (1 << static_cast<uint32_t>(types[i]));
-    option.AddOption(types[i]);
-    DALI_TEST_EQUALS(option.GetOptionHash(), hash, TEST_LOCATION);
-  }
-
-  END_TEST;
-}
-
-int UtcDaliShaderDefinitionOptionGetDefines(void)
-{
-  Scene3D::Loader::ShaderDefinitionOption option;
-  DALI_TEST_EQUALS(option.GetOptionHash(), 0u, TEST_LOCATION);
-
-  Scene3D::Loader::ShaderDefinitionOption::Type types[19] = {
-    Scene3D::Loader::ShaderDefinitionOption::Type::GLTF_CHANNELS,
-    Scene3D::Loader::ShaderDefinitionOption::Type::THREE_TEXTURE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::BASE_COLOR_TEXTURE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::METALLIC_ROUGHNESS_TEXTURE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::NORMAL_TEXTURE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::OCCLUSION,
-    Scene3D::Loader::ShaderDefinitionOption::Type::EMISSIVE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::ALPHA_TEST,
-    Scene3D::Loader::ShaderDefinitionOption::Type::SUBSURFACE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::SPECULAR,
-    Scene3D::Loader::ShaderDefinitionOption::Type::SPECULAR_COLOR,
-    Scene3D::Loader::ShaderDefinitionOption::Type::SKINNING,
-    Scene3D::Loader::ShaderDefinitionOption::Type::FLIP_UVS_VERTICAL,
-    Scene3D::Loader::ShaderDefinitionOption::Type::COLOR_ATTRIBUTE,
-    Scene3D::Loader::ShaderDefinitionOption::Type::VEC4_TANGENT,
-    Scene3D::Loader::ShaderDefinitionOption::Type::MORPH_POSITION,
-    Scene3D::Loader::ShaderDefinitionOption::Type::MORPH_NORMAL,
-    Scene3D::Loader::ShaderDefinitionOption::Type::MORPH_TANGENT,
-    Scene3D::Loader::ShaderDefinitionOption::Type::MORPH_VERSION_2_0};
-
-  uint64_t hash = 0u;
-  for(uint32_t i = 0; i < 19; ++i)
-  {
-    hash |= (1 << static_cast<uint32_t>(types[i]));
-    option.AddOption(types[i]);
-    DALI_TEST_EQUALS(option.GetOptionHash(), hash, TEST_LOCATION);
-
-    std::vector<std::string> defines;
-    option.GetDefines(defines);
-    DALI_TEST_EQUALS(defines.size(), i + 1, TEST_LOCATION);
-    for(uint32_t j = 0; j < defines.size(); ++j)
-    {
-      DALI_TEST_EQUALS(defines[j], option.GetDefineKeyword(types[j]), TEST_LOCATION);
-    }
-  }
-
-  END_TEST;
-}
\ No newline at end of file
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ShaderManager.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ShaderManager.cpp
new file mode 100644 (file)
index 0000000..f272ba9
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2022 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Enable debug log for test coverage
+#define DEBUG_ENABLED 1
+
+#include <dali-scene3d/public-api/loader/node-definition.h>
+#include <dali-scene3d/public-api/loader/resource-bundle.h>
+#include <dali-scene3d/public-api/loader/shader-manager.h>
+#include <dali-test-suite-utils.h>
+#include <set>
+#include <string_view>
+
+using namespace Dali;
+using namespace Dali::Scene3D::Loader;
+
+namespace
+{
+struct Context
+{
+  ResourceBundle resources;
+};
+
+struct ShaderParameters
+{
+  MeshDefinition&     meshDefinition;
+  MaterialDefinition& materialDefinition;
+  NodeDefinition&     nodeDefinition;
+};
+
+struct Permutation
+{
+  using ConfigureFn = void (*)(ShaderParameters&);
+
+  ConfigureFn configureFn;
+
+  std::set<ShaderOption::Type> options;
+  RendererState::Type          rendererStateSet   = 0;
+  RendererState::Type          rendererStateClear = 0;
+};
+
+struct PermutationSet
+{
+  std::vector<const Permutation*> permutations;
+};
+
+} // namespace
+
+int UtcDaliShaderManagerProduceShader(void)
+{
+  Context ctx;
+  ctx.resources.mMaterials.push_back({});
+  ctx.resources.mMeshes.push_back({});
+
+  Permutation permutations[]{
+    {
+      [](ShaderParameters& p) {},
+      {},
+      RendererState::DEPTH_TEST | RendererState::CULL_BACK,
+    },
+    {
+      [](ShaderParameters& p)
+      {
+        p.materialDefinition.mFlags |= MaterialDefinition::TRANSPARENCY;
+      },
+      {ShaderOption::Type::THREE_TEXTURE},
+      RendererState::ALPHA_BLEND,
+    },
+    {[](ShaderParameters& p)
+     {
+       p.materialDefinition.mFlags |= MaterialDefinition::ALBEDO;
+       p.materialDefinition.mTextureStages.push_back({MaterialDefinition::ALBEDO, {}});
+     },
+     {ShaderOption::Type::THREE_TEXTURE, ShaderOption::Type::BASE_COLOR_TEXTURE}},
+    {[](ShaderParameters& p)
+     {
+       p.materialDefinition.mTextureStages.push_back({MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS, {}});
+     },
+     {ShaderOption::Type::THREE_TEXTURE, ShaderOption::Type::METALLIC_ROUGHNESS_TEXTURE}},
+    {[](ShaderParameters& p)
+     {
+       p.materialDefinition.mFlags |= MaterialDefinition::NORMAL;
+       p.materialDefinition.mTextureStages.push_back({MaterialDefinition::NORMAL, {}});
+     },
+     {ShaderOption::Type::THREE_TEXTURE, ShaderOption::Type::NORMAL_TEXTURE}},
+    {[](ShaderParameters& p)
+     {
+       p.materialDefinition.mFlags |= MaterialDefinition::SUBSURFACE;
+     },
+     {ShaderOption::Type::SUBSURFACE}},
+    {[](ShaderParameters& p)
+     {
+       p.materialDefinition.SetAlphaCutoff(.5f);
+     },
+     {ShaderOption::Type::ALPHA_TEST}},
+    {[](ShaderParameters& p)
+     {
+       p.materialDefinition.SetAlphaCutoff(1.f);
+     },
+     {ShaderOption::Type::ALPHA_TEST}},
+    {[](ShaderParameters& p)
+     {
+       p.materialDefinition.mFlags |= MaterialDefinition::GLTF_CHANNELS;
+     },
+     {ShaderOption::Type::GLTF_CHANNELS}},
+    {[](ShaderParameters& p)
+     {
+       p.meshDefinition.mJoints0.mBlob.mOffset  = 0;
+       p.meshDefinition.mWeights0.mBlob.mOffset = 0;
+     },
+     {ShaderOption::Type::SKINNING}},
+    {[](ShaderParameters& p)
+     {
+       p.meshDefinition.mFlags |= MeshDefinition::FLIP_UVS_VERTICAL;
+     },
+     {ShaderOption::Type::FLIP_UVS_VERTICAL}},
+    {
+      [](ShaderParameters& p)
+      {
+        p.meshDefinition.mBlendShapes.push_back({});
+      },
+    },
+    {[](ShaderParameters& p)
+     {
+       p.meshDefinition.mBlendShapes.back().deltas.mBlob.mOffset = 0;
+     },
+     {ShaderOption::Type::MORPH_POSITION}},
+    {[](ShaderParameters& p)
+     {
+       p.meshDefinition.mBlendShapes.back().normals.mBlob.mOffset = 0;
+     },
+     {ShaderOption::Type::MORPH_NORMAL}},
+    {[](ShaderParameters& p)
+     {
+       p.meshDefinition.mBlendShapes.back().tangents.mBlob.mOffset = 0;
+     },
+     {ShaderOption::Type::MORPH_TANGENT}},
+    {[](ShaderParameters& p)
+     {
+       auto& blendShapes = p.meshDefinition.mBlendShapes;
+       DALI_ASSERT_ALWAYS(!blendShapes.empty() &&
+                          (blendShapes.back().deltas.mBlob.mOffset != MeshDefinition::INVALID ||
+                           blendShapes.back().normals.mBlob.mOffset != MeshDefinition::INVALID ||
+                           blendShapes.back().tangents.mBlob.mOffset != MeshDefinition::INVALID));
+       p.meshDefinition.mBlendShapeVersion = BlendShapes::Version::VERSION_2_0;
+     },
+     {ShaderOption::Type::MORPH_VERSION_2_0}},
+
+    {[](ShaderParameters& p)
+     {
+       p.materialDefinition.mFlags |= MaterialDefinition::OCCLUSION;
+     },
+     {ShaderOption::Type::OCCLUSION}},
+
+    {[](ShaderParameters& p)
+     {
+       p.meshDefinition.mColors.mBlob.mOffset = 0;
+     },
+     {ShaderOption::Type::COLOR_ATTRIBUTE}},
+    {[](ShaderParameters& p)
+     {
+       p.meshDefinition.mTangentType = Property::VECTOR4;
+     },
+     {ShaderOption::Type::VEC4_TANGENT}},
+  };
+
+  PermutationSet permutationSets[]{
+    // default
+    {{&permutations[0]}},
+
+    // alpha
+    {{&permutations[0], &permutations[1]}},
+
+    // three-texture setups
+    {{&permutations[0], &permutations[2]}},
+    {{&permutations[0], &permutations[3]}},
+    {{&permutations[0], &permutations[4]}},
+    {{&permutations[0], &permutations[2], &permutations[3]}},
+    {{&permutations[0], &permutations[3], &permutations[4]}},
+    {{&permutations[0], &permutations[4], &permutations[2]}},
+    {{&permutations[0], &permutations[2], &permutations[3], &permutations[4]}},
+
+    // subsurface scattering
+    {{&permutations[0], &permutations[5]}},
+
+    // alpha test
+    {{&permutations[0], &permutations[6]}},
+    {{&permutations[0], &permutations[7]}},
+
+    // glTF channels
+    {{&permutations[0], &permutations[8]}},
+
+    // skinning
+    {{&permutations[0], &permutations[9]}},
+
+    // flip uvs
+    {{&permutations[0], &permutations[10]}},
+
+    // morphing
+    {{&permutations[0], &permutations[11], &permutations[12]}},
+    {{&permutations[0], &permutations[11], &permutations[13]}},
+    {{&permutations[0], &permutations[11], &permutations[14]}},
+    {{&permutations[0], &permutations[11], &permutations[12], &permutations[13]}},
+    {{&permutations[0], &permutations[11], &permutations[13], &permutations[14]}},
+    {{&permutations[0], &permutations[11], &permutations[14], &permutations[12]}},
+    {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14]}},
+
+    {{&permutations[0], &permutations[11], &permutations[12], &permutations[15]}},
+    {{&permutations[0], &permutations[11], &permutations[13], &permutations[15]}},
+    {{&permutations[0], &permutations[11], &permutations[14], &permutations[15]}},
+    {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[15]}},
+    {{&permutations[0], &permutations[11], &permutations[13], &permutations[14], &permutations[15]}},
+    {{&permutations[0], &permutations[11], &permutations[14], &permutations[12], &permutations[15]}},
+    {{&permutations[0], &permutations[11], &permutations[12], &permutations[13], &permutations[14], &permutations[15]}},
+
+    // etc.
+    {{&permutations[0], &permutations[1], &permutations[2]}},
+    {{&permutations[0], &permutations[1], &permutations[3]}},
+    {{&permutations[0], &permutations[1], &permutations[2], &permutations[3]}},
+
+    // occlusion
+    {{&permutations[0], &permutations[16]}},
+  };
+
+  TestApplication app;
+  ShaderManager   shaderManager;
+  for(auto& permutationSet : permutationSets)
+  {
+    static int tc = 0;
+    tet_printf("Test %d's tc\n", ++tc);
+    auto modelRenderable          = new ModelRenderable();
+    modelRenderable->mMeshIdx     = 0;
+    modelRenderable->mMaterialIdx = 0;
+
+    NodeDefinition                              nodeDefinition;
+    std::unique_ptr<NodeDefinition::Renderable> renderable;
+    renderable.reset(modelRenderable);
+    nodeDefinition.mRenderables.push_back(std::move(renderable));
+
+    MeshDefinition     meshDefinition;
+    MaterialDefinition materialDefinition;
+    ShaderParameters   shaderParameter{meshDefinition, materialDefinition, nodeDefinition};
+
+    std::set<std::string> defines;
+    ShaderOption          option;
+    RendererState::Type   rendererState = 0;
+    for(auto permutation : permutationSet.permutations)
+    {
+      permutation->configureFn(shaderParameter);
+      if(materialDefinition.mFlags & MaterialDefinition::TRANSPARENCY)
+      {
+        option.SetTransparency();
+      }
+      for(auto&& optionType : permutation->options)
+      {
+        option.AddOption(optionType);
+      }
+      rendererState = (rendererState | permutation->rendererStateSet) & ~permutation->rendererStateClear;
+    }
+    option.AddOption(ShaderOption::Type::THREE_TEXTURE);
+
+    Shader shaderFromMeshAndMaterial = shaderManager.ProduceShader(materialDefinition, meshDefinition);
+    Shader shaderFromOption          = shaderManager.ProduceShader(option);
+    DALI_TEST_EQUAL(shaderFromMeshAndMaterial, shaderFromOption);
+
+    RendererState::Type rendererStateFromMaterialDefinition = shaderManager.GetRendererState(materialDefinition);
+    DALI_TEST_EQUAL(rendererStateFromMaterialDefinition, rendererState);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliShaderManagerAddAndRemoveLights(void)
+{
+  TestApplication app;
+  ShaderManager   shaderManager;
+
+  ShaderOption option1;
+  option1.AddOption(ShaderOption::Type::THREE_TEXTURE);
+  Dali::Shader shader1 = shaderManager.ProduceShader(option1);
+
+  ShaderOption option2;
+  option2.AddOption(ShaderOption::Type::BASE_COLOR_TEXTURE);
+  Dali::Shader shader2 = shaderManager.ProduceShader(option2);
+
+  DALI_TEST_NOT_EQUALS(shader1, shader2, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(shader1.GetProperty<int>(shader1.GetPropertyIndex("uLightCount")), 0, TEST_LOCATION);
+  DALI_TEST_EQUALS(shader2.GetProperty<int>(shader2.GetPropertyIndex("uLightCount")), 0, TEST_LOCATION);
+
+  Scene3D::Light light = Scene3D::Light::New();
+  shaderManager.AddLight(light);
+
+  DALI_TEST_EQUALS(shader1.GetProperty<int>(shader1.GetPropertyIndex("uLightCount")), 1, TEST_LOCATION);
+  DALI_TEST_EQUALS(shader2.GetProperty<int>(shader2.GetPropertyIndex("uLightCount")), 1, TEST_LOCATION);
+  
+  ShaderOption option3;
+  option3.AddOption(ShaderOption::Type::METALLIC_ROUGHNESS_TEXTURE);
+  Dali::Shader shader3 = shaderManager.ProduceShader(option3);
+
+  DALI_TEST_NOT_EQUALS(shader1, shader3, 0.1f, TEST_LOCATION);
+  DALI_TEST_NOT_EQUALS(shader2, shader3, 0.1f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(shader3.GetProperty<int>(shader3.GetPropertyIndex("uLightCount")), 1, TEST_LOCATION);
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ShaderOption.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ShaderOption.cpp
new file mode 100644 (file)
index 0000000..71514fd
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-test-suite-utils.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <string_view>
+#include "dali-scene3d/public-api/loader/shader-option.h"
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+
+void shader_definition_option_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void shader_definition_option_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliShaderOptionInit(void)
+{
+  Scene3D::Loader::ShaderOption option;
+  DALI_TEST_EQUALS(option.GetOptionHash(), 0u, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliShaderOptionSetTransparency(void)
+{
+  Scene3D::Loader::ShaderOption option;
+  DALI_TEST_EQUALS(option.GetOptionHash(), 0u, TEST_LOCATION);
+
+  option.SetTransparency();
+  DALI_TEST_NOT_EQUALS(option.GetOptionHash(), static_cast<uint64_t>(0u), 0.1f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliShaderOptionAddOption(void)
+{
+  Scene3D::Loader::ShaderOption option;
+  DALI_TEST_EQUALS(option.GetOptionHash(), 0u, TEST_LOCATION);
+
+  Scene3D::Loader::ShaderOption::Type types[19] = {
+    Scene3D::Loader::ShaderOption::Type::GLTF_CHANNELS,
+    Scene3D::Loader::ShaderOption::Type::THREE_TEXTURE,
+    Scene3D::Loader::ShaderOption::Type::BASE_COLOR_TEXTURE,
+    Scene3D::Loader::ShaderOption::Type::METALLIC_ROUGHNESS_TEXTURE,
+    Scene3D::Loader::ShaderOption::Type::NORMAL_TEXTURE,
+    Scene3D::Loader::ShaderOption::Type::OCCLUSION,
+    Scene3D::Loader::ShaderOption::Type::EMISSIVE,
+    Scene3D::Loader::ShaderOption::Type::ALPHA_TEST,
+    Scene3D::Loader::ShaderOption::Type::SUBSURFACE,
+    Scene3D::Loader::ShaderOption::Type::SPECULAR,
+    Scene3D::Loader::ShaderOption::Type::SPECULAR_COLOR,
+    Scene3D::Loader::ShaderOption::Type::SKINNING,
+    Scene3D::Loader::ShaderOption::Type::FLIP_UVS_VERTICAL,
+    Scene3D::Loader::ShaderOption::Type::COLOR_ATTRIBUTE,
+    Scene3D::Loader::ShaderOption::Type::VEC4_TANGENT,
+    Scene3D::Loader::ShaderOption::Type::MORPH_POSITION,
+    Scene3D::Loader::ShaderOption::Type::MORPH_NORMAL,
+    Scene3D::Loader::ShaderOption::Type::MORPH_TANGENT,
+    Scene3D::Loader::ShaderOption::Type::MORPH_VERSION_2_0};
+
+  uint64_t hash = 0u;
+  for(uint32_t i = 0; i < 19; ++i)
+  {
+    hash |= (1 << static_cast<uint32_t>(types[i]));
+    option.AddOption(types[i]);
+    DALI_TEST_EQUALS(option.GetOptionHash(), hash, TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliShaderOptionGetDefines(void)
+{
+  Scene3D::Loader::ShaderOption option;
+  DALI_TEST_EQUALS(option.GetOptionHash(), 0u, TEST_LOCATION);
+
+  Scene3D::Loader::ShaderOption::Type types[19] = {
+    Scene3D::Loader::ShaderOption::Type::GLTF_CHANNELS,
+    Scene3D::Loader::ShaderOption::Type::THREE_TEXTURE,
+    Scene3D::Loader::ShaderOption::Type::BASE_COLOR_TEXTURE,
+    Scene3D::Loader::ShaderOption::Type::METALLIC_ROUGHNESS_TEXTURE,
+    Scene3D::Loader::ShaderOption::Type::NORMAL_TEXTURE,
+    Scene3D::Loader::ShaderOption::Type::OCCLUSION,
+    Scene3D::Loader::ShaderOption::Type::EMISSIVE,
+    Scene3D::Loader::ShaderOption::Type::ALPHA_TEST,
+    Scene3D::Loader::ShaderOption::Type::SUBSURFACE,
+    Scene3D::Loader::ShaderOption::Type::SPECULAR,
+    Scene3D::Loader::ShaderOption::Type::SPECULAR_COLOR,
+    Scene3D::Loader::ShaderOption::Type::SKINNING,
+    Scene3D::Loader::ShaderOption::Type::FLIP_UVS_VERTICAL,
+    Scene3D::Loader::ShaderOption::Type::COLOR_ATTRIBUTE,
+    Scene3D::Loader::ShaderOption::Type::VEC4_TANGENT,
+    Scene3D::Loader::ShaderOption::Type::MORPH_POSITION,
+    Scene3D::Loader::ShaderOption::Type::MORPH_NORMAL,
+    Scene3D::Loader::ShaderOption::Type::MORPH_TANGENT,
+    Scene3D::Loader::ShaderOption::Type::MORPH_VERSION_2_0};
+
+  uint64_t hash = 0u;
+  for(uint32_t i = 0; i < 19; ++i)
+  {
+    hash |= (1 << static_cast<uint32_t>(types[i]));
+    option.AddOption(types[i]);
+    DALI_TEST_EQUALS(option.GetOptionHash(), hash, TEST_LOCATION);
+
+    std::vector<std::string> defines;
+    option.GetDefines(defines);
+    DALI_TEST_EQUALS(defines.size(), i + 1, TEST_LOCATION);
+    for(uint32_t j = 0; j < defines.size(); ++j)
+    {
+      DALI_TEST_EQUALS(defines[j], option.GetDefineKeyword(types[j]), TEST_LOCATION);
+    }
+  }
+
+  END_TEST;
+}
\ No newline at end of file
index 1e4dfe1..8f3c69e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/text-abstraction/font-client.h>
 #include <limits>
+#include <cstring> ///< for memcpy
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/internal/text/bidirectional-support.h>
index 6571365..03a65c1 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/rendering/texture-set.h>
 #include <dali/public-api/rendering/texture.h>
 #include <set> // For std::multiset
index eb7c60a..df626ad 100644 (file)
@@ -59,8 +59,8 @@
 #include <dali-scene3d/public-api/loader/renderer-state.h>
 #include <dali-scene3d/public-api/loader/resource-bundle.h>
 #include <dali-scene3d/public-api/loader/scene-definition.h>
-#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
 #include <dali-scene3d/public-api/loader/shader-definition.h>
+#include <dali-scene3d/public-api/loader/shader-manager.h>
 #include <dali-scene3d/public-api/loader/skeleton-definition.h>
 #include <dali-scene3d/public-api/loader/skinning-details.h>
 #include <dali-scene3d/public-api/loader/string-callback.h>
index c54c73b..608e100 100644 (file)
@@ -60,21 +60,6 @@ public:
    * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f].
    */
   virtual void NotifyImageBasedLightScaleFactor(float scaleFactor) = 0;
-
-  /**
-   * @brief Notifies new light is added on SceneView
-   *
-   * @param[in] lightIndex Index of added light.
-   * @param[in] light Added light.
-   */
-  virtual void NotifyLightAdded(uint32_t lightIndex, Scene3D::Light light) = 0;
-
-  /**
-   * @brief Notifies a light is removed from SceneView
-   *
-   * @param[in] lightIndex Index of light to be removed.
-   */
-  virtual void NotifyLightRemoved(uint32_t lightIndex) = 0;
 };
 
 } // namespace Internal
index 7c82d4b..1feb6b5 100644 (file)
@@ -42,7 +42,7 @@
 #include <dali-scene3d/public-api/loader/load-result.h>
 #include <dali-scene3d/public-api/loader/node-definition.h>
 #include <dali-scene3d/public-api/loader/scene-definition.h>
-#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
+#include <dali-scene3d/public-api/loader/shader-manager.h>
 #include <dali-scene3d/public-api/model-motion/motion-index/blend-shape-index.h>
 
 using namespace Dali;
@@ -172,33 +172,35 @@ void AddModelTreeToAABB(BoundingVolume& AABB, const Dali::Scene3D::Loader::Scene
   }
 }
 
-void AddLightRecursively(Scene3D::ModelNode node, Scene3D::Light light, uint32_t lightIndex)
+void UpdateBlendShapeNodeMapRecursively(Model::BlendShapeModelNodeMap& resultMap, const Scene3D::ModelNode& node)
 {
   if(!node)
   {
     return;
   }
-  GetImplementation(node).AddLight(light, lightIndex);
+  const auto childCount = node.GetChildCount();
+  for(auto i = 0u; i < childCount; ++i)
+  {
+    UpdateBlendShapeNodeMapRecursively(resultMap, Scene3D::ModelNode::DownCast(node.GetChildAt(i)));
+  }
 
-  uint32_t childrenCount = node.GetChildCount();
-  for(uint32_t i = 0; i < childrenCount; ++i)
+  std::vector<std::string> blendShapeNames;
+  node.RetrieveBlendShapeNames(blendShapeNames);
+  for(const auto& iter : blendShapeNames)
   {
-    Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
-    if(childNode)
-    {
-      AddLightRecursively(childNode, light, lightIndex);
-    }
+    // Append or create new list.
+    resultMap[iter].push_back(node);
   }
 }
 
-void RemoveLightRecursively(Scene3D::ModelNode node, uint32_t lightIndex)
+void UpdateShaderRecursively(Scene3D::ModelNode node, Scene3D::Loader::ShaderManagerPtr shaderManager)
 {
   if(!node)
   {
     return;
   }
 
-  GetImplementation(node).RemoveLight(lightIndex);
+  GetImplementation(node).UpdateShader(shaderManager);
 
   uint32_t childrenCount = node.GetChildCount();
   for(uint32_t i = 0; i < childrenCount; ++i)
@@ -206,32 +208,11 @@ void RemoveLightRecursively(Scene3D::ModelNode node, uint32_t lightIndex)
     Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i));
     if(childNode)
     {
-      RemoveLightRecursively(childNode, lightIndex);
+      UpdateShaderRecursively(childNode, shaderManager);
     }
   }
 }
 
-void UpdateBlendShapeNodeMapRecursively(Model::BlendShapeModelNodeMap& resultMap, const Scene3D::ModelNode& node)
-{
-  if(!node)
-  {
-    return;
-  }
-  const auto childCount = node.GetChildCount();
-  for(auto i = 0u; i < childCount; ++i)
-  {
-    UpdateBlendShapeNodeMapRecursively(resultMap, Scene3D::ModelNode::DownCast(node.GetChildAt(i)));
-  }
-
-  std::vector<std::string> blendShapeNames;
-  node.RetrieveBlendShapeNames(blendShapeNames);
-  for(const auto& iter : blendShapeNames)
-  {
-    // Append or create new list.
-    resultMap[iter].push_back(node);
-  }
-}
-
 } // anonymous namespace
 
 Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl)
@@ -239,6 +220,7 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr
   mModelUrl(modelUrl),
   mResourceDirectoryUrl(resourceDirectoryUrl),
   mModelRoot(),
+  mShaderManager(new Scene3D::Loader::ShaderManager()),
   mNaturalSize(Vector3::ZERO),
   mModelPivot(AnchorPoint::CENTER),
   mSceneIblScaleFactor(1.0f),
@@ -296,21 +278,14 @@ void Model::AddModelNode(Scene3D::ModelNode modelNode)
     mModelResourceReady = true;
   }
 
+  UpdateShaderRecursively(modelNode, mShaderManager);
+
   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
   {
     UpdateImageBasedLightTexture();
     UpdateImageBasedLightScaleFactor();
   }
 
-  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxLightCount; ++i)
-  {
-    if(mLights[i])
-    {
-      AddLightRecursively(modelNode, mLights[i], i);
-    }
-  }
-
   if(Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
   {
     NotifyResourceReady();
@@ -321,14 +296,7 @@ void Model::RemoveModelNode(Scene3D::ModelNode modelNode)
 {
   if(mModelRoot)
   {
-    uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-    for(uint32_t i = 0; i < maxLightCount; ++i)
-    {
-      if(mLights[i])
-      {
-        RemoveLightRecursively(modelNode, i);
-      }
-    }
+    UpdateShaderRecursively(modelNode, nullptr);
     mModelRoot.Remove(modelNode);
   }
 }
@@ -769,11 +737,40 @@ void Model::OnInitialize()
 {
   // Make ParentOrigin as Center.
   Self().SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
-  mLights.resize(Scene3D::Internal::Light::GetMaximumEnabledLightCount());
 }
 
 void Model::OnSceneConnection(int depth)
 {
+  Actor parent = Self().GetParent();
+  while(parent)
+  {
+    // If this Model has parent SceneView and the its ShaderManager is same with privious ShaderManager,
+    // this Model don't need to update shader.
+    Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent);
+    if(sceneView)
+    {
+      mParentSceneView = sceneView;
+      GetImpl(sceneView).RegisterSceneItem(this);
+      Scene3D::Loader::ShaderManagerPtr shaderManager = GetImpl(sceneView).GetShaderManager();
+      if(mShaderManager != shaderManager)
+      {
+        mShaderManager = shaderManager;
+        UpdateShaderRecursively(mModelRoot, mShaderManager);
+      }
+      break;
+    }
+    parent = parent.GetParent();
+  }
+
+  // Model can be added on Dali::Scene directly without SceneView.
+  // So, Model's mShaderManager and shaders of child ModelNodes are needed to be reset when this Model has not parent SceneView.
+  Scene3D::SceneView parentSceneView = mParentSceneView.GetHandle();
+  if(!parentSceneView)
+  {
+    mShaderManager = new Dali::Scene3D::Loader::ShaderManager();
+    UpdateShaderRecursively(mModelRoot, mShaderManager);
+  }
+
   if(!mModelLoadTask && !mModelResourceReady && !mModelUrl.empty())
   {
     // Request model load only if we setup url.
@@ -791,19 +788,6 @@ void Model::OnSceneConnection(int depth)
     SetImageBasedLightSource(mDiffuseIblUrl, mSpecularIblUrl, mIblScaleFactor);
   }
 
-  Actor parent = Self().GetParent();
-  while(parent)
-  {
-    Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent);
-    if(sceneView)
-    {
-      GetImpl(sceneView).RegisterSceneItem(this);
-      mParentSceneView = sceneView;
-      break;
-    }
-    parent = parent.GetParent();
-  }
-
   NotifyResourceReady();
 
   mSizeNotification = Self().AddPropertyNotification(Actor::Property::SIZE, StepCondition(SIZE_STEP_CONDITION));
@@ -813,8 +797,11 @@ void Model::OnSceneConnection(int depth)
 
 void Model::OnSceneDisconnection()
 {
+  // If mParentSceneView is still onScene, that means this model
+  // is disconnected from mParentSceneView's sub tree.
+  // So, Unregister this Model from SceneView.
   Scene3D::SceneView sceneView = mParentSceneView.GetHandle();
-  if(sceneView)
+  if(sceneView && sceneView.GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE))
   {
     GetImpl(sceneView).UnregisterSceneItem(this);
     mParentSceneView.Reset();
@@ -1045,21 +1032,6 @@ void Model::NotifyImageBasedLightScaleFactor(float scaleFactor)
   }
 }
 
-void Model::NotifyLightAdded(uint32_t lightIndex, Scene3D::Light light)
-{
-  mLights[lightIndex] = light;
-  AddLightRecursively(mModelRoot, light, lightIndex);
-}
-
-void Model::NotifyLightRemoved(uint32_t lightIndex)
-{
-  if(mLights[lightIndex])
-  {
-    RemoveLightRecursively(mModelRoot, lightIndex);
-    mLights[lightIndex].Reset();
-  }
-}
-
 void Model::OnModelLoadComplete()
 {
   if(!mModelLoadTask->HasSucceeded())
@@ -1090,15 +1062,6 @@ void Model::OnModelLoadComplete()
     mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular;
   }
 
-  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxLightCount; ++i)
-  {
-    if(mLights[i])
-    {
-      AddLightRecursively(mModelRoot, mLights[i], i);
-    }
-  }
-
   UpdateImageBasedLightTexture();
   UpdateImageBasedLightScaleFactor();
   Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z));
@@ -1174,12 +1137,13 @@ void Model::NotifyResourceReady()
 
 void Model::CreateModel()
 {
-  BoundingVolume                                      AABB;
-  auto&                                               resources       = mModelLoadTask->GetResources();
-  auto&                                               scene           = mModelLoadTask->GetScene();
-  auto&                                               resourceChoices = mModelLoadTask->GetResourceChoices();
-  Dali::Scene3D::Loader::Transforms                   xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
-  Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, {}, {}, {}};
+  BoundingVolume                    AABB;
+  auto&                             resources       = mModelLoadTask->GetResources();
+  auto&                             scene           = mModelLoadTask->GetScene();
+  auto&                             resourceChoices = mModelLoadTask->GetResourceChoices();
+  Dali::Scene3D::Loader::Transforms xforms{Dali::Scene3D::Loader::MatrixStack{}, Dali::Scene3D::Loader::ViewProjection{}};
+
+  Dali::Scene3D::Loader::NodeDefinition::CreateParams nodeParams{resources, xforms, mShaderManager, {}, {}, {}};
 
   // Generate Dali handles from resource bundle. Note that we generate all scene's resouce immediatly.
   resources.GenerateResources();
index f383aff..23337a4 100644 (file)
@@ -281,16 +281,6 @@ public: // Overrides LightObserver Methods.
    */
   void NotifyImageBasedLightScaleFactor(float scaleFactor) override;
 
-  /**
-   * @copydoc Dali::Scene3D::Internal::LightObserver::NotifyLightAdded()
-   */
-  void NotifyLightAdded(uint32_t lightIndex, Scene3D::Light light) override;
-
-  /**
-   * @copydoc Dali::Scene3D::Internal::LightObserver::NotifyLightRemoved()
-   */
-  void NotifyLightRemoved(uint32_t lightIndex) override;
-
 private:
   /**
    * @brief Asynchronously model loading finished.
@@ -361,8 +351,7 @@ private:
   WeakHandle<Scene3D::SceneView> mParentSceneView;
   Dali::PropertyNotification     mSizeNotification;
 
-  // Light
-  std::vector<Scene3D::Light> mLights;
+  Dali::Scene3D::Loader::ShaderManagerPtr mShaderManager;
 
   // List of ModelNode for name of blend shape.
   BlendShapeModelNodeMap mBlendShapeModelNodeMap;
index 5746b93..b4bd19d 100644 (file)
@@ -41,6 +41,8 @@
 #include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
 #include <dali-scene3d/internal/light/light-impl.h>
 
+#include <dali/integration-api/debug.h>
+
 using namespace Dali;
 
 namespace Dali
@@ -62,7 +64,7 @@ DALI_TYPE_REGISTRATION_END()
 
 Property::Index   RENDERING_BUFFER    = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1;
 constexpr int32_t DEFAULT_ORIENTATION = 0;
-constexpr int32_t INVALID_INDEX = -1;
+constexpr int32_t INVALID_INDEX       = -1;
 
 static constexpr std::string_view SKYBOX_INTENSITY_STRING = "uIntensity";
 
@@ -153,7 +155,8 @@ SceneView::SceneView()
   mWindowOrientation(DEFAULT_ORIENTATION),
   mSkybox(),
   mSkyboxOrientation(Quaternion()),
-  mSkyboxIntensity(1.0f)
+  mSkyboxIntensity(1.0f),
+  mShaderManager(new Scene3D::Loader::ShaderManager())
 {
 }
 
@@ -280,18 +283,6 @@ void SceneView::RegisterSceneItem(Scene3D::Internal::LightObserver* item)
   if(item)
   {
     item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
-
-    if(mActivatedLightCount > 0)
-    {
-      uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-      for(uint32_t i = 0; i < maxLightCount; ++i)
-      {
-        if(mActivatedLights[i])
-        {
-          item->NotifyLightAdded(i, mActivatedLights[i]);
-        }
-      }
-    }
     mItems.push_back(item);
   }
 }
@@ -304,17 +295,6 @@ void SceneView::UnregisterSceneItem(Scene3D::Internal::LightObserver* item)
     {
       if(mItems[i] == item)
       {
-        if(mActivatedLightCount > 0)
-        {
-          uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-          for(uint32_t i = 0; i < maxLightCount; ++i)
-          {
-            if(mActivatedLights[i])
-            {
-              item->NotifyLightRemoved(i);
-            }
-          }
-        }
         mItems.erase(mItems.begin() + i);
         break;
       }
@@ -439,60 +419,40 @@ float SceneView::GetImageBasedLightScaleFactor() const
 
 void SceneView::AddLight(Scene3D::Light light)
 {
-  bool enabled = AddLightInternal(light);
+  bool enabled = mShaderManager->AddLight(light);
   mLights.push_back(std::make_pair(light, enabled));
 }
 
 void SceneView::RemoveLight(Scene3D::Light light)
 {
-  if(mActivatedLights.empty())
-  {
-    return;
-  }
-
-  bool needToDisable = false;
+  mShaderManager->RemoveLight(light);
   for(uint32_t i = 0; i < mLights.size(); ++i)
   {
     if(mLights[i].first == light)
     {
-      // If mLights[i].second is true, it means the light is currently activated in Scene.
-      // Then it should be removed from mActivatedLights list too.
-      needToDisable = mLights[i].second;
       mLights.erase(mLights.begin() + i);
       break;
     }
   }
 
-  uint32_t maxNumberOfLight = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  if(needToDisable)
+  if(mLights.size() > mShaderManager->GetLightCount())
   {
-    uint32_t removedIndex = RemoveLightInternal(light);
-    if(mActivatedLightCount < maxNumberOfLight && mLights.size() >= maxNumberOfLight)
+    for(auto && waitingLight : mLights)
     {
-      for(auto && lightItem : mLights)
+      if(waitingLight.second)
       {
-        if(lightItem.second == false)
-        {
-          lightItem.second = AddLightInternal(lightItem.first);
-          break;
-        }
+        continue;
       }
-    }
 
-    // To remove empty entity of mActivatedLights, moves last object to empty position.
-    // Because one Light is removed, mActivatedLights[mActivatedLightCount] is current last object of the list.
-    if(!mActivatedLights[removedIndex] && mActivatedLightCount > 0 && removedIndex < mActivatedLightCount)
-    {
-      Scene3D::Light reorderingLight = mActivatedLights[mActivatedLightCount];
-      RemoveLightInternal(reorderingLight);
-      AddLightInternal(reorderingLight);
+      waitingLight.second = mShaderManager->AddLight(waitingLight.first);
+      break;
     }
   }
 }
 
 uint32_t SceneView::GetActivatedLightCount() const
 {
-  return mActivatedLightCount;
+  return mShaderManager->GetLightCount();
 }
 
 void SceneView::UseFramebuffer(bool useFramebuffer)
@@ -585,6 +545,11 @@ Quaternion SceneView::GetSkyboxOrientation() const
   return mSkyboxOrientation;
 }
 
+Dali::Scene3D::Loader::ShaderManagerPtr SceneView::GetShaderManager() const
+{
+  return mShaderManager;
+}
+
 ///////////////////////////////////////////////////////////
 //
 // Private methods
@@ -838,9 +803,9 @@ void SceneView::UpdateSkybox(const std::string& skyboxUrl, Scene3D::EnvironmentM
 
     if(mSkybox)
     {
-        mSkybox.Unparent();
-        mSkybox.Reset();
-        mSkyboxTexture.Reset();
+      mSkybox.Unparent();
+      mSkybox.Reset();
+      mSkyboxTexture.Reset();
     }
 
     mSkyboxDirty         = false;
@@ -953,66 +918,6 @@ void SceneView::NotifyImageBasedLightTextureChange()
   }
 }
 
-bool SceneView::AddLightInternal(Scene3D::Light light)
-{
-  uint32_t maxNumberOfLight = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  if(mActivatedLightCount == 0)
-  {
-    mActivatedLights.resize(maxNumberOfLight);
-  }
-
-  bool enabled = false;
-  if(mActivatedLightCount < maxNumberOfLight)
-  {
-    uint32_t newLightIndex = 0u;
-    for(; newLightIndex < maxNumberOfLight; ++newLightIndex)
-    {
-      if(!mActivatedLights[newLightIndex])
-      {
-        mActivatedLights[newLightIndex] = light;
-        break;
-      }
-    }
-
-    for(auto&& item : mItems)
-    {
-      if(item)
-      {
-        item->NotifyLightAdded(newLightIndex, light);
-      }
-    }
-
-    mActivatedLightCount++;
-    enabled = true;
-  }
-  return enabled;
-}
-
-int32_t SceneView::RemoveLightInternal(Scene3D::Light light)
-{
-  int32_t removedIndex = INVALID_INDEX;
-  uint32_t maxNumberOfLight = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxNumberOfLight; ++i)
-  {
-    if(mActivatedLights[i] == light)
-    {
-      for(auto&& item : mItems)
-      {
-        if(item)
-        {
-          item->NotifyLightRemoved(i);
-        }
-      }
-      mActivatedLights[i].Reset();
-      mActivatedLightCount--;
-      removedIndex = i;
-      break;
-    }
-  }
-
-  return removedIndex;
-}
-
 } // namespace Internal
 } // namespace Scene3D
 } // namespace Dali
index cf117f9..3f6eca7 100644 (file)
@@ -35,6 +35,7 @@
 #include <dali-scene3d/internal/common/environment-map-load-task.h>
 #include <dali-scene3d/internal/common/light-observer.h>
 #include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
+#include <dali-scene3d/public-api/loader/shader-manager.h>
 
 namespace Dali
 {
@@ -203,6 +204,12 @@ public:
    */
   Quaternion GetSkyboxOrientation() const;
 
+  /**
+   * @brief Retrieves ShaderManager of this SceneView.
+   * @return ShaderManager of this SceneView.
+   */
+  Dali::Scene3D::Loader::ShaderManagerPtr GetShaderManager() const;
+
 protected:
   /**
    * @brief Constructs a new SceneView.
@@ -315,22 +322,6 @@ private:
    */
   void NotifyImageBasedLightTextureChange();
 
-  /**
-   * @brief Internal method to add an Light object to this SceneView.
-   *
-   * @param[in] light Light object to be added.
-   * @return True if successed to enable.
-   */
-  bool AddLightInternal(Scene3D::Light light);
-
-  /**
-   * @brief Internal method to remove an Light object to this SceneView.
-   *
-   * @param[in] light Light object to be added.
-   * @return Index of removed light in enabled light list. If failed to remove it returns negative value;
-   */
-  int32_t RemoveLightInternal(Scene3D::Light light);
-
 private:
   Toolkit::Visual::Base mVisual;
 
@@ -352,10 +343,11 @@ private:
   float                                          mSkyboxIntensity{1.0f};
   uint8_t                                        mFrameBufferMultiSamplingLevel{0u};
 
+  // Shader Factory
+  Dali::Scene3D::Loader::ShaderManagerPtr mShaderManager;
+
   // Light
   std::vector<std::pair<Scene3D::Light, bool>> mLights; // Pair of Light object and flag that denotes the light is currently activated or not.
-  std::vector<Scene3D::Light>                  mActivatedLights;
-  uint32_t                                     mActivatedLightCount{0u};
 
   // Asynchronous Loading.
   EnvironmentMapLoadTaskPtr mSkyboxLoadTask;
@@ -378,8 +370,6 @@ private:
   bool                        mSkyboxDirty{false};
   bool                        mIblDiffuseDirty{false};
   bool                        mIblSpecularDirty{false};
-
-  // TODO : Light Source
 };
 
 } // namespace Internal
index 9a436f5..de7b28d 100644 (file)
@@ -117,7 +117,7 @@ void main()
   lowp float metallic = uMetallicFactor;
   lowp float perceptualRoughness = uRoughnessFactor;
   // If there isn't normal texture, use surface normal
-  mediump vec3 n = normalize(vTBN[2].xyz);
+  highp vec3 n = normalize(vTBN[2].xyz);
 
 #ifdef THREE_TEX
   // The albedo may be defined from a base texture or a flat color
@@ -222,8 +222,8 @@ void main()
 
     for(int i = 0; i < uLightCount; ++i)
     {
-      mediump vec3 l = normalize(-uLightDirection[i]);               // Vector from surface point to light
-      mediump vec3 h = normalize(l+v);                              // Half vector between both l and v
+      highp vec3 l = normalize(-uLightDirection[i]); // Vector from surface point to light
+      mediump vec3 h = normalize(l+v);               // Half vector between both l and v
       mediump float VdotH = dot(v, h);
       lowp vec3 specularReflection = f0 + (reflectance90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0);
 
@@ -231,8 +231,8 @@ void main()
       lowp float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
       lowp float geometricOcclusion = attenuationL * attenuationV;
 
-      mediump float NdotH = dot(n, h);
-      lowp float f = (NdotH * roughnessSq - NdotH) * NdotH + 1.0;
+      highp float NdotH = dot(n, h);
+      highp float f = (NdotH * roughnessSq - NdotH) * NdotH + 1.0;
       lowp float microfacetDistribution = roughnessSq / (M_PI * f * f);;
 
       // Calculation of analytical lighting contribution
index 90deac9..5e6942f 100644 (file)
@@ -594,6 +594,8 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
 
   MaterialDefinition materialDefinition;
 
+  materialDefinition.mFlags |= MaterialDefinition::GLTF_CHANNELS;
+
   auto& pbr = material.mPbrMetallicRoughness;
   if(material.mAlphaMode == gltf2::AlphaMode::BLEND)
   {
@@ -625,7 +627,7 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map<s
 
   if(pbr.mMetallicRoughnessTexture)
   {
-    AddTextureStage(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS | MaterialDefinition::GLTF_CHANNELS,
+    AddTextureStage(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS,
                     materialDefinition,
                     pbr.mMetallicRoughnessTexture,
                     getTextureMetaData(imageMetaData, pbr.mMetallicRoughnessTexture),
@@ -890,8 +892,6 @@ ModelRenderable* MakeModelRenderable(const gltf2::Mesh::Primitive& primitive, Co
 {
   auto modelRenderable = new ModelRenderable();
 
-  modelRenderable->mShaderIdx = 0; // TODO: further thought
-
   auto materialIdx = primitive.mMaterial.GetIndex();
   if(INVALID_INDEX == materialIdx)
   {
@@ -1353,22 +1353,6 @@ void ProcessSkins(const gltf2::Document& document, ConversionContext& context)
   }
 }
 
-void ProduceShaders(ShaderDefinitionFactory& shaderFactory, Dali::Scene3D::Loader::SceneDefinition& scene)
-{
-  uint32_t nodeCount = scene.GetNodeCount();
-  for(uint32_t i = 0; i < nodeCount; ++i)
-  {
-    auto nodeDefinition = scene.GetNode(i);
-    for(auto& renderable : nodeDefinition->mRenderables)
-    {
-      if(shaderFactory.ProduceShader(*renderable) == INVALID_INDEX)
-      {
-        DALI_LOG_ERROR("Fail to produce shader\n");
-      }
-    }
-  }
-}
-
 void SetObjectReaders()
 {
   json::SetObjectReader(GetBufferReader());
@@ -1470,17 +1454,12 @@ bool GenerateDocument(json::unique_ptr& root, gt::Document& document, bool& isMR
 
 void ConvertGltfToContext(gt::Document& document, Gltf2Util::ConversionContext& context, bool isMRendererModel)
 {
-  Dali::Scene3D::Loader::ShaderDefinitionFactory shaderFactory;
-  shaderFactory.SetResources(context.mOutput.mResources);
-
   Gltf2Util::ConvertBuffers(document, context);
   Gltf2Util::ConvertMaterials(document, context);
   Gltf2Util::ConvertMeshes(document, context);
   Gltf2Util::ConvertNodes(document, context, isMRendererModel);
   Gltf2Util::ConvertAnimations(document, context);
   Gltf2Util::ProcessSkins(document, context);
-  Gltf2Util::ProduceShaders(shaderFactory, context.mOutput.mScene);
-  context.mOutput.mScene.EnsureUniqueSkinningShaderInstances(context.mOutput.mResources);
 
   // Set Default Environment map
   Gltf2Util::SetDefaultEnvironmentMap(document, context);
index 457140e..d12addd 100644 (file)
@@ -25,7 +25,6 @@
 #include <dali-scene3d/public-api/loader/load-result.h>
 #include <dali-scene3d/public-api/loader/resource-bundle.h>
 #include <dali-scene3d/public-api/loader/scene-definition.h>
-#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
 
 namespace gt = gltf2;
 namespace js = json;
@@ -48,8 +47,8 @@ struct NodeMapping
 class NodeIndexMapper
 {
 public:
-  NodeIndexMapper()                       = default;
-  NodeIndexMapper(const NodeIndexMapper&) = delete;
+  NodeIndexMapper()                                  = default;
+  NodeIndexMapper(const NodeIndexMapper&)            = delete;
   NodeIndexMapper& operator=(const NodeIndexMapper&) = delete;
 
   ///@brief Registers a mapping of the @a gltfIndex of a node to its @a runtimeIndex .
@@ -101,8 +100,6 @@ void ConvertAnimations(const gt::Document& document, ConversionContext& context)
 
 void ProcessSkins(const gt::Document& document, ConversionContext& context);
 
-void ProduceShaders(ShaderDefinitionFactory& shaderFactory, SceneDefinition& scene);
-
 void SetDefaultEnvironmentMap(const gt::Document& document, ConversionContext& context);
 
 const std::string_view GetRendererModelIdentification();
index 4ce7d57..b7c16a7 100644 (file)
@@ -30,8 +30,8 @@
 #include <dali-scene3d/internal/model-components/material-modify-observer.h>
 #include <dali-scene3d/public-api/loader/node-definition.h>
 #include <dali-scene3d/public-api/loader/renderer-state.h>
+#include <dali-scene3d/public-api/loader/shader-option.h>
 #include <dali-scene3d/public-api/loader/utils.h>
-#include <dali-scene3d/public-api/loader/shader-definition-option.h>
 
 namespace Dali
 {
@@ -101,13 +101,13 @@ Material::Material()
   mTextureInformations[SPECULAR].mSemantic       = Scene3D::Loader::MaterialDefinition::SPECULAR;
   mTextureInformations[SPECULAR_COLOR].mSemantic = Scene3D::Loader::MaterialDefinition::SPECULAR_COLOR;
 
-  mTextureInformations[BASE_COLOR].mDefineKeyword         = Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Loader::ShaderDefinitionOption::Type::BASE_COLOR_TEXTURE).data();
-  mTextureInformations[METALLIC_ROUGHNESS].mDefineKeyword = Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Loader::ShaderDefinitionOption::Type::METALLIC_ROUGHNESS_TEXTURE).data();
-  mTextureInformations[NORMAL].mDefineKeyword             = Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Loader::ShaderDefinitionOption::Type::NORMAL_TEXTURE).data();
-  mTextureInformations[OCCLUSION].mDefineKeyword          = Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Loader::ShaderDefinitionOption::Type::OCCLUSION).data();
-  mTextureInformations[EMISSIVE].mDefineKeyword           = Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Loader::ShaderDefinitionOption::Type::EMISSIVE).data();
-  mTextureInformations[SPECULAR].mDefineKeyword           = Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Loader::ShaderDefinitionOption::Type::SPECULAR).data();
-  mTextureInformations[SPECULAR_COLOR].mDefineKeyword     = Scene3D::Loader::ShaderDefinitionOption::GetDefineKeyword(Loader::ShaderDefinitionOption::Type::SPECULAR_COLOR).data();
+  mTextureInformations[BASE_COLOR].mShaderOptionType         = Loader::ShaderOption::Type::BASE_COLOR_TEXTURE;
+  mTextureInformations[METALLIC_ROUGHNESS].mShaderOptionType = Loader::ShaderOption::Type::METALLIC_ROUGHNESS_TEXTURE;
+  mTextureInformations[NORMAL].mShaderOptionType             = Loader::ShaderOption::Type::NORMAL_TEXTURE;
+  mTextureInformations[OCCLUSION].mShaderOptionType          = Loader::ShaderOption::Type::OCCLUSION;
+  mTextureInformations[EMISSIVE].mShaderOptionType           = Loader::ShaderOption::Type::EMISSIVE;
+  mTextureInformations[SPECULAR].mShaderOptionType           = Loader::ShaderOption::Type::SPECULAR;
+  mTextureInformations[SPECULAR_COLOR].mShaderOptionType     = Loader::ShaderOption::Type::SPECULAR_COLOR;
 
   mTextureInformations[TextureIndex::EMISSIVE].mFactor = Vector4::ZERO;
 }
@@ -517,14 +517,9 @@ Dali::Sampler Material::GetSampler(Scene3D::Material::TextureType index)
   return Dali::Sampler();
 }
 
-std::string Material::GetVertexShader()
+Scene3D::Loader::ShaderOption Material::GetShaderOption() const
 {
-  return mShaderData.mVertexShaderSource;
-}
-
-std::string Material::GetFragmentShader()
-{
-  return mShaderData.mFragmentShaderSource;
+  return mShaderOption;
 }
 
 void Material::Apply()
@@ -614,34 +609,31 @@ void Material::UpdateMaterialData()
     materialFlag |= textureInformation.mSemantic;
   }
 
-  if(mMaterialFlag != materialFlag || mShaderData.mVertexShaderSource.empty() || mShaderData.mFragmentShaderSource.empty())
+  if(mMaterialFlag != materialFlag)
   {
     mModifyFlag |= MaterialModifyObserver::ModifyFlag::SHADER;
 
-    mMaterialFlag                     = materialFlag;
-    mShaderData.mVertexShaderSource   = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_VERT.data();
-    mShaderData.mFragmentShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
+    mMaterialFlag = materialFlag;
 
-    std::vector<std::string> defines;
-    defines.push_back(THREE_TEX_KEYWORD.data());
+    mShaderOption = Loader::ShaderOption();
     for(auto&& textureInformation : mTextureInformations)
     {
       if(!textureInformation.mTexture)
       {
         continue;
       }
-      defines.push_back(textureInformation.mDefineKeyword);
+      mShaderOption.AddOption(textureInformation.mShaderOptionType);
     }
-    defines.push_back(GLTF_CHANNELS_KEYWORD.data());
-
-    for(const auto& define : defines)
+    mShaderOption.AddOption(Loader::ShaderOption::Type::THREE_TEXTURE);
+    mShaderOption.AddOption(Loader::ShaderOption::Type::GLTF_CHANNELS);
+    if(materialFlag & Scene3D::Loader::MaterialDefinition::TRANSPARENCY)
     {
-      Scene3D::Loader::ShaderDefinition::ApplyDefine(mShaderData.mFragmentShaderSource, define);
+      mShaderOption.SetTransparency();
     }
   }
 
   // Finish to make all the material flag according to the gltf2-util.
-  // Then make defines as fallowing shader-definition-factory.
+  // Then make defines as fallowing shader-manager.
 
   // The renderer State below can be used in primitive to set renderer properties.
 
@@ -698,21 +690,6 @@ void Material::SetRendererUniform(Dali::Renderer renderer)
   renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), 1.0f);
   renderer.RegisterProperty(Scene3D::Loader::NodeDefinition::GetIblYDirectionUniformName().data(), Vector3(1.0f, -1.0, 1.0));
 
-  std::string lightCountPropertyName(Scene3D::Internal::Light::GetLightCountUniformName());
-  renderer.RegisterProperty(lightCountPropertyName, 0);
-
-  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxLightCount; ++i)
-  {
-    std::string lightDirectionPropertyName(Scene3D::Internal::Light::GetLightDirectionUniformName());
-    lightDirectionPropertyName += "[" + std::to_string(i) + "]";
-    renderer.RegisterProperty(lightDirectionPropertyName, Vector3::ZAXIS);
-
-    std::string lightColorPropertyName(Scene3D::Internal::Light::GetLightColorUniformName());
-    lightColorPropertyName += "[" + std::to_string(i) + "]";
-    renderer.RegisterProperty(lightColorPropertyName, Vector3(Color::WHITE));
-  }
-
   Scene3D::Loader::RendererState::Apply(mRendererState, renderer);
 }
 
@@ -769,7 +746,9 @@ void Material::NotifyObserver()
     mObserverNotifying = false;
 
     // Resolve observer queue during notify
-    mObservers.erase(std::remove_if(mObservers.begin(), mObservers.end(), [](auto& e) { return !e.second; }), mObservers.end());
+    mObservers.erase(std::remove_if(mObservers.begin(), mObservers.end(), [](auto& e)
+                                    { return !e.second; }),
+                     mObservers.end());
   }
 }
 
index 563bf82..3b0c985 100644 (file)
@@ -34,6 +34,7 @@
 #include <dali-scene3d/internal/model-components/material-modify-observer.h>
 #include <dali-scene3d/public-api/loader/material-definition.h>
 #include <dali-scene3d/public-api/loader/shader-definition.h>
+#include <dali-scene3d/public-api/loader/shader-option.h>
 #include <dali-scene3d/public-api/model-components/material.h>
 
 namespace Dali
@@ -65,13 +66,13 @@ public:
       return mLoadingTaskId == 0u;
     }
 
-    std::string   mUrl;
-    Dali::Texture mTexture;
-    Vector4       mFactor{Vector4::ONE};
-    Dali::Sampler mSampler;
-    uint32_t      mLoadingTaskId{0u};
-    uint32_t      mSemantic;
-    std::string   mDefineKeyword;
+    std::string                         mUrl;
+    Dali::Texture                       mTexture;
+    Vector4                             mFactor{Vector4::ONE};
+    Dali::Sampler                       mSampler;
+    uint32_t                            mLoadingTaskId{0u};
+    uint32_t                            mSemantic;
+    Scene3D::Loader::ShaderOption::Type mShaderOptionType;
   };
 
   using TextureInformationContainer = std::vector<TextureInformation>;
@@ -112,7 +113,7 @@ public:
   Dali::Property::Value GetProperty(Dali::Property::Index index) const;
 
   /**
-   * @brief Set a texture information for the material.
+   * @brief Sets a texture information for the material.
    *
    * @param[in] index The index of the texture to set.
    * @param[in] textureInformation The texture information to set.
@@ -122,7 +123,7 @@ public:
   void SetTextureInformation(Scene3D::Material::TextureType index, TextureInformation&& textureInformation);
 
   /**
-   * @brief Set a texture for the material.
+   * @brief Sets a texture for the material.
    *
    * @param[in] index The index of the texture to set.
    * @param[in] texture The texture to set.
@@ -130,7 +131,7 @@ public:
   void SetTexture(Scene3D::Material::TextureType index, Dali::Texture texture);
 
   /**
-   * @brief Get texture for the material.
+   * @brief Retrieves texture for the material.
    *
    * @param[in] index The index of the texture to get.
    *
@@ -139,14 +140,14 @@ public:
   Dali::Texture GetTexture(Scene3D::Material::TextureType index);
 
   /**
-   * @brief Get the texture set for this material.
+   * @brief Retrieves the texture set for this material.
    *
    * @return The texture set for this material.
    */
   TextureSet GetTextureSet();
 
   /**
-   * @brief Set a sampler for the material.
+   * @brief Sets a sampler for the material.
    *
    * @param[in] index The index of the sampler to set.
    * @param[in] sampler The sampler to set.
@@ -154,104 +155,96 @@ public:
   void SetSampler(Scene3D::Material::TextureType index, Dali::Sampler sampler);
 
   /**
-   * @brief Get a sampler for the material.
-
-   * @param[in] index The index of the sampler to get.
+   * @brief Retrieves a sampler for the material.
    *
+   * @param[in] index The index of the sampler to get.
    * @return The sampler at the given index.
    */
   Dali::Sampler GetSampler(Scene3D::Material::TextureType index);
 
   /**
-   * @brief Get vertex shader code for this material.
-   *
-   * @return Vertex shader code for this material.
-   */
-  std::string GetVertexShader();
-
-  /**
-   * @brief Get fragment shader code for this material.
+   * @brief Retrieves Shader Option of this Material.
    *
-   * @return Fragment shader code for this material.
+   * @return Shader Option of this Material.
    */
-  std::string GetFragmentShader();
+  Scene3D::Loader::ShaderOption GetShaderOption() const;
 
 public:
   /**
-   * @brief Add observer to this material.
+   * @brief Adds observer to this material.
    *
    * @param[in] observer Pointer of observer.
    */
   void AddObserver(MaterialModifyObserver* observer);
 
   /**
-   * @brief Remove observer from this material.
+   * @brief Removes observer from this material.
    *
    * @param[in] observer Pointer of observer.
    */
   void RemoveObserver(MaterialModifyObserver* observer);
 
   /**
-   * @brief Update material data.
+   * @brief Updates material data.
    */
   void UpdateMaterialData();
 
   /**
-   * @brief Set uniform value to the Renderer.
+   * @brief Sets uniform value to the Renderer.
    *
    * @param[in] renderer Renderer object.
    */
   void SetRendererUniform(Dali::Renderer renderer);
 
   /**
-   * @brief Get specular image based light texture offset.
+   * @brief Retrieves specular image based light texture offset.
    *
    * @return Specular image based light texture offset.
    */
   uint32_t GetSpecularImageBasedLightTextureOffset();
 
   /**
-   * @brief Get diffuse image based light texture offset.
+   * @brief Retrieves diffuse image based light texture offset.
    *
    * @return Diffuse image based light texture offset.
    */
   uint32_t GetDiffuseImageBasedLightTextureOffset();
 
   /**
-   * @brief Get image based light scale factor name.
+   * @brief Retrieves image based light scale factor name.
    *
    * @return Image based light scale factor name.
    */
   std::string_view GetImageBasedLightScaleFactorName();
 
   /**
-   * @brief Get image based light max lod uniform name.
+   * @brief Retrieves image based light max lod uniform name.
    *
    * @return Image based light max lod uniform name.
    */
   std::string_view GetImageBasedLightMaxLodUniformName();
 
   /**
-   * @brief Check if resource is ready.
+   * @brief Checks if resource is ready.
    *
    * @return True if resource is ready, false otherwise.
    */
   bool IsResourceReady();
 
   /**
-   * @brief Reset dirty flag of this material.
+   * @brief Resets dirty flag of this material.
    */
   void ResetFlag();
 
 private:
   /**
-   * @brief Check modify flag and send observers the material changeness.
+   * @brief Checks modify flag and send observers the material changeness.
    * It will clean up modify flag
    */
   void NotifyObserver();
 
   /**
-   * @brief Request loading an image from a URL and store it in TextureInformation.
+   * @brief Requests loading an image from a URL and store it in TextureInformation.
    *
    * @param[in] textureInformation TextureInformation object to store loaded texture information.
    * @param[in] url URL of the image to load.
@@ -272,16 +265,16 @@ private:
   void ResourcesLoadComplete();
 
   /**
-   * @brief Update the material using each attribute of this material and send a notification to the ModelPrimitive class.
+   * @brief Updates the material using each attribute of this material and send a notification to the ModelPrimitive class.
    */
   void Apply();
 
 private:
   // Delete copy & move operator
-  Material(const Material&) = delete;
-  Material(Material&&)      = delete;
+  Material(const Material&)                = delete;
+  Material(Material&&)                     = delete;
   Material& operator=(const Material& rhs) = delete;
-  Material& operator=(Material&& rhs) = delete;
+  Material& operator=(Material&& rhs)      = delete;
 
 private:
   ObserverContainer mObservers{}; ///< List of observers who need to be notified after some properties are changed.
@@ -296,9 +289,8 @@ private:
   float                                  mIor         = -1.0f;                                    ///< Index of refraction (TODO: Magic number)
   MaterialModifyObserver::ModifyFlag     mModifyFlag  = MaterialModifyObserver::ModifyFlag::NONE; ///< Modified dirty flags
 
-  Scene3D::Loader::ShaderDefinition::RawData mShaderData;
-
-  uint32_t                             mMaterialFlag  = 0u;
+  Scene3D::Loader::ShaderOption        mShaderOption;
+  uint32_t                             mMaterialFlag  = std::numeric_limits<uint32_t>::max();
   Scene3D::Loader::RendererState::Type mRendererState = Scene3D::Loader::RendererState::NONE;
 
   bool mIsOpaque = true;
index a37d4a8..9d8d4b6 100644 (file)
@@ -75,7 +75,6 @@ ModelNode::~ModelNode()
 void ModelNode::Initialize()
 {
   OnInitialize();
-  mLights.resize(Scene3D::Internal::Light::GetMaximumEnabledLightCount());
 }
 
 void ModelNode::OnInitialize()
@@ -193,14 +192,7 @@ void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
     GetImplementation(modelPrimitive).SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
   }
 
-  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxLightCount; ++i)
-  {
-    if(mLights[i])
-    {
-      GetImplementation(modelPrimitive).AddLight(mLights[i], i);
-    }
-  }
+  GetImplementation(modelPrimitive).UpdateShader(mShaderManager);
 
   Dali::Renderer renderer = GetImplementation(modelPrimitive).GetRenderer();
   if(renderer)
@@ -244,14 +236,7 @@ void ModelNode::RemoveModelPrimitive(uint32_t index)
     return;
   }
 
-  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxLightCount; ++i)
-  {
-    if(mLights[i])
-    {
-      GetImplementation(mModelPrimitiveContainer[index]).RemoveLight(i);
-    }
-  }
+  GetImplementation(mModelPrimitiveContainer[index]).UpdateShader(nullptr);
 
   Actor self = Self();
   GetImplementation(mModelPrimitiveContainer[index]).RemovePrimitiveObserver(this);
@@ -320,22 +305,16 @@ void ModelNode::SetImageBasedLightScaleFactor(float iblScaleFactor)
   }
 }
 
-void ModelNode::AddLight(Scene3D::Light light, uint32_t lightIndex)
+void ModelNode::UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager)
 {
-  mLights[lightIndex] = light;
-  for(auto&& primitive : mModelPrimitiveContainer)
+  if(mShaderManager != shaderManager)
   {
-    GetImplementation(primitive).AddLight(light, lightIndex);
-  }
-}
-
-void ModelNode::RemoveLight(uint32_t lightIndex)
-{
-  for(auto&& primitive : mModelPrimitiveContainer)
-  {
-    GetImplementation(primitive).RemoveLight(lightIndex);
+    mShaderManager = shaderManager;
+    for(auto&& primitive : mModelPrimitiveContainer)
+    {
+      GetImplementation(primitive).UpdateShader(mShaderManager);
+    }
   }
-  mLights[lightIndex].Reset();
 }
 
 void ModelNode::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data, Scene3D::ModelPrimitive primitive)
index 8a06116..2cc4f1a 100644 (file)
@@ -29,6 +29,7 @@
 #include <dali-scene3d/internal/model-components/model-primitive-modify-observer.h>
 #include <dali-scene3d/public-api/light/light.h>
 #include <dali-scene3d/public-api/loader/mesh-definition.h>
+#include <dali-scene3d/public-api/loader/shader-manager.h>
 #include <dali-scene3d/public-api/loader/skinning-details.h>
 #include <dali-scene3d/public-api/model-components/model-node.h>
 #include <dali-scene3d/public-api/model-components/model-primitive.h>
@@ -246,8 +247,12 @@ public: // Public Method
    */
   void SetImageBasedLightScaleFactor(float iblScaleFactor);
 
-  void AddLight(Scene3D::Light light, uint32_t lightIndex);
-  void RemoveLight(uint32_t lightIndex);
+  /**
+   * @brief Updates shaders by using current material
+   *
+   * @param[in] shaderManager Shader manager to create shader.
+   */
+  void UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager);
 
   /**
    * @brief Sets the blend shape data for a ModelPrimitive.
@@ -291,16 +296,14 @@ private:
   DALI_INTERNAL ModelNode& operator=(ModelNode&&) = delete;      ///< Deleted move assignment operator.
 
 private:
-  ModelPrimitiveContainer mModelPrimitiveContainer; ///< List of model primitives
-  BoneDataContainer       mBoneDataContainer;
-  BlendShapeIndexMap      mBlendShapeIndexMap; ///< Index of blend shape by name
-  Dali::Texture           mSpecularTexture;
-  Dali::Texture           mDiffuseTexture;
-  float                   mIblScaleFactor{1.0f};
-  uint32_t                mSpecularMipmapLevels{1u};
-
-  // Light
-  std::vector<Scene3D::Light> mLights;
+  Scene3D::Loader::ShaderManagerPtr mShaderManager;
+  ModelPrimitiveContainer           mModelPrimitiveContainer; ///< List of model primitives
+  BoneDataContainer                 mBoneDataContainer;
+  BlendShapeIndexMap                mBlendShapeIndexMap;      ///< Index of blend shape by name
+  Dali::Texture                     mSpecularTexture;
+  Dali::Texture                     mDiffuseTexture;
+  float                             mIblScaleFactor{1.0f};
+  uint32_t                          mSpecularMipmapLevels{1u};
   /// @endcond
 };
 
index df71d6d..0aea879 100644 (file)
@@ -29,6 +29,8 @@
 #include <dali-scene3d/internal/model-components/material-impl.h>
 #include <dali-scene3d/public-api/loader/environment-definition.h>
 
+#include <dali/integration-api/debug.h>
+
 namespace Dali
 {
 namespace Scene3D
@@ -49,11 +51,6 @@ BaseHandle Create()
 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelPrimitive, Dali::BaseHandle, Create);
 DALI_TYPE_REGISTRATION_END()
 
-constexpr std::string_view MORPH_POSITION_KEYWORD    = "MORPH_POSITION";
-constexpr std::string_view MORPH_NORMAL_KEYWORD      = "MORPH_NORMAL";
-constexpr std::string_view MORPH_TANGENT_KEYWORD     = "MORPH_TANGENT";
-constexpr std::string_view MORPH_VERSION_2_0_KEYWORD = "MORPH_VERSION_2_0";
-
 static constexpr uint32_t INDEX_FOR_LIGHT_CONSTRAINT_TAG = 10;
 } // unnamed namespace
 
@@ -67,6 +64,7 @@ ModelPrimitivePtr ModelPrimitive::New()
 }
 
 ModelPrimitive::ModelPrimitive()
+: mShaderManager(new Scene3D::Loader::ShaderManager())
 {
 }
 
@@ -81,7 +79,6 @@ ModelPrimitive::~ModelPrimitive()
 
 void ModelPrimitive::Initialize()
 {
-  mLights.resize(Scene3D::Internal::Light::GetMaximumEnabledLightCount());
 }
 
 void ModelPrimitive::SetRenderer(Dali::Renderer renderer)
@@ -179,52 +176,18 @@ void ModelPrimitive::SetImageBasedLightScaleFactor(float iblScaleFactor)
   }
 }
 
-void ModelPrimitive::AddLight(Scene3D::Light light, uint32_t lightIndex)
+void ModelPrimitive::UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager)
 {
-  if(mLights[lightIndex])
-  {
-    RemoveLight(lightIndex);
-  }
-
-  mLights[lightIndex] = light;
-  // TODO  Remove light at lightIndex if it is already set.
-  if(mRenderer && mMaterial)
+  if(mShaderManager != shaderManager)
   {
-    mLightCount++;
-    std::string lightCountPropertyName(Scene3D::Internal::Light::GetLightCountUniformName());
-    mRenderer.RegisterProperty(lightCountPropertyName, mLightCount);
-
-    std::string lightDirectionPropertyName(Scene3D::Internal::Light::GetLightDirectionUniformName());
-    lightDirectionPropertyName += "[" + std::to_string(lightIndex) + "]";
-    auto             lightDirectionPropertyIndex = mRenderer.RegisterProperty(lightDirectionPropertyName, Vector3::ZAXIS);
-    Dali::Constraint lightDirectionConstraint    = Dali::Constraint::New<Vector3>(mRenderer, lightDirectionPropertyIndex, [](Vector3& output, const PropertyInputContainer& inputs)
-                                                                               { output = inputs[0]->GetQuaternion().Rotate(Vector3::ZAXIS); });
-    lightDirectionConstraint.AddSource(Source{light, Dali::Actor::Property::WORLD_ORIENTATION});
-    lightDirectionConstraint.ApplyPost();
-    lightDirectionConstraint.SetTag(INDEX_FOR_LIGHT_CONSTRAINT_TAG + lightIndex);
-
-    std::string lightColorPropertyName(Scene3D::Internal::Light::GetLightColorUniformName());
-    lightColorPropertyName += "[" + std::to_string(lightIndex) + "]";
-    auto             lightColorPropertyIndex = mRenderer.RegisterProperty(lightColorPropertyName, Vector3(Color::WHITE));
-    Dali::Constraint lightColorConstraint    = Dali::Constraint::New<Vector3>(mRenderer, lightColorPropertyIndex, [](Vector3& output, const PropertyInputContainer& inputs)
-                                                                           { output = Vector3(inputs[0]->GetVector4()); });
-    lightColorConstraint.AddSource(Source{light, Dali::Actor::Property::COLOR});
-    lightColorConstraint.ApplyPost();
-    lightColorConstraint.SetTag(INDEX_FOR_LIGHT_CONSTRAINT_TAG + lightIndex);
+    mShaderManager = (shaderManager) ? shaderManager : new Scene3D::Loader::ShaderManager();
+    if(mMaterial && GetImplementation(mMaterial).IsResourceReady())
+    {
+      ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag::SHADER);
+    }
   }
 }
 
-void ModelPrimitive::RemoveLight(uint32_t lightIndex)
-{
-  mLightCount--;
-  std::string lightCountPropertyName(Scene3D::Internal::Light::GetLightCountUniformName());
-  mRenderer.RegisterProperty(lightCountPropertyName, mLightCount);
-
-  mRenderer.RemoveConstraints(INDEX_FOR_LIGHT_CONSTRAINT_TAG + lightIndex);
-
-  mLights[lightIndex].Reset();
-}
-
 void ModelPrimitive::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data)
 {
   mBlendShapeData = std::move(data);
@@ -236,11 +199,12 @@ void ModelPrimitive::SetBlendShapeGeometry(Dali::Texture blendShapeGeometry)
   mBlendShapeGeometry = blendShapeGeometry;
 }
 
-void ModelPrimitive::SetBlendShapeOptions(bool hasPositions, bool hasNormals, bool hasTangents)
+void ModelPrimitive::SetBlendShapeOptions(bool hasPositions, bool hasNormals, bool hasTangents, Scene3D::Loader::BlendShapes::Version version)
 {
-  mHasPositions = hasPositions;
-  mHasNormals   = hasNormals;
-  mHasTangents  = hasTangents;
+  mHasPositions      = hasPositions;
+  mHasNormals        = hasNormals;
+  mHasTangents       = hasTangents;
+  mBlendShapeVersion = version;
 }
 
 void ModelPrimitive::SetSkinned(bool isSkinned)
@@ -257,44 +221,43 @@ void ModelPrimitive::OnMaterialModified(Dali::Scene3D::Material material, Materi
 
 void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag)
 {
+  if(!mMaterial)
+  {
+    return;
+  }
+
   uint32_t shaderFlag = (flag & static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::SHADER));
   if(mIsMaterialChanged || shaderFlag == static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::SHADER))
   {
-    std::string vertexShader   = GetImplementation(mMaterial).GetVertexShader();
-    std::string fragmentShader = GetImplementation(mMaterial).GetFragmentShader();
+    Scene3D::Loader::ShaderOption shaderOption = GetImplementation(mMaterial).GetShaderOption();
 
-    std::vector<std::string> defines;
-    defines.push_back("VEC4_TANGENT");
+    shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::VEC4_TANGENT);
     if(mHasSkinning)
     {
-      defines.push_back("SKINNING");
+      shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::SKINNING);
     }
     if(mHasPositions || mHasNormals || mHasTangents)
     {
       if(mHasPositions)
       {
-        defines.push_back(MORPH_POSITION_KEYWORD.data());
+        shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::MORPH_POSITION);
       }
       if(mHasNormals)
       {
-        defines.push_back(MORPH_NORMAL_KEYWORD.data());
+        shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::MORPH_NORMAL);
       }
       if(mHasTangents)
       {
-        defines.push_back(MORPH_TANGENT_KEYWORD.data());
+        shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::MORPH_TANGENT);
       }
-      if(mBlendShapeData.version == Scene3D::Loader::BlendShapes::Version::VERSION_2_0)
+      if(mBlendShapeVersion == Scene3D::Loader::BlendShapes::Version::VERSION_2_0)
       {
-        defines.push_back(MORPH_VERSION_2_0_KEYWORD.data());
+        shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::MORPH_VERSION_2_0);
       }
     }
-    for(const auto& define : defines)
-    {
-      Scene3D::Loader::ShaderDefinition::ApplyDefine(vertexShader, define);
-    }
 
     mShader.Reset();
-    mShader = Shader::New(vertexShader, fragmentShader);
+    mShader = mShaderManager->ProduceShader(shaderOption);
 
     if(!mRenderer)
     {
@@ -388,15 +351,6 @@ void ModelPrimitive::CreateRenderer()
   mRenderer.SetTextures(mTextureSet);
   UpdateRendererUniform();
 
-  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxLightCount; ++i)
-  {
-    if(mLights[i])
-    {
-      AddLight(mLights[i], i);
-    }
-  }
-
   for(auto* observer : mObservers)
   {
     observer->OnRendererCreated(mRenderer);
@@ -445,9 +399,12 @@ void ModelPrimitive::UpdateImageBasedLightTexture()
 
 void ModelPrimitive::UpdateRendererUniform()
 {
-  mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightScaleFactorName().data(), mIblScaleFactor);
-  mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightMaxLodUniformName().data(), static_cast<float>(mSpecularMipmapLevels));
-  GetImplementation(mMaterial).SetRendererUniform(mRenderer);
+  if(mMaterial)
+  {
+    mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightScaleFactorName().data(), mIblScaleFactor);
+    mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightMaxLodUniformName().data(), static_cast<float>(mSpecularMipmapLevels));
+    GetImplementation(mMaterial).SetRendererUniform(mRenderer);
+  }
 }
 
 } // namespace Internal
index 027ecac..7334699 100644 (file)
@@ -32,6 +32,7 @@
 #include <dali-scene3d/public-api/light/light.h>
 #include <dali-scene3d/public-api/loader/blend-shape-details.h>
 #include <dali-scene3d/public-api/loader/mesh-definition.h>
+#include <dali-scene3d/public-api/loader/shader-manager.h>
 #include <dali-scene3d/public-api/model-components/material.h>
 #include <dali-scene3d/public-api/model-components/model-primitive.h>
 
@@ -140,19 +141,11 @@ public:
   void SetImageBasedLightScaleFactor(float iblScaleFactor);
 
   /**
-   * @brief Adds a Light on this medel primitive
+   * @brief Updates shaders by using current material
    *
-   * @param[in] light Added light.
-   * @param[in] lightIndex Index of added light.
+   * @param[in] shaderManager Shader manager to create shader.
    */
-  void AddLight(Scene3D::Light light, uint32_t lightIndex);
-
-  /**
-   * @brief Removes a light at the lightIndex of this model primitive
-   *
-   * @param[in] lightIndex Index of added light.
-   */
-  void RemoveLight(uint32_t lightIndex);
+  void UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager);
 
   /**
    * @brief Sets the blend shape data for this model primitive.
@@ -174,8 +167,9 @@ public:
    * @param[in] hasPositions Whether or not this model primitive has positions for blend shapes.
    * @param[in] hasNormals Whether or not this model primitive has normals for blend shapes.
    * @param[in] hasTangents Whether or not this model primitive has tangents for blend shapes.
+   * @param[in] version blendShape version.
    */
-  void SetBlendShapeOptions(bool hasPositions, bool hasNormals, bool hasTangents);
+  void SetBlendShapeOptions(bool hasPositions, bool hasNormals, bool hasTangents, Scene3D::Loader::BlendShapes::Version version);
 
   /**
    * @brief Sets whether or not this model primitive is skinned.
@@ -228,9 +222,7 @@ private:
   Dali::TextureSet        mTextureSet;
   Dali::Scene3D::Material mMaterial;
 
-  // Light
-  std::vector<Scene3D::Light> mLights;
-  int32_t                     mLightCount{0};
+  Scene3D::Loader::ShaderManagerPtr mShaderManager;
 
   // For IBL
   Dali::Texture mSpecularTexture;
@@ -241,10 +233,11 @@ private:
   // For blend shape
   Scene3D::Loader::BlendShapes::BlendShapeData mBlendShapeData;
   Dali::Texture                                mBlendShapeGeometry;
-  bool                                         mHasSkinning  = false;
-  bool                                         mHasPositions = false;
-  bool                                         mHasNormals   = false;
-  bool                                         mHasTangents  = false;
+  bool                                         mHasSkinning       = false;
+  bool                                         mHasPositions      = false;
+  bool                                         mHasNormals        = false;
+  bool                                         mHasTangents       = false;
+  Scene3D::Loader::BlendShapes::Version        mBlendShapeVersion = Scene3D::Loader::BlendShapes::Version::INVALID;
 
   bool mIsMaterialChanged        = false;
   bool mNeedToSetRendererUniform = false;
index 70c1f6c..0c394df 100644 (file)
@@ -32,8 +32,8 @@ set(scene3d_src_files ${scene3d_src_files}
        ${scene3d_public_api_dir}/loader/resource-bundle.cpp
        ${scene3d_public_api_dir}/loader/scene-definition.cpp
        ${scene3d_public_api_dir}/loader/shader-definition.cpp
-       ${scene3d_public_api_dir}/loader/shader-definition-factory.cpp
-       ${scene3d_public_api_dir}/loader/shader-definition-option.cpp
+       ${scene3d_public_api_dir}/loader/shader-manager.cpp
+       ${scene3d_public_api_dir}/loader/shader-option.cpp
        ${scene3d_public_api_dir}/loader/skinning-details.cpp
        ${scene3d_public_api_dir}/loader/string-callback.cpp
        ${scene3d_public_api_dir}/loader/utils.cpp
index 16d0189..f0a0eba 100644 (file)
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
+#include <dali-scene3d/internal/light/light-impl.h>
 #include <dali-scene3d/internal/model-components/material-impl.h>
+#include <dali-scene3d/internal/model-components/model-node-impl.h>
 #include <dali-scene3d/internal/model-components/model-primitive-impl.h>
 #include <dali-scene3d/public-api/loader/renderer-state.h>
 #include <dali-scene3d/public-api/loader/utils.h>
-#include <dali-scene3d/internal/light/light-impl.h>
 
 namespace Dali
 {
@@ -255,7 +256,20 @@ void ModelRenderable::ReflectResources(IResourceReflector& reflector)
 void ModelRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const
 {
   DALI_ASSERT_DEBUG(mMeshIdx != INVALID_INDEX);
-  Renderable::OnCreate(nodeDefinition, params, node);
+  if(mShaderIdx == INVALID_INDEX)
+  {
+    Shader          shader          = params.mShaderManager->ProduceShader(params.mResources.mMaterials[mMaterialIdx].first, params.mResources.mMeshes[mMeshIdx].first);
+    static Geometry defaultGeometry = Geometry::New();
+    Renderer        renderer        = Renderer::New(defaultGeometry, shader);
+
+    RendererState::Apply(params.mShaderManager->GetRendererState(params.mResources.mMaterials[mMaterialIdx].first), renderer);
+    Internal::GetImplementation(node).UpdateShader(params.mShaderManager);
+    node.AddRenderer(renderer);
+  }
+  else
+  {
+    Renderable::OnCreate(nodeDefinition, params, node);
+  }
 
   auto& resources = params.mResources;
   auto& mesh      = resources.mMeshes[mMeshIdx];
@@ -299,7 +313,7 @@ void ModelRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinit
     bool hasNormals   = false;
     bool hasTangents  = false;
     mesh.first.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
-    GetImplementation(primitive).SetBlendShapeOptions(hasPositions, hasNormals, hasTangents);
+    GetImplementation(primitive).SetBlendShapeOptions(hasPositions, hasNormals, hasTangents, mesh.first.mBlendShapeVersion);
     GetImplementation(primitive).SetBlendShapeGeometry(mesh.second.blendShapeGeometry);
     GetImplementation(primitive).SetSkinned(mesh.first.IsSkinned());
   }
@@ -343,23 +357,10 @@ void ModelRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinit
   renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIndex].first.mIblIntensity);
   renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIndex].first.mYDirection);
 
-  std::string lightCountPropertyName(Scene3D::Internal::Light::GetLightCountUniformName());
-  renderer.RegisterProperty(lightCountPropertyName, 0);
-
-  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxLightCount; ++i)
-  {
-    std::string lightDirectionPropertyName(Scene3D::Internal::Light::GetLightDirectionUniformName());
-    lightDirectionPropertyName += "[" + std::to_string(i) + "]";
-    renderer.RegisterProperty(lightDirectionPropertyName, Vector3::ZAXIS);
-
-    std::string lightColorPropertyName(Scene3D::Internal::Light::GetLightColorUniformName());
-    lightColorPropertyName += "[" + std::to_string(i) + "]";
-    renderer.RegisterProperty(lightColorPropertyName, Vector3(Color::WHITE));
-  }
-
   node.SetProperty(Actor::Property::COLOR, mColor);
 
+  // If user uses customshader, the properties of the shader could not be changed by Material.
+  if(mShaderIdx == INVALID_INDEX)
   {
     matDef.mMaterial            = Material::New();
     auto     material           = matDef.mMaterial;
index 02d056f..f3aa578 100644 (file)
@@ -30,6 +30,7 @@
 #include <dali-scene3d/public-api/loader/customization.h>
 #include <dali-scene3d/public-api/loader/matrix-stack.h>
 #include <dali-scene3d/public-api/loader/resource-bundle.h>
+#include <dali-scene3d/public-api/loader/shader-manager.h>
 #include <dali-scene3d/public-api/model-components/model-node.h>
 
 namespace Dali
@@ -150,8 +151,9 @@ public: // TYPES
   struct CreateParams
   {
   public: // input
-    ResourceBundle& mResources;
-    Transforms&     mXforms;
+    ResourceBundle&                         mResources;
+    Transforms&                             mXforms;
+    Dali::Scene3D::Loader::ShaderManagerPtr mShaderManager;
 
   public: // output
     std::vector<ConstraintRequest>                    mConstrainables;
index cf5aa61..0cb9dde 100644 (file)
@@ -159,7 +159,7 @@ void AddJointDebugVisual(Actor aJoint)
 
   aJoint.SetVisible(true);
 }
-#endif //DEBUG_JOINTS
+#endif // DEBUG_JOINTS
 
 class ActorCreatorVisitor : public NodeDefinition::IVisitor
 {
@@ -371,7 +371,10 @@ void SceneDefinition::CountResourceRefs(Index iNode, const Customization::Choice
 
     void Register(ResourceType::Value type, Index id)
     {
-      ++(*refCounts)[type][id];
+      if((!(*refCounts)[type].Empty()) && ((*refCounts)[type].Size() > id))
+      {
+        ++(*refCounts)[type][id];
+      }
     }
   };
 
@@ -486,8 +489,7 @@ bool SceneDefinition::ReparentNode(const std::string& name, const std::string& n
     {
       stream << i << ", ";
     }
-    LOGD(("%s", stream.str().c_str()));
-  };)
+    LOGD(("%s", stream.str().c_str())); };)
 
   // Remove node from children of previous parent (if any).
   if(node->mParentIdx != INVALID_INDEX)
diff --git a/dali-scene3d/public-api/loader/shader-definition-factory.cpp b/dali-scene3d/public-api/loader/shader-definition-factory.cpp
deleted file mode 100644 (file)
index 5eadd67..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright (c) 2023 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// CLASS HEADER
-#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
-
-// EXTERNAL INCLUDES
-#include <dali/devel-api/common/map-wrapper.h>
-#include <cstring>
-
-// INTERNAL INCLUDES
-#include <dali-scene3d/internal/loader/hash.h>
-#include <dali-scene3d/public-api/loader/blend-shape-details.h>
-#include <dali-scene3d/public-api/loader/node-definition.h>
-#include <dali-scene3d/public-api/loader/shader-definition-option.h>
-
-namespace Dali::Scene3D::Loader
-{
-namespace
-{
-struct ResourceReceiver : IResourceReceiver
-{
-  const ResourceBundle&     mResources;
-  const MeshDefinition*     mMeshDef     = nullptr;
-  const MaterialDefinition* mMaterialDef = nullptr;
-
-  ResourceReceiver(const ResourceBundle& resources)
-  : mResources(resources)
-  {
-  }
-
-  void Register(ResourceType::Value type, Index id) override
-  {
-    switch(type)
-    {
-      case ResourceType::Mesh:
-        mMeshDef = &mResources.mMeshes[id].first;
-        break;
-
-      case ResourceType::Material:
-        mMaterialDef = &mResources.mMaterials[id].first;
-        break;
-
-      default:
-        break;
-    }
-  }
-};
-
-ShaderDefinitionOption MakeOption(const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
-{
-  ShaderDefinitionOption option;
-
-  const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY);
-  if(hasTransparency)
-  {
-    option.SetTransparency();
-  }
-
-  if(hasTransparency ||
-     !materialDef.CheckTextures(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC) ||
-     !materialDef.CheckTextures(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS))
-  {
-    option.AddOption(ShaderDefinitionOption::Type::THREE_TEXTURE);
-
-    // For the glTF, each of basecolor, metallic_roughness, normal texture is not essential.
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::ALBEDO))
-    {
-      option.AddOption(ShaderDefinitionOption::Type::BASE_COLOR_TEXTURE);
-    }
-
-    if(materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS))
-    {
-      option.AddOption(ShaderDefinitionOption::Type::METALLIC_ROUGHNESS_TEXTURE);
-    }
-
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::NORMAL))
-    {
-      option.AddOption(ShaderDefinitionOption::Type::NORMAL_TEXTURE);
-    }
-  }
-
-  if(materialDef.GetAlphaCutoff() > 0.f)
-  {
-    option.AddOption(ShaderDefinitionOption::Type::ALPHA_TEST);
-  }
-
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SUBSURFACE))
-  {
-    option.AddOption(ShaderDefinitionOption::Type::SUBSURFACE);
-  }
-
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
-  {
-    option.AddOption(ShaderDefinitionOption::Type::OCCLUSION);
-  }
-
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
-  {
-    option.AddOption(ShaderDefinitionOption::Type::EMISSIVE);
-  }
-
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
-  {
-    option.AddOption(ShaderDefinitionOption::Type::SPECULAR);
-  }
-
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
-  {
-    option.AddOption(ShaderDefinitionOption::Type::SPECULAR_COLOR);
-  }
-
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
-  {
-    option.AddOption(ShaderDefinitionOption::Type::GLTF_CHANNELS);
-  }
-
-  if(meshDef.IsSkinned())
-  {
-    option.AddOption(ShaderDefinitionOption::Type::SKINNING);
-  }
-
-  if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL))
-  {
-    option.AddOption(ShaderDefinitionOption::Type::FLIP_UVS_VERTICAL);
-  }
-
-  if(meshDef.mColors.IsDefined())
-  {
-    option.AddOption(ShaderDefinitionOption::Type::COLOR_ATTRIBUTE);
-  }
-
-  if(meshDef.mTangentType == Property::VECTOR4)
-  {
-    option.AddOption(ShaderDefinitionOption::Type::VEC4_TANGENT);
-  }
-
-  if(meshDef.HasBlendShapes())
-  {
-    bool hasPositions = false;
-    bool hasNormals   = false;
-    bool hasTangents  = false;
-    meshDef.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
-    if(hasPositions)
-    {
-      option.AddOption(ShaderDefinitionOption::Type::MORPH_POSITION);
-    }
-
-    if(hasNormals)
-    {
-      option.AddOption(ShaderDefinitionOption::Type::MORPH_NORMAL);
-    }
-
-    if(hasTangents)
-    {
-      option.AddOption(ShaderDefinitionOption::Type::MORPH_TANGENT);
-    }
-
-    if(hasPositions || hasNormals || hasTangents)
-    {
-      if(BlendShapes::Version::VERSION_2_0 == meshDef.mBlendShapeVersion)
-      {
-        option.AddOption(ShaderDefinitionOption::Type::MORPH_VERSION_2_0);
-      }
-    }
-  }
-
-  return option;
-}
-} // namespace
-
-struct ShaderDefinitionFactory::Impl
-{
-  ResourceBundle*           mResources; // no ownership
-  std::map<uint64_t, Index> mShaderMap;
-};
-
-ShaderDefinitionFactory::ShaderDefinitionFactory()
-: mImpl{new Impl()}
-{
-}
-
-ShaderDefinitionFactory::~ShaderDefinitionFactory() = default;
-
-void ShaderDefinitionFactory::SetResources(ResourceBundle& resources)
-{
-  mImpl->mResources = &resources;
-  mImpl->mShaderMap.clear();
-}
-
-Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& renderable)
-{
-  auto& resources = *mImpl->mResources;
-
-  ResourceReceiver receiver{resources};
-  renderable.RegisterResources(receiver);
-
-  if(!(receiver.mMeshDef && receiver.mMaterialDef))
-  {
-    renderable.mShaderIdx = INVALID_INDEX;
-    return INVALID_INDEX;
-  }
-
-  auto&                  shaderMap = mImpl->mShaderMap;
-  ShaderDefinitionOption option    = MakeOption(*receiver.mMaterialDef, *receiver.mMeshDef);
-  uint64_t               hash      = option.GetOptionHash();
-  auto                   iFind     = shaderMap.find(hash);
-  if(iFind != shaderMap.end())
-  {
-    renderable.mShaderIdx = iFind->second;
-  }
-  else
-  {
-    ShaderDefinition shaderDef;
-    shaderDef.mUseBuiltInShader = true;
-    shaderDef.mRendererState    = RendererState::DEPTH_TEST;
-
-    auto& materialDef = *receiver.mMaterialDef;
-    if(!materialDef.mDoubleSided)
-    {
-      shaderDef.mRendererState |= RendererState::CULL_BACK;
-    }
-
-    const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY);
-    if(hasTransparency)
-    {
-      // TODO: this requires more granularity
-      shaderDef.mRendererState = (shaderDef.mRendererState | RendererState::ALPHA_BLEND);
-    }
-
-    option.GetDefines(shaderDef.mDefines);
-    shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
-
-    Index result    = resources.mShaders.size();
-    shaderMap[hash] = result;
-
-    resources.mShaders.emplace_back(std::move(shaderDef), Shader());
-
-    renderable.mShaderIdx = result;
-  }
-
-  return renderable.mShaderIdx;
-}
-
-} // namespace Dali::Scene3D::Loader
diff --git a/dali-scene3d/public-api/loader/shader-definition-factory.h b/dali-scene3d/public-api/loader/shader-definition-factory.h
deleted file mode 100644 (file)
index 273ac8f..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef DALI_SCENE3D_LOADER_SHADER_DEFINITION_FACTORY_H_
-#define DALI_SCENE3D_LOADER_SHADER_DEFINITION_FACTORY_H_
-/*
- * Copyright (c) 2023 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-// EXTERNAL INCLUDER
-#include <memory>
-
-// INTERNAL INCLUDES
-#include <dali-scene3d/public-api/api.h>
-#include <dali-scene3d/public-api/loader/index.h>
-#include <dali-scene3d/public-api/loader/node-definition.h>
-
-namespace Dali::Scene3D::Loader
-{
-struct NodeDefinition;
-class ResourceBundle;
-
-class DALI_SCENE3D_API ShaderDefinitionFactory
-{
-public:
-  ShaderDefinitionFactory();
-  ~ShaderDefinitionFactory();
-
-  /*
-   * @brief Input for meshes and materials, output for shaders.
-   */
-  void SetResources(ResourceBundle& resources);
-
-  /*
-   * @brief Produces the index of a shader, which should be used to index into the shaders
-   *  vector of the ResourceBundle which was provided for the factory. This shader will be
-   *  created if one with the given settings hasn't been created by the factory yet (shaders
-   *  already existing in the ResourceBundle are ignored), otherwise the index of the previously
-   *  created shader will be returned.
-   */
-  Index ProduceShader(NodeDefinition::Renderable& renderable);
-
-private:
-  struct Impl;
-  const std::unique_ptr<Impl> mImpl;
-};
-
-} // namespace Dali::Scene3D::Loader
-
-#endif //DALI_SCENE3D_LOADER_SHADER_DEFINITION_FACTORY_H_
index 27bb051..61f4a7c 100644 (file)
@@ -52,7 +52,7 @@ struct DALI_SCENE3D_API ShaderDefinition
   ShaderDefinition(const ShaderDefinition& other);
   ShaderDefinition& operator=(const ShaderDefinition& other);
 
-  ShaderDefinition(ShaderDefinition&&) = default;
+  ShaderDefinition(ShaderDefinition&&)            = default;
   ShaderDefinition& operator=(ShaderDefinition&&) = default;
 
   /*
diff --git a/dali-scene3d/public-api/loader/shader-manager.cpp b/dali-scene3d/public-api/loader/shader-manager.cpp
new file mode 100644 (file)
index 0000000..158598f
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali-scene3d/public-api/loader/shader-manager.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/common/map-wrapper.h>
+#include <dali/public-api/animation/constraint.h>
+#include <cstring>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/internal/light/light-impl.h>
+#include <dali-scene3d/internal/loader/hash.h>
+#include <dali-scene3d/public-api/loader/blend-shape-details.h>
+#include <dali-scene3d/public-api/loader/node-definition.h>
+
+namespace Dali::Scene3D::Loader
+{
+namespace
+{
+static constexpr uint32_t INDEX_FOR_LIGHT_CONSTRAINT_TAG = 10;
+
+ShaderOption MakeOption(const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
+{
+  ShaderOption option;
+
+  const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY);
+  if(hasTransparency)
+  {
+    option.SetTransparency();
+  }
+
+  if(hasTransparency ||
+     !materialDef.CheckTextures(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC) ||
+     !materialDef.CheckTextures(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS))
+  {
+    option.AddOption(ShaderOption::Type::THREE_TEXTURE);
+
+    // For the glTF, each of basecolor, metallic_roughness, normal texture is not essential.
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::ALBEDO))
+    {
+      option.AddOption(ShaderOption::Type::BASE_COLOR_TEXTURE);
+    }
+
+    if(materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS))
+    {
+      option.AddOption(ShaderOption::Type::METALLIC_ROUGHNESS_TEXTURE);
+    }
+
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::NORMAL))
+    {
+      option.AddOption(ShaderOption::Type::NORMAL_TEXTURE);
+    }
+  }
+
+  if(materialDef.GetAlphaCutoff() > 0.f)
+  {
+    option.AddOption(ShaderOption::Type::ALPHA_TEST);
+  }
+
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SUBSURFACE))
+  {
+    option.AddOption(ShaderOption::Type::SUBSURFACE);
+  }
+
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
+  {
+    option.AddOption(ShaderOption::Type::OCCLUSION);
+  }
+
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
+  {
+    option.AddOption(ShaderOption::Type::EMISSIVE);
+  }
+
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
+  {
+    option.AddOption(ShaderOption::Type::SPECULAR);
+  }
+
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
+  {
+    option.AddOption(ShaderOption::Type::SPECULAR_COLOR);
+  }
+
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
+  {
+    option.AddOption(ShaderOption::Type::GLTF_CHANNELS);
+  }
+
+  if(meshDef.IsSkinned())
+  {
+    option.AddOption(ShaderOption::Type::SKINNING);
+  }
+
+  if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL))
+  {
+    option.AddOption(ShaderOption::Type::FLIP_UVS_VERTICAL);
+  }
+
+  if(meshDef.mColors.IsDefined())
+  {
+    option.AddOption(ShaderOption::Type::COLOR_ATTRIBUTE);
+  }
+
+  if(meshDef.mTangentType == Property::VECTOR4)
+  {
+    option.AddOption(ShaderOption::Type::VEC4_TANGENT);
+  }
+
+  if(meshDef.HasBlendShapes())
+  {
+    bool hasPositions = false;
+    bool hasNormals   = false;
+    bool hasTangents  = false;
+    meshDef.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
+    if(hasPositions)
+    {
+      option.AddOption(ShaderOption::Type::MORPH_POSITION);
+    }
+
+    if(hasNormals)
+    {
+      option.AddOption(ShaderOption::Type::MORPH_NORMAL);
+    }
+
+    if(hasTangents)
+    {
+      option.AddOption(ShaderOption::Type::MORPH_TANGENT);
+    }
+
+    if(hasPositions || hasNormals || hasTangents)
+    {
+      if(BlendShapes::Version::VERSION_2_0 == meshDef.mBlendShapeVersion)
+      {
+        option.AddOption(ShaderOption::Type::MORPH_VERSION_2_0);
+      }
+    }
+  }
+
+  return option;
+}
+} // namespace
+
+struct ShaderManager::Impl
+{
+  std::map<uint64_t, Index>   mShaderMap;
+  std::vector<Dali::Shader>   mShaders;
+  std::vector<Scene3D::Light> mLights;
+};
+
+ShaderManager::ShaderManager()
+: mImpl{new Impl()}
+{
+}
+
+ShaderManager::~ShaderManager() = default;
+
+Dali::Shader ShaderManager::ProduceShader(const MaterialDefinition& materialDefinition, const MeshDefinition& meshDefinition)
+{
+  ShaderOption option = MakeOption(materialDefinition, meshDefinition);
+  return ProduceShader(option);
+}
+
+Dali::Shader ShaderManager::ProduceShader(const ShaderOption& shaderOption)
+{
+  Dali::Shader result;
+
+  auto&    shaderMap = mImpl->mShaderMap;
+  uint64_t hash      = shaderOption.GetOptionHash();
+  auto     iFind     = shaderMap.find(hash);
+  if(iFind != shaderMap.end())
+  {
+    result = mImpl->mShaders[iFind->second];
+  }
+  else
+  {
+    ShaderDefinition shaderDef;
+    shaderDef.mUseBuiltInShader = true;
+
+    shaderOption.GetDefines(shaderDef.mDefines);
+    shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
+
+    shaderMap[hash] = mImpl->mShaders.size();
+
+    auto raw = shaderDef.LoadRaw("");
+    mImpl->mShaders.emplace_back(shaderDef.Load(std::move(raw)));
+    result = mImpl->mShaders.back();
+
+    std::string lightCountPropertyName(Scene3D::Internal::Light::GetLightCountUniformName());
+    result.RegisterProperty(lightCountPropertyName, static_cast<int32_t>(mImpl->mLights.size()));
+
+    for(uint32_t index = 0; index < mImpl->mLights.size(); ++index)
+    {
+      SetLightConstraintToShader(index, result);
+    }
+  }
+
+  return result;
+}
+
+RendererState::Type ShaderManager::GetRendererState(const MaterialDefinition& materialDefinition)
+{
+  RendererState::Type rendererState = RendererState::DEPTH_TEST;
+
+  if(!materialDefinition.mDoubleSided)
+  {
+    rendererState |= RendererState::CULL_BACK;
+  }
+
+  const bool hasTransparency = MaskMatch(materialDefinition.mFlags, MaterialDefinition::TRANSPARENCY);
+  if(hasTransparency)
+  {
+    // TODO: this requires more granularity
+    rendererState = (rendererState | RendererState::ALPHA_BLEND);
+  }
+  return rendererState;
+}
+
+bool ShaderManager::AddLight(Scene3D::Light light)
+{
+  if(!light || mImpl->mLights.size() >= Scene3D::Internal::Light::GetMaximumEnabledLightCount())
+  {
+    return false;
+  }
+
+  int32_t lightIndex = mImpl->mLights.size();
+  mImpl->mLights.push_back(light);
+
+  for(auto&& shader : mImpl->mShaders)
+  {
+    std::string lightCountPropertyName(Scene3D::Internal::Light::GetLightCountUniformName());
+    shader.RegisterProperty(lightCountPropertyName, static_cast<int32_t>(mImpl->mLights.size()));
+  }
+
+  SetLightConstraint(lightIndex);
+
+  return true;
+}
+
+void ShaderManager::RemoveLight(Scene3D::Light light)
+{
+  uint32_t lightCount = mImpl->mLights.size();
+  for(uint32_t index = 0; index < lightCount; ++index)
+  {
+    if(mImpl->mLights[index] != light)
+    {
+      continue;
+    }
+
+    RemoveLightConstraint(index);
+
+    if(!mImpl->mLights.empty() && light != mImpl->mLights.back())
+    {
+      RemoveLightConstraint(mImpl->mLights.size() - 1);
+      mImpl->mLights[index] = mImpl->mLights.back();
+      SetLightConstraint(index);
+    }
+
+    mImpl->mLights.pop_back();
+
+    for(auto&& shader : mImpl->mShaders)
+    {
+      std::string lightCountPropertyName(Scene3D::Internal::Light::GetLightCountUniformName());
+      shader.RegisterProperty(lightCountPropertyName, static_cast<int32_t>(mImpl->mLights.size()));
+    }
+    break;
+  }
+}
+
+uint32_t ShaderManager::GetLightCount() const
+{
+  return mImpl->mLights.size();
+}
+
+void ShaderManager::SetLightConstraint(uint32_t lightIndex)
+{
+  for(auto&& shader : mImpl->mShaders)
+  {
+    SetLightConstraintToShader(lightIndex, shader);
+  }
+}
+
+void ShaderManager::SetLightConstraintToShader(uint32_t lightIndex, Dali::Shader shader)
+{
+  std::string lightDirectionPropertyName(Scene3D::Internal::Light::GetLightDirectionUniformName());
+  lightDirectionPropertyName += "[" + std::to_string(lightIndex) + "]";
+  auto             lightDirectionPropertyIndex = shader.RegisterProperty(lightDirectionPropertyName, Vector3::ZAXIS);
+  Dali::Constraint lightDirectionConstraint    = Dali::Constraint::New<Vector3>(shader, lightDirectionPropertyIndex, [](Vector3& output, const PropertyInputContainer& inputs)
+                                                                             { output = inputs[0]->GetQuaternion().Rotate(Vector3::ZAXIS); });
+  lightDirectionConstraint.AddSource(Source{mImpl->mLights[lightIndex], Dali::Actor::Property::WORLD_ORIENTATION});
+  lightDirectionConstraint.ApplyPost();
+  lightDirectionConstraint.SetTag(INDEX_FOR_LIGHT_CONSTRAINT_TAG + lightIndex);
+
+  std::string lightColorPropertyName(Scene3D::Internal::Light::GetLightColorUniformName());
+  lightColorPropertyName += "[" + std::to_string(lightIndex) + "]";
+  auto             lightColorPropertyIndex = shader.RegisterProperty(lightColorPropertyName, Vector3(Color::WHITE));
+  Dali::Constraint lightColorConstraint    = Dali::Constraint::New<Vector3>(shader, lightColorPropertyIndex, [](Vector3& output, const PropertyInputContainer& inputs)
+                                                                         { output = Vector3(inputs[0]->GetVector4()); });
+  lightColorConstraint.AddSource(Source{mImpl->mLights[lightIndex], Dali::Actor::Property::COLOR});
+  lightColorConstraint.ApplyPost();
+  lightColorConstraint.SetTag(INDEX_FOR_LIGHT_CONSTRAINT_TAG + lightIndex);
+}
+
+void ShaderManager::RemoveLightConstraint(uint32_t lightIndex)
+{
+  for(auto&& shader : mImpl->mShaders)
+  {
+    shader.RemoveConstraints(INDEX_FOR_LIGHT_CONSTRAINT_TAG + lightIndex);
+  }
+}
+
+} // namespace Dali::Scene3D::Loader
diff --git a/dali-scene3d/public-api/loader/shader-manager.h b/dali-scene3d/public-api/loader/shader-manager.h
new file mode 100644 (file)
index 0000000..56adf38
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef DALI_SCENE3D_LOADER_SHADER_MANAGER_H_
+#define DALI_SCENE3D_LOADER_SHADER_MANAGER_H_
+/*
+ * Copyright (c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDER
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/rendering/shader.h>
+#include <memory>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/api.h>
+#include <dali-scene3d/public-api/loader/index.h>
+#include <dali-scene3d/public-api/loader/material-definition.h>
+#include <dali-scene3d/public-api/loader/mesh-definition.h>
+#include <dali-scene3d/public-api/loader/renderer-state.h>
+#include <dali-scene3d/public-api/loader/shader-option.h>
+#include <dali-scene3d/public-api/light/light.h>
+
+namespace Dali::Scene3D::Loader
+{
+struct NodeDefinition;
+class ResourceBundle;
+class ShaderManager;
+typedef IntrusivePtr<ShaderManager> ShaderManagerPtr;
+
+/**
+ * @brief This class is to manage Shaders.
+ * This class could be used as factory class to create Dali::Shader.
+ * And once created Dali::Shader is kept in this manager and will be returned when the same Dali::Shader is requested to be created.
+ */
+class DALI_SCENE3D_API ShaderManager : public RefObject
+{
+public:
+  ShaderManager();
+  ~ShaderManager();
+
+  /**
+   * @brief Produces a Dali::Shader for the input materialDefinition and meshDefinition.
+   * Returns a cached Dali::Shader if the requested Dali::Shader has already been created once.
+   * (Although the input materialDefinition and meshDefinition are not identical to those used to create the cached Dali::Shader, they share the cached one.)
+   * @param[in] materialDefinition MaterialDefinition that includes information of material to create Shader.
+   * @param[in] meshDefinition meshDefinition that includes information of mesh to create Shader.
+   * @return Dali::Shader for the materialDefinition and meshDefinition.
+   */
+  Dali::Shader ProduceShader(const MaterialDefinition& materialDefinition, const MeshDefinition& meshDefinition);
+
+  /**
+   * @brief Produces a Dali::Shader for the input ShaderOption
+   * Returns a cached Dali::Shader if the requested Dali::Shader has already been created once.
+   * @param[in] shaderOption shader option to create Shader.
+   * @return Dali::Shader of the shader option
+   */
+  Dali::Shader ProduceShader(const ShaderOption& shaderOption);
+
+  /**
+   * @brief Returns RendererState of the input materialDefinition.
+   * @param[in] materialDefinition MaterialDefinition to get RendererState
+   * @return RendererState of the materialDefinition.
+   */
+  RendererState::Type GetRendererState(const MaterialDefinition& materialDefinition);
+
+  /**
+   * @brief Adds new lights for each of shaders.
+   * @param[in] light Light object to be newly added.
+   * @return True when the new light object is added successfully.
+   */
+  bool AddLight(Scene3D::Light light);
+
+  /**
+   * @brief Removes light from each of shaders.
+   * @param[in] light Light object to be removed.
+   */
+  void RemoveLight(Scene3D::Light light);
+
+  /**
+   * @brief Retrieves added light counts.
+   * @return The number of added light count.
+   */
+  uint32_t GetLightCount() const;
+
+private:
+  /**
+   * @brief Sets constraint to the shaders with light of light index.
+   * @param[in] lightIndex index of light that will be connected with shaders by constraint.
+   */
+  DALI_INTERNAL void SetLightConstraint(uint32_t lightIndex);
+
+  /**
+   * @brief Sets constraint to a shader with light of light index.
+   * @param[in] lightIndex index of light that will be connected with input shader by constraint.
+   * @param[in] shader Shader that the constraint will be applied.
+   */
+  DALI_INTERNAL void SetLightConstraintToShader(uint32_t lightIndex, Dali::Shader shader);
+
+  /**
+   * @brief Removes constraint of shaders and light of light index.
+   * @param[in] lightIndex index of light that will be disconnected with shaders.
+   */
+  DALI_INTERNAL void RemoveLightConstraint(uint32_t lightIndex);
+private:
+  struct Impl;
+  const std::unique_ptr<Impl> mImpl;
+};
+
+} // namespace Dali::Scene3D::Loader
+
+#endif // DALI_SCENE3D_LOADER_SHADER_MANAGER_H_
@@ -16,7 +16,7 @@
  */
 
 // CLASS HEADER
-#include <dali-scene3d/public-api/loader/shader-definition-option.h>
+#include <dali-scene3d/public-api/loader/shader-option.h>
 
 // EXTERNAL INCLUDES
 #include <string>
@@ -50,22 +50,22 @@ static constexpr std::string_view OPTION_KEYWORD[] =
 static constexpr uint32_t NUMBER_OF_OPTIONS = sizeof(OPTION_KEYWORD) / sizeof(OPTION_KEYWORD[0]);
 } // namespace
 
-void ShaderDefinitionOption::SetTransparency()
+void ShaderOption::SetTransparency()
 {
   mOptionHash |= (1 << NUMBER_OF_OPTIONS);
 }
 
-void ShaderDefinitionOption::AddOption(Type shaderDefinitionOptionType)
+void ShaderOption::AddOption(Type shaderOptionType)
 {
-  mOptionHash |= (1 << static_cast<uint32_t>(shaderDefinitionOptionType));
+  mOptionHash |= (1 << static_cast<uint32_t>(shaderOptionType));
 }
 
-uint64_t ShaderDefinitionOption::GetOptionHash() const
+uint64_t ShaderOption::GetOptionHash() const
 {
   return mOptionHash;
 }
 
-void ShaderDefinitionOption::GetDefines(std::vector<std::string>& defines) const
+void ShaderOption::GetDefines(std::vector<std::string>& defines) const
 {
   defines.clear();
   for(uint32_t i = 0; i < NUMBER_OF_OPTIONS; ++i)
@@ -77,9 +77,9 @@ void ShaderDefinitionOption::GetDefines(std::vector<std::string>& defines) const
   }
 }
 
-std::string_view ShaderDefinitionOption::GetDefineKeyword(Type shaderDefinitionOptionType)
+std::string_view ShaderOption::GetDefineKeyword(Type shaderOptionType)
 {
-  return OPTION_KEYWORD[static_cast<uint32_t>(shaderDefinitionOptionType)];
+  return OPTION_KEYWORD[static_cast<uint32_t>(shaderOptionType)];
 }
 
 } // namespace Dali::Scene3D::Loader
@@ -1,5 +1,5 @@
-#ifndef DALI_SCENE3D_LOADER_SHADER_DEFINITION_OPTION_H_
-#define DALI_SCENE3D_LOADER_SHADER_DEFINITION_OPTION_H_
+#ifndef DALI_SCENE3D_LOADER_SHADER_OPTION_H_
+#define DALI_SCENE3D_LOADER_SHADER_OPTION_H_
 /*
  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
@@ -28,7 +28,7 @@
 namespace Dali::Scene3D::Loader
 {
 
-class DALI_SCENE3D_API ShaderDefinitionOption
+class DALI_SCENE3D_API ShaderOption
 {
 public:
   enum class Type
@@ -64,9 +64,9 @@ public:
    * @brief Adds new shader definition option.
    * If the option is already added, nothin is changed.
    *
-   * @param[in] shaderDefinitionOptionType Option to be added,
+   * @param[in] shaderOptionType Option to be added,
    */
-  void AddOption(Type shaderDefinitionOptionType);
+  void AddOption(Type shaderOptionType);
 
   /**
    * @brief Retrieves current shader option hash
@@ -85,10 +85,10 @@ public:
   /**
    * @brief Retrieves a single shader define keyword of input type.
    *
-   * @param[in] shaderDefinitionOptionType Shader definition option type to know its keyword.
+   * @param[in] shaderOptionType Shader definition option type to know its keyword.
    * @return string keyword of shader define.
    */
-  static std::string_view GetDefineKeyword(Type shaderDefinitionOptionType);
+  static std::string_view GetDefineKeyword(Type shaderOptionType);
 
 private:
   uint64_t mOptionHash{0u};
@@ -96,4 +96,4 @@ private:
 
 } // namespace Dali::Scene3D::Loader
 
-#endif // DALI_SCENE3D_LOADER_SHADER_DEFINITION_OPTION_H_
+#endif // DALI_SCENE3D_LOADER_SHADER_OPTION_H_
index c3e3678..1bdd463 100644 (file)
@@ -71,7 +71,8 @@ class MotionData;
  * @endcode
  *
  * We can request to load MotionData from file or buffer asynchronously.
- * If load completed, LoadCompetedSignal will be emmited.
+ * If load completed, LoadCompletedSignal will be emitted.
+ * If we try to load before LoadCompletedSignal emitted, previous load request cancel and only latest request loaded.
  *
  * @code
  *
@@ -95,6 +96,7 @@ class MotionData;
  *
  * @endcode
  * @note We don't check duplicated MotionIndex internally.
+ * @note We don't check MotionValue type is matched with MotionIndex.
  * @SINCE_2_2.34
  */
 class DALI_SCENE3D_API MotionData : public Dali::BaseHandle
index f633a42..4ad77ad 100644 (file)
@@ -40,8 +40,10 @@ class BlendShapeIndex;
 
 /**
  * @brief Specialized MotionIndex to control blend shape.
- * We can control the blend shape by index (when we set BlendShapeId as IndexKey)
- * or by name (when we set BlendShapeId as StringKey)
+ * We can control the blend shape by index (when we set BlendShapeId as IndexKey),
+ * or by name (when we set BlendShapeId as StringKey).
+ *
+ * MotionValue should be float type.
  *
  * @code
  *
index c3723a9..8dff8f1 100644 (file)
@@ -43,6 +43,8 @@ class MotionTransformIndex;
  * It will be used when app developer don't care about Dali::Actor::Property list,
  * but want to change the transform properties anyway fast enough.
  *
+ * Each TransformType has their own matched MotionValue type.
+ *
  * @code
  *
  * MotionTransformIndex position = MotionTransformIndex::New("nodeName", MotionTransformIndex::TransformType::POSITION);
index 6d4b2ef..b1e9bea 100644 (file)
@@ -106,10 +106,12 @@ void VectorAnimationTask::Finalize()
   if(mAnimationFinishedCallback)
   {
     mVectorAnimationThread.RemoveEventTriggerCallback(mAnimationFinishedCallback.get());
+    mAnimationFinishedCallback.reset();
   }
   if(mLoadCompletedCallback)
   {
     mVectorAnimationThread.RemoveEventTriggerCallback(mLoadCompletedCallback.get());
+    mLoadCompletedCallback.reset();
   }
 
   mVectorRenderer.Finalize();
@@ -139,7 +141,7 @@ bool VectorAnimationTask::Load(bool synchronousLoading)
     DALI_LOG_ERROR("VectorAnimationTask::Load: Load failed [%s]\n", mUrl.c_str());
     mLoadRequest = false;
     mLoadFailed  = true;
-    if(!synchronousLoading)
+    if(!synchronousLoading && mLoadCompletedCallback)
     {
       mVectorAnimationThread.AddEventTriggerCallback(mLoadCompletedCallback.get());
     }
@@ -154,7 +156,7 @@ bool VectorAnimationTask::Load(bool synchronousLoading)
   mFrameDurationMicroSeconds = MICROSECONDS_PER_SECOND / mFrameRate;
 
   mLoadRequest = false;
-  if(!synchronousLoading)
+  if(!synchronousLoading && mLoadCompletedCallback)
   {
     mVectorAnimationThread.AddEventTriggerCallback(mLoadCompletedCallback.get());
   }
index 08b52d6..9d2cfbe 100644 (file)
@@ -263,15 +263,25 @@ void VectorAnimationThread::Rasterize()
 
 void VectorAnimationThread::OnEventCallbackTriggered()
 {
+  while(CallbackBase* callback = GetNextEventCallback())
+  {
+    CallbackBase::Execute(*callback);
+  }
+}
+
+CallbackBase* VectorAnimationThread::GetNextEventCallback()
+{
   ConditionalWait::ScopedLock lock(mConditionalWait);
 
-  for(auto&& iter : mTriggerEventCallbacks)
+  if(!mTriggerEventCallbacks.empty())
   {
-    CallbackBase::Execute(*iter);
+    auto          iter     = mTriggerEventCallbacks.begin();
+    CallbackBase* callback = *iter;
+    mTriggerEventCallbacks.erase(iter);
+    return callback;
   }
-
-  mTriggerEventCallbacks.clear();
   mEventTriggered = false;
+  return nullptr;
 }
 
 VectorAnimationThread::SleepThread::SleepThread(CallbackBase* callback)
index 79d1a48..14aa6c9 100644 (file)
@@ -95,7 +95,7 @@ protected:
 
 private:
   /**
-   * Rasterizes the tasks.
+   * @brief Rasterizes the tasks.
    */
   void Rasterize();
 
@@ -105,6 +105,11 @@ private:
   void OnEventCallbackTriggered();
 
   /**
+   * @brief Gets next event callback to process.
+   */
+  CallbackBase* GetNextEventCallback();
+
+  /**
    * @brief The thread to sleep until the next frame time.
    */
   class SleepThread : public Thread
index 47e8232..468c140 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 const unsigned int TOOLKIT_MAJOR_VERSION = 2;
 const unsigned int TOOLKIT_MINOR_VERSION = 2;
-const unsigned int TOOLKIT_MICRO_VERSION = 34;
+const unsigned int TOOLKIT_MICRO_VERSION = 35;
 const char* const  TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 3320ec4..8e566ac 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali2-toolkit
 Summary:    Dali 3D engine Toolkit
-Version:    2.2.34
+Version:    2.2.35
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0 and BSD-3-Clause and MIT