Shader "CrispyPin/elementary_ca"
{
	Properties
	{
		[NoScaleOffset]
		_LastFrame ("Render texture", 2D) = "white" {}
		_Rule("Rule", Integer) = 110
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			#define WIDTH 256

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			texture2D _LastFrame;
			int _Rule;

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = v.uv;
				return o;
			}

			inline int state(uint2 p, int dx, int dy)
			{
				const uint x = (p.x + dx) % WIDTH;
				const uint y = (p.y + dy) % WIDTH;
				return _LastFrame[uint2(x, y)].b > 0.1;
			}

			float3 frag (v2f i) : SV_Target
			{
				if(_ProjectionParams.z > 1) discard;

				const uint2 p = i.uv * WIDTH;
				if (p.y == WIDTH-1) {
					return state(p, 0, 0);
				}
				int permutation =
					(state(p, -1, 1) << 2) |
					(state(p, 0, 1) << 1) |
					state(p, 1, 1);

				float next = (_Rule >> permutation) & 1;
				return float3(i.uv * next, next * (_SinTime.y * 0.4 + 0.6));
			}
			ENDCG
		}
	}
}
