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();
*/
}
}