[Tizen] Removed unused macro invocation from shader
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / model-components / model-primitive-impl.cpp
index 569be53..48519f7 100644 (file)
 #include <dali/public-api/object/type-registry.h>
 
 // INTERNAL INCLUDES
+#include <dali-scene3d/internal/common/image-resource-loader.h>
 #include <dali-scene3d/internal/light/light-impl.h>
 #include <dali-scene3d/internal/model-components/material-impl.h>
 #include <dali-scene3d/public-api/loader/environment-definition.h>
 
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/object/property-array.h>
+#include <dali/public-api/object/property-map.h>
+
+#if defined(DEBUG_ENABLED)
+#include <sys/types.h>
+#include <unistd.h>
+#include <filesystem>
+namespace fs = std::filesystem;
+#endif
+
 namespace Dali
 {
 namespace Scene3D
@@ -37,6 +49,55 @@ namespace Internal
 {
 namespace
 {
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SCENE3D_MODEL_PRIMITIVE");
+
+std::string tmpFilename(std::string prefix, std::string suffix)
+{
+  static int id = 0;
+  id++;
+  std::ostringstream oss;
+  oss << prefix << getpid() << "_" << std::setfill('0') << std::setw(4) << id << suffix;
+  return oss.str();
+}
+
+#define DALI_LOG_WRITE_FILE(filename, stream) \
+  {                                           \
+    fs::path tmp = fs::temp_directory_path(); \
+    tmp /= filename;                          \
+    std::ofstream ostrm(tmp, std::ios::out);  \
+    ostrm << stream;                          \
+    ostrm.flush();                            \
+  }
+
+inline Property::Map GetMap(Shader shader)
+{
+  Property::Value program = shader[Shader::Property::PROGRAM];
+  Property::Map*  map{nullptr};
+  if(program.GetType() == Property::ARRAY)
+  {
+    Property::Array* array = program.GetArray();
+    if(array)
+    {
+      Property::Value& value = array->GetElementAt(0);
+      if(value.GetType() == Property::MAP)
+      {
+        map = value.GetMap();
+      }
+    }
+  }
+  else if(program.GetType() == Property::MAP)
+  {
+    map = program.GetMap();
+  }
+  if(map)
+  {
+    return *map;
+  }
+  return Property::Map();
+}
+
+#endif
 /**
  * Creates control through type registry
  */
@@ -49,13 +110,8 @@ 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";
-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
 
 ModelPrimitivePtr ModelPrimitive::New()
@@ -68,6 +124,7 @@ ModelPrimitivePtr ModelPrimitive::New()
 }
 
 ModelPrimitive::ModelPrimitive()
+: mShaderManager(new Scene3D::Loader::ShaderManager())
 {
 }
 
@@ -82,7 +139,6 @@ ModelPrimitive::~ModelPrimitive()
 
 void ModelPrimitive::Initialize()
 {
-  mLights.resize(Scene3D::Internal::Light::GetMaximumEnabledLightCount());
 }
 
 void ModelPrimitive::SetRenderer(Dali::Renderer renderer)
@@ -142,6 +198,7 @@ void ModelPrimitive::SetMaterial(Dali::Scene3D::Material material, bool updateRe
         ApplyMaterialToRenderer();
       }
     }
+    UpdateShadowMapTexture();
     UpdateImageBasedLightTexture();
   }
 }
@@ -161,6 +218,12 @@ void ModelPrimitive::RemovePrimitiveObserver(ModelPrimitiveModifyObserver* obser
   mObservers.erase(observer);
 }
 
+void ModelPrimitive::SetShadowMapTexture(Dali::Texture shadowMapTexture)
+{
+  mShadowMapTexture = shadowMapTexture;
+  UpdateShadowMapTexture();
+}
+
 void ModelPrimitive::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
 {
   mDiffuseTexture       = diffuseTexture;
@@ -180,52 +243,18 @@ void ModelPrimitive::SetImageBasedLightScaleFactor(float iblScaleFactor)
   }
 }
 
-void ModelPrimitive::AddLight(Scene3D::Light light, uint32_t lightIndex)
+void ModelPrimitive::UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager, Loader::ShaderOption::HashType hash)
 {
-  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, hash);
+    }
   }
 }
 
-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);
@@ -237,16 +266,23 @@ 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;
+  mBlendShapeVersion = version;
+}
+
+void ModelPrimitive::SetSkinned(bool isSkinned, uint32_t numberOfJointSets)
 {
-  mHasPositions = hasPositions;
-  mHasNormals   = hasNormals;
-  mHasTangents  = hasTangents;
+  mHasSkinning       = isSkinned;
+  mNumberOfJointSets = numberOfJointSets;
 }
 
-void ModelPrimitive::SetSkinned(bool isSkinned)
+void ModelPrimitive::SetVertexColor(bool hasVertexColor)
 {
-  mHasSkinning = isSkinned;
+  mHasVertexColor = hasVertexColor;
 }
 
 // From MaterialModifyObserver
@@ -256,47 +292,73 @@ void ModelPrimitive::OnMaterialModified(Dali::Scene3D::Material material, Materi
   ApplyMaterialToRenderer(flag);
 }
 
-void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag)
+void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag, Loader::ShaderOption::HashType oldHash)
 {
+  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);
+      shaderOption.AddJointMacros(mNumberOfJointSets);
+    }
+    else
+    {
+      shaderOption.AddJointMacros(0);
+    }
+    if(mHasVertexColor)
+    {
+      shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::COLOR_ATTRIBUTE);
     }
     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);
       }
-      defines.push_back(MORPH_KEYWORD.data());
-      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)
+
+    Shader newShader = mShaderManager->ProduceShader(shaderOption);
+    if(mShader != newShader)
     {
-      Scene3D::Loader::ShaderDefinition::ApplyDefine(vertexShader, define);
-    }
+      DALI_LOG_INFO(gLogFilter, Debug::General, "Warning!  Model primitive shader changed: OldHash:%x NewHash:%x\n", oldHash, shaderOption.GetOptionHash());
 
-    mShader.Reset();
-    mShader = Shader::New(vertexShader, fragmentShader);
+#if defined(DEBUG_ENABLED)
+      if(mShader)
+      {
+        Property::Map oldMap = GetMap(mShader);
+        DALI_LOG_WRITE_FILE(tmpFilename("oldShader", ".txt"), "Vertex Shader:\n"
+                                                                << oldMap["vertex"] << "\n\nFragmentShader: " << oldMap["fragment"] << "\n");
+      }
+      if(newShader)
+      {
+        Property::Map newMap = GetMap(newShader);
+        DALI_LOG_WRITE_FILE(tmpFilename("newShader", ".txt"), "Vertex Shader:\n"
+                                                                << newMap["vertex"] << "\n\nFragmentShader: " << newMap["fragment"] << "\n");
+      }
+#endif
+    }
+    mShader = newShader;
 
     if(!mRenderer)
     {
@@ -330,7 +392,14 @@ void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag
     }
 
     uint32_t textureCount = mTextureSet.GetTextureCount();
-    Texture  brdfTexture  = Scene3D::Loader::EnvironmentDefinition::GetBrdfTexture();
+
+    if(!mShadowMapTexture)
+    {
+      mShadowMapTexture = Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyTextureWhiteRGB();
+    }
+    mTextureSet.SetTexture(textureCount++, mShadowMapTexture);
+
+    Texture brdfTexture = Scene3D::Loader::EnvironmentDefinition::GetBrdfTexture();
     if(!mSpecularTexture || !mDiffuseTexture)
     {
       Scene3D::Loader::EnvironmentMapData environmentMapData;
@@ -390,18 +459,43 @@ void ModelPrimitive::CreateRenderer()
   mRenderer.SetTextures(mTextureSet);
   UpdateRendererUniform();
 
-  uint32_t maxLightCount = Scene3D::Internal::Light::GetMaximumEnabledLightCount();
-  for(uint32_t i = 0; i < maxLightCount; ++i)
+  for(auto* observer : mObservers)
   {
-    if(mLights[i])
-    {
-      AddLight(mLights[i], i);
-    }
+    observer->OnRendererCreated(mRenderer);
   }
+}
 
-  for(auto* observer : mObservers)
+void ModelPrimitive::UpdateShadowMapTexture()
+{
+  if(mRenderer && mMaterial)
   {
-    observer->OnRendererCreated(mRenderer);
+    Dali::TextureSet textures = mRenderer.GetTextures();
+    if(!textures)
+    {
+      return;
+    }
+
+    uint32_t textureCount = textures.GetTextureCount();
+    if(mShadowMapTexture &&
+       textureCount >= GetImplementation(mMaterial).GetShadowMapTextureOffset() &&
+       textures.GetTexture(textureCount - GetImplementation(mMaterial).GetShadowMapTextureOffset()) != mShadowMapTexture)
+    {
+      Dali::TextureSet newTextures = Dali::TextureSet::New();
+
+      for(uint32_t index = 0u; index < textureCount; ++index)
+      {
+        Dali::Texture texture = textures.GetTexture(index);
+        if(index == textureCount - GetImplementation(mMaterial).GetShadowMapTextureOffset())
+        {
+          texture = (!!mShadowMapTexture) ? mShadowMapTexture : Dali::Scene3D::Internal::ImageResourceLoader::GetEmptyTextureWhiteRGB();
+        }
+
+        newTextures.SetTexture(index, texture);
+        newTextures.SetSampler(index, textures.GetSampler(index));
+      }
+
+      mRenderer.SetTextures(newTextures);
+    }
   }
 }
 
@@ -447,9 +541,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