/// <summary> /// 初期化 /// </summary> protected virtual void Initialize() { particleNum = (particleMax / THREAD_NUM_X) * THREAD_NUM_X; emitNum = (emitMax / THREAD_NUM_X) * THREAD_NUM_X; //Debug.Log("particleNum " + particleNum + " emitNum " + emitNum + " THREAD_NUM_X " + THREAD_NUM_X); particleBuffer = new ComputeBuffer(particleNum, Marshal.SizeOf(typeof(T)), ComputeBufferType.Default); particleActiveBuffer = new ComputeBuffer(particleNum, Marshal.SizeOf(typeof(int)), ComputeBufferType.Append); particleActiveBuffer.SetCounterValue(0); particlePoolBuffer = new ComputeBuffer(particleNum, Marshal.SizeOf(typeof(int)), ComputeBufferType.Append); particlePoolBuffer.SetCounterValue(0); particleActiveCountBuffer = new ComputeBuffer(4, Marshal.SizeOf(typeof(int)), ComputeBufferType.IndirectArguments); particlePoolCountBuffer = new ComputeBuffer(4, Marshal.SizeOf(typeof(int)), ComputeBufferType.IndirectArguments); particlePoolCountBuffer.SetData(particleCounts); initKernel = cs.FindKernel("Init"); emitKernel = cs.FindKernel("Emit"); updateKernel = cs.FindKernel("Update"); cspropid_Particles = ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._Particles); cspropid_DeadList = ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._DeadList); cspropid_ActiveList = ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._ActiveList); cspropid_ParticlePool = ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._ParticlePool); cspropid_EmitNum = ShaderDefines.GetIntPropertyID(ShaderDefines.IntID._EmitNum); //Debug.Log("initKernel " + initKernel + " emitKernel " + emitKernel + " updateKernel " + updateKernel); cs.SetBuffer(initKernel, cspropid_Particles, particleBuffer); cs.SetBuffer(initKernel, cspropid_DeadList, particlePoolBuffer); cs.Dispatch(initKernel, particleNum / THREAD_NUM_X, 1, 1); isInitialized = true; }
// 地形描画 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); }
// 更新処理 public void Update(ComputeShader _computeShader, Camera _camera, int _numParticles, ComputeBuffer _particlesBuffer, ComputeBuffer _activeParticlesBuffer) { // 視錘台カリングを行うカーネル int kernel = _computeShader.FindKernel("FrustumCulling"); // 視錘台の計算 CalculateFrustumPlanes(_camera.projectionMatrix * _camera.worldToCameraMatrix, ref m_planes); // 視錘台の法線を分解 for (int i = 0; i < 4; i++) { Debug.DrawRay(_camera.transform.position, m_planes[i].normal * 10f, Color.yellow); m_normalsFloat[i + 0] = m_planes[i].normal.x; m_normalsFloat[i + 4] = m_planes[i].normal.y; m_normalsFloat[i + 8] = m_planes[i].normal.z; } // バッファのカウンターをリセット m_inViewParticlesBuffer.SetCounterValue(0); // カメラの座標 Vector3 cameraPosition = _camera.transform.position; // 変数を設定 _computeShader.SetInt(ShaderDefines.GetIntPropertyID(ShaderDefines.IntID._numParticles), _numParticles); _computeShader.SetFloats(ShaderDefines.GetVectorPropertyID(ShaderDefines.VectorID._cameraPosition), cameraPosition.x, cameraPosition.y, cameraPosition.z); _computeShader.SetFloats(ShaderDefines.GetVectorPropertyID(ShaderDefines.VectorID._cameraFrustumNormals), m_normalsFloat); // バッファを設定 _computeShader.SetBuffer(kernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._particlesBuffer), _particlesBuffer); _computeShader.SetBuffer(kernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._activeParticlesBuffer), _activeParticlesBuffer); _computeShader.SetBuffer(kernel, ShaderDefines.GetBufferPropertyID(ShaderDefines.BufferID._inViewParticlesBuffer), m_inViewParticlesBuffer); // カーネルを実行 _computeShader.Dispatch(kernel, Mathf.CeilToInt((float)_activeParticlesBuffer.count / NUM_THREAD_X), 1, 1); // バッファにデータを渡す m_inViewCountsBuffer.SetData(m_inViewCounts); // 視界内のパーティクル数を取得 ComputeBuffer.CopyCount(m_inViewParticlesBuffer, m_inViewCountsBuffer, 4); }