// Amplify Texture - Massive Virtual Texturing for Unity Pro
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>

Shader "Hidden/Amplify Texture/PrePass" {
	Properties {
		_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_VTInfoBlock ( "VT (auto)", Vector) = ( 0, 0, 0, 0 )
	}

	CGINCLUDE
		#include "UnityCG.cginc"
		#include "../Shared.cginc"

		float4 _VTPrePassTransform;

		sampler2D _MainTex;
		float4 _MainTex_ST;
		uniform float _Cutoff;

		struct Vertex
		{
			float4 vertex : POSITION;
			float3 normal : NORMAL;
			float4 texcoord : TEXCOORD0;
		};

		struct VertexOutput
		{
			float4 pos	: POSITION;
			float3 uv	: TEXCOORD0;
		};

		VertexOutput prePassVert( Vertex v )
		{
			VertexOutput o;
			o.pos = mul( UNITY_MATRIX_MVP, v.vertex );
			o.pos.xy += ( _ScreenParams.zw - 1 ) * _VTPrePassTransform.xy;
			o.uv.xy = TRANSFORM_TEX( v.texcoord, _MainTex );
			o.uv.y = ( _VTInfoBlock.z >= 0 ) ? o.uv.y :  1 - o.uv.y;
			o.uv.z = trunc( abs( _VTInfoBlock.z ) );
			return o;
		}

		float4 prePassFrag( VertexOutput i, bool cutout )
		{
			TextureDesc tex = FetchTextureDesc();
			VirtualUV virtual_uv = VTComputeVirtualUV( i.uv.xy, tex );
			float mip = VTComputeVirtualMip( i.uv.xy, _VTBorderAndPrePass.zw, tex );
			float packedMipAsset = mip + i.uv.z * 16.0f;

			if ( cutout )
			{
				float3 page = VTFetchPageTable( virtual_uv, mip, tex );
				float2 dx, dy, pageuv = VTComputePageCoords( virtual_uv, mip, page, tex, dx, dy );
				float coverage = tex2D( _VTDiffuseCache, pageuv, dx, dy ).a;
				clip( coverage - _Cutoff );
			}

			float2 tile = floor( virtual_uv.wrap * tex.table.yy ) / 256.0f;

			float2 tileFrac = frac( tile.xy );
			float2 tileMod = floor( tileFrac.xy * 256.0f );
			float2 tileRem = tile.xy - tileFrac.xy;
			float packedTileRem = tileRem.x + tileRem.y * 16.0f;

			return float4( tileMod.xy, packedMipAsset, packedTileRem ) / 255.0f;
		}
	ENDCG

	SubShader {
		Tags { "RenderType"="Opaque" "IgnoreProjector"="True" "LightMode"="Always" "ForceNoShadowCasting"="True" }
		Pass {
			Blend Off Fog{ Mode off }
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma target 3.0
				#pragma glsl
				#pragma multi_compile _ _ALPHATEST_ON

			#if _VT_DISPLACEMENT
				float _Displacement;
			#endif

				VertexOutput vert( Vertex v )
				{
				#if _VT_DISPLACEMENT
					v.vertex.xyz += v.normal * VTVertexSampleDisplacement( v.texcoord ) * _Displacement;
				#endif
					return prePassVert( v );
				}

				float4 frag( VertexOutput i ) : COLOR
				{
				#if _ALPHATEST_ON
					bool cutout = true;
				#else
					bool cutout = false;
				#endif
					return prePassFrag( i, cutout );
				}
			ENDCG
		}
	}

	SubShader {
		Tags { "RenderType"="TransparentCutout" "IgnoreProjector"="True" "LightMode"="Always" "ForceNoShadowCasting"="True" }
		Pass {
			Blend Off Fog{ Mode off }
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma target 3.0
				#pragma glsl

				VertexOutput vert( Vertex v ) { return prePassVert( v ); }
				float4 frag( VertexOutput i ) : COLOR { return prePassFrag( i, true ); }
			ENDCG
		}
	}

	SubShader {
		Tags { "RenderType"="TreeBark" "IgnoreProjector"="True" "LightMode"="Always" "ForceNoShadowCasting"="True" }
		Pass {
			Blend Off Fog{ Mode off }
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma target 3.0
				#pragma glsl

				VertexOutput vert( Vertex v ) { return prePassVert( v ); }
				float4 frag( VertexOutput i ) : COLOR { return prePassFrag( i, false ); }
			ENDCG
		}
	}

	SubShader {
		Tags { "RenderType"="TreeLeaf" "IgnoreProjector"="True" "LightMode"="Always" "ForceNoShadowCasting"="True" }
		Pass {
			Blend Off Fog{ Mode off }
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma target 3.0
				#pragma glsl

				VertexOutput vert( Vertex v ) { return prePassVert( v ); }
				float4 frag( VertexOutput i ) : COLOR { return prePassFrag( i, true ); }
			ENDCG
		}
	}

	SubShader {
		Tags { "RenderType"="TreeOpaque" "IgnoreProjector"="True" "LightMode"="Always" "ForceNoShadowCasting"="True" }
		Pass {
			Blend Off Fog{ Mode off }
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma target 3.0
				#pragma glsl
				#pragma multi_compile _ _ALPHATEST_ON

				VertexOutput vert( Vertex v ) { return prePassVert( v ); }

				float4 frag( VertexOutput i ) : COLOR
				{
				#if _ALPHATEST_ON
					bool cutout = true;
				#else
					bool cutout = false;
				#endif
					return prePassFrag( i, cutout );
				}
			ENDCG
		}
	}

	SubShader {
		Tags { "RenderType"="TreeTransparentCutout" "IgnoreProjector"="True" "LightMode"="Always" "ForceNoShadowCasting"="True" }
		Pass {
			Blend Off Fog{ Mode off }
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma target 3.0
				#pragma glsl

				VertexOutput vert( Vertex v ) { return prePassVert( v ); }
				float4 frag( VertexOutput i ) : COLOR { return prePassFrag( i, true ); }
			ENDCG
		}
	}

	SubShader {
		Tags { "RenderType"="TreeBillboard" "IgnoreProjector"="True" "LightMode"="Always" "ForceNoShadowCasting"="True" }
		Pass {
			Blend Off Fog{ Mode off }
			Cull Off
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma target 3.0
				#pragma glsl

				VertexOutput vert( Vertex v ) { return prePassVert( v ); }
				float4 frag( VertexOutput i ) : COLOR { return prePassFrag( i, true ); }
			ENDCG
		}
	}

	SubShader {
		Tags { "RenderType"="GrassBillboard" "IgnoreProjector"="True" "LightMode"="Always" "ForceNoShadowCasting"="True" }
		Pass {
			Blend Off Fog{ Mode off }
			Cull Off
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma target 3.0
				#pragma glsl

				VertexOutput vert( Vertex v ) { return prePassVert( v ); }
				float4 frag( VertexOutput i ) : COLOR { return prePassFrag( i, true ); }
			ENDCG
		}
	}

	SubShader {
		Tags { "RenderType"="Grass" "IgnoreProjector"="True" "LightMode"="Always" "ForceNoShadowCasting"="True" }
		Pass {
			Blend Off Fog{ Mode off }
			Cull Off
			CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma target 3.0
				#pragma glsl

				VertexOutput vert( Vertex v ) { return prePassVert( v ); }
				float4 frag( VertexOutput i ) : COLOR { return prePassFrag( i, true ); }
			ENDCG
		}
	}

	Fallback off
}
