#T#PoiVideoEffectsProperties
//ifex _VideoEffectsEnable==0
[HideInInspector] m_start_videoEffects ("Video Effects--{reference_property:_VideoEffectsEnable}", Float) = 0
[HideInInspector][ThryToggle]_VideoEffectsEnable ("Enable VideoEffects", Float) = 0
[Enum(LCD, 0, TN, 1, CRT, 2, OLED, 3, Gameboy, 4, Projector, 5)] _VideoType ("Screen Type", Int) = 3
_VideoBacklight ("Brightness", Range(0, 100)) = 1
[ToggleUI]_VideoEmissionEnabled ("Emission Enabled", Float) = 1
_VideoPixelTexture ("Pixel Texture--{reference_properties:[_VideoPixelTextureUV]}", 2D) = "white" { }
[HideInInspector][ThryWideEnum(UV0, 0, UV1, 1, UV2, 2, UV3, 3)]_VideoPixelTextureUV ("UV", Int) = 0
[sRGBWarning]_VideoMaskTexture ("Mask--{reference_properties:[_VideoMaskTexturePan, _VideoMaskTextureUV, _VideoMaskTextureChannel]}", 2D) = "white" { }
[HideInInspector][Vector2]_VideoMaskTexturePan ("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)]_VideoMaskTextureUV ("UV", Int) = 0
[HideInInspector][Enum(R, 0, G, 1, B, 2, A, 3)]_VideoMaskTextureChannel ("Channel", Float) = 0
[HideInInspector] m_start_VideoSettings ("Video Texture Settings", Float) = 0
[Vector2]_VideoResolution ("Resolution", Vector) = (1280, 720, 0, 0)
[ToggleUI]_VideoPixelateToResolution ("Pixelate To Resolution", Float) = 0
// [ToggleUI]_VideoRepeatVideoTexture ("Clamp To UV", Float) = 0
_VideoSaturation ("Saturation", Range(-1, 3)) = 0
_VideoContrast ("Contrast boost", Range(0, 3)) = 0

[HideInInspector] m_end_VideoSettings ("Video Texture Settings", Float) = 0

[HideInInspector] m_start_CRT ("CRT Options--{condition_showS:(_VideoType==2)}", Float) = 0
_VideoCRTRefreshRate ("Refresh Rate", Float) = 24
_VideoCRTPixelEnergizedTime ("Pixel Fade Time", Float) = 1.9
[HideInInspector] m_end_CRT ("CRT Options", Float) = 0

[HideInInspector] m_start_Gameboy ("Gameboy Options--{condition_showS:(_VideoType==4)}", Float) = 0
[sRGBWarning(true)][Gradient]_VideoGameboyRamp ("Color Ramp", 2D) = "white" { }
[HideInInspector] m_end_Gameboy ("Gameboy Options", Float) = 0

[HideInInspector] m_end_videoEffects ("Video Effects", Float) = 0
//endex

#T#PoiVideoEffectsVariables
//ifex _VideoEffectsEnable==0
float _VideoEffectsEnable;
#if defined(PROP_VIDEOPIXELTEXTURE) || !defined(OPTIMIZER_ENABLED)
	sampler2D _VideoPixelTexture;
	float4 _VideoPixelTexture_ST;
	float _VideoPixelTextureUV;
#endif
#if defined(PROP_VIDEOMASKTEXTURE) || !defined(OPTIMIZER_ENABLED)
	Texture2D _VideoMaskTexture;
	float4 _VideoMaskTexture_ST;
	float2 _VideoMaskTexturePan;
	float _VideoMaskTextureUV;
	float _VideoMaskTextureChannel;
#endif

float _VideoType;
float2 _VideoResolution;
sampler2D _VideoGameboyRamp;
float _VideoBacklight;
float _VideoCRTRefreshRate;
float _VideoCRTPixelEnergizedTime;
float _VideoRepeatVideoTexture;
float _VideoPixelateToResolution;
float2 _VideoMaskPanning;

float _VideoSaturation;
float _VideoContrast;
float _VideoEmissionEnabled;
//endex

#T#PoiVideoEffectsFunctions
//ifex _VideoEffectsEnable==0
float3 applyBacklight(float3 videoTexture, half backlightStrength)
{
	return max(backlightStrength, videoTexture.rgb);
}

float3 applyViewAngleTN(float3 videoTexture, PoiCam poiCam, PoiMesh poiMesh)
{
	float3 reflectionVector = normalize(reflect(poiCam.viewDir.rgb, poiMesh.normals[1].rgb));
	float upwardShift = dot(reflectionVector, poiMesh.binormal[0]);
	upwardShift = pow(upwardShift, 1);
	float sideShift = dot(reflectionVector, poiMesh.tangent[0]);
	sideShift *= pow(sideShift, 3);
	#if !UNITY_COLORSPACE_GAMMA
		videoTexture = LinearToGammaSpace(videoTexture);
	#endif
	videoTexture = saturate(lerp(half3(0.5, 0.5, 0.5), videoTexture, upwardShift + 1));
	#if !UNITY_COLORSPACE_GAMMA
		videoTexture = GammaToLinearSpace(videoTexture);
	#endif
	videoTexture = (lerp(videoTexture, videoTexture.gbr, sideShift));
	return videoTexture;
}

float calculateCRTPixelBrightness(float2 uv)
{
	float totalPixels = _VideoResolution.x * _VideoResolution.y;
	float2 uvPixel = float2((floor((1 - uv.y) * _VideoResolution.y)) / _VideoResolution.y, (floor(uv.x * _VideoResolution.x)) / _VideoResolution.x);
	float currentPixelNumber = _VideoResolution.x * (_VideoResolution.y * uvPixel.x) + _VideoResolution.y * uvPixel.y;
	float currentPixelAlpha = currentPixelNumber / totalPixels;
	half electronBeamAlpha = frac(_Time.y * _VideoCRTRefreshRate);
	float electronBeamPixelNumber = totalPixels * electronBeamAlpha;
	
	float DistanceInPixelsFromCurrentElectronBeamPixel = 0;
	if (electronBeamPixelNumber >= currentPixelNumber)
	{
		DistanceInPixelsFromCurrentElectronBeamPixel = electronBeamPixelNumber - currentPixelNumber;
	}
	else
	{
		DistanceInPixelsFromCurrentElectronBeamPixel = electronBeamPixelNumber + (totalPixels - currentPixelNumber);
	}
	float CRTFrameTime = 1 / _VideoCRTRefreshRate;
	float timeSincecurrentPixelWasHitByElectronBeam = (DistanceInPixelsFromCurrentElectronBeamPixel / totalPixels);
	
	return saturate(_VideoCRTPixelEnergizedTime - timeSincecurrentPixelWasHitByElectronBeam);
}

void applyContrastSettings(inout float3 pixel)
{
	#if !UNITY_COLORSPACE_GAMMA
		pixel = LinearToGammaSpace(pixel);
	#endif
	pixel = saturate(lerp(half3(0.5, 0.5, 0.5), pixel, _VideoContrast + 1));
	#if !UNITY_COLORSPACE_GAMMA
		pixel = GammaToLinearSpace(pixel);
	#endif
}

void applySaturationSettings(inout float3 pixel)
{
	pixel = lerp(pixel.rgb, dot(pixel.rgb, float3(0.3, 0.59, 0.11)), -(_VideoSaturation));
}

void applyVideoSettings(inout float3 pixel)
{
	applySaturationSettings(pixel);
	applyContrastSettings(pixel);
}

void calculateLCD(inout float4 videoTexture, float3 pixels)
{
	videoTexture.rgb = applyBacklight(videoTexture, _VideoBacklight * .01);
	applyVideoSettings(videoTexture.rgb);
	videoTexture.rgb = videoTexture * pixels * _VideoBacklight;
}
void calculateTN(inout float4 videoTexture, float3 pixels, PoiCam poiCam, PoiMesh poiMesh)
{
	videoTexture.rgb = applyBacklight(videoTexture, _VideoBacklight * .01);
	videoTexture.rgb = applyViewAngleTN(videoTexture, poiCam, poiMesh);
	applyVideoSettings(videoTexture.rgb);
	videoTexture.rgb = videoTexture * pixels * _VideoBacklight;
}
void calculateCRT(inout float4 videoTexture, float3 pixels, float2 uv)
{
	float brightness = calculateCRTPixelBrightness(uv);
	applyVideoSettings(videoTexture.rgb);
	videoTexture.rgb = videoTexture * pixels * brightness * _VideoBacklight;
}
void calculateOLED(inout float4 videoTexture, float3 pixels)
{
	applyVideoSettings(videoTexture.rgb);
	videoTexture.rgb = videoTexture * pixels * _VideoBacklight;
}
void calculateGameboy(inout float4 videoTexture)
{
	applyVideoSettings(videoTexture.rgb);
	// half brightness = saturate((videoTexture.r + videoTexture.g + videoTexture.b) * .3333333);
	half brightness = LinearRgbToLuminance(LinearToGammaSpace(videoTexture.rgb));
	#if defined(PROP_VIDEOGAMEBOYRAMP) || !defined(OPTIMIZER_ENABLED)
		videoTexture.rgb = tex2Dlod(_VideoGameboyRamp, float4(brightness.xx, 0, 0));
	#else
		float3 dg = float3(0.00392156863, 0.0392156863, 0.00392156863);
		float3 lg = float3(0.333333333, 0.5, 0.00392156863);
		videoTexture.rgb = lerp(dg, lg, brightness);
	#endif
}
void calculateProjector(inout float4 videoTexture)
{
	applyVideoSettings(videoTexture.rgb);
	
	float3 projectorColor = videoTexture * _VideoBacklight;
	videoTexture.r = clamp(projectorColor.r, videoTexture.r, 1000);
	videoTexture.g = clamp(projectorColor.g, videoTexture.g, 1000);
	videoTexture.b = clamp(projectorColor.b, videoTexture.b, 1000);
}

void applyVideoEffectsMainTex(inout float4 mainTexture, in PoiMesh poiMesh)
{
	float2 uvs = poiMesh.uv[_MainTexUV];
	if(_VideoPixelateToResolution)
	{
		float2 originalUVs = uvs;
		uvs = sharpSample(float4(1/_VideoResolution.xy, _VideoResolution.xy), uvs);
		uvs = poiUV(uvs, _MainTex_ST) + _Time.x * _MainTexPan;
		mainTexture = _MainTex.SampleGrad(sampler_MainTex, uvs, ddx(originalUVs), ddy(originalUVs));
	}
}
void applyVideoEffects(inout PoiFragData poiFragData, in PoiCam poiCam, in PoiMesh poiMesh, in PoiLight poiLight, in PoiMods poiMods)
{
	#if defined(PROP_VIDEOPIXELTEXTURE) || !defined(OPTIMIZER_ENABLED)
		float3 pixels = tex2D(_VideoPixelTexture, poiUV(poiMesh.uv[_VideoPixelTextureUV], _VideoPixelTexture_ST) * _VideoResolution);
	#else
		float3 pixels = 1;
	#endif
	float2 uvs = poiMesh.uv[_MainTexUV];
	if(_VideoPixelateToResolution)
	{
		uvs = sharpSample(float4(1/_VideoResolution.xy, _VideoResolution.xy), uvs);
		uvs = poiUV(uvs, _MainTex_ST) + _Time.x * _MainTexPan;
	}
	else
	{
		uvs = poiUV(uvs, _MainTex_ST) + _Time.x * _MainTexPan;
	}
	float4 modifiedVideoTexture = 0;
	modifiedVideoTexture.rgb = poiFragData.baseColor;
	modifiedVideoTexture.a = poiFragData.alpha;
	
	// UNITY_BRANCH
	// if(_VideoRepeatVideoTexture == 1)
	// {
	// 	if(poiMesh.uv[_VideoUVNumber].x > 1 || poiMesh.uv[_VideoUVNumber].x < 0 || poiMesh.uv[_VideoUVNumber].y > 1 || poiMesh.uv[_VideoUVNumber].y < 0)
	// 	{
	// 		return;
	// 	}
	// }
	
	switch(_VideoType)
	{
		case 0: // LCD
		{
			calculateLCD(modifiedVideoTexture, pixels);
			break;
		}
		case 1: // TN
		{
			calculateTN(modifiedVideoTexture, pixels, poiCam, poiMesh);
			break;
		}
		case 2: // CRT
		{
			calculateCRT(modifiedVideoTexture, pixels, uvs);
			break;
		}
		case 3: // OLED
		{
			calculateOLED(modifiedVideoTexture, pixels);
			break;
		}
		case 4: // Gameboy
		{
			calculateGameboy(modifiedVideoTexture);
			break;
		}
		case 5: // Projector
		{
			calculateProjector(modifiedVideoTexture);
			break;
		}
	}
	#if defined(PROP_VIDEOMASKTEXTURE) || !defined(OPTIMIZER_ENABLED)
		float screenMask = POI2D_SAMPLER_PAN(_VideoMaskTexture, _MainTex, poiUV(poiMesh.uv[_VideoMaskTextureUV], _VideoMaskTexture_ST), _VideoMaskTexturePan)[_VideoMaskTextureChannel];
	#else
		float screenMask = 1;
	#endif
	
	poiFragData.baseColor = lerp(poiFragData.baseColor, modifiedVideoTexture, screenMask);
	// UNITY_BRANCH
	if (_VideoEmissionEnabled)
	{
		poiFragData.emission += modifiedVideoTexture.rgb * screenMask;
	}
}
//endex

#T#PoiVideoEffectsMainTexFunctionCalls
//ifex _VideoEffectsEnable==0
if (_VideoEffectsEnable)
{
	applyVideoEffectsMainTex(mainTexture, poiMesh);
}
//endex
#T#PoiVideoEffectsFunctionCalls
//ifex _VideoEffectsEnable==0
if (_VideoEffectsEnable)
{
	applyVideoEffects(poiFragData, poiCam, poiMesh, poiLight, poiMods);
}
//endex