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

📄 tnl.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		********************************************/
		
		if(psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_SPECULAR)
		{
			/*
				Srgb = Vs * sum(Pow(N.h, Mp) * Lcs * Atteni)
				if localviewer:
					h = norm(norm(Vpe) + Ld)
					Vpe = vector from vertex to camera(0,0,0)
				else
					h = norm(0,0,-1 + Ld)
			*/


			/* 
				define specular color at vertex, Vs
			 	select material ambient by default 
			*/
			psVs = &psMaterial->Specular;
	
			/* 
				define specular alpha as material specular alpha by default 
			*/
			AlphaChnl = psMaterial->Specular.a;
			
			/* override defaults? */
			if (psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_COLORVERTEX)
			{
				/* override Va? */
				if ((psContext->sTState.sSWTNLState.psD3DColourSourceSel[TNLCOLSRCTYPE_SPECULAR] == D3DMMCS_COLOR1)
				&&	(psVertex->ui32Flags & D3DM_HASFLAG_DIFFUSE_COLOR))
				{
					psVs = &psVertex->sDiffuseIn;
					AlphaChnl = psVertex->sDiffuseIn.a;
				}	
				else if ((psContext->sTState.sSWTNLState.psD3DColourSourceSel[TNLCOLSRCTYPE_SPECULAR] == D3DMMCS_COLOR2)
				&&	(psVertex->ui32Flags & D3DM_HASFLAG_SPECULAR_COLOR))
				{
					psVs = &psVertex->sSpecularIn;
					AlphaChnl = psVertex->sSpecularIn.a;
				}
			}

			/* init sum color */		
			sSum.a = D3DM_Zero;
			sSum.r = D3DM_Zero;
			sSum.g = D3DM_Zero;
			sSum.b = D3DM_Zero;

			/* compute specular */
			for(i=0; i < ui32LightCount; i++)
			{
				psLight = ppsEnabledLight[i];

				if ((psLight->dwFlags & LIGHTDATA_FLAGS_ENABLED)
				&&	(NLd[i] > D3DM_Zero))/* Spec. highlights don't extend beyond 180degs. */
				{
					PVR_VECTOR3 sHalfVector;
					NTV_TYPE NhMp;

					/* Calculate halfway vector */
					if (psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_LOCALVIEWER)
					{
						PVR_VECTOR3 sTmpVec;
						/*
							I assume camera position is 0,0,0 in eye space so:
							Camera - Vertex => -Vertex

							 hi = Norm(Norm(Vpe) + Ldi) 
						*/
						
						/* Norm(Vpe) */ 						
						VectorNegate((PVR_VECTOR3*)&psVertex->sEye, &sTmpVec);
						Normalize(&sTmpVec);

						 /* hi = Norm(Norm(Vpe) + Ldi) */
						VectorAdd(&sTmpVec, (PVR_VECTOR3*)&psLight->sLightInfo.EyeDirection, &sHalfVector);
						Normalize(&sHalfVector);
					}
					else
					{
						/* hi = Norm((0,0,-1) + Ldi) */
						PVR_VECTOR3 sOrthVec = { D3DM_Zero, D3DM_Zero, -D3DM_One };
						VectorAdd((PVR_VECTOR3*)&psLight->sLightInfo.EyeDirection, &sOrthVec, &sHalfVector);
						Normalize(&sHalfVector);
					}

					/* (N.hi)^mp */
					NhMp = PowPR_A(DotProduct_PR((PVR_VECTOR3*)&psVertex->sNormal, &sHalfVector), psMaterial->Power);

					/* ((N.hi)^mp) * Lcsi */
					ScalarColorMultiply(&psLight->sLightInfo.Specular, NhMp, &sTmpCol1);

					/* (((N.hi)^mp) * Lcsi) * Atteni */
					ScalarColorMultiply(&sTmpCol1, NAtten[i], &sTmpCol1);

					/* Sum [(((N.hi)^mp) * Lcsi) * Atteni] */
					ColorAddClamp(&sTmpCol1, &sSum, &sSum);
				}	
			}

			/* Srgb = Vs * Sum [(((N.hi)^mp) * Lcsi) * Atteni] */
			ColorMultiply(psVs, &sSum, &sSum);

			/* 
				copy specular result to vertex Specular output color 
			*/
			if(psVertex->ui32Flags & D3DM_HASFLAG_FOG)
			{
				psVertex->sSpecularOut.a = NTV_MAX(D3DM_Zero, NTV_MIN(psVertex->Fog, D3DM_One));
			}
			else
			{
				psVertex->sSpecularOut.a = NTV_MAX(D3DM_Zero, NTV_MIN(AlphaChnl, D3DM_One));
			}

			psVertex->sSpecularOut.r = sSum.r;
			psVertex->sSpecularOut.g = sSum.g;
			psVertex->sSpecularOut.b = sSum.b;
				
		}
		else
		{

			/* Specular is disabled so zero specular value and check fog */
			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;
			}

		}
	}
	else /* Lighting disabled */
	{
		/* no lighting */
		if(psVertex->ui32Flags & D3DM_HASFLAG_DIFFUSE_COLOR)
		{
			/* pass through diffure vertex colour */
			psVertex->sDiffuseOut =	psVertex->sDiffuseIn;
		}
		else
		{
			/* From d3dm spec. */
			psVertex->sDiffuseOut.r = D3DM_One;
			psVertex->sDiffuseOut.g = D3DM_One;
			psVertex->sDiffuseOut.b = D3DM_One;
			psVertex->sDiffuseOut.a = D3DM_One;
		}
		
		if(psVertex->ui32Flags & D3DM_HASFLAG_SPECULAR_COLOR && 
		   psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_SPECULAR)
		{
			/* Lighting is disabled but specular is enabled so pass through specular vertex colour */
			psVertex->sSpecularOut =  psVertex->sSpecularIn;

			/* Check for fogging */
			if(psVertex->ui32Flags & D3DM_HASFLAG_FOG)
			{
				psVertex->sSpecularOut.a = NTV_MAX(D3DM_Zero, NTV_MIN(psVertex->Fog, D3DM_One));
			}
		}
		else
		{
			/* Spec disabled or no spec 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;
			}

		}		
	}

	PROFILE_STOP_FUNC(CALC_RGB_COLOUR);
}	

/***********************************************************************************
 Function Name      : ValidateVertex
 Inputs             : psContext, ppsVertex, ui32Count
 Outputs            : psVertex
 Returns            : -
 Description        : Performs required tnl calculations on current vertex
************************************************************************************/
IMG_VOID ValidateVertex(LPD3DM_CONTEXT psContext, 
					 PVR_NATIVE_VERTEX **ppsVertex, 
					 IMG_UINT32 ui32Count)
{
	PVR_NATIVE_VERTEX *psVertex;
	IMG_UINT32		  i;

	PROFILE_START_FUNC(VALIDATE_VERTEX);

	while (ui32Count--)
	{
		psVertex = *ppsVertex++;

		if(psVertex->ui32Flags & D3DM_TNLFLAG_VERTEX_VALIDATED)
		{
			continue;
		}

		if(!(psVertex->ui32Flags & D3DM_HASFLAG_RHW))
		{
			/* transform to obj to eye space */
			TransformVector4(&psContext->sTState.sSWTNLState.sWorldView, 
							 &psVertex->sObj, &psVertex->sEye);
		}
		
		if(psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_FOG)
		{
			NTV_TYPE Distance, Fog = D3DM_Zero, Density, End;
		
			if(psContext->sTState.dwD3DVertexFogMode != D3DMFOG_NONE)
			{
				/* Calculate Fog value */
			    if(psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_RANGE_FOG)
			    {
				    /* range based - slow but no artefacts */
				    Distance = Magnitude((PVR_VECTOR3*)&psVertex->sEye);
			    }
			    else
			    {
				    /* depth based - fast but suffers artefacts */
				    Distance = psVertex->sEye.z;
				    
				    if (Distance < D3DM_Zero)
				    {
		    		    Distance = -Distance;
				    }
			    }
		
				switch (psContext->sTState.dwD3DVertexFogMode) 
			    {
				    case D3DMFOG_EXP:
					    Density = psContext->sTState.D3DFogDensity;
					    Fog = Pow(D3DM_E, -Mul(Density, Distance));
					    break;
				    case D3DMFOG_EXP2:
					    Density = psContext->sTState.D3DFogDensity;
					    Fog = Pow(D3DM_E, -Mul(Mul(Mul(Density, Distance), Density), Distance));
					    break;
				    case D3DMFOG_LINEAR:
					    End = psContext->sTState.D3DFogEnd;
					    Fog = Mul(Sub(End, Distance), psContext->sTState.OneOverEndMinusStart);
					    break;
		        }
			}
			else
			{
				/* Pass though fog value */
				Fog = psVertex->sSpecularIn.a;
			}
			psVertex->Fog = Fog;
			psVertex->ui32Flags |= D3DM_HASFLAG_FOG;
		}


		if (psVertex->ui32Flags & D3DM_HASFLAG_NORMAL) 
		{	
			/* Store World Z of Normal */
			psVertex->WorldNormalZ = psVertex->sNormal.z;

			if (psContext->sTState.dwRSFlags & TSTATE_RSFLAGS_NORMALIZENORMALS)
			{
				PVR_VECTOR4 sNe;

				TransformVector4(&psContext->sTState.sSWTNLState.sWorldViewInvT, &psVertex->sNormal, &sNe);

				Normalized((PVR_VECTOR3*)&sNe, (PVR_VECTOR3*)&psVertex->sNormal);
			}
			else 
			{
				PVR_VECTOR4 sNe;
				TransformVector4(&psContext->sTState.sSWTNLState.sWorldViewInvT, &psVertex->sNormal, &sNe);
				psVertex->sNormal = sNe;
			}
	    }

		/* Texture Coordinate generation */
		for(i=0; i < sPVRD3DMCaps.MaxSimultaneousTextures; i++)
		{
			PSWTNLSTATE  	psSWTNLState;
			PLAYER_TSTATE 	psLState;

			psSWTNLState   = &psContext->sTState.sSWTNLState;
			psLState       = &psContext->sTState.sLState[i];

			/* Texture co-ordinate generation requested */
			switch(psLState->dwCoordAutoGenMode)
			{
				case D3DMTSS_TCI_CAMERASPACENORMAL:
				{
					if(psVertex->ui32Flags & D3DM_HASFLAG_NORMAL)
					{
						/*
							Use the vertex normal, transformed to camera space as the
							vertex's texture coordinates for the given stage. The results
							will be normalized vectors
						*/
						psVertex->sTextures[i].x = psVertex->sNormal.x;
						psVertex->sTextures[i].y = psVertex->sNormal.y;
						psVertex->sTextures[i].z = psVertex->sNormal.z;
					}
					else
					{
						psVertex->sTextures[i].x = D3DM_Zero;
						psVertex->sTextures[i].y = D3DM_Zero;
						psVertex->sTextures[i].z = D3DM_Zero;
						psContext->hrLastError	 = D3DMERR_INVALIDCALL;
					}
					break;
				}
				case D3DMTSS_TCI_CAMERASPACEPOSITION:
				{
					/* 
						Use the vertex position, transformed to camera space as
						the vertex's texture coordinates for the given stage.
					*/
					psVertex->sTextures[i].x = psVertex->sEye.x;
					psVertex->sTextures[i].y = psVertex->sEye.y;
					psVertex->sTextures[i].z = psVertex->sEye.z;
					break;
				}
				case D3DMTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
				{
					if(psVertex->ui32Flags & D3DM_HASFLAG_NORMAL)
					{
						/*
							Use the reflection vector at the vertex as the vertex's texture
							coordinates for the given stage. The results will be normalized 
							vectors.

							From Microsoft documentation for DX9: -

							When you enable automatic texture coordinate generation, the system 
							uses one of two formulas to compute the reflection vector for each vertex. 
							When the D3DRS_LOCALVIEWER render state is set to TRUE, the formula used 
							is the following:

							R = 2(E.N)N-E

							In the preceding formula, R is the reflection vector being computed, E 
							is the normalized position-to-eye vector, and N is the camera-space vertex normal.
							When the D3DRS_LOCALVIEWER render state is set to FALSE, the system uses 
							the following formula.

							R = 2NzN-I

							The R and N elements in this formula are identical to the previous formula. 
							The Nz element is the world-space z of the vertex normal, and I is the vector 
							(0,0,1) of an infinitely distant viewpoint.

						*/
						PTRANSIENT_STATE	psTState = &psContext->sTState;
						NTV_TYPE			ntvTmp;
						PVR_VECTOR3			sE;
						PVR_VECTOR3			sN = *(PVR_VECTOR3*) &psVertex->sNormal;
						PVR_VECTOR3			sI = { D3DM_Zero, D3DM_Zero, D3DM_One };
						PVR_VECTOR3			sVecTemp;

						if(psVertex->ui32Flags & D3DM_HASFLAG_NORMAL)
						{
							if(psTState->dwRSFlags & TSTATE_RSFLAGS_LOCALVIEWER)
							{
								/* E is Position to Eye vec = inverse of pos in Eye space */
								VectorNegate((PVR_VECTOR3*) &psVertex->sEye, &sE);
								Normalize(&sE);

								/* 2(E.N) */
								ntvTmp = Mul(D3DM_Two ,DotProduct(&sE, &sN));

⌨️ 快捷键说明

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