#include "stdafx.h"														// for precompiled headers (has to be in first place)
#include <assert.h>														// assert()
#include <d3d8.h>															// IDirect3DTexture8
#include "D3dx8math.h"												// D3DXMATRIX, D3DXCreateTextureFromFile
#include "Error.h"														// Error,Message
#include "3DMaterial.h"												// C3DMaterial
#include "3DRenderer.h"												// C3DRenderer
#include "3DScene.h"													// C3DScene
#include "3DTriangleBunch.h"									// C3DTriangleBunch

#ifdef USE_MATROXDISPLACEMENTMAPPING
	#include "mtxDmExt v1.0.h"									// MTX_EXT_BEGIN_X, ..   used for DX8.x backdoor to Parhelia displacement mapping
#endif


// Specifies the dimensionality and arithmetic data type. The following values are defined. 
//
// D3DVSDT_D3DCOLOR	// 4-D packed unsigned bytes mapped to 0.0 to 1.0 range. In double word format this is ARGB, or in byte ordering it would be B, G, R, A. 
// D3DVSDT_FLOAT1		// 1-D float expanded to (value, 0.0, 0.0, 1.0) 
// D3DVSDT_FLOAT2		// 2-D float expanded to (value, value, 0.0, 1.0) 
// D3DVSDT_FLOAT3		// 3-D float expanded to (value, value, value, 1.0) 
// D3DVSDT_FLOAT4		// 4-D float. 
// D3DVSDT_SHORT2		// 2-D signed short expanded to (value, value, 0.0, 1.0) 
// D3DVSDT_SHORT4		// 4-D signed short 
// D3DVSDT_UBYTE4		// 4-D unsigned byte. In double word format this is ABGR, or in byte ordering it would be R, G, B, A. 
DWORD PolyBumpVertexDecl[]=
{

#ifdef USE_MATROXDISPLACEMENTMAPPING
  D3DVSD_CONST( 0, 4 ),
  MTX_EXT_BEGIN_X, MTX_EXT_BEGIN_Y, MTX_EXT_BEGIN_Z, MTX_EXT_BEGIN_W,
//    MTX_EXT_DMSHADER, m_dwTessellationType, m_dwInterpolationType, 0,
  MTX_EXT_DMSHADER, MTX_EXT_DMADAPTIVE, MTX_EXT_DMLINEAR, 0,
	MTX_EXT_DMMAPPING, MTX_EXT_DMSEGMENTS, 4, 0,
  MTX_EXT_END_X, MTX_EXT_END_Y, MTX_EXT_END_Z, MTX_EXT_END_W,
#endif
	D3DVSD_STREAM(0),
  D3DVSD_REG( 0, D3DVSDT_FLOAT3 ),		// position
  D3DVSD_REG( 1, D3DVSDT_FLOAT3 ),		// normal

	D3DVSD_REG( 3, D3DVSDT_FLOAT2 ),		// texture
  D3DVSD_REG( 4, D3DVSDT_FLOAT3 ),		// s x t
  D3DVSD_REG( 5, D3DVSDT_FLOAT3 ),		// s
  D3DVSD_REG( 6, D3DVSDT_FLOAT3 ),		// t
  D3DVSD_END()
};


// constructor
C3DMaterial::C3DMaterial( const char *inszName )
{
	m_sName=inszName;
	m_Ka=D3DXCOLOR(1,1,1,0);
	m_Kd=D3DXCOLOR(1,1,1,0);
	m_Ks=D3DXCOLOR(1,1,1,0);
	m_Kss=D3DXCOLOR(0,0,0,0);

	m_pDiffuseTexture=0;
	m_pPolybumpTexture=0;
	m_pOccDirTexture=0;

	m_TriangleCount=0;
}


// destructor
C3DMaterial::~C3DMaterial( void )
{
	FreeData();
}




// set attribute (load the texture)
bool C3DMaterial::SetDiffuseTexture( C3DRenderer &inRenderer, const char *inszFileName )
{
	IDirect3DDevice8 *pDev=inRenderer.GetDirectXDevice();				assert(pDev);

	if(m_pDiffuseTexture)
	{ 
		Error.Add("Diffuse texture already set (new one: '%s')",inszFileName);return(false); 
	}

	HRESULT hRes;

	// load diffuse texture
	if(*inszFileName)
	{
		hRes=D3DXCreateTextureFromFile( pDev, inszFileName,(LPDIRECT3DTEXTURE8 *)&m_pDiffuseTexture );
		if(FAILED(hRes))
		{
			Error.AddDirectX("D3DXCreateTextureFromFile failed: ",hRes);
			return(false);
		}
	}

	return(true);
}



// set attribute (load the texture)
bool C3DMaterial::SetPolyBumpTexture( C3DRenderer &inRenderer, const char *inszFileName, bool inbLoadClonemap )
{
	IDirect3DDevice8 *pDev=inRenderer.GetDirectXDevice();				assert(pDev);
	if(m_pPolybumpTexture){ Error.Add("Bump texture already set (new one: '%s')",inszFileName);return(false); }

	HRESULT hRes;

	// load diffuse texture
	if(*inszFileName)
	{
		hRes=D3DXCreateTextureFromFile( pDev, inszFileName,(LPDIRECT3DTEXTURE8 *)&m_pPolybumpTexture );
		if(FAILED(hRes))
		{
			Error.AddDirectX("D3DXCreateTextureFromFile failed: ",hRes);
			return(false);
		}

		// load Clonemap .cln if there is one
		if(inbLoadClonemap)
		{
			string sFilename=inszFileName;
			int iLen=sFilename.length();

			if(iLen>3)
			if(sFilename[iLen-4]=='.')
			{
				sFilename[iLen-3]='c';
				sFilename[iLen-2]='l';
				sFilename[iLen-1]='n';

				m_PolybumpClonemap.LoadCloneMap(sFilename.c_str());
			}
		}
	}

	return(true);
}



// set attribute (load the texture)
bool C3DMaterial::SetOcclusionDirectionTexture( C3DRenderer &inRenderer, const char *inszFileName )
{
	IDirect3DDevice8 *pDev=inRenderer.GetDirectXDevice();				assert(pDev);
	if(m_pOccDirTexture){ Error.Add("OccDir texture already set (new one: '%s')",inszFileName);return(false); }

	HRESULT hRes;

	// load diffuse texture
	if(*inszFileName)
	{
		hRes=D3DXCreateTextureFromFile( pDev, inszFileName,(LPDIRECT3DTEXTURE8 *)&m_pOccDirTexture );
		if(FAILED(hRes))
		{
			Error.AddDirectX("D3DXCreateTextureFromFile failed: ",hRes);
			return(false);
		}
	}

	return(true);
}

// free textures (used by destructor)
void C3DMaterial::FreeData( void )
{
	if(m_pDiffuseTexture)
	{
		m_pDiffuseTexture->Release();
		m_pDiffuseTexture=0;
	}

	if(m_pPolybumpTexture)
	{
		m_pPolybumpTexture->Release();
		m_pPolybumpTexture=0;
	}

	if(m_pOccDirTexture)
	{
		m_pOccDirTexture->Release();
		m_pOccDirTexture=0;
	}
}


void C3DMaterial::SetMaterialAndRender( C3DRenderer &inRenderer,
																				C3DTriangleBunch &inTriBunch, C3DScene &inScene )
{
	IDirect3DDevice8 *pDev=inRenderer.GetDirectXDevice();				assert(pDev);

	DWORD inoutdwBackBufferLayers=0;

//	pDev->SetRenderState(D3DRS_ZFUNC,D3DCMP_LESS);
	pDev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
	pDev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
	pDev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ZERO);

	for(DWORD dwPass=1;dwPass<=inRenderer.AskAmountOfPasses();dwPass++)
	{
		if(SetMaterial(inRenderer,dwPass))
			RenderTriangleList(inRenderer,inTriBunch,inScene,inoutdwBackBufferLayers);
	}
}







bool C3DMaterial::SetMaterial( C3DRenderer &inRenderer, const DWORD indwPass )
{
	IDirect3DDevice8 *pDev=inRenderer.GetDirectXDevice();				assert(pDev);

	HRESULT hRes;

	bool bTexturesThere=false;

	if(inRenderer.AskTextured())
	{
		bTexturesThere=true;

		if(inRenderer.AskShowNormalmap())
		{
			if(!m_pPolybumpTexture) bTexturesThere=false;
			hRes=pDev->SetTexture(0,m_pPolybumpTexture);
			if(FAILED(hRes)){ Error.AddDirectX("SetTexture(2) failed: ",hRes); bTexturesThere=false; }

			hRes=pDev->SetTexture(1,0);
			if(FAILED(hRes))Error.AddDirectX("SetTexture(4) failed: ",hRes);

			hRes=pDev->SetTexture(2,0);
			if(FAILED(hRes))Error.AddDirectX("SetTexture(4) failed: ",hRes);
		}
		else
		{
			if(m_pDiffuseTexture)
        hRes=pDev->SetTexture(0,m_pDiffuseTexture);
			 else
				hRes=pDev->SetTexture(0,inRenderer.m_ShaderManager.m_pWhiteTexture);

			if(FAILED(hRes)){ Error.AddDirectX("SetTexture(1) failed: ",hRes); bTexturesThere=false; }


			IDirect3DTexture8 *pNormalmap=0;

			if(m_pPolybumpTexture)
				pNormalmap=m_pPolybumpTexture;

			if(indwPass==1 && m_pOccDirTexture)
				pNormalmap=m_pOccDirTexture;

			if(!pNormalmap)
				bTexturesThere=false;

			hRes=pDev->SetTexture(1,pNormalmap);

			if(FAILED(hRes)){ Error.AddDirectX("SetTexture(2) failed: ",hRes); bTexturesThere=false; }

			if(inRenderer.AskUseNormalizeCubemapT2T3())
			{
				hRes=pDev->SetTexture(2,inRenderer.m_ShaderManager.m_pCubeNormalize);
				if(FAILED(hRes)){ Error.AddDirectX("SetTexture(2) failed: ",hRes); bTexturesThere=false; }

				hRes=pDev->SetTexture(3,inRenderer.m_ShaderManager.m_pCubeNormalize);
				if(FAILED(hRes)){ Error.AddDirectX("SetTexture(2) failed: ",hRes); bTexturesThere=false; }
			}
			else
			{
				if(!inRenderer.m_ShaderManager.m_pIrradianceTexture) bTexturesThere=false;
				hRes=pDev->SetTexture(3,inRenderer.m_ShaderManager.m_pIrradianceTexture);
				if(FAILED(hRes)){ Error.AddDirectX("SetTexture(3) failed: ",hRes); bTexturesThere=false; }
			}
		}
	}
	else
	{
		hRes=pDev->SetTexture(0,0);
		if(FAILED(hRes))Error.AddDirectX("SetTexture(4) failed: ",hRes);

		hRes=pDev->SetTexture(1,0);
		if(FAILED(hRes))Error.AddDirectX("SetTexture(5) failed: ",hRes);

		hRes=pDev->SetTexture(2,0);
		if(FAILED(hRes))Error.AddDirectX("SetTexture(6) failed: ",hRes);

		hRes=pDev->SetTexture(3,0);
		if(FAILED(hRes))Error.AddDirectX("SetTexture(7) failed: ",hRes);
	}

	DWORD dwShader=inRenderer.AskPixelShader(indwPass,!bTexturesThere);

	if(!bTexturesThere)
		if(indwPass==2)return(false);			// additional pass is not neccessary

	// pixel shader
	hRes=pDev->SetPixelShader(dwShader);
	if(FAILED(hRes))Error.AddDirectX("SetPixelShader failed: ",hRes);


	if(inRenderer.AskPolyBumpFallback())
	{
		pDev->SetRenderState(D3DRS_SPECULARENABLE, TRUE);

//   d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
//    d3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); 

//    d3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );

//		pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3 );
//		pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
//		pDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );
		pDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
		pDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_SPECULAR );
		pDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE );

		pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
		pDev->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
		pDev->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );

		pDev->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
		pDev->SetTextureStageState( 2, D3DTSS_COLORARG1, D3DTA_TFACTOR );
		pDev->SetTextureStageState( 2, D3DTSS_COLORARG2, D3DTA_TEXTURE );

		pDev->SetTextureStageState( 3, D3DTSS_COLOROP, D3DTOP_DISABLE );

		//    pDev->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 2 );
//		pDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
		pDev->SetRenderState(D3DRS_TEXTUREFACTOR,D3DXCOLOR(0.7f,0.0f,0.0f,0));		// fuck this is changed by light calculation
//		pDev->SetRenderState(D3DRS_TEXTUREFACTOR,);			// light direction

		// TODO: Polybump fallback
	}
	else if(dwShader!=0)							// a pixel shader is used
	{
		pDev->SetRenderState(D3DRS_SPECULARENABLE, FALSE);

		{
			// Base texture stage
			pDev->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
			pDev->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
			pDev->SetRenderState( D3DRS_WRAP0, 0 );

			// bump map texture stage
			pDev->SetTextureStageState(1, D3DTSS_ADDRESSU,	D3DTADDRESS_WRAP);
			pDev->SetTextureStageState(1, D3DTSS_ADDRESSV,	D3DTADDRESS_WRAP);
			pDev->SetRenderState( D3DRS_WRAP1, 0 );

			// Illumination texture
			pDev->SetTextureStageState(2, D3DTSS_ADDRESSU,	D3DTADDRESS_CLAMP);
			pDev->SetTextureStageState(2, D3DTSS_ADDRESSV,	D3DTADDRESS_CLAMP);	
			pDev->SetTextureStageState(2, D3DTSS_ADDRESSW,	D3DTADDRESS_CLAMP);
			pDev->SetRenderState( D3DRS_WRAP2, 0);

			pDev->SetTextureStageState(3, D3DTSS_ADDRESSU,	D3DTADDRESS_CLAMP);
			pDev->SetTextureStageState(3, D3DTSS_ADDRESSV,	D3DTADDRESS_CLAMP);	
			pDev->SetTextureStageState(3, D3DTSS_ADDRESSW,	D3DTADDRESS_CLAMP);	

			// Need wrap for the sphere model - no dup verts in the sphere
			pDev->SetRenderState( D3DRS_WRAP3, 0);
		}
	}
	else			// no pixel shader and polybump fallback is used
	{
		pDev->SetRenderState(D3DRS_SPECULARENABLE, inRenderer.AskSpecularEnable());

		if(inRenderer.AskFullbright())
		{
			pDev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);

			if(!inRenderer.AskTextured())
			{
				if(inRenderer.AskWireframe())
					hRes=pDev->SetTexture(0,inRenderer.m_ShaderManager.m_pWhiteTexture);
				 else
					hRes=pDev->SetTexture(0,inRenderer.m_ShaderManager.m_pDarkGreenTexture);

				if(FAILED(hRes))Error.AddDirectX("SetTexture(0) failed: ",hRes);
			}

			pDev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
		}
		else
		{
			if(inRenderer.AskTextured())
			{
				pDev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
				pDev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
			}
			else
			{
				pDev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG2);
			}
			pDev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
		}

		pDev->SetTextureStageState(0,D3DTSS_RESULTARG,D3DTA_CURRENT);
	}



	// vertex shader
	{
		hRes=pDev->SetVertexShader(inRenderer.AskVertexShader(indwPass,!bTexturesThere));
		if(FAILED(hRes))Error.AddDirectX("SetVertexShader failed: ",hRes);

		pDev->SetVertexShaderConstant(0, D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f), 1);			// c0 zero
		pDev->SetVertexShaderConstant(1, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f), 1);			// c1 one

		// c2,c3,c4,c5
		{
			D3DXMATRIX mat=inRenderer.GetWVPMatrix();
			hRes=pDev->SetVertexShaderConstant( 2, &mat, 4 );
			if(FAILED(hRes))Error.AddDirectX("SetVertexShaderConstant failed: ",hRes);
		}

		// c6,c7,c8,c9
		{
			D3DXMATRIX mat=inRenderer.GetWVMatrix();
			hRes=pDev->SetVertexShaderConstant( 6, &mat, 4 );
			if(FAILED(hRes))Error.AddDirectX("SetVertexShaderConstant failed: ",hRes);
		}

		// c13,c14,c15,c16
		{
			D3DXMATRIX mat=inRenderer.GetWMatrix();
			hRes=pDev->SetVertexShaderConstant( 13, &mat, 4 );
			if(FAILED(hRes))Error.AddDirectX("SetVertexShaderConstant failed: ",hRes);
		}

		pDev->SetVertexShaderConstant(18, D3DXVECTOR4(0.5f,0.5f,0.5f,0.5f), 1);				// c18 CV_HALF half
		pDev->SetVertexShaderConstant(23, D3DXVECTOR4(16.0f, 0.0f, 0.0f, 0.0f), 1);		// CV_MATERIALPROP .x=specular exponent
		pDev->SetVertexShaderConstant(24, inRenderer.GetEyePos(), 1);									// CV_EYE_POS_WORLD eye pos world
		pDev->SetVertexShaderConstant(27, inRenderer.GetEyeDir(), 1);									// CV_LIGHT_DIRECTION eye pos world
	}


	if(inRenderer.AskWireframe())
		pDev->SetVertexShaderConstant(25, D3DXVECTOR4(0,0,0,0), 1);										// c25 CV_DIFFLIGHTCOLOR
	 else
		pDev->SetVertexShaderConstant(25, D3DXVECTOR4(1,1,1,0), 1);										// c25 CV_DIFFLIGHTCOLOR

	// used for MeasureOverdraw
	if(inRenderer.AskDestBlendOneOne())
	{
		pDev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
		pDev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
		pDev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
	}

	pDev->SetRenderState(D3DRS_CULLMODE,inRenderer.AskCullMode());

	return(true);
}






// get attribute
const char *C3DMaterial::GetName( void )
{
	return(m_sName.c_str());
}



// add to attribute (only used during LoadObj())
void C3DMaterial::AddTriangleCount( const DWORD dwCount )
{
	m_TriangleCount+=dwCount;
}


// get attribute (only used during LoadObj())
DWORD C3DMaterial::GetTriangleCount( void )
{
	return(m_TriangleCount);
}


// set attribute
void C3DMaterial::SetAmbientColor( D3DXCOLOR inColor )
{
	m_Ka=inColor;
}

// set attribute
void C3DMaterial::SetDiffuseColor( D3DXCOLOR inColor )
{
	m_Kd=inColor;
}


// set attribute
void C3DMaterial::SetSpecularColor( D3DXCOLOR inColor )
{
	m_Ks=inColor;
}

// set attribute
void C3DMaterial::SetSubsurfaceColor( D3DXCOLOR inColor )
{
	m_Kss=inColor;
}


// render a triangle bunch
void C3DMaterial::RenderTriangleList( C3DRenderer &inRenderer, C3DTriangleBunch &inTriBunch, C3DScene &inScene,
																		  DWORD &inoutdwBackBufferLayers )
{
	assert(this);
	HRESULT hRes;

	IDirect3DDevice8 *pDev=inRenderer.GetDirectXDevice();				assert(pDev);

	DWORD dwNo=0;

	// ambient color
	if(inoutdwBackBufferLayers!=0)
	{
		pDev->SetPixelShaderConstant(1, D3DXVECTOR4(0,0,0,0.0f), 1);			// c1 no ambient
		pDev->SetVertexShaderConstant(28, D3DXVECTOR4(0,0,0,0.0f), 1);		// c28
	}
	else
	{
		D3DXCOLOR AmbientColor=inScene.GetAmbientColor();
		D3DXColorModulate(&AmbientColor,&AmbientColor,&m_Ka);
		pDev->SetPixelShaderConstant(1, D3DXVECTOR4(AmbientColor.r,AmbientColor.g,AmbientColor.b,0.0f), 1);			// c1 ambient
		pDev->SetVertexShaderConstant(28, D3DXVECTOR4(AmbientColor.r,AmbientColor.g,AmbientColor.b,0.0f), 1);		// c28
	}


	// for every lightsource
	while(C3DLight *pLight=inScene.GetLightNo(dwNo++))
	{
/*		{
			char str[80];

			sprintf(str,"\nRenderLight %d\n",dwNo);
			OutputDebugString(str);
		}
*/
		D3DXCOLOR LightColor=pLight->GetColor();

		// set first light, add additional lights
		if(inoutdwBackBufferLayers>0)
		{
			if(LightColor==D3DXCOLOR(0,0,0,0))continue;				// don't use black lights

			if(!inRenderer.AskEachLightOnePass())break;
		}

		assert(pLight);
		D3DXVECTOR3 vDir=-pLight->GetDirection();

		pDev->SetVertexShaderConstant(21, D3DXVECTOR4(vDir.x,vDir.y,vDir.z, 1.0f), 1);								// light direction

		vDir=pLight->GetFrom();
		pDev->SetVertexShaderConstant(22, D3DXVECTOR4(vDir.x,vDir.y,vDir.z, 1.0f), 1);								// light position

		// light color
		D3DXCOLOR diffLightColor,specLightColor,subsLightColor;
		D3DXColorModulate(&diffLightColor,&LightColor,&m_Kd);
		D3DXColorModulate(&subsLightColor,&LightColor,&m_Kss);

		if(inRenderer.AskSpecularEnable())
			D3DXColorModulate(&specLightColor,&LightColor,&m_Ks);
		 else
			specLightColor=D3DXCOLOR(0,0,0,0);

		// set material*light color
		pDev->SetRenderState(D3DRS_TEXTUREFACTOR,diffLightColor);
		pDev->SetPixelShaderConstant(2, D3DXVECTOR4(diffLightColor.r,diffLightColor.g,diffLightColor.b,0.0f), 1);	
		pDev->SetPixelShaderConstant(3, D3DXVECTOR4(specLightColor.r,specLightColor.g,specLightColor.b,0.0f), 1);	
		pDev->SetVertexShaderConstant(25, D3DXVECTOR4(diffLightColor.r,diffLightColor.g,diffLightColor.b,0.0f), 1);		
		pDev->SetVertexShaderConstant(26, D3DXVECTOR4(specLightColor.r,specLightColor.g,specLightColor.b,0.0f), 1);

		// light direction
		hRes=pDev->SetPixelShaderConstant(0, D3DXVECTOR4(vDir.x,vDir.y,vDir.z,0.0f), 1);	
		if(FAILED(hRes))Error.AddDirectX("SetPixelShaderConstant failed: ",hRes);

		//  fake subsurface scattering test
		pDev->SetVertexShaderConstant(29, D3DXVECTOR4(subsLightColor.r,subsLightColor.g,subsLightColor.b,0.0f), 1);		// c29 fake subsurface scattering test

		if(inoutdwBackBufferLayers==1)
		{
			if(inRenderer.AskReadZBuffer())
				pDev->SetRenderState(D3DRS_ZFUNC,D3DCMP_LESSEQUAL);
			 else
				pDev->SetRenderState(D3DRS_ZFUNC,D3DCMP_ALWAYS);

			pDev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
			pDev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
			pDev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
			pDev->SetVertexShaderConstant(28, D3DXVECTOR4(0,0,0,0.0f), 1);		// c28 no ambient color in further passes
			pDev->SetPixelShaderConstant(1, D3DXVECTOR4(0,0,0,0.0f), 1);			// c1 no ambient color in further passes
		}
		else
		{
			if(inRenderer.AskReadZBuffer())
				pDev->SetRenderState(D3DRS_ZFUNC,D3DCMP_LESSEQUAL);
			 else
				pDev->SetRenderState(D3DRS_ZFUNC,D3DCMP_ALWAYS);
		}

//	D3DPRIMITIVETYPE Type, UINT MinIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount
		hRes=pDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,inTriBunch.m_minlocalVertex,inTriBunch.m_maxlocalVertex-inTriBunch.m_minlocalVertex,
																					inTriBunch.m_localIndex,inTriBunch.m_PrimitiveCount);

/*
		Message.Add("DrawIndexedPrimitive (%d %d=%d-%d %d %d)", inTriBunch.m_minlocalVertex,
																											inTriBunch.m_maxlocalVertex-inTriBunch.m_minlocalVertex,
																											inTriBunch.m_maxlocalVertex,inTriBunch.m_minlocalVertex,
																											inTriBunch.m_localIndex,
																											inTriBunch.m_PrimitiveCount);
*/
		if(FAILED(hRes))
		{
			Error.Add("DrawIndexedPrimitive (%d %d %d %d)", inTriBunch.m_minlocalVertex,
																											inTriBunch.m_maxlocalVertex-inTriBunch.m_minlocalVertex,
																											inTriBunch.m_localIndex,
																											inTriBunch.m_PrimitiveCount);
			Error.AddDirectX("DrawIndexedPrimitive failed: ",hRes);
		}

/*
		{
			char str[80];

			sprintf(str,"(%d %d %d %d) ",inTriBunch.m_minlocalVertex,
																											inTriBunch.m_maxlocalVertex-inTriBunch.m_minlocalVertex,
																											inTriBunch.m_localIndex,
																											inTriBunch.m_PrimitiveCount);
			OutputDebugString(str);
		}
*/
		inoutdwBackBufferLayers++;

	}	// for every lightsource
}






CPBCloneMapDest &C3DMaterial::GetCloneMapRef( void )
{
	return(m_PolybumpClonemap);
}
