// Provided by OBS
uniform float4x4 ViewProj <
	bool visible = false;
>;

uniform texture2d image <
	bool visible = false;
>;

// Parameters
uniform float2 image_size <
	bool visible = false;
>;

uniform float2 image_inverse_size <
	bool visible = false;
>;

uniform texture2d normal <
	bool visible = true;
	string name = "Normal Map";
	string description = "A normal map that is used for displacing the texture sample locations.";
>;

uniform float2 scale <
	bool visible = true;
	string mode = "slider";
	float2 minimum = {0.0, 0.0};
	float2 maximum = {100.0, 100.0};
	float2 step = {0.01, 0.01};
> = {0.0, 0.0};

uniform float scale_type <
	bool visible = true;
	string mode = "slider";
	string name = "Scale Mode";
	string description = "A value of 0.0 is in Texel Space, while a value of 100.0 is in Pixel Space.";
	float2 minimum = {0.0, 0.0};
	float2 maximum = {100.0, 100.0};
	float2 step = {0.01, 0.01};
> = 0.0;

// Samplers
sampler_state smp_linear_wrap {
	Filter = Linear;
	AddressU = Wrap;
	AddressV = Wrap;
};

sampler_state smp_linear_clamp {
	Filter = Linear;
	AddressU = Clamp;
	AddressV = Clamp;
};

// Structs
struct FunctionData {
	float4 pos : POSITION;
	float2 uv : TEXCOORD0;
};

// Functions
FunctionData vertex_shader(FunctionData v) {
	v.pos = mul(float4(v.pos.xyz, 1.0), ViewProj);
	return v;
};

float4 pixel_shader(FunctionData v) : TARGET {
	float4 v_normal = normal.Sample(smp_linear_wrap, v.uv);

	float2 offset = v_normal.rg;
	offset -= float2(.5, .5);
	offset *= 255.0;
	offset = floor(abs(offset)) * sign(offset);
	offset /= 127.0;

	offset *= lerp(float2(1.0, 1.0), image_inverse_size, scale_type);
	offset *= scale;

	return image.Sample(smp_linear_clamp, v.uv + offset);
};

// Techniques
technique Draw
{
	pass
	{
		vertex_shader = vertex_shader(v);
		pixel_shader  = pixel_shader(v);
	}
}
