//PLEASE NOTE: The ParticleEmitter class functions have changed since this tutorial //after I reorganized some things for the SIMD update loop. The final code for that //is linked in the optimization section. enum ParticleFacingType { ParticleFacing_2D_Billboard, ParticleFacing_3D_Billboard }; struct ParticleEmitterDepthSettings { ParticleEmitterDepthSettings() { UsesDepthSoftening = false; DepthFadeDistance = 1.0f; DepthFadePower = 1.0f; } bool UsesDepthSoftening; float DepthFadeDistance; float DepthFadePower; }; struct ParticleEmitterTextureAnimation { ParticleEmitterTextureAnimation() { IsAnimated = false; RandomizeInitialFrame = false; FrameCountX = 0; FrameCountY = 0; FramesPerSecond = 0; IsAnimatedForTextureIndex[0] = false; IsAnimatedForTextureIndex[1] = false; IsAnimatedForTextureIndex[2] = false; FrameTimeVariance = 0.0f; } bool IsAnimated; bool RandomizeInitialFrame; uint32 FrameCountX; uint32 FrameCountY; float FramesPerSecond; float FrameTimeVariance; bool IsAnimatedForTextureIndex[3]; }; enum ParticleBlendMode { ParticleBlendMode_AlphaBlend = 0, ParticleBlendMode_Additive, ParticleBlendMode_Multiply, ParticleBlendMode_Multiply2x, ParticleBlendMode_Subtract }; struct ParticleEmitterWideUpdates { float rotationalVelocity; Vector2 uvScrollDelta[3]; Vector3 particleUp; Vector3 particleRight; Vector3 particleForward; }; class ParticleEmitter { public: ParticleEmitter(); ~ParticleEmitter(); void OnFree(); void Initialize(uint32_t maxParticles, uint32 poolId); void Render(ID3D11DeviceContext *deviceContext, ParticleVertexBuffer *managedBuffer); void Update(ParticleVertexBuffer *managedBuffer, float deltaTime, const Vector3 &cameraDirection, const Vector3 &cameraPosition); void SetShaderParameters(ID3D11DeviceContext* deviceContext, ShaderParams &inputParams); void SetTexture(Texture *texture, uint32 index) { mTextures[index] = texture; } void SetMaterial(MaterialInstance *material) { mMaterial = material; } float GetDistanceFromCamera() { return mDistanceFromCamera; } bool IsInitialized() { return mInitialized; } bool IsComplete(); void Start(); void Stop(); ParticleBlendMode GetBlendMode() { return mBlendMode; } void SetPosition(Vector3 position) { mPosition = position; } private: void CleanUp(); void UpdateParticle(Particle *particle, ParticleVertexBuffer *managedBuffer, float deltaTime, const ParticleEmitterWideUpdates &particleUpdates); void UpdateParticles(Particle *particle[4], ParticleVertexBuffer *managedBuffer, float deltaTime, const ParticleEmitterWideUpdates &particleUpdates); uint32 mPoolId; bool mInitialized; bool mShouldEmit; bool mLoop; Vector3 mPosition; Vector3 mRotation; float mDistanceFromCamera; Vector3 mSpawnArea; AnimatedValue mColorMultiplier; Vector4 mColorVariance; AnimatedValue mScale; float mScaleVariance; AnimatedValue mVelocity; AnimatedValue mVelocityOverLifetime; Vector3 mVelocityVariance; Vector3 mGravity; AnimatedValue mRotationalVelocity; float mRotationVariance; float mRotationRateVariance; AnimatedValue mMaterialIntensity; float mMaterialIntensityVariance; AnimatedValue mEmissionPerSecond; float mEmitterLifeTime; float mEmitterCurrentLife; float mParticleLifeTime; float mParticleLifeTimeVariance; ParticleBlendMode mBlendMode; ParticleFacingType mFacingType; ParticleEmitterDepthSettings mDepthSettings; AnimatedValue mUVScroll[3]; Vector2 mUVScrollOffsets[3]; Vector2 mUVScrollVariance[3]; Texture *mTextures[3]; ParticleEmitterTextureAnimation mTextureAnimation; uint32_t mMaxParticles; uint32 mMinActiveParticles; float mPartialParticle; MaterialInstance *mMaterial; DynamicArray mParticles; uint32 mStartVert; uint32 mEndVert; };