ComputeShader Small Example: Snow
![ComputeShader Small Example: Snow ComputeShader Small Example: Snow](http://up-free-imgs.azimiao.com/wp-content/uploads/2017/10/imageUnityOk02.jpg)
effect
principle
code
1.ComputeShder
#pragma kernel CSMain //Snow particle attributes (position, survival time) struct Particle { float3 position; float lifetime; }; //Buffer, used to set or retrieve data RWStructuredBuffer<Particle> particleBuffer; //Frame time interval float deltaTime; [numthreads (256, 1, 1)]//It is convenient to cut groups when calculating. Only one dimension value is used void CSMain(uint3 id : SV_DispatchThreadID) { float3 delta = float3(0, -2, 0); // gravity //Gravity fall particleBuffer[id.x].position += delta * deltaTime; //Update lifetime particleBuffer[id.x].lifetime += deltaTime; //When the particle survives for more than 25 seconds, reset it back to the point where y=0 if (particleBuffer[id.x].lifetime > 25) { particleBuffer[id.x].lifetime = 0; particleBuffer[id.x].position.y = 0; } }
2.Shader
Shader "SnowShader" { Properties { _Tint("Tint", Color) = (1, 1, 1, 1) } SubShader { Pass { Blend SrcAlpha one CGPROGRAM #pragma target 5.0 #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" //Particle data (corresponding to ComputeShader) struct Particle { float3 position; float lifetime; }; //input struct PS_INPUT { float4 position : SV_POSITION; float4 color : COLOR; }; //Buffer shared with ComputeShader StructuredBuffer<Particle> particleBuffer; //Color set through editor (Properties above) uniform float4 _Tint; //Vertex shader PS_INPUT vert(uint vertex_id : SV_VertexID, uint instance_id : SV_InstanceID) { PS_INPUT o = (PS_INPUT)0; o.color = _Tint; //Set position (take particle data at different positions from buffer through instance_id) o.position = UnityObjectToClipPos(float4(particleBuffer[instance_id].position, 1.0f)); return o; } //Pixel shader float4 frag(PS_INPUT i) : COLOR { return i.color; } ENDCG } } Fallback Off }
3.Csharp
public class Snow : MonoBehaviour { //Particle data structure (same as in ComputeShader, used to set buffer) private struct Particle { public Vector3 position; public float lifetime; } //Quantity public int particleCount = 10000; //Material for painting particles (shader is the above snow) public Material material; public ComputeShader computeShader; //Single structure size (bytes, used to initialize buffer, 3 * 4+4=16) private const int SIZE_PARTICLE = 16; //kernel ID private int mComputeShaderKernelID; //Buffer, setting, retrieving data, sharing with shader, etc ComputeBuffer particleBuffer; //ComputeBuffer The number of threads in a group, which is used to calculate packets when dispatching private const int WARP_SIZE = 256; //Number of groups required private int mWarpCount; void Start() { if (particleCount <= 0) particleCount = 1; //Calculate the number of groups mWarpCount = Mathf.CeilToInt((float)particleCount / WARP_SIZE); //Initialize particle data Particle[] particleArray = new Particle[particleCount]; for (int i = 0; i < particleCount; ++i) { particleArray[i].position.x = Random. Range(-50f, 50f); particleArray[i].position.y = 0; particleArray[i].position.z = Random. Range(-50f, 50f); particleArray[i].lifetime = Random. Range(0f, 25f); } //Create and set buffer data particleBuffer = new ComputeBuffer(particleCount, SIZE_PARTICLE); particleBuffer.SetData(particleArray); mComputeShaderKernelID = computeShader.FindKernel("CSMain"); //Set the buffer of the current kernel computeShader.SetBuffer(mComputeShaderKernelID, "particleBuffer", particleBuffer); //Shader shares this buffer material.SetBuffer("particleBuffer", particleBuffer); } void OnDestroy() { if (particleBuffer != null) particleBuffer.Release(); } void Update() { computeShader.SetFloat("deltaTime", Time.deltaTime); //Performing operations computeShader.Dispatch(mComputeShaderKernelID, mWarpCount, 1, 1); } void OnRenderObject() { //Activate the given pass for rendering material.SetPass(0); //GPU drawing Graphics.DrawProceduralNow(MeshTopology. Points, 1, particleCount); } }
References
-
[Code information] [Github] lukakostic ComputeShaderExamples