Shader "CrispyPin/HilbertWorms" { Properties { _Speed ("Speed (px/s)", Integer) = 100 [IntRange]_Worms ("Worms", Range(1,10)) = 1 [IntRange]_Level ("Level", Range(2,9)) = 3 [IntRange]_SmallLen ("Small length", Range(1,32)) = 8 _WormColor ("worm color", Color) = (1, 0.5, 1, 1) } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #define SPEED _Speed #define WORM_COUNT _Worms #define LEVELS _Level #define PIXEL_COUNT (1 << (2 * LEVELS + 2 - WORM_COUNT)) #define SMALL_LEN _SmallLen float _Speed; uint _Worms; uint _Level; uint _SmallLen; float3 _WormColor; struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; UNITY_VERTEX_OUTPUT_STEREO }; v2f vert (appdata v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); UNITY_INITIALIZE_OUTPUT(v2f, o); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } float4 frag (v2f i) : SV_Target { uint pos = 0; uint mask = 1 << (2 * LEVELS); float2 p = i.uv * 2 - 1; for (uint level = 0; level < LEVELS; level += 1) { bool lower_half = false; bool lower_quarter = false; if (p.x < 0) { lower_half = true; p.x = (p.x * 2) + 1.0; p.y *= -1; } else { pos |= mask; p.x = (p.x - 0.5) * 2; } if (p.y < 0) { p.y = (p.y * 2) + 1.0; pos |= mask/2; } else { lower_quarter = true; p.y = (p.y - 0.5) * 2; } if (lower_half && lower_quarter) { p = float2(-p.y, p.x); } else if (lower_half && !lower_quarter) { p.y *= -1; } else if (!lower_half && !lower_quarter) { p = -p.yx; } mask >>= 2; } uint time = ((uint)(_Time.y * SPEED)) % PIXEL_COUNT; uint distance = (time - pos) % PIXEL_COUNT; if (distance < SMALL_LEN) { float worm = 1 - ((float)distance / SMALL_LEN); return float4(_WormColor * worm, 1); } else { // distance = (time/32 - pos/32) % (PIXEL_COUNT/32); // const int tail_length = 4; // if (distance < tail_length) { // float tail = ((float)distance / tail_length); // tail = 1-abs(1-tail*2); // return float4(tail, tail/8, 0, 1); // } } // if ((time - pos) % PIXEL_COUNT <= n){ // return 1 - ((float)((time - pos) % PIXEL_COUNT) / n); // } return 0; } ENDCG } } }