#include "../../Direct3D/Shader/RuShader_D3D_Skin_FX.h"

#pragma managed(push, off)

// ************************************************************************************************************************************************************

CRuShader_Skin_Z::CRuShader_Skin_Z(CRuEngineD3D *engine)
:	CRuShader_Skin_Base(engine)
{
	char *vsSource = "\
																													\n\
	// Globals																										\n\
	float4x3			g_worldTransform		: register(c0);														\n\
	float4x3			g_viewTransform			: register(c3);														\n\
	float4x4			g_projectionTransform	: register(c6);														\n\
																													\n\
	float4				g_ambientColor			: register(c10);													\n\
	float4				g_shCoefficients[9]		: register(c11);													\n\
	float4				g_selfIllumination		: register(c23);													\n\
	float4				g_globalSettings		: register(c25);		// (?, Fog Start, Fog End, Tween Factor)	\n\
	float4				g_globalDiffuse			: register(c26);													\n\
	float4x4			g_uvTransform0			: register(c27);													\n\
																													\n\
	float4x3			g_bonePalette[74] : register(c32);															\n\
																													\n\
	struct VS_INPUT																									\n\
	{																												\n\
		float4			position				: POSITION;															\n\
		float3			normal_packed			: NORMAL;															\n\
		float4			diffuse					: COLOR0;															\n\
		float4			indices					: BLENDINDICES;														\n\
		float4			weights					: BLENDWEIGHT;														\n\
		float2			texcoord				: TEXCOORD;															\n\
	};																												\n\
																													\n\
	struct VS_OUTPUT																								\n\
	{																												\n\
		float4			position				: POSITION;															\n\
		float4			color					: COLOR;															\n\
		float2			texcoord				: TEXCOORD;															\n\
		float1			fog						: FOG;																\n\
	};																												\n\
																													\n\
	VS_OUTPUT main(const VS_INPUT v)																				\n\
	{																												\n\
		VS_OUTPUT output;																							\n\
																													\n\
		// Initialize world-view vectors to 1																		\n\
		float4 objectPos = float4(0, 0, 0, 1);																		\n\
		float4 worldPos = float4(1, 1, 1, 1);																		\n\
		float4 viewPos = float4(1, 1, 1, 1);																		\n\
																													\n\
		// Skin the object																							\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[0]]) * v.weights[0] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[1]]) * v.weights[1] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[2]]) * v.weights[2] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[3]]) * v.weights[3] / 255.0f;				\n\
																													\n\
		// Transform position to projected space																	\n\
		worldPos.xyz = mul(objectPos, (float4x3) g_worldTransform);													\n\
		viewPos.xyz = mul(worldPos, (float4x3) g_viewTransform);													\n\
		output.position = mul(viewPos, (float4x4) g_projectionTransform);											\n\
																													\n\
		// Calculate fog																							\n\
		output.fog = 1.0f;																							\n\
																													\n\
		// Set output diffuse to unshaded color																		\n\
		output.color = float4(1, 1, 1, 1);																			\n\
																													\n\
		// Copy texture coordinates																					\n\
		float4 texCoordTemp = float4(v.texcoord.x, v.texcoord.y, 0, 1);												\n\
		texCoordTemp = mul(texCoordTemp, (float4x4) g_uvTransform0);												\n\
		output.texcoord.x = texCoordTemp.x;																			\n\
		output.texcoord.y = texCoordTemp.y;																			\n\
																													\n\
		return output;																								\n\
	}																												\n\
	";

	char *psSource = "\
																													\n\
	sampler2D tex0 : register(s0);																					\n\
																													\n\
	struct PS_INPUT																									\n\
	{																												\n\
		float4			position				: POSITION;															\n\
		float4			diffuse					: COLOR;															\n\
		float2			texcoord0				: TEXCOORD0;														\n\
	};																												\n\
																													\n\
	struct PS_OUTPUT																								\n\
	{																												\n\
		float4			color					: COLOR;															\n\
	};																												\n\
																													\n\
	PS_OUTPUT main(const PS_INPUT v)																				\n\
	{																												\n\
		PS_OUTPUT output;																							\n\
																													\n\
		// Sample diffuse map																						\n\
		float4 color = tex2D(tex0, v.texcoord0);																	\n\
																													\n\
		// Set color to one																							\n\
		color.x = 1.0f;																								\n\
		color.y = 1.0f;																								\n\
		color.z = 1.0f;																								\n\
																													\n\
		output.color = color;																						\n\
																													\n\
		return output;																								\n\
	}																												\n\
	";

	// Assemble vertex shader
	m_vertexShader = RuD3DCompileVertexShader(vsSource, "main", "vs_2_0", NULL);

	// Compile pixel shader
	m_pixelShader = RuD3DCompilePixelShader(psSource, "main", "ps_2_0", NULL);

	// Enable alpha blending and testing override
	m_override_AlphaBlend = TRUE;
}

CRuShader_Skin_Z::~CRuShader_Skin_Z()
{
}

void CRuShader_Skin_Z::BeginPass(INT32 passNumber)
{
	// Call base BeginPass to perform any additional setup
	CRuShader_Skin_Base::BeginPass(passNumber);

	if(passNumber == 0)
	{
		m_vertexDecl->Select();
		m_engine->SetVertexShader(m_vertexShader);
		m_engine->SetPixelShader(m_pixelShader);
		m_engine->SetVertexShaderConstants(0, m_shaderConstants, m_numBaseConstants + m_numSubFrames * 3);
		m_engine->SetPixelShaderConstants(0, m_pixelShaderConstants, m_numBasePixelShaderConstants);

		m_engine->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
		m_engine->SetRenderState(D3DRS_COLORWRITEENABLE, 0);

		m_engine->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

		m_engine->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
		m_engine->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);

		m_engine->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
	}
}

void CRuShader_Skin_Z::SetParameters(const CRuParameterCache *paramCache)
{
	// Chain set parameters call to parent
	CRuShader_Skin_Base::SetParameters(paramCache);
}

// ************************************************************************************************************************************************************

CRuShader_Skin_Unshaded::CRuShader_Skin_Unshaded(CRuEngineD3D *engine)
:	CRuShader_Skin_Base(engine)
{
	char *vsSource = "\
																													\n\
	// Globals																										\n\
	float4x3			g_worldTransform : register(c0);															\n\
	float4x3			g_viewTransform : register(c3);																\n\
	float4x4			g_projectionTransform : register(c6);														\n\
																													\n\
	float4				g_ambientColor : register(c10);																\n\
	float4				g_shCoefficients[9] : register(c11);														\n\
	float4				g_selfIllumination : register(c23);															\n\
	float4				g_globalSettings : register(c25);		// (?, Fog Start, Fog End, Tween Factor)			\n\
	float4				g_globalDiffuse : register(c26);															\n\
	float4x4			g_uvTransform0			: register(c27);													\n\
	float4				g_unshadedColor : register(c31);															\n\
																													\n\
	float4x3			g_bonePalette[74] : register(c32);															\n\
																													\n\
	struct VS_INPUT																									\n\
	{																												\n\
		float4			position				: POSITION;															\n\
		float3			normal_packed			: NORMAL;															\n\
		float4			diffuse					: COLOR0;															\n\
		float4			indices					: BLENDINDICES;														\n\
		float4			weights					: BLENDWEIGHT;														\n\
		float2			texcoord				: TEXCOORD;															\n\
	};																												\n\
																													\n\
	struct VS_OUTPUT																								\n\
	{																												\n\
		float4			position : POSITION;																		\n\
		float4			color : COLOR;																				\n\
		float2			texcoord : TEXCOORD;																		\n\
		float1			fog : FOG;																					\n\
	};																												\n\
																													\n\
	VS_OUTPUT main(const VS_INPUT v)																				\n\
	{																												\n\
		VS_OUTPUT output;																							\n\
																													\n\
		// Initialize world-view vectors to 1																		\n\
		float4 objectPos = float4(0, 0, 0, 1);																		\n\
		float4 worldPos = float4(1, 1, 1, 1);																		\n\
		float4 viewPos = float4(1, 1, 1, 1);																		\n\
																													\n\
		// Skin the object																							\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[0]]) * v.weights[0] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[1]]) * v.weights[1] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[2]]) * v.weights[2] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[3]]) * v.weights[3] / 255.0f;				\n\
																													\n\
		// Transform position to projected space																	\n\
		worldPos.xyz = mul(objectPos, (float4x3) g_worldTransform);													\n\
		viewPos.xyz = mul(worldPos, (float4x3) g_viewTransform);													\n\
		output.position = mul(viewPos, (float4x4) g_projectionTransform);											\n\
																													\n\
		// Calculate fog																							\n\
		output.fog = 1.0f;																							\n\
																													\n\
		// Set output diffuse to unshaded color																		\n\
		output.color = g_unshadedColor;																				\n\
																													\n\
		// Copy texture coordinates																					\n\
		float4 texCoordTemp = float4(v.texcoord.x, v.texcoord.y, 0, 1);												\n\
		texCoordTemp = mul(texCoordTemp, (float4x4) g_uvTransform0);												\n\
		output.texcoord.x = texCoordTemp.x;																			\n\
		output.texcoord.y = texCoordTemp.y;																			\n\
																													\n\
		return output;																								\n\
	}																												\n\
	";

	char *psSource = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	; Texture sampling																								\n\
	tex					t0											; Sample diffuse texture						\n\
																													\n\
	; Arithmetic ops																								\n\
	mov					r0,			v0								; Copy diffuse color to output					\n\
	mul					r0.w,		r0,			t0.w				; Copy texture alpha to output					\n\
	";

	// Assemble vertex shader
	m_vertexShader = RuD3DCompileVertexShader(vsSource, "main", "vs_2_0", NULL);

	// Assemble pixel shader
	m_pixelShader = RuD3DAssemblePixelShader(psSource);

	// Enable alpha blending override
	m_override_AlphaBlend = TRUE;
}

CRuShader_Skin_Unshaded::~CRuShader_Skin_Unshaded()
{
}

void CRuShader_Skin_Unshaded::BeginPass(INT32 passNumber)
{
	m_override_AlphaTest = TRUE;
	m_override_AlphaBlend = TRUE;

	// Call base BeginPass to perform any additional setup
	CRuShader_Skin_Base::BeginPass(passNumber);

	if(passNumber == 0)
	{
		m_vertexDecl->Select();
		m_engine->SetVertexShader(m_vertexShader);
		m_engine->SetPixelShader(m_pixelShader);
		m_engine->SetVertexShaderConstants(0, m_shaderConstants, m_numBaseConstants + m_numSubFrames * 3);
		m_engine->SetPixelShaderConstants(0, m_pixelShaderConstants, m_numBasePixelShaderConstants);

		m_engine->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

		m_engine->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

		m_engine->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
		m_engine->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);

		m_engine->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);

		m_engine->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
		m_engine->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
//		m_engine->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
		m_engine->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
	}
}

void CRuShader_Skin_Unshaded::SetParameters(const CRuParameterCache *paramCache)
{
	// Chain set parameters call to parent
	CRuShader_Skin_Base::SetParameters(paramCache);

	DWORD param;
	if(paramCache->GetParameter(ruPARAMTYPE_DWORD_0, param))
	{
		INT32 unshadedColorOffset = 31 * 4;
		RUCOLOR unshadedColor = static_cast<RUCOLOR>(param);

		m_shaderConstants[unshadedColorOffset++] = ((unshadedColor >> 16) & 0xFF) / 255.0f;
		m_shaderConstants[unshadedColorOffset++] = ((unshadedColor >>  8) & 0xFF) / 255.0f;
		m_shaderConstants[unshadedColorOffset++] = ((unshadedColor >>  0) & 0xFF) / 255.0f;
		m_shaderConstants[unshadedColorOffset++] = ((unshadedColor >> 24) & 0xFF) / 255.0f;
	}
}

// ************************************************************************************************************************************************************

CRuShader_Skin_Highlight::CRuShader_Skin_Highlight(CRuEngineD3D *engine)
:	CRuShader_Skin_Base(engine)
{
	char *vsSource = "\
																													\n\
	// Globals																										\n\
	float4x3			g_worldTransform : register(c0);															\n\
	float4x3			g_viewTransform : register(c3);																\n\
	float4x4			g_projectionTransform : register(c6);														\n\
																													\n\
	float4				g_ambientColor : register(c10);																\n\
	float4				g_shCoefficients[9] : register(c11);														\n\
	float4				g_selfIllumination : register(c23);															\n\
	float4				g_globalSettings : register(c25);		// (?, Fog Start, Fog End, Tween Factor)			\n\
	float4				g_globalDiffuse : register(c26);															\n\
	float4				g_highlightColor : register(c31);															\n\
																													\n\
	float4x3			g_bonePalette[74] : register(c32);															\n\
																													\n\
	struct VS_INPUT																									\n\
	{																												\n\
		float4			position				: POSITION;															\n\
		float3			normal_packed			: NORMAL;															\n\
		float4			diffuse					: COLOR0;															\n\
		float4			indices					: BLENDINDICES;														\n\
		float4			weights					: BLENDWEIGHT;														\n\
		float2			texcoord				: TEXCOORD;															\n\
	};																												\n\
																													\n\
	struct VS_OUTPUT																								\n\
	{																												\n\
		float4			position : POSITION;																		\n\
		float4			color : COLOR;																				\n\
		float2			texcoord : TEXCOORD;																		\n\
		float1			fog : FOG;																					\n\
	};																												\n\
																													\n\
	VS_OUTPUT main(const VS_INPUT v)																				\n\
	{																												\n\
		VS_OUTPUT output;																							\n\
																													\n\
		// Initialize world-view vectors to 1																		\n\
		float4 objectPos = float4(0, 0, 0, 1);																		\n\
		float4 worldPos = float4(1, 1, 1, 1);																		\n\
		float4 viewPos = float4(1, 1, 1, 1);																		\n\
																													\n\
		// Skin the object																							\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[0]]) * v.weights[0] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[1]]) * v.weights[1] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[2]]) * v.weights[2] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[3]]) * v.weights[3] / 255.0f;				\n\
																													\n\
		// Transform position to projected space																	\n\
		worldPos.xyz = mul(objectPos, (float4x3) g_worldTransform);													\n\
		viewPos.xyz = mul(worldPos, (float4x3) g_viewTransform);													\n\
		output.position = mul(viewPos, (float4x4) g_projectionTransform);											\n\
																													\n\
		// Calculate fog																							\n\
		float1 rcpFogRange = 1.0f / (g_globalSettings.z - g_globalSettings.y);										\n\
		float1 relativeZ = max(viewPos.z - g_globalSettings.y, 0.0f);												\n\
		output.fog = clamp(1.0f - (relativeZ * rcpFogRange) - g_globalSettings.x, 0.0f, 1.0f);						\n\
																													\n\
		// Accumulate global diffuse and self illumination															\n\
		output.color = g_highlightColor;																			\n\
																													\n\
		// Copy texture coordinates																					\n\
		output.texcoord = v.texcoord;																				\n\
																													\n\
		return output;																								\n\
	}																												\n\
	";

	char *psSource = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	; Texture sampling																								\n\
	tex					t0											; Sample diffuse texture						\n\
																													\n\
	; Arithmetic ops																								\n\
	mov					r0,			v0								; Copy diffuse color to output					\n\
	mov					r0.w,		t0.w							; Copy texture alpha to output					\n\
	";

	// Assemble vertex shader
	m_vertexShader = RuD3DCompileVertexShader(vsSource, "main", "vs_2_0", NULL);

	// Assemble pixel shader
	m_pixelShader = RuD3DAssemblePixelShader(psSource);

	// Enable alpha blending override
	m_override_AlphaBlend = TRUE;
}

CRuShader_Skin_Highlight::~CRuShader_Skin_Highlight()
{
}

void CRuShader_Skin_Highlight::BeginPass(INT32 passNumber)
{
	// Call base BeginPass to perform any additional setup
	CRuShader_Skin_Base::BeginPass(passNumber);

	if(passNumber == 0)
	{
		m_vertexDecl->Select();
		m_engine->SetVertexShader(m_vertexShader);
		m_engine->SetPixelShader(m_pixelShader);
		m_engine->SetVertexShaderConstants(0, m_shaderConstants, m_numBaseConstants + m_numSubFrames * 3);
		m_engine->SetPixelShaderConstants(0, m_pixelShaderConstants, m_numBasePixelShaderConstants);

		m_engine->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

		m_engine->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

		m_engine->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
		m_engine->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);

		m_engine->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
		m_engine->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
		m_engine->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
	}
}

void CRuShader_Skin_Highlight::SetParameters(const CRuParameterCache *paramCache)
{
	// Chain set parameters call to parent
	CRuShader_Skin_Base::SetParameters(paramCache);

	DWORD param;
	if(paramCache->GetParameter(ruPARAMTYPE_DWORD_0, param))
	{
		INT32 highlightColorOffset = 31 * 4;
		RUCOLOR highlightColor = static_cast<RUCOLOR>(param);

		m_shaderConstants[highlightColorOffset++] = ((highlightColor >> 16) & 0xFF) / 255.0f;
		m_shaderConstants[highlightColorOffset++] = ((highlightColor >>  8) & 0xFF) / 255.0f;
		m_shaderConstants[highlightColorOffset++] = ((highlightColor >>  0) & 0xFF) / 255.0f;
	}
}

// ************************************************************************************************************************************************************

CRuShader_Skin_CelHighlight::CRuShader_Skin_CelHighlight(CRuEngineD3D *engine)
:	CRuShader_Skin_Base(engine)
{
	char *vsSource = "\
																													\n\
	// Globals																										\n\
	float4x3			g_worldTransform : register(c0);															\n\
	float4x3			g_viewTransform : register(c3);																\n\
	float4x4			g_projectionTransform : register(c6);														\n\
																													\n\
	float4				g_ambientColor : register(c10);																\n\
	float4				g_shCoefficients[9] : register(c11);														\n\
	float4				g_selfIllumination : register(c23);															\n\
	float4				g_globalSettings : register(c25);		// (?, Fog Start, Fog End, Tween Factor)			\n\
	float4				g_globalDiffuse : register(c26);															\n\
	float4				g_highlightColor : register(c31);															\n\
																													\n\
	float4x3			g_bonePalette[74] : register(c32);															\n\
																													\n\
	struct VS_INPUT																									\n\
	{																												\n\
		float4			position				: POSITION;															\n\
		float3			normal_packed			: NORMAL;															\n\
		float4			diffuse					: COLOR0;															\n\
		float4			indices					: BLENDINDICES;														\n\
		float4			weights					: BLENDWEIGHT;														\n\
		float2			texcoord				: TEXCOORD;															\n\
	};																												\n\
																													\n\
	struct VS_OUTPUT																								\n\
	{																												\n\
		float4			position : POSITION;																		\n\
		float4			color : COLOR;																				\n\
		float2			texcoord : TEXCOORD;																		\n\
		float1			fog : FOG;																					\n\
	};																												\n\
																													\n\
	VS_OUTPUT main(const VS_INPUT v)																				\n\
	{																												\n\
		VS_OUTPUT output;																							\n\
																													\n\
		// Initialize world-view vectors to 1																		\n\
		float4 objectPos = float4(0, 0, 0, 1);																		\n\
		float4 objectNormal = float4(0, 0, 0, 1);																	\n\
		float4 scaledPos = float4(1, 1, 1, 1);																		\n\
		float4 worldPos = float4(1, 1, 1, 1);																		\n\
		float4 viewPos = float4(1, 1, 1, 1);																		\n\
																													\n\
		// Skin the object																							\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[0]]) * v.weights[0] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[1]]) * v.weights[1] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[2]]) * v.weights[2] / 255.0f;				\n\
		objectPos.xyz += mul(v.position, g_bonePalette[(int) v.indices[3]]) * v.weights[3] / 255.0f;				\n\
																													\n\
		// Unpack normal																							\n\
		float3 normal = (v.normal_packed.xyz - 127.0f) / 127.0f;													\n\
																													\n\
		objectNormal.xyz += mul(normal, g_bonePalette[(int) v.indices[0]]) * v.weights[0] / 255.0f;					\n\
		objectNormal.xyz += mul(normal, g_bonePalette[(int) v.indices[1]]) * v.weights[1] / 255.0f;					\n\
		objectNormal.xyz += mul(normal, g_bonePalette[(int) v.indices[2]]) * v.weights[2] / 255.0f;					\n\
		objectNormal.xyz += mul(normal, g_bonePalette[(int) v.indices[3]]) * v.weights[3] / 255.0f;					\n\
																													\n\
		// Transform position to projected space																	\n\
		scaledPos.xyz = objectPos.xyz + objectNormal.xyz * 0.25f;													\n\
		worldPos.xyz = mul(scaledPos, (float4x3) g_worldTransform);													\n\
		viewPos.xyz = mul(worldPos, (float4x3) g_viewTransform);													\n\
		output.position = mul(viewPos, (float4x4) g_projectionTransform);											\n\
																													\n\
		// Calculate fog																							\n\
		float1 rcpFogRange = 1.0f / (g_globalSettings.z - g_globalSettings.y);										\n\
		float1 relativeZ = max(viewPos.z - g_globalSettings.y, 0.0f);												\n\
		output.fog = clamp(1.0f - (relativeZ * rcpFogRange) - g_globalSettings.x, 0.0f, 1.0f);						\n\
																													\n\
		// Accumulate global diffuse and self illumination															\n\
		output.color = g_highlightColor;																			\n\
																													\n\
		// Copy texture coordinates																					\n\
		output.texcoord = v.texcoord;																				\n\
																													\n\
		return output;																								\n\
	}																												\n\
	";

	char *psSource = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	; Arithmetic ops																								\n\
	mov					r0,			v0								; Direcly output VS diffuse color				\n\
	";

	// Assemble vertex shader
	m_vertexShader = RuD3DCompileVertexShader(vsSource, "main", "vs_2_0", NULL);

	// Assemble pixel shader
	m_pixelShader = RuD3DAssemblePixelShader(psSource);
}

CRuShader_Skin_CelHighlight::~CRuShader_Skin_CelHighlight()
{
}

void CRuShader_Skin_CelHighlight::BeginPass(INT32 passNumber)
{
	// Reverse culling mode
	m_fx_ReverseCull = TRUE;

	// Call base BeginPass to perform any additional setup
	CRuShader_Skin_Base::BeginPass(passNumber);

	if(passNumber == 0)
	{
		m_vertexDecl->Select();
		m_engine->SetVertexShader(m_vertexShader);
		m_engine->SetPixelShader(m_pixelShader);
		m_engine->SetVertexShaderConstants(0, m_shaderConstants, m_numBaseConstants + m_numSubFrames * 3);
		m_engine->SetPixelShaderConstants(0, m_pixelShaderConstants, m_numBasePixelShaderConstants);

		m_engine->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);

		m_engine->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

		m_engine->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
		m_engine->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
	}
}

void CRuShader_Skin_CelHighlight::SetParameters(const CRuParameterCache *paramCache)
{
	// Chain set parameters call to parent
	CRuShader_Skin_Base::SetParameters(paramCache);

	DWORD param;
	if(paramCache->GetParameter(ruPARAMTYPE_DWORD_0, param))
	{
		INT32 highlightColorOffset = 31 * 4;
		RUCOLOR highlightColor = static_cast<RUCOLOR>(param);

		m_shaderConstants[highlightColorOffset++] = ((highlightColor >> 16) & 0xFF) / 255.0f;
		m_shaderConstants[highlightColorOffset++] = ((highlightColor >>  8) & 0xFF) / 255.0f;
		m_shaderConstants[highlightColorOffset++] = ((highlightColor >>  0) & 0xFF) / 255.0f;
		m_shaderConstants[highlightColorOffset++] = 1.0f;
	}
}

// ************************************************************************************************************************************************************

#pragma managed(pop)
