X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fgraphics%2Fshaders%2Fcolor-visual-shader.frag;h=36a410420963cd5f6f2eaddc8f3cbaaa194a2b3f;hp=74e8f581662bd673fb03fd316ca8f9ca2ec7e6ea;hb=6c0714272287978686a586369b1a909f27ab172d;hpb=d3a0ce5bb20589eb078cb4b86801482005b95b2c diff --git a/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag b/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag index 74e8f58..36a4104 100644 --- a/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag +++ b/dali-toolkit/internal/graphics/shaders/color-visual-shader.frag @@ -1,35 +1,25 @@ -#ifndef IS_REQUIRED_ROUNDED_CORNER -#define IS_REQUIRED_ROUNDED_CORNER 0 -#endif -#ifndef IS_REQUIRED_BORDERLINE -#define IS_REQUIRED_BORDERLINE 0 -#endif -#ifndef IS_REQUIRED_BLUR -#define IS_REQUIRED_BLUR 0 -#endif - -#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR +#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE) || defined(IS_REQUIRED_BLUR) INPUT mediump vec2 vPosition; INPUT mediump vec2 vRectSize; INPUT mediump vec2 vOptRectSize; -#if IS_REQUIRED_ROUNDED_CORNER +#ifdef IS_REQUIRED_ROUNDED_CORNER INPUT mediump vec4 vCornerRadius; #endif #endif uniform lowp vec4 uColor; uniform lowp vec3 mixColor; -#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE +#ifdef IS_REQUIRED_BLUR +uniform mediump float blurRadius; +#elif defined(IS_REQUIRED_BORDERLINE) uniform mediump float borderlineWidth; uniform mediump float borderlineOffset; uniform lowp vec4 borderlineColor; -#endif -#if IS_REQUIRED_BLUR -uniform mediump float blurRadius; +uniform lowp vec4 uActorColor; #endif -#if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE || IS_REQUIRED_BLUR +#if defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE) || defined(IS_REQUIRED_BLUR) // Global values both rounded corner and borderline use // radius of rounded corner on this quadrant @@ -53,7 +43,7 @@ mediump float gMinInlinePotential = 0.0; void calculateCornerRadius() { -#if IS_REQUIRED_ROUNDED_CORNER +#ifdef IS_REQUIRED_ROUNDED_CORNER gRadius = mix( mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5), @@ -67,7 +57,8 @@ void calculatePosition() { gFragmentPosition = abs(vPosition) - vRectSize; gCenterPosition = -gRadius; -#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE +#ifdef IS_REQUIRED_BLUR +#elif defined(IS_REQUIRED_BORDERLINE) gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5; #endif gDiff = gFragmentPosition - gCenterPosition; @@ -85,7 +76,10 @@ void setupMinMaxPotential() gMaxOutlinePotential = gRadius + gPotentialRange; gMinOutlinePotential = gRadius - gPotentialRange; -#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE +#ifdef IS_REQUIRED_BLUR + gMaxInlinePotential = gMaxOutlinePotential; + gMinInlinePotential = gMinOutlinePotential; +#elif defined(IS_REQUIRED_BORDERLINE) gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth; gMinInlinePotential = gMinOutlinePotential - borderlineWidth; #else @@ -108,7 +102,8 @@ void PreprocessPotential() } #endif -#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE +#ifdef IS_REQUIRED_BLUR +#elif defined(IS_REQUIRED_BORDERLINE) lowp vec4 convertBorderlineColor(lowp vec4 textureColor) { mediump float potential = gPotential; @@ -121,32 +116,59 @@ lowp vec4 convertBorderlineColor(lowp vec4 textureColor) { // potential is inside borderline range. borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential); + + // Muliply borderlineWidth to resolve very thin borderline + borderlineOpacity *= min(1.0, borderlineWidth); } - //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 tCornerRadius = -gCenterPosition + gPotentialRange; 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(borderlineColor.xyz, 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(borderlineColor.xyz, 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; } - borderlineOpacity *= borderlineColor.a; - return mix(textureColor, vec4(borderlineColor.xyz, 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, borderlineColor, borderlineOpacity); + return mix(textureColor, vec4(borderlineColorRGB, borderlineColorAlpha), borderlineOpacity); } #endif -#if !IS_REQUIRED_BLUR && IS_REQUIRED_ROUNDED_CORNER +#ifdef IS_REQUIRED_BLUR +#elif defined(IS_REQUIRED_ROUNDED_CORNER) mediump float calculateCornerOpacity() { mediump float potential = gPotential; @@ -168,7 +190,7 @@ mediump float calculateCornerOpacity() } #endif -#if IS_REQUIRED_BLUR +#ifdef IS_REQUIRED_BLUR mediump float calculateBlurOpacity() { // Don't use borderline! @@ -176,7 +198,7 @@ mediump float calculateBlurOpacity() mediump float cy = gRadius + blurRadius; mediump float cr = gRadius + blurRadius; -#if IS_REQUIRED_ROUNDED_CORNER +#ifdef IS_REQUIRED_ROUNDED_CORNER // This routine make perfect circle. If corner radius is not exist, we don't consider prefect circle. cy = min(cy, min(vRectSize.x, vRectSize.y) - gRadius); #endif @@ -213,19 +235,19 @@ mediump float calculateBlurOpacity() // highest point of that circle is (x, x + r) and potential is x + r // solve (v.x - x)^2 + (v.y - x)^2 = (cr / cy * x)^2 -#if IS_REQUIRED_ROUNDED_CORNER - // NOTE : lowspec HW cannot calculate here. need to reduce numeric error - mediump float A = (cr * cr - 2.0 * cy * cy); - mediump float B = cy * (v.x + v.y); - mediump float V = dot(v,v); - mediump float D = B * B + A * V; +#ifdef IS_REQUIRED_ROUNDED_CORNER + // Note : lowspec HW cannot calculate here. need to reduce numeric error + highp float A = (cr * cr - 2.0 * cy * cy); + highp float B = cy * (v.x + v.y); + highp float V = dot(v,v); + highp float D = B * B + A * V; potential = V * (cr + cy) / (sqrt(D) + B); #else // We can simplify this value cause cy = 0.8 * blurRadius, cr = 1.2 * blurRadius // potential = 5.0*(sqrt(4.0*(v.x+v.y)^2 + dot(v,v)) - 2.0*(v.x+v.y)); // = 10.0*(v.x+v.y) * (sqrt(1.0 + (length(v) / (2.0*(v.x+v.y)))^2) - 1.0); // = 10.0*(v.x+v.y) * (sqrt(1.25 - x + x^2) - 1.0); - // ~= 10.0*(v.x+v.y) * (0.11803399 - 0.44721360x + 0.35777088x^2 - 0.14310x^3 + O(x^4)) (Taylor series) + // ~= 10.0*(v.x+v.y) * (0.11803399 - 0.44721360x + 0.35777088x^2 - 0.14310x^3 + O(x^5)) (Taylor series) // ~= -1.0557281 * (v.x + v.y) + 2.236068 * length(v) - ~~~ (here, x <= 0.5 * (1.0 - sqrt(0.5)) < 0.1464467) // Note : This simplify need cause we should use it on lowspec HW. mediump float x = 0.5 * (1.0 - length(v) / (v.x + v.y)); @@ -239,28 +261,34 @@ 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 +#if defined(IS_REQUIRED_BLUR) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE) // skip most potential calculate for performance if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y) { - OUT_COLOR = targetColor * uColor; - return; + OUT_COLOR = targetColor; } - PreprocessPotential(); + else + { + PreprocessPotential(); #endif -#if !IS_REQUIRED_BLUR && IS_REQUIRED_BORDERLINE - targetColor = convertBorderlineColor(targetColor); +#ifdef IS_REQUIRED_BLUR +#elif defined(IS_REQUIRED_BORDERLINE) + targetColor = convertBorderlineColor(targetColor); +#endif + OUT_COLOR = targetColor; + +#ifdef IS_REQUIRED_BLUR + mediump float opacity = calculateBlurOpacity(); + OUT_COLOR.a *= opacity; +#elif defined(IS_REQUIRED_ROUNDED_CORNER) + mediump float opacity = calculateCornerOpacity(); + OUT_COLOR.a *= opacity; #endif - OUT_COLOR = targetColor * uColor; - -#if IS_REQUIRED_BLUR - mediump float opacity = calculateBlurOpacity(); - OUT_COLOR.a *= opacity; -#elif IS_REQUIRED_ROUNDED_CORNER - mediump float opacity = calculateCornerOpacity(); - OUT_COLOR.a *= opacity; + +#if defined(IS_REQUIRED_BLUR) || defined(IS_REQUIRED_ROUNDED_CORNER) || defined(IS_REQUIRED_BORDERLINE) + } #endif }