text: ﻿//UNITY_SHADER_NO_UPGRADE
  Shader "Hidden/CSG/internal/Grid"
  {
  	Properties
  	{
  		_GridSpacing("Grid Spacing", Float) = (1.0, 1.0, 1.0)
  		_GridSubdivisions("Grid Subdivisions", Float) = (4, 4, 0, 0)
  
  		_GridSize("Grid Size", Float) = 1
  		_GridColor("Grid Color", Color) = (1.0, 1.0, 1.0, 0.5)
  		_CenterColor("Center Color", Color) = (1.0, 1.0, 1.0, 0.75)
  		_StartLevel("Start Zoom Level", Float) = 4
  //		_LowestLevel("Lowest Level", Float) = -2
  		_GridLineThickness("Grid Line Thickness", Float) = 1
  		_CenterLineThickness("Center Line Thickness", Float) = 2
  		_SubdivisionTransparency("Subdivision Transparency", Float) = 0.7
  	}
  
  	SubShader
  	{
  		Tags
  		{ 
  			"ForceSupported" = "True" 
  			"Queue" = "Overlay+5105" 
  			"IgnoreProjector" = "True" 
  			"RenderType" = "Transparent" 
  			"PreviewType" = "Plane"
  			"DisableBatching" = "True"
  			"ForceNoShadowCasting" = "True"
  			"LightMode" = "Always"
  		}
  
  		Pass
  		{
  			Blend One OneMinusSrcAlpha 
  			ColorMask RGB
  			Cull Off
  			Offset -1,-1
  			Lighting Off
  			SeparateSpecular Off
  			ZTest LEqual
  			ZWrite Off
  
  			CGPROGRAM
  				#pragma vertex vert
  				#pragma fragment frag
  				#include "UnityCG.cginc"
  
  				uniform float	_GridLineThickness;
  				uniform float	_CenterLineThickness;
  				uniform float2	_GridSpacing;
  				uniform float2	_GridSubdivisions;
  
  				uniform float	_GridSize;
  				 
  				uniform fixed4	_GridColor;
  				uniform fixed4	_CenterColor;
  				uniform float	_StartLevel;
  //				uniform float	_LowestLevel;
  				uniform float	_SubdivisionTransparency;
  
  				struct vertexInput 
  				{
  					half4 vertex : POSITION;
  				};
  
  				struct vertexOutput 
  				{
  					float4 pos			: SV_POSITION;
  					float2 uv			: TEXCOORD0;
  					float4 objectPos	: TEXCOORD1;
  					float4 normal		: NORMAL;
  				};
  
  				vertexOutput vert(vertexInput input) 
  				{
  					half3 worldGridCenter	= half4(_WorldSpaceCameraPos.x, 0, _WorldSpaceCameraPos.z, 1);
  					float4 objectCenter		= mul(unity_ObjectToWorld, float4(0,0,0,1));
  					objectCenter.xyz /= objectCenter.w;
  					objectCenter.w = 0.0f;
  					
  					vertexOutput output;
  
  					//half3 normal		= normalize(mul((float3x3)unity_ObjectToWorld, half3(0, 1, 0)));
  					//half4 gridPlane	= half4(normal, -dot(normal, objectCenter));
  					//float distance	= (gridPlane.x * _WorldSpaceCameraPos.x) + (gridPlane.y * _WorldSpaceCameraPos.y) + (gridPlane.z * _WorldSpaceCameraPos.z) + (gridPlane.w);					
  					//float gridSize	= (max(1, abs(distance)) * 100);
  
  					float gridSize		= max(1, abs(_GridSize)) * 200;
  
  					float3 vposition	= (input.vertex.xzy * gridSize);
  					float4 position		= float4(vposition, 1);
  
  					output.objectPos	= mul(unity_ObjectToWorld, float4(vposition, 1));
  					output.uv			= position.xz + objectCenter.xz;
  
  					output.normal		= mul(unity_ObjectToWorld, fixed4(0, 1, 0, 0));
  
  					//position += float4(worldGridCenter,1);
  					position.y	= 0;
  					output.pos	= UnityObjectToClipPos(position);
  					return output;
  				}
  
  				// sample small and large grid in both x and y direction
  				fixed4 lineSampler4(half4 uv, half4 lineSize)
  				{
  					fixed4 t = abs((frac(uv + lineSize) / lineSize) - 1);
  					fixed4 s = saturate(exp(-pow(t, 80)));
  					return s;
  				}
  
  				// sample center grid lines in both x and y direction
  				fixed2 centerLineSampler2(half2 uv, half2 lineSize)
  				{
  					fixed2 t = abs(((uv + lineSize) / lineSize) - 1);
  					fixed2 s = saturate(exp(-pow(t, 80)));
  					return s;
  				}
  
  				fixed4 gridMultiSampler(float2 uv, half3 camDelta, float camDistance)
  				{
  					const half4 lowestLevel				= half4(2, 2, 2, 2);//_LowestLevel, _LowestLevel);
  					const fixed4 transparency			= half4(1, 1, _SubdivisionTransparency, _SubdivisionTransparency);
  					const half4 subdivisions			= half4(1, 1, 1.0 / _GridSubdivisions.xy);
  					const half4 gridspacing				= _GridSpacing.xyxy;
  					const half  startDepthPow			= pow(2, _StartLevel);
  					const half4 constantThickness		= (startDepthPow * (_GridLineThickness / 1000)) * half4(1, 1, _GridSubdivisions.xy * 0.5);
  					const half4 startDistance			= startDepthPow * gridspacing;
  					const half4 constantStepSize		= gridspacing * subdivisions;
  					const half2 constantCenterThickness = (startDepthPow * (_CenterLineThickness / 1000)) * half2(1, 1);
  
  
  					half4 gridDepth			= log2(_GridSize);//camDistance / startDistance);
  					half4 gridDepthClamp	= max(lowestLevel, gridDepth);
  					half4 gridDepthFloor	= floor(gridDepthClamp);
  					half4 gridDepthFrac		= 1 - (gridDepthClamp - gridDepthFloor);
  
  					half4 stepSize			= constantStepSize * pow(2, gridDepthFloor);
  					half2 centerStepSize	= constantStepSize * pow(2, gridDepthClamp);
  
  					half4 lineDepth			= log2(camDistance / startDistance);
  					half4 lineDepthClamp	= max(lowestLevel, lineDepth);
  					half4 lineSize			= constantThickness       / max(1, pow(2, lineDepthClamp    - lineDepth));
  					half2 centerLineSize	= constantCenterThickness / max(1, pow(2, lineDepthClamp.xy - lineDepth.xy));
  					
  #if SHADER_TARGET < 25 // no anti-aliasing on older hardware because no fwidth!
  					float4	values		= uv.xyxy;
  
  					// get the x/y lines for the thick and the thin grid lines
  					fixed4	resultB		= lineSampler4(values / stepSize, lineSize);
  
  					// get the x/y lines for the thick and the thin grid lines, one level higher
  					stepSize *= 2;
  					fixed4	resultA		= lineSampler4(values / stepSize, lineSize);
  
  					// fade in between the grid line levels
  					fixed4	result		= lerp(resultA, resultB, gridDepthFrac)
  											* transparency; // make the thin lines more transparent
  
  					// get the most visible line for this pixel
  					float t = max(max(result.x, result.y), max(result.z, result.w));
  
  
  					// get the center line thickness
  					fixed2	resultC = centerLineSampler2(values/ centerStepSize, centerLineSize.xy);
  					float c = lerp(max(resultC.x, resultC.y);
  #else
  
  					half4	pixelSize	= fwidth(uv).xyxy;
  					
  					float4	values		= uv.xyxy;
  					half4	position1	= values + (half4( 0.125, -0.375,  0.125, -0.375) * pixelSize);
  					half4	position2	= values + (half4(-0.375, -0.125, -0.375, -0.125) * pixelSize);
  					half4	position3	= values + (half4( 0.375,  0.125,  0.375,  0.125) * pixelSize);
  					half4	position4	= values + (half4(-0.125,  0.375, -0.125,  0.375) * pixelSize);
  
  					// get the x/y lines for the thick and the thin grid lines
  					float4	resultB		= lineSampler4(position1 / stepSize, lineSize) +
  										  lineSampler4(position2 / stepSize, lineSize) +
  										  lineSampler4(position3 / stepSize, lineSize) +
  										  lineSampler4(position4 / stepSize, lineSize);
  					
  					// get the x/y lines for the thick and the thin grid lines, one level higher
  					stepSize *= 2;
  					float4	resultA		= lineSampler4(position1 / stepSize, lineSize) +
  										  lineSampler4(position2 / stepSize, lineSize) +
  										  lineSampler4(position3 / stepSize, lineSize) +
  										  lineSampler4(position4 / stepSize, lineSize);
  					
  					// fade in between the grid line levels
  					fixed4	result		= lerp(resultA, resultB, gridDepthFrac)
  											* transparency
  						; // make the thin lines more transparent
  
  					// get the most visible line for this pixel
  					float t = max(max(result.x, result.y), max(result.z, result.w)) 
  
  								// subdivide by the number of samples
  								/ 4;
  
  
  					// get the center line thickness
  					float2	resultC = centerLineSampler2(position1 / centerStepSize, centerLineSize.xy) +
  									  centerLineSampler2(position2 / centerStepSize, centerLineSize.xy) +
  									  centerLineSampler2(position3 / centerStepSize, centerLineSize.xy) +
  									  centerLineSampler2(position4 / centerStepSize, centerLineSize.xy);
  					float c =	max(resultC.x, resultC.y)
  
  								// subdivide by the number of samples
  								/ 4;
  
  #endif
  					// interpolate between the center grid lines and the regular grid
  					return (fixed4(_GridColor.rgb,   _GridColor.a   * t) * (1 - c)) + 
  						   (fixed4(_CenterColor.rgb, _CenterColor.a * c) *      c );
  				}
  
  				half4 frag(vertexOutput input) : COLOR
  				{
  					float3	camDelta	= _WorldSpaceCameraPos.xyz - (input.objectPos.xyz / input.objectPos.w);
  					float	camDistance = length(camDelta);		
  					
  
  					float2	uv			= input.uv;
  
  
  					// get the color for our pixel
  					fixed4	color		= gridMultiSampler(uv, camDelta, camDistance);
  
  					// fade out on grazing angles to hide line aliasing
  					float	angle = abs(dot(camDelta / camDistance, input.normal));
  					color.a	  *= angle;
  
  					// pre-multiply our rgb color by our alpha
  					color.rgb *= color.a;
  					return color;
  				}
  			ENDCG
  		}
  	}
  }