Updated demos to use DALi clang-format
[platform/core/uifw/dali-demo.git] / examples / sparkle / sparkle-effect.h
1 #ifndef DALI_SPARKLE_EFFECT_H
2 #define DALI_SPARKLE_EFFECT_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 #include <dali-toolkit/dali-toolkit.h>
22 #include <dali/dali.h>
23
24 using namespace Dali;
25 using Dali::Toolkit::ImageView;
26
27 /************************************************************/
28 /* Custom sparkle effect shader******************************/
29 /************************************************************/
30
31 namespace SparkleEffect
32 {
33 // uniform which controls the position of particle on the path
34 const std::string PERCENTAGE_UNIFORM_NAME("uPercentage");
35 // uniform array of particle color, set their value as the PARTICLE_COLORS given below
36 const std::string PARTICLE_COLOR_UNIFORM_NAME("uParticleColors[");
37 // uniform array of particle opacity
38 const std::string OPACITY_UNIFORM_NAME("uOpacity[");
39 // uniform which offsets the path control point, with this values >=0, the paths are squeezed towards the GatheringPoint
40 const std::string ACCELARATION_UNIFORM_NAME("uAcceleration");
41 // uniform which indicates the ongoing tap animations
42 const std::string TAP_INDICES_UNIFORM_NAME("uTapIndices");
43 // uniform which controls how much the offset of the midpoints relative to the start/end points of the cubic bezier curve when the path is squeezed for tap animation
44 const std::string TAP_OFFSET_UNIFORM_NAME("uTapOffset[");
45 // uniform which gives the position of the tapping, in this way the particles will be pushed away from this point
46 const std::string TAP_POINT_UNIFORM_NAME("uTapPoint[");
47 // uniform which trigger the break animation, set to 1.0 when break animation is playing, otherwise set to 0.0
48 const std::string BREAK_UNIFORM_NAME("uBreak");
49
50 /****************particle colors******************/
51
52 struct ParticleColor
53 {
54   Vector3      RGB;
55   Vector2      AlphaRange;
56   unsigned int numParticle;
57 };
58
59 ParticleColor PARTICLE_COLORS[] =
60   {
61     {Vector3(0.f, 240.f, 255.f) / 255.f, Vector2(0.2f, 1.f), 22},    // 00f0ff, opacity 20%~100%
62     {Vector3(89.f, 151.f, 239.f) / 255.f, Vector2(0.2f, 0.5f), 12},  // 5997ef, opacity 20%~50%
63     {Vector3(181.f, 181.f, 207.f) / 255.f, Vector2(0.5f, 1.f), 22},  // b5b5cf, opacity 50%~100%
64     {Vector3(147.f, 147.f, 170.f) / 255.f, Vector2(0.5f, 0.5f), 22}, // 9393aa, opacity 50%~50%
65     {Vector3(145.f, 145.f, 201.f) / 255.f, Vector2(1.f, 1.f), 12},   // 91bdc9, opacity 100%~100%
66     {Vector3(145.f, 145.f, 201.f) / 255.f, Vector2(0.2f, 0.2f), 21}  // 91bdc9, opacity 20%~20%
67 };
68 const unsigned int NUM_COLOR(sizeof(PARTICLE_COLORS) / sizeof(PARTICLE_COLORS[0]));
69
70 /***************particle moving paths********************/
71
72 typedef int MovingPath[12];
73
74 // these paths are defined inside the circle which has the center at (250, 250) and the radius as 250
75 MovingPath PATHS[] =
76   { // each path is composed of two cubic b-curves: (p0, p1, p2, p3) & (p3, p4, p5, p0)
77     // p0        p1        p2       p3        p4        p5
78     {280, 273, 386, 41, 489, 141, 491, 199, 494, 256, 230, 394},
79     {129, 226, 357, 120, 150, 491, 291, 406, 433, 320, 47, 283},
80     {96, 264, 356, 133, 446, 196, 370, 297, 294, 399, -169, 384},
81     {345, 110, 359, 186, 14, 393, 4, 247, -6, 101, 321, -28},
82     {166, 161, 128, 353, 566, 200, 487, 304, 413, 403, 203, -32},
83     {193, 286, 106, 331, 206, 569, 334, 477, 462, 385, 279, 240},
84     {336, 247, 293, 232, 301, 465, 346, 479, 390, 493, 374, 261},
85     {250, 72, 314, 72, 332, 495, 250, 497, 168, 499, 161, 72},
86     {48, 387, 32, 241, 452, 558, 433, 358, 411, 121, 62, 523},
87     {300, 32, 159, 27, 442, 568, 186, 492, -70, 415, 551, 41},
88     {479, 150, 503, 203, 216, 403, 163, 298, 110, 193, 448, 78},
89     {346, 75, 311, 97, 336, 196, 389, 160, 442, 123, 383, 51},
90     {90, 61, 54, 96, 218, 373, 294, 300, 370, 227, 141, 11},
91     {126, 225, 240, 280, 378, 29, 221, 16, 64, 4, 11, 170},
92     {308, 101, 243, 22, -10, 271, 22, 352, 49, 422, 396, 208},
93     {193, 188, 174, 302, 502, 389, 500, 250, 498, 111, 212, 72},
94     {227, 3, 16, 35, 577, 309, 428, 423, 279, 537, 438, -28},
95     {410, 58, 387, 18, 22, 179, 154, 277, 286, 374, 459, 142},
96     {178, 272, 109, 299, 144, 429, 218, 396, 293, 362, 221, 254},
97     {247, 46, 98, 5, -91, 357, 160, 431, 412, 505, 397, 88},
98     {41, 112, 22, 144, 123, 273, 158, 187, 192, 101, 75, 56},
99     {8, 300, 23, 340, 267, 294, 238, 218, 209, 142, -20, 226},
100     {112, 256, 24, 270, -1, 470, 154, 433, 308, 396, 201, 242},
101     {212, 277, 267, 346, 509, 202, 452, 103, 398, 8, 150, 199},
102     {154, 205, 146, 287, 496, 282, 492, 194, 488, 107, 160, 140},
103     {281, 350, 365, 318, 415, 476, 332, 482, 248, 489, 204, 379},
104     {327, 23, 346, 81, 154, 319, 123, 207, 92, 95, 313, -21},
105     {323, 233, 283, 307, 454, 420, 478, 354, 501, 288, 374, 136},
106     {318, 186, 311, 252, 488, 248, 481, 168, 474, 87, 328, 76},
107     {7, 192, -10, 270, 249, 398, 269, 307, 290, 216, 25, 111},
108     {148, 22, 98, 22, 25, 458, 125, 458, 225, 458, 198, 22},
109     {349, 32, 307, 39, 492, 416, 399, 446, 305, 477, 460, 16},
110     {147, 474, 222, 554, 392, 154, 486, 240, 581, 325, 73, 394},
111     {57, 186, 13, 200, 51, 398, 114, 374, 178, 349, 97, 174},
112     {257, 192, 198, 188, 162, 345, 240, 349, 319, 354, 316, 197},
113     {242, 4, 283, 21, 30, 172, 81, 215, 133, 257, 209, -10},
114     {149, 408, 165, 442, 472, 340, 444, 275, 416, 210, 120, 348},
115     {106, 271, 136, 359, 483, 370, 422, 186, 360, 2, 76, 186},
116     {120, 146, 29, 224, 469, 262, 346, 390, 222, 518, 393, -87},
117     {318, 265, 415, 280, 398, 537, 247, 491, 96, 446, 222, 249},
118     {171, 275, 207, 246, 274, 469, 237, 497, 199, 525, 139, 300},
119     {196, 84, 135, 105, 256, 510, 334, 486, 412, 462, 280, 55},
120     {485, 314, 452, 170, 158, 606, 111, 411, 55, 179, 515, 446},
121     {134, 54, 266, 4, 175, 607, 392, 451, 609, 296, -100, 144},
122     {3, 229, -1, 287, 334, 383, 350, 267, 366, 150, 10, 151},
123     {105, 115, 146, 125, 154, 227, 92, 209, 30, 192, 62, 105},
124     {343, 20, 388, 42, 323, 357, 228, 313, 132, 269, 278, -10},
125     {362, 186, 271, 274, 60, 82, 204, 19, 349, -44, 453, 97},
126     {145, 128, 181, 32, 501, 185, 498, 272, 495, 347, 97, 257},
127     {286, 172, 342, 274, 59, 463, 16, 331, -27, 198, 231, 69},
128     {194, 7, 404, -32, -38, 410, 140, 469, 317, 528, -16, 45},
129     {39, 120, 48, 74, 445, 109, 352, 244, 259, 379, 20, 215},
130     {328, 247, 402, 250, 411, 384, 330, 377, 248, 370, 281, 244},
131     {189, 56, 317, -31, 610, 240, 396, 392, 183, 543, 61, 144},
132     {402, 53, 430, 77, 376, 231, 315, 161, 255, 91, 351, 10},
133     {496, 218, 494, 260, 249, 296, 251, 214, 254, 133, 498, 139},
134     {381, 210, 469, 195, 557, 376, 399, 391, 241, 407, 292, 226},
135     {297, 263, 267, 346, -8, 289, 14, 176, 35, 69, 331, 168},
136     {329, 187, 363, 263, 30, 371, 5, 287, -19, 203, 302, 128},
137     {257, 354, 168, 351, 171, 516, 252, 496, 333, 475, 340, 356},
138     {106, 60, 107, 121, 366, 284, 359, 168, 352, 52, 105, 14},
139     {178, 257, 240, 314, 115, 476, 71, 421, 28, 367, 98, 182},
140     {163, 213, 191, 273, 22, 327, 3, 248, -17, 170, 118, 113},
141     {459, 117, 500, 185, 297, 390, 248, 311, 199, 232, 416, 46},
142     {270, 3, 317, -14, 528, 375, 434, 407, 339, 440, 223, 19},
143     {88, 76, 130, 68, 78, 485, 176, 483, 274, 482, -22, 96},
144     {422, 428, 378, 528, 88, 205, 26, 317, -36, 428, 467, 328},
145     {414, 127, 460, 125, 489, 325, 421, 322, 353, 320, 372, 128},
146     {227, 197, 281, 174, 367, 311, 294, 340, 221, 370, 173, 220},
147     {180, 14, 147, 44, 436, 104, 401, 161, 366, 219, 207, -10},
148     {400, 367, 395, 404, 71, 406, 77, 336, 82, 265, 407, 300},
149     {396, 222, 396, 316, 71, 439, 70, 245, 68, 51, 396, 132},
150     {342, 109, 454, 153, 49, 332, 208, 413, 367, 494, 8, -23},
151     {147, 167, 222, 137, 266, 169, 231, 199, 197, 229, 129, 178},
152     {227, 272, 310, 243, 277, 313, 322, 266, 367, 219, 207, 313},
153     {279, 192, 339, 233, 396, 211, 367, 182, 338, 152, 228, 194},
154     {236, 20, 283, 75, 346, 26, 338, 71, 330, 116, 207, 17},
155     {129, 83, 164, 23, 158, 14, 179, 11, 200, 8, 91, 78},
156     {86, 231, 129, 293, 164, 421, 104, 348, 44, 275, 66, 200},
157     {193, 328, 197, 278, 240, 348, 276, 305, 311, 263, 199, 354},
158     {231, 364, 241, 209, 309, 104, 326, 236, 342, 367, 225, 424},
159     {414, 230, 398, 328, 446, 445, 467, 363, 489, 281, 373, 254},
160     {289, 122, 332, 123, 348, 161, 322, 158, 297, 156, 275, 125},
161     {142, 235, 199, 308, 402, 229, 283, 218, 164, 206, 130, 206},
162     {174, 396, 210, 387, 328, 501, 246, 455, 165, 409, 138, 394},
163     {288, 388, 366, 357, 372, 458, 393, 400, 414, 343, 249, 431},
164     {351, 278, 409, 369, 497, 316, 437, 288, 376, 260, 351, 243},
165     {87, 134, 181, 77, 311, 121, 206, 140, 101, 160, 61, 159},
166     {95, 195, 126, 208, 133, 258, 110, 236, 88, 215, 95, 195},
167     {140, 293, 158, 330, 169, 275, 184, 299, 198, 323, 126, 313},
168     {336, 319, 383, 357, 388, 278, 393, 333, 397, 388, 311, 325},
169     {338, 107, 434, 209, -37, 469, 151, 287, 338, 104, 285, 50},
170     {403, 134, 446, 182, 378, 318, 386, 233, 393, 149, 360, 98},
171     {366, 82, 413, 93, 416, 158, 390, 118, 364, 78, 336, 75},
172     {448, 188, 448, 230, 465, 269, 470, 225, 474, 181, 448, 177},
173     {121, 398, 142, 418, 126, 475, 111, 436, 96, 396, 100, 382},
174     {40, 296, 90, 352, 170, 310, 143, 350, 116, 391, 7, 300},
175     {25, 203, 45, 241, 70, 204, 45, 248, 19, 293, 4, 204},
176     {243, 222, 225, 275, 345, 256, 296, 237, 247, 218, 249, 199},
177     {159, 149, 282, 133, 284, 199, 226, 191, 169, 184, 147, 160},
178     {149, 257, 290, 322, 151, 374, 166, 338, 182, 302, 116, 263},
179     {255, 285, 354, 327, 234, 287, 279, 327, 323, 367, 193, 290},
180     {188, 220, 353, 190, 290, 354, 348, 293, 407, 231, 152, 248},
181     {305, 122, 382, 174, 402, 229, 366, 198, 329, 167, 297, 127},
182     {378, 260, 406, 267, 390, 330, 384, 293, 377, 257, 366, 263},
183     {178, 396, 357, 365, 273, 461, 248, 431, 223, 401, 157, 412},
184     {180, 89, 258, 88, 302, 94, 255, 115, 207, 136, 166, 96},
185     {81, 197, 139, 232, 39, 257, 94, 259, 150, 261, 58, 200},
186     {314, 89, 378, 40, 383, 38, 389, 42, 395, 45, 267, 90},
187     {371, 141, 482, 233, 508, 244, 498, 272, 488, 299, 307, 157},
188     {339, 348, 361, 465, 382, 477, 406, 442, 430, 406, 269, 369}};
189 const unsigned int NUM_PARTICLE(sizeof(PATHS) / sizeof(PATHS[0]));
190
191 const float PARTICLE_SIZE = 13.f;
192
193 const float   ACTOR_SCALE = 0.704f; // resize 500*500 to 352*352, a bit smaller than 360*360
194 const Vector3 ACTOR_POSITION(-176.f, -176.f, 1.f);
195
196 const int MAXIMUM_ANIMATION_COUNT = 30;
197
198 // Geometry format used by the SparkeEffect
199 struct Vertex
200 {
201   Vertex(const Vector2& texCoord,
202          const Vector2& aParticlePath0,
203          const Vector2& aParticlePath1,
204          const Vector2& aParticlePath2,
205          const Vector2& aParticlePath3,
206          const Vector2& aParticlePath4,
207          const Vector2& aParticlePath5)
208   : aTexCoord(texCoord),
209     aParticlePath0(aParticlePath0),
210     aParticlePath1(aParticlePath1),
211     aParticlePath2(aParticlePath2),
212     aParticlePath3(aParticlePath3),
213     aParticlePath4(aParticlePath4),
214     aParticlePath5(aParticlePath5)
215   {
216   }
217
218   Vector2 aTexCoord;
219   Vector2 aParticlePath0;
220   Vector2 aParticlePath1;
221   Vector2 aParticlePath2;
222   Vector2 aParticlePath3;
223   Vector2 aParticlePath4;
224   Vector2 aParticlePath5;
225 };
226
227 /**
228    * Create a SparkleEffect object.
229    * @return A handle to a newly allocated SparkleEffect
230    */
231 Shader New()
232 {
233   // clang-format off
234     std::string vertexShader = DALI_COMPOSE_SHADER(
235       precision highp float;\n
236       \n
237       attribute vec2  aTexCoord;\n
238       uniform   mat4  uMvpMatrix;\n
239       varying   vec2  vTexCoord;\n
240       \n
241       attribute vec2  aParticlePath0;\n
242       attribute vec2  aParticlePath1;\n
243       attribute vec2  aParticlePath2;\n
244       attribute vec2  aParticlePath3;\n
245       attribute vec2  aParticlePath4;\n
246       attribute vec2  aParticlePath5;\n
247       \n
248       uniform float uPercentage;\n
249       uniform float uPercentageMarked;\n
250       uniform vec3  uParticleColors[NUM_COLOR];\n
251       uniform float uOpacity[NUM_PARTICLE];\n
252       uniform vec2  uTapIndices;
253       uniform float uTapOffset[MAXIMUM_ANIMATION_COUNT];\n
254       uniform vec2  uTapPoint[MAXIMUM_ANIMATION_COUNT];\n
255       uniform float uAcceleration;\n
256       uniform float uRadius;\n
257       uniform float uScale;\n
258       uniform float uBreak;\n
259       \n
260       varying lowp vec4 vColor;\n
261       \n
262       void main()\n
263       {\n
264         // we store the particle index inside texCoord attribute
265         float idx = abs(aTexCoord.y)-1.0;\n
266         \n
267         // early out if the particle is invisible
268         if(uOpacity[int(idx)]<1e-5)\n
269         {\n
270           gl_Position = vec4(0.0);\n
271           vColor = vec4(0.0);\n
272           return;\n
273         }\n
274         \n
275         // As the movement along the b-curve has nonuniform speed with a uniform increasing parameter 'uPercentage'
276         // we give different particles the different 'percentage' to make them looks more random
277         float increment = idx / float(NUM_PARTICLE)*5.0;
278         float percentage = mod(uPercentage +uAcceleration+increment, 1.0);
279         \n
280         vec2 p0; vec2 p1; vec2 p2; vec2 p3;
281         // calculate the particle position by using the cubic b-curve equation
282         if(percentage<0.5)\n // particle on the first b-curve
283         {\n
284           p0 = aParticlePath0;\n
285           p1 = aParticlePath1;\n
286           p2 = aParticlePath2;\n
287           p3 = aParticlePath3;\n
288         }\n
289         else\n
290         {\n
291           p0 = aParticlePath3;\n
292           p1 = aParticlePath4;\n
293           p2 = aParticlePath5;\n
294           p3 = aParticlePath0;\n
295         }\n
296         float t = mod( percentage*2.0, 1.0);\n
297         vec2 position = (1.0-t)*(1.0-t)*(1.0-t)*p0 + 3.0*(1.0-t)*(1.0-t)*t*p1+3.0*(1.0-t)*t*t*p2 + t*t*t*p3;\n
298         \n
299         vec2 referencePoint = mix(p0,p3,0.5);\n
300         float maxAnimationCount = float(MAXIMUM_ANIMATION_COUNT);\n
301         \n
302         for( float i=uTapIndices.x; i<uTapIndices.y; i+=1.0 )\n
303         {
304           int id = int( mod(i+0.5,maxAnimationCount ) );\n
305           vec2 edgePoint = normalize(referencePoint-uTapPoint[id])*uRadius+vec2(uRadius);\n
306           position = mix( position, edgePoint, uTapOffset[id] ) ;\n
307         }\n
308         \n
309         position = mix( position, vec2( 250.0,250.0 ),uBreak*(1.0-uOpacity[int(idx)]) ) ;
310         \n
311         // vertex position on the mesh: (sign(aTexCoord.x), sign(aTexCoord.y))*PARTICLE_HALF_SIZE
312         gl_Position = uMvpMatrix * vec4( position.x+sign(aTexCoord.x)*PARTICLE_HALF_SIZE/uScale,
313                                          position.y+sign(aTexCoord.y)*PARTICLE_HALF_SIZE/uScale,
314                                          0.0, 1.0 );\n
315         \n
316         // we store the color index inside texCoord attribute
317         float colorIndex = abs(aTexCoord.x);
318         vColor.rgb = uParticleColors[int(colorIndex)-1];\n
319         vColor.a = fract(colorIndex) * uOpacity[int(idx)];\n
320         \n
321         // produce a 'seemingly' random fade in/out
322         percentage = mod(uPercentage+increment+0.15, 1.0);\n
323         float ramdomOpacity = (min(percentage, 0.25)-0.15+0.9-max(percentage,0.9))*10.0;\n
324         vColor.a *=ramdomOpacity;\n
325         \n
326         vTexCoord = clamp(aTexCoord, 0.0, 1.0);\n
327       }\n
328     );
329
330     std::string fragmentShader = DALI_COMPOSE_SHADER(
331         precision highp float;\n
332         uniform sampler2D sTexture;\n
333         varying vec2      vTexCoord;\n
334         \n
335         varying lowp vec4 vColor;\n
336         \n
337         void main()\n
338         {\n
339           gl_FragColor = vColor;\n
340           gl_FragColor.a *= texture2D(sTexture, vTexCoord).a;\n
341         }\n
342     );
343   // clang-format on
344
345   std::ostringstream vertexShaderStringStream;
346   vertexShaderStringStream << "#define NUM_COLOR " << NUM_COLOR << "\n"
347                            << "#define NUM_PARTICLE " << NUM_PARTICLE << "\n"
348                            << "#define PARTICLE_HALF_SIZE " << PARTICLE_SIZE * ACTOR_SCALE / 2.f << "\n"
349                            << "#define MAXIMUM_ANIMATION_COUNT " << MAXIMUM_ANIMATION_COUNT << "\n"
350                            << vertexShader;
351
352   Shader handle = Shader::New(vertexShaderStringStream.str(), fragmentShader);
353
354   // set the particle colors
355   std::ostringstream oss;
356   for(unsigned int i = 0; i < NUM_COLOR; i++)
357   {
358     oss.str("");
359     oss << PARTICLE_COLOR_UNIFORM_NAME << i << "]";
360     handle.RegisterProperty(oss.str(), PARTICLE_COLORS[i].RGB);
361   }
362   handle.RegisterProperty("uRadius", 250.f);
363   handle.RegisterProperty("uScale", ACTOR_SCALE);
364
365   // set the initial uniform values
366
367   for(unsigned int i = 0; i < NUM_PARTICLE; i++)
368   {
369     oss.str("");
370     oss << OPACITY_UNIFORM_NAME << i << "]";
371     handle.RegisterProperty(oss.str(), 1.f);
372   }
373   handle.RegisterProperty(PERCENTAGE_UNIFORM_NAME, 0.f);
374   handle.RegisterProperty(ACCELARATION_UNIFORM_NAME, 0.f);
375   handle.RegisterProperty(BREAK_UNIFORM_NAME, 0.f);
376   handle.RegisterProperty(TAP_INDICES_UNIFORM_NAME, Vector2::ZERO);
377
378   for(int i = 0; i < MAXIMUM_ANIMATION_COUNT; i++)
379   {
380     oss.str("");
381     oss << TAP_OFFSET_UNIFORM_NAME << i << "]";
382     handle.RegisterProperty(oss.str(), 0.f);
383
384     oss.str("");
385     oss << TAP_POINT_UNIFORM_NAME << i << "]";
386     handle.RegisterProperty(oss.str(), Vector2(250.0f, 250.0f));
387   }
388
389   return handle;
390 }
391
392 }; // namespace SparkleEffect
393
394 #endif // DALI_SPARKLE_EFFECT_H