Shader "CrispyPin/Bocs"
{
	Properties
	{
		[Header(Raymarcher Properties)]
		_MaxSteps ("Max steps", Integer) = 128
		_MaxDist ("Max distance", Float) = 128
		_SurfDist ("Surface distance threshold", Range(.0001, .05)) = .001
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		Cull Front
		LOD 100

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			int _MaxSteps;
			float _MaxDist;
			float _SurfDist;
			#define MAX_STEPS _MaxSteps
			#define MAX_DIST _MaxDist
			#define SURF_DIST _SurfDist


			#define SCENE_FN main
			//#define LIGHT_FN lighting

			// #define SCENE_SCALE 1

			#define DISCARD_ON_MISS

			#include "lib/libgarbage.cginc"

			#define SPEED 1.5
			#define BOX_SIZE .15
			#define RADIUS BOX_SIZE*2

			float3 checkers(float3 p, float3 a, float3 b, float2 size) {
				float2 q = p.xz / size;
				q = int2(abs(q) + .5);
				int s = ((q.x + q.y) % 2);
				return s * a + (1 - s) * b;
			}

			Material gridtexture(float3 p) {
				return mat(checkers(p + BOX_SIZE/2 , 0.35, 0.45, BOX_SIZE));
			}

			SurfacePoint Boc(float3 p, float t, float3 grid_transform = float3(1,1,1)) {
				float x = smoothstep(0, .5, fmod(t, 4) - .5) * RADIUS;
				float z = smoothstep(1, .5, fmod(t, 4) - 2) * RADIUS;
				float y = smoothstep(.25, .75, abs(fmod(t - .75, 2) - 1)) * BOX_SIZE * 2 - BOX_SIZE / 2;
				return mBox(p - float3(x,y,z), BOX_SIZE,
				//  mat(.05, .8, .8)
				gridtexture((p - float3(x,y,z)) * grid_transform)
				 );
			}

			SurfacePoint main(float3 p) {
				SurfacePoint d;

				// base
				const float base_width = BOX_SIZE * 6 - 0.01;
				d = mBox(p - float3(0,-.15,0), float3(base_width, .3, base_width), gridtexture(p));
				float t = _Time.y * SPEED;

				// holes
				float3 ph = float3(abs(p.x), p.y, abs(p.z));
				d = qSub(d, mBox(ph - float3(RADIUS, 0, RADIUS), float3(BOX_SIZE, RADIUS, BOX_SIZE)));
				d = qSub(d, mBox(ph - float3(0, 0, RADIUS), float3(BOX_SIZE, RADIUS, BOX_SIZE)));
				d = qSub(d, mBox(ph - float3(RADIUS, 0, 0), float3(BOX_SIZE, RADIUS, BOX_SIZE)));

				// boxes
				d = qUnion(d, Boc(p, t));
				d = qUnion(d, Boc(p, t + 2));
				float3 p2 = p * float3(-1,1,-1);
				d = qUnion(d, Boc(p2, t));
				d = qUnion(d, Boc(p2, t + 2));
				const float3 flip_x = float3(-1,1,1);
				const float3 flip_z = float3(1,1,-1);
				float3 p3 = p.zyx * flip_x;
				d = qUnion(d, Boc(p3, t, flip_x));
				d = qUnion(d, Boc(p3, t + 2, flip_x));
				float3 p4 = p.zyx * flip_z;
				d = qUnion(d, Boc(p4, t, flip_x));
				d = qUnion(d, Boc(p4, t + 2, flip_x));

				return d;
			}
			ENDCG
		}
	}
}
