// AUTOGENERATED COPYRIGHT HEADER START
// Copyright (C) 2021-2023 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
// AUTOGENERATED COPYRIGHT HEADER END

#include "shared.effect"

uniform texture2d InputA<
	bool automatic = true;
>;

uniform float2 CornerTL<
	string name = "Corner: Top Left";
	string field_type = "slider";
	string suffix = " %";
	float2 minimum = {-100., -100.};
	float2 maximum = {-200., -200.};
	float2 step = {.01, .01};
	float2 scale = {.01, .01};
> = {0., 0.};

uniform float2 CornerTR<
	string name = "Corner: Top Right";
	string field_type = "slider";
	string suffix = " %";
	float2 minimum = {-100., -100.};
	float2 maximum = {-200., -200.};
	float2 step = {.01, .01};
	float2 scale = {.01, .01};
> = {100., 0.};

uniform float2 CornerBL<
	string name = "Corner: Bottom Left";
	string field_type = "slider";
	string suffix = " %";
	float2 minimum = {-100., -100.};
	float2 maximum = {-200., -200.};
	float2 step = {.01, .01};
	float2 scale = {.01, .01};
> = {0., 100.};

uniform float2 CornerBR<
	string name = "Corner: Bottom Right";
	string field_type = "slider";
	string suffix = " %";
	float2 minimum = {-100., -100.};
	float2 maximum = {-200., -200.};
	float2 step = {.01, .01};
	float2 scale = {.01, .01};
> = {100., 100.};

//------------------------------------------------------------------------------
// Technique: Corner Pin
//------------------------------------------------------------------------------
//
// Credits:
// - Inigo Quilez: https://www.iquilezles.org/www/articles/ibilinear/ibilinear.htm
//
// Parameters:
// - InputA: RGBA Texture
// - CornerTL: Corner "A"
// - CornerTR: Corner "B"
// - CornerBL: Corner "D"
// - CornerBR: Corner "C"

float cross2d(in float2 a, in float2 b) {
	return (a.x * b.y) - (a.y * b.x);
};

float2 inverse_bilinear(in float2 p, in float2 a, in float2 b, in float2 c, in float2 d) {
	float2 result = float2(-1., -1.);

	float2 e = b - a;
	float2 f = d - a;
	float2 g = a-b+c-d;
	float2 h = p-a;

	float k2 = cross2d(g, f);
	float k1 = cross2d(e, f) + cross2d(h, g);
	float k0 = cross2d(h, e);

	if (abs(k2) < .001) { // Edges are likely parallel, so this is a linear equation.
		result = float2(
			(h.x * k1 + f.x * k0) / (e.x * k1 - g.x * k0),
			-k0 / k1
		);
	} else { // It's a quadratic equation.
		float w = k1 * k1 - 4.0 * k0 * k2;
		if (w < 0.0) { // Prevent GPUs from going insane.
			return result;
		}
		w = sqrt(w);

		float ik2 = 0.5/k2;
		float v = (-k1 - w) * ik2;
		float u = (h.x - f.x * v) / (e.x + g.x * v);

		if (u < 0.0 || u > 1.0 || v < 0.0 || v > 1.0) {
			v = (-k1 + w) * ik2;
			u = (h.x - f.x * v) / (e.x + g.x * v);
		}

		result = float2(u, v);
	}

	return result;
};

float4 PSCornerPin(VertexData vtx) : TARGET {
	// Convert from screen coords to potential Quad UV coordinates.
	float2 uv = inverse_bilinear((vtx.uv * 2.) - 1., CornerTL, CornerTR, CornerBR, CornerBL);

	if (max(abs(uv.x - .5), abs(uv.y - .5)) >= .5) {
		return float4(0, 0, 0, 0);
	}

	return InputA.Sample(BlankSampler, uv);
};

technique CornerPin
{
	pass
	{
		vertex_shader = DefaultVertexShader(vtx);
		pixel_shader = PSCornerPin(vtx);
	};
};
