Merge "Support KHR_materials_specular and KHR_materials_ior extension of glTF" into...
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / shader-definition-factory.cpp
index 59dd3b4..a341d20 100644 (file)
@@ -68,7 +68,7 @@ void RetrieveBlendShapeComponents(const std::vector<MeshDefinition::BlendShape>&
   }
 }
 
-uint64_t HashNode(const NodeDefinition& nodeDef, const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
+uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& meshDef)
 {
   Hash hash;
 
@@ -93,6 +93,16 @@ uint64_t HashNode(const NodeDefinition& nodeDef, const MaterialDefinition& mater
     hash.Add("SSS");
   }
 
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
+  {
+    hash.Add("SPECTEX");
+  }
+
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
+  {
+    hash.Add("SPECCOLTEX");
+  }
+
   if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
   {
     hash.Add("OCCL" /*USION*/);
@@ -173,145 +183,165 @@ 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);
+  uint64_t hash      = HashNode(*receiver.mMaterialDef, *receiver.mMeshDef);
   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 | RendererState::DEPTH_WRITE;
 
-    // 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) & ~RendererState::DEPTH_WRITE;
     }
 
-    if(MaskMatch(materialDef.mFlags, MaterialDefinition::NORMAL))
+    if(hasTransparency ||
+       !materialDef.CheckTextures(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC) ||
+       !materialDef.CheckTextures(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS))
+
     {
-      shaderDef.mDefines.push_back("NORMAL_TEX");
-    }
-  }
+      shaderDef.mDefines.push_back("THREE_TEX");
 
-  if(materialDef.GetAlphaCutoff() > 0.f)
-  {
-    shaderDef.mDefines.push_back("ALPHA_TEST");
-  }
+      // 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(MaskMatch(materialDef.mFlags, MaterialDefinition::SUBSURFACE))
-  {
-    shaderDef.mDefines.push_back("SSS");
-  }
+      if(materialDef.CheckTextures(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS))
+      {
+        shaderDef.mDefines.push_back("METALLIC_ROUGHNESS_TEX");
+      }
 
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
-  {
-    shaderDef.mDefines.push_back("OCCLUSION");
-  }
+      if(MaskMatch(materialDef.mFlags, MaterialDefinition::NORMAL))
+      {
+        shaderDef.mDefines.push_back("NORMAL_TEX");
+      }
+    }
 
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
-  {
-    shaderDef.mDefines.push_back("EMISSIVE");
-  }
+    if(materialDef.GetAlphaCutoff() > 0.f)
+    {
+      shaderDef.mDefines.push_back("ALPHA_TEST");
+    }
 
-  if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
-  {
-    shaderDef.mDefines.push_back("GLTF_CHANNELS");
-  }
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SUBSURFACE))
+    {
+      shaderDef.mDefines.push_back("SSS");
+    }
 
-  const auto& meshDef = *receiver.mMeshDef;
-  if(meshDef.IsSkinned())
-  {
-    shaderDef.mDefines.push_back("SKINNING");
-  }
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
+    {
+      shaderDef.mDefines.push_back("MATERIAL_SPECULAR_TEXTURE");
+    }
 
-  if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL))
-  {
-    shaderDef.mDefines.push_back("FLIP_V");
-  }
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
+    {
+      shaderDef.mDefines.push_back("MATERIAL_SPECULAR_COLOR_TEXTURE");
+    }
 
-  if(meshDef.HasBlendShapes())
-  {
-    bool hasPositions = false;
-    bool hasNormals   = false;
-    bool hasTangents  = false;
-    RetrieveBlendShapeComponents(meshDef.mBlendShapes, hasPositions, hasNormals, hasTangents);
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
+    {
+      shaderDef.mDefines.push_back("OCCLUSION");
+    }
 
-    if(hasPositions)
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
     {
-      shaderDef.mDefines.push_back("MORPH_POSITION");
+      shaderDef.mDefines.push_back("EMISSIVE");
     }
 
-    if(hasNormals)
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
     {
-      shaderDef.mDefines.push_back("MORPH_NORMAL");
+      shaderDef.mDefines.push_back("GLTF_CHANNELS");
     }
 
-    if(hasTangents)
+    const auto& meshDef = *receiver.mMeshDef;
+    if(meshDef.IsSkinned())
     {
-      shaderDef.mDefines.push_back("MORPH_TANGENT");
+      shaderDef.mDefines.push_back("SKINNING");
     }
 
-    if(hasPositions || hasNormals || hasTangents)
+    if(MaskMatch(meshDef.mFlags, MeshDefinition::FLIP_UVS_VERTICAL))
     {
-      shaderDef.mDefines.push_back("MORPH");
+      shaderDef.mDefines.push_back("FLIP_V");
+    }
 
-      if(BlendShapes::Version::VERSION_2_0 == meshDef.mBlendShapeVersion)
+    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_VERSION_2_0");
+        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");
-  }
+    if(meshDef.mTangentType == Property::VECTOR4)
+    {
+      shaderDef.mDefines.push_back("VEC4_TANGENT");
+    }
 
-  shaderDef.mUniforms["uMaxLOD"]     = 6.f;
-  shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
+    shaderDef.mUniforms["uMaxLOD"]     = 6.f;
+    shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
 
-  Index result    = resources.mShaders.size();
-  shaderMap[hash] = result;
+    Index result    = resources.mShaders.size();
+    shaderMap[hash] = result;
 
-  resources.mShaders.emplace_back(std::move(shaderDef), Shader());
+    resources.mShaders.emplace_back(std::move(shaderDef), Shader());
+
+    renderable.mShaderIdx = result;
+  }
 
-  return result;
+  return renderable.mShaderIdx;
 }
 
 } // namespace Loader