Shader "Grinlin/Shadertoy Convert/aiekick/HexaGold 2"
{ // Converted and edited by Koda, jzody. From ->> https://www.shadertoy.com/view/sltSR2 by aiekick
    Properties
    {
        [Header(General)]
        _MainTex ("iChannel0", 2D) = "white" {}
        _SecondTex ("iChannel1", 2D) = "white" {}
        _ThirdTex ("iChannel2", 2D) = "white" {}
        _FourthTex ("iChannel3", 2D) = "white" {}
        _Mouse ("Mouse", Vector) = (0.5, 0.5, 0.5, 0.5)
        [ToggleUI] _GammaCorrect ("Gamma Correction", Float) = 1
        _Resolution ("Resolution (Change if AA is bad)", Range(1, 1024)) = 1

        [Header(Raymarching)]
        [ToggleUI] _WorldSpace ("World Space Marching", Float) = 0
        _Offset ("Offset (W=Scale)", Vector) = (0, 0, 0, 1)

		[IntRange] _StencilRef("Stencil Reference Value", Range(0, 255)) = 0
		[IntRange] _StencilReadMask("Stencil ReadMask Value", Range(0, 255)) = 255
		[IntRange] _StencilWriteMask("Stencil WriteMask Value", Range(0, 255)) = 255
		[Enum(UnityEngine.Rendering.CompareFunction)] _StencilCompareFunction("Stencil Compare Function", Float) = 8
    }
    SubShader
    {
		Stencil
		{
			Ref[_StencilRef]
			ReadMask[_StencilReadMask]
			WriteMask[_StencilWriteMask]
			Comp[_StencilCompareFunction]
		}
        Pass
        {
            Cull Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 ro_w : TEXCOORD1;
                float3 hitPos_w : TEXCOORD2;
            };

            // Built-in properties
            sampler2D _MainTex;   float4 _MainTex_TexelSize;
            sampler2D _SecondTex; float4 _SecondTex_TexelSize;
            sampler2D _ThirdTex;  float4 _ThirdTex_TexelSize;
            sampler2D _FourthTex; float4 _FourthTex_TexelSize;
            float4 _Mouse;
            float _GammaCorrect;
            float _Resolution;
            float _WorldSpace;
            float4 _Offset;

            // GLSL Compatability macros
            #define glsl_mod(x,y) (((x)-(y)*floor((x)/(y))))
            #define texelFetch(ch, uv, lod) tex2Dlod(ch, float4((uv).xy * ch##_TexelSize.xy + ch##_TexelSize.xy * 0.5, 0, lod))
            #define textureLod(ch, uv, lod) tex2Dlod(ch, float4(uv, 0, lod))
            #define iResolution float3(_Resolution, _Resolution, _Resolution)
            #define iFrame (floor(_Time.y / 60))
            #define iChannelTime float4(_Time.y, _Time.y, _Time.y, _Time.y)
            #define iDate float4(2020, 6, 18, 30)
            #define iSampleRate (44100)
            #define iChannelResolution float4x4(                      \
                _MainTex_TexelSize.z,   _MainTex_TexelSize.w,   0, 0, \
                _SecondTex_TexelSize.z, _SecondTex_TexelSize.w, 0, 0, \
                _ThirdTex_TexelSize.z,  _ThirdTex_TexelSize.w,  0, 0, \
                _FourthTex_TexelSize.z, _FourthTex_TexelSize.w, 0, 0)

            // Global access to uv data
            static v2f vertex_output;

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

                if (_WorldSpace)
                {
                    o.ro_w = _WorldSpaceCameraPos;
                    o.hitPos_w = mul(unity_ObjectToWorld, v.vertex);
                }
                else
                {
                    o.ro_w = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
                    o.hitPos_w = v.vertex;
                }

                return o;
            }

            float3x3 rotz(float a)
            {
                return transpose(float3x3(cos(a), -sin(a), 0., sin(a), cos(a), 0., 0., 0., 1.));
            }

            float sdHexPrism(float3 p, float2 h)
            {
                float3 q = abs(p);
                const float3 k = float3(-0.8660254, 0.5, 0.57735);
                p = abs(p);
                p.xy -= 2.*min(dot(k.xy, p.xy), 0.)*k.xy;
                float2 d = float2(length(p.xy-float2(clamp(p.x, -k.z*h.x, k.z*h.x), h.x))*sign(p.y-h.x), p.z-h.y);
                return min(max(d.x, d.y), 0.)+length(max(d, 0.));
            }

#define ox 1.3
#define oz 1.5
            void common_map(float3 p, out float df0, out float df1)
            {
                df1 = 0;
                df0 = 0;
                p = mul(p,transpose(rotz(p.z*0.05)));
                p.y = 5.+5.*(sin(p.z*0.1)*0.5+0.5)-abs(p.y);
                float wave = sin(length(p.xz)*0.25-_Time.y*1.5);
                df0 = abs(p.y+wave)-1.;
                float2 hex_size = float2(0.25+p.y*0.25, 10.);
                float3 q0 = p;
                q0.x = glsl_mod(q0.x-ox, ox+ox)-ox;
                q0.z = glsl_mod(q0.z-oz*0.5, oz)-oz*0.5;
                float hex0 = sdHexPrism(q0.xzy, hex_size)-0.2;
                float3 q1 = p;
                q1.x = glsl_mod(q1.x, ox+ox)-ox;
                q1.z = glsl_mod(q1.z, oz)-oz*0.5;
                float hex1 = sdHexPrism(q1.xzy, hex_size)-0.2;
                df1 = min(hex0, hex1);
            }

            float smin(float a, float b, float k)
            {
                float h = clamp(0.5+0.5*(b-a)/k, 0., 1.);
                return lerp(b, a, h)-k*h*(1.-h);
            }

            float smax(float a, float b, float k)
            {
                return smin(a, b, -k);
            }

            float map(float3 p)
            {
                float df0, df1;
                common_map(p, df0, df1);
                return smax(df0, df1, 0.1);
            }

            float mat(float3 p)
            {
                float df0, df1;
                common_map(p, df0, df1);
                if (df0>df1)
                    return 1.;
                    
                return 0.;
            }

            float3 getNormal(float3 p, float prec)
            {
                float3 e = float3(prec, 0, 0);
                return normalize(float3(map(p+e)-map(p-e), map(p+e.yxz)-map(p-e.yxz), map(p+e.zyx)-map(p-e.zyx)));
            }

            float getAmbiantOcclusion(float3 p, float3 n, float k)
            {
                const float aoStep = 0.1;
                float occl = 0.;
                for (int i = min(iFrame, 0);i<6; ++i)
                {
                    float diff = float(i)*aoStep;
                    float d = map(p+n*diff);
                    occl += (diff-d)*pow(2., float(-i));
                }
                return min(1., 1.-k*occl);
            }

            float getShadow(float3 ro, float3 rd, float minD, float maxD, float k)
            {
                float res = 1.;
                float d = minD;
                float s = 0.;
                for (int i = min(iFrame, 0);i<20; ++i)
                {
                    s = map(ro+rd*d);
                    if (abs(s)<d*d*0.00001)
                        return 0.;
                        
                    res = min(res, k*s/d);
                    d += s;
                    if (d>=maxD)
                        break;
                        
                }
                return res;
            }

            float3 cam(float2 uv, float3 ro, float3 cv, float fov)
            {
                float3 cu = normalize(float3(0, 1, 0));
                float3 z = normalize(cv-ro);
                float3 x = normalize(cross(cu, z));
                float3 y = cross(z, x);
                return normalize(z+fov*uv.x*x+fov*uv.y*y);
            }

            float3 hsv2rgb_smooth(in float3 c)
            {
                float3 rgb = clamp(abs(glsl_mod(c.x*6.+float3(0., 4., 2.), 6.)-3.)-1., 0., 1.);
                rgb = rgb*rgb*(3.-2.*rgb);
                return c.z*lerp(((float3)1.), rgb, c.y);
            }

            float4 frag (v2f __vertex_output, float facing : VFACE) : SV_Target
            {
                vertex_output = __vertex_output;
                float4 fragColor = 0;
                float2 fragCoord = vertex_output.uv * _Resolution;
                float2 si = iResolution.xy;
                float2 uvc = (2.*fragCoord.xy-si)/si.y;
                float3 ro = ((facing>0 ? vertex_output.hitPos_w : vertex_output.ro_w)+_Offset)*_Offset.w;
                float3 cv = ro+float3(0., 0., 4.);
                float3 rd = normalize(vertex_output.hitPos_w-vertex_output.ro_w);
                float3 col = ((float3)0.1);
                float s = 1., d = 0., md = 100.;
                for (int i = min(iFrame, 0);i<200; i++)
                {
                    if (d*d/s>1000000.||d>70.)
                        break;
                        
                    s = map(ro+rd*d);
                    d += s*0.5;
                }
                if (d<md)
                {
                    float3 p = ro+rd*d;
                    float3 n = getNormal(p, 0.1);
                    float3 lp = float3(0, 5, 0);
                    float3 ld = normalize(lp-p);
                    float diff = pow(dot(n, ld)*0.5+0.5, 2.);
                    float ao = getAmbiantOcclusion(p, n, 40.);
                    float sha = clamp(getShadow(p, ld, 0.01, 150., 5.), 0., 0.9);
                    if (mat(p)>0.5)
                    {
                        col = lerp(float3(1.5, 1., 0.), ((float3)2.), sin(p.z*0.1)*0.5+0.5);
                    }
                    else 
                    {
                        col = float3(1., 0.85, 0.)*0.5;
                    }
                    col *= tex2D(_MainTex, reflect(rd, n)).rgb;
                    col += diff*sha*0.5;
                    col = clamp(col, 0., 1.);
                }
                
                col *= exp(1.-d*d*0.001);
                fragColor = float4(col, 1);
                if (_GammaCorrect) fragColor.rgb = pow(fragColor.rgb, 2.2);
                return fragColor;
            }
            ENDCG
        }
    }
}
