#include "../../../Direct3D/Shader/SM10/RuShader_SM10_Terrain.h"

#pragma managed(push, off)

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

CRuShader_SM10_Terrain_Base::CRuShader_SM10_Terrain_Base(CRuEngineD3D *engine)
:	CRuShader_SM10_Base(engine)
{
	// Setup vertex elements
	CRuVertexElement vertexElements[] =
	{
		{ 0,	0,	ruELEMENTTYPE_FLOAT3,		ruELEMENTMETHOD_DEFAULT,	ruELEMENTUSAGE_POSITION,	0 },
		{ 0,	12,	ruELEMENTTYPE_FLOAT3,		ruELEMENTMETHOD_DEFAULT,	ruELEMENTUSAGE_NORMAL,		0 },
		{ 0,	24,	ruELEMENTTYPE_RUCOLOR,		ruELEMENTMETHOD_DEFAULT,	ruELEMENTUSAGE_COLOR,		0 },
		{ 0,	28,	ruELEMENTTYPE_FLOAT2,		ruELEMENTMETHOD_DEFAULT,	ruELEMENTUSAGE_TEXCOORD,	0 },
		RUVERTEXDECL_END()
	};

	// Construct vertex declaration
	m_vertexDecl = m_engine->CreateVertexDeclaration(vertexElements);
}

CRuShader_SM10_Terrain_Base::~CRuShader_SM10_Terrain_Base()
{
}

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

CRuShader_SM10_Terrain::CRuShader_SM10_Terrain(CRuEngineD3D *engine)
:	CRuShader_SM10_Terrain_Base(engine),
	m_maxLayersPerPass(6),
	m_maxTextureLayers(12),
	m_numTextureLayers(0)
{
	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);	// Spherical harmonics coefficients				\n\
	float4				g_specularDirection		: register(c21);	// Object space specular position				\n\
	float4				g_specularColor			: register(c22);													\n\
	float4				g_selfIllumination		: register(c23);	// Self-illumination term						\n\
	float4				g_globalSettings		: register(c25);	// (Fog Constant, Start, End, Extrude Scale)	\n\
	float4				g_globalDiffuse			: register(c26);													\n\
	float4				g_alphaUVModifier		: register(c27);													\n\
	float4				g_uvStretchModifier		: register(c28);													\n\
																													\n\
	struct VS_INPUT																									\n\
	{																												\n\
		float4			position				: POSITION;															\n\
		float3			normal					: NORMAL;															\n\
		float4			diffuse					: COLOR0;															\n\
		float2			texcoord				: TEXCOORD;															\n\
	};																												\n\
																													\n\
	struct VS_OUTPUT																								\n\
	{																												\n\
		float4			position				: POSITION;															\n\
		float4			diffuse					: COLOR0;															\n\
		float4			specular				: COLOR1;															\n\
		float2			texcoord0				: TEXCOORD0;														\n\
		float2			texcoord1				: TEXCOORD1;														\n\
		float2			texcoord2				: TEXCOORD2;														\n\
		float2			texcoord3				: TEXCOORD3;														\n\
		float2			texcoord4				: TEXCOORD4;														\n\
		float2			texcoord5				: TEXCOORD5;														\n\
		float2			texcoord6				: TEXCOORD6;														\n\
		float2			texcoord7				: TEXCOORD7;														\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 worldPos = float4(1, 1, 1, 1);																		\n\
		float4 viewPos = float4(1, 1, 1, 1);																		\n\
																													\n\
		// Transform position to projected space																	\n\
		worldPos.xyz = v.position.xyz + v.normal.xyz * g_globalSettings.w;											\n\
		worldPos.xyz = mul(worldPos, (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 ambient color																					\n\
		output.diffuse = g_ambientColor;																			\n\
																													\n\
		// Accumulate SH color																						\n\
		output.diffuse += g_shCoefficients[0];																		\n\
		output.diffuse += g_shCoefficients[1] * (float4) v.normal.x;												\n\
		output.diffuse += g_shCoefficients[2] * (float4) v.normal.y;												\n\
		output.diffuse += g_shCoefficients[3] * (float4) v.normal.z;												\n\
		output.diffuse += g_shCoefficients[4] * (float4) (v.normal.x * v.normal.z);									\n\
		output.diffuse += g_shCoefficients[5] * (float4) (v.normal.z * v.normal.y);									\n\
		output.diffuse += g_shCoefficients[6] * (float4) (v.normal.y * v.normal.x);									\n\
		output.diffuse += g_shCoefficients[7] * (float4) (3 * v.normal.z * v.normal.z - 1);							\n\
		output.diffuse += g_shCoefficients[8] * (float4) (v.normal.x * v.normal.x - v.normal.y * v.normal.y);		\n\
																													\n\
		// Lerp between real lighting color and self-illumination color based on self-illumination strength			\n\
		output.diffuse.xyz = lerp(output.diffuse.xyz, g_selfIllumination.xyz, g_selfIllumination.w);				\n\
																													\n\
		// Set lighting alpha to 1																					\n\
		output.diffuse.w = 1;																						\n\
																													\n\
		// Modulate lighting color with vertex color																\n\
		output.diffuse *= v.diffuse;																				\n\
																													\n\
		// Modulate final diffuse color by the global diffuse modifier												\n\
		output.diffuse *= g_globalDiffuse;																			\n\
																													\n\
		// Transform normal to view space																			\n\
		float3 N = normalize(mul(mul(v.normal, g_worldTransform), g_viewTransform));								\n\
																													\n\
		// Specular																									\n\
		float3 V = normalize(-viewPos.xyz);																			\n\
		float3 L = g_specularDirection;																				\n\
																													\n\
		L = normalize(mul(mul(L, (float3x3) g_worldTransform), (float3x3) g_viewTransform));						\n\
																													\n\
		float3 H = normalize(V + L);																				\n\
		float1 NL = dot(N, L);																						\n\
																													\n\
		if(NL > 0.0f)																								\n\
			NL = 1.0f;																								\n\
		else																										\n\
			NL = 0.0f;																								\n\
																													\n\
		float1 HN = clamp(dot(H, N), 0.0f, 1.0f);																	\n\
		float1 specularPower = pow(HN, 32) * NL * 3.0f;																\n\
																													\n\
		output.specular.xyz = g_specularColor * specularPower.xxxx;													\n\
		output.specular.w = 1.0f;																					\n\
																													\n\
		// Copy texture coordinates																					\n\
		float2 stretchedUV = v.texcoord.xy * g_uvStretchModifier.xy;												\n\
																													\n\
		output.texcoord0 = v.texcoord;																				\n\
		output.texcoord1 = stretchedUV;																				\n\
		output.texcoord2 = stretchedUV;																				\n\
		output.texcoord3 = stretchedUV;																				\n\
		output.texcoord4 = v.texcoord;																				\n\
		output.texcoord5 = stretchedUV;																				\n\
		output.texcoord6 = stretchedUV;																				\n\
		output.texcoord7 = stretchedUV;																				\n\
																													\n\
		return output;																								\n\
	}																												\n\
	";

	char *psSource0_1_1 = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	; Fog																											\n\
	mov					r0,			c1								; Move fog color to output						\n\
	mov					r0.w,		v0.w							; Move fog factor to output alpha				\n\
	";

	char *psSource1_1_1 = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	def					c1,			1.0, 0.0, 0.0, 0.0																\n\
																													\n\
	; Texture sampling																								\n\
	tex					t0											; Sample alpha 0								\n\
	tex					t1											; Sample splat 0								\n\
																													\n\
	; Arithmetic ops																								\n\
	dp3					r1,			t0,			c1					; Get RED into r1								\n\
	mul_sat				r0,			t1,			r1					; Modulate layer 0								\n\
																													\n\
	; Fog and diffuse color																							\n\
	mul					r0.xyz,		r0,			v0					; Modulate base texture with diffuse into r0	\n\
	";

	char *psSource2_1_1 = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	def					c1,			1.0, 0.0, 0.0, 0.0																\n\
	def					c2,			0.0, 1.0, 0.0, 0.0																\n\
																													\n\
	; Texture sampling																								\n\
	tex					t0											; Sample alpha 0								\n\
	tex					t1											; Sample splat 0								\n\
	tex					t2											; Sample splat 1								\n\
																													\n\
	; Arithmetic ops																								\n\
	dp3					r1,			t0,			c1					; Get RED into r1								\n\
	mul_sat				r0,			t1,			r1					; Modulate layer 0								\n\
																													\n\
	dp3					r1,			t0,			c2					; Get BLUE into r1								\n\
	mad_sat				r0,			t2,			r1,			r0		; Modulate layer 1								\n\
																													\n\
	; Fog and diffuse color																							\n\
	mul					r0.xyz,		r0,			v0					; Modulate base texture with diffuse into r0	\n\
	";

	char *psSource3_1_1 = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	def					c1,			1.0, 0.0, 0.0, 0.0																\n\
	def					c2,			0.0, 1.0, 0.0, 0.0																\n\
	def					c3,			0.0, 0.0, 1.0, 0.0																\n\
																													\n\
	; Texture sampling																								\n\
	tex					t0											; Sample alpha 0								\n\
	tex					t1											; Sample splat 0								\n\
	tex					t2											; Sample splat 1								\n\
	tex					t3											; Sample splat 2								\n\
																													\n\
	; Arithmetic ops																								\n\
	dp3					r1,			t0,			c1					; Get RED into r1								\n\
	mul_sat				r0,			t1,			r1					; Modulate layer 0								\n\
																													\n\
	dp3					r1,			t0,			c2					; Get BLUE into r1								\n\
	mad_sat				r0,			t2,			r1,			r0		; Modulate layer 1								\n\
																													\n\
	dp3					r1,			t0,			c3					; Get GREEN into r1								\n\
	mad_sat				r0,			t3,			r1,			r0		; Modulate layer 2								\n\
																													\n\
	mul					r0.xyz,		r0,			v0					; Modulate base texture with diffuse into r0	\n\
	";

	char *psSourceFog_1_1 = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	; Fog																											\n\
	mov					r0,			c1								; Move fog color to output						\n\
	mov					r0.w,		v0.w							; Move fog factor to output alpha				\n\
	";

	char *psSource_SM2_D2_L1 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; ALPHA_0										\n\
	dcl_2d				s1											; LAYER_0										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s0					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s1					; Sample layer 0								\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r7,			c1,			r9.x				; Modulate fog color by alpha factor into r7	\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v0.w,		r8,			r7		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L2 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; ALPHA_0										\n\
	dcl_2d				s1											; LAYER_0										\n\
	dcl_2d				s2											; LAYER_1										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
	dcl					t2.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s0					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s1					; Sample layer 0								\n\
	texld_pp			r2,			t2,			s2					; Sample layer 1								\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r7,			c1,			r9.x				; Modulate fog color by alpha factor into r7	\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v0.w,		r8,			r7		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L3 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; ALPHA_0										\n\
	dcl_2d				s1											; LAYER_0										\n\
	dcl_2d				s2											; LAYER_1										\n\
	dcl_2d				s3											; LAYER_2										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
	dcl					t2.xy																						\n\
	dcl					t3.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s0					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s1					; Sample layer 0								\n\
	texld_pp			r2,			t2,			s2					; Sample layer 1								\n\
	texld_pp			r3,			t3,			s3					; Sample layer 2								\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r7,			c1,			r9.x				; Modulate fog color by alpha factor into r7	\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v0.w,		r8,			r7		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L4 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; ALPHA_0										\n\
	dcl_2d				s1											; LAYER_0										\n\
	dcl_2d				s2											; LAYER_1										\n\
	dcl_2d				s3											; LAYER_2										\n\
	dcl_2d				s4											; ALPHA_1										\n\
	dcl_2d				s5											; LAYER_3										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
	dcl					t2.xy																						\n\
	dcl					t3.xy																						\n\
	dcl					t4.xy																						\n\
	dcl					t5.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s0					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s1					; Sample layer 0								\n\
	texld_pp			r2,			t2,			s2					; Sample layer 1								\n\
	texld_pp			r3,			t3,			s3					; Sample layer 2								\n\
	texld_pp			r4,			t4,			s4					; Sample ALPHA_1 into R2						\n\
	texld_pp			r5,			t5,			s5					; Sample layer 3								\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
	mad_pp				r8,			r5,			r4.x,		r8		; Multiply layer 3 by its factor into R8		\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	dp3_pp				r9.y,		r4,			c0.x				; Combine alpha factor from ALPHA_1 into r9.y	\n\
	add_pp				r9.x,		r9.x,		r9.y				; Combine alpha factor from both textures		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r7,			c1,			r9.x				; Modulate fog color by alpha factor into r7	\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v0.w,		r8,			r7		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L5 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; ALPHA_0										\n\
	dcl_2d				s1											; LAYER_0										\n\
	dcl_2d				s2											; LAYER_1										\n\
	dcl_2d				s3											; LAYER_2										\n\
	dcl_2d				s4											; ALPHA_1										\n\
	dcl_2d				s5											; LAYER_3										\n\
	dcl_2d				s6											; LAYER_4										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
	dcl					t2.xy																						\n\
	dcl					t3.xy																						\n\
	dcl					t4.xy																						\n\
	dcl					t5.xy																						\n\
	dcl					t6.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s0					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s1					; Sample layer 0								\n\
	texld_pp			r2,			t2,			s2					; Sample layer 1								\n\
	texld_pp			r3,			t3,			s3					; Sample layer 2								\n\
	texld_pp			r4,			t4,			s4					; Sample ALPHA_1 into R2						\n\
	texld_pp			r5,			t5,			s5					; Sample layer 3								\n\
	texld_pp			r6,			t6,			s6					; Sample layer 4								\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
	mad_pp				r8,			r5,			r4.x,		r8		; Multiply layer 3 by its factor into R8		\n\
	mad_pp				r8,			r6,			r4.y,		r8		; Multiply layer 4 by its factor into R8		\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	dp3_pp				r9.y,		r4,			c0.x				; Combine alpha factor from ALPHA_1 into r9.y	\n\
	add_pp				r9.x,		r9.x,		r9.y				; Combine alpha factor from both textures		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r7,			c1,			r9.x				; Modulate fog color by alpha factor into r7	\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v0.w,		r8,			r7		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L6 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; ALPHA_0										\n\
	dcl_2d				s1											; LAYER_0										\n\
	dcl_2d				s2											; LAYER_1										\n\
	dcl_2d				s3											; LAYER_2										\n\
	dcl_2d				s4											; ALPHA_1										\n\
	dcl_2d				s5											; LAYER_3										\n\
	dcl_2d				s6											; LAYER_4										\n\
	dcl_2d				s7											; LAYER_5										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
	dcl					t2.xy																						\n\
	dcl					t3.xy																						\n\
	dcl					t4.xy																						\n\
	dcl					t5.xy																						\n\
	dcl					t6.xy																						\n\
	dcl					t7.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n\
																													\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s0					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s1					; Sample layer 0								\n\
	texld_pp			r2,			t2,			s2					; Sample layer 1								\n\
	texld_pp			r3,			t3,			s3					; Sample layer 2								\n\
	texld_pp			r4,			t4,			s4					; Sample ALPHA_1 into R2						\n\
	texld_pp			r5,			t5,			s5					; Sample layer 3								\n\
	texld_pp			r6,			t6,			s6					; Sample layer 4								\n\
	texld_pp			r7,			t7,			s7					; Sample layer 5								\n"
	"																												\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
	mad_pp				r8,			r5,			r4.x,		r8		; Multiply layer 3 by its factor into R8		\n\
	mad_pp				r8,			r6,			r4.y,		r8		; Multiply layer 4 by its factor into R8		\n\
	mad_pp				r8,			r7,			r4.z,		r8		; Multiply layer 5 by its factor into R8		\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	dp3_pp				r9.y,		r4,			c0.x				; Combine alpha factor from ALPHA_1 into r9.y	\n\
	add_pp				r9.x,		r9.x,		r9.y				; Combine alpha factor from both textures		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r7,			c1,			r9.x				; Modulate fog color by alpha factor into r7	\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v0.w,		r8,			r7		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSources_1_1[] = { psSource0_1_1, psSource1_1_1, psSource2_1_1, psSource3_1_1, psSourceFog_1_1 };
	char *psSources_2_0[] = { psSource0_1_1, psSource_SM2_D2_L1, psSource_SM2_D2_L2, psSource_SM2_D2_L3, psSource_SM2_D2_L4, psSource_SM2_D2_L5, psSource_SM2_D2_L6 };

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

	// Assemble pixel shaders (1.1)
	for(INT32 i = 0; i < 5; ++i)
	{
		m_pixelShaders_1_1[i] = RuD3DAssemblePixelShader(psSources_1_1[i]);

		if(m_pixelShaders_1_1[i] == NULL)
		{
			// Massive error, no pixel-shading capabilities
			m_maxLayersPerPass = 0;
		}
	}

	// Assemble pixel shaders (2.0)
	for(INT32 i = 0; i < 7; ++i)
	{
		m_pixelShaders_2_0[i] = RuD3DAssemblePixelShader(psSources_2_0[i]);

		if(m_pixelShaders_2_0[i] == NULL)
		{
			m_maxLayersPerPass = 3;
		}
	}

	// Overrides
	m_override_ZWrite = TRUE;
}

CRuShader_SM10_Terrain::~CRuShader_SM10_Terrain()
{
	for(INT32 i = 0; i < 5; ++i)
	{
		ruSAFE_RELEASE(m_pixelShaders_1_1[i]);
	}

	for(INT32 i = 0; i < 7; ++i)
	{
		ruSAFE_RELEASE(m_pixelShaders_2_0[i]);
	}
}

void CRuShader_SM10_Terrain::BeginPass(INT32 passNumber)
{
	BOOL isFogPass = ((passNumber == m_numPasses - 1) && (m_maxLayersPerPass == 3)) ? TRUE : FALSE;

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

	// Common
	INT32 uvStretchModifierConstantsOffset = 28 * 4;
	m_shaderConstants[uvStretchModifierConstantsOffset++] = 24.0f;
	m_shaderConstants[uvStretchModifierConstantsOffset++] = -24.0f;
	m_shaderConstants[uvStretchModifierConstantsOffset++] = 4.0f;
	m_shaderConstants[uvStretchModifierConstantsOffset++] = 4.0f;

	m_vertexDecl->Select();
	m_engine->SetVertexShader(m_vertexShader);

	INT32 numTexturesRemaining = m_numTextureLayers - (passNumber * m_maxLayersPerPass);

	if(m_maxLayersPerPass == 6)
	{
		// If the number of textures remaining is greater than the maximum number of layers per pass, then ...
		if(numTexturesRemaining >= m_maxLayersPerPass)
		{
			m_engine->SetPixelShader(m_pixelShaders_2_0[m_maxLayersPerPass]);
		}
		else
		{
			m_engine->SetPixelShader(m_pixelShaders_2_0[numTexturesRemaining]);
		}
	}
	else
	{
		// Fog pass - no samplers
		if(isFogPass)
		{
			m_engine->SetPixelShader(m_pixelShaders_1_1[4]);
		}
		else
		{
			// If the number of textures remaining is greater than the maximum number of layers per pass, then ...
			if(numTexturesRemaining >= m_maxLayersPerPass)
			{
				m_engine->SetPixelShader(m_pixelShaders_1_1[m_maxLayersPerPass]);
			}
			else
			{
				m_engine->SetPixelShader(m_pixelShaders_1_1[numTexturesRemaining]);
			}
		}
	}

	// Set shader constants
	m_engine->SetVertexShaderConstants(0, m_shaderConstants, m_numBaseConstants);
	m_engine->SetPixelShaderConstants(0, m_pixelShaderConstants, m_numBasePixelShaderConstants);

	for(INT32 i = 0; i < 8; ++i)
	{
		m_engine->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
		m_engine->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);

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

		m_engine->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 4);
	}

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

	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(4, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
	m_engine->SetSamplerState(4, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);

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

	if(passNumber == 0)
	{
		m_engine->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);

		m_engine->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

		m_engine->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
	}
	else
	{
		if(isFogPass)
		{
			m_engine->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
			m_engine->SetRenderState(D3DRS_ALPHAREF, 0xFF);
			m_engine->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS);

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

			m_engine->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
		}
		else
		{
			m_engine->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
			m_engine->SetRenderState(D3DRS_ALPHAREF, 0x00);
			m_engine->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);

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

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

void CRuShader_SM10_Terrain::EndPass(INT32 passNumber)
{
	CRuShader_SM10_Terrain_Base::EndPass(passNumber);
}

void CRuShader_SM10_Terrain::SetParameters(const CRuParameterCache *paramCache)
{
	DWORD param;

	CRuShader_SM10_Terrain_Base::SetParameters(paramCache);

	if(paramCache->GetParameter(ruPARAMTYPE_SPLAT_ALPHAUVMODIFIER, param))
	{
		if(param)
		{
			INT32 uvModifierConstantsOffset = 27 * 4;
			float *uvModifier = (float *) param;

			m_shaderConstants[uvModifierConstantsOffset++] = uvModifier[0];
			m_shaderConstants[uvModifierConstantsOffset++] = uvModifier[1];
			m_shaderConstants[uvModifierConstantsOffset++] = uvModifier[2];
			m_shaderConstants[uvModifierConstantsOffset++] = uvModifier[3];
		}
	}

	if(paramCache->GetParameter(ruPARAMTYPE_SPLAT_LAYERCOUNT, param))
	{
		// Set the number of texture layers to blend
		m_numTextureLayers = param;

		if(m_numTextureLayers == 0)
		{
			m_numPasses = 1;
		}
		else
		{
			// If the number of texture layers requested exceeds the maximum allowed, cap it
			if(m_numTextureLayers > m_maxTextureLayers)
			{
				m_numTextureLayers = m_maxTextureLayers;
			}

			// Calculate the number of passes
			m_numPasses = (m_numTextureLayers / m_maxLayersPerPass) + ((m_numTextureLayers % m_maxLayersPerPass) ? 1 : 0);

			// Pixel Shader 1.1 has one extra fog pass
			if(m_maxLayersPerPass == 3)
			{
				m_numPasses += 1;
			}
		}
	}
}

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

CRuShader_SM10_Terrain_Packed_Base::CRuShader_SM10_Terrain_Packed_Base(CRuEngineD3D *engine)
:	CRuShader_SM10_Base(engine)
{
	// Setup vertex elements
	CRuVertexElement vertexElements[] =
	{
		{ 0,	0,	ruELEMENTTYPE_UBYTE4,		ruELEMENTMETHOD_DEFAULT,	ruELEMENTUSAGE_POSITION,	0 },
		{ 0,	4,	ruELEMENTTYPE_RUCOLOR,		ruELEMENTMETHOD_DEFAULT,	ruELEMENTUSAGE_COLOR,		0 },
		RUVERTEXDECL_END()
	};

	// Construct vertex declaration
	m_vertexDecl = m_engine->CreateVertexDeclaration(vertexElements);

	// Overrides
	m_override_ZWrite = TRUE;
}

CRuShader_SM10_Terrain_Packed_Base::~CRuShader_SM10_Terrain_Packed_Base()
{
}

void CRuShader_SM10_Terrain_Packed_Base::SetParameters(const CRuParameterCache *paramCache)
{
	// Chain to base class
	CRuShader_SM10_Base::SetParameters(paramCache);

	DWORD param;

	if(paramCache->GetParameter(ruPARAMTYPE_CHUNK_SPACING, param))
	{
		m_chunk_Spacing = RuCastDWORDToFloat(param);
	}

	if(paramCache->GetParameter(ruPARAMTYPE_CHUNK_Y_BASE, param))
	{
		m_chunk_Y_Base = RuCastDWORDToFloat(param);
	}

	if(paramCache->GetParameter(ruPARAMTYPE_CHUNK_Y_INCREMENT, param))
	{
		m_chunk_Y_Increment = RuCastDWORDToFloat(param);
	}

	INT32 constOffset_spc_base_inc_x = 29 * 4;
	m_shaderConstants[constOffset_spc_base_inc_x++] = m_chunk_Spacing;
	m_shaderConstants[constOffset_spc_base_inc_x++] = m_chunk_Y_Base;
	m_shaderConstants[constOffset_spc_base_inc_x++] = m_chunk_Y_Increment;
}

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

CRuShader_SM10_Terrain_Packed::CRuShader_SM10_Terrain_Packed(CRuEngineD3D *engine)
:	CRuShader_SM10_Terrain_Packed_Base(engine),
	m_maxLayersPerPass(6),
	m_maxTextureLayers(12),
	m_numTextureLayers(0)
{
	m_override_Fog = FALSE;
	m_override_AlphaTest = TRUE;
	m_override_AlphaBlend = TRUE;

	char *vsSource_Simple = "\
																													\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);		// Spherical harmonics coefficients			\n\
	float4				g_specularDirection		: register(c21);		// Object space specular position			\n\
	float4				g_specularColor			: register(c22);													\n\
	float4				g_selfIllumination		: register(c23);		// Self-illumination term					\n\
	float4				g_globalSettings		: register(c25);		// (?, Fog Start, Fog End, Tween Factor)	\n\
	float4				g_globalDiffuse			: register(c26);													\n\
	float4				g_alphaUVModifier		: register(c27);													\n\
	float4				g_uvStretchModifier		: register(c28);													\n\
	float4				g_spc_base_inc_x		: register(c29);		// (spacing, y base, y increment, undefined)\n\
																													\n\
	struct VS_INPUT																									\n\
	{																												\n\
		float4			x_z_yH_yL				: POSITION;															\n\
		float4			diffuse					: COLOR0;				// Packed as (0xAAXXYYZZ)					\n\
	};																												\n\
																													\n\
	struct VS_OUTPUT																								\n\
	{																												\n\
		float4			position				: POSITION;															\n\
		float4			diffuse					: COLOR0;															\n\
		float4			specular				: COLOR1;															\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 localPos = float4(1, 1, 1, 1);																		\n\
		float4 worldPos = float4(1, 1, 1, 1);																		\n\
		float4 viewPos = float4(1, 1, 1, 1);																		\n\
																													\n\
		// Unpack world position																					\n\
		localPos.x = v.x_z_yH_yL.x * g_spc_base_inc_x.x;															\n\
		localPos.z = v.x_z_yH_yL.y * g_spc_base_inc_x.x;															\n\
		localPos.y = (v.x_z_yH_yL.z * 255 + v.x_z_yH_yL.w) * g_spc_base_inc_x.z + g_spc_base_inc_x.y;				\n\
																													\n\
		// Transform position to projected space																	\n\
		worldPos.xyz = mul(localPos, (float4x3) g_worldTransform);													\n\
		viewPos.xyz = mul(worldPos, (float4x3) g_viewTransform);													\n\
		output.position = mul(viewPos, (float4x4) g_projectionTransform);											\n\
																													\n\
		// Output full fog																							\n\
		output.fog = 1.0f;																							\n\
																													\n\
		// Accumulate global diffuse and self illumination															\n\
		output.diffuse = float4(1.0f, 1.0f, 1.0f, 1.0f);															\n\
		output.specular = float4(1.0f, 1.0f, 1.0f, 1.0f);															\n\
																													\n\
		return output;																								\n\
	}																												\n\
	";

	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);		// Spherical harmonics coefficients			\n\
	float4				g_specularDirection		: register(c21);		// Object space specular position			\n\
	float4				g_specularColor			: register(c22);													\n\
	float4				g_selfIllumination		: register(c23);		// Self-illumination term					\n\
	float4				g_globalSettings		: register(c25);		// (Fog Constant, Fog Start, Fog End, Tween Factor)	\n\
	float4				g_globalDiffuse			: register(c26);													\n\
	float4				g_alphaUVModifier		: register(c27);													\n\
	float4				g_uvStretchModifier		: register(c28);													\n\
	float4				g_spc_base_inc_x		: register(c29);		// (spacing, y base, y increment, undefined)\n\
																													\n\
	struct VS_INPUT																									\n\
	{																												\n\
		float4			x_z_yH_yL				: POSITION;															\n\
		float4			diffuse					: COLOR0;				// Packed as (0xAAXXYYZZ)					\n\
	};																												\n\
																													\n\
	struct VS_OUTPUT																								\n\
	{																												\n\
		float4			position				: POSITION;															\n\
		float4			diffuse					: COLOR0;															\n\
		float4			specular				: COLOR1;															\n\
		float2			texcoord0				: TEXCOORD0;														\n\
		float2			texcoord1				: TEXCOORD1;														\n\
		float2			texcoord2				: TEXCOORD2;														\n\
		float2			texcoord3				: TEXCOORD3;														\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 localPos = float4(1, 1, 1, 1);																		\n\
		float4 worldPos = float4(1, 1, 1, 1);																		\n\
		float4 viewPos = float4(1, 1, 1, 1);																		\n\
																													\n\
		// Unpack world position																					\n\
		localPos.x = v.x_z_yH_yL.x * g_spc_base_inc_x.x;															\n\
		localPos.z = v.x_z_yH_yL.y * g_spc_base_inc_x.x;															\n\
		localPos.y = (v.x_z_yH_yL.z * 255 + v.x_z_yH_yL.w) * g_spc_base_inc_x.z + g_spc_base_inc_x.y;				\n\
																													\n\
		// Transform position to projected space																	\n\
		worldPos.xyz = mul(localPos, (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\
		// Unpack normal																							\n\
		float3 normal = (v.diffuse.xyz - 0.5f) * 2.0f;																\n\
																													\n\
		// Accumulate ambient color																					\n\
		output.diffuse = g_ambientColor;																			\n\
																													\n\
		// Accumulate SH color																						\n\
		output.diffuse += g_shCoefficients[0];																		\n\
		output.diffuse += g_shCoefficients[1] * (float4) normal.x;													\n\
		output.diffuse += g_shCoefficients[2] * (float4) normal.y;													\n\
		output.diffuse += g_shCoefficients[3] * (float4) normal.z;													\n\
		output.diffuse += g_shCoefficients[4] * (float4) (normal.x * normal.z);										\n\
		output.diffuse += g_shCoefficients[5] * (float4) (normal.z * normal.y);										\n\
		output.diffuse += g_shCoefficients[6] * (float4) (normal.y * normal.x);										\n\
		output.diffuse += g_shCoefficients[7] * (float4) (3 * normal.z * normal.z - 1);								\n\
		output.diffuse += g_shCoefficients[8] * (float4) (normal.x * normal.x - normal.y * normal.y);				\n\
																													\n\
		// Lerp between real lighting color and self-illumination color based on self-illumination strength			\n\
		output.diffuse.xyz = lerp(output.diffuse.xyz, g_selfIllumination.xyz, g_selfIllumination.w);				\n\
																													\n\
		// Set lighting alpha to 1																					\n\
		output.diffuse.w = 1;																						\n\
																													\n\
		// Modulate final diffuse color by the global diffuse modifier												\n\
		output.diffuse *= g_globalDiffuse;																			\n\
																													\n\
		// Transform normal to view space																			\n\
		float3 N = normalize(mul(mul(normal, g_worldTransform), g_viewTransform));									\n\
																													\n\
		// Specular																									\n\
		float3 V = normalize(-viewPos.xyz);																			\n\
		float3 L = g_specularDirection;																				\n\
																													\n\
		L = normalize(mul(mul(L, (float3x3) g_worldTransform), (float3x3) g_viewTransform));						\n\
																													\n\
		float3 H = normalize(V + L);																				\n\
		float1 NL = dot(N, L);																						\n\
																													\n\
		if(NL > 0.0f)																								\n\
			NL = 1.0f;																								\n\
		else																										\n\
			NL = 0.0f;																								\n\
																													\n\
		float1 HN = clamp(dot(H, N), 0.0f, 1.0f);																	\n\
		float1 specularPower = pow(HN, 32) * NL * 3.0f;																\n\
																													\n\
		output.specular.xyz = g_specularColor * specularPower.xxxx;													\n\
		output.specular.w = 1.0f;																					\n\
																													\n\
		// Copy texture coordinates																					\n\
		float2 alphaTexUV = localPos.xz * g_alphaUVModifier.zz;														\n\
		float2 stretchedUV = alphaTexUV * g_uvStretchModifier.xy;													\n\
																													\n\
		output.texcoord0 = alphaTexUV;																				\n\
		output.texcoord1 = stretchedUV;																				\n\
		output.texcoord2 = stretchedUV;																				\n\
		output.texcoord3 = stretchedUV;																				\n\
																													\n\
		return output;																								\n\
	}																												\n\
	";

	char *psSource0_1_1 = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	; Fog																											\n\
	mov					r0,			c1								; Move fog color to output						\n\
	mov					r0.w,		v0.w							; Move fog factor to output alpha				\n\
	";

	char *psSource1_1_1 = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	def					c1,			1.0, 0.0, 0.0, 0.0																\n\
																													\n\
	; Texture sampling																								\n\
	tex					t0											; Sample alpha 0								\n\
	tex					t1											; Sample splat 0								\n\
																													\n\
	; Arithmetic ops																								\n\
	dp3					r1,			t0,			c1					; Get RED into r1								\n\
	mul_sat				r0,			t1,			r1					; Modulate layer 0								\n\
																													\n\
	; Fog and diffuse color																							\n\
	mul					r0.xyz,		r0,			v0					; Modulate base texture with diffuse into r0	\n\
	";

	char *psSource2_1_1 = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	def					c1,			1.0, 0.0, 0.0, 0.0																\n\
	def					c2,			0.0, 1.0, 0.0, 0.0																\n\
																													\n\
	; Texture sampling																								\n\
	tex					t0											; Sample alpha 0								\n\
	tex					t1											; Sample splat 0								\n\
	tex					t2											; Sample splat 1								\n\
																													\n\
	; Arithmetic ops																								\n\
	dp3					r1,			t0,			c1					; Get RED into r1								\n\
	mul_sat				r0,			t1,			r1					; Modulate layer 0								\n\
																													\n\
	dp3					r1,			t0,			c2					; Get BLUE into r1								\n\
	mad_sat				r0,			t2,			r1,			r0		; Modulate layer 1								\n\
																													\n\
	; Fog and diffuse color																							\n\
	mul					r0.xyz,		r0,			v0					; Modulate base texture with diffuse into r0	\n\
	";

	char *psSource3_1_1 = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	def					c1,			1.0, 0.0, 0.0, 0.0																\n\
	def					c2,			0.0, 1.0, 0.0, 0.0																\n\
	def					c3,			0.0, 0.0, 1.0, 0.0																\n\
																													\n\
	; Texture sampling																								\n\
	tex					t0											; Sample alpha 0								\n\
	tex					t1											; Sample splat 0								\n\
	tex					t2											; Sample splat 1								\n\
	tex					t3											; Sample splat 2								\n\
																													\n\
	; Arithmetic ops																								\n\
	dp3					r1,			t0,			c1					; Get RED into r1								\n\
	mul_sat				r0,			t1,			r1					; Modulate layer 0								\n\
																													\n\
	dp3					r1,			t0,			c2					; Get BLUE into r1								\n\
	mad_sat				r0,			t2,			r1,			r0		; Modulate layer 1								\n\
																													\n\
	dp3					r1,			t0,			c3					; Get GREEN into r1								\n\
	mad_sat				r0,			t3,			r1,			r0		; Modulate layer 2								\n\
																													\n\
	mul					r0.xyz,		r0,			v0					; Modulate base texture with diffuse into r0	\n\
	";

	char *psSourceFog_1_1 = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	; Fog																											\n\
	mov					r0,			c1								; Move fog color to output						\n\
	mov					r0.w,		v0.w							; Move fog factor to output alpha				\n\
	";

	char *psSource_SM2_D1_L1 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D1_L2 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
	dcl_2d				s3											; LAYER_1										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
	texld_pp			r2,			t1,			s3					; Sample layer 1								\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	add_pp				r9.x,		r0.x,		r0.y				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	rcp_pp				r9.y,		r9.x							; Calculate reciprocal of total alpha factor	\n\
	mul_pp				r0.xyz,		r0,			r9.y				; Scale alpha factor such that the total is one	\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D1_L3 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
	dcl_2d				s3											; LAYER_1										\n\
	dcl_2d				s4											; LAYER_2										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
	texld_pp			r2,			t1,			s3					; Sample layer 1								\n\
	texld_pp			r3,			t1,			s4					; Sample layer 2								\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	rcp_pp				r9.y,		r9.x							; Calculate reciprocal of total alpha factor	\n\
	mul_pp				r0.xyz,		r0,			r9.y				; Scale alpha factor such that the total is one	\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D1_L4 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
	dcl_2d				s3											; LAYER_1										\n\
	dcl_2d				s4											; LAYER_2										\n\
	dcl_2d				s5											; ALPHA_1										\n\
	dcl_2d				s6											; LAYER_3										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
	texld_pp			r2,			t1,			s3					; Sample layer 1								\n\
	texld_pp			r3,			t1,			s4					; Sample layer 2								\n\
	texld_pp			r4,			t0,			s5					; Sample ALPHA_1 into R2						\n\
	texld_pp			r5,			t1,			s6					; Sample layer 3								\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	add_pp				r9.x,		r9.x,		r4.x				; Combine alpha factor from both textures		\n\
	rcp_pp				r9.y,		r9.x							; Calculate reciprocal of total alpha factor	\n\
	mul_pp				r0.xyz,		r0,			r9.y				; Scale alpha factor such that the total is one	\n\
	mul_pp				r4.xyz,		r4,			r9.y				; Scale alpha factor such that the total is one	\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
	mad_pp				r8,			r5,			r4.x,		r8		; Multiply layer 3 by its factor into R8		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D1_L5 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
	dcl_2d				s3											; LAYER_1										\n\
	dcl_2d				s4											; LAYER_2										\n\
	dcl_2d				s5											; ALPHA_1										\n\
	dcl_2d				s6											; LAYER_3										\n\
	dcl_2d				s7											; LAYER_4										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
	texld_pp			r2,			t1,			s3					; Sample layer 1								\n\
	texld_pp			r3,			t1,			s4					; Sample layer 2								\n\
	texld_pp			r4,			t0,			s5					; Sample ALPHA_1 into R2						\n\
	texld_pp			r5,			t1,			s6					; Sample layer 3								\n\
	texld_pp			r6,			t1,			s7					; Sample layer 4								\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	dp3_pp				r9.y,		r4,			c0.x				; Combine alpha factor from ALPHA_1 into r9.y	\n\
	add_pp				r9.x,		r9.x,		r9.y				; Combine alpha factor from both textures		\n\
	rcp_pp				r9.y,		r9.x							; Calculate reciprocal of total alpha factor	\n\
	mul_pp				r0.xyz,		r0,			r9.y				; Scale alpha factor such that the total is one	\n\
	mul_pp				r4.xyz,		r4,			r9.y				; Scale alpha factor such that the total is one	\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
	mad_pp				r8,			r5,			r4.x,		r8		; Multiply layer 3 by its factor into R8		\n\
	mad_pp				r8,			r6,			r4.y,		r8		; Multiply layer 4 by its factor into R8		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D1_L6 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
	dcl_2d				s3											; LAYER_1										\n\
	dcl_2d				s4											; LAYER_2										\n\
	dcl_2d				s5											; ALPHA_1										\n\
	dcl_2d				s6											; LAYER_3										\n\
	dcl_2d				s7											; LAYER_4										\n\
	dcl_2d				s8											; LAYER_5										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n\
																													\n\
	; Texture sampling																								\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
	texld_pp			r2,			t1,			s3					; Sample layer 1								\n\
	texld_pp			r3,			t1,			s4					; Sample layer 2								\n\
	texld_pp			r4,			t0,			s5					; Sample ALPHA_1 into R2						\n\
	texld_pp			r5,			t1,			s6					; Sample layer 3								\n\
	texld_pp			r6,			t1,			s7					; Sample layer 4								\n\
	texld_pp			r7,			t1,			s8					; Sample layer 5								\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	dp3_pp				r9.y,		r4,			c0.x				; Combine alpha factor from ALPHA_1 into r9.y	\n\
	add_pp				r9.x,		r9.x,		r9.y				; Combine alpha factor from both textures		\n\
	rcp_pp				r9.y,		r9.x							; Calculate reciprocal of total alpha factor	\n\
	mul_pp				r0.xyz,		r0,			r9.y				; Scale alpha factor such that the total is one	\n\
	mul_pp				r4.xyz,		r4,			r9.y				; Scale alpha factor such that the total is one	\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
	mad_pp				r8,			r5,			r4.x,		r8		; Multiply layer 3 by its factor into R8		\n\
	mad_pp				r8,			r6,			r4.y,		r8		; Multiply layer 4 by its factor into R8		\n\
	mad_pp				r8,			r7,			r4.z,		r8		; Multiply layer 5 by its factor into R8		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mov_pp				oC0,		r0								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L1 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r10,		t0,			s0					; Sample RT LIGHTMAP into R10					\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mul_pp				r1,			r0,			r10					; Modulate by light map into r1					\n\
	mov_pp				oC0,		r1								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L2 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
	dcl_2d				s3											; LAYER_1										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r10,		t0,			s0					; Sample RT LIGHTMAP into R10					\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
	texld_pp			r2,			t1,			s3					; Sample layer 1								\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	add_pp				r9.x,		r0.x,		r0.y				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	rcp_pp				r9.y,		r9.x							; Calculate reciprocal of total alpha factor	\n\
	mul_pp				r0.xyz,		r0,			r9.y				; Scale alpha factor such that the total is one	\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mul_pp				r1,			r0,			r10					; Modulate by light map into r1					\n\
	mov_pp				oC0,		r1								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L3 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
	dcl_2d				s3											; LAYER_1										\n\
	dcl_2d				s4											; LAYER_2										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r10,		t0,			s0					; Sample RT LIGHTMAP into R10					\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
	texld_pp			r2,			t1,			s3					; Sample layer 1								\n\
	texld_pp			r3,			t1,			s4					; Sample layer 2								\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	rcp_pp				r9.y,		r9.x							; Calculate reciprocal of total alpha factor	\n\
	mul_pp				r0.xyz,		r0,			r9.y				; Scale alpha factor such that the total is one	\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mul_pp				r1,			r0,			r10					; Modulate by light map into r1					\n\
	mov_pp				oC0,		r1								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L4 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
	dcl_2d				s3											; LAYER_1										\n\
	dcl_2d				s4											; LAYER_2										\n\
	dcl_2d				s5											; ALPHA_1										\n\
	dcl_2d				s6											; LAYER_3										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r10,		t0,			s0					; Sample RT LIGHTMAP into R10					\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
	texld_pp			r2,			t1,			s3					; Sample layer 1								\n\
	texld_pp			r3,			t1,			s4					; Sample layer 2								\n\
	texld_pp			r4,			t0,			s5					; Sample ALPHA_1 into R2						\n\
	texld_pp			r5,			t1,			s6					; Sample layer 3								\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	add_pp				r9.x,		r9.x,		r4.x				; Combine alpha factor from both textures		\n\
	rcp_pp				r9.y,		r9.x							; Calculate reciprocal of total alpha factor	\n\
	mul_pp				r0.xyz,		r0,			r9.y				; Scale alpha factor such that the total is one	\n\
	mul_pp				r4.xyz,		r4,			r9.y				; Scale alpha factor such that the total is one	\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
	mad_pp				r8,			r5,			r4.x,		r8		; Multiply layer 3 by its factor into R8		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mul_pp				r1,			r0,			r10					; Modulate by light map into r1					\n\
	mov_pp				oC0,		r1								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L5 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
	dcl_2d				s3											; LAYER_1										\n\
	dcl_2d				s4											; LAYER_2										\n\
	dcl_2d				s5											; ALPHA_1										\n\
	dcl_2d				s6											; LAYER_3										\n\
	dcl_2d				s7											; LAYER_4										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n"
	"																												\n\
	; Texture sampling																								\n\
	texld_pp			r10,		t0,			s0					; Sample RT LIGHTMAP into R10					\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
	texld_pp			r2,			t1,			s3					; Sample layer 1								\n\
	texld_pp			r3,			t1,			s4					; Sample layer 2								\n\
	texld_pp			r4,			t0,			s5					; Sample ALPHA_1 into R2						\n\
	texld_pp			r5,			t1,			s6					; Sample layer 3								\n\
	texld_pp			r6,			t1,			s7					; Sample layer 4								\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	dp3_pp				r9.y,		r4,			c0.x				; Combine alpha factor from ALPHA_1 into r9.y	\n\
	add_pp				r9.x,		r9.x,		r9.y				; Combine alpha factor from both textures		\n\
	rcp_pp				r9.y,		r9.x							; Calculate reciprocal of total alpha factor	\n\
	mul_pp				r0.xyz,		r0,			r9.y				; Scale alpha factor such that the total is one	\n\
	mul_pp				r4.xyz,		r4,			r9.y				; Scale alpha factor such that the total is one	\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
	mad_pp				r8,			r5,			r4.x,		r8		; Multiply layer 3 by its factor into R8		\n\
	mad_pp				r8,			r6,			r4.y,		r8		; Multiply layer 4 by its factor into R8		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mul_pp				r1,			r0,			r10					; Modulate by light map into r1					\n\
	mov_pp				oC0,		r1								; Move result into output						\n\
	";

	char *psSource_SM2_D2_L6 = "\
																													\n\
	ps_2_0																											\n\
																													\n\
	; Declare texture samplers																						\n\
	dcl_2d				s0											; RT LIGHTMAP									\n\
	dcl_2d				s1											; ALPHA_0										\n\
	dcl_2d				s2											; LAYER_0										\n\
	dcl_2d				s3											; LAYER_1										\n\
	dcl_2d				s4											; LAYER_2										\n\
	dcl_2d				s5											; ALPHA_1										\n\
	dcl_2d				s6											; LAYER_3										\n\
	dcl_2d				s7											; LAYER_4										\n\
	dcl_2d				s8											; LAYER_5										\n\
																													\n\
	; Declare texture coordinate registers																			\n\
	dcl					t0.xy																						\n\
	dcl					t1.xy																						\n\
																													\n\
	dcl					v0.xyzw																						\n\
	dcl					v1.xyzw																						\n\
																													\n\
	; Texture sampling																								\n\
	texld_pp			r10,		t0,			s0					; Sample RT LIGHTMAP into R10					\n\
	texld_pp			r0,			t0,			s1					; Sample ALPHA_0 into R1						\n\
	texld_pp			r1,			t1,			s2					; Sample layer 0								\n\
	texld_pp			r2,			t1,			s3					; Sample layer 1								\n\
	texld_pp			r3,			t1,			s4					; Sample layer 2								\n\
	texld_pp			r4,			t0,			s5					; Sample ALPHA_1 into R2						\n\
	texld_pp			r5,			t1,			s6					; Sample layer 3								\n\
	texld_pp			r6,			t1,			s7					; Sample layer 4								\n\
	texld_pp			r7,			t1,			s8					; Sample layer 5								\n\
																													\n\
	; Accumulate alpha factor into r9																				\n\
	dp3_pp				r9.x,		r0,			c0.x				; Combine alpha factor from ALPHA_0 into r9.x	\n\
	dp3_pp				r9.y,		r4,			c0.x				; Combine alpha factor from ALPHA_1 into r9.y	\n\
	add_pp				r9.x,		r9.x,		r9.y				; Combine alpha factor from both textures		\n\
	rcp_pp				r9.y,		r9.x							; Calculate reciprocal of total alpha factor	\n\
	mul_pp				r0.xyz,		r0,			r9.y				; Scale alpha factor such that the total is one	\n\
	mul_pp				r4.xyz,		r4,			r9.y				; Scale alpha factor such that the total is one	\n\
																													\n\
	; Accumulate base color into r8																					\n\
	mul_pp				r8,			r1,			r0.x				; Multiply layer 0 by its factor into R8		\n\
	mad_pp				r8,			r2,			r0.y,		r8		; Multiply layer 1 by its factor into R8		\n\
	mad_pp				r8,			r3,			r0.z,		r8		; Multiply layer 2 by its factor into R8		\n\
	mad_pp				r8,			r5,			r4.x,		r8		; Multiply layer 3 by its factor into R8		\n\
	mad_pp				r8,			r6,			r4.y,		r8		; Multiply layer 4 by its factor into R8		\n\
	mad_pp				r8,			r7,			r4.z,		r8		; Multiply layer 5 by its factor into R8		\n\
																													\n\
	; Calculate base color * diffuse * fog																			\n\
	mul_pp				r8,			r8,			v0					; Modulate base texture with diffuse into r8	\n\
	lrp_pp				r0,			v1.w,		r8,			c1		; Linearly interpolate between fog and diffuse	\n\
																													\n\
	mad_pp				r0.xyz,		v1,			r8.w,		r0		; Modulate specular by alpha channel (*)		\n\
	mov_pp				r0.w,		r9.x							; Copy alpha factor into diffuse channel alpha	\n\
																													\n\
	; Move final result to output																					\n\
	mul_pp				r1,			r0,			r10					; Modulate by light map into r1					\n\
	mov_pp				oC0,		r1								; Move result into output						\n\
	";

	char *psSources_1_1[] = { psSource0_1_1, psSource1_1_1, psSource2_1_1, psSource3_1_1, psSourceFog_1_1 };
	char *psSources_SM2_D1[] = { psSource0_1_1, psSource_SM2_D1_L1, psSource_SM2_D1_L2, psSource_SM2_D1_L3, psSource_SM2_D1_L4, psSource_SM2_D1_L5, psSource_SM2_D1_L6 };
	char *psSources_SM2_D2[] = { psSource0_1_1, psSource_SM2_D2_L1, psSource_SM2_D2_L2, psSource_SM2_D2_L3, psSource_SM2_D2_L4, psSource_SM2_D2_L5, psSource_SM2_D2_L6 };

	// Compile vertex shader
	m_vertexShaders[0] = RuD3DCompileVertexShader(vsSource_Simple, "main", "vs_2_0", NULL);
	m_vertexShaders[1] = RuD3DCompileVertexShader(vsSource, "main", "vs_2_0", NULL);

	// Assemble pixel shaders (1.1)
	for(INT32 i = 0; i < 5; ++i)
	{
		m_pixelShaders_1_1[i] = RuD3DAssemblePixelShader(psSources_1_1[i]);

		if(m_pixelShaders_1_1[i] == NULL)
		{
			// Massive error, no pixel-shading capabilities
			m_maxLayersPerPass = 0;
		}
	}

	// Assemble pixel shaders (2.0)
	for(INT32 i = 0; i < 7; ++i)
	{
		m_pixelShaders_SM2_D1[i] = RuD3DAssemblePixelShader(psSources_SM2_D1[i]);

		if(m_pixelShaders_SM2_D1[i] == NULL)
		{
			m_maxLayersPerPass = 3;
		}
	}

	// Assemble pixel shaders (2.0)
	for(INT32 i = 0; i < 7; ++i)
	{
		m_pixelShaders_SM2_D2[i] = RuD3DAssemblePixelShader(psSources_SM2_D2[i]);

		if(m_pixelShaders_SM2_D2[i] == NULL)
		{
			m_maxLayersPerPass = 3;
		}
	}
}

CRuShader_SM10_Terrain_Packed::~CRuShader_SM10_Terrain_Packed()
{
	for(INT32 i = 0; i < 2; ++i)
	{
		if(m_vertexShaders[i])
		{
			m_vertexShaders[i]->Release();
		}
	}

	for(INT32 i = 0; i < 5; ++i)
	{
		ruSAFE_RELEASE(m_pixelShaders_1_1[i]);
	}

	for(INT32 i = 0; i < 7; ++i)
	{
		ruSAFE_RELEASE(m_pixelShaders_SM2_D1[i]);
	}

	for(INT32 i = 0; i < 7; ++i)
	{
		ruSAFE_RELEASE(m_pixelShaders_SM2_D2[i]);
	}
}

void CRuShader_SM10_Terrain_Packed::BeginPass(INT32 passNumber)
{
//	BOOL isFogPass = ((passNumber == m_numPasses - 1) && (m_maxLayersPerPass == 3)) ? TRUE : FALSE;
	BOOL isFogPass = FALSE;

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

	// Common
	INT32 uvStretchModifierConstantsOffset = 28 * 4;
	m_shaderConstants[uvStretchModifierConstantsOffset++] = 24.0f;
	m_shaderConstants[uvStretchModifierConstantsOffset++] = -24.0f;
	m_shaderConstants[uvStretchModifierConstantsOffset++] = 4.0f;
	m_shaderConstants[uvStretchModifierConstantsOffset++] = 4.0f;

	m_vertexDecl->Select();

	if(m_numTextureLayers == 0)
	{
		m_engine->SetVertexShader(m_vertexShaders[0]);
	}
	else
	{
		m_engine->SetVertexShader(m_vertexShaders[1]);
	}

	INT32 numTexturesRemaining = m_numTextureLayers - (passNumber * m_maxLayersPerPass);

	if(m_maxLayersPerPass == 6)
	{
		RuPropertyType propertyValue;
		INT32 shaderLevel = g_ruEngineSettings->GetSetting("terrain:splat technique", propertyValue) ? boost::get<INT32>(propertyValue) : 2;

		// If the number of textures remaining is greater than the maximum number of layers per pass, then ...
		if(numTexturesRemaining >= m_maxLayersPerPass)
		{
			if(shaderLevel < 2)
			{
				m_engine->SetPixelShader(m_pixelShaders_SM2_D1[m_maxLayersPerPass]);
			}
			else
			{
				m_engine->SetPixelShader(m_pixelShaders_SM2_D2[m_maxLayersPerPass]);
			}
		}
		else
		{
			if(shaderLevel < 2)
			{
				m_engine->SetPixelShader(m_pixelShaders_SM2_D1[numTexturesRemaining]);
			}
			else
			{
				m_engine->SetPixelShader(m_pixelShaders_SM2_D2[numTexturesRemaining]);
			}
		}
	}
	else
	{
		// Fog pass - no samplers
		if(isFogPass)
		{
			m_engine->SetPixelShader(m_pixelShaders_1_1[4]);
		}
		else
		{
			// If the number of textures remaining is greater than the maximum number of layers per pass, then ...
			if(numTexturesRemaining >= m_maxLayersPerPass)
			{
				m_engine->SetPixelShader(m_pixelShaders_1_1[m_maxLayersPerPass]);
			}
			else
			{
				m_engine->SetPixelShader(m_pixelShaders_1_1[numTexturesRemaining]);
			}
		}
	}

	// Set shader constants
	m_engine->SetVertexShaderConstants(0, m_shaderConstants, m_numBaseConstants);
	m_engine->SetPixelShaderConstants(0, m_pixelShaderConstants, m_numBasePixelShaderConstants);

	for(INT32 i = 2; i <= 4; ++i)
	{
		m_engine->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
		m_engine->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
/*
		m_engine->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
*/
		m_engine->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
		m_engine->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

		m_engine->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 4);
	}

	for(INT32 i = 6; i <= 8; ++i)
	{
		m_engine->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
		m_engine->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
/*
		m_engine->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
*/
		m_engine->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
		m_engine->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		m_engine->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

		m_engine->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 4);
	}

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

	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(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
	m_engine->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);

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

	m_engine->SetSamplerState(5, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
	m_engine->SetSamplerState(5, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);

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

	if(passNumber == 0)
	{
		m_engine->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);

		m_engine->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

		m_engine->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
	}
	else
	{
		if(isFogPass)
		{
			m_engine->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
			m_engine->SetRenderState(D3DRS_ALPHAREF, 0xFF);
			m_engine->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS);

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

			m_engine->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
		}
		else
		{
			m_engine->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
			m_engine->SetRenderState(D3DRS_ALPHAREF, 0x00);
			m_engine->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);

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

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

//	m_engine->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
}

void CRuShader_SM10_Terrain_Packed::EndPass(INT32 passNumber)
{
	CRuShader_SM10_Terrain_Packed_Base::EndPass(passNumber);

//	m_engine->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
}

void CRuShader_SM10_Terrain_Packed::SetParameters(const CRuParameterCache *paramCache)
{
	DWORD param;

	CRuShader_SM10_Terrain_Packed_Base::SetParameters(paramCache);

	if(paramCache->GetParameter(ruPARAMTYPE_SPLAT_ALPHAUVMODIFIER, param))
	{
		if(param)
		{
			INT32 uvModifierConstantsOffset = 27 * 4;
			float *uvModifier = (float *) param;

			m_shaderConstants[uvModifierConstantsOffset++] = uvModifier[0];
			m_shaderConstants[uvModifierConstantsOffset++] = uvModifier[1];
			m_shaderConstants[uvModifierConstantsOffset++] = uvModifier[2];
			m_shaderConstants[uvModifierConstantsOffset++] = uvModifier[3];
		}
	}

	if(paramCache->GetParameter(ruPARAMTYPE_SPLAT_LAYERCOUNT, param))
	{
		// Set the number of texture layers to blend
		m_numTextureLayers = param;

		if(m_numTextureLayers == 0)
		{
			m_numPasses = 1;
		}
		else
		{
			// If the number of texture layers requested exceeds the maximum allowed, cap it
			if(m_numTextureLayers > m_maxTextureLayers)
			{
				m_numTextureLayers = m_maxTextureLayers;
			}

			// Calculate the number of passes
			m_numPasses = (m_numTextureLayers / m_maxLayersPerPass) + ((m_numTextureLayers % m_maxLayersPerPass) ? 1 : 0);

			// Pixel Shader 1.1 has one extra fog pass
			if(m_maxLayersPerPass == 3)
			{
				m_numPasses += 1;
			}
		}
	}
}

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

CRuShader_SM10_Terrain_Packed_Backdrop::CRuShader_SM10_Terrain_Packed_Backdrop(CRuEngineD3D *engine)
:	CRuShader_SM10_Terrain_Packed_Base(engine)
{
	m_override_Fog = FALSE;
	m_override_AlphaTest = TRUE;
	m_override_AlphaBlend = TRUE;

	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);		// Spherical harmonics coefficients			\n\
	float4				g_specularDirection		: register(c21);		// Object space specular position			\n\
	float4				g_specularColor			: register(c22);													\n\
	float4				g_selfIllumination		: register(c23);		// Self-illumination term					\n\
	float4				g_globalSettings		: register(c25);		// (?, Fog Start, Fog End, Tween Factor)	\n\
	float4				g_globalDiffuse			: register(c26);													\n\
	float4				g_alphaUVModifier		: register(c27);													\n\
	float4				g_uvStretchModifier		: register(c28);													\n\
	float4				g_spc_base_inc_x		: register(c29);		// (spacing, y base, y increment, undefined)\n\
																													\n\
	struct VS_INPUT																									\n\
	{																												\n\
		float4			x_z_yH_yL				: POSITION;															\n\
		float4			diffuse					: COLOR0;				// Packed as (0xAAXXYYZZ)					\n\
	};																												\n\
																													\n\
	struct VS_OUTPUT																								\n\
	{																												\n\
		float4			position				: POSITION;															\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 localPos = float4(1, 1, 1, 1);																		\n\
		float4 worldPos = float4(1, 1, 1, 1);																		\n\
		float4 viewPos = float4(1, 1, 1, 1);																		\n\
																													\n\
		// Unpack world position																					\n\
		localPos.x = v.x_z_yH_yL.x * g_spc_base_inc_x.x;															\n\
		localPos.z = v.x_z_yH_yL.y * g_spc_base_inc_x.x;															\n\
		localPos.y = (v.x_z_yH_yL.z * 255 + v.x_z_yH_yL.w) * g_spc_base_inc_x.z + g_spc_base_inc_x.y;				\n\
																													\n\
		// Transform position to projected space																	\n\
		worldPos.xyz = mul(localPos, (float4x3) g_worldTransform);													\n\
		viewPos.xyz = mul(worldPos, (float4x3) g_viewTransform);													\n\
		output.position = mul(viewPos, (float4x4) g_projectionTransform);											\n\
																													\n\
		return output;																								\n\
	}																												\n\
	";

	char *psSource = "\
																													\n\
	ps_1_1																											\n\
																													\n\
	; Fog																											\n\
	mov					r0,			c1								; Move fog color to output						\n\
	";


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

	m_pixelShader = RuD3DAssemblePixelShader(psSource);
}

CRuShader_SM10_Terrain_Packed_Backdrop::~CRuShader_SM10_Terrain_Packed_Backdrop()
{
}

void CRuShader_SM10_Terrain_Packed_Backdrop::BeginPass(INT32 passNumber)
{
	// Force 2-sided rendering
	m_2Sided = TRUE;

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

	m_vertexDecl->Select();
	m_engine->SetVertexShader(m_vertexShader);
	m_engine->SetPixelShader(m_pixelShader);

	// Set shader constants
	m_engine->SetVertexShaderConstants(0, m_shaderConstants, m_numBaseConstants);
	m_engine->SetPixelShaderConstants(0, m_pixelShaderConstants, m_numBasePixelShaderConstants);

	m_engine->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);

	m_engine->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

	m_engine->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
}

void CRuShader_SM10_Terrain_Packed_Backdrop::EndPass(INT32 passNumber)
{
	CRuShader_SM10_Terrain_Packed_Base::EndPass(passNumber);
}

void CRuShader_SM10_Terrain_Packed_Backdrop::SetParameters(const CRuParameterCache *paramCache)
{
	CRuShader_SM10_Terrain_Packed_Base::SetParameters(paramCache);
}

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

#pragma managed(pop)
