⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tnl.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************
<module>
* Name         : tnl.c
* Title        : D3DM software tnl functions
* Author(s)    : Imagination Technologies
* Created      : 2 March 2004
*
* Copyright    : 2004 by Imagination Technologies Limited.
*                All rights reserved.  No part of this software, either
*                material or conceptual may be copied or distributed,
*                transmitted, transcribed, stored in a retrieval system
*                or translated into any human or computer language in any
*                form by any means, electronic, mechanical, manual or
*                other-wise, or disclosed to third parties without the
*                express written permission of Imagination Technologies
*                Limited, Unit 8, HomePark Industrial Estate,
*                King's Langley, Hertfordshire, WD4 8LZ, U.K.
*
* Description  : Transformation and lighting code for software tnl
*
* Platform     : Windows CE
* 
$Log: tnl.c $

 --- Revision Logs Removed --- 
********************************************************************************/
#include "context.h"

#if (defined(SUPPORT_VGP) && (COREVERSION < 13))		|| \
	(defined(SUPPORT_VGP_LITE) && (COREVERSION < 120))	|| \
	(!defined(SUPPORT_VGP) && !defined(SUPPORT_VGP_LITE))

/***********************************************************************************
 Function Name      : DoClipTestandVPTransform
 Inputs             : psContext, ppsVertex, ui32Count
 Outputs            : 
 Description        : Performs front and rear clip plane test on a primitive. transforms
					  vertex obj co-ords to window co-ords.
************************************************************************************/
IMG_VOID DoClipTestandVPTransform(LPD3DM_CONTEXT	psContext, 
								  PVR_NATIVE_VERTEX **ppsVertex, 
								  IMG_UINT32		ui32Count)
{
    IMG_UINT32 ui32ClipCode = 0;    
    IMG_UINT32 i;
    NTV_TYPE x, y, z, w, invw;
    NTV_TYPE wx, wy, wz;
    PVR_VP_TRANSFORM *psVPTransform = &psContext->sHWState.sTACtl3DState.sVPTrans;
	PVR_NATIVE_VERTEX *psVertex;

	PROFILE_START_FUNC(DO_CLIP_TEST_AND_VP_TRANSFORM);

    for (i=0; i<ui32Count; i++) 
    {   
		/* set up the vertex */
		psVertex = *ppsVertex++;

		if(!(psVertex->ui32Flags & D3DM_HASFLAG_RHW))
		{
			/* transform to post projection */
			TransformVector4_PRZW(&psContext->sTState.sSWTNLState.sWorldViewProj, &psVertex->sObj, &psVertex->sClip);

			w = psVertex->sClip.w;
			invw = w ? DivPR_Y(D3DM_One, w) : D3DM_Zero;
			x = psVertex->sClip.x;
			y = psVertex->sClip.y;
			z = psVertex->sClip.z;

			/* Set clip codes */
			ui32ClipCode = 0;
 
			if(psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_CLIPPING)
			{
				/*
				** NOTE: it is possible for x to be less than negW and greater than w
				** (if w is negative).  Otherwise there would be "else" clauses here.
				*/
				if (z < D3DM_Zero) 
				{
					ui32ClipCode |= D3DM_CLIPFLAG_NEAR; /* FIXME - SetClipStatus */
				}
				if (z > w)
				{
					ui32ClipCode |= D3DM_CLIPFLAG_FAR;
				}
			}
    
			psVertex->ui32Flags |= D3DM_HASFLAG_CLIP | ui32ClipCode;
    
			/*	
				Compute window coordinates unless clipped 
				(BFCulling won't work if clip w is outside -1 to 1 range) 
			*/

			/* Rotate if this is a presentable rendertarget */
			if(psContext->dwRotationAngle == 0										||
			   psContext->dwRotationAngle == 180									||	
			   psContext->psCurrentRenderTarget->eSurfaceType == D3DMRTYPE_SURFACE	||
			   psContext->psCurrentRenderTarget->eSurfaceType == D3DMRTYPE_TEXTURE)
			{
				wx = Add(Mul(Mul(x, psVPTransform->XScale), PR_UNSHIFT(invw)), psVPTransform->XOffset);
				wy = Add(Mul(Mul(y, psVPTransform->YScale), PR_UNSHIFT(invw)), psVPTransform->YOffset);
			}
			else
			{
				wx = Add(Mul(Mul(y, psVPTransform->XScale), PR_UNSHIFT(invw)), psVPTransform->XOffset);
				wy = Add(Mul(Mul(x, psVPTransform->YScale), PR_UNSHIFT(invw)), psVPTransform->YOffset);
			}

			wz = Add(MulPR_XY(MulPR_X(z, psVPTransform->ZScale), invw), PR_SHIFT(psVPTransform->ZOffset));
			
			psVertex->sWindow.x = wx;
			psVertex->sWindow.y = wy;
			psVertex->sWindow.z = wz;
			psVertex->sWindow.w = invw;
		}
		else
		{
			if(psContext->dwRotationAngle == 0										||
			   psContext->psCurrentRenderTarget->eSurfaceType == D3DMRTYPE_SURFACE	||
			   psContext->psCurrentRenderTarget->eSurfaceType == D3DMRTYPE_TEXTURE)
			{
				/* Copy co-ordinates straight to window vector */ 
				psVertex->sWindow.x = psVertex->sObj.x;
				psVertex->sWindow.y = psVertex->sObj.y;
				psVertex->sWindow.z = PR_SHIFT(psVertex->sObj.z);
				psVertex->sWindow.w = PR_SHIFT(psVertex->sObj.w);
			}
			else
			{

				GetRotatedVertex(psContext, 
								 psVertex->sObj.x,
								 psVertex->sObj.y,
								 &psVertex->sWindow.x,
								 &psVertex->sWindow.y,
								 psContext->psCurrentRenderTarget->dwWidth,
								 psContext->psCurrentRenderTarget->dwHeight,
								 psContext->dwRotationAngle);

				psVertex->sWindow.z = PR_SHIFT(psVertex->sObj.z);
				psVertex->sWindow.w = PR_SHIFT(psVertex->sObj.w);
			}

			/* Pretransformed, so no clipping required */
			psVertex->ui32Flags |= D3DM_HASFLAG_CLIP | ui32ClipCode;
		}
	}

	PROFILE_STOP_FUNC(DO_CLIP_TEST_AND_VP_TRANSFORM);
}
/***********************************************************************************
 Function Name      : CalcRGBColor
 Inputs             : psContext, ui32Face, psVertex
 Outputs            : psVertex
 Returns            : -
 Description        : Generates the vertex color through lighting. An implementation 
					  concerned with performing an exponent for the spot/sSpecular 
					  calculations on a per vertex basis, could use table lookup
					  (calculated at validation time and cached) for performance.
************************************************************************************/
IMG_VOID CalcRGBColor(LPD3DM_CONTEXT psContext, PVR_NATIVE_VERTEX *psVertex)
{
	PROFILE_START_FUNC(CALC_RGB_COLOUR);

	/* If vertex is pre-transformed then we dont need to calculate lighting */
	if(psVertex->ui32Flags & D3DM_HASFLAG_RHW)
	{
		if(psVertex->ui32Flags & D3DM_HASFLAG_DIFFUSE_COLOR)
		{
			/* copy diffuse color (HWFormat) */
			psVertex->sDiffuseOut =	psVertex->sDiffuseIn;
		}
		else
		{
			/* default to all F's (From d3dm spec) */
			psVertex->sDiffuseOut.r				= D3DM_One;
			psVertex->sDiffuseOut.g				= D3DM_One;
			psVertex->sDiffuseOut.b				= D3DM_One;
			psVertex->sDiffuseOut.a				= D3DM_One;
			psVertex->sDiffuseOut.ui32Colour	= 0xFFFFFFFF;
		}

		/* Pre-transformed, so default to 0 (From d3dm spec) */
		psVertex->sSpecularOut.r = D3DM_Zero;
		psVertex->sSpecularOut.g = D3DM_Zero;
		psVertex->sSpecularOut.b = D3DM_Zero;

		if(psVertex->ui32Flags & D3DM_HASFLAG_FOG)
		{
			psVertex->sSpecularOut.a = NTV_MAX(D3DM_Zero, NTV_MIN(psVertex->Fog, D3DM_One));
		}
		else
		{
			psVertex->sSpecularOut.a = D3DM_Zero;
		}
		

		return;
	}
	
	if(psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_LIGHTING)
	{		
		NTV_TYPE NLd[PVR_SWTNL_MAX_LIGHTS];
		NTV_TYPE NAtten[PVR_SWTNL_MAX_LIGHTS];
		PVR_MATERIAL *psMaterial = &psContext->sTState.sSWTNLState.sMaterial;
		PVR_COLORVALUE *psVa, *psVd, *psVs, sSum, sTmpCol1;
		PVR_VECTOR3 sTmpVec;
		PLIGHTDATA	psLight;
		NTV_TYPE AlphaChnl;
		IMG_UINT32 i, ui32LightCount;
		PSWTNLSTATE psSWTNLState;
		PLIGHTDATA	*ppsEnabledLight;

		psSWTNLState	= &psContext->sTState.sSWTNLState;
		ppsEnabledLight	= psSWTNLState->ppsEnabledLights;
		ui32LightCount	= psSWTNLState->dwLightCount;

		/********************************************
			DIFFUSE LIGHTING CALCULATION
		********************************************/

		/* 
			Drgb = Va * La + sum[Vd * (N.Ld) * Atteni*Lci + Va * Lcai] 
		*/

		/* 
			define ambient color at vertex, Va
		 	select material ambient by default 
		*/
		psVa = &psMaterial->Ambient;

		/* 
			define diffuse alpha as material diffuse alpha by default 
		*/
		AlphaChnl = psMaterial->Diffuse.a;

		/* 
			define diffuse color at vertex, Vd
		 	select material diffuse by default 
		*/
		psVd = &psMaterial->Diffuse;
		
		/* override defaults? */
		if (psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_COLORVERTEX)
		{
			/* override Va? */
			if ((psContext->sTState.sSWTNLState.psD3DColourSourceSel[TNLCOLSRCTYPE_AMBIENT] == D3DMMCS_COLOR1)
			&&	(psVertex->ui32Flags & D3DM_HASFLAG_DIFFUSE_COLOR))
			{
				psVa = &psVertex->sDiffuseIn;
			}	
			else if ((psContext->sTState.sSWTNLState.psD3DColourSourceSel[TNLCOLSRCTYPE_AMBIENT] == D3DMMCS_COLOR2)
			&&	(psVertex->ui32Flags & D3DM_HASFLAG_SPECULAR_COLOR))
			{
				psVa = &psVertex->sSpecularIn;
			}

			/* override Vd, AlphaChnl? */
			if ((psContext->sTState.sSWTNLState.psD3DColourSourceSel[TNLCOLSRCTYPE_DIFFUSE] == D3DMMCS_COLOR1)
			&&	(psVertex->ui32Flags & D3DM_HASFLAG_DIFFUSE_COLOR))
			{
				psVd = &psVertex->sDiffuseIn;
				AlphaChnl = psVertex->sDiffuseIn.a;
			}	
			else if ((psContext->sTState.sSWTNLState.psD3DColourSourceSel[TNLCOLSRCTYPE_DIFFUSE] == D3DMMCS_COLOR2)
			&&	(psVertex->ui32Flags & D3DM_HASFLAG_SPECULAR_COLOR))
			{
				psVd = &psVertex->sSpecularIn;
				AlphaChnl = psVertex->sSpecularIn.a;
			}
		}
	
		/* 
			first (global) term of the diffuse lighting calculation.
			Drgb = Va * La
		*/
		ColorMultiply(psVa, &psContext->sTState.sSWTNLState.sAmbientColour, &sSum);
		
		/* tranverse lights, adding contributions as we go */
		for(i=0; i < ui32LightCount; i++)
		{
			psLight = ppsEnabledLight[i];

			if(psLight->dwFlags & LIGHTDATA_FLAGS_ENABLED)
			{
				PVR_COLORVALUE sTmpCol2;


				if(psVertex->ui32Flags & D3DM_HASFLAG_NORMAL)
				{
					/* Work out attenuation value */
					if(psLight->sLightInfo.Type == D3DMLIGHT_DIRECTIONAL)
					{
						NAtten[i] = D3DM_One;
					}
					else /* D3DMLIGHT_POINT */
					{
						NTV_TYPE NDist;

						/* Calculate Ldi */
						DistanceVector((PVR_VECTOR3*)&psLight->sLightInfo.EyePosition, (PVR_VECTOR3*)&psVertex->sEye, &sTmpVec);

						/* Get Magnitude of distance vector before normalization */
						NDist = Magnitude(&sTmpVec);
						Normalized((PVR_VECTOR3*)&sTmpVec, (PVR_VECTOR3*)&psLight->sLightInfo.EyeDirection);

						if(NDist > psLight->sLightInfo.Range)
						{
							NAtten[i] = D3DM_Zero;
						}
						else
						{
							/* Attenuation = 1 / (Latt0i + LAtt1i * Ldi + LAtt2i * Ldi^2) */
							NTV_TYPE NTemp1, NTemp2/*, NMag*/;

							/* LAtt1i * Ldi */
							NTemp1 = Mul(psLight->sLightInfo.Attenuation1, NDist);

							/* LAtt2i * Ldi^2 */
							NTemp2 = Mul(psLight->sLightInfo.Attenuation2, LPow(NDist, D3DM_Two));
							
							/* (LAtt1i * Ldi) + (LAtt2i * Ldi^2) */
							NTemp1 = Add(NTemp1, NTemp2);

							/* Latt0i + (LAtt1i * Ldi) + (LAtt2i * Ldi^2) */
							NTemp2	= Add(psLight->sLightInfo.Attenuation0, NTemp1);

							/* 1 / (Latt0i + LAtt1i * Ldi + LAtt2i * Ldi^2) */
							if(NTemp2 != D3DM_Zero)
							{
								NAtten[i]= Div(D3DM_One, NTemp2);
							}
							else
							{
								NAtten[i] = D3DM_One;
							}
						}
					}

					/* (N.Ldi) */
					NLd[i] = DotProduct((PVR_VECTOR3*)&psVertex->sNormal, 
										(PVR_VECTOR3*)&psLight->sLightInfo.EyeDirection);
					/* Atteni * Lci */
					ScalarColorMultiply(&psLight->sLightInfo.Diffuse, NAtten[i], &sTmpCol2);

					/* (N.Ldi) * (Atteni * Lci) */
					ScalarColorMultiply(&sTmpCol2, NLd[i], &sTmpCol1);

					/* Vd * ((N.Ldi) * (Atteni * Lci)) */
					ColorMultiply(psVd, &sTmpCol1, &sTmpCol1);

					/* Va * Lcai */
					ColorMultiply(psVa, &psLight->sLightInfo.Ambient, &sTmpCol2);

					/* (Vd * ((N.Ldi) * (Atteni * Lci))) + (Va * Lcai) */
					ColorAdd(&sTmpCol1, &sTmpCol2, &sTmpCol2);

					/* Drgb = Va * La + Sum[(Vd * ((N.Ldi) * (Atteni * Lci))) + (Va * Lcai)]*/ 
					ColorAddClamp(&sTmpCol2, &sSum, &sSum);
				}
				else
				{
					/* 
						if no normals, dot products go to zero.
						0 + (Va * Lcai)
					*/
					ColorMultiply(psVa, &psLight->sLightInfo.Ambient, &sTmpCol1);

					/* Drgb = Va * La + Sum[Va * Lcai] */ 
					ColorAddClamp(&sTmpCol1, &sSum, &sSum);
				}
			}	
		}



		/* copy diffuse result to vertex diffuse Output color */
		psVertex->sDiffuseOut.a = NTV_MAX(D3DM_Zero, NTV_MIN(AlphaChnl, D3DM_One));
		psVertex->sDiffuseOut.r = sSum.r;
		psVertex->sDiffuseOut.g = sSum.g;
		psVertex->sDiffuseOut.b = sSum.b;
		
		/********************************************
			SPECULAR LIGHTING CALCULATION

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -