blob: 691b15fd471aff99318b64eb9ac42a437e4dbde3 [file] [log] [blame]
Brian Osman7c979f52019-02-12 13:27:51 -05001/*
2* Copyright 2019 Google LLC
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
8#ifndef SkParticleEffect_DEFINED
9#define SkParticleEffect_DEFINED
10
Brian Osmand46cb972019-09-12 16:25:52 -040011#include "include/core/SkColor.h"
12#include "include/core/SkPoint.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkRefCnt.h"
Brian Osmanfe491632019-07-25 15:14:50 -040014#include "include/core/SkString.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "include/private/SkTArray.h"
Brian Osmanfe491632019-07-25 15:14:50 -040016#include "include/private/SkTemplates.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "include/utils/SkRandom.h"
Brian Osmanfe491632019-07-25 15:14:50 -040018#include "modules/particles/include/SkParticleData.h"
Brian Osmanfe491632019-07-25 15:14:50 -040019
20#include <memory>
Brian Osman7c979f52019-02-12 13:27:51 -050021
Brian Osman7c979f52019-02-12 13:27:51 -050022class SkCanvas;
Brian Osman2aa85df2019-08-30 10:59:47 -040023class SkFieldVisitor;
24class SkParticleBinding;
Brian Osman543d2e22019-02-15 14:29:38 -050025class SkParticleDrawable;
Brian Osmanfe491632019-07-25 15:14:50 -040026class SkParticleExternalValue;
27
28namespace SkSL {
29 struct ByteCode;
Brian Osmanfe491632019-07-25 15:14:50 -040030}
31
Brian Osman7c979f52019-02-12 13:27:51 -050032class SkParticleEffectParams : public SkRefCnt {
33public:
Brian Osmanfe491632019-07-25 15:14:50 -040034 SkParticleEffectParams();
35
Brian Osmand46cb972019-09-12 16:25:52 -040036 // Maximum number of particles per instance of the effect
37 int fMaxCount;
Brian Osman7c979f52019-02-12 13:27:51 -050038
Brian Osman3da607e2019-07-26 15:11:46 -040039 // What is drawn for each particle? (Image, shape, sprite sheet, etc.)
40 // See SkParticleDrawable::Make*
Brian Osman543d2e22019-02-15 14:29:38 -050041 sk_sp<SkParticleDrawable> fDrawable;
Brian Osman7c979f52019-02-12 13:27:51 -050042
Brian Osmand46cb972019-09-12 16:25:52 -040043 // Particle behavior is driven by two chunks of SkSL code. Effect functions are defined in
44 // fEffectCode, and get a mutable Effect struct:
Brian Osman3da607e2019-07-26 15:11:46 -040045 //
Brian Osmand46cb972019-09-12 16:25:52 -040046 // struct Effect {
47 // float age;
48 // float lifetime;
49 // int loop;
50 // float rate;
51 // int burst; // Set to trigger a burst of particles.
52 //
53 // // Everything below this line controls the state of the effect, which is also the
54 // // default values for new particles.
55 // float2 pos = { 0, 0 }; // Local position
Brian Osman3da607e2019-07-26 15:11:46 -040056 // float2 dir = { 0, -1 }; // Heading. Should be a normalized vector.
57 // float scale = 1; // Size, normalized relative to the drawable's native size
58 // float2 vel = { 0, 0 }; // Linear velocity, in (units / second)
59 // float spin = 0; // Angular velocity, in (radians / second)
60 // float4 color = { 1, 1, 1, 1 }; // RGBA color
61 // float frame = 0; // Normalized sprite index for multi-frame drawables
62 // };
63 //
Brian Osmand46cb972019-09-12 16:25:52 -040064 // Particle functions are defined in fParticleCode, and get a mutable Particle struct, as well
65 // as a uniform copy of the current Effect, named 'effect'.
Brian Osman3da607e2019-07-26 15:11:46 -040066 //
Brian Osmand46cb972019-09-12 16:25:52 -040067 // struct Particle {
68 // float age;
69 // float lifetime;
70 // float2 pos;
71 // float2 dir;
72 // float scale;
73 // float2 vel;
74 // float spin;
75 // float4 color;
76 // float frame;
77 // };
78 //
79 // All functions have access to a global variable named 'rand'. Every read of 'rand' returns a
80 // random floating point value in [0, 1). For particle functions, the state is rewound after
81 // each update, so calls to 'rand' will return consistent values from one update to the next.
82 //
83 // Finally, there is one global uniform values available, 'dt'. This is a floating point
84 // number of seconds that have elapsed since the last update.
85 //
86 // Effect code should define two functions:
87 //
88 // 'void effectSpawn(inout Effect e)' is called when an instance of the effect is first
89 // created, and again at every loop point (if the effect is played with the looping flag).
90 //
91 // 'void effectUpdate(inout Effect e)' is called once per update to adjust properties of the
92 // effect (ie emitter).
93 //
94 // Particle code should also define two functions:
Brian Osman3da607e2019-07-26 15:11:46 -040095 //
96 // 'void spawn(inout Particle p)' is called once for each particle when it is first created,
97 // to set initial values. At a minimum, this should set 'lifetime' to the number of seconds
Brian Osmand46cb972019-09-12 16:25:52 -040098 // that the particle will exist. Other parameters will will get default values from the effect.
Brian Osman3da607e2019-07-26 15:11:46 -040099 //
100 // 'void update(inout Particle p)' is called for each particle on every call to the running
101 // SkParticleEffect's update() method. It can animate any of the particle's values. Note that
102 // the 'lifetime' field has a different meaning in 'update', and should not be used or changed.
Brian Osmand46cb972019-09-12 16:25:52 -0400103
104 SkString fEffectCode;
105 SkString fParticleCode;
Brian Osmanfe491632019-07-25 15:14:50 -0400106
Brian Osman3da607e2019-07-26 15:11:46 -0400107 // External objects accessible by the effect's SkSL code. Each binding is a name and particular
108 // kind of object. See SkParticleBinding::Make* for details.
Brian Osmanfe491632019-07-25 15:14:50 -0400109 SkTArray<sk_sp<SkParticleBinding>> fBindings;
Brian Osman7c979f52019-02-12 13:27:51 -0500110
111 void visitFields(SkFieldVisitor* v);
Brian Osmanfe491632019-07-25 15:14:50 -0400112
113private:
114 friend class SkParticleEffect;
115
116 // Cached
Brian Osmand46cb972019-09-12 16:25:52 -0400117 struct Program {
118 std::unique_ptr<SkSL::ByteCode> fByteCode;
119 SkTArray<std::unique_ptr<SkParticleExternalValue>> fExternalValues;
120 };
121
122 Program fEffectProgram;
123 Program fParticleProgram;
Brian Osmanfe491632019-07-25 15:14:50 -0400124
125 void rebuild();
Brian Osman7c979f52019-02-12 13:27:51 -0500126};
127
128class SkParticleEffect : public SkRefCnt {
129public:
Brian Osman5c1f8eb2019-02-14 14:49:55 -0500130 SkParticleEffect(sk_sp<SkParticleEffectParams> params, const SkRandom& random);
Brian Osman7c979f52019-02-12 13:27:51 -0500131
Kevin Lubick269fe892019-03-06 09:32:55 -0500132 void start(double now, bool looping = false);
Kevin Lubick269fe892019-03-06 09:32:55 -0500133 void update(double now);
Brian Osman7c979f52019-02-12 13:27:51 -0500134 void draw(SkCanvas* canvas);
135
Brian Osmand46cb972019-09-12 16:25:52 -0400136 bool isAlive() const { return fState.fAge >= 0 && fState.fAge <= 1; }
Brian Osmanb77d5022019-03-06 11:08:48 -0500137 int getCount() const { return fCount; }
Brian Osman7c979f52019-02-12 13:27:51 -0500138
Brian Osman2aa85df2019-08-30 10:59:47 -0400139 static void RegisterParticleTypes();
140
Brian Osman7c979f52019-02-12 13:27:51 -0500141private:
142 void setCapacity(int capacity);
143
Brian Osman7c979f52019-02-12 13:27:51 -0500144 sk_sp<SkParticleEffectParams> fParams;
Brian Osman7c979f52019-02-12 13:27:51 -0500145
Brian Osman5c1f8eb2019-02-14 14:49:55 -0500146 SkRandom fRandom;
147
148 bool fLooping;
Brian Osman7c979f52019-02-12 13:27:51 -0500149 int fCount;
150 double fLastTime;
151 float fSpawnRemainder;
152
Brian Osmand46cb972019-09-12 16:25:52 -0400153 // Effect-associated values exposed to script. They are some mix of uniform and inout,
154 // depending on whether we're executing per-feffect or per-particle scripts.
155 struct EffectState {
156 float fDeltaTime;
157
158 // Above this line is always uniform. Below is uniform for particles, inout for effect.
159
160 float fAge;
161 float fLifetime;
162 int fLoopCount;
163 float fRate;
164 int fBurst;
165
166 // Properties that determine default values for new particles
167 SkPoint fPosition;
168 SkVector fHeading;
169 float fScale;
170 SkVector fVelocity;
171 float fSpin;
172 SkColor4f fColor;
173 float fFrame;
174 };
175 EffectState fState;
176
Brian Osmanfe491632019-07-25 15:14:50 -0400177 SkParticles fParticles;
178 SkAutoTMalloc<SkRandom> fStableRandoms;
Brian Osman7c979f52019-02-12 13:27:51 -0500179
180 // Cached
181 int fCapacity;
182};
183
184#endif // SkParticleEffect_DEFINED