2 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-scene3d/internal/model-components/material-impl.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/public-api/object/type-registry-helper.h>
24 #include <dali/public-api/object/type-registry.h>
25 #include <dali/public-api/rendering/sampler.h>
28 #include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
29 #include <dali-scene3d/internal/light/light-impl.h>
30 #include <dali-scene3d/internal/model-components/material-modify-observer.h>
31 #include <dali-scene3d/public-api/loader/node-definition.h>
32 #include <dali-scene3d/public-api/loader/renderer-state.h>
33 #include <dali-scene3d/public-api/loader/shader-option.h>
34 #include <dali-scene3d/public-api/loader/utils.h>
45 * Creates Material through type registry
49 return Scene3D::Material::New();
52 // Setup properties, signals and actions using the type-registry.
53 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::Material, Dali::BaseHandle, Create);
54 DALI_TYPE_REGISTRATION_END()
56 static constexpr uint32_t OFFSET_FOR_SHADOW_MAP_TEXTURE = 4u;
57 static constexpr uint32_t OFFSET_FOR_DIFFUSE_CUBE_TEXTURE = 2u;
58 static constexpr uint32_t OFFSET_FOR_SPECULAR_CUBE_TEXTURE = 1u;
59 static constexpr uint32_t INVALID_INDEX = 0u;
60 static constexpr uint32_t ALPHA_CUTOFF_FLAG = Scene3D::Loader::MaterialDefinition::Flags::SUBSURFACE << 1;
61 static constexpr std::string_view THREE_TEX_KEYWORD = "THREE_TEX";
62 static constexpr std::string_view GLTF_CHANNELS_KEYWORD = "GLTF_CHANNELS";
64 static constexpr Vector3 IBL_BASIS(1.0f, -1.0f, 1.0f);
79 * @brief Helper API to register uniform property only if don't register before.
81 * @tparam T Type of uniform value.
82 * @param[in] renderer The renderer what we want to check / register property.
83 * @param[in] uniformName The name of uniform.
84 * @param[in] defaultUniformValue The default value if renderer don't register given uniform before.
87 void RegisterUniformIfNotDefinedBefore(Renderer renderer, const std::string_view& uniformName, const T& defaultUniformValue)
89 if(renderer.GetPropertyIndex(uniformName.data()) == Property::INVALID_INDEX)
91 renderer.RegisterProperty(uniformName, defaultUniformValue);
95 } // unnamed namespace
97 MaterialPtr Material::New()
99 MaterialPtr material = new Material();
101 material->Initialize();
108 mModifyFlag(MaterialModifyObserver::ModifyFlag::NONE),
109 mObserverNotifying(false)
111 mAsyncImageLoader = Dali::Toolkit::AsyncImageLoader::New();
112 mAsyncImageLoader.ImageLoadedSignal().Connect(this, &Material::TextureLoadComplete);
113 mTextureInformations.assign(TEXTURE_TYPE_NUMBER, TextureInformation());
114 mTextureInformations[BASE_COLOR].mSemantic = Scene3D::Loader::MaterialDefinition::ALBEDO;
115 // TODO : How we support dli manner
116 mTextureInformations[METALLIC_ROUGHNESS].mSemantic = Scene3D::Loader::MaterialDefinition::METALLIC | Scene3D::Loader::MaterialDefinition::ROUGHNESS |
117 Scene3D::Loader::MaterialDefinition::GLTF_CHANNELS;
118 mTextureInformations[NORMAL].mSemantic = Scene3D::Loader::MaterialDefinition::NORMAL;
119 mTextureInformations[OCCLUSION].mSemantic = Scene3D::Loader::MaterialDefinition::OCCLUSION;
120 mTextureInformations[EMISSIVE].mSemantic = Scene3D::Loader::MaterialDefinition::EMISSIVE;
121 mTextureInformations[SPECULAR].mSemantic = Scene3D::Loader::MaterialDefinition::SPECULAR;
122 mTextureInformations[SPECULAR_COLOR].mSemantic = Scene3D::Loader::MaterialDefinition::SPECULAR_COLOR;
124 mTextureInformations[BASE_COLOR].mShaderOptionType = Loader::ShaderOption::Type::BASE_COLOR_TEXTURE;
125 mTextureInformations[METALLIC_ROUGHNESS].mShaderOptionType = Loader::ShaderOption::Type::METALLIC_ROUGHNESS_TEXTURE;
126 mTextureInformations[NORMAL].mShaderOptionType = Loader::ShaderOption::Type::NORMAL_TEXTURE;
127 mTextureInformations[OCCLUSION].mShaderOptionType = Loader::ShaderOption::Type::OCCLUSION;
128 mTextureInformations[EMISSIVE].mShaderOptionType = Loader::ShaderOption::Type::EMISSIVE;
129 mTextureInformations[SPECULAR].mShaderOptionType = Loader::ShaderOption::Type::SPECULAR;
130 mTextureInformations[SPECULAR_COLOR].mShaderOptionType = Loader::ShaderOption::Type::SPECULAR_COLOR;
132 mTextureInformations[TextureIndex::EMISSIVE].mFactor = Vector4::ZERO;
135 Material::~Material() = default;
137 void Material::Initialize()
141 void Material::SetProperty(Dali::Property::Index index, Dali::Property::Value propertyValue)
143 bool needToApply = true;
146 case Dali::Scene3D::Material::Property::NAME:
149 if(propertyValue.Get(name))
156 case Dali::Scene3D::Material::Property::BASE_COLOR_URL:
158 std::string baseColorUrl;
159 if(propertyValue.Get(baseColorUrl))
161 RequestTextureLoad(mTextureInformations[TextureIndex::BASE_COLOR], baseColorUrl);
166 case Dali::Scene3D::Material::Property::BASE_COLOR_FACTOR:
168 Vector4 baseColorFactor;
169 if(propertyValue.Get(baseColorFactor))
171 mTextureInformations[TextureIndex::BASE_COLOR].mFactor = baseColorFactor;
172 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
176 case Dali::Scene3D::Material::Property::METALLIC_ROUGHNESS_URL:
178 std::string metallicRoughnessUrl;
179 if(propertyValue.Get(metallicRoughnessUrl))
181 RequestTextureLoad(mTextureInformations[TextureIndex::METALLIC_ROUGHNESS], metallicRoughnessUrl);
186 case Dali::Scene3D::Material::Property::METALLIC_FACTOR:
188 float metallicFactor;
189 if(propertyValue.Get(metallicFactor))
191 mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.x = metallicFactor;
192 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
196 case Dali::Scene3D::Material::Property::ROUGHNESS_FACTOR:
198 float roughnessFactor;
199 if(propertyValue.Get(roughnessFactor))
201 mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.y = roughnessFactor;
202 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
206 case Dali::Scene3D::Material::Property::NORMAL_URL:
208 std::string normalUrl;
209 if(propertyValue.Get(normalUrl))
211 RequestTextureLoad(mTextureInformations[TextureIndex::NORMAL], normalUrl);
216 case Dali::Scene3D::Material::Property::NORMAL_SCALE:
219 if(propertyValue.Get(normalScale))
221 mTextureInformations[TextureIndex::NORMAL].mFactor.x = normalScale;
222 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
226 case Dali::Scene3D::Material::Property::OCCLUSION_URL:
228 std::string occlusionUrl;
229 if(propertyValue.Get(occlusionUrl))
231 RequestTextureLoad(mTextureInformations[TextureIndex::OCCLUSION], occlusionUrl);
236 case Dali::Scene3D::Material::Property::OCCLUSION_STRENGTH:
238 float occlusionStrength;
239 if(propertyValue.Get(occlusionStrength))
241 mTextureInformations[TextureIndex::OCCLUSION].mFactor.x = occlusionStrength;
242 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
246 case Dali::Scene3D::Material::Property::EMISSIVE_URL:
248 std::string emissiveUrl;
249 if(propertyValue.Get(emissiveUrl))
251 RequestTextureLoad(mTextureInformations[TextureIndex::EMISSIVE], emissiveUrl);
256 case Dali::Scene3D::Material::Property::EMISSIVE_FACTOR:
258 Vector3 emissiveFactor;
259 if(propertyValue.Get(emissiveFactor))
261 mTextureInformations[TextureIndex::EMISSIVE].mFactor = emissiveFactor;
262 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
266 case Dali::Scene3D::Material::Property::ALPHA_MODE:
268 Dali::Scene3D::Material::AlphaModeType alphaMode;
269 if(propertyValue.Get(alphaMode))
271 mAlphaMode = alphaMode;
272 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
276 case Dali::Scene3D::Material::Property::ALPHA_CUTOFF:
279 if(propertyValue.Get(alphaCutoff))
281 mAlphaCutoff = alphaCutoff;
282 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
286 case Dali::Scene3D::Material::Property::DOUBLE_SIDED:
289 if(propertyValue.Get(doubleSided))
291 mDoubleSided = doubleSided;
292 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
296 case Dali::Scene3D::Material::Property::IOR:
299 if(propertyValue.Get(ior))
302 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
306 case Dali::Scene3D::Material::Property::SPECULAR_URL:
308 std::string specularUrl;
309 if(propertyValue.Get(specularUrl))
311 RequestTextureLoad(mTextureInformations[TextureIndex::SPECULAR], specularUrl);
316 case Dali::Scene3D::Material::Property::SPECULAR_FACTOR:
318 float specularFactor;
319 if(propertyValue.Get(specularFactor))
321 mTextureInformations[TextureIndex::SPECULAR].mFactor.x = specularFactor;
322 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
326 case Dali::Scene3D::Material::Property::SPECULAR_COLOR_URL:
328 std::string specularColorUrl;
329 if(propertyValue.Get(specularColorUrl))
331 RequestTextureLoad(mTextureInformations[TextureIndex::SPECULAR_COLOR], specularColorUrl);
336 case Dali::Scene3D::Material::Property::SPECULAR_COLOR_FACTOR:
338 Vector3 specularColorFactor;
339 if(propertyValue.Get(specularColorFactor))
341 mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor = specularColorFactor;
342 mModifyFlag |= MaterialModifyObserver::ModifyFlag::UNIFORM;
346 case Dali::Scene3D::Material::Property::DEPTH_INDEX:
348 int32_t depthIndex = 0;
349 if(propertyValue.Get(depthIndex) && mDepthIndex != depthIndex)
351 mDepthIndex = depthIndex;
352 mModifyFlag |= MaterialModifyObserver::ModifyFlag::PROPERTY;
364 Dali::Property::Value Material::GetProperty(Dali::Property::Index index) const
366 Dali::Property::Value value;
369 case Dali::Scene3D::Material::Property::NAME:
374 case Dali::Scene3D::Material::Property::BASE_COLOR_URL:
376 value = mTextureInformations[TextureIndex::BASE_COLOR].mUrl;
379 case Dali::Scene3D::Material::Property::BASE_COLOR_FACTOR:
381 value = mTextureInformations[TextureIndex::BASE_COLOR].mFactor;
384 case Dali::Scene3D::Material::Property::METALLIC_ROUGHNESS_URL:
386 value = mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mUrl;
389 case Dali::Scene3D::Material::Property::METALLIC_FACTOR:
391 value = mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.x;
394 case Dali::Scene3D::Material::Property::ROUGHNESS_FACTOR:
396 value = mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.y;
399 case Dali::Scene3D::Material::Property::NORMAL_URL:
401 value = mTextureInformations[TextureIndex::NORMAL].mUrl;
404 case Dali::Scene3D::Material::Property::NORMAL_SCALE:
406 value = mTextureInformations[TextureIndex::NORMAL].mFactor.x;
409 case Dali::Scene3D::Material::Property::OCCLUSION_URL:
411 value = mTextureInformations[TextureIndex::OCCLUSION].mUrl;
414 case Dali::Scene3D::Material::Property::OCCLUSION_STRENGTH:
416 value = mTextureInformations[TextureIndex::OCCLUSION].mFactor.x;
419 case Dali::Scene3D::Material::Property::EMISSIVE_URL:
421 value = mTextureInformations[TextureIndex::EMISSIVE].mUrl;
424 case Dali::Scene3D::Material::Property::EMISSIVE_FACTOR:
426 value = Vector3(mTextureInformations[TextureIndex::EMISSIVE].mFactor);
429 case Dali::Scene3D::Material::Property::ALPHA_MODE:
434 case Dali::Scene3D::Material::Property::ALPHA_CUTOFF:
436 value = mAlphaCutoff;
439 case Dali::Scene3D::Material::Property::DOUBLE_SIDED:
441 value = mDoubleSided;
444 case Dali::Scene3D::Material::Property::IOR:
449 case Dali::Scene3D::Material::Property::SPECULAR_URL:
451 value = mTextureInformations[TextureIndex::SPECULAR].mUrl;
454 case Dali::Scene3D::Material::Property::SPECULAR_FACTOR:
456 value = mTextureInformations[TextureIndex::SPECULAR].mFactor.x;
459 case Dali::Scene3D::Material::Property::SPECULAR_COLOR_URL:
461 value = mTextureInformations[TextureIndex::SPECULAR_COLOR].mUrl;
464 case Dali::Scene3D::Material::Property::SPECULAR_COLOR_FACTOR:
466 value = Vector3(mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor);
469 case Dali::Scene3D::Material::Property::DEPTH_INDEX:
478 void Material::SetTextureInformation(Scene3D::Material::TextureType index, TextureInformation&& textureInformation)
480 mTextureInformations[index].mFactor = textureInformation.mFactor;
481 mTextureInformations[index].mSampler = textureInformation.mSampler;
482 mTextureInformations[index].mTexture = textureInformation.mTexture;
483 mTextureInformations[index].mUrl = std::move(textureInformation.mUrl);
486 void Material::SetTexture(Scene3D::Material::TextureType index, Dali::Texture texture)
488 if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
490 if(mTextureInformations[index].mTexture != texture)
492 if(mTextureInformations[index].mLoadingTaskId != INVALID_INDEX)
494 mAsyncImageLoader.Cancel(mTextureInformations[index].mLoadingTaskId);
495 mTextureInformations[index].mLoadingTaskId = INVALID_INDEX;
497 mTextureInformations[index].mTexture = texture;
498 if(IsResourceReady())
500 ResourcesLoadComplete();
506 Dali::Texture Material::GetTexture(Scene3D::Material::TextureType index)
508 if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
510 return mTextureInformations[index].mTexture;
512 return Dali::Texture();
515 TextureSet Material::GetTextureSet()
517 TextureSet textures = TextureSet::New();
518 for(uint32_t i = 0, count = 0; i < TEXTURE_TYPE_NUMBER; ++i)
520 if(!mTextureInformations[i].mTexture)
524 textures.SetTexture(count, mTextureInformations[i].mTexture);
525 Sampler sampler = mTextureInformations[i].mSampler;
528 auto samplerFlag = Scene3D::Loader::SamplerFlags::FILTER_LINEAR | (Scene3D::Loader::SamplerFlags::FILTER_LINEAR << Scene3D::Loader::SamplerFlags::FILTER_MAG_SHIFT) |
529 (Scene3D::Loader::SamplerFlags::WRAP_REPEAT << Scene3D::Loader::SamplerFlags::WRAP_S_SHIFT) | (Scene3D::Loader::SamplerFlags::WRAP_REPEAT << Scene3D::Loader::SamplerFlags::WRAP_T_SHIFT);
530 sampler = Scene3D::Loader::SamplerFlags::MakeSampler(samplerFlag);
532 textures.SetSampler(count, sampler);
538 void Material::SetSampler(Scene3D::Material::TextureType index, Dali::Sampler sampler)
540 if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
542 mTextureInformations[index].mSampler = sampler;
546 Dali::Sampler Material::GetSampler(Scene3D::Material::TextureType index)
548 if(static_cast<uint32_t>(index) < static_cast<uint32_t>(TextureIndex::TEXTURE_TYPE_NUMBER))
550 return mTextureInformations[index].mSampler;
552 return Dali::Sampler();
555 Scene3D::Loader::ShaderOption Material::GetShaderOption() const
557 return mShaderOption;
560 void Material::Apply()
562 if(IsResourceReady())
564 UpdateMaterialData();
568 // The cases this material is applied to primitive are,
569 // 1. material is added on Primitive.
570 // When material is added on Primitive (1 case)
571 // 1-1. when IsResourceReady() returns true,
572 // Primitive can takes information from Material
574 // Material will noti to primitives when all resources are ready.
575 // 2. Some properties are changed
576 // 2-1. when IsResourceReady() returns true,
577 // Call NotifyObserver directly.
579 // Material will noti to primitives when all resources are ready.
582 void Material::AddObserver(MaterialModifyObserver* observer)
584 for(auto& observerEntity : mObservers)
586 if(observerEntity.first == observer)
588 observerEntity.second = true;
592 mObservers.push_back({observer, true});
595 void Material::RemoveObserver(MaterialModifyObserver* observer)
597 // Block during notifying to observer
598 if(mObserverNotifying)
600 for(uint32_t i = 0; i < mObservers.size(); ++i)
602 if(mObservers[i].first == observer)
604 mObservers[i].second = false;
611 for(uint32_t i = 0; i < mObservers.size(); ++i)
613 if(mObservers[i].first == observer)
615 mObservers.erase(mObservers.begin() + i);
622 void Material::UpdateMaterialData()
624 uint32_t materialFlag = 0u;
625 if(mAlphaMode == Dali::Scene3D::Material::AlphaModeType::BLEND)
629 materialFlag |= Scene3D::Loader::MaterialDefinition::TRANSPARENCY;
631 else if(mAlphaMode == Dali::Scene3D::Material::AlphaModeType::MASK)
636 const bool hasTransparency = MaskMatch(materialFlag, Scene3D::Loader::MaterialDefinition::TRANSPARENCY);
638 for(auto&& textureInformation : mTextureInformations)
640 if(!textureInformation.mTexture)
644 materialFlag |= textureInformation.mSemantic;
647 if(mMaterialFlag != materialFlag)
649 mModifyFlag |= MaterialModifyObserver::ModifyFlag::SHADER;
651 mMaterialFlag = materialFlag;
653 mShaderOption = Loader::ShaderOption();
654 for(auto&& textureInformation : mTextureInformations)
656 if(!textureInformation.mTexture)
660 mShaderOption.AddOption(textureInformation.mShaderOptionType);
662 mShaderOption.AddOption(Loader::ShaderOption::Type::THREE_TEXTURE);
663 mShaderOption.AddOption(Loader::ShaderOption::Type::GLTF_CHANNELS);
664 if(materialFlag & Scene3D::Loader::MaterialDefinition::TRANSPARENCY)
666 mShaderOption.SetTransparency();
670 // Finish to make all the material flag according to the gltf2-util.
671 // Then make defines as fallowing shader-manager.
673 // The renderer State below can be used in primitive to set renderer properties.
675 // for renderer setting
676 mRendererState = Scene3D::Loader::RendererState::DEPTH_TEST;
679 mRendererState |= Scene3D::Loader::RendererState::CULL_BACK;
684 mRendererState = (mRendererState | Scene3D::Loader::RendererState::ALPHA_BLEND);
688 bool Material::IsResourceReady()
690 for(auto&& textureInformation : mTextureInformations)
692 if(!textureInformation.IsReady())
700 void Material::SetRendererUniform(Dali::Renderer renderer)
702 renderer.RegisterProperty("uColorFactor", mTextureInformations[TextureIndex::BASE_COLOR].mFactor);
703 renderer.RegisterProperty("uMetallicFactor", mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.x);
704 renderer.RegisterProperty("uRoughnessFactor", mTextureInformations[TextureIndex::METALLIC_ROUGHNESS].mFactor.y);
705 renderer.RegisterProperty("uNormalScale", mTextureInformations[TextureIndex::NORMAL].mFactor.x);
706 if(mTextureInformations[TextureIndex::OCCLUSION].mTexture)
708 renderer.RegisterProperty("uOcclusionStrength", mTextureInformations[TextureIndex::OCCLUSION].mFactor.x);
710 renderer.RegisterProperty("uEmissiveFactor", Vector3(mTextureInformations[TextureIndex::EMISSIVE].mFactor));
711 float dielectricSpecular = (Dali::Equals(mIor, -1.0)) ? 0.04f : powf((mIor - 1.0f) / (mIor + 1.0f), 2.0f);
712 renderer.RegisterProperty("uDielectricSpecular", dielectricSpecular);
713 renderer.RegisterProperty("uSpecularFactor", mTextureInformations[TextureIndex::SPECULAR].mFactor.x);
714 renderer.RegisterProperty("uSpecularColorFactor", Vector3(mTextureInformations[TextureIndex::SPECULAR_COLOR].mFactor));
716 float opaque = mIsOpaque ? 1.0f : 0.0f;
717 float mask = mIsMask ? 1.0f : 0.0f;
718 renderer.RegisterProperty("uOpaque", opaque);
719 renderer.RegisterProperty("uMask", mask);
720 renderer.RegisterProperty("uAlphaThreshold", mAlphaCutoff);
722 // Setup default uniform values what we might need.
723 RegisterUniformIfNotDefinedBefore(renderer, "uBaseColorTextureTransformAvailable", 0.0f);
724 RegisterUniformIfNotDefinedBefore(renderer, "uNormalTextureTransformAvailable", 0.0f);
725 RegisterUniformIfNotDefinedBefore(renderer, "uNormalRoughnessTextureTransformAvailable", 0.0f);
726 RegisterUniformIfNotDefinedBefore(renderer, "uMetalRoughnessTextureTransformAvailable", 0.0f);
727 RegisterUniformIfNotDefinedBefore(renderer, "uOcclusionTextureTransformAvailable", 0.0f);
728 RegisterUniformIfNotDefinedBefore(renderer, "uEmissiveTextureTransformAvailable", 0.0f);
730 RegisterUniformIfNotDefinedBefore(renderer, "uBaseColorTextureTransform", Matrix3::IDENTITY);
731 RegisterUniformIfNotDefinedBefore(renderer, "uNormalRoughnessTextureTransform", Matrix3::IDENTITY);
732 RegisterUniformIfNotDefinedBefore(renderer, "uNormalTextureTransform", Matrix3::IDENTITY);
733 RegisterUniformIfNotDefinedBefore(renderer, "uMetalRoughnessTextureTransform", Matrix3::IDENTITY);
734 RegisterUniformIfNotDefinedBefore(renderer, "uOcclusionTextureTransform", Matrix3::IDENTITY);
735 RegisterUniformIfNotDefinedBefore(renderer, "uEmissiveTextureTransform", Matrix3::IDENTITY);
737 RegisterUniformIfNotDefinedBefore(renderer, "uCubeMatrix", Matrix::IDENTITY);
739 RegisterUniformIfNotDefinedBefore(renderer, Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName(), 1.0f);
740 RegisterUniformIfNotDefinedBefore(renderer, Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName(), 1.0f);
741 RegisterUniformIfNotDefinedBefore(renderer, Scene3D::Loader::NodeDefinition::GetIblYDirectionUniformName(), IBL_BASIS);
743 Scene3D::Loader::RendererState::Apply(mRendererState, renderer);
746 void Material::SetRendererProperty(Dali::Renderer renderer)
748 renderer.SetProperty(Dali::Renderer::Property::DEPTH_INDEX, mDepthIndex);
751 uint32_t Material::GetShadowMapTextureOffset()
753 return OFFSET_FOR_SHADOW_MAP_TEXTURE;
756 uint32_t Material::GetSpecularImageBasedLightTextureOffset()
758 return OFFSET_FOR_SPECULAR_CUBE_TEXTURE;
761 uint32_t Material::GetDiffuseImageBasedLightTextureOffset()
763 return OFFSET_FOR_DIFFUSE_CUBE_TEXTURE;
766 std::string_view Material::GetImageBasedLightScaleFactorName()
768 return Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName();
771 std::string_view Material::GetImageBasedLightMaxLodUniformName()
773 return Dali::Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName();
776 void Material::ResetFlag()
778 mModifyFlag = MaterialModifyObserver::ModifyFlag::NONE;
781 void Material::NotifyObserver()
783 if(mModifyFlag != MaterialModifyObserver::ModifyFlag::NONE && IsResourceReady())
785 if(mObserverNotifying)
787 DALI_LOG_ERROR("Notify during observing is not allowed.");
791 Dali::Scene3D::Material handle(this); // Keep itself's life during notify
793 // Copy the flag due to the flag can be changed during observe.
794 MaterialModifyObserver::ModifyFlag copiedFlag = mModifyFlag;
795 mModifyFlag = MaterialModifyObserver::ModifyFlag::NONE;
797 // Need to block mObserver container change during observe
798 mObserverNotifying = true;
799 for(uint32_t i = 0; i < mObservers.size(); ++i)
801 if(mObservers[i].second)
803 mObservers[i].first->OnMaterialModified(handle, copiedFlag);
806 mObserverNotifying = false;
808 // Resolve observer queue during notify
809 mObservers.erase(std::remove_if(mObservers.begin(), mObservers.end(), [](auto& e) { return !e.second; }),
814 void Material::RequestTextureLoad(TextureInformation& textureInformation, const std::string& url)
816 if(textureInformation.mUrl == url)
821 textureInformation.mUrl = url;
822 if(textureInformation.mLoadingTaskId != INVALID_INDEX)
824 mAsyncImageLoader.Cancel(textureInformation.mLoadingTaskId);
825 textureInformation.mLoadingTaskId = INVALID_INDEX;
830 textureInformation.mTexture.Reset();
833 textureInformation.mLoadingTaskId = mAsyncImageLoader.Load(url);
836 void Material::TextureLoadComplete(uint32_t loadedTaskId, PixelData pixelData)
838 for(auto&& textureInformation : mTextureInformations)
840 if(textureInformation.mLoadingTaskId != loadedTaskId)
847 textureInformation.mTexture = Texture::New(Dali::TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
848 textureInformation.mTexture.Upload(pixelData);
850 textureInformation.mLoadingTaskId = INVALID_INDEX;
854 if(IsResourceReady())
856 ResourcesLoadComplete();
860 void Material::ResourcesLoadComplete()
862 mModifyFlag |= MaterialModifyObserver::ModifyFlag::TEXTURE;
866 } // namespace Internal
868 } // namespace Scene3D