Fix several squircle error + Make render effect shader latest squircle code 15/319815/3
authorEunki Hong <eunkiki.hong@samsung.com>
Sun, 3 Nov 2024 16:30:14 +0000 (01:30 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Mon, 4 Nov 2024 01:20:59 +0000 (10:20 +0900)
- We don't need to calcualte positiveDiff if cornerSquareness value is 1.0
- Support Squircle shape for animated vector image / svg / animated image.
- Use morden method to calculate SDF value with squareness at BackgroundBlurEffect.

Change-Id: I4d4d97e497b5d76a33fcab42c49b8089c09d4425
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
dali-toolkit/devel-api/visuals/visual-properties-devel.h
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/graphics/shaders/render-effect.frag
dali-toolkit/internal/visuals/animated-image/animated-image-visual.cpp
dali-toolkit/internal/visuals/animated-vector-image/animated-vector-image-visual.cpp
dali-toolkit/internal/visuals/svg/svg-visual.cpp

index 7d0c8158ecf9b738a09f3fbe18bc2c4876e19e03..57865fb45d17a48da1b91faee3e76af6eef57a50 100644 (file)
@@ -124,7 +124,6 @@ enum Type
    * @details Name "cornerSquareness", type Property::FLOAT or Property::VECTOR4, animatable
    * @note By default, it is Vector::ZERO.
    * @note Each squareness will clamp internally as [0.0 1.0].
-   * @note If squareness is not zero, the width of borderline might not equal with it's real value.
    * @note Squareness value are used in clockwise order from top-left-corner to bottom-left-corner.
    *       When squareness is Vector4(x, y, z, w)
    *       x    y
index 8b5193de0b8f735322c159ffb8a85f1f674d0836..f5dee4407477a25400d13bc44d113d9ad932e92b 100644 (file)
@@ -96,6 +96,13 @@ void calculatePosition(highp float currentBorderlineWidth)
 void calculatePotential()
 {
 #ifdef IS_REQUIRED_SQUIRCLE_CORNER
+  // If gSquareness is near 1.0, it make some numeric error. Let we avoid this situation by heuristic value.
+  if(gSquareness > 0.99)
+  {
+    gPotential = max(gDiff.x, gDiff.y);
+    return;
+  }
+
   // We need to found the r value s.t. x^2 + y^2 - s/r/r x^2y^2 = r^2
   // and check this r is inside [gRadius - vAliasMargin, gRadius + vAliasMargin]
 
@@ -105,13 +112,6 @@ void calculatePotential()
 
   highp vec2 positiveDiff = max(gDiff, 0.0);
 
-  // If gSquareness is near 1.0, it make some numeric error. Let we avoid this situation by heuristic value.
-  if(gSquareness > 0.99)
-  {
-    gPotential = max(gDiff.x, gDiff.y);
-    return;
-  }
-
   // make sqr to avoid duplicate codes.
   positiveDiff *= positiveDiff;
 
@@ -161,8 +161,6 @@ void PreprocessPotential(highp vec4 cornerRadius, highp vec2 position, highp vec
 #elif defined(IS_REQUIRED_BORDERLINE)
 lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
 {
-  // TODO : Need to consider squareness
-
   highp float potential = gPotential;
 
   // default opacity of borderline is 0.0
index 911b4af72943360501a0b12d05a22b3b62fc9bb0..44d4d7c8d268c15800ca481947ca9fe83cb1ef08 100644 (file)
@@ -89,6 +89,13 @@ void calculatePosition()
 void calculatePotential()
 {
 #ifdef IS_REQUIRED_SQUIRCLE_CORNER
+  // If gSquareness is near 1.0, it make some numeric error. Let we avoid this situation by heuristic value.
+  if(gSquareness > 0.99)
+  {
+    gPotential = max(gDiff.x, gDiff.y);
+    return;
+  }
+
   // We need to found the r value s.t. x^2 + y^2 - s/r/r x^2y^2 = r^2
   // and check this r is inside [gRadius - vAliasMargin, gRadius + vAliasMargin]
 
@@ -98,13 +105,6 @@ void calculatePotential()
 
   highp vec2 positiveDiff = max(gDiff, 0.0);
 
-  // If gSquareness is near 1.0, it make some numeric error. Let we avoid this situation by heuristic value.
-  if(gSquareness > 0.99)
-  {
-    gPotential = max(gDiff.x, gDiff.y);
-    return;
-  }
-
   // make sqr to avoid duplicate codes.
   positiveDiff *= positiveDiff;
 
@@ -152,8 +152,6 @@ void setupMinMaxPotential()
 #ifdef IS_REQUIRED_BORDERLINE
 lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
 {
-  // TODO : Need to consider squareness
-
   highp float potential = gPotential;
 
   // default opacity of borderline is 0.0
index f86c3fe7766a7d391ed27c05014abf0cfb645964..679902983da857951365b969170b712dfb3eb6d5 100644 (file)
@@ -126,6 +126,13 @@ void calculatePosition()
 void calculatePotential()
 {
 #ifdef IS_REQUIRED_SQUIRCLE_CORNER
+  // If gSquareness is near 1.0, it make some numeric error. Let we avoid this situation by heuristic value.
+  if(gSquareness > 0.99)
+  {
+    gPotential = max(gDiff.x, gDiff.y);
+    return;
+  }
+
   // We need to found the r value s.t. x^2 + y^2 - s/r/r x^2y^2 = r^2
   // and check this r is inside [gRadius - vAliasMargin, gRadius + vAliasMargin]
 
@@ -135,13 +142,6 @@ void calculatePotential()
 
   highp vec2 positiveDiff = max(gDiff, 0.0);
 
-  // If gSquareness is near 1.0, it make some numeric error. Let we avoid this situation by heuristic value.
-  if(gSquareness > 0.99)
-  {
-    gPotential = max(gDiff.x, gDiff.y);
-    return;
-  }
-
   // make sqr to avoid duplicate codes.
   positiveDiff *= positiveDiff;
 
@@ -188,8 +188,6 @@ void setupMinMaxPotential()
 #ifdef IS_REQUIRED_BORDERLINE
 lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
 {
-  // TODO : Need to consider squareness
-
   highp float potential = gPotential;
 
   // default opacity of borderline is 0.0
index 15fa6b7ab5b93a16e01ae444f4ee2837b77a6ff3..40968e0e53d8011622f41f2e5f2f26f0e1bc48bf 100644 (file)
@@ -23,19 +23,34 @@ vec3 applyDithering( vec3 inColor )
 }
 
 // from https://iquilezles.org/articles/distfunctions
-float roundedBoxSDF(vec2 PixelPositionFromCenter, vec2 RectangleEdgePositionFromCenter, float Radius, float Squareness) {
-  highp vec2 positiveDiff = max(PixelPositionFromCenter
-                                - RectangleEdgePositionFromCenter
-                                + Radius
-                                , 0.0);
+float roundedBoxSDF(vec2 pixelPositionFromCenter, vec2 rectangleEdgePositionFromCenter, float radius, float squareness) {
+  highp vec2 diff = pixelPositionFromCenter
+                    - rectangleEdgePositionFromCenter
+                    + radius;
 
-  highp float squrenessFactor = Squareness / max(1.0, Radius * Radius);
+  // If squareness is near 1.0 or 0.0, it make some numeric error. Let we avoid this situation by heuristic value.
+  if(squareness < 0.01)
+  {
+    return length(max(diff, 0.0)) + min(0.0, max(diff.x, diff.y)) - radius;
+  }
+  if(squareness > 0.99)
+  {
+    return max(diff.x, diff.y) - radius;
+  }
+
+  highp vec2 positiveDiff = max(diff, 0.0);
 
   // make sqr to avoid duplicate codes.
   positiveDiff *= positiveDiff;
 
-  return sqrt(positiveDiff.x + positiveDiff.y - squrenessFactor * positiveDiff.x * positiveDiff.y)
-         - Radius;
+  // TODO : Could we remove this double-sqrt code?
+  return sqrt(((positiveDiff.x + positiveDiff.y)
+               + sqrt(positiveDiff.x * positiveDiff.x
+                      + positiveDiff.y * positiveDiff.y
+                      + (2.0 - 4.0 * squareness) * positiveDiff.x * positiveDiff.y))
+              * 0.5)
+         + min(0.0, max(diff.x, diff.y)) ///< Consider negative potential, to avoid visual defect when radius is zero
+         - radius;
 }
 
 void main()
@@ -57,12 +72,6 @@ void main()
         mix(vCornerRadius.w, vCornerRadius.z, sign(location.x) * 0.5 + 0.5),
         sign(location.y) * 0.5 + 0.5
       );
-    float squareness =
-      mix(
-        mix(uCornerSquareness.x, uCornerSquareness.y, sign(location.x) * 0.5 + 0.5),
-        mix(uCornerSquareness.w, uCornerSquareness.z, sign(location.x) * 0.5 + 0.5),
-        sign(location.y) * 0.5 + 0.5
-      );
 
     float edgeSoftness = min(1.0, radius);
 
@@ -76,9 +85,16 @@ void main()
     }
     else
     {
-      float distance = roundedBoxSDF(location, halfSize, radius, squareness);
+      float squareness =
+        mix(
+          mix(uCornerSquareness.x, uCornerSquareness.y, sign(location.x) * 0.5 + 0.5),
+          mix(uCornerSquareness.w, uCornerSquareness.z, sign(location.x) * 0.5 + 0.5),
+          sign(location.y) * 0.5 + 0.5
+        );
+
+      float signedDistance = roundedBoxSDF(location, halfSize, radius, squareness);
 
-      float smoothedAlpha = 1.0 - smoothstep(-edgeSoftness, edgeSoftness, distance);
+      float smoothedAlpha = 1.0 - smoothstep(-edgeSoftness, edgeSoftness, signedDistance);
 
       // Premultiply alpha feature used.
       gl_FragColor *= smoothedAlpha;
index a643e0153cdd4fb3950fabb422f92e829462eaa8..8cd3d4feec899d820e03f285a9bc1baaaea3eee0 100644 (file)
@@ -945,7 +945,7 @@ Shader AnimatedImageVisual::GenerateShader() const
     mFactoryCache,
     ImageVisualShaderFeature::FeatureBuilder()
       .ApplyDefaultTextureWrapMode(defaultWrapMode)
-      .EnableRoundedCorner(IsRoundedCornerRequired())
+      .EnableRoundedCorner(IsRoundedCornerRequired(), IsSquircleCornerRequired())
       .EnableBorderline(IsBorderlineRequired())
       .EnableAlphaMaskingOnRendering(requiredAlphaMaskingOnRendering));
   return shader;
index 959694b2af72daf33b9066d9957a017dd56c3b43..87de98ab3a557615f2df17666af9052575ca4b27 100644 (file)
@@ -905,7 +905,7 @@ Shader AnimatedVectorImageVisual::GenerateShader() const
     shader = mImageVisualShaderFactory.GetShader(
       mFactoryCache,
       ImageVisualShaderFeature::FeatureBuilder()
-        .EnableRoundedCorner(IsRoundedCornerRequired())
+        .EnableRoundedCorner(IsRoundedCornerRequired(), IsSquircleCornerRequired())
         .EnableBorderline(IsBorderlineRequired())
         .SetTextureForFragmentShaderCheck(mUseNativeImage ? mImpl->mRenderer.GetTextures().GetTexture(0) : Dali::Texture()));
   }
index 7728733811574291b344a1b86784d3b5b08c6f18..b6b931a90dca9e6f039231ec74fbb0686268bff9 100644 (file)
@@ -536,7 +536,7 @@ Shader SvgVisual::GenerateShader() const
       mFactoryCache,
       ImageVisualShaderFeature::FeatureBuilder()
         .EnableTextureAtlas(mImpl->mFlags & Visual::Base::Impl::IS_ATLASING_APPLIED)
-        .EnableRoundedCorner(IsRoundedCornerRequired())
+        .EnableRoundedCorner(IsRoundedCornerRequired(), IsSquircleCornerRequired())
         .EnableBorderline(IsBorderlineRequired()));
   }
   else