return static_cast<uint32_t>(mModelPrimitiveContainer.size());
}
-void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
+void ModelNode::AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive, Loader::ShaderOption::HashType hash)
{
for(auto&& primitive : mModelPrimitiveContainer)
{
GetImplementation(modelPrimitive).SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
}
- GetImplementation(modelPrimitive).UpdateShader(mShaderManager);
+ GetImplementation(modelPrimitive).UpdateShader(mShaderManager, hash);
Dali::Renderer renderer = GetImplementation(modelPrimitive).GetRenderer();
if(renderer)
return;
}
- GetImplementation(mModelPrimitiveContainer[index]).UpdateShader(nullptr);
+ GetImplementation(mModelPrimitiveContainer[index]).UpdateShader(nullptr, 0u);
Actor self = Self();
GetImplementation(mModelPrimitiveContainer[index]).RemovePrimitiveObserver(this);
mShaderManager = shaderManager;
for(auto&& primitive : mModelPrimitiveContainer)
{
- GetImplementation(primitive).UpdateShader(mShaderManager);
+ GetImplementation(primitive).UpdateShader(mShaderManager, 0u);
}
}
}
#include <dali-scene3d/public-api/light/light.h>
#include <dali-scene3d/public-api/loader/mesh-definition.h>
#include <dali-scene3d/public-api/loader/shader-manager.h>
+#include <dali-scene3d/public-api/loader/shader-option.h>
#include <dali-scene3d/public-api/loader/skinning-details.h>
#include <dali-scene3d/public-api/model-components/model-node.h>
#include <dali-scene3d/public-api/model-components/model-primitive.h>
/**
* @copydoc Dali::Scene3D::ModelNode::AddModelPrimitive()
*/
- void AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive);
+ void AddModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive, Loader::ShaderOption::HashType hash);
/**
* @copydoc Dali::Scene3D::ModelNode::RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)
Scene3D::Loader::ShaderManagerPtr mShaderManager;
ModelPrimitiveContainer mModelPrimitiveContainer; ///< List of model primitives
BoneDataContainer mBoneDataContainer;
- BlendShapeIndexMap mBlendShapeIndexMap; ///< Index of blend shape by name
+ BlendShapeIndexMap mBlendShapeIndexMap; ///< Index of blend shape by name
Dali::Texture mShadowMapTexture;
Dali::Texture mSpecularTexture;
Dali::Texture mDiffuseTexture;
#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
{
#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(); \
}
}
-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);
}
}
}
mNumberOfJointSets = numberOfJointSets;
}
+void ModelPrimitive::SetVertexColor(bool hasVertexColor)
+{
+ mHasVertexColor = hasVertexColor;
+}
+
// From MaterialModifyObserver
void ModelPrimitive::OnMaterialModified(Dali::Scene3D::Material material, MaterialModifyObserver::ModifyFlag flag)
ApplyMaterialToRenderer(flag);
}
-void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag)
+void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag, Loader::ShaderOption::HashType oldHash)
{
if(!mMaterial)
{
shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::SKINNING);
shaderOption.AddJointMacros(mNumberOfJointSets);
}
+ if(mHasVertexColor)
+ {
+ shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::COLOR_ATTRIBUTE);
+ }
if(mHasPositions || mHasNormals || mHasTangents)
{
if(mHasPositions)
Shader newShader = mShaderManager->ProduceShader(shaderOption);
if(mShader != newShader)
{
- DALI_LOG_INFO(gLogFilter, Debug::General, "Warning! Model primitive shader changed\n");
+ 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("oldShader.txt", "Vertex Shader:\n"
- << oldMap["vertex"] << "\n\nFragmentShader: " << oldMap["fragment"] << "\n");
+ 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("newShader.txt", "Vertex Shader:\n"
- << newMap["vertex"] << "\n\nFragmentShader: " << newMap["fragment"] << "\n");
+ DALI_LOG_WRITE_FILE(tmpFilename("newShader", ".txt"), "Vertex Shader:\n"
+ << newMap["vertex"] << "\n\nFragmentShader: " << newMap["fragment"] << "\n");
}
#endif
}
* @brief Updates shaders by using current material
*
* @param[in] shaderManager Shader manager to create shader.
+ * @param[in] hash of old shader option
*/
- void UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager);
+ void UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager, Loader::ShaderOption::HashType hash);
/**
* @brief Sets the blend shape data for this model primitive.
*/
void SetSkinned(bool isSkinned, uint32_t numberOfJointSets);
+ /**
+ * @brief Set whether this model primitve has vertex color attributes
+ *
+ * @param[in] hasVertexColor Whether or not this model primitive has vertex color attributes
+ */
+ void SetVertexColor(bool hasVertexColor);
+
private: // From MaterialModifyObserver
/**
* @copydoc Dali::Scene3D::Internal::Material::MaterialModifyObserver::OnMaterialModified()
/**
* @brief Apply materials data into renderer.
*/
- void ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag = MaterialModifyObserver::ModifyFlag::NONE);
+ void ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag = MaterialModifyObserver::ModifyFlag::NONE,
+ Loader::ShaderOption::HashType oldHash = 0u);
/**
* @brief Updates the uniform of renderer.
Scene3D::Loader::BlendShapes::BlendShapeData mBlendShapeData;
Dali::Texture mBlendShapeGeometry;
bool mHasSkinning = false;
+ bool mHasVertexColor = false;
bool mHasPositions = false;
bool mHasNormals = false;
bool mHasTangents = false;
{
return !mJoints.empty() && !mWeights.empty();
}
+
+bool MeshDefinition::HasVertexColor() const
+{
+ return !mColors.empty();
+}
+
uint32_t MeshDefinition::GetNumberOfJointSets() const
{
return static_cast<uint32_t>(mJoints.size());
bool IsSkinned() const;
/**
+ * @brief Determines if the mesh has any vertex colors
+ */
+ bool HasVertexColor() const;
+
+ /**
* @brief Returns the number of joint sets defined by the mesh
*/
uint32_t GetNumberOfJointSets() const;
reflector.Reflect(ResourceType::Material, mMaterialIdx);
}
+// How many shader managers are there?!
void ModelRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const
{
DALI_ASSERT_DEBUG(mMeshIdx != INVALID_INDEX);
+ ShaderOption::HashType shaderOptionHash{0u};
if(mShaderIdx == INVALID_INDEX)
{
- Shader shader = params.mShaderManager->ProduceShader(params.mResources.mMaterials[mMaterialIdx].first, params.mResources.mMeshes[mMeshIdx].first);
+ ShaderOption option = params.mShaderManager->ProduceShaderOption(params.mResources.mMaterials[mMaterialIdx].first,
+ params.mResources.mMeshes[mMeshIdx].first);
+ shaderOptionHash = option.GetOptionHash();
+ Shader shader = params.mShaderManager->ProduceShader(option);
+
static Geometry defaultGeometry = Geometry::New();
Renderer renderer = Renderer::New(defaultGeometry, shader);
{
mesh.first.mModelPrimitive = ModelPrimitive::New();
- auto primitive = mesh.first.mModelPrimitive;
- GetImplementation(primitive).SetRenderer(renderer);
+ auto& primitive = GetImplementation(mesh.first.mModelPrimitive);
+ primitive.SetRenderer(renderer);
Index envIndex = resources.mMaterials[mMaterialIdx].first.mEnvironmentIdx;
uint32_t specularMipmap = resources.mEnvironmentMaps[envIndex].second.mSpecularMipmapLevels;
- GetImplementation(primitive).SetImageBasedLightTexture(resources.mEnvironmentMaps[envIndex].second.mDiffuse,
- resources.mEnvironmentMaps[envIndex].second.mSpecular,
- resources.mEnvironmentMaps[envIndex].first.mIblIntensity,
- specularMipmap);
+ primitive.SetImageBasedLightTexture(resources.mEnvironmentMaps[envIndex].second.mDiffuse,
+ resources.mEnvironmentMaps[envIndex].second.mSpecular,
+ resources.mEnvironmentMaps[envIndex].first.mIblIntensity,
+ specularMipmap);
bool hasPositions = false;
bool hasNormals = false;
bool hasTangents = false;
mesh.first.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
- GetImplementation(primitive).SetBlendShapeOptions(hasPositions, hasNormals, hasTangents, mesh.first.mBlendShapeVersion);
- GetImplementation(primitive).SetBlendShapeGeometry(mesh.second.blendShapeGeometry);
- GetImplementation(primitive).SetSkinned(mesh.first.IsSkinned(), mesh.first.GetNumberOfJointSets());
+ primitive.SetBlendShapeOptions(hasPositions, hasNormals, hasTangents, mesh.first.mBlendShapeVersion);
+ primitive.SetBlendShapeGeometry(mesh.second.blendShapeGeometry);
+ primitive.SetSkinned(mesh.first.IsSkinned(), mesh.first.GetNumberOfJointSets());
+ primitive.SetVertexColor(mesh.first.HasVertexColor());
}
auto shader = renderer.GetShader();
material.SetProperty(Scene3D::Material::Property::ALPHA_CUTOFF, matDef.GetAlphaCutoff());
material.SetProperty(Scene3D::Material::Property::DOUBLE_SIDED, matDef.mDoubleSided);
material.SetProperty(Scene3D::Material::Property::IOR, matDef.mIor);
+
+ // This _should_ keep the same shader as generated at the top of the method.
GetImplementation(mesh.first.mModelPrimitive).SetMaterial(material, false);
GetImplementation(material).ResetFlag();
}
- node.AddModelPrimitive(mesh.first.mModelPrimitive);
+ Internal::GetImplementation(node).AddModelPrimitive(mesh.first.mModelPrimitive, shaderOptionHash);
}
void ArcRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const
ShaderManager::~ShaderManager() = default;
-Dali::Shader ShaderManager::ProduceShader(const MaterialDefinition& materialDefinition, const MeshDefinition& meshDefinition)
+ShaderOption ShaderManager::ProduceShaderOption(const MaterialDefinition& materialDefinition, const MeshDefinition& meshDefinition)
{
DALI_LOG_INFO(gLogFilter, Debug::Concise, "Defining shader from mat/mesh definitions\n");
- ShaderOption option = MakeOption(materialDefinition, meshDefinition);
- return ProduceShader(option);
+ return MakeOption(materialDefinition, meshDefinition);
}
Dali::Shader ShaderManager::ProduceShader(const ShaderOption& shaderOption)
// INTERNAL INCLUDES
#include <dali-scene3d/public-api/api.h>
+#include <dali-scene3d/public-api/light/light.h>
#include <dali-scene3d/public-api/loader/index.h>
#include <dali-scene3d/public-api/loader/material-definition.h>
#include <dali-scene3d/public-api/loader/mesh-definition.h>
#include <dali-scene3d/public-api/loader/renderer-state.h>
#include <dali-scene3d/public-api/loader/shader-option.h>
-#include <dali-scene3d/public-api/light/light.h>
namespace Dali::Scene3D::Loader
{
* (Although the input materialDefinition and meshDefinition are not identical to those used to create the cached Dali::Shader, they share the cached one.)
* @param[in] materialDefinition MaterialDefinition that includes information of material to create Shader.
* @param[in] meshDefinition meshDefinition that includes information of mesh to create Shader.
- * @return Dali::Shader for the materialDefinition and meshDefinition.
+ * @return ShaderOption for the materialDefinition and meshDefinition.
*/
- Dali::Shader ProduceShader(const MaterialDefinition& materialDefinition, const MeshDefinition& meshDefinition);
+ ShaderOption ProduceShaderOption(const MaterialDefinition& materialDefinition, const MeshDefinition& meshDefinition);
/**
* @brief Produces a Dali::Shader for the input ShaderOption
* @param[in] shader Shader that the constraint will be applied.
*/
DALI_INTERNAL void SetShadowConstraintToShader(Dali::Shader shader);
+
private:
struct Impl;
const std::unique_ptr<Impl> mImpl;
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
+ GLTF_CHANNELS = 0, // 00001
+ THREE_TEXTURE, // 00002
+ BASE_COLOR_TEXTURE, // 00004
+ METALLIC_ROUGHNESS_TEXTURE, // 00008
+ NORMAL_TEXTURE, // 00010
+ OCCLUSION, // 00020
+ EMISSIVE, // 00040
+ ALPHA_TEST, // 00080
+ SUBSURFACE, // 00100
+ SPECULAR, // 00200
+ SPECULAR_COLOR, // 00400
+ SKINNING, // 00800
+ FLIP_UVS_VERTICAL, // 01000
+ COLOR_ATTRIBUTE, // 02000
+ VEC4_TANGENT, // 04000
+ MORPH_POSITION, // 08000
+ MORPH_NORMAL, // 10000
+ MORPH_TANGENT, // 20000
+ MORPH_VERSION_2_0 // 40000
};
struct MacroDefinition
ShaderOption(const ShaderOption& rhs);
ShaderOption& operator=(const ShaderOption& rhs);
+ using HashType = uint64_t;
+
public:
/**
* @brief Sets transparency option.
*
* @return Hash value of currently added options.
*/
- uint64_t GetOptionHash() const;
+ HashType GetOptionHash() const;
/**
* @brief Retrieves a list of define keywords.
const std::vector<MacroDefinition>& GetMacroDefinitions() const;
private:
- uint64_t mOptionHash{0u};
+ HashType mOptionHash{0u};
std::vector<MacroDefinition> mMacros;
};
void ModelNode::AddModelPrimitive(ModelPrimitive modelPrimitive)
{
- Internal::GetImplementation(*this).AddModelPrimitive(modelPrimitive);
+ Internal::GetImplementation(*this).AddModelPrimitive(modelPrimitive, 0u);
}
void ModelNode::RemoveModelPrimitive(Dali::Scene3D::ModelPrimitive modelPrimitive)