Let borderline color doesn't affect to mixcolor alpha by uActorColor 68/263568/13
authorEunki, Hong <eunkiki.hong@samsung.com>
Mon, 6 Sep 2021 11:18:16 +0000 (20:18 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Fri, 24 Sep 2021 12:36:49 +0000 (21:36 +0900)
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 <eunkiki.hong@samsung.com>
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-gl-abstraction.cpp
automated-tests/src/dali-toolkit/dali-toolkit-test-utils/test-graphics-reflection.cpp
dali-toolkit/internal/graphics/shaders/color-visual-shader.frag
dali-toolkit/internal/graphics/shaders/gradient-visual-shader.frag
dali-toolkit/internal/graphics/shaders/image-visual-shader.frag
dali-toolkit/internal/visuals/visual-base-impl.cpp

index b85cf4d..e99de5c 100644 (file)
@@ -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},
index 8493992..25c09b5 100644 (file)
@@ -40,6 +40,7 @@ static const std::vector<UniformData> 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),
index 74e8f58..cf1eb08 100644 (file)
@@ -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();
index cb72c67..78f8f22 100644 (file)
@@ -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();
index 0bba311..676c02b 100644 (file)
@@ -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();
index 49b3120..f518895 100644 (file)
@@ -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<Toolkit::DevelVisual::Type>(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<Toolkit::DevelVisual::Type>(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<Vector4>(mImpl->mCornerRadiusIndex);
+    if(mImpl->mRenderer && mImpl->mCornerRadiusIndex != Property::INVALID_INDEX)
+    {
+      // Update values from Renderer
+      mImpl->mCornerRadius = mImpl->mRenderer.GetProperty<Vector4>(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<float>(mImpl->mBorderlineWidthIndex);
+    if(mImpl->mRenderer && mImpl->mBorderlineWidthIndex != Property::INVALID_INDEX)
+    {
+      // Update values from Renderer
+      mImpl->mBorderlineWidth = mImpl->mRenderer.GetProperty<float>(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;