//--------------------------------------------------------------------
// Block Outlining with Instancing
// Author: Ben Smith
// Date  : November 28th, 2005
//--------------------------------------------------------------------

#include "Effects/StdFunctions.fx"

//--------------------------------------------------------------------
// Global Variables
//--------------------------------------------------------------------
#define MAX_INST 45
float4   PositionArray[MAX_INST];
float4   ScaleArray[MAX_INST];
float4	 OrientationArray[MAX_INST];
float4	 ColorArray[MAX_INST];

//--------------------------------------------------------------------
// External Texture for Outline
//--------------------------------------------------------------------
texture  texOutline : EXTTEXTURE
<
  int TextureID = 26;
>;

//--------------------------------------------------------------------
// Vertex Shader Output Structure
//--------------------------------------------------------------------
struct VS_OUTPUT
{
    float4 position   : POSITION;  //Vertex position on screen
    float4 lightColor : COLOR;     //Lit Color at vertex
    float2 texCoords  : TEXCOORD0; //Vertex texture coordinates
};

//--------------------------------------------------------------------
// Vertex Shader that computes screen position, texture coordinates,
// and lit vertex color.
//--------------------------------------------------------------------
VS_OUTPUT VSRenderScene( float4 pos : POSITION,
			 float3 normal : NORMAL,
			 float2 texCoords: TEXCOORD0,
			 float	instanceID : TEXCOORD1 )
{
    VS_OUTPUT Output;

    //Calculate screen position of vertex
    float3x3 rot = QuaternionToMatrix(OrientationArray[instanceID]);
    pos.xyz = pos.xyz*ScaleArray[instanceID].xyz;
    pos.xyz = mul(pos.xyz, rot);
    pos.xyz += PositionArray[instanceID].xyz;
    Output.position = mul(pos,ViewProjection);

    //Set U,V coordinates
    Output.texCoords = texCoords;
    
    //Phong Vertex Lighting
    float3 nnormal = mul(normal, rot)*ScaleArray[instanceID].xyz;
    float  diffuseI = saturate(dot(nnormal, LightDir));
    Output.lightColor.rgb = diffuseI*ColorArray[instanceID].rgb + ColorArray[instanceID].rgb;
	Output.lightColor.a = ColorArray[instanceID].a;

    return Output;
}

sampler Sampler = sampler_state
{
    Texture = (Tex);
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
};

sampler OutlineSampler = sampler_state
{
    Texture = (texOutline);
	MinFilter = Linear;
	MagFilter = Linear;
};

//--------------------------------------------------------------------
// Pixel Shader Output Structure
//--------------------------------------------------------------------
struct PS_OUTPUT
{
    float4 color : COLOR;     //Pixel's final color
};

//--------------------------------------------------------------------
// Pixel Shader that computes pixel color based on vertex color and
// texture.
//--------------------------------------------------------------------
PS_OUTPUT PSRenderScene( VS_OUTPUT Input, uniform bool hasTexture )
{
    PS_OUTPUT Output;

	if (hasTexture)
		Output.color.rgb = tex2D(OutlineSampler, Input.texCoords)*tex2D(Sampler, Input.texCoords)*Input.lightColor.rgb;
    else
		Output.color.rgb = tex2D(OutlineSampler, Input.texCoords)*Input.lightColor.rgb;
		
	Output.color.a = Input.lightColor.a;
    
    return Output;
}

//--------------------------------------------------------------------------------------
// Medium Requirement Scene Rendering
//-------------------------------------- ------------------------------------------------
technique RenderScene
{
    pass Scene
    {
		//Clockwise culling for RHW
		CULLMODE = CW;
		
		ZENABLE = true;
		ZWRITEENABLE = true;

        VertexShader = compile vs_2_0 VSRenderScene();
        PixelShader  = compile ps_2_0 PSRenderScene(true);
    }
}

technique RenderScene_NoTexture
{
    pass Scene
    {
		//Clockwise culling for RHW
		CULLMODE = CW;
		
		ZENABLE = true;
		ZWRITEENABLE = true;

        VertexShader = compile vs_2_0 VSRenderScene();
        PixelShader  = compile ps_2_0 PSRenderScene(false);
    }
}
