From 48220839bdcedaca9d53cbd15aab66353187c14b Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Mon, 6 Sep 2021 20:18:16 +0900 Subject: [PATCH] Let borderline color doesn't affect to mixcolor alpha by uActorColor Previously, DevelRenderer always merged into uColor.a value. This situation usally have no problem. But when we want to use both MIX_COLOR and BORDERLINE_COLOR there was no way to split Actor's opacity and MIX_COLOR's opacity. So BORDERLINE_COLOR.a is always pre-multiplired by MIX_COLOR.a. And also, when MIX_COLOR.a is zero, There is no way to render BORDERLINE only. This patch try to fix this issue. First, Add logic to keep-rendering logic. (BlendMode::ON_WITHOUT_CULL) Second, Turn on that flag only if borderline required. Third, Modify shader s.t. use default uniform : uActorColor. Change-Id: I033fa6accebe5ae59aedc1e0b68ee4b8d0df7098 Signed-off-by: Eunki, Hong --- .../test-gl-abstraction.cpp | 1 + .../test-graphics-reflection.cpp | 1 + .../graphics/shaders/color-visual-shader.frag | 19 +++-- .../graphics/shaders/gradient-visual-shader.frag | 17 ++-- .../graphics/shaders/image-visual-shader.frag | 16 ++-- dali-toolkit/internal/visuals/visual-base-impl.cpp | 95 ++++++++++++++++++---- 6 files changed, 116 insertions(+), 33 deletions(-) diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp index b85cf4d..e99de5c 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp @@ -130,6 +130,7 @@ void TestGlAbstraction::Initialize() {"sTextureRect", GL_SAMPLER_2D, 1}, {"sGloss", GL_SAMPLER_2D, 1}, {"uColor", GL_FLOAT_VEC4, 1}, + {"uActorColor", GL_FLOAT_VEC4, 1}, {"uModelMatrix", GL_FLOAT_MAT4, 1}, {"uModelView", GL_FLOAT_MAT4, 1}, {"uMvpMatrix", GL_FLOAT_MAT4, 1}, diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-reflection.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-reflection.cpp index 8493992..25c09b5 100644 --- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-reflection.cpp +++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-reflection.cpp @@ -40,6 +40,7 @@ static const std::vector UNIFORMS = UniformData("sTextureRect", Property::Type::FLOAT), UniformData("sGloss", Property::Type::FLOAT), UniformData("uColor", Property::Type::VECTOR4), + UniformData("uActorColor", Property::Type::VECTOR4), UniformData("uModelMatrix", Property::Type::MATRIX), UniformData("uModelView", Property::Type::MATRIX), UniformData("uMvpMatrix", Property::Type::MATRIX), diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag index 74e8f58..cf1eb08 100644 --- a/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag +++ b/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag @@ -23,6 +23,7 @@ uniform lowp vec3 mixColor; uniform mediump float borderlineWidth; uniform mediump float borderlineOffset; uniform lowp vec4 borderlineColor; +uniform lowp vec4 uActorColor; #endif #if IS_REQUIRED_BLUR uniform mediump float blurRadius; @@ -123,6 +124,9 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor) borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential); } + lowp vec3 BorderlineColorRGB = borderlineColor.rgb * uActorColor.rgb; + lowp float BorderlineColorAlpha = borderlineColor.a * uActorColor.a; + //calculate inside of borderline when outilneColor.a < 1.0 if(borderlineColor.a < 1.0) { @@ -132,17 +136,18 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor) if(potential > MaxTexturelinePotential) { // potential is out of texture range. use borderline color instead of texture - textureColor = vec4(borderlineColor.xyz, 0.0); + textureColor = vec4(BorderlineColorRGB, 0.0); } else if(potential > MinTexturelinePotential) { // potential is in texture range - textureColor = mix(textureColor, vec4(borderlineColor.xyz, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential)); + textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential)); } + // TODO : need to fix here when uColor.a = 0.0 and uActorColor.a != 0 borderlineOpacity *= borderlineColor.a; - return mix(textureColor, vec4(borderlineColor.xyz, 1.0), borderlineOpacity); + return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity); } - return mix(textureColor, borderlineColor, borderlineOpacity); + return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity); } #endif @@ -239,13 +244,13 @@ mediump float calculateBlurOpacity() void main() { - lowp vec4 targetColor = vec4(mixColor, 1.0); + lowp vec4 targetColor = vec4(mixColor, 1.0) * uColor; #if IS_REQUIRED_BLUR || IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE // skip most potential calculate for performance if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) { - OUT_COLOR = targetColor * uColor; + OUT_COLOR = targetColor; return; } PreprocessPotential(); @@ -254,7 +259,7 @@ void main() #if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE targetColor = convertBorderlineColor(targetColor); #endif - OUT_COLOR = targetColor * uColor; + OUT_COLOR = targetColor; #if IS_REQUIRED_BLUR mediump float opacity = calculateBlurOpacity(); diff --git a/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag index cb72c67..78f8f22 100644 --- a/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag +++ b/dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag @@ -25,6 +25,7 @@ uniform lowp vec3 mixColor; uniform mediump float borderlineWidth; uniform mediump float borderlineOffset; uniform lowp vec4 borderlineColor; +uniform lowp vec4 uActorColor; #endif #if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE @@ -122,6 +123,11 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor) borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential); } + lowp vec3 BorderlineColorRGB = borderlineColor.rgb * uActorColor.rgb; + lowp float BorderlineColorAlpha = borderlineColor.a * uActorColor.a; + // Gradient is always preMultiplied. + BorderlineColorRGB *= BorderlineColorAlpha; + //calculate inside of borderline when outilneColor.a < 1.0 if(borderlineColor.a < 1.0) { @@ -139,10 +145,11 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor) // potential is in texture range textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential)); } + // TODO : need to fix here when uColor.a = 0.0 and uActorColor.a != 0 borderlineOpacity *= borderlineColor.a; return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity); } - return mix(textureColor, borderlineColor, borderlineOpacity); + return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity); } #endif @@ -171,16 +178,16 @@ mediump float calculateCornerOpacity() void main() { #if RADIAL - lowp vec4 textureColor = TEXTURE(sTexture, vec2(length(vTexCoord), 0.5)) * vec4(mixColor, 1.0); + lowp vec4 textureColor = TEXTURE(sTexture, vec2(length(vTexCoord), 0.5)) * vec4(mixColor, 1.0) * uColor; #else - lowp vec4 textureColor = TEXTURE(sTexture, vec2(vTexCoord.y, 0.5)) * vec4(mixColor, 1.0); + lowp vec4 textureColor = TEXTURE(sTexture, vec2(vTexCoord.y, 0.5)) * vec4(mixColor, 1.0) * uColor; #endif #if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE // skip most potential calculate for performance if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) { - OUT_COLOR = textureColor * uColor; + OUT_COLOR = textureColor; return; } PreprocessPotential(); @@ -189,7 +196,7 @@ void main() #if IS_REQUIRED_BORDERLINE textureColor = convertBorderlineColor(textureColor); #endif - OUT_COLOR = textureColor * uColor; + OUT_COLOR = textureColor; #if IS_REQUIRED_ROUNDED_CORNER mediump float opacity = calculateCornerOpacity(); diff --git a/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag index 0bba311..676c02b 100644 --- a/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag +++ b/dali-toolkit/internal/graphics/shaders/image-visual-shader.frag @@ -36,6 +36,7 @@ uniform lowp float preMultipliedAlpha; uniform mediump float borderlineWidth; uniform mediump float borderlineOffset; uniform lowp vec4 borderlineColor; +uniform lowp vec4 uActorColor; #endif #if ATLAS_CUSTOM_WARP @@ -144,14 +145,16 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor) borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential); } + lowp vec3 BorderlineColorRGB = borderlineColor.rgb * uActorColor.rgb; + lowp float BorderlineColorAlpha = borderlineColor.a * uActorColor.a; + BorderlineColorRGB *= mix(1.0, BorderlineColorAlpha, preMultipliedAlpha); + //calculate inside of borderline when outilneColor.a < 1.0 if(borderlineColor.a < 1.0) { mediump float tCornerRadius = -gCenterPosition; mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange; mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange; - lowp vec3 BorderlineColorRGB = borderlineColor.xyz; - BorderlineColorRGB *= mix(1.0, borderlineColor.a, preMultipliedAlpha); if(potential > MaxTexturelinePotential) { // potential is out of texture range. use borderline color instead of texture @@ -162,10 +165,11 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor) // potential is in texture range textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential)); } + // TODO : need to fix here when uColor.a = 0.0 and uActorColor.a != 0 borderlineOpacity *= borderlineColor.a; return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity); } - return mix(textureColor, borderlineColor, borderlineOpacity); + return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity); } #endif @@ -202,13 +206,13 @@ void main() mediump vec2 texCoord = vTexCoord; #endif - lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * vec4( mixColor, 1.0 ); + lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * vec4( mixColor, 1.0 ) * uColor; #if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE // skip most potential calculate for performance if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) { - OUT_COLOR = textureColor * uColor; + OUT_COLOR = textureColor; return; } PreprocessPotential(); @@ -217,7 +221,7 @@ void main() #if IS_REQUIRED_BORDERLINE textureColor = convertBorderlineColor(textureColor); #endif - OUT_COLOR = textureColor * uColor; + OUT_COLOR = textureColor; #if IS_REQUIRED_ROUNDED_CORNER mediump float opacity = calculateCornerOpacity(); diff --git a/dali-toolkit/internal/visuals/visual-base-impl.cpp b/dali-toolkit/internal/visuals/visual-base-impl.cpp index 49b3120..f518895 100644 --- a/dali-toolkit/internal/visuals/visual-base-impl.cpp +++ b/dali-toolkit/internal/visuals/visual-base-impl.cpp @@ -60,6 +60,56 @@ DALI_ENUM_TO_STRING_TABLE_BEGIN(VISUAL_FITTING_MODE) DALI_ENUM_TO_STRING_WITH_SCOPE(Visual::FittingMode, FIT_HEIGHT) DALI_ENUM_TO_STRING_TABLE_END(VISUAL_FITTING_MODE) +/** + * @brief Check whether this visual type can use corner radius feature or not. + * @param type VisualType that want to checkup + * @return true if type can use corner radius feature. + */ +static bool IsTypeAvailableForCornerRadius(Toolkit::Visual::Type type) +{ + switch(static_cast(type)) + { + case Toolkit::Visual::Type::COLOR: + case Toolkit::Visual::Type::GRADIENT: + case Toolkit::Visual::Type::IMAGE: + case Toolkit::Visual::Type::SVG: + case Toolkit::Visual::Type::ANIMATED_IMAGE: + case Toolkit::DevelVisual::Type::ANIMATED_VECTOR_IMAGE: + { + return true; + } + default: + { + return false; + } + } +} + +/** + * @brief Check whether this visual type can use borderline feature or not. + * @param type VisualType that want to checkup + * @return true if type can use borderline feature. + */ +static bool IsTypeAvailableForBorderline(Toolkit::Visual::Type type) +{ + switch(static_cast(type)) + { + case Toolkit::Visual::Type::COLOR: + case Toolkit::Visual::Type::GRADIENT: + case Toolkit::Visual::Type::IMAGE: + case Toolkit::Visual::Type::SVG: + case Toolkit::Visual::Type::ANIMATED_IMAGE: + case Toolkit::DevelVisual::Type::ANIMATED_VECTOR_IMAGE: + { + return true; + } + default: + { + return false; + } + } +} + } // namespace Visual::Base::Base(VisualFactoryCache& factoryCache, FittingMode fittingMode, Toolkit::Visual::Type type) @@ -95,7 +145,7 @@ void Visual::Base::Initialize() mImpl->mBorderlineColorIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_COLOR, BORDERLINE_COLOR, mImpl->mBorderlineColor); mImpl->mBorderlineOffsetIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_OFFSET, BORDERLINE_OFFSET, mImpl->mBorderlineOffset); - mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON); + mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON_WITHOUT_CULL); } } } @@ -525,22 +575,32 @@ bool Visual::Base::IsOnScene() const bool Visual::Base::IsRoundedCornerRequired() const { - if(mImpl->mRenderer && mImpl->mCornerRadiusIndex != Property::INVALID_INDEX) + // If VisualType doesn't support rounded corner, always return false. + if(IsTypeAvailableForCornerRadius(mImpl->mType)) { - // Update values from Renderer - mImpl->mCornerRadius = mImpl->mRenderer.GetProperty(mImpl->mCornerRadiusIndex); + if(mImpl->mRenderer && mImpl->mCornerRadiusIndex != Property::INVALID_INDEX) + { + // Update values from Renderer + mImpl->mCornerRadius = mImpl->mRenderer.GetProperty(mImpl->mCornerRadiusIndex); + } + return !(mImpl->mCornerRadius == Vector4::ZERO) || mImpl->mNeedCornerRadius; } - return !(mImpl->mCornerRadius == Vector4::ZERO) || mImpl->mNeedCornerRadius; + return false; } bool Visual::Base::IsBorderlineRequired() const { - if(mImpl->mRenderer && mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX) + // If VisualType doesn't support borderline, always return false. + if(IsTypeAvailableForBorderline(mImpl->mType)) { - // Update values from Renderer - mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty(mImpl->mBorderlineWidthIndex); + if(mImpl->mRenderer && mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX) + { + // Update values from Renderer + mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty(mImpl->mBorderlineWidthIndex); + } + return !EqualsZero(mImpl->mBorderlineWidth) || mImpl->mNeedBorderline; } - return !EqualsZero(mImpl->mBorderlineWidth) || mImpl->mNeedBorderline; + return false; } void Visual::Base::OnDoAction(const Property::Index actionId, const Property::Value& attributes) @@ -897,11 +957,12 @@ Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key) Property::Index index = GetPropertyIndex(key); if(index == Property::INVALID_INDEX) { - if((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_WIDTH) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_WIDTH) || - (key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_COLOR) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_COLOR) || - (key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_OFFSET) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_OFFSET)) + if(IsTypeAvailableForBorderline(mImpl->mType) && + ((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_WIDTH) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_WIDTH) || + (key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_COLOR) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_COLOR) || + (key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::BORDERLINE_OFFSET) || (key.type == Property::Key::STRING && key.stringKey == BORDERLINE_OFFSET))) { - mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON); + mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON_WITHOUT_CULL); // Register borderline properties mImpl->mBorderlineWidthIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::BORDERLINE_WIDTH, BORDERLINE_WIDTH, mImpl->mBorderlineWidth); @@ -914,13 +975,17 @@ Dali::Property Visual::Base::GetPropertyObject(Dali::Property::Key key) // Change shader UpdateShader(); } - else if((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::CORNER_RADIUS) || (key.type == Property::Key::STRING && key.stringKey == CORNER_RADIUS)) + else if(IsTypeAvailableForCornerRadius(mImpl->mType) && ((key.type == Property::Key::INDEX && key.indexKey == DevelVisual::Property::CORNER_RADIUS) || (key.type == Property::Key::STRING && key.stringKey == CORNER_RADIUS))) { // Register CORNER_RADIUS property mImpl->mCornerRadiusIndex = mImpl->mRenderer.RegisterProperty(DevelVisual::Property::CORNER_RADIUS, CORNER_RADIUS, mImpl->mCornerRadius); mImpl->mRenderer.RegisterProperty(CORNER_RADIUS_POLICY, mImpl->mCornerRadiusPolicy); - mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON); + if(!mImpl->mNeedBorderline) + { + // If mNeedBorderline is true, BLEND_MODE is already BlendMode::ON_WITHOUT_CULL. So we don't overwrite it. + mImpl->mRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::ON); + } index = mImpl->mCornerRadiusIndex; mImpl->mNeedCornerRadius = true; -- 2.7.4