using System.Collections; using System.Collections.Generic; using UnityEngine; public class RunCompute : MonoBehaviour { private Vector2 cursorPos; // struct struct Particle { public Vector3 position; public Vector3 velocity; public float life; } /// /// Size in octet of the Particle struct. /// since float = 4 bytes... /// 4 floats = 16 bytes /// //private const int SIZE_PARTICLE = 24; private const int SIZE_PARTICLE = 28; // since property "life" is added... /// /// Number of Particle created in the system. /// private int particleCount = 1000000; /// /// Material used to draw the Particle on screen. /// public Material material; /// /// Compute shader used to update the Particles. /// public ComputeShader computeShader; /// /// Id of the kernel used. /// private int mComputeShaderKernelID; /// /// Buffer holding the Particles. /// ComputeBuffer particleBuffer; /// /// Number of particle per warp. /// private const int WARP_SIZE = 256; // TODO? /// /// Number of warp needed. /// private int mWarpCount; // TODO? //public ComputeShader shader; // Use this for initialization void Start () { InitComputeShader(); } void InitComputeShader() { mWarpCount = Mathf.CeilToInt((float)particleCount / WARP_SIZE); // initialize the particles Particle[] particleArray = new Particle[particleCount]; for (int i = 0; i < particleCount; i++) { float x = Random.value * 2 - 1.0f; float y = Random.value * 2 - 1.0f; float z = Random.value * 2 - 1.0f; Vector3 xyz = new Vector3(x, y, z); xyz.Normalize(); xyz *= Random.value; xyz *= 0.5f; particleArray[i].position.x = xyz.x; particleArray[i].position.y = xyz.y; particleArray[i].position.z = xyz.z + 3; particleArray[i].velocity.x = 0; particleArray[i].velocity.y = 0; particleArray[i].velocity.z = 0; // Initial life value particleArray[i].life = Random.value * 5.0f + 1.0f; } // create compute buffer particleBuffer = new ComputeBuffer(particleCount, SIZE_PARTICLE); particleBuffer.SetData(particleArray); // find the id of the kernel mComputeShaderKernelID = computeShader.FindKernel("CSParticle"); // bind the compute buffer to the shader and the compute shader computeShader.SetBuffer(mComputeShaderKernelID, "particleBuffer", particleBuffer); material.SetBuffer("particleBuffer", particleBuffer); } void OnRenderObject() { material.SetPass(0); Graphics.DrawProcedural(MeshTopology.Points, 1, particleCount); } void OnDestroy() { if (particleBuffer != null) particleBuffer.Release(); } // Update is called once per frame void Update () { float[] mousePosition2D = { cursorPos.x, cursorPos.y }; // Send datas to the compute shader computeShader.SetFloat("deltaTime", Time.deltaTime); computeShader.SetFloats("mousePosition", mousePosition2D); // Update the Particles computeShader.Dispatch(mComputeShaderKernelID, mWarpCount, 1, 1); } void OnGUI() { Vector3 p = new Vector3(); Camera c = Camera.main; Event e = Event.current; Vector2 mousePos = new Vector2(); // Get the mouse position from Event. // Note that the y position from Event is inverted. mousePos.x = e.mousePosition.x; mousePos.y = c.pixelHeight - e.mousePosition.y; p = c.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, c.nearClipPlane + 14));// z = 3. cursorPos.x = p.x; cursorPos.y = p.y; /* GUILayout.BeginArea(new Rect(20, 20, 250, 120)); GUILayout.Label("Screen pixels: " + c.pixelWidth + ":" + c.pixelHeight); GUILayout.Label("Mouse position: " + mousePos); GUILayout.Label("World position: " + p.ToString("F3")); GUILayout.EndArea(); */ } }