Beispiel #1
0
// Add the object to its appropriate queue to be rendered later.
static void d3d_ReallyProcessObject(LTObject *pObject)
{

	// Is this object visible?
	if (g_ObjectHandlers[pObject->m_ObjectType].m_bCheckWorldVisibility &&
		g_have_world && 
		g_Device.m_pRenderWorld && 
		((pObject->m_Flags & FLAG_REALLYCLOSE) == 0))
	{
		IncFrameStat(eFS_ObjectsCullTested, 1);

		LTVector vDims = g_ObjectHandlers[pObject->m_ObjectType].m_GetDims(pObject);
		if (!g_Device.m_pRenderWorld->IsAABBVisible(g_ViewParams,	pObject->m_Pos - vDims, 
																	pObject->m_Pos + vDims, 
																	CObjectGroupMgr::ShouldOccludeObjectGroup(pObject->m_nRenderGroup)))
		{
			IncFrameStat(eFS_ObjectsCulled, 1);
			return;
		}
	}

	// Process this object.
	ASSERT(pObject->m_ObjectType >= 0 && pObject->m_ObjectType < NUM_OBJECTTYPES);
	g_ObjectHandlers[pObject->m_ObjectType].m_ProcessObjectFn(pObject);

	// Process attachments.
	if(pObject->m_Attachments)
	{
		d3d_ProcessAttachments(pObject, 0);
	}
}
// THIS Function should be removed when we go to the full render object implementation - it's
//	temporary on the path to full render objects. The D3D pipe render model path call this guy to do
//	the transform and lighting stuff.
void CD3DSkelMesh::Render(ModelInstance *pInstance, D3DMATRIX* pD3DTransforms, CD3DRenderStyle* pRenderStyle, uint32 iRenderPass)
{
	switch (m_eRenderMethod)
	{
		case eD3DRenderDirect :
		{	// We need to do the bone walk, but we can render direct (they've been pre-processed into triangle group/bone group order)...
			uint32 iCurrentPolyIndex = 0;
			int32 nNumActiveBones = -1;
			for( int32 iBoneSet = 0; (iBoneSet < (int32)m_iBoneSetCount) ; ++iBoneSet )
			{
				BoneSetListItem* pBoneSet = &m_pBoneSetArray[iBoneSet];
				nNumActiveBones = SetTransformsToBoneSet(pBoneSet,pD3DTransforms, nNumActiveBones);

				// Set the vertex shader constants.
				if (m_pVertexShader != NULL)
				{
					// Let the client set some constants.
					if (NULL != i_client_shell)
					{
						i_client_shell->OnVertexShaderSetConstants(m_pVertexShader, iRenderPass, pRenderStyle, pInstance,
																   LTShaderDeviceStateImp::GetSingleton());
					}

					// Send the constants to the video card.
					LTVertexShaderMgr::GetSingleton().SetVertexShaderConstants(m_pVertexShader);
				}

				// Set the pixel shader constants.
				if (m_pPixelShader != NULL)
				{
					// Let the client set some constants.
					if (NULL != i_client_shell)
					{
						i_client_shell->OnPixelShaderSetConstants(m_pPixelShader, iRenderPass, pRenderStyle, pInstance,
																  LTShaderDeviceStateImp::GetSingleton());
					}

					// Send the constants to the video card.
					LTPixelShaderMgr::GetSingleton().SetPixelShaderConstants(m_pPixelShader);
				}

				RSD3DOptions rsD3DOptions;
				pRenderStyle->GetDirect3D_Options(&rsD3DOptions);
				if(rsD3DOptions.bUseEffectShader)
				{
					LTEffectImpl* _pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(rsD3DOptions.EffectShaderID);
					ID3DXEffect* pEffect = _pEffect->GetEffect();
				
					if(pEffect)
					{
						i_client_shell->OnEffectShaderSetParams((LTEffectShader*)_pEffect, pRenderStyle, pInstance, LTShaderDeviceStateImp::GetSingleton());
						pEffect->SetInt("BoneCount", nNumActiveBones);
						pEffect->CommitChanges();
					}
				
				}

				m_VBController.Render(	pBoneSet->iFirstVertIndex,
										iCurrentPolyIndex,
										pBoneSet->iVertCount,
										(pBoneSet->iIndexIntoIndexBuff - iCurrentPolyIndex)/3);



				iCurrentPolyIndex = pBoneSet->iIndexIntoIndexBuff;

				IncFrameStat(eFS_ModelRender_NumSkeletalRenderObjects, 1);
			}

			break;
		}
		case eD3DRenderMatrixPalettes :
		{
			uint32 nNumActiveBones = SetMatrixPalette(m_iMinBone,m_iMaxBone,pD3DTransforms);

			// Set the vertex shader constants.
			if (m_pVertexShader != NULL)
			{
				// Let the client set some constants.
				if (NULL != i_client_shell)
				{
					i_client_shell->OnVertexShaderSetConstants(m_pVertexShader, iRenderPass, pRenderStyle, pInstance,
															   LTShaderDeviceStateImp::GetSingleton());
				}

				// Send the constants to the video card.
				LTVertexShaderMgr::GetSingleton().SetVertexShaderConstants(m_pVertexShader);
			}

			// Set the pixel shader constants.
			if (m_pPixelShader != NULL)
			{
				// Let the client set some constants.
				if (NULL != i_client_shell)
				{
					i_client_shell->OnPixelShaderSetConstants(m_pPixelShader, iRenderPass, pRenderStyle, pInstance,
															  LTShaderDeviceStateImp::GetSingleton());
				}

				// Send the constants to the video card.
				LTPixelShaderMgr::GetSingleton().SetPixelShaderConstants(m_pPixelShader);
			}

			RSD3DOptions rsD3DOptions;
			pRenderStyle->GetDirect3D_Options(&rsD3DOptions);
			if(rsD3DOptions.bUseEffectShader)
			{
				LTEffectImpl* _pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(rsD3DOptions.EffectShaderID);
				ID3DXEffect* pEffect = _pEffect->GetEffect();

				if(pEffect)
				{
					i_client_shell->OnEffectShaderSetParams((LTEffectShader*)_pEffect, pRenderStyle, pInstance, LTShaderDeviceStateImp::GetSingleton());
					pEffect->SetInt("BoneCount", nNumActiveBones);
					pEffect->CommitChanges();
				}

			}

			m_VBController.Render(0,0,m_iVertCount,m_iPolyCount);

			break;
		}
	}
}
Beispiel #3
0
void d3d_DrawSprite(const ViewParams& Params, LTObject *pObj)
{
	SpriteEntry	*pSe;
	SpriteAnim *pAnim;
	SpriteInstance *pInstance;
	uint32 srcBlend, destBlend, dwFog, dwFogColor;
	
	pInstance = (SpriteInstance*)pObj;
	pSe = pInstance->m_SpriteTracker.m_pCurFrame;
	pAnim = pInstance->m_SpriteTracker.m_pCurAnim;

	//update the number of triangles
	IncFrameStat(eFS_SpriteTriangles, 2);

	if(pAnim && pSe && pSe->m_pTex)
	{
		// Set the correct blend states.
		d3d_GetBlendStates(pInstance, srcBlend, destBlend, dwFog, dwFogColor);
		StateSet ssSrcBlend(D3DRS_SRCBLEND, srcBlend);
		StateSet ssDestBlend(D3DRS_DESTBLEND, destBlend);
		StateSet ssFog(D3DRS_FOGENABLE, dwFog);
		StateSet ssFogColor(D3DRS_FOGCOLOR, dwFogColor);

		//disable backface culling
		StateSet ssCullMode(D3DRS_CULLMODE, D3DCULL_NONE);

		//clamp the texture coordinates so that we don't have to worry about wrap around
		SamplerStateSet ssWrapModeU0(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
		SamplerStateSet ssWrapModeV0(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);

		CSpriteMultiplySS ssMultiply;

		if((pInstance->m_Flags2 & FLAG2_MULTIPLY) && !(pInstance->m_Flags2 & FLAG2_ADDITIVE))
			ssMultiply.SetStates();

		//handle reallyclose
		CReallyCloseData RCData;
		if(pInstance->m_Flags & FLAG_REALLYCLOSE)
		{
			d3d_SetReallyClose(&RCData);
		}

		if(pInstance->m_Flags & FLAG_ROTATABLESPRITE)
		{
			d3d_DrawRotatableSprite(Params, pInstance, pSe->m_pTex);
		}
		else
		{
			d3d_DrawSprite(Params, pInstance, pSe->m_pTex);
		}

		//free really close
		if(pInstance->m_Flags & FLAG_REALLYCLOSE)
		{
			d3d_UnsetReallyClose(&RCData);
		}

		if((pInstance->m_Flags2 & FLAG2_MULTIPLY) && !(pInstance->m_Flags2 & FLAG2_ADDITIVE))
			ssMultiply.UnsetStates();

	}
}
Beispiel #4
0
void d3d_DrawPolyGrid(const ViewParams &Params, LTObject *pObj)
{
	//the global pixel shader to be used for the water bumpmapping and a flag indicating if
	//creation failed
	bool				s_bPixelShaderFailed = false;

	//make sure that the polygrid is valid
	assert(pObj);

	//get our polygrid
    LTPolyGrid *pGrid = (LTPolyGrid*)pObj;

	// Make sure it's initialized.
	if(!pGrid->m_Data)
		return;

	//must have an index buffer
	if(!pGrid->m_Indices || (pGrid->m_nIndices == 0))
		return;

	//and of course, make sure that the size is reasonable
	if((pGrid->m_Width < 2) || (pGrid->m_Height < 2))
		return;

	IncFrameStat(eFS_PolyGridTriangles, pGrid->m_nTris);

	//cache the half dimensions
	float fHalfGridWidth  = ((float)pGrid->m_Width - 1) * 0.5f;
	float fHalfGridHeight = ((float)pGrid->m_Height - 1) * 0.5f;

	//now we need to build our color lookup table for this polygrid, this is faster for any
	//polygrid that is larger than 8x8, and even then we can get a nice tight loop that
	//should still be rather optimal

	// Set the blending mode based on the flags.
	uint32 nSrcBlend, nDestBlend, nFog, nFogColor;
	d3d_GetBlendStates(pGrid, nSrcBlend, nDestBlend, nFog, nFogColor);
	StateSet ssSrcBlend(D3DRS_SRCBLEND, nSrcBlend);
	StateSet ssDestBlend(D3DRS_DESTBLEND, nDestBlend);
	StateSet ssFog(D3DRS_FOGENABLE, nFog);
	StateSet ssFogColor(D3DRS_FOGCOLOR, nFogColor);

	//flag indicating whether or not
	bool bEnvMap		= false;
	bool bCubicEnvMap	= false;
	bool bBumpMap		= false;

	//vertex information
	uint32 nVertexSize  = sizeof(CPolyGridVertex);
	uint32 nVertexFVF	= POLYGRIDVERTEX_FORMAT;

	//UV scales to adjust the texture by (defaults to 1, but if we are bump mapping, this will
	//be set to the detail texture scale)
	float	fPGUScale	= 1.0f;
	float	fPGVScale	= 1.0f;

	// Set the texture if necessary.
	SpriteTracker* pTracker;

	LTPixelShader *pPixelShader = NULL;

	if(pGrid->m_pSprite)
	{
		pTracker = &pGrid->m_SpriteTracker;
		if(pTracker->m_pCurFrame)
		{
			SharedTexture* pTex = pTracker->m_pCurFrame->m_pTex;
			if(pTex)
			{
				//get the type of this texture
				ESharedTexType eTexType = pTex->m_eTexType;

				//the base texture
				SharedTexture* pBaseTex		= NULL;
				//the environment map
				SharedTexture* pEnvMapTex	= pGrid->m_pEnvMap;
				//the bumpmap
				SharedTexture* pBumpMapTex	= NULL;

				//determine our texture data
				if(pGrid->m_nPGFlags & PG_NORMALMAPSPRITE)
				{
					//only use a bump map texture if we actually have an environment map
					if(pEnvMapTex)
						pBumpMapTex	= pTex;
				}
				else
				{
					//we have a normal texture
					pBaseTex	= pTex;
				}

				// Set up the environment mapping texture if applicable
				if(	pEnvMapTex && g_CV_EnvMapPolyGrids.m_Val)
				{
					//see if the is a cubic environment map
					RTexture *pRenderTexture = (RTexture*)pEnvMapTex->m_pRenderData;
					if(pRenderTexture && pRenderTexture->IsCubeMap())
					{
						bCubicEnvMap = true;
					}

					bEnvMap = true;
				}

				if(	pBumpMapTex && g_CV_BumpMapPolyGrids.m_Val)
				{
					//we now need to make sure that the bump map shader is valid

					//see if we need to load it
					if (!s_bPixelShaderFailed)
					{
						// Get the pixel shader.
						pPixelShader = LTPixelShaderMgr::GetSingleton().GetPixelShader(LTPixelShader::PIXELSHADER_ENVBUMPMAP);
						if (NULL == pPixelShader)
						{
							FileRef ref;
							ref.m_FileType 	= FILE_ANYFILE;
							ref.m_pFilename = "ps\\envbumpmap.psh";

							// Try to load it.
							ILTStream *pStream = g_pIClientFileMgr->OpenFile(&ref);
							if (NULL != pStream)
							{
								if (LTPixelShaderMgr::GetSingleton().AddPixelShader(pStream, ref.m_pFilename,
																					LTPixelShader::PIXELSHADER_ENVBUMPMAP, true))
								{
									pPixelShader = LTPixelShaderMgr::GetSingleton().GetPixelShader(LTPixelShader::PIXELSHADER_ENVBUMPMAP);
								}

								// Close the file.
								pStream->Release();
							}
						}
					}

					// See if we can continue.
					if (NULL != pPixelShader && pPixelShader->IsValidShader())
					{
						bBumpMap	= true;
						nVertexSize = sizeof(CPolyGridBumpVertex);
						nVertexFVF	= POLYGRIDBUMPVERTEX_FORMAT;
						fPGUScale	= ((RTexture*)pBumpMapTex->m_pRenderData)->m_DetailTextureScale;
						fPGVScale	= fPGUScale;
					}
					else
					{
						//we failed to create the shader, the device can't support it
						s_bPixelShaderFailed = true;
					}
				}

				//setup the textures based upon the configuration
				if(bBumpMap)
				{
					d3d_SetTexture(pBumpMapTex, 0, eFS_PolyGridBumpMapTexMemory);
					d3d_SetTexture(pEnvMapTex, 3, eFS_PolyGridEnvMapTexMemory);
				}
				else
				{
					LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID);
					if(pEffect)
					{
						ID3DXEffect* pD3DEffect = pEffect->GetEffect();
						if(pD3DEffect)
						{
							nVertexSize = sizeof(CPolyGridEffectVertex); 

							RTexture* pRTexture = (RTexture*)pBaseTex->m_pRenderData;
							pD3DEffect->SetTexture("texture0", pRTexture->m_pD3DTexture);

							if(bEnvMap)
							{
								pRTexture = (RTexture*)pEnvMapTex->m_pRenderData;
								pD3DEffect->SetTexture("texture1", pRTexture->m_pD3DTexture);
							}

						}
					}else
					{
						d3d_SetTexture(pBaseTex, 0, eFS_PolyGridBaseTexMemory);

						if(bEnvMap)
						{
							d3d_SetTexture(pEnvMapTex, 1, eFS_PolyGridEnvMapTexMemory);
						}
					}
				}
			}
			else
			{
				//if we didn't set any texture, we need to make sure and clear out the texture
				//channel
				d3d_DisableTexture(0);
			}
		}
	}

	//specify that we were visible
	pGrid->m_Flags |= FLAG_INTERNAL1;

	// Build the vertex list.
	uint32 nBufferSize = pGrid->m_Width * pGrid->m_Height * nVertexSize;
	if(nBufferSize > g_TriVertListSize)
	{
		//we need to reallocate our list of vertices
		dfree(g_TriVertList);
		LT_MEM_TRACK_ALLOC(g_TriVertList = dalloc(nBufferSize),LT_MEM_TYPE_RENDERER);

		//check the allocation
		if(!g_TriVertList)
		{
			g_TriVertListSize = 0;
			return;
		}

		g_TriVertListSize = nBufferSize;
	}

	//determine if this polygrid should be lit or not
	bool bFresnel = (pGrid->m_nPGFlags & PG_FRESNEL) && (g_CV_FresnelPolyGrids.m_Val) ? true : false;

	//determine what alpha value we should use
	uint8 nColorAlpha = 0;
	if(!bEnvMap)
		nColorAlpha = 255;
	else if(!bFresnel)
		nColorAlpha = 128;

	float fScaledR = pGrid->m_ColorR * MATH_ONE_OVER_255;
	float fScaledG = pGrid->m_ColorG * MATH_ONE_OVER_255;
	float fScaledB = pGrid->m_ColorB * MATH_ONE_OVER_255;

	uint32 nColorTable[256];
	for(uint32 nCurrColor = 0; nCurrColor < 256; nCurrColor++)
	{
		//Note that the color table is 0..255, object color is 0..255 as well
		nColorTable[nCurrColor] = D3DRGBA_255(	pGrid->m_ColorTable[nCurrColor].x * fScaledR,
												pGrid->m_ColorTable[nCurrColor].y * fScaledG,
												pGrid->m_ColorTable[nCurrColor].z * fScaledB,
												nColorAlpha);
	}

	//setup our world matrix to represent a space that holds the orientation of the polygrid
	//as well as the center position. This allows all operations to take place
	//as if performed on the XZ plane (note that we don't do the scale as that tends
	//to mess up normals)
	LTMatrix mWorldTrans;
	LTVector vUnitScale(1.0f, 1.0f, 1.0f);
	d3d_SetupTransformation(&pGrid->GetPos(), (float*)&pGrid->m_Rotation, &vUnitScale, &mWorldTrans);
	d3d_SetD3DMat(D3DTS_WORLD, &mWorldTrans);

	//calculate our position increments
	float fXInc			= pGrid->GetDims().x * 2.0f / (pGrid->m_Width - 1);
	float fZInc			= pGrid->GetDims().z * 2.0f / (pGrid->m_Height - 1);
	float fYScale		= pGrid->GetDims().y / 127.0f;

	float fXStart		= -fHalfGridWidth * fXInc;
	float fCurrX		= fXStart;
	float fCurrZ		= -fHalfGridHeight * fZInc;


	int8* pDataPos		= (int8*)pGrid->m_Data;
	int8* pDataEnd		= pDataPos + pGrid->m_Width * pGrid->m_Height;
	int8* pLineDataEnd	= pDataPos + pGrid->m_Width;

	uint32* pColor		= nColorTable + 128;

	float fXScale		= pGrid->m_xScale / ((pGrid->m_Width - 1) * fXInc);
	float fZScale		= pGrid->m_yScale / ((pGrid->m_Height - 1) * fZInc);

	float fStartU		= (float)fmod(pGrid->m_xPan * fPGUScale, 1.0f);
	float fStartV		= (float)fmod(pGrid->m_yPan * fPGVScale, 1.0f);

	float fCurrU		= fStartU;
	float fCurrV		= fStartV;

	float fUInc			= fXInc * fXScale * fPGUScale;
	float fVInc			= fZInc * fZScale * fPGVScale;

	int32 nWidth		= pGrid->m_Width;
	float fSpacingX		= fXInc * 2.0f;
	float fSpacingZ		= fZInc * 2.0f;

	uint32 nNumVerts;

	bool bEffect = false;
	LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID);
	if(pEffect)
	{
		ID3DXEffect* pD3DEffect = pEffect->GetEffect();
		if(pD3DEffect)
		{
			bEffect = true;
		}
	}

	if(bBumpMap)
	{
		CPolyGridBumpVertex* pVertexPos = (CPolyGridBumpVertex*)g_TriVertList;

		if(pGrid->m_pValidMask)
		{
			//this polygrid has a valid mask, meaning that we need to skip over vertices
			//as needed
			uint32* pCurrMask = pGrid->m_pValidMask;

			//amount to adjust the mask at the end of a line
			uint32 nMaskLineAdjust = (pGrid->m_Width % 32) ? 1 : 0;

			uint32 nShift;
			uint32 nNormalY1 = 0;
			uint32 nNormalY2 = nWidth;

			float fWidthTimesHeight = fSpacingX * fSpacingZ;

			while(pDataPos < pDataEnd)
			{
				nShift = 0x1;

				while(pDataPos < pLineDataEnd)
				{
					if(*pCurrMask & nShift)
					{
						//this is valid, add this vertex
						d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV);

						//generate a normal for it
						GenerateBasisSpace(pDataPos, pVertexPos, -1, 1, nNormalY1, nNormalY2, fSpacingX, fSpacingZ, fWidthTimesHeight, fYScale);

						//move along to the next vertex
						pVertexPos++;
					}

					pDataPos++;
					fCurrX += fXInc;
					fCurrU += fUInc;

					if(nShift == 0x80000000)
					{
						pCurrMask++;
						nShift = 1;
					}
					else
					{
						nShift <<= 1;
					}
				}

				//reset the line
				fCurrX = fXStart;

				//update our threshold for when to move onto the next line
				pLineDataEnd += pGrid->m_Width;
				pCurrMask += nMaskLineAdjust;

				//update our position
				fCurrZ += fZInc;
				fCurrU  = fStartU;
				fCurrV += fVInc;

				//update the normal offsets to ensure we don't go outside of our buffer
				nNormalY1 = -nWidth;
				if(pLineDataEnd >= pDataEnd)
					nNormalY2 = 0;
			}

			nNumVerts = pVertexPos - (CPolyGridBumpVertex*)g_TriVertList;
		}
		else
		{
			nNumVerts = pGrid->m_Width * pGrid->m_Height;

			while(pDataPos < pDataEnd)
			{
				while(pDataPos < pLineDataEnd)
				{
					d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV);

					pDataPos++;
					pVertexPos++;
					fCurrX += fXInc;
					fCurrU += fUInc;
				}

				//reset the line
				fCurrX = fXStart;

				//update our threshold for when to move onto the next line
				pLineDataEnd += pGrid->m_Width;

				//update our position
				fCurrZ += fZInc;
				fCurrU  = fStartU;
				fCurrV += fVInc;
			}

			//now we need to generate the normals for the polygrid
			GeneratePolyGridVectors(pGrid, (CPolyGridBumpVertex*)g_TriVertList, GenerateBasisSpace);
		}
	}
	else if(bEffect)
	{
		CPolyGridEffectVertex* pVertexPos = (CPolyGridEffectVertex*)g_TriVertList;

		if(pGrid->m_pValidMask)
		{
			//this polygrid has a valid mask, meaning that we need to skip over vertices
			//as needed
			uint32* pCurrMask = pGrid->m_pValidMask;

			//amount to adjust the mask at the end of a line
			uint32 nMaskLineAdjust = (pGrid->m_Width % 32) ? 1 : 0;

			uint32 nShift;
			uint32 nNormalY1 = 0;
			uint32 nNormalY2 = nWidth;

			float fWidthTimesHeight = fSpacingX * fSpacingZ;

			while(pDataPos < pDataEnd)
			{
				nShift = 0x1;

				while(pDataPos < pLineDataEnd)
				{
					if(*pCurrMask & nShift)
					{
						//this is valid, add this vertex
						d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV);

						//generate a normal for it
						GenerateEffectBasisSpace(pDataPos, pVertexPos, -1, 1, nNormalY1, nNormalY2, fSpacingX, fSpacingZ, fWidthTimesHeight, fYScale);

						//move along to the next vertex
						pVertexPos++;
					}

					pDataPos++;
					fCurrX += fXInc;
					fCurrU += fUInc;

					if(nShift == 0x80000000)
					{
						pCurrMask++;
						nShift = 1;
					}
					else
					{
						nShift <<= 1;
					}
				}

				//reset the line
				fCurrX = fXStart;

				//update our threshold for when to move onto the next line
				pLineDataEnd += pGrid->m_Width;
				pCurrMask += nMaskLineAdjust;

				//update our position
				fCurrZ += fZInc;
				fCurrU  = fStartU;
				fCurrV += fVInc;

				//update the normal offsets to ensure we don't go outside of our buffer
				nNormalY1 = -nWidth;
				if(pLineDataEnd >= pDataEnd)
					nNormalY2 = 0;
			}

			nNumVerts = pVertexPos - (CPolyGridEffectVertex*)g_TriVertList;
		}
		else
		{
			nNumVerts = pGrid->m_Width * pGrid->m_Height;

			while(pDataPos < pDataEnd)
			{
				while(pDataPos < pLineDataEnd)
				{
					d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV);

					pDataPos++;
					pVertexPos++;
					fCurrX += fXInc;
					fCurrU += fUInc;
				}

				//reset the line
				fCurrX = fXStart;

				//update our threshold for when to move onto the next line
				pLineDataEnd += pGrid->m_Width;

				//update our position
				fCurrZ += fZInc;
				fCurrU  = fStartU;
				fCurrV += fVInc;
			}

			//now we need to generate the normals for the polygrid
			LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID);
			if(pEffect)
			{
				ID3DXEffect* pD3DEffect = pEffect->GetEffect();
				if(pD3DEffect)
				{
					GeneratePolyGridVectors(pGrid, (CPolyGridEffectVertex*)g_TriVertList, GenerateEffectBasisSpace);
				}
			}
			else
			{
				GeneratePolyGridVectors(pGrid, (CPolyGridVertex*)g_TriVertList, GenerateNormal);
			}
		}
	}
	else //fixed function
	{
		CPolyGridVertex* pVertexPos = (CPolyGridVertex*)g_TriVertList;

		if(pGrid->m_pValidMask)
		{
			//this polygrid has a valid mask, meaning that we need to skip over vertices
			//as needed
			uint32* pCurrMask = pGrid->m_pValidMask;

			//amount to adjust the mask at the end of a line
			uint32 nMaskLineAdjust = (pGrid->m_Width % 32) ? 1 : 0;

			uint32 nShift;
			uint32 nNormalY1 = 0;
			uint32 nNormalY2 = nWidth;

			float fWidthTimesHeight = fSpacingX * fSpacingZ;

			while(pDataPos < pDataEnd)
			{
				nShift = 0x1;

				while(pDataPos < pLineDataEnd)
				{
					if(*pCurrMask & nShift)
					{
						//this is valid, add this vertex
						d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV);

						//generate a normal for it
						GenerateNormal(pDataPos, pVertexPos, -1, 1, nNormalY1, nNormalY2, fSpacingX, fSpacingZ, fWidthTimesHeight, fYScale);

						//move along to the next vertex
						pVertexPos++;
					}

					pDataPos++;
					fCurrX += fXInc;
					fCurrU += fUInc;

					if(nShift == 0x80000000)
					{
						pCurrMask++;
						nShift = 1;
					}
					else
					{
						nShift <<= 1;
					}
				}

				//reset the line
				fCurrX = fXStart;

				//update our threshold for when to move onto the next line
				pLineDataEnd += pGrid->m_Width;
				pCurrMask += nMaskLineAdjust;

				//update our position
				fCurrZ += fZInc;
				fCurrU  = fStartU;
				fCurrV += fVInc;

				//update the normal offsets to ensure we don't go outside of our buffer
				nNormalY1 = -nWidth;
				if(pLineDataEnd >= pDataEnd)
					nNormalY2 = 0;
			}

			nNumVerts = pVertexPos - (CPolyGridVertex*)g_TriVertList;
		}
		else
		{
			nNumVerts = pGrid->m_Width * pGrid->m_Height;

			while(pDataPos < pDataEnd)
			{
				while(pDataPos < pLineDataEnd)
				{
					d3d_SetupVertexPos(pVertexPos, fCurrX, *pDataPos * fYScale, fCurrZ, pColor[*pDataPos], fCurrU, fCurrV);

					pDataPos++;
					pVertexPos++;
					fCurrX += fXInc;
					fCurrU += fUInc;
				}

				//reset the line
				fCurrX = fXStart;

				//update our threshold for when to move onto the next line
				pLineDataEnd += pGrid->m_Width;

				//update our position
				fCurrZ += fZInc;
				fCurrU  = fStartU;
				fCurrV += fVInc;
			}

			//now we need to generate the normals for the polygrid
			LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID);
			if(pEffect)
			{
				ID3DXEffect* pD3DEffect = pEffect->GetEffect();
				if(pD3DEffect)
				{
					GeneratePolyGridVectors(pGrid, (CPolyGridEffectVertex*)g_TriVertList, GenerateEffectBasisSpace);
				}
			}
			else
			{
				GeneratePolyGridVectors(pGrid, (CPolyGridVertex*)g_TriVertList, GenerateNormal);
			}
		}
	}

	// Set environment map texture coordinates.
	if(bEnvMap && !bBumpMap)
	{
		d3d_SetEnvMapTextureStates(Params, pTracker->m_pCurFrame->m_pTex->m_eTexType, pGrid, bCubicEnvMap);
	}

	//see if we are just doing a base texture
	if(!bEnvMap && !bBumpMap)
	{
		d3d_SetDefaultBlendStates();
	}

	//generate the alpha if we can use it
	if(bBumpMap)
	{
		GeneratePolyGridFresnelAlphaAndCamera(Params.m_Pos, (CPolyGridBumpVertex*)g_TriVertList, pGrid, nNumVerts);
	}
	else if(bFresnel)
	{
		GeneratePolyGridFresnelAlpha(Params.m_Pos, (CPolyGridVertex*)g_TriVertList, pGrid, nNumVerts);
	}

	//make the backfacing polygons cull
	StateSet ssCullMode(D3DRS_CULLMODE, (pGrid->m_nPGFlags & PG_NOBACKFACECULL) ? D3DCULL_NONE : D3DCULL_CCW);

	//setup the pixel shader if we are bumpmapping
	if(bBumpMap)
	{
		assert(NULL != pPixelShader && pPixelShader->IsValidShader());

		// Set the pixel shader constants.
		float *pConstants = pPixelShader->GetConstants();
		pConstants[0] = 0.0f;
		pConstants[1] = 0.0f;
		pConstants[2] = 0.0f;
		pConstants[3] = pGrid->m_ColorA / 255.0f;
		LTPixelShaderMgr::GetSingleton().SetPixelShaderConstants(pPixelShader);

		// Install the pixel shader.
		LTPixelShaderMgr::GetSingleton().InstallPixelShader(pPixelShader);

		//now actually draw the polygrid
		D3D_CALL(PD3DDEVICE->SetVertexShader(NULL));
		D3D_CALL(PD3DDEVICE->SetFVF(nVertexFVF));
		
		int nNumPolies = (pGrid->m_nIndices/3);

		// Is this polygrid larger than our buffer? If so, break it into smaller patches.
		if(nNumPolies > g_CV_PolyGridBufferSize)
		{
			int32 nRemainingPolies = nNumPolies;
			uint32 nCurrentVertPosition = 0;

			while(nRemainingPolies > 0)
			{
				uint32 nPoliesThisFrame = (nRemainingPolies > g_CV_PolyGridBufferSize) ? g_CV_PolyGridBufferSize: nRemainingPolies;
				D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,nPoliesThisFrame,&pGrid->m_Indices[nCurrentVertPosition],D3DFMT_INDEX16,g_TriVertList, nVertexSize));
				nCurrentVertPosition += nPoliesThisFrame*3;
				nRemainingPolies -= nPoliesThisFrame;
			}
		}
		else
		{
			D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,(pGrid->m_nIndices)/3,pGrid->m_Indices,D3DFMT_INDEX16,g_TriVertList, nVertexSize));
		}

		// Uninstall the pixel shader.
		LTPixelShaderMgr::GetSingleton().UninstallPixelShader();

		d3d_DisableTexture(0);
		d3d_DisableTexture(3);
	}
	else
	{
		//now actually draw the polygrid
		D3D_CALL(PD3DDEVICE->SetVertexShader(NULL));
		D3D_CALL(PD3DDEVICE->SetFVF(nVertexFVF));

		int nNumPolies = (pGrid->m_nIndices/3);

		// Is this polygrid larger than our buffer? If so, break it into smaller patches.
		if(nNumPolies > g_CV_PolyGridBufferSize)
		{
			int32 nRemainingPolies = nNumPolies;
			uint32 nCurrentVertPosition = 0;

			while(nRemainingPolies > 0)
			{
				uint32 nPoliesThisFrame = (nRemainingPolies > g_CV_PolyGridBufferSize) ? g_CV_PolyGridBufferSize: nRemainingPolies;
				
				LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID);
				if(pEffect)
				{
					pEffect->UploadVertexDeclaration();

					ID3DXEffect* pD3DEffect = pEffect->GetEffect();
					if(pD3DEffect)
					{
						i_client_shell->OnEffectShaderSetParams(pEffect, NULL, NULL, LTShaderDeviceStateImp::GetSingleton());

						UINT nPasses = 0;
						pD3DEffect->Begin(&nPasses, 0);

						for(UINT i = 0; i < nPasses; ++i)
						{
							pD3DEffect->BeginPass(i);
							D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,nPoliesThisFrame,&pGrid->m_Indices[nCurrentVertPosition],D3DFMT_INDEX16,g_TriVertList, nVertexSize));
							pD3DEffect->EndPass();
						}

						pD3DEffect->End();
					}

				}
				else
				{
					D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,nPoliesThisFrame,&pGrid->m_Indices[nCurrentVertPosition],D3DFMT_INDEX16,g_TriVertList, nVertexSize));
				}

				nCurrentVertPosition += nPoliesThisFrame*3;
				nRemainingPolies -= nPoliesThisFrame;
			}
		}
		else
		{
			LTEffectImpl* pEffect = (LTEffectImpl*)LTEffectShaderMgr::GetSingleton().GetEffectShader(pGrid->m_nEffectShaderID);
			if(pEffect)
			{
				pEffect->UploadVertexDeclaration();

				ID3DXEffect* pD3DEffect = pEffect->GetEffect();
				if(pD3DEffect)
				{
					i_client_shell->OnEffectShaderSetParams(pEffect, NULL, NULL, LTShaderDeviceStateImp::GetSingleton());

					UINT nPasses = 0;
					pD3DEffect->Begin(&nPasses, 0);
					
					for(UINT i = 0; i < nPasses; ++i)
					{
						pD3DEffect->BeginPass(i);
						D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,(pGrid->m_nIndices)/3,pGrid->m_Indices,D3DFMT_INDEX16,g_TriVertList, nVertexSize));
						pD3DEffect->EndPass();
					}

					pD3DEffect->End();
				}

			}
			else
			{
				// No Effect Shader, just fixed function.
				D3D_CALL(PD3DDEVICE->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST,0,nNumVerts,(pGrid->m_nIndices)/3,pGrid->m_Indices,D3DFMT_INDEX16,g_TriVertList, nVertexSize));
			}
			
		}

		d3d_DisableTexture(0);
		d3d_DisableTexture(1);
	}

	if (bEnvMap)
		d3d_UnsetEnvMapTextureStates();

	//reset our world transform so that it won't mess up the rendering of other objects
	d3d_SetD3DMat(D3DTS_WORLD, &Params.m_mIdentity);
}