#include "world.inc"
#include "material.inc"


struct VS_INPUT
{
	float4 Pos : POSITION;
	float4 Col : COLOR0;
	uint NumVert : NUMVERTEX;
};

struct GS_INPUT
{
	float4 Pos : SV_POSITION;
	float4 WorldPos : TEXCOORD0;
	float4 Col : COLOR0;
	uint NumVert : COLOR1;
};

struct PS_INPUT
{
	float4 Pos : SV_POSITION;
	float4 WorldPos : TEXCOORD0;
	float4 Col : COLOR0;
};


GS_INPUT VS(const VS_INPUT In)
{
	GS_INPUT Out;
	Out.Pos = mul(In.Pos, WorldViewProj);
	Out.WorldPos = In.Pos;
	Out.Col = In.Col;
	Out.NumVert = In.NumVert;
	return Out;
}

// Geometry shader for point with a size
[maxvertexcount(16)]
void GS(lineadj GS_INPUT input[4], inout TriangleStream<PS_INPUT> stream)
{
	PS_INPUT output;

	float2 sv0 = input[0].Pos.xy / input[0].Pos.w;
	float2 sv1 = input[1].Pos.xy / input[1].Pos.w;
	float2 sv2 = input[2].Pos.xy / input[2].Pos.w;
	float2 sv3 = input[3].Pos.xy / input[3].Pos.w;
	float inprod1, inprod2;
	if(input[0].NumVert >= 3){
		inprod1 = (sv1.x-sv0.x) * (sv2.y-sv1.y)
	            - (sv1.y-sv0.y) * (sv2.x-sv1.x);
	}else{
		inprod1 = 1.0;
	}
	if(input[0].NumVert >= 4){
		inprod2 = (sv2.x-sv0.x) * (sv3.y-sv2.y)
	            - (sv2.y-sv0.y) * (sv3.x-sv2.x);
	}else{
		inprod2 = -1.0;
	}
	float a = (inprod1 > 0 || inprod2 > 0) ? 1.0 : BackLineAlpha;
	if(a > 0.0){
		for(uint i=0; i<input[0].NumVert; i++){
			if(input[i].Col.a > 0.0){
				float dx = input[i].Pos.w * 2.0f * PointSize / Resolution.x;
				float dy = input[i].Pos.w * 2.0f * PointSize / Resolution.y;

				output.WorldPos = input[i].WorldPos;
				output.Col = input[i].Col;

				// Emit two new triangles
				output.Pos = input[i].Pos;
				output.Pos.x -= dx;
				output.Pos.y -= dy;
				stream.Append(output);

				output.Pos = input[i].Pos;
				output.Pos.x += dx;
				output.Pos.y -= dy;
				stream.Append(output);

				output.Pos = input[i].Pos;
				output.Pos.x -= dx;
				output.Pos.y += dy;
				stream.Append(output);

				output.Pos = input[i].Pos;
				output.Pos.x += dx;
				output.Pos.y += dy;
				stream.Append(output);

				stream.RestartStrip();
			}
		}
	}
}

float4 PS(PS_INPUT In) : SV_Target
{
	if(IsArbClipped(In.WorldPos.xyz))
		discard;	
	return In.Col;
}

