Hello!
I’m fairly new to compute shaders with Unity but I’m trying to follow a tutorial about recreating Game of Life using compute shaders.
At first I had to refactor the code to use Texture2D since sample2D is no longer supported as a declaration.
The issue that I am having is that my texture is wrapping across the Quad and I’m not sure why.
My compute shade and C# script is below.
ComputeShader
#pragma kernel GameOfLife
float Width;
float Height;
Texture2D Input;
SamplerState sampler_Input;
// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
RWTexture2D<float4> Result;
[numthreads(8,8,1)]
void GameOfLife (uint3 id : SV_DispatchThreadID)
{
// TODO: insert actual code here!
float2 position = float2((id.x) / Width, (id.y) / Height);
float2 pixelSize = float2(1.0 / Width, 1.0 / Height);
// TODO: insert actual code here!
float4 currentPixel = Input.SampleLevel(sampler_Input, float2(position.x, position.y), 0);
float4 neighborPixels = float4(0,0,0,0);
// +Y
neighborPixels += Input.SampleLevel(sampler_Input, float2(position.x + pixelSize.x, position.y + pixelSize.y), 0);
neighborPixels += Input.SampleLevel(sampler_Input, float2(position.x, position.y + pixelSize.y), 0);
neighborPixels += Input.SampleLevel(sampler_Input, float2(position.x - pixelSize.x, position.y + pixelSize.y), 0);
// Neutral Y
neighborPixels += Input.SampleLevel(sampler_Input, float2(position.x + pixelSize.x, position.y), 0);
neighborPixels += Input.SampleLevel(sampler_Input, float2(position.x - pixelSize.x, position.y), 0);
// -Y
neighborPixels += Input.SampleLevel(sampler_Input, float2(position.x + pixelSize.x, position.y - pixelSize.y), 0);
neighborPixels += Input.SampleLevel(sampler_Input, float2(position.x, position.y - pixelSize.y), 0);
neighborPixels += Input.SampleLevel(sampler_Input, float2(position.x - pixelSize.x, position.y - pixelSize.y), 0);
// Add current pixel for reason
//neighborPixels += currentPixel;
if (currentPixel.r > 0.5) {
if (neighborPixels.r > 1.5 && neighborPixels.r < 3.5) { //Between 2 and 3
Result[id.xy] = float4(1, 1, 1, 1);
}
else {
Result[id.xy] = float4(0, 0, 0, 1);
}
}
else {
if (neighborPixels.r > 2.5 && neighborPixels.r < 3.5) { // == 3
Result[id.xy] = float4(1, 1, 1, 1);
}
else {
Result[id.xy] = float4(0, 0, 0, 1);
}
}
//Result[id.xy] = neighborPixels / 9;
}
C# Script
public Texture2D input;
public int width = 512;
public int height = 512;
public ComputeShader compute;
RenderTexture renderTexPing;
RenderTexture renderTexPong;
public Material material;
private int kernel;
private bool pingPong;
// Use this for initialization
void Start () {
if (height < 1 || width < 1) return;
kernel = compute.FindKernel("GameOfLife");
renderTexPing = new RenderTexture(width, height, 24);
renderTexPing.wrapMode = TextureWrapMode.Repeat;
renderTexPing.wrapModeU = TextureWrapMode.Repeat;
renderTexPing.wrapModeV = TextureWrapMode.Repeat;
renderTexPing.wrapModeW = TextureWrapMode.Repeat;
renderTexPing.enableRandomWrite = true;
renderTexPing.filterMode = FilterMode.Point;
renderTexPing.useMipMap = false;
renderTexPing.Create();
renderTexPong = new RenderTexture(width, height, 24);
renderTexPong.wrapMode = TextureWrapMode.Repeat;
renderTexPong.wrapModeU = TextureWrapMode.Repeat;
renderTexPong.wrapModeV = TextureWrapMode.Repeat;
renderTexPong.wrapModeW = TextureWrapMode.Repeat;
renderTexPong.enableRandomWrite = true;
renderTexPong.filterMode = FilterMode.Point;
renderTexPong.useMipMap = false;
renderTexPong.Create();
Graphics.Blit(input, renderTexPing);
pingPong = true;
compute.SetFloat("Width", width);
compute.SetFloat("Height", height);
}
// Update is called once per frame
void Update ()
{
//if (!step) return;
//step = false;
if (height < 1 || width < 1) return;
if (true == pingPong)
{
compute.SetTexture(kernel, "Input", renderTexPing);
compute.SetTexture(kernel, "Result", renderTexPong);
compute.Dispatch(kernel, width / 8, height / 8, 1);
material.mainTexture = renderTexPong;
pingPong = false;
}
else
{
compute.SetTexture(kernel, "Input", renderTexPong);
compute.SetTexture(kernel, "Result", renderTexPing);
compute.Dispatch(kernel, width / 8, height / 8, 1);
material.mainTexture = renderTexPing;
pingPong = true;
}
}
I am importing a glider 16x16 texture like in the video and once it hits the bottom right corner of the screen it is treating it as a wall and it is not appearing back at the top left.
If anyone could point me in the right direction that would be appreciated.
Here is repo of the original code.