// **** RESPONSIVE UI SHADER ****
// Contributors: SinsOfSeven
// Ispired by VV_Mod_Maker

Texture1D<float4> IniParams : register(t120);

#define SIZE IniParams[87].xy
#define OFFSET IniParams[87].zw
#define FLIP_SCALE IniParams[88].x
#define LOCKED IniParams[88].y
#define FLIP_TILT IniParams[88].z
#define GRADIENT IniParams[88].w

struct vs2ps {
	float4 pos : SV_Position0;
	float2 uv : TEXCOORD1;
};

#ifdef VERTEX_SHADER
void main(
		out vs2ps output,
		uint vertex : SV_VertexID)
{
	float2 BaseCoord,Offset;
	Offset.x = OFFSET.x*2-1;
	Offset.y = (1-OFFSET.y)*2-1;
	BaseCoord.xy = float2((2*SIZE.x),(2*(-SIZE.y)));
	// Not using vertex buffers so manufacture our own coordinates.
	switch(vertex) {
		case 0:
			output.pos.xy = float2(BaseCoord.x+Offset.x, BaseCoord.y+Offset.y);
			output.uv = float2(1,0);
			break;
		case 1:
			output.pos.xy = float2(BaseCoord.x+Offset.x, 0+Offset.y);
			output.uv = float2(1,1);
			break;
		case 2:
			output.pos.xy = float2(0+Offset.x, BaseCoord.y+Offset.y);
			output.uv = float2(0,0);
			break;
		case 3:
			output.pos.xy = float2(0+Offset.x, 0+Offset.y);
			output.uv = float2(0,1);
			break;
		default:
			output.pos.xy = 0;
			output.uv = float2(0,0);
			break;
	};
	float flipScale = FLIP_SCALE;
	if (flipScale <= 0) flipScale = 1;
	float2 center = Offset + float2(SIZE.x, -SIZE.y);
	float2 rel = output.pos.xy - center;
	rel.x *= flipScale;
	rel.y += (output.uv.x - 0.5) * FLIP_TILT * SIZE.y * 1.35;
	rel.x += (output.uv.y - 0.5) * FLIP_TILT * SIZE.x * 0.18;
	output.pos.xy = center + rel;
	output.pos.zw = float2(0, 1);
}
#endif

#ifdef PIXEL_SHADER
Texture2D<float4> tex : register(t100);

float4 load_texel_clamped(int2 p, int2 size)
{
	p = clamp(p, int2(0, 0), size - int2(1, 1));
	return tex.Load(int3(p, 0));
}

float4 sample_linear(float2 uv, int2 size)
{
	float2 p = saturate(uv) * (float2(size) - 1.0);
	int2 p0 = int2(floor(p));
	int2 p1 = min(p0 + int2(1, 1), size - int2(1, 1));
	float2 f = frac(p);
	float4 c00 = load_texel_clamped(p0, size);
	float4 c10 = load_texel_clamped(int2(p1.x, p0.y), size);
	float4 c01 = load_texel_clamped(int2(p0.x, p1.y), size);
	float4 c11 = load_texel_clamped(p1, size);
	return lerp(lerp(c00, c10, f.x), lerp(c01, c11, f.x), f.y);
}

void main(vs2ps input, out float4 result : SV_Target0)
{
	uint width, height;
	tex.GetDimensions(width, height);
	if (!width || !height) discard;
	input.uv.y = 1 - input.uv.y;
	int2 texSize = int2(width, height);
	float2 uv = input.uv.xy;
	float2 dx = ddx(uv) * 0.35;
	float2 dy = ddy(uv) * 0.35;
	result = sample_linear(uv, texSize) * 0.72;
	result += (sample_linear(uv + dx, texSize) + sample_linear(uv - dx, texSize) + sample_linear(uv + dy, texSize) + sample_linear(uv - dy, texSize)) * 0.07;
	float gradient = GRADIENT;
	if (abs(gradient) > 0.0001) {
		float gradientAbs = abs(gradient);
		bool invertMask = gradientAbs > 1.0;
		float progress = saturate(gradientAbs - (invertMask ? 1.0 : 0.0));
		float coord = saturate(input.uv.x + (input.uv.y - 0.5) * 0.22);
		if (gradient < 0) coord = 1 - coord;
		float edge = 0.22;
		float mask = saturate((progress * (1 + edge) - coord) / edge);
		if (invertMask) mask = 1 - mask;
		result.w *= mask;
	}
	if (LOCKED == 1) result.w = min(result.w, 0.15);
}
#endif
