devNotes 8-29-16 Compute Shaders with Geometry

#pragma kernel main

// The same particle data structure used by both the compute shader and the shader.
struct Particle
{
	float3 position;
	float3 velocity;
};

// The buffer holding the particles shared with the regular shader.
RWStructuredBuffer<Particle> particleBuffer;

// parameters from GPU
float deltaTime;									// Even here deltaTime is needed!
float3 targ1;										// Targ1 position.
float3 targ2;										// Targ1 position.
float targetStrengh;								// Strengh, from the inspector!

[numthreads(32,1,1)] 								// 32 is the minimal size to fullfill the wrap. this is just the number of thread to run by wrap, "x, y, z" make easy 3D indexing.
void main (uint3 id : SV_DispatchThreadID)
{
	// particleBuffer[id.x] is the particle this thread must Update, according to the thread ID.
	
	// Direction and distance to target.
	float3 dir1 = normalize((targ1 - particleBuffer[id.x].position));
	float3 dir2 = normalize((targ2 - particleBuffer[id.x].position));

	float dist1 = distance(targ1, particleBuffer[id.x].position);
    float dist2 = distance(targ2, particleBuffer[id.x].position);
	
    float3 dir;
    float dist;

    if(dist1 < dist2) 
    {
        dist = dist1;
        dir = dir1;
    }
    else
    {
        dist = dist2;
        dir = dir2;
    }


    if(dist > 10)
    {
        particleBuffer[id.x].velocity += targetStrengh * dir * deltaTime / dist;
    }
    else
    {
        particleBuffer[id.x].velocity -= targetStrengh * dir * deltaTime / dist;
    }
      
    particleBuffer[id.x].velocity = particleBuffer[id.x].velocity* 0.98f;
	particleBuffer[id.x].position += particleBuffer[id.x].velocity * deltaTime;
}

 

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;

public class TestParticle : MonoBehaviour 
{
	// The same particle data structure used by both the compute shader and the shader.
	struct Particle
	{
		public Vector3 position;
		public Vector3 velocity;
	};
	
	public static List<TestParticle> list;	// Static list, just to call Render() from the camera.
	
	public int warpCount = 10;				// The number particle /32.
	public float initialSpread = 0.1f;			// Initial speed to the center of the sphere.
	public float pPowerMag = 100;		// velocity change from the mouse position.
	
	public Material material;				// Use "particle" shader.
	public ComputeShader computeShader;		// Use "moveParticle" compute shader.
	
	const int warpSize = 32; 				// GPUs process data by warp, 32 for every modern ones.
	int particleCount; 						// = warpSize * warpCount.
	
	ComputeBuffer particleBuffer;			// The GPU buffer holding the particules.

    public GameObject frisbee1;
    public GameObject frisbee2;

    public UI_Control ui_Control;

    void Start () 
	{
		// Just init the static list 
		if (list == null)
			list = new List<TestParticle>();
		list.Add(this);

		particleCount = warpCount * warpSize;
		
		// Init particles
		Particle[] particleArray = new Particle[particleCount];
		for (int i = 0; i < particleCount; ++i)
		{
			particleArray[i].position = Random.insideUnitSphere * initialSpread;
            particleArray[i].velocity = particleArray[i].position.normalized;
		}
		
		// Instanciate and initialise the GPU buffer.
		particleBuffer = new ComputeBuffer(particleCount, 24); // 24 = sizeof(Particle)
		particleBuffer.SetData(particleArray);
		
		// bind the buffer to both the compute shader and the shader.
		computeShader.SetBuffer(0, "particleBuffer", particleBuffer);
		material.SetBuffer ("particleBuffer", particleBuffer);
	}

	
	void Update () 
	{
		// Get the mouse position in the 3D space (a flat box collider catch the ray) .
		float[] targ1 = {0f, 0f, 0f };
        float[] targ2 = { 0f, 0f, 0f };

        Vector3 pos = frisbee1.transform.position;

        targ1[0] = pos.x;
        targ1[1] = pos.y;
        targ1[2] = pos.z;

        pos = frisbee2.transform.position;

        targ2[0] = pos.x;
        targ2[1] = pos.y;
        targ2[2] = pos.z;

        pPowerMag = ui_Control.pParticlePower;

        // Initialise the compute shader variables.
        computeShader.SetFloat("targetStrengh", pPowerMag);
		computeShader.SetFloat("deltaTime", Time.deltaTime);
		computeShader.SetFloats("targ1", targ1);
        computeShader.SetFloats("targ2", targ2);

        // Start the compute shader (move every particle for this frame).
        computeShader.Dispatch(0, warpCount, 1, 1);
	}
	
	// Called by the camera in OnRender
	public void Render () 
	{
		// Bind the pass to the pipeline then call a draw (this use the buffer bound in Start() instead of a VBO).
		material.SetPass (0);
		Graphics.DrawProcedural (MeshTopology.Points, 1, particleCount);
	}
	
	
	void OnDestroy()
	{
		list.Remove(this);
		
		// Unity cry if the GPU buffer isn't manually cleaned
		particleBuffer.Release();
	}
}

ssdfsgdgf-1 dgfngn1 fdgngfdng1

dgfngn1