Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / site / docs / user / modules / particles.md
1
2 ---
3 title: "Particles"
4 linkTitle: "Particles"
5
6 weight: 40
7
8 ---
9
10
11 Skia’s particle module provides a way to quickly generate large numbers of
12 drawing primitives with dynamic, animated behavior. Particles can be used to
13 create effects like fireworks, spark trails, ambient “weather”, and much more.
14 Nearly all properties and behavior are controlled by scripts written in Skia’s
15 custom language, SkSL.
16
17 ## Samples
18
19 <style>
20   #demo canvas {
21     border: 1px dashed #AAA;
22     margin: 2px;
23   }
24
25   figure {
26     display: inline-block;
27     margin: 0;
28   }
29
30   figcaption > a {
31     margin: 2px 10px;
32   }
33 </style>
34
35 <div id=demo>
36   <figure>
37     <canvas id=trail width=400 height=400></canvas>
38     <figcaption>
39       Trail (Click and Drag!)
40     </figcaption>
41   </figure>
42   <figure>
43     <canvas id=cube width=400 height=400></canvas>
44     <figcaption>
45       <a href="https://particles.skia.org/?nameOrHash=@cube"
46          target=_blank rel=noopener>Cuboid</a>
47     </figcaption>
48   </figure>
49   <figure>
50     <canvas id=confetti width=400 height=400></canvas>
51     <figcaption>
52       <a href="https://particles.skia.org/?nameOrHash=@confetti"
53          target=_blank rel=noopener>Confetti</a>
54     </figcaption>
55   </figure>
56   <figure>
57     <canvas id=curves width=400 height=400></canvas>
58     <figcaption>
59       <a href="https://particles.skia.org/?nameOrHash=@swirl"
60          target=_blank rel=noopener>Curves</a>
61     </figcaption>
62   </figure>
63   <figure>
64     <canvas id=fireworks width=400 height=400></canvas>
65     <figcaption>
66       <a href="https://particles.skia.org/?nameOrHash=@fireworks"
67          target=_blank rel=noopener>Fireworks</a>
68     </figcaption>
69   </figure>
70   <figure>
71     <canvas id=text width=400 height=400></canvas>
72     <figcaption>
73       <a href="https://particles.skia.org/?nameOrHash=@text"
74          target=_blank rel=noopener>Text</a>
75     </figcaption>
76   </figure>
77
78 </div>
79
80 <script type="text/javascript" charset="utf-8">
81 (function() {
82   // Tries to load the WASM version if supported, shows error otherwise
83   let s = document.createElement('script');
84   var locate_file = '';
85   if (window.WebAssembly && typeof window.WebAssembly.compile === 'function') {
86     console.log('WebAssembly is supported!');
87     locate_file = 'https://particles.skia.org/dist/';
88   } else {
89     console.log('WebAssembly is not supported (yet) on this browser.');
90     document.getElementById('demo').innerHTML = "<div>WASM not supported by your browser. Try a recent version of Chrome, Firefox, Edge, or Safari.</div>";
91     return;
92   }
93   s.src = locate_file + 'canvaskit.js';
94   s.onload = () => {
95   var CanvasKit = null;
96   CanvasKitInit({
97     locateFile: (file) => locate_file + file,
98   }).then((CK) => {
99     CanvasKit = CK;
100     TrailExample(CanvasKit, 'trail', trail);
101     ParticleExample(CanvasKit, 'confetti', confetti, 200, 200);
102     ParticleExample(CanvasKit, 'curves', curves, 200, 300);
103     ParticleExample(CanvasKit, 'cube', cube, 200, 200);
104     ParticleExample(CanvasKit, 'fireworks', fireworks, 200, 300);
105     ParticleExample(CanvasKit, 'text', text, 75, 250);
106   });
107
108   function ParticleExample(CanvasKit, id, jsonData, cx, cy) {
109     if (!CanvasKit || !jsonData) {
110       return;
111     }
112     const surface = CanvasKit.MakeCanvasSurface(id);
113     if (!surface) {
114       console.error('Could not make surface');
115       return;
116     }
117     const canvas = surface.getCanvas();
118     canvas.translate(cx, cy);
119
120     const particles = CanvasKit.MakeParticles(JSON.stringify(jsonData));
121     particles.start(Date.now() / 1000.0, true);
122
123     function drawFrame(canvas) {
124       particles.update(Date.now() / 1000.0);
125
126       canvas.clear(CanvasKit.WHITE);
127       particles.draw(canvas);
128       surface.requestAnimationFrame(drawFrame);
129     }
130     surface.requestAnimationFrame(drawFrame);
131   }
132
133 const confetti ={
134    "MaxCount": 200,
135    "Drawable": {
136       "Type": "SkCircleDrawable",
137       "Radius": 8
138    },
139    "Code": [
140      "void effectSpawn(inout Effect effect) {",
141      "  effect.lifetime = 2;",
142      "}",
143      "",
144      "void effectUpdate(inout Effect effect) {",
145      "  if (effect.age < 0.25 || effect.age > 0.75) { effect.rate = 0; }",
146      "  else { effect.rate = 200; }",
147      "}",
148      "",
149       "void spawn(inout Particle p) {",
150       "  int idx = int(rand(p.seed) * 4);",
151       "  p.color.rgb = (idx == 0) ? float3(0.87, 0.24, 0.11)",
152       "              : (idx == 1) ? float3(1.00, 0.90, 0.20)",
153       "              : (idx == 2) ? float3(0.44, 0.73, 0.24)",
154       "              :              float3(0.38, 0.54, 0.95);",
155       "",
156       "  p.lifetime = (1 - effect.age) * effect.lifetime;",
157       "  p.scale = mix(0.6, 1, rand(p.seed));",
158       "}",
159       "",
160       "void update(inout Particle p) {",
161       "  p.color.a = 1 - p.age;",
162       "",
163       "  float a = radians(rand(p.seed) * 360);",
164       "  float invAge = 1 - p.age;",
165       "  p.vel = float2(cos(a), sin(a)) * mix(250, 550, rand(p.seed)) * invAge * invAge;",
166       "}",
167       ""
168    ],
169    "Bindings": []
170 };
171
172 const cube = {
173   "MaxCount": 2000,
174   "Drawable": {
175     "Type": "SkCircleDrawable",
176     "Radius": 4
177   },
178   "Code": [
179     "void effectSpawn(inout Effect effect) {",
180     "  effect.lifetime = 2;",
181     "  effect.rate = 200;",
182     "}",
183     "",
184     "void spawn(inout Particle p) {",
185     "  p.lifetime = 10;",
186     "}",
187     "",
188     "float4x4 rx(float rad) {",
189     "  float c = cos(rad);",
190     "  float s = sin(rad);",
191     "  return float4x4(1, 0,  0, 0,",
192     "                  0, c, -s, 0,",
193     "                  0, s,  c, 0,",
194     "                  0, 0,  0, 1);",
195     "}",
196     "",
197     "float4x4 ry(float rad) {",
198     "  float c = cos(rad);",
199     "  float s = sin(rad);",
200     "  return float4x4(c, 0, -s, 0,",
201     "                  0, 1,  0, 0,",
202     "                  s, 0,  c, 0,",
203     "                  0, 0,  0, 1);",
204     "}",
205     "",
206     "float4x4 rz(float rad) {",
207     "  float c = cos(rad);",
208     "  float s = sin(rad);",
209     "  return float4x4( c, s, 0, 0,",
210     "                  -s, c, 0, 0,",
211     "                   0, 0, 1, 0,",
212     "                   0, 0, 0, 1);",
213     "}",
214     "",
215     "void update(inout Particle p) {",
216     "  float3 pos = float3(rand(p.seed), rand(p.seed), rand(p.seed));",
217     "  if (rand(p.seed) < 0.33) {",
218     "    if (pos.x > 0.5) {",
219     "      pos.x = 1;",
220     "      p.color.rgb = float3(1, 0.2, 0.2);",
221     "    } else {",
222     "      pos.x = 0;",
223     "      p.color.rgb = float3(0.2, 1, 1);",
224     "    }",
225     "  } else if (rand(p.seed) < 0.5) {",
226     "    if (pos.y > 0.5) {",
227     "      pos.y = 1;",
228     "      p.color.rgb = float3(0.2, 0.2, 1);",
229     "    } else {",
230     "      pos.y = 0;",
231     "      p.color.rgb = float3(1, 1, 0.2);",
232     "    }",
233     "  } else {",
234     "    if (pos.z > 0.5) {",
235     "      pos.z = 1;",
236     "      p.color.rgb = float3(0.2, 1, 0.2);",
237     "    } else {",
238     "      pos.z = 0;",
239     "      p.color.rgb = float3(1, 0.2, 1);",
240     "    }",
241     "  }",
242     "",
243     "  float s = effect.age * 2 - 1;",
244     "  s = s < 0 ? -s : s;",
245     "",
246     "  pos = pos * 2 - 1;",
247     "  pos = mix(pos, normalize(pos), s);",
248     "  pos = pos * 100;",
249     "",
250     "  float age = float(effect.loop) + effect.age;",
251     "  float4x4 mat = rx(age * radians(60))",
252     "               * ry(age * radians(70))",
253     "               * rz(age * radians(80));",
254     "  pos = (mat * float4(pos, 1)).xyz;",
255     "",
256     "  p.pos.x = pos.x;",
257     "  p.pos.y = pos.y;",
258     "  p.scale = ((pos.z + 50) / 100 + 0.5) / 2;",
259     "}",
260     ""
261   ],
262   "Bindings": []
263 };
264
265 const curves = {
266    "MaxCount": 1000,
267    "Drawable": {
268       "Type": "SkCircleDrawable",
269       "Radius": 2
270    },
271    "Code": [
272      "void effectSpawn(inout Effect effect) {",
273      "  effect.rate = 200;",
274      "  effect.color = float4(1, 0, 0, 1);",
275      "}",
276      "",
277       "void spawn(inout Particle p) {",
278       "  p.lifetime = 3 + rand(p.seed);",
279       "  p.vel.y = -50;",
280       "}",
281       "",
282       "void update(inout Particle p) {",
283       "  float w = mix(15, 3, p.age);",
284       "  p.pos.x = sin(radians(p.age * 320)) * mix(25, 10, p.age) + mix(-w, w, rand(p.seed));",
285       "  if (rand(p.seed) < 0.5) { p.pos.x = -p.pos.x; }",
286       "",
287       "  p.color.g = (mix(75, 220, p.age) + mix(-30, 30, rand(p.seed))) / 255;",
288       "}",
289       ""
290    ],
291    "Bindings": []
292 };
293
294 const fireworks = {
295    "MaxCount": 300,
296    "Drawable": {
297       "Type": "SkCircleDrawable",
298       "Radius": 3
299    },
300    "Code": [
301      "void effectSpawn(inout Effect effect) {",
302      "  // Phase one: Launch",
303      "  effect.lifetime = 4;",
304      "  effect.rate = 120;",
305      "  float a = radians(mix(-20, 20, rand(effect.seed)) - 90);",
306      "  float s = mix(200, 220, rand(effect.seed));",
307      "  effect.vel.x = cos(a) * s;",
308      "  effect.vel.y = sin(a) * s;",
309      "  effect.color.rgb = float3(rand(effect.seed), rand(effect.seed), rand(effect.seed));",
310      "  effect.pos.x = 0;",
311      "  effect.pos.y = 0;",
312      "  effect.scale = 0.25;  // Also used as particle behavior flag",
313      "}",
314      "",
315      "void effectUpdate(inout Effect effect) {",
316      "  if (effect.age > 0.5 && effect.rate > 0) {",
317      "    // Phase two: Explode",
318      "    effect.rate = 0;",
319      "    effect.burst = 50;",
320      "    effect.scale = 1;",
321      "  } else {",
322      "    effect.vel.y += dt * 90;",
323      "  }",
324      "}",
325      "",
326       "void spawn(inout Particle p) {",
327       "  bool explode = p.scale == 1;",
328       "",
329       "  p.lifetime = explode ? (2 + rand(p.seed) * 0.5) : 0.5;",
330       "  float a = radians(rand(p.seed) * 360);",
331       "  float s = explode ? mix(90, 100, rand(p.seed)) : mix(5, 10, rand(p.seed));",
332       "  p.vel.x = cos(a) * s;",
333       "  p.vel.y = sin(a) * s;",
334       "}",
335       "",
336       "void update(inout Particle p) {",
337       "  p.color.a = 1 - p.age;",
338       "  if (p.scale == 1) {",
339       "    p.vel.y += dt * 50;",
340       "  }",
341       "}",
342       ""
343    ],
344    "Bindings": []
345 };
346
347 const text = {
348    "MaxCount": 2000,
349    "Drawable": {
350       "Type": "SkCircleDrawable",
351       "Radius": 1
352    },
353    "Code": [
354      "void effectSpawn(inout Effect effect) {",
355      "  effect.rate = 1000;",
356      "}",
357      "",
358       "void spawn(inout Particle p) {",
359       "  p.lifetime = mix(1, 3, rand(p.seed));",
360       "  float a = radians(mix(250, 290, rand(p.seed)));",
361       "  float s = mix(10, 30, rand(p.seed));",
362       "  p.vel.x = cos(a) * s;",
363       "  p.vel.y = sin(a) * s;",
364       "  p.pos = text(rand(p.seed)).xy;",
365       "}",
366       "",
367       "void update(inout Particle p) {",
368       "  float4 startColor = float4(1, 0.196, 0.078, 1);",
369       "  float4 endColor   = float4(1, 0.784, 0.078, 1);",
370       "  p.color = mix(startColor, endColor, p.age);",
371       "}",
372       ""
373    ],
374    "Bindings": [
375       {
376          "Type": "SkTextBinding",
377          "Name": "text",
378          "Text": "SKIA",
379          "FontSize": 96
380       }
381    ]
382 };
383
384   function preventScrolling(canvas) {
385     canvas.addEventListener('touchmove', (e) => {
386       // Prevents touch events in the canvas from scrolling the canvas.
387       e.preventDefault();
388       e.stopPropagation();
389     });
390   }
391
392   function TrailExample(CanvasKit, id, jsonData) {
393     if (!CanvasKit || !jsonData) {
394       return;
395     }
396     const surface = CanvasKit.MakeCanvasSurface(id);
397     if (!surface) {
398       console.error('Could not make surface');
399       return;
400     }
401     const canvas = surface.getCanvas();
402
403     const particles = CanvasKit.MakeParticles(JSON.stringify(jsonData));
404     particles.start(Date.now() / 1000.0, true);
405
406     function drawFrame(canvas) {
407       particles.update(Date.now() / 1000.0);
408
409       canvas.clear(CanvasKit.WHITE);
410       particles.draw(canvas);
411       surface.requestAnimationFrame(drawFrame);
412     }
413     surface.requestAnimationFrame(drawFrame);
414
415     let interact = (e) => {
416       particles.setPosition([e.offsetX, e.offsetY]);
417       particles.setRate(e.pressure * 1000);
418     };
419     document.getElementById('trail').addEventListener('pointermove', interact);
420     document.getElementById('trail').addEventListener('pointerdown', interact);
421     document.getElementById('trail').addEventListener('pointerup', interact);
422     preventScrolling(document.getElementById('trail'));
423   }
424
425 const trail = {
426    "MaxCount": 2000,
427    "Drawable": {
428       "Type": "SkCircleDrawable",
429       "Radius": 4
430    },
431    "Code": [
432       "void spawn(inout Particle p) {",
433       "  p.lifetime = 2 + rand(p.seed);",
434       "  float a = radians(rand(p.seed) * 360);",
435       "  p.vel = float2(cos(a), sin(a)) * mix(5, 15, rand(p.seed));",
436       "  p.scale = mix(0.25, 0.75, rand(p.seed));",
437       "}",
438       "",
439       "void update(inout Particle p) {",
440       "  p.color.r = p.age;",
441       "  p.color.g = 1 - p.age;",
442       "}",
443       ""
444    ],
445    "Bindings": []
446 };
447
448   }
449   document.head.appendChild(s);
450 })();
451 </script>
452