// 初期化処理 private void Initialize() { // パーティクル数をスレッド数の倍数にする m_numParticles = Mathf.CeilToInt(_numMaxParticles / (float)THREAD_NUM_X) * THREAD_NUM_X; // エミット数をスレッド数の倍数にする m_numEmitParticles = Mathf.CeilToInt(_numMaxEmitParticles / (float)THREAD_NUM_X) * THREAD_NUM_X; // バッファを生成 m_particlesBuffer = new ComputeBuffer(m_numParticles, Marshal.SizeOf(typeof(GPUParticleData)), ComputeBufferType.Default); m_activeParticlesBuffer = new ComputeBuffer(m_numParticles, Marshal.SizeOf(typeof(int)), ComputeBufferType.Append); m_particlePoolBuffer = new ComputeBuffer(m_numParticles, Marshal.SizeOf(typeof(int)), ComputeBufferType.Append); m_activeParticleCountsBuffer = new ComputeBuffer(4, Marshal.SizeOf(typeof(int)), ComputeBufferType.IndirectArguments); m_particlePoolCountsBuffer = new ComputeBuffer(4, Marshal.SizeOf(typeof(int)), ComputeBufferType.IndirectArguments); // バッファにデータを渡す m_activeParticleCountsBuffer.SetData(m_particleCounts); m_particlePoolCountsBuffer.SetData(m_particleCounts); // カーネルを設定 m_initKernel = _computeShader.FindKernel("Init"); m_emitKernel = _computeShader.FindKernel("Emit"); m_updateKernel = _computeShader.FindKernel("Update"); // 変数を設定 _computeShader.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._gravity), _gravity); // バッファを設定 _computeShader.SetBuffer(m_initKernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._particlesBuffer), m_particlesBuffer); _computeShader.SetBuffer(m_initKernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._deadParticlesBuffer), m_particlePoolBuffer); // 初期化カーネルを実行 _computeShader.Dispatch(m_initKernel, m_numParticles / THREAD_NUM_X, 1, 1); }
// パーティクルの発生処理 public void EmitParticle(Vector3 _position) { // 使用できるパーティクル数を取得 ComputeBuffer.CopyCount(m_particlePoolBuffer, m_particlePoolCountsBuffer, 0); m_particlePoolCountsBuffer.GetData(m_particleCounts); m_particlePoolNum = m_particleCounts[0]; // エミット数未満ならエミット処理をしない if (m_particleCounts[0] < m_numEmitParticles) { return; } // 変数を設定 _computeShader.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._elapsedTime), Time.time); _computeShader.SetVector(ShaderDefines.GetVectorPropertyID(ShaderDefines.VectorID._position), _position); _computeShader.SetVector(ShaderDefines.GetVectorPropertyID(ShaderDefines.VectorID._range), _range); _computeShader.SetVector(ShaderDefines.GetVectorPropertyID(ShaderDefines.VectorID._minVelocity), _minVelocity); _computeShader.SetVector(ShaderDefines.GetVectorPropertyID(ShaderDefines.VectorID._maxVelocity), _maxVelocity); _computeShader.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._startScale), _startScale); _computeShader.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._endScale), _endScale); _computeShader.SetVector(ShaderDefines.GetVectorPropertyID(ShaderDefines.VectorID._color), _color); _computeShader.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._lifeTime), _lifeTime); // バッファを設定 _computeShader.SetBuffer(m_emitKernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._particlePoolBuffer), m_particlePoolBuffer); _computeShader.SetBuffer(m_emitKernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._particlesBuffer), m_particlesBuffer); // エミットカーネルを実行 _computeShader.Dispatch(m_emitKernel, m_numEmitParticles / THREAD_NUM_X, 1, 1); }
// 地形描画 void RenderTerrain() { // テクスチャを設定 _shaderMaterial.SetTexture(ShaderDefines.GetTexturePropertyID(ShaderDefines.TextureID._mainTexture), _texture); // 変数を設定 _shaderMaterial.SetInt(ShaderDefines.GetIntPropertyID(ShaderDefines.IntID._numVertices), _numVertices); _shaderMaterial.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._height), _height); // バッファの設定 _shaderMaterial.SetBuffer(ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._verticesBuffer), m_verticesBuffer); // 描画処理 Graphics.DrawMeshInstancedIndirect(_mesh, 0, _shaderMaterial, new Bounds(Vector3.zero, new Vector3(1000.0f, 1000.0f, 1000.0f)), m_argsBuffer); }
// 頂点の計算 void CalculateVertex() { // バッファを設定 _computeShader.SetBuffer(m_calculateKernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._verticesBuffer), m_verticesBuffer); // 変数を設定 _computeShader.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._fieldSize), FIELD_SIZE); _computeShader.SetInt(ShaderDefines.GetIntPropertyID(ShaderDefines.IntID._numVertices), _numVertices); _computeShader.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._distance), m_distance); _computeShader.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._height), _height); _computeShader.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._smoothness), _smoothness * _numVertices); _computeShader.SetVector(ShaderDefines.GetVectorPropertyID(ShaderDefines.VectorID._offset), new Vector2(_offsetX, _offsetY)); // カーネルの実行 _computeShader.Dispatch(m_calculateKernel, m_numThreadGroups, 1, m_numThreadGroups); }
// パーティクルの更新処理 private void UpdateParticle() { // バッファのカウンターをリセット m_activeParticlesBuffer.SetCounterValue(0); // 変数を設定 _computeShader.SetFloat(ShaderDefines.GetFloatPropertyID(ShaderDefines.FloatID._deltaTime), Time.deltaTime); // バッファを設定 _computeShader.SetBuffer(m_updateKernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._particlesBuffer), m_particlesBuffer); _computeShader.SetBuffer(m_updateKernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._deadParticlesBuffer), m_particlePoolBuffer); _computeShader.SetBuffer(m_updateKernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._activeParticlesBuffer), m_activeParticlesBuffer); // 更新カーネルを実行 _computeShader.Dispatch(m_updateKernel, m_numParticles / THREAD_NUM_X, 1, 1); // 使用中のパーティクル数を取得 ComputeBuffer.CopyCount(m_activeParticlesBuffer, m_activeParticleCountsBuffer, 0); }