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