Example #1
0
        internal void Update(GameTime gameTime)
        {
            if (gameTime.TotalGameTime < _nextUpdate)
            {
                return;
            }

            _nextUpdate = gameTime.TotalGameTime + TimeSpan.FromSeconds(1 / 30.0f);

            if (_initialDelay > 0)
            {
                _initialDelay -= 1;
                return;
            }

            if (Definition.SystemLifetime != 0 && _timer > Definition.SystemLifetime)
            {
                State = ParticleSystemState.Finished;
            }

            for (var i = 0; i < _particles.Length; i++)
            {
                ref var particle = ref _particles[i];

                if (particle.Dead)
                {
                    continue;
                }

                if (particle.Timer > particle.Lifetime)
                {
                    particle.Dead = true;
                    _deadList.Add(i);
                }
            }
        private void TransformParticleSystem(ParticleSystem particles, Transform anchorTransform, float forward, float height, float rotationYModifier)
        {
            if (particles == null || !IsFirstPerson || Intensity == 0.0f)
            {
                return;
            }
            Vector3 pos = anchorTransform.position;
            Vector3 anchorForward;
            bool    inNullZone = false;
            int     count      = Physics.OverlapSphereNonAlloc(anchorTransform.position, 0.001f, WeatherMakerScript.tempColliders);

            for (int i = 0; i < count; i++)
            {
                WeatherMakerNullZoneScript script = WeatherMakerScript.tempColliders[i].GetComponent <WeatherMakerNullZoneScript>();
                if (script != null && script.NullZoneActive && (script.CurrentMask & (int)NullZoneRenderMask.Precipitation) == 0)
                {
                    inNullZone = true;
                    break;
                }
            }

            // update particle system state for this transform
            ParticleSystemState state;
            Dictionary <ParticleSystem, ParticleSystemState> stateDict;

            if (!states.TryGetValue(anchorTransform, out stateDict))
            {
                states[anchorTransform] = stateDict = new Dictionary <ParticleSystem, ParticleSystemState>();
            }
            if (!stateDict.TryGetValue(particles, out state))
            {
                stateDict[particles] = state = new ParticleSystemState {
                    PreviousPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue)
                };
            }

            // if we were forced to world space from local space, go back to local space
            if (state.WasChangedFromLocalToWorldSpace)
            {
                state.WasChangedFromLocalToWorldSpace = false;
                var main = particles.main;
                main.simulationSpace = ParticleSystemSimulationSpace.Local;
            }

            if (particles.main.simulationSpace == ParticleSystemSimulationSpace.Local && !inNullZone)
            {
                if (WeatherMakerWindScript.Instance != null && WeatherMakerWindScript.Instance.CurrentWindVelocity != Vector3.zero)
                {
                    // as wind intensity increases, move forward and height of the system more inline with the player so it blows in their face
                    anchorForward = -(WeatherMakerWindScript.Instance.CurrentWindVelocity.normalized);
                    pos          += (anchorForward * Mathf.Lerp(forward, Mathf.Max(forward, 10.0f), WeatherMakerWindScript.Instance.WindZone.windMain * 4.0f));
                }
                else
                {
                    // can't move against the transform forward because it will look awful as player rotates
                    // just set on top of player directly
                    anchorForward = Vector3.zero;
                    pos.y        += height;
                }
            }
            else
            {
                if (inNullZone)
                {
                    // in null zone, put the precipitation right above the player at a distance
                    forward = 0.0f;
                    float standardHeight = (particles == ParticleSystem ? Height : (particles == MistParticleSystem ? MistHeight : SecondaryHeight));
                    height = Mathf.Max(NullZoneHeight, standardHeight);

                    var main = particles.main;
                    if (main.simulationSpace == ParticleSystemSimulationSpace.Local)
                    {
                        // mark this so we can switch back to local space when the null zone is exited
                        state.WasChangedFromLocalToWorldSpace = true;

                        // must use world space, looks funny swimming under water or moving in a building and moving with the player
                        main.simulationSpace = ParticleSystemSimulationSpace.World;
                    }
                }

                // position up and forward based on parameters
                anchorForward = anchorTransform.forward;
                pos.x        += anchorForward.x * forward;
                pos.y        += height;
                pos.z        += anchorForward.z * forward;
            }

            // if new state or a long distance, just snap the particle system into place
            if (Vector3.Distance(pos, state.PreviousPosition) > 100.0f)
            {
                particles.transform.position = state.PreviousPosition = pos;
            }
            else
            {
                // go to new position quickly but not instantly
                particles.transform.position = state.PreviousPosition = (FirstPersonFollowSpeed <= 0.0f ? pos : Vector3.Slerp(state.PreviousPosition, pos, Time.deltaTime * FirstPersonFollowSpeed));
            }
            if (particles.shape.mesh != null)
            {
                Vector3 angles = particles.transform.rotation.eulerAngles;
                particles.transform.rotation = Quaternion.Euler(angles.x, anchorTransform.rotation.eulerAngles.y * rotationYModifier, angles.z);
            }
        }
Example #3
0
        protected override void Start()
        {
            base.Start();

            _particleEffect = ContentManager.GetEffect <ParticleEffect>();

            _velocityType = VelocityTypeUtility.GetImplementation(Definition.VelocityType);
            _volumeType   = VolumeTypeUtility.GetImplementation(Definition.VolumeType);

            var texturePath = Path.Combine("Art", "Textures", Definition.ParticleName);

            _texture = ContentManager.Load <Texture>(texturePath, uploadBatch: null);

            var blendState = GetBlendState(Definition.Shader);

            _pipelineStateHandle = new EffectPipelineState(
                RasterizerStateDescription.CullBackSolid,
                DepthStencilStateDescription.DepthRead,
                blendState)
                                   .GetHandle();

            _initialDelay = Definition.InitialDelay.GetRandomInt();

            _startSizeRate = Definition.StartSizeRate.GetRandomFloat();
            _startSize     = 0;

            _colorKeyframes = new List <ParticleColorKeyframe>();

            if (Definition.Color1 != null)
            {
                _colorKeyframes.Add(new ParticleColorKeyframe(Definition.Color1));
            }

            void addColorKeyframe(RgbColorKeyframe keyframe, RgbColorKeyframe previous)
            {
                if (keyframe != null && keyframe.Time > previous.Time)
                {
                    _colorKeyframes.Add(new ParticleColorKeyframe(keyframe));
                }
            }

            addColorKeyframe(Definition.Color2, Definition.Color1);
            addColorKeyframe(Definition.Color3, Definition.Color2);
            addColorKeyframe(Definition.Color4, Definition.Color3);
            addColorKeyframe(Definition.Color5, Definition.Color4);
            addColorKeyframe(Definition.Color6, Definition.Color5);
            addColorKeyframe(Definition.Color7, Definition.Color6);
            addColorKeyframe(Definition.Color8, Definition.Color7);

            var maxParticles = CalculateMaxParticles();

            _particles = new Particle[maxParticles];
            for (var i = 0; i < _particles.Length; i++)
            {
                _particles[i].Dead = true;
            }

            _deadList = new List <int>();
            _deadList.AddRange(Enumerable.Range(0, maxParticles));

            _vertexBuffer = DynamicBuffer <ParticleVertex> .CreateArray(
                GraphicsDevice,
                maxParticles * 4,
                BufferUsageFlags.None);

            _vertices = new ParticleVertex[_vertexBuffer.ElementCount];

            _indexBuffer = CreateIndexBuffer(GraphicsDevice, maxParticles);

            State = ParticleSystemState.Active;
        }
Example #4
0
        public ParticleSystem(
            ContentManager contentManager,
            FXParticleSystemTemplate template,
            GetMatrixReferenceDelegate getWorldMatrix)
        {
            Template = template;

            _getWorldMatrix = getWorldMatrix;

            var maxParticles = CalculateMaxParticles();

            // If this system never emits any particles, there's no reason to fully initialise it.
            if (maxParticles == 0)
            {
                return;
            }

            _graphicsDevice = contentManager.GraphicsDevice;

            _renderItemConstantsBufferVS = AddDisposable(new ConstantBuffer <MeshShaderResources.RenderItemConstantsVS>(_graphicsDevice));

            _velocityType = Template.EmissionVelocity;
            _volumeType   = Template.EmissionVolume;

            var texturePath = Path.Combine("Art", "Textures", Template.ParticleName);
            var texture     = contentManager.Load <Texture>(texturePath);

            _particleResourceSet = AddDisposable(contentManager.ShaderResources.Particle.CreateParticleResoureSet(
                                                     _renderItemConstantsBufferVS.Buffer,
                                                     texture));

            _shaderSet = contentManager.ShaderResources.Particle.ShaderSet;
            _pipeline  = contentManager.ShaderResources.Particle.GetCachedPipeline(Template.Shader);

            _initialDelay = Template.InitialDelay.GetRandomInt();

            _startSizeRate = Template.StartSizeRate.GetRandomFloat();
            _startSize     = 0;

            _colorKeyframes = new List <ParticleColorKeyframe>();

            var colors = Template.Colors;

            if (colors.Color1 != null)
            {
                _colorKeyframes.Add(new ParticleColorKeyframe(colors.Color1));
            }

            void addColorKeyframe(RgbColorKeyframe keyframe, RgbColorKeyframe previous)
            {
                if (keyframe != null && keyframe.Time > previous.Time)
                {
                    _colorKeyframes.Add(new ParticleColorKeyframe(keyframe));
                }
            }

            addColorKeyframe(colors.Color2, colors.Color1);
            addColorKeyframe(colors.Color3, colors.Color2);
            addColorKeyframe(colors.Color4, colors.Color3);
            addColorKeyframe(colors.Color5, colors.Color4);
            addColorKeyframe(colors.Color6, colors.Color5);
            addColorKeyframe(colors.Color7, colors.Color6);
            addColorKeyframe(colors.Color8, colors.Color7);

            _particles = new Particle[maxParticles];
            for (var i = 0; i < _particles.Length; i++)
            {
                _particles[i].AlphaKeyframes = new List <ParticleAlphaKeyframe>();
                _particles[i].Dead           = true;
            }

            _deadList = new List <int>();
            _deadList.AddRange(Enumerable.Range(0, maxParticles));

            var numVertices = maxParticles * 4;

            _vertexBuffer = AddDisposable(contentManager.GraphicsDevice.ResourceFactory.CreateBuffer(
                                              new BufferDescription(
                                                  (uint)(ParticleShaderResources.ParticleVertex.VertexDescriptor.Stride * maxParticles * 4),
                                                  BufferUsage.VertexBuffer | BufferUsage.Dynamic)));

            _vertices = new ParticleShaderResources.ParticleVertex[numVertices];

            _indexBuffer = AddDisposable(CreateIndexBuffer(
                                             contentManager.GraphicsDevice,
                                             maxParticles,
                                             out _numIndices));

            State = ParticleSystemState.Active;

            _beforeRender = (cl, context) =>
            {
                // Only update once we know this particle system is visible on screen.
                Update(cl, context.GameTime);

                if (_worldMatrixChanged)
                {
                    _renderItemConstantsBufferVS.Update(cl);
                }

                cl.SetGraphicsResourceSet(1, _particleResourceSet);

                cl.SetVertexBuffer(0, _vertexBuffer);
            };
        }
Example #5
0
        public ParticleSystem(
            ContentManager contentManager,
            ParticleSystemDefinition definition,
            GetMatrixReferenceDelegate getWorldMatrix)
        {
            Definition = definition;

            _getWorldMatrix = getWorldMatrix;

            var maxParticles = CalculateMaxParticles();

            // If this system never emits any particles, there's no reason to fully initialise it.
            if (maxParticles == 0)
            {
                return;
            }

            _graphicsDevice = contentManager.GraphicsDevice;

            _particleMaterial = AddDisposable(new ParticleMaterial(contentManager, contentManager.EffectLibrary.Particle));

            _velocityType = VelocityTypeUtility.GetImplementation(Definition.VelocityType);
            _volumeType   = VolumeTypeUtility.GetImplementation(Definition.VolumeType);

            var texturePath = Path.Combine("Art", "Textures", Definition.ParticleName);
            var texture     = contentManager.Load <Texture>(texturePath);

            _particleMaterial.SetTexture(texture);

            var blendState = GetBlendState(Definition.Shader);

            _particleMaterial.PipelineState = new EffectPipelineState(
                RasterizerStateDescriptionUtility.DefaultFrontIsCounterClockwise,
                DepthStencilStateDescription.DepthOnlyLessEqualRead,
                blendState,
                RenderPipeline.GameOutputDescription);

            _initialDelay = Definition.InitialDelay.GetRandomInt();

            _startSizeRate = Definition.StartSizeRate.GetRandomFloat();
            _startSize     = 0;

            _colorKeyframes = new List <ParticleColorKeyframe>();

            if (Definition.Color1 != null)
            {
                _colorKeyframes.Add(new ParticleColorKeyframe(Definition.Color1));
            }

            void addColorKeyframe(RgbColorKeyframe keyframe, RgbColorKeyframe previous)
            {
                if (keyframe != null && keyframe.Time > previous.Time)
                {
                    _colorKeyframes.Add(new ParticleColorKeyframe(keyframe));
                }
            }

            addColorKeyframe(Definition.Color2, Definition.Color1);
            addColorKeyframe(Definition.Color3, Definition.Color2);
            addColorKeyframe(Definition.Color4, Definition.Color3);
            addColorKeyframe(Definition.Color5, Definition.Color4);
            addColorKeyframe(Definition.Color6, Definition.Color5);
            addColorKeyframe(Definition.Color7, Definition.Color6);
            addColorKeyframe(Definition.Color8, Definition.Color7);

            _particles = new Particle[maxParticles];
            for (var i = 0; i < _particles.Length; i++)
            {
                _particles[i].AlphaKeyframes = new List <ParticleAlphaKeyframe>();
                _particles[i].Dead           = true;
            }

            _deadList = new List <int>();
            _deadList.AddRange(Enumerable.Range(0, maxParticles));

            var numVertices = maxParticles * 4;

            _vertexBuffer = AddDisposable(contentManager.GraphicsDevice.ResourceFactory.CreateBuffer(
                                              new BufferDescription(
                                                  (uint)(ParticleVertex.VertexDescriptor.Stride * maxParticles * 4),
                                                  BufferUsage.VertexBuffer | BufferUsage.Dynamic)));

            _vertices = new ParticleVertex[numVertices];

            _indexBuffer = AddDisposable(CreateIndexBuffer(
                                             contentManager.GraphicsDevice,
                                             maxParticles,
                                             out _numIndices));

            State = ParticleSystemState.Active;
        }