﻿// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Quantum/Galaxy"{
	Properties{
		_Stars1 ("Stars1", Color) = (1, 1, 1, 1)
		_Stars2 ("Stars2", Color) = (1, 1, 1, 1)
		_Stars3 ("Stars3", Color) = (1, 1, 1, 1)
		_Nebula1 ("Nebula1", Color) = (.1, .1, .1, 1)
		_Nebula2 ("Nebula2", Color) = (.1, .1, .1, 1)
		_Nebula3 ("Nebula3", Color) = (.1, .1, .1, 1)
		_Seed ("RNG Seed", Range(0,3.1416)) = 0
	}

	CGINCLUDE
	float4 _Stars1;
	float4 _Stars2;
	float4 _Stars3;
	float _Seed;
	float2 noise_2d(float3 p) {
		p.z += frac(sin(dot(floor(p).xy,float2(127.1, 311.7)))*(43758.5453 + _Seed));
		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 + _Seed));
		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 + _Seed));
		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);
	}

	float4 voronoi(float2 x){
		float2 n = floor(x);
		float2 f = frac(x);

		// 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, _Time.x*5.));

				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 = _Stars2;
				o = normalize(o);
				float tintD = (o.x)*2-1;
				if(tintD < 0){
					tint = _Stars1 * -tintD + tint*(1+tintD);
				}else{
					tint = _Stars3 * tintD + tint*(1-tintD);
				}
				r = 1.0-sqrt(abs(r*9.));
				d = clamp(((r.x+r.y))-1./(v*2.), 0., 1.);
				col += float3(d, d, d)*tint;
			}
		}
		return float4(col, 1);
	}

	#define rand3 float3(12.9898,78.233,54.5913)

	float random3dLerp(in float3 st) {
		float3 i = floor(st);
		float3 f = frac(st);
		return lerp(lerp(lerp(frac(sin(dot(i,rand3))*(43758.5453 + _Seed)),
		 					  frac(sin(dot(i+float3(1.0, 0.0, 0.0),rand3))*(43758.5453 + _Seed)),
						 f.x),
						 lerp(frac(sin(dot(i+float3(0.0, 1.0, 0.0),rand3))*(43758.5453 + _Seed)),
						 	  frac(sin(dot(i+float3(1.0, 1.0, 0.0),rand3))*(43758.5453 + _Seed)),
						 f.x),
					f.y),
					lerp(lerp(frac(sin(dot(i+float3(0.0, 0.0, 1.0),rand3))*(43758.5453 + _Seed)),
							  frac(sin(dot(i+float3(1.0, 0.0, 1.0),rand3))*(43758.5453 + _Seed)),
						 f.x),
					 	 lerp(frac(sin(dot(i+float3(0.0, 1.0, 1.0),rand3))*(43758.5453 + _Seed)),
						 	  frac(sin(dot(i+float3(1.0, 1.0, 1.0),rand3))*(43758.5453 + _Seed)),
						 f.x),
					f.y),
				f.z);
	}

	#define NUM_OCTAVES 5

	float fbm ( in float3 _st) {
		float v = 0.0;
		float a = 0.5;
		float2 shift = float2(100.0, 100.0);
		// Rotate to reduce axial bias
		float2x2 rot = float2x2(cos(0.5), sin(0.5),
						-sin(0.5), cos(0.50));
		for (int i = 0; i < NUM_OCTAVES; ++i) {
			v += a * random3dLerp(_st);
			_st.xy = mul(rot,_st.xy) * 2.0 + shift;
			a *= 0.5;
		}
		return v;
	}
	ENDCG

	SubShader{
		Cull Off
		Pass{
			CGPROGRAM

			#pragma vertex vertexFunction
			#pragma fragment fragmentFunction

			#include "UnityCG.cginc"

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

			struct v2f{
				float4 position : SV_POSITION;
				float2 uv : TEXCOORD0;
			};

			float4 _Nebula1;
			float4 _Nebula2;
			float4 _Nebula3;

			sampler2D _MainTex;

			v2f vertexFunction(appdata IN){
				v2f OUT;

				OUT.position = UnityObjectToClipPos(IN.vertex);
				OUT.uv = IN.uv;

				return OUT;
			}

			fixed4 fragmentFunction(v2f IN) : SV_Target{
				float3 col = float3(0,0,0);
				col = voronoi(IN.uv.xy*10.0);
				col += voronoi(IN.uv.xy*30.0);
				col += voronoi(IN.uv.xy*100.0);
				col += fbm(float3(IN.uv.xy*10.0,_Time.y/5.))*_Nebula1.xyz;
				col += fbm(float3(IN.uv.xy*20.0,_Time.y/5.+1.))*_Nebula2.xyz;
				col += fbm(float3(IN.uv.xy*50.0,_Time.y/5.+3.))*_Nebula3.xyz;
				return float4(col,1);
			}
			ENDCG
		}
	}
}
