Merge "Make CreateSolidColorTexture upload pixel data" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / shader-definition-factory.cpp
index 59dd3b4..5eadd67 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.
  * limitations under the License.
  *
  */
-#include "dali-scene3d/public-api/loader/shader-definition-factory.h"
+
+// CLASS HEADER
+#include <dali-scene3d/public-api/loader/shader-definition-factory.h>
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/common/map-wrapper.h>
 #include <cstring>
-#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/devel-api/common/map-wrapper.h"
 
-namespace Dali
-{
-namespace Scene3D
-{
-namespace Loader
+// 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
 {
@@ -58,64 +61,92 @@ struct ResourceReceiver : IResourceReceiver
   }
 };
 
-void RetrieveBlendShapeComponents(const std::vector<MeshDefinition::BlendShape>& blendShapes, bool& hasPositions, bool& hasNormals, bool& hasTangents)
+ShaderDefinitionOption MakeOption(const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
 {
-  for(const auto& blendShape : blendShapes)
-  {
-    hasPositions = hasPositions || blendShape.deltas.IsDefined();
-    hasNormals   = hasNormals || blendShape.normals.IsDefined();
-    hasTangents  = hasTangents || blendShape.tangents.IsDefined();
-  }
-}
-
-uint64_t HashNode(const NodeDefinition& nodeDef, 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(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)
   {
-    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))
+  {
+    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))
   {
-    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())
+  {
+    option.AddOption(ShaderDefinitionOption::Type::COLOR_ATTRIBUTE);
+  }
+
+  if(meshDef.mTangentType == Property::VECTOR4)
+  {
+    option.AddOption(ShaderDefinitionOption::Type::VEC4_TANGENT);
   }
 
   if(meshDef.HasBlendShapes())
@@ -123,34 +154,32 @@ uint64_t HashNode(const NodeDefinition& nodeDef, const MaterialDefinition& mater
     bool hasPositions = false;
     bool hasNormals   = false;
     bool hasTangents  = false;
-    RetrieveBlendShapeComponents(meshDef.mBlendShapes, hasPositions, hasNormals, hasTangents);
+    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
 
@@ -173,147 +202,58 @@ void ShaderDefinitionFactory::SetResources(ResourceBundle& resources)
   mImpl->mShaderMap.clear();
 }
 
-Index ShaderDefinitionFactory::ProduceShader(const NodeDefinition& nodeDef)
+Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& renderable)
 {
-  DALI_ASSERT_DEBUG(nodeDef.mRenderable);
+  auto& resources = *mImpl->mResources;
 
-  auto&            resources = *mImpl->mResources;
   ResourceReceiver receiver{resources};
-  nodeDef.mRenderable->RegisterResources(receiver);
+  renderable.RegisterResources(receiver);
+
   if(!(receiver.mMeshDef && receiver.mMaterialDef))
   {
+    renderable.mShaderIdx = INVALID_INDEX;
     return INVALID_INDEX;
   }
 
-  auto&    shaderMap = mImpl->mShaderMap;
-  uint64_t hash      = HashNode(nodeDef, *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())
   {
-    return iFind->second;
-  }
-
-  ShaderDefinition shaderDef;
-  shaderDef.mUseBuiltInShader = true;
-  shaderDef.mRendererState    = RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE | RendererState::CULL_BACK;
-
-  auto&      materialDef     = *receiver.mMaterialDef;
-  const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY);
-  if(hasTransparency)
-  {
-    // TODO: this requires more granularity
-    shaderDef.mRendererState = (shaderDef.mRendererState | RendererState::ALPHA_BLEND) & ~RendererState::DEPTH_WRITE;
+    renderable.mShaderIdx = iFind->second;
   }
-
-  if(hasTransparency ||
-     !materialDef.CheckTextures(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC) ||
-     !materialDef.CheckTextures(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS))
-
+  else
   {
-    shaderDef.mDefines.push_back("THREE_TEX");
+    ShaderDefinition shaderDef;
+    shaderDef.mUseBuiltInShader = true;
+    shaderDef.mRendererState    = RendererState::DEPTH_TEST;
 
-    // For the glTF, each of basecolor, metallic_roughness, normal texture is not essential.
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::ALBEDO))
+    auto& materialDef = *receiver.mMaterialDef;
+    if(!materialDef.mDoubleSided)
     {
-      shaderDef.mDefines.push_back("BASECOLOR_TEX");
+      shaderDef.mRendererState |= RendererState::CULL_BACK;
     }
 
-    if(materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS))
+    const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY);
+    if(hasTransparency)
     {
-      shaderDef.mDefines.push_back("METALLIC_ROUGHNESS_TEX");
+      // TODO: this requires more granularity
+      shaderDef.mRendererState = (shaderDef.mRendererState | RendererState::ALPHA_BLEND);
     }
 
-    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");
-  }
+    option.GetDefines(shaderDef.mDefines);
+    shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
 
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
-  {
-    shaderDef.mDefines.push_back("GLTF_CHANNELS");
-  }
+    Index result    = resources.mShaders.size();
+    shaderMap[hash] = result;
 
-  const auto& meshDef = *receiver.mMeshDef;
-  if(meshDef.IsSkinned())
-  {
-    shaderDef.mDefines.push_back("SKINNING");
-  }
+    resources.mShaders.emplace_back(std::move(shaderDef), Shader());
 
-  if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL))
-  {
-    shaderDef.mDefines.push_back("FLIP_V");
+    renderable.mShaderIdx = result;
   }
 
-  if(meshDef.HasBlendShapes())
-  {
-    bool hasPositions = false;
-    bool hasNormals   = false;
-    bool hasTangents  = false;
-    RetrieveBlendShapeComponents(meshDef.mBlendShapes, 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");
-      }
-    }
-  }
-
-  if(meshDef.mTangentType == Property::VECTOR4)
-  {
-    shaderDef.mDefines.push_back("VEC4_TANGENT");
-  }
-
-  shaderDef.mUniforms["uMaxLOD"]     = 6.f;
-  shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
-
-  Index result    = resources.mShaders.size();
-  shaderMap[hash] = result;
-
-  resources.mShaders.emplace_back(std::move(shaderDef), Shader());
-
-  return result;
+  return renderable.mShaderIdx;
 }
 
-} // namespace Loader
-} // namespace Scene3D
-} // namespace Dali
+} // namespace Dali::Scene3D::Loader