Rendering, Compute Shader and Shaderlab functions and classes
Import from git or package.json into Unity Package manager
https://github.com/wTechnoo/ComputeHelper.git
Compute Runner multiple kernels examples Import through package manager
This class implements boilerplate code of compute shaders
public class ExampleComputeRunner : MonoBehaviour
{
ComputeRunner runner;
ComputeShader computeShader;
void Start()
{
runner = new ComputeRunner(computeShader, new Vector3Int(1,1,1));
}
void Update()
{
runner.Dispatch();
}
}
Arguments:
computeShader:
Compute shader reference.count:
Object count or texture resolution (ex: new Vector3Int(512, 512, 1)).kernels[]:
Kernel string array with kernel names.
This class handles generic data and ComputeBuffers
public class ExampleBufferHolder : MonoBehaviour
{
public struct Example
{
Vector3 position;
Matrix4x4 mat;
}
BufferHolder<Example> buffer;
int count;
void Start()
{
var data = new Example[count];
for (int i = 0; i < count; i++)
{
data[i].position = Vector3.one * i;
data[i].mat = Matrix4x4.zero;
}
buffer = new BufferHolder<Example>(data, "Buffer");
}
}
Arguments:
T[] data:
Array containing generic data.name:
Name inside ComputeShader.kernel:
Which kernel to set the buffer to (Default=0).
This class implements Instanced Indirect mesh rendering
public class ExampleInstancedRendering : MonoBehaviour
{
public struct Example
{
Vector3 position;
Matrix4x4 mat;
}
int count;
Mesh mesh;
Material material;
BufferHolder<Example> buffer;
InstancedRenderer renderer;
void Start()
{
renderer = new InstancedRenderer(count, mesh, material, Vector3.zero);
var data = new Example[count];
for (int i = 0; i < count; i++)
{
data[i].position = Vector3.one*i;
data[i].mat = Matrix4x4.TRS(data[i].position, Quaternion.identity, Vector3.one);
}
buffer = new BufferHolder<Example>(data, "Buffer");
renderer.AddBuffer(buffer);
}
void Update()
{
renderer.Render();
}
}
Arguments:
instanceCount:
How many instances are going to be drawn.mesh:
Mesh to be drawn.material:
Shader that will draw the instanced meshes.boundCenter:
Where the center of the bound will be placed for rendering.boundSize:
Maximum bound size.
struct Example
{
float3 position;
float4x4 mat;
};
StructuredBuffer<Example> Buffer;
v2f vert(appdata v, uint instanceID : SV_InstanceID)
{
v2f o;
float4 position = mul(Buffer[instanceID].mat, v.vertex);
o.vertex = UnityObjectToClipPos(position);
o.uv = v.uv;
return o;
}
Utilize uint instanceID : SV_InstanceID
inside the arguments of the vert function to get the current instanced instance
Use both InstancedRendering together with ComputeRunner
public class ExampleInstancedRenderingCompute : MonoBehaviour
{
public struct Example
{
Vector3 position;
Matrix4x4 mat;
}
int count;
Mesh mesh;
Material material;
ComputeShader computeShader;
BufferHolder<Example> buffer;
ComputeRunner runner;
InstancedRenderer renderer;
void Start()
{
runner = new ComputeRunner(computeShader, new Vector3Int(count, 1, 1));
renderer = new InstancedRenderer(count, mesh, material, Vector3.zero);
var data = new Example[count];
for (int i = 0; i < count; i++)
{
data[i].position = Vector3.one*i;
data[i].mat = Matrix4x4.TRS(data[i].position, Quaternion.identity, Vector3.one);
}
buffer = new BufferHolder<Example>(data, "Buffer");
runner.AddBuffer(buffer);
renderer.AddBuffer(buffer);
}
void Update()
{
runner.Dispatch();
renderer.Render();
}
}
#include "Packages/com.technoo.computehelper/Runtime/Computehelper.cginc"
struct Example
{
float3 position;
float4x4 mat;
};
RWStructuredBuffer<Example> Buffer;
[numthreads(8,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
Buffer[id.x].position = float3(id.x, 0, id.x);
Buffer[id.x].mat = compose(GrassBuffer[id.x].position);
}
Packages/com.technoo.computehelper/Runtime/Computehelper.cginc
contains the compose function that builds a 4x4 matrix (position, rotation quaternion, scale)
struct Example
{
float3 position;
float4x4 mat;
};
StructuredBuffer<Example> Buffer;
v2f vert(appdata v, uint instanceID : SV_InstanceID)
{
v2f o;
float4 position = mul(Buffer[instanceID].mat, v.vertex);
o.vertex = UnityObjectToClipPos(position);
o.uv = v.uv;
return o;
}