805 lines
27 KiB
C++
805 lines
27 KiB
C++
#include "StdAfx.h"
|
||
#include "MapOutdoor.h"
|
||
#include "TerrainPatch.h"
|
||
#include "TerrainQuadtree.h"
|
||
|
||
#include "../eterlib/Camera.h"
|
||
#include "../eterlib/StateManager.h"
|
||
|
||
struct SoftwareTransformPatch_SSplatVertex
|
||
{
|
||
D3DXVECTOR4 kPosition;
|
||
DWORD dwDiffuse;
|
||
DWORD dwSpecular;
|
||
D3DXVECTOR2 kTex1;
|
||
D3DXVECTOR2 kTex2;
|
||
};
|
||
|
||
|
||
|
||
void CMapOutdoor::__RenderTerrain_RenderSoftwareTransformPatch()
|
||
{
|
||
SoftwareTransformPatch_SRenderState kTPRS;
|
||
|
||
DWORD dwFogEnable = STATEMANAGER.GetRenderState(D3DRS_FOGENABLE);
|
||
|
||
__SoftwareTransformPatch_ApplyRenderState();
|
||
|
||
__SoftwareTransformPatch_BuildPipeline(kTPRS);
|
||
|
||
std::pair<float, long> fog_far(kTPRS.m_fFogFarDistance+800.0f, 0);
|
||
std::pair<float, long> fog_near(kTPRS.m_fFogNearDistance-3200.0f, 0);
|
||
|
||
std::vector<std::pair<float ,long> >::iterator far_it = std::upper_bound(m_PatchVector.begin(),m_PatchVector.end(),fog_far);
|
||
std::vector<std::pair<float ,long> >::iterator near_it = std::upper_bound(m_PatchVector.begin(),m_PatchVector.end(),fog_near);
|
||
|
||
WORD wPrimitiveCount;
|
||
D3DPRIMITIVETYPE ePrimitiveType;
|
||
|
||
BYTE byCUrrentLODLevel = 0;
|
||
|
||
float fLODLevel1Distance = __GetNoFogDistance();
|
||
float fLODLevel2Distance = __GetFogDistance();
|
||
|
||
SelectIndexBuffer(0, &wPrimitiveCount, &ePrimitiveType);
|
||
|
||
STATEMANAGER.SetVertexShader(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX2);
|
||
|
||
std::vector<std::pair<float, long> >::iterator it = m_PatchVector.begin();
|
||
|
||
for( ; it != near_it; ++it)
|
||
{
|
||
if (byCUrrentLODLevel == 0 && fLODLevel1Distance <= it->first)
|
||
{
|
||
byCUrrentLODLevel = 1;
|
||
SelectIndexBuffer(1, &wPrimitiveCount, &ePrimitiveType);
|
||
}
|
||
else if (byCUrrentLODLevel == 1 && fLODLevel2Distance <= it->first)
|
||
{
|
||
byCUrrentLODLevel = 2;
|
||
SelectIndexBuffer(2, &wPrimitiveCount, &ePrimitiveType);
|
||
}
|
||
|
||
__SoftwareTransformPatch_RenderPatchSplat(kTPRS, it->second, wPrimitiveCount, ePrimitiveType, false);
|
||
if (m_iRenderedSplatNum >= m_iSplatLimit)
|
||
break;
|
||
|
||
}
|
||
|
||
if (m_iRenderedSplatNum < m_iSplatLimit)
|
||
{
|
||
for(it = near_it; it != far_it; ++it)
|
||
{
|
||
if (byCUrrentLODLevel == 0 && fLODLevel1Distance <= it->first)
|
||
{
|
||
byCUrrentLODLevel = 1;
|
||
SelectIndexBuffer(1, &wPrimitiveCount, &ePrimitiveType);
|
||
}
|
||
else if (byCUrrentLODLevel == 1 && fLODLevel2Distance <= it->first)
|
||
{
|
||
byCUrrentLODLevel = 2;
|
||
SelectIndexBuffer(2, &wPrimitiveCount, &ePrimitiveType);
|
||
}
|
||
|
||
__SoftwareTransformPatch_RenderPatchSplat(kTPRS, it->second, wPrimitiveCount, ePrimitiveType, true);
|
||
|
||
if (m_iRenderedSplatNum >= m_iSplatLimit)
|
||
break;
|
||
|
||
}
|
||
}
|
||
|
||
|
||
STATEMANAGER.SetTexture(0, NULL);
|
||
STATEMANAGER.SetTexture(1, NULL);
|
||
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
|
||
|
||
STATEMANAGER.SetVertexShader(D3DFVF_XYZRHW);
|
||
|
||
if (IsFastTNL())
|
||
{
|
||
if (byCUrrentLODLevel != 2)
|
||
{
|
||
byCUrrentLODLevel = 2;
|
||
SelectIndexBuffer(2, &wPrimitiveCount, &ePrimitiveType);
|
||
}
|
||
|
||
if (m_iRenderedSplatNum < m_iSplatLimit)
|
||
{
|
||
for(it = far_it; it != m_PatchVector.end(); ++it)
|
||
{
|
||
__SoftwareTransformPatch_RenderPatchNone(kTPRS, it->second, wPrimitiveCount, ePrimitiveType);
|
||
|
||
if (m_iRenderedSplatNum >= m_iSplatLimit)
|
||
break;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
// Render State & TextureStageState
|
||
__SoftwareTransformPatch_RestoreRenderState(dwFogEnable);
|
||
}
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_RenderPatchSplat(SoftwareTransformPatch_SRenderState& rkTPRS, long patchnum, WORD wPrimitiveCount, D3DPRIMITIVETYPE ePrimitiveType, bool isFogEnable)
|
||
{
|
||
assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::__SoftwareTransformPatch_RenderPatchSplat");
|
||
|
||
CTerrainPatchProxy * pTerrainPatchProxy = &m_pTerrainPatchProxyList[patchnum];
|
||
|
||
if (!pTerrainPatchProxy->isUsed())
|
||
return;
|
||
|
||
bool isDynamicShadow = pTerrainPatchProxy->IsIn(rkTPRS.m_v3Player, 3000.0f);
|
||
|
||
if (!m_bDrawChrShadow)
|
||
isDynamicShadow = false;
|
||
|
||
long sPatchNum = pTerrainPatchProxy->GetPatchNum();
|
||
|
||
if (sPatchNum < 0)
|
||
return;
|
||
|
||
BYTE ucTerrainNum = pTerrainPatchProxy->GetTerrainNum();
|
||
|
||
if (0xFF == ucTerrainNum)
|
||
return;
|
||
|
||
CTerrain * pTerrain;
|
||
if (!GetTerrainPointer(ucTerrainNum, &pTerrain))
|
||
return;
|
||
|
||
WORD wCoordX, wCoordY;
|
||
pTerrain->GetCoordinate(&wCoordX, &wCoordY);
|
||
|
||
TTerrainSplatPatch & rTerrainSplatPatch = pTerrain->GetTerrainSplatPatch();
|
||
|
||
SoftwareTransformPatch_STLVertex akTransVertex[CTerrainPatch::TERRAIN_VERTEX_COUNT];
|
||
if (!__SoftwareTransformPatch_SetTransform(rkTPRS, akTransVertex, *pTerrainPatchProxy, wCoordX, wCoordY, isFogEnable, isDynamicShadow))
|
||
return;
|
||
|
||
if (!__SoftwareTransformPatch_SetSplatStream(akTransVertex))
|
||
return;
|
||
|
||
if (isFogEnable)
|
||
{
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
|
||
}
|
||
else
|
||
{
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||
}
|
||
|
||
int iPrevRenderedSplatNum=m_iRenderedSplatNum;
|
||
|
||
bool isFirst=true;
|
||
for (DWORD j = 1; j < pTerrain->GetNumTextures(); ++j)
|
||
{
|
||
TTerainSplat & rSplat = rTerrainSplatPatch.Splats[j];
|
||
|
||
if (!rSplat.Active)
|
||
continue;
|
||
|
||
if (rTerrainSplatPatch.PatchTileCount[sPatchNum][j] == 0)
|
||
continue;
|
||
|
||
const TTerrainTexture & rTexture = m_TextureSet.GetTexture(j);
|
||
|
||
if (isFirst)
|
||
{
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
|
||
STATEMANAGER.SetTexture(0, rTexture.pd3dTexture);
|
||
STATEMANAGER.SetTexture(1, rSplat.pd3dTexture);
|
||
STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
isFirst=false;
|
||
}
|
||
else
|
||
{
|
||
STATEMANAGER.SetTexture(0, rTexture.pd3dTexture);
|
||
STATEMANAGER.SetTexture(1, rSplat.pd3dTexture);
|
||
STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount);
|
||
}
|
||
|
||
std::vector<int>::iterator aIterator = std::find(m_RenderedTextureNumVector.begin(), m_RenderedTextureNumVector.end(), (int)j);
|
||
if (aIterator == m_RenderedTextureNumVector.end())
|
||
m_RenderedTextureNumVector.push_back(j);
|
||
++m_iRenderedSplatNum;
|
||
if (m_iRenderedSplatNum >= m_iSplatLimit)
|
||
break;
|
||
}
|
||
|
||
// <20><EFBFBD><D7B8><EFBFBD>
|
||
if (m_bDrawShadow)
|
||
{
|
||
__SoftwareTransformPatch_SetShadowStream(akTransVertex);
|
||
__SoftwareTransformPatch_ApplyStaticShadowRenderState();
|
||
|
||
if (isDynamicShadow)
|
||
__SoftwareTransformPatch_ApplyDynamicShadowRenderState();
|
||
else
|
||
__SoftwareTransformPatch_ApplyFogShadowRenderState();
|
||
|
||
if (isFogEnable)
|
||
{
|
||
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, TRUE);
|
||
STATEMANAGER.SetRenderState(D3DRS_FOGCOLOR, 0xFFFFFFFF);
|
||
STATEMANAGER.SetTexture(0, pTerrain->GetShadowTexture());
|
||
STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount);
|
||
STATEMANAGER.SetRenderState(D3DRS_FOGCOLOR, rkTPRS.m_dwFogColor);
|
||
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||
}
|
||
else
|
||
{
|
||
STATEMANAGER.SetTexture(0, pTerrain->GetShadowTexture());
|
||
STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount);
|
||
}
|
||
|
||
if (isDynamicShadow)
|
||
__SoftwareTransformPatch_RestoreDynamicShadowRenderState();
|
||
else
|
||
__SoftwareTransformPatch_RestoreFogShadowRenderState();
|
||
|
||
ms_faceCount += wPrimitiveCount;
|
||
++m_iRenderedSplatNum;
|
||
|
||
|
||
|
||
__SoftwareTransformPatch_RestoreStaticShadowRenderState();
|
||
}
|
||
|
||
++m_iRenderedPatchNum;
|
||
|
||
int iCurRenderedSplatNum=m_iRenderedSplatNum-iPrevRenderedSplatNum;
|
||
|
||
m_iRenderedSplatNumSqSum+=iCurRenderedSplatNum*iCurRenderedSplatNum;
|
||
}
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_RenderPatchNone(SoftwareTransformPatch_SRenderState& rkTPRS, long patchnum, WORD wPrimitiveCount, D3DPRIMITIVETYPE ePrimitiveType)
|
||
{
|
||
assert(NULL!=m_pTerrainPatchProxyList && "CMapOutdoor::__SoftwareTransformPatch_RenderPatchNone");
|
||
|
||
CTerrainPatchProxy * pTerrainPatchProxy = &m_pTerrainPatchProxyList[patchnum];
|
||
|
||
if (!pTerrainPatchProxy->isUsed())
|
||
return;
|
||
|
||
long sPatchNum = pTerrainPatchProxy->GetPatchNum();
|
||
if (sPatchNum < 0)
|
||
return;
|
||
|
||
BYTE ucTerrainNum = pTerrainPatchProxy->GetTerrainNum();
|
||
if (0xFF == ucTerrainNum)
|
||
return;
|
||
|
||
CTerrain * pTerrain;
|
||
if (!GetTerrainPointer(ucTerrainNum, &pTerrain))
|
||
return;
|
||
|
||
WORD wCoordX, wCoordY;
|
||
pTerrain->GetCoordinate(&wCoordX, &wCoordY);
|
||
|
||
SoftwareTransformPatch_SSourceVertex* akSrcVertex=pTerrainPatchProxy->SoftwareTransformPatch_GetTerrainVertexDataPtr();
|
||
if (!akSrcVertex)
|
||
return;
|
||
|
||
float fScreenHalfWidth=rkTPRS.m_fScreenHalfWidth;
|
||
float fScreenHalfHeight=rkTPRS.m_fScreenHalfHeight;
|
||
|
||
D3DXMATRIX m4Frustum=rkTPRS.m_m4Frustum;
|
||
|
||
SoftwareTransformPatch_STVertex akTransVertex[CTerrainPatch::TERRAIN_VERTEX_COUNT];
|
||
|
||
D3DXVECTOR4* akPosition=(D3DXVECTOR4*)akTransVertex;
|
||
D3DXVECTOR4* pkPosition;
|
||
for (UINT uIndex=0; uIndex!=CTerrainPatch::TERRAIN_VERTEX_COUNT; ++uIndex)
|
||
{
|
||
pkPosition=akPosition+uIndex;
|
||
D3DXVec3Transform(pkPosition, &akSrcVertex[uIndex].kPosition, &m4Frustum);
|
||
pkPosition->w=1.0f/pkPosition->w;
|
||
pkPosition->z*=pkPosition->w;
|
||
pkPosition->y=(pkPosition->y*pkPosition->w-1.0f)*fScreenHalfHeight;
|
||
pkPosition->x=(pkPosition->x*pkPosition->w+1.0f)*fScreenHalfWidth;
|
||
}
|
||
|
||
|
||
IDirect3DVertexBuffer8* pkVB=m_kSTPD.m_pkVBNone[m_kSTPD.m_dwNonePos++];
|
||
m_kSTPD.m_dwNonePos%=SoftwareTransformPatch_SData::NONE_VB_NUM;
|
||
if (!pkVB)
|
||
return;
|
||
|
||
DWORD dwVBSize=sizeof(SoftwareTransformPatch_STVertex)*CTerrainPatch::TERRAIN_VERTEX_COUNT;
|
||
SoftwareTransformPatch_STVertex* akDstVertex;
|
||
if (FAILED(
|
||
pkVB->Lock(0, dwVBSize, (BYTE**)&akDstVertex, D3DLOCK_DISCARD)
|
||
)) return;
|
||
|
||
memcpy(akDstVertex, akTransVertex, dwVBSize);
|
||
|
||
pkVB->Unlock();
|
||
|
||
STATEMANAGER.SetStreamSource(0, pkVB, sizeof(SoftwareTransformPatch_STVertex));
|
||
STATEMANAGER.DrawIndexedPrimitive(ePrimitiveType, 0, m_iPatchTerrainVertexCount, 0, wPrimitiveCount);
|
||
ms_faceCount += wPrimitiveCount;
|
||
}
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_ApplyStaticShadowRenderState()
|
||
{
|
||
STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
|
||
STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR);
|
||
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
|
||
|
||
}
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_ApplyDynamicShadowRenderState()
|
||
{
|
||
STATEMANAGER.SetTexture(1, m_lpCharacterShadowMapTexture);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
|
||
}
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_ApplyFogShadowRenderState()
|
||
{
|
||
STATEMANAGER.SetTexture(1, NULL);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
}
|
||
void CMapOutdoor::__SoftwareTransformPatch_RestoreStaticShadowRenderState()
|
||
{
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
|
||
|
||
STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||
STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||
}
|
||
|
||
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_RestoreDynamicShadowRenderState()
|
||
{
|
||
STATEMANAGER.SetTexture(1, NULL);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
|
||
}
|
||
|
||
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_RestoreFogShadowRenderState()
|
||
{
|
||
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||
|
||
STATEMANAGER.SetTexture(1, NULL);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
}
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_ApplyRenderState()
|
||
{
|
||
DWORD dwFogColor=0xffffffff;
|
||
if (mc_pEnvironmentData)
|
||
dwFogColor=mc_pEnvironmentData->FogColor;
|
||
|
||
BOOL isSoftwareVertexClipping=FALSE;
|
||
if (!IsTLVertexClipping())
|
||
isSoftwareVertexClipping=TRUE;
|
||
|
||
STATEMANAGER.SaveRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, isSoftwareVertexClipping);
|
||
|
||
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||
STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||
STATEMANAGER.SaveRenderState(D3DRS_ALPHAREF, 0x00000000);
|
||
STATEMANAGER.SaveRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
|
||
|
||
STATEMANAGER.SaveRenderState(D3DRS_TEXTUREFACTOR, dwFogColor);
|
||
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE);
|
||
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
|
||
STATEMANAGER.SetBestFiltering(0);
|
||
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
|
||
STATEMANAGER.SetBestFiltering(1);
|
||
|
||
CSpeedTreeWrapper::ms_bSelfShadowOn = true;
|
||
|
||
// Render State & TextureStageState
|
||
//////////////////////////////////////////////////////////////////////////
|
||
|
||
m_iRenderedSplatNumSqSum = 0;
|
||
m_iRenderedPatchNum = 0;
|
||
m_iRenderedSplatNum = 0;
|
||
m_RenderedTextureNumVector.clear();
|
||
|
||
m_matWorldForCommonUse._41 = 0.0f;
|
||
m_matWorldForCommonUse._42 = 0.0f;
|
||
STATEMANAGER.SetTransform(D3DTS_WORLD, &m_matWorldForCommonUse);
|
||
}
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_RestoreRenderState(DWORD dwFogEnable)
|
||
{
|
||
STATEMANAGER.SetRenderState(D3DRS_LIGHTING, TRUE);
|
||
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
|
||
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||
|
||
STATEMANAGER.SetRenderState(D3DRS_FOGENABLE, dwFogEnable);
|
||
|
||
std::sort(m_RenderedTextureNumVector.begin(),m_RenderedTextureNumVector.end());
|
||
|
||
STATEMANAGER.RestoreRenderState(D3DRS_TEXTUREFACTOR);
|
||
|
||
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
|
||
STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE);
|
||
STATEMANAGER.RestoreRenderState(D3DRS_ALPHAREF);
|
||
STATEMANAGER.RestoreRenderState(D3DRS_ALPHAFUNC);
|
||
|
||
STATEMANAGER.RestoreRenderState(D3DRS_SOFTWAREVERTEXPROCESSING);
|
||
|
||
// Render State & TextureStageState
|
||
//////////////////////////////////////////////////////////////////////////
|
||
}
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_BuildPipeline(SoftwareTransformPatch_SRenderState& rkTPRS)
|
||
{
|
||
memset(&rkTPRS, 0, sizeof(rkTPRS));
|
||
|
||
if (mc_pEnvironmentData)
|
||
{
|
||
rkTPRS.m_dwFogColor = mc_pEnvironmentData->FogColor;
|
||
rkTPRS.m_fFogNearDistance = mc_pEnvironmentData->GetFogNearDistance();
|
||
rkTPRS.m_fFogFarDistance = mc_pEnvironmentData->GetFogFarDistance();
|
||
}
|
||
else
|
||
{
|
||
rkTPRS.m_dwFogColor = 0xffffffff;
|
||
rkTPRS.m_fFogNearDistance = 5000.0f;
|
||
rkTPRS.m_fFogFarDistance = 10000.0f;
|
||
}
|
||
|
||
UINT uScreenWidth;
|
||
UINT uScreenHeight;
|
||
CScreen::GetBackBufferSize(&uScreenWidth, &uScreenHeight);
|
||
|
||
rkTPRS.m_fScreenHalfWidth = +float(uScreenWidth) / 2.0f;
|
||
rkTPRS.m_fScreenHalfHeight = -float(uScreenHeight) / 2.0f;
|
||
|
||
STATEMANAGER.GetLight(0, &rkTPRS.m_kLight);
|
||
STATEMANAGER.GetMaterial(&rkTPRS.m_kMtrl);
|
||
|
||
D3DXMATRIX m4View;STATEMANAGER.GetTransform(D3DTS_VIEW, &m4View);
|
||
D3DXMATRIX m4Proj;STATEMANAGER.GetTransform(D3DTS_PROJECTION, &m4Proj);
|
||
|
||
D3DXMatrixMultiply(&rkTPRS.m_m4Frustum, &m4View, &m4Proj);
|
||
|
||
rkTPRS.m_v3Player.x = +m_v3Player.x;
|
||
rkTPRS.m_v3Player.y = -m_v3Player.y;
|
||
rkTPRS.m_v3Player.z = +m_v3Player.z;
|
||
|
||
rkTPRS.m_m4Proj = m4Proj;
|
||
rkTPRS.m_m4DynamicShadow = m_matLightView * m_matDynamicShadowScale;
|
||
|
||
D3DXVECTOR3 kFogNearVector;
|
||
D3DXVec3TransformCoord(&kFogNearVector, &D3DXVECTOR3(0.0f, 0.0f, -rkTPRS.m_fFogNearDistance), &rkTPRS.m_m4Proj);
|
||
|
||
D3DXVECTOR3 kFogFarVector;
|
||
D3DXVec3TransformCoord(&kFogFarVector, &D3DXVECTOR3(0.0f, 0.0f, -rkTPRS.m_fFogFarDistance), &rkTPRS.m_m4Proj);
|
||
|
||
float fFogNear = kFogNearVector.z;
|
||
float fFogFar = kFogFarVector.z;
|
||
float fFogLenInv = 1.0f / (fFogFar-fFogNear);
|
||
|
||
rkTPRS.m_fFogNearTransZ = fFogNear;
|
||
rkTPRS.m_fFogFarTransZ = fFogFar;
|
||
rkTPRS.m_fFogLenInv = fFogLenInv;
|
||
|
||
}
|
||
|
||
bool CMapOutdoor::__SoftwareTransformPatch_SetTransform(SoftwareTransformPatch_SRenderState& rkTPRS, SoftwareTransformPatch_STLVertex* akTransVertex, CTerrainPatchProxy& rkTerrainPatchProxy, UINT uTerrainX, UINT uTerrainY, bool isFogEnable, bool isDynamicShadow)
|
||
{
|
||
SoftwareTransformPatch_SSourceVertex* akSrcVertex=rkTerrainPatchProxy.SoftwareTransformPatch_GetTerrainVertexDataPtr();
|
||
if (!akSrcVertex)
|
||
return false;
|
||
|
||
rkTerrainPatchProxy.SoftwareTransformPatch_UpdateTerrainLighting(
|
||
m_kSTPD.m_dwLightVersion,
|
||
rkTPRS.m_kLight, rkTPRS.m_kMtrl);
|
||
|
||
D3DXVECTOR3* pkSrcPosition;
|
||
|
||
float fTilePatternX=+1/640.0f;
|
||
float fTilePatternY=-1/640.0f;
|
||
|
||
float fTerrainBaseX=-(float) (uTerrainX * CTerrainImpl::TERRAIN_XSIZE)+m_fTerrainTexCoordBase * 12.30769f;
|
||
float fTerrainBaseY=+(float) (uTerrainY * CTerrainImpl::TERRAIN_YSIZE)+m_fTerrainTexCoordBase * 12.30769f;
|
||
|
||
float fScreenHalfWidth=rkTPRS.m_fScreenHalfWidth;
|
||
float fScreenHalfHeight=rkTPRS.m_fScreenHalfHeight;
|
||
|
||
float fAlphaPatternX=m_matSplatAlpha._11;
|
||
float fAlphaPatternY=m_matSplatAlpha._22;
|
||
float fAlphaBiasX=m_matSplatAlpha._41;
|
||
float fAlphaBiasY=m_matSplatAlpha._42;
|
||
float fShadowPatternX=+m_fTerrainTexCoordBase * ((float) CTerrainImpl::PATCH_XSIZE / (CTerrainImpl::XSIZE));
|
||
float fShadowPatternY=-m_fTerrainTexCoordBase * ((float) CTerrainImpl::PATCH_YSIZE / (CTerrainImpl::YSIZE));
|
||
|
||
D3DXMATRIX m4Frustum=rkTPRS.m_m4Frustum;
|
||
|
||
if (isFogEnable)
|
||
{
|
||
float fFogCur;
|
||
float fFogFar=rkTPRS.m_fFogFarTransZ;
|
||
float fFogLenInv=rkTPRS.m_fFogLenInv;
|
||
|
||
float fLocalX;
|
||
float fLocalY;
|
||
|
||
SoftwareTransformPatch_STLVertex kWorkVertex;
|
||
for (UINT uIndex=0; uIndex!=CTerrainPatch::TERRAIN_VERTEX_COUNT; ++uIndex)
|
||
{
|
||
pkSrcPosition=&akSrcVertex[uIndex].kPosition;
|
||
D3DXVec3Transform(&kWorkVertex.kPosition, pkSrcPosition, &m4Frustum);
|
||
fLocalX=pkSrcPosition->x+fTerrainBaseX;
|
||
fLocalY=pkSrcPosition->y+fTerrainBaseY;
|
||
kWorkVertex.kPosition.w=1.0f/kWorkVertex.kPosition.w;
|
||
kWorkVertex.kPosition.x*=kWorkVertex.kPosition.w;
|
||
kWorkVertex.kPosition.y*=kWorkVertex.kPosition.w;
|
||
kWorkVertex.kPosition.z*=kWorkVertex.kPosition.w;
|
||
kWorkVertex.kPosition.x=(kWorkVertex.kPosition.x+1.0f)*fScreenHalfWidth;
|
||
kWorkVertex.kPosition.y=(kWorkVertex.kPosition.y-1.0f)*fScreenHalfHeight;
|
||
kWorkVertex.dwDiffuse=akSrcVertex[uIndex].dwDiffuse;
|
||
kWorkVertex.kTexTile.x=pkSrcPosition->x*fTilePatternX;
|
||
kWorkVertex.kTexTile.y=pkSrcPosition->y*fTilePatternY;
|
||
kWorkVertex.kTexAlpha.x=fLocalX*fAlphaPatternX+fAlphaBiasX;
|
||
kWorkVertex.kTexAlpha.y=fLocalY*fAlphaPatternY+fAlphaBiasY;
|
||
kWorkVertex.kTexStaticShadow.x=fLocalX*fShadowPatternX;
|
||
kWorkVertex.kTexStaticShadow.y=fLocalY*fShadowPatternY;
|
||
kWorkVertex.kTexDynamicShadow.x=0.0f;
|
||
kWorkVertex.kTexDynamicShadow.y=0.0f;
|
||
|
||
fFogCur=(fFogFar-kWorkVertex.kPosition.z)*fFogLenInv;
|
||
if (fFogCur<0.0f)
|
||
kWorkVertex.dwFog=kWorkVertex.dwDiffuse=0x0000000|(kWorkVertex.dwDiffuse&0xffffff);
|
||
else if (fFogCur>1.0f)
|
||
kWorkVertex.dwFog=kWorkVertex.dwDiffuse=0xFF000000|(kWorkVertex.dwDiffuse&0xffffff);
|
||
else
|
||
kWorkVertex.dwFog=kWorkVertex.dwDiffuse=BYTE(255.0f*fFogCur)<<24|(kWorkVertex.dwDiffuse&0xffffff);
|
||
|
||
*(akTransVertex+uIndex)=kWorkVertex;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
float fLocalX;
|
||
float fLocalY;
|
||
|
||
SoftwareTransformPatch_STLVertex kWorkVertex;
|
||
for (UINT uIndex=0; uIndex!=CTerrainPatch::TERRAIN_VERTEX_COUNT; ++uIndex)
|
||
{
|
||
pkSrcPosition=&akSrcVertex[uIndex].kPosition;
|
||
D3DXVec3Transform(&kWorkVertex.kPosition, pkSrcPosition, &m4Frustum);
|
||
fLocalX=pkSrcPosition->x+fTerrainBaseX;
|
||
fLocalY=pkSrcPosition->y+fTerrainBaseY;
|
||
kWorkVertex.kPosition.w=1.0f/kWorkVertex.kPosition.w;
|
||
kWorkVertex.kPosition.x*=kWorkVertex.kPosition.w;
|
||
kWorkVertex.kPosition.y*=kWorkVertex.kPosition.w;
|
||
kWorkVertex.kPosition.z*=kWorkVertex.kPosition.w;
|
||
kWorkVertex.kPosition.x=(kWorkVertex.kPosition.x+1.0f)*fScreenHalfWidth;
|
||
kWorkVertex.kPosition.y=(kWorkVertex.kPosition.y-1.0f)*fScreenHalfHeight;
|
||
kWorkVertex.dwDiffuse=akSrcVertex[uIndex].dwDiffuse;
|
||
kWorkVertex.dwFog=0xffffffff;
|
||
kWorkVertex.kTexTile.x=pkSrcPosition->x*fTilePatternX;
|
||
kWorkVertex.kTexTile.y=pkSrcPosition->y*fTilePatternY;
|
||
kWorkVertex.kTexAlpha.x=fLocalX*fAlphaPatternX+fAlphaBiasX;
|
||
kWorkVertex.kTexAlpha.y=fLocalY*fAlphaPatternY+fAlphaBiasY;
|
||
kWorkVertex.kTexStaticShadow.x=fLocalX*fShadowPatternX;
|
||
kWorkVertex.kTexStaticShadow.y=fLocalY*fShadowPatternY;
|
||
kWorkVertex.kTexDynamicShadow.x=0.0f;
|
||
kWorkVertex.kTexDynamicShadow.y=0.0f;
|
||
|
||
*(akTransVertex+uIndex)=kWorkVertex;
|
||
}
|
||
}
|
||
|
||
if (isDynamicShadow)
|
||
{
|
||
D3DXMATRIX m4DynamicShadow=rkTPRS.m_m4DynamicShadow;
|
||
|
||
D3DXVECTOR3 v3Shadow;
|
||
for (UINT uIndex=0; uIndex!=CTerrainPatch::TERRAIN_VERTEX_COUNT; ++uIndex)
|
||
{
|
||
D3DXVec3TransformCoord(&v3Shadow, &akSrcVertex[uIndex].kPosition, &m4DynamicShadow);
|
||
akTransVertex[uIndex].kTexDynamicShadow.x=v3Shadow.x;
|
||
akTransVertex[uIndex].kTexDynamicShadow.y=v3Shadow.y;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool CMapOutdoor::__SoftwareTransformPatch_SetSplatStream(SoftwareTransformPatch_STLVertex* akSrcVertex)
|
||
{
|
||
IDirect3DVertexBuffer8* pkVB=m_kSTPD.m_pkVBSplat[m_kSTPD.m_dwSplatPos++];
|
||
m_kSTPD.m_dwSplatPos%=SoftwareTransformPatch_SData::SPLAT_VB_NUM;
|
||
if (!pkVB)
|
||
return false;
|
||
|
||
DWORD dwVBSize=sizeof(SoftwareTransformPatch_SSplatVertex)*CTerrainPatch::TERRAIN_VERTEX_COUNT;
|
||
SoftwareTransformPatch_SSplatVertex* akDstVertex;
|
||
if (FAILED(
|
||
pkVB->Lock(0, dwVBSize, (BYTE**)&akDstVertex, 0)//D3DLOCK_DISCARD)
|
||
)) return false;
|
||
|
||
for (UINT uIndex=0; uIndex!=CTerrainPatch::TERRAIN_VERTEX_COUNT; ++uIndex)
|
||
*(akDstVertex+uIndex)=*((SoftwareTransformPatch_SSplatVertex*)(akSrcVertex+uIndex));
|
||
|
||
pkVB->Unlock();
|
||
|
||
STATEMANAGER.SetStreamSource(0, pkVB, sizeof(SoftwareTransformPatch_SSplatVertex));
|
||
return true;
|
||
}
|
||
|
||
bool CMapOutdoor::__SoftwareTransformPatch_SetShadowStream(SoftwareTransformPatch_STLVertex* akSrcVertex)
|
||
{
|
||
IDirect3DVertexBuffer8* pkVB=m_kSTPD.m_pkVBSplat[m_kSTPD.m_dwSplatPos++];
|
||
m_kSTPD.m_dwSplatPos%=SoftwareTransformPatch_SData::SPLAT_VB_NUM;
|
||
if (!pkVB)
|
||
return false;
|
||
|
||
DWORD dwVBSize=sizeof(SoftwareTransformPatch_SSplatVertex)*CTerrainPatch::TERRAIN_VERTEX_COUNT;
|
||
SoftwareTransformPatch_SSplatVertex* akDstVertex;
|
||
if (FAILED(
|
||
pkVB->Lock(0, dwVBSize, (BYTE**)&akDstVertex, 0)//D3DLOCK_DISCARD)
|
||
)) return false;
|
||
|
||
SoftwareTransformPatch_STLVertex* pkSrcVertex;
|
||
SoftwareTransformPatch_SSplatVertex* pkDstVertex;
|
||
for (UINT uIndex=0; uIndex!=CTerrainPatch::TERRAIN_VERTEX_COUNT; ++uIndex)
|
||
{
|
||
pkSrcVertex=akSrcVertex+uIndex;
|
||
pkDstVertex=akDstVertex+uIndex;
|
||
pkDstVertex->kPosition=pkSrcVertex->kPosition;
|
||
pkDstVertex->dwDiffuse=pkSrcVertex->dwDiffuse;
|
||
pkDstVertex->dwSpecular=pkSrcVertex->dwFog;
|
||
pkDstVertex->kTex1=pkSrcVertex->kTexStaticShadow;
|
||
pkDstVertex->kTex2=pkSrcVertex->kTexDynamicShadow;
|
||
}
|
||
pkVB->Unlock();
|
||
|
||
|
||
ms_lpd3dDevice->SetStreamSource(0, pkVB, sizeof(SoftwareTransformPatch_SSplatVertex));
|
||
return true;
|
||
}
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_Initialize()
|
||
{
|
||
{
|
||
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::SPLAT_VB_NUM; ++uIndex)
|
||
m_kSTPD.m_pkVBSplat[uIndex]=NULL;
|
||
m_kSTPD.m_dwSplatPos=0;
|
||
}
|
||
|
||
{
|
||
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::NONE_VB_NUM; ++uIndex)
|
||
m_kSTPD.m_pkVBNone[uIndex]=NULL;
|
||
m_kSTPD.m_dwNonePos=0;
|
||
}
|
||
}
|
||
|
||
|
||
bool CMapOutdoor::__SoftwareTransformPatch_Create()
|
||
{
|
||
{
|
||
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::SPLAT_VB_NUM; ++uIndex)
|
||
{
|
||
assert(NULL==m_kSTPD.m_pkVBSplat[uIndex]);
|
||
if (FAILED(
|
||
ms_lpd3dDevice->CreateVertexBuffer(
|
||
sizeof(SoftwareTransformPatch_SSplatVertex)*CTerrainPatch::TERRAIN_VERTEX_COUNT,
|
||
D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
|
||
D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_SPECULAR|D3DFVF_TEX2,
|
||
D3DPOOL_SYSTEMMEM,
|
||
&m_kSTPD.m_pkVBSplat[uIndex]
|
||
)
|
||
)) return false;
|
||
}
|
||
}
|
||
|
||
{
|
||
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::NONE_VB_NUM; ++uIndex)
|
||
{
|
||
assert(NULL==m_kSTPD.m_pkVBNone[uIndex]);
|
||
if (FAILED(
|
||
ms_lpd3dDevice->CreateVertexBuffer(
|
||
sizeof(SoftwareTransformPatch_STVertex)*CTerrainPatch::TERRAIN_VERTEX_COUNT,
|
||
D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
|
||
D3DFVF_XYZRHW,
|
||
D3DPOOL_SYSTEMMEM,
|
||
&m_kSTPD.m_pkVBNone[uIndex]
|
||
)
|
||
)) return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
void CMapOutdoor::__SoftwareTransformPatch_Destroy()
|
||
{
|
||
{
|
||
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::SPLAT_VB_NUM; ++uIndex)
|
||
{
|
||
if (m_kSTPD.m_pkVBSplat[uIndex])
|
||
m_kSTPD.m_pkVBSplat[uIndex]->Release();
|
||
}
|
||
}
|
||
|
||
{
|
||
for (UINT uIndex=0; uIndex!=SoftwareTransformPatch_SData::NONE_VB_NUM; ++uIndex)
|
||
{
|
||
if (m_kSTPD.m_pkVBNone[uIndex])
|
||
m_kSTPD.m_pkVBNone[uIndex]->Release();
|
||
}
|
||
}
|
||
__SoftwareTransformPatch_Initialize();
|
||
}
|
||
|
||
|