Getting Started With Compute Shaders
The shader that's a 'Jack of all trades'. Of course, it's the Compute Shader.These beauties allow your general purpose parallelized code to run on the GPU.
These can be used to do some pretty cool stuff that would be pretty difficult to do otherwise even with multi-threaded CPU code.
When bringing up Compute shaders in the context of video games, It's mostly used in physics simulations and freaky looking particle effects and to a lower extent as a core part of some post-processing effects and render pipeline optimizations such as various culling operations like occlusion culling.
The most important thing about compute shaders is that it allows for more efficient communication from CPU to GPU side and vice-versa. That basically means you can send arbitrary data to the GPU, let it do some work and then read it's output and then do whatever you want with it.
You can now see that how different compute shaders are when compared to other shaders, such as the fragment shader; which will only give output from the GPU in the form of a pixel buffer.
This will be the start of a series of tutorials related to creating various effects & simulations with the help of Compute Shaders in Unity.
You should somewhat familiar with writing shaders as well as have basic C# and Unity knowledge.
Before we start on the good stuff we need to be able to run a basic compute shader and see it's output in Unity.
Keep in mind that you need a graphics card released after the year 2011 ( or Intel HD 4000 or later ) be able to run compute shaders.
Unity setup
- Create a new scene
- Create a new compute shader & name it 'Test.compute'
This is default Compute Shader template, We won't be changing this.// Each #kernel tells which function to compile; you can have many kernels #pragma kernel CSMain // Create a RenderTexture with enableRandomWrite flag and set it // with cs.SetTexture RWTexture2D Result; [numthreads(8,8,1)] void CSMain (uint3 id : SV_DispatchThreadID) { // TODO: insert actual code here! Result[id.xy] = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0); }
- Create a C# script called 'ComputeTester.cs'
Attach this script to any gameObject with a renderer component. Don't forget to assign our compute shader in the editor.using UnityEngine; public class ComputeTester : MonoBehaviour { public ComputeShader computeShader; public int textureRes = 256; // Size of render texture we will be making private Renderer rend; private RenderTexture renderTexture; private void Start() { renderTexture = new RenderTexture(textureRes, textureRes, 24) // We have 24 as parameter for depth so that we will have depth buffer & stencil buffer support { enableRandomWrite = true }; renderTexture.Create();//Need to call this to actually make it available in graphics memory rend = GetComponent(); rend.enabled = true; int kernelHandle = computeShader.FindKernel("CSMain"); //Find entry point to our Compute Shader computeShader.SetTexture(kernelHandle, "Result", renderTexture); //Assigning our render texture in our Compute Shader which is called 'Result' computeShader.Dispatch(kernelHandle, textureRes / 8, textureRes / 8, 1); // Executes code on GPU with the input we have provided. rend.material.SetTexture("_MainTex", renderTexture); //Telling out render's material to use the render texture as it's texture } private void OnDestroy() { renderTexture.Release(); // Remove the render texture from graphics memory } }
- We should end up with this.
We didn't go into any depth here, Just go this up and running.
In future tutorials we will explore this in greater detail.
If you have any questions that you might have about shaders or unity development in general don't be shy and leave a message on my facebook page or down in the comments.
For more Shader development tutorials, go : HERE
For Unity development tutorials, go : HERE