- Loosen the coupling between SceneView and Model using observer.
- Add Priority of IBL. Model IBL has higher priority than SceneView.
Change-Id: I65ebd109911df22704a7106f0e3421a01c342637
Signed-off-by: seungho <sbsh.baek@samsung.com>
END_TEST;
}
-int UtcDaliSceneViewImageBasedLight(void)
+int UtcDaliSceneViewImageBasedLight01(void)
{
ToolkitTestApplication application;
END_TEST;
}
+int UtcDaliSceneViewImageBasedLight02(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
+
+ application.GetScene().Add(view);
+
+ application.SendNotification();
+ application.Render();
+
+ Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
+ view.Add(modelView1);
+
+ view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
+ Dali::Texture diffuseTexture = GetDiffuseTexture(modelView1);
+ Dali::Texture specularTexture = GetSpecularTexture(modelView1);
+
+ modelView1.SetImageBasedLightSource(TEST_SPECULAR_TEXTURE, TEST_DIFFUSE_TEXTURE);
+ DALI_TEST_NOT_EQUALS(GetDiffuseTexture(modelView1), diffuseTexture, 0.0f, TEST_LOCATION);
+ DALI_TEST_NOT_EQUALS(GetSpecularTexture(modelView1), specularTexture, 0.0f, TEST_LOCATION);
+ diffuseTexture = GetDiffuseTexture(modelView1);
+ specularTexture = GetSpecularTexture(modelView1);
+
+ // reset SceneView IBL
+ view.SetImageBasedLightSource("", "");
+ DALI_TEST_EQUALS(GetDiffuseTexture(modelView1), diffuseTexture, TEST_LOCATION);
+ DALI_TEST_EQUALS(GetSpecularTexture(modelView1), specularTexture, TEST_LOCATION);
+
+ modelView1.SetImageBasedLightSource("", "");
+ DALI_TEST_NOT_EQUALS(GetDiffuseTexture(modelView1), diffuseTexture, 0.0f, TEST_LOCATION);
+ DALI_TEST_NOT_EQUALS(GetSpecularTexture(modelView1), specularTexture, 0.0f, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliSceneViewImageBasedLight03(void)
+{
+ ToolkitTestApplication application;
+
+ Scene3D::SceneView view = Scene3D::SceneView::New();
+ view.SetProperty(Dali::Actor::Property::SIZE, Vector2(100, 100));
+
+ application.GetScene().Add(view);
+
+ application.SendNotification();
+ application.Render();
+
+ Scene3D::Model modelView1 = Scene3D::Model::New(TEST_GLTF_FILE_NAME);
+ view.Add(modelView1);
+
+ modelView1.SetImageBasedLightSource(TEST_SPECULAR_TEXTURE, TEST_DIFFUSE_TEXTURE);
+ Dali::Texture diffuseTexture = GetDiffuseTexture(modelView1);
+ Dali::Texture specularTexture = GetSpecularTexture(modelView1);
+
+ view.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
+ DALI_TEST_EQUALS(GetDiffuseTexture(modelView1), diffuseTexture, TEST_LOCATION);
+ DALI_TEST_EQUALS(GetSpecularTexture(modelView1), specularTexture, TEST_LOCATION);
+
+ modelView1.SetImageBasedLightSource("", "");
+ DALI_TEST_NOT_EQUALS(GetDiffuseTexture(modelView1), diffuseTexture, 0.0f, TEST_LOCATION);
+ DALI_TEST_NOT_EQUALS(GetSpecularTexture(modelView1), specularTexture, 0.0f, TEST_LOCATION);
+ diffuseTexture = GetDiffuseTexture(modelView1);
+ specularTexture = GetSpecularTexture(modelView1);
+
+ // reset SceneView IBL
+ view.SetImageBasedLightSource("", "");
+ DALI_TEST_NOT_EQUALS(GetDiffuseTexture(modelView1), diffuseTexture, 0.0f, TEST_LOCATION);
+ DALI_TEST_NOT_EQUALS(GetSpecularTexture(modelView1), specularTexture, 0.0f, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliSceneViewImageBasedFactor(void)
{
ToolkitTestApplication application;
view.SetImageBasedLightScaleFactor(0.5f);
DALI_TEST_EQUALS(view.GetImageBasedLightScaleFactor(), 0.5f, TEST_LOCATION);
- DALI_TEST_EQUALS(modelView1.GetImageBasedLightScaleFactor(), 0.5f, TEST_LOCATION);
+ DALI_TEST_EQUALS(modelView1.GetImageBasedLightScaleFactor(), 1.0f, TEST_LOCATION);
END_TEST;
}
--- /dev/null
+#ifndef DALI_SCENE3D_INTERNAL_IMAGE_BASED_LIGHT_OBSERVER_H
+#define DALI_SCENE3D_INTERNAL_IMAGE_BASED_LIGHT_OBSERVER_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali-toolkit/public-api/dali-toolkit-common.h>
+#include <dali/public-api/rendering/texture.h>
+
+namespace Dali
+{
+namespace Scene3D
+{
+namespace Internal
+{
+class ImageBasedLightObserver
+{
+public:
+ /**
+ * @brief Constructor.
+ */
+ ImageBasedLightObserver() = default;
+
+ /**
+ * @brief Virtual destructor.
+ */
+ virtual ~ImageBasedLightObserver() = default;
+
+ /**
+ * @brief Notifies Image Based Light Textures are changed by parent SceneView.
+ *
+ * @param[in] diffuseTexture cube map texture that can be used as a diffuse IBL source.
+ * @param[in] specularTexture cube map texture that can be used as a specular IBL source.
+ * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.
+ */
+ virtual void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor) = 0;
+
+ /**
+ * @brief Notifies Scale Factor of Image Based Light is changed by parent SceneView.
+ *
+ * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f].
+ */
+ virtual void NotifyImageBasedLightScaleFactor(float scaleFactor) = 0;
+};
+
+} // namespace Internal
+
+} // namespace Scene3D
+
+} // namespace Dali
+
+#endif // DALI_SCENE3D_INTERNAL_IMAGE_BASED_LIGHT_OBSERVER_H
mModelRoot(),
mNaturalSize(Vector3::ZERO),
mModelPivot(AnchorPoint::CENTER),
+ mSceneIblScaleFactor(1.0f),
mIblScaleFactor(1.0f),
mModelChildrenSensitive(DEFAULT_MODEL_CHILDREN_SENSITIVE),
mModelResourceReady(false),
void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
{
mIBLResourceReady = false;
- Texture diffuseTexture = Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl);
- Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(specularUrl);
+ Texture diffuseTexture = (!diffuseUrl.empty()) ? Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl) : Texture();
+ Texture specularTexture = (!specularUrl.empty()) ? Dali::Scene3D::Loader::LoadCubeMap(specularUrl) : Texture();
SetImageBasedLightTexture(diffuseTexture, specularTexture, scaleFactor);
mIBLResourceReady = true;
void Model::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
{
- if(diffuseTexture && specularTexture)
+ // If input texture is wrong, Model is rendered with SceneView's IBL.
+ if(mDiffuseTexture != diffuseTexture || mSpecularTexture != specularTexture)
{
- if(mDiffuseTexture != diffuseTexture || mSpecularTexture != specularTexture)
- {
- mDiffuseTexture = diffuseTexture;
- mSpecularTexture = specularTexture;
- UpdateImageBasedLightTexture();
- }
- if(mIblScaleFactor != scaleFactor)
- {
- mIblScaleFactor = scaleFactor;
- UpdateImageBasedLightScaleFactor();
- }
+ mDiffuseTexture = diffuseTexture;
+ mSpecularTexture = specularTexture;
+ mIblScaleFactor = scaleFactor;
+ UpdateImageBasedLightTexture();
}
}
Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(parent);
if(sceneView)
{
- GetImpl(sceneView).RegisterModel(Scene3D::Model::DownCast(Self()));
+ GetImpl(sceneView).RegisterSceneItem(this);
mParentSceneView = sceneView;
break;
}
Scene3D::SceneView sceneView = mParentSceneView.GetHandle();
if(sceneView)
{
- GetImpl(sceneView).UnregisterModel(Scene3D::Model::DownCast(Self()));
+ GetImpl(sceneView).UnregisterSceneItem(this);
mParentSceneView.Reset();
}
Control::OnSceneDisconnection();
AddModelTreeToAABB(AABB, scene, choices, iRoot, nodeParams, Matrix::IDENTITY);
}
+ if(!resources.mEnvironmentMaps.empty())
+ {
+ mDefaultDiffuseTexture = resources.mEnvironmentMaps.front().second.mDiffuse;
+ mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular;
+ }
+
if(!animations.empty())
{
auto getActor = [&](const std::string& name) {
void Model::UpdateImageBasedLightTexture()
{
- if(!mDiffuseTexture || !mSpecularTexture)
+ Dali::Texture currentDiffuseTexture = (mDiffuseTexture) ? mDiffuseTexture : mSceneDiffuseTexture;
+ Dali::Texture currentSpecularTexture = (mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture;
+ float currentIBLScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
+ if(!currentDiffuseTexture || !currentSpecularTexture)
{
- return;
+ currentDiffuseTexture = mDefaultDiffuseTexture;
+ currentSpecularTexture = mDefaultSpecularTexture;
+ currentIBLScaleFactor = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
}
for(auto&& actor : mRenderableActors)
// EnvMap requires at least 2 texture, diffuse and specular
if(textureCount > 2u)
{
- textures.SetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE, mDiffuseTexture);
- textures.SetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE, mSpecularTexture);
+ textures.SetTexture(textureCount - OFFSET_FOR_DIFFUSE_CUBE_TEXTURE, currentDiffuseTexture);
+ textures.SetTexture(textureCount - OFFSET_FOR_SPECULAR_CUBE_TEXTURE, currentSpecularTexture);
}
}
}
}
+ renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIBLScaleFactor);
}
}
}
void Model::UpdateImageBasedLightScaleFactor()
{
- if(!mDiffuseTexture || !mSpecularTexture)
+ if((!mDiffuseTexture || !mSpecularTexture) &&
+ (!mSceneDiffuseTexture || !mSceneSpecularTexture))
{
return;
}
+
+ float currentIBLScaleFactor = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
for(auto&& actor : mRenderableActors)
{
Actor renderableActor = actor.GetHandle();
if(renderableActor)
{
- renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), mIblScaleFactor);
+ renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIBLScaleFactor);
}
}
}
+void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
+{
+ if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
+ {
+ mSceneDiffuseTexture = diffuseTexture;
+ mSceneSpecularTexture = specularTexture;
+ mSceneIblScaleFactor = scaleFactor;
+ UpdateImageBasedLightTexture();
+ }
+}
+
+void Model::NotifyImageBasedLightScaleFactor(float scaleFactor)
+{
+ mSceneIblScaleFactor = scaleFactor;
+ if(mSceneDiffuseTexture && mSceneSpecularTexture)
+ {
+ UpdateImageBasedLightScaleFactor();
+ }
+}
+
} // namespace Internal
} // namespace Scene3D
} // namespace Dali
// INTERNAL INCLUDES
#include <dali-scene3d/public-api/controls/model/model.h>
#include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
+#include <dali-scene3d/internal/common/image-based-light-observer.h>
namespace Dali
{
/**
* @brief Impl class for Model.
*/
-class Model : public Dali::Toolkit::Internal::Control
+class Model : public Dali::Toolkit::Internal::Control, public ImageBasedLightObserver
{
public:
using AnimationData = std::pair<std::string, Dali::Animation>;
*/
void UpdateImageBasedLightScaleFactor();
+public: // Overrides ImageBasedLightObserver Methods.
+
+ /**
+ * @copydoc Dali::Scene3D::Internal::ImageBasedLightObserver::NotifyImageBasedLightTexture()
+ */
+ void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor) override;
+
+ /**
+ * @copydoc Dali::Scene3D::Internal::ImageBasedLightObserver::NotifyImageBasedLightScaleFactor()
+ */
+ void NotifyImageBasedLightScaleFactor(float scaleFactor) override;
+
private:
std::string mModelUrl;
std::string mResourceDirectoryUrl;
std::vector<WeakHandle<Actor>> mRenderableActors;
WeakHandle<Scene3D::SceneView> mParentSceneView;
+ // TODO: This default texture can be removed after 3D Resource Cache is added.
+ Dali::Texture mDefaultSpecularTexture;
+ Dali::Texture mDefaultDiffuseTexture;
+ Dali::Texture mSceneSpecularTexture;
+ Dali::Texture mSceneDiffuseTexture;
Dali::Texture mSpecularTexture;
Dali::Texture mDiffuseTexture;
Vector3 mNaturalSize;
Vector3 mModelPivot;
+ float mSceneIblScaleFactor;
float mIblScaleFactor;
bool mModelChildrenSensitive;
bool mModelResourceReady;
#include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
#include <dali-scene3d/public-api/loader/cube-map-loader.h>
-#include <dali/integration-api/debug.h>
-
using namespace Dali;
namespace Dali
UpdateCamera(GetCamera(name));
}
-void SceneView::RegisterModel(Scene3D::Model model)
+void SceneView::RegisterSceneItem(Scene3D::Internal::ImageBasedLightObserver *item)
{
- if(model)
+ if(item)
{
- model.SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
- mModels.push_back(model);
+ item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
+ mItems.push_back(item);
}
}
-void SceneView::UnregisterModel(Scene3D::Model model)
+void SceneView::UnregisterSceneItem(Scene3D::Internal::ImageBasedLightObserver *item)
{
- if(model)
+ if(item)
{
- for(uint32_t i = 0; i < mModels.size(); ++i)
+ for(uint32_t i = 0; i < mItems.size(); ++i)
{
- if(mModels[i] == model)
+ if(mItems[i] == item)
{
- mModels.erase(mModels.begin() + i);
+ mItems.erase(mItems.begin() + i);
break;
}
}
void SceneView::SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor)
{
- mIBLResourceReady = false;
- Texture diffuseTexture = Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl);
- if(diffuseTexture)
+ mIBLResourceReady = false;
+
+ // If url is empty or invalid, reset IBL.
+ mDiffuseTexture = (!diffuseUrl.empty()) ? Dali::Scene3D::Loader::LoadCubeMap(diffuseUrl) : Texture();
+ mSpecularTexture = (!specularUrl.empty()) ? Dali::Scene3D::Loader::LoadCubeMap(specularUrl) : Texture();
+
+ mIblScaleFactor = scaleFactor;
+
+ for(auto&& item : mItems)
{
- Texture specularTexture = Dali::Scene3D::Loader::LoadCubeMap(specularUrl);
- if(specularTexture)
+ if(item)
{
- mDiffuseTexture = diffuseTexture;
- mSpecularTexture = specularTexture;
- mIblScaleFactor = scaleFactor;
-
- for(auto&& model : mModels)
- {
- if(model)
- {
- model.SetImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
- }
- }
+ item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
}
}
+
mIBLResourceReady = true;
if(IsResourceReady())
{
void SceneView::SetImageBasedLightScaleFactor(float scaleFactor)
{
mIblScaleFactor = scaleFactor;
- for(auto&& model : mModels)
+ for(auto&& item : mItems)
{
- if(model)
+ if(item)
{
- model.SetImageBasedLightScaleFactor(scaleFactor);
+ item->NotifyImageBasedLightScaleFactor(scaleFactor);
}
}
}
void SceneView::OnSceneDisconnection()
{
- mModels.clear();
+ mItems.clear();
Window window = DevelWindow::Get(Self());
if(window)
#include <dali/public-api/rendering/texture.h>
// INTERNAL INCLUDES
-#include <dali-scene3d/public-api/controls/model/model.h>
+#include <dali-scene3d/internal/common/image-based-light-observer.h>
#include <dali-scene3d/public-api/controls/scene-view/scene-view.h>
namespace Dali
void SelectCamera(const std::string& name);
/**
- * @brief Register a Model.
- * Some works like ibl setting should be applied on the only Model not the all child actors.
- * SceneView contains child Model list to apply the works effectively.
+ * @brief Register an item.
*
- * @param[in] model Model to be registered.
+ * Some works(e.g, lighting) of SceneView should be propagated to the child 3D items.
+ * SceneView can avoid unnecessary tree traversal to find 3D items by storing only 3D items as a list.
+ *
+ * @param[in] item scene observer to be registered.
*/
- void RegisterModel(Scene3D::Model model);
+ void RegisterSceneItem(Scene3D::Internal::ImageBasedLightObserver* item);
/**
- * @brief Unregister a Model
+ * @brief Unregister an item
*
- * @param[in] model Model to be unregistered.
+ * @param[in] item scene observer to be unregistered.
*/
- void UnregisterModel(Scene3D::Model model);
+ void UnregisterSceneItem(Scene3D::Internal::ImageBasedLightObserver* item);
/**
* @copydoc SceneView::SetImageBasedLightSource()
/////////////////////////////////////////////////////////////
// FrameBuffer and Rendertask to render child objects as a 3D Scene
- CameraActor mDefaultCamera;
- CameraActor mSelectedCamera;
- std::vector<CameraActor> mCameras;
- std::vector<Scene3D::Model> mModels;
- Dali::FrameBuffer mRenderTarget;
- Dali::Texture mTexture;
- Dali::RenderTask mRenderTask;
- Layer mRootLayer;
- int32_t mWindowOrientation;
- Dali::Actor mSkybox;
- Quaternion mSkyboxOrientation;
- float mSkyboxIntensity{1.0f};
+ CameraActor mDefaultCamera;
+ CameraActor mSelectedCamera;
+ std::vector<CameraActor> mCameras;
+ std::vector<Scene3D::Internal::ImageBasedLightObserver*> mItems;
+ Dali::FrameBuffer mRenderTarget;
+ Dali::Texture mTexture;
+ Dali::RenderTask mRenderTask;
+ Layer mRootLayer;
+ int32_t mWindowOrientation;
+ Dali::Actor mSkybox;
+ Quaternion mSkyboxOrientation;
+ float mSkyboxIntensity{1.0f};
Dali::Texture mSpecularTexture;
Dali::Texture mDiffuseTexture;
set(scene3d_internal_dir "${scene3d_dir}/internal")
set(scene3d_src_files ${scene3d_src_files}
+ ${scene3d_internal_dir}/controls/model/model-impl.cpp
+ ${scene3d_internal_dir}/controls/scene-view/scene-view-impl.cpp
${scene3d_internal_dir}/loader/gltf2-asset.cpp
${scene3d_internal_dir}/loader/hash.cpp
${scene3d_internal_dir}/loader/json-reader.cpp
${scene3d_internal_dir}/loader/json-util.cpp
- ${scene3d_internal_dir}/controls/model/model-impl.cpp
- ${scene3d_internal_dir}/controls/scene-view/scene-view-impl.cpp
)
{
return (nullptr == DALI_IMAGE_DIR) ? Dali::EnvironmentVariable::GetEnvironmentVariable(TOKEN_STRING(DALI_IMAGE_DIR)) : DALI_IMAGE_DIR;
}
+
+static constexpr float DEFAULT_INTENSITY = 1.0f;
} // unnamed namespace
namespace Dali
return textures;
}
+float EnvironmentDefinition::GetDefaultIntensity()
+{
+ return DEFAULT_INTENSITY;
+}
+
} // namespace Loader
} // namespace Scene3D
} // namespace Dali
*/
Textures Load(RawData&& raw) const;
+ /**
+ * @brief Get default intensity value.
+ * @return Default intensity. (1.0f)
+ */
+ static float GetDefaultIntensity();
+
public: // DATA
std::string mDiffuseMapPath;
std::string mSpecularMapPath;
const std::string ROOT_NODE_NAME("RootNode");
const Vector3 SCALE_TO_ADJUST(100.0f, 100.0f, 100.0f);
-constexpr float DEFAULT_INTENSITY = 0.5f;
-
const Geometry::Type GLTF2_TO_DALI_PRIMITIVES[]{
Geometry::POINTS,
Geometry::LINES,
{
EnvironmentDefinition envDef;
envDef.mUseBrdfTexture = true;
- envDef.mIblIntensity = DEFAULT_INTENSITY;
+ envDef.mIblIntensity = Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
cctx.mOutput.mResources.mEnvironmentMaps.push_back({std::move(envDef), EnvironmentDefinition::Textures()});
}