1 #ifndef IS_REQUIRED_ROUNDED_CORNER
2 #define IS_REQUIRED_ROUNDED_CORNER 0
4 #ifndef IS_REQUIRED_BORDERLINE
5 #define IS_REQUIRED_BORDERLINE 0
7 #ifndef ATLAS_DEFAULT_WARP
8 #define ATLAS_DEFAULT_WARP 0
10 #ifndef ATLAS_CUSTOM_WARP
11 #define ATLAS_CUSTOM_WARP 0
14 INPUT mediump vec2 vTexCoord;
15 #if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
16 INPUT mediump vec2 vPosition;
17 INPUT mediump vec2 vRectSize;
18 INPUT mediump vec2 vOptRectSize;
19 #if IS_REQUIRED_ROUNDED_CORNER
20 INPUT mediump vec4 vCornerRadius;
24 uniform sampler2D sTexture;
25 #if ATLAS_DEFAULT_WARP
26 uniform mediump vec4 uAtlasRect;
27 #elif ATLAS_CUSTOM_WARP
28 // WrapMode -- 0: CLAMP; 1: REPEAT; 2: REFLECT;
29 uniform lowp vec2 wrapMode;
32 uniform lowp vec4 uColor;
33 uniform lowp vec3 mixColor;
34 uniform lowp float preMultipliedAlpha;
35 #if IS_REQUIRED_BORDERLINE
36 uniform mediump float borderlineWidth;
37 uniform mediump float borderlineOffset;
38 uniform lowp vec4 borderlineColor;
39 uniform lowp vec4 uActorColor;
43 mediump float wrapCoordinate( mediump vec2 range, mediump float coordinate, lowp float wrap )
46 if( wrap > 1.5 ) /* REFLECT */
47 coord = 1.0 - abs(fract(coordinate*0.5)*2.0 - 1.0);
48 else /* warp is 0 or 1 */
49 coord = mix(coordinate, fract(coordinate), wrap);
50 return clamp(mix(range.x, range.y, coord), range.x, range.y);
54 #if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
55 // Global values both rounded corner and borderline use
57 // radius of rounded corner on this quadrant
58 mediump float gRadius = 0.0;
60 // fragment coordinate. NOTE : vec2(0.0, 0.0) is vRectSize, the corner of visual
61 mediump vec2 gFragmentPosition = vec2(0.0, 0.0);
62 // center coordinate of rounded corner circle. vec2(gCenterPosition, gCenterPosition).
63 mediump float gCenterPosition = 0.0;
64 // relative coordinate of gFragmentPosition from gCenterPosition.
65 mediump vec2 gDiff = vec2(0.0, 0.0);
66 // potential value what our algorithm use.
67 mediump float gPotential = 0.0;
69 // threshold of potential
70 mediump float gPotentialRange = 0.0;
71 mediump float gMaxOutlinePotential = 0.0;
72 mediump float gMinOutlinePotential = 0.0;
73 mediump float gMaxInlinePotential = 0.0;
74 mediump float gMinInlinePotential = 0.0;
76 void calculateCornerRadius()
78 #if IS_REQUIRED_ROUNDED_CORNER
81 mix(vCornerRadius.x, vCornerRadius.y, sign(vPosition.x) * 0.5 + 0.5),
82 mix(vCornerRadius.w, vCornerRadius.z, sign(vPosition.x) * 0.5 + 0.5),
83 sign(vPosition.y) * 0.5 + 0.5
88 void calculatePosition()
90 gFragmentPosition = abs(vPosition) - vRectSize;
91 gCenterPosition = -gRadius;
92 #if IS_REQUIRED_BORDERLINE
93 gCenterPosition += borderlineWidth * (clamp(borderlineOffset, -1.0, 1.0) + 1.0) * 0.5;
95 gDiff = gFragmentPosition - gCenterPosition;
98 void calculatePotential()
100 gPotential = length(max(gDiff, 0.0)) + min(0.0, max(gDiff.x, gDiff.y));
103 void setupMinMaxPotential()
105 gPotentialRange = 1.0;
107 gMaxOutlinePotential = gRadius + gPotentialRange;
108 gMinOutlinePotential = gRadius - gPotentialRange;
110 #if IS_REQUIRED_BORDERLINE
111 gMaxInlinePotential = gMaxOutlinePotential - borderlineWidth;
112 gMinInlinePotential = gMinOutlinePotential - borderlineWidth;
114 gMaxInlinePotential = gMaxOutlinePotential;
115 gMinInlinePotential = gMinOutlinePotential;
118 // reduce defect near edge of rounded corner.
119 gMaxOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0);
120 gMinOutlinePotential += clamp(-min(gDiff.x, gDiff.y)/ max(1.0, gRadius) , 0.0, 1.0);
123 void PreprocessPotential()
125 calculateCornerRadius();
127 calculatePotential();
129 setupMinMaxPotential();
133 #if IS_REQUIRED_BORDERLINE
134 lowp vec4 convertBorderlineColor(lowp vec4 textureColor)
136 mediump float potential = gPotential;
138 // default opacity of borderline is 0.0
139 mediump float borderlineOpacity = 0.0;
141 // calculate borderline opacity by potential
142 if(potential > gMinInlinePotential)
144 // potential is inside borderline range.
145 borderlineOpacity = smoothstep(gMinInlinePotential, gMaxInlinePotential, potential);
148 lowp vec3 BorderlineColorRGB = borderlineColor.rgb * uActorColor.rgb;
149 lowp float BorderlineColorAlpha = borderlineColor.a * uActorColor.a;
150 BorderlineColorRGB *= mix(1.0, BorderlineColorAlpha, preMultipliedAlpha);
152 //calculate inside of borderline when outilneColor.a < 1.0
153 if(borderlineColor.a < 1.0)
155 mediump float tCornerRadius = -gCenterPosition;
156 mediump float MaxTexturelinePotential = tCornerRadius + gPotentialRange;
157 mediump float MinTexturelinePotential = tCornerRadius - gPotentialRange;
158 if(potential > MaxTexturelinePotential)
160 // potential is out of texture range. use borderline color instead of texture
161 textureColor = vec4(BorderlineColorRGB, 0.0);
163 else if(potential > MinTexturelinePotential)
165 // potential is in texture range
166 textureColor = mix(textureColor, vec4(BorderlineColorRGB, 0.0), smoothstep(MinTexturelinePotential, MaxTexturelinePotential, potential));
168 // TODO : need to fix here when uColor.a = 0.0 and uActorColor.a != 0
169 borderlineOpacity *= borderlineColor.a;
170 return mix(textureColor, vec4(BorderlineColorRGB, 1.0), borderlineOpacity);
172 return mix(textureColor, vec4(BorderlineColorRGB, BorderlineColorAlpha), borderlineOpacity);
176 #if IS_REQUIRED_ROUNDED_CORNER
177 mediump float calculateCornerOpacity()
179 mediump float potential = gPotential;
181 // default opacity is 1.0
182 mediump float opacity = 1.0;
184 // calculate borderline opacity by potential
185 if(potential > gMaxOutlinePotential)
187 // potential is out of borderline range. just discard here
190 else if(potential > gMinOutlinePotential)
192 opacity = 1.0 - smoothstep(gMinOutlinePotential, gMaxOutlinePotential, potential);
200 #if ATLAS_DEFAULT_WARP
201 mediump vec2 texCoord = clamp( mix( uAtlasRect.xy, uAtlasRect.zw, vTexCoord ), uAtlasRect.xy, uAtlasRect.zw );
202 #elif ATLAS_CUSTOM_WARP
203 mediump vec2 texCoord = vec2( wrapCoordinate( uAtlasRect.xz, vTexCoord.x, wrapMode.x ),
204 wrapCoordinate( uAtlasRect.yw, vTexCoord.y, wrapMode.y ) );
206 mediump vec2 texCoord = vTexCoord;
209 lowp vec4 textureColor = TEXTURE( sTexture, texCoord ) * vec4( mixColor, 1.0 ) * uColor;
211 #if IS_REQUIRED_ROUNDED_CORNER || IS_REQUIRED_BORDERLINE
212 // skip most potential calculate for performance
213 if(abs(vPosition.x) < vOptRectSize.x && abs(vPosition.y) < vOptRectSize.y)
215 OUT_COLOR = textureColor;
218 PreprocessPotential();
221 #if IS_REQUIRED_BORDERLINE
222 textureColor = convertBorderlineColor(textureColor);
224 OUT_COLOR = textureColor;
226 #if IS_REQUIRED_ROUNDED_CORNER
227 mediump float opacity = calculateCornerOpacity();
228 OUT_COLOR.a *= opacity;
229 OUT_COLOR.rgb *= mix(1.0, opacity, preMultipliedAlpha);