From: Adeel Kazmi Date: Fri, 1 Sep 2023 14:02:39 +0000 (+0000) Subject: Merge changes I776588c1,I7292a2fb into devel/master X-Git-Tag: dali_2.2.43~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4dec2735f5e5b5ed74f70a402c9a008d6c21af05;hp=537c38c0fc284ad7c61b8d815a9d4ec9f3ab4edc;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git Merge changes I776588c1,I7292a2fb into devel/master * changes: Adding chipmunk implementation for physics adaptor Adding bullet physics files --- diff --git a/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp b/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp index adf95eb..723c3ae 100644 --- a/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp +++ b/automated-tests/src/dali-scene3d-internal/utc-Dali-Gltf2LoaderImpl.cpp @@ -209,6 +209,7 @@ int UtcDaliGltfLoaderSuccess1(void) Scene3D::Material::AlphaModeType::MASK, true, true, + true, { { MaterialDefinition::ALBEDO, @@ -291,6 +292,7 @@ int UtcDaliGltfLoaderSuccess1(void) Scene3D::Material::AlphaModeType::OPAQUE, true, false, + true, { { MaterialDefinition::ALBEDO, @@ -620,7 +622,7 @@ int UtcDaliGltfLoaderMRendererTest(void) DALI_TEST_EQUAL(child.GetProperty(Actor::Property::NAME).Get(), "RootNode"); DALI_TEST_EQUAL(child.GetProperty(Actor::Property::SCALE).Get(), Vector3(1.0f, 1.0f, 1.0f)); DALI_TEST_EQUAL(child.GetRendererCount(), 1u); - DALI_TEST_EQUAL(child.GetRendererAt(0).GetTextures().GetTextureCount(), 4u); + DALI_TEST_EQUAL(child.GetRendererAt(0).GetTextures().GetTextureCount(), 5u); DALI_TEST_EQUAL(child.GetRendererCount(), 1u); DALI_TEST_EQUAL(child.GetRendererAt(0u).GetProperty(Renderer::Property::BLEND_MODE), BlendMode::ON); diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Light.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Light.cpp index 01bb4b0..cc5bc7f 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-Light.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-Light.cpp @@ -599,3 +599,450 @@ int UtcDaliLightModelAddAndRemove(void) END_TEST; } + +// Enable Shadow and add the light to SceneView. +int UtcDaliLightEnableShadowOnScene01(void) +{ + ToolkitTestApplication application; + + Scene3D::SceneView sceneView = Scene3D::SceneView::New(); + sceneView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + sceneView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + sceneView.SetProperty(Dali::Actor::Property::WIDTH_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + sceneView.SetProperty(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + application.GetScene().Add(sceneView); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + sceneView.Add(model); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + application.SendNotification(); + application.Render(); + + // Light is added on layer when on scene + DALI_TEST_EQUALS(true, model.GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE), TEST_LOCATION); + + Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u); + DALI_TEST_CHECK(renderer); + Shader shader = renderer.GetShader(); + DALI_TEST_CHECK(shader); + + auto shadowEnabledIndex = shader.GetPropertyIndex("uIsShadowEnabled"); + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + Scene3D::Light light = Scene3D::Light::New(); + light.SetProperty(Dali::Actor::Property::COLOR, Color::BLUE); + Dali::DevelActor::LookAt(light, Vector3(1.0f, 0.0f, 0.0f)); + light.EnableShadow(true); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + sceneView.Add(light); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + END_TEST; +} + +// Add the light to SceneView and Enable Shadow. +int UtcDaliLightEnableShadowOnScene02(void) +{ + ToolkitTestApplication application; + + Scene3D::SceneView sceneView = Scene3D::SceneView::New(); + sceneView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + sceneView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + sceneView.SetProperty(Dali::Actor::Property::WIDTH_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + sceneView.SetProperty(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + application.GetScene().Add(sceneView); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + sceneView.Add(model); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + application.SendNotification(); + application.Render(); + + // Light is added on layer when on scene + DALI_TEST_EQUALS(true, model.GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE), TEST_LOCATION); + + Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u); + DALI_TEST_CHECK(renderer); + Shader shader = renderer.GetShader(); + DALI_TEST_CHECK(shader); + + auto shadowEnabledIndex = shader.GetPropertyIndex("uIsShadowEnabled"); + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + Scene3D::Light light = Scene3D::Light::New(); + light.SetProperty(Dali::Actor::Property::COLOR, Color::BLUE); + Dali::DevelActor::LookAt(light, Vector3(1.0f, 0.0f, 0.0f)); + sceneView.Add(light); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + light.EnableShadow(true); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + light.EnableShadow(true); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + END_TEST; +} + +// Add the light to SceneView and Add Model. +int UtcDaliLightEnableShadowOnScene03(void) +{ + ToolkitTestApplication application; + + Scene3D::SceneView sceneView = Scene3D::SceneView::New(); + sceneView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + sceneView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + sceneView.SetProperty(Dali::Actor::Property::WIDTH_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + sceneView.SetProperty(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + application.GetScene().Add(sceneView); + + Scene3D::Light light = Scene3D::Light::New(); + light.SetProperty(Dali::Actor::Property::COLOR, Color::BLUE); + Dali::DevelActor::LookAt(light, Vector3(1.0f, 0.0f, 0.0f)); + light.EnableShadow(true); + sceneView.Add(light); + + application.SendNotification(); + application.Render(); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + sceneView.Add(model); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + application.SendNotification(); + application.Render(); + + // Light is added on layer when on scene + DALI_TEST_EQUALS(true, model.GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE), TEST_LOCATION); + + Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u); + DALI_TEST_CHECK(renderer); + Shader shader = renderer.GetShader(); + DALI_TEST_CHECK(shader); + + auto shadowEnabledIndex = shader.GetPropertyIndex("uIsShadowEnabled"); + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + END_TEST; +} + +// Disable Shadow +int UtcDaliLightDisableShadow01(void) +{ + ToolkitTestApplication application; + + Scene3D::SceneView sceneView = Scene3D::SceneView::New(); + sceneView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + sceneView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + sceneView.SetProperty(Dali::Actor::Property::WIDTH_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + sceneView.SetProperty(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + application.GetScene().Add(sceneView); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + sceneView.Add(model); + + Scene3D::Light light = Scene3D::Light::New(); + light.SetProperty(Dali::Actor::Property::COLOR, Color::BLUE); + Dali::DevelActor::LookAt(light, Vector3(1.0f, 0.0f, 0.0f)); + light.EnableShadow(true); + sceneView.Add(light); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + application.SendNotification(); + application.Render(); + + // Light is added on layer when on scene + DALI_TEST_EQUALS(true, model.GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE), TEST_LOCATION); + + Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u); + DALI_TEST_CHECK(renderer); + Shader shader = renderer.GetShader(); + DALI_TEST_CHECK(shader); + + auto shadowEnabledIndex = shader.GetPropertyIndex("uIsShadowEnabled"); + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + light.EnableShadow(false); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + light.EnableShadow(true); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + light.Unparent(); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + END_TEST; +} + +// Disable Shadow +int UtcDaliLightDisableShadow02(void) +{ + ToolkitTestApplication application; + + Scene3D::SceneView sceneView = Scene3D::SceneView::New(); + sceneView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + sceneView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + sceneView.SetProperty(Dali::Actor::Property::WIDTH_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + sceneView.SetProperty(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + application.GetScene().Add(sceneView); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + sceneView.Add(model); + + Scene3D::Light light = Scene3D::Light::New(); + light.SetProperty(Dali::Actor::Property::COLOR, Color::BLUE); + Dali::DevelActor::LookAt(light, Vector3(1.0f, 0.0f, 0.0f)); + light.EnableShadow(true); + sceneView.Add(light); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + application.SendNotification(); + application.Render(); + + // Light is added on layer when on scene + DALI_TEST_EQUALS(true, model.GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE), TEST_LOCATION); + + Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u); + DALI_TEST_CHECK(renderer); + Shader shader = renderer.GetShader(); + DALI_TEST_CHECK(shader); + + auto shadowEnabledIndex = shader.GetPropertyIndex("uIsShadowEnabled"); + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + light.EnableShadow(false); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + light.EnableShadow(true); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + Scene3D::Light newLight = Scene3D::Light::New(); + newLight.SetProperty(Dali::Actor::Property::COLOR, Color::BLUE); + Dali::DevelActor::LookAt(newLight, Vector3(1.0f, 0.0f, 0.0f)); + newLight.EnableShadow(true); + sceneView.Add(newLight); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + // Disable light's shadow, the shadow of newLight is rendered + light.EnableShadow(false); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + // Enable light's shadow, but newLight's shadow is rendered. + light.EnableShadow(true); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + // Disable newLight's shadow, light's shadow is rendered. + newLight.Unparent(); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + // Every shadow is disabled. + light.Unparent(); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + END_TEST; +} + +// Make a light EnableShadow that is not enabled on scene +int UtcDaliLightEnableShadowOfNotEnabledLight(void) +{ + ToolkitTestApplication application; + + Scene3D::SceneView sceneView = Scene3D::SceneView::New(); + sceneView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + sceneView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + sceneView.SetProperty(Dali::Actor::Property::WIDTH_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + sceneView.SetProperty(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + application.GetScene().Add(sceneView); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + sceneView.Add(model); + + uint32_t maxLightCount = Scene3D::Light::GetMaximumEnabledLightCount(); + std::vector lights; + for(uint32_t i = 0; i < maxLightCount; ++i) + { + Scene3D::Light light = Scene3D::Light::New(); + light.SetProperty(Dali::Actor::Property::COLOR, Color::BLUE); + Dali::DevelActor::LookAt(light, Vector3(1.0f, 0.0f, 0.0f)); + sceneView.Add(light); + lights.push_back(light); + } + + Scene3D::Light shadowLight = Scene3D::Light::New(); + shadowLight.SetProperty(Dali::Actor::Property::COLOR, Color::BLUE); + Dali::DevelActor::LookAt(shadowLight, Vector3(1.0f, 0.0f, 0.0f)); + sceneView.Add(shadowLight); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + application.SendNotification(); + application.Render(); + + // Light is added on layer when on scene + DALI_TEST_EQUALS(true, model.GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE), TEST_LOCATION); + + Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u); + DALI_TEST_CHECK(renderer); + Shader shader = renderer.GetShader(); + DALI_TEST_CHECK(shader); + + auto shadowEnabledIndex = shader.GetPropertyIndex("uIsShadowEnabled"); + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + shadowLight.EnableShadow(true); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + lights[0].Enable(false); + + DALI_TEST_CHECK(shadowEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowEnabledIndex), TEST_LOCATION); + + END_TEST; +} + +// Set/Get Shadow Properties +int UtcDaliLightSetGetProperty(void) +{ + ToolkitTestApplication application; + + Scene3D::SceneView sceneView = Scene3D::SceneView::New(); + sceneView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + sceneView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + sceneView.SetProperty(Dali::Actor::Property::WIDTH_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + sceneView.SetProperty(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + application.GetScene().Add(sceneView); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + sceneView.Add(model); + + Scene3D::Light light = Scene3D::Light::New(); + light.SetProperty(Dali::Actor::Property::COLOR, Color::BLUE); + Dali::DevelActor::LookAt(light, Vector3(1.0f, 0.0f, 0.0f)); + light.EnableShadow(true); + sceneView.Add(light); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + application.SendNotification(); + application.Render(); + + // Light is added on layer when on scene + DALI_TEST_EQUALS(true, model.GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE), TEST_LOCATION); + + DALI_TEST_EQUALS(0.001f, light.GetShadowBias(), TEST_LOCATION); + light.SetShadowBias(0.1f); + DALI_TEST_EQUALS(0.1f, light.GetShadowBias(), TEST_LOCATION); + + DALI_TEST_EQUALS(0.5f, light.GetShadowIntensity(), TEST_LOCATION); + light.SetShadowIntensity(0.1f); + DALI_TEST_EQUALS(0.1f, light.GetShadowIntensity(), TEST_LOCATION); + + END_TEST; +} + +// Enable PCF for soft shadow edge. +int UtcDaliLightShadowSoftFiltering(void) +{ + ToolkitTestApplication application; + + Scene3D::SceneView sceneView = Scene3D::SceneView::New(); + sceneView.SetProperty(Dali::Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + sceneView.SetProperty(Dali::Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + sceneView.SetProperty(Dali::Actor::Property::WIDTH_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + sceneView.SetProperty(Dali::Actor::Property::HEIGHT_RESIZE_POLICY, ResizePolicy::FILL_TO_PARENT); + application.GetScene().Add(sceneView); + + Scene3D::Model model = Scene3D::Model::New(TEST_GLTF_FILE_NAME); + sceneView.Add(model); + + Scene3D::Light light = Scene3D::Light::New(); + light.SetProperty(Dali::Actor::Property::COLOR, Color::BLUE); + Dali::DevelActor::LookAt(light, Vector3(1.0f, 0.0f, 0.0f)); + light.EnableShadow(true); + sceneView.Add(light); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Test::WaitForEventThreadTrigger(1), true, TEST_LOCATION); + application.SendNotification(); + application.Render(); + + // Light is added on layer when on scene + DALI_TEST_EQUALS(true, model.GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE), TEST_LOCATION); + + Renderer renderer = model.FindChildByName("node2").GetRendererAt(0u); + DALI_TEST_CHECK(renderer); + Shader shader = renderer.GetShader(); + DALI_TEST_CHECK(shader); + + DALI_TEST_EQUALS(false, light.IsShadowSoftFilteringEnabled(), TEST_LOCATION); + auto shadowFilteringEnabledIndex = shader.GetPropertyIndex("uEnableShadowSoftFiltering"); + DALI_TEST_CHECK(shadowFilteringEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowFilteringEnabledIndex), TEST_LOCATION); + + light.EnableShadowSoftFiltering(true); + DALI_TEST_EQUALS(true, light.IsShadowSoftFilteringEnabled(), TEST_LOCATION); + + DALI_TEST_CHECK(shadowFilteringEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(1, shader.GetProperty(shadowFilteringEnabledIndex), TEST_LOCATION); + + light.EnableShadowSoftFiltering(false); + DALI_TEST_EQUALS(false, light.IsShadowSoftFilteringEnabled(), TEST_LOCATION); + DALI_TEST_CHECK(shadowFilteringEnabledIndex != DALI_KEY_INVALID); + DALI_TEST_EQUALS(0, shader.GetProperty(shadowFilteringEnabledIndex), TEST_LOCATION); + + END_TEST; +} diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp index 30b755d..1b898a0 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-Model.cpp @@ -424,10 +424,10 @@ int UtcDaliModelSetImageBasedLightSource01(void) DALI_TEST_CHECK(renderer); TextureSet textureSet = renderer.GetTextures(); - DALI_TEST_EQUALS(textureSet.GetTextureCount(), 9u, TEST_LOCATION); + DALI_TEST_EQUALS(textureSet.GetTextureCount(), 10u, TEST_LOCATION); - Texture diffuseTexture = textureSet.GetTexture(7u); - Texture specularTexture = textureSet.GetTexture(8u); + Texture diffuseTexture = textureSet.GetTexture(8u); + Texture specularTexture = textureSet.GetTexture(9u); gResourceReadyCalled = false; DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION); @@ -443,8 +443,8 @@ int UtcDaliModelSetImageBasedLightSource01(void) DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION); TextureSet newTextureSet = renderer.GetTextures(); - Texture newDiffuseTexture = newTextureSet.GetTexture(7u); - Texture newSpecularTexture = newTextureSet.GetTexture(8u); + Texture newDiffuseTexture = newTextureSet.GetTexture(8u); + Texture newSpecularTexture = newTextureSet.GetTexture(9u); DALI_TEST_NOT_EQUALS(diffuseTexture, newDiffuseTexture, 0.0f, TEST_LOCATION); DALI_TEST_NOT_EQUALS(specularTexture, newSpecularTexture, 0.0f, TEST_LOCATION); @@ -481,16 +481,16 @@ int UtcDaliModelSetImageBasedLightSource02(void) DALI_TEST_CHECK(renderer); TextureSet textureSet = renderer.GetTextures(); - DALI_TEST_EQUALS(textureSet.GetTextureCount(), 9u, TEST_LOCATION); + DALI_TEST_EQUALS(textureSet.GetTextureCount(), 10u, TEST_LOCATION); - Texture diffuseTexture = textureSet.GetTexture(7u); - Texture specularTexture = textureSet.GetTexture(8u); + Texture diffuseTexture = textureSet.GetTexture(8u); + Texture specularTexture = textureSet.GetTexture(9u); // if url is empty, loading is not requested. model.SetImageBasedLightSource("", ""); - Texture newDiffuseTexture = textureSet.GetTexture(7u); - Texture newSpecularTexture = textureSet.GetTexture(8u); + Texture newDiffuseTexture = textureSet.GetTexture(8u); + Texture newSpecularTexture = textureSet.GetTexture(9u); DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION); DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION); @@ -525,10 +525,10 @@ int UtcDaliModelSetImageBasedLightSource03(void) DALI_TEST_CHECK(renderer); TextureSet textureSet = renderer.GetTextures(); - DALI_TEST_EQUALS(textureSet.GetTextureCount(), 9u, TEST_LOCATION); + DALI_TEST_EQUALS(textureSet.GetTextureCount(), 10u, TEST_LOCATION); - Texture diffuseTexture = textureSet.GetTexture(7u); - Texture specularTexture = textureSet.GetTexture(8u); + Texture diffuseTexture = textureSet.GetTexture(8u); + Texture specularTexture = textureSet.GetTexture(9u); gResourceReadyCalled = false; DALI_TEST_EQUALS(gResourceReadyCalled, false, TEST_LOCATION); @@ -543,8 +543,8 @@ int UtcDaliModelSetImageBasedLightSource03(void) DALI_TEST_EQUALS(gResourceReadyCalled, true, TEST_LOCATION); - Texture newDiffuseTexture = textureSet.GetTexture(7u); - Texture newSpecularTexture = textureSet.GetTexture(8u); + Texture newDiffuseTexture = textureSet.GetTexture(8u); + Texture newSpecularTexture = textureSet.GetTexture(9u); DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION); DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION); @@ -1352,16 +1352,16 @@ int UtcDaliModelResourceCacheCheck(void) // but all the other textures are still the same TextureSet textureSet2 = renderer2.GetTextures(); TextureSet textureSet3 = renderer3.GetTextures(); - DALI_TEST_EQUALS(textureSet2.GetTextureCount(), 9u, TEST_LOCATION); - DALI_TEST_EQUALS(textureSet3.GetTextureCount(), 9u, TEST_LOCATION); + DALI_TEST_EQUALS(textureSet2.GetTextureCount(), 10u, TEST_LOCATION); + DALI_TEST_EQUALS(textureSet3.GetTextureCount(), 10u, TEST_LOCATION); for(uint32_t i = 0; i < 7u; i++) { DALI_TEST_EQUALS(textureSet2.GetTexture(i), textureSet3.GetTexture(i), TEST_LOCATION); } - DALI_TEST_NOT_EQUALS(textureSet2.GetTexture(7u), textureSet3.GetTexture(7u), 0.0f, TEST_LOCATION); - DALI_TEST_NOT_EQUALS(textureSet2.GetTexture(8u), textureSet3.GetTexture(8u), 0.0f, TEST_LOCATION); + DALI_TEST_NOT_EQUALS(textureSet2.GetTexture(8u), textureSet3.GetTexture(7u), 0.0f, TEST_LOCATION); + DALI_TEST_NOT_EQUALS(textureSet2.GetTexture(9u), textureSet3.GetTexture(8u), 0.0f, TEST_LOCATION); END_TEST; } diff --git a/automated-tests/src/dali-scene3d/utc-Dali-PathFinding.cpp b/automated-tests/src/dali-scene3d/utc-Dali-PathFinding.cpp index b0cfeb4..d924c3a 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-PathFinding.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-PathFinding.cpp @@ -109,7 +109,7 @@ int UtcDaliPathFinderFindShortestPath0(void) auto navmesh = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin"); std::vector testAlgorithms = { - PathFinderAlgorithm::DJIKSTRA_SHORTEST_PATH, + PathFinderAlgorithm::DIJKSTRA_SHORTEST_PATH, PathFinderAlgorithm::SPFA, }; @@ -159,7 +159,7 @@ int UtcDaliPathFinderFindShortestPath1(void) navmesh->SetSceneTransform(Matrix(Matrix::IDENTITY)); std::vector testAlgorithms = { - PathFinderAlgorithm::DJIKSTRA_SHORTEST_PATH, + PathFinderAlgorithm::DIJKSTRA_SHORTEST_PATH, PathFinderAlgorithm::SPFA, PathFinderAlgorithm::SPFA_DOUBLE_WAY, /* Note : Even this algorithm doesn't found shortest path, UTC will pass. */ }; diff --git a/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp b/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp index 53e7725..ca87d38 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp @@ -88,9 +88,9 @@ Dali::Texture GetDiffuseTexture(Dali::Scene3D::Model model) if(renderer) { TextureSet textureSet = renderer.GetTextures(); - if(textureSet.GetTextureCount() == 9u) + if(textureSet.GetTextureCount() == 10u) { - texture = textureSet.GetTexture(7u); + texture = textureSet.GetTexture(8u); } } } @@ -109,9 +109,9 @@ Dali::Texture GetSpecularTexture(Dali::Scene3D::Model model) if(renderer) { TextureSet textureSet = renderer.GetTextures(); - if(textureSet.GetTextureCount() == 9u) + if(textureSet.GetTextureCount() == 10u) { - texture = textureSet.GetTexture(8u); + texture = textureSet.GetTexture(9u); } } } @@ -327,9 +327,9 @@ int UtcDaliSceneViewOnScene02(void) application.Render(); renderTaskCount = application.GetScene().GetRenderTaskList().GetTaskCount(); - DALI_TEST_EQUALS(2u, renderTaskCount, TEST_LOCATION); + DALI_TEST_EQUALS(3u, renderTaskCount, TEST_LOCATION); - RenderTask renderTask = application.GetScene().GetRenderTaskList().GetTask(1u); + RenderTask renderTask = application.GetScene().GetRenderTaskList().GetTask(2u); CameraActor camera = renderTask.GetCameraActor(); CameraActor defaultCamera = renderTask.GetCameraActor(); @@ -693,7 +693,7 @@ int UtcDaliSceneViewUseFramebuffer02(void) application.SendNotification(); application.Render(); - RenderTask renderTask = application.GetScene().GetRenderTaskList().GetTask(1u); + RenderTask renderTask = application.GetScene().GetRenderTaskList().GetTask(2u); DALI_TEST_CHECK(!renderTask.GetFrameBuffer()); view.UseFramebuffer(true); @@ -1005,7 +1005,7 @@ int UtcDaliSceneViewCreateAndRemoveRenderTask(void) application.GetScene().Add(view); - DALI_TEST_EQUALS(renderTaskCount + 1, application.GetScene().GetRenderTaskList().GetTaskCount(), TEST_LOCATION); + DALI_TEST_EQUALS(renderTaskCount + 2, application.GetScene().GetRenderTaskList().GetTaskCount(), TEST_LOCATION); view.Unparent(); diff --git a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp index 6a5a089..732d6b1 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-AnimatedVectorImageVisual.cpp @@ -2126,3 +2126,153 @@ int UtcDaliAnimatedVectorImageVisualDesiredSize(void) END_TEST; } + +int UtcDaliAnimatedVectorImageVisualFlushAction(void) +{ + ToolkitTestApplication application; + + tet_infoline("UtcDaliAnimatedVectorImageVisualFlushAction"); + + int startFrame = 1; + int endFrame = 2; + + int totalFrameCount = 0; + + Property::Array playRange; + playRange.PushBack(startFrame); + playRange.PushBack(endFrame); + + Property::Map resultMap; + Property::Value* value = nullptr; + + // request AnimatedVectorImageVisual with a property map + VisualFactory factory = VisualFactory::Get(); + Visual::Base visual = factory.CreateVisual( + Property::Map() + .Add(Toolkit::Visual::Property::TYPE, DevelVisual::ANIMATED_VECTOR_IMAGE) + .Add(ImageVisual::Property::URL, TEST_VECTOR_IMAGE_FILE_NAME) + .Add(DevelImageVisual::Property::PLAY_RANGE, playRange) + .Add(ImageVisual::Property::SYNCHRONOUS_LOADING, true)); + + DummyControl dummyControl = DummyControl::New(true); + Impl::DummyControl& dummyImpl = static_cast(dummyControl.GetImplementation()); + dummyImpl.RegisterVisual(DummyControl::Property::TEST_VISUAL, visual); + dummyControl.SetResizePolicy(ResizePolicy::FILL_TO_PARENT, Dimension::ALL_DIMENSIONS); + + application.GetScene().Add(dummyControl); + + // Retry function to get playrange until expect values comes. + auto CheckAndRetryPlayRange = [&](int expectStartFrame, int expectEndFrame, std::vector> retrialFrames) { + int tryCount = 0; + int tryCountMax = 30; + while(++tryCount <= tryCountMax) + { + Property::Map resultMap = dummyControl.GetProperty(DummyControl::Property::TEST_VISUAL); + + Property::Value* value = resultMap.Find(DevelImageVisual::Property::PLAY_RANGE, Property::ARRAY); + DALI_TEST_CHECK(value); + + Property::Array* result = value->GetArray(); + DALI_TEST_CHECK(result); + DALI_TEST_EQUALS(result->Count(), 2, TEST_LOCATION); + + bool tryAgain = false; + for(auto& framePair : retrialFrames) + { + if(result->GetElementAt(0).Get() == framePair.first && result->GetElementAt(1).Get() == framePair.second) + { + tryAgain = true; + break; + } + } + if(tryAgain) + { + tet_printf("Retry to get value again! [%d]\n", tryCount); + // Dummy sleep 1 second. + Test::WaitForEventThreadTrigger(1, 1); + continue; + } + + DALI_TEST_EQUALS(result->GetElementAt(0).Get(), expectStartFrame, TEST_LOCATION); + DALI_TEST_EQUALS(result->GetElementAt(1).Get(), expectEndFrame, TEST_LOCATION); + break; + } + DALI_TEST_CHECK(tryCount <= tryCountMax); + }; + + tet_printf("Pause lottie first.\n"); + + Property::Map attributes; + DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::PAUSE, attributes); + + application.SendNotification(); + application.Render(16); + + do + { + resultMap = dummyControl.GetProperty(DummyControl::Property::TEST_VISUAL); + + value = resultMap.Find(DevelImageVisual::Property::TOTAL_FRAME_NUMBER, Property::INTEGER); + DALI_TEST_CHECK(value); + totalFrameCount = value->Get(); + } while(totalFrameCount == 0); + + // Ensure that vector data sended well. + CheckAndRetryPlayRange(startFrame, endFrame, {{0, 0}, {0, totalFrameCount - 1}}); + + resultMap = dummyControl.GetProperty(DummyControl::Property::TEST_VISUAL); + + value = resultMap.Find(DevelImageVisual::Property::CURRENT_FRAME_NUMBER, Property::INTEGER); + DALI_TEST_CHECK(value); + DALI_TEST_EQUALS(value->Get(), startFrame, TEST_LOCATION); + + tet_printf("Now logically, range : [%d~%d], current : %d\n", startFrame, endFrame, startFrame); + + int changedStartFrame1 = startFrame + 2; + int changedEndFrame1 = endFrame + 2; + + playRange.Clear(); + playRange.Add(changedStartFrame1); + playRange.Add(changedEndFrame1); + + tet_printf("Change play range\n"); + attributes.Add(DevelImageVisual::Property::PLAY_RANGE, playRange); + DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes); + + tet_printf("Jump to changedEndFrame!\n"); + DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::JUMP_TO, changedEndFrame1); + + attributes.Clear(); + tet_infoline("Flush Action!"); + tet_printf("Now logically, range : [%d~%d], current : %d\n", changedStartFrame1, changedEndFrame1, changedEndFrame1); + DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelAnimatedVectorImageVisual::Action::FLUSH, attributes); + + int changedStartFrame2 = startFrame + 1; + int changedEndFrame2 = endFrame + 1; + + playRange.Clear(); + playRange.Add(changedStartFrame2); + playRange.Add(changedEndFrame2); + + tet_printf("Change play range again\n"); + tet_printf("Now logically, range : [%d~%d], current : %d\n", changedStartFrame2, changedEndFrame2, changedEndFrame2); + attributes.Add(DevelImageVisual::Property::PLAY_RANGE, playRange); + DevelControl::DoAction(dummyControl, DummyControl::Property::TEST_VISUAL, Dali::Toolkit::DevelVisual::Action::UPDATE_PROPERTY, attributes); + + application.SendNotification(); + application.Render(16); + + // Ensure that vector data sended well. + CheckAndRetryPlayRange(changedStartFrame2, changedEndFrame2, {{changedStartFrame1, changedEndFrame1}, {startFrame, endFrame}}); + + resultMap = dummyControl.GetProperty(DummyControl::Property::TEST_VISUAL); + + tet_printf("Test whether current frame number changed well. If Flush not works, current frame become startFrame."); + value = resultMap.Find(DevelImageVisual::Property::CURRENT_FRAME_NUMBER, Property::INTEGER); + DALI_TEST_CHECK(value); + DALI_TEST_EQUALS(value->Get(), changedEndFrame2, TEST_LOCATION); + + dummyControl.Unparent(); + + END_TEST; +} \ No newline at end of file diff --git a/automated-tests/src/dali-toolkit/utc-Dali-Image.cpp b/automated-tests/src/dali-toolkit/utc-Dali-Image.cpp index 4767977..e6451bc 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-Image.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-Image.cpp @@ -77,6 +77,23 @@ int UtcDaliImageConvertFrameBufferToUrl2(void) END_TEST; } +int UtcDaliImageConvertDepthTextureFrameBufferToUrl(void) +{ + ToolkitTestApplication application; + tet_infoline("UtcDaliImageConvertDepthTextureFrameBufferToUrl"); + + unsigned int width(64); + unsigned int height(64); + FrameBuffer frameBuffer = FrameBuffer::New(width, height, FrameBuffer::Attachment::NONE); + + Texture texture = Texture::New(TextureType::TEXTURE_2D, Pixel::DEPTH_UNSIGNED_INT, width, height); + DevelFrameBuffer::AttachDepthTexture(frameBuffer, texture); + + DALI_TEST_CHECK(Dali::Toolkit::Image::GenerateDepthUrl(frameBuffer).GetUrl().size() > 0u); + + END_TEST; +} + int UtcDaliImageConvertPixelDataToUrl01(void) { ToolkitTestApplication application; diff --git a/dali-scene3d/internal/algorithm/path-finder-djikstra.cpp b/dali-scene3d/internal/algorithm/path-finder-dijkstra.cpp similarity index 73% rename from dali-scene3d/internal/algorithm/path-finder-djikstra.cpp rename to dali-scene3d/internal/algorithm/path-finder-dijkstra.cpp index 726c1fb..ad64b96 100644 --- a/dali-scene3d/internal/algorithm/path-finder-djikstra.cpp +++ b/dali-scene3d/internal/algorithm/path-finder-dijkstra.cpp @@ -15,11 +15,13 @@ */ // CLASS HEADER -#include +#include // EXTERNAL INCLUDES #include #include +#include ///< for std::priority_queue +#include ///< for std::priority_queue // INTERNAL INCLUDES #include @@ -27,17 +29,38 @@ using WayPointList = Dali::Scene3D::Algorithm::WayPointList; +namespace +{ +struct DijkstraComparer +{ + float distance{-1.0f}; + Dali::Scene3D::Algorithm::FaceIndex index{Dali::Scene3D::Algorithm::NavigationMesh::NULL_FACE}; + + /** + * @brief Custom operator for Dijkstra comparer. + * + * @param[in] rhs Target to be compared. + * @return True if this has less priority than rhs. + */ + bool operator<(const DijkstraComparer& rhs) const + { + // Shorter distance have higher prioirty. + return distance > rhs.distance; + } +}; +} // namespace + namespace Dali::Scene3D::Internal::Algorithm { -PathFinderAlgorithmDjikstra::PathFinderAlgorithmDjikstra(Dali::Scene3D::Algorithm::NavigationMesh& navMesh) +PathFinderAlgorithmDijkstra::PathFinderAlgorithmDijkstra(Dali::Scene3D::Algorithm::NavigationMesh& navMesh) : mNavigationMesh(&GetImplementation(navMesh)) { PrepareData(); } -PathFinderAlgorithmDjikstra::~PathFinderAlgorithmDjikstra() = default; +PathFinderAlgorithmDijkstra::~PathFinderAlgorithmDijkstra() = default; -Scene3D::Algorithm::WayPointList PathFinderAlgorithmDjikstra::FindPath(const Dali::Vector3& positionFrom, const Dali::Vector3& positionTo) +Scene3D::Algorithm::WayPointList PathFinderAlgorithmDijkstra::FindPath(const Dali::Vector3& positionFrom, const Dali::Vector3& positionTo) { Dali::Vector3 outPosFrom; FaceIndex polyIndexFrom; @@ -56,18 +79,20 @@ Scene3D::Algorithm::WayPointList PathFinderAlgorithmDjikstra::FindPath(const Dal // Get waypoints waypoints = FindPath(polyIndexFrom, polyIndexTo); - // replace first and last waypoint - auto& wpFrom = static_cast(waypoints[0]); - auto& wpTo = static_cast(waypoints.back()); + if(!waypoints.empty()) + { + // replace first and last waypoint + auto& wpFrom = static_cast(waypoints[0]); + auto& wpTo = static_cast(waypoints.back()); - Vector2 fromCenter(wpFrom.point3d.x, wpFrom.point3d.y); - wpFrom.point3d = outPosFrom; - wpFrom.point2d = fromCenter - Vector2(outPosFrom.x, outPosFrom.y); + Vector2 fromCenter(wpFrom.point3d.x, wpFrom.point3d.y); + wpFrom.point3d = outPosFrom; + wpFrom.point2d = fromCenter - Vector2(outPosFrom.x, outPosFrom.y); - Vector2 toCenter(wpTo.point3d.x, wpTo.point3d.y); - wpTo.point3d = outPosTo; - wpTo.point2d = toCenter - Vector2(outPosTo.x, outPosTo.y); - wpTo.point3d = outPosTo; + Vector2 toCenter(wpTo.point3d.x, wpTo.point3d.y); + wpTo.point3d = outPosTo; + wpTo.point2d = toCenter - Vector2(outPosTo.x, outPosTo.y); + } } } @@ -75,85 +100,78 @@ Scene3D::Algorithm::WayPointList PathFinderAlgorithmDjikstra::FindPath(const Dal return waypoints; } -Scene3D::Algorithm::WayPointList PathFinderAlgorithmDjikstra::FindPath(FaceIndex sourcePolyIndex, FaceIndex targetPolyIndex) +Scene3D::Algorithm::WayPointList PathFinderAlgorithmDijkstra::FindPath(FaceIndex sourcePolyIndex, FaceIndex targetPolyIndex) { auto nodeCount = uint32_t(mNodes.size()); std::vector dist; std::vector prev; + std::vector faceVisited; + + std::priority_queue priorityDistanceHeap; dist.resize(mNodes.size()); prev.resize(mNodes.size()); - std::vector nodeQueue; - nodeQueue.reserve(nodeCount); - - [[maybe_unused]] auto sourcePos = Dali::Vector3(Face(sourcePolyIndex)->center); + faceVisited.resize(nodeCount); for(auto i = 0u; i < nodeCount; ++i) { dist[i] = std::numeric_limits::infinity(); prev[i] = Scene3D::Algorithm::NavigationMesh::NULL_FACE; // set prev to null polygon - nodeQueue.emplace_back(&mNodes[i]); + faceVisited[i] = false; } - auto removeCount = 0u; // Set distance of source dist[sourcePolyIndex] = 0.0f; - // TO OPTIMIZE WITH PRIORITY QUEUE - auto FindMinDistance = [&nodeQueue](decltype(dist)& dist) { - float w = std::numeric_limits::max(); - int index = -1; - for(auto i = 0u; i < dist.size(); ++i) - { - // skip infinity - if(nodeQueue[i] && dist[i] != std::numeric_limits::infinity() && dist[i] < w) - { - w = dist[i]; - index = int(i); - } - } - return index; - }; + priorityDistanceHeap.push({dist[sourcePolyIndex], sourcePolyIndex}); - do + while(!priorityDistanceHeap.empty()) { - // find minimum distance - auto minDistIndex = FindMinDistance(dist); + // find minimum distance index + auto comparer = priorityDistanceHeap.top(); + priorityDistanceHeap.pop(); - // Failed to find minimum distance - if(minDistIndex == -1) - { - // Return empty WayPointList - return {}; - } + auto minDistanceIndex = comparer.index; - // remove from queue by assigning infinity to distance - removeCount++; - if(removeCount == nodeCount) + // Old item. just ignore. + if(faceVisited[minDistanceIndex]) { continue; } - nodeQueue[minDistIndex] = nullptr; + faceVisited[minDistanceIndex] = true; - [[maybe_unused]] auto sizeTmp = nodeQueue.size() - removeCount; + // Fast break if we found solution. + if(minDistanceIndex == targetPolyIndex) + { + break; + } // check the neighbours for(auto i = 0u; i < 3; ++i) { - auto nIndex = mNodes[minDistIndex].faces[i]; - if(nIndex != Scene3D::Algorithm::NavigationMesh::NULL_FACE && nodeQueue[nIndex] != nullptr) + auto nIndex = mNodes[minDistanceIndex].faces[i]; + if(nIndex != Scene3D::Algorithm::NavigationMesh::NULL_FACE && !faceVisited[nIndex]) { - auto alt = dist[minDistIndex] + mNodes[minDistIndex].weight[i]; + auto alt = dist[minDistanceIndex] + mNodes[minDistanceIndex].weight[i]; if(alt < dist[nIndex]) { dist[nIndex] = alt; - prev[nIndex] = minDistIndex; + prev[nIndex] = minDistanceIndex; + + priorityDistanceHeap.push({dist[nIndex], nIndex}); } } } - } while(removeCount != nodeCount); + } + + // Failed to find minimum distance + if(!faceVisited[targetPolyIndex]) + { + // Return empty WayPointList + return {}; + } // Compute distances for each node back to the source auto u = targetPolyIndex; @@ -200,7 +218,7 @@ Scene3D::Algorithm::WayPointList PathFinderAlgorithmDjikstra::FindPath(FaceIndex return OptimizeWaypoints(waypoints); } -void PathFinderAlgorithmDjikstra::PrepareData() +void PathFinderAlgorithmDijkstra::PrepareData() { // Build the list structure connecting the nodes auto faceCount = mNavigationMesh->GetFaceCount(); @@ -245,7 +263,7 @@ void PathFinderAlgorithmDjikstra::PrepareData() return ccw(A, C, D) != ccw(B, C, D) && ccw(A, B, C) != ccw(A, B, D); } -Scene3D::Algorithm::WayPointList PathFinderAlgorithmDjikstra::OptimizeWaypoints(WayPointList& waypoints) const +Scene3D::Algorithm::WayPointList PathFinderAlgorithmDijkstra::OptimizeWaypoints(WayPointList& waypoints) const { WayPointList optimizedWaypoints; optimizedWaypoints.emplace_back(waypoints[0]); diff --git a/dali-scene3d/internal/algorithm/path-finder-djikstra.h b/dali-scene3d/internal/algorithm/path-finder-dijkstra.h similarity index 88% rename from dali-scene3d/internal/algorithm/path-finder-djikstra.h rename to dali-scene3d/internal/algorithm/path-finder-dijkstra.h index 08a6cee..237b1c9 100644 --- a/dali-scene3d/internal/algorithm/path-finder-djikstra.h +++ b/dali-scene3d/internal/algorithm/path-finder-dijkstra.h @@ -1,5 +1,5 @@ -#ifndef DALI_SCENE3D_INTERNAL_PATH_FINDER_DJIKSTRA_H -#define DALI_SCENE3D_INTERNAL_PATH_FINDER_DJIKSTRA_H +#ifndef DALI_SCENE3D_INTERNAL_PATH_FINDER_DIJKSTRA_H +#define DALI_SCENE3D_INTERNAL_PATH_FINDER_DIJKSTRA_H /* * Copyright (c) 2023 Samsung Electronics Co., Ltd. @@ -23,7 +23,7 @@ namespace Dali::Scene3D::Internal::Algorithm { -class PathFinderAlgorithmDjikstra : public Dali::Scene3D::Algorithm::PathFinderBase +class PathFinderAlgorithmDijkstra : public Dali::Scene3D::Algorithm::PathFinderBase { public: /** @@ -31,12 +31,12 @@ public: * * @param[in] navMesh Navigation mesh to associate with the algorithm */ - explicit PathFinderAlgorithmDjikstra(Dali::Scene3D::Algorithm::NavigationMesh& navMesh); + explicit PathFinderAlgorithmDijkstra(Dali::Scene3D::Algorithm::NavigationMesh& navMesh); /** * @brief Destructor */ - ~PathFinderAlgorithmDjikstra() override; + ~PathFinderAlgorithmDijkstra() override; /** * @brief Looks for a path from point A to point B. @@ -85,4 +85,4 @@ public: std::vector mNodes; ///< List of nodes }; } // namespace Dali::Scene3D::Internal::Algorithm -#endif // DALI_SCENE3D_INTERNAL_PATH_FINDER_DJIKSTRA_H +#endif // DALI_SCENE3D_INTERNAL_PATH_FINDER_DIJKSTRA_H diff --git a/dali-scene3d/internal/algorithm/path-finder-spfa-double-way.cpp b/dali-scene3d/internal/algorithm/path-finder-spfa-double-way.cpp index 0eb29a3..53ab038 100644 --- a/dali-scene3d/internal/algorithm/path-finder-spfa-double-way.cpp +++ b/dali-scene3d/internal/algorithm/path-finder-spfa-double-way.cpp @@ -118,18 +118,20 @@ Scene3D::Algorithm::WayPointList PathFinderAlgorithmSPFADoubleWay::FindPath(cons // Get waypoints waypoints = FindPath(polyIndexFrom, polyIndexTo); - // replace first and last waypoint - auto& wpFrom = static_cast(waypoints[0]); - auto& wpTo = static_cast(waypoints.back()); - - Vector2 fromCenter(wpFrom.point3d.x, wpFrom.point3d.y); - wpFrom.point3d = outPosFrom; - wpFrom.point2d = fromCenter - Vector2(outPosFrom.x, outPosFrom.y); - - Vector2 toCenter(wpTo.point3d.x, wpTo.point3d.y); - wpTo.point3d = outPosTo; - wpTo.point2d = toCenter - Vector2(outPosTo.x, outPosTo.y); - wpTo.point3d = outPosTo; + if(!waypoints.empty()) + { + // replace first and last waypoint + auto& wpFrom = static_cast(waypoints[0]); + auto& wpTo = static_cast(waypoints.back()); + + Vector2 fromCenter(wpFrom.point3d.x, wpFrom.point3d.y); + wpFrom.point3d = outPosFrom; + wpFrom.point2d = fromCenter - Vector2(outPosFrom.x, outPosFrom.y); + + Vector2 toCenter(wpTo.point3d.x, wpTo.point3d.y); + wpTo.point3d = outPosTo; + wpTo.point2d = toCenter - Vector2(outPosTo.x, outPosTo.y); + } } } diff --git a/dali-scene3d/internal/algorithm/path-finder-spfa.cpp b/dali-scene3d/internal/algorithm/path-finder-spfa.cpp index c6b1d48..02f308e 100644 --- a/dali-scene3d/internal/algorithm/path-finder-spfa.cpp +++ b/dali-scene3d/internal/algorithm/path-finder-spfa.cpp @@ -56,18 +56,20 @@ Scene3D::Algorithm::WayPointList PathFinderAlgorithmSPFA::FindPath(const Dali::V // Get waypoints waypoints = FindPath(polyIndexFrom, polyIndexTo); - // replace first and last waypoint - auto& wpFrom = static_cast(waypoints[0]); - auto& wpTo = static_cast(waypoints.back()); - - Vector2 fromCenter(wpFrom.point3d.x, wpFrom.point3d.y); - wpFrom.point3d = outPosFrom; - wpFrom.point2d = fromCenter - Vector2(outPosFrom.x, outPosFrom.y); - - Vector2 toCenter(wpTo.point3d.x, wpTo.point3d.y); - wpTo.point3d = outPosTo; - wpTo.point2d = toCenter - Vector2(outPosTo.x, outPosTo.y); - wpTo.point3d = outPosTo; + if(!waypoints.empty()) + { + // replace first and last waypoint + auto& wpFrom = static_cast(waypoints[0]); + auto& wpTo = static_cast(waypoints.back()); + + Vector2 fromCenter(wpFrom.point3d.x, wpFrom.point3d.y); + wpFrom.point3d = outPosFrom; + wpFrom.point2d = fromCenter - Vector2(outPosFrom.x, outPosFrom.y); + + Vector2 toCenter(wpTo.point3d.x, wpTo.point3d.y); + wpTo.point3d = outPosTo; + wpTo.point2d = toCenter - Vector2(outPosTo.x, outPosTo.y); + } } } diff --git a/dali-scene3d/internal/common/light-observer.h b/dali-scene3d/internal/common/light-observer.h index 608e100..eb98c90 100644 --- a/dali-scene3d/internal/common/light-observer.h +++ b/dali-scene3d/internal/common/light-observer.h @@ -60,6 +60,13 @@ public: * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. */ virtual void NotifyImageBasedLightScaleFactor(float scaleFactor) = 0; + + /** + * @brief Notifies Shadow Map texture is changed by parent SceneView. + * + * @param[in] shadowMapTexture Shadow Map texture that will be used to compute shadow. + */ + virtual void NotifyShadowMapTexture(Dali::Texture shadowMapTexture) = 0; }; } // namespace Internal diff --git a/dali-scene3d/internal/controls/model/model-impl.cpp b/dali-scene3d/internal/controls/model/model-impl.cpp index 1feb6b5..2763de6 100644 --- a/dali-scene3d/internal/controls/model/model-impl.cpp +++ b/dali-scene3d/internal/controls/model/model-impl.cpp @@ -213,6 +213,26 @@ void UpdateShaderRecursively(Scene3D::ModelNode node, Scene3D::Loader::ShaderMan } } +void UpdateShadowMapTextureRecursively(Scene3D::ModelNode node, Dali::Texture shadowMapTexture) +{ + if(!node) + { + return; + } + + GetImplementation(node).SetShadowMapTexture(shadowMapTexture); + + uint32_t childrenCount = node.GetChildCount(); + for(uint32_t i = 0; i < childrenCount; ++i) + { + Scene3D::ModelNode childNode = Scene3D::ModelNode::DownCast(node.GetChildAt(i)); + if(childNode) + { + UpdateShadowMapTextureRecursively(childNode, shadowMapTexture); + } + } +} + } // anonymous namespace Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUrl) @@ -280,6 +300,11 @@ void Model::AddModelNode(Scene3D::ModelNode modelNode) UpdateShaderRecursively(modelNode, mShaderManager); + if(mShadowMapTexture) + { + UpdateShadowMapTextureRecursively(modelNode, mShadowMapTexture); + } + if(mIblDiffuseResourceReady && mIblSpecularResourceReady) { UpdateImageBasedLightTexture(); @@ -1007,6 +1032,15 @@ void Model::ApplyCameraTransform(Dali::CameraActor camera) const camera.SetProperty(Actor::Property::SCALE, resultScale); } +void Model::NotifyShadowMapTexture(Dali::Texture shadowMapTexture) +{ + if(mShadowMapTexture != shadowMapTexture) + { + mShadowMapTexture = shadowMapTexture; + UpdateShadowMapTextureRecursively(mModelRoot, mShadowMapTexture); + } +} + void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels) { if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture) @@ -1062,6 +1096,10 @@ void Model::OnModelLoadComplete() mDefaultSpecularTexture = resources.mEnvironmentMaps.front().second.mSpecular; } + if(mShadowMapTexture) + { + UpdateShadowMapTextureRecursively(mModelRoot, mShadowMapTexture); + } UpdateImageBasedLightTexture(); UpdateImageBasedLightScaleFactor(); Self().SetProperty(Dali::Actor::Property::ANCHOR_POINT, Vector3(mModelPivot.x, 1.0f - mModelPivot.y, mModelPivot.z)); diff --git a/dali-scene3d/internal/controls/model/model-impl.h b/dali-scene3d/internal/controls/model/model-impl.h index 23337a4..b740da4 100644 --- a/dali-scene3d/internal/controls/model/model-impl.h +++ b/dali-scene3d/internal/controls/model/model-impl.h @@ -272,6 +272,11 @@ private: public: // Overrides LightObserver Methods. /** + * @copydoc Dali::Scene3D::Internal::LightObserver::NotifyShadowMapTexture() + */ + void NotifyShadowMapTexture(Dali::Texture shadowMapTexture) override; + + /** * @copydoc Dali::Scene3D::Internal::LightObserver::NotifyImageBasedLightTexture() */ void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels) override; @@ -361,6 +366,9 @@ private: EnvironmentMapLoadTaskPtr mIblDiffuseLoadTask; EnvironmentMapLoadTaskPtr mIblSpecularLoadTask; + // Shadow + Dali::Texture mShadowMapTexture; + std::string mDiffuseIblUrl; std::string mSpecularIblUrl; diff --git a/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp b/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp index b4bd19d..0c377cc 100644 --- a/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp +++ b/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp @@ -62,9 +62,10 @@ BaseHandle Create() DALI_TYPE_REGISTRATION_BEGIN(Scene3D::SceneView, Toolkit::Control, Create); DALI_TYPE_REGISTRATION_END() -Property::Index RENDERING_BUFFER = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1; -constexpr int32_t DEFAULT_ORIENTATION = 0; -constexpr int32_t INVALID_INDEX = -1; +Property::Index RENDERING_BUFFER = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1; +constexpr int32_t DEFAULT_ORIENTATION = 0; +constexpr int32_t INVALID_INDEX = -1; +constexpr uint32_t MAXIMUM_SIZE_SHADOW_MAP = 2048; static constexpr std::string_view SKYBOX_INTENSITY_STRING = "uIntensity"; @@ -148,6 +149,143 @@ Dali::Actor CreateSkybox() return skyboxActor; } +void SetShadowLightConstraint(Dali::CameraActor selectedCamera, Dali::CameraActor shadowLightCamera) +{ + shadowLightCamera.SetProperty(Dali::CameraActor::Property::ASPECT_RATIO, 1.0f); + + shadowLightCamera.SetProperty(Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE, 1.0f); + shadowLightCamera.SetProperty(Dali::CameraActor::Property::NEAR_PLANE_DISTANCE, 0.5f); + shadowLightCamera.SetProperty(Dali::CameraActor::Property::FAR_PLANE_DISTANCE, 3.5f); + + //< Make constraint for above properties. + shadowLightCamera.RemoveConstraints(); + + // Compute View Matrix of ShadowLightCamera + // Input : ShadowLightCamera's world position, world orientation + auto tempViewMatrixIndex = shadowLightCamera.RegisterProperty("tempViewMatrix", Matrix::IDENTITY); + Constraint viewMatrixConstraint = Constraint::New(shadowLightCamera, tempViewMatrixIndex, [](Matrix& output, const PropertyInputContainer& inputs) + { + output = inputs[0]->GetMatrix(); + output.Invert(); }); + viewMatrixConstraint.AddSource(Source{shadowLightCamera, Dali::Actor::Property::WORLD_MATRIX}); + viewMatrixConstraint.ApplyPost(); + + // Compute Orthographic Size / Near / Far and store it to "TempCameraProperty" property that is a Vector3 property + auto tempProjectionMatrixIndex = shadowLightCamera.RegisterProperty("tempProjectionMatrix", Matrix::IDENTITY); + Constraint projectionMatrixConstraint = Constraint::New(shadowLightCamera, tempProjectionMatrixIndex, [](Matrix& output, const PropertyInputContainer& inputs) + { + Matrix worldMatrix = inputs[0]->GetMatrix(); + float tangentFov_2 = tanf(inputs[4]->GetFloat()); + float nearDistance = inputs[5]->GetFloat(); + float farDistance = inputs[6]->GetFloat(); + float aspectRatio = inputs[7]->GetFloat(); + float nearY = 0.0f; + float nearX = 0.0f; + float farY = 0.0f; + float farX = 0.0f; + if(inputs[1]->GetInteger() == Dali::Camera::ProjectionMode::PERSPECTIVE_PROJECTION) + { + if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL) + { + nearY = tangentFov_2 * nearDistance; + nearX = nearY * aspectRatio; + farY = tangentFov_2 * farDistance; + farX = farY * aspectRatio; + } + else + { + nearX = tangentFov_2 * nearDistance; + nearY = nearX / aspectRatio; + farX = tangentFov_2 * farDistance; + farY = farX / aspectRatio; + } + } + else + { + if(inputs[2]->GetInteger() == Dali::DevelCameraActor::ProjectionDirection::VERTICAL) + { + nearY = inputs[3]->GetFloat(); + nearX = nearY * aspectRatio; + } + else + { + nearX = inputs[3]->GetFloat(); + nearY = nearX / aspectRatio; + } + farX = nearX; + farY = nearY; + } + + std::vector points; + points.push_back(Vector4(nearX, nearY, nearDistance, 1.0f)); + points.push_back(Vector4(-nearX, nearY, nearDistance, 1.0f)); + points.push_back(Vector4(-nearX, -nearY, nearDistance, 1.0f)); + points.push_back(Vector4(nearX, -nearY, nearDistance, 1.0f)); + points.push_back(Vector4(farX, farY, farDistance, 1.0f)); + points.push_back(Vector4(-farX, farY, farDistance, 1.0f)); + points.push_back(Vector4(-farX, -farY, farDistance, 1.0f)); + points.push_back(Vector4(farX, -farY, farDistance, 1.0f)); + + Vector3 areaMin = Vector3::ONE * MAXFLOAT, areaMax = Vector3::ONE * -MAXFLOAT; + for(auto&& point : points) + { + Vector4 pointW = worldMatrix * point; + Vector4 pointV = inputs[8]->GetMatrix() * pointW; + areaMin.x = std::min(areaMin.x, pointV.x); + areaMin.y = std::min(areaMin.y, pointV.y); + areaMin.z = std::min(areaMin.z, pointV.z); + areaMax.x = std::max(areaMax.x, pointV.x); + areaMax.y = std::max(areaMax.y, pointV.y); + areaMax.z = std::max(areaMax.z, pointV.z); + } + + Vector2 center = Vector2(areaMax + areaMin) / 2.0f; + float delta = std::max(std::abs(areaMax.x - areaMin.x), std::abs(areaMax.y - areaMin.y)); + float delta_2 = delta * 0.5f; + Vector2 squareAreaMin = center - Vector2::ONE * delta_2; + Vector2 squareAreaMax = center + Vector2::ONE * delta_2; + float deltaZ = areaMax.z - areaMin.z; + + float right = -squareAreaMin.x; + float left = -squareAreaMax.x; + float top = squareAreaMin.y; + float bottom = squareAreaMax.y; + float near = areaMin.z; + float far = areaMax.z; + + float* projMatrix = output.AsFloat(); + + projMatrix[0] = -2.0f / delta; + projMatrix[1] = 0.0f; + projMatrix[2] = 0.0f; + projMatrix[3] = 0.0f; + + projMatrix[4] = 0.0f; + projMatrix[5] = -2.0f / delta; + projMatrix[6] = 0.0f; + projMatrix[7] = 0.0f; + + projMatrix[8] = 0.0f; + projMatrix[9] = 0.0f; + projMatrix[10] = 2.0f / deltaZ; + projMatrix[11] = 0.0f; + + projMatrix[12] = -(right + left) / delta; + projMatrix[13] = -(top + bottom) / delta; + projMatrix[14] = -(near + far) / deltaZ; + projMatrix[15] = 1.0f; }); + projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::Actor::Property::WORLD_MATRIX}); + projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::PROJECTION_MODE}); + projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::DevelCameraActor::Property::PROJECTION_DIRECTION}); + projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE}); + projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::FIELD_OF_VIEW}); + projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::NEAR_PLANE_DISTANCE}); + projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::FAR_PLANE_DISTANCE}); + projectionMatrixConstraint.AddSource(Source{selectedCamera, Dali::CameraActor::Property::ASPECT_RATIO}); + projectionMatrixConstraint.AddSource(Source{shadowLightCamera, tempViewMatrixIndex}); + projectionMatrixConstraint.ApplyPost(); +} + } // anonymous namespace SceneView::SceneView() @@ -421,6 +559,11 @@ void SceneView::AddLight(Scene3D::Light light) { bool enabled = mShaderManager->AddLight(light); mLights.push_back(std::make_pair(light, enabled)); + + if(light.IsShadowEnabled()) + { + SetShadow(light); + } } void SceneView::RemoveLight(Scene3D::Light light) @@ -437,7 +580,7 @@ void SceneView::RemoveLight(Scene3D::Light light) if(mLights.size() > mShaderManager->GetLightCount()) { - for(auto && waitingLight : mLights) + for(auto&& waitingLight : mLights) { if(waitingLight.second) { @@ -448,6 +591,86 @@ void SceneView::RemoveLight(Scene3D::Light light) break; } } + + if(light == mShadowLight) + { + RemoveShadow(light); + } + + if(!mShadowLight) + { + for(auto&& lightEntity : mLights) + { + if(!lightEntity.second || !lightEntity.first.IsShadowEnabled()) + { + continue; + } + SetShadow(lightEntity.first); + break; + } + } +} + +void SceneView::SetShadow(Scene3D::Light light) +{ + if(!!mShadowLight) + { + return; + } + + auto foundLight = std::find_if(mLights.begin(), mLights.end(), [light](std::pair lightEntity) -> bool + { return (lightEntity.second && lightEntity.first == light); }); + + if(foundLight == mLights.end()) + { + return; + } + + mShadowLight = light; + + // Directional Light setting. + CameraActor lightCamera = GetImplementation(light).GetCamera(); + CameraActor selectedCamera = GetSelectedCamera(); + SetShadowLightConstraint(selectedCamera, lightCamera); + + // make framebuffer for depth map and set it to render task. + Vector3 size = Self().GetProperty(Dali::Actor::Property::SIZE); + uint32_t shadowMapBufferSize = std::min(static_cast(std::max(size.width, size.height)), MAXIMUM_SIZE_SHADOW_MAP); + UpdateShadowMapBuffer(shadowMapBufferSize); + + // use lightCamera as a camera of shadow render task. + mShadowMapRenderTask.SetCameraActor(lightCamera); + + mShaderManager->SetShadow(light); +} + +void SceneView::RemoveShadow(Scene3D::Light light) +{ + if(mShadowLight != light) + { + return; + } + + // remove all constraint from light camera + CameraActor lightCamera = GetImplementation(mShadowLight).GetCamera(); + lightCamera.RemoveConstraints(); + + // reset framebuffer and remove it from render task. + mShadowFrameBuffer.Reset(); + mShaderManager->RemoveShadow(); + mShadowMapRenderTask.SetCameraActor(CameraActor()); + + mShadowLight.Reset(); + + for(auto&& lightEntity : mLights) + { + if(!lightEntity.second || !lightEntity.first.IsShadowEnabled()) + { + continue; + } + SetShadow(lightEntity.first); + break; + } } uint32_t SceneView::GetActivatedLightCount() const @@ -550,6 +773,11 @@ Dali::Scene3D::Loader::ShaderManagerPtr SceneView::GetShaderManager() const return mShaderManager; } +void SceneView::UpdateShadowUniform(Scene3D::Light light) +{ + mShaderManager->UpdateShadowUniform(light); +} + /////////////////////////////////////////////////////////// // // Private methods @@ -583,7 +811,17 @@ void SceneView::OnSceneConnection(int depth) if(mSceneHolder) { RenderTaskList taskList = mSceneHolder.GetRenderTaskList(); - mRenderTask = taskList.CreateTask(); + 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.SetSourceActor(mRootLayer); mRenderTask.SetExclusive(true); mRenderTask.SetInputEnabled(true); @@ -615,9 +853,16 @@ void SceneView::OnSceneDisconnection() taskList.RemoveTask(mRenderTask); mRenderTask.Reset(); } + if(mShadowMapRenderTask) + { + RenderTaskList taskList = mSceneHolder.GetRenderTaskList(); + taskList.RemoveTask(mShadowMapRenderTask); + mShadowMapRenderTask.Reset(); + } mSceneHolder.Reset(); } mFrameBuffer.Reset(); + mShadowFrameBuffer.Reset(); Control::OnSceneDisconnection(); } @@ -694,6 +939,10 @@ void SceneView::UpdateCamera(CameraActor camera) } mSelectedCamera = camera; + if(mShadowLight) + { + SetShadowLightConstraint(mSelectedCamera, GetImplementation(mShadowLight).GetCamera()); + } UpdateRenderTask(); } @@ -710,6 +959,9 @@ void SceneView::UpdateRenderTask() const float aspectRatio = size.width / size.height; mSelectedCamera.SetAspectRatio(aspectRatio); + uint32_t shadowMapBufferSize = std::min(static_cast(std::max(size.width, size.height)), MAXIMUM_SIZE_SHADOW_MAP); + UpdateShadowMapBuffer(shadowMapBufferSize); + if(mUseFrameBuffer) { Dali::FrameBuffer currentFrameBuffer = mRenderTask.GetFrameBuffer(); @@ -918,6 +1170,29 @@ void SceneView::NotifyImageBasedLightTextureChange() } } +void SceneView::UpdateShadowMapBuffer(uint32_t shadowMapSize) +{ + Dali::FrameBuffer currentShadowFrameBuffer = mShadowMapRenderTask.GetFrameBuffer(); + if(mShadowLight && + (!currentShadowFrameBuffer || + !Dali::Equals(DevelFrameBuffer::GetDepthTexture(currentShadowFrameBuffer).GetWidth(), shadowMapSize))) + { + mShadowFrameBuffer.Reset(); + Dali::Texture shadowTexture = Dali::Texture::New(TextureType::TEXTURE_2D, Pixel::DEPTH_UNSIGNED_INT, shadowMapSize, shadowMapSize); + mShadowFrameBuffer = FrameBuffer::New(shadowMapSize, shadowMapSize, FrameBuffer::Attachment::NONE); + DevelFrameBuffer::AttachDepthTexture(mShadowFrameBuffer, shadowTexture); + mShadowMapRenderTask.SetFrameBuffer(mShadowFrameBuffer); + + for(auto&& item : mItems) + { + if(item) + { + item->NotifyShadowMapTexture(shadowTexture); + } + } + } +} + } // namespace Internal } // namespace Scene3D } // namespace Dali diff --git a/dali-scene3d/internal/controls/scene-view/scene-view-impl.h b/dali-scene3d/internal/controls/scene-view/scene-view-impl.h index 3f6eca7..647df5e 100644 --- a/dali-scene3d/internal/controls/scene-view/scene-view-impl.h +++ b/dali-scene3d/internal/controls/scene-view/scene-view-impl.h @@ -150,6 +150,22 @@ public: void RemoveLight(Scene3D::Light light); /** + * @brief Set a shadow to this scene by input light. + * Currently, SceneView supports only one shadow. + * + * @param[in] light Light object to make shadow. + * @note The shadow will be drawn if the input light is turn on in current scene. + */ + void SetShadow(Scene3D::Light light); + + /** + * @brief Removes Shadow from this SceneView. + * + * @param[in] light Light object to be removed. + */ + void RemoveShadow(Scene3D::Light light); + + /** * @copydoc SceneView::GetActivatedLightCount() */ uint32_t GetActivatedLightCount() const; @@ -210,6 +226,12 @@ public: */ Dali::Scene3D::Loader::ShaderManagerPtr GetShaderManager() const; + /** + * @brief Update shader uniforms about shadow. + * @param[in] light Light that makes shadow. + */ + void UpdateShadowUniform(Scene3D::Light light); + protected: /** * @brief Constructs a new SceneView. @@ -322,6 +344,12 @@ private: */ void NotifyImageBasedLightTextureChange(); + /** + * @brief Update shadowMap framebuffer when the size should be changed. + * @param[in] shadowMapSize The size of shadowMap texture. The texture's width and hight is equal. + */ + void UpdateShadowMapBuffer(uint32_t shadowMapSize); + private: Toolkit::Visual::Base mVisual; @@ -348,6 +376,9 @@ private: // Light std::vector> mLights; // Pair of Light object and flag that denotes the light is currently activated or not. + Dali::FrameBuffer mShadowFrameBuffer; + Dali::RenderTask mShadowMapRenderTask; + Scene3D::Light mShadowLight; // Asynchronous Loading. EnvironmentMapLoadTaskPtr mSkyboxLoadTask; diff --git a/dali-scene3d/internal/file.list b/dali-scene3d/internal/file.list index 9ea43a8..761ebb8 100644 --- a/dali-scene3d/internal/file.list +++ b/dali-scene3d/internal/file.list @@ -2,7 +2,7 @@ set(scene3d_internal_dir "${scene3d_dir}/internal") set(scene3d_src_files ${scene3d_src_files} ${scene3d_internal_dir}/algorithm/navigation-mesh-impl.cpp - ${scene3d_internal_dir}/algorithm/path-finder-djikstra.cpp + ${scene3d_internal_dir}/algorithm/path-finder-dijkstra.cpp ${scene3d_internal_dir}/algorithm/path-finder-spfa.cpp ${scene3d_internal_dir}/algorithm/path-finder-spfa-double-way.cpp ${scene3d_internal_dir}/common/environment-map-load-task.cpp diff --git a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag index de7b28d..db3c146 100644 --- a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag +++ b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag @@ -78,6 +78,11 @@ uniform mediump int uLightCount; uniform mediump vec3 uLightDirection[MAX_LIGHTS]; uniform mediump vec3 uLightColor[MAX_LIGHTS]; +// For Shadow Map +uniform lowp int uIsShadowEnabled; +uniform sampler2D sShadowMap; +in highp vec3 positionFromLightView; + //// For IBL uniform sampler2D sbrdfLUT; uniform samplerCube sDiffuseEnvSampler; @@ -102,6 +107,21 @@ out vec4 FragColor; const float c_MinRoughness = 0.04; const float M_PI = 3.141592653589793; +// These properties can be used for circular sampling for PCF + +// Percentage Closer Filtering to mitigate the banding artifacts. +const int kPcfSampleCount = 9; + +const float kPi = 3.141592653589f; +const float kInvSampleCount = 1.0 / float(kPcfSampleCount); +const float kPcfTheta = 2.f * kPi * kInvSampleCount; +const float kSinPcfTheta = sin(kPcfTheta); +const float kCosPcfTheta = cos(kPcfTheta); + +uniform lowp int uEnableShadowSoftFiltering; +uniform mediump float uShadowIntensity; +uniform mediump float uShadowBias; + vec3 linear(vec3 color) { return pow(color, vec3(2.2)); @@ -244,6 +264,31 @@ void main() } } + if(float(uIsShadowEnabled) * uShadowIntensity > 0.0) + { + mediump float exposureFactor = 0.0; + if(uEnableShadowSoftFiltering > 0) + { + ivec2 texSize = textureSize(sShadowMap, 0); + mediump vec2 texelSize = vec2(1.0) / vec2(texSize.x, texSize.y); + mediump vec2 pcfSample = vec2(1.f, 0.f); + for (int i = 0; i < kPcfSampleCount; ++i) + { + pcfSample = vec2(kCosPcfTheta * pcfSample.x - kSinPcfTheta * pcfSample.y, + kSinPcfTheta * pcfSample.x + kCosPcfTheta * pcfSample.y); + lowp float depthValue = texture(sShadowMap, positionFromLightView.xy + pcfSample * texelSize).r; + exposureFactor += (depthValue < positionFromLightView.z - uShadowBias) ? 0.0 : 1.0; + } + exposureFactor *= kInvSampleCount; + } + else + { + mediump float depthValue = texture(sShadowMap, positionFromLightView.xy).r; + exposureFactor = (depthValue < positionFromLightView.z - uShadowBias) ? 0.0 : 1.0; + } + color *= (1.0 - (1.0 - exposureFactor) * uShadowIntensity); + } + #ifdef OCCLUSION lowp float ao = texture(sOcclusion, vUV).r; color = mix(color, color * ao, uOcclusionStrength); diff --git a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert index 5b6140c..6f637ed 100644 --- a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert +++ b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.vert @@ -58,6 +58,11 @@ uniform highp float uBlendShapeUnnormalizeFactor[MAX_BLEND_SHAPE_NUMBER]; ///< F uniform highp int uBlendShapeComponentSize; ///< The size in the texture of either the vertices, normals or tangents. Used to calculate the offset to address them. #endif +// Shadow +uniform lowp int uIsShadowEnabled; +uniform highp mat4 uShadowLightViewProjectionMatrix; +out highp vec3 positionFromLightView; + void main() { highp vec4 position = vec4(aPosition, 1.0); @@ -169,5 +174,12 @@ void main() vColor = aVertexColor; + positionFromLightView = vec3(1.0); + if(uIsShadowEnabled > 0) + { + highp vec4 positionInLightView = uShadowLightViewProjectionMatrix * positionW; + positionFromLightView = ((positionInLightView.xyz / positionInLightView.w) * 0.5) + vec3(0.5); + } + gl_Position = uProjection * positionV; } diff --git a/dali-scene3d/internal/graphics/shaders/shadow-map-shader.frag b/dali-scene3d/internal/graphics/shaders/shadow-map-shader.frag new file mode 100644 index 0000000..91dace8 --- /dev/null +++ b/dali-scene3d/internal/graphics/shaders/shadow-map-shader.frag @@ -0,0 +1,50 @@ +#version 300 es + +uniform lowp vec4 uColorFactor; // Color from material +uniform lowp float uMask; +uniform lowp float uAlphaThreshold; + +in mediump vec2 vUV; +in lowp vec4 vColor; + +//in highp float depth; +//out highp vec4 FragColor; + +#ifdef THREE_TEX +#ifdef BASECOLOR_TEX +uniform sampler2D sAlbedoAlpha; +#endif // BASECOLOR_TEX +#else // THREE_TEX +uniform sampler2D sAlbedoMetal; +#endif + +lowp vec3 linear(lowp vec3 color) +{ + return pow(color, vec3(2.2)); +} + +void main() +{ +#ifdef THREE_TEX + // The albedo may be defined from a base texture or a flat color +#ifdef BASECOLOR_TEX + lowp vec4 baseColor = texture(sAlbedoAlpha, vUV); + baseColor = vColor * vec4(linear(baseColor.rgb), baseColor.w) * uColorFactor; +#else // BASECOLOR_TEX + lowp vec4 baseColor = vColor * uColorFactor; +#endif // BASECOLOR_TEX +#else // THREE_TEX + lowp vec4 albedoMetal = texture(sAlbedoMetal, vUV); + lowp vec4 baseColor = vec4(linear(albedoMetal.rgb), 1.0) * vColor * uColorFactor; +#endif // THREE_TEX + + // The value of uOpaque and uMask can be 0.0 or 1.0. + // If uMask is 1.0, a Pixel that has bigger alpha than uAlphaThreashold becomes fully opaque, + // and, a pixel that has smaller alpha than uAlphaThreashold becomes fully transparent. + // If uOpaque is 1.0, alpha value of final color is 1.0; + // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_material_alphamode + if(uMask > 0.5 && baseColor.a < uAlphaThreshold) + { + discard; + } +} \ No newline at end of file diff --git a/dali-scene3d/internal/graphics/shaders/shadow-map-shader.vert b/dali-scene3d/internal/graphics/shaders/shadow-map-shader.vert new file mode 100644 index 0000000..73bb37c --- /dev/null +++ b/dali-scene3d/internal/graphics/shaders/shadow-map-shader.vert @@ -0,0 +1,110 @@ +#version 300 es + +precision highp float; + +in vec3 aPosition; +in vec2 aTexCoord; +in vec4 aVertexColor; + +out mediump vec2 vUV; +out lowp vec4 vColor; + +uniform highp mat4 uViewMatrix; +uniform highp mat4 uModelMatrix; +uniform highp mat4 uProjection; + +#ifdef SKINNING + in vec4 aJoints; + in vec4 aWeights; + #define MAX_BONES 64 + uniform mat4 uBone[MAX_BONES]; + uniform mediump vec3 uYDirection; +#endif + +#ifdef MORPH +#define MAX_BLEND_SHAPE_NUMBER 128 +uniform int uNumberOfBlendShapes; ///< Total number of blend shapes loaded. +uniform highp float uBlendShapeWeight[MAX_BLEND_SHAPE_NUMBER]; ///< The weight of each blend shape. +#ifdef MORPH_VERSION_2_0 +uniform highp float uBlendShapeUnnormalizeFactor; ///< Factor used to unnormalize the geometry of the blend shape. +#else +uniform highp float uBlendShapeUnnormalizeFactor[MAX_BLEND_SHAPE_NUMBER]; ///< Factor used to unnormalize the geometry of the blend shape. +#endif +uniform highp int uBlendShapeComponentSize; ///< The size in the texture of either the vertices, normals or tangents. Used to calculate the offset to address them. +#endif + +uniform highp mat4 uShadowLightViewProjectionMatrix; + +void main() +{ + highp vec4 position = vec4(aPosition, 1.0); + +#ifdef MORPH + int width = textureSize( sBlendShapeGeometry, 0 ).x; + + highp int blendShapeBufferOffset = 0; + + for( int index = 0; index < uNumberOfBlendShapes; ++index ) + { + highp vec3 diff = vec3(0.0); + highp int vertexId = 0; + highp int x = 0; + highp int y = 0; + +#ifdef MORPH_POSITION + // Calculate the index to retrieve the geometry from the texture. + vertexId = gl_VertexID + blendShapeBufferOffset; + x = vertexId % width; + y = vertexId / width; + + // Retrieves the blend shape geometry from the texture, unnormalizes it and multiply by the weight. + if( 0.0 != uBlendShapeWeight[index] ) + { +#ifdef MORPH_VERSION_2_0 + highp float unnormalizeFactor = uBlendShapeUnnormalizeFactor; +#else + highp float unnormalizeFactor = uBlendShapeUnnormalizeFactor[index]; +#endif + + diff = uBlendShapeWeight[index] * unnormalizeFactor * ( texelFetch( sBlendShapeGeometry, ivec2(x, y), 0 ).xyz - 0.5 ); + } + + position.xyz += diff; + + blendShapeBufferOffset += uBlendShapeComponentSize; +#endif + +#ifdef MORPH_NORMAL + blendShapeBufferOffset += uBlendShapeComponentSize; +#endif + +#ifdef MORPH_TANGENT + blendShapeBufferOffset += uBlendShapeComponentSize; +#endif + } + +#endif + +#ifdef SKINNING + highp mat4 bone = uBone[int(aJoints.x)] * aWeights.x + + uBone[int(aJoints.y)] * aWeights.y + + uBone[int(aJoints.z)] * aWeights.z + + uBone[int(aJoints.w)] * aWeights.w; + position = bone * position; + + highp vec4 positionW = position; +#else + highp vec4 positionW = uModelMatrix * position; +#endif + + // To synchronize View-Projection matrix with pbr shader + gl_Position = uShadowLightViewProjectionMatrix * positionW; + +#ifdef FLIP_V + vUV = vec2(aTexCoord.x, 1.0 - aTexCoord.y); +#else + vUV = aTexCoord; +#endif + + vColor = aVertexColor; +} diff --git a/dali-scene3d/internal/light/light-impl.cpp b/dali-scene3d/internal/light/light-impl.cpp index 00eb0f4..0a0a453 100644 --- a/dali-scene3d/internal/light/light-impl.cpp +++ b/dali-scene3d/internal/light/light-impl.cpp @@ -38,6 +38,8 @@ static constexpr uint32_t MAX_NUMBER_OF_LIGHT = 5; static constexpr std::string_view LIGHT_COUNT_STRING("uLightCount"); static constexpr std::string_view LIGHT_DIRECTION_STRING("uLightDirection"); static constexpr std::string_view LIGHT_COLOR_STRING("uLightColor"); +static constexpr std::string_view SHADOW_ENABLED_STRING("uIsShadowEnabled"); +static constexpr std::string_view SHADOW_VIEW_PROJECTION_MATRIX_STRING("uShadowLightViewProjectionMatrix"); /** * Creates control through type registry @@ -79,6 +81,13 @@ Light::~Light() void Light::Initialize() { Self().SetProperty(Dali::Actor::Property::COLOR, Color::WHITE); + + // Directional Light setting + mLightSourceActor = Dali::CameraActor::New(); + mLightSourceActor.SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION); + mLightSourceActor.SetProperty(Dali::Actor::Property::POSITION, Vector3::ZERO); + mLightSourceActor.SetProperty(Dali::Actor::Property::ORIENTATION, Quaternion()); + Self().Add(mLightSourceActor); } void Light::Enable(bool enable) @@ -110,6 +119,73 @@ bool Light::IsEnabled() const return mIsEnabled; } +void Light::EnableShadow(bool enable) +{ + if(enable == mIsShadowEnabled) + { + return; + } + mIsShadowEnabled = enable; + + Scene3D::SceneView sceneView = mParentSceneView.GetHandle(); + if(!sceneView) + { + return; + } + + if(mIsShadowEnabled) + { + GetImpl(sceneView).SetShadow(Scene3D::Light::DownCast(Self())); + } + else + { + GetImpl(sceneView).RemoveShadow(Scene3D::Light::DownCast(Self())); + } +} + +bool Light::IsShadowEnabled() const +{ + return mIsShadowEnabled; +} + +CameraActor Light::GetCamera() const +{ + return mLightSourceActor; +} + +void Light::EnableShadowSoftFiltering(bool useSoftFiltering) +{ + mUseSoftFiltering = useSoftFiltering; + UpdateShadowUniforms(); +} + +bool Light::IsShadowSoftFilteringEnabled() const +{ + return mUseSoftFiltering; +} + +void Light::SetShadowIntensity(float shadowIntensity) +{ + mShadowIntensity = shadowIntensity; + UpdateShadowUniforms(); +} + +float Light::GetShadowIntensity() const +{ + return mShadowIntensity; +} + +void Light::SetShadowBias(float shadowBias) +{ + mShadowBias = shadowBias; + UpdateShadowUniforms(); +} + +float Light::GetShadowBias() const +{ + return mShadowBias; +} + void Light::OnSceneConnection(int depth) { Actor parent = Self().GetParent(); @@ -123,6 +199,10 @@ void Light::OnSceneConnection(int depth) { GetImpl(sceneView).AddLight(Scene3D::Light::DownCast(Self())); } + if(mIsShadowEnabled) + { + GetImpl(sceneView).SetShadow(Scene3D::Light::DownCast(Self())); + } break; } parent = parent.GetParent(); @@ -234,6 +314,30 @@ std::string_view Light::GetLightColorUniformName() return LIGHT_COLOR_STRING; } +std::string_view Light::GetShadowEnabledUniformName() +{ + return SHADOW_ENABLED_STRING; +} + +std::string_view Light::GetShadowViewProjectionMatrixUniformName() +{ + return SHADOW_VIEW_PROJECTION_MATRIX_STRING; +} + +void Light::UpdateShadowUniforms() +{ + Scene3D::SceneView sceneView = mParentSceneView.GetHandle(); + if(!sceneView) + { + return; + } + + if(mIsShadowEnabled) + { + GetImpl(sceneView).UpdateShadowUniform(Scene3D::Light::DownCast(Self())); + } +} + } // namespace Internal } // namespace Scene3D diff --git a/dali-scene3d/internal/light/light-impl.h b/dali-scene3d/internal/light/light-impl.h index 70b51f5..c691423 100644 --- a/dali-scene3d/internal/light/light-impl.h +++ b/dali-scene3d/internal/light/light-impl.h @@ -67,6 +67,51 @@ public: */ bool IsEnabled() const; + /** + * @copydoc Scene3D::Light::EnableShadow() + */ + void EnableShadow(bool enable); + + /** + * @copydoc Scene3D::Light::IsShadowEnabled() + */ + bool IsShadowEnabled() const; + + /** + * @copydoc Scene3D::Light::GetCamera() + */ + CameraActor GetCamera() const; + + /** + * @copydoc Scene3D::Light::EnableShadowSoftFiltering() + */ + void EnableShadowSoftFiltering(bool useSoftFiltering); + + /** + * @copydoc Scene3D::Light::IsShadowSoftFilteringEnabled() + */ + bool IsShadowSoftFilteringEnabled() const; + + /** + * @copydoc Scene3D::Light::SetShadowIntensity() + */ + void SetShadowIntensity(float shadowIntensity); + + /** + * @copydoc Scene3D::Light::GetShadowIntensity() + */ + float GetShadowIntensity() const; + + /** + * @copydoc Scene3D::Light::SetShadowBias() + */ + void SetShadowBias(float shadowBias); + + /** + * @copydoc Scene3D::Light::GetShadowBias() + */ + float GetShadowBias() const; + protected: /** * @brief Virtual destructor. @@ -194,6 +239,21 @@ public: // Public Method */ static std::string_view GetLightColorUniformName(); + /** + * @brief Retrieves Uniform Name to define shadow is enabled or not. + * @return string_view for ShadowEnabledUniformName + */ + static std::string_view GetShadowEnabledUniformName(); + + /** + * @brief Retrieves Uniform Name for View/Projection matrix of the Shadow. + * @return string_view for ShadowViewProjectionMatrixUniformName + */ + static std::string_view GetShadowViewProjectionMatrixUniformName(); + +private: + void UpdateShadowUniforms(); + private: /// @cond internal @@ -204,8 +264,13 @@ private: DALI_INTERNAL Light& operator=(Light&&) = delete; ///< Deleted move assignment operator. private: + Dali::CameraActor mLightSourceActor; WeakHandle mParentSceneView; - bool mIsEnabled{true}; + bool mIsEnabled{true}; + bool mIsShadowEnabled{false}; + bool mUseSoftFiltering{false}; + float mShadowIntensity{0.5f}; + float mShadowBias{0.001f}; /// @endcond }; diff --git a/dali-scene3d/internal/loader/dli-loader-impl.cpp b/dali-scene3d/internal/loader/dli-loader-impl.cpp index a4dbeda..668a10c 100644 --- a/dali-scene3d/internal/loader/dli-loader-impl.cpp +++ b/dali-scene3d/internal/loader/dli-loader-impl.cpp @@ -667,6 +667,12 @@ void DliLoaderImpl::Impl::ParseShaders(const TreeNode* shaders, Dali::Scene3D::L auto& node = (*i0).second; ShaderDefinition shaderDef; ReadStringVector(node.GetChild("defines"), shaderDef.mDefines); + auto sssIter = std::find_if(shaderDef.mDefines.begin(), shaderDef.mDefines.end(), [](std::string& item) + { return (item == "SSS"); }); + if(sssIter != shaderDef.mDefines.end()) + { + shaderDef.mDefines.erase(sssIter); + } // Read shader hints. Possible values are: // Don't define for No hints. @@ -1027,14 +1033,17 @@ void DliLoaderImpl::Impl::ParseMaterials(const TreeNode* materials, DliInputPara materialDef.mFlags |= semantic; } - if(ReadString(node.GetChild("subsurfaceMap"), texturePath)) - { - ToUnixFileSeparators(texturePath); - - const auto semantic = MaterialDefinition::SUBSURFACE; - materialDef.mTextureStages.push_back({semantic, TextureDefinition{std::move(texturePath)}}); - materialDef.mFlags |= semantic; - } +/// @TODO : Some dli shader don't implement this subsurfaceMp usage. +/// To make visual test pass, Skip subsurfaceMap texture using +/// until dli shaders are support it. +// if(ReadString(node.GetChild("subsurfaceMap"), texturePath)) +// { +// ToUnixFileSeparators(texturePath); +// +// const auto semantic = MaterialDefinition::SUBSURFACE; +// materialDef.mTextureStages.push_back({semantic, TextureDefinition{std::move(texturePath)}}); +// materialDef.mFlags |= semantic; +// } if(ReadString(node.GetChild("occlusionMap"), texturePath)) { diff --git a/dali-scene3d/internal/loader/gltf2-util.cpp b/dali-scene3d/internal/loader/gltf2-util.cpp index 8cdbecf..1bda11a 100644 --- a/dali-scene3d/internal/loader/gltf2-util.cpp +++ b/dali-scene3d/internal/loader/gltf2-util.cpp @@ -597,6 +597,7 @@ void ConvertMaterial(const gltf2::Material& material, const std::unordered_map= GetImplementation(mMaterial).GetShadowMapTextureOffset() && + textures.GetTexture(textureCount - GetImplementation(mMaterial).GetShadowMapTextureOffset()) != mShadowMapTexture) + { + Dali::TextureSet newTextures = Dali::TextureSet::New(); + + for(uint32_t index = 0u; index < textureCount; ++index) + { + Dali::Texture texture = textures.GetTexture(index); + if(index == textureCount - GetImplementation(mMaterial).GetShadowMapTextureOffset()) + { + texture = (!!mShadowMapTexture) ? mShadowMapTexture : MakeEmptyTexture(); + } + + newTextures.SetTexture(index, texture); + newTextures.SetSampler(index, textures.GetSampler(index)); + } + + mRenderer.SetTextures(newTextures); + } + } +} + void ModelPrimitive::UpdateImageBasedLightTexture() { if(mRenderer && mMaterial) diff --git a/dali-scene3d/internal/model-components/model-primitive-impl.h b/dali-scene3d/internal/model-components/model-primitive-impl.h index 7334699..c6dbf37 100644 --- a/dali-scene3d/internal/model-components/model-primitive-impl.h +++ b/dali-scene3d/internal/model-components/model-primitive-impl.h @@ -124,6 +124,13 @@ public: void RemovePrimitiveObserver(ModelPrimitiveModifyObserver* observer); /** + * @brief Sets shadow map texture for this model primitive. + * + * @param[in] shadowMapTexture The shadow map texture. + */ + void SetShadowMapTexture(Dali::Texture shadowMapTexture); + + /** * @brief Sets the image-based lighting texture for this model primitive. * * @param[in] diffuseTexture The diffuse texture. @@ -200,6 +207,8 @@ private: */ void CreateRenderer(); + void UpdateShadowMapTexture(); + /** * @brief Updates the image-based lighting texture. */ @@ -224,6 +233,9 @@ private: Scene3D::Loader::ShaderManagerPtr mShaderManager; + // For Shadow + Dali::Texture mShadowMapTexture; + // For IBL Dali::Texture mSpecularTexture; Dali::Texture mDiffuseTexture; diff --git a/dali-scene3d/public-api/algorithm/path-finder.cpp b/dali-scene3d/public-api/algorithm/path-finder.cpp index 621fc82..2f89e5d 100644 --- a/dali-scene3d/public-api/algorithm/path-finder.cpp +++ b/dali-scene3d/public-api/algorithm/path-finder.cpp @@ -19,7 +19,7 @@ // INTERNAL INCLUDES // default algorithm -#include +#include #include #include @@ -31,9 +31,9 @@ std::unique_ptr PathFinder::New(NavigationMesh& navigationMesh, Path switch(algorithm) { - case PathFinderAlgorithm::DJIKSTRA_SHORTEST_PATH: + case PathFinderAlgorithm::DIJKSTRA_SHORTEST_PATH: { - impl = new Dali::Scene3D::Internal::Algorithm::PathFinderAlgorithmDjikstra(navigationMesh); + impl = new Dali::Scene3D::Internal::Algorithm::PathFinderAlgorithmDijkstra(navigationMesh); break; } case PathFinderAlgorithm::SPFA: diff --git a/dali-scene3d/public-api/algorithm/path-finder.h b/dali-scene3d/public-api/algorithm/path-finder.h index 5d2a6f1..8b5e15c 100644 --- a/dali-scene3d/public-api/algorithm/path-finder.h +++ b/dali-scene3d/public-api/algorithm/path-finder.h @@ -32,11 +32,11 @@ using WayPointList = std::vector; */ enum class PathFinderAlgorithm { - DJIKSTRA_SHORTEST_PATH, ///< Using A* variant (Djikstra) finding a shortest path + DIJKSTRA_SHORTEST_PATH, ///< Using A* variant (Dijkstra) finding a shortest path SPFA, ///< Using SPFA-SLF (Shortest Path Fast Algorithm with Short Label First) finding a shortest path. SPFA_DOUBLE_WAY, ///< Using SPFA-SLF double way. It might not find shortest, but will use less memory. - DEFAULT = DJIKSTRA_SHORTEST_PATH, ///< Default algorithm to use + DEFAULT = DIJKSTRA_SHORTEST_PATH, ///< Default algorithm to use }; /** diff --git a/dali-scene3d/public-api/light/light.cpp b/dali-scene3d/public-api/light/light.cpp index 0b7f493..095e053 100644 --- a/dali-scene3d/public-api/light/light.cpp +++ b/dali-scene3d/public-api/light/light.cpp @@ -81,6 +81,46 @@ uint32_t Light::GetMaximumEnabledLightCount() return Internal::Light::GetMaximumEnabledLightCount(); } +void Light::EnableShadow(bool enable) +{ + Internal::GetImplementation(*this).EnableShadow(enable); +} + +bool Light::IsShadowEnabled() const +{ + return Internal::GetImplementation(*this).IsShadowEnabled(); +} + +void Light::EnableShadowSoftFiltering(bool useSoftFiltering) +{ + Internal::GetImplementation(*this).EnableShadowSoftFiltering(useSoftFiltering); +} + +bool Light::IsShadowSoftFilteringEnabled() const +{ + return Internal::GetImplementation(*this).IsShadowSoftFilteringEnabled(); +} + +void Light::SetShadowIntensity(float shadowIntensity) +{ + Internal::GetImplementation(*this).SetShadowIntensity(shadowIntensity); +} + +float Light::GetShadowIntensity() const +{ + return Internal::GetImplementation(*this).GetShadowIntensity(); +} + +void Light::SetShadowBias(float shadowBias) +{ + Internal::GetImplementation(*this).SetShadowBias(shadowBias); +} + +float Light::GetShadowBias() const +{ + return Internal::GetImplementation(*this).GetShadowBias(); +} + Light::Light(Internal::Light& implementation) : CustomActor(implementation) { diff --git a/dali-scene3d/public-api/light/light.h b/dali-scene3d/public-api/light/light.h index eabb278..ef4892a 100644 --- a/dali-scene3d/public-api/light/light.h +++ b/dali-scene3d/public-api/light/light.h @@ -159,6 +159,79 @@ public: */ static uint32_t GetMaximumEnabledLightCount(); + /** + * @brief Enables shadow for this light. + * Dali::Scene3D generates shadow by using shadow map. + * For the Directional Light, the shadow map is created to cover view frustum of current selected camera. + * This means that if the distance between the near and far planes is too large, + * the shadow map has to cover an unnecessarily large area. This results in lower shadow quality. + * @SINCE_2_2.43 + * @note This light should be already turned on in the SceneView. + * @note (When enable is true) If there is previous light already enabled shadow in the SceneView, this function call is ignored. + * @note (When enable is false, and this light is currently used for shader) + * If there are other lights those are turned on and shadow enabled, one of the light will be used for shadow automatically. + * @param[in] enable True to make this Light's shadow enable. + */ + void EnableShadow(bool enable); + + /** + * @brief Checks whether the shadow of this light is enabled or not. + * @SINCE_2_2.43 + * @return True if the shadow of this light is enabled. + */ + bool IsShadowEnabled() const; + + /** + * @brief Enables filtering to soften the edge of shadow. + * Basically the shadow is hard shadow that has sharp edge. + * This method enables soft filtering to make the sharp edge to smoothing. + * @SINCE_2_2.43 + * @note This soft filtering requires expensive computation power. + * @param[in] useSoftFiltering True to soften the shadow edge. + */ + void EnableShadowSoftFiltering(bool useSoftFiltering); + + /** + * @brief Checks whether the shadow uses soft filtering. + * @SINCE_2_2.43 + * @return True if the shadow edge is soften. + */ + bool IsShadowSoftFilteringEnabled() const; + + /** + * @brief Sets shadow intensity. + * If the intensity is larger, the shadow area will be darker. + * The intensity value is between [0, 1]. + * Default value is 0.5 + * @SINCE_2_2.43 + * @param[in] shadowIntensity Shadow intensity value + */ + void SetShadowIntensity(float shadowIntensity); + + /** + * @brief Retrieve shadow intensity. + * @SINCE_2_2.43 + * @return Current shadow intensity value. + */ + float GetShadowIntensity() const; + + /** + * @brief Sets shadow bias. + * Shadow bias is an offset value to remove shadow acne that is a visual artifact can be shown on the Shadow + * Default value is 0.001 + * @SINCE_2_2.43 + * @param[in] shadowBias bias value to remove shadow acne. + * @note If the shadow bias is too large, the object will appear detached from the shadow. + */ + void SetShadowBias(float shadowBias); + + /** + * @brief Retrieves shadow bias value. + * @SINCE_2_2.43 + * @return Shadow bias value. + */ + float GetShadowBias() const; + public: // Not intended for application developers /// @cond internal /** diff --git a/dali-scene3d/public-api/loader/material-definition.cpp b/dali-scene3d/public-api/loader/material-definition.cpp index eb87ae1..4fc6ac3 100644 --- a/dali-scene3d/public-api/loader/material-definition.cpp +++ b/dali-scene3d/public-api/loader/material-definition.cpp @@ -345,6 +345,14 @@ TextureSet MaterialDefinition::Load(const EnvironmentDefinition::Vector& environ ++n; } + if(mShadowAvailable) + { + PixelData shadowMapPixelData = PixelData::New(new uint8_t[3]{0xff, 0xff, 0xff}, 3, 1, 1, Pixel::RGB888, PixelData::DELETE_ARRAY); + Texture shadowMapTexture = Texture::New(TextureType::TEXTURE_2D, shadowMapPixelData.GetPixelFormat(), shadowMapPixelData.GetWidth(), shadowMapPixelData.GetHeight()); + shadowMapTexture.Upload(shadowMapPixelData, 0, 0, 0, 0, shadowMapPixelData.GetWidth(), shadowMapPixelData.GetHeight()); + textureSet.SetTexture(n++, shadowMapTexture); + } + // Assign textures to slots -- starting with 2D ones, then cubemaps, if any. if(mEnvironmentIdx < static_cast(environments.size())) { diff --git a/dali-scene3d/public-api/loader/material-definition.h b/dali-scene3d/public-api/loader/material-definition.h index b8da495..43dabc1 100644 --- a/dali-scene3d/public-api/loader/material-definition.h +++ b/dali-scene3d/public-api/loader/material-definition.h @@ -251,6 +251,8 @@ public: // DATA bool mIsOpaque = true; bool mIsMask = false; + bool mShadowAvailable = false; + std::vector mTextureStages; Material mMaterial; }; diff --git a/dali-scene3d/public-api/loader/shader-definition.cpp b/dali-scene3d/public-api/loader/shader-definition.cpp index 2796340..49ff885 100644 --- a/dali-scene3d/public-api/loader/shader-definition.cpp +++ b/dali-scene3d/public-api/loader/shader-definition.cpp @@ -18,6 +18,9 @@ // CLASS HEADER #include +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include @@ -100,8 +103,10 @@ ShaderDefinition::LoadRaw(const std::string& shadersPath) const } else { - raw.mVertexShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_VERT.data(); - raw.mFragmentShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data(); + raw.mVertexShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_VERT.data(); + raw.mFragmentShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data(); + raw.mShadowVertexShaderSource = SHADER_SHADOW_MAP_SHADER_VERT.data(); + raw.mShadowFragmentShaderSource = SHADER_SHADOW_MAP_SHADER_FRAG.data(); } if(!fail) @@ -110,6 +115,7 @@ ShaderDefinition::LoadRaw(const std::string& shadersPath) const { ApplyDefine(raw.mVertexShaderSource, definevar); ApplyDefine(raw.mFragmentShaderSource, definevar); + ApplyDefine(raw.mShadowVertexShaderSource, definevar); } } @@ -131,7 +137,21 @@ Shader ShaderDefinition::Load(RawData&& raw) const } } - Shader shader = Shader::New(raw.mVertexShaderSource, raw.mFragmentShaderSource, static_cast(hints)); + Property::Map map[2]; + map[0]["vertex"] = raw.mVertexShaderSource; + map[0]["fragment"] = raw.mFragmentShaderSource; + map[0]["renderPassTag"] = 0; + map[0]["hints"] = static_cast(hints); + + map[1]["vertex"] = raw.mShadowVertexShaderSource; + map[1]["fragment"] = raw.mShadowFragmentShaderSource; + map[1]["renderPassTag"] = 10; + + Property::Array array; + array.PushBack(map[0]); + array.PushBack(map[1]); + + Shader shader = Shader::New(array); for(Property::Map::SizeType i0 = 0, i1 = mUniforms.Count(); i0 != i1; ++i0) { auto pair = mUniforms.GetKeyValue(i0); diff --git a/dali-scene3d/public-api/loader/shader-definition.h b/dali-scene3d/public-api/loader/shader-definition.h index 61f4a7c..0fe83d3 100644 --- a/dali-scene3d/public-api/loader/shader-definition.h +++ b/dali-scene3d/public-api/loader/shader-definition.h @@ -40,6 +40,8 @@ struct DALI_SCENE3D_API ShaderDefinition { std::string mVertexShaderSource; std::string mFragmentShaderSource; + std::string mShadowVertexShaderSource; + std::string mShadowFragmentShaderSource; }; /* diff --git a/dali-scene3d/public-api/loader/shader-manager.cpp b/dali-scene3d/public-api/loader/shader-manager.cpp index df8e16a..f4f6f34 100644 --- a/dali-scene3d/public-api/loader/shader-manager.cpp +++ b/dali-scene3d/public-api/loader/shader-manager.cpp @@ -29,11 +29,14 @@ #include #include +#include + namespace Dali::Scene3D::Loader { namespace { -static constexpr uint32_t INDEX_FOR_LIGHT_CONSTRAINT_TAG = 10; +static constexpr uint32_t INDEX_FOR_LIGHT_CONSTRAINT_TAG = 10; +static constexpr uint32_t INDEX_FOR_SHADOW_CONSTRAINT_TAG = 100; ShaderOption MakeOption(const MaterialDefinition& materialDef, const MeshDefinition& meshDef) { @@ -162,6 +165,8 @@ struct ShaderManager::Impl std::map mShaderMap; std::vector mShaders; std::vector mLights; + + Scene3D::Light mShadowLight; }; ShaderManager::ShaderManager() @@ -209,6 +214,13 @@ Dali::Shader ShaderManager::ProduceShader(const ShaderOption& shaderOption) { SetLightConstraintToShader(index, result); } + + result.RegisterProperty("uIsShadowEnabled", static_cast(!!mImpl->mShadowLight)); + if(!!mImpl->mShadowLight) + { + SetShadowConstraintToShader(result); + SetShadowUniformToShader(result); + } } return result; @@ -288,6 +300,42 @@ uint32_t ShaderManager::GetLightCount() const return mImpl->mLights.size(); } +void ShaderManager::SetShadow(Scene3D::Light light) +{ + mImpl->mShadowLight = light; + for(auto&& shader : mImpl->mShaders) + { + std::string shadowEnabledPropertyName(Scene3D::Internal::Light::GetShadowEnabledUniformName()); + shader.RegisterProperty(shadowEnabledPropertyName, static_cast(true)); + } + + SetShadowProperty(); +} + +void ShaderManager::RemoveShadow() +{ + for(auto&& shader : mImpl->mShaders) + { + std::string shadowEnabledPropertyName(Scene3D::Internal::Light::GetShadowEnabledUniformName()); + shader.RegisterProperty(shadowEnabledPropertyName, static_cast(false)); + shader.RemoveConstraints(INDEX_FOR_SHADOW_CONSTRAINT_TAG); + } + mImpl->mShadowLight.Reset(); +} + +void ShaderManager::UpdateShadowUniform(Scene3D::Light light) +{ + if(light != mImpl->mShadowLight) + { + return; + } + + for(auto&& shader : mImpl->mShaders) + { + SetShadowUniformToShader(shader); + } +} + void ShaderManager::SetLightConstraint(uint32_t lightIndex) { for(auto&& shader : mImpl->mShaders) @@ -323,4 +371,49 @@ void ShaderManager::RemoveLightConstraint(uint32_t lightIndex) } } +void ShaderManager::SetShadowUniformToShader(Dali::Shader shader) +{ + shader.RegisterProperty("uShadowIntensity", mImpl->mShadowLight.GetShadowIntensity()); + shader.RegisterProperty("uShadowBias", mImpl->mShadowLight.GetShadowBias()); + shader.RegisterProperty("uEnableShadowSoftFiltering", static_cast(mImpl->mShadowLight.IsShadowSoftFilteringEnabled())); +} + +void ShaderManager::SetShadowProperty() +{ + for(auto&& shader : mImpl->mShaders) + { + SetShadowUniformToShader(shader); + SetShadowConstraintToShader(shader); + } +} + +void ShaderManager::SetShadowConstraintToShader(Dali::Shader shader) +{ + // Constraint is applied before View/Projection Matrix is computed in update thread. + // So, it could show not plausible result if camera properties are changed discontinuesly. + // If we want to make it be synchronized, View/Projection matrix are needed to be conputed in below constraint. + + std::string shadowViewProjectionPropertyName(Scene3D::Internal::Light::GetShadowViewProjectionMatrixUniformName()); + auto shadowViewProjectionPropertyIndex = shader.RegisterProperty(shadowViewProjectionPropertyName, Matrix::IDENTITY); + Dali::CameraActor shadowLightCamera = Dali::Scene3D::Internal::GetImplementation(mImpl->mShadowLight).GetCamera(); + auto tempViewMatrixIndex = shadowLightCamera.GetPropertyIndex("tempViewMatrix"); + if(tempViewMatrixIndex != Dali::Property::INVALID_INDEX) + { + tempViewMatrixIndex = shadowLightCamera.RegisterProperty("tempViewMatrix", Matrix::IDENTITY); + } + auto tempProjectionMatrixIndex = shadowLightCamera.GetPropertyIndex("tempProjectionMatrix"); + if(tempProjectionMatrixIndex != Dali::Property::INVALID_INDEX) + { + tempProjectionMatrixIndex = shadowLightCamera.RegisterProperty("tempProjectionMatrix", Matrix::IDENTITY); + } + Dali::Constraint shadowViewProjectionConstraint = Dali::Constraint::New(shader, shadowViewProjectionPropertyIndex, [](Matrix& output, const PropertyInputContainer& inputs) + { + output = inputs[1]->GetMatrix() * inputs[0]->GetMatrix(); }); + + shadowViewProjectionConstraint.AddSource(Source{shadowLightCamera, tempViewMatrixIndex}); + shadowViewProjectionConstraint.AddSource(Source{shadowLightCamera, tempProjectionMatrixIndex}); + shadowViewProjectionConstraint.ApplyPost(); + shadowViewProjectionConstraint.SetTag(INDEX_FOR_SHADOW_CONSTRAINT_TAG); +} + } // namespace Dali::Scene3D::Loader diff --git a/dali-scene3d/public-api/loader/shader-manager.h b/dali-scene3d/public-api/loader/shader-manager.h index 56adf38..4ca1384 100644 --- a/dali-scene3d/public-api/loader/shader-manager.h +++ b/dali-scene3d/public-api/loader/shader-manager.h @@ -93,6 +93,24 @@ public: */ uint32_t GetLightCount() const; + /** + * @brief Set a shadow to this scene by input light. + * + * @param[in] light Light object to make shadow. + */ + void SetShadow(Scene3D::Light light); + + /** + * @brief Removes Shadow from this SceneView. + */ + void RemoveShadow(); + + /** + * @brief Update uniform properties of shadow for the input light. + * @param[in] light Light object to update shadow uniform. + */ + void UpdateShadowUniform(Scene3D::Light light); + private: /** * @brief Sets constraint to the shaders with light of light index. @@ -112,6 +130,23 @@ private: * @param[in] lightIndex index of light that will be disconnected with shaders. */ DALI_INTERNAL void RemoveLightConstraint(uint32_t lightIndex); + + /** + * @brief Sets uniform about the shadow. + * @param[in] shader Shader that the constraint will be applied. + */ + DALI_INTERNAL void SetShadowUniformToShader(Dali::Shader shader); + + /** + * @brief Sets properties and constraint to the shaders. + */ + DALI_INTERNAL void SetShadowProperty(); + + /** + * @brief Sets constraint to a shader about shadow + * @param[in] shader Shader that the constraint will be applied. + */ + DALI_INTERNAL void SetShadowConstraintToShader(Dali::Shader shader); private: struct Impl; const std::unique_ptr mImpl; diff --git a/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h b/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h index a175eb3..b17e79d 100644 --- a/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h +++ b/dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h @@ -20,8 +20,8 @@ // EXTERNAL INCLUDES #include -#include #include +#include #include #include @@ -48,7 +48,9 @@ enum Type JUMP_TO = DevelAnimatedImageVisual::Action::JUMP_TO, ///< Jump to the specified frame. Property::INTEGER value should be passed. // AnimatedVectorImageVisual only actions - SET_DYNAMIC_PROPERTY = DevelAnimatedImageVisual::Action::ANIMATED_IMAGE_VISUAL_ACTION_END_INDEX ///< Set the dynamic property. + SET_DYNAMIC_PROPERTY = DevelAnimatedImageVisual::Action::ANIMATED_IMAGE_VISUAL_ACTION_END_INDEX, ///< Set the dynamic property. + + FLUSH, ///< Flush animation data. It will make ensure that changeness of animated vector image properties flushed. }; } // namespace Action diff --git a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp index e713486..aef9910 100644 --- a/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp +++ b/dali-toolkit/internal/controls/text-controls/text-label-impl.cpp @@ -1100,10 +1100,16 @@ void TextLabel::OnRelayout(const Vector2& size, RelayoutContainer& container) layoutSize.width = maxTextureSize; } + // This affects font rendering quality. + // It need to be integerized. + Vector2 visualTransformOffset; + visualTransformOffset.x = roundf(padding.start + alignmentOffset.x); + visualTransformOffset.y = roundf(padding.top + alignmentOffset.y); + Property::Map visualTransform; visualTransform.Add(Toolkit::Visual::Transform::Property::SIZE, layoutSize) .Add(Toolkit::Visual::Transform::Property::SIZE_POLICY, Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE)) - .Add(Toolkit::Visual::Transform::Property::OFFSET, Vector2(padding.start, padding.top) + alignmentOffset) + .Add(Toolkit::Visual::Transform::Property::OFFSET, visualTransformOffset) .Add(Toolkit::Visual::Transform::Property::OFFSET_POLICY, Vector2(Toolkit::Visual::Transform::Policy::ABSOLUTE, Toolkit::Visual::Transform::Policy::ABSOLUTE)) .Add(Toolkit::Visual::Transform::Property::ORIGIN, Toolkit::Align::TOP_BEGIN) .Add(Toolkit::Visual::Transform::Property::ANCHOR_POINT, Toolkit::Align::TOP_BEGIN); diff --git a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp index 8a4ada9..8da0313 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp @@ -557,6 +557,14 @@ void AnimatedVectorImageVisual::OnDoAction(const Property::Index actionId, const } break; } + case DevelAnimatedVectorImageVisual::Action::FLUSH: + { + if(DALI_LIKELY(!mCoreShutdown)) + { + SendAnimationData(); + } + break; + } } TriggerVectorRasterization(); diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp index c19a440..6bb0d13 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp @@ -215,7 +215,7 @@ void VectorAnimationTask::SetAnimationData(const AnimationData& data) uint32_t index = mAnimationDataIndex == 0 ? 1 : 0; // Use the other buffer - mAnimationData[index] = data; + mAnimationData[index].push_back(data); mAnimationDataUpdated = true; if(data.resendFlag & VectorAnimationTask::RESEND_SIZE) @@ -660,7 +660,7 @@ void VectorAnimationTask::ApplyAnimationData() { ConditionalWait::ScopedLock lock(mConditionalWait); - if(!mAnimationDataUpdated || mAnimationData[mAnimationDataIndex].resendFlag != 0) + if(!mAnimationDataUpdated || mAnimationData[mAnimationDataIndex].size() != 0) { // Data is not updated or the previous data is not applied yet. return; @@ -672,63 +672,65 @@ void VectorAnimationTask::ApplyAnimationData() index = mAnimationDataIndex; } - if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_LOOP_COUNT) + for(const auto& animationData : mAnimationData[index]) { - SetLoopCount(mAnimationData[index].loopCount); - } - - if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_PLAY_RANGE) - { - SetPlayRange(mAnimationData[index].playRange); - } - - if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_STOP_BEHAVIOR) - { - SetStopBehavior(mAnimationData[index].stopBehavior); - } + if(animationData.resendFlag & VectorAnimationTask::RESEND_LOOP_COUNT) + { + SetLoopCount(animationData.loopCount); + } - if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_LOOPING_MODE) - { - SetLoopingMode(mAnimationData[index].loopingMode); - } + if(animationData.resendFlag & VectorAnimationTask::RESEND_PLAY_RANGE) + { + SetPlayRange(animationData.playRange); + } - if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_CURRENT_FRAME) - { - SetCurrentFrameNumber(mAnimationData[index].currentFrame); - } + if(animationData.resendFlag & VectorAnimationTask::RESEND_STOP_BEHAVIOR) + { + SetStopBehavior(animationData.stopBehavior); + } - if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_NEED_RESOURCE_READY) - { - mVectorRenderer.InvalidateBuffer(); - } + if(animationData.resendFlag & VectorAnimationTask::RESEND_LOOPING_MODE) + { + SetLoopingMode(animationData.loopingMode); + } - if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_DYNAMIC_PROPERTY) - { - for(auto&& iter : mAnimationData[index].dynamicProperties) + if(animationData.resendFlag & VectorAnimationTask::RESEND_CURRENT_FRAME) { - mVectorRenderer.AddPropertyValueCallback(iter.keyPath, static_cast(iter.property), iter.callback, iter.id); + SetCurrentFrameNumber(animationData.currentFrame); } - } - if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_PLAY_STATE) - { - if(mAnimationData[index].playState == DevelImageVisual::PlayState::PLAYING) + if(animationData.resendFlag & VectorAnimationTask::RESEND_NEED_RESOURCE_READY) { - PlayAnimation(); + mVectorRenderer.InvalidateBuffer(); } - else if(mAnimationData[index].playState == DevelImageVisual::PlayState::PAUSED) + + if(animationData.resendFlag & VectorAnimationTask::RESEND_DYNAMIC_PROPERTY) { - PauseAnimation(); + for(auto&& iter : animationData.dynamicProperties) + { + mVectorRenderer.AddPropertyValueCallback(iter.keyPath, static_cast(iter.property), iter.callback, iter.id); + } } - else if(mAnimationData[index].playState == DevelImageVisual::PlayState::STOPPED) + + if(animationData.resendFlag & VectorAnimationTask::RESEND_PLAY_STATE) { - StopAnimation(); + if(animationData.playState == DevelImageVisual::PlayState::PLAYING) + { + PlayAnimation(); + } + else if(animationData.playState == DevelImageVisual::PlayState::PAUSED) + { + PauseAnimation(); + } + else if(animationData.playState == DevelImageVisual::PlayState::STOPPED) + { + StopAnimation(); + } } } - // reset data - mAnimationData[index].dynamicProperties.clear(); - mAnimationData[index].resendFlag = 0; + // reset data list + mAnimationData[index].clear(); } void VectorAnimationTask::OnUploadCompleted() diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h index e1b80c3..fdf1e2c 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h @@ -357,7 +357,7 @@ private: std::string mUrl; VectorAnimationRenderer mVectorRenderer; - AnimationData mAnimationData[2]; + std::vector mAnimationData[2]; VectorAnimationThread& mVectorAnimationThread; ConditionalWait mConditionalWait; ResourceReadySignalType mResourceReadySignal; diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp index 81f6f7d..7e46322 100644 --- a/dali-toolkit/public-api/dali-toolkit-version.cpp +++ b/dali-toolkit/public-api/dali-toolkit-version.cpp @@ -29,7 +29,7 @@ namespace Toolkit { const unsigned int TOOLKIT_MAJOR_VERSION = 2; const unsigned int TOOLKIT_MINOR_VERSION = 2; -const unsigned int TOOLKIT_MICRO_VERSION = 41; +const unsigned int TOOLKIT_MICRO_VERSION = 42; const char* const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__; #ifdef DEBUG_ENABLED diff --git a/dali-toolkit/public-api/image-loader/image.cpp b/dali-toolkit/public-api/image-loader/image.cpp index 8ca77d2..dea398a 100644 --- a/dali-toolkit/public-api/image-loader/image.cpp +++ b/dali-toolkit/public-api/image-loader/image.cpp @@ -67,6 +67,13 @@ Dali::Toolkit::ImageUrl GenerateUrl(const Dali::EncodedImageBuffer encodedImageB return Dali::Toolkit::ImageUrl::New(encodedImageBuffer); } +Dali::Toolkit::ImageUrl GenerateDepthUrl(const Dali::FrameBuffer frameBuffer) +{ + Texture texture = Dali::DevelFrameBuffer::GetDepthTexture(frameBuffer); + Dali::Toolkit::ImageUrl imageUrl = Dali::Toolkit::ImageUrl::New(texture, false); + return imageUrl; +} + } // namespace Image } // namespace Toolkit diff --git a/dali-toolkit/public-api/image-loader/image.h b/dali-toolkit/public-api/image-loader/image.h index f3675ef..bdb9996 100644 --- a/dali-toolkit/public-api/image-loader/image.h +++ b/dali-toolkit/public-api/image-loader/image.h @@ -90,6 +90,15 @@ DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::NativeImageSour */ DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateUrl(const Dali::EncodedImageBuffer encodedImageBuffer); +/** + * @brief Generate a Url of depth texture from frame buffer. + * This Url can be used in visuals to render the frame buffer. + * This method does not check for duplicates, If same frame buffer is entered multiple times, a different URL is returned each time. + * @param[in] frameBuffer the frame buffer to converted to Url + * @return the ImageUrl representing this frame buffer + */ +DALI_TOOLKIT_API Dali::Toolkit::ImageUrl GenerateDepthUrl(const Dali::FrameBuffer frameBuffer); + } // namespace Image } // namespace Toolkit diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec index 431c5ce..48fab3d 100644 --- a/packaging/dali-toolkit.spec +++ b/packaging/dali-toolkit.spec @@ -1,6 +1,6 @@ Name: dali2-toolkit Summary: Dali 3D engine Toolkit -Version: 2.2.41 +Version: 2.2.42 Release: 1 Group: System/Libraries License: Apache-2.0 and BSD-3-Clause and MIT