// Interface
interface IMaterial
{
	float4 GetColor(float2 texCoords);
};

// Solid color material
float4 staticColor;
class SolidMaterial : IMaterial
{
	float4 GetColor(float2 texCoords);
};

float4 SolidMaterial::GetColor(float2 texCoords)
{
	return staticColor;
}

// Texture material
Texture2D diffuseTexture;
SamplerState diffuseSampler
{
	Filter = MIN_MAG_MIP_LINEAR;
	AddressU = Wrap;
	AddressV = Wrap;
};

class TextureMaterial : IMaterial
{
	float4 GetColor(float2 texCoords);
};

float4 TextureMaterial::GetColor(float2 texCoords)
{
	return diffuseTexture.Sample(diffuseSampler, texCoords);
}

// Instances
cbuffer cbInstances
{
	SolidMaterial cSolidMaterial;
	TextureMaterial cTextureMaterial;
}

// Effect
IMaterial abstractMaterial;

cbuffer globals
{
	matrix worldProjectionMatrix;
}

struct VS_IN
{
	float3 pos : POSITION;
	float2 uv : TEXCOORD0;
};

struct PS_IN
{
	float4 pos : SV_POSITION;
	float2 uv : TEXCOORD0;
};

// Vertex Shader
PS_IN VS( VS_IN input )
{
	PS_IN output = (PS_IN)0;
	
	output.pos = mul(float4(input.pos, 1), worldProjectionMatrix);
	output.uv = input.uv;
	
	return output;
}

// Pixel Shader
float4 PS( PS_IN input ) : SV_Target
{
	return abstractMaterial.GetColor(input.uv);	
}

// Technique

technique11 Render11
{
	pass P0
	{
		SetGeometryShader( 0 );
		SetVertexShader( CompileShader( vs_5_0, VS() ) );
		SetPixelShader( CompileShader( ps_5_0, PS() ) );
	}
}