Merge "DALi Version 2.3.5" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / internal / controls / scene-view / scene-view-impl.cpp
1 /*
2  * Copyright (c) 2024 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/internal/controls/scene-view/scene-view-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali-toolkit/dali-toolkit.h>
23 #include <dali-toolkit/devel-api/controls/control-devel.h>
24 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
25 #include <dali-toolkit/internal/controls/control/control-data-impl.h>
26 #include <dali-toolkit/public-api/image-loader/image-url.h>
27 #include <dali-toolkit/public-api/image-loader/image.h>
28 #include <dali/devel-api/actors/camera-actor-devel.h>
29 #include <dali/devel-api/adaptor-framework/window-devel.h>
30 #include <dali/devel-api/common/stage.h>
31 #include <dali/devel-api/rendering/frame-buffer-devel.h>
32 #include <dali/integration-api/adaptor-framework/adaptor.h>
33 #include <dali/integration-api/debug.h>
34 #include <dali/public-api/math/math-utils.h>
35 #include <dali/public-api/object/type-registry-helper.h>
36 #include <dali/public-api/object/type-registry.h>
37 #include <string_view>
38
39 // INTERNAL INCLUDES
40 #include <dali-scene3d/internal/controls/model/model-impl.h>
41 #include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
42 #include <dali-scene3d/internal/light/light-impl.h>
43
44 #include <dali/integration-api/debug.h>
45
46 using namespace Dali;
47
48 namespace Dali
49 {
50 namespace Scene3D
51 {
52 namespace Internal
53 {
54 namespace
55 {
56 BaseHandle Create()
57 {
58   return Scene3D::SceneView::New();
59 }
60
61 // Setup properties, signals and actions using the type-registry.
62 DALI_TYPE_REGISTRATION_BEGIN(Scene3D::SceneView, Toolkit::Control, Create);
63
64 DALI_PROPERTY_REGISTRATION(Scene3D, SceneView, "AlphaMaskUrl", STRING, ALPHA_MASK_URL)
65 DALI_PROPERTY_REGISTRATION(Scene3D, SceneView, "MaskContentScale", FLOAT, MASK_CONTENT_SCALE)
66 DALI_PROPERTY_REGISTRATION(Scene3D, SceneView, "CropToMask", BOOLEAN, CROP_TO_MASK)
67 DALI_TYPE_REGISTRATION_END()
68
69 Property::Index    RENDERING_BUFFER        = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1;
70 constexpr int32_t  DEFAULT_ORIENTATION     = 0;
71 constexpr int32_t  INVALID_INDEX           = -1;
72 constexpr uint32_t MAXIMUM_SIZE_SHADOW_MAP = 2048;
73
74 static constexpr std::string_view SKYBOX_INTENSITY_STRING = "uIntensity";
75 static constexpr std::string_view Y_FLIP_MASK_TEXTURE     = "uYFlipMaskTexture";
76 static constexpr float            FLIP_MASK_TEXTURE       = 1.0f;
77
78 Dali::Actor CreateSkybox()
79 {
80   struct Vertex
81   {
82     Vector3 aPosition;
83   };
84
85   Vertex skyboxVertices[] = {
86     // back
87     {Vector3(-1.0f, 1.0f, -1.0f)},
88     {Vector3(-1.0f, -1.0f, -1.0f)},
89     {Vector3(1.0f, -1.0f, -1.0f)},
90     {Vector3(1.0f, -1.0f, -1.0f)},
91     {Vector3(1.0f, 1.0f, -1.0f)},
92     {Vector3(-1.0f, 1.0f, -1.0f)},
93
94     // left
95     {Vector3(-1.0f, -1.0f, 1.0f)},
96     {Vector3(-1.0f, -1.0f, -1.0f)},
97     {Vector3(-1.0f, 1.0f, -1.0f)},
98     {Vector3(-1.0f, 1.0f, -1.0f)},
99     {Vector3(-1.0f, 1.0f, 1.0f)},
100     {Vector3(-1.0f, -1.0f, 1.0f)},
101
102     // right
103     {Vector3(1.0f, -1.0f, -1.0f)},
104     {Vector3(1.0f, -1.0f, 1.0f)},
105     {Vector3(1.0f, 1.0f, 1.0f)},
106     {Vector3(1.0f, 1.0f, 1.0f)},
107     {Vector3(1.0f, 1.0f, -1.0f)},
108     {Vector3(1.0f, -1.0f, -1.0f)},
109
110     // front
111     {Vector3(-1.0f, -1.0f, 1.0f)},
112     {Vector3(-1.0f, 1.0f, 1.0f)},
113     {Vector3(1.0f, 1.0f, 1.0f)},
114     {Vector3(1.0f, 1.0f, 1.0f)},
115     {Vector3(1.0f, -1.0f, 1.0f)},
116     {Vector3(-1.0f, -1.0f, 1.0f)},
117
118     // botton
119     {Vector3(-1.0f, 1.0f, -1.0f)},
120     {Vector3(1.0f, 1.0f, -1.0f)},
121     {Vector3(1.0f, 1.0f, 1.0f)},
122     {Vector3(1.0f, 1.0f, 1.0f)},
123     {Vector3(-1.0f, 1.0f, 1.0f)},
124     {Vector3(-1.0f, 1.0f, -1.0f)},
125
126     // top
127     {Vector3(-1.0f, -1.0f, -1.0f)},
128     {Vector3(-1.0f, -1.0f, 1.0f)},
129     {Vector3(1.0f, -1.0f, -1.0f)},
130     {Vector3(1.0f, -1.0f, -1.0f)},
131     {Vector3(-1.0f, -1.0f, 1.0f)},
132     {Vector3(1.0f, -1.0f, 1.0f)}};
133
134   Dali::VertexBuffer vertexBuffer = Dali::VertexBuffer::New(Property::Map().Add("aPosition", Property::VECTOR3));
135   vertexBuffer.SetData(skyboxVertices, sizeof(skyboxVertices) / sizeof(Vertex));
136
137   Dali::Geometry skyboxGeometry = Geometry::New();
138   skyboxGeometry.AddVertexBuffer(vertexBuffer);
139   skyboxGeometry.SetType(Geometry::TRIANGLES);
140
141   Dali::Shader   shaderSkybox = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data());
142   Dali::Renderer skyboxRenderer;
143   skyboxRenderer = Renderer::New(skyboxGeometry, shaderSkybox);
144   skyboxRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, 2.0f);
145   // Enables the depth test.
146   skyboxRenderer.SetProperty(Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON);
147   // The fragment shader will run only is those pixels that have the max depth value.
148   skyboxRenderer.SetProperty(Renderer::Property::DEPTH_FUNCTION, DepthFunction::LESS_EQUAL);
149
150   Dali::Actor skyboxActor = Actor::New();
151   skyboxActor.SetProperty(Dali::Actor::Property::NAME, "SkyBox");
152   skyboxActor.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
153   skyboxActor.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
154   skyboxActor.AddRenderer(skyboxRenderer);
155   return skyboxActor;
156 }
157
158 void SetShadowLightConstraint(Dali::CameraActor selectedCamera, Dali::CameraActor shadowLightCamera)
159 {
160   shadowLightCamera.SetProperty(Dali::CameraActor::Property::ASPECT_RATIO, 1.0f);
161   shadowLightCamera.SetProperty(Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE, 1.0f);
162   shadowLightCamera.SetProperty(Dali::CameraActor::Property::NEAR_PLANE_DISTANCE, 0.5f);
163   shadowLightCamera.SetProperty(Dali::CameraActor::Property::FAR_PLANE_DISTANCE, 3.5f);
164
165   //< Make constraint for above properties.
166   shadowLightCamera.RemoveConstraints();
167
168   // Compute ViewProjectionMatrix and store it to "tempViewProjectionMatrix" property
169   auto       tempViewProjectionMatrixIndex = shadowLightCamera.RegisterProperty("tempViewProjectionMatrix", Matrix::IDENTITY);
170   Constraint projectionMatrixConstraint    = Constraint::New<Matrix>(shadowLightCamera, tempViewProjectionMatrixIndex, [](Matrix& output, const PropertyInputContainer& inputs) {
171     Matrix worldMatrix  = inputs[0]->GetMatrix();
172     float  tangentFov_2 = tanf(inputs[4]->GetFloat());
173     float  nearDistance = inputs[5]->GetFloat();
174     float  farDistance  = inputs[6]->GetFloat();
175     float  aspectRatio  = inputs[7]->GetFloat();
176     float  nearY        = 0.0f;
177     float  nearX        = 0.0f;
178     float  farY         = 0.0f;
179     float  farX         = 0.0f;
180     if(inputs[1]->GetInteger() == Dali::Camera::ProjectionMode::PERSPECTIVE_PROJECTION)
181     {
182       if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL)
183       {
184         nearY = tangentFov_2 * nearDistance;
185         nearX = nearY * aspectRatio;
186         farY  = tangentFov_2 * farDistance;
187         farX  = farY * aspectRatio;
188       }
189       else
190       {
191         nearX = tangentFov_2 * nearDistance;
192         nearY = nearX / aspectRatio;
193         farX  = tangentFov_2 * farDistance;
194         farY  = farX / aspectRatio;
195       }
196     }
197     else
198     {
199       if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL)
200       {
201         nearY = inputs[3]->GetFloat();
202         nearX = nearY * aspectRatio;
203       }
204       else
205       {
206         nearX = inputs[3]->GetFloat();
207         nearY = nearX / aspectRatio;
208       }
209       farX = nearX;
210       farY = nearY;
211     }
212
213     std::vector<Vector4> points;
214     points.push_back(Vector4(nearX, nearY, nearDistance, 1.0f));
215     points.push_back(Vector4(-nearX, nearY, nearDistance, 1.0f));
216     points.push_back(Vector4(-nearX, -nearY, nearDistance, 1.0f));
217     points.push_back(Vector4(nearX, -nearY, nearDistance, 1.0f));
218     points.push_back(Vector4(farX, farY, farDistance, 1.0f));
219     points.push_back(Vector4(-farX, farY, farDistance, 1.0f));
220     points.push_back(Vector4(-farX, -farY, farDistance, 1.0f));
221     points.push_back(Vector4(farX, -farY, farDistance, 1.0f));
222
223     Matrix  shadowCameraWorldMatrix = inputs[8]->GetMatrix();
224     Vector4 worldCenter;
225     for(auto&& point : points)
226     {
227       point = worldMatrix * point;
228       worldCenter += point;
229     }
230     worldCenter /= 8.0f;
231     shadowCameraWorldMatrix.SetTranslation(Vector3(worldCenter));
232     Matrix shadowCameraViewMatrix = shadowCameraWorldMatrix;
233     shadowCameraViewMatrix.Invert();
234
235     Vector3 areaMin = Vector3::ONE * MAXFLOAT, areaMax = Vector3::ONE * -MAXFLOAT;
236     for(auto&& point : points)
237     {
238       Vector4 pointV = shadowCameraViewMatrix * point;
239       areaMin.x      = std::min(areaMin.x, pointV.x);
240       areaMin.y      = std::min(areaMin.y, pointV.y);
241       areaMin.z      = std::min(areaMin.z, pointV.z);
242       areaMax.x      = std::max(areaMax.x, pointV.x);
243       areaMax.y      = std::max(areaMax.y, pointV.y);
244       areaMax.z      = std::max(areaMax.z, pointV.z);
245     }
246
247     Vector2 center        = Vector2(areaMax + areaMin) * 0.5;
248     float   delta         = std::max(std::abs(areaMax.x - areaMin.x), std::abs(areaMax.y - areaMin.y));
249     float   delta_2       = delta * 0.5f;
250     Vector2 squareAreaMin = center - Vector2::ONE * delta_2;
251     Vector2 squareAreaMax = center + Vector2::ONE * delta_2;
252     float   deltaZ        = areaMax.z - areaMin.z;
253
254     float right  = -squareAreaMin.x;
255     float left   = -squareAreaMax.x;
256     float top    = squareAreaMin.y;
257     float bottom = squareAreaMax.y;
258     float near   = areaMin.z;
259     float far    = areaMax.z;
260
261     float* projMatrix = output.AsFloat();
262
263     projMatrix[0] = -2.0f / delta;
264     projMatrix[1] = 0.0f;
265     projMatrix[2] = 0.0f;
266     projMatrix[3] = 0.0f;
267
268     projMatrix[4] = 0.0f;
269     projMatrix[5] = -2.0f / delta;
270     projMatrix[6] = 0.0f;
271     projMatrix[7] = 0.0f;
272
273     projMatrix[8]  = 0.0f;
274     projMatrix[9]  = 0.0f;
275     projMatrix[10] = 2.0f / deltaZ;
276     projMatrix[11] = 0.0f;
277
278     projMatrix[12] = -(right + left) / delta;
279     projMatrix[13] = -(top + bottom) / delta;
280     projMatrix[14] = -(near + far) / deltaZ;
281     projMatrix[15] = 1.0f;
282
283     output = output * shadowCameraViewMatrix;
284   });
285   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::Actor::Property::WORLD_MATRIX});
286   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::PROJECTION_MODE});
287   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::DevelCameraActor::Property::PROJECTION_DIRECTION});
288   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE});
289   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::FIELD_OF_VIEW});
290   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::NEAR_PLANE_DISTANCE});
291   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::FAR_PLANE_DISTANCE});
292   projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::ASPECT_RATIO});
293   projectionMatrixConstraint.AddSource(Source{shadowLightCamera, Dali::Actor::Property::WORLD_MATRIX});
294   projectionMatrixConstraint.ApplyPost();
295 }
296
297 } // anonymous namespace
298
299 SceneView::SceneView()
300 : Control(ControlBehaviour(CONTROL_BEHAVIOUR_DEFAULT)),
301   mWindowOrientation(DEFAULT_ORIENTATION),
302   mSkybox(),
303   mSkyboxOrientation(Quaternion()),
304   mSkyboxIntensity(1.0f),
305   mShaderManager(new Scene3D::Loader::ShaderManager())
306 {
307 }
308
309 SceneView::~SceneView()
310 {
311   if(Dali::Adaptor::IsAvailable())
312   {
313     if(mIblDiffuseLoadTask)
314     {
315       Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
316       mIblDiffuseLoadTask.Reset();
317     }
318     if(mIblSpecularLoadTask)
319     {
320       Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
321       mIblSpecularLoadTask.Reset();
322     }
323     if(mSkyboxLoadTask)
324     {
325       Dali::AsyncTaskManager::Get().RemoveTask(mSkyboxLoadTask);
326       mSkyboxLoadTask.Reset();
327     }
328   }
329 }
330
331 Dali::Scene3D::SceneView SceneView::New()
332 {
333   SceneView* impl = new SceneView();
334
335   Dali::Scene3D::SceneView handle = Dali::Scene3D::SceneView(*impl);
336
337   // Second-phase init of the implementation
338   // This can only be done after the CustomActor connection has been made...
339   impl->Initialize();
340
341   return handle;
342 }
343
344 void SceneView::AddCamera(CameraActor camera)
345 {
346   if(camera)
347   {
348     if(mCameras.empty())
349     {
350       UpdateCamera(camera);
351     }
352     mCameras.push_back(camera);
353   }
354 }
355
356 void SceneView::RemoveCamera(CameraActor camera)
357 {
358   if(camera == mDefaultCamera)
359   {
360     DALI_LOG_ERROR("Default Camera cannot removed.\n");
361     return;
362   }
363
364   if(camera)
365   {
366     for(uint32_t i = 0; i < mCameras.size(); ++i)
367     {
368       if(mCameras[i] == camera)
369       {
370         mCameras.erase(mCameras.begin() + i);
371         break;
372       }
373     }
374
375     if(mSelectedCamera == camera)
376     {
377       CameraActor newCurrentCamera = *mCameras.begin();
378       UpdateCamera(newCurrentCamera);
379     }
380   }
381 }
382
383 uint32_t SceneView::GetCameraCount() const
384 {
385   return mCameras.size();
386 }
387
388 CameraActor SceneView::GetSelectedCamera() const
389 {
390   return mSelectedCamera;
391 }
392
393 CameraActor SceneView::GetCamera(uint32_t index) const
394 {
395   if(index < mCameras.size())
396   {
397     return mCameras[index];
398   }
399   DALI_LOG_ERROR("Input index is out of bounds\n");
400   return CameraActor();
401 }
402
403 CameraActor SceneView::GetCamera(const std::string& name) const
404 {
405   CameraActor returnCamera;
406   for(auto&& camera : mCameras)
407   {
408     if(camera.GetProperty<std::string>(Actor::Property::NAME) == name)
409     {
410       returnCamera = camera;
411       break;
412     }
413   }
414   return returnCamera;
415 }
416
417 void SceneView::SelectCamera(uint32_t index)
418 {
419   UpdateCamera(GetCamera(index));
420 }
421
422 void SceneView::SelectCamera(const std::string& name)
423 {
424   UpdateCamera(GetCamera(name));
425 }
426
427 void SceneView::RegisterSceneItem(Scene3D::Internal::LightObserver* item)
428 {
429   if(item)
430   {
431     item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
432     item->NotifyShadowMapTexture(mShadowTexture);
433     mItems.push_back(item);
434   }
435 }
436
437 void SceneView::UnregisterSceneItem(Scene3D::Internal::LightObserver* item)
438 {
439   if(item)
440   {
441     for(uint32_t i = 0; i < mItems.size(); ++i)
442     {
443       if(mItems[i] == item)
444       {
445         mItems.erase(mItems.begin() + i);
446         break;
447       }
448     }
449   }
450 }
451
452 void SceneView::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
453 {
454   bool needIblReset = false;
455   bool isOnScene    = Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE);
456   if(mDiffuseIblUrl != diffuseUrl)
457   {
458     mDiffuseIblUrl = diffuseUrl;
459     if(mDiffuseIblUrl.empty())
460     {
461       needIblReset = true;
462     }
463     else
464     {
465       mIblDiffuseDirty         = true;
466       mIblDiffuseResourceReady = false;
467     }
468   }
469
470   if(mSpecularIblUrl != specularUrl)
471   {
472     mSpecularIblUrl = specularUrl;
473     if(mSpecularIblUrl.empty())
474     {
475       needIblReset = true;
476     }
477     else
478     {
479       mIblSpecularDirty         = true;
480       mIblSpecularResourceReady = false;
481     }
482   }
483
484   // If one or both of diffuse url and specular url are empty,
485   // we don't need to request to load texture.
486   if(needIblReset)
487   {
488     if(mIblDiffuseLoadTask)
489     {
490       Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
491       mIblDiffuseLoadTask.Reset();
492     }
493
494     if(mIblSpecularLoadTask)
495     {
496       Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
497       mIblSpecularLoadTask.Reset();
498     }
499
500     mIblDiffuseDirty          = false;
501     mIblSpecularDirty         = false;
502     mIblDiffuseResourceReady  = true;
503     mIblSpecularResourceReady = true;
504
505     mDiffuseTexture.Reset();
506     mSpecularTexture.Reset();
507
508     mSpecularMipmapLevels = 1u;
509     NotifyImageBasedLightTextureChange();
510   }
511   else
512   {
513     if(isOnScene && mIblDiffuseDirty)
514     {
515       if(mIblDiffuseLoadTask)
516       {
517         Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
518         mIblDiffuseLoadTask.Reset();
519       }
520       mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &SceneView::OnIblDiffuseLoadComplete));
521       Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask);
522       mIblDiffuseDirty = false;
523     }
524
525     if(isOnScene && mIblSpecularDirty)
526     {
527       if(mIblSpecularLoadTask)
528       {
529         Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
530         mIblSpecularLoadTask.Reset();
531       }
532       mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &SceneView::OnIblSpecularLoadComplete));
533       Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask);
534       mIblSpecularDirty = false;
535     }
536   }
537
538   if(!Dali::Equals(mIblScaleFactor, scaleFactor))
539   {
540     SetImageBasedLightScaleFactor(scaleFactor);
541   }
542
543   // If diffuse and specular textures are already loaded, emits resource ready signal here.
544   if(IsResourceReady())
545   {
546     Control::SetResourceReady();
547   }
548 }
549
550 void SceneView::SetImageBasedLightScaleFactor(float scaleFactor)
551 {
552   mIblScaleFactor = scaleFactor;
553   for(auto&& item : mItems)
554   {
555     if(item)
556     {
557       item->NotifyImageBasedLightScaleFactor(scaleFactor);
558     }
559   }
560 }
561
562 float SceneView::GetImageBasedLightScaleFactor() const
563 {
564   return mIblScaleFactor;
565 }
566
567 void SceneView::AddLight(Scene3D::Light light)
568 {
569   bool enabled = mShaderManager->AddLight(light);
570   mLights.push_back(std::make_pair(light, enabled));
571
572   if(light.IsShadowEnabled())
573   {
574     SetShadow(light);
575   }
576 }
577
578 void SceneView::RemoveLight(Scene3D::Light light)
579 {
580   mShaderManager->RemoveLight(light);
581   for(uint32_t i = 0; i < mLights.size(); ++i)
582   {
583     if(mLights[i].first == light)
584     {
585       mLights.erase(mLights.begin() + i);
586       break;
587     }
588   }
589
590   if(mLights.size() > mShaderManager->GetLightCount())
591   {
592     for(auto&& waitingLight : mLights)
593     {
594       if(waitingLight.second)
595       {
596         continue;
597       }
598
599       waitingLight.second = mShaderManager->AddLight(waitingLight.first);
600       break;
601     }
602   }
603
604   if(light == mShadowLight)
605   {
606     RemoveShadow(light);
607   }
608
609   if(!mShadowLight)
610   {
611     for(auto&& lightEntity : mLights)
612     {
613       if(!lightEntity.second || !lightEntity.first.IsShadowEnabled())
614       {
615         continue;
616       }
617       SetShadow(lightEntity.first);
618       break;
619     }
620   }
621 }
622
623 void SceneView::SetShadow(Scene3D::Light light)
624 {
625   if(!!mShadowLight)
626   {
627     return;
628   }
629
630   auto foundLight = std::find_if(mLights.begin(), mLights.end(), [light](std::pair<Scene3D::Light, bool> lightEntity) -> bool { return (lightEntity.second && lightEntity.first == light); });
631
632   if(foundLight == mLights.end())
633   {
634     return;
635   }
636
637   mShadowLight = light;
638
639   // Directional Light setting.
640   CameraActor lightCamera    = GetImplementation(light).GetCamera();
641   CameraActor selectedCamera = GetSelectedCamera();
642   SetShadowLightConstraint(selectedCamera, lightCamera);
643
644   // make framebuffer for depth map and set it to render task.
645   uint32_t shadowMapBufferSize = std::min(std::max(GetResolutionWidth(), GetResolutionHeight()), MAXIMUM_SIZE_SHADOW_MAP);
646   UpdateShadowMapBuffer(shadowMapBufferSize);
647
648   // use lightCamera as a camera of shadow render task.
649   mShadowMapRenderTask.SetCameraActor(lightCamera);
650
651   mShaderManager->SetShadow(light);
652 }
653
654 void SceneView::RemoveShadow(Scene3D::Light light)
655 {
656   if(mShadowLight != light)
657   {
658     return;
659   }
660
661   // remove all constraint from light camera
662   CameraActor lightCamera = GetImplementation(mShadowLight).GetCamera();
663   lightCamera.RemoveConstraints();
664
665   // reset framebuffer and remove it from render task.
666   mShadowFrameBuffer.Reset();
667   mShaderManager->RemoveShadow();
668   mShadowMapRenderTask.SetCameraActor(CameraActor());
669
670   mShadowLight.Reset();
671
672   mShadowTexture.Reset();
673   for(auto&& item : mItems)
674   {
675     if(item)
676     {
677       item->NotifyShadowMapTexture(mShadowTexture);
678     }
679   }
680
681   for(auto&& lightEntity : mLights)
682   {
683     if(!lightEntity.second || !lightEntity.first.IsShadowEnabled())
684     {
685       continue;
686     }
687     SetShadow(lightEntity.first);
688     break;
689   }
690 }
691
692 uint32_t SceneView::GetActivatedLightCount() const
693 {
694   return mShaderManager->GetLightCount();
695 }
696
697 void SceneView::UseFramebuffer(bool useFramebuffer)
698 {
699   if(mUseFrameBuffer != useFramebuffer)
700   {
701     mUseFrameBuffer = useFramebuffer;
702     UpdateRenderTask();
703   }
704 }
705
706 bool SceneView::IsUsingFramebuffer() const
707 {
708   return mUseFrameBuffer;
709 }
710
711 void SceneView::SetResolution(uint32_t width, uint32_t height)
712 {
713   if(mWindowWidth != width || mWindowHeight != height)
714   {
715     mWindowWidth  = width;
716     mWindowHeight = height;
717     if(mUseFrameBuffer)
718     {
719       mWindowSizeChanged = true;
720       UpdateRenderTask();
721     }
722   }
723 }
724
725 uint32_t SceneView::GetResolutionWidth()
726 {
727   if(!mUseFrameBuffer || mWindowWidth == 0u || mWindowHeight == 0u)
728   {
729     return static_cast<uint32_t>(Self().GetProperty<float>(Dali::Actor::Property::SIZE_WIDTH));
730   }
731   return mWindowWidth;
732 }
733
734 uint32_t SceneView::GetResolutionHeight()
735 {
736   if(!mUseFrameBuffer || mWindowWidth == 0u || mWindowHeight == 0u)
737   {
738     return static_cast<uint32_t>(Self().GetProperty<float>(Dali::Actor::Property::SIZE_HEIGHT));
739   }
740   return mWindowHeight;
741 }
742
743 void SceneView::ResetResolution()
744 {
745   SetResolution(0u, 0u);
746 }
747
748 void SceneView::SetFramebufferMultiSamplingLevel(uint8_t multiSamplingLevel)
749 {
750   if(mFrameBufferMultiSamplingLevel != multiSamplingLevel)
751   {
752     mFrameBufferMultiSamplingLevel = multiSamplingLevel;
753
754     // Create new framebuffer with changed multiSamplingLevel.
755     if(mRenderTask && mFrameBuffer && mTexture)
756     {
757       mFrameBuffer = FrameBuffer::New(GetResolutionWidth(), GetResolutionHeight(), FrameBuffer::Attachment::DEPTH_STENCIL);
758       mFrameBuffer.AttachColorTexture(mTexture);
759       DevelFrameBuffer::SetMultiSamplingLevel(mFrameBuffer, mFrameBufferMultiSamplingLevel);
760       mRenderTask.SetFrameBuffer(mFrameBuffer);
761
762       // Note : we don't need to create new visual since visual's url is depend on mTexture.
763     }
764   }
765 }
766
767 uint8_t SceneView::GetFramebufferMultiSamplingLevel() const
768 {
769   return mFrameBufferMultiSamplingLevel;
770 }
771
772 void SceneView::SetSkybox(const std::string& skyboxUrl)
773 {
774   if(mSkyboxUrl != skyboxUrl)
775   {
776     UpdateSkybox(skyboxUrl, mSkyboxEnvironmentMapType);
777   }
778 }
779
780 void SceneView::SetSkyboxEnvironmentMapType(Scene3D::EnvironmentMapType skyboxEnvironmentMapType)
781 {
782   if(mSkyboxEnvironmentMapType != skyboxEnvironmentMapType)
783   {
784     UpdateSkybox(mSkyboxUrl, skyboxEnvironmentMapType);
785   }
786 }
787
788 void SceneView::SetSkyboxIntensity(float intensity)
789 {
790   mSkyboxIntensity = intensity;
791   if(intensity < 0)
792   {
793     DALI_LOG_ERROR("Intensity should be greater than or equal to 0.\n");
794     mSkyboxIntensity = 0.0f;
795   }
796
797   if(mSkybox)
798   {
799     mSkybox.RegisterProperty(SKYBOX_INTENSITY_STRING.data(), mSkyboxIntensity);
800   }
801 }
802
803 float SceneView::GetSkyboxIntensity() const
804 {
805   return mSkyboxIntensity;
806 }
807
808 void SceneView::SetSkyboxOrientation(const Quaternion& orientation)
809 {
810   mSkyboxOrientation = orientation;
811   if(mSkybox)
812   {
813     mSkybox.SetProperty(Dali::Actor::Property::ORIENTATION, orientation);
814   }
815 }
816
817 Quaternion SceneView::GetSkyboxOrientation() const
818 {
819   return mSkyboxOrientation;
820 }
821
822 Dali::Scene3D::Loader::ShaderManagerPtr SceneView::GetShaderManager() const
823 {
824   return mShaderManager;
825 }
826
827 void SceneView::UpdateShadowUniform(Scene3D::Light light)
828 {
829   mShaderManager->UpdateShadowUniform(light);
830 }
831
832 void SceneView::SetAlphaMaskUrl(std::string& alphaMaskUrl)
833 {
834   if(mAlphaMaskUrl != alphaMaskUrl)
835   {
836     mAlphaMaskUrl           = alphaMaskUrl;
837     mMaskingPropertyChanged = true;
838     UpdateRenderTask();
839   }
840 }
841
842 std::string SceneView::GetAlphaMaskUrl()
843 {
844   return mAlphaMaskUrl;
845 }
846
847 void SceneView::SetMaskContentScaleFactor(float maskContentScaleFactor)
848 {
849   if(mMaskContentScaleFactor != maskContentScaleFactor)
850   {
851     mMaskContentScaleFactor = maskContentScaleFactor;
852     mMaskingPropertyChanged = true;
853     UpdateRenderTask();
854   }
855 }
856
857 float SceneView::GetMaskContentScaleFactor()
858 {
859   return mMaskContentScaleFactor;
860 }
861
862 void SceneView::EnableCropToMask(bool enableCropToMask)
863 {
864   if(mCropToMask != enableCropToMask)
865   {
866     mCropToMask             = enableCropToMask;
867     mMaskingPropertyChanged = true;
868     UpdateRenderTask();
869   }
870 }
871
872 bool SceneView::IsEnabledCropToMask()
873 {
874   return mCropToMask;
875 }
876
877 void SceneView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
878 {
879   Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(Dali::BaseHandle(object));
880
881   if(sceneView)
882   {
883     SceneView& sceneViewImpl(GetImpl(sceneView));
884
885     switch(index)
886     {
887       case Scene3D::SceneView::Property::ALPHA_MASK_URL:
888       {
889         std::string alphaMaskUrl = value.Get<std::string>();
890         sceneViewImpl.SetAlphaMaskUrl(alphaMaskUrl);
891         break;
892       }
893       case Scene3D::SceneView::Property::MASK_CONTENT_SCALE:
894       {
895         sceneViewImpl.SetMaskContentScaleFactor(value.Get<float>());
896         break;
897       }
898       case Scene3D::SceneView::Property::CROP_TO_MASK:
899       {
900         sceneViewImpl.EnableCropToMask(value.Get<bool>());
901         break;
902       }
903     }
904   }
905 }
906
907 Property::Value SceneView::GetProperty(BaseObject* object, Property::Index index)
908 {
909   Property::Value value;
910
911   Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(Dali::BaseHandle(object));
912
913   if(sceneView)
914   {
915     SceneView& sceneViewImpl(GetImpl(sceneView));
916
917     switch(index)
918     {
919       case Scene3D::SceneView::Property::ALPHA_MASK_URL:
920       {
921         value = sceneViewImpl.GetAlphaMaskUrl();
922         break;
923       }
924       case Scene3D::SceneView::Property::MASK_CONTENT_SCALE:
925       {
926         value = sceneViewImpl.GetMaskContentScaleFactor();
927         break;
928       }
929       case Scene3D::SceneView::Property::CROP_TO_MASK:
930       {
931         value = sceneViewImpl.IsEnabledCropToMask();
932         break;
933       }
934     }
935   }
936   return value;
937 }
938
939 ///////////////////////////////////////////////////////////
940 //
941 // Private methods
942 //
943
944 void SceneView::OnSceneConnection(int depth)
945 {
946   // If diffuse and specular url is not valid, IBL does not need to be loaded.
947   if(!mDiffuseIblUrl.empty() && !mSpecularIblUrl.empty())
948   {
949     SetImageBasedLightSource(mDiffuseIblUrl, mSpecularIblUrl, mIblScaleFactor);
950   }
951
952   if(!mSkyboxUrl.empty())
953   {
954     UpdateSkybox(mSkyboxUrl, mSkyboxEnvironmentMapType);
955   }
956
957   Window window = DevelWindow::Get(Self());
958   if(window)
959   {
960     // Only for on-screen window
961     window.ResizeSignal().Connect(this, &SceneView::OnWindowResized);
962
963     mWindow            = window;
964     mWindowOrientation = DevelWindow::GetPhysicalOrientation(window);
965   }
966
967   // On-screen / Off-screen window
968   mSceneHolder = Integration::SceneHolder::Get(Self());
969   if(mSceneHolder)
970   {
971     RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
972     mShadowMapRenderTask    = taskList.CreateTask();
973     mShadowMapRenderTask.SetSourceActor(mRootLayer);
974     mShadowMapRenderTask.SetExclusive(true);
975     mShadowMapRenderTask.SetInputEnabled(false);
976     mShadowMapRenderTask.SetCullMode(false);
977     mShadowMapRenderTask.SetClearEnabled(true);
978     mShadowMapRenderTask.SetClearColor(Color::WHITE);
979     mShadowMapRenderTask.SetRenderPassTag(10);
980     mShadowMapRenderTask.SetCameraActor(CameraActor());
981
982     mRenderTask = taskList.CreateTask();
983     mRenderTask.SetSourceActor(mRootLayer);
984     mRenderTask.SetExclusive(true);
985     mRenderTask.SetInputEnabled(true);
986     mRenderTask.SetCullMode(false);
987     mRenderTask.SetScreenToFrameBufferMappingActor(Self());
988
989     UpdateRenderTask();
990   }
991
992   Control::OnSceneConnection(depth);
993 }
994
995 void SceneView::OnSceneDisconnection()
996 {
997   mItems.clear();
998
999   Window window = mWindow.GetHandle();
1000   if(window)
1001   {
1002     window.ResizeSignal().Disconnect(this, &SceneView::OnWindowResized);
1003   }
1004   mWindow.Reset();
1005
1006   if(mSceneHolder)
1007   {
1008     if(mRenderTask)
1009     {
1010       RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
1011       taskList.RemoveTask(mRenderTask);
1012       mRenderTask.Reset();
1013     }
1014     if(mShadowMapRenderTask)
1015     {
1016       RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
1017       taskList.RemoveTask(mShadowMapRenderTask);
1018       mShadowMapRenderTask.Reset();
1019     }
1020     mSceneHolder.Reset();
1021   }
1022   mFrameBuffer.Reset();
1023   mShadowFrameBuffer.Reset();
1024
1025   Control::OnSceneDisconnection();
1026 }
1027
1028 void SceneView::OnInitialize()
1029 {
1030   Actor self = Self();
1031   mRootLayer = Layer::New();
1032   mRootLayer.SetProperty(Layer::Property::BEHAVIOR, Layer::LAYER_3D);
1033   mRootLayer.SetProperty(Layer::Property::DEPTH_TEST, true);
1034   // The models in the SceneView should be have independent coordinate with DALi default coordinate.
1035   mRootLayer.SetProperty(Dali::Actor::Property::INHERIT_POSITION, false);
1036   mRootLayer.SetProperty(Dali::Actor::Property::INHERIT_ORIENTATION, false);
1037   mRootLayer.SetProperty(Dali::Actor::Property::INHERIT_SCALE, false);
1038   self.Add(mRootLayer);
1039
1040   mDefaultCamera = Dali::CameraActor::New3DCamera();
1041   mDefaultCamera.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
1042   mDefaultCamera.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
1043   AddCamera(mDefaultCamera);
1044   UpdateCamera(mDefaultCamera);
1045 }
1046
1047 void SceneView::OnChildAdd(Actor& child)
1048 {
1049   if(child != mRootLayer)
1050   {
1051     mRootLayer.Add(child);
1052   }
1053   Control::OnChildAdd(child);
1054 }
1055
1056 void SceneView::OnChildRemove(Actor& child)
1057 {
1058   mRootLayer.Remove(child);
1059   Control::OnChildRemove(child);
1060 }
1061
1062 float SceneView::GetHeightForWidth(float width)
1063 {
1064   Extents padding;
1065   padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
1066   return Control::GetHeightForWidth(width) + padding.top + padding.bottom;
1067 }
1068
1069 float SceneView::GetWidthForHeight(float height)
1070 {
1071   Extents padding;
1072   padding = Self().GetProperty<Extents>(Toolkit::Control::Property::PADDING);
1073   return Control::GetWidthForHeight(height) + padding.start + padding.end;
1074 }
1075
1076 void SceneView::OnRelayout(const Vector2& size, RelayoutContainer& container)
1077 {
1078   Control::OnRelayout(size, container);
1079   // Change canvas size of camera actor.
1080   UpdateRenderTask();
1081 }
1082
1083 bool SceneView::IsResourceReady() const
1084 {
1085   return mIblDiffuseResourceReady && mIblSpecularResourceReady && mSkyboxResourceReady;
1086 }
1087
1088 void SceneView::UpdateCamera(CameraActor camera)
1089 {
1090   if(camera)
1091   {
1092     if(mSelectedCamera && mSelectedCamera.GetParent())
1093     {
1094       mSelectedCamera.Unparent();
1095     }
1096     mRootLayer.Add(camera);
1097   }
1098
1099   mSelectedCamera = camera;
1100   if(mShadowLight)
1101   {
1102     SetShadowLightConstraint(mSelectedCamera, GetImplementation(mShadowLight).GetCamera());
1103   }
1104   UpdateRenderTask();
1105 }
1106
1107 void SceneView::UpdateRenderTask()
1108 {
1109   if(mRenderTask)
1110   {
1111     if(mSelectedCamera != mRenderTask.GetCameraActor())
1112     {
1113       mRenderTask.SetCameraActor(mSelectedCamera);
1114     }
1115     uint32_t width  = GetResolutionWidth();
1116     uint32_t height = GetResolutionHeight();
1117
1118     uint32_t shadowMapBufferSize = std::min(std::max(width, height), MAXIMUM_SIZE_SHADOW_MAP);
1119     UpdateShadowMapBuffer(shadowMapBufferSize);
1120
1121     if(mUseFrameBuffer)
1122     {
1123       Dali::FrameBuffer currentFrameBuffer = mRenderTask.GetFrameBuffer();
1124       if(!currentFrameBuffer ||
1125          !Dali::Equals(currentFrameBuffer.GetColorTexture().GetWidth(), width) ||
1126          !Dali::Equals(currentFrameBuffer.GetColorTexture().GetHeight(), height) ||
1127          mMaskingPropertyChanged ||
1128          mWindowSizeChanged)
1129       {
1130         mRootLayer.SetProperty(Dali::Actor::Property::COLOR_MODE, ColorMode::USE_OWN_COLOR);
1131         mRenderTask.ResetViewportGuideActor();
1132         mRenderTask.SetViewport(Dali::Viewport(Vector4::ZERO));
1133
1134         // create offscreen buffer of new size to render our child actors to
1135         mTexture     = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
1136         mFrameBuffer = FrameBuffer::New(width, height, FrameBuffer::Attachment::DEPTH_STENCIL);
1137         mFrameBuffer.AttachColorTexture(mTexture);
1138         DevelFrameBuffer::SetMultiSamplingLevel(mFrameBuffer, mFrameBufferMultiSamplingLevel);
1139         Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::Image::GenerateUrl(mFrameBuffer, 0u);
1140
1141         Property::Map imagePropertyMap;
1142         imagePropertyMap.Insert(Toolkit::Visual::Property::TYPE, Toolkit::Visual::IMAGE);
1143         imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, imageUrl.GetUrl());
1144         // To flip rendered scene without CameraActor::SetInvertYAxis() to avoid backface culling.
1145         imagePropertyMap.Insert(Toolkit::ImageVisual::Property::PIXEL_AREA, Vector4(0.0f, 1.0f, 1.0f, -1.0f));
1146         if(!mAlphaMaskUrl.empty())
1147         {
1148           imagePropertyMap.Insert(Toolkit::ImageVisual::Property::ALPHA_MASK_URL, mAlphaMaskUrl);
1149           imagePropertyMap.Insert(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, true);
1150           imagePropertyMap.Insert(Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE, mMaskContentScaleFactor);
1151           imagePropertyMap.Insert(Toolkit::ImageVisual::Property::CROP_TO_MASK, mCropToMask);
1152           imagePropertyMap.Insert(Toolkit::DevelImageVisual::Property::MASKING_TYPE, Toolkit::DevelImageVisual::MaskingType::MASKING_ON_RENDERING);
1153           Self().RegisterProperty(Y_FLIP_MASK_TEXTURE, FLIP_MASK_TEXTURE);
1154         }
1155
1156         mVisual = Toolkit::VisualFactory::Get().CreateVisual(imagePropertyMap);
1157         Toolkit::DevelControl::RegisterVisual(*this, RENDERING_BUFFER, mVisual);
1158
1159         mRenderTask.SetFrameBuffer(mFrameBuffer);
1160         mRenderTask.SetClearEnabled(true);
1161         mRenderTask.SetClearColor(Color::TRANSPARENT);
1162
1163         mMaskingPropertyChanged = false;
1164         mWindowSizeChanged      = false;
1165       }
1166     }
1167     else
1168     {
1169       mRenderTask.SetViewportGuideActor(Self());
1170       if(mRenderTask.GetFrameBuffer())
1171       {
1172         mRootLayer.SetProperty(Dali::Actor::Property::COLOR_MODE, ColorMode::USE_OWN_MULTIPLY_PARENT_ALPHA);
1173         FrameBuffer framebuffer;
1174         mRenderTask.SetFrameBuffer(framebuffer);
1175         mRenderTask.SetClearEnabled(false);
1176
1177         Toolkit::DevelControl::UnregisterVisual(*this, RENDERING_BUFFER);
1178
1179         mVisual.Reset();
1180         mFrameBuffer.Reset();
1181         mTexture.Reset();
1182       }
1183     }
1184
1185     if(width > 0u && height > 0u)
1186     {
1187       float aspectRatio = static_cast<float>(width) / static_cast<float>(height);
1188       mSelectedCamera.SetAspectRatio(aspectRatio);
1189     }
1190
1191     RotateCamera();
1192   }
1193 }
1194
1195 void SceneView::OnWindowResized(Window window, Window::WindowSize size)
1196 {
1197   mWindowOrientation = DevelWindow::GetPhysicalOrientation(window);
1198   RotateCamera();
1199 }
1200
1201 void SceneView::RotateCamera()
1202 {
1203   if(mUseFrameBuffer)
1204   {
1205     DevelCameraActor::RotateProjection(mSelectedCamera, DEFAULT_ORIENTATION);
1206   }
1207   else
1208   {
1209     DevelCameraActor::RotateProjection(mSelectedCamera, mWindowOrientation);
1210   }
1211 }
1212
1213 void SceneView::UpdateSkybox(const std::string& skyboxUrl, Scene3D::EnvironmentMapType skyboxEnvironmentMapType)
1214 {
1215   bool isOnScene = Self().GetProperty<bool>(Dali::Actor::Property::CONNECTED_TO_SCENE);
1216   if(mSkyboxUrl != skyboxUrl || mSkyboxEnvironmentMapType != skyboxEnvironmentMapType)
1217   {
1218     mSkyboxDirty              = true;
1219     mSkyboxResourceReady      = false;
1220     mSkyboxUrl                = skyboxUrl;
1221     mSkyboxEnvironmentMapType = skyboxEnvironmentMapType;
1222   }
1223
1224   if(mSkyboxUrl.empty())
1225   {
1226     if(mSkyboxLoadTask)
1227     {
1228       Dali::AsyncTaskManager::Get().RemoveTask(mSkyboxLoadTask);
1229       mSkyboxLoadTask.Reset();
1230     }
1231
1232     if(mSkybox)
1233     {
1234       mSkybox.Unparent();
1235       mSkybox.Reset();
1236       mSkyboxTexture.Reset();
1237     }
1238
1239     mSkyboxDirty         = false;
1240     mSkyboxResourceReady = true;
1241   }
1242   else
1243   {
1244     if(isOnScene && mSkyboxDirty)
1245     {
1246       if(mSkyboxLoadTask)
1247       {
1248         Dali::AsyncTaskManager::Get().RemoveTask(mSkyboxLoadTask);
1249         mSkyboxLoadTask.Reset();
1250       }
1251
1252       mSkyboxLoadTask = new EnvironmentMapLoadTask(mSkyboxUrl, mSkyboxEnvironmentMapType, MakeCallback(this, &SceneView::OnSkyboxLoadComplete));
1253       Dali::AsyncTaskManager::Get().AddTask(mSkyboxLoadTask);
1254       mSkyboxDirty = false;
1255     }
1256   }
1257
1258   if(IsResourceReady())
1259   {
1260     Control::SetResourceReady();
1261   }
1262 }
1263
1264 void SceneView::OnSkyboxLoadComplete()
1265 {
1266   if(!mSkybox)
1267   {
1268     mSkybox = CreateSkybox();
1269     SetSkyboxIntensity(mSkyboxIntensity);
1270     SetSkyboxOrientation(mSkyboxOrientation);
1271     if(mRootLayer)
1272     {
1273       mRootLayer.Add(mSkybox);
1274     }
1275   }
1276
1277   mSkyboxResourceReady = true;
1278   mSkyboxTexture       = mSkyboxLoadTask->GetLoadedTexture();
1279   Shader skyboxShader;
1280   if(mSkyboxLoadTask->GetEnvironmentMapType() == Scene3D::EnvironmentMapType::CUBEMAP)
1281   {
1282     skyboxShader = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data());
1283   }
1284   else
1285   {
1286     skyboxShader = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_EQUIRECTANGULAR_SHADER_FRAG.data());
1287   }
1288
1289   Renderer skyboxRenderer = (mSkybox.GetRendererCount() > 0u) ? mSkybox.GetRendererAt(0u) : Renderer();
1290   if(skyboxRenderer)
1291   {
1292     Dali::TextureSet skyboxTextures = TextureSet::New();
1293     skyboxTextures.SetTexture(0, mSkyboxTexture);
1294     skyboxRenderer.SetTextures(skyboxTextures);
1295     skyboxRenderer.SetShader(skyboxShader);
1296   }
1297
1298   mSkyboxLoadTask.Reset();
1299
1300   if(IsResourceReady())
1301   {
1302     Control::SetResourceReady();
1303   }
1304 }
1305
1306 void SceneView::OnIblDiffuseLoadComplete()
1307 {
1308   mDiffuseTexture          = mIblDiffuseLoadTask->GetLoadedTexture();
1309   mIblDiffuseResourceReady = true;
1310   mIblDiffuseLoadTask.Reset();
1311   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
1312   {
1313     OnIblLoadComplete();
1314   }
1315 }
1316
1317 void SceneView::OnIblSpecularLoadComplete()
1318 {
1319   mSpecularTexture          = mIblSpecularLoadTask->GetLoadedTexture();
1320   mSpecularMipmapLevels     = mIblSpecularLoadTask->GetMipmapLevels();
1321   mIblSpecularResourceReady = true;
1322   mIblSpecularLoadTask.Reset();
1323   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
1324   {
1325     OnIblLoadComplete();
1326   }
1327 }
1328
1329 void SceneView::OnIblLoadComplete()
1330 {
1331   NotifyImageBasedLightTextureChange();
1332   if(IsResourceReady())
1333   {
1334     Control::SetResourceReady();
1335   }
1336 }
1337
1338 void SceneView::NotifyImageBasedLightTextureChange()
1339 {
1340   for(auto&& item : mItems)
1341   {
1342     if(item)
1343     {
1344       item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
1345     }
1346   }
1347 }
1348
1349 void SceneView::UpdateShadowMapBuffer(uint32_t shadowMapSize)
1350 {
1351   Dali::FrameBuffer currentShadowFrameBuffer = mShadowMapRenderTask.GetFrameBuffer();
1352   if(mShadowLight &&
1353      (!currentShadowFrameBuffer ||
1354       !mShadowTexture ||
1355       !Dali::Equals(DevelFrameBuffer::GetDepthTexture(currentShadowFrameBuffer).GetWidth(), shadowMapSize)))
1356   {
1357     mShadowFrameBuffer.Reset();
1358     mShadowTexture     = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::DEPTH_UNSIGNED_INT, shadowMapSize, shadowMapSize);
1359     mShadowFrameBuffer = FrameBuffer::New(shadowMapSize, shadowMapSize, FrameBuffer::Attachment::NONE);
1360     DevelFrameBuffer::AttachDepthTexture(mShadowFrameBuffer, mShadowTexture);
1361     mShadowMapRenderTask.SetFrameBuffer(mShadowFrameBuffer);
1362
1363     for(auto&& item : mItems)
1364     {
1365       if(item)
1366       {
1367         item->NotifyShadowMapTexture(mShadowTexture);
1368       }
1369     }
1370   }
1371 }
1372
1373 } // namespace Internal
1374 } // namespace Scene3D
1375 } // namespace Dali