Shader "Quantum/Flat Lit Toon/Tex Layers"
{
	Properties
	{
		_MainTex("MainTex", 2D) = "white" {}
		_Color("Color", Color) = (1,1,1,1)
		_ColorMask("ColorMask", 2D) = "black" {}
		_Shadow("Shadow", Range(0, 1)) = 0.4
		_outline_width("outline_width", Float) = 0.2
		_outline_color("outline_color", Color) = (0.5,0.5,0.5,1)
		_outline_tint("outline_tint", Range(0, 1)) = 0.5
		_EmissionMap("Emission Map", 2D) = "white" {}
		[HDR]_EmissionColor("Emission Color", Color) = (0,0,0,1)
		_BumpMap("BumpMap", 2D) = "bump" {}
		_Cutoff("Alpha cutoff", Range(0,1)) = 0.5

		_hearts_angle("Hearts Angle", Range(0,360)) = 0.0
		_EffectMask("Effect Mask", 2D) = "white" {}
		_StarLayers("star layers", Float) = 2.0
		[ToggleOff]  _IndividualColors("individ colors", Float) = 0.0
		//STARLAYER 1
		[ToggleOff]  _stars1_rainbow ("Stars1 Rainbow Color", Float) = 0.0
		[ToggleOff]  _stars1_uniform ("Stars1 Uniform Color", Float) = 0.0
		_stars1_rb_speed("Stars1 Rainbow Speed", Range(0,100)) = 5.0
		_stars1_offset("stars1 Offset", Vector) = (0.0,0.0,0.0,0.0)
		_stars1_size("Stars1 Size", Range(0,100)) = 10.0
		_stars1_speed("Stars1 Speed", Range(0,100)) = 5.0
		_stars1_c1("stars1 c1", Color) = (1.0,0.0,0.0,1.0)
		_stars1_c2("stars1 c2", Color) = (1.0,0.5,0.5,1.0)
		_stars1_c3("stars1 c3", Color) = (1.0,0.0,0.5,1.0)
		_stars1_tex("Stars1 Texture", 2D) = "white" {}
		//STARLAYER 2
		[ToggleOff]  _stars2_rainbow ("Stars2 Rainbow Color", Float) = 0.0
		[ToggleOff]  _stars2_uniform ("Stars2 Uniform Color", Float) = 0.0
		_stars2_rb_speed("Stars2 Rainbow Speed", Range(0,100)) = 5.0
		_stars2_offset("stars2 Offset", Vector) = (0.0,0.0,1.0,0.0)
		_stars2_size("Stars2 Size", Range(0,100)) = 3.0
		_stars2_speed("Stars2 Speed", Range(0,100)) = 5.0
		_stars2_c1("stars2 c1", Color) = (1.0,0.0,0.0,1.0)
		_stars2_c2("stars2 c2", Color) = (1.0,0.5,0.5,1.0)
		_stars2_c3("stars2 c3", Color) = (1.0,0.0,0.5,1.0)
		_stars2_tex("Stars2 Texture", 2D) = "white" {}
		//STARLAYER 3
		[ToggleOff]  _stars3_rainbow ("Stars3 Rainbow Color", Float) = 0.0
		[ToggleOff]  _stars3_uniform ("Stars3 Uniform Color", Float) = 0.0
		_stars3_rb_speed("Stars3 Rainbow Speed", Range(0,100)) = 5.0
		_stars3_offset("stars3 Offset", Vector) = (0.0,0.0,2.0,0.0)
		_stars3_size("Stars3 Size", Range(0,100)) = 1.0
		_stars3_speed("Stars3 Speed", Range(0,100)) = 5.0
		_stars3_c1("stars3 c1", Color) = (1.0,0.0,0.0,1.0)
		_stars3_c2("stars3 c2", Color) = (1.0,0.5,0.5,1.0)
		_stars3_c3("stars3 c3", Color) = (1.0,0.0,0.5,1.0)
		_stars3_tex("Stars3 Texture", 2D) = "white" {}

		// Blending state
		[HideInInspector] _Mode ("__mode", Float) = 0.0
		[HideInInspector] _OutlineMode("__outline_mode", Float) = 0.0
		[HideInInspector] _SrcBlend ("__src", Float) = 1.0
		[HideInInspector] _DstBlend ("__dst", Float) = 0.0
		[HideInInspector] _ZWrite ("__zw", Float) = 1.0
	}

	CGINCLUDE

	float2 noise_2d(float3 p) {
		p.z += frac(sin(dot(floor(p).xy,float2(127.1, 311.7)))*43758.5453);
		float f = frac(p.z);
		float2 u = f*f*(3.0-2.0*f);
		p.z = floor(p.z);
		float2 t1 = frac(sin(float2(dot(p,float3(127.1,311.7,413.5)),dot(p,float3(269.5,183.3,197.7))))*43758.5453);
		p.z+=1.0;
		float2 t2 = frac(sin(float2(dot(p,float3(127.1,311.7,413.5)),dot(p,float3(269.5,183.3,197.7))))*43758.5453);
		return float2(t1*(1.0-u) + t2*u);
	}

	float3 hsv2rgb(float3 c){
		float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
		float3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
		return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
	}

	float _hearts_angle;

	float4 voronoi(float2 x, float t, float3 c1, float3 c2, float3 c3, float uni, sampler2D samp){
		float2 n = floor(x);
		float2 f = frac(x);
		//0.01745329251994329576923690768489 = 1.0/360.0*3.141*2.
		float angle = _hearts_angle*0.01745329251994329576923690768489;
		float2x2 rotate = float2x2(cos(angle), -sin(angle), sin(angle), cos(angle));

		// first pass: regular voronoi
		float2 mg, mr, mx;
		float3 col = float3(0,0,0);
		float md = 8.0, mv;
		float2 uniTint = noise_2d(float3(0.0, 0.0, t));
		for (int j1= -1; j1 <= 1; j1++) {
			for (int i1= -1; i1 <= 1; i1++) {
				float2 g = float2(float(i1),float(j1));
				float2 o = noise_2d(float3(n + g, t));

				float2 r = g + o - f;
				float d = dot(r,r);
				float v = length(o);
				if( d < md ) {
					md = d;
					mr = r;
					mg = g;
					mv = v;
				}
				float3 tint;
				if(uni != 0.0){
					tint = c1*uniTint.x + c2*(1.0-(uniTint.x+uniTint.y)) + c3*uniTint.y;
				}else{
					if((o.x + o.y) > 1.0){
						o = 1.0 - o;
					}
					tint = c1*o.x + c2*(1.0-(o.x+o.y)) + c3*o.y;
				}
				r*= 4.0 + 4.0*v;
				r = mul(r, rotate);
				if(abs(r.x) <= 1.0 && abs(r.y) <= 1.0){
					col += tex2D(samp, r/2.0 + 0.5) * tint;
				}
			}
		}
		return float4(col, 1);
	}

	float4 voronoi_rainbow(float2 x, float t, float speed, float uni, sampler2D samp){
		float2 n = floor(x);
		float2 f = frac(x);
		//0.01745329251994329576923690768489 = 1.0/360.0*3.141*2.
		float angle = _hearts_angle*0.01745329251994329576923690768489;
		float2x2 rotate = float2x2(cos(angle), -sin(angle), sin(angle), cos(angle));

		// first pass: regular voronoi
		float2 mg, mr, mx;
		float3 col = float3(0,0,0);
		float md = 8.0, mv;
		for (int j1= -1; j1 <= 1; j1++) {
			for (int i1= -1; i1 <= 1; i1++) {
				float2 g = float2(float(i1),float(j1));
				float2 o = noise_2d(float3(n + g, t));

				float2 r = g + o - f;
				float d = dot(r,r);
				float v = length(o);
				if( d < md ) {
					md = d;
					mr = r;
					mg = g;
					mv = v;
				}
				r*= 4.0 + 4.0*v;
				r = mul(r, rotate);
				if(abs(r.x) <= 1.0 && abs(r.y) <= 1.0){
					if(uni != 0.0){
						col += tex2D(samp, r/2.0 + 0.5) * hsv2rgb(float3((_Time.x+frac(sin(311.7)*43758.5453))*speed, 1.0, 1.0));
					}else{
						col += tex2D(samp, r/2.0 + 0.5) * hsv2rgb(float3((_Time.x+frac(sin(dot(floor(n + g).xy,float2(127.1, 311.7)))*43758.5453))*speed, 1.0, 1.0));
					}
				}
			}
		}
		return float4(col, 1);
	}
	ENDCG

	SubShader
	{
		Tags
		{
			"RenderType" = "Opaque"
		}

		Pass
		{

			Name "FORWARD"
			Tags { "LightMode" = "ForwardBase" }

			Blend [_SrcBlend] [_DstBlend]
			ZWrite [_ZWrite]

			CGPROGRAM
			#include "FlatLitToonCore.cginc"
			#pragma shader_feature NO_OUTLINE TINTED_OUTLINE COLORED_OUTLINE
			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
			#pragma shader_feature _SECOND_LAYER
			#pragma shader_feature _THIRD_LAYER
			#pragma shader_feature _UNIFORM_COLOR
			#pragma shader_feature _RAINBOW_L1
			#pragma shader_feature _RAINBOW_L2
			#pragma shader_feature _RAINBOW_L3
			#pragma vertex vert
			#pragma geometry geom
			#pragma fragment frag

			#pragma only_renderers d3d11 glcore gles
			#pragma target 4.0

			#pragma multi_compile_fwdbase
			#pragma multi_compile_fog

			float _IndividualColors;

			sampler2D _EffectMask;

			float _stars1_rainbow;
			float _stars1_uniform;
			float _stars1_rb_speed;
			float _stars1_size;
			float _stars1_speed;
			float4 _stars1_offset;
			float4 _stars1_c1;
			float4 _stars1_c2;
			float4 _stars1_c3;

			float _stars2_rainbow;
			float _stars2_uniform;
			float _stars2_rb_speed;
			float _stars2_size;
			float _stars2_speed;
			float4 _stars2_offset;
			float4 _stars2_c1;
			float4 _stars2_c2;
			float4 _stars2_c3;

			float _stars3_rainbow;
			float _stars3_uniform;
			float _stars3_rb_speed;
			float _stars3_size;
			float _stars3_speed;
			float4 _stars3_offset;
			float4 _stars3_c1;
			float4 _stars3_c2;
			float4 _stars3_c3;

			sampler2D _stars1_tex;
			sampler2D _stars2_tex;
			sampler2D _stars3_tex;

			float4 frag(VertexOutput i) : COLOR
			{
				float4 _ColorMask_var = tex2D(_ColorMask,TRANSFORM_TEX(i.uv0, _ColorMask));
				float4 objPos = mul(unity_ObjectToWorld, float4(0,0,0,1));
				i.normalDir = normalize(i.normalDir);
				float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir);
				float3 _BumpMap_var = UnpackNormal(tex2D(_BumpMap,TRANSFORM_TEX(i.uv0, _BumpMap)));
				float3 normalDirection = normalize(mul(_BumpMap_var.rgb, tangentTransform)); // Perturbed normals
				float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));
				float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
				float3 lightColor = _LightColor0.rgb;
				UNITY_LIGHT_ATTENUATION(attenuation, i, i.posWorld.xyz);

				float4 _EmissionMap_var = tex2D(_EmissionMap,TRANSFORM_TEX(i.uv0, _EmissionMap));
				float3 emissive = (_EmissionMap_var.rgb*_EmissionColor.rgb);
				//>>>>>>>>>>>>>>>>>>>>>>>>>>>>CUSTOM <<<<<<<<<<<<<<<<<<<<<<<<<//
				if(tex2D(_EffectMask,TRANSFORM_TEX(i.uv0, _MainTex)).r > 0.0){
					#if _UNIFORM_COLOR
						#if _RAINBOW_L1
							emissive += voronoi_rainbow((i.uv0.xy+_stars1_offset.xy)*(100.0/_stars1_size), (_Time.x+_stars1_offset.z)*_stars1_speed, _stars1_rb_speed, _stars1_uniform, _stars1_tex);
						#else
							emissive += voronoi((i.uv0.xy+_stars1_offset.xy)*(100.0/_stars1_size), (_Time.x+_stars1_offset.z)*_stars1_speed, _stars1_c1, _stars1_c2, _stars1_c3, _stars1_uniform, _stars1_tex);
						#endif
						#if _SECOND_LAYER
							#if _RAINBOW_L2
								emissive += voronoi_rainbow((i.uv0.xy+_stars2_offset.xy)*(100.0/_stars2_size), (_Time.x+_stars2_offset.z)*_stars2_speed, _stars2_rb_speed, _stars2_uniform, _stars2_tex);
							#else
								emissive += voronoi((i.uv0.xy+_stars2_offset.xy)*(100.0/_stars2_size), (_Time.x+_stars2_offset.z)*_stars2_speed, _stars2_c1, _stars2_c2, _stars2_c3, _stars2_uniform, _stars2_tex);
							#endif
							#if _THIRD_LAYER
								#if _RAINBOW_L3
									emissive += voronoi_rainbow((i.uv0.xy+_stars3_offset.xy)*(100.0/_stars3_size), (_Time.x+_stars3_offset.z)*_stars3_speed, _stars3_rb_speed, _stars3_uniform, _stars3_tex);
								#else
									emissive += voronoi((i.uv0.xy+_stars3_offset.xy)*(100.0/_stars3_size), (_Time.x+_stars3_offset.z)*_stars3_speed, _stars3_c1, _stars3_c2, _stars3_c3, _stars3_uniform, _stars3_tex);
								#endif
							#endif
						#endif
					#else
						#if _RAINBOW_L1
							emissive += voronoi_rainbow((i.uv0.xy+_stars1_offset.xy)*(100.0/_stars1_size), (_Time.x+_stars1_offset.z)*_stars1_speed, _stars1_rb_speed, _stars1_uniform, _stars1_tex);
							#if _SECOND_LAYER
								emissive += voronoi_rainbow((i.uv0.xy+_stars2_offset.xy)*(100.0/_stars2_size), (_Time.x+_stars2_offset.z)*_stars2_speed, _stars1_rb_speed, _stars1_uniform, _stars2_tex);
								#if _THIRD_LAYER
									emissive += voronoi_rainbow((i.uv0.xy+_stars3_offset.xy)*(100.0/_stars3_size), (_Time.x+_stars3_offset.z)*_stars3_speed, _stars1_rb_speed, _stars1_uniform, _stars3_tex);
								#endif
							#endif
						#else
							emissive += voronoi((i.uv0.xy+_stars1_offset.xy)*(100.0/_stars1_size), (_Time.x+_stars1_offset.z)*_stars1_speed, _stars1_c1, _stars1_c2, _stars1_c3, _stars1_uniform, _stars1_tex);
							#if _SECOND_LAYER
								emissive += voronoi((i.uv0.xy+_stars2_offset.xy)*(100.0/_stars2_size), (_Time.x+_stars2_offset.z)*_stars2_speed, _stars1_c1, _stars1_c2, _stars1_c3, _stars1_uniform, _stars2_tex);
								#if _THIRD_LAYER
									emissive += voronoi((i.uv0.xy+_stars3_offset.xy)*(100.0/_stars3_size), (_Time.x+_stars3_offset.z)*_stars3_speed, _stars1_c1, _stars1_c2, _stars1_c3, _stars1_uniform, _stars3_tex);
								#endif
							#endif
						#endif
					#endif
				}
				//>>>>>>>>>>>>>>>>>>>>>>>>>>>>CUSTOM <<<<<<<<<<<<<<<<<<<<<<<<<//
				float4 baseColor = lerp((_MainTex_var.rgba*_Color.rgba),_MainTex_var.rgba,_ColorMask_var.r);
				baseColor *= float4(i.col.rgb, 1);

				#if COLORED_OUTLINE
				if(i.is_outline)
				{
					baseColor.rgb = i.col.rgb;
				}
				#endif

				#if defined(_ALPHATEST_ON)
        		clip (baseColor.a - _Cutoff);
    			#endif

				float3 lightmap = float4(1.0,1.0,1.0,1.0);
				#ifdef LIGHTMAP_ON
				lightmap = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv1 * unity_LightmapST.xy + unity_LightmapST.zw));
				#endif

				float3 reflectionMap = DecodeHDR(UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, normalize((_WorldSpaceCameraPos - objPos.rgb)), 7), unity_SpecCube0_HDR)* 0.02;

				float grayscalelightcolor = dot(_LightColor0.rgb, grayscale_vector);
				float bottomIndirectLighting = grayscaleSH9(float3(0.0, -1.0, 0.0));
				float topIndirectLighting = grayscaleSH9(float3(0.0, 1.0, 0.0));
				float grayscaleDirectLighting = dot(lightDirection, normalDirection)*grayscalelightcolor*attenuation + grayscaleSH9(normalDirection);

				float lightDifference = topIndirectLighting + grayscalelightcolor - bottomIndirectLighting;
				float remappedLight = (grayscaleDirectLighting - bottomIndirectLighting) / lightDifference;

				float3 indirectLighting = saturate((ShadeSH9(half4(0.0, -1.0, 0.0, 1.0)) + reflectionMap));
				float3 directLighting = saturate((ShadeSH9(half4(0.0, 1.0, 0.0, 1.0)) + reflectionMap + _LightColor0.rgb));
				float3 directContribution = saturate((1.0 - _Shadow) + floor(saturate(remappedLight) * 2.0));
				float3 finalColor = emissive + (baseColor * lerp(indirectLighting, directLighting, directContribution));
				fixed4 finalRGBA = fixed4(finalColor * lightmap, baseColor.a);
				UNITY_APPLY_FOG(i.fogCoord, finalRGBA);

				return finalRGBA;
			}
			ENDCG
		}

		Pass
		{
			Name "FORWARD_DELTA"
			Tags { "LightMode" = "ForwardAdd" }
			Blend [_SrcBlend] One

			CGPROGRAM
			#pragma shader_feature NO_OUTLINE TINTED_OUTLINE COLORED_OUTLINE
			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
			#include "FlatLitToonCore.cginc"
			#pragma vertex vert
			#pragma geometry geom
			#pragma fragment frag

			#pragma only_renderers d3d11 glcore gles
			#pragma target 4.0

			#pragma multi_compile_fwdadd_fullshadows
			#pragma multi_compile_fog

			float4 frag(VertexOutput i) : COLOR
			{
				float4 objPos = mul(unity_ObjectToWorld, float4(0,0,0,1));
				i.normalDir = normalize(i.normalDir);
				float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir);
				float3 _BumpMap_var = UnpackNormal(tex2D(_BumpMap,TRANSFORM_TEX(i.uv0, _BumpMap)));
				float3 normalDirection = normalize(mul(_BumpMap_var.rgb, tangentTransform)); // Perturbed normals
				float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));

				float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
				float3 lightColor = _LightColor0.rgb;
				UNITY_LIGHT_ATTENUATION(attenuation, i, i.posWorld.xyz);

				float4 _ColorMask_var = tex2D(_ColorMask,TRANSFORM_TEX(i.uv0, _ColorMask));
				float4 baseColor = lerp((_MainTex_var.rgba*_Color.rgba),_MainTex_var.rgba,_ColorMask_var.r);
				baseColor *= float4(i.col.rgb, 1);

				#if COLORED_OUTLINE
				if(i.is_outline) {
					baseColor.rgb = i.col.rgb;
				}
				#endif

				#if defined(_ALPHATEST_ON)
        		clip (baseColor.a - _Cutoff);
    			#endif

				float lightContribution = dot(normalize(_WorldSpaceLightPos0.xyz - i.posWorld.xyz),normalDirection)*attenuation;
				float3 directContribution = floor(saturate(lightContribution) * 2.0);
				float3 finalColor = baseColor * lerp(0, _LightColor0.rgb, saturate(directContribution + ((1 - _Shadow) * attenuation)));
				fixed4 finalRGBA = fixed4(finalColor,1) * i.col;
				UNITY_APPLY_FOG(i.fogCoord, finalRGBA);

				return finalRGBA;
			}
			ENDCG
		}

		Pass
		{
			Name "SHADOW_CASTER"
			Tags{ "LightMode" = "ShadowCaster" }

			ZWrite On ZTest LEqual

			CGPROGRAM
			#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
			#include "FlatLitToonShadows.cginc"

			#pragma multi_compile_shadowcaster
			#pragma fragmentoption ARB_precision_hint_fastest

			#pragma only_renderers d3d11 glcore gles
			#pragma target 4.0

			#pragma vertex vertShadowCaster
			#pragma fragment fragShadowCaster
			ENDCG
		}
	}
	FallBack "Diffuse"
	CustomEditor "FlatLitToonInspectorTexLayers"
}
