#T#PoiVoronoiProperties
//ifex _VoronoiEnabled!=1
[HideInInspector] m_start_voronoi ("Voronoi--{reference_property:_VoronoiEnabled}", Int) = 0
[HideInInspector][ThryToggle(POI_VORONOI)]_VoronoiEnabled ("Voronoi Enabled", Int) = 0
[Enum(2D(Fast), 0, 3D(Fast with color bugs), 1, 3D(slow but no bugs), 2)] _VoronoiType ("Type", Int) = 1
[Enum(Local, 0, World, 1, UV, 2)] _VoronoiSpace ("Space", Int) = 0
[Enum(Color and Emission, 0, Just Emission, 1)] _VoronoiBlend ("Blend", Int) = 0
[ToggleUI]_VoronoiAffectsMaterialAlpha("Affects Material Alpha", Int) = 0

[sRGBWarning] _VoronoiMask ("Mask--{reference_properties:[_VoronoiMaskPan, _VoronoiMaskUV, _VoronoiMaskChannel]}", 2D) = "white" {}
[HideInInspector][Vector2] _VoronoiMaskPan ("Panning", Vector) = (0, 0, 0, 0)
[HideInInspector][ThryWideEnum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Panosphere, 4, World Pos XZ, 5, Polar UV, 6, Distorted UV, 7)] _VoronoiMaskUV ("UV", Int) = 0
[HideInInspector][Enum(R, 0, G, 1, B, 2, A, 3)] _VoronoiMaskChannel ("Channel", Int) = 0

[ThryWideEnum(Off, 0, 1R, 1, 1G, 2, 1B, 3, 1A, 4, 2R, 5, 2G, 6, 2B, 7, 2A, 8, 3R, 9, 3G, 10, 3B, 11, 3A, 12, 4R, 13, 4G, 14, 4B, 15, 4A, 16)] _VoronoiGlobalMask ("Global Mask--{reference_property:_VoronoiGlobalMaskBlendType}", Int) = 0
[HideInInspector][ThryWideEnum(Replace, 0, Darken, 1, Multiply, 2, Color Burn, 3, Linear Burn, 4, Lighten, 5, Screen, 6, Color Dodge, 7, Linear Dodge(Add), 8, Overlay, 9, Soft Lighten, 10, Hard Light, 11, Vivid Light, 12, Linear Light, 13, Pin Light, 14, Hard Mix, 15, Difference, 16, Exclusion, 17, Subtract, 18, Divide, 19)] _VoronoiGlobalMaskBlendType ("Blending", Int) = 2

[sRGBWarning] _VoronoiNoise ("Noise--{reference_properties:[_VoronoiNoisePan, _VoronoiNoiseUV, _VoronoiNoiseChannel]}", 2D) = "black" {}
[HideInInspector][Vector2] _VoronoiNoisePan ("Panning", Vector) = (0, 0, 0, 0)
[HideInInspector][ThryWideEnum(UV0, 0, UV1, 1, UV2, 2, UV3, 3, Panosphere, 4, World Pos XZ, 5, Polar UV, 6, Distorted UV, 7)] _VoronoiNoiseUV ("UV", Int) = 0
[HideInInspector][Enum(R, 0, G, 1, B, 2, A, 3)] _VoronoiNoiseChannel ("Channel", Int) = 0

_VoronoiNoiseIntensity ("Noise Intensity", Range(0, 1)) = .1
_VoronoiOuterColor ("Outer Color", Color) = (0, 0, 0, 1)
_VoronoiOuterEmissionStrength ("Outer Emission", Range(0, 20)) = 0
_VoronoiInnerColor ("Inner Color", Color) = (1, 1, 1, 1)
_VoronoiInnerEmissionStrength ("Inner Emission", Range(0, 20)) = 0
[Vector2]_VoronoiGradient ("Gradient", Vector) = (0, 0.5, 0, 0)
_VoronoiPower ("Power", Float) = 0.45454545
_VoronoiScale ("Scale", Float) = 5.0
[Vector3]_VoronoiSpeed ("Speed", Vector) = (1.0, 1.0, 1.0)

[HideInInspector] m_start_voronoiRandom ("Voronoi Random Cell Color--{reference_property:_VoronoiEnableRandomCellColor}", Int) = 0
[HideInInspector][ToggleUI]_VoronoiEnableRandomCellColor ("Rando Cell Col", Int) = 0
[MultiSlider]_VoronoiRandomMinMaxSaturation ("Saturation Range", Vector) = (0.8, 1, 0, 1)
[MultiSlider]_VoronoiRandomMinMaxBrightness ("Brightness Range", Vector) = (0.8, 1, 0, 1)
[HideInInspector] m_end_voronoiRandom ("Voronoi Random Cell Color", Float) = 0

[HideInInspector] m_start_VoronoiAudioLink ("Audio Link ♫--{condition_showS:_EnableAudioLink==1}", Float) = 0
[Enum(Bass, 0, Low Mid, 1, High Mid, 2, Treble, 3)] _AudioLinkVoronoiInnerEmissionBand ("Inner Emission Band", Int) = 0
[VectorLabel(Min, Max)]_AudioLinkVoronoiInnerEmission ("Inner Emission Mod", Vector) = (0, 0, 0, 0)
	[Space(7)]
[Enum(Bass, 0, Low Mid, 1, High Mid, 2, Treble, 3)] _AudioLinkVoronoiOuterEmissionBand ("Outer Emission Band", Int) = 0
[VectorLabel(Min, Max)]_AudioLinkVoronoiOuterEmission ("Outer Emission Mod", Vector) = (0, 0, 0, 0)
	[Space(7)]
[Enum(Bass, 0, Low Mid, 1, High Mid, 2, Treble, 3)] _AudioLinkVoronoiGradientMinAddBand ("Gradient Min Band", Int) = 0
_AudioLinkVoronoiGradientMinAdd ("Gradient Min Add", Float) = 0
	[Space(7)]
[Enum(Bass, 0, Low Mid, 1, High Mid, 2, Treble, 3)] _AudioLinkVoronoiGradientMaxAddBand ("Gradient Max Band", Int) = 0
_AudioLinkVoronoiGradientMaxAdd ("Gradient Max Add", Float) = 0
	[Space(7)]
[ThryWideEnum(Motion increases as intensity of band increases, 0, Above but Smooth, 1, Motion moves back and forth as a function of intensity, 2, Above but Smoooth, 3, Fixed speed increase when the band is dark Stationary when light, 4, Above but Smooooth, 5, Fixed speed increase when the band is dark Fixed speed decrease when light, 6, Above but Smoooooth, 7)]_AudioLinkVoronoiChronoSpeedXType ("Speed X Motion Type", Int) = 0
[Enum(Bass, 0, Low Mid, 1, High Mid, 2, Treble, 3)] _AudioLinkVoronoiChronoSpeedXBand ("Speed X Band", Int) = 0
_AudioLinkVoronoiChronoSpeedXSpeed ("Speed X", Float) = 0
[ThryWideEnum(Motion increases as intensity of band increases, 0, Above but Smooth, 1, Motion moves back and forth as a function of intensity, 2, Above but Smoooth, 3, Fixed speed increase when the band is dark Stationary when light, 4, Above but Smooooth, 5, Fixed speed increase when the band is dark Fixed speed decrease when light, 6, Above but Smoooooth, 7)]_AudioLinkVoronoiChronoSpeedYType ("Speed Y Motion Type", Int) = 0
[Enum(Bass, 0, Low Mid, 1, High Mid, 2, Treble, 3)] _AudioLinkVoronoiChronoSpeedYBand ("Speed Y Band", Int) = 0
_AudioLinkVoronoiChronoSpeedYSpeed ("Speed Y", Float) = 0
[ThryWideEnum(Motion increases as intensity of band increases, 0, Above but Smooth, 1, Motion moves back and forth as a function of intensity, 2, Above but Smoooth, 3, Fixed speed increase when the band is dark Stationary when light, 4, Above but Smooooth, 5, Fixed speed increase when the band is dark Fixed speed decrease when light, 6, Above but Smoooooth, 7)]_AudioLinkVoronoiChronoSpeedZType ("Speed Z Motion Type", Int) = 0
[Enum(Bass, 0, Low Mid, 1, High Mid, 2, Treble, 3)] _AudioLinkVoronoiChronoSpeedZBand ("Speed Z Band", Int) = 0
_AudioLinkVoronoiChronoSpeedZSpeed ("Speed Z", Float) = 0
[HideInInspector] m_end_VoronoiAudioLink ("Audio Link", Float) = 0

[HideInInspector] m_end_voronoi ("Voronoi", Float) = 0
//endex
#T#PoiVoronoiKeywords
//ifex _VoronoiEnabled!=1
#pragma shader_feature_local POI_VORONOI
//endex
#T#PoiVoronoiVariables
//ifex _VoronoiEnabled!=1
#ifdef POI_VORONOI
#if defined(PROP_VORONOIMASK) || !defined(OPTIMIZER_ENABLED)
	Texture2D _VoronoiMask;
	float4 _VoronoiMask_ST;
	float2 _VoronoiMaskPan;
	float _VoronoiMaskUV;
	int _VoronoiMaskChannel;
#endif
#if defined(PROP_VORONOINOISE) || !defined(OPTIMIZER_ENABLED)
	Texture2D _VoronoiNoise;
	float4 _VoronoiNoise_ST;
	float2 _VoronoiNoisePan;
	float _VoronoiNoiseUV;
	int _VoronoiNoiseChannel;
#endif
int _VoronoiSpace;
int _VoronoiBlend;
int _VoronoiType;
float4 _VoronoiOuterColor;
float _VoronoiOuterEmissionStrength;
float4 _VoronoiInnerColor;
float _VoronoiInnerEmissionStrength;
float _VoronoiPower;
float2 _VoronoiGradient;
float _VoronoiScale;
float3 _VoronoiSpeed;
float _VoronoiEnableRandomCellColor;
float2 _VoronoiRandomMinMaxSaturation;
float2 _VoronoiRandomMinMaxBrightness;
float _VoronoiNoiseIntensity;
int _VoronoiAffectsMaterialAlpha;
float _VoronoiGlobalMask;
float _VoronoiGlobalMaskBlendType;

// AudioLink
int _AudioLinkVoronoiInnerEmissionBand;
float2 _AudioLinkVoronoiInnerEmission;
int _AudioLinkVoronoiOuterEmissionBand;
float2 _AudioLinkVoronoiOuterEmission;

int _AudioLinkVoronoiGradientMinAddBand;
float _AudioLinkVoronoiGradientMinAdd;
int _AudioLinkVoronoiGradientMaxAddBand;
float _AudioLinkVoronoiGradientMaxAdd;

int _AudioLinkVoronoiChronoSpeedXType;
int _AudioLinkVoronoiChronoSpeedXBand;
float _AudioLinkVoronoiChronoSpeedXSpeed;
int _AudioLinkVoronoiChronoSpeedYType;
int _AudioLinkVoronoiChronoSpeedYBand;
float _AudioLinkVoronoiChronoSpeedYSpeed;
int _AudioLinkVoronoiChronoSpeedZType;
int _AudioLinkVoronoiChronoSpeedZBand;
float _AudioLinkVoronoiChronoSpeedZSpeed;
#endif
//endex
#T#PoiVoronoiFunction
//ifex _VoronoiEnabled!=1
#ifdef POI_VORONOI
	//1/7
	#define VoronoiK 0.142857142857
	//3/7
	#define VoronoiKo 0.428571428571
	// Permutation polynomial: (34x^2 + x) mod 289
	float3 Permutation(float3 x)
	{
		return glsl_mod((34.0 * x + 1.0) * x, 289.0);
	}
	
	float3 inoise(float3 P, float jitter, out float3 randomPoint)
	{
		P *= 0.7f; // Scale adjustment
		float3 Pi = glsl_mod(floor(P), 289.0);
		float3 Pf = frac(P);
		float3 oi = float3(-1.0, 0.0, 1.0);
		float3 of = float3(-0.5, 0.5, 1.5);
		float3 px = Permutation(Pi.x + oi);
		float3 py = Permutation(Pi.y + oi);
		float3 pz = Permutation(Pi.z + oi);
		
		float3 p, ox, oy, oz, dx, dy, dz;
		float3 F = 1e6;
		
		[unroll(3)]
		for (int i = 0; i < 3; i ++)
		{
			[unroll(3)]
			for (int j = 0; j < 3; j ++)
			{
				[unroll(3)]
				for (int k = 0; k < 3; k ++)
				{
					p = Permutation(px[i] + py[j] + pz[k] + oi); // pij1, pij2, pij3
					float3 ogp = p;
					
					ox = frac(p * VoronoiK) - VoronoiKo;
					oy = glsl_mod(floor(p * VoronoiK), 7.0) * VoronoiK - VoronoiKo;
					
					p = Permutation(p);
					oz = frac(p * VoronoiK) - VoronoiKo;
					
					dx = Pf.x - of[i] + jitter * ox;
					dy = Pf.y - of[j] + jitter * oy;
					dz = Pf.z - of[k] + jitter * oz;
					
					float3 d = dx * dx + dy * dy + dz * dz; // dij1, dij2 and dij3, squared
					
					//Find lowest and second lowest distances
					for (int n = 0; n < 3; n ++)
					{
						if (d[n] < F[0])
						{
							F[1] = F[0];
							F[0] = d[n];
							randomPoint = p;
						}
						else if(d[n] < F[1])
						{
							F[1] = d[n];
						}
					}
				}
			}
		}
		
		return F;
	}
	

	float voronoi2D(in float2 x, float scale, float2 speed, out float2 randomPoint)
	{
		x *= scale;
		x += speed * _Time.x;
		float2 n = floor(x);
		float2 f = frac(x);
		
		// first pass: regular voronoi
		float2 mg, mr;
		float md = 8.0;
		for (int j = -1; j <= 1; j ++)
		{
			for (int i = -1; i <= 1; i ++)
			{
				float2 g = float2(float(i), float(j));
				float2 o = random2(n + g);
				float2 currentPoint = o;
				
				float2 r = g + o - f;
				float d = dot(r, r);
				
				if (d < md)
				{
					md = d;
					mr = r;
					mg = g;
					randomPoint.xy = currentPoint;
				}
			}
		}
		
		// second pass: distance to borders
		md = 8.0;
		for (int r = -2; r <= 2; r ++)
		{
			for (int q = -2; q <= 2; q ++)
			{
				float2 g = mg + float2(float(q), float(r));
				float2 o = random2(n + g);
				
				float2 r = g + o - f;
				
				if (dot(mr - r, mr - r) > 0.00001)
				{
					md = min(md, dot(0.5 * (mr + r), normalize(r - mr)));
				}
			}
		}
		return md;
	}
	
	float voronoi3D(in float3 x, float scale, float3 speed, out float3 randomPoint)
	{
		x *= scale;
		x += speed * _Time.x;
		float3 n = floor(x);
		float3 f = frac(x);
		
		// first pass: regular voronoi
		float3 mg, mr;
		float md = 8.0;
		for (int j = -1; j <= 1; j ++)
		{
			for (int i = -1; i <= 1; i ++)
			{
				for (int h = -1; h <= 1; h ++)
				{
					float3 g = float3(float(h), float(i), float(j));
					float3 o = random3(n + g);
					float3 currentPoint = o;
					
					float3 r = g + o - f;
					float d = dot(r, r);
					
					if (d < md)
					{
						md = d;
						mr = r;
						mg = g;
						randomPoint = currentPoint;
					}
				}
			}
		}
		
		// second pass: distance to borders
		md = 8.0;
		for (int r = -2; r <= 2; r ++)
		{
			for (int q = -2; q <= 2; q ++)
			{
				for (int p = -2; p <= 2; p ++)
				{
					float3 g = mg + float3(float(p), float(q), float(r));
					float3 o = random3(n + g);
					
					float3 r = g + o - f;
					
					if (dot(mr - r, mr - r) > 0.00001)
					{
						md = min(md, dot(0.5 * (mr + r), normalize(r - mr)));
					}
				}
			}
		}
		return md;
	}
	
	
	
	// fracal sum, range -1.0 - 1.0
	float VoronoiNoise_Octaves(float3 p, float scale, float3 speed, int octaveNumber, float octaveScale, float octaveAttenuation, float jitter, float time, out float3 randomPoint)
	{
		float freq = scale;
		float weight = 1.0f;
		float sum = 0;
		// Uncomment when the octave stuff is actually used
		// for (int i = 0; i < octaveNumber; i ++)
		// {
			float3 F = inoise(p * freq + time * speed, jitter, randomPoint) * weight;
			
			sum += sqrt(F[0]);
			
		// 	freq *= octaveScale;
		// 	weight *= 1.0f - octaveAttenuation;
		// }
		return sum;
	}
	
	float VoronoiNoiseDiff_Octaves(float3 p, float scale, float3 speed, int octaveNumber, float octaveScale, float octaveAttenuation, float jitter, float time, out float3 randomPoint)
	{
		float freq = scale;
		float weight = 1.0f;
		float sum = 0;
		// Uncomment when the octave stuff is actually used
		// for (int i = 0; i < octaveNumber; i ++)
		// {
			float3 F = inoise(p * freq + time * speed, jitter, randomPoint) * weight;
			
			sum += sqrt(F[1]) - sqrt(F[0]);
			
			// freq *= octaveScale;
			// weight *= 1.0f - octaveAttenuation;
		// }
		return sum;
	}
	
	void ApplyVoronoi(inout PoiFragData poiFragData, in PoiMesh poiMesh, in PoiMods poiMods)
	{
		float voronoiOctaveNumber = 1;
		float voronoiOctaveScale = 1;
		float voronoiOctaveAttenuation = 1;
		float3 randomPoint = 0;
		
		float voronoi = 0;
		
		float3 position = 0;
		
		UNITY_BRANCH
		if (_VoronoiSpace == 0)
		{
			position = poiMesh.localPos;
		}
		UNITY_BRANCH
		if(_VoronoiSpace == 1)
		{
			position = poiMesh.worldPos;
		}
		UNITY_BRANCH
		if(_VoronoiSpace == 2)
		{
			position = float3(poiMesh.uv[0].x, poiMesh.uv[0].y, 0);
		}
		#if defined(PROP_VORONOIMASK) || !defined(OPTIMIZER_ENABLED)
			float mask = POI2D_SAMPLER_PAN(_VoronoiMask, _MainTex, poiUV(poiMesh.uv[_VoronoiMaskUV], _VoronoiMask_ST), _VoronoiMaskPan)[_VoronoiMaskChannel];
		#else
			float mask = 1;
		#endif

		if (_VoronoiGlobalMask > 0)
		{
			mask = customBlend(mask, poiMods.globalMask[_VoronoiGlobalMask-1], _VoronoiGlobalMaskBlendType);
		}

		#if defined(PROP_VORONOINOISE) || !defined(OPTIMIZER_ENABLED)
			float edgeNoise = POI2D_SAMPLER_PAN(_VoronoiNoise, _MainTex, poiUV(poiMesh.uv[_VoronoiNoiseUV], _VoronoiNoise_ST), _VoronoiNoisePan)[_VoronoiNoiseChannel];
		#else
			float edgeNoise = 0;
		#endif
		edgeNoise *= _VoronoiNoiseIntensity;

		float3 voronoiSpeed = _VoronoiSpeed * 10;
		#ifdef POI_AUDIOLINK
			voronoiSpeed.x += AudioLinkGetChronoTime(_AudioLinkVoronoiChronoSpeedXType, _AudioLinkVoronoiChronoSpeedXBand) * _AudioLinkVoronoiChronoSpeedXSpeed * 0.01 * _AudioLinkAnimToggle;
			voronoiSpeed.y += AudioLinkGetChronoTime(_AudioLinkVoronoiChronoSpeedYType, _AudioLinkVoronoiChronoSpeedYBand) * _AudioLinkVoronoiChronoSpeedYSpeed * 0.01 * _AudioLinkAnimToggle;
			voronoiSpeed.z += AudioLinkGetChronoTime(_AudioLinkVoronoiChronoSpeedZType, _AudioLinkVoronoiChronoSpeedZBand) * _AudioLinkVoronoiChronoSpeedZSpeed * 0.01 * _AudioLinkAnimToggle;
		#endif
		
		if(_VoronoiType == 0) // Basic
		{
			voronoi = voronoi2D(position.xy, _VoronoiScale, voronoiSpeed, randomPoint.xy);
			voronoi *= 1.55; // Range adjustment
		}
		if (_VoronoiType == 1) // Diff
		{
			voronoi = VoronoiNoiseDiff_Octaves(position, _VoronoiScale, voronoiSpeed, voronoiOctaveNumber, voronoiOctaveScale, voronoiOctaveAttenuation, 1, _Time.x, randomPoint);
		}
		if (_VoronoiType == 2) // Fixed Border
		{
			voronoi = voronoi3D(position, _VoronoiScale, voronoiSpeed, randomPoint);
			voronoi *= 1.8; // Range adjustment
		}

		float4 outerColor = _VoronoiOuterColor;
		float4 innerColor = _VoronoiInnerColor;
		
		if (_VoronoiEnableRandomCellColor == 1)
		{
			float3 rando = random3(randomPoint);
			fixed hue = rando.x;
			fixed saturation = lerp(_VoronoiRandomMinMaxSaturation.x, _VoronoiRandomMinMaxSaturation.y, rando.y);
			fixed value = lerp(_VoronoiRandomMinMaxBrightness.x, _VoronoiRandomMinMaxBrightness.y, rando.z);
			float3 hsv = float3(hue, saturation, value);
			innerColor.rgb = HSVtoRGB(hsv);
		}
		voronoi = pow(voronoi, _VoronoiPower);
		float2 voronoiGradient = _VoronoiGradient.xy + edgeNoise;
		#ifdef POI_AUDIOLINK
			voronoiGradient.x += _AudioLinkVoronoiGradientMinAdd * poiMods.audioLink[_AudioLinkVoronoiGradientMinAddBand];
			voronoiGradient.y -= _AudioLinkVoronoiGradientMaxAdd * poiMods.audioLink[_AudioLinkVoronoiGradientMaxAddBand];
		#endif
		float ramp = smoothstep(voronoiGradient.x, voronoiGradient.y, voronoi);
		
		if(_VoronoiBlend == 0)
		{
			float4 voronoiColor = lerp(outerColor, innerColor, ramp);
			poiFragData.baseColor.rgb = lerp(poiFragData.baseColor.rgb, voronoiColor, min(mask * voronoiColor.a, 0.99999));
			if(_VoronoiAffectsMaterialAlpha)
			{
				poiFragData.alpha = lerp(poiFragData.alpha, voronoiColor.a, min(mask, 0.99999));
			}
		}
		float outerEmissionStrength = _VoronoiOuterEmissionStrength;
		float innerEmissionStrength = _VoronoiInnerEmissionStrength;
		#ifdef POI_AUDIOLINK
			outerEmissionStrength += lerp(_AudioLinkVoronoiOuterEmission.x, _AudioLinkVoronoiOuterEmission.y, poiMods.audioLink[_AudioLinkVoronoiOuterEmissionBand]);
			innerEmissionStrength += lerp(_AudioLinkVoronoiInnerEmission.x, _AudioLinkVoronoiInnerEmission.y, poiMods.audioLink[_AudioLinkVoronoiInnerEmissionBand]);
		#endif
		float4 voronoiEmissionColor = lerp(outerColor, innerColor, ramp);
		voronoiEmissionColor.rgb *= lerp(outerEmissionStrength, innerEmissionStrength, ramp); 
		poiFragData.emission += voronoiEmissionColor.rgb * mask * voronoiEmissionColor.a;
	}
#endif
//endex
#T#PoiVoronoiFunctionCall
//ifex _VoronoiEnabled!=1
#ifdef POI_VORONOI
	ApplyVoronoi(poiFragData, poiMesh, poiMods);
#endif
//endex

