📄 tnl.c
字号:
********************************************/
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 + -