baobao
12/14/2018 - 11:04 AM

[失敗例]コンピュートシェーダで大量の立方体を回す

using UnityEngine;

public class ComputeCubes : MonoBehaviour
{
    [SerializeField]
    private ComputeShader _computeShader;

    private ComputeBuffer _buffer;

    /// <summary>
    /// 生成個数
    /// </summary>
    private int _cubeCount = 640;

    /// <summary>
    /// キューブ参照
    /// </summary>
    private GameObject[] _cubes;

    /// <summary>
    /// 各キューブの角度を格納配列
    /// </summary>
    private float[] _angles;

    private int _mainKernel = 0;

    void Start()
    {
        _cubes = new GameObject[_cubeCount];
        _angles = new float[_cubeCount];
        for (int i = 0; i < _cubeCount; i++)
        {
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
            // 配置範囲
            float len = 20f;
            cube.transform.localPosition =
                new Vector3(Random.Range(-len, len), Random.Range(-len, len), Random.Range(-len, len));
            _cubes[i] = cube;
        }

        _buffer = new ComputeBuffer(_cubeCount, sizeof(float));
        _mainKernel = _computeShader.FindKernel("CSMain");
        _computeShader.SetBuffer(_mainKernel, "Result", _buffer);
    }

    void Update()
    {
        // 現在の角度をシェーダにpush
        for (int i = 0; i < _cubeCount; i++)
        {
            _computeShader.SetFloat("eulerAngleX", _angles[i]);
        }

        // GPU並列処理実行
        _computeShader.Dispatch(_mainKernel, 8, 1, 1);

        var data = new float[_cubeCount];
        // 更新結果を取得
        _buffer.GetData(data);

        for (int i = 0; i < _cubeCount; i++)
        {
            float result = data[i];
            _angles[i] = result;
            _cubes[i].transform.localEulerAngles = new Vector3(_angles[i], 0, 0);
        }
    }

    private void OnDestroy()
    {
        _buffer.Release();
    }
}