2 * Copyright (c) 2023 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/model-primitive-impl.h>
22 #include <dali/devel-api/adaptor-framework/image-loading.h>
23 #include <dali/public-api/animation/constraint.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25 #include <dali/public-api/object/type-registry.h>
28 #include <dali-scene3d/internal/light/light-impl.h>
29 #include <dali-scene3d/internal/model-components/material-impl.h>
30 #include <dali-scene3d/public-api/loader/environment-definition.h>
32 #include <dali/integration-api/debug.h>
43 * Creates control through type registry
47 return Scene3D::ModelPrimitive::New();
50 // Setup properties, signals and actions using the type-registry.
51 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::ModelPrimitive, Dali::BaseHandle, Create);
52 DALI_TYPE_REGISTRATION_END()
54 static constexpr uint32_t INDEX_FOR_LIGHT_CONSTRAINT_TAG = 10;
56 Texture MakeEmptyTexture()
58 PixelData pixelData = PixelData::New(new uint8_t[3]{0xff, 0xff, 0xff}, 3, 1, 1, Pixel::RGB888, PixelData::DELETE_ARRAY);
59 Texture texture = Texture::New(TextureType::TEXTURE_2D, pixelData.GetPixelFormat(), pixelData.GetWidth(), pixelData.GetHeight());
60 texture.Upload(pixelData, 0, 0, 0, 0, pixelData.GetWidth(), pixelData.GetHeight());
64 } // unnamed namespace
66 ModelPrimitivePtr ModelPrimitive::New()
68 ModelPrimitivePtr primitive = new ModelPrimitive();
70 primitive->Initialize();
75 ModelPrimitive::ModelPrimitive()
76 : mShaderManager(new Scene3D::Loader::ShaderManager())
80 ModelPrimitive::~ModelPrimitive()
84 GetImplementation(mMaterial).RemoveObserver(this);
89 void ModelPrimitive::Initialize()
93 void ModelPrimitive::SetRenderer(Dali::Renderer renderer)
96 mGeometry = renderer.GetGeometry();
97 mTextureSet = renderer.GetTextures();
98 mShader = renderer.GetShader();
101 Dali::Renderer ModelPrimitive::GetRenderer() const
106 void ModelPrimitive::SetGeometry(Dali::Geometry geometry)
108 mGeometry = geometry;
112 Dali::Geometry ModelPrimitive::GetGeometry() const
117 void ModelPrimitive::SetMaterial(Dali::Scene3D::Material material, bool updateRenderer)
124 if(mMaterial != material)
126 // Stop observe from previous material.
129 GetImplementation(mMaterial).RemoveObserver(this);
132 mMaterial = material;
134 // Start observe from new material.
138 GetImplementation(mMaterial).AddObserver(this);
143 mIsMaterialChanged = true;
144 if(GetImplementation(mMaterial).IsResourceReady())
146 GetImplementation(mMaterial).UpdateMaterialData();
147 ApplyMaterialToRenderer();
150 UpdateShadowMapTexture();
151 UpdateImageBasedLightTexture();
155 Dali::Scene3D::Material ModelPrimitive::GetMaterial() const
160 void ModelPrimitive::AddPrimitiveObserver(ModelPrimitiveModifyObserver* observer)
162 mObservers.insert(observer);
165 void ModelPrimitive::RemovePrimitiveObserver(ModelPrimitiveModifyObserver* observer)
167 mObservers.erase(observer);
170 void ModelPrimitive::SetShadowMapTexture(Dali::Texture shadowMapTexture)
172 mShadowMapTexture = shadowMapTexture;
174 UpdateShadowMapTexture();
177 void ModelPrimitive::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float iblScaleFactor, uint32_t specularMipmapLevels)
179 mDiffuseTexture = diffuseTexture;
180 mSpecularTexture = specularTexture;
181 mIblScaleFactor = iblScaleFactor;
182 mSpecularMipmapLevels = specularMipmapLevels;
184 UpdateImageBasedLightTexture();
187 void ModelPrimitive::SetImageBasedLightScaleFactor(float iblScaleFactor)
189 mIblScaleFactor = iblScaleFactor;
190 if(mRenderer && mMaterial)
192 mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightScaleFactorName().data(), iblScaleFactor);
196 void ModelPrimitive::UpdateShader(Scene3D::Loader::ShaderManagerPtr shaderManager)
198 if(mShaderManager != shaderManager)
200 mShaderManager = (shaderManager) ? shaderManager : new Scene3D::Loader::ShaderManager();
201 if(mMaterial && GetImplementation(mMaterial).IsResourceReady())
203 ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag::SHADER);
208 void ModelPrimitive::SetBlendShapeData(Scene3D::Loader::BlendShapes::BlendShapeData& data)
210 mBlendShapeData = std::move(data);
211 Scene3D::Loader::BlendShapes::ConfigureProperties(mBlendShapeData, mRenderer);
214 void ModelPrimitive::SetBlendShapeGeometry(Dali::Texture blendShapeGeometry)
216 mBlendShapeGeometry = blendShapeGeometry;
219 void ModelPrimitive::SetBlendShapeOptions(bool hasPositions, bool hasNormals, bool hasTangents, Scene3D::Loader::BlendShapes::Version version)
221 mHasPositions = hasPositions;
222 mHasNormals = hasNormals;
223 mHasTangents = hasTangents;
224 mBlendShapeVersion = version;
227 void ModelPrimitive::SetSkinned(bool isSkinned)
229 mHasSkinning = isSkinned;
232 // From MaterialModifyObserver
234 void ModelPrimitive::OnMaterialModified(Dali::Scene3D::Material material, MaterialModifyObserver::ModifyFlag flag)
236 ApplyMaterialToRenderer(flag);
239 void ModelPrimitive::ApplyMaterialToRenderer(MaterialModifyObserver::ModifyFlag flag)
246 uint32_t shaderFlag = (flag & static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::SHADER));
247 if(mIsMaterialChanged || shaderFlag == static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::SHADER))
249 Scene3D::Loader::ShaderOption shaderOption = GetImplementation(mMaterial).GetShaderOption();
251 shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::VEC4_TANGENT);
254 shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::SKINNING);
256 if(mHasPositions || mHasNormals || mHasTangents)
260 shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::MORPH_POSITION);
264 shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::MORPH_NORMAL);
268 shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::MORPH_TANGENT);
270 if(mBlendShapeVersion == Scene3D::Loader::BlendShapes::Version::VERSION_2_0)
272 shaderOption.AddOption(Scene3D::Loader::ShaderOption::Type::MORPH_VERSION_2_0);
277 mShader = mShaderManager->ProduceShader(shaderOption);
285 mRenderer.SetShader(mShader);
289 uint32_t textureFlag = (flag & static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::TEXTURE));
290 if(mIsMaterialChanged || textureFlag == static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::TEXTURE))
292 mTextureSet = GetImplementation(mMaterial).GetTextureSet();
294 if(mBlendShapeGeometry)
296 TextureSet newTextureSet = TextureSet::New();
297 newTextureSet.SetTexture(0u, mBlendShapeGeometry);
299 const unsigned int numberOfTextures = mTextureSet.GetTextureCount();
300 for(unsigned int index = 0u; index < numberOfTextures; ++index)
302 const unsigned int newIndex = index + 1u;
303 newTextureSet.SetTexture(newIndex, mTextureSet.GetTexture(index));
304 newTextureSet.SetSampler(newIndex, mTextureSet.GetSampler(index));
307 mTextureSet = newTextureSet;
310 uint32_t textureCount = mTextureSet.GetTextureCount();
312 if(!mShadowMapTexture)
314 mShadowMapTexture = MakeEmptyTexture();
316 mTextureSet.SetTexture(textureCount++, mShadowMapTexture);
318 Texture brdfTexture = Scene3D::Loader::EnvironmentDefinition::GetBrdfTexture();
319 if(!mSpecularTexture || !mDiffuseTexture)
321 Scene3D::Loader::EnvironmentMapData environmentMapData;
322 environmentMapData.mPixelData.resize(6);
323 for(auto& face : environmentMapData.mPixelData)
325 face.push_back(PixelData::New(new uint8_t[3]{0xff, 0xff, 0xff}, 3, 1, 1, Pixel::RGB888, PixelData::DELETE_ARRAY));
327 environmentMapData.SetEnvironmentMapType(Dali::Scene3D::EnvironmentMapType::CUBEMAP);
328 Texture iblTexture = environmentMapData.GetTexture();
329 mDiffuseTexture = iblTexture;
330 mSpecularTexture = iblTexture;
333 mTextureSet.SetTexture(textureCount++, brdfTexture);
334 mTextureSet.SetTexture(textureCount++, mDiffuseTexture);
335 mTextureSet.SetTexture(textureCount, mSpecularTexture);
337 auto specularSampler = Sampler::New();
338 specularSampler.SetWrapMode(WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE, WrapMode::CLAMP_TO_EDGE);
339 specularSampler.SetFilterMode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR);
340 mTextureSet.SetSampler(textureCount, specularSampler);
348 mRenderer.SetTextures(mTextureSet);
352 uint32_t uniformFlag = (flag & static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::UNIFORM));
353 if(mIsMaterialChanged || uniformFlag == static_cast<uint32_t>(MaterialModifyObserver::ModifyFlag::UNIFORM))
357 mNeedToSetRendererUniform = true;
361 UpdateRendererUniform();
364 mIsMaterialChanged = false;
367 void ModelPrimitive::CreateRenderer()
369 if(!mShader || !mGeometry || !mTextureSet || mRenderer)
374 mRenderer = Renderer::New(mGeometry, mShader);
375 mRenderer.SetTextures(mTextureSet);
376 UpdateRendererUniform();
378 for(auto* observer : mObservers)
380 observer->OnRendererCreated(mRenderer);
384 void ModelPrimitive::UpdateShadowMapTexture()
386 if(mRenderer && mMaterial)
388 Dali::TextureSet textures = mRenderer.GetTextures();
394 uint32_t textureCount = textures.GetTextureCount();
395 if(mShadowMapTexture &&
396 textureCount >= GetImplementation(mMaterial).GetShadowMapTextureOffset() &&
397 textures.GetTexture(textureCount - GetImplementation(mMaterial).GetShadowMapTextureOffset()) != mShadowMapTexture)
399 Dali::TextureSet newTextures = Dali::TextureSet::New();
401 for(uint32_t index = 0u; index < textureCount; ++index)
403 Dali::Texture texture = textures.GetTexture(index);
404 if(index == textureCount - GetImplementation(mMaterial).GetShadowMapTextureOffset())
406 texture = (!!mShadowMapTexture) ? mShadowMapTexture : MakeEmptyTexture();
409 newTextures.SetTexture(index, texture);
410 newTextures.SetSampler(index, textures.GetSampler(index));
413 mRenderer.SetTextures(newTextures);
418 void ModelPrimitive::UpdateImageBasedLightTexture()
420 if(mRenderer && mMaterial)
422 Dali::TextureSet textures = mRenderer.GetTextures();
428 uint32_t textureCount = textures.GetTextureCount();
429 if(textureCount > 2u &&
430 (textures.GetTexture(textureCount - GetImplementation(mMaterial).GetDiffuseImageBasedLightTextureOffset()) != mDiffuseTexture ||
431 textures.GetTexture(textureCount - GetImplementation(mMaterial).GetSpecularImageBasedLightTextureOffset()) != mSpecularTexture))
433 Dali::TextureSet newTextures = Dali::TextureSet::New();
435 for(uint32_t index = 0u; index < textureCount; ++index)
437 Dali::Texture texture = textures.GetTexture(index);
438 if(index == textureCount - GetImplementation(mMaterial).GetDiffuseImageBasedLightTextureOffset())
440 texture = mDiffuseTexture;
442 else if(index == textureCount - GetImplementation(mMaterial).GetSpecularImageBasedLightTextureOffset())
444 texture = mSpecularTexture;
447 newTextures.SetTexture(index, texture);
448 newTextures.SetSampler(index, textures.GetSampler(index));
451 mRenderer.SetTextures(newTextures);
453 mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightScaleFactorName().data(), mIblScaleFactor);
454 mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightMaxLodUniformName().data(), static_cast<float>(mSpecularMipmapLevels));
458 void ModelPrimitive::UpdateRendererUniform()
462 mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightScaleFactorName().data(), mIblScaleFactor);
463 mRenderer.RegisterProperty(GetImplementation(mMaterial).GetImageBasedLightMaxLodUniformName().data(), static_cast<float>(mSpecularMipmapLevels));
464 GetImplementation(mMaterial).SetRendererUniform(mRenderer);
468 } // namespace Internal
470 } // namespace Scene3D