/// <summary> /// パーティクルの生成位置に利用するメッシュターゲット /// </summary> /// <param name="target">メッシュターゲット</param> /// <param name="particleCount">頂点ごとのパーティクル数</param> public void EmitWithMesh(MeshFilter filter, int particleCount, float delay = 0) { Vector3[] vertices = filter.mesh.vertices; Matrix4x4 m = filter.transform.localToWorldMatrix; for (int i = 0; i < vertices.Length; i++) { vertices[i] = m.MultiplyPoint(CurlParticleUtility.GetRandomVector(vertices[i], _randomRange)); } EmitWithVertices(vertices, particleCount, delay); }
/// <summary> /// パーティクルをエミットする /// </summary> /// <param name="p">パーティクル設定</param> /// <param name="count">パーティクル数</param> public void Emit(ParticleParam p, int count) { if (!_isInitialized) { Initialize(); } _computeShader.SetBuffer(_emitKernel, _particlesId, _particlesBuffer); _computeShader.SetBuffer(_emitKernel, _particlePoolId, _particlePoolBuffer); _computeShader.SetVector(_positionId, CurlParticleUtility.GetRandomVector(p.Position, _randomRange)); _computeShader.SetVector(_colorId, p.Color); _computeShader.SetFloat(_minLifeTimeId, _minLifeTime); _computeShader.SetFloat(_maxLifeTimeId, _maxLifeTime); _computeShader.SetFloat(_delayId, p.Delay); _computeShader.SetFloat(_scaleId, 1.0f); _computeShader.SetFloat(_baseScaleId, _baseScale); int poolSize = GetParticlePoolSize() / 8; if (poolSize <= 0) { return; } int countSize = count / 8; int size = Mathf.Min(countSize, poolSize); _computeShader.Dispatch(_emitKernel, size, 1, 1); float lifeTime = _maxLifeTime + p.Delay; if (lifeTime > _lifeTime) { _lifeTime = lifeTime; } Activate(); }
/// <summary> /// Reset particles. /// </summary> /// <param name="paramList">Params for reseting.</param> /// <param name="particleCount">Count per param.</param> private void ResetParticles(ParticleParam[] paramList, int particleCount) { float maxLifeTime = float.MinValue; int pidx = 0; for (int i = 0; i < _particles.Length; i++) { pidx = i / particleCount; if (pidx < paramList.Length) { _particles[i].active = true; _particles[i].position = CurlParticleUtility.GetRandomVector(paramList[pidx].Position, _randomRange); _particles[i].delay = paramList[pidx].Delay; _particles[i].color = paramList[pidx].Color; _particles[i].scale = 1f; _particles[i].time = 0; _particles[i].liefTime = Random.Range(_minLifeTime, _maxLifeTime); _particles[i].velocity = Vector3.zero; float lifetime = _particles[i].liefTime + _particles[i].delay; if (lifetime > maxLifeTime) { maxLifeTime = lifetime; } } else { _particles[i].active = false; _particles[i].liefTime = 0; } } _lifeTime = maxLifeTime; _particlesBuffer.SetData(_particles); }
/// <summary> /// Initialize the particle. /// </summary> private void Initialize() { if (_isInitialized) { return; } _isInitialized = true; // Propety to id. { _useFakeId = Shader.PropertyToID("_UseFake"); _octavesId = Shader.PropertyToID("_Octaves"); _frequencyId = Shader.PropertyToID("_Frequency"); _pId = Shader.PropertyToID("_P"); _noiseScalesId = Shader.PropertyToID("_NoiseScales"); _noiseGainId = Shader.PropertyToID("_NoiseGain"); _risingForceId = Shader.PropertyToID("_RisingForce"); _timeId = Shader.PropertyToID("_Time"); _plumeBaseId = Shader.PropertyToID("_PlumeBase"); _plumeHeightId = Shader.PropertyToID("_PlumeHeight"); _plumeCeilingId = Shader.PropertyToID("_PlumeCeiling"); _ringRadiusId = Shader.PropertyToID("_RingRadius"); _ringMagnitudeId = Shader.PropertyToID("_RingMagnitude"); _ringFalloffId = Shader.PropertyToID("_RingFalloff"); _ringSpeedId = Shader.PropertyToID("_RingSpeed"); _ringPerSecondId = Shader.PropertyToID("_RingPerSecond"); _curlNoiseIntencityId = Shader.PropertyToID("_CurlNoiseIntencity"); _speedFactorId = Shader.PropertyToID("_SpeedFactor"); _particlesId = Shader.PropertyToID("_Particles"); _deadListId = Shader.PropertyToID("_DeadList"); _deltaTimeId = Shader.PropertyToID("_DeltaTime"); _idOffsetId = Shader.PropertyToID("_IdOffset"); _particlePoolId = Shader.PropertyToID("_ParticlePool"); _positionId = Shader.PropertyToID("_Position"); _colorId = Shader.PropertyToID("_Color"); _minLifeTimeId = Shader.PropertyToID("_MinLifeTime"); _maxLifeTimeId = Shader.PropertyToID("_MaxLifeTime"); _delayId = Shader.PropertyToID("_Delay"); _scaleId = Shader.PropertyToID("_Scale"); _baseScaleId = Shader.PropertyToID("_BaseScale"); } int seed = Mathf.Clamp(_curlParticleProfile.Seed, 0, 2 << 30 - 1); _p = CurlParticleUtility.CreateGrid(seed); _particles = GenerateParticles(); // Generate combined mesh. { _particleNumPerMesh = CurlParticleUtility.MAX_VERTEX_NUM / _mesh.vertexCount; _meshNum = (int)Mathf.Ceil((float)_particleNumLimit / _particleNumPerMesh); _material = new Material(_shader); for (int i = 0; i < _meshNum; i++) { MaterialPropertyBlock block = new MaterialPropertyBlock(); block.SetFloat(_idOffsetId, _particleNumPerMesh * i); _propertyBlocks.Add(block); } _combinedMesh = CurlParticleUtility.CreateCombinedMesh(_mesh, _particleNumPerMesh); } // Generate ComputeBuffer { _particlesBuffer = new ComputeBuffer(_particleNumLimit, Marshal.SizeOf(typeof(Particle)), ComputeBufferType.Default); _particlePoolBuffer = new ComputeBuffer(_particleNumLimit, sizeof(int), ComputeBufferType.Append); _particlePoolBuffer.SetCounterValue(0); _particleArgsBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.IndirectArguments); _particleArgs = new int[] { 0 }; } // Kernel info. { _initKernel = _computeShader.FindKernel("Init"); _stopKernel = _computeShader.FindKernel("Stop"); _emitKernel = _computeShader.FindKernel("Emit"); _curlnoiseKernel = _computeShader.FindKernel("CurlNoiseMain"); } DispatchInit(); }