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/public-api/loader/node-definition.h>
22 #include <dali/integration-api/debug.h>
25 #include <dali-scene3d/internal/light/light-impl.h>
26 #include <dali-scene3d/internal/model-components/material-impl.h>
27 #include <dali-scene3d/internal/model-components/model-node-impl.h>
28 #include <dali-scene3d/internal/model-components/model-primitive-impl.h>
29 #include <dali-scene3d/public-api/loader/renderer-state.h>
30 #include <dali-scene3d/public-api/loader/utils.h>
36 static constexpr std::string_view IBL_INTENSITY_STRING("uIblIntensity");
37 static constexpr std::string_view IBL_Y_DIRECTION("uYDirection");
38 static constexpr std::string_view IBL_MAXLOD("uMaxLOD");
40 static constexpr uint32_t MAX_NUMBER_OF_MATERIAL_TEXTURE = 7;
41 static constexpr uint32_t SEMANTICS[MAX_NUMBER_OF_MATERIAL_TEXTURE] =
43 Scene3D::Loader::MaterialDefinition::ALBEDO,
44 Scene3D::Loader::MaterialDefinition::METALLIC | Scene3D::Loader::MaterialDefinition::ROUGHNESS,
45 Scene3D::Loader::MaterialDefinition::NORMAL,
46 Scene3D::Loader::MaterialDefinition::OCCLUSION,
47 Scene3D::Loader::MaterialDefinition::EMISSIVE,
48 Scene3D::Loader::MaterialDefinition::SPECULAR,
49 Scene3D::Loader::MaterialDefinition::SPECULAR_COLOR,
52 static constexpr Scene3D::Material::TextureType TEXTURE_TYPES[MAX_NUMBER_OF_MATERIAL_TEXTURE] =
54 Scene3D::Material::TextureType::BASE_COLOR,
55 Scene3D::Material::TextureType::METALLIC_ROUGHNESS,
56 Scene3D::Material::TextureType::NORMAL,
57 Scene3D::Material::TextureType::OCCLUSION,
58 Scene3D::Material::TextureType::EMISSIVE,
59 Scene3D::Material::TextureType::SPECULAR,
60 Scene3D::Material::TextureType::SPECULAR_COLOR,
63 Vector4 GetTextureFactor(Scene3D::Loader::MaterialDefinition& materialDefinition, uint32_t semantic)
65 Vector4 factor = Vector4::ONE;
68 case Scene3D::Loader::MaterialDefinition::ALBEDO:
69 factor = materialDefinition.mBaseColorFactor;
71 case Scene3D::Loader::MaterialDefinition::METALLIC | Scene3D::Loader::MaterialDefinition::ROUGHNESS:
72 factor = Vector4(materialDefinition.mMetallic, materialDefinition.mRoughness, 0.0f, 0.0f);
74 case Scene3D::Loader::MaterialDefinition::NORMAL:
75 factor.x = materialDefinition.mNormalScale;
77 case Scene3D::Loader::MaterialDefinition::OCCLUSION:
78 factor.x = materialDefinition.mOcclusionStrength;
80 case Scene3D::Loader::MaterialDefinition::EMISSIVE:
81 factor = materialDefinition.mEmissiveFactor;
83 case Scene3D::Loader::MaterialDefinition::SPECULAR:
84 factor.x = materialDefinition.mSpecularFactor;
86 case Scene3D::Loader::MaterialDefinition::SPECULAR_COLOR:
87 factor = materialDefinition.mSpecularColorFactor;
101 bool NodeDefinition::Renderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
106 void NodeDefinition::Renderable::RegisterResources(IResourceReceiver& receiver) const
108 receiver.Register(ResourceType::Shader, mShaderIdx);
111 void NodeDefinition::Renderable::ReflectResources(IResourceReflector& reflector)
113 reflector.Reflect(ResourceType::Shader, mShaderIdx);
116 void NodeDefinition::Renderable::OnCreate(const NodeDefinition& nodeDefinition, CreateParams& params, ModelNode& node) const
118 DALI_ASSERT_DEBUG(mShaderIdx != INVALID_INDEX);
119 auto& resources = params.mResources;
120 Shader shader = resources.mShaders[mShaderIdx].second;
122 static Geometry defaultGeometry = Geometry::New();
123 Renderer renderer = Renderer::New(defaultGeometry, shader);
125 RendererState::Apply(resources.mShaders[mShaderIdx].first.mRendererState, renderer);
127 node.AddRenderer(renderer);
130 const char* NodeDefinition::ORIGINAL_MATRIX_PROPERTY_NAME = "originalMatrix";
132 ModelNode NodeDefinition::CreateModelNode(CreateParams& params)
134 ModelNode node = ModelNode::New();
135 mNodeId = node.GetProperty<int32_t>(Dali::Actor::Property::ID);
137 SetActorCentered(node);
139 node.SetProperty(Actor::Property::NAME, mName);
140 node.SetProperty(Actor::Property::POSITION, mPosition);
141 node.SetProperty(Actor::Property::ORIENTATION, mOrientation);
142 node.SetProperty(Actor::Property::SCALE, mScale);
143 node.SetProperty(Actor::Property::SIZE, mSize);
144 node.SetProperty(Actor::Property::VISIBLE, mIsVisible);
146 node.RegisterProperty(ORIGINAL_MATRIX_PROPERTY_NAME, GetLocalSpace(), Property::AccessMode::READ_ONLY);
148 node.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
150 for(auto& renderable : mRenderables)
152 renderable->OnCreate(*this, params, node);
155 for(auto& e : mExtras)
157 node.RegisterProperty(e.mKey, e.mValue);
160 for(auto& c : mConstraints)
162 params.mConstrainables.push_back(ConstraintRequest{&c, node});
168 Matrix NodeDefinition::GetLocalSpace() const
170 Matrix localSpace{false};
171 localSpace.SetTransformComponents(mScale, mOrientation, mPosition);
175 std::string_view NodeDefinition::GetIblScaleFactorUniformName()
177 return IBL_INTENSITY_STRING;
180 std::string_view NodeDefinition::GetIblYDirectionUniformName()
182 return IBL_Y_DIRECTION;
185 std::string_view NodeDefinition::GetIblMaxLodUniformName()
190 bool NodeDefinition::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
192 if(mRenderables.empty())
197 bool useModelExtents = false;
198 for(auto& renderable : mRenderables)
200 Vector3 renderableMin(Vector3::ONE * MAXFLOAT), renderableMax(-Vector3::ONE * MAXFLOAT);
201 if(!renderable->GetExtents(resources, renderableMin, renderableMax))
203 useModelExtents = false;
206 useModelExtents = true;
207 min.x = std::min(min.x, renderableMin.x);
208 min.y = std::min(min.y, renderableMin.y);
209 min.z = std::min(min.z, renderableMin.z);
210 max.x = std::max(max.x, renderableMax.x);
211 max.y = std::max(max.y, renderableMax.y);
212 max.z = std::max(max.z, renderableMax.z);
216 // If the renderable node don't have mesh accessor, use size to compute extents.
223 bool ModelRenderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
225 auto& mesh = resources.mMeshes[mMeshIdx];
226 uint32_t minSize = mesh.first.mPositions.mBlob.mMin.size();
227 uint32_t maxSize = mesh.first.mPositions.mBlob.mMax.size();
228 if(minSize == maxSize && minSize >= 2u && maxSize >= 2u)
230 min = Vector3(mesh.first.mPositions.mBlob.mMin[0], mesh.first.mPositions.mBlob.mMin[1], 0.0f);
231 max = Vector3(mesh.first.mPositions.mBlob.mMax[0], mesh.first.mPositions.mBlob.mMax[1], 0.0f);
234 min.z = mesh.first.mPositions.mBlob.mMin[2];
235 max.z = mesh.first.mPositions.mBlob.mMax[2];
242 void ModelRenderable::RegisterResources(IResourceReceiver& receiver) const
244 Renderable::RegisterResources(receiver);
245 receiver.Register(ResourceType::Mesh, mMeshIdx);
246 receiver.Register(ResourceType::Material, mMaterialIdx);
249 void ModelRenderable::ReflectResources(IResourceReflector& reflector)
251 Renderable::ReflectResources(reflector);
252 reflector.Reflect(ResourceType::Mesh, mMeshIdx);
253 reflector.Reflect(ResourceType::Material, mMaterialIdx);
256 // How many shader managers are there?!
257 void ModelRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const
259 DALI_ASSERT_DEBUG(mMeshIdx != INVALID_INDEX);
260 ShaderOption::HashType shaderOptionHash{0u};
261 if(mShaderIdx == INVALID_INDEX)
263 ShaderOption option = params.mShaderManager->ProduceShaderOption(params.mResources.mMaterials[mMaterialIdx].first,
264 params.mResources.mMeshes[mMeshIdx].first);
265 shaderOptionHash = option.GetOptionHash();
266 Shader shader = params.mShaderManager->ProduceShader(option);
268 static Geometry defaultGeometry = Geometry::New();
269 Renderer renderer = Renderer::New(defaultGeometry, shader);
271 RendererState::Apply(params.mShaderManager->GetRendererState(params.mResources.mMaterials[mMaterialIdx].first), renderer);
272 Internal::GetImplementation(node).UpdateShader(params.mShaderManager);
273 node.AddRenderer(renderer);
277 Renderable::OnCreate(nodeDefinition, params, node);
280 auto& resources = params.mResources;
281 auto& mesh = resources.mMeshes[mMeshIdx];
283 auto renderer = node.GetRendererAt(node.GetRendererCount() - 1u);
284 Geometry geometry = mesh.second.geometry;
285 renderer.SetGeometry(geometry);
287 TextureSet textures = resources.mMaterials[mMaterialIdx].second;
288 // Set the blend shape texture.
289 if(mesh.second.blendShapeGeometry)
291 TextureSet newTextureSet = TextureSet::New();
292 newTextureSet.SetTexture(0u, mesh.second.blendShapeGeometry);
294 const unsigned int numberOfTextures = textures.GetTextureCount();
295 for(unsigned int index = 0u; index < numberOfTextures; ++index)
297 const unsigned int newIndex = index + 1u;
298 newTextureSet.SetTexture(newIndex, textures.GetTexture(index));
299 newTextureSet.SetSampler(newIndex, textures.GetSampler(index));
302 textures = newTextureSet;
304 renderer.SetTextures(textures);
307 mesh.first.mModelPrimitive = ModelPrimitive::New();
308 auto& primitive = GetImplementation(mesh.first.mModelPrimitive);
309 primitive.SetRenderer(renderer);
311 Index envIndex = resources.mMaterials[mMaterialIdx].first.mEnvironmentIdx;
312 uint32_t specularMipmap = resources.mEnvironmentMaps[envIndex].second.mSpecularMipmapLevels;
313 primitive.SetImageBasedLightTexture(resources.mEnvironmentMaps[envIndex].second.mDiffuse,
314 resources.mEnvironmentMaps[envIndex].second.mSpecular,
315 resources.mEnvironmentMaps[envIndex].first.mIblIntensity,
318 bool hasPositions = false;
319 bool hasNormals = false;
320 bool hasTangents = false;
321 mesh.first.RetrieveBlendShapeComponents(hasPositions, hasNormals, hasTangents);
322 primitive.SetBlendShapeOptions(hasPositions, hasNormals, hasTangents, mesh.first.mBlendShapeVersion);
323 primitive.SetBlendShapeGeometry(mesh.second.blendShapeGeometry);
324 primitive.SetSkinned(mesh.first.IsSkinned(), mesh.first.GetNumberOfJointSets());
325 primitive.SetVertexColor(mesh.first.HasVertexColor());
328 auto shader = renderer.GetShader();
329 if(mesh.first.IsSkinned())
331 params.mSkinnables.push_back(SkinningShaderConfigurationRequest{mesh.first.mSkeletonIdx, shader, mesh.first.mModelPrimitive});
334 if(mesh.first.HasBlendShapes())
336 params.mBlendshapeRequests.push_back(BlendshapeShaderConfigurationRequest{nodeDefinition.mName, mMeshIdx, shader, mesh.first.mModelPrimitive});
339 auto& matDef = resources.mMaterials[mMaterialIdx].first;
340 renderer.RegisterProperty("uColorFactor", matDef.mBaseColorFactor);
341 renderer.RegisterProperty("uMetallicFactor", matDef.mMetallic);
342 renderer.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
343 renderer.RegisterProperty("uDielectricSpecular", matDef.mDielectricSpecular);
344 renderer.RegisterProperty("uSpecularFactor", matDef.mSpecularFactor);
345 renderer.RegisterProperty("uSpecularColorFactor", matDef.mSpecularColorFactor);
346 renderer.RegisterProperty("uNormalScale", matDef.mNormalScale);
347 renderer.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
348 if(matDef.mFlags & MaterialDefinition::OCCLUSION)
350 renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
353 renderer.RegisterProperty("uBaseColorTextureTransformAvailable", 0.0f);
354 renderer.RegisterProperty("uNormalTextureTransformAvailable", 0.0f);
355 renderer.RegisterProperty("uNormalRoughnessTextureTransformAvailable", 0.0f);
356 renderer.RegisterProperty("uMetalRoughnessTextureTransformAvailable", 0.0f);
357 renderer.RegisterProperty("uOcclusionTextureTransformAvailable", 0.0f);
358 renderer.RegisterProperty("uEmissiveTextureTransformAvailable", 0.0f);
360 auto iTexture = matDef.mTextureStages.begin();
361 auto checkStage = [&](uint32_t flags) {
362 return iTexture != matDef.mTextureStages.end() && MaskMatch(iTexture->mSemantic, flags);
365 if(checkStage(MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC))
367 renderer.RegisterProperty("uBaseColorTextureTransformAvailable", 1.0f);
368 renderer.RegisterProperty("uBaseColorTextureTransform", iTexture->mTexture.mTransform);
371 if(checkStage(MaterialDefinition::NORMAL | MaterialDefinition::ROUGHNESS))
373 renderer.RegisterProperty("uNormalRoughnessTextureTransformAvailable", 1.0f);
374 renderer.RegisterProperty("uNormalRoughnessTextureTransform", iTexture->mTexture.mTransform);
378 else if(checkStage(MaterialDefinition::ALBEDO))
380 renderer.RegisterProperty("uBaseColorTextureTransformAvailable", 1.0f);
381 renderer.RegisterProperty("uBaseColorTextureTransform", iTexture->mTexture.mTransform);
385 if(checkStage(MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS))
387 renderer.RegisterProperty("uMetalRoughnessTextureTransformAvailable", 1.0f);
388 renderer.RegisterProperty("uMetalRoughnessTextureTransform", iTexture->mTexture.mTransform);
392 if(checkStage(MaterialDefinition::NORMAL))
394 renderer.RegisterProperty("uNormalTextureTransformAvailable", 1.0f);
395 renderer.RegisterProperty("uNormalTextureTransform", iTexture->mTexture.mTransform);
399 if(checkStage(MaterialDefinition::OCCLUSION))
401 renderer.RegisterProperty("uOcclusionTextureTransformAvailable", 1.0f);
402 renderer.RegisterProperty("uOcclusionTextureTransform", iTexture->mTexture.mTransform);
406 if(checkStage(MaterialDefinition::EMISSIVE))
408 renderer.RegisterProperty("uEmissiveTextureTransformAvailable", 1.0f);
409 renderer.RegisterProperty("uEmissiveTextureTransform", iTexture->mTexture.mTransform);
413 float opaque = matDef.mIsOpaque ? 1.0f : 0.0f;
414 float mask = matDef.mIsMask ? 1.0f : 0.0f;
415 float alphaCutoff = matDef.GetAlphaCutoff();
417 renderer.RegisterProperty("uOpaque", opaque);
418 renderer.RegisterProperty("uMask", mask);
419 renderer.RegisterProperty("uAlphaThreshold", alphaCutoff);
421 Index envIndex = matDef.mEnvironmentIdx;
422 uint32_t specularMipmap = resources.mEnvironmentMaps[envIndex].second.mSpecularMipmapLevels;
423 renderer.RegisterProperty(IBL_MAXLOD.data(), static_cast<float>(specularMipmap));
424 renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIndex].first.mIblIntensity);
425 renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIndex].first.mYDirection);
427 node.SetProperty(Actor::Property::COLOR, mColor);
429 // If user uses customshader, the properties of the shader could not be changed by Material.
430 if(mShaderIdx == INVALID_INDEX)
432 matDef.mMaterial = Material::New();
433 auto material = matDef.mMaterial;
434 uint32_t textureIndexOffset = (mesh.second.blendShapeGeometry) ? 1 : 0;
435 uint32_t textureIndex = 0;
436 for(uint32_t i = 0; i < MAX_NUMBER_OF_MATERIAL_TEXTURE; ++i)
438 Internal::Material::TextureInformation textureInformation;
439 if(matDef.CheckTextures(SEMANTICS[i]))
441 textureInformation.mTexture = textures.GetTexture(textureIndex + textureIndexOffset);
442 textureInformation.mSampler = textures.GetSampler(textureIndex + textureIndexOffset);
443 textureInformation.mUrl = matDef.mTextureStages[textureIndex].mTexture.mDirectoryPath + matDef.mTextureStages[textureIndex].mTexture.mImageUri;
444 textureInformation.mTransform = matDef.mTextureStages[textureIndex].mTexture.mTransform;
447 textureInformation.mFactor = GetTextureFactor(matDef, SEMANTICS[i]);
448 GetImplementation(material).SetTextureInformation(TEXTURE_TYPES[i], std::move(textureInformation));
450 material.SetProperty(Scene3D::Material::Property::ALPHA_MODE, matDef.mAlphaModeType);
451 material.SetProperty(Scene3D::Material::Property::ALPHA_CUTOFF, matDef.GetAlphaCutoff());
452 material.SetProperty(Scene3D::Material::Property::DOUBLE_SIDED, matDef.mDoubleSided);
453 material.SetProperty(Scene3D::Material::Property::IOR, matDef.mIor);
455 // This _should_ keep the same shader as generated at the top of the method.
456 GetImplementation(mesh.first.mModelPrimitive).SetMaterial(material, false);
457 GetImplementation(material).ResetFlag();
460 Internal::GetImplementation(node).AddModelPrimitive(mesh.first.mModelPrimitive, shaderOptionHash);
463 void ArcRenderable::OnCreate(const NodeDefinition& nodeDefinition, NodeDefinition::CreateParams& params, ModelNode& node) const
465 ModelRenderable::OnCreate(nodeDefinition, params, node);
467 node.RegisterProperty("antiAliasing", mAntiAliasing ? 1 : 0);
468 node.RegisterProperty("arcCaps", mArcCaps);
469 node.RegisterProperty("radius", mRadius);
471 const float startAngleRadians = mStartAngleDegrees * Math::PI_OVER_180;
472 Vector2 startPolar{std::cos(startAngleRadians), std::sin(startAngleRadians)};
473 node.RegisterProperty("startAngle", startPolar);
475 const float endAngleRadians = mEndAngleDegrees * Math::PI_OVER_180;
476 Vector2 endPolar{std::cos(endAngleRadians), std::sin(endAngleRadians)};
477 node.RegisterProperty("endAngle", endPolar);
480 void ArcRenderable::GetEndVectorWithDiffAngle(float startAngle, float diffAngle, Vector2& endVector)
482 float endAngle = 0.f;
484 if(diffAngle <= 0.001f)
486 // 0.001 is used to ensure is empty arc when startAngle = endAngle + 360 * N
487 endAngle = startAngle + 0.001f;
489 else if(diffAngle >= 360.f)
491 endAngle = diffAngle + 359.99f;
495 endAngle = startAngle + 360.0f + diffAngle;
497 endVector.x = cosf(endAngle * Math::PI_OVER_180);
498 endVector.y = sinf(endAngle * Math::PI_OVER_180);
501 } // namespace Loader
502 } // namespace Scene3D