
// This shader is custom made for the forest example
// It draws a map using 2 input textures
//     tex_0.rg is the UV coordinates for small roads
//     tex_0.ba is the UV coordinates for large roads
//     tex_1.r is the height map
//     tex_1.gba is the texture blend map
//     tex_2 is the tile atlas

#define RoadMap tex_0
#define HeightMap tex_1
#define TileAtlas tex_2
	#define Tile_LargeRoad_MIN_UV float2(0.0f,0.0f)
	#define Tile_LargeRoad_MAX_UV float2(0.5f,1.0f)
	#define Tile_SmallRoad_MIN_UV float2(0.5f,0.02f)
	#define Tile_SmallRoad_MAX_UV float2(1.0f,0.98f)
#define ObstacleMap tex_3

// The amount of the U coordinate that contain a road for each road type
#define LargeRoadRatio Arg[0].x
#define SmallRoadRatio Arg[0].y

#define LoopForward(min,var,max) for(var=min;var<=max;var++)
#define LoopBackward(min,var,max) for(var=max;var>=min;var--)
#define MountainHeight 2.0f

float4 PS( VS_to_PS input) : SV_Target {
	float4 SumColor;
	float4 SubPixelColor;
	float DX = ddx(UV1.x);
	float DY = ddy(UV1.y);
	int X;
	int Y;
	LoopForward(0,X,1) {
		LoopForward(0,Y,1) {
			float2 UV = float2(UV1.x + ((float(X) + 0.5f) * 0.66 * DX), UV1.y + ((float(Y) + 0.5f) * 0.66 * DY));
			
			float4 Road = RoadMap.Sample( samClampedLinear, UV );
			float4 Ground = HeightMap.Sample( samClampedLinear, UV );
			float4 Obstacle = ObstacleMap.Sample( samClampedLinear, UV );
			
			// Debug distance transform using this code
			//SubPixelColor = saturate(1.0f - float4(Obstacle.g * 0.1f,Obstacle.g * 0.05f,Obstacle.g * 0.02f,0.0f));
			
			//if (Obstacle.r > -0.5f) {
			//	// Obstacle
			//	SubPixelColor = float4(0.0f,0.0f,0.0f,1.0f);
			//} else
			if (Ground.r > MountainHeight) {
				// Mountain
				SubPixelColor = saturate(lerp(float4(0.0f,1.0f,0.0f,1.0f),float4(1.0f,1.0f,1.0f,1.0f),saturate((Ground.r - MountainHeight) / MountainHeight)));
			} else if (Ground.r > 0.0f) {
				// Land
				SubPixelColor = saturate(lerp(float4(0.0f,0.4f,0.0f,1.0f),float4(0.0f,1.0f,0.0f,1.0f),saturate(Ground.r / MountainHeight)));
			} else {
				// Water
				SubPixelColor = saturate(lerp(float4(0.0f,0.0f,1.0f,0.5f),float4(0.0f,0.0f,1.0f,0.0f),-Ground.r));
			}
			
			// Get the dimensions of the road map
			uint RoadMap_Width; uint RoadMap_Height; uint RoadMap_Levels;
			RoadMap.GetDimensions(0,RoadMap_Width,RoadMap_Height,RoadMap_Levels);
			
			if (Ground.g + Ground.b + Ground.a > 0.9) {
				// Draw roads
				if (UV.x > 0.0f && UV.x < 1.0f && UV.y > 0.0f && UV.y < 1.0f) {
					float2 RoadPixel = float2(UV.x * RoadMap_Width,UV.y * RoadMap_Height);
					uint LX = floor(RoadPixel.x);
					uint HX = LX + 1;
					uint LY = floor(RoadPixel.y);
					uint HY = LY + 1;
					float4 Road_LXLY = RoadMap.Load(int3(LX,LY,0));
					float4 Road_LXHY = RoadMap.Load(int3(LX,HY,0));
					float4 Road_HXLY = RoadMap.Load(int3(HX,LY,0));
					float4 Road_HXHY = RoadMap.Load(int3(HX,HY,0));
					
					// Draw large roads
					if (Road_LXLY.b > -0.5f && Road_LXHY.b > -0.5f && Road_HXLY.b > -0.5f && Road_HXHY.b > -0.5f) {
						float4 RoadColor;
						float2 FracRP = frac(RoadPixel);
						float4 Road;
						if ((Road_LXLY.b > 0.4f && Road_LXHY.b > 0.4f && Road_HXLY.b > 0.4f && Road_HXHY.b > 0.4f) || (Road_LXLY.b < 0.6f && Road_LXHY.b < 0.6f && Road_HXLY.b < 0.6f && Road_HXHY.b < 0.6f)) {
							// Interpolated UV
							Road = lerp(lerp(Road_LXLY,Road_HXLY,FracRP.x),lerp(Road_LXHY,Road_HXHY,FracRP.x),FracRP.y);
							float2 RoadUV = lerp(Tile_LargeRoad_MIN_UV,Tile_LargeRoad_MAX_UV,Road.ba);
							RoadColor = TileAtlas.Sample( samLinear, RoadUV );
						} else {
							// Interpolate color
							float4 RoadColor_LXLY = TileAtlas.Sample( samLinear, lerp(Tile_LargeRoad_MIN_UV,Tile_LargeRoad_MAX_UV,Road_LXLY.xy) );
							float4 RoadColor_LXHY = TileAtlas.Sample( samLinear, lerp(Tile_LargeRoad_MIN_UV,Tile_LargeRoad_MAX_UV,Road_LXHY.xy) );
							float4 RoadColor_HXLY = TileAtlas.Sample( samLinear, lerp(Tile_LargeRoad_MIN_UV,Tile_LargeRoad_MAX_UV,Road_HXLY.xy) );
							float4 RoadColor_HXHY = TileAtlas.Sample( samLinear, lerp(Tile_LargeRoad_MIN_UV,Tile_LargeRoad_MAX_UV,Road_HXHY.xy) );
							RoadColor = lerp(lerp(RoadColor_LXLY,RoadColor_HXLY,FracRP.x),lerp(RoadColor_LXHY,RoadColor_HXHY,FracRP.x),FracRP.y);
						}
						
						SubPixelColor = lerp(SubPixelColor,float4(RoadColor.rgb, 1.0f),RoadColor.a);
					}
					
					// Draw small roads
					if (Road_LXLY.r > -0.5f && Road_LXHY.r > -0.5f && Road_HXLY.r > -0.5f && Road_HXHY.r > -0.5f) {
						float4 RoadColor;
						float2 FracRP = frac(RoadPixel);
						float4 Road;
						if ((Road_LXLY.r > 0.4f && Road_LXHY.r > 0.4f && Road_HXLY.r > 0.4f && Road_HXHY.r > 0.4f) || (Road_LXLY.r < 0.6f && Road_LXHY.r < 0.6f && Road_HXLY.r < 0.6f && Road_HXHY.r < 0.6f)) {
							// Interpolated UV
							Road = lerp(lerp(Road_LXLY,Road_HXLY,FracRP.x),lerp(Road_LXHY,Road_HXHY,FracRP.x),FracRP.y);
							float2 RoadUV = lerp(Tile_SmallRoad_MIN_UV,Tile_SmallRoad_MAX_UV,Road.rg);
							RoadColor = TileAtlas.Sample( samLinear, RoadUV );
						} else {
							// Interpolate color
							float4 RoadColor_LXLY = TileAtlas.Sample( samLinear, lerp(Tile_SmallRoad_MIN_UV,Tile_SmallRoad_MAX_UV,Road_LXLY.xy) );
							float4 RoadColor_LXHY = TileAtlas.Sample( samLinear, lerp(Tile_SmallRoad_MIN_UV,Tile_SmallRoad_MAX_UV,Road_LXHY.xy) );
							float4 RoadColor_HXLY = TileAtlas.Sample( samLinear, lerp(Tile_SmallRoad_MIN_UV,Tile_SmallRoad_MAX_UV,Road_HXLY.xy) );
							float4 RoadColor_HXHY = TileAtlas.Sample( samLinear, lerp(Tile_SmallRoad_MIN_UV,Tile_SmallRoad_MAX_UV,Road_HXHY.xy) );
							RoadColor = lerp(lerp(RoadColor_LXLY,RoadColor_HXLY,FracRP.x),lerp(RoadColor_LXHY,RoadColor_HXHY,FracRP.x),FracRP.y);
						}
						
						SubPixelColor = lerp(SubPixelColor,float4(RoadColor.rgb, 1.0f),RoadColor.a);
					}
				}
			}
			SumColor = SumColor + SubPixelColor;
		}
	}
	return (SumColor / 4.0f) * Color;
}
