Merge "Shader Factory refactoring" into devel/master
authorSeungho BAEK <sbsh.baek@samsung.com>
Tue, 27 Jun 2023 04:48:39 +0000 (04:48 +0000)
committerGerrit Code Review <gerrit@review>
Tue, 27 Jun 2023 04:48:39 +0000 (04:48 +0000)
automated-tests/src/dali-scene3d-internal/utc-Dali-MaterialImpl.cpp
automated-tests/src/dali-scene3d/CMakeLists.txt
automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionOption.cpp [new file with mode: 0644]
dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert
dali-scene3d/internal/model-components/material-impl.cpp
dali-scene3d/internal/model-components/model-primitive-impl.cpp
dali-scene3d/public-api/file.list
dali-scene3d/public-api/loader/shader-definition-factory.cpp
dali-scene3d/public-api/loader/shader-definition-option.cpp [new file with mode: 0644]
dali-scene3d/public-api/loader/shader-definition-option.h [new file with mode: 0644]

index 088bb6f..34a82b2 100644 (file)
  *
  */
 
-#include <toolkit-event-thread-callback.h>
 #include <dali-toolkit-test-suite-utils.h>
 #include <dali-toolkit/dali-toolkit.h>
 #include <stdlib.h>
+#include <toolkit-event-thread-callback.h>
 #include <iostream>
 
-#include <dali-scene3d/internal/model-components/material-impl.h>
 #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>
 
 using namespace Dali;
 using namespace Dali::Toolkit;
@@ -96,11 +97,11 @@ int UtcDaliMaterialImplSetGetTextureInformation(void)
   GetImplementation(material).UpdateMaterialData();
 
   std::vector<std::string> defines;
-  defines.push_back("THREE_TEX");
-  defines.push_back("GLTF_CHANNELS");
-  defines.push_back("BASECOLOR_TEX");
-  defines.push_back("METALLIC_ROUGHNESS_TEX");
-  defines.push_back("NORMAL_TEX");
+  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());
 
   std::string fragmentShader = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
   for(const auto& define : defines)
@@ -175,10 +176,10 @@ int UtcDaliMaterialImplSetGetTextureInformation(void)
   DALI_TEST_EQUALS(true, GetImplementation(material).IsResourceReady(), TEST_LOCATION);
   GetImplementation(material).UpdateMaterialData();
 
-  defines.push_back("OCCLUSION");
-  defines.push_back("EMISSIVE");
-  defines.push_back("MATERIAL_SPECULAR_TEXTURE");
-  defines.push_back("MATERIAL_SPECULAR_COLOR_TEXTURE");
+  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)
index 29b6775..4dff80c 100755 (executable)
@@ -31,6 +31,7 @@ SET(TC_SOURCES
   utc-Dali-SceneDefinition.cpp
   utc-Dali-ShaderDefinition.cpp
   utc-Dali-ShaderDefinitionFactory.cpp
+  utc-Dali-ShaderDefinitionOption.cpp
   utc-Dali-StringCallback.cpp
   utc-Dali-Utils.cpp
   utc-Dali-ViewProjection.cpp
diff --git a/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionOption.cpp b/automated-tests/src/dali-scene3d/utc-Dali-ShaderDefinitionOption.cpp
new file mode 100644 (file)
index 0000000..0f320a8
--- /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-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
index d57d974..8be7c88 100644 (file)
@@ -4,6 +4,8 @@
 // https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/glTF-WebGL-PBR/shaders/pbr-vert.glsl
 // Commit dc84b5e374fb3d23153d2248a338ef88173f9eb6
 
+#define MORPH defined(MORPH_POSITION) || defined(MORPH_NORMAL) || defined(MORPH_TANGENT)
+
 #ifdef HIGHP
   precision highp float;
 #else
index a117d48..4ce7d57 100644 (file)
@@ -31,6 +31,7 @@
 #include <dali-scene3d/public-api/loader/node-definition.h>
 #include <dali-scene3d/public-api/loader/renderer-state.h>
 #include <dali-scene3d/public-api/loader/utils.h>
+#include <dali-scene3d/public-api/loader/shader-definition-option.h>
 
 namespace Dali
 {
@@ -100,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         = "BASECOLOR_TEX";
-  mTextureInformations[METALLIC_ROUGHNESS].mDefineKeyword = "METALLIC_ROUGHNESS_TEX";
-  mTextureInformations[NORMAL].mDefineKeyword             = "NORMAL_TEX";
-  mTextureInformations[OCCLUSION].mDefineKeyword          = "OCCLUSION";
-  mTextureInformations[EMISSIVE].mDefineKeyword           = "EMISSIVE";
-  mTextureInformations[SPECULAR].mDefineKeyword           = "MATERIAL_SPECULAR_TEXTURE";
-  mTextureInformations[SPECULAR_COLOR].mDefineKeyword     = "MATERIAL_SPECULAR_COLOR_TEXTURE";
+  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[TextureIndex::EMISSIVE].mFactor = Vector4::ZERO;
 }
index 569be53..df71d6d 100644 (file)
@@ -49,7 +49,6 @@ BaseHandle Create()
 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelPrimitive, Dali::BaseHandle, Create);
 DALI_TYPE_REGISTRATION_END()
 
-constexpr std::string_view MORPH_KEYWORD             = "MORPH";
 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";
@@ -284,7 +283,6 @@ void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag
       {
         defines.push_back(MORPH_TANGENT_KEYWORD.data());
       }
-      defines.push_back(MORPH_KEYWORD.data());
       if(mBlendShapeData.version == Scene3D::Loader::BlendShapes::Version::VERSION_2_0)
       {
         defines.push_back(MORPH_VERSION_2_0_KEYWORD.data());
index f039518..43e992f 100644 (file)
@@ -33,6 +33,7 @@ set(scene3d_src_files ${scene3d_src_files}
        ${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/skinning-details.cpp
        ${scene3d_public_api_dir}/loader/string-callback.cpp
        ${scene3d_public_api_dir}/loader/utils.cpp
index 0d1e346..5eadd67 100644 (file)
@@ -26,6 +26,7 @@
 #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
 {
@@ -60,90 +61,92 @@ struct ResourceReceiver : IResourceReceiver
   }
 };
 
-uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
+ShaderDefinitionOption MakeOption(const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
 {
-  Hash hash;
+  ShaderDefinitionOption option;
 
   const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY);
-  hash.Add(hasTransparency);
+  if(hasTransparency)
+  {
+    option.SetTransparency();
+  }
 
   if(hasTransparency ||
-     materialDef.CheckTextures(MaterialDefinition::ALBEDO) ||
-     materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS) ||
-     materialDef.CheckTextures(MaterialDefinition::NORMAL))
+     !materialDef.CheckTextures(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC) ||
+     !materialDef.CheckTextures(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS))
   {
-    hash.Add("3TEX");
+    option.AddOption(ShaderDefinitionOption::Type::THREE_TEXTURE);
 
     // For the glTF, each of basecolor, metallic_roughness, normal texture is not essential.
-    if(materialDef.CheckTextures(MaterialDefinition::ALBEDO))
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::ALBEDO))
     {
-      hash.Add("BCTEX");
+      option.AddOption(ShaderDefinitionOption::Type::BASE_COLOR_TEXTURE);
     }
 
     if(materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS))
     {
-      hash.Add("MRTEX");
+      option.AddOption(ShaderDefinitionOption::Type::METALLIC_ROUGHNESS_TEXTURE);
     }
 
-    if(materialDef.CheckTextures(MaterialDefinition::NORMAL))
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::NORMAL))
     {
-      hash.Add("NTEX");
+      option.AddOption(ShaderDefinitionOption::Type::NORMAL_TEXTURE);
     }
   }
 
   if(materialDef.GetAlphaCutoff() > 0.f)
   {
-    hash.Add("ALPH" /*A_TEST*/);
+    option.AddOption(ShaderDefinitionOption::Type::ALPHA_TEST);
   }
 
   if(MaskMatch(materialDef.mFlags, MaterialDefinition::SUBSURFACE))
   {
-    hash.Add("SSS");
+    option.AddOption(ShaderDefinitionOption::Type::SUBSURFACE);
   }
 
   if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
   {
-    hash.Add("OCCL" /*USION*/);
+    option.AddOption(ShaderDefinitionOption::Type::OCCLUSION);
   }
 
   if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
   {
-    hash.Add("EMIS" /*SIVE*/);
+    option.AddOption(ShaderDefinitionOption::Type::EMISSIVE);
   }
 
   if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
   {
-    hash.Add("SPECTEX");
+    option.AddOption(ShaderDefinitionOption::Type::SPECULAR);
   }
 
   if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
   {
-    hash.Add("SPECCOLTEX");
+    option.AddOption(ShaderDefinitionOption::Type::SPECULAR_COLOR);
   }
 
   if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
   {
-    hash.Add("GLTF" /*_CHANNELS*/);
+    option.AddOption(ShaderDefinitionOption::Type::GLTF_CHANNELS);
   }
 
   if(meshDef.IsSkinned())
   {
-    hash.Add("SKIN" /*NING*/);
+    option.AddOption(ShaderDefinitionOption::Type::SKINNING);
   }
 
   if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL))
   {
-    hash.Add("FLIP" /*_V*/);
+    option.AddOption(ShaderDefinitionOption::Type::FLIP_UVS_VERTICAL);
   }
 
   if(meshDef.mColors.IsDefined())
   {
-    hash.Add("COLATT");
+    option.AddOption(ShaderDefinitionOption::Type::COLOR_ATTRIBUTE);
   }
 
   if(meshDef.mTangentType == Property::VECTOR4)
   {
-    hash.Add("V4TAN");
+    option.AddOption(ShaderDefinitionOption::Type::VEC4_TANGENT);
   }
 
   if(meshDef.HasBlendShapes())
@@ -154,31 +157,29 @@ uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& m
     meshDef.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
     if(hasPositions)
     {
-      hash.Add("MORPHPOS");
+      option.AddOption(ShaderDefinitionOption::Type::MORPH_POSITION);
     }
 
     if(hasNormals)
     {
-      hash.Add("MORPHNOR");
+      option.AddOption(ShaderDefinitionOption::Type::MORPH_NORMAL);
     }
 
     if(hasTangents)
     {
-      hash.Add("MORPHTAN");
+      option.AddOption(ShaderDefinitionOption::Type::MORPH_TANGENT);
     }
 
     if(hasPositions || hasNormals || hasTangents)
     {
-      hash.Add("MORPH");
-
       if(BlendShapes::Version::VERSION_2_0 == meshDef.mBlendShapeVersion)
       {
-        hash.Add("MORPHV2");
+        option.AddOption(ShaderDefinitionOption::Type::MORPH_VERSION_2_0);
       }
     }
   }
 
-  return hash;
+  return option;
 }
 } // namespace
 
@@ -214,9 +215,10 @@ Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& rendera
     return INVALID_INDEX;
   }
 
-  auto&    shaderMap = mImpl->mShaderMap;
-  uint64_t hash      = HashNode(*receiver.mMaterialDef, *receiver.mMeshDef);
-  auto     iFind     = shaderMap.find(hash);
+  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;
@@ -240,119 +242,7 @@ Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& rendera
       shaderDef.mRendererState = (shaderDef.mRendererState | RendererState::ALPHA_BLEND);
     }
 
-    if(hasTransparency ||
-       !materialDef.CheckTextures(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC) ||
-       !materialDef.CheckTextures(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS))
-
-    {
-      shaderDef.mDefines.push_back("THREE_TEX");
-
-      // For the glTF, each of basecolor, metallic_roughness, normal texture is not essential.
-      if(MaskMatch(materialDef.mFlags, MaterialDefinition::ALBEDO))
-      {
-        shaderDef.mDefines.push_back("BASECOLOR_TEX");
-      }
-
-      if(materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS))
-      {
-        shaderDef.mDefines.push_back("METALLIC_ROUGHNESS_TEX");
-      }
-
-      if(MaskMatch(materialDef.mFlags, MaterialDefinition::NORMAL))
-      {
-        shaderDef.mDefines.push_back("NORMAL_TEX");
-      }
-    }
-
-    if(materialDef.GetAlphaCutoff() > 0.f)
-    {
-      shaderDef.mDefines.push_back("ALPHA_TEST");
-    }
-
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SUBSURFACE))
-    {
-      shaderDef.mDefines.push_back("SSS");
-    }
-
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
-    {
-      shaderDef.mDefines.push_back("OCCLUSION");
-    }
-
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
-    {
-      shaderDef.mDefines.push_back("EMISSIVE_TEXTURE");
-    }
-
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
-    {
-      shaderDef.mDefines.push_back("MATERIAL_SPECULAR_TEXTURE");
-    }
-
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
-    {
-      shaderDef.mDefines.push_back("MATERIAL_SPECULAR_COLOR_TEXTURE");
-    }
-
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
-    {
-      shaderDef.mDefines.push_back("GLTF_CHANNELS");
-    }
-
-    const auto& meshDef = *receiver.mMeshDef;
-    if(meshDef.IsSkinned())
-    {
-      shaderDef.mDefines.push_back("SKINNING");
-    }
-
-    if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL))
-    {
-      shaderDef.mDefines.push_back("FLIP_V");
-    }
-
-    if(meshDef.mColors.IsDefined())
-    {
-      shaderDef.mDefines.push_back("COLOR_ATTRIBUTE");
-    }
-
-    if(meshDef.mTangentType == Property::VECTOR4)
-    {
-      shaderDef.mDefines.push_back("VEC4_TANGENT");
-    }
-
-    if(meshDef.HasBlendShapes())
-    {
-      bool hasPositions = false;
-      bool hasNormals   = false;
-      bool hasTangents  = false;
-      meshDef.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
-
-      if(hasPositions)
-      {
-        shaderDef.mDefines.push_back("MORPH_POSITION");
-      }
-
-      if(hasNormals)
-      {
-        shaderDef.mDefines.push_back("MORPH_NORMAL");
-      }
-
-      if(hasTangents)
-      {
-        shaderDef.mDefines.push_back("MORPH_TANGENT");
-      }
-
-      if(hasPositions || hasNormals || hasTangents)
-      {
-        shaderDef.mDefines.push_back("MORPH");
-
-        if(BlendShapes::Version::VERSION_2_0 == meshDef.mBlendShapeVersion)
-        {
-          shaderDef.mDefines.push_back("MORPH_VERSION_2_0");
-        }
-      }
-    }
-
+    option.GetDefines(shaderDef.mDefines);
     shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
 
     Index result    = resources.mShaders.size();
diff --git a/dali-scene3d/public-api/loader/shader-definition-option.cpp b/dali-scene3d/public-api/loader/shader-definition-option.cpp
new file mode 100644 (file)
index 0000000..18360de
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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-option.h>
+
+// EXTERNAL INCLUDES
+#include <string>
+
+namespace Dali::Scene3D::Loader
+{
+namespace
+{
+static constexpr std::string_view OPTION_KEYWORD[] =
+  {
+    "GLTF_CHANNELS",
+    "THREE_TEX",
+    "BASECOLOR_TEX",
+    "METALLIC_ROUGHNESS_TEX",
+    "NORMAL_TEX",
+    "OCCLUSION",
+    "EMISSIVE_TEXTURE",
+    "ALPHA_TEST",
+    "SSS",
+    "MATERIAL_SPECULAR_TEXTURE",
+    "MATERIAL_SPECULAR_COLOR_TEXTURE",
+    "SKINNING",
+    "FLIP_V",
+    "COLOR_ATTRIBUTE",
+    "VEC4_TANGENT",
+    "MORPH_POSITION",
+    "MORPH_NORMAL",
+    "MORPH_TANGENT",
+    "MORPH_VERSION_2_0",
+};
+static constexpr uint32_t NUMBER_OF_OPTIONS = sizeof(OPTION_KEYWORD) / sizeof(OPTION_KEYWORD[0]);
+} // namespace
+
+void ShaderDefinitionOption::SetTransparency()
+{
+  mOptionHash |= (1 << NUMBER_OF_OPTIONS);
+}
+
+void ShaderDefinitionOption::AddOption(Type shaderDefinitionOptionType)
+{
+  mOptionHash |= (1 << static_cast<uint32_t>(shaderDefinitionOptionType));
+}
+
+uint64_t ShaderDefinitionOption::GetOptionHash() const
+{
+  return mOptionHash;
+}
+
+void ShaderDefinitionOption::GetDefines(std::vector<std::string>& defines) const
+{
+  defines.clear();
+  for(uint32_t i = 0; i < NUMBER_OF_OPTIONS; ++i)
+  {
+    if(mOptionHash & 1 << i)
+    {
+      defines.push_back(OPTION_KEYWORD[i].data());
+    }
+  }
+}
+
+std::string_view ShaderDefinitionOption::GetDefineKeyword(Type shaderDefinitionOptionType)
+{
+  return OPTION_KEYWORD[static_cast<uint32_t>(shaderDefinitionOptionType)];
+}
+
+} // namespace Dali::Scene3D::Loader
diff --git a/dali-scene3d/public-api/loader/shader-definition-option.h b/dali-scene3d/public-api/loader/shader-definition-option.h
new file mode 100644 (file)
index 0000000..3dc56be
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef DALI_SCENE3D_LOADER_SHADER_DEFINITION_OPTION_H_
+#define DALI_SCENE3D_LOADER_SHADER_DEFINITION_OPTION_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/vector-wrapper.h>
+#include <memory>
+#include <string_view>
+
+// INTERNAL INCLUDES
+#include <dali-scene3d/public-api/api.h>
+
+namespace Dali::Scene3D::Loader
+{
+
+class DALI_SCENE3D_API ShaderDefinitionOption
+{
+public:
+  enum class Type
+  {
+    GLTF_CHANNELS = 0,
+    THREE_TEXTURE,
+    BASE_COLOR_TEXTURE,
+    METALLIC_ROUGHNESS_TEXTURE,
+    NORMAL_TEXTURE,
+    OCCLUSION,
+    EMISSIVE,
+    ALPHA_TEST,
+    SUBSURFACE,
+    SPECULAR,
+    SPECULAR_COLOR,
+    SKINNING,
+    FLIP_UVS_VERTICAL,
+    COLOR_ATTRIBUTE,
+    VEC4_TANGENT,
+    MORPH_POSITION,
+    MORPH_NORMAL,
+    MORPH_TANGENT,
+    MORPH_VERSION_2_0
+  };
+
+public:
+  /**
+   * @brief Sets transparency option.
+   */
+  void SetTransparency();
+
+  /**
+   * @brief Adds new shader definition option.
+   * If the option is already added, nothin is changed.
+   *
+   * @param[in] shaderDefinitionOptionType Option to be added,
+   */
+  void AddOption(Type shaderDefinitionOptionType);
+
+  /**
+   * @brief Retrieves current shader option hash
+   *
+   * @return Hash value of currently added options.
+   */
+  uint64_t GetOptionHash() const;
+
+  /**
+   * @brief Retrieves a list of define keywords.
+   *
+   * @param[out] defines A list of define keywords those are used in this option.
+   */
+  void GetDefines(std::vector<std::string>& defines) const;
+
+  /**
+   * @brief Retrieves a single shader define keyword of input type.
+   *
+   * @param[in] shaderDefinitionOptionType Shader definition option type to know its keyword.
+   * @return string keyword of shader define.
+   */
+  static std::string_view GetDefineKeyword(Type shaderDefinitionOptionType);
+
+private:
+  uint64_t mOptionHash{0u};
+};
+
+} // namespace Dali::Scene3D::Loader
+
+#endif // DALI_SCENE3D_LOADER_SHADER_DEFINITION_OPTION_H_