Merge "Use Mipmap level to sample specular texture" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / node-definition.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-scene3d/public-api/loader/node-definition.h>
20
21 // INTERNAL INCLUDES
22 #include <dali-scene3d/public-api/loader/renderer-state.h>
23 #include <dali-scene3d/public-api/loader/utils.h>
24
25 namespace Dali
26 {
27 namespace
28 {
29 constexpr std::string_view IBL_INTENSITY_STRING("uIblIntensity");
30 constexpr std::string_view IBL_Y_DIRECTION("uYDirection");
31 constexpr std::string_view IBL_MAXLOD("uMaxLOD");
32 } // namespace
33
34 namespace Scene3D
35 {
36 namespace Loader
37 {
38 bool NodeDefinition::Renderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
39 {
40   return false;
41 }
42
43 void NodeDefinition::Renderable::RegisterResources(IResourceReceiver& receiver) const
44 {
45   receiver.Register(ResourceType::Shader, mShaderIdx);
46 }
47
48 void NodeDefinition::Renderable::ReflectResources(IResourceReflector& reflector)
49 {
50   reflector.Reflect(ResourceType::Shader, mShaderIdx);
51 }
52
53 void NodeDefinition::Renderable::OnCreate(const NodeDefinition& node, CreateParams& params, Actor& actor) const
54 {
55   DALI_ASSERT_DEBUG(mShaderIdx != INVALID_INDEX);
56   auto&  resources = params.mResources;
57   Shader shader    = resources.mShaders[mShaderIdx].second;
58
59   static Geometry defaultGeometry = Geometry::New();
60   Renderer        renderer        = Renderer::New(defaultGeometry, shader);
61
62   RendererState::Apply(resources.mShaders[mShaderIdx].first.mRendererState, renderer);
63
64   actor.AddRenderer(renderer);
65 }
66
67 const char* NodeDefinition::ORIGINAL_MATRIX_PROPERTY_NAME = "originalMatrix";
68
69 Actor NodeDefinition::CreateActor(CreateParams& params)
70 {
71   Actor actor = Actor::New();
72   mNodeId     = actor.GetProperty<int32_t>(Dali::Actor::Property::ID);
73
74   SetActorCentered(actor);
75
76   actor.SetProperty(Actor::Property::NAME, mName);
77   actor.SetProperty(Actor::Property::POSITION, mPosition);
78   actor.SetProperty(Actor::Property::ORIENTATION, mOrientation);
79   actor.SetProperty(Actor::Property::SCALE, mScale);
80   actor.SetProperty(Actor::Property::SIZE, mSize);
81   actor.SetProperty(Actor::Property::VISIBLE, mIsVisible);
82
83   actor.RegisterProperty(ORIGINAL_MATRIX_PROPERTY_NAME, GetLocalSpace(), Property::AccessMode::READ_ONLY);
84
85   actor.SetProperty(Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_COLOR);
86
87   for(auto& renderable : mRenderables)
88   {
89     renderable->OnCreate(*this, params, actor);
90   }
91
92   for(auto& e : mExtras)
93   {
94     actor.RegisterProperty(e.mKey, e.mValue);
95   }
96
97   for(auto& c : mConstraints)
98   {
99     params.mConstrainables.push_back(ConstraintRequest{&c, actor});
100   }
101
102   return actor;
103 }
104
105 Matrix NodeDefinition::GetLocalSpace() const
106 {
107   Matrix localSpace{false};
108   localSpace.SetTransformComponents(mScale, mOrientation, mPosition);
109   return localSpace;
110 }
111
112 std::string_view NodeDefinition::GetIblScaleFactorUniformName()
113 {
114   return IBL_INTENSITY_STRING;
115 }
116
117 std::string_view NodeDefinition::GetIblYDirectionUniformName()
118 {
119   return IBL_Y_DIRECTION;
120 }
121
122 std::string_view NodeDefinition::GetIblMaxLodUniformName()
123 {
124   return IBL_MAXLOD;
125 }
126
127 bool NodeDefinition::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
128 {
129   if(mRenderables.empty())
130   {
131     return false;
132   }
133
134   bool useModelExtents = false;
135   for(auto& renderable : mRenderables)
136   {
137     Vector3 renderableMin(Vector3::ONE * MAXFLOAT), renderableMax(-Vector3::ONE * MAXFLOAT);
138     if(!renderable->GetExtents(resources, renderableMin, renderableMax))
139     {
140       useModelExtents = false;
141       break;
142     }
143     useModelExtents = true;
144     min.x           = std::min(min.x, renderableMin.x);
145     min.y           = std::min(min.y, renderableMin.y);
146     min.z           = std::min(min.z, renderableMin.z);
147     max.x           = std::max(max.x, renderableMax.x);
148     max.y           = std::max(max.y, renderableMax.y);
149     max.z           = std::max(max.z, renderableMax.z);
150   }
151   if(!useModelExtents)
152   {
153     // If the renderable node don't have mesh accessor, use size to compute extents.
154     min = -mSize / 2.0f;
155     max = mSize / 2.0f;
156   }
157   return true;
158 }
159
160 bool ModelRenderable::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
161 {
162   auto&    mesh    = resources.mMeshes[mMeshIdx];
163   uint32_t minSize = mesh.first.mPositions.mBlob.mMin.size();
164   uint32_t maxSize = mesh.first.mPositions.mBlob.mMax.size();
165   if(minSize == maxSize && minSize >= 2u && maxSize >= 2u)
166   {
167     min = Vector3(mesh.first.mPositions.mBlob.mMin[0], mesh.first.mPositions.mBlob.mMin[1], 0.0f);
168     max = Vector3(mesh.first.mPositions.mBlob.mMax[0], mesh.first.mPositions.mBlob.mMax[1], 0.0f);
169     if(minSize == 3u)
170     {
171       min.z = mesh.first.mPositions.mBlob.mMin[2];
172       max.z = mesh.first.mPositions.mBlob.mMax[2];
173     }
174     return true;
175   }
176   return false;
177 }
178
179 void ModelRenderable::RegisterResources(IResourceReceiver& receiver) const
180 {
181   Renderable::RegisterResources(receiver);
182   receiver.Register(ResourceType::Mesh, mMeshIdx);
183   receiver.Register(ResourceType::Material, mMaterialIdx);
184 }
185
186 void ModelRenderable::ReflectResources(IResourceReflector& reflector)
187 {
188   Renderable::ReflectResources(reflector);
189   reflector.Reflect(ResourceType::Mesh, mMeshIdx);
190   reflector.Reflect(ResourceType::Material, mMaterialIdx);
191 }
192
193 void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
194 {
195   DALI_ASSERT_DEBUG(mMeshIdx != INVALID_INDEX);
196   Renderable::OnCreate(node, params, actor);
197
198   auto& resources = params.mResources;
199   auto& mesh      = resources.mMeshes[mMeshIdx];
200
201   auto     renderer = actor.GetRendererAt(actor.GetRendererCount() - 1u);
202   Geometry geometry = mesh.second.geometry;
203   renderer.SetGeometry(geometry);
204
205   auto shader = renderer.GetShader();
206
207   if(mesh.first.IsSkinned())
208   {
209     params.mSkinnables.push_back(SkinningShaderConfigurationRequest{mesh.first.mSkeletonIdx, shader});
210   }
211
212   if(mesh.first.HasBlendShapes())
213   {
214     params.mBlendshapeRequests.push_back(BlendshapeShaderConfigurationRequest{node.mName, mMeshIdx, shader});
215   }
216
217   TextureSet textures = resources.mMaterials[mMaterialIdx].second;
218
219   // Set the blend shape texture.
220   if(mesh.second.blendShapeGeometry)
221   {
222     TextureSet newTextureSet = TextureSet::New();
223     newTextureSet.SetTexture(0u, mesh.second.blendShapeGeometry);
224
225     const unsigned int numberOfTextures = textures.GetTextureCount();
226     for(unsigned int index = 0u; index < numberOfTextures; ++index)
227     {
228       const unsigned int newIndex = index + 1u;
229       newTextureSet.SetTexture(newIndex, textures.GetTexture(index));
230       newTextureSet.SetSampler(newIndex, textures.GetSampler(index));
231     }
232
233     textures = newTextureSet;
234   }
235
236   renderer.RegisterProperty("uHasVertexColor", static_cast<float>(mesh.first.mColors.IsDefined()));
237
238   auto& matDef = resources.mMaterials[mMaterialIdx].first;
239   actor.RegisterProperty("uColorFactor", matDef.mBaseColorFactor);
240   actor.RegisterProperty("uMetallicFactor", matDef.mMetallic);
241   actor.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
242   actor.RegisterProperty("uDielectricSpecular", matDef.mDielectricSpecular);
243   actor.RegisterProperty("uSpecularFactor", matDef.mSpecularFactor);
244   actor.RegisterProperty("uSpecularColorFactor", matDef.mSpecularColorFactor);
245   actor.RegisterProperty("uNormalScale", matDef.mNormalScale);
246   actor.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
247   if(matDef.mFlags & MaterialDefinition::OCCLUSION)
248   {
249     renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
250   }
251
252   Index envIdx = matDef.mEnvironmentIdx;
253   renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
254   renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection);
255
256   float opaque      = matDef.mIsOpaque ? 1.0f : 0.0f;
257   float mask        = matDef.mIsMask ? 1.0f : 0.0f;
258   float alphaCutoff = matDef.GetAlphaCutoff();
259
260   renderer.RegisterProperty("uOpaque", opaque);
261   renderer.RegisterProperty("uMask", mask);
262   renderer.RegisterProperty("uAlphaThreshold", alphaCutoff);
263
264   renderer.SetTextures(textures);
265
266   uint32_t specularMipmap = resources.mEnvironmentMaps[envIdx].second.mSpecularMipmapLevels;
267   actor.SetProperty(Actor::Property::COLOR, mColor);
268   actor.RegisterProperty(IBL_MAXLOD.data(), static_cast<float>(specularMipmap));
269 }
270
271 void ArcRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
272 {
273   ModelRenderable::OnCreate(node, params, actor);
274
275   actor.RegisterProperty("antiAliasing", mAntiAliasing ? 1 : 0);
276   actor.RegisterProperty("arcCaps", mArcCaps);
277   actor.RegisterProperty("radius", mRadius);
278
279   const float startAngleRadians = mStartAngleDegrees * Math::PI_OVER_180;
280   Vector2     startPolar{std::cos(startAngleRadians), std::sin(startAngleRadians)};
281   actor.RegisterProperty("startAngle", startPolar);
282
283   const float endAngleRadians = mEndAngleDegrees * Math::PI_OVER_180;
284   Vector2     endPolar{std::cos(endAngleRadians), std::sin(endAngleRadians)};
285   actor.RegisterProperty("endAngle", endPolar);
286 }
287
288 void ArcRenderable::GetEndVectorWithDiffAngle(float startAngle, float diffAngle, Vector2& endVector)
289 {
290   float endAngle = 0.f;
291
292   if(diffAngle <= 0.001f)
293   {
294     // 0.001 is used to ensure is empty arc when startAngle = endAngle + 360 * N
295     endAngle = startAngle + 0.001f;
296   }
297   else if(diffAngle >= 360.f)
298   {
299     endAngle = diffAngle + 359.99f;
300   }
301   else
302   {
303     endAngle = startAngle + 360.0f + diffAngle;
304   }
305   endVector.x = cosf(endAngle * Math::PI_OVER_180);
306   endVector.y = sinf(endAngle * Math::PI_OVER_180);
307 }
308
309 } // namespace Loader
310 } // namespace Scene3D
311 } // namespace Dali