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); } }
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; }
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); }; }
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; }