﻿Shader "Corpse/Connecting Loop v1.2" {
	Properties {

	    [Header(Pairing Settings)]
		[Space(10)]

		_key ("Pairing Key(0~9999)",float) = 0
		[Space(20)]

		[Header(Material Settings)]
		[Space(10)]

		[HDR]_color ("Color", COLOR) = (0.0,0.3,0.4,1.0)
		_MainTex ("Texture", 2D) = "white" {}
		[Space]

        _Matcap ("Matcap Texture", 2D) = "white" {}
		[Space]

		_Range ("Matcap Range", Range(0, 1.5)) = 0

		[Space(50)]

		[Header(Advanced Settings)]
		[Space(10)]

		_position ("Position",vector) = (0.0,0.0,0.0,0.0)
		_rotation ("Rotation",vector) = (0.0,0.0,0.0,0.0)
		_scale ("Scale",vector) = (1.0,1.0,1.0,0.0)
		[Space]

		_laydist ("Connection Distance", Range(0,10)) = 3.0
		_laysag ("Arc Adjust", Range(-1,1)) = 0.1
		[IntRange]_roop ("Loop Amount",range(1,34)) = 20

		[Header(Render Settings)]
		[Space(10)]

		[Toggle] _ZWriteMode("ZWrite Enabled?", Int) = 1
		[Space]

		[Enum(Cull Off,0, Cull Front,1, Cull Back,2)] _CullMode("Culling", Float) = 0 //0 = off, 2=back
		[Space]

		[Enum(UnityEngine.Rendering.CompareFunction)] _ZTestMode("ZTest", Int) = 4

	}
	SubShader {
		Tags {"RenderType"="Opaque" "Queue" = "Overlay-702"}
		LOD 100
		grabpass{"_GrabTexture"}
		Pass {
			Cull[_CullMode]
			ZWrite[_ZWriteMode]
			ZTest[_ZTestMode]

			CGPROGRAM
			#pragma vertex vert
			#pragma geometry geom
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			#include "memoryHelper.cginc"
			#define SQRT3 1.7320508075688772935274463415059

			sampler2D _GrabTexture;
			sampler2D _MainTex; float4 _MainTex_ST;

			uniform float4 _position;
			uniform float4 _rotation;
			uniform float4 _scale;

			uniform int _direction;
			uniform float4 _color;
			uniform float _laydist;
			uniform int _pair;
			uniform float _laysag;
            sampler2D _Matcap;
            float _Range;
			float _roop;

			// taken from http://answers.unity.com/answers/641391/view.html
            float4x4 inverse(float4x4 input) {
                #define minor(a,b,c) determinant(float3x3(input.a, input.b, input.c))
                float4x4 cofactors = float4x4(
                    minor(_22_23_24, _32_33_34, _42_43_44), 
                    -minor(_21_23_24, _31_33_34, _41_43_44),
                    minor(_21_22_24, _31_32_34, _41_42_44),
                    -minor(_21_22_23, _31_32_33, _41_42_43),

                    -minor(_12_13_14, _32_33_34, _42_43_44),
                    minor(_11_13_14, _31_33_34, _41_43_44),
                    -minor(_11_12_14, _31_32_34, _41_42_44),
                    minor(_11_12_13, _31_32_33, _41_42_43),

                    minor(_12_13_14, _22_23_24, _42_43_44),
                    -minor(_11_13_14, _21_23_24, _41_43_44),
                    minor(_11_12_14, _21_22_24, _41_42_44),
                    -minor(_11_12_13, _21_22_23, _41_42_43),

                    -minor(_12_13_14, _22_23_24, _32_33_34),
                    minor(_11_13_14, _21_23_24, _31_33_34),
                    -minor(_11_12_14, _21_22_24, _31_32_34),
                    minor(_11_12_13, _21_22_23, _31_32_33)
                );
                #undef minor
                return transpose(cofactors) / determinant(input);
            }

			float4 curve(float x){
				float saga = (sin(x*UNITY_PI))*_laysag;
				return float4(mul(UNITY_MATRIX_V,float3(0.0,-saga,0.0)).xyz,0.0);
			}

			float3 rotate(float3 input, float angle, float3 axis){
				axis = normalize(axis);
				float3x3 rotation = float3x3(
					cos(angle)+axis.x*axis.x*(1-cos(angle)),
					axis.x*axis.y*(1-cos(angle))+axis.z*sin(angle),
					axis.z*axis.x*(1-cos(angle))-axis.y*sin(angle),

					axis.x*axis.y*(1-cos(angle))-axis.z*sin(angle),
					cos(angle)+axis.y*axis.y*(1-cos(angle)),
					axis.y*axis.z*(1-cos(angle))+axis.x*sin(angle),

					axis.z*axis.x*(1-cos(angle))+axis.y*sin(angle),
					axis.y*axis.z*(1-cos(angle))-axis.x*sin(angle),
					cos(angle)+axis.z*axis.z*(1-cos(angle))
				);
				float3 output = mul(rotation,input);
				return output;
			}

			float4 modelex(float4 input){
				float4 rotation = radians(_rotation);
				float4x4 xmat = {	float4(             1.0,            0.0,              0.0, 0.0),
									float4(             0.0, cos(rotation.x), sin(rotation.x), 0.0),
									float4(             0.0,-sin(rotation.x), cos(rotation.x), 0.0),
									float4(             0.0,             0.0,             0.0, 1.0),};

				float4x4 ymat = {	float4( cos(rotation.y),             0.0,-sin(rotation.y), 0.0),
									float4(             0.0,             1.0,             0.0, 0.0),
									float4( sin(rotation.y),             0.0, cos(rotation).y, 0.0),
									float4(             0.0,             0.0,             0.0, 1.0),};

				float4x4 zmat = {	float4( cos(rotation.z), sin(rotation.z),               0.0, 0.0),
									float4(-sin(rotation.z), cos(rotation.z),               0.0, 0.0),
									float4(             0.0,             0.0,               1.0, 1.0),
									float4(             0.0,             0.0,               0.0, 1.0),};

				return mul(xmat,mul(ymat,mul(zmat,input))) * _scale + _position;
			}

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

			struct v2g {
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
                float4 normal : TEXCOORD1;
			};

			struct g2f {
				float4 vertex : SV_POSITION;
				float2 uv : TEXCOORD0;
                float4 normal : TEXCOORD1;
			};
			
			v2g vert (appdata v) {
				v2g o;
				o.vertex = v.vertex;
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				o.normal = v.normal;
				return o;
			}

			[maxvertexcount(102)]
            void geom(triangle v2g input[3], uint primID : SV_PrimitiveID, inout TriangleStream<g2f> output) {
                g2f o;
				float4 buf = tex2Dlod(_GrabTexture,float4(memouvunpack_lay(),0.0,0.0)); //テクスチャから終端地点を読み取り
				
					float4 wpos = mul(UNITY_MATRIX_M,float4(0.0,0.0,0.0,1.0));

					float4 pos1 = float4(mul(UNITY_MATRIX_MV,float4(0.0,0.0,0.0,1.0)).xyz,1.0); //自分の位置
					float4 pos2 = float4(buf.xyz,1.0); pos2 = lerp(pos1,pos2,2.0); //テクスチャから読み取った位置
					float4 vertex;
					float3 vec,vec1;
					float axis1,axis2;

					float4 pos[35];
					[unroll]for(int index=0;index<35;index++){
						pos[index] = lerp(pos1,pos2,index/(_roop-1)) + curve(index/(_roop-1)); //posを線形補完＆ちょっとたるませる
						pos[index] = mul(inverse(UNITY_MATRIX_V),pos[index]);
					}

					[unroll]for(int index=0;index<34;index++){
						vec = normalize(pos[index]-pos[index+1]);
						vec1 = cross(vec,float3(0.0,1.0,0.0));
						axis1 = atan2(vec.x,vec.z);
						axis2 = atan2(length(vec.xz),vec.y);
						
						[unroll]for(int id=0;id<3;id++){
							vertex = modelex(input[id].vertex);
							vertex = float4(rotate(vertex.xyz,axis1,float3(0.0,1.0,0.0)),vertex.w);
							vertex = float4(rotate(vertex.xyz,axis2,vec1),vertex.w);
							vertex += wpos;
							o.vertex = mul(UNITY_MATRIX_VP,vertex+pos[index]);
							o.vertex = lerp(o.vertex,float4(-1.0,-1.0,-1.0,-1.0),step(_roop,index));
							o.vertex = lerp(o.vertex,float4(-1.0,-1.0,-1.0,-1.0),step(length(buf.rgb),0.01));
							o.uv = input[id].uv;
							o.normal = input[id].normal;
							output.Append(o);
						}
						output.RestartStrip();
					}

            }

			fixed4 frag (g2f i) : SV_Target {
				float4 col = tex2D(_MainTex,i.uv);
                float2 normalProj = normalize(i.normal.xyz) * 0.5 + 0.5;
                col *= tex2D(_Matcap, normalProj * _Range);
				return col * _color;
			}
			ENDCG
		}
		
	}
}
