Update exact formula when borderline is transluency.
This patch will fix so many visual defects
TODO : If there is a good way to calculate result without division, change it.
TODO : Visual defect occur when BorderlineWidth is 0.0f.
Not related with this patch but anyway we need to fix some other patch.
Change-Id: Ic14f18eb508dc488a95cdb8f0eff4f615a78629b
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
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)
+ lowp vec3 borderlineColorRGB = borderlineColor.rgb * uActorColor.rgb;
+ lowp float borderlineColorAlpha = borderlineColor.a * uActorColor.a;
+ // NOTE : color-visual is always not preMultiplied.
+
+ // Calculate inside of borderline when alpha is between (0.0 1.0). So we need to apply texture color.
+ // If borderlineOpacity is exactly 0.0, we always use whole texture color. In this case, we don't need to run below code.
+ // But if borderlineOpacity > 0.0 and borderlineColor.a == 0.0, we need to apply tCornerRadius.
+ if(borderlineOpacity > 0.0 && borderlineColor.a * borderlineOpacity < 1.0)
{
mediump float tCornerRadius = -gCenterPosition;
mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
if(potential > MaxTexturelinePotential)
{
- // potential is out of texture range. use borderline color instead of texture
- textureColor = vec4(BorderlineColorRGB, 0.0);
+ // potential is out of texture range.
+ textureColor = vec4(0.0);
}
- else if(potential > MinTexturelinePotential)
+ else
{
- // potential is in texture range
- textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ // potential is in texture range.
+ lowp float textureAlphaScale = mix(1.0, 0.0, smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ textureColor.a *= textureAlphaScale;
+ textureColor.rgb *= textureColor.a;
}
- // 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);
+
+ // NOTE : color-visual is always not preMultiplied.
+ borderlineColorAlpha *= borderlineOpacity;
+ borderlineColorRGB *= borderlineColorAlpha;
+ // We use pre-multiplied color to reduce operations.
+ // In here, textureColor and borderlineColorRGB is pre-multiplied color now.
+
+ // Manual blend operation with premultiplied colors.
+ // Final alpha = borderlineColorAlpha + (1.0 - borderlineColorAlpha) * textureColor.a.
+ // (Final rgb * alpha) = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb
+ // If preMultipliedAlpha == 1.0, just return vec4(rgb*alpha, alpha)
+ // Else, return vec4((rgb*alpha) / alpha, alpha)
+
+ lowp float finalAlpha = mix(textureColor.a, 1.0, borderlineColorAlpha);
+ lowp vec3 finalMultipliedRGB = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb;
+ // TODO : Need to find some way without division
+ return vec4(finalMultipliedRGB / finalAlpha, finalAlpha);
}
- return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity);
+ return mix(textureColor, vec4(borderlineColorRGB, borderlineColorAlpha), borderlineOpacity);
}
#endif
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)
+ lowp vec3 borderlineColorRGB = borderlineColor.rgb * uActorColor.rgb;
+ lowp float borderlineColorAlpha = borderlineColor.a * uActorColor.a;
+ // NOTE : gradient-visual is always preMultiplied.
+ borderlineColorRGB *= borderlineColorAlpha;
+
+ // Calculate inside of borderline when alpha is between (0.0 1.0). So we need to apply texture color.
+ // If borderlineOpacity is exactly 0.0, we always use whole texture color. In this case, we don't need to run below code.
+ // But if borderlineOpacity > 0.0 and borderlineColor.a == 0.0, we need to apply tCornerRadius.
+ if(borderlineOpacity > 0.0 && borderlineColor.a * borderlineOpacity < 1.0)
{
mediump float tCornerRadius = -gCenterPosition;
mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
- lowp vec3 BorderlineColorRGB = borderlineColor.xyz * borderlineColor.a;
if(potential > MaxTexturelinePotential)
{
- // potential is out of texture range. use borderline color instead of texture
- textureColor = vec4(BorderlineColorRGB, 0.0);
+ // potential is out of texture range.
+ textureColor = vec4(0.0);
}
- else if(potential > MinTexturelinePotential)
+ else
{
- // potential is in texture range
- textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ // potential is in texture range.
+ lowp float textureAlphaScale = mix(1.0, 0.0, smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ textureColor.a *= textureAlphaScale;
+ textureColor.rgb *= textureAlphaScale;
}
- // 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);
+
+ // NOTE : gradient-visual is always preMultiplied.
+ borderlineColorAlpha *= borderlineOpacity;
+ borderlineColorRGB *= borderlineOpacity;
+ // We use pre-multiplied color to reduce operations.
+ // In here, textureColor and borderlineColorRGB is pre-multiplied color now.
+
+ // Manual blend operation with premultiplied colors.
+ // Final alpha = borderlineColorAlpha + (1.0 - borderlineColorAlpha) * textureColor.a.
+ // (Final rgb * alpha) = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb
+ // If preMultipliedAlpha == 1.0, just return vec4(rgb*alpha, alpha)
+ // Else, return vec4((rgb*alpha) / alpha, alpha)
+
+ lowp float finalAlpha = mix(textureColor.a, 1.0, borderlineColorAlpha);
+ lowp vec3 finalMultipliedRGB = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb;
+ return vec4(finalMultipliedRGB, finalAlpha);
}
- return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity);
+ return mix(textureColor, vec4(borderlineColorRGB, borderlineColorAlpha), borderlineOpacity);
}
#endif
vOptRectSize -= 0.2929 * maxRadius + 1.0;
#endif
+ mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
#if IS_REQUIRED_BORDERLINE
vPosition = aPosition * (visualSize + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth);
+ vertexPosition.xy *= (1.0 + (1.0 + clamp(borderlineOffset, -1.0, 1.0)) * borderlineWidth / visualSize);
vOptRectSize -= (1.0 - clamp(borderlineOffset, -1.0, 1.0)) * 0.5 * borderlineWidth + 1.0;
#elif IS_REQUIRED_ROUNDED_CORNER
vPosition = aPosition * visualSize;
mediump vec2 vPosition = aPosition * visualSize;
#endif
+#if USER_SPACE
+ vertexPosition.xyz *= uSize;
+#endif
+
+ vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
+
return vec4(vPosition + anchorPoint * visualSize + (visualOffset + origin) * uSize.xy, 0.0, 1.0);
}
void main()
{
- mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
gl_Position = uMvpMatrix * ComputeVertexPosition();
-#if USER_SPACE
- vertexPosition.xyz *= uSize;
-#endif
- vTexCoord = (uAlignmentMatrix*vertexPosition.xyw).xy;
}
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)
+ 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 alpha is between (0.0 1.0). So we need to apply texture color.
+ // If borderlineOpacity is exactly 0.0, we always use whole texture color. In this case, we don't need to run below code.
+ // But if borderlineOpacity > 0.0 and borderlineColor.a == 0.0, we need to apply tCornerRadius.
+ if(borderlineOpacity > 0.0 && borderlineColor.a * borderlineOpacity < 1.0)
{
mediump float tCornerRadius = -gCenterPosition;
mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
if(potential > MaxTexturelinePotential)
{
- // potential is out of texture range. use borderline color instead of texture
- textureColor = vec4(BorderlineColorRGB, 0.0);
+ // potential is out of texture range.
+ textureColor = vec4(0.0);
}
- else if(potential > MinTexturelinePotential)
+ else
{
- // potential is in texture range
- textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ // potential is in texture range.
+ lowp float textureAlphaScale = mix(1.0, 0.0, smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
+ textureColor.a *= textureAlphaScale;
+ textureColor.rgb *= mix(textureColor.a, textureAlphaScale, preMultipliedAlpha);
}
- // 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);
+
+ borderlineColorAlpha *= borderlineOpacity;
+ borderlineColorRGB *= mix(borderlineColorAlpha, borderlineOpacity, preMultipliedAlpha);
+ // We use pre-multiplied color to reduce operations.
+ // In here, textureColor and borderlineColorRGB is pre-multiplied color now.
+
+ // Manual blend operation with premultiplied colors.
+ // Final alpha = borderlineColorAlpha + (1.0 - borderlineColorAlpha) * textureColor.a.
+ // (Final rgb * alpha) = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb
+ // If preMultipliedAlpha == 1.0, just return vec4(rgb*alpha, alpha)
+ // Else, return vec4((rgb*alpha) / alpha, alpha)
+
+ lowp float finalAlpha = mix(textureColor.a, 1.0, borderlineColorAlpha);
+ lowp vec3 finalMultipliedRGB = borderlineColorRGB + (1.0 - borderlineColorAlpha) * textureColor.rgb;
+ // TODO : Need to find some way without division
+ return vec4(finalMultipliedRGB * mix(1.0 / finalAlpha, 1.0, preMultipliedAlpha), finalAlpha);
}
- return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity);
+ return mix(textureColor, vec4(borderlineColorRGB, borderlineColorAlpha), borderlineOpacity);
}
#endif
if(!IsBorderlineRequired())
{
- // If mNeedBorderline is true, BLEND_MODE is already BlendMode::ON_WITHOUT_CULL. So we don't overwrite it.
+ // If IsBorderlineRequired 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);
}