//*******************************************************************
//
// File: Asura_Direct3D_Botanicals_Game_Render_Shaders.cpp
//
// Created: 13 Mar 2006
//
// Description: 
//
//*******************************************************************

// system libraries
#include "Core/Asura.h"

#if defined( ASURA_USE_BOTANICALS)

// main header
#include "Botanical/Asura_Direct3D_Botanicals_Game_Render.h"

// other libraries
#include "Botanical/Asura_Direct3D_Botanicals_Game_Render_Manager.h"

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_SM11) && 1 == ASURA_DIRECT3D_BGR_SUPPORT_SM11

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_SM30)
	#error ASURA_DIRECT3D_BGR_SUPPORT_SM30 and ASURA_DIRECT3D_BGR_SUPPORT_SM11 cannot be used together
#endif

// internal dependencies
#include "Camera/Asura_Camera.h"

#include "Core/Asura_Maths.h"

#include "Rendering/Asura_Direct3d.h"
#include "Rendering/Asura_DIPCache.h"
#include "Rendering/Asura_Direct3D_Shaders.h"
#include "Rendering/Asura_Fog.h"
#include "Rendering/Asura_Render.h"

#if defined( ASURA_TOOLS)
#include "Botanicals/Tools_Botanicals_Statistics.h"
#include "Misc/Tools_Render_Options.h"
#endif

//*******************************************************************
// Constants
//*******************************************************************

#if defined( ASURA_BOTANICAL_INSTANCE_USER_DATA_TYPE)
	#error There is no need for ASURA_BOTANICAL_INSTANCE_USER_DATA_TYPE to be on in SM11 version
#endif


// DLH - Use this to turn off all the D3D calls to measure just calculation times
#define ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS

//ASURA_STATIC_ASSERT( ASURA_DIRECT3D_BGR_VS_CONSTANT_GLOBAL_SIZE <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE0);

static Direct3D_VertexElement g_xaVSD_Botanical_Geometry3D[] =
{
	{ 0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
	{ 0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,    0 },
	{ 0, 16, D3DDECLTYPE_FLOAT2,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_NORMALS)
	{ 0, 24, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
#endif
	D3DDECL_END()
};

static Direct3D_VertexElement g_xaVSD_Botanical_GeometryLeaf[] =
{
	{ 0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
	{ 0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,    0 },
	{ 0, 16, D3DDECLTYPE_FLOAT2,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
	{ 0, 24, D3DDECLTYPE_FLOAT2,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
	D3DDECL_END()
};

static Direct3D_VertexElement g_xaVSD_Botanical_GeometryImposter[] =
{
	{ 0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
	{ 0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,    0 },
	{ 0, 16, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
	{ 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,    1 },
	{ 0, 32, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,    2 },
	{ 0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,    3 },
	D3DDECL_END()
};

static const char* const g_szVS_Botanical_VSO_LightS_Code =
"#line 1 \" "__FILE__"\" \n"
"struct VertexShaderOutputTexCoords \n"
"{ \n"
"	float2 texCoordBase		: TEXCOORD0; \n"
"}; \n"

"struct VertexShaderOutput \n"
"{ \n"
"	float4 pos				: POSITION0; \n"
"	float4 color0			: COLOR0; \n"
"	float  fog				: FOG; \n"
"	VertexShaderOutputTexCoords texCoords; \n"
#if defined ASURA_TARGET_SM3
"	float depth				: TEXCOORD7; \n"
#endif
"}; \n"

"struct VertexShaderOutputTexCoordsT1 \n"
"{ \n"
"	float4 texCoord0		: TEXCOORD0; \n"
"}; \n"

"struct VertexShaderOutputTexCoordsT2 \n"
"{ \n"
"	float4 texCoord0		: TEXCOORD0; \n"
"	float4 texCoord1		: TEXCOORD1; \n"
"}; \n"

"struct VertexShaderImposterT1Output \n"
"{ \n"
"	float4 pos				: POSITION0; \n"
"	float4 color0			: COLOR0; \n"
"	float  fog				: FOG; \n"
"	VertexShaderOutputTexCoordsT1 texCoords; \n"
#if defined ASURA_TARGET_SM3
"	float depth				: TEXCOORD7; \n"
#endif
"}; \n"

"struct VertexShaderImposterT2Output \n"
"{ \n"
"	float4 pos				: POSITION0; \n"
"	float4 color0			: COLOR0; \n"
"	float4 color1			: COLOR1; \n"
"	float  fog				: FOG; \n"
"	VertexShaderOutputTexCoordsT2 texCoords; \n"
#if defined ASURA_TARGET_SM3
"	float depth				: TEXCOORD7; \n"
#endif
"}; \n"
;

static const char* const g_szVS_Botanical_VSO_LightD_Code =
"#line 1 \" "__FILE__"\" \n"

"struct VertexShaderOutputTexCoords \n"
"{ \n"
"	float2 texCoordBase		: TEXCOORD0; \n"
"	float2 texCoordLightXY	: TEXCOORD1; \n"
"	float2 texCoordLightZ		: TEXCOORD2; \n"
"}; \n"

"struct VertexShaderOutput \n"
"{ \n"
"	float4 pos				: POSITION0; \n"
"	float4 color0			: COLOR0; \n"
"	float  fog				: FOG; \n"
"	VertexShaderOutputTexCoords texCoords; \n"
#if defined ASURA_TARGET_SM3
"	float  depth			: TEXCOORD7; \n"
#endif
"}; \n"

"struct VertexShaderOutputTexCoordsT1 \n"
"{ \n"
"	float4 texCoord0		: TEXCOORD0; \n"
"	float2 texCoordLightXY	: TEXCOORD1; \n"
"	float2 texCoordLightZ		: TEXCOORD2; \n"
"}; \n"

"struct VertexShaderOutputTexCoordsT2 \n"
"{ \n"
"	float4 texCoord0		: TEXCOORD0; \n"
"	float4 texCoord1		: TEXCOORD1; \n"
"	float2 texCoordLightXY	: TEXCOORD2; \n"
"	float2 texCoordLightZ		: TEXCOORD3; \n"
"}; \n"

"struct VertexShaderImposterT1Output \n"
"{ \n"
"	float4 pos				: POSITION0; \n"
"	float4 color0			: COLOR0; \n"
"	float  fog				: FOG; \n"
"	VertexShaderOutputTexCoordsT1 texCoords; \n"
#if defined ASURA_TARGET_SM3
"	float depth				: TEXCOORD7; \n"
#endif
"}; \n"

"struct VertexShaderImposterT2Output \n"
"{ \n"
"	float4 pos				: POSITION0; \n"
"	float4 color0			: COLOR0; \n"
"	float4 color1			: COLOR1; \n"
"	float  fog				: FOG; \n"
"	VertexShaderOutputTexCoordsT2 texCoords; \n"
#if defined ASURA_TARGET_SM3
"	float depth				: TEXCOORD7; \n"
#endif
"}; \n"
;


static const char* const g_szVS_Botanical_Types_Code =
"struct VertexShaderGeometry3DInput \n"
"{ \n"
"	float4 pos				: POSITION0; \n"
"	float4 color			: COLOR0; \n"
"	float4 tex0				: TEXCOORD0; \n"
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_NORMALS)
"	float4 normal			: NORMAL0; \n"
#endif
"}; \n"

"struct VertexShaderLeafInput \n"
"{ \n"
"	float4 pos				: POSITION0; \n"
"	float4 color			: COLOR0; \n"
"	float4 tex0				: TEXCOORD0; \n"
"	float4 corner				: TEXCOORD1; \n"
"}; \n"

"struct VertexShaderImposterInput \n"
"{ \n"
"	float4 pos				: POSITION0; \n"
"	float4 color			: COLOR0; \n"
"	float4 up				: TEXCOORD0; \n"
"	float4 shr				: COLOR1; \n"
"	float4 shg				: COLOR2; \n"
"	float4 shb				: COLOR3; \n"
"}; \n"

"struct InstanceData \n"
"{ \n"
#if 1 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
"	float4 m_const0; \n"
#endif
#if 2 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
"	float4 m_const1; \n"
#endif
#if 3 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
"	float4 m_const2; \n"
#endif
#if 4 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
"	float4 m_const3; \n"
#endif
#if 5 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
"	float4 m_const4; \n"
#endif
#if 6 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
"	float4 m_const5; \n"
#endif
#if 7 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
"	float4 m_const6; \n"
#endif
#if 8 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
"	float4 m_const7; \n"
#endif
#if 9 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
"	float4 m_const8; \n"
#endif
#if 10 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
"	float4 m_const9; \n"
#endif
#if 11 <= ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE
	#error ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE is too big 
#endif
"}; \n"

"struct ImposterPositionData \n"
"{ \n"
"	float4 m_XY; \n"
"}; \n"

"struct ImposterUVData \n"
"{ \n"
"	float4 m_UV; \n"
"}; \n"

"float4x4 g_WorldViewProject				: register( vs, c0);		// World-view-project matrix (uses constants 0-3). \n"
"float4 g_CameraRightVector				: register( vs, c4); \n"
"float4 g_CameraUpVector					: register( vs, c5); \n"
"float4 g_CameraForwardVector			: register( vs, c6); \n"

"float4 g_FogLinearColour				: register( vs, c7); \n"
"float4 g_FogLinearPlane					: register( vs, c8); \n"

"float4 g_FogGraphPlane					: register( vs, c7); \n"
"float4 g_FogGraphScale[2]				: register( vs, c8); \n"
"float4 g_FogGraphCoeffs[2]				: register( vs, c10); \n"

"float4 g_DynamicLightX					: register( vs, c12); \n"
"float4 g_DynamicLightY					: register( vs, c13); \n"
"float4 g_DynamicLightZ					: register( vs, c14); \n"
"float4 g_DynamicLightW					: register( vs, c15); \n"
"float4 g_NormalScale						: register( vs, c16); \n"

"InstanceData g_xInstanceTable[ 100]	: register( vs, c20); \n"

"float4 g_xCameraPosition : register( vs, c20); \n"
"float4 g_xImposterAlphaFade : register( vs, c21); \n"
"float4 g_xImposterAlphaRotate : register( vs, c22); \n"
"ImposterPositionData	g_xImposterPositionTable[ 4]		: register( vs, c23); \n"
"ImposterUVData		g_xImposterUVTable0[ 4]		: register( vs, c27); \n"
"ImposterUVData		g_xImposterUVTable1[ 4]		: register( vs, c31); \n"
;

static const char* const g_szVS_Botanical_Functions_Code =
"float4 GetImposterSphericalR( VertexShaderImposterInput xImposterData) \n"
"{ \n"
"	float4 xCoeffs = (8.0f * xImposterData.shr) - 4.0f; \n"
"	return( xCoeffs); \n"
"} \n"

"float4 GetImposterSphericalG( VertexShaderImposterInput xImposterData) \n"
"{ \n"
"	float4 xCoeffs = (8.0f * xImposterData.shg) - 4.0f; \n"
"	return( xCoeffs); \n"
"} \n"

"float4 GetImposterSphericalB( VertexShaderImposterInput xImposterData) \n"
"{ \n"
"	float4 xCoeffs = (8.0f * xImposterData.shb) - 4.0f; \n"
"	return( xCoeffs); \n"
"} \n"

"float4 GetInstanceSphericalR( InstanceData xInstanceData) \n"
"{ \n"
"	float4 xCoeffs = xInstanceData.m_const4; \n"
"	return( xCoeffs); \n"
"} \n"

"float4 GetInstanceSphericalG( InstanceData xInstanceData) \n"
"{ \n"
"	float4 xCoeffs = xInstanceData.m_const5; \n"
"	return( xCoeffs); \n"
"} \n"

"float4 GetInstanceSphericalB( InstanceData xInstanceData) \n"
"{ \n"
"	float4 xCoeffs = xInstanceData.m_const6; \n"
"	return( xCoeffs); \n"
"} \n"

"float3 GetInstanceAmbient( InstanceData xInstanceData) \n"
"{ \n"
"	float3 fColourOut = xInstanceData.m_const3.xyz; \n"
"	return( fColourOut); \n"
"} \n"

"float GetInstanceAlphaCut( InstanceData xInstanceData) \n"
"{ \n"
"	return( xInstanceData.m_const3.w);\n"
"} \n"

"float GetInstanceScale( InstanceData xInstanceData) \n"
"{ \n"
"	return( length( xInstanceData.m_const0.xyz));\n"
"} \n"

"float4 VertexScaleRotateTransform(  InstanceData xInstanceData, float4 xVertex) \n"
"{ \n"
"	float4 xVertexOut = xVertex; \n"

"	xVertexOut.x = dot( xVertex.xyzw, xInstanceData.m_const0.xyzw); \n"
"	xVertexOut.y = dot( xVertex.xyzw, xInstanceData.m_const1.xyzw); \n"
"	xVertexOut.z = dot( xVertex.xyzw, xInstanceData.m_const2.xyzw); \n"

"	return( xVertexOut);\n"
"} \n"

"float4 NormalRotate(  InstanceData xInstanceData, float4 xNormal) \n"
"{ \n"
"	float4 xNormalOut = xNormal; \n"

"	xNormalOut.x = dot( xNormal.xyz, xInstanceData.m_const0.xyz); \n"
"	xNormalOut.y = dot( xNormal.xyz, xInstanceData.m_const1.xyz); \n"
"	xNormalOut.z = dot( xNormal.xyz, xInstanceData.m_const2.xyz); \n"

"	xNormalOut.xyz = normalize( xNormalOut.xyz); \n"

"	return( xNormalOut);\n"
"} \n"

"VertexShaderOutput mainGeometry3D(VertexShaderGeometry3DInput i) \n"
"{ \n"
"	VertexShaderOutput o; \n"
// DLH - 24 March 2006 15:13:59 - The 0.9 on the end of the 255 stops the float to int rounding to the next int value down 
//"	float fInstanceIndex = (255.9f) * i.color.a; \n"
// KOR - 05/02/2008 - this seemed to be causing problems, at least on my graphics card. Removed the offset to fix the bug;
// if it breaks on other systems, we will need to investigate a universal solution
"	float fInstanceIndex = (255.f) * i.color.a; \n"
// Okay, that broke on GeForce 7 models. After discussion with Andy McDonald, we reckon it's probably some sort of
// floating point conversion from u_int colour difference between GeForce 7 and 8 models. Hence this third attempt at a fix:
// added a half to get a float-to-int near rather than chop.
// When changing this, remember to fix up mainLeaf, mainImposterT1, and mainImposterT2 as well.
"	int iInstanceIndex = (int)(fInstanceIndex + 0.5f); \n"
"	InstanceData xInstanceData = g_xInstanceTable[ iInstanceIndex]; \n"

// DLH - 27 March 2006 15:47:21 - Get Vertex and Transform
"	float4 xPosition = i.pos; \n"
//"	float4 xNormal = i.pos; \n"
"	xPosition.xyzw = VertexScaleRotateTransform( xInstanceData, xPosition); \n"

"	o.pos = mul( xPosition, g_WorldViewProject); \n"
#if defined ASURA_TARGET_SM3
"	o.depth = o.pos.w; \n"
#endif

"	float fAlphaCut = GetInstanceAlphaCut( xInstanceData); \n"

//"	o.color0.rgb = i.color; \n"
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_NORMALS)
"	float4 xVerterxNormal = g_NormalScale * i.normal; \n"
"	xVerterxNormal.xyzw = NormalRotate( xInstanceData, xVerterxNormal); \n"
"	o.color0.rgb = GetInstanceLightingColor( xInstanceData, i.color, xPosition, xVerterxNormal); \n"
#else
"	o.color0.rgb = GetInstanceLightingColor( xInstanceData, i.color, xPosition, float4( 1.0f,0.0f,0.0f,1.0f)); \n"
#endif
"	o.color0.a = fAlphaCut; \n"

//"	o.color1.rgb = 0.0f; \n"
"	o.fog = SetFog( xPosition); \n"

"	o.texCoords = GetDynamicLights( i.tex0, xPosition); \n"

"	return o; \n"
"} \n"

"VertexShaderOutput mainLeaf(VertexShaderLeafInput i) \n"
"{ \n"
"	VertexShaderOutput o; \n"
"	float fInstanceIndex = (255.f) * i.color.a; \n"
"	int iInstanceIndex = (int)(fInstanceIndex + 0.5f); \n"
"	InstanceData xInstanceData = g_xInstanceTable[ iInstanceIndex]; \n"

// DLH - 27 March 2006 15:47:21 - Get Vertex and Transform
"	float4 xPosition = i.pos; \n"
"	xPosition.xyzw = VertexScaleRotateTransform( xInstanceData, xPosition); \n"

"	float fInstanceScale = GetInstanceScale( xInstanceData); \n"
"	float2 xCorner = fInstanceScale * i.corner.xy; \n"
"	xPosition.xyz += g_CameraRightVector * xCorner.x; \n"
"	xPosition.xyz += g_CameraUpVector * xCorner.y; \n"

"	o.pos = mul( xPosition, g_WorldViewProject); \n"
#if defined ASURA_TARGET_SM3
"	o.depth = o.pos.w; \n"
#endif

"	float fAlphaCut = GetInstanceAlphaCut( xInstanceData); \n"

"	o.color0.rgb = GetInstanceLightingColor( xInstanceData, i.color, xPosition, g_CameraForwardVector); \n"
"	o.color0.a = fAlphaCut; \n"

"	o.fog = SetFog( xPosition); \n"

"	o.texCoords = GetDynamicLights( i.tex0, xPosition); \n"

"	return o; \n"
"} \n"

"VertexShaderImposterT1Output mainImposterT1(VertexShaderImposterInput i) \n"
"{ \n"
"	VertexShaderImposterT1Output o; \n"

"	float fImposterIndex = (255.f) * i.color.a; \n"
"	int iImposterIndex = (int)(fImposterIndex + 0.5f); \n"
"	ImposterPositionData xImposterPositionData = g_xImposterPositionTable[ iImposterIndex]; \n"

// DLH - 27 March 2006 15:47:21 - Get Vertex and Transform
"	float4 xPosition = i.pos; \n"
"	float4 xDirectionToCamera; \n"
"	xDirectionToCamera.xyz = g_xCameraPosition.xyz - xPosition.xyz;\n"
"	xDirectionToCamera.w = 1.0f; \n"

"	float fDistanceToCamera = length( xDirectionToCamera.xyz); \n"
"	xDirectionToCamera.xyz = normalize( xDirectionToCamera.xyz); \n"

"	float fFadeDistance = (fDistanceToCamera * g_xImposterAlphaFade.x) + g_xImposterAlphaFade.y + g_xImposterAlphaFade.z; \n"
"	float fFadeAngle1 = g_xImposterAlphaFade.z; \n"
"	o.color0.a = max( 0.5f, fFadeDistance) + fFadeAngle1; \n"

"	o.color0.rgb = GetInstanceLightingColor( i, i.color, xPosition, xDirectionToCamera); \n"

// DLH - 11 April 2006 14:54:14 - This shrinks the size of the billboard to zero area is it is faded out
"	float fScale = fFadeDistance <= 1.0f; \n"
"	fScale *= 4.0f * i.color.r; \n"
"	xPosition.xyz += fScale * g_CameraRightVector * xImposterPositionData.m_XY.xxx; \n"
"	xPosition.xyz += fScale * i.up.xyz * xImposterPositionData.m_XY.yyy; \n"
"	o.pos = mul( xPosition, g_WorldViewProject); \n"
#if defined ASURA_TARGET_SM3
"	o.depth = o.pos.w; \n"
#endif

"	o.fog = SetFog( xPosition); \n"

"	o.texCoords = GetTexCoordsT1( iImposterIndex, xPosition); \n"

"	return o; \n"
"} \n"

"VertexShaderImposterT2Output mainImposterT2(VertexShaderImposterInput i) \n"
"{ \n"
"	VertexShaderImposterT2Output o; \n"

"	float fImposterIndex = (255.f) * i.color.a; \n"
"	int iImposterIndex = (int)(fImposterIndex + 0.5f); \n"
"	ImposterPositionData xImposterPositionData = g_xImposterPositionTable[ iImposterIndex]; \n"

// DLH - 27 March 2006 15:47:21 - Get Vertex and Transform
"	float4 xPosition = i.pos; \n"
"	float4 xDirectionToCamera; \n"
"	xDirectionToCamera.xyz = g_xCameraPosition.xyz - xPosition.xyz;\n"
"	xDirectionToCamera.w = 1.0f; \n"

"	float fDistanceToCamera = length( xDirectionToCamera.xyz); \n"
"	xDirectionToCamera.xyz = normalize( xDirectionToCamera.xyz); \n"

"	float fFadeDistance = (fDistanceToCamera * g_xImposterAlphaFade.x) + g_xImposterAlphaFade.y; \n"
"	float fFadeDistanceClamped = max( 0.5f, fFadeDistance); \n"
"	float fFadeAngle1 = g_xImposterAlphaFade.z; \n"
"	float fFadeAngle2 = g_xImposterAlphaFade.w; \n"
"	o.color0.a = fFadeDistanceClamped + fFadeAngle1; \n"
"	o.color1.a = fFadeDistanceClamped + fFadeAngle2; \n"
"	o.color1.rgb = g_xImposterAlphaRotate.x; \n"

"	o.color0.rgb = GetInstanceLightingColor( i, i.color, xPosition, xDirectionToCamera); \n"

// DLH - 11 April 2006 14:54:14 - This shrinks the size of the billboard to zero area is it is faded out
"	float fScale = fFadeDistance <= 1.0f; \n"
"	fScale *= 4.0f * i.color.r; \n"
"	xPosition.xyz += fScale * g_CameraRightVector * xImposterPositionData.m_XY.xxx; \n"
"	xPosition.xyz += fScale * i.up.xyz * xImposterPositionData.m_XY.yyy; \n"
"	o.pos = mul( xPosition, g_WorldViewProject); \n"
#if defined ASURA_TARGET_SM3
"	o.depth = o.pos.w; \n"
#endif

"	o.fog = SetFog( xPosition); \n"

"	o.texCoords = GetTexCoordsT2( iImposterIndex, xPosition); \n"

"	return o; \n"
"} \n"
;

static const char* const g_szVS_Botanical_FogL_Code =
"float SetFog( in float4 xPosition) \n"
"{ \n"
"	float fFog = dot( xPosition.xyzw, g_FogLinearPlane.xyzw); \n"
"	fFog = min( 1.0f, fFog); \n"
"	fFog = (fFog * g_FogLinearColour.x) + g_FogLinearColour.y; \n"
"	return( fFog); \n"
"} \n"
;

static const char* const g_szVS_Botanical_FogG_Code =
"float SetFog( in float4 xPosition) \n"
"{ \n"
	// Fog: Get range fog near and far planes (Scaled by the number of splines)
"	float fDistanceFog = dot( xPosition.xyzw, g_FogGraphPlane.xyzw); \n"
	// Fog: Clamp to 0 - (Max of Spline Index)
"	fDistanceFog = min( g_FogGraphScale[0].w, fDistanceFog); \n"
"	fDistanceFog = max( g_FogGraphScale[0].z, fDistanceFog); \n"
	// Fog: Setup Fog Table offset (Use >= for this as it maps directly to the ASM instruction)
"	int iIndex = (fDistanceFog >= g_FogGraphScale[1].z) ? 1 : 0; \n"
	// Fog: Scale Index into Coeff useful values
"	float4 xScale = g_FogGraphScale[ iIndex]; \n"
"	fDistanceFog = (fDistanceFog * xScale.x) + xScale.y; \n"
	// Fog: Build (r1.z^3, r1.z^2, r1.z, 1) for easy calc
"	float4 xCoeffX; \n"
"	xCoeffX.w = 1; \n"
"	xCoeffX.z = fDistanceFog; \n"
"	xCoeffX.y = fDistanceFog * fDistanceFog; \n"
"	xCoeffX.x = fDistanceFog * xCoeffX.y; \n"
	// Fog: Calc fog via lookup coeffs
"	float fFog = dot( xCoeffX, g_FogGraphCoeffs[ iIndex]); \n"

"	return( fFog); \n"
"} \n"
;

static const char* const g_szVS_Botanical_LightS_Code =
"float4 GetInstanceSphericalR( InstanceData xInstanceData); \n"
"float4 GetInstanceSphericalG( InstanceData xInstanceData); \n"
"float4 GetInstanceSphericalB( InstanceData xInstanceData); \n"

"float4 GetImposterSphericalR( VertexShaderImposterInput xImposterData); \n"
"float4 GetImposterSphericalG( VertexShaderImposterInput xImposterData); \n"
"float4 GetImposterSphericalB( VertexShaderImposterInput xImposterData); \n"

"float3 GetInstanceLightingColor( InstanceData xInstanceData, float4 xVertexColour, float4 xVertexPosition, float4 xVertexNormal) \n"
"{ \n"
"	float3 xColourSpherical; \n"

"	xColourSpherical.r = dot( xVertexNormal.xyzw, GetInstanceSphericalR( xInstanceData)); \n"
"	xColourSpherical.g = dot( xVertexNormal.xyzw, GetInstanceSphericalG( xInstanceData)); \n"
"	xColourSpherical.b = dot( xVertexNormal.xyzw, GetInstanceSphericalB( xInstanceData)); \n"

"	float3 xColourOut = xColourSpherical.rgb; \n"

"	return( xColourOut); \n"
"} \n"

"float3 GetInstanceLightingColor( VertexShaderImposterInput xImposterData, float4 xVertexColour, float4 xVertexPosition, float4 xVertexNormal) \n"
"{ \n"
"	float3 xColourSpherical; \n"

"	xColourSpherical.r = dot( xVertexNormal.xyzw, GetImposterSphericalR( xImposterData)); \n"
"	xColourSpherical.g = dot( xVertexNormal.xyzw, GetImposterSphericalG( xImposterData)); \n"
"	xColourSpherical.b = dot( xVertexNormal.xyzw, GetImposterSphericalB( xImposterData)); \n"

"	float3 xColourOut = xColourSpherical.rgb; \n"

"	return( xColourOut); \n"
"} \n"

"VertexShaderOutputTexCoordsT1 GetTexCoordsT1( int iImposterIndex, in float4 xWorldPosition)\n"
"{ \n"
"	VertexShaderOutputTexCoordsT1 o; \n"

"	ImposterUVData xImposterUVData0 = g_xImposterUVTable0[ iImposterIndex]; \n"
"	o.texCoord0 = xImposterUVData0.m_UV; \n"

"	return( o); \n"
"} \n"

"VertexShaderOutputTexCoordsT2 GetTexCoordsT2( int iImposterIndex, in float4 xWorldPosition)\n"
"{ \n"
"	VertexShaderOutputTexCoordsT2 o; \n"

"	ImposterUVData xImposterUVData0 = g_xImposterUVTable0[ iImposterIndex]; \n"
"	o.texCoord0 = xImposterUVData0.m_UV; \n"

"	ImposterUVData xImposterUVData1 = g_xImposterUVTable1[ iImposterIndex]; \n"
"	o.texCoord1 = xImposterUVData1.m_UV; \n"

"	return( o); \n"
"} \n"

"VertexShaderOutputTexCoords GetDynamicLights( float4 xTexCoord0, float4 xWorldPosition)\n"
"{ \n"
"	VertexShaderOutputTexCoords o; \n"
"	o.texCoordBase = xTexCoord0; \n"
"	return( o); \n"
"} \n"
;

static const char* const g_szVS_Botanical_LightD_Code =

"float3 GetInstanceLightingColor( InstanceData xInstanceData, float4 xVertexColour, float4 xVertexPosition, float4 xVertexNormal) \n"
"{ \n"
"	float3 xVertexPhotonPosition; \n"

"	xVertexPhotonPosition.x = dot( g_DynamicLightX, xVertexPosition); \n"
"	xVertexPhotonPosition.y = dot( g_DynamicLightY, xVertexPosition); \n"
"	xVertexPhotonPosition.z = dot( g_DynamicLightZ, xVertexPosition); \n"

"	xVertexPhotonPosition = (-1.0f * xVertexPhotonPosition) + 0.5f; \n"

"	float3 xVertexPhotonDirection = normalize( xVertexPhotonPosition); \n"
"	float fDotNL = dot( xVertexPhotonDirection, xVertexNormal); \n"
"	float3 xColourOut = max( fDotNL, 0); \n"

"	return( xColourOut); \n"
"} \n"

"float3 GetInstanceLightingColor( VertexShaderImposterInput xImposterData, float4 xVertexColour, float4 xVertexPosition, float4 xVertexNormal) \n"
"{ \n"
"	float3 xColourOut = 1.0f; \n"

"	return( xColourOut); \n"
"} \n"

"float2 GetDynamicLightsXY( in float4 xWorldPosition)\n"
"{ \n"
"	float2 o; \n"
"	o.x = dot( g_DynamicLightX, xWorldPosition); \n"
"	o.y = dot( g_DynamicLightY, xWorldPosition); \n"
"	return( o); \n"
"} \n"

"float2 GetDynamicLightsZ( in float4 xWorldPosition)\n"
"{ \n"
"	float2 o; \n"
"	o.x = dot( g_DynamicLightZ, xWorldPosition); \n"
"	o.y = 0.5f; \n"
"	return( o); \n"
"} \n"

"VertexShaderOutputTexCoordsT1 GetTexCoordsT1( int iImposterIndex, in float4 xWorldPosition)\n"
"{ \n"
"	VertexShaderOutputTexCoordsT1 o; \n"

"	ImposterUVData xImposterUVData0 = g_xImposterUVTable0[ iImposterIndex]; \n"
"	o.texCoord0 = xImposterUVData0.m_UV; \n"

"	o.texCoordLightXY = GetDynamicLightsXY( xWorldPosition); \n"
"	o.texCoordLightZ = GetDynamicLightsZ( xWorldPosition); \n"

"	return( o); \n"
"} \n"

"VertexShaderOutputTexCoordsT2 GetTexCoordsT2( int iImposterIndex, in float4 xWorldPosition)\n"
"{ \n"
"	VertexShaderOutputTexCoordsT2 o; \n"

"	ImposterUVData xImposterUVData0 = g_xImposterUVTable0[ iImposterIndex]; \n"
"	o.texCoord0 = xImposterUVData0.m_UV; \n"

"	ImposterUVData xImposterUVData1 = g_xImposterUVTable1[ iImposterIndex]; \n"
"	o.texCoord1 = xImposterUVData1.m_UV; \n"

"	o.texCoordLightXY = GetDynamicLightsXY( xWorldPosition); \n"
"	o.texCoordLightZ = GetDynamicLightsZ( xWorldPosition); \n"

"	return( o); \n"
"} \n"

"VertexShaderOutputTexCoords GetDynamicLights( float4 xTexCoord0, in float4 xWorldPosition)\n"
"{ \n"
"	VertexShaderOutputTexCoords o; \n"
"	o.texCoordBase = xTexCoord0; \n"

"	o.texCoordLightXY = GetDynamicLightsXY( xWorldPosition); \n"
"	o.texCoordLightZ = GetDynamicLightsZ( xWorldPosition); \n"

"	return( o); \n"
"} \n"
;



static char* xVS_Botanical_GetCode_FogL_LightS()
{
	static Asura_String xString;
	
	if( 0 == xString.GetLength())
	{
		xString += g_szVS_Botanical_VSO_LightS_Code;
		xString += g_szVS_Botanical_Types_Code;
		xString += g_szVS_Botanical_LightS_Code;
		xString += g_szVS_Botanical_FogL_Code;
		xString += g_szVS_Botanical_Functions_Code;
	}
	
	return( xString.GetString());
}

static char* xVS_Botanical_GetCode_FogG_LightS()
{
	static Asura_String xString;
	if( 0 == xString.GetLength())
	{
		xString += g_szVS_Botanical_VSO_LightS_Code;
		xString += g_szVS_Botanical_Types_Code;
		xString += g_szVS_Botanical_LightS_Code;
		xString += g_szVS_Botanical_FogG_Code;
		xString += g_szVS_Botanical_Functions_Code;
	}
	
	return( xString.GetString());
}

static char* xVS_Botanical_GetCode_FogL_LightD()
{
	static Asura_String xString;
	
	if( 0 == xString.GetLength())
	{
		xString += g_szVS_Botanical_VSO_LightD_Code;
		xString += g_szVS_Botanical_Types_Code;
		xString += g_szVS_Botanical_LightD_Code;
		xString += g_szVS_Botanical_FogL_Code;
		xString += g_szVS_Botanical_Functions_Code;
	}
	
	return( xString.GetString());
}

static char* xVS_Botanical_GetCode_FogG_LightD()
{
	static Asura_String xString;
	if( 0 == xString.GetLength())
	{
		xString += g_szVS_Botanical_VSO_LightD_Code;
		xString += g_szVS_Botanical_Types_Code;
		xString += g_szVS_Botanical_LightD_Code;
		xString += g_szVS_Botanical_FogG_Code;
		xString += g_szVS_Botanical_Functions_Code;
	}
	
	return( xString.GetString());
}

#if defined ASURA_TARGET_SM3
	const float fVERTEX_SHADER_VERSION = 3.0f;
#else
	const float fVERTEX_SHADER_VERSION = 1.1f;
#endif

const Asura_Direct3D_VertexShader xVS_Botanical_Goemetry3D_Shader_FogL_LightS(	ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGL_LIGHTS,	xVS_Botanical_GetCode_FogL_LightS(), &g_xaVSD_Botanical_Geometry3D[0],			fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainGeometry3D");
const Asura_Direct3D_VertexShader xVS_Botanical_Leaf_Shader_FogL_LightS(		ASURA_D3D_VS_BOTANICAL_LEAF_FOGL_LIGHTS,		xVS_Botanical_GetCode_FogL_LightS(), &g_xaVSD_Botanical_GeometryLeaf[0],		fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainLeaf");
const Asura_Direct3D_VertexShader xVS_Botanical_ImposterT1_Shader_FogL_LightS(	ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGL_LIGHTS,	xVS_Botanical_GetCode_FogL_LightS(), &g_xaVSD_Botanical_GeometryImposter[0],	fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainImposterT1");
const Asura_Direct3D_VertexShader xVS_Botanical_ImposterT2_Shader_FogL_LightS(	ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGL_LIGHTS,	xVS_Botanical_GetCode_FogL_LightS(), &g_xaVSD_Botanical_GeometryImposter[0],	fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainImposterT2");

const Asura_Direct3D_VertexShader xVS_Botanical_Goemetry3D_Shader_FogL_LightD(	ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGL_LIGHTD,	xVS_Botanical_GetCode_FogL_LightD(), &g_xaVSD_Botanical_Geometry3D[0],			fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainGeometry3D");
const Asura_Direct3D_VertexShader xVS_Botanical_Leaf_Shader_FogL_LightD(		ASURA_D3D_VS_BOTANICAL_LEAF_FOGL_LIGHTD,		xVS_Botanical_GetCode_FogL_LightD(), &g_xaVSD_Botanical_GeometryLeaf[0],		fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainLeaf");
const Asura_Direct3D_VertexShader xVS_Botanical_ImposterT1_Shader_FogL_LightD(	ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGL_LIGHTD,	xVS_Botanical_GetCode_FogL_LightD(), &g_xaVSD_Botanical_GeometryImposter[0],	fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainImposterT1");
const Asura_Direct3D_VertexShader xVS_Botanical_ImposterT2_Shader_FogL_LightD(	ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGL_LIGHTD,	xVS_Botanical_GetCode_FogL_LightD(), &g_xaVSD_Botanical_GeometryImposter[0],	fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainImposterT2");

const Asura_Direct3D_VertexShader xVS_Botanical_Goemetry3D_Shader_FogG_LightS(	ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGG_LIGHTS,	xVS_Botanical_GetCode_FogG_LightS(), &g_xaVSD_Botanical_Geometry3D[0],			fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainGeometry3D");
const Asura_Direct3D_VertexShader xVS_Botanical_Leaf_Shader_FogG_LightS(		ASURA_D3D_VS_BOTANICAL_LEAF_FOGG_LIGHTS,		xVS_Botanical_GetCode_FogG_LightS(), &g_xaVSD_Botanical_GeometryLeaf[0],		fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainLeaf");
const Asura_Direct3D_VertexShader xVS_Botanical_ImposterT1_Shader_FogG_LightS(	ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGG_LIGHTS,	xVS_Botanical_GetCode_FogG_LightS(), &g_xaVSD_Botanical_GeometryImposter[0],	fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainImposterT1");
const Asura_Direct3D_VertexShader xVS_Botanical_ImposterT2_Shader_FogG_LightS(	ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGG_LIGHTS,	xVS_Botanical_GetCode_FogG_LightS(), &g_xaVSD_Botanical_GeometryImposter[0],	fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainImposterT2");

const Asura_Direct3D_VertexShader xVS_Botanical_Goemetry3D_Shader_FogG_LightD(	ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGG_LIGHTD,	xVS_Botanical_GetCode_FogG_LightD(), &g_xaVSD_Botanical_Geometry3D[0],			fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainGeometry3D");
const Asura_Direct3D_VertexShader xVS_Botanical_Leaf_Shader_FogG_LightD(		ASURA_D3D_VS_BOTANICAL_LEAF_FOGG_LIGHTD,		xVS_Botanical_GetCode_FogG_LightD(), &g_xaVSD_Botanical_GeometryLeaf[0],		fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainLeaf");
const Asura_Direct3D_VertexShader xVS_Botanical_ImposterT1_Shader_FogG_LightD(	ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGG_LIGHTD,	xVS_Botanical_GetCode_FogG_LightD(), &g_xaVSD_Botanical_GeometryImposter[0],	fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainImposterT1");
const Asura_Direct3D_VertexShader xVS_Botanical_ImposterT2_Shader_FogG_LightD(	ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGG_LIGHTD,	xVS_Botanical_GetCode_FogG_LightD(), &g_xaVSD_Botanical_GeometryImposter[0],	fVERTEX_SHADER_VERSION, ASURA_D3D_VS_CODE_TYPE_HLSL, "mainImposterT2");


static const char* const g_szPS_Botanical_Geometry3D_Code =

#if defined ASURA_TARGET_SM3

	"ps_3_0								\n"
	"dcl_color v0						\n"
	"dcl_texcoord0 v1.xy				\n"
	"dcl_texcoord7 v2.x					\n"
	"dcl_2d s0							\n"

	"def c0, 2.0, 0.0, 0.0, 1.0			\n"

	"mul r0.rgb, v0.rgb, c0.x			\n"
	"texld r1, v1, s0					\n"
	"mul_sat oC0.rgb, r1.rgb, r0.rgb	\n"
	"sub_sat oC0.a, r1.a, v0.a			\n"
	"mov oC1.rgb, c0.yzw				\n"
	"mov oC1.a, v2.x					\n"

#else // !defined ASURA_TARGET_SM3

	"ps.1.1				\n"
	"tex t0				\n"	// base texture

	"mul_x2_sat r0.rgb, t0, v0 \n"
	"sub_sat r0.a, t0.a, v0.a \n"

#endif // !defined ASURA_TARGET_SM3
;

// Register the shader with Asura
const Asura_Direct3D_PixelShader xPS_Botanical_Goemetry3D_Shader( ASURA_D3D_PS_BOTANICAL_GEOMETRY3D, g_szPS_Botanical_Geometry3D_Code);

static const char* const g_szPS_Botanical_Geometry3D_LightD_Code =

#if defined ASURA_TARGET_SM3

	"ps_3_0							\n"
	"dcl_color v0					\n"
	"dcl_texcoord0 v1.xy			\n"
	"dcl_texcoord1 v2.xy			\n"
	"dcl_texcoord2 v3.xy			\n"
	"dcl_texcoord7 v4.x				\n"
	"dcl_2d s0						\n"
	"dcl_2d s1						\n"
	"dcl_2d s2						\n"

	"def c1, 8.0, 2.0, 0.0, 1.0		\n"

	"texld r0, v1, s0				\n"
	"texld r1, v2, s1				\n"
	"texld r2, v3, s2				\n"

	"mul r1.rgb, r1.rgb, r2.rgb		\n"
	"mul r0.rgb, r1.rgb, r0.rgb		\n"
	"mul r0.rgb, r0.rgb, v0.rgb		\n"
	"mul r0.rgb, c0.rgb, r0.rgb		\n"
	"mul_sat oC0.rgb, r0.rgb, c1.x	\n"
	"sub_sat oC0.a, r0.a, v0.a		\n"
	"mov oC1.rgb, c1.zzw			\n"
	"mov oC1.a, v4.x				\n"

#else // !defined ASURA_TARGET_SM3

	"ps.1.1				\n"
	"tex t0				\n"	// base texture
	"tex t1				\n"	// base texture
	"tex t2				\n"	// base texture

	"mul r0.rgb, t1, t2\n"
	"mul r0.rgb, r0, t0 \n"
	"mul r0.rgb, r0, v0\n"
	"mul_x4 r0.rgb, c0, r0\n"
	"mov_x2_sat r0.rgb, r0 \n"
	"sub_sat r0.a, t0.a, v0.a \n"

#endif // !defined ASURA_TARGET_SM3
;

// Register the shader with Asura
const Asura_Direct3D_PixelShader xPS_Botanical_Goemetry3D_LightD_Shader( ASURA_D3D_PS_BOTANICAL_GEOMETRY3D_LIGHTD, g_szPS_Botanical_Geometry3D_LightD_Code);

static const char* const g_szPS_Botanical_ImposterT1_LightS_Code =

#if defined ASURA_TARGET_SM3

	"ps_3_0								\n"
	"dcl_color v0						\n"
	"dcl_texcoord0 v1.xy				\n"
	"dcl_texcoord7 v2.x					\n"
	"dcl_2d s0							\n"

	"def c0, 2.0, 0.0, 0.0, 1.0			\n"

	"mul r0.rgb, v0.rgb, c0.x			\n"
	"texld r1, v1, s0					\n"
	"mul_sat oC0.rgb, r1.rgb, r0.rgb	\n"
	"sub_sat oC0.a, r1.a, v0.a			\n"
	"mov oC1.rgb, c0.yzw				\n"
	"mov oC1.a, v2.x					\n"

#else // !defined ASURA_TARGET_SM3

	"ps.1.1				\n"
	"tex t0				\n"	// base texture

	"mul_x2_sat r0.rgb, t0, v0 \n"
	"sub_sat r0.a, t0.a, v0.a \n"

#endif // !defined ASURA_TARGET_SM3
;

static const char* const g_szPS_Botanical_ImposterT2_LightS_Code =

#if defined ASURA_TARGET_SM3

	"ps_3_0									\n"
	"dcl_color0 v0							\n"
	"dcl_color1 v1							\n"
	"dcl_texcoord0 v2.xy					\n"
	"dcl_texcoord1 v3.xy					\n"
	"dcl_texcoord7 v4.x						\n"
	"dcl_2d s0								\n"
	"dcl_2d s1								\n"

	"def c0, 2.0, 0.0, 0.0, 1.0				\n"

	"mul r0.rgb, v0.rgb, c0.x				\n"
	"mul r1.rgb, v1.rgb, c0.x				\n"

	"texld r2, v2, s0						\n"
	"texld r3, v3, s1						\n"

	"mul_sat r2.rgb, r2.rgb, r0.rgb			\n"
	"sub_sat r2.a, r2.a, v0.a				\n"
	"mul_sat r3.rgb, r3.rgb, r0.rgb			\n"
	"sub_sat r3.a, r3.a, v1.a				\n"
	"lrp oC0.rgb, v1.rgb, r2.rgb, r3.rgb	\n"
	"lrp oC0.a, v1.b, r2.a, r3.a			\n"
	"mov oC1.rgb, c0.yzw					\n"
	"mov oC1.a, v4.x						\n"

#else // !defined ASURA_TARGET_SM3

	"ps.1.1				\n"
	"tex t0				\n"	// base texture
	"tex t1				\n"	// base texture

	"mul_x2_sat r0.rgb, t0, v0 \n"
	"sub_sat r0.a, t0.a, v0.a \n"
	"mul_x2_sat r1.rgb, t1, v0 \n"
	"sub_sat r1.a, t1.a, v1.a \n"
	"lrp r0.rgb, v1, r0, r1 \n"
	"lrp r0.a, v1.b, r0, r1 \n"

#endif // !defined ASURA_TARGET_SM3
;

static const char* const g_szPS_Botanical_ImposterT1_LightD_Code =

#if defined ASURA_TARGET_SM3

	"ps_3_0						\n"
	"dcl_color v0.a				\n"
	"dcl_texcoord0 v1.xy		\n"
	"dcl_texcoord1 v2.xy		\n"
	"dcl_texcoord2 v3.xy		\n"
	"dcl_texcoord7 v4.x			\n"
	"dcl_2d s0					\n"
	"dcl_2d s1					\n"
	"dcl_2d s2					\n"

	"def c1, 4.0, 0.0, 0.0, 1.0	\n"

	"texld r0, v1, s0			\n"
	"texld r1, v2, s1			\n"
	"texld r2, v3, s2			\n"

	"mul r1.rgb, r1.rgb, r2.rgb	\n"
	"mul r0.rgb, r1.rgb, r0.rgb	\n"
	"mul r0.rgb, c0.rgb, r0.rgb	\n"
	"mul oC0.rgb, c1.x, r0.rgb	\n"
	"sub_sat oC0.a, r0.a, v0.a	\n"
	"mov oC1.rgb, c1.yzw		\n"
	"mov oC1.a, v4.x			\n"

#else // !defined ASURA_TARGET_SM3

	"ps.1.1				\n"
	"tex t0				\n"	// base texture
	"tex t1				\n"	// light texture 0
	"tex t2				\n"	// light texture 1

	"mul r0.rgb, t1, t2 \n"
	"mul r0.rgb, t0, r0 \n"
	"mul_x4 r0.rgb, c0, r0 \n"
	"sub_sat r0.a, t0.a, v0.a \n"

#endif // !defined ASURA_TARGET_SM3
;

static const char* const g_szPS_Botanical_ImposterT2_LightD_Code =

#if defined ASURA_TARGET_SM3

	"ps_3_0								\n"
	"dcl_color0 v0						\n"
	"dcl_color1 v1						\n"
	"dcl_texcoord0 v2.xy				\n"
	"dcl_texcoord1 v3.xy				\n"
	"dcl_texcoord2 v4.xy				\n"
	"dcl_texcoord3 v5.xy				\n"
	"dcl_texcoord7 v6.x					\n"
	"dcl_2d s0							\n"
	"dcl_2d s1							\n"
	"dcl_2d s2							\n"
	"dcl_2d s3							\n"

	"def c1, 4.0, 0.0, 0.0, 1.0			\n"

	"texld r0, v2, s0					\n"
	"texld r1, v3, s1					\n"
	"texld r2, v4, s2					\n"
	"texld r3, v5, s3					\n"

	"lrp r4.rgb, v1.rgb, r0.rgb, r1.rgb	\n"
	"mul r0.rgb, r2.rgb, r3.rgb			\n"
	"sub_sat r0.a, r0.a, v0.a			\n"
	"mul r0.rgb, r0.rgb, r4.rgb			\n"
	"sub_sat r1.a, r1.a, v1.a			\n"
	"mul r0.rgb, c0.rgb, r0.rgb			\n"
	"mul_sat oC0.rgb, r0.rgb, c1.x		\n"
	"lrp oC0.a, v1.b, r0.a, r1.a		\n"
	"mov oC1.rgb, c1.yzw				\n"
	"mov oC1.a, v6.x					\n"

#else // !defined ASURA_TARGET_SM3

	"ps.1.1				\n"
	"tex t0				\n"	// base texture
	"tex t1				\n"	// base texture
	"tex t2				\n"	// light texture 0
	"tex t3				\n"	// light texture 1

//	"mul_x2_sat r0.rgb, t0, v0 \n"
//	"mul_x2_sat r1.rgb, t1, v0 \n"
	"lrp r1.rgb, v1, t0, t1 \n"

	"mul r0.rgb, t2, t3 \n"
	"sub_sat r0.a, t0.a, v0.a \n"
	"mul r0.rgb, r0, r1 \n"
	"sub_sat r1.a, t1.a, v1.a \n"
	"mul_x4_sat r0.rgb, c0, r0 \n"
	"lrp r0.a, v1.b, r0, r1 \n"

#endif // !defined ASURA_TARGET_SM3
;

// Register the shader with Asura
const Asura_Direct3D_PixelShader xPS_Botanical_ImposterT1_LightS_Shader( ASURA_D3D_PS_BOTANICAL_IMPOSTER_T1_LIGHTS, g_szPS_Botanical_ImposterT1_LightS_Code);
const Asura_Direct3D_PixelShader xPS_Botanical_ImposterT2_LightS_Shader( ASURA_D3D_PS_BOTANICAL_IMPOSTER_T2_LIGHTS, g_szPS_Botanical_ImposterT2_LightS_Code);
const Asura_Direct3D_PixelShader xPS_Botanical_ImposterT1_LightD_Shader( ASURA_D3D_PS_BOTANICAL_IMPOSTER_T1_LIGHTD, g_szPS_Botanical_ImposterT1_LightD_Code);
const Asura_Direct3D_PixelShader xPS_Botanical_ImposterT2_LightD_Shader( ASURA_D3D_PS_BOTANICAL_IMPOSTER_T2_LIGHTD, g_szPS_Botanical_ImposterT2_LightD_Code);

//*******************************************************************
// Local Classes
//*******************************************************************


//*******************************************************************
// Function Definitions
//*******************************************************************

bool Asura_Direct3D_BGR_Manager::ResetRenderStates( void)
{
	SCOPEDPIXEVENT((0xff00ff00, L"ResetRenderStates"));

	if( false == this->m_bDrawGlobalRenderStatesSet)
	{
		return( true);
	}
	
#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
	HRESULT xResult;
	
	// DLH - Have to add these two lines otherwise NOTHING else renders correctly!
	Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_WHITE);
	Asura_Direct3D_Shaders::RequestFixedFunctionVertexShader( D3DFVF_GENERICVERTEX);
	
	Asura_Direct3D::D3DDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
	
	Asura_Render::CurrentStates.RequestAlphaTest( false);
	Asura_Render::CurrentStates.RequestZBufferEnabled(true);
	Asura_Render::CurrentStates.RequestZBufferWriteEnabled(true);
	Asura_Render::CurrentStates.RequestZBufferCompareMode(ASURA_ZBUFFERCMP_LESSEQUAL);
	Asura_Render::CurrentStates.RequestCullMode( ASURA_CULLMODE_NONE);

	if (Asura_Fog::IsFogRenderable())
	{
		// Set the fog color.
		xResult = Asura_Direct3D::D3DDevice->SetRenderState(D3DRS_FOGCOLOR, Asura_Fog::GetFogColourAsUint());
		ASURA_D3D_OK( xResult);
	}
	
	//Asura_Render::CurrentStates.Request(ASURA_TEXTUREOP_WHITE);
	//Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_WHITE);
#endif
	
	return( true);
}

bool Asura_Direct3D_BGR_Manager::Draw_SM11_GlobalRenderStates( void)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawGlobalRenderStates"));

	if( true == this->m_bDrawGlobalRenderStatesSet)
	{
		return( true);
	}
	
	this->m_bDrawGlobalRenderStatesSet = true;

#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
	HRESULT xResult;
	
	#if defined( ASURA_ASSERT )
		Direct3D_Device* pxD3DDevice = Asura_Direct3D::D3DDevice;
	#endif

	Asura_Assert( NULL != pxD3DDevice, "It would be nice for Direct3D to be setup!");

	//-- Setup render states.
	{
		Asura_Direct3D_BGR_GlobalConstants xGlobalConstants;
		
		ASURA_STATIC_ASSERT( sizeof( xGlobalConstants.m_xData) == sizeof( xGlobalConstants.m_afConstantData));
		
		D3DXMATRIX xView;
		//D3DXMATRIX& xViewProj = *(static_cast< D3DXMATRIX* > ( &xGlobalConstants.m_xData.m_afViewProj));
		D3DXMATRIX& xViewProj = *((D3DXMATRIX*) &xGlobalConstants.m_xData.m_afViewProj);
		
		xResult = Asura_Direct3D::D3DDevice->GetTransform(D3DTS_VIEW, &xView);
		ASURA_D3D_OK( xResult);	
		xResult = Asura_Direct3D::D3DDevice->GetTransform(D3DTS_PROJECTION, &xViewProj);
		ASURA_D3D_OK( xResult);	
		D3DXMatrixMultiply(&xViewProj, &xView, &xViewProj);
		D3DXMatrixTranspose(&xViewProj, &xViewProj);
		
		Asura_Vector_3 xCameraUp;
		Asura_Vector_3 xCameraRight;
		Asura_Vector_3 xCameraForwards;
		Asura_Camera::GetUpVector( xCameraUp);
		Asura_Camera::GetRightVector( xCameraRight);
		Asura_Camera::GetForwardVector( xCameraForwards);
		
		xCameraUp.Normalise();
		xCameraRight.Normalise();
		xCameraForwards.Normalise();
		
		xGlobalConstants.m_xData.m_afCameraUp[0] = xCameraUp.GetX();
		xGlobalConstants.m_xData.m_afCameraUp[1] = xCameraUp.GetY();
		xGlobalConstants.m_xData.m_afCameraUp[2] = xCameraUp.GetZ();
		xGlobalConstants.m_xData.m_afCameraUp[3] = 1.0f;

		xGlobalConstants.m_xData.m_afCameraRight[0] = xCameraRight.GetX();
		xGlobalConstants.m_xData.m_afCameraRight[1] = xCameraRight.GetY();
		xGlobalConstants.m_xData.m_afCameraRight[2] = xCameraRight.GetZ();
		xGlobalConstants.m_xData.m_afCameraRight[3] = 1.0f;

		xGlobalConstants.m_xData.m_afCameraForwards[0] = -xCameraForwards.GetX();
		xGlobalConstants.m_xData.m_afCameraForwards[1] = -xCameraForwards.GetY();
		xGlobalConstants.m_xData.m_afCameraForwards[2] = -xCameraForwards.GetZ();
		xGlobalConstants.m_xData.m_afCameraForwards[3] = 1.0f;

		if( true == Asura_Fog::IsGraphFogEnabled())
		{
			const float fStart = Asura_Fog::GetFogNearPlane();
			const float fEnd = Asura_Fog::GetFogFarPlane();
			const float fScale = ( fStart != fEnd) ? (1.0f / (fEnd - fStart)) : 0;

			// DLH - 15 May 2006 15:27:09 - Calc scaled Plane to workout ABS distance from camera into 0-1 fog range value
			Asura_Vector_3 xCameraForwards;
			Asura_Camera::GetForwardVector( xCameraForwards);
			const Asura_Vector_3 xCameraPosition( *Asura_Camera::GetPosition());

			Asura_Vector_3 xFogPlane = xCameraForwards;
			xFogPlane.Normalise();
			xFogPlane *= fScale;
			
			Asura_Vector_3 xFogPoint = (xCameraForwards * fStart) + xCameraPosition;
			const float fPlaneDistance = xFogPoint * xFogPlane;
			
			xGlobalConstants.m_xData.m_afFogGraphPlane[0] = xFogPlane.GetX();
			xGlobalConstants.m_xData.m_afFogGraphPlane[1] = xFogPlane.GetY();
			xGlobalConstants.m_xData.m_afFogGraphPlane[2] = xFogPlane.GetZ();
			xGlobalConstants.m_xData.m_afFogGraphPlane[3] = -fPlaneDistance;
			
			Asura_Vector_2 xCenterpoint = Asura_Fog::GetGraphFogPoint();
			
			const float fCenterPointError = 1e-6f;
			xCenterpoint.x = Asura_Maths::Max( fCenterPointError, xCenterpoint.x);
			xCenterpoint.x = Asura_Maths::Min( (1.0f - fCenterPointError), xCenterpoint.x);

			// DLH - 15 May 2006 15:24:22 - Scale 0-2 to 0-CenterPoint
			xGlobalConstants.m_xData.m_afFogGraphScale[0][0] = 1.0f / xCenterpoint.x;
			xGlobalConstants.m_xData.m_afFogGraphScale[0][1] = 0.0f;
			// DLH - 15 May 2006 15:23:50 - Clamp a0.x Lookup values
			xGlobalConstants.m_xData.m_afFogGraphScale[0][2] = 0.0f;
			xGlobalConstants.m_xData.m_afFogGraphScale[0][3] = 1.0f;
			
			// DLH - 15 May 2006 15:24:22 - Scale 0-2 to CenterPoint-1
			xGlobalConstants.m_xData.m_afFogGraphScale[1][0] = 1.0f / (1.0f-xCenterpoint.x);
			xGlobalConstants.m_xData.m_afFogGraphScale[1][1] = -xCenterpoint.x / (1.0f - xCenterpoint.x);
			// DLH - 15 May 2006 15:59:53 - Center point for comprassison
			xGlobalConstants.m_xData.m_afFogGraphScale[1][2] = xCenterpoint.x;
			xGlobalConstants.m_xData.m_afFogGraphScale[1][3] = 0.0f;
			
			// DLH - 15 May 2006 15:25:12 - Coeffs Spline One
			{
				const float fValue0 = 1.f - (-xCenterpoint.y);
				const float fValue1 = 1.f - (0.f);
				const float fValue2 = 1.f - (xCenterpoint.y);
				const float fValue3 = 1.f - (Asura_Fog::GetFogValueAtFarPlane());

				xGlobalConstants.m_xData.m_afFogGraphCoeffs[0][0] =  0.5f * ( fValue0 * -1.0f + fValue1 *  3.0f + fValue2 * -3.0f + fValue3 *  1.0f );
				xGlobalConstants.m_xData.m_afFogGraphCoeffs[0][1] =  0.5f * ( fValue0 *  2.0f + fValue1 * -5.0f + fValue2 *  4.0f + fValue3 * -1.0f );
				xGlobalConstants.m_xData.m_afFogGraphCoeffs[0][2] =  0.5f * ( fValue0 * -1.0f +                   fValue2 *  1.0f                   );
				xGlobalConstants.m_xData.m_afFogGraphCoeffs[0][3] =  fValue1;
			}
			// DLH - 15 May 2006 15:25:12 - Coeffs Spline Two
			{
				const float fValue0 = 1.f - (0.f);
				const float fValue1 = 1.f - (xCenterpoint.y);
				const float fValue2 = 1.f - (Asura_Fog::GetFogValueAtFarPlane());
				const float fValue3 = 1.f - (2.f * Asura_Fog::GetFogValueAtFarPlane() - xCenterpoint.y);

				xGlobalConstants.m_xData.m_afFogGraphCoeffs[1][0] =  0.5f * ( fValue0 * -1.0f + fValue1 *  3.0f + fValue2 * -3.0f + fValue3 *  1.0f );
				xGlobalConstants.m_xData.m_afFogGraphCoeffs[1][1] =  0.5f * ( fValue0 *  2.0f + fValue1 * -5.0f + fValue2 *  4.0f + fValue3 * -1.0f );
				xGlobalConstants.m_xData.m_afFogGraphCoeffs[1][2] =  0.5f * ( fValue0 * -1.0f +                   fValue2 *  1.0f                   );
				xGlobalConstants.m_xData.m_afFogGraphCoeffs[1][3] =  fValue1;
			}
		}
		else
		{
			float fStrenght = Asura_Fog::GetFogValueAtFarPlane();
			float fStart = Asura_Fog::GetFogNearPlane();
			float fEnd = Asura_Fog::GetFogFarPlane();
			float fScale = ( fStart != fEnd) ? (1.0f / (fEnd - fStart)) : 0;
			
			const Asura_Vector_3 xCameraPosition( *Asura_Camera::GetPosition());
			Asura_Vector_3 xCameraForwards;
			
			Asura_Camera::GetForwardVector( xCameraForwards);

			Asura_AVector3 xFogPlane( xCameraForwards);
			xFogPlane *= fScale;
			
			Asura_AVector3 xFogPoint = (Asura_AVector3( xCameraForwards) * fStart) + Asura_AVector3( xCameraPosition);
			const float fPlaneDistance = xFogPoint * xFogPlane;
			
			xGlobalConstants.m_xData.m_afFogLinearPlane[0] = xFogPlane.GetX();
			xGlobalConstants.m_xData.m_afFogLinearPlane[1] = xFogPlane.GetY();
			xGlobalConstants.m_xData.m_afFogLinearPlane[2] = xFogPlane.GetZ();
			xGlobalConstants.m_xData.m_afFogLinearPlane[3] = -fPlaneDistance;
			
			xGlobalConstants.m_xData.m_afFogLinearColour[0] = -(fStrenght);
			xGlobalConstants.m_xData.m_afFogLinearColour[1] = 1.0f;
			xGlobalConstants.m_xData.m_afFogLinearColour[2] = 0.75f;
			xGlobalConstants.m_xData.m_afFogLinearColour[3] = 0.5f;
			
		}
		xResult = Asura_Direct3D_Shaders::SetVertexShaderConstantF( ASURA_DIRECT3D_BGR_VS_CONSTANT_GLOBAL, &xGlobalConstants.m_afConstantData[0][0], ASURA_DIRECT3D_BGR_VS_CONSTANT_GLOBAL_SIZE);
		ASURA_D3D_OK( xResult);	
	}
	
	Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_OFF);
	Asura_Render::CurrentStates.RequestWireFrameMode( false);
	Asura_Render::CurrentStates.RequestAlphaTest( true, 0x00);
	Asura_Render::CurrentStates.RequestZBufferEnabled(true);
	Asura_Render::CurrentStates.RequestZBufferWriteEnabled(true);
	Asura_Render::CurrentStates.RequestZBufferCompareMode(ASURA_ZBUFFERCMP_LESSEQUAL);
	
	if (Asura_Fog::IsFogRenderable())
	{
		Asura_Direct3D::D3DDevice->SetRenderState(D3DRS_FOGENABLE, TRUE);
	}
	
	xResult = Asura_Direct3D::D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
	ASURA_D3D_OK( xResult);	
	xResult = Asura_Direct3D::D3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
	ASURA_D3D_OK( xResult);	

#if 1 && defined( ASURA_TOOLS)
	if (Tools_Render_Options::GetWireframeMode() != TOOLS_WIREFRAME_OFF)
	{
		Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_WHITE);
		Asura_Render::CurrentStates.RequestWireFrameMode( true);
	}
#endif

	return( true);
#else
	return( true);
#endif
}

bool Asura_Direct3D_BGR_Manager::Draw_SM11_StaticLightRenderStates()
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawStaticLightRenderStates"));

	HRESULT xResult;
	
	Asura_Render::CurrentStates.RequestZBufferWriteEnabled(true);
	Asura_Render::CurrentStates.RequestZBufferCompareMode(ASURA_ZBUFFERCMP_LESSEQUAL);

	if (Asura_Fog::IsFogRenderable())
	{
		// Set the fog color.
		xResult = Asura_Direct3D::D3DDevice->SetRenderState(D3DRS_FOGCOLOR, Asura_Fog::GetFogColourAsUint());
		ASURA_D3D_OK( xResult);
	}
	
	return( true);
}
	
bool Asura_Direct3D_BGR_Manager::Draw_SM11_DynamicLightRenderStates( const Asura_Photon& xPhoton)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawDynamicLightRenderStates"));

	HRESULT xResult;
	
	{	
		Asura_Direct3D_BGR_DynamicLightConstants xDynamicLightConstants;
		
		Asura_Vector_3 xPosition = xPhoton.GetPosition();
		const float fRange = xPhoton.GetRange();
		const float fScale = 1.0f / fRange;
		const float fScale2 = 0.5f * fScale;
		
		xDynamicLightConstants.m_xData.m_afTransformX[0] = fScale2;
		xDynamicLightConstants.m_xData.m_afTransformX[1] = 0;
		xDynamicLightConstants.m_xData.m_afTransformX[2] = 0;
		xDynamicLightConstants.m_xData.m_afTransformX[3] = 0.5f - (fScale2 * xPosition.GetX());
		
		xDynamicLightConstants.m_xData.m_afTransformY[0] = 0;
		xDynamicLightConstants.m_xData.m_afTransformY[1] = fScale2;
		xDynamicLightConstants.m_xData.m_afTransformY[2] = 0;
		xDynamicLightConstants.m_xData.m_afTransformY[3] = 0.5f - (fScale2 * xPosition.GetY());
		
		xDynamicLightConstants.m_xData.m_afTransformZ[0] = 0;
		xDynamicLightConstants.m_xData.m_afTransformZ[1] = 0;
		xDynamicLightConstants.m_xData.m_afTransformZ[2] = fScale2;
		xDynamicLightConstants.m_xData.m_afTransformZ[3] = 0.5f - (fScale2 * xPosition.GetZ());
		
		ASURA_STATIC_ASSERT( sizeof( xDynamicLightConstants.m_xData) == sizeof( xDynamicLightConstants.m_afConstantData));
		
		xResult = Asura_Direct3D_Shaders::SetVertexShaderConstantF( ASURA_DIRECT3D_BGR_VS_CONSTANT_DYNAMICLIGHT, &xDynamicLightConstants.m_afConstantData[0][0], ASURA_DIRECT3D_BGR_VS_CONSTANT_DYNAMIC_LIGHT_SIZE);
		ASURA_D3D_OK( xResult);	
	}
	
	{
		const float fBrightnessScale = 1.0f / 4.0f;
		float afColour[4];
		
		afColour[0] = fBrightnessScale * xPhoton.GetRedComponent();
		afColour[1] = fBrightnessScale * xPhoton.GetGreenComponent();
		afColour[2] = fBrightnessScale * xPhoton.GetBlueComponent();
		afColour[3] = 1.0f;
		
		xResult = Asura_Direct3D::D3DDevice->SetPixelShaderConstantF( 0, afColour, 1);
	}
	
	Asura_Render::CurrentStates.RequestZBufferWriteEnabled(false);
	//Asura_Render::CurrentStates.RequestZBufferCompareMode(ASURA_ZBUFFERCMP_EQUALS);

	Asura_Direct3D::D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
	Asura_Direct3D::D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );

	Asura_Direct3D::D3DDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
	Asura_Direct3D::D3DDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
			
	Asura_Render::CurrentStates.RequestTextureIndex( 1, this->m_iAttenuationMap);
	Asura_Render::CurrentStates.RequestTextureIndex( 2, this->m_iAttenuationMap);
	
	if (Asura_Fog::IsFogRenderable())
	{
		// Set the fog color.
		xResult = Asura_Direct3D::D3DDevice->SetRenderState(D3DRS_FOGCOLOR, 0x00000000);
		ASURA_D3D_OK( xResult);
	}
	
	return( true);
}

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
uint32 Asura_Direct3D_BGR_Manager::DrawTree_SM11_LeafInstances( const Asura_Direct3D_BGR_Type_Geometry &xGeometry, const struct Asura_Direct3D_BGR_GeometryInstanceConstants *pxCacheConstants, const uint32 uCountCacheInstances, const void* pxDataPointer)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawTreeLeafInstances"));

	Direct3D_VertexBuffer* pxVertexBuffer = xGeometry.m_pxVertexBuffer;
	if( NULL == pxVertexBuffer)
	{
		return( 0);
	}

	Direct3D_IndexBuffer* pxIndexBuffer = xGeometry.m_pxIndexBuffer;
	if( NULL == pxIndexBuffer)
	{
		return( 0);
	}
	
	const uint32 uPrimitiveCount = xGeometry.m_uPrimitiveCount;
	
	if( 0 == uPrimitiveCount)
	{
		return( 0);
	}
	
	const uint32 uCountInstance = Asura_Maths::Min( uCountCacheInstances, xGeometry.m_uBufferInstances);
#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
	HRESULT xResult;
	
	//uint32 uCountInstance = Asura_Maths::Min( uCountCacheInstances, xGeometry.m_uBufferInstances);
	//uCountInstance = Asura_Maths::Min( static_cast< uint32>( 1), uCountInstance);
	
	Direct3D_Device* pxD3DDevice = Asura_Direct3D::D3DDevice;

	// Set index & vertex buffer.
	xResult = Asura_Direct3D::D3DDevice->SetStreamSource( 0, pxVertexBuffer, xGeometry.m_uVBStart * sizeof( Asura_Direct3D_BGR_Type_VertexGeometryLeaf), sizeof( Asura_Direct3D_BGR_Type_VertexGeometryLeaf));
	ASURA_D3D_OK( xResult);	
	xResult = Asura_Direct3D::D3DDevice->SetIndices( pxIndexBuffer);
	ASURA_D3D_OK( xResult);	

	//-- Setup render states.

	const uint32 uCountDataConstantInstance = ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE;

	#if defined( ASURA_ASSERT )
		const uint32 uSizeDataConstantInstance = (4 * sizeof( float)) * uCountDataConstantInstance;
	#endif

	Asura_Assert( sizeof( *pxCacheConstants) == uSizeDataConstantInstance, "Constant size differes");
	
	xResult = Asura_Direct3D_Shaders::SetVertexShaderConstantF( ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE0, &(pxCacheConstants->m_afConstantData[0][0]), uCountDataConstantInstance * uCountInstance);
	ASURA_D3D_OK( xResult);	
	
	//-- Finally, the actual rendering!

//	uint32 uIndexVBStart = xGeometry.m_uVBStart;
	uint32 uIndexIBStart = xGeometry.m_uIBStart;
	{
		const uint32 uBaseVertexIndex = 0;
//		const uint32 uVBStart = xGeometry.m_uVBStart;
		const uint32 uVBStart = 0;
		const uint32 uVBSize = xGeometry.m_uVBSize * uCountInstance;
//		const uint32 uIBStart = xGeometry.m_uIBStart;
		const uint32 uIBSize = xGeometry.m_uIBSize * uCountInstance;
//		const uint32 uPrimitiveCount = uIBSize - 2;
		const uint32 uPrimitiveCount = uIBSize / 3;
		
		xResult = pxD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, uBaseVertexIndex + uVBStart, 0, uVBSize, uIndexIBStart, uPrimitiveCount);
		ASURA_D3D_OK( xResult);	
		
		#if defined( ASURA_TOOLS)
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPCount, 1);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPLeafCount, 1);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPIndexCount, uIBSize);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPVertexCount, uVBSize);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPPrimitiveCount, uPrimitiveCount);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPLeafPrimitiveCount, uPrimitiveCount);
		#endif
	}
#endif

	return( uCountInstance);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_LEAVES)
bool Asura_Direct3D_BGR_Manager::DrawTree_SM11_LeafRenderStates( const Asura_Direct3D_BGR_Type_Geometry &xGeometry, const void* pxDataPointer)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawTreeLeafRenderStates"));

	const uint32 primitiveCount = xGeometry.m_uPrimitiveCount;
	
	if( 0 == primitiveCount)
	{
		return( true);
	}
	
#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
	this->Draw_SM11_GlobalRenderStates();
	
	#if defined( ASURA_ASSERT )
		Direct3D_Device* pxD3DDevice = Asura_Direct3D::D3DDevice;
	#endif
	
	Asura_Assert( NULL != pxD3DDevice, "It would be nice for Direct3D to be setup!");

	const Asura_Photon* pxPhoton = reinterpret_cast< const Asura_Photon*>( pxDataPointer);
	
	{
		
		// Set vertex shader.	
		if( NULL == pxPhoton)
		{
			if( true == Asura_Fog::IsGraphFogEnabled())
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_LEAF_FOGG_LIGHTS);
			}
			else
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_LEAF_FOGL_LIGHTS);
			}
			Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_GEOMETRY3D);
			Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_OFF);
			Asura_Render::CurrentStates.ResetTextureIndexToLast( 1);
			
			this->Draw_SM11_StaticLightRenderStates();
		}
		else
		{
			if( true == Asura_Fog::IsGraphFogEnabled())
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_LEAF_FOGG_LIGHTD);
			}
			else
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_LEAF_FOGL_LIGHTD);
			}
			Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_GEOMETRY3D_LIGHTD);
			Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_ADD);
			
			Asura_Render::CurrentStates.ResetTextureIndexToLast( 3);
			
			this->Draw_SM11_DynamicLightRenderStates( *pxPhoton);
		}

		//-- Setup render states.
		{
			int32 iTextureDiffuse = xGeometry.xMaterial.m_iDiffuseTexture0;
			
			Asura_Render::CurrentStates.RequestTextureIndex( 0, iTextureDiffuse);
		}
	}

	Asura_Render::CurrentStates.RequestCullMode( ASURA_CULLMODE_NONE);
	
#if 1 && defined( ASURA_TOOLS)
	if (Tools_Render_Options::GetWireframeMode() != TOOLS_WIREFRAME_OFF)
	{
		Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_WHITE);
		Asura_Render::CurrentStates.RequestWireFrameMode( true);
	}
#endif

	return( true);
#else
	return( true);
#endif
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
uint32 Asura_Direct3D_BGR_Manager::DrawTree_SM11_3D1SidedInstances( const Asura_Direct3D_BGR_Type_Geometry &xGeometry, const struct Asura_Direct3D_BGR_GeometryInstanceConstants *pxCacheConstants, const uint32 uCountCacheInstances, const void* pxDataPointer)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawTree3D1SidedInstances"));

	Direct3D_VertexBuffer* pxVertexBuffer = xGeometry.m_pxVertexBuffer;
	if( NULL == pxVertexBuffer)
	{
		return( 0);
	}

	Direct3D_IndexBuffer* pxIndexBuffer = xGeometry.m_pxIndexBuffer;
	if( NULL == pxIndexBuffer)
	{
		return( 0);
	}
	
	const uint32 uPrimitiveCount = xGeometry.m_uPrimitiveCount;
	
	if( 0 == uPrimitiveCount)
	{
		return( 0);
	}
	
	const uint32 uCountInstance = Asura_Maths::Min( uCountCacheInstances, xGeometry.m_uBufferInstances);
#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
	HRESULT xResult;
	
	//uint32 uCountInstance = Asura_Maths::Min( uCountCacheInstances, xGeometry.m_uBufferInstances);
	//uCountInstance = Asura_Maths::Min( static_cast< uint32>( 1), uCountInstance);
	
	Direct3D_Device* pxD3DDevice = Asura_Direct3D::D3DDevice;

	// Set index & vertex buffer.
	xResult = Asura_Direct3D::D3DDevice->SetStreamSource( 0, pxVertexBuffer, xGeometry.m_uVBStart * sizeof( Asura_Direct3D_BGR_Type_VertexGeometry3DBasic), sizeof( Asura_Direct3D_BGR_Type_VertexGeometry3DBasic));
	ASURA_D3D_OK( xResult);	
	xResult = Asura_Direct3D::D3DDevice->SetIndices( pxIndexBuffer);
	ASURA_D3D_OK( xResult);	

	//-- Setup render states.

	const uint32 uCountDataConstantInstance = ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE;

	#if defined( ASURA_ASSERT )
		const uint32 uSizeDataConstantInstance = (4 * sizeof( float)) * uCountDataConstantInstance;
	#endif

	Asura_Assert( sizeof( *pxCacheConstants) == uSizeDataConstantInstance, "Constant size differes");
	
	xResult = Asura_Direct3D_Shaders::SetVertexShaderConstantF( ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE0, &(pxCacheConstants->m_afConstantData[0][0]), uCountDataConstantInstance * uCountInstance);
	ASURA_D3D_OK( xResult);	
	
	{
		const float afNormalScale[4] = { 1.0f, 1.0f, 1.0f, 1.0f};
		
		xResult = Asura_Direct3D_Shaders::SetVertexShaderConstantF( ASURA_DIRECT3D_BGR_VS_CONSTANT_VERTEXSCALE, &afNormalScale[0], 1);
		ASURA_D3D_OK( xResult);	
	}
	
	//-- Finally, the actual rendering!

//	uint32 uIndexVBStart = xGeometry.m_uVBStart;
	uint32 uIndexIBStart = xGeometry.m_uIBStart;
	{
		const uint32 uBaseVertexIndex = 0;
//		const uint32 uVBStart = xGeometry.m_uVBStart;
		const uint32 uVBStart = 0;
		const uint32 uVBSize = xGeometry.m_uVBSize * uCountInstance;
//		const uint32 uIBStart = xGeometry.m_uIBStart;
		const uint32 uIBSize = xGeometry.m_uIBSize * uCountInstance;
//		const uint32 uPrimitiveCount = uIBSize - 2;
		const uint32 uPrimitiveCount = uIBSize / 3;
		
		xResult = pxD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, uBaseVertexIndex + uVBStart, 0, uVBSize, uIndexIBStart, uPrimitiveCount);
		ASURA_D3D_OK( xResult);	
		
		#if defined( ASURA_TOOLS)
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPCount, 1);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIP3DCount, 1);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPIndexCount, uIBSize);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPVertexCount, uVBSize);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPPrimitiveCount, uPrimitiveCount);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIP3DPrimitiveCount, uPrimitiveCount);
		#endif
	}
#endif

	return( uCountInstance);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
bool Asura_Direct3D_BGR_Manager::DrawTree_SM11_3D1SidedRenderStates( const Asura_Direct3D_BGR_Type_Geometry &xGeometry, const void* pxDataPointer)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawTree3D1SidedRenderStates"));

	const uint32 primitiveCount = xGeometry.m_uPrimitiveCount;
	
	if( 0 == primitiveCount)
	{
		return( true);
	}
	
#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
	this->Draw_SM11_GlobalRenderStates();
	
	#if defined( ASURA_ASSERT )
		Direct3D_Device* pxD3DDevice = Asura_Direct3D::D3DDevice;
	#endif

	Asura_Assert( NULL != pxD3DDevice, "It would be nice for Direct3D to be setup!");

	const Asura_Photon* pxPhoton = reinterpret_cast< const Asura_Photon*>( pxDataPointer);
	
	{
		// Set vertex shader.	
		if( NULL == pxPhoton)
		{
			if( true == Asura_Fog::IsGraphFogEnabled())
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGG_LIGHTS);
			}
			else
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGL_LIGHTS);
			}
			
			Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_GEOMETRY3D);
			Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_OFF);
			Asura_Render::CurrentStates.ResetTextureIndexToLast( 1);
			
			this->Draw_SM11_StaticLightRenderStates();
		}
		else
		{
			if( true == Asura_Fog::IsGraphFogEnabled())
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGG_LIGHTD);
			}
			else
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGL_LIGHTD);
			}
			
			Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_GEOMETRY3D_LIGHTD);
			Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_ADD);
			
			Asura_Render::CurrentStates.ResetTextureIndexToLast( 3);
			
			this->Draw_SM11_DynamicLightRenderStates( *pxPhoton);
		}
		
		//-- Setup render states.
		{
			int32 iTextureDiffuse = xGeometry.xMaterial.m_iDiffuseTexture0;
			
			Asura_Render::CurrentStates.RequestTextureIndex( 0, iTextureDiffuse);
		}
	}
	
	Asura_Render::CurrentStates.RequestCullMode( ASURA_CULLMODE_CW);
	
#if 1 && defined( ASURA_TOOLS)
	if (Tools_Render_Options::GetWireframeMode() != TOOLS_WIREFRAME_OFF)
	{
		Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_WHITE);
		Asura_Render::CurrentStates.RequestWireFrameMode( true);
	}
#endif

	return( true);
#else
	return( true);
#endif
}
#endif
	
#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
uint32 Asura_Direct3D_BGR_Manager::DrawTree_SM11_3D2SidedInstances( const Asura_Direct3D_BGR_Type_Geometry &xGeometry, const struct Asura_Direct3D_BGR_GeometryInstanceConstants *pxCacheConstants, const uint32 uCountCacheInstances, const void* pxDataPointer)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawTree3D2SidedInstances"));

	Direct3D_VertexBuffer* pxVertexBuffer = xGeometry.m_pxVertexBuffer;
	if( NULL == pxVertexBuffer)
	{
		return( 0);
	}

	Direct3D_IndexBuffer* pxIndexBuffer = xGeometry.m_pxIndexBuffer;
	if( NULL == pxIndexBuffer)
	{
		return( 0);
	}
	
	const uint32 uPrimitiveCount = xGeometry.m_uPrimitiveCount;
	
	if( 0 == uPrimitiveCount)
	{
		return( 0);
	}
	
	const uint32 uCountInstance = Asura_Maths::Min( uCountCacheInstances, xGeometry.m_uBufferInstances);
#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
	HRESULT xResult;
	
	//uint32 uCountInstance = Asura_Maths::Min( uCountCacheInstances, xGeometry.m_uBufferInstances);
	//uCountInstance = Asura_Maths::Min( static_cast< uint32>( 1), uCountInstance);
	
	Direct3D_Device* pxD3DDevice = Asura_Direct3D::D3DDevice;

	// Set index & vertex buffer.
	xResult = Asura_Direct3D::D3DDevice->SetStreamSource( 0, pxVertexBuffer, xGeometry.m_uVBStart * sizeof( Asura_Direct3D_BGR_Type_VertexGeometry3DBasic), sizeof( Asura_Direct3D_BGR_Type_VertexGeometry3DBasic));
	ASURA_D3D_OK( xResult);	
	xResult = Asura_Direct3D::D3DDevice->SetIndices( pxIndexBuffer);
	ASURA_D3D_OK( xResult);	

	//-- Setup render states.

	const uint32 uCountDataConstantInstance = ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE_SIZE;

	#if defined( ASURA_ASSERT )
		const uint32 uSizeDataConstantInstance = (4 * sizeof( float)) * uCountDataConstantInstance;
	#endif

	Asura_Assert( sizeof( *pxCacheConstants) == uSizeDataConstantInstance, "Constant size differes");
	
	xResult = Asura_Direct3D_Shaders::SetVertexShaderConstantF( ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE0, &(pxCacheConstants->m_afConstantData[0][0]), uCountDataConstantInstance * uCountInstance);
	ASURA_D3D_OK( xResult);	
	
	//-- Finally, the actual rendering!

//	uint32 uIndexVBStart = xGeometry.m_uVBStart;
	uint32 uIndexIBStart = xGeometry.m_uIBStart;
	{
		const uint32 uBaseVertexIndex = 0;
//		const uint32 uVBStart = xGeometry.m_uVBStart;
		const uint32 uVBStart = 0;
		const uint32 uVBSize = xGeometry.m_uVBSize * uCountInstance;
//		const uint32 uIBStart = xGeometry.m_uIBStart;
		const uint32 uIBSize = xGeometry.m_uIBSize * uCountInstance;
//		const uint32 uPrimitiveCount = uIBSize - 2;
		const uint32 uPrimitiveCount = uIBSize / 3;
		
		// DLH - Draw the Front facing side first to help hide the back facing side
		{
			const float afNormalScale[4] = { 1.0f, 1.0f, 1.0f, 1.0f};
			
			xResult = Asura_Direct3D_Shaders::SetVertexShaderConstantF( ASURA_DIRECT3D_BGR_VS_CONSTANT_VERTEXSCALE, &afNormalScale[0], 1);
			ASURA_D3D_OK( xResult);	
		}
		
		Asura_Render::CurrentStates.RequestCullMode( ASURA_CULLMODE_CW);
	
		xResult = pxD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, uBaseVertexIndex + uVBStart, 0, uVBSize, uIndexIBStart, uPrimitiveCount);
		ASURA_D3D_OK( xResult);	
		
		#if defined( ASURA_TOOLS)
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPCount, 1);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIP3DCount, 1);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPIndexCount, uIBSize);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPVertexCount, uVBSize);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPPrimitiveCount, uPrimitiveCount);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIP3DPrimitiveCount, uPrimitiveCount);
		#endif

		// DLH - Draw the Back facing side
		{
			const float afNormalScale[4] = { -1.0f, -1.0f, -1.0f, 1.0f};
			
			xResult = Asura_Direct3D_Shaders::SetVertexShaderConstantF( ASURA_DIRECT3D_BGR_VS_CONSTANT_VERTEXSCALE, &afNormalScale[0], 1);
			ASURA_D3D_OK( xResult);	
		}
		
		Asura_Render::CurrentStates.RequestCullMode( ASURA_CULLMODE_CCW);
	
		xResult = pxD3DDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, uBaseVertexIndex + uVBStart, 0, uVBSize, uIndexIBStart, uPrimitiveCount);
		ASURA_D3D_OK( xResult);	
		
		#if defined( ASURA_TOOLS)
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPCount, 1);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIP3DCount, 1);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPIndexCount, uIBSize);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPVertexCount, uVBSize);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPPrimitiveCount, uPrimitiveCount);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIP3DPrimitiveCount, uPrimitiveCount);
		#endif
		
	}
#endif

	return( uCountInstance);
}
#endif

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_GEOMETRY3D)
bool Asura_Direct3D_BGR_Manager::DrawTree_SM11_3D2SidedRenderStates( const Asura_Direct3D_BGR_Type_Geometry &xGeometry, const void* pxDataPointer)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawTree3D2SidedRenderStates"));

	const uint32 primitiveCount = xGeometry.m_uPrimitiveCount;
	
	if( 0 == primitiveCount)
	{
		return( true);
	}
	
#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
	this->Draw_SM11_GlobalRenderStates();
	
	#if defined( ASURA_ASSERT )
		Direct3D_Device* pxD3DDevice = Asura_Direct3D::D3DDevice;
	#endif

	Asura_Assert( NULL != pxD3DDevice, "It would be nice for Direct3D to be setup!");

	const Asura_Photon* pxPhoton = reinterpret_cast< const Asura_Photon*>( pxDataPointer);
	
	Asura_Render::CurrentStates.RequestTextureOpMode( ASURA_TEXTUREOP_CUSTOM);
	
	{
		// Set vertex shader.	
		if( NULL == pxPhoton)
		{
			if( true == Asura_Fog::IsGraphFogEnabled())
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGG_LIGHTS);
			}
			else
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGL_LIGHTS);
			}
			
			Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_GEOMETRY3D);
			Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_OFF);
			Asura_Render::CurrentStates.ResetTextureIndexToLast( 1);
			
			this->Draw_SM11_StaticLightRenderStates();
		}
		else
		{
			if( true == Asura_Fog::IsGraphFogEnabled())
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGG_LIGHTD);
			}
			else
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_GEOMETRY3D_FOGL_LIGHTD);
			}
			
			Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_GEOMETRY3D_LIGHTD);
			Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_ADD);
			
			Asura_Render::CurrentStates.ResetTextureIndexToLast( 3);
			
			this->Draw_SM11_DynamicLightRenderStates( *pxPhoton);
		}
		
		//-- Setup render states.
		{
			int32 iTextureDiffuse = xGeometry.xMaterial.m_iDiffuseTexture0;
			
			Asura_Render::CurrentStates.RequestTextureIndex( 0, iTextureDiffuse);
		}
	}
	
	Asura_Render::CurrentStates.RequestCullMode( ASURA_CULLMODE_CW);
	
#if 1 && defined( ASURA_TOOLS)
	if (Tools_Render_Options::GetWireframeMode() != TOOLS_WIREFRAME_OFF)
	{
		Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_WHITE);
		Asura_Render::CurrentStates.RequestWireFrameMode( true);
	}
#endif

	return( true);
#else
	return( true);
#endif
}
#endif
	
uint32 Asura_Direct3D_BGR_Manager::DrawTreeBillboardInstances( const Asura_Direct3D_BGR_Type_Geometry &xGeometry, const struct Asura_Direct3D_BGR_GeometryInstanceConstants *xCacheConstants, const uint32 uCountCacheInstances, const void* pxDataPointer)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawTreeBillboardInstances"));
	return( 0);
}

bool Asura_Direct3D_BGR_Manager::DrawTreeBillboardInstancesDIPCacheRenderStates_End( Asura_Direct3D_Effect* pxD3DEffect)
{
	return( true);
}

bool Asura_Direct3D_BGR_Manager::DrawTreeBillboardInstancesDIPCacheRenderStates_Start( const Asura_Direct3D_BGR_Type& xTreeDescription, const float fScreenDistanceScale, const Asura_Direct3D_BGR_Type_Geometry &xGeometry, Asura_Direct3D_Effect*& pxD3DEffect)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawTreeBillboardRenderStates"));

	HRESULT xResult;
	
	Direct3D_VertexBuffer* pxVertexBuffer = xGeometry.m_pxVertexBuffer;
	if( NULL == pxVertexBuffer)
	{
		return( false);
	}

	Direct3D_IndexBuffer* pxIndexBuffer = xGeometry.m_pxIndexBuffer;
	if( NULL == pxIndexBuffer)
	{
		return( false);
	}
	
	Asura_Vector_3 xCameraDirection;
	Asura_Camera::GetForwardVector( xCameraDirection);
	xCameraDirection *= -1.0f;
	xCameraDirection.SetY( 0);
	xCameraDirection.Normalise();
	
	const Asura_Direct3D_BGR_Type_GeometryBillboard &xGeometryImposter = static_cast< const Asura_Direct3D_BGR_Type_GeometryBillboard& >( xGeometry);
	
	const uint32 uSignificantImposterMaxCount = 2;
	struct SignificantImposter
	{
		const Asura_Direct3D_BGR_Type_VertexGeometryImposterStorage* m_pxImposterType;
		float m_fAlphaFade;
	};
	SignificantImposter axMSImposters[ uSignificantImposterMaxCount] = 
	{ 
		{NULL, 1.0f},
		{NULL, 1.0f}
	};
	
	const uint32 uImposterCount = xGeometryImposter.m_xArrayBillboards.Size();
	for( uint32 uImposterIndex = 0; uImposterIndex < uImposterCount; uImposterIndex += 1)
	{
		const Asura_Direct3D_BGR_Type_VertexGeometryImposterStorage* pxImposter = &(xGeometryImposter.m_xArrayBillboards[ uImposterIndex]);
		float fAlphaRotateFade = 1.0f;
		const float fImposterDotCamera = xCameraDirection * Asura_Vector_3( pxImposter->m_xDirection);
		if( fImposterDotCamera < pxImposter->m_fFieldOfViewDotOutter)
		{
			continue;
		}
		const float fImposterAngleCamera = Asura_Maths::ArcCosine( fImposterDotCamera);
		fAlphaRotateFade = 0.5f * (fImposterAngleCamera - pxImposter->m_fFieldOfViewAngleInner) / (pxImposter->m_fFieldOfViewAngleOutter - pxImposter->m_fFieldOfViewAngleInner);
		fAlphaRotateFade = Asura_Maths::Min( fAlphaRotateFade, 1.0f);
		fAlphaRotateFade = Asura_Maths::Max( fAlphaRotateFade, 0.0f);
		
		for( uint32 uSignificantImposterCheckIndex = 0; uSignificantImposterCheckIndex < uSignificantImposterMaxCount; uSignificantImposterCheckIndex += 1)
		{
			SignificantImposter& xMSImposter = axMSImposters[ uSignificantImposterCheckIndex];
			if( NULL != xMSImposter.m_pxImposterType && xMSImposter.m_fAlphaFade <= fAlphaRotateFade)
			{
				continue;
			}

			const Asura_Direct3D_BGR_Type_VertexGeometryImposterStorage* pxImposterOld = xMSImposter.m_pxImposterType;
			const float fAlphaRotateFadeOld = xMSImposter.m_fAlphaFade;
			
			xMSImposter.m_pxImposterType = pxImposter;
			xMSImposter.m_fAlphaFade = fAlphaRotateFade;
			
			pxImposter = pxImposterOld;
			fAlphaRotateFade = fAlphaRotateFadeOld;
		}
	}
	
//	const uint32 uSignificantImposterCount = 1;
//	axMSImposters[0].m_pxImposterType = &(xGeometryImposter.m_xArrayBillboards[0]);
	
	const Asura_Direct3D_BGR_Type_VertexGeometryImposterStorage* pxImposterType0 = axMSImposters[0].m_pxImposterType;
	const Asura_Direct3D_BGR_Type_VertexGeometryImposterStorage* pxImposterType1 = axMSImposters[1].m_pxImposterType;

	Asura_Assert( (pxImposterType0 == NULL && pxImposterType1 == NULL) || (pxImposterType0 != NULL && pxImposterType1 == NULL) || (pxImposterType0 != NULL && pxImposterType1 != NULL), "Most Significant Imposters does not seem right");
	uint32 uSignificantImposterCount = ((NULL != pxImposterType0) ? 1 : 0) + ((NULL != pxImposterType1) ? 1 : 0);
	
	if( 0 == uSignificantImposterCount)
	{
		return( false);
	}

#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
	this->Draw_SM11_GlobalRenderStates();
	
	#if defined( ASURA_ASSERT )
		Direct3D_Device* pxD3DDevice = Asura_Direct3D::D3DDevice;
	#endif

	Asura_Assert( NULL != pxD3DDevice, "It would be nice for Direct3D to be setup!");

	xResult = Asura_Direct3D::D3DDevice->SetStreamSource( 0, pxVertexBuffer, 0, sizeof( Asura_Direct3D_BGR_Type_VertexGeometryImposter));
	ASURA_D3D_OK( xResult);	
	xResult = Asura_Direct3D::D3DDevice->SetIndices( pxIndexBuffer);
	ASURA_D3D_OK( xResult);	
	
	// Set vertex shader.	
	switch( uSignificantImposterCount)
	{
	
		case 1:
		{
			if( true == Asura_Fog::IsGraphFogEnabled())
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGG_LIGHTS);
			}
			else
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGL_LIGHTS);
			}
			Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_IMPOSTER_T1_LIGHTS);
			break;
		}
		case 2:
		{
			if( true == Asura_Fog::IsGraphFogEnabled())
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGG_LIGHTS);
			}
			else
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGL_LIGHTS);
			}
			Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_IMPOSTER_T2_LIGHTS);
			break;
		}
		default:
		{
			Asura_Assert( false, "Unhandled number of Signifiant Imposters");
			return( false);
		}	
	}
	//-- Setup render states.
	
	// DLH - 07 April 2006 15:52:09 - Setup the Render States

	{
	
#define ASURA_DIRECT3D_BGR_VS_CONSTANT_IMPOSTER_SIZE 15
struct Asura_Direct3D_BGR_ImposterConstants
{
	Asura_Direct3D_BGR_ImposterConstants() { ASURA_STATIC_ASSERT( sizeof( m_afConstantData) == sizeof( m_xData));}
	union
	{
		// DLH - 30 March 2006 11:09:58 - Do not use this variable to set Data, EVER
		float m_afConstantData[ ASURA_DIRECT3D_BGR_VS_CONSTANT_IMPOSTER_SIZE][4];
		
		// DLH - 30 March 2006 11:09:58 - USE THESE to set the Data
		struct
		{
			float m_afCameraPosition[4];
			float m_afAlphaFade[4];
			float m_afAlphaRotate[4];
			float m_afXY[4][4];
			float m_afUV[ uSignificantImposterMaxCount][4][4];
		}m_xData;
	};
};

		Asura_Direct3D_BGR_ImposterConstants xImposterConstants;
		
		memset( &xImposterConstants, 0, sizeof( xImposterConstants));
		
		{
			const Asura_Vector_3* pxCameraPosition = Asura_Camera::GetPosition();
			
			xImposterConstants.m_xData.m_afCameraPosition[0] = pxCameraPosition->x;
			xImposterConstants.m_xData.m_afCameraPosition[1] = pxCameraPosition->y;
			xImposterConstants.m_xData.m_afCameraPosition[2] = pxCameraPosition->z;
			xImposterConstants.m_xData.m_afCameraPosition[3] = 1.0f;
		}
		
		{
			const float fDeltaL0 = xGeometryImposter.m_xLodRange.m_afDelta[ Asura_Direct3D_BGR_Type_GeometryLODRange::LOW_0];
			const float fDeltaL1 = xGeometryImposter.m_xLodRange.m_afDelta[ Asura_Direct3D_BGR_Type_GeometryLODRange::LOW_1];
			const float fDistanceL0 = (xTreeDescription.m_fLodLimitNear + (xTreeDescription.m_fLodLimitDelta * fDeltaL0)) / fScreenDistanceScale;
			const float fDistanceL1 = (xTreeDescription.m_fLodLimitNear + (xTreeDescription.m_fLodLimitDelta * fDeltaL1)) / fScreenDistanceScale;

			const float fDistanceDelta = (fDistanceL1 != fDistanceL0) ? fDistanceL1 - fDistanceL0 : 1e-3f;
			const float fGradient = -0.5f / (fDistanceDelta);
			
			xImposterConstants.m_xData.m_afAlphaFade[0] = fGradient;
			// DLH - 18 April 2006 17:11:31 - Alpha Fade Imposter 0
			xImposterConstants.m_xData.m_afAlphaFade[1] = (-fDistanceL1 * fGradient) + 0.5f;
			// DLH - 18 April 2006 17:11:31 - Alpha Fade Imposter 1
			xImposterConstants.m_xData.m_afAlphaFade[2] = (-fDistanceL1 * fGradient) + 0.5f;
			xImposterConstants.m_xData.m_afAlphaFade[3] = 0;
		}
		
		if( NULL != pxImposterType0)
		{
			const float fRadius = 0.5f * pxImposterType0->m_fWidth;
			const float fHeight = pxImposterType0->m_fHeight;
			
			xImposterConstants.m_xData.m_afXY[ 0][ 0] = -fRadius;
			xImposterConstants.m_xData.m_afXY[ 0][ 1] = -fHeight;
			xImposterConstants.m_xData.m_afXY[ 1][ 0] = -fRadius;
			xImposterConstants.m_xData.m_afXY[ 1][ 1] = 0.0f;
			xImposterConstants.m_xData.m_afXY[ 2][ 0] = +fRadius;
			xImposterConstants.m_xData.m_afXY[ 2][ 1] = -fHeight;
			xImposterConstants.m_xData.m_afXY[ 3][ 0] = +fRadius;
			xImposterConstants.m_xData.m_afXY[ 3][ 1] = 0.0f;
		}
		
		for( uint32 uSignificantImposterIndex = 0; uSignificantImposterIndex < uSignificantImposterMaxCount; uSignificantImposterIndex += 1)
		{
			const Asura_Direct3D_BGR_Type_VertexGeometryImposterStorage* pxImposterType = axMSImposters[ uSignificantImposterIndex].m_pxImposterType;
			
			if( NULL == pxImposterType)
			{
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 0][ 0] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 0][ 1] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 0][ 2] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 0][ 3] = 0.5f;
				
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 1][ 0] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 1][ 1] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 1][ 2] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 1][ 3] = 0.5f;
				
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 2][ 0] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 2][ 1] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 2][ 2] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 2][ 3] = 0.5f;
				
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 3][ 0] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 3][ 1] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 3][ 2] = 0.5f;
				xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 3][ 3] = 0.5f;

				xImposterConstants.m_xData.m_afAlphaFade[2 + uSignificantImposterIndex] = 1.0f;
				
				Asura_Render::CurrentStates.RequestTextureIndex( uSignificantImposterIndex, ASURA_TEXTURE_INVALID);
				continue;
			}
			
			float fUMin = pxImposterType->m_afTextcoord0[ 0];
			float fVMin = pxImposterType->m_afTextcoord0[ 1];
			float fUMax = pxImposterType->m_afTextcoord1[ 0];
			float fVMax = pxImposterType->m_afTextcoord1[ 1];
			
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 0][ 0] = fUMin;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 0][ 1] = fVMin;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 0][ 2] = 1.0f;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 0][ 3] = 1.0f;
			
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 1][ 0] = fUMin;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 1][ 1] = fVMax;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 1][ 2] = 1.0f;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 1][ 3] = 1.0f;
			
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 2][ 0] = fUMax;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 2][ 1] = fVMin;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 2][ 2] = 1.0f;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 2][ 3] = 1.0f;
			
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 3][ 0] = fUMax;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 3][ 1] = fVMax;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 3][ 2] = 1.0f;
			xImposterConstants.m_xData.m_afUV[ uSignificantImposterIndex][ 3][ 3] = 1.0f;
			
			xImposterConstants.m_xData.m_afAlphaFade[2 + uSignificantImposterIndex] = axMSImposters[ uSignificantImposterIndex].m_fAlphaFade;
			
			int32 iTextureDiffuse = pxImposterType->m_iTextureDiffuse;
			
			Asura_Render::CurrentStates.RequestTextureIndex( uSignificantImposterIndex, iTextureDiffuse);
		}
		
		{
			const float fRotateFade0 =  0.5f - xImposterConstants.m_xData.m_afAlphaFade[2];
			const float fRotateFade1 =  0.5f - xImposterConstants.m_xData.m_afAlphaFade[3];
			const float fRotateFadeTotal = fRotateFade0 + fRotateFade1;
			const float fRotateFade = (0 != fRotateFadeTotal) ? (fRotateFade0 / fRotateFadeTotal) : 0.0f;
			xImposterConstants.m_xData.m_afAlphaRotate[0] = fRotateFade;
		}

		xResult = Asura_Direct3D_Shaders::SetVertexShaderConstantF( ASURA_DIRECT3D_BGR_VS_CONSTANT_INSTANCE0, &(xImposterConstants.m_afConstantData[0][0]), ASURA_DIRECT3D_BGR_VS_CONSTANT_IMPOSTER_SIZE);
		ASURA_D3D_OK( xResult);	
	}
	
	Asura_Render::CurrentStates.RequestCullMode( ASURA_CULLMODE_NONE);
	Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_OFF);
	Asura_Render::CurrentStates.RequestZBufferWriteEnabled( true);
	
	if (Asura_Fog::IsFogRenderable())
	{
		// Set the fog color.
		xResult = Asura_Direct3D::D3DDevice->SetRenderState(D3DRS_FOGCOLOR, Asura_Fog::GetFogColourAsUint());
		ASURA_D3D_OK( xResult);
	}
#if 1 && defined( ASURA_TOOLS)
	if (Tools_Render_Options::GetWireframeMode() != TOOLS_WIREFRAME_OFF)
	{
		Asura_Render::CurrentStates.RequestTextureOpMode(ASURA_TEXTUREOP_WHITE);
		Asura_Render::CurrentStates.RequestWireFrameMode( true);
	}
#endif

	return( true);
#else
	return( true);
#endif
}

bool Asura_Direct3D_BGR_Manager::DrawTreeBillboardDynamicRenderStates( const Asura_Photon& xPhoton, Asura_Direct3D_Effect*& pxD3DEffect)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawTreeBillboardDynamicRenderStates"));

#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
	HRESULT xResult;
	
	{
		// DLH - 30 June 2006 12:30:49 - Remap the present shaders to Dynamic light versions
		const ASURA_D3D_VERTEXSHADER_ID eCurrentVertexShader = Asura_Direct3D_Shaders::GetCurrentVertexShader();
		switch( eCurrentVertexShader)
		{
			case ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGG_LIGHTS:
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGG_LIGHTD);
				Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_IMPOSTER_T1_LIGHTD);

				Asura_Direct3D::D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
				Asura_Direct3D::D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );

				Asura_Direct3D::D3DDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
				Asura_Direct3D::D3DDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
						
				Asura_Render::CurrentStates.RequestTextureIndex( 1, this->m_iAttenuationMap);
				Asura_Render::CurrentStates.RequestTextureIndex( 2, this->m_iAttenuationMap);
				break;
			}
			case ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGL_LIGHTS:
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGL_LIGHTD);
				Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_IMPOSTER_T1_LIGHTD);

				Asura_Direct3D::D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
				Asura_Direct3D::D3DDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );

				Asura_Direct3D::D3DDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
				Asura_Direct3D::D3DDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
						
				Asura_Render::CurrentStates.RequestTextureIndex( 1, this->m_iAttenuationMap);
				Asura_Render::CurrentStates.RequestTextureIndex( 2, this->m_iAttenuationMap);
				break;
			}
			case ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGG_LIGHTS:
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGG_LIGHTD);
				Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_IMPOSTER_T2_LIGHTD);

				Asura_Direct3D::D3DDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
				Asura_Direct3D::D3DDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );

				Asura_Direct3D::D3DDevice->SetSamplerState(3, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
				Asura_Direct3D::D3DDevice->SetSamplerState(3, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
						
				Asura_Render::CurrentStates.RequestTextureIndex( 2, this->m_iAttenuationMap);
				Asura_Render::CurrentStates.RequestTextureIndex( 3, this->m_iAttenuationMap);
				break;
			}
			case ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGL_LIGHTS:
			{
				Asura_Direct3D_Shaders::RequestVertexShader( ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGL_LIGHTD);
				Asura_Direct3D_Shaders::RequestPixelShader( ASURA_D3D_PS_BOTANICAL_IMPOSTER_T2_LIGHTD);

				Asura_Direct3D::D3DDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
				Asura_Direct3D::D3DDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );

				Asura_Direct3D::D3DDevice->SetSamplerState(3, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
				Asura_Direct3D::D3DDevice->SetSamplerState(3, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
						
				Asura_Render::CurrentStates.RequestTextureIndex( 2, this->m_iAttenuationMap);
				Asura_Render::CurrentStates.RequestTextureIndex( 3, this->m_iAttenuationMap);
				break;
			}
			case ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGG_LIGHTD:
			case ASURA_D3D_VS_BOTANICAL_IMPOSTER_T1_FOGL_LIGHTD:
			case ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGG_LIGHTD:
			case ASURA_D3D_VS_BOTANICAL_IMPOSTER_T2_FOGL_LIGHTD:
			{
				// DLH - 30 June 2006 12:31:23 - These do not need to be remapped
				break;
			}
			default:
			{
				Asura_Assertf( false, ("Unhandled Vertex Shader setup (%d)", eCurrentVertexShader));
			}
		}
	}
	
	{	
		Asura_Direct3D_BGR_DynamicLightConstants xDynamicLightConstants;
		
		Asura_Vector_3 xPosition = xPhoton.GetPosition();
		const float fRange = xPhoton.GetRange();
		const float fScale = 1.0f / fRange;
		const float fScale2 = 0.5f * fScale;
		
		xDynamicLightConstants.m_xData.m_afTransformX[0] = fScale2;
		xDynamicLightConstants.m_xData.m_afTransformX[1] = 0;
		xDynamicLightConstants.m_xData.m_afTransformX[2] = 0;
		xDynamicLightConstants.m_xData.m_afTransformX[3] = 0.5f - (fScale2 * xPosition.GetX());
		
		xDynamicLightConstants.m_xData.m_afTransformY[0] = 0;
		xDynamicLightConstants.m_xData.m_afTransformY[1] = fScale2;
		xDynamicLightConstants.m_xData.m_afTransformY[2] = 0;
		xDynamicLightConstants.m_xData.m_afTransformY[3] = 0.5f - (fScale2 * xPosition.GetY());
		
		xDynamicLightConstants.m_xData.m_afTransformZ[0] = 0;
		xDynamicLightConstants.m_xData.m_afTransformZ[1] = 0;
		xDynamicLightConstants.m_xData.m_afTransformZ[2] = fScale2;
		xDynamicLightConstants.m_xData.m_afTransformZ[3] = 0.5f - (fScale2 * xPosition.GetZ());
		
		ASURA_STATIC_ASSERT( sizeof( xDynamicLightConstants.m_xData) == sizeof( xDynamicLightConstants.m_afConstantData));
		
		xResult = Asura_Direct3D_Shaders::SetVertexShaderConstantF( ASURA_DIRECT3D_BGR_VS_CONSTANT_DYNAMICLIGHT, &xDynamicLightConstants.m_afConstantData[0][0], ASURA_DIRECT3D_BGR_VS_CONSTANT_DYNAMIC_LIGHT_SIZE);
		ASURA_D3D_OK( xResult);	
	}
	
	{
		const float fBrightnessScale = 1.0f / 4.0f;
		float afColour[4];
		
		afColour[0] = fBrightnessScale * xPhoton.GetRedComponent();
		afColour[1] = fBrightnessScale * xPhoton.GetGreenComponent();
		afColour[2] = fBrightnessScale * xPhoton.GetBlueComponent();
		afColour[3] = 1.0f;
		
		xResult = Asura_Direct3D::D3DDevice->SetPixelShaderConstantF( 0, afColour, 1);
	}
	
	Asura_Render::CurrentStates.RequestTranslucencyMode(ASURA_TRANSLUCENCY_ADD);
	Asura_Render::CurrentStates.RequestZBufferWriteEnabled(false);
	
	if (Asura_Fog::IsFogRenderable())
	{
		// Set the fog color.
		xResult = Asura_Direct3D::D3DDevice->SetRenderState(D3DRS_FOGCOLOR, 0x00000000);
		ASURA_D3D_OK( xResult);
	}
	
	return( true);
#else
	return( true);
#endif
}

#if defined( ASURA_DIRECT3D_BGR_SUPPORT_IMPOSTERS)
bool Asura_Direct3D_BGR_Manager::DrawTreeBillboardInstancesDIPCache( const Asura_DIPCache_DIPData& xDIPData, const uint32 uCallbackData)
{
	SCOPEDPIXEVENT((0xff00ff00, L"DrawTreeBillboardInstancesDIPCache"));

#if 1 && defined( ASURA_DIRECT3D_BGR_ENABLE_D3D_CALLS)
//	const static uint32 uIndexMaxCount = Asura_Direct3D_Carpet_Game_Render::GetBatchIndexBufferSize();
	const uint32 uIndexMaxCount = 0x10000;
	
	HRESULT xResult;

	uint32 uIndexTotalCount = xDIPData.GetIndexBufferStop() - xDIPData.GetIndexBufferStart();
	uint32 uVertexBufferOffset = 0;
	while( 0 < uIndexTotalCount)
	{
		const uint32 uIndexCount = Asura_Maths::Min( uIndexMaxCount, uIndexTotalCount);
		const uint32 uCountPrimitives = uIndexCount / 3;
		const uint32 uVertexCount = 2 * uCountPrimitives;
		xResult = Asura_Direct3D::D3DDevice->DrawIndexedPrimitive( 
			D3DPT_TRIANGLELIST, 
			xDIPData.GetVertexBufferStart() + uVertexBufferOffset, 0, uVertexCount, 
			0, uCountPrimitives);
		if( ASURA_D3D_FAILED( xResult))
		{
			return( false);
		}
		
		#if defined( ASURA_TOOLS)
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPCount, 1);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPImposterCount, 1);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPIndexCount, uIndexCount);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPVertexCount, uVertexCount);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPPrimitiveCount, uCountPrimitives);
			TOOLS_BOTANICAL_STATISTICS_ADD( s_uDIPImposterPrimitiveCount, uCountPrimitives);
		#endif
		
		//Asura_Render::AddToTrianglesRendered()
		
		uIndexTotalCount -= uIndexCount;
		uVertexBufferOffset += uVertexCount;
	}
#endif

	return( true);
}
#endif


//*******************************************************************
//
// (c) 2006 Rebellion (Derby)
//
// Warning: This computer program is protected by copyright law and 
// international treaties. Unauthorized reproduction or distribution
// of this program, or any portion of it, may result in severe civil and
// criminal penalties, and will be prosecuted to the maximum extent 
// possible under the law.
//
//*******************************************************************

#endif
#endif //defined( ASURA_USE_BOTANICALS)
