Shader "CrispyPin/Raymarch1"
{
    Properties
    {
        [Header(Raymarcher Properties)]
        _MaxSteps ("Max steps", Int) = 256
        _MaxDist ("Max distance", Float) = 100
        _SurfDist ("Surface distance threshold", Range(0.00001, 0.05)) = 0.001
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Cull Off
        LOD 100

   /*      Pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 ro : TEXCOORD1;
                float3 hitPos : TEXCOORD2;
            };


             v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                //object space
                o.ro = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
                o.hitPos = v.vertex;
                //world space
                //o.ro = _WorldSpaceCameraPos;
                //o.hitPos = mul(unity_ObjectToWorld, v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                discard;
                return fixed4(0,0,0,0);
            }

            ENDCG
        } */

        Pass
        {
            Name "AddPass"
            Tags { "LightMode" = "ForwardAdd"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 ro : TEXCOORD1;
                float3 hitPos : TEXCOORD2;
            };

            int _MaxSteps;
            float _MaxDist;
            float _SurfDist;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                //object space
                o.ro = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
                o.hitPos = v.vertex;
                //world space
                //o.ro = _WorldSpaceCameraPos;
                //o.hitPos = mul(unity_ObjectToWorld, v.vertex);
                return o;
            }

            float smoothMin(float a, float b, float k)
            {
                return min(a, b) - pow(max(k - abs(a-b), 0), 3)/(6*k*k);
            }

            float sdSphere(float3 p, float3 o, float r) {
                return length(p - o) - r;
            }

            float sdBox(float3 p, float3 dim)
            {
                return length(float3(
                    max(abs(p.x) - dim.x/2.0, 0),
                    max(abs(p.y) - dim.y/2.0, 0),
                    max(abs(p.z) - dim.z/2.0, 0)));
            }

            float3 repDomain(float3 p, float3 r)
            {
                return fmod(abs(p + r/2.0), r) - r/2.0;
            }


            float GetDist(float3 p)
            {
/*                 float d = 0;

                float s = sin(100*_Time + p.x*10) * 0.02 + 0.028;
                float s2 = cos(105*_Time + p.x*10) * 0.02 + 0.028;
                //s += sin(p.x/10)*0.03;

                float3 rep = repDomain(p, float3(0.026, 0.15, 0.2));// fmod(abs(p + 0.05), 0.1)-0.05;
                d = sdBox(rep, float3(0.02, s2, s)) - 0.004;
                d = smoothMin(d, sdBox(rep, float3(0.01, s*1.0, s2*1.5)) - 0.004, 0.01);
 */
                float d = sdSphere(p, 0, 0.1f);
                // float3 second =  ObjSpaceLightDir(0);
                // float3 second = _WorldSpaceLightPos0;
                float3 second = mul(unity_WorldToObject, _WorldSpaceLightPos0);
                d = smoothMin(d, sdBox(p-second, 0.3f), 0.2);
                //d = smoothMin(d, sdSphere(p, float3(0,0,0), 5), .3);
                return d;
            }

            //marches a ray through the scene
            float Raymarch(float3 ro, float3 rd)
            {
                float rayLen = 0;// total distance marched / distance from origin
                float dist; // distance from the raymarched scene
                for ( int i = 0; i < _MaxSteps; i++)
                {
                    //position = origin + distance * direction
                    float3 p = ro + rayLen * rd;
                    dist = GetDist(p);
                    rayLen += dist;// move forward
                    if (dist < _SurfDist || rayLen > _MaxDist) {
                        break;
                    }
                }

                return rayLen;
            }

            float3 GetNormal(float3 p)
            {
                float2 e = float2(0.001, 0);
                float3 n = GetDist(p) - float3(
                    GetDist(p-e.xyy),
                    GetDist(p-e.yxy),
                    GetDist(p-e.yyx));
                return normalize(n);
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float3 ro = i.ro;
                float3 rd = normalize(i.hitPos - ro);

                float d = Raymarch(ro, rd);
                fixed4 col = 1;

                if (d >= _MaxDist)
                {
                    discard;
                }
                float3 p = ro + rd * d;
                float3 n = GetNormal(p);

                col.rgb = dot(n, normalize(float3(1,0.5,1)));
                col *= float4(d, 1, 1, 1);
                return col;
            }
            ENDCG
        }
    }
}
