Files
FC1/RenderDll/XRenderD3D9/D3DREOcean.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

898 lines
24 KiB
C++

/*=============================================================================
D3DREOcean.cpp : implementation of the Ocean Rendering.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "DriverD3D9.h"
#include "D3DCGVProgram.h"
#include "D3DCGPShader.h"
#include "I3dengine.h"
#include "../Common/NvTriStrip/NVTriStrip.h"
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
//=======================================================================
void CREOcean::GenerateIndices(int nLodCode)
{
CD3D9Renderer *r = gcpRendD3D;
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
HRESULT h;
SPrimitiveGroup pg;
IDirect3DIndexBuffer9* ibuf;
int size;
int flags = D3DUSAGE_WRITEONLY;
D3DPOOL Pool = D3DPOOL_MANAGED;
ushort *dst;
TArray<ushort> Indicies;
if (m_OceanIndicies[nLodCode])
return;
SOceanIndicies *oi = new SOceanIndicies;
m_OceanIndicies[nLodCode] = oi;
if (!(nLodCode & ~LOD_MASK))
{
int nL = nLodCode & LOD_MASK;
pg.offsIndex = 0;
pg.numIndices = m_pIndices[nL].Num();
pg.numTris = pg.numIndices-2;
pg.type = PT_STRIP;
oi->m_Groups.AddElem(pg);
size = pg.numIndices*sizeof(ushort);
h = dv->CreateIndexBuffer(size, flags, D3DFMT_INDEX16, Pool, (IDirect3DIndexBuffer9**)&oi->m_pIndicies, NULL);
ibuf = (IDirect3DIndexBuffer9*)oi->m_pIndicies;
oi->m_nInds = pg.numIndices;
h = ibuf->Lock(0, 0, (void **) &dst, 0);
cryMemcpy(dst, &m_pIndices[nL][0], pg.numIndices*sizeof(ushort));
h = ibuf->Unlock();
return;
}
int nLod = nLodCode & LOD_MASK;
int nl = 1<<nLod;
int nGrid = (OCEANGRID+1);
// set indices
int iIndex = nGrid*nl+nl;
int yStep = nGrid * nl;
for(int a=nl; a<nGrid-1-nl; a+=nl)
{
for(int i=nl; i<nGrid-nl; i+=nl, iIndex+=nl)
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex + yStep);
}
int iNextIndex = (a+nl) * nGrid + nl;
// connect two strips by inserting two degenerated triangles
if(a < nGrid-1-nl*2)
{
Indicies.AddElem(iIndex + yStep - nl);
Indicies.AddElem(iNextIndex);
}
iIndex = iNextIndex;
}
pg.numIndices = Indicies.Num();
pg.numTris = pg.numIndices-2;
pg.type = PT_STRIP;
pg.offsIndex = 0;
oi->m_Groups.AddElem(pg);
// Left
pg.offsIndex = Indicies.Num();
iIndex = nGrid*(nGrid-1);
if (!(nLodCode & (1<<LOD_LEFTSHIFT)))
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex - nGrid * nl + nl);
Indicies.AddElem(iIndex - nGrid * nl);
iIndex = iIndex - nGrid * nl + nl;
yStep = -(nGrid * nl) - nl;
for(int i=nl; i<nGrid-nl; i+=nl, iIndex-=nGrid*nl)
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex + yStep);
}
}
else
{
for(int i=0; i<nGrid-nl; i+=nl*2)
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex - (nGrid * nl) + nl);
Indicies.AddElem(iIndex - nGrid * nl * 2);
if (i < nGrid-nl-nl*2)
Indicies.AddElem(iIndex - nGrid * nl * 2 + nl);
iIndex -= nGrid * nl * 2;
}
}
pg.numIndices = Indicies.Num()-pg.offsIndex;
pg.numTris = pg.numIndices-2;
oi->m_Groups.AddElem(pg);
// Bottom
pg.offsIndex = Indicies.Num();
iIndex = 0;
if (!(nLodCode & (1<<LOD_BOTTOMSHIFT)))
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex + nGrid*nl + nl);
Indicies.AddElem(iIndex + nl);
iIndex = iIndex + nGrid*nl + nl;
yStep = -(nGrid * nl) + nl;
for(int i=nl; i<nGrid-nl; i+=nl, iIndex+=nl)
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex + yStep);
}
}
else
{
for(int i=0; i<nGrid-nl; i+=nl*2)
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex + (nGrid * nl) + nl);
Indicies.AddElem(iIndex + nl * 2);
if (i < nGrid-nl-nl*2)
Indicies.AddElem(iIndex + nGrid * nl + nl * 2);
iIndex += nl * 2;
}
}
pg.numIndices = Indicies.Num()-pg.offsIndex;
pg.numTris = pg.numIndices-2;
oi->m_Groups.AddElem(pg);
// Right
pg.offsIndex = Indicies.Num();
iIndex = nGrid-1;
if (!(nLodCode & (1<<LOD_RIGHTSHIFT)))
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex + nGrid * nl - nl);
Indicies.AddElem(iIndex + nGrid * nl);
iIndex = iIndex + nGrid * nl - nl;
yStep = nGrid * nl + nl;
for(int i=nl; i<nGrid-nl; i+=nl, iIndex+=nGrid*nl)
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex + yStep);
}
}
else
{
for(int i=0; i<nGrid-nl; i+=nl*2)
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex + (nGrid * nl) - nl);
Indicies.AddElem(iIndex + nGrid * nl * 2);
if (i < nGrid-nl-nl*2)
Indicies.AddElem(iIndex + nGrid * nl * 2 - nl);
iIndex += nGrid * nl * 2;
}
}
pg.numIndices = Indicies.Num()-pg.offsIndex;
pg.numTris = pg.numIndices-2;
oi->m_Groups.AddElem(pg);
// Top
pg.offsIndex = Indicies.Num();
iIndex = nGrid*(nGrid-1)+nGrid-1;
if (!(nLodCode & (1<<LOD_TOPSHIFT)))
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex - nGrid*nl - nl);
Indicies.AddElem(iIndex - nl);
iIndex = iIndex - nGrid*nl - nl;
yStep = nGrid * nl - nl;
for(int i=nl; i<nGrid-nl; i+=nl, iIndex-=nl)
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex + yStep);
}
}
else
{
for(int i=0; i<nGrid-nl; i+=nl*2)
{
Indicies.AddElem(iIndex);
Indicies.AddElem(iIndex - (nGrid * nl) - nl);
Indicies.AddElem(iIndex - nl * 2);
if (i < nGrid-nl-nl*2)
Indicies.AddElem(iIndex - nGrid * nl - nl * 2);
iIndex -= nl * 2;
}
}
pg.numIndices = Indicies.Num()-pg.offsIndex;
pg.numTris = pg.numIndices-2;
oi->m_Groups.AddElem(pg);
size = Indicies.Num()*sizeof(ushort);
h = dv->CreateIndexBuffer(size, flags, D3DFMT_INDEX16, Pool, (IDirect3DIndexBuffer9**)&oi->m_pIndicies, NULL);
ibuf = (IDirect3DIndexBuffer9*)oi->m_pIndicies;
oi->m_nInds = Indicies.Num();
h = ibuf->Lock(0, 0, (void **) &dst, 0);
cryMemcpy(dst, &Indicies[0], size);
h = ibuf->Unlock();
}
void CREOcean::UpdateTexture()
{
if (m_CustomTexBind[0]>0 && !CRenderer::CV_r_oceantexupdate)
return;
HRESULT h;
CD3D9Renderer *r = gcpRendD3D;
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
byte data[OCEANGRID][OCEANGRID][4];
double time0 = 0;
ticks(time0);
for(unsigned int y=0; y<OCEANGRID; y++)
{
for( unsigned int x=0; x<OCEANGRID; x++)
{
data[y][x][0] = (byte)(m_Normals[y][x].x * 127.0f);
data[y][x][1] = (byte)(m_Normals[y][x].y * 127.0f);
data[y][x][2] = (byte)(m_Normals[y][x].z * 127.0f);
data[y][x][3] = 0;
}
}
if (m_CustomTexBind[0] <= 0)
{
char name[128];
sprintf(name, "$AutoOcean_%d", r->m_TexGenID++);
STexPic *tp = r->m_TexMan->CreateTexture(name, OCEANGRID, OCEANGRID, 1, FT_NOMIPS | FT_NOSTREAM, FT2_NODXT, &data[0][0][0], eTT_DSDTBump, -1.0f, -1.0f, 0, NULL, 0, eTF_0888);
m_CustomTexBind[0] = tp->m_Bind;
}
else
{
STexPicD3D *tp = (STexPicD3D *)gRenDev->m_TexMan->m_Textures[m_CustomTexBind[0]-TX_FIRSTBIND];
IDirect3DTexture9 *pID3DTexture = (IDirect3DTexture9*)tp->m_RefTex.m_VidTex;
D3DLOCKED_RECT d3dlr;
h = pID3DTexture->LockRect(0, &d3dlr, NULL, 0);
D3DSURFACE_DESC ddsdDescDest;
pID3DTexture->GetLevelDesc(0, &ddsdDescDest);
if (d3dlr.Pitch == tp->m_Width*4)
cryMemcpy(d3dlr.pBits, data, tp->m_Width*tp->m_Height*4);
else
{
switch(ddsdDescDest.Format)
{
case D3DFMT_X8L8V8U8:
{
byte *pDst = (byte *)d3dlr.pBits;
byte *pSrc = &data[0][0][0];
for (int i=0; i<tp->m_Height; i++)
{
cryMemcpy(pDst, pSrc, tp->m_Width*4);
pDst += d3dlr.Pitch;
pSrc += tp->m_Width*4;
}
}
break;
case D3DFMT_L6V5U5:
break;
case D3DFMT_V8U8:
{
byte *pDst = (byte *)d3dlr.pBits;
byte *pSrc = &data[0][0][0];
for (int i=0; i<tp->m_Height; i++)
{
for (int j=0; j<tp->m_Width; j++)
{
pDst[j*2+0] = pSrc[j*4+0];
pDst[j*2+1] = pSrc[j*4+1];
}
pDst += d3dlr.Pitch;
pSrc += tp->m_Width*4;
}
}
break;
default:
assert(0);
}
}
h = pID3DTexture->UnlockRect(0);
}
unticks(time0);
m_RS.m_StatsTimeTexUpdate = (float)(time0*1000.0*g_SecondsPerCycle);
}
void CREOcean::DrawOceanSector(SOceanIndicies *oi)
{
CD3D9Renderer *r = gcpRendD3D;
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
HRESULT h;
h = dv->SetIndices((IDirect3DIndexBuffer9 *)oi->m_pIndicies);
for (int i=0; i<oi->m_Groups.Num(); i++)
{
SPrimitiveGroup *g = &oi->m_Groups[i];
switch (g->type)
{
case PT_STRIP:
if (FAILED(h=dv->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, 0, (OCEANGRID+1)*(OCEANGRID+1), g->offsIndex, g->numTris)))
{
r->Error("CREOcean::DrawOceanSector: DrawIndexedPrimitive error", h);
return;
}
break;
case PT_LIST:
if (FAILED(h=dv->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, (OCEANGRID+1)*(OCEANGRID+1), g->offsIndex, g->numTris)))
{
r->Error("CREOcean::DrawOceanSector: DrawIndexedPrimitive error", h);
return;
}
break;
case PT_FAN:
if (FAILED(h=dv->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0, 0, (OCEANGRID+1)*(OCEANGRID+1), g->offsIndex, g->numTris)))
{
r->Error("CREOcean::DrawOceanSector: DrawIndexedPrimitive error", h);
return;
}
break;
}
gRenDev->m_nPolygons += g->numTris;
}
}
static _inline int Compare(SOceanSector *& p1, SOceanSector *& p2)
{
if(p1->m_Flags > p2->m_Flags)
return 1;
else
if(p1->m_Flags < p2->m_Flags)
return -1;
return 0;
}
static _inline float sCalcSplash(SSplash *spl, float fX, float fY)
{
CD3D9Renderer *r = gcpRendD3D;
float fDeltaTime = r->m_RP.m_RealTime - spl->m_fStartTime;
float fScaleFactor = 1.0f / (r->m_RP.m_RealTime - spl->m_fLastTime + 1.0f);
float vDelt[2];
// Calculate 2D distance
vDelt[0] = spl->m_Pos[0] - fX; vDelt[1] = spl->m_Pos[1] - fY;
float fSqDist = vDelt[0]*vDelt[0] + vDelt[1]*vDelt[1];
// Inverse square root
unsigned int *n1 = (unsigned int *)&fSqDist;
unsigned int nn = 0x5f3759df - (*n1 >> 1);
float *n2 = (float *)&nn;
float fDistSplash = 1.0f / ((1.5f - (fSqDist * 0.5f) * *n2 * *n2) * *n2);
// Emulate sin waves
float fDistFactor = fDeltaTime*10.0f - fDistSplash + 4.0f;
fDistFactor = CLAMP(fDistFactor, 0.0f, 1.0f);
float fRad = (fDistSplash - fDeltaTime*10) * 0.4f / 3.1416f * 1024.0f;
float fSin = gRenDev->m_RP.m_tSinTable[QRound(fRad)&0x3ff] * fDistFactor;
return fSin * fScaleFactor * spl->m_fForce;
}
float *CREOcean::mfFillAdditionalBuffer(SOceanSector *os, int nSplashes, SSplash *pSplashes[], int& nCurSize, int nLod, float fSize)
{
float *pHM, *pTZ;
int nFloats = (os->m_Flags & OSF_NEEDHEIGHTS) ? 1 : 0;
if (nSplashes)
nFloats++;
pTZ = (float *)GetVBPtr((OCEANGRID+1)*(OCEANGRID+1));
pHM = pTZ;
int nStep = 1<<nLod;
if (!nSplashes)
{
for (int ty=0; ty<OCEANGRID+1; ty+=nStep)
{
pTZ = &pHM[ty*(OCEANGRID+1)*2];
for (int tx=0; tx<OCEANGRID+1; tx+=nStep)
{
float fX = m_Pos[ty][tx][0]*fSize+os->x;
float fY = m_Pos[ty][tx][1]*fSize+os->y;
float fZ = GetHMap(fX, fY);
pTZ[0] = fZ;
pTZ += nStep*2;
}
}
}
else
if (!(os->m_Flags & OSF_NEEDHEIGHTS))
{
for (int ty=0; ty<OCEANGRID+1; ty+=nStep)
{
pTZ = &pHM[ty*(OCEANGRID+1)*2];
for (int tx=0; tx<OCEANGRID+1; tx+=nStep)
{
float fX = m_Pos[ty][tx][0]*fSize+os->x;
float fY = m_Pos[ty][tx][1]*fSize+os->y;
float fSplash = 0;
for (int n=0; n<nSplashes; n++)
{
SSplash *spl = pSplashes[n];
fSplash += sCalcSplash(spl, fX, fY);
}
pTZ[0] = 0;
pTZ[1] = fSplash;
pTZ += nStep*2;
}
}
}
else
{
for (int ty=0; ty<OCEANGRID+1; ty+=nStep)
{
pTZ = &pHM[ty*(OCEANGRID+1)*2];
for (int tx=0; tx<OCEANGRID+1; tx+=nStep)
{
float fX = m_Pos[ty][tx][0]*fSize+os->x;
float fY = m_Pos[ty][tx][1]*fSize+os->y;
float fZ = GetHMap(fX, fY);
pTZ[0] = fZ;
float fSplash = 0;
for (int n=0; n<nSplashes; n++)
{
SSplash *spl = pSplashes[n];
fSplash += sCalcSplash(spl, fX, fY);
}
pTZ[1] = fSplash; // / (float)nSplashes;
pTZ += nStep*2;
}
}
}
return pHM;
}
void CREOcean::mfReset()
{
for (int i=0; i<NUM_OCEANVBS; i++)
{
IDirect3DVertexBuffer9* vb = (IDirect3DVertexBuffer9*)m_pVertsPool[i];
SAFE_RELEASE(vb);
m_pVertsPool[i] = NULL;
}
if (m_pBuffer)
{
gRenDev->ReleaseBuffer(m_pBuffer);
m_pBuffer = NULL;
}
}
void CREOcean::InitVB()
{
CD3D9Renderer *r = gcpRendD3D;
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
HRESULT h;
m_nNumVertsInPool = (OCEANGRID+1)*(OCEANGRID+1);
int size = m_nNumVertsInPool * sizeof(struct_VERTEX_FORMAT_TEX2F);
for (int i=0; i<NUM_OCEANVBS; i++)
{
h = dv->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFVF_TEX1, D3DPOOL_DEFAULT, (IDirect3DVertexBuffer9**)&m_pVertsPool[i], NULL);
}
m_nCurVB = 0;
m_bLockedVB = false;
{
D3DVERTEXELEMENT9 elem[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, // position
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, // normal
D3DDECL_END()
};
h = dv->CreateVertexDeclaration(&elem[0], (IDirect3DVertexDeclaration9**)&m_VertDecl);
}
{
D3DVERTEXELEMENT9 elem[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, // position
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, // normal
{1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0}, // heightmpa/splashes
D3DDECL_END()
};
h = dv->CreateVertexDeclaration(&elem[0], (IDirect3DVertexDeclaration9**)&m_VertDeclHeightSplash);
}
}
struct_VERTEX_FORMAT_TEX2F *CREOcean::GetVBPtr(int nVerts)
{
HRESULT h;
struct_VERTEX_FORMAT_TEX2F *pVertices = NULL;
if (nVerts > m_nNumVertsInPool)
{
assert(0);
return NULL;
}
if (m_bLockedVB)
UnlockVBPtr();
m_nCurVB++;
if (m_nCurVB >= NUM_OCEANVBS)
m_nCurVB = 0;
IDirect3DVertexBuffer9 *pVB = (IDirect3DVertexBuffer9 *)m_pVertsPool[m_nCurVB];
h = pVB->Lock(0, 0, (void **) &pVertices, D3DLOCK_DISCARD);
m_bLockedVB = true;
return pVertices;
}
void CREOcean::UnlockVBPtr()
{
if (m_bLockedVB)
{
IDirect3DVertexBuffer9 *pVB = (IDirect3DVertexBuffer9 *)m_pVertsPool[m_nCurVB];
HRESULT hr = pVB->Unlock();
m_bLockedVB = false;
}
}
void CREOcean::mfDrawOceanSectors()
{
float x, y;
CD3D9Renderer *r = gcpRendD3D;
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
HRESULT h;
CVertexBuffer *vb = m_pBuffer;
int i;
m_RS.m_StatsNumRendOceanSectors = 0;
ushort *saveInds = r->m_RP.m_RendIndices;
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
float fMaxDist = eng->GetMaxViewDistance() / 1.0f;
CCamera cam = r->GetCamera();
Vec3d mins;
Vec3d maxs;
Vec3d cameraPos = cam.GetPos();
float fCurX = (float)((int)cameraPos[0] & ~255) + 128.0f;
float fCurY = (float)((int)cameraPos[1] & ~255) + 128.0f;
float fSize = (float)CRenderer::CV_r_oceansectorsize;
float fHeightScale = (float)CRenderer::CV_r_oceanheightscale;
fMaxDist = (float)((int)(fMaxDist / fSize + 1.0f)) * fSize;
if (fSize != m_fSectorSize)
{
m_fSectorSize = fSize;
for (int i=0; i<256; i++)
{
m_OceanSectorsHash[i].Free();
}
}
float fWaterLevel = eng->GetWaterLevel();
CVProgram *vp = NULL;
int nMaxSplashes = CLAMP(CRenderer::CV_r_oceanmaxsplashes, 0, 16);
//x = y = 0;
//x = fCurX;
//y = fCurY;
m_VisOceanSectors.SetUse(0);
int osNear = -1;
int nMinLod = 65536;
for (y=fCurY-fMaxDist; y<fCurY+fMaxDist; y+=fSize)
{
for (x=fCurX-fMaxDist; x<fCurX+fMaxDist; x+=fSize)
{
SOceanSector *os = GetSectorByPos(x, y);
if (!(os->m_Flags & (OSF_FIRSTTIME | OSF_VISIBLE)))
continue;
mins.x = x+m_MinBound.x*fSize;
mins.y = y+m_MinBound.y*fSize;
mins.z = fWaterLevel+m_MinBound.z*fHeightScale;
maxs.x = x+fSize+m_MaxBound.x*fSize;
maxs.y = y+fSize+m_MaxBound.y*fSize;
maxs.z = fWaterLevel+m_MaxBound.z*fHeightScale;
int cull = cam.IsAABBVisible_hierarchical( AABB(mins,maxs) );
if (cull != CULL_EXCLUSION)
{
Vec3d vCenter = (mins + maxs) * 0.5f;
os->nLod = GetLOD(cameraPos, vCenter);
if (os->nLod < nMinLod)
{
nMinLod = os->nLod;
osNear = m_VisOceanSectors.Num();
}
os->m_Frame = gRenDev->m_cEF.m_Frame;
os->m_Flags &= ~OSF_LODUPDATED;
m_VisOceanSectors.AddElem(os);
}
}
}
if (m_VisOceanSectors.Num())
{
LinkVisSectors(fSize);
::Sort(&m_VisOceanSectors[0], m_VisOceanSectors.Num());
}
int nCurSize;
bool bCurNeedBuffer = false;
h = dv->SetVertexDeclaration((LPDIRECT3DVERTEXDECLARATION9)m_VertDecl);
float *pHM, *pTZ;
int nIndVP = CRenderer::CV_r_waterreflections ? 0 : 1;
for (i=0; i<m_VisOceanSectors.Num(); i++)
{
SOceanSector *os = m_VisOceanSectors[i];
// if ((int)os != 0x1ac32240 && (int)os != 0xe985fc8)
// continue;
int nLod = os->nLod;
bool bL = (nLod < GetSectorByPos(os->x-fSize, os->y)->nLod);
bool bR = (nLod < GetSectorByPos(os->x+fSize, os->y)->nLod);
bool bT = (nLod < GetSectorByPos(os->x, os->y+fSize)->nLod);
bool bB = (nLod < GetSectorByPos(os->x, os->y-fSize)->nLod);
int nLodCode = nLod + (bL<<LOD_LEFTSHIFT) + (bR<<LOD_RIGHTSHIFT) + (bT<<LOD_TOPSHIFT) + (bB<<LOD_BOTTOMSHIFT);
if (!m_OceanIndicies[nLodCode])
GenerateIndices(nLodCode);
int nSplashes = 0;
SSplash *pSplashes[16];
int nS;
for (nS=0; nS<r->m_RP.m_Splashes.Num(); nS++)
{
SSplash *spl = &r->m_RP.m_Splashes[nS];
float fCurRadius = spl->m_fCurRadius;
if (spl->m_Pos[0]-fCurRadius > os->x+fSize ||
spl->m_Pos[1]-fCurRadius > os->y+fSize ||
spl->m_Pos[0]+fCurRadius < os->x ||
spl->m_Pos[1]+fCurRadius < os->y)
continue;
pSplashes[nSplashes++] = spl;
if (nSplashes == nMaxSplashes)
break;
}
if (os->m_Flags & OSF_FIRSTTIME)
{
pTZ = (float *)GetVBPtr((OCEANGRID+1)*(OCEANGRID+1));
pHM = pTZ;
float fMinLevel = 99999.0f;
bool bBlend = false;
bool bNeedHeights = false;
for (uint ty=0; ty<OCEANGRID+1; ty++)
{
for (uint tx=0; tx<OCEANGRID+1; tx++)
{
float fX = m_Pos[ty][tx][0]*fSize+os->x;
float fY = m_Pos[ty][tx][1]*fSize+os->y;
float fZ = GetHMap(fX, fY);
pTZ[0] = fZ;
pTZ += 2;
fMinLevel = min(fMinLevel, fZ);
if (!bBlend && fWaterLevel-fZ <= 1.0f)
bBlend = true;
if (fWaterLevel-fZ < 16.0f)
bNeedHeights = true;
}
}
os->m_Flags &= ~OSF_FIRSTTIME;
if (fMinLevel <= fWaterLevel)
os->m_Flags |= OSF_VISIBLE;
//bNeedHeights = bBlend = false;
if (bNeedHeights)
os->m_Flags |= OSF_NEEDHEIGHTS;
if (bBlend)
{
os->m_Flags |= OSF_BLEND;
os->RenderState = GS_DEPTHWRITE | GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA;
}
else
os->RenderState = GS_DEPTHWRITE;
}
else
if ((os->m_Flags & OSF_NEEDHEIGHTS) || nSplashes)
pHM = mfFillAdditionalBuffer(os, nSplashes, pSplashes, nCurSize, nLod, fSize);
m_RS.m_StatsNumRendOceanSectors++;
r->EF_SetState(os->RenderState);
int nVP = 0;
if (os->m_Flags & OSF_NEEDHEIGHTS)
nVP += OVP_HEIGHT;
if (nSplashes)
nVP++;
CVProgram *curVP = m_VPs[nVP];
if (!curVP)
continue;
if (vp != curVP)
{
vp = curVP;
vp->mfSet(true, NULL, 0);
}
int nFloats = (os->m_Flags & OSF_NEEDHEIGHTS) ? 1 : 0;
if (nSplashes)
nFloats++;
UnlockVBPtr();
if (nFloats)
{
IDirect3DVertexBuffer9 *pVB = (IDirect3DVertexBuffer9 *)m_pVertsPool[m_nCurVB];
h = dv->SetStreamSource(1, pVB, 0, sizeof(struct_VERTEX_FORMAT_TEX2F));
if (!bCurNeedBuffer)
{
h = dv->SetVertexDeclaration((LPDIRECT3DVERTEXDECLARATION9)m_VertDeclHeightSplash);
bCurNeedBuffer = true;
}
}
else
if (bCurNeedBuffer)
{
h = dv->SetStreamSource(1, NULL, 0, 0);
h = dv->SetVertexDeclaration((LPDIRECT3DVERTEXDECLARATION9)m_VertDecl);
bCurNeedBuffer = false;
}
float param[4];
param[0] = os->x;
param[1] = os->y;
param[2] = 0;
param[3] = 0;
CCGVProgram_D3D *vpD3D = (CCGVProgram_D3D *)vp;
SCGBind *pBind = vpD3D->mfGetParameterBind("PosOffset");
if (pBind)
vpD3D->mfParameter4f(pBind, param);
pBind = vpD3D->mfGetParameterBind("PosScale");
param[0] = fSize;
param[1] = fSize;
param[2] = fHeightScale;
param[3] = 1;
if (pBind)
vpD3D->mfParameter4f(pBind, param);
/*if (nSplashes)
{
static Vec3d sPos;
static float sTime;
sPos = Vec3d(306, 1942, 0);
if ((GetAsyncKeyState(VK_NUMPAD1) & 0x8000))
sTime = r->m_RP.m_RealTime;
float fForce = 1.5f;
cgBindIter *pBind = vpGL->mfGetParameterBind("Splash1");
if (pBind)
{
param[0] = sPos[0];
param[1] = sPos[1];
param[2] = sPos[2];
param[3] = 0;
vpGL->mfParameter4f(pBind, param);
}
pBind = vpGL->mfGetParameterBind("Time");
if (pBind)
{
float fDeltaTime = r->m_RP.m_RealTime - sTime;
float fScaleFactor = 1.0f / (r->m_RP.m_RealTime - sTime + 1.0f);
param[0] = fForce * fScaleFactor;
param[1] = 0;
param[2] = -fDeltaTime*10;
param[3] = fDeltaTime*10.0f;
vpGL->mfParameter4f(pBind, param);
}
}*/
DrawOceanSector(m_OceanIndicies[nLodCode]);
}
}
void CREOcean::mfDrawOceanScreenLod()
{
}
bool CREOcean::mfDraw(SShader *ef, SShaderPass *sfm)
{
double time0 = 0;
ticks(time0);
if (!m_pVertsPool[0])
InitVB();
if (!m_pBuffer)
m_pBuffer = gRenDev->CreateBuffer((OCEANGRID+1)*(OCEANGRID+1), VERTEX_FORMAT_P3F_N, "Ocean", true);
if (CRenderer::CV_r_oceanrendtype == 0)
mfDrawOceanSectors();
else
mfDrawOceanScreenLod();
unticks(time0);
m_RS.m_StatsTimeRendOcean = (float)(time0*1000.0*g_SecondsPerCycle);
// gRenDev->PostLoad();
return true;
}
bool CREOcean::mfPreDraw(SShaderPass *sl)
{
CVertexBuffer *vb = m_pBuffer;
for (int i=0; i<VSF_NUM; i++)
{
if (vb->m_VS[i].m_bLocked)
gcpRendD3D->UnlockBuffer(vb, i);
}
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
HRESULT h;
h = dv->SetStreamSource(0, (IDirect3DVertexBuffer9 *)vb->m_VS[VSF_GENERAL].m_VertBuf.m_pPtr, 0, m_VertexSize[vb->m_vertexformat]);
return true;
}
char BoxSides[0x40*8] = {
0,0,0,0, 0,0,0,0, //00
0,4,6,2, 0,0,0,4, //01
7,5,1,3, 0,0,0,4, //02
0,0,0,0, 0,0,0,0, //03
0,1,5,4, 0,0,0,4, //04
0,1,5,4, 6,2,0,6, //05
7,5,4,0, 1,3,0,6, //06
0,0,0,0, 0,0,0,0, //07
7,3,2,6, 0,0,0,4, //08
0,4,6,7, 3,2,0,6, //09
7,5,1,3, 2,6,0,6, //0a
0,0,0,0, 0,0,0,0, //0b
0,0,0,0, 0,0,0,0, //0c
0,0,0,0, 0,0,0,0, //0d
0,0,0,0, 0,0,0,0, //0e
0,0,0,0, 0,0,0,0, //0f
0,2,3,1, 0,0,0,4, //10
0,4,6,2, 3,1,0,6, //11
7,5,1,0, 2,3,0,6, //12
0,0,0,0, 0,0,0,0, //13
0,2,3,1, 5,4,0,6, //14
1,5,4,6, 2,3,0,6, //15
7,5,4,0, 2,3,0,6, //16
0,0,0,0, 0,0,0,0, //17
0,2,6,7, 3,1,0,6, //18
0,4,6,7, 3,1,0,6, //19
7,5,1,0, 2,6,0,6, //1a
0,0,0,0, 0,0,0,0, //1b
0,0,0,0, 0,0,0,0, //1c
0,0,0,0, 0,0,0,0, //1d
0,0,0,0, 0,0,0,0, //1e
0,0,0,0, 0,0,0,0, //1f
7,6,4,5, 0,0,0,4, //20
0,4,5,7, 6,2,0,6, //21
7,6,4,5, 1,3,0,6, //22
0,0,0,0, 0,0,0,0, //23
7,6,4,0, 1,5,0,6, //24
0,1,5,7, 6,2,0,6, //25
7,6,4,0, 1,3,0,6, //26
0,0,0,0, 0,0,0,0, //27
7,3,2,6, 4,5,0,6, //28
0,4,5,7, 3,2,0,6, //29
6,4,5,1, 3,2,0,6, //2a
0,0,0,0, 0,0,0,0, //2b
0,0,0,0, 0,0,0,0, //2c
0,0,0,0, 0,0,0,0, //2d
0,0,0,0, 0,0,0,0, //2e
0,0,0,0, 0,0,0,0, //2f
0,0,0,0, 0,0,0,0, //30
0,0,0,0, 0,0,0,0, //31
0,0,0,0, 0,0,0,0, //32
0,0,0,0, 0,0,0,0, //33
0,0,0,0, 0,0,0,0, //34
0,0,0,0, 0,0,0,0, //35
0,0,0,0, 0,0,0,0, //36
0,0,0,0, 0,0,0,0, //37
0,0,0,0, 0,0,0,0, //38
0,0,0,0, 0,0,0,0, //39
0,0,0,0, 0,0,0,0, //3a
0,0,0,0, 0,0,0,0, //3b
0,0,0,0, 0,0,0,0, //3c
0,0,0,0, 0,0,0,0, //3d
0,0,0,0, 0,0,0,0, //3e
0,0,0,0, 0,0,0,0, //3f
};