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<std::string>(Dali::Scene3D::SceneView::Property::ALPHA_MASK_URL), "", TEST_LOCATION);
+ DALI_TEST_EQUALS(view.GetProperty<bool>(Dali::Scene3D::SceneView::Property::CROP_TO_MASK), true, TEST_LOCATION);
+ DALI_TEST_EQUALS(view.GetProperty<float>(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<std::string>(Dali::Scene3D::SceneView::Property::ALPHA_MASK_URL), TEST_MASK_IMAGE_FILE_NAME, TEST_LOCATION);
+ DALI_TEST_EQUALS(view.GetProperty<bool>(Dali::Scene3D::SceneView::Property::CROP_TO_MASK), false, TEST_LOCATION);
+ DALI_TEST_EQUALS(view.GetProperty<float>(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<float>(yFlipMaskTextureIndex), 1.0f, TEST_LOCATION);
+
+ END_TEST;
+}
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);
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<Vector2>(index), Vector2::ONE, TEST_LOCATION);
+
END_TEST;
}
// 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;
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()
{
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<std::string>();
+ sceneViewImpl.SetAlphaMaskUrl(alphaMaskUrl);
+ break;
+ }
+ case Scene3D::SceneView::Property::MASK_CONTENT_SCALE:
+ {
+ sceneViewImpl.SetMaskContentScaleFactor(value.Get<float>());
+ break;
+ }
+ case Scene3D::SceneView::Property::CROP_TO_MASK:
+ {
+ sceneViewImpl.EnableCropToMask(value.Get<bool>());
+ 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
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();
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);
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.
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;
{
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
#ifdef IS_REQUIRED_ALPHA_MASKING
uniform sampler2D sMaskTexture;
+uniform lowp float uYFlipMaskTexture;
INPUT mediump vec2 vMaskTexCoord;
#endif
#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
{
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;
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;
return mTexture;
}
+bool ImageVisualShaderFeatureBuilder::IsEnabledAlphaMaskingOnRendering() const
+{
+ return mAlphaMaskingOnRendering == ImageVisualShaderFeature::AlphaMaskingOnRendering::ENABLED;
+}
+
} // namespace Internal
} // namespace Toolkit
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
{
mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, ComputeMaskTextureRatio());
}
+ else
+ {
+ mImpl->mRenderer.RegisterProperty(MASK_TEXTURE_RATIO_NAME, Vector2::ONE);
+ }
maskLoadFailed = false;
}