/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#include <string_view>
// INTERNAL INCLUDES
+#include <dali-scene3d/internal/common/image-resource-loader.h>
#include <dali-scene3d/internal/controls/model/model-impl.h>
#include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
#include <dali-scene3d/internal/light/light-impl.h>
constexpr int32_t INVALID_INDEX = -1;
constexpr uint32_t MAXIMUM_SIZE_SHADOW_MAP = 2048;
+constexpr int32_t SCENE_ORDER_INDEX = 100;
+constexpr int32_t SHADOW_ORDER_INDEX = 99;
+
static constexpr std::string_view SKYBOX_INTENSITY_STRING = "uIntensity";
-static constexpr std::string_view Y_FLIP_MASK_TEXTURE = "uYFlipMaskTexture";
-static constexpr float FLIP_MASK_TEXTURE = 1.0f;
+static constexpr std::string_view Y_FLIP_MASK_TEXTURE = "uYFlipMaskTexture";
+static constexpr float FLIP_MASK_TEXTURE = 1.0f;
Dali::Actor CreateSkybox()
{
skyboxGeometry.AddVertexBuffer(vertexBuffer);
skyboxGeometry.SetType(Geometry::TRIANGLES);
- Dali::Shader shaderSkybox = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data());
+ Dali::Shader shaderSkybox = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data(), Shader::Hint::NONE, "SCENE3D_SKYBOX_CUBE");
Dali::Renderer skyboxRenderer;
skyboxRenderer = Renderer::New(skyboxGeometry, shaderSkybox);
skyboxRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, 2.0f);
mSkybox(),
mSkyboxOrientation(Quaternion()),
mSkyboxIntensity(1.0f),
+ mLightObservers(),
mShaderManager(new Scene3D::Loader::ShaderManager())
{
}
Dali::AsyncTaskManager::Get().RemoveTask(mSkyboxLoadTask);
mSkyboxLoadTask.Reset();
}
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
}
{
item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
item->NotifyShadowMapTexture(mShadowTexture);
- mItems.push_back(item);
+ mLightObservers.PushBack(item);
}
}
{
if(item)
{
- for(uint32_t i = 0; i < mItems.size(); ++i)
+ auto iter = mLightObservers.Find(item);
+ if(iter != mLightObservers.End())
{
- if(mItems[i] == item)
- {
- mItems.erase(mItems.begin() + i);
- break;
- }
+ mLightObservers.Erase(iter);
}
}
}
mSpecularMipmapLevels = 1u;
NotifyImageBasedLightTextureChange();
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
else
{
{
Dali::AsyncTaskManager::Get().RemoveTask(mIblDiffuseLoadTask);
mIblDiffuseLoadTask.Reset();
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
mIblDiffuseLoadTask = new EnvironmentMapLoadTask(mDiffuseIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &SceneView::OnIblDiffuseLoadComplete));
Dali::AsyncTaskManager::Get().AddTask(mIblDiffuseLoadTask);
{
Dali::AsyncTaskManager::Get().RemoveTask(mIblSpecularLoadTask);
mIblSpecularLoadTask.Reset();
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
mIblSpecularLoadTask = new EnvironmentMapLoadTask(mSpecularIblUrl, Scene3D::EnvironmentMapType::CUBEMAP, MakeCallback(this, &SceneView::OnIblSpecularLoadComplete));
Dali::AsyncTaskManager::Get().AddTask(mIblSpecularLoadTask);
void SceneView::SetImageBasedLightScaleFactor(float scaleFactor)
{
mIblScaleFactor = scaleFactor;
- for(auto&& item : mItems)
+ for(auto&& item : mLightObservers)
{
if(item)
{
SetShadowLightConstraint(selectedCamera, lightCamera);
// make framebuffer for depth map and set it to render task.
- Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
- uint32_t shadowMapBufferSize = std::min(static_cast<uint32_t>(std::max(size.width, size.height)), MAXIMUM_SIZE_SHADOW_MAP);
+ uint32_t shadowMapBufferSize = std::min(std::max(GetResolutionWidth(), GetResolutionHeight()), MAXIMUM_SIZE_SHADOW_MAP);
UpdateShadowMapBuffer(shadowMapBufferSize);
// use lightCamera as a camera of shadow render task.
- mShadowMapRenderTask.SetCameraActor(lightCamera);
+ if(mShadowMapRenderTask)
+ {
+ mShadowMapRenderTask.SetCameraActor(lightCamera);
+ }
mShaderManager->SetShadow(light);
+ UpdateShadowMapBuffer(shadowMapBufferSize);
}
void SceneView::RemoveShadow(Scene3D::Light light)
// reset framebuffer and remove it from render task.
mShadowFrameBuffer.Reset();
mShaderManager->RemoveShadow();
- mShadowMapRenderTask.SetCameraActor(CameraActor());
+ if(mShadowMapRenderTask)
+ {
+ mShadowMapRenderTask.SetCameraActor(CameraActor());
+ }
mShadowLight.Reset();
mShadowTexture.Reset();
- for(auto&& item : mItems)
+ for(auto&& item : mLightObservers)
{
if(item)
{
SetShadow(lightEntity.first);
break;
}
+
+ if(mSceneHolder && mShadowMapRenderTask)
+ {
+ RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
+ taskList.RemoveTask(mShadowMapRenderTask);
+ mShadowMapRenderTask.Reset();
+ }
}
uint32_t SceneView::GetActivatedLightCount() const
// Create new framebuffer with changed multiSamplingLevel.
if(mRenderTask && mFrameBuffer && mTexture)
{
- Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
-
- mFrameBuffer = FrameBuffer::New(size.width, size.height, FrameBuffer::Attachment::DEPTH_STENCIL);
+ mFrameBuffer = FrameBuffer::New(GetResolutionWidth(), GetResolutionHeight(), FrameBuffer::Attachment::DEPTH_STENCIL);
mFrameBuffer.AttachColorTexture(mTexture);
DevelFrameBuffer::SetMultiSamplingLevel(mFrameBuffer, mFrameBufferMultiSamplingLevel);
mRenderTask.SetFrameBuffer(mFrameBuffer);
{
if(mAlphaMaskUrl != alphaMaskUrl)
{
- mAlphaMaskUrl = alphaMaskUrl;
+ mAlphaMaskUrl = alphaMaskUrl;
mMaskingPropertyChanged = true;
UpdateRenderTask();
}
{
if(mCropToMask != enableCropToMask)
{
- mCropToMask = enableCropToMask;
+ mCropToMask = enableCropToMask;
mMaskingPropertyChanged = true;
UpdateRenderTask();
}
return mCropToMask;
}
+Dali::RenderTask SceneView::GetRenderTask()
+{
+ return mRenderTask;
+}
+
void SceneView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value)
{
Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(Dali::BaseHandle(object));
if(mSceneHolder)
{
RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
- mShadowMapRenderTask = taskList.CreateTask();
- mShadowMapRenderTask.SetSourceActor(mRootLayer);
- mShadowMapRenderTask.SetExclusive(true);
- mShadowMapRenderTask.SetInputEnabled(false);
- mShadowMapRenderTask.SetCullMode(false);
- mShadowMapRenderTask.SetClearEnabled(true);
- mShadowMapRenderTask.SetClearColor(Color::WHITE);
- mShadowMapRenderTask.SetRenderPassTag(10);
- mShadowMapRenderTask.SetCameraActor(CameraActor());
-
- mRenderTask = taskList.CreateTask();
+ mRenderTask = taskList.CreateTask();
mRenderTask.SetSourceActor(mRootLayer);
mRenderTask.SetExclusive(true);
mRenderTask.SetInputEnabled(true);
mRenderTask.SetCullMode(false);
+ mRenderTask.SetOrderIndex(SCENE_ORDER_INDEX);
mRenderTask.SetScreenToFrameBufferMappingActor(Self());
UpdateRenderTask();
void SceneView::OnSceneDisconnection()
{
- mItems.clear();
+ mLightObservers.Clear();
Window window = mWindow.GetHandle();
if(window)
{
mRenderTask.SetCameraActor(mSelectedCamera);
}
+ uint32_t width = GetResolutionWidth();
+ uint32_t height = GetResolutionHeight();
- Vector3 size = Self().GetProperty<Vector3>(Dali::Actor::Property::SIZE);
- float aspectRatio = size.width / size.height;
-
- uint32_t shadowMapBufferSize = std::min(static_cast<uint32_t>(std::max(size.width, size.height)), MAXIMUM_SIZE_SHADOW_MAP);
+ uint32_t shadowMapBufferSize = std::min(std::max(width, height), MAXIMUM_SIZE_SHADOW_MAP);
UpdateShadowMapBuffer(shadowMapBufferSize);
if(mUseFrameBuffer)
{
- uint32_t width = (mWindowWidth == 0 || mWindowHeight == 0) ? static_cast<uint32_t>(size.width) : mWindowWidth;
- uint32_t height = (mWindowWidth == 0 || mWindowHeight == 0) ? static_cast<uint32_t>(size.height) : mWindowHeight;
- aspectRatio = static_cast<float>(width) / static_cast<float>(height);
-
Dali::FrameBuffer currentFrameBuffer = mRenderTask.GetFrameBuffer();
if(!currentFrameBuffer ||
- !Dali::Equals(currentFrameBuffer.GetColorTexture().GetWidth(), size.width) ||
- !Dali::Equals(currentFrameBuffer.GetColorTexture().GetHeight(), size.height) ||
+ !Dali::Equals(currentFrameBuffer.GetColorTexture().GetWidth(), width) ||
+ !Dali::Equals(currentFrameBuffer.GetColorTexture().GetHeight(), height) ||
mMaskingPropertyChanged ||
mWindowSizeChanged)
{
mRenderTask.SetClearColor(Color::TRANSPARENT);
mMaskingPropertyChanged = false;
- mWindowSizeChanged = false;
+ mWindowSizeChanged = false;
}
}
else
}
}
- mSelectedCamera.SetAspectRatio(aspectRatio);
+ if(width > 0u && height > 0u)
+ {
+ float aspectRatio = static_cast<float>(width) / static_cast<float>(height);
+ mSelectedCamera.SetAspectRatio(aspectRatio);
+ }
RotateCamera();
}
mSkyboxDirty = false;
mSkyboxResourceReady = true;
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
else
{
{
Dali::AsyncTaskManager::Get().RemoveTask(mSkyboxLoadTask);
mSkyboxLoadTask.Reset();
+
+ // Request image resource GC
+ Dali::Scene3D::Internal::ImageResourceLoader::RequestGarbageCollect();
}
mSkyboxLoadTask = new EnvironmentMapLoadTask(mSkyboxUrl, mSkyboxEnvironmentMapType, MakeCallback(this, &SceneView::OnSkyboxLoadComplete));
Shader skyboxShader;
if(mSkyboxLoadTask->GetEnvironmentMapType() == Scene3D::EnvironmentMapType::CUBEMAP)
{
- skyboxShader = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data());
+ skyboxShader = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_SHADER_FRAG.data(), Shader::Hint::NONE, "SCENE3D_SKYBOX_CUBE");
}
else
{
- skyboxShader = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_EQUIRECTANGULAR_SHADER_FRAG.data());
+ skyboxShader = Shader::New(SHADER_SKYBOX_SHADER_VERT.data(), SHADER_SKYBOX_EQUIRECTANGULAR_SHADER_FRAG.data(), Shader::Hint::NONE, "SCENE3D_SKYBOX_EQUIRECTANGULAR");
}
Renderer skyboxRenderer = (mSkybox.GetRendererCount() > 0u) ? mSkybox.GetRendererAt(0u) : Renderer();
void SceneView::NotifyImageBasedLightTextureChange()
{
- for(auto&& item : mItems)
+ for(auto&& item : mLightObservers)
{
if(item)
{
void SceneView::UpdateShadowMapBuffer(uint32_t shadowMapSize)
{
+ if(!mShadowLight || !mSceneHolder)
+ {
+ return;
+ }
+
+ if(!mShadowMapRenderTask)
+ {
+ RenderTaskList taskList = mSceneHolder.GetRenderTaskList();
+ mShadowMapRenderTask = taskList.CreateTask();
+ mShadowMapRenderTask.SetSourceActor(mRootLayer);
+ mShadowMapRenderTask.SetExclusive(true);
+ mShadowMapRenderTask.SetInputEnabled(false);
+ mShadowMapRenderTask.SetCullMode(false);
+ mShadowMapRenderTask.SetClearEnabled(true);
+ mShadowMapRenderTask.SetClearColor(Color::WHITE);
+ mShadowMapRenderTask.SetRenderPassTag(10);
+ mShadowMapRenderTask.SetCameraActor(GetImplementation(mShadowLight).GetCamera());
+ mShadowMapRenderTask.SetOrderIndex(SHADOW_ORDER_INDEX);
+ }
+
Dali::FrameBuffer currentShadowFrameBuffer = mShadowMapRenderTask.GetFrameBuffer();
- if(mShadowLight &&
- (!currentShadowFrameBuffer ||
- !mShadowTexture ||
- !Dali::Equals(DevelFrameBuffer::GetDepthTexture(currentShadowFrameBuffer).GetWidth(), shadowMapSize)))
+ if(!currentShadowFrameBuffer ||
+ !mShadowTexture ||
+ !Dali::Equals(DevelFrameBuffer::GetDepthTexture(currentShadowFrameBuffer).GetWidth(), shadowMapSize))
{
mShadowFrameBuffer.Reset();
mShadowTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::DEPTH_UNSIGNED_INT, shadowMapSize, shadowMapSize);
DevelFrameBuffer::AttachDepthTexture(mShadowFrameBuffer, mShadowTexture);
mShadowMapRenderTask.SetFrameBuffer(mShadowFrameBuffer);
- for(auto&& item : mItems)
+ for(auto&& item : mLightObservers)
{
if(item)
{