1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #pragma once |
4 | |
5 | #include "BsCorePrerequisites.h" |
6 | #include "Image/BsPixelData.h" |
7 | #include "Utility/BsModule.h" |
8 | #include "Math/BsAABox.h" |
9 | #include "CoreThread/BsCoreThread.h" |
10 | #include "BsParticleSystem.h" |
11 | |
12 | namespace bs |
13 | { |
14 | class ParticleSet; |
15 | struct EvaluatedAnimationData; |
16 | |
17 | /** @addtogroup Particles-Internal |
18 | * @{ |
19 | */ |
20 | |
21 | /** |
22 | * Contains data resulting from a single frame of CPU particle simulation of a single particle system, used by all |
23 | * rendering modes. |
24 | */ |
25 | struct BS_CORE_EXPORT ParticleRenderData |
26 | { |
27 | /** Contains mapping from unsorted to sorted particle indices. */ |
28 | Vector<UINT32> indices; |
29 | |
30 | /** Total number of particles in the particle system. */ |
31 | UINT32 numParticles; |
32 | |
33 | /** Bounds of the particle system, in the system's simulation space. */ |
34 | AABox bounds; |
35 | }; |
36 | |
37 | /** |
38 | * Contains data used for rendering particles as billboards. Per-particle data is stored in a 2D square layout so it |
39 | * can be used for quickly initializing a texture. |
40 | */ |
41 | struct BS_CORE_EXPORT ParticleBillboardRenderData : ParticleRenderData |
42 | { |
43 | /** Contains particle positions in .xyz and 2D rotation in .w */ |
44 | PixelData positionAndRotation; |
45 | |
46 | /** Contains particle color in .xyz and transparency in .a. */ |
47 | PixelData color; |
48 | |
49 | /** Contains 2D particle size in .xy, frame index (used for animation) in .z. */ |
50 | PixelData sizeAndFrameIdx; |
51 | }; |
52 | |
53 | /** |
54 | * Contains data used for rendering particles as meshes. Per-particle data is stored in a 2D square layout so it |
55 | * can be used for quickly initializing a texture. |
56 | */ |
57 | struct BS_CORE_EXPORT ParticleMeshRenderData : ParticleRenderData |
58 | { |
59 | /** Contains particle positions in .xyz with .w unused. */ |
60 | PixelData position; |
61 | |
62 | /** Contains particle color in .xyz and transparency in .a. */ |
63 | PixelData color; |
64 | |
65 | /** Contains particle size in .xyz with .w unused. */ |
66 | PixelData size; |
67 | |
68 | /** Contains particle rotation in radians in .xyz with .w unused. */ |
69 | PixelData rotation; |
70 | }; |
71 | /** |
72 | * Contains information about a single particle about to be inserted into the GPU simulation. Matches the structure |
73 | * of the vertex buffer element used for injecting shader data into the simulation. |
74 | */ |
75 | struct GpuParticleVertex |
76 | { |
77 | Vector3 position; |
78 | float lifetime; |
79 | Vector3 velocity; |
80 | float invMaxLifetime; |
81 | Vector2 size; |
82 | float rotation; |
83 | Vector2 dataUV; |
84 | }; |
85 | |
86 | /** Extension of GpuParticle that contains data not required by the injection vertex buffer. */ |
87 | struct GpuParticle : GpuParticleVertex |
88 | { |
89 | /** Gets a version of this object suitable for upload to the injection vertex buffer. */ |
90 | GpuParticleVertex getVertex() const |
91 | { |
92 | GpuParticleVertex output; |
93 | output.position = position; |
94 | output.lifetime = (initialLifetime - lifetime) / initialLifetime; |
95 | output.velocity = velocity; |
96 | output.invMaxLifetime = 1.0f / initialLifetime; |
97 | output.size = size; |
98 | output.rotation = rotation; |
99 | output.dataUV = dataUV; |
100 | |
101 | return output; |
102 | } |
103 | |
104 | float initialLifetime; |
105 | }; |
106 | |
107 | /** Contains inputs to the GPU particle simulation as provided by the particle system manager. */ |
108 | struct BS_CORE_EXPORT ParticleGPUSimulationData |
109 | { |
110 | /** A set of the particles to be inserted into the simulation. */ |
111 | Vector<GpuParticle> particles; |
112 | }; |
113 | |
114 | /** Contains simulation data resulting from all particle systems, for a single frame. */ |
115 | struct ParticlePerFrameData |
116 | { |
117 | UnorderedMap<UINT32, ParticleRenderData*> cpuData; |
118 | UnorderedMap<UINT32, ParticleGPUSimulationData*> gpuData; |
119 | }; |
120 | |
121 | /** Keeps track of all active ParticleSystem%s and performs per-frame updates. */ |
122 | class BS_CORE_EXPORT ParticleManager final : public Module<ParticleManager> |
123 | { |
124 | struct Members; |
125 | public: |
126 | ParticleManager(); |
127 | ~ParticleManager(); |
128 | |
129 | /** |
130 | * Advances the simulation for all particle systems using the current frame time delta. Outputs a set of data |
131 | * that can be used for rendering & updating every active particle system. |
132 | */ |
133 | ParticlePerFrameData* update(const EvaluatedAnimationData& animData); |
134 | |
135 | private: |
136 | friend class ParticleSystem; |
137 | |
138 | /** Must be called by a ParticleSystem upon construction. */ |
139 | UINT32 registerParticleSystem(ParticleSystem* system); |
140 | |
141 | /** Must be called by a ParticleSystem before destruction. */ |
142 | void unregisterParticleSystem(ParticleSystem* system); |
143 | |
144 | /** |
145 | * Sorts the particles in the provided @p using the @p sortMode. Sorted particle indices are placed in the |
146 | * @p indices array which is expected to be pre-allocated with enough space to hold an index for each particle |
147 | * in a set. @p viewPoint is used as a reference point when using the Distance sort mode. |
148 | */ |
149 | void sortParticles(const ParticleSet& set, ParticleSortMode sortMode, const Vector3& viewPoint, UINT32* indices); |
150 | |
151 | Members* m; |
152 | |
153 | UINT32 mNextId = 1; |
154 | UnorderedSet<ParticleSystem*> mSystems; |
155 | |
156 | bool mPaused = false; |
157 | |
158 | // Worker threads |
159 | ParticlePerFrameData mSimulationData[CoreThread::NUM_SYNC_BUFFERS]; |
160 | |
161 | UINT32 mReadBufferIdx = 1; |
162 | UINT32 mWriteBufferIdx = 0; |
163 | |
164 | Signal mWorkerDoneSignal; |
165 | Mutex mMutex; |
166 | |
167 | UINT32 mNumActiveWorkers = 0; |
168 | bool mSwapBuffers = false; |
169 | }; |
170 | |
171 | /** @} */ |
172 | } |
173 | |