Shader "CrispyPin/Sunset (Dynamic)"
{
	Properties
	{
		[Header(Sky)]
		_SkyCol ("Sky color", Color) = (0.22, 0.23, 0.58, 1.0)
		_HorizonCol ("Horizon color", Color) = (0.43, 0.27, 0.49, 1.0)
		[Header(Sun)]
		_SunCol ("Sun color", Color) = (1.0, 0.65, 0.05, 1.0)
		_SunAngle ("Sun angle", Range(0, 6.28)) = 0
		_SunRadius ("Sun radius", Range(0, 0.3)) = 0.06
		_SunCutoff ("Sun cutoff", Range(0, 0.5)) = 0.08
		[Header(Star Layout)]
		[NoScaleOffset]
		_MainTex ("Noise source", 2D) = "white" {}
		_StarDensity ("Star density", Range(4, 50)) = 20
		_StarRandom ("Star randomness", Range(0, 1)) = 0.85
		[Header(Star)]
		_StarsMissing ("Stars missing", Range(0, 1)) = 0.75
		_StarSize ("Star size", Range(0, 0.1)) = 0.06
		_StarSizeRandom ("Star size randomness", Range(0, 1)) = 0.5
		_StarTint ("Star tint", Range(0, 1)) = 0.4
		[Header(Debug)]
		_Grid ("Grid visibility", Range(0, 1)) = 0

	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100
		Cull back

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			#define PI 3.1416f
			#define WHITE fixed4(1.0, 1.0, 1.0, 1.0)

			struct appdata
			{
				float4 vertex : POSITION;
			};

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

			sampler2D _MainTex;
			fixed4 _SkyCol;
			fixed4 _HorizonCol;

			float _StarsMissing;
			float _StarDensity;
			float _StarRandom;

			float _StarSize;
			float _StarSizeRandom;
			float _StarTint;

			fixed4 _SunCol;
			float _SunAngle;
			float _SunRadius;
			float _SunCutoff;

			float _Grid;

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.camPos = _WorldSpaceCameraPos;
				o.hitPos = mul(unity_ObjectToWorld, v.vertex);
				return o;
			}

			fixed4 frag (v2f i) : SV_Target
			{
				float3 dir = normalize(i.hitPos - i.camPos);
				float y = asin(dir.y);
				float phi = atan2(dir.x, dir.z);

				/// sky
				float factor = smoothstep(0.0, 0.5, dir.y + 0.2);
				factor = min(factor, 1.0);
				fixed4 col = lerp(_HorizonCol, _SkyCol, factor);

				/// stars
				float2 cells = float2(-1, floor(_StarDensity));
				float cell_x_base = floor(cells.y * PI);
				float celly = y * cells.y;
				// cells per ring depend on y pos, to reduce warping around the poles:
				cells.x = max(floor(cos(floor(celly)/_StarDensity) * cell_x_base), 3);
				float cellx = (phi / PI * cells.x);

				float2 pos = float2(cellx, celly);// cell-space pos of this fragment
				float2 cell_pos = float2(floor(cellx), floor(celly)); // position of this cell
				float2 cell_center = cell_pos + float2(0.5, 0.5);

				float2 star_pos = cell_center + (tex2D(_MainTex, cell_pos / cells + float2(0., 0.1)) - 0.5) * _StarRandom;

				/// star color
				float3 r = tex2D(_MainTex, cell_pos / cells);
				float rnum = frac((r.r + r.g - r.b) * 10);
				float rnum2 = frac((r.r - r.g + r.b) * 10);

				float star_size = _StarSize * (rnum * _StarSizeRandom + (1 - _StarSizeRandom));

				float distance = length(pos - star_pos);
				float star_strength = max(min(star_size/distance*0.5, 1.25)-0.25, 0); // star glow

				star_strength *= clamp(sin(y*2) - 0.1, 0, 1); // fade stars near/under horizon
				star_strength *= length(r)/2; // fade stars
				star_strength *= rnum2 > _StarsMissing; // remove stars

				fixed3 star_col = lerp(1.0, r, _StarTint);

				col = lerp(col, fixed4(star_col, 1.0), star_strength);


				/// debug grid
				col = lerp(col, WHITE, _Grid * (frac(cellx) < 0.04 || frac(celly) < 0.04) );

				/// sun
				float3 sun_dir = float3(sin(_SunAngle), 0.0, cos(_SunAngle));
				float alignment = min(acos(dot(dir, sun_dir)), 1);
				// float sun_gradient = pow(y-1, 2) * 0.5 + 0.8;
				float sun_gradient = 1;
				float sun_amount = max(min(_SunRadius/alignment * sun_gradient, 5) - _SunCutoff, 0);

				col = lerp(col, _SunCol, sun_amount);
				return col;
			}
			ENDCG
		}
	}
}
