From: seungho baek Date: Wed, 25 Oct 2023 05:45:17 +0000 (+0900) Subject: Enable masking for Scene3D::SceneView X-Git-Tag: dali_2.3.2~6^2~1 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=093b82a746bf46752a9c94b1346f876ee8c228f1 Enable masking for Scene3D::SceneView Change-Id: Ia725f8a19a96d6020e1247cc49b9568a5f562215 Signed-off-by: seungho baek --- diff --git a/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp b/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp index ca87d38..aaf05f6 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp @@ -1033,3 +1033,39 @@ int UtcDaliSceneViewColorMode(void) END_TEST; } + +namespace +{ +const char* TEST_MASK_IMAGE_FILE_NAME = TEST_RESOURCE_DIR "/mask.png"; + +static constexpr std::string_view Y_FLIP_MASK_TEXTURE = "uYFlipMaskTexture"; +} // namespace + +int UtcDaliSceneViewMasking(void) +{ + ToolkitTestApplication application; + + Scene3D::SceneView view = Scene3D::SceneView::New(); + application.GetScene().Add(view); + + DALI_TEST_EQUALS(view.GetProperty(Dali::Scene3D::SceneView::Property::ALPHA_MASK_URL), "", TEST_LOCATION); + DALI_TEST_EQUALS(view.GetProperty(Dali::Scene3D::SceneView::Property::CROP_TO_MASK), true, TEST_LOCATION); + DALI_TEST_EQUALS(view.GetProperty(Dali::Scene3D::SceneView::Property::MASK_CONTENT_SCALE), 1.0f, TEST_LOCATION); + + auto yFlipMaskTextureIndex = view.GetPropertyIndex(Y_FLIP_MASK_TEXTURE.data()); + DALI_TEST_EQUALS(yFlipMaskTextureIndex, Property::INVALID_INDEX, TEST_LOCATION); + + view.UseFramebuffer(true); + view.SetProperty(Dali::Scene3D::SceneView::Property::ALPHA_MASK_URL, TEST_MASK_IMAGE_FILE_NAME); + view.SetProperty(Dali::Scene3D::SceneView::Property::CROP_TO_MASK, false); + view.SetProperty(Dali::Scene3D::SceneView::Property::MASK_CONTENT_SCALE, 0.5f); + + DALI_TEST_EQUALS(view.GetProperty(Dali::Scene3D::SceneView::Property::ALPHA_MASK_URL), TEST_MASK_IMAGE_FILE_NAME, TEST_LOCATION); + DALI_TEST_EQUALS(view.GetProperty(Dali::Scene3D::SceneView::Property::CROP_TO_MASK), false, TEST_LOCATION); + DALI_TEST_EQUALS(view.GetProperty(Dali::Scene3D::SceneView::Property::MASK_CONTENT_SCALE), 0.5f, TEST_LOCATION); + + yFlipMaskTextureIndex = view.GetPropertyIndex(std::string(Y_FLIP_MASK_TEXTURE)); + DALI_TEST_EQUALS(view.GetProperty(yFlipMaskTextureIndex), 1.0f, TEST_LOCATION); + + END_TEST; +} diff --git a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp index 7b07ffc..f63b5cf 100644 --- a/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp +++ b/automated-tests/src/dali-toolkit/utc-Dali-ImageVisual.cpp @@ -2175,6 +2175,7 @@ int UtcDaliImageVisualAlphaMask02(void) propertyMap.Insert(ImageVisual::Property::URL, TEST_LARGE_IMAGE_FILE_NAME); propertyMap.Insert(ImageVisual::Property::ALPHA_MASK_URL, TEST_MASK_IMAGE_FILE_NAME); propertyMap.Insert(DevelImageVisual::Property::MASKING_TYPE, DevelImageVisual::MaskingType::MASKING_ON_RENDERING); + propertyMap.Insert(DevelImageVisual::Property::CROP_TO_MASK, false); Visual::Base visual = factory.CreateVisual(propertyMap); DALI_TEST_CHECK(visual); @@ -2220,6 +2221,10 @@ int UtcDaliImageVisualAlphaMask02(void) dummyImpl.UnregisterVisual(Control::CONTROL_PROPERTY_END_INDEX + 1); DALI_TEST_EQUALS(actor.GetRendererCount(), 0u, TEST_LOCATION); + auto index = renderer.GetPropertyIndex("maskTextureRatio"); + DALI_TEST_NOT_EQUALS(index, Property::INVALID_INDEX, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(renderer.GetProperty(index), Vector2::ONE, TEST_LOCATION); + END_TEST; } 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 75c9b51..7e59d6a 100644 --- a/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp +++ b/dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp @@ -60,6 +60,10 @@ BaseHandle Create() // Setup properties, signals and actions using the type-registry. DALI_TYPE_REGISTRATION_BEGIN(Scene3D::SceneView, Toolkit::Control, Create); + +DALI_PROPERTY_REGISTRATION(Scene3D, SceneView, "AlphaMaskUrl", STRING, ALPHA_MASK_URL) +DALI_PROPERTY_REGISTRATION(Scene3D, SceneView, "MaskContentScale", FLOAT, MASK_CONTENT_SCALE) +DALI_PROPERTY_REGISTRATION(Scene3D, SceneView, "CropToMask", BOOLEAN, CROP_TO_MASK) DALI_TYPE_REGISTRATION_END() Property::Index RENDERING_BUFFER = Dali::Toolkit::Control::CONTROL_PROPERTY_END_INDEX + 1; @@ -68,6 +72,8 @@ constexpr int32_t INVALID_INDEX = -1; constexpr uint32_t MAXIMUM_SIZE_SHADOW_MAP = 2048; static constexpr std::string_view SKYBOX_INTENSITY_STRING = "uIntensity"; +static constexpr std::string_view Y_FLIP_MASK_TEXTURE = "uYFlipMaskTexture"; +static constexpr float FLIP_MASK_TEXTURE = 1.0f; Dali::Actor CreateSkybox() { @@ -789,6 +795,113 @@ void SceneView::UpdateShadowUniform(Scene3D::Light light) mShaderManager->UpdateShadowUniform(light); } +void SceneView::SetAlphaMaskUrl(std::string& alphaMaskUrl) +{ + if(mAlphaMaskUrl != alphaMaskUrl) + { + mAlphaMaskUrl = alphaMaskUrl; + mMaskingPropertyChanged = true; + UpdateRenderTask(); + } +} + +std::string SceneView::GetAlphaMaskUrl() +{ + return mAlphaMaskUrl; +} + +void SceneView::SetMaskContentScaleFactor(float maskContentScaleFactor) +{ + if(mMaskContentScaleFactor != maskContentScaleFactor) + { + mMaskContentScaleFactor = maskContentScaleFactor; + mMaskingPropertyChanged = true; + UpdateRenderTask(); + } +} + +float SceneView::GetMaskContentScaleFactor() +{ + return mMaskContentScaleFactor; +} + +void SceneView::EnableCropToMask(bool enableCropToMask) +{ + if(mCropToMask != enableCropToMask) + { + mCropToMask = enableCropToMask; + mMaskingPropertyChanged = true; + UpdateRenderTask(); + } +} + +bool SceneView::IsEnabledCropToMask() +{ + return mCropToMask; +} + +void SceneView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value) +{ + Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(Dali::BaseHandle(object)); + + if(sceneView) + { + SceneView& sceneViewImpl(GetImpl(sceneView)); + + switch(index) + { + case Scene3D::SceneView::Property::ALPHA_MASK_URL: + { + std::string alphaMaskUrl = value.Get(); + sceneViewImpl.SetAlphaMaskUrl(alphaMaskUrl); + break; + } + case Scene3D::SceneView::Property::MASK_CONTENT_SCALE: + { + sceneViewImpl.SetMaskContentScaleFactor(value.Get()); + break; + } + case Scene3D::SceneView::Property::CROP_TO_MASK: + { + sceneViewImpl.EnableCropToMask(value.Get()); + break; + } + } + } +} + +Property::Value SceneView::GetProperty(BaseObject* object, Property::Index index) +{ + Property::Value value; + + Scene3D::SceneView sceneView = Scene3D::SceneView::DownCast(Dali::BaseHandle(object)); + + if(sceneView) + { + SceneView& sceneViewImpl(GetImpl(sceneView)); + + switch(index) + { + case Scene3D::SceneView::Property::ALPHA_MASK_URL: + { + value = sceneViewImpl.GetAlphaMaskUrl(); + break; + } + case Scene3D::SceneView::Property::MASK_CONTENT_SCALE: + { + value = sceneViewImpl.GetMaskContentScaleFactor(); + break; + } + case Scene3D::SceneView::Property::CROP_TO_MASK: + { + value = sceneViewImpl.IsEnabledCropToMask(); + break; + } + } + } + return value; +} + /////////////////////////////////////////////////////////// // // Private methods @@ -978,7 +1091,8 @@ void SceneView::UpdateRenderTask() Dali::FrameBuffer currentFrameBuffer = mRenderTask.GetFrameBuffer(); if(!currentFrameBuffer || !Dali::Equals(currentFrameBuffer.GetColorTexture().GetWidth(), size.width) || - !Dali::Equals(currentFrameBuffer.GetColorTexture().GetHeight(), size.height)) + !Dali::Equals(currentFrameBuffer.GetColorTexture().GetHeight(), size.height) || + mMaskingPropertyChanged) { mRootLayer.SetProperty(Dali::Actor::Property::COLOR_MODE, ColorMode::USE_OWN_COLOR); mRenderTask.ResetViewportGuideActor(); @@ -996,8 +1110,18 @@ void SceneView::UpdateRenderTask() imagePropertyMap.Insert(Toolkit::ImageVisual::Property::URL, imageUrl.GetUrl()); // To flip rendered scene without CameraActor::SetInvertYAxis() to avoid backface culling. imagePropertyMap.Insert(Toolkit::ImageVisual::Property::PIXEL_AREA, Vector4(0.0f, 1.0f, 1.0f, -1.0f)); - mVisual = Toolkit::VisualFactory::Get().CreateVisual(imagePropertyMap); + if(!mAlphaMaskUrl.empty()) + { + imagePropertyMap.Insert(Toolkit::ImageVisual::Property::ALPHA_MASK_URL, mAlphaMaskUrl); + imagePropertyMap.Insert(Toolkit::ImageVisual::Property::SYNCHRONOUS_LOADING, true); + imagePropertyMap.Insert(Toolkit::ImageVisual::Property::MASK_CONTENT_SCALE, mMaskContentScaleFactor); + imagePropertyMap.Insert(Toolkit::ImageVisual::Property::CROP_TO_MASK, mCropToMask); + imagePropertyMap.Insert(Toolkit::DevelImageVisual::Property::MASKING_TYPE, Toolkit::DevelImageVisual::MaskingType::MASKING_ON_RENDERING); + Self().RegisterProperty(Y_FLIP_MASK_TEXTURE, FLIP_MASK_TEXTURE); + } + mMaskingPropertyChanged = false; + mVisual = Toolkit::VisualFactory::Get().CreateVisual(imagePropertyMap); Toolkit::DevelControl::RegisterVisual(*this, RENDERING_BUFFER, mVisual); mRenderTask.SetFrameBuffer(mFrameBuffer); 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 79c3705..ce9641a 100644 --- a/dali-scene3d/internal/controls/scene-view/scene-view-impl.h +++ b/dali-scene3d/internal/controls/scene-view/scene-view-impl.h @@ -227,11 +227,65 @@ public: Dali::Scene3D::Loader::ShaderManagerPtr GetShaderManager() const; /** - * @brief Update shader uniforms about shadow. + * @brief Updates shader uniforms about shadow. * @param[in] light Light that makes shadow. */ void UpdateShadowUniform(Scene3D::Light light); + /** + * @brief Sets alpha mask url + * @param[in] alphaMaskUrl Url for alpha mask. + */ + void SetAlphaMaskUrl(std::string& alphaMaskUrl); + + /** + * @brief Retrieves alpha mask url + * @return Alpha mask url. + */ + std::string GetAlphaMaskUrl(); + + /** + * @brief Sets mask content scale factor + * @param[in] maskContentScaleFactor Scale factor for mask content. + */ + void SetMaskContentScaleFactor(float maskContentScaleFactor); + + /** + * @brief Retrieves mask content scale factor + * @return Scale factor for mask content. + */ + float GetMaskContentScaleFactor(); + + /** + * @brief Sets whether the rendered result will be crop to mask or not. + * @param[in] enableCropToMask True for crop rendered result to mask. + */ + void EnableCropToMask(bool enableCropToMask); + + /** + * @brief Retrieves whether the crop to mask is enabled or not. + * @return True when rendered result is cropped to mask. + */ + bool IsEnabledCropToMask(); + + // Properties + + /** + * Called when a property of an object of this type is set. + * @param[in] object The object whose property is set. + * @param[in] index The property index. + * @param[in] value The new property value. + */ + static void SetProperty(BaseObject* object, Property::Index index, const Property::Value& value); + + /** + * Called to retrieve a property of an object of this type. + * @param[in] object The object whose property is to be retrieved. + * @param[in] index The property index. + * @return The current value of the property. + */ + static Property::Value GetProperty(BaseObject* object, Property::Index index); + protected: /** * @brief Constructs a new SceneView. @@ -371,6 +425,12 @@ private: float mSkyboxIntensity{1.0f}; uint8_t mFrameBufferMultiSamplingLevel{0u}; + // Masking + std::string mAlphaMaskUrl; + float mMaskContentScaleFactor{1.0f}; + bool mCropToMask{true}; + bool mMaskingPropertyChanged{false}; + // Shader Factory Dali::Scene3D::Loader::ShaderManagerPtr mShaderManager; diff --git a/dali-scene3d/public-api/controls/scene-view/scene-view.h b/dali-scene3d/public-api/controls/scene-view/scene-view.h index 1f4ec52..41b9e17 100644 --- a/dali-scene3d/public-api/controls/scene-view/scene-view.h +++ b/dali-scene3d/public-api/controls/scene-view/scene-view.h @@ -105,6 +105,50 @@ class DALI_SCENE3D_API SceneView : public Dali::Toolkit::Control { public: /** + * @brief The start and end property ranges for this control. + * @SINCE_2_3.1 + */ + enum PropertyRange + { + PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, + PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000 + }; + + struct Property + { + enum + { + /** + * @brief URL of a masking image + * @details Name "alphaMaskUrl", type Property::STRING, URL of image to apply as + * a mask after SceneView is drawn. + * @note Alpha masking is only available when framebuffer is used. + * @note Optional. + */ + ALPHA_MASK_URL = PROPERTY_START_INDEX, + + /** + * @brief The scale factor to apply to the content image before masking + * @details Name "maskContentScale", type Property::FLOAT, The scale factor + * to apply to the content before masking. Note, scaled result is cropped to + * the same size as the alpha mask. + * @note Optional. + */ + MASK_CONTENT_SCALE, + + /** + * @brief Whether to crop rendered result to mask or scale mask to fit result + * @details Name "cropToMask", type Property::BOOLEAN, True if the rendered result should + * be cropped to match the mask size, or false if the result should remain the same size. + * @note Optional, Default true + * @note If this is false, then the mask is scaled to fit the rendered result before being applied. + */ + CROP_TO_MASK, + }; + }; + +public: + /** * @brief Create an initialized SceneView. * * @SINCE_2_1.38 diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag index 98a7347..f13f865 100644 --- a/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag +++ b/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag @@ -17,6 +17,7 @@ uniform sampler2D sTextureV; #ifdef IS_REQUIRED_ALPHA_MASKING uniform sampler2D sMaskTexture; +uniform lowp float uYFlipMaskTexture; INPUT mediump vec2 vMaskTexCoord; #endif @@ -255,7 +256,9 @@ void main() #endif #ifdef IS_REQUIRED_ALPHA_MASKING - mediump float maskAlpha = TEXTURE(sMaskTexture, vMaskTexCoord).a; + mediump vec2 maskTexCoord = vMaskTexCoord; + maskTexCoord.y = mix(maskTexCoord.y, 1.0-maskTexCoord.y, uYFlipMaskTexture); + mediump float maskAlpha = TEXTURE(sMaskTexture, maskTexCoord).a; textureColor.a *= maskAlpha; textureColor.rgb *= mix(1.0, maskAlpha, preMultipliedAlpha); #endif diff --git a/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp b/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp index c193fe7..7bbe186 100644 --- a/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp +++ b/dali-toolkit/internal/visuals/image-visual-shader-factory.cpp @@ -35,8 +35,9 @@ namespace { const Vector4 FULL_TEXTURE_RECT(0.f, 0.f, 1.f, 1.f); -const int NATIVE_SHADER_TYPE_OFFSET = VisualFactoryCache::ShaderType::NATIVE_IMAGE_SHADER - VisualFactoryCache::ShaderType::IMAGE_SHADER; - +const int NATIVE_SHADER_TYPE_OFFSET = VisualFactoryCache::ShaderType::NATIVE_IMAGE_SHADER - VisualFactoryCache::ShaderType::IMAGE_SHADER; +static constexpr std::string_view Y_FLIP_MASK_TEXTURE = "uYFlipMaskTexture"; +static constexpr float NOT_FLIP_MASK_TEXTURE = 0.0f; } // unnamed namespace static constexpr auto SHADER_TYPE_COUNT = 6u; @@ -121,6 +122,10 @@ Shader ImageVisualShaderFactory::GetShader(VisualFactoryCache& factoryCache, Ima shader = Shader::New(vertexShader, fragmentShader); shader.RegisterProperty(PIXEL_AREA_UNIFORM_NAME, FULL_TEXTURE_RECT); + if(featureBuilder.IsEnabledAlphaMaskingOnRendering()) + { + shader.RegisterProperty(Y_FLIP_MASK_TEXTURE, NOT_FLIP_MASK_TEXTURE); + } factoryCache.SaveShader(shaderType, shader); return shader; diff --git a/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.cpp b/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.cpp index 9b3eb8c..6939cd1 100644 --- a/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.cpp +++ b/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.cpp @@ -224,6 +224,11 @@ Dali::Texture ImageVisualShaderFeatureBuilder::GetTexture() return mTexture; } +bool ImageVisualShaderFeatureBuilder::IsEnabledAlphaMaskingOnRendering() const +{ + return mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED; +} + } // namespace Internal } // namespace Toolkit diff --git a/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h b/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h index d757f70..0f1eccb 100644 --- a/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h +++ b/dali-toolkit/internal/visuals/image-visual-shader-feature-builder.h @@ -154,6 +154,8 @@ public: Dali::Texture GetTexture(); + bool IsEnabledAlphaMaskingOnRendering() const; + private: ImageVisualShaderFeature::TextureAtlas::Type mTextureAtlas : 2; ///< Whether use texture with atlas, or not. default as TextureAtlas::DISABLED ImageVisualShaderFeature::DefaultTextureWrapMode::Type mDefaultTextureWrapMode : 2; ///< Whether apply to texture wraping in default, or not. default as DefaultTextureWrapMode::APPLY diff --git a/dali-toolkit/internal/visuals/image/image-visual.cpp b/dali-toolkit/internal/visuals/image/image-visual.cpp index ff8d961..9e18e36 100644 --- a/dali-toolkit/internal/visuals/image/image-visual.cpp +++ b/dali-toolkit/internal/visuals/image/image-visual.cpp @@ -1323,6 +1323,10 @@ void ImageVisual::CheckMaskTexture() { mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, ComputeMaskTextureRatio()); } + else + { + mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, Vector2::ONE); + } maskLoadFailed = false; }