Merge "Changed all property & signal names to lowerCamelCase" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / devel-api / shader-effects / distance-field-effect.h
1 #ifndef __DALI_TOOLKIT_SHADER_EFFECT_DISTANCEFIELD_H__
2 #define __DALI_TOOLKIT_SHADER_EFFECT_DISTANCEFIELD_H__
3
4 /*
5  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <string.h>
23 #include <dali/public-api/shader-effects/shader-effect.h>
24
25 namespace Dali
26 {
27
28 namespace Toolkit
29 {
30
31 /**
32  * Creates a new DistanceFieldEffect
33  *
34  * DistanceFieldEffect is a custom shader effect to achieve distance field on Image actors
35  *
36  * Animatable/Constrainable uniforms - These will need to be registered to the actor as a custom property to take into effect:
37  *
38  *  "uDoGlow"       - The glow state. If true, glow is enabled
39  *  "uGlowBoundary" - The glow boundary factor
40  *  "uGlowColor"    - The glow color multiplier
41
42  *  "uDoShadow"     - The shadow state. If true, shadows is enabled. Cannot be used with glow/and or outline
43  *  "uShadowColor"  - The shadow color multiplier
44  *  "uShadowOffset" - The shadow offset
45
46  *  "uDoOutline"    - The outline state. If true, outline is enabled
47  *  "uOutlineColor" - The outline color multiplier
48  *  "uOutlineParams"- Thickness of outline. The outline thickness is determined by two values.
49  *                    First value [0-1] Specifies the distance field value for the center of the outline.
50  *                    Second value [0-1] Specifies the softness/width/anti-aliasing of the outlines inner edge.
51  *
52  *  @return The newly created Property::Map with the distance field effect
53  */
54 inline Dali::Property::Map CreateDistanceFieldEffect()
55 {
56   const char* fragmentShaderPrefix( "#extension GL_OES_standard_derivatives : enable\n" );
57
58   const char* fragmentShader( DALI_COMPOSE_SHADER(
59       varying mediump vec2 vTexCoord;\n
60       \n
61       uniform mediump float uGlowBoundary;\n
62       uniform mediump vec2  uOutlineParams;\n
63       uniform lowp    vec4  uOutlineColor;\n
64       uniform lowp    vec4  uShadowColor;\n
65       uniform mediump vec2  uShadowOffset;\n
66       uniform lowp    vec4  uGlowColor;\n
67       uniform lowp    float uDoOutline;\n
68       uniform lowp    float uDoShadow;\n
69       uniform lowp    float uDoGlow;\n
70       \n
71       uniform sampler2D sTexture;\n
72       uniform lowp vec4 uColor;\n
73       \n
74       void main()\n
75       {\n
76         // sample distance field\n
77         mediump float smoothing = 0.5;\n
78
79         mediump float distance = texture2D(sTexture, vTexCoord).a;\n
80         mediump float smoothWidth = fwidth(distance);\n
81         mediump float alphaFactor = smoothstep(smoothing - smoothWidth, smoothing + smoothWidth, distance);\n
82         lowp    vec4  color;\n
83         if (uDoShadow == 0.0)\n
84         {\n
85           mediump float alpha = uColor.a * alphaFactor;\n
86           lowp    vec4  rgb = uColor;\n
87           \n
88           if (uDoOutline > 0.0)\n
89           {\n
90             mediump float outlineWidth = uOutlineParams[1] + smoothWidth;\n
91             mediump float outlineBlend = smoothstep(uOutlineParams[0] - outlineWidth, uOutlineParams[0] + outlineWidth, distance);\n
92             alpha = smoothstep(smoothing - smoothWidth, smoothing + smoothWidth, distance);\n
93             rgb = mix(uOutlineColor, uColor, outlineBlend);\n
94           }\n
95           \n
96           if (uDoGlow > 0.0)\n
97           {\n
98             rgb = mix(uGlowColor, rgb, alphaFactor);\n
99             alpha = smoothstep(uGlowBoundary, smoothing, distance);\n
100           }\n
101           \n
102           // set fragment color\n
103           color = vec4(rgb.rgb, alpha);\n
104         }\n
105         \n
106         else // (uDoShadow > 0.0)\n
107         {\n
108           mediump float shadowDistance = texture2D(sTexture, vTexCoord - uShadowOffset).a;\n
109           mediump float inText = alphaFactor;\n
110           mediump float inShadow = smoothstep(smoothing - smoothWidth, smoothing + smoothWidth, shadowDistance);\n
111           \n
112           // inside object, outside shadow\n
113           if (inText == 1.0)\n
114           {\n
115             color = uColor;\n
116           }\n
117           // inside object, outside shadow\n
118           else if ((inText != 0.0) && (inShadow == 0.0))\n
119           {\n
120             color = uColor;\n
121             color.a *= inText;\n
122           }\n
123           // outside object, completely inside shadow\n
124           else if ((inText == 0.0) && (inShadow == 1.0))\n
125           {\n
126             color = uShadowColor;\n
127           }\n
128           // inside object, completely inside shadow\n
129           else if ((inText != 0.0) && (inShadow == 1.0))\n
130           {\n
131             color = mix(uShadowColor, uColor, inText);\n
132             color.a = uShadowColor.a;\n
133           }\n
134           // inside object, inside shadow's border\n
135           else if ((inText != 0.0) && (inShadow != 0.0))\n
136           {\n
137             color = mix(uShadowColor, uColor, inText);\n
138             color.a *= max(inText, inShadow);\n
139           }\n
140           // inside shadow's border\n
141           else if (inShadow != 0.0)\n
142           {\n
143             color = uShadowColor;\n
144             color.a *= inShadow;\n
145           }\n
146           // outside shadow and object\n
147           else \n
148           {\n
149             color.a = 0.0;\n
150           }\n
151           \n
152         }\n
153         \n
154         gl_FragColor = color;\n
155         \n
156       } )
157   );
158
159   Property::Map map;
160
161   Property::Map customShader;
162
163   std::string fragmentShaderString;
164   fragmentShaderString.reserve( strlen( fragmentShaderPrefix ) + strlen( fragmentShader ) );
165   fragmentShaderString.append( fragmentShaderPrefix );
166   fragmentShaderString.append( fragmentShader );
167
168   customShader[ "fragmentShader" ] = fragmentShaderString;
169   customShader[ "hints" ] = "outputIsTransparent";
170
171   map[ "shader" ] = customShader;
172   return map;
173 }
174
175
176 } // namespace Toolkit
177
178 } // namespace Dali
179
180 #endif // __DALI_TOOLKIT_SHADER_EFFECT_SPOT_H__