(Visuals) Added visual indices
[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) 2016 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/object/property-map.h>
24
25 // INTERNAL INCLUDES
26 #include <dali-toolkit/public-api/visuals/visual-properties.h>
27
28 namespace Dali
29 {
30
31 namespace Toolkit
32 {
33
34 /**
35  * Creates a new DistanceFieldEffect
36  *
37  * DistanceFieldEffect is a custom shader effect to achieve distance field on Image actors
38  *
39  * Animatable/Constrainable uniforms - These will need to be registered to the actor as a custom property to take into effect:
40  *
41  *  "uDoGlow"       - The glow state. If true, glow is enabled
42  *  "uGlowBoundary" - The glow boundary factor
43  *  "uGlowColor"    - The glow color multiplier
44
45  *  "uDoShadow"     - The shadow state. If true, shadows is enabled. Cannot be used with glow/and or outline
46  *  "uShadowColor"  - The shadow color multiplier
47  *  "uShadowOffset" - The shadow offset
48
49  *  "uDoOutline"    - The outline state. If true, outline is enabled
50  *  "uOutlineColor" - The outline color multiplier
51  *  "uOutlineParams"- Thickness of outline. The outline thickness is determined by two values.
52  *                    First value [0-1] Specifies the distance field value for the center of the outline.
53  *                    Second value [0-1] Specifies the softness/width/anti-aliasing of the outlines inner edge.
54  *
55  *  @return The newly created Property::Map with the distance field effect
56  */
57 inline Dali::Property::Map CreateDistanceFieldEffect()
58 {
59   const char* fragmentShaderPrefix( "#extension GL_OES_standard_derivatives : enable\n" );
60
61   const char* fragmentShader( DALI_COMPOSE_SHADER(
62       varying mediump vec2 vTexCoord;\n
63       \n
64       uniform mediump float uGlowBoundary;\n
65       uniform mediump vec2  uOutlineParams;\n
66       uniform lowp    vec4  uOutlineColor;\n
67       uniform lowp    vec4  uShadowColor;\n
68       uniform mediump vec2  uShadowOffset;\n
69       uniform lowp    vec4  uGlowColor;\n
70       uniform lowp    float uDoOutline;\n
71       uniform lowp    float uDoShadow;\n
72       uniform lowp    float uDoGlow;\n
73       \n
74       uniform sampler2D sTexture;\n
75       uniform lowp vec4 uColor;\n
76       \n
77       void main()\n
78       {\n
79         // sample distance field\n
80         mediump float smoothing = 0.5;\n
81
82         mediump float distance = texture2D(sTexture, vTexCoord).a;\n
83         mediump float smoothWidth = fwidth(distance);\n
84         mediump float alphaFactor = smoothstep(smoothing - smoothWidth, smoothing + smoothWidth, distance);\n
85         lowp    vec4  color;\n
86         if (uDoShadow == 0.0)\n
87         {\n
88           mediump float alpha = uColor.a * alphaFactor;\n
89           lowp    vec4  rgb = uColor;\n
90           \n
91           if (uDoOutline > 0.0)\n
92           {\n
93             mediump float outlineWidth = uOutlineParams[1] + smoothWidth;\n
94             mediump float outlineBlend = smoothstep(uOutlineParams[0] - outlineWidth, uOutlineParams[0] + outlineWidth, distance);\n
95             alpha = smoothstep(smoothing - smoothWidth, smoothing + smoothWidth, distance);\n
96             rgb = mix(uOutlineColor, uColor, outlineBlend);\n
97           }\n
98           \n
99           if (uDoGlow > 0.0)\n
100           {\n
101             rgb = mix(uGlowColor, rgb, alphaFactor);\n
102             alpha = smoothstep(uGlowBoundary, smoothing, distance);\n
103           }\n
104           \n
105           // set fragment color\n
106           color = vec4(rgb.rgb, alpha);\n
107         }\n
108         \n
109         else // (uDoShadow > 0.0)\n
110         {\n
111           mediump float shadowDistance = texture2D(sTexture, vTexCoord - uShadowOffset).a;\n
112           mediump float inText = alphaFactor;\n
113           mediump float inShadow = smoothstep(smoothing - smoothWidth, smoothing + smoothWidth, shadowDistance);\n
114           \n
115           // inside object, outside shadow\n
116           if (inText == 1.0)\n
117           {\n
118             color = uColor;\n
119           }\n
120           // inside object, outside shadow\n
121           else if ((inText != 0.0) && (inShadow == 0.0))\n
122           {\n
123             color = uColor;\n
124             color.a *= inText;\n
125           }\n
126           // outside object, completely inside shadow\n
127           else if ((inText == 0.0) && (inShadow == 1.0))\n
128           {\n
129             color = uShadowColor;\n
130           }\n
131           // inside object, completely inside shadow\n
132           else if ((inText != 0.0) && (inShadow == 1.0))\n
133           {\n
134             color = mix(uShadowColor, uColor, inText);\n
135             color.a = uShadowColor.a;\n
136           }\n
137           // inside object, inside shadow's border\n
138           else if ((inText != 0.0) && (inShadow != 0.0))\n
139           {\n
140             color = mix(uShadowColor, uColor, inText);\n
141             color.a *= max(inText, inShadow);\n
142           }\n
143           // inside shadow's border\n
144           else if (inShadow != 0.0)\n
145           {\n
146             color = uShadowColor;\n
147             color.a *= inShadow;\n
148           }\n
149           // outside shadow and object\n
150           else \n
151           {\n
152             color.a = 0.0;\n
153           }\n
154           \n
155         }\n
156         \n
157         gl_FragColor = color;\n
158         \n
159       } )
160   );
161
162   Property::Map map;
163
164   Property::Map customShader;
165
166   std::string fragmentShaderString;
167   fragmentShaderString.reserve( strlen( fragmentShaderPrefix ) + strlen( fragmentShader ) );
168   fragmentShaderString.append( fragmentShaderPrefix );
169   fragmentShaderString.append( fragmentShader );
170
171   customShader[ Visual::Shader::Property::FRAGMENT_SHADER ] = fragmentShaderString;
172   customShader[ Visual::Shader::Property::HINTS ] = Shader::Hint::OUTPUT_IS_TRANSPARENT;
173
174   map[ Visual::Property::SHADER ] = customShader;
175   return map;
176 }
177
178
179 } // namespace Toolkit
180
181 } // namespace Dali
182
183 #endif // __DALI_TOOLKIT_SHADER_EFFECT_SPOT_H__