﻿// Created by Neitri, free of charge, free to redistribute

Shader "Neitri/Clock V3 Realtime World Only"
{
	Properties
	{
		_Texture("Texture", 2D) = "black" {}
		_MainTex("Sync Texture", 2D) = "white" {}		
		_Color("Color", Color) = (1,1,1,1)
	}
	SubShader
	{
		Tags
		{
			"Queue" = "Transparent"
			"RenderType" = "Transparent"
		}
		LOD 100
		Cull Off
		Blend SrcAlpha OneMinusSrcAlpha // transparent

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fog
			
			#include "UnityCG.cginc"

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

			struct v2f
			{
				float4 vertex : SV_POSITION;
				float2 uv : TEXCOORD0;
				float3 progress : TEXCOORD1;
				float4 color : COLOR;
				UNITY_FOG_COORDS(1)
			};

			sampler2D _Texture;
			float4 _Texture_ST;

			sampler2D _MainTex;
			float4 _MainTex_ST;

			float4 _Color;


			int getHour(float3 textureFloats) {
				return round(((textureFloats.x + textureFloats.y + textureFloats.z) / 3) * 24);
			}

			int getMinSec(float3 textureFloats) {
				return round(((textureFloats.x + textureFloats.y + textureFloats.z) / 3) * 60);
			}

			float getTime()
			{
				// From Maki's and Desunyan's realtime clock: https://maki.cat/vrchat/

				float3 first = tex2Dlod(_MainTex, float4(0.25, 0.75, 0, 0)).rgb;
				float3 second = tex2Dlod(_MainTex, float4(0.75, 0.75, 0, 0)).rgb;
				float3 third = tex2Dlod(_MainTex, float4(0.25, 0.25, 0, 0)).rgb;

				float3 offsetTime = float3(
					getHour(float3(first.r, second.g, third.b)),
					getMinSec(float3(first.g, second.b, third.r)),
					getMinSec(float3(first.b, second.r, third.g))
				);

				float offset = (
					(offsetTime.r * 60 * 60) +
					(offsetTime.g * 60) +
					(offsetTime.b)
				);

				float time = 0;
				if (tex2Dlod(_MainTex, float4(0.75, 0.25, 0, 0)).r < 0.5) {
					time = offset + _Time.y;
				}

				return time;
			}


			v2f vert (appdata v)
			{
			
				v2f o;
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				o.color = _Color;
				o.progress = 0;

				uint s1 = floor(getTime());
				uint s10 = floor(s1 / 10);
				uint m1 = floor(s10 / 6);
				uint m10 = floor(m1 / 10);
				uint h1 = floor(m10 / 6);
				h1 = h1 % 24;
				uint h10 = floor(h1 / 10);

				s1 -= s10 * 10;
				s10 -= m1 * 6;
				m1 -= m10 * 10;
				m10 -= h1 * 6;
				h1 -= h10 * 10;

				if (v.color.r == 0) {
					if (v.color.g == 0) {
						if (v.color.b == 0) {
							// seconds
							o.uv.x += s1 / 10.0f;
						} else {
							// 10 seconds
							o.uv.x += s10 / 10.0f;
						}
					} else {
						if (v.color.b == 0) {
							// minutes
							o.uv.x += m1 / 10.0f;
							if (h10 + h1 + m10 + m1 == 0) o.color *= 0.5;
						} else {
							// 10 minutes
							o.uv.x += m10 / 10.0f;
							if (h10 + h1 + m10 == 0) o.color *= 0.5;
						}
					}
				} else if (v.color.r == 1) {
					if (v.color.g == 0) {
						if (v.color.b == 0) {
							// hours
							o.uv.x += h1 / 10.0f;
							if (h10 + h1 == 0) o.color *= 0.5;
						} else {
							// 10 hours
							o.uv.x += h10 / 10.0f;
							if (h10 == 0) o.color *= 0.5;
						}
					} else {
						if (v.color.b == 0) {
							// :
							o.color *= fmod(floor(_Time.y * 2), 2);
						} else {
							// static texture
						}
					}
				} else { // v.color.r == 0.5
					if (v.color.g == 0) {
						if (v.color.b == 0) {
							// seconds progress indicator
							float d = frac(_Time.y);
							o.progress = float3(d, 0.15, 0.05);
						} else {
							// fps indicator
							float d = unity_DeltaTime.w / 90.0;
							d = saturate(d); 
							o.progress = float3(d, 0.03, 0.01);
						}
					}
				}				

				o.vertex = UnityObjectToClipPos(v.vertex);
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 col = tex2D(_Texture, i.uv) * i.color;
				
				if (i.progress.x > 0)
				{
					col.a *= step(0, i.progress.x - floor(i.uv.x / i.progress.y) * i.progress.y);
					col.a *= step(-0.5, floor(i.uv.x / i.progress.y) - floor((i.uv.x + i.progress.z) / i.progress.y));
					// DEBUG
					//col.a = step(0, i.progress.x - i.uv.x);
				}
				if (col.a < 0.3) discard;
				// apply fog
				UNITY_APPLY_FOG(i.fogCoord, col);
				return col;
			}
			ENDCG
		}
	}
}
