#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
{
+#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
*/
DALI_TYPE_REGISTRATION_END()
static constexpr uint32_t INDEX_FOR_LIGHT_CONSTRAINT_TAG = 10;
+
} // unnamed namespace
ModelPrimitivePtr ModelPrimitive::New()
ApplyMaterialToRenderer();
}
}
+ UpdateShadowMapTexture();
UpdateImageBasedLightTexture();
}
}
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;
}
}
-void ModelPrimitive::UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager)
+void ModelPrimitive::UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager, Loader::ShaderOption::HashType hash)
{
if(mShaderManager != shaderManager)
{
mShaderManager = (shaderManager) ? shaderManager : new Scene3D::Loader::ShaderManager();
if(mMaterial && GetImplementation(mMaterial).IsResourceReady())
{
- ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag::SHADER);
+ ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag::SHADER, hash);
}
}
}
mBlendShapeVersion = version;
}
-void ModelPrimitive::SetSkinned(bool isSkinned)
+void ModelPrimitive::SetSkinned(bool isSkinned, uint32_t numberOfJointSets)
+{
+ mHasSkinning = isSkinned;
+ mNumberOfJointSets = numberOfJointSets;
+}
+
+void ModelPrimitive::SetVertexColor(bool hasVertexColor)
{
- mHasSkinning = isSkinned;
+ mHasVertexColor = hasVertexColor;
}
// From MaterialModifyObserver
ApplyMaterialToRenderer(flag);
}
-void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag)
+void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag, Loader::ShaderOption::HashType oldHash)
{
if(!mMaterial)
{
if(mHasSkinning)
{
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)
{
}
}
- mShader.Reset();
- mShader = mShaderManager->ProduceShader(shaderOption);
+ Shader newShader = mShaderManager->ProduceShader(shaderOption);
+ if(mShader != newShader)
+ {
+ DALI_LOG_INFO(gLogFilter, Debug::General, "Warning! Model primitive shader changed: OldHash:%x NewHash:%x\n", oldHash, shaderOption.GetOptionHash());
+
+#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)
{
}
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;
}
}
+void ModelPrimitive::UpdateShadowMapTexture()
+{
+ if(mRenderer && mMaterial)
+ {
+ 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);
+ }
+ }
+}
+
void ModelPrimitive::UpdateImageBasedLightTexture()
{
if(mRenderer && mMaterial)