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

4180 lines
116 KiB
C++

/*=============================================================================
D3DTextures.cpp : Direct3D specific texture manager implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honitch Andrey
=============================================================================*/
#include "stdafx.h"
#include "DriverD3D8.h"
#include "I3dengine.h"
int CD3D8TexMan::m_Format = D3DFMT_A8R8G8B8;
int CD3D8TexMan::m_FirstBind = 1;
TTextureMap CD3D8TexMan::m_RefTexs;
//===============================================================================
void STexPic::ReleaseHW()
{
}
void STexPic::SetFilter()
{
}
void STexPic::SetWrapping()
{
}
void STexPic::Set()
{
}
void STexPic::SetClamp(bool bEnable)
{
}
void STexPicD3D::Release(bool bForce)
{
STexPic::Release(bForce);
}
void STexPicD3D::ReleaseHW()
{
if (!(m_Flags2 & FT2_WASUNLOADED) && (m_Bind && m_Bind != TX_FIRSTBIND))
{
m_Flags2 &= ~FT2_PARTIALLYLOADED;
if (m_LoadedSize)
CTexMan::m_StatsCurTexMem -= m_LoadedSize;
else
CTexMan::m_StatsCurTexMem -= m_Size;
m_LoadedSize = 0;
Unlink();
if (!m_RefTex)
return;
CD3D8Renderer *r = gcpRendD3D;
LPDIRECT3DDEVICE8 dv = r->mfGetD3DDevice();
IDirect3DBaseTexture8 *pTex = (IDirect3DBaseTexture8*)m_RefTex->m_VidTex;
SAFE_RELEASE(pTex);
m_RefTex->m_VidTex = NULL;
}
}
void STexPicD3D::SetClamp(bool bEnable)
{
if (!m_RefTex || !m_RefTex->m_VidTex)
return;
if (bEnable)
m_RefTex->bRepeats = false;
else
m_RefTex->bRepeats = true;
}
void STexPicD3D::Set()
{
if (!m_RefTex)
return;
CD3D8Renderer *r = gcpRendD3D;
int tmu = r->m_TexMan->m_CurStage;
if ((m_Flags2 & (FT2_WASUNLOADED | FT2_PARTIALLYLOADED)))
{
int Size = m_LoadedSize;
Restore();
if (Size != m_LoadedSize)
r->mStages[tmu].Texture = NULL;
}
else
Relink(&STexPic::m_Root);
if (CRenderer::CV_r_log == 3 || CRenderer::CV_r_log == 4)
gRenDev->Logv(SRendItem::m_RecurseLevel, "STexPic::Set(): (%d) \"%s\"\n", tmu, m_SourceName.c_str());
if (!m_RefTex->m_VidTex)
return;
LPDIRECT3DDEVICE8 dv = r->mfGetD3DDevice();
HRESULT hr;
if (r->mStages[tmu].Texture == this)
return;
r->mStages[tmu].Texture = this;
hr = dv->SetTexture(tmu, (IDirect3DBaseTexture8*)m_RefTex->m_VidTex);
#ifndef _XBOX
if (m_RefTex->m_Pal>0 && (m_Flags & FT_PALETTED) && r->mStages[tmu].Palette != m_RefTex->m_Pal)
{
r->mStages[tmu].Palette = m_RefTex->m_Pal;
dv->SetCurrentTexturePalette(m_RefTex->m_Pal);
}
#else
if (m_RefTex->m_pPal && (m_Flags & FT_PALETTED) && r->mStages[tmu].pPalette != m_RefTex->m_pPal)
{
r->mStages[tmu].pPalette = m_RefTex->m_pPal;
dv->SetPalette(tmu, m_RefTex->m_pPal);
}
if (m_eTT == eTT_DSDTBump)
dv->SetTextureStageState( tmu, D3DTSS_COLORSIGN, D3DTSIGN_RSIGNED|D3DTSIGN_GSIGNED|D3DTSIGN_BSIGNED );
else
dv->SetTextureStageState( tmu, D3DTSS_COLORSIGN, 0 );
#endif
if(m_RefTex->bMips!=r->mStages[tmu].UseMips || m_RefTex->m_MagFilter!=r->mStages[tmu].MagFilter || m_RefTex->m_MinFilter!=r->mStages[tmu].MinFilter || m_RefTex->m_AnisLevel!=r->mStages[tmu].Anisotropic)
{
r->mStages[tmu].UseMips = m_RefTex->bMips;
r->mStages[tmu].Anisotropic = m_RefTex->m_AnisLevel;
r->mStages[tmu].MagFilter = m_RefTex->m_MagFilter;
r->mStages[tmu].MinFilter = m_RefTex->m_MinFilter;
if (!m_RefTex->bMips)
{
dv->SetTextureStageState( tmu, D3DTSS_MIPFILTER, D3DTEXF_NONE);
dv->SetTextureStageState( tmu, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
dv->SetTextureStageState( tmu, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
}
else
if (m_RefTex->m_AnisLevel > 1)
{
dv->SetTextureStageState( tmu, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
dv->SetTextureStageState( tmu, D3DTSS_MAGFILTER, D3DTEXF_ANISOTROPIC );
dv->SetTextureStageState( tmu, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC );
dv->SetTextureStageState( tmu, D3DTSS_MAXANISOTROPY, m_RefTex->m_AnisLevel);
}
else
{
CD3D8TexMan *tm = (CD3D8TexMan *)r->m_TexMan;
dv->SetTextureStageState(tmu, D3DTSS_MIPFILTER, tm->GetMipFilter() );
dv->SetTextureStageState(tmu, D3DTSS_MAGFILTER, m_RefTex->m_MagFilter );
dv->SetTextureStageState(tmu, D3DTSS_MINFILTER, m_RefTex->m_MinFilter );
}
}
if (m_RefTex->bRepeats != r->mStages[tmu].Repeat)
{
r->mStages[tmu].Repeat = m_RefTex->bRepeats;
dv->SetTextureStageState(tmu, D3DTSS_ADDRESSU, m_RefTex->bRepeats ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
dv->SetTextureStageState(tmu, D3DTSS_ADDRESSV, m_RefTex->bRepeats ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
if (m_RefTex->m_Type == TEXTGT_CUBEMAP)
dv->SetTextureStageState(tmu, D3DTSS_ADDRESSW, m_RefTex->bRepeats ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
}
gRenDev->m_TexMan->m_LastTex = this;
// SaveTGA("bug.tga", false);
}
void CD3D8TexMan::SetTexture(int Id, ETexType eTT)
{
CD3D8Renderer *r = gcpRendD3D;
LPDIRECT3DDEVICE8 dv = r->mfGetD3DDevice();
int tmu = r->m_TexMan->m_CurStage;
SRefTex *rt = NULL;
if (Id > TX_FIRSTBIND)
{
STexPicD3D *tp = (STexPicD3D *)m_Textures[Id-TX_FIRSTBIND];
if (tp && tp->m_Bind == Id)
{
tp->Set();
return;
}
}
if (!rt)
{
TTextureMapItor it = m_RefTexs.find(Id);
if (it == m_RefTexs.end())
{
dv->SetTexture(tmu, NULL);
r->mStages[tmu].Texture = NULL;
return;
}
rt = it->second;
}
r->mStages[tmu].Texture = NULL;
dv->SetTexture(tmu, (IDirect3DBaseTexture8*)rt->m_VidTex);
#ifndef _XBOX
if (rt->m_Pal>0 && rt->m_Pal!=r->mStages[tmu].Palette)
{
r->mStages[tmu].Palette = rt->m_Pal;
dv->SetCurrentTexturePalette(rt->m_Pal);
}
#else
if (rt->m_pPal && r->mStages[tmu].pPalette != rt->m_pPal)
{
r->mStages[tmu].pPalette = rt->m_pPal;
dv->SetPalette(tmu, rt->m_pPal);
}
dv->SetTextureStageState( tmu, D3DTSS_COLORSIGN, 0 );
#endif
if(rt->bMips!=r->mStages[tmu].UseMips || rt->m_MagFilter!=r->mStages[tmu].MagFilter || rt->m_MinFilter!=r->mStages[tmu].MinFilter || rt->m_AnisLevel!=r->mStages[tmu].Anisotropic)
{
r->mStages[tmu].UseMips = rt->bMips;
r->mStages[tmu].Anisotropic = rt->m_AnisLevel;
r->mStages[tmu].MagFilter = rt->m_MagFilter;
r->mStages[tmu].MinFilter = rt->m_MinFilter;
if (!rt->bMips)
{
dv->SetTextureStageState( tmu, D3DTSS_MIPFILTER, D3DTEXF_NONE);
dv->SetTextureStageState( tmu, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
dv->SetTextureStageState( tmu, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
}
else
if (rt->m_AnisLevel > 1)
{
dv->SetTextureStageState( tmu, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
dv->SetTextureStageState( tmu, D3DTSS_MAGFILTER, D3DTEXF_ANISOTROPIC );
dv->SetTextureStageState( tmu, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC );
dv->SetTextureStageState( tmu, D3DTSS_MAXANISOTROPY, rt->m_AnisLevel);
}
else
{
dv->SetTextureStageState(tmu, D3DTSS_MIPFILTER, m_MipFilter );
dv->SetTextureStageState(tmu, D3DTSS_MAGFILTER, rt->m_MagFilter );
dv->SetTextureStageState(tmu, D3DTSS_MINFILTER, rt->m_MinFilter );
}
}
if (rt->bRepeats != r->mStages[tmu].Repeat)
{
r->mStages[tmu].Repeat = rt->bRepeats;
dv->SetTextureStageState(tmu, D3DTSS_ADDRESSU, rt->bRepeats ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
dv->SetTextureStageState(tmu, D3DTSS_ADDRESSV, rt->bRepeats ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
if (rt->m_Type == TEXTGT_CUBEMAP)
dv->SetTextureStageState(tmu, D3DTSS_ADDRESSW, rt->bRepeats ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP);
}
if (rt->m_SrcTex)
m_LastTex = rt->m_SrcTex;
}
int SShaderTexUnit::mfSetTexture(int State, int nt)
{
CD3D8Renderer *rd = gcpRendD3D;
if (nt >= 0 && rd->m_TexMan->m_CurStage != nt)
{
rd->m_TexMan->m_CurStage = nt;
}
SShaderTexUnit *pSTU;
int nSetID = -1;
if (m_TexPic && m_TexPic->m_Bind < EFTT_MAX)
{
if (m_TexPic->m_Bind == EFTT_LIGHTMAP)
{
if (gRenDev->m_RP.m_pCurObject->m_nLMId)
nSetID = gRenDev->m_RP.m_pCurObject->m_nLMId;
}
if (m_TexPic->m_Bind == EFTT_LIGHTMAP_DIR)
{
if (gRenDev->m_RP.m_pCurObject->m_nLMDirId)
nSetID = gRenDev->m_RP.m_pCurObject->m_nLMDirId;
}
if (nSetID < 0)
{
if (!rd->m_RP.m_pShaderResources || !rd->m_RP.m_pShaderResources->m_Textures[m_TexPic->m_Bind])
{
iLog->Log("WARNING: SShaderTexUnit::mfSetTexture: Missed template texture '%s' for shader '%s'\n", gcEf.mfTemplateTexIdToName(m_TexPic->m_Bind), rd->m_RP.m_pShader->GetName());
pSTU = this;
}
else
pSTU = &rd->m_RP.m_pShaderResources->m_Textures[m_TexPic->m_Bind]->m_TU;
}
}
else
pSTU = this;
if (pSTU->m_AnimInfo)
pSTU->mfUpdate();
if (pSTU->m_TexPic)
{
if (CRenderer::CV_r_nobindtextures==1)
rd->SetTexture(0);
else if (CRenderer::CV_r_nobindtextures==2)
rd->SetTexture(4096);
else
if (nSetID > 0)
{
gRenDev->m_TexMan->SetTexture(nSetID, eTT_Base);
}
else
{
int bind = pSTU->m_TexPic->m_Bind;
if (bind >= TX_FIRSTBIND)
{
pSTU->m_TexPic->Set();
//pSTU->m_TexPic->SaveJPG("white_ddn.jpg", false);
}
else
switch (bind)
{
case TO_FROMRE0:
case TO_FROMRE1:
case TO_FROMRE2:
case TO_FROMRE3:
{
if (rd->m_RP.m_pRE)
bind = rd->m_RP.m_pRE->m_CustomTexBind[bind-TO_FROMRE0];
if (bind < 0)
return false;
rd->SetTexture(bind, pSTU->m_TexPic->m_eTT);
}
break;
case TO_FROMOBJ:
{
if (rd->m_RP.m_pCurObject)
bind = rd->m_RP.m_pCurObject->m_NumCM;
if (bind <= 0)
return false;
rd->SetTexture(bind, eTT_Base);
}
break;
case TO_FROMLIGHT:
{
bool bRes = false;
if (rd->m_RP.m_nCurLight < rd->m_RP.m_DLights.Num())
{
CDLight *dl = rd->m_RP.m_pCurLight;
if (dl && dl->m_pLightImage)
{
bRes = true;
STexPic *tp = (STexPic *)dl->m_pLightImage;
if (dl->m_NumCM >= 0)
tp = CTexMan::m_CustomCMaps[dl->m_NumCM].m_Tex;
tp->Set();
}
}
if (!bRes)
iLog->Log("Warning: Couldn't set projected texture for %d light source (Shader: '%s')\n", rd->m_RP.m_nCurLight, rd->m_RP.m_pShader->m_Name.c_str());
}
break;
case TO_ENVIRONMENT_CUBE_MAP:
{
SEnvTexture *cm = NULL;
cm = gcEf.mfFindSuitableEnvCMap(Vec3d(rd->m_RP.m_pCurObject->m_Matrix[3][0], rd->m_RP.m_pCurObject->m_Matrix[3][1], rd->m_RP.m_pCurObject->m_Matrix[3][2]), true, 0);
if (cm)
cm->m_Tex->Set();
else
return false;
}
break;
case TO_ENVIRONMENT_TEX:
{
SEnvTexture *cm = NULL;
CCamera cam = rd->GetCamera();
Vec3d Angs = cam.GetAngles();
Vec3d Pos = cam.GetPos();
cm = gcEf.mfFindSuitableEnvTex(Pos, Angs, true, 0);
if (cm)
cm->m_Tex->Set();
else
return false;
}
break;
case TO_TEXTURE_MOTIONBLUR_FIRST:
{
State &= 0xf;
if (!((1<<State) & gcEf.m_NightMapReady))
return false;
bind = State + bind;
rd->SetTexture(bind, pSTU->m_TexPic->m_eTT);
}
break;
default:
{
if (bind >= TO_CUSTOM_CUBE_MAP_FIRST && bind <= TO_CUSTOM_CUBE_MAP_LAST)
{
SEnvTexture *cm = &CTexMan::m_CustomCMaps[bind-TO_CUSTOM_CUBE_MAP_FIRST];
if (!cm->m_bReady)
{
iLog->Log("Warning: Custom CubeMap %d don't ready\n", bind-TO_CUSTOM_CUBE_MAP_FIRST);
return false;
}
cm->m_Tex->Set();
}
else
if (bind >= TO_CUSTOM_TEXTURE_FIRST && bind <= TO_CUSTOM_TEXTURE_LAST)
{
SEnvTexture *cm = &CTexMan::m_CustomTextures[bind-TO_CUSTOM_TEXTURE_FIRST];
if (!cm->m_bReady)
{
iLog->Log("Warning: Custom Texture %d don't ready\n", bind-TO_CUSTOM_TEXTURE_FIRST);
return false;
}
cm->m_Tex->Set();
}
else
{
pSTU->m_TexPic->Set();
//pSTU->m_TexPic->SaveJPG("NCMap.jpg", false);
}
}
break;
}
}
}
if (m_GTC)
{
if (!m_GTC->mfSet(true))
return 0;
}
if (m_eColorOp != eCO_NOSET)
rd->EF_SetColorOp(m_eColorOp);
return 1;
}
bool SShaderPass::mfSetTextures(bool bEnable)
{
CD3D8Renderer *rd = gcpRendD3D;
if (bEnable)
{
bool bRes = false;
int n = rd->m_numtmus;
for (int i=0; i<m_TUnits.Num() && i<rd->m_numtmus; i++)
{
SShaderTexUnit *tl = m_TUnits[i];
if (tl->mfSetTexture(0, i))
bRes = true;
else
n = Min(n, i);
}
n = Min(n, i);
CD3D8TexMan::BindNULL(n);
return bRes;
}
else
{
for (int i=0; i<m_TUnits.Num() && i<rd->m_numtmus; i++)
{
SShaderTexUnit *tl = m_TUnits[i];
if (tl->m_GTC)
{
gcpRendD3D->EF_SelectTMU(i);
tl->m_GTC->mfSet(false);
}
}
}
rd->EF_SelectTMU(0);
return true;
}
//===================================================================================
STexPic *CD3D8TexMan::GetByID(int Id)
{
TTextureMapItor it = m_RefTexs.find(Id);
if (it != m_RefTexs.end())
{
SRefTex *rt = it->second;
return rt->m_SrcTex;
}
return NULL;
}
SRefTex *CD3D8TexMan::AddToHash(int Id, STexPic *ti)
{
TTextureMapItor it = m_RefTexs.find(Id);
SRefTex *rt;
if (it == m_RefTexs.end())
{
rt = new SRefTex;
m_RefTexs.insert(TTextureMapItor::value_type(Id, rt));
}
else
rt = it->second;
if (ti)
{
STexPicD3D *t = (STexPicD3D *)ti;
t->m_RefTex = rt;
rt->m_SrcTex = t;
}
return rt;
}
void CD3D8TexMan::RemoveFromHash(int Id, STexPic *ti)
{
TTextureMapItor it = m_RefTexs.find(Id);
if (it != m_RefTexs.end())
{
SRefTex *rt = it->second;
IDirect3DBaseTexture8* vt = (IDirect3DBaseTexture8*)rt->m_VidTex;
if (vt)
vt->Release();
delete rt;
m_RefTexs.erase(Id);
}
if (ti)
{
STexPicD3D *t = (STexPicD3D *)ti;
t->m_RefTex = NULL;
}
}
CD3D8TexMan::~CD3D8TexMan()
{
}
STexPic *CD3D8TexMan::CreateTexture()
{
#ifdef DEBUGALLOC
#undef new
#endif
return new STexPicD3D;
#ifdef DEBUGALLOC
#define new DEBUG_CLIENTBLOCK
#endif
}
bool CD3D8TexMan::SetFilter(char *tex)
{
int i;
struct textype
{
char *name;
uint typemin;
uint typemag;
uint typemip;
};
static textype tt[] =
{
{"BILINEAR", D3DTEXF_LINEAR, D3DTEXF_LINEAR,D3DTEXF_POINT},
{"TRILINEAR", D3DTEXF_LINEAR, D3DTEXF_LINEAR,D3DTEXF_LINEAR},
};
m_CurAnisotropic = Clamp(CRenderer::CV_r_texture_anisotropic_level, 1, gcpRendD3D->m_MaxAnisotropyLevel);
CRenderer::CV_r_texture_anisotropic_level = m_CurAnisotropic;
if ((gRenDev->GetFeatures() & RFT_ALLOWANISOTROPIC) && m_CurAnisotropic > 1)
tex = "TRILINEAR";
LPDIRECT3DDEVICE8 dv = gcpRendD3D->mfGetD3DDevice();
for (i=0; i<2; i++)
{
if (!stricmp(tex, tt[i].name) )
{
m_MinFilter = tt[i].typemin;
m_MagFilter = tt[i].typemag;
m_MipFilter = tt[i].typemip;
for (i=0; i<m_Textures.Num(); i++)
{
if (m_Textures[i] && m_Textures[i]->m_bBusy && !(m_Textures[i]->m_Flags & FT_NOMIPS))
{
STexPicD3D *pTP = (STexPicD3D *)m_Textures[i];
if (pTP->m_RefTex)
{
pTP->m_RefTex->m_MinFilter = GetMinFilter();
pTP->m_RefTex->m_MagFilter = GetMagFilter();
pTP->m_RefTex->m_AnisLevel = gcpRendD3D->GetAnisotropicLevel();
}
}
}
return true;
}
}
iLog->Log("Bad texture filter name <%s>\n", tex);
return false;
}
int CD3D8TexMan::TexSize(int wdt, int hgt, int mode)
{
switch (mode)
{
case D3DFMT_X8R8G8B8:
#ifndef _XBOX
case D3DFMT_X8L8V8U8:
#endif //_XBOX
return wdt * hgt * 4;
#ifndef _XBOX
case D3DFMT_R8G8B8:
return wdt * hgt * 3;
#endif
case D3DFMT_A8R8G8B8:
return wdt * hgt * 4;
case D3DFMT_A8:
return wdt * hgt;
case D3DFMT_A4R4G4B4:
case D3DFMT_A1R5G5B5:
case D3DFMT_X1R5G5B5:
case D3DFMT_R5G6B5:
return wdt * hgt * 2;
case D3DFMT_DXT1:
case D3DFMT_DXT3:
case D3DFMT_DXT5:
{
int blockSize = (mode == D3DFMT_DXT1) ? 8 : 16;
return ((wdt+3)/4)*((hgt+3)/4)*blockSize;
}
case D3DFMT_P8:
return wdt * hgt;
default:
assert(0);
break;
}
return 0;
}
void CD3D8TexMan::CalcMipsAndSize(STexPic *ti)
{
ti->m_nMips = 0;
ti->m_Size = 0;
int wdt = ti->m_Width;
int hgt = ti->m_Height;
STexPicD3D *tp = (STexPicD3D *)ti;
int mode = tp->m_RefTex->m_DstFormat;
while (wdt || hgt)
{
if (!wdt)
wdt = 1;
if (!hgt)
hgt = 1;
ti->m_nMips++;
ti->m_Size += TexSize(wdt,hgt,mode);
if (ti->m_Flags & FT_NOMIPS)
break;
wdt >>= 1;
hgt >>= 1;
}
}
void STexPic::SaveTGA(const char *nam, bool bMips)
{
}
void STexPic::SaveJPG(const char *nam, bool bMips)
{
}
void STexPicD3D::SaveTGA(const char *name, bool bMips)
{
if (!m_RefTex || !m_RefTex->m_VidTex)
return;
CD3D8Renderer *r = gcpRendD3D;
LPDIRECT3DDEVICE8 dv = r->mfGetD3DDevice();
IDirect3DTexture8 *pID3DTexture = NULL;
IDirect3DCubeTexture8 *pID3DCubeTexture = NULL;
if (m_eTT == eTT_Cubemap)
pID3DCubeTexture = (IDirect3DCubeTexture8*)m_RefTex->m_VidTex;
else
pID3DTexture = (IDirect3DTexture8*)m_RefTex->m_VidTex;
HRESULT h;
D3DLOCKED_RECT d3dlr;
D3DSURFACE_DESC ddsdDescDest;
if (pID3DTexture)
pID3DTexture->GetLevelDesc(0, &ddsdDescDest);
else
pID3DCubeTexture->GetLevelDesc(0, &ddsdDescDest);
int sComps = 0;
int sCompDst = 0;
int sCompSrc = 0;
switch (ddsdDescDest.Format)
{
case D3DFMT_X8R8G8B8:
#ifndef _XBOX
case D3DFMT_X8L8V8U8:
#endif
case D3DFMT_A8R8G8B8:
sComps = 4;
sCompDst = 4;
break;
}
if (sComps)
{
byte *pDst = new byte [ddsdDescDest.Width*ddsdDescDest.Height*4];
if (pID3DCubeTexture)
{
for (int CubeSide=0; CubeSide<6; CubeSide++)
{
char nm[128];
sprintf(nm, "%s_%d", name, CubeSide);
// Lock the texture to copy the image data into the texture
h = pID3DCubeTexture->LockRect((D3DCUBEMAP_FACES)CubeSide, 0, &d3dlr, NULL, 0);
// Copy data to the texture
byte *pSrc = (byte *)d3dlr.pBits;
byte *pd = pDst;
for (uint j=0; j<ddsdDescDest.Width*ddsdDescDest.Height; j++)
{
for (int n=0; n<sComps; n++)
{
pd[n] = pSrc[n];
}
pd += sCompDst;
pSrc += sComps;
}
WriteTGA(pDst, ddsdDescDest.Width, ddsdDescDest.Height, nm);
// Unlock the texture
pID3DCubeTexture->UnlockRect((D3DCUBEMAP_FACES)CubeSide, 0);
}
}
else
{
// Lock the texture to copy the image data into the texture
h = pID3DTexture->LockRect(0, &d3dlr, NULL, 0);
// Copy data to the texture
byte *pSrc = (byte *)d3dlr.pBits;
byte *pd = pDst;
for (uint j=0; j<ddsdDescDest.Width*ddsdDescDest.Height; j++)
{
for (int n=0; n<sComps; n++)
{
pd[n] = pSrc[n];
}
pd += sCompDst;
pSrc += sComps;
}
WriteTGA(pDst, ddsdDescDest.Width, ddsdDescDest.Height, (char *)name, 32);
// Unlock the texture
pID3DTexture->UnlockRect(0);
}
delete [] pDst;
}
}
void STexPicD3D::SaveJPG(const char *nam, bool bMips)
{
if (!m_RefTex || !m_RefTex->m_VidTex)
return;
char name[64];
StripExtension(nam, name);
CD3D8Renderer *r = gcpRendD3D;
LPDIRECT3DDEVICE8 dv = r->mfGetD3DDevice();
IDirect3DTexture8 *pID3DTexture = NULL;
IDirect3DCubeTexture8 *pID3DCubeTexture = NULL;
if (m_eTT == eTT_Cubemap)
pID3DCubeTexture = (IDirect3DCubeTexture8*)m_RefTex->m_VidTex;
else
pID3DTexture = (IDirect3DTexture8*)m_RefTex->m_VidTex;
HRESULT h;
D3DLOCKED_RECT d3dlr;
D3DSURFACE_DESC ddsdDescDest;
if (pID3DTexture)
pID3DTexture->GetLevelDesc(0, &ddsdDescDest);
else
pID3DCubeTexture->GetLevelDesc(0, &ddsdDescDest);
int sComps = 0;
int sCompDst = 0;
int sCompSrc = 0;
switch (ddsdDescDest.Format)
{
case D3DFMT_X8R8G8B8:
#ifndef _XBOX
case D3DFMT_X8L8V8U8:
#endif
case D3DFMT_A8R8G8B8:
sComps = 4;
sCompDst = 4;
break;
}
if (sComps)
{
byte *pDst = new byte [ddsdDescDest.Width*ddsdDescDest.Height*4];
if (pID3DCubeTexture)
{
static char* scubefaces[6] = {"posx","negx","posy","negy","posz","negz"};
for (int CubeSide=0; CubeSide<6; CubeSide++)
{
char nm[128];
sprintf(nm, "%s_%s.jpg", name, scubefaces[CubeSide]);
// Lock the texture to copy the image data into the texture
h = pID3DCubeTexture->LockRect((D3DCUBEMAP_FACES)CubeSide, 0, &d3dlr, NULL, 0);
// Copy data to the texture
byte *pSrc = (byte *)d3dlr.pBits;
byte *pd = pDst;
for (uint j=0; j<ddsdDescDest.Width*ddsdDescDest.Height; j++)
{
for (int n=0; n<sComps; n++)
{
pd[n] = pSrc[n];
}
pd += sCompDst;
pSrc += sComps;
}
#ifndef _XBOX
WriteJPG(pDst, ddsdDescDest.Width, ddsdDescDest.Height, nm);
#endif
// Unlock the texture
pID3DCubeTexture->UnlockRect((D3DCUBEMAP_FACES)CubeSide, 0);
}
}
else
{
char nm[128];
sprintf(nm, "%s.jpg", name);
// Lock the texture to copy the image data into the texture
h = pID3DTexture->LockRect(0, &d3dlr, NULL, 0);
// Copy data to the texture
byte *pSrc = (byte *)d3dlr.pBits;
byte *pd = pDst;
for (uint j=0; j<ddsdDescDest.Width*ddsdDescDest.Height; j++)
{
for (int n=0; n<sComps; n++)
{
pd[n] = pSrc[n];
}
pd += sCompDst;
pSrc += sComps;
}
#ifndef _XBOX
WriteJPG(pDst, ddsdDescDest.Width, ddsdDescDest.Height, (char *)nm);
#endif
// Unlock the texture
pID3DTexture->UnlockRect(0);
}
delete [] pDst;
}
}
void CD3D8TexMan::D3DCreateVideoTexture(int tgt, byte *src, int wdt, int hgt, D3DFORMAT SrcFormat, D3DFORMAT DstFormat, STexPicD3D *ti, bool bMips, int CubeSide, PALETTEENTRY *pe, int DXTSize)
{
int i = 0;
int offset = 0;
int size;
LPDIRECT3DSURFACE8 pDestSurf;
LPDIRECT3DSURFACE8 pSourceSurf;
if (!ti->m_RefTex)
return;
HRESULT h;
D3DLOCKED_RECT d3dlr;
LPDIRECT3DDEVICE8 dv = gcpRendD3D->mfGetD3DDevice();
LPDIRECT3DTEXTURE8 pID3DTexture = NULL;
LPDIRECT3DCUBETEXTURE8 pID3DCubeTexture = NULL;
LPDIRECT3DTEXTURE8 pID3DSrcTexture = NULL;
ti->m_RefTex->m_DstFormat = DstFormat;
ti->m_CubeSide = CubeSide;
// Create the video texture
if (tgt == TEXTGT_2D)
{
if (ti->m_Flags2 & FT2_RENDERTARGET)
{
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pID3DTexture)))
return;
ti->m_RefTex->m_VidTex = pID3DTexture;
return;
}
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, bMips ? D3DX_DEFAULT : 1, 0, DstFormat, D3DPOOL_MANAGED, &pID3DTexture)))
return;
}
else
if (tgt == TEXTGT_CUBEMAP)
{
if (CubeSide == 0)
{
if (ti->m_Flags2 & FT2_RENDERTARGET)
{
if( FAILED( h = dv->CreateCubeTexture(wdt, 1, D3DUSAGE_RENDERTARGET, DstFormat, D3DPOOL_DEFAULT, &pID3DCubeTexture)))
return;
ti->m_RefTex->m_VidTex = pID3DCubeTexture;
}
else
if( FAILED( h = D3DXCreateCubeTexture(dv, wdt, bMips ? D3DX_DEFAULT : 1, 0, DstFormat, D3DPOOL_MANAGED, &pID3DCubeTexture)))
return;
m_pCurCubeTexture = pID3DCubeTexture;
}
else
pID3DCubeTexture = m_pCurCubeTexture;
if (ti->m_Flags2 & FT2_RENDERTARGET)
return;
}
if ((SrcFormat==D3DFMT_DXT1 || SrcFormat==D3DFMT_DXT3 || SrcFormat==D3DFMT_DXT5) && SrcFormat==DstFormat)
{
int DxtBlockSize = (ti->m_Flags & FT_DXT1) ? 8 : 16;
ti->m_Size = 0;
while (wdt || hgt)
{
if (offset == DXTSize)
break;
if (wdt == 0)
wdt = 1;
if (hgt == 0)
hgt = 1;
size = ((wdt+3)/4)*((hgt+3)/4)*DxtBlockSize;
ti->m_Size += size;
// Lock the texture to copy the image data into the texture
if (pID3DCubeTexture)
h = pID3DCubeTexture->LockRect((D3DCUBEMAP_FACES)CubeSide, i, &d3dlr, NULL, 0);
else
h = pID3DTexture->LockRect(i, &d3dlr, NULL, 0);
// Copy data to video texture
memcpy((byte *)d3dlr.pBits, &src[offset], size);
// Unlock the system texture
if (pID3DCubeTexture)
pID3DCubeTexture->UnlockRect((D3DCUBEMAP_FACES)CubeSide, i);
else
pID3DTexture->UnlockRect(i);
i++;
offset += size;
wdt >>= 1;
hgt >>= 1;
if (!bMips)
break;
}
if (pID3DCubeTexture)
ti->m_RefTex->m_VidTex = pID3DCubeTexture;
else
ti->m_RefTex->m_VidTex = pID3DTexture;
return;
}
else
if ((SrcFormat==D3DFMT_P8) && SrcFormat==DstFormat)
{
#ifndef _XBOX
HRESULT hr = dv->SetPaletteEntries(m_CurPal, pe);
ti->m_RefTex->m_Pal = m_CurPal++;
#else
HRESULT hr = dv->CreatePalette(D3DPALETTE_256, &ti->m_RefTex->m_pPal);
if (FAILED(hr))
{
iLog->Log("Couldn't create palette for texture '%s'\n", ti->m_SearchName);
}
else
{
D3DCOLOR *pPal;
ti->m_RefTex->m_pPal->Lock(&pPal, D3DLOCK_NOOVERWRITE);
for (int i=0; i<256; i++)
{
pPal[i] = (pe[i].peFlags<<24) | (pe[i].peRed<<16) | (pe[i].peGreen<<8) | pe[i].peBlue;
}
ti->m_RefTex->m_pPal->Unlock();
}
#endif
byte *out = new byte [wdt*hgt];
byte *outRet = out;
while (wdt || hgt)
{
if (wdt == 0)
wdt = 1;
if (hgt == 0)
hgt = 1;
// Lock the texture to copy the image data into the texture
if (pID3DCubeTexture)
h = pID3DCubeTexture->LockRect((D3DCUBEMAP_FACES)CubeSide, i, &d3dlr, NULL, 0);
else
h = pID3DTexture->LockRect(i, &d3dlr, NULL, 0);
// Copy data to video texture P8
memcpy((byte *)d3dlr.pBits, src, wdt*hgt);
// Unlock the system texture
if (pID3DCubeTexture)
pID3DCubeTexture->UnlockRect((D3DCUBEMAP_FACES)CubeSide, i);
else
pID3DTexture->UnlockRect(i);
if (ti->m_nMips)
src += wdt * hgt;
else
{
MipMap8Bit (ti, src, out, wdt, hgt);
Exchange(out, src);
}
wdt >>= 1;
hgt >>= 1;
i++;
if (!bMips)
break;
}
delete [] outRet;
if (pID3DCubeTexture)
ti->m_RefTex->m_VidTex = pID3DCubeTexture;
else
ti->m_RefTex->m_VidTex = pID3DTexture;
return;
}
else
#ifdef _XBOX
if ((SrcFormat == D3DFMT_LIN_A8R8G8B8 || SrcFormat == D3DFMT_LIN_X8R8G8B8 || SrcFormat == D3DFMT_A8R8G8B8 || SrcFormat == D3DFMT_X8R8G8B8 || SrcFormat == D3DFMT_X8L8V8U8 || SrcFormat == D3DFMT_LIN_X8L8V8U8) && (DstFormat == D3DFMT_A8R8G8B8 || DstFormat == D3DFMT_X8R8G8B8 || DstFormat == D3DFMT_X8L8V8U8 || DstFormat == D3DFMT_LIN_X8L8V8U8))
#else
if ((SrcFormat == D3DFMT_A8R8G8B8 || SrcFormat == D3DFMT_X8R8G8B8 || SrcFormat == D3DFMT_X8L8V8U8) && (DstFormat == D3DFMT_A8R8G8B8 || DstFormat == D3DFMT_X8R8G8B8 || DstFormat == D3DFMT_X8L8V8U8))
#endif
{
ti->m_Size = 0;
while (wdt || hgt)
{
if (wdt == 0)
wdt = 1;
if (hgt == 0)
hgt = 1;
size = wdt*hgt*4;
ti->m_Size += size;
#ifndef _XBOX
// Lock the texture to copy the image data into the texture
if (pID3DCubeTexture)
h = pID3DCubeTexture->LockRect((D3DCUBEMAP_FACES)CubeSide, i, &d3dlr, NULL, 0);
else
h = pID3DTexture->LockRect(i, &d3dlr, NULL, 0);
// Copy data to video texture
memcpy((byte *)d3dlr.pBits, &src[offset], size);
// Unlock the system texture
if (pID3DCubeTexture)
pID3DCubeTexture->UnlockRect((D3DCUBEMAP_FACES)CubeSide, i);
else
pID3DTexture->UnlockRect(i);
#else
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, 1, 0, SrcFormat, D3DPOOL_SYSTEMMEM, &pID3DSrcTexture ) ) )
return;
h = pID3DSrcTexture->LockRect(0, &d3dlr, NULL, 0);
// Copy data to src texture
memcpy((byte *)d3dlr.pBits, &src[offset], size);
// Unlock the system texture
pID3DSrcTexture->UnlockRect(0);
if (pID3DCubeTexture)
h = pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)CubeSide, i, &pDestSurf);
else
h = pID3DTexture->GetSurfaceLevel(i, &pDestSurf);
h = pID3DSrcTexture->GetSurfaceLevel(0, &pSourceSurf);
h = D3DXLoadSurfaceFromSurface(pDestSurf, NULL, NULL, pSourceSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
SAFE_RELEASE(pDestSurf);
SAFE_RELEASE(pSourceSurf);
if (pID3DSrcTexture)
SAFE_RELEASE(pID3DSrcTexture);
#endif
i++;
offset += size;
wdt >>= 1;
hgt >>= 1;
if (!bMips)
break;
if (i >= ti->m_nMips)
break;
}
if (pID3DCubeTexture)
ti->m_RefTex->m_VidTex = pID3DCubeTexture;
else
ti->m_RefTex->m_VidTex = pID3DTexture;
}
else
{
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, 1, 0, SrcFormat, D3DPOOL_SYSTEMMEM, &pID3DSrcTexture ) ) )
return;
#ifndef _XBOX
if (SrcFormat == D3DFMT_A8)
#else
if (SrcFormat == D3DFMT_A8 || SrcFormat == D3DFMT_LIN_A8)
#endif
size = wdt*hgt;
else
size = wdt*hgt*4;
h = pID3DSrcTexture->LockRect(0, &d3dlr, NULL, 0);
// Copy data to src texture
memcpy((byte *)d3dlr.pBits, &src[offset], size);
// Unlock the system texture
pID3DSrcTexture->UnlockRect(0);
if (pID3DCubeTexture)
h = pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)CubeSide, i, &pDestSurf);
else
h = pID3DTexture->GetSurfaceLevel(i, &pDestSurf);
h = pID3DSrcTexture->GetSurfaceLevel(0, &pSourceSurf);
h = D3DXLoadSurfaceFromSurface(pDestSurf, NULL, NULL, pSourceSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
SAFE_RELEASE(pDestSurf);
SAFE_RELEASE(pSourceSurf);
if (pID3DSrcTexture)
SAFE_RELEASE(pID3DSrcTexture);
}
if (bMips && ti->m_nMips <= 1)
{
DWORD MipFilter;
switch (gcpRendD3D->CV_d3d8_texmipfilter)
{
case 0:
MipFilter = D3DX_FILTER_POINT;
break;
case 1:
default:
MipFilter = D3DX_FILTER_BOX;
break;
case 2:
MipFilter = D3DX_FILTER_LINEAR;
break;
case 3:
MipFilter = D3DX_FILTER_TRIANGLE;
break;
}
if (pID3DCubeTexture)
{
if (CubeSide == 5)
{
#ifdef _XBOX
h = D3DXFilterCubeTexture(pID3DCubeTexture, NULL, 0, MipFilter);
#else
h = D3DXFilterTexture((LPDIRECT3DTEXTURE8)pID3DCubeTexture, NULL, 0, MipFilter);
#endif
}
}
else
h = D3DXFilterTexture(pID3DTexture, NULL, 0, MipFilter);
}
if (pID3DCubeTexture)
ti->m_RefTex->m_VidTex = pID3DCubeTexture;
else
ti->m_RefTex->m_VidTex = pID3DTexture;
}
void CD3D8TexMan::D3DCompressTexture(int tgt, STexPicD3D *ti, int CubeSide)
{
D3DSURFACE_DESC desc;
D3DFORMAT Format;
LPDIRECT3DDEVICE8 dv = gcpRendD3D->mfGetD3DDevice();
int i;
LPDIRECT3DTEXTURE8 pID3DSrcTexture = NULL;
LPDIRECT3DCUBETEXTURE8 pID3DSrcCubeTexture = NULL;
LPDIRECT3DTEXTURE8 pID3DTexture = NULL;
LPDIRECT3DCUBETEXTURE8 pID3DCubeTexture = NULL;
if (tgt == TEXTGT_2D)
pID3DSrcTexture = (LPDIRECT3DTEXTURE8)ti->m_RefTex->m_VidTex;
else
{
if (CubeSide < 5)
return;
pID3DSrcCubeTexture = (LPDIRECT3DCUBETEXTURE8)ti->m_RefTex->m_VidTex;
}
int wdt = ti->m_Width;
int hgt = ti->m_Height;
if (pID3DSrcTexture)
{
pID3DSrcTexture->GetLevelDesc(0, &desc);
Format = desc.Format;
}
else
{
pID3DSrcCubeTexture->GetLevelDesc(0, &desc);
Format = desc.Format;
}
if (Format == D3DFMT_X8R8G8B8 || Format == D3DFMT_R5G6B5 || Format == D3DFMT_X1R5G5B5)
Format = D3DFMT_DXT1;
else
Format = D3DFMT_DXT3;
if (pID3DSrcTexture)
{
// Create the video texture
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, ti->m_RefTex->bMips ? D3DX_DEFAULT : 1, 0, Format, D3DPOOL_MANAGED, &pID3DTexture ) ) )
return;
for (i=0; i<(int)pID3DSrcTexture->GetLevelCount(); i++)
{
LPDIRECT3DSURFACE8 pDestSurf;
LPDIRECT3DSURFACE8 pSourceSurf;
pID3DTexture->GetSurfaceLevel(i, &pDestSurf);
pID3DSrcTexture->GetSurfaceLevel(i, &pSourceSurf);
D3DXLoadSurfaceFromSurface(pDestSurf, NULL, NULL, pSourceSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
SAFE_RELEASE(pDestSurf);
SAFE_RELEASE(pSourceSurf);
}
ti->m_RefTex->m_VidTex = pID3DTexture;
SAFE_RELEASE(pID3DSrcTexture);
}
else
if (pID3DSrcCubeTexture)
{
// Create the video texture
if( FAILED( h = D3DXCreateCubeTexture(dv, hgt, ti->m_RefTex->bMips ? D3DX_DEFAULT : 1, 0, Format, D3DPOOL_MANAGED, &pID3DCubeTexture ) ) )
return;
int side;
for (side=0; side<6; side++)
{
for (i=0; i<(int)pID3DSrcCubeTexture->GetLevelCount(); i++)
{
LPDIRECT3DSURFACE8 pDestSurf;
LPDIRECT3DSURFACE8 pSourceSurf;
pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)side, i, &pDestSurf);
pID3DSrcCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)side, i, &pSourceSurf);
D3DXLoadSurfaceFromSurface(pDestSurf, NULL, NULL, pSourceSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
SAFE_RELEASE(pDestSurf);
SAFE_RELEASE(pSourceSurf);
}
}
SAFE_RELEASE(pID3DSrcCubeTexture);
m_pCurCubeTexture = pID3DCubeTexture;
}
}
byte *CD3D8TexMan::GenerateDXT_HW(STexPic *ti, EImFormat eF, byte *dst, int *numMips, int *DXTSize, bool bMips)
{
D3DFORMAT Format, srcFormat;
LPDIRECT3DDEVICE8 dv = gcpRendD3D->mfGetD3DDevice();
int i;
D3DLOCKED_RECT d3dlr;
#ifndef _XBOX
srcFormat = D3DFMT_A8R8G8B8;
#else
srcFormat = D3DFMT_LIN_A8R8G8B8;
#endif
int wdt = ti->m_Width;
int hgt = ti->m_Height;
int Size = wdt * hgt * 4;
LPDIRECT3DTEXTURE8 pID3DSrcTexture = NULL;
LPDIRECT3DTEXTURE8 pID3DTexture = NULL;
LPDIRECT3DTEXTURE8 pID3DTempTexture = NULL;
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, 1, 0, srcFormat, D3DPOOL_SYSTEMMEM, &pID3DTempTexture ) ) )
return NULL;
// Lock the texture to copy the image data into the texture
h = pID3DTempTexture->LockRect(0, &d3dlr, NULL, 0);
// Copy data to the texture
memcpy(d3dlr.pBits, dst, Size);
// Unlock the texture
pID3DTempTexture->UnlockRect(0);
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, bMips ? D3DX_DEFAULT : 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSrcTexture ) ) )
return NULL;
{
LPDIRECT3DSURFACE8 pDestSurf;
LPDIRECT3DSURFACE8 pSourceSurf;
pID3DSrcTexture->GetSurfaceLevel(0, &pDestSurf);
pID3DTempTexture->GetSurfaceLevel(0, &pSourceSurf);
D3DXLoadSurfaceFromSurface(pDestSurf, NULL, NULL, pSourceSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
SAFE_RELEASE(pDestSurf);
SAFE_RELEASE(pSourceSurf);
}
SAFE_RELEASE(pID3DTempTexture);
if (eF == eIF_DXT1)
Format = D3DFMT_DXT1;
else
if (eF == eIF_DXT3)
Format = D3DFMT_DXT3;
else
if (eF == eIF_DXT5)
Format = D3DFMT_DXT5;
DWORD MipFilter;
switch (gcpRendD3D->CV_d3d8_texmipfilter)
{
case 0:
MipFilter = D3DX_FILTER_POINT;
break;
case 1:
default:
MipFilter = D3DX_FILTER_BOX;
break;
case 2:
MipFilter = D3DX_FILTER_LINEAR;
break;
case 3:
MipFilter = D3DX_FILTER_TRIANGLE;
break;
}
if (bMips)
h = D3DXFilterTexture(pID3DSrcTexture, NULL, 0, MipFilter);
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, bMips ? D3DX_DEFAULT : 1, 0, Format, D3DPOOL_SYSTEMMEM, &pID3DTexture ) ) )
{
SAFE_RELEASE(pID3DSrcTexture);
return NULL;
}
for (i=0; i<(int)pID3DSrcTexture->GetLevelCount(); i++)
{
LPDIRECT3DSURFACE8 pDestSurf;
LPDIRECT3DSURFACE8 pSourceSurf;
pID3DTexture->GetSurfaceLevel(i, &pDestSurf);
pID3DSrcTexture->GetSurfaceLevel(i, &pSourceSurf);
D3DXLoadSurfaceFromSurface(pDestSurf, NULL, NULL, pSourceSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
SAFE_RELEASE(pDestSurf);
SAFE_RELEASE(pSourceSurf);
}
SAFE_RELEASE(pID3DSrcTexture);
int nOffs = 0;
Size = 0;
for (i=0; i<(int)pID3DTexture->GetLevelCount(); i++)
{
h = pID3DTexture->LockRect(i, &d3dlr, NULL, 0);
Size += TexSize(wdt, hgt, Format);
h = pID3DTexture->UnlockRect(i);
wdt >>= 1;
hgt >>= 1;
if (wdt < 1)
wdt = 1;
if (hgt < 1)
hgt = 1;
}
*numMips = pID3DTexture->GetLevelCount();
*DXTSize = Size;
wdt = ti->m_Width;
hgt = ti->m_Height;
byte *data = new byte [Size];
for (i=0; i<(int)pID3DTexture->GetLevelCount(); i++)
{
h = pID3DTexture->LockRect(i, &d3dlr, NULL, 0);
Size = TexSize(wdt, hgt, Format);
memcpy(&data[nOffs], d3dlr.pBits, Size);
nOffs += Size;
h = pID3DTexture->UnlockRect(i);
wdt >>= 1;
hgt >>= 1;
if (wdt < 1)
wdt = 1;
if (hgt < 1)
hgt = 1;
}
SAFE_RELEASE(pID3DTexture);
return data;
}
STexPic *CD3D8TexMan::CopyTexture(const char *name, STexPic *tiSrc, int CubeSide)
{
return NULL;
}
STexPic *CD3D8TexMan::CreateTexture(const char *name, int wdt, int hgt, int depth, uint flags, uint flags2, byte *dst, ETexType eTT, float fAmount1, float fAmount2, int DXTSize, STexPic *tp, int bind, ETEX_Format eTF, const char *szSourceName)
{
byte *dst1 = NULL;
int i;
LPDIRECT3DDEVICE8 dv = gcpRendD3D->mfGetD3DDevice();
LPDIRECT3DTEXTURE8 pID3DTexture;
pID3DTexture = NULL;
int DxtBlockSize = 0;
int DxtOneSize = 0;
bool bMips;
int CubeSide = -1;
PALETTEENTRY pe[256];
int w = ilog2(wdt);
int h = ilog2(hgt);
assert (w == wdt && h == hgt);
if (!tp)
{
tp = TextureInfoForName(name, NULL, -1, eTT, flags, flags2, bind);
tp->m_bBusy = true;
tp->m_Flags = flags;
tp->m_Flags2 = flags2;
tp->m_Bind = TX_FIRSTBIND + tp->m_Id;
AddToHash(tp->m_Bind, tp);
tp->m_Height = tp->m_HeightReal = hgt;
tp->m_Width = tp->m_WidthReal = wdt;
tp->m_nMips = 0;
tp->m_ETF = eTF;
bind = tp->m_Bind;
}
if (szSourceName)
tp->m_SourceName = szSourceName;
STexPicD3D *ti = (STexPicD3D *)tp;
if (ti->m_Flags & FT_NOMIPS)
bMips = false;
else
bMips = true;
if (ti->m_Flags & FT_DXT)
{
DxtBlockSize = (ti->m_Flags & FT_DXT1) ? 8 : 16;
DxtOneSize = ((wdt+3)/4)*((hgt+3)/4)*DxtBlockSize;
}
ti->m_DXTSize = DXTSize;
ti->m_fAmount1 = fAmount1;
ti->m_fAmount2 = fAmount2;
if (dst)
{
if (ti->m_Flags & FT_CONV_GREY)
ti->m_pData32 = Convert8888_Gray(dst, ti, ti->m_Flags);
if (ti->m_Flags & FT_NODOWNLOAD)
{
if (ti->m_Flags & FT_DXT)
ti->m_pData32 = ImgConvertDXT_RGBA(dst, ti, DXTSize);
else
ti->m_pData32 = dst;
return ti;
}
D3DFORMAT format = D3DFMT_X8R8G8B8;
D3DFORMAT srcFormat;
int SizeSrc = 0;
if (eTF == eTF_8888 || eTF == eTF_RGBA)
{
srcFormat = D3DFMT_A8R8G8B8;
SizeSrc = wdt * hgt * 4;
}
else
if (eTF == eTF_0888 || eTF == eTF_DSDT_MAG)
{
int size = 0;
int w = wdt;
int h = hgt;
if (ti->m_nMips)
{
for (int l=0; l<ti->m_nMips; l++)
{
if (!w)
w = 1;
if (!h)
h = 1;
size += w*h*4;
w >>= 1;
h >>= 1;
}
dst1 = new byte [size];
w = wdt;
h = hgt;
byte *ds1 = dst1;
byte *ds = dst;
for (int l=0; l<ti->m_nMips; l++)
{
if (!w)
w = 1;
if (!h)
h = 1;
for (i=0; i<w*h; i++)
{
ds1[i*4+0] = ds[i*3+0];
ds1[i*4+1] = ds[i*3+1];
ds1[i*4+2] = ds[i*3+2];
ds1[i*4+3] = 0;
}
ds1 += w*h*4;
ds += w*h*3;
w >>= 1;
h >>= 1;
}
}
else
{
dst1 = new byte [wdt*hgt*4];
byte *ds1 = dst1;
byte *ds = dst;
for (i=0; i<w*h; i++)
{
ds1[i*4+0] = ds[i*3+0];
ds1[i*4+1] = ds[i*3+1];
ds1[i*4+2] = ds[i*3+2];
ds1[i*4+3] = 0;
}
}
dst = dst1;
SizeSrc = wdt * hgt * 4;
srcFormat = D3DFMT_X8L8V8U8;
eTF = eTF_8888;
}
else
if (eTF == eTF_8000)
{
SizeSrc = wdt * hgt;
srcFormat = D3DFMT_A8;
format = D3DFMT_A8;
ti->m_Flags |= FT_HASALPHA;
}
if (!(ti->m_Flags & FT_DXT) && !ti->m_pPalette)
{
if (format != D3DFMT_A8 && !(gRenDev->GetFeatures() & RFT_HWGAMMA) && (!(ti->m_Flags & FT_NOGAMMA) || (ti->m_Flags & FT_NOREMOVE)) )
{
if (!CRenderer::CV_r_noswgamma && ti->m_eTT != eTT_Bumpmap)
BuildImageGamma(ti->m_Width, ti->m_Height, dst, false);
}
}
if (ti->m_Flags2 & FT2_FORCEDXT)
{
if (!(ti->m_Flags & FT_HASALPHA))
format = D3DFMT_DXT1;
else
format = D3DFMT_DXT3;
if (ti->m_Flags & FT_DXT1)
srcFormat = D3DFMT_DXT1;
else
if (ti->m_Flags & FT_DXT3)
srcFormat = D3DFMT_DXT3;
else
if (ti->m_Flags & FT_DXT5)
srcFormat = D3DFMT_DXT5;
else
{
iLog->Log("Unknown DXT format for texture %s", ti->m_SearchName.c_str());
srcFormat = D3DFMT_DXT1;
}
SizeSrc = DxtOneSize;
}
else
if (ti->m_Flags & FT_DXT)
{
if (ti->m_Flags & FT_DXT1)
format = D3DFMT_DXT1;
else
if (ti->m_Flags & FT_DXT3)
format = D3DFMT_DXT3;
else
if (ti->m_Flags & FT_DXT5)
format = D3DFMT_DXT5;
else
{
iLog->Log("Unknown DXT format for texture %s", ti->m_SearchName.c_str());
format = D3DFMT_DXT1;
}
srcFormat = format;
SizeSrc = DxtOneSize;
}
else
if (format != D3DFMT_A8)
{
if (!(ti->m_Flags & FT_HASALPHA) || ti->m_eTT == eTT_Bumpmap || ti->m_eTT == eTT_DSDTBump) // 3 components;
{
if (ti->m_eTT == eTT_Bumpmap)
{
if (CRenderer::CV_r_texbumpquality == 0)
format = D3DFMT_X8L8V8U8;
else
if (CRenderer::CV_r_texbumpquality == 1)
{
ti->m_Flags |= FT_PALETTED;
ti->m_pPalette = &m_NMPalette[0][0];
dst1 = ConvertNMToPalettedFormat(dst, ti, eTF);
dst = dst1;
format = D3DFMT_P8;
SizeSrc = wdt*hgt;
}
else
if (CRenderer::CV_r_texbumpquality == 2)
format = D3DFMT_DXT1;
else
format = D3DFMT_X8L8V8U8;
}
else
if (ti->m_eTT == eTT_DSDTBump)
format = D3DFMT_X8L8V8U8;
else
{
if (CRenderer::CV_r_texquality == 0)
format = D3DFMT_X8R8G8B8;
else
if (CRenderer::CV_r_texquality == 1)
format = D3DFMT_R5G6B5;
else
if (CRenderer::CV_r_texquality == 2)
format = D3DFMT_DXT1;
else
format = D3DFMT_X8R8G8B8;
}
}
else
{
if (CRenderer::CV_r_texquality == 0)
format = D3DFMT_A8R8G8B8;
else
if (CRenderer::CV_r_texquality == 1)
format = D3DFMT_A4R4G4B4;
else
if (CRenderer::CV_r_texquality == 2)
format = D3DFMT_DXT3;
else
format = D3DFMT_A8R8G8B8;
}
}
else
SizeSrc = wdt * hgt;
if (ti->m_Flags & FT_PALETTED)
{
if (gRenDev->GetFeatures() & RFT_PALTEXTURE)
{
srcFormat = D3DFMT_P8;
format = D3DFMT_P8;
SizeSrc = wdt * hgt;
}
else
{
srcFormat = D3DFMT_A8R8G8B8;
SRGBPixel *pal = ti->m_pPalette;
ti->m_Flags &= ~FT_PALETTED;
ti->m_ETF = eTF_8888;
byte *pDst = new byte[wdt*hgt*4];
for (int i=0; i<wdt*hgt; i++)
{
int l = dst[i];
pDst[i*4+0] = pal[l].red;
pDst[i*4+1] = pal[l].green;
pDst[i*4+2] = pal[l].blue;
pDst[i*4+3] = pal[l].alpha;
}
dst1 = pDst;
dst = pDst;
}
}
#ifdef _XBOX
if (srcFormat == D3DFMT_A8)
srcFormat = D3DFMT_LIN_A8;
else
if (srcFormat == D3DFMT_A8R8G8B8)
srcFormat = D3DFMT_LIN_A8R8G8B8;
else
if (srcFormat == D3DFMT_X8R8G8B8)
srcFormat = D3DFMT_LIN_X8R8G8B8;
else
if (srcFormat == D3DFMT_X8L8V8U8)
srcFormat = D3DFMT_LIN_X8L8V8U8;
else
if (srcFormat == D3DFMT_A4R4G4B4)
srcFormat = D3DFMT_LIN_A4R4G4B4;
else
if (srcFormat == D3DFMT_R5G6B5)
srcFormat = D3DFMT_LIN_R5G6B5;
#endif
int tgt = TEXTGT_2D;
{
{
if (ti->m_eTT == eTT_Cubemap)
{
tgt = TEXTGT_CUBEMAP;
int n = strlen(ti->m_SearchName.c_str()) - 4;
if (!strcmp(&ti->m_SearchName.c_str()[n], "posx"))
CubeSide = 0;
else
if (!strcmp(&ti->m_SearchName.c_str()[n], "negx"))
CubeSide = 1;
else
if (!strcmp(&ti->m_SearchName.c_str()[n], "posy"))
CubeSide = 2;
else
if (!strcmp(&ti->m_SearchName.c_str()[n], "negy"))
CubeSide = 3;
else
if (!strcmp(&ti->m_SearchName.c_str()[n], "posz"))
CubeSide = 4;
else
if (!strcmp(&ti->m_SearchName.c_str()[n], "negz"))
CubeSide = 5;
else
CubeSide = 0;
m_CurCubeFaces[CubeSide] = ti;
}
if (!(ti->m_Flags & FT_DXT))
{
if (ti->m_pPalette && (ti->m_pData || dst))
{
if ((ti->m_Flags & FT_PALETTED) && (gRenDev->GetFeatures() & RFT_PALTEXTURE))
{
SRGBPixel *pal = ti->m_pPalette;
// Create the color table
for (i=0; i<256; i++)
{
pe[i].peBlue = pal[i].red;
pe[i].peGreen = pal[i].green;
pe[i].peRed = pal[i].blue;
pe[i].peFlags = pal[i].alpha;
}
if (!ti->m_p8to24table)
ti->m_p8to24table = new uint [256];
if (!ti->m_p15to8table)
ti->m_p15to8table = new uchar [32768];
uint *table = ti->m_p8to24table;
uint as = 255;
uint r, g, b, a;
uint v;
for (i=0; i<256; i++)
{
r = pal->red;
g = pal->green;
b = pal->blue;
a = pal->alpha;
as &= a;
pal++;
v = (a<<24) + (r<<0) + (g<<8) + (b<<16);
*table++ = v;
}
if (as < 255)
ti->m_bAlphaPal = 1;
for (i=0; i<(1<<15); i++)
{
/* Maps
0000 0000 0000 0000
0000 0000 0001 1111 = Red = 0x1F
0000 0011 1110 0000 = Blue = 0x03E0
0111 1100 0000 0000 = Grn = 0x7C00
*/
r = ((i & 0x1F) << 3)+4;
g = ((i & 0x03E0) >> 2)+4;
b = ((i & 0x7C00) >> 7)+4;
uchar *pal = (uchar *)ti->m_p8to24table;
uint v;
int j,k,l;
int r1,g1,b1;
for (v=0,k=0,l=10000*10000; v<256; v++,pal+=4)
{
r1 = r-pal[0];
g1 = g-pal[1];
b1 = b-pal[2];
j = (r1*r1)+(g1*g1)+(b1*b1);
if (j<l)
{
k = v;
l = j;
}
}
ti->m_p15to8table[i] = k;
}
}
}
}
}
ti->m_RefTex->bMips = bMips;
if (dst)
D3DCreateVideoTexture(tgt, dst, wdt, hgt, srcFormat, format, ti, bMips, CubeSide, pe, DXTSize);
if (ti->m_eTT == eTT_Cubemap)
{
ti->m_RefTex->bRepeats = false;
ti->m_RefTex->m_MinFilter = GetMinFilter();
ti->m_RefTex->m_MagFilter = GetMagFilter();
ti->m_RefTex->m_AnisLevel = gcpRendD3D->GetAnisotropicLevel();
}
else
{
if (ti->m_Flags & FT_CLAMP)
ti->m_RefTex->bRepeats = false;
else
ti->m_RefTex->bRepeats = true;
ti->m_RefTex->m_MinFilter = GetMinFilter();
ti->m_RefTex->m_MagFilter = GetMagFilter();
ti->m_RefTex->m_AnisLevel = gcpRendD3D->GetAnisotropicLevel();
}
ti->m_RefTex->m_Type = tgt;
if (CubeSide == 5)
{
for (i=0; i<6; i++)
{
if (i == 0)
m_CurCubeFaces[i]->m_RefTex->m_VidTex = m_pCurCubeTexture;
else
m_CurCubeFaces[i]->m_RefTex->m_VidTex = NULL;
}
}
} // if (!gIsDedicated)
} // if (dst)
// ti->Set();
CD3D8TexMan::CalcMipsAndSize(ti);
if (ti->m_Flags & FT_NOMIPS)
ti->m_nMips = 1;
if (ti->m_eTT == eTT_Cubemap)
{
ti->m_Size *= 6;
if (m_LastCMSide)
m_LastCMSide->m_NextCMSide = ti;
if (CubeSide == 5)
m_LastCMSide = NULL;
else
m_LastCMSide = ti;
}
if (ti->m_eTT != eTT_Cubemap || !ti->m_CubeSide)
{
CTexMan::m_StatsCurTexMem += ti->m_Size;
ti->Unlink();
ti->Link(&STexPic::m_Root);
//sTestStr.AddElem(ti);
}
CheckTexLimits();
if (m_Streamed == 2)
ti->Unload();
if (dst1)
delete [] dst1;
return ti;
}
//============================================================================
void CD3D8TexMan::BuildMipsSub(byte* src, int wdt, int hgt)
{
}
void CD3D8TexMan::UpdateTextureData(STexPic *pic, byte *data, int USize, int VSize, bool bProc, int State, bool bPal)
{
STexPicD3D *ti = (STexPicD3D *)pic;
LPDIRECT3DTEXTURE8 pID3DTexture = NULL;
LPDIRECT3DCUBETEXTURE8 pID3DCubeTexture = NULL;
int CubeSide = ti->m_CubeSide;
HRESULT h;
D3DLOCKED_RECT d3dlr;
LPDIRECT3DDEVICE8 dv = gcpRendD3D->mfGetD3DDevice();
D3DSURFACE_DESC ddsdDescDest;
if (ti->m_RefTex->m_Type == TEXTGT_2D)
{
pID3DTexture = (LPDIRECT3DTEXTURE8)ti->m_RefTex->m_VidTex;
assert(pID3DTexture);
}
else
{
pID3DCubeTexture = (LPDIRECT3DCUBETEXTURE8)ti->m_RefTex->m_VidTex;
assert(pID3DCubeTexture);
}
if (bPal)
{
bool bMips;
if (CD3D8Renderer::CV_d3d8_mipprocedures && !(pic->m_Flags & FT_NOMIPS))
bMips = true;
else
bMips = false;
if (!ti->m_RefTex->bMips)
bMips = false;
ti->m_RefTex->bMips = bMips;
int wdt = USize;
int hgt = VSize;
int i = 0;
byte *out = new byte [wdt*hgt];
byte *outRet = out;
while (wdt || hgt)
{
if (wdt == 0)
wdt = 1;
if (hgt == 0)
hgt = 1;
// Lock the texture to copy the image data into the texture
if (pID3DCubeTexture)
{
h = pID3DCubeTexture->LockRect((D3DCUBEMAP_FACES)CubeSide, i, &d3dlr, NULL, 0);
pID3DCubeTexture->GetLevelDesc(i, &ddsdDescDest);
}
else
{
h = pID3DTexture->LockRect(i, &d3dlr, NULL, 0);
pID3DTexture->GetLevelDesc(i, &ddsdDescDest);
}
// Copy data to video texture P8
memcpy((byte *)d3dlr.pBits, data, ddsdDescDest.Size);
// Unlock the system texture
if (pID3DCubeTexture)
pID3DCubeTexture->UnlockRect((D3DCUBEMAP_FACES)CubeSide, i);
else
pID3DTexture->UnlockRect(i);
if (!bMips)
break;
MipMap8Bit (ti, (byte *)data, out, wdt, hgt);
wdt >>= 1;
hgt >>= 1;
Exchange(out, (byte *)data);
i++;
}
delete [] outRet;
}
else
{
bool bMips;
if (CD3D8Renderer::CV_d3d8_mipprocedures && !(pic->m_Flags & FT_NOMIPS))
bMips = true;
else
bMips = false;
if (!ti->m_RefTex->bMips)
bMips = false;
ti->m_RefTex->bMips = bMips;
int wdt = USize;
int hgt = VSize;
int i = 0;
byte *out = new byte [wdt*hgt];
byte *outRet = out;
while (wdt || hgt)
{
if (wdt == 0)
wdt = 1;
if (hgt == 0)
hgt = 1;
// Lock the texture to copy the image data into the texture
if (pID3DCubeTexture)
{
h = pID3DCubeTexture->LockRect((D3DCUBEMAP_FACES)CubeSide, i, &d3dlr, NULL, 0);
pID3DCubeTexture->GetLevelDesc(i, &ddsdDescDest);
}
else
{
h = pID3DTexture->LockRect(i, &d3dlr, NULL, 0);
pID3DTexture->GetLevelDesc(i, &ddsdDescDest);
}
// Copy data to video texture A8R8G8B8
memcpy((byte *)d3dlr.pBits, data, ddsdDescDest.Size);
// Unlock the texture
if (pID3DCubeTexture)
pID3DCubeTexture->UnlockRect((D3DCUBEMAP_FACES)CubeSide, i);
else
pID3DTexture->UnlockRect(i);
if (!bMips)
break;
wdt >>= 1;
hgt >>= 1;
MipMap32Bit (ti, (byte *)data, out, wdt, hgt);
Exchange(out, (byte *)data);
i++;
}
delete [] outRet;
}
ti->Set();
}
static _inline int sLimitSizeByScreenRes(int size)
{
while(true)
{
if (size>gRenDev->GetWidth() || size>gRenDev->GetHeight())
size >>= 1;
else
break;
}
return size;
}
//TODO:replace with ARB_Buffer_Region and move into the class
void ClearBufferWithQuad(int x2,int y2,int x1,int y1,float fR,float fG,float fB,STexPic *pImage, int Side)
{
if (pImage)
{
if (gRenDev->CV_r_ReplaceCubeMap==1)
pImage = (STexPic *)gRenDev->EF_LoadTexture("textures/cube_face", 0, 0, eTT_Cubemap);
gRenDev->Set2DMode(true, 256, 256);
Vec3d crd[4];
if (pImage->m_eTT == eTT_Cubemap)
{
switch(Side)
{
case 0: //posx
crd[0] = Vec3d(1,1,1);
crd[1] = Vec3d(1,-1,1);
crd[2] = Vec3d(1,-1,-1);
crd[3] = Vec3d(1,1,-1);
break;
case 1: //negx
crd[0] = Vec3d(-1,1,1);
crd[1] = Vec3d(-1,-1,1);
crd[2] = Vec3d(-1,-1,-1);
crd[3] = Vec3d(-1,1,-1);
break;
case 2: //posy
crd[0] = Vec3d(1,1,1);
crd[1] = Vec3d(-1,1,1);
crd[2] = Vec3d(-1,1,-1);
crd[3] = Vec3d(1,1,-1);
break;
case 3: //negy
crd[0] = Vec3d(1,-1,1);
crd[1] = Vec3d(-1,-1,1);
crd[2] = Vec3d(-1,-1,-1);
crd[3] = Vec3d(1,-1,-1);
break;
case 4: //posz
crd[0] = Vec3d(1,1,1);
crd[1] = Vec3d(-1,1,1);
crd[2] = Vec3d(-1,-1,1);
crd[3] = Vec3d(1,-1,1);
break;
case 5: //negz
crd[0] = Vec3d(1,1,-1);
crd[1] = Vec3d(-1,1,-1);
crd[2] = Vec3d(-1,-1,-1);
crd[3] = Vec3d(1,-1,-1);
break;
}
}
//glDisable(GL_BLEND);
gRenDev->EnableBlend(false);
//glDisable(GL_STENCIL_TEST);
//gRenDev->EnableStencilTest(false);
((CD3D8Renderer*)gRenDev)->mfGetD3DDevice()->SetRenderState(D3DRS_STENCILENABLE, false);
//glDisable(GL_DEPTH_TEST);
gRenDev->EnableDepthTest(false);
//glDepthMask(1);
gRenDev->EnableDepthWrites(true);
//glDisable(GL_CULL_FACE);
gRenDev->SetCullMode(R_CULL_DISABLE);
//glEnable(GL_TEXTURE_2D);
gRenDev->EnableTMU(true);
pImage->Set();
//!!! WARNING !!!
//glEnable(pImage->m_TargetType);
////
/*
glBegin(GL_QUADS);
glColor3f(fR,fG,fB);
glTexCoord3f(crd[0][0], crd[0][1], crd[0][2]);
glVertex3f(0.0f, 0.0f, 0.0f); // Top Left
glTexCoord3f(crd[1][0], crd[1][1], crd[1][2]);
glVertex3f(0.0f, 256.0f, 0.0f); // Bottom Left
glTexCoord3f(crd[2][0], crd[2][1], crd[2][2]);
glVertex3f(256.0f, 256.0f, 0.0f); // Bottom Right
glTexCoord3f(crd[3][0], crd[3][1], crd[3][2]);
glVertex3f(256.0f, 0.0f, 0.0f); // Top Right
glEnd();
*/
{
struct SPipeTRVertex_D_3T_w
{
float dvSX;
float dvSY;
float dvSZ;
float dvRHW;
DWORD dcColor;
float dvTU[3];
};
LPDIRECT3DDEVICE8 dv = ((CD3D8Renderer*)gRenDev)->mfGetD3DDevice();
CFColor color(fR,fG,fB,1);
DWORD col = (DWORD(color.a * 255) << 24) | (DWORD(color.r * 255) << 16) |
(DWORD(color.g * 255)<<8) | DWORD(color.b * 255);
SPipeTRVertex_D_3T_w *vQuad;
#ifdef _XBOX
HRESULT hr = ((CD3D8Renderer*)gRenDev)->m_pQuadVB->Lock(0, 0, (BYTE **) &vQuad, 0);
#else
HRESULT hr = ((CD3D8Renderer*)gRenDev)->m_pQuadVB->Lock(0, 0, (BYTE **) &vQuad, D3DLOCK_DISCARD);
#endif
float x0 = 0.0f;
float y0 = 0.0f;
float x1 = 256.0f;
float y1 = 256.0f;
vQuad[0].dvSX = x0;
vQuad[0].dvSY = y0;
vQuad[0].dvSZ = 1.0f;
vQuad[0].dvRHW = 1.0f;
vQuad[0].dcColor = col;
vQuad[0].dvTU[0] = crd[0][0];
vQuad[0].dvTU[1] = crd[0][1];
vQuad[0].dvTU[2] = crd[0][2];
vQuad[1].dvSX = x0;
vQuad[1].dvSY = y1;
vQuad[1].dvSZ = 1.0f;
vQuad[1].dvRHW = 1.0f;
vQuad[1].dcColor = col;
vQuad[1].dvTU[0] = crd[1][0];
vQuad[1].dvTU[1] = crd[1][1];
vQuad[1].dvTU[2] = crd[1][2];
vQuad[2].dvSX = x1;
vQuad[2].dvSY = y1;
vQuad[2].dvSZ = 1.0f;
vQuad[2].dvRHW = 1.0f;
vQuad[2].dcColor = col;
vQuad[2].dvTU[0] = crd[2][0];
vQuad[2].dvTU[1] = crd[2][1];
vQuad[2].dvTU[2] = crd[2][2];
vQuad[3].dvSX = x1;
vQuad[3].dvSY = y0;
vQuad[3].dvSZ = 1.0f;
vQuad[3].dvRHW = 1.0f;
vQuad[3].dcColor = col;
vQuad[3].dvTU[0] = crd[3][0];
vQuad[3].dvTU[1] = crd[3][1];
vQuad[3].dvTU[2] = crd[3][2];
((CD3D8Renderer*)gRenDev)->m_pQuadVB->Unlock();
dv->SetStreamSource(0, ((CD3D8Renderer*)gRenDev)->m_pQuadVB, sizeof(SPipeTRVertex_D_3T_w));
dv->SetVertexShader((D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0)));
dv->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
gRenDev->m_nPolygons += 2;
}
// !!! WARNING !!!
//if (pImage->m_eTT == eTT_Cubemap)
// glDisable(pImage->m_TargetType);
gRenDev->Set2DMode(false, 256, 256);
//glEnable(GL_TEXTURE_2D);
gRenDev->EnableTMU(true);
//glEnable(GL_CULL_FACE);
gRenDev->SetCullMode(R_CULL_BACK);
//glEnable(GL_DEPTH_TEST);
gRenDev->EnableDepthTest(true);
//glClear(GL_DEPTH_BUFFER_BIT);
gRenDev->ClearDepthBuffer();
{
/*int width = 256;
int height = 256;
byte *pic = new byte [width * height * 4];
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pic);
WriteTGA(pic,width,height,"EndCube.tga");
delete [] pic;*/
}
}
else
{
//glClearColor(1,0,0,0);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glScissor(0, 0, x2, y2);
//glDisable (GL_SCISSOR_TEST);
// !!! WARNING !!!
///gcpOGL->EF_ClearBuffers(true, false);
//glScissor(0, 0, gcpOGL->GetWidth(), gcpOGL->GetHeight());
/*gcpOGL->m_bWasCleared = true;
glClearColor(gcpOGL->m_vClearColor.x,gcpOGL->m_vClearColor.y,gcpOGL->m_vClearColor.z,0);
if (gRenDev->GetStencilBpp())
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
else
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/
}
}
void CD3D8TexMan::ClearBuffer(int Width, int Height, bool bEnd, STexPic *pImage, int Side)
{
}
//===================================================================================
void CD3D8TexMan::DrawCubeSide( const float *angle, Vec3d& Pos, int tex_size, int side, int RendFlags)
{
if (!iSystem)
return;
CRenderer * renderer = gRenDev;
CCamera tmp_camera = renderer->GetCamera();
CCamera prevCamera = tmp_camera;
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
float fMaxDist = eng->GetMaxViewDistance();
float fMinDist = 0.25f;
tmp_camera.Init(tex_size,tex_size, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
tmp_camera.SetPos(Pos);
tmp_camera.SetAngle(Vec3d(angle[0], angle[1], angle[2]));
tmp_camera.Update();
iSystem->SetViewCamera(tmp_camera);
gRenDev->SetCamera(tmp_camera);
gRenDev->SetViewport(0, 0, tex_size, tex_size);
if (gRenDev->m_LogFile)
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. DrawLowDetail .. (DrawCubeSide %d)\n", side);
eng->DrawLowDetail(RendFlags);
if (gRenDev->m_LogFile)
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. End DrawLowDetail .. (DrawCubeSide %d)\n", side);
iSystem->SetViewCamera(prevCamera);
gRenDev->SetCamera(prevCamera);
}
bool CD3D8TexMan::ScanEnvironmentCM (const char *name, int size, Vec3d& Pos)
{
return false;
}
void CD3D8TexMan::ScanEnvironmentCube(SEnvTexture *cm, int RendFlags)
{
if (cm->m_bInprogress)
return;
CRenderer * renderer = gRenDev;
int tex_size;
switch (CRenderer::CV_r_envcmresolution)
{
case 0:
tex_size = 64;
break;
case 1:
tex_size = 128;
break;
case 2:
default:
tex_size = 256;
break;
}
while(true)
{
if (tex_size*3>renderer->GetWidth() || tex_size*2>renderer->GetHeight())
tex_size >>= 1;
else
break;
}
if (tex_size <= 8)
return;
int n;
Vec3d cur_pos;
static float sAngles[6][5] =
{
{ 90, -90, 0, 0, 0 }, //posx
{ 90, 90, 0, 1, 0 }, //negx
{ 180, 180, 0, 2, 0 }, //posy
{ 0, 180, 0, 0, 1 }, //negy
{ 90, 180, 0, 1, 1 }, //posz
{ 90, 0, 0, 2, 1 }, //negz
};
cm->m_bInprogress = true;
int tid = TO_ENVIRONMENT_CUBE_MAP_REAL + cm->m_Id;
if (!(cm->m_Tex->m_Flags & FT_ALLOCATED) || tex_size != cm->m_TexSize)
{
cm->m_Tex->m_Flags |= FT_ALLOCATED | FT_NOMIPS;
cm->m_Tex->m_Flags &= ~FT_DXT;
cm->m_Tex->m_Flags2 |= FT2_NODXT | FT2_RENDERTARGET;
cm->m_Tex->m_nMips = 0;
cm->m_Tex->m_Width = cm->m_Tex->m_WidthReal = tex_size;
cm->m_Tex->m_Height = cm->m_Tex->m_HeightReal = tex_size;
cm->m_TexSize = tex_size;
byte *data = new byte [tex_size*tex_size*4];
gRenDev->m_TexMan->CreateTexture(NULL, tex_size, tex_size, 1, FT_NOMIPS, FT2_NODXT | FT2_RENDERTARGET, data, eTT_Cubemap, -1.0f, -1.0f, 0, cm->m_Tex);
SetTexture(0, eTT_Cubemap);
delete [] data;
}
STexPicD3D *tp = (STexPicD3D *)cm->m_Tex;
if (!tp->m_RefTex || !tp->m_RefTex->m_VidTex)
return;
CD3D8Renderer *r = gcpRendD3D;
LPDIRECT3DCUBETEXTURE8 pID3DTargetTexture = (LPDIRECT3DCUBETEXTURE8)tp->m_RefTex->m_VidTex;
gRenDev->EF_SaveDLights();
int Start, End;
if (!cm->m_bReady || CRenderer::CV_r_envcmwrite)
{
Start = 0;
End = 6;
}
else
{
Start = cm->m_MaskReady;
End = cm->m_MaskReady+1;
}
int vX, vY, vWidth, vHeight;
gRenDev->GetViewport(&vX, &vY, &vWidth, &vHeight);
gRenDev->EF_PushFog();
gRenDev->m_RP.m_bDrawToTexture = true;
Vec3d Pos;
gRenDev->m_RP.m_pRE->mfCenter(Pos, gRenDev->m_RP.m_pCurObject);
Pos += cm->m_CamPos;
for(n=Start; n<End; n++)
{
LPDIRECT3DSURFACE8 pSrcSurf;
h = pID3DTargetTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)n, 0, &pSrcSurf);
r->m_pd3dDevice->SetRenderTarget( pSrcSurf, r->m_pZBuffer );
pSrcSurf->Release();
D3DCOLOR cColor = D3DRGBA(0.0f,0.0f,0.0f,0.0f);
// render object
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
DrawCubeSide( &sAngles[n][0], Pos, tex_size, n, RendFlags);
if (CRenderer::CV_r_envcmwrite)
{
static char* cubefaces[6] = {"posx","negx","posy","negy","posz","negz"};
char str[64];
int width = tex_size;
int height = tex_size;
byte *pic = new byte [width * height * 4];
//glReadPixels(tex_size*(int)sAngles[n][3], tex_size*(int)sAngles[n][4], width, height, GL_RGBA, GL_UNSIGNED_BYTE, pic);
sprintf(str, "Cube_%s.jpg", cubefaces[n]);
#ifndef _XBOX
WriteJPG(pic, width, height, str);
#endif
delete [] pic;
}
}
r->m_pd3dDevice->SetRenderTarget( r->m_pBackBuffer, r->m_pZBuffer );
CRenderer::CV_r_envcmwrite = 0;
cm->m_Tex->m_Bind = tid;
gRenDev->SetViewport(vX, vY, vWidth, vHeight);
ClearBuffer(tex_size,tex_size,true,NULL,0);
cm->m_bInprogress = false;
cm->m_MaskReady = End;
if (cm->m_MaskReady == 6)
{
cm->m_MaskReady = 0;
cm->m_bReady = true;
}
SetTexture(0, eTT_Cubemap);
gRenDev->m_RP.m_bDrawToTexture = false;
gRenDev->EF_PopFog();
gRenDev->EF_RestoreDLights();
}
void CD3D8TexMan::ScanEnvironmentTexture(SEnvTexture *cm, int RendFlags)
{
if (cm->m_bInprogress)
return;
CRenderer * renderer = gRenDev;
int tex_size;
switch (CRenderer::CV_r_envtexresolution)
{
case 0:
tex_size = 64;
break;
case 1:
tex_size = 128;
break;
case 2:
default:
tex_size = 256;
break;
case 3:
tex_size = 512;
break;
}
while(true)
{
if (tex_size>renderer->GetWidth() || tex_size>renderer->GetHeight())
tex_size >>= 1;
else
break;
}
if (tex_size <= 8)
return;
Vec3d cur_pos;
cm->m_bInprogress = true;
int tid = TO_ENVIRONMENT_TEX_MAP_REAL + cm->m_Id;
if (!(cm->m_Tex->m_Flags & FT_ALLOCATED) || tex_size != cm->m_TexSize)
{
cm->m_Tex->m_Flags |= FT_ALLOCATED | FT_NOMIPS;
cm->m_Tex->m_Flags &= ~FT_DXT;
cm->m_Tex->m_Flags2 |= FT2_NODXT | FT2_RENDERTARGET;
cm->m_TexSize = tex_size;
cm->m_Tex->m_Width = cm->m_Tex->m_Height = tex_size;
cm->m_Tex->m_WidthReal = cm->m_Tex->m_HeightReal = tex_size;
cm->m_Tex->m_nMips = 0;
byte *data = new byte [tex_size*tex_size*4];
gRenDev->m_TexMan->CreateTexture(NULL, tex_size, tex_size, 1, FT_NOMIPS, FT2_NODXT | FT2_RENDERTARGET, data, eTT_Base, -1.0f, -1.0f, 0, cm->m_Tex);
delete [] data;
}
STexPicD3D *tp = (STexPicD3D *)cm->m_Tex;
if (!tp->m_RefTex || !tp->m_RefTex->m_VidTex)
return;
CD3D8Renderer *r = gcpRendD3D;
LPDIRECT3DTEXTURE8 pID3DTargetTexture = (LPDIRECT3DTEXTURE8)tp->m_RefTex->m_VidTex;
LPDIRECT3DSURFACE8 pSrcSurf;
h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
r->m_pd3dDevice->SetRenderTarget( pSrcSurf, r->m_pZBuffer );
pSrcSurf->Release();
D3DCOLOR cColor = D3DRGBA(0.0f,0.0f,0.0f,0.0f);
// render object
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
int vX, vY, vWidth, vHeight;
gRenDev->GetViewport(&vX, &vY, &vWidth, &vHeight);
gRenDev->EF_PushFog();
gRenDev->m_RP.m_bDrawToTexture = true;
{
CCamera tmp_camera = renderer->GetCamera();
CCamera prevCamera = tmp_camera;
r->SetViewport(0, 0, tex_size, tex_size);
I3DEngine *eng = (I3DEngine *)iSystem->GetIProcess();
eng->DrawLowDetail(0);
iSystem->SetViewCamera(prevCamera);
r->SetCamera(prevCamera);
}
r->m_pd3dDevice->SetRenderTarget( r->m_pBackBuffer, r->m_pZBuffer );
/* int width = tex_size;
int height = tex_size;
byte *pic = new byte [width * height * 3];
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pic);
CImage::SaveTga(pic,FORMAT_24_BIT,width,height,"TexEnv.tga",false);
delete [] pic;*/
gRenDev->SetViewport(vX, vY, vWidth, vHeight);
gRenDev->EF_PopFog();
cm->m_bInprogress = false;
cm->m_bReady = true;
cm->m_MaskReady = 1;
gRenDev->m_RP.m_bDrawToTexture = false;
}
//========================================================================================
void CD3D8TexMan::StartCubeSide(CCObject *obj)
{
}
void CD3D8TexMan::EndCubeSide(CCObject *obj, bool bNeedClear)
{
}
void CD3D8TexMan::DrawToTexture(Plane& Pl, STexPic *Tex, int RendFlags)
{
float Smat[16] =
{
0.5f, 0, 0, 0,
0, -0.5f, 0, 0,
0, 0, 0.5f, 0,
0.5f, 0.5f, 0.5f, 1.0f
};
if (Tex->m_Flags & FT_BUILD)
return;
CD3D8Renderer *r = gcpRendD3D;
float plane[4];
plane[0] = Pl.n[0];
plane[1] = Pl.n[1];
plane[2] = Pl.n[2];
plane[3] = -Pl.d;
Tex->m_Width = sLimitSizeByScreenRes(Tex->m_Width);
Tex->m_Height = sLimitSizeByScreenRes(Tex->m_Height);
Tex->m_Flags |= FT_BUILD;
if (!(Tex->m_Flags & FT_ALLOCATED))
{
Tex->m_Flags |= FT_ALLOCATED;
// Preallocate texture
int tex_size = Tex->m_Width;
byte *data = new byte [tex_size*tex_size*4];
//memset(data, 0, tex_size*tex_size*4);
Tex->m_Flags |= FT_NOMIPS | FT_CLAMP;
Tex->m_Flags2 |= FT2_NODXT | FT2_RENDERTARGET;
Tex->m_nMips = 0;
AddToHash(Tex->m_Bind, Tex);
gRenDev->m_TexMan->CreateTexture(NULL, tex_size, tex_size, 1, FT_NOMIPS | FT_CLAMP, FT2_NODXT | FT2_RENDERTARGET, data, eTT_Base, -1.0f, -1.0f, 0, Tex);
delete [] data;
}
gRenDev->EF_SaveDLights();
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
float fMinDist = Min(16.0f, eng->GetDistanceToSectorWithWater()); // 16 is half of skybox size
float fMaxDist = eng->GetMaxViewDistance();
CCamera tmp_cam = gRenDev->GetCamera();
CCamera prevCamera = tmp_cam;
tmp_cam.Init(Tex->m_Width, Tex->m_Height, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
Vec3d pos = tmp_cam.GetPos();
Vec3d vMirPos = Pl.MirrorPosition(pos);
Vec3d vOccPos = pos - Pl.n * (0.99f * ((Pl.n | pos) - Pl.d));
tmp_cam.SetPos(vMirPos);
tmp_cam.SetOccPos(vOccPos);
Vec3d ang = tmp_cam.GetAngles();
ang[0] = -ang[0];
tmp_cam.SetAngle(ang);
tmp_cam.Update();
int TempX, TempY, TempWidth, TempHeight;
DWORD cColor = D3DRGBA(gRenDev->m_vClearColor[0], gRenDev->m_vClearColor[1], gRenDev->m_vClearColor[2], 0);
#ifdef _XBOX
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, cColor, 1.0f, 0);
#endif //_XBOX
STexPicD3D *tp = (STexPicD3D *)Tex;
LPDIRECT3DTEXTURE8 pID3DTargetTexture = (LPDIRECT3DTEXTURE8)tp->m_RefTex->m_VidTex;
LPDIRECT3DSURFACE8 pSrcSurf;
h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
h = r->m_pd3dDevice->SetRenderTarget(pSrcSurf, r->m_pZBuffer);
pSrcSurf->Release();
gRenDev->GetViewport(&TempX, &TempY, &TempWidth, &TempHeight);
gRenDev->SetViewport( 0, 0, Tex->m_Width, Tex->m_Height );
gRenDev->EF_PushFog();
gRenDev->m_RP.m_bDrawToTexture = true;
#ifndef _XBOX
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, cColor, 1.0f, 0);
#endif //_XBOX
// render object
iSystem->SetViewCamera(tmp_cam);
gRenDev->SetCamera(tmp_cam);
if (!Tex->m_Matrix)
Tex->m_Matrix = new float[16];
float matProj[16], matView[16];
r->GetModelViewMatrix(matView);
r->GetProjectionMatrix(matProj);
Matrix m;
m = Matrix(Smat);
D3DXMatrixMultiply((D3DXMATRIX *)&m(0,0), (D3DXMATRIX *)matProj, (D3DXMATRIX *)&m(0,0));
D3DXMatrixMultiply((D3DXMATRIX *)Tex->m_Matrix, (D3DXMATRIX *)matView, (D3DXMATRIX *)&m(0,0));
r->m_RP.m_PersFlags |= RBPF_NOCLEARBUF;
//r->m_pd3dDevice->SetClipPlane( 0, plane);
//r->m_pd3dDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 1);
eng->DrawLowDetail(RendFlags);
/*{
int tex_size = Tex->m_Width;
LPDIRECT3DTEXTURE8 pID3DSrcTexture;
D3DLOCKED_RECT d3dlr;
h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
LPDIRECT3DSURFACE8 pDstSurf;
h = D3DXCreateTexture(r->m_pd3dDevice, tex_size, tex_size, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSrcTexture );
h = pID3DSrcTexture->GetSurfaceLevel(0, &pDstSurf);
h = r->m_pd3dDevice->CopyRects(pSrcSurf, NULL, 0, pDstSurf, NULL);
h = pID3DSrcTexture->LockRect(0, &d3dlr, NULL, 0);
// Copy data to the texture
#ifdef _XBOX
DWORD *pSrcBits = new DWORD[tex_size*tex_size];
//XGUnswizzleRect( d3dlr.pBits, tex_size, tex_size, NULL, pSrcBits, d3dlr.Pitch, NULL, 4 );
//WriteTGA((byte *)pSrcBits, tex_size, tex_size, "d:\\Problem.tga", 32);
delete [] pSrcBits;
#else
WriteTGA((byte *)d3dlr.pBits, tex_size, tex_size, "d:\\Problem.tga", 32);
#endif
// Unlock the texture
pID3DSrcTexture->UnlockRect(0);
pSrcSurf->Release();
pDstSurf->Release();
SAFE_RELEASE (pID3DSrcTexture);
}*/
r->m_RP.m_PersFlags &= ~RBPF_NOCLEARBUF;
Tex->m_Flags &= ~FT_BUILD;
//r->m_pd3dDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
h = r->m_pd3dDevice->SetRenderTarget( r->m_pBackBuffer, r->m_pZBuffer );
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, cColor, 1.0f, 0);
gRenDev->SetCamera(prevCamera);
iSystem->SetViewCamera(prevCamera);
gRenDev->SetViewport(TempX, TempY, TempWidth, TempHeight);
gRenDev->m_RP.m_bDrawToTexture = false;
gRenDev->EF_PopFog();
gRenDev->EF_RestoreDLights();
}
void CD3D8TexMan::DrawToTextureForRainMap(int Id)
{
}
void CD3D8TexMan::CreateBufRegion(int Width, int Height)
{
/// !!! WARNING !!!
}
_inline byte mulc(int i1)
{
//amplify colors a bit
int r = i1 + (i1/4);
if (r > 255)
return 255;
else
return r;
}
void CD3D8TexMan::AmplifyGlare(SByteColor *glarepixels, int width, int height)
{
int i;
for (i=0; i<width*height; i++)
{
if ( glarepixels[i].r > CRenderer::CV_r_glarethreshold || glarepixels[i].g > CRenderer::CV_r_glarethreshold || glarepixels[i].b > CRenderer::CV_r_glarethreshold)
{
glarepixels[i].r = mulc(glarepixels[i].r);
glarepixels[i].g = mulc(glarepixels[i].g);
glarepixels[i].b = mulc(glarepixels[i].b);
}
else
{
glarepixels[i].r = 0; //divc(glarepixels[i].r);
glarepixels[i].g = 0; //divc(glarepixels[i].g);
glarepixels[i].b = 0; //divc(glarepixels[i].b);
}
}
}
void CD3D8TexMan::SmoothGlare(SByteColor *src, int src_w, int src_h, SLongColor *dst)
{
int y,x;
for (y=0;y<src_h;y++)
{
for (x=0;x<src_w;x++)
{
dst->r = src[0].r;
dst->g = src[0].g;
dst->b = src[0].b;
if (x > 0)
{
dst->r += dst[-1].r;
dst->g += dst[-1].g;
dst->b += dst[-1].b;
}
if (y > 0)
{
dst->r += dst[-src_w].r;
dst->g += dst[-src_w].g;
dst->b += dst[-src_w].b;
}
if (x > 0 && y > 0)
{
dst->r -= dst[-src_w-1].r;
dst->g -= dst[-src_w-1].g;
dst->b -= dst[-src_w-1].b;
}
dst++;
src++;
}
}
}
// this is a utility function used by DoBoxBlur below
_inline SLongColor *ReadP(SLongColor *p, int w, int h, int x, int y, int UBits)
{
if (x < 0)
x = 0;
else
if (x >= w)
x = w-1;
if (y < 0)
y = 0;
else
if (y >= h)
y = h-1;
return &p[x+(y<<UBits)];
}
void CD3D8TexMan::BlurGlare(SByteColor *src, int src_w, int src_h, SByteColor *dst, SLongColor *p, int boxw, int boxh)
{
SLongColor *to1, *to2, *to3, *to4;
int y,x;
float fmul;
if (boxw < 0 || boxh < 0)
{
memcpy(dst,src,src_w*src_h*4); // deal with degenerate kernel sizes
return;
}
fmul=1.f/((boxw*2+1)*(boxh*2+1));
int n = 0;
while (!(src_w & (1<<n)))
n++;
int UBits = n;
for (y=0;y<src_h;y++)
{
for (x=0;x<src_w;x++)
{
to1 = ReadP(p,src_w,src_h,x+boxw,y+boxh, UBits);
to2 = ReadP(p,src_w,src_h,x-boxw,y-boxh, UBits);
to3 = ReadP(p,src_w,src_h,x-boxw,y+boxh, UBits);
to4 = ReadP(p,src_w,src_h,x+boxw,y-boxh, UBits);
dst->r = (byte)QRound((to1->r + to2->r - to3->r - to4->r)*fmul);
dst->g = (byte)QRound((to1->g + to2->g - to3->g - to4->g)*fmul);
dst->b = (byte)QRound((to1->b + to2->b - to3->b - to4->b)*fmul);
dst++;
src++;
}
}
}
void CD3D8TexMan::DrawToTextureForGlare(int Id)
{
//*
LPDIRECT3DDEVICE8 dv = gcpRendD3D->mfGetD3DDevice();
if (!iSystem)
return;
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
CREGlare *pRE = gRenDev->m_RP.m_pREGlare;
STexPic *Tex = CTexMan::m_Text_Glare;
if (Tex->m_Flags & FT_BUILD)
return;
Tex->m_Flags |= FT_BUILD;
if (CRenderer::CV_r_glaresize != gRenDev->m_RP.m_GlareSize)
{
if (CRenderer::CV_r_glaresize <= 32)
CRenderer::CV_r_glaresize = 32;
else
if (CRenderer::CV_r_glaresize <= 64)
CRenderer::CV_r_glaresize = 64;
else
if (CRenderer::CV_r_glaresize <= 128)
CRenderer::CV_r_glaresize = 128;
else
CRenderer::CV_r_glaresize = 256;
CRenderer::CV_r_glaresize = sLimitSizeByScreenRes(CRenderer::CV_r_glaresize);
gRenDev->m_RP.m_GlareSize = CRenderer::CV_r_glaresize;
Tex->m_Flags &= ~FT_ALLOCATED;
pRE->m_GlareWidth = pRE->m_GlareHeight = gRenDev->m_RP.m_GlareSize;
pRE->mfInit();
}
int nTexWidth = pRE->m_GlareWidth;
int nTexHeight = pRE->m_GlareHeight;
float fMaxDist = eng->GetMaxViewDistance();
float fMinDist = 0.25f;
int width = 512;
int height = 512;
if (!(Tex->m_Flags & FT_ALLOCATED))
{
/// !!! WARNING !!!
/*
Tex->m_Width = Tex->m_WidthReal = nTexWidth;
Tex->m_Height = Tex->m_HeightReal = nTexHeight;
Tex->m_Flags |= FT_ALLOCATED;
// Preallocate texture
AddToHash(Tex->m_Bind, Tex);
SetTexture(Tex->m_Bind, eTT_Base);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Tex->m_Width, Tex->m_Height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
SetTexture(0, eTT_Base);
*/
}
CreateBufRegion(width, height);
ClearBuffer(width, height, true, NULL, 0);
gRenDev->EF_SaveDLights();
CCamera tmp_cam = gRenDev->GetCamera();
CCamera prevCamera = tmp_cam;
//tmp_cam.Init(Tex->m_Width, Tex->m_Height, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
//tmp_cam.Update();
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
gRenDev->SetViewport( 0, 0, width, height );
gRenDev->EF_PushFog();
gRenDev->m_RP.m_bDrawToTexture = true;
eng->SetCamera(tmp_cam,false);
if (gRenDev->m_LogFile)
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** Draw scene to texture for glare ***\n");
int nDrawFlags = DLD_INDOORS | DLD_ADD_LIGHTSOURCES | DLD_ENTITIES | DLD_PARTICLES | DLD_STATIC_OBJECTS | DLD_FAR_SPRITES | DLD_TERRAIN_FULLRES;
eng->DrawLowDetail(nDrawFlags);
if (gRenDev->m_LogFile)
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. End DrawLowDetail .. (DrawToTextureForGlare)\n");
// Generate texture with mip-maps
{
/// !!! WARNING !!!!
static uint sTexId;
if (!sTexId)
{
/*
glGenTextures(1, &sTexId);
SetTexture(sTexId, eTT_Base);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
*/
byte *data = new byte[width*height*4];
char name[128];
sprintf(name, "$AutoGlare_%d", gcpRendD3D->m_TexGenID++);
STexPic *tp = gcpRendD3D->m_TexMan->CreateTexture(name, width, height, 1, FT_NOMIPS | FT_ALLOCATED, FT2_NODXT, data, eTT_Base, -1.0f, -1.0f, 0, NULL);
delete [] data;
sTexId = tp->m_Bind;
IDirect3DSurface8 * pTar = gcpRendD3D->mfGetBackSurface();
D3DSURFACE_DESC dc;
pTar->GetDesc(&dc);
if(tp->m_RefTex->m_VidTex)
((LPDIRECT3DTEXTURE8)tp->m_RefTex->m_VidTex)->Release();
HRESULT h = D3DXCreateTexture(dv, width, height, 1, D3DUSAGE_DYNAMIC, dc.Format, D3DPOOL_DEFAULT, ((LPDIRECT3DTEXTURE8* )& tp->m_RefTex->m_VidTex ));
}
SetTexture(sTexId, eTT_Base);
///!!! WARNING !!!
///if (SUPPORTS_GL_SGIS_generate_mipmap)
/// glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
///glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width, height);
{
//byte *pDst = new byte [width*height*4];
//glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pDst);
//WriteJPG(pDst, width, height, "GlareBig.jpg");
//delete [] pDst;
}
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
///glMatrixMode(GL_PROJECTION);
///glLoadIdentity();
///glOrtho(0.0, gRenDev->GetWidth(), 0.0, gRenDev->GetHeight(), -20.0, 0.0);
gcpRendD3D->m_matProj->LoadIdentity();
dv->SetTransform(D3DTS_PROJECTION, gcpRendD3D->m_matProj->GetTop());
///glMatrixMode(GL_MODELVIEW);
///glLoadIdentity();
gcpRendD3D->m_matView->LoadIdentity();
dv->SetTransform(D3DTS_VIEW, gcpRendD3D->m_matView->GetTop());
gRenDev->SetCullMode(R_CULL_NONE);
// Reduce texture size
{
/// !!! WARNING !!!
/*
glDisable(GL_DEPTH_TEST);
SetTexture(sTexId, eTT_Base);
// gRenDev->SetState(GS_NODEPTHTEST);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0, 0, 0);
glTexCoord2f(1, 0);
glVertex3f((float)Tex->m_Width, 0, 0);
glTexCoord2f(1, 1);
glVertex3f((float)Tex->m_Width, (float)Tex->m_Height, 0);
glTexCoord2f(0, 1);
glVertex3f(0, (float)Tex->m_Height, 0);
glEnd();
*/
}
/// !!! WARNING !!!
///if (SUPPORTS_GL_SGIS_generate_mipmap)
/// glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);
}
/// !!! WARNING !!!
///glReadPixels (0, 0, Tex->m_Width, Tex->m_Height, GL_RGBA, GL_UNSIGNED_BYTE, pRE->m_pGlarePixels);
//WriteJPG((byte *)pRE->m_pGlarePixels, 64, 64, "GlareSmall.jpg");
if (CRenderer::CV_r_glare == 3)
{
CRenderer::CV_r_glare = 1;
#ifndef _XBOX
WriteJPG((byte *)pRE->m_pGlarePixels, Tex->m_Width, Tex->m_Height, "Glare.jpg");
#endif
}
AmplifyGlare(pRE->m_pGlarePixels, Tex->m_Width, Tex->m_Height);
SmoothGlare(pRE->m_pGlarePixels, Tex->m_Width, Tex->m_Height, pRE->m_pGlareSum);
BlurGlare(pRE->m_pGlarePixels, Tex->m_Width, Tex->m_Height, pRE->m_pGlareBlurPixels, pRE->m_pGlareSum, CRenderer::CV_r_glareboxsize, CRenderer::CV_r_glareboxsize);
/// !!! WARNING !!!
/*
SetTexture(Tex->m_Bind, eTT_Base);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Tex->m_Width, Tex->m_Height, GL_RGBA, GL_UNSIGNED_BYTE, pRE->m_pGlareBlurPixels);
*/
//Tex->SaveJPG("GlareFinal.jpg", false);
SetTexture(0, eTT_Base);
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
gRenDev->SetCamera(prevCamera);
iSystem->SetViewCamera(prevCamera);
ClearBuffer(width, height, true, NULL,0);
Tex->m_Flags &= ~FT_BUILD;
gRenDev->m_RP.m_bDrawToTexture = false;
gRenDev->EF_PopFog();
gRenDev->EF_RestoreDLights();
/**/
}
//==================================================================================
// Heat map
_inline void D3DQuad(float wdt, float hgt, CFColor fcol)
{
DWORD col = fcol.GetTrue();
CD3D8Renderer *r = gcpRendD3D;
void *pVertices;
#ifndef _XBOX
HRESULT hr = r->m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, D3DLOCK_DISCARD);
#else //_XBOX
HRESULT hr = r->m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, 0);
#endif //_XBOX
SPipeTRVertex_D_1T *vQuad = (SPipeTRVertex_D_1T *)pVertices;
// Define the quad
vQuad[0].dvSX = 0.0f;
vQuad[0].dvSY = 0.0f;
vQuad[0].dvSZ = 0.0f;
vQuad[0].dvRHW = 1.0f;
vQuad[0].dcColor = col;
vQuad[0].dvTU[0] = 0.0f;
vQuad[0].dvTU[1] = 0.0f;
vQuad[1].dvSX = wdt;
vQuad[1].dvSY = 0.0f;
vQuad[1].dvSZ = 0.0f;
vQuad[1].dvRHW = 1.0f;
vQuad[1].dcColor = col;
vQuad[1].dvTU[0] = 1.0f;
vQuad[1].dvTU[1] = 0.0f;
vQuad[2].dvSX = wdt;
vQuad[2].dvSY = hgt;
vQuad[2].dvSZ = 0.0f;
vQuad[2].dvRHW = 1.0f;
vQuad[2].dcColor = col;
vQuad[2].dvTU[0] = 1.0f;
vQuad[2].dvTU[1] = 1.0f;
vQuad[3].dvSX = 0.0f;
vQuad[3].dvSY = hgt;
vQuad[3].dvSZ = 0.0f;
vQuad[3].dvRHW = 1.0f;
vQuad[3].dcColor = col;
vQuad[3].dvTU[0] = 0.0f;
vQuad[3].dvTU[1] = 1.0f;
// We are finished with accessing the vertex buffer
r->m_pQuadVB->Unlock();
// Bind our vertex as the first data stream of our device
r->m_pd3dDevice->SetStreamSource(0, r->m_pQuadVB, STRIDE_TR_D_1T);
// Set the vertex shader to the FVF fixed function shader
r->m_pd3dDevice->SetVertexShader(D3DFVF_TRVERTEX_D_1T);
// Render the two triangles from the data stream
hr = r->m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
}
void CD3D8TexMan::EndHeatMap()
{
STexPic *Tex = CTexMan::m_Text_HeatMap;
CD3D8Renderer *r = gcpRendD3D;
r->m_RP.m_PersFlags &= ~(RBPF_NOCLEARBUF | RBPF_DRAWHEATMAP);
Tex->m_Flags &= ~FT_BUILD;
if (CRenderer::CV_r_heattype == 1)
{
int i;
float wdt = (float)Tex->m_Width;
float hgt = (float)Tex->m_Height;
r->EF_SetVertColor();
r->m_matProj->Push();
D3DXMATRIX *m = r->m_matProj->GetTop();
D3DXMatrixOrthoOffCenterLH(m, 0.0, wdt, 0.0, hgt, -20.0, 0.0);
r->m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
r->EF_PushMatrix();
m = r->m_matView->GetTop();
r->m_matView->LoadIdentity();
r->m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
r->SetCullMode(R_CULL_NONE);
r->SetEnviMode(R_MODE_MODULATE);
r->SetState(GS_NODEPTHTEST);
//CTexMan::m_Text_White->Set();
Tex->Set();
//D3DQuad(wdt, hgt, CFColor(1,1,1,1));
r->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
for (i=0; i<4; i++)
{
float fOffs = (i+1)*(Tex->m_Width/1024.0f);
float fAlpha = 0.1f;
r->EF_PushMatrix();
r->m_matView->TranslateLocal(fOffs,0,0);
m = r->m_matView->GetTop();
r->m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
D3DQuad(wdt, hgt, CFColor(1,1,1,fAlpha));
r->EF_PopMatrix();
r->EF_PushMatrix();
r->m_matView->TranslateLocal(-fOffs,0,0);
m = r->m_matView->GetTop();
r->m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
D3DQuad(wdt, hgt, CFColor(1,1,1,fAlpha));
r->EF_PopMatrix();
r->EF_PushMatrix();
r->m_matView->TranslateLocal(0,fOffs,0);
m = r->m_matView->GetTop();
r->m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
D3DQuad(wdt, hgt, CFColor(1,1,1,fAlpha));
r->EF_PopMatrix();
r->EF_PushMatrix();
r->m_matView->TranslateLocal(0,-fOffs,0);
m = r->m_matView->GetTop();
r->m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
D3DQuad(wdt, hgt, CFColor(1,1,1,fAlpha));
r->EF_PopMatrix();
}
float fRandU = RandomNum() * 2.0f;
float fRandV = RandomNum() * 2.0f;
gRenDev->SetState(GS_BLSRC_DSTCOL | GS_BLDST_SRCCOL | GS_NODEPTHTEST);
STexPic *tp = gRenDev->m_TexMan->LoadTexture("Textures/Defaults/HeatNoise", 0, 0);
tp->Set();
void *pVertices;
#ifndef _XBOX
HRESULT hr = r->m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, D3DLOCK_DISCARD);
#else //_XBOX
HRESULT hr = r->m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, 0);
#endif //_XBOX
SPipeTRVertex_D_1T *vQuad = (SPipeTRVertex_D_1T *)pVertices;
DWORD col = -1;
// Define the quad
vQuad[0].dvSX = 0.0f;
vQuad[0].dvSY = 0.0f;
vQuad[0].dvSZ = 0.0f;
vQuad[0].dvRHW = 1.0f;
vQuad[0].dcColor = col;
vQuad[0].dvTU[0] = fRandU;
vQuad[0].dvTU[1] = fRandV;
vQuad[1].dvSX = wdt;
vQuad[1].dvSY = 0.0f;
vQuad[1].dvSZ = 0.0f;
vQuad[1].dvRHW = 1.0f;
vQuad[1].dcColor = col;
vQuad[1].dvTU[0] = 4.0f+fRandU;
vQuad[1].dvTU[1] = fRandV;
vQuad[2].dvSX = wdt;
vQuad[2].dvSY = hgt;
vQuad[2].dvSZ = 0.0f;
vQuad[2].dvRHW = 1.0f;
vQuad[2].dcColor = col;
vQuad[2].dvTU[0] = 4.0f+fRandU;
vQuad[2].dvTU[1] = 4.0f+fRandV;
vQuad[3].dvSX = 0.0f;
vQuad[3].dvSY = hgt;
vQuad[3].dvSZ = 0.0f;
vQuad[3].dvRHW = 1.0f;
vQuad[3].dcColor = col;
vQuad[3].dvTU[0] = fRandU;
vQuad[3].dvTU[1] = 4.0f+fRandV;
// We are finished with accessing the vertex buffer
r->m_pQuadVB->Unlock();
// Bind our vertex as the first data stream of our device
r->m_pd3dDevice->SetStreamSource(0, r->m_pQuadVB, STRIDE_TR_D_1T);
// Set the vertex shader to the FVF fixed function shader
r->m_pd3dDevice->SetVertexShader(D3DFVF_TRVERTEX_D_1T);
// Render the two triangles from the data stream
hr = r->m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
r->EF_PopMatrix();
r->m_matProj->Pop();
m = r->m_matProj->GetTop();
r->m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
}
h = r->m_pd3dDevice->SetRenderTarget(0, r->m_pBackBuffer);
iSystem->SetViewCamera(m_PrevCamera);
gRenDev->SetCamera(m_PrevCamera);
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
gRenDev->m_RP.m_bDrawToTexture = false;
if (CRenderer::CV_r_heatmapsave)
{
CRenderer::CV_r_heatmapsave = 0;
Tex->SaveJPG("HeatMap.jpg", false);
}
}
void CD3D8TexMan::StartHeatMap(int Id)
{
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
STexPic *Tex = CTexMan::m_Text_HeatMap;
if (Tex->m_Flags & FT_BUILD)
return;
CD3D8Renderer *r = gcpRendD3D;
if (CRenderer::CV_r_heatsize != gRenDev->m_RP.m_HeatSize)
{
if (CRenderer::CV_r_heatsize <= 64)
CRenderer::CV_r_heatsize = 64;
else
if (CRenderer::CV_r_heatsize <= 128)
CRenderer::CV_r_heatsize = 128;
else
if (CRenderer::CV_r_heatsize <= 256)
CRenderer::CV_r_heatsize = 256;
else
if (CRenderer::CV_r_heatsize <= 512)
CRenderer::CV_r_heatsize = 512;
gRenDev->m_RP.m_HeatSize = CRenderer::CV_r_heatsize;
Tex->m_Flags &= ~FT_ALLOCATED;
}
int nTexWidth = gRenDev->m_RP.m_HeatSize;
int nTexHeight = gRenDev->m_RP.m_HeatSize;
float fMaxDist = eng->GetMaxViewDistance();
float fMinDist = 0.25f;
Tex->m_Flags |= FT_BUILD;
if (!(Tex->m_Flags & FT_ALLOCATED))
{
Tex->m_Width = Tex->m_WidthReal = nTexWidth;
Tex->m_Height = Tex->m_HeightReal = nTexHeight;
Tex->m_Flags |= FT_ALLOCATED;
// Preallocate texture
byte *data = new byte [Tex->m_Width*Tex->m_Height*4];
Tex->m_Flags |= FT_NOMIPS;
Tex->m_Flags2 |= FT2_NODXT | FT2_RENDERTARGET;
AddToHash(Tex->m_Bind, Tex);
gRenDev->m_TexMan->CreateTexture(NULL, Tex->m_Width, Tex->m_Height, 1, FT_NOMIPS, FT2_NODXT | FT2_RENDERTARGET, data, eTT_Base, -1.0f, -1.0f, 0, Tex);
delete [] data;
}
CCamera tmp_cam = gRenDev->GetCamera();
m_PrevCamera = tmp_cam;
//tmp_cam.Init(Tex->m_Width, Tex->m_Height, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
//tmp_cam.Update();
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
gRenDev->SetViewport( 0, 0, Tex->m_Width, Tex->m_Height );
iSystem->SetViewCamera(tmp_cam);
gRenDev->SetCamera(tmp_cam);
if (gRenDev->m_LogFile)
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** Draw scene to texture for heat ***\n");
STexPicD3D *tp = (STexPicD3D *)Tex;
LPDIRECT3DTEXTURE8 pID3DTargetTexture = (LPDIRECT3DTEXTURE8)tp->m_RefTex->m_VidTex;
LPDIRECT3DSURFACE8 pSrcSurf;
h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
h = r->m_pd3dDevice->SetRenderTarget(0, pSrcSurf);
pSrcSurf->Release();
DWORD cColor = D3DRGBA(gRenDev->m_vClearColor[0], gRenDev->m_vClearColor[1], gRenDev->m_vClearColor[2], 0);
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
r->m_RP.m_PersFlags |= RBPF_NOCLEARBUF | RBPF_DRAWHEATMAP;
gRenDev->m_RP.m_bDrawToTexture = true;
//int nDrawFlags = DLD_INDOORS | DLD_ADD_LIGHTSOURCES | DLD_ENTITIES | DLD_PARTICLES | DLD_STATIC_OBJECTS | DLD_FAR_SPRITES | DLD_TERRAIN_FULLRES | DLD_TERRAIN_LIGHT | DLD_TERRAIN_WATER | DLD_NEAR_OBJECTS;
//eng->DrawLowDetail(nDrawFlags);
}
void CD3D8TexMan::EndNightMap()
{
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
STexPicD3D *Tex = (STexPicD3D *)CTexMan::m_Text_NightVisMap;
CD3D8Renderer *r = gcpRendD3D;
r->m_RP.m_PersFlags &= ~(RBPF_NOCLEARBUF | RBPF_DRAWNIGHTMAP);
Tex->m_Flags &= ~FT_BUILD;
r->m_RP.m_bDrawToTexture = false;
if (CRenderer::CV_r_nighttype == 1)
{
int i;
float wdt = (float)Tex->m_Width;
float hgt = (float)Tex->m_Height;
r->EF_SetVertColor();
r->m_matProj->Push();
D3DXMATRIX *m = r->m_matProj->GetTop();
D3DXMatrixOrthoOffCenterLH(m, 0.0, wdt, 0.0, hgt, -20.0, 0.0);
r->m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
r->EF_PushMatrix();
m = r->m_matView->GetTop();
r->m_matView->LoadIdentity();
r->m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
r->SetCullMode(R_CULL_NONE);
r->SetEnviMode(R_MODE_MODULATE);
r->SetState(GS_NODEPTHTEST);
LPDIRECT3DSURFACE8 pDstSurf, pSrcSurf;
LPDIRECT3DTEXTURE8 pID3DTargetTexture, pID3DTexture;
pID3DTargetTexture = (LPDIRECT3DTEXTURE8)Tex->m_RefTex->m_VidTex;
h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
h = D3DXCreateTexture(r->m_pd3dDevice, Tex->m_Width, Tex->m_Height, 1, 0, (D3DFORMAT)Tex->m_RefTex->m_DstFormat, D3DPOOL_DEFAULT, &pID3DTexture );
h = pID3DTexture->GetSurfaceLevel(0, &pDstSurf);
h = r->m_pd3dDevice->CopyRects(pSrcSurf, NULL, 0, pDstSurf, NULL);
SAFE_RELEASE (pSrcSurf);
SAFE_RELEASE (pDstSurf);
h = r->m_pd3dDevice->SetTexture(0, (IDirect3DBaseTexture8*)pID3DTexture);
r->m_pd3dDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
r->m_pd3dDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
r->m_pd3dDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
r->m_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
r->m_pd3dDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
D3DQuad(wdt, hgt, CFColor(1,1,1,1));
r->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
for (i=0; i<0; i++)
{
float fOffs = (i+1)*(Tex->m_Width/1024.0f);
float fAlpha = 0.1f;
r->EF_PushMatrix();
r->m_matView->TranslateLocal(fOffs,0,0);
m = r->m_matView->GetTop();
r->m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
D3DQuad(wdt, hgt, CFColor(1,1,1,fAlpha));
r->EF_PopMatrix();
r->EF_PushMatrix();
r->m_matView->TranslateLocal(-fOffs,0,0);
m = r->m_matView->GetTop();
r->m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
D3DQuad(wdt, hgt, CFColor(1,1,1,fAlpha));
r->EF_PopMatrix();
r->EF_PushMatrix();
r->m_matView->TranslateLocal(0,fOffs,0);
m = r->m_matView->GetTop();
r->m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
D3DQuad(wdt, hgt, CFColor(1,1,1,fAlpha));
r->EF_PopMatrix();
r->EF_PushMatrix();
r->m_matView->TranslateLocal(0,-fOffs,0);
m = r->m_matView->GetTop();
r->m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
D3DQuad(wdt, hgt, CFColor(1,1,1,fAlpha));
r->EF_PopMatrix();
}
float fRandU = RandomNum() * 2.0f;
float fRandV = RandomNum() * 2.0f;
gRenDev->SetState(GS_BLSRC_DSTCOL | GS_BLDST_SRCCOL | GS_NODEPTHTEST);
STexPic *tp = gRenDev->m_TexMan->LoadTexture("Textures/Defaults/HeatNoise", 0, 0);
tp->Set();
void *pVertices;
#ifndef _XBOX
HRESULT hr = r->m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, D3DLOCK_DISCARD);
#else //_XBOX
HRESULT hr = r->m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, 0);
#endif //_XBOX
SPipeTRVertex_D_1T *vQuad = (SPipeTRVertex_D_1T *)pVertices;
DWORD col = -1;
// Define the quad
vQuad[0].dvSX = 0.0f;
vQuad[0].dvSY = 0.0f;
vQuad[0].dvSZ = 0.0f;
vQuad[0].dvRHW = 1.0f;
vQuad[0].dcColor = col;
vQuad[0].dvTU[0] = fRandU;
vQuad[0].dvTU[1] = fRandV;
vQuad[1].dvSX = wdt;
vQuad[1].dvSY = 0.0f;
vQuad[1].dvSZ = 0.0f;
vQuad[1].dvRHW = 1.0f;
vQuad[1].dcColor = col;
vQuad[1].dvTU[0] = 4.0f+fRandU;
vQuad[1].dvTU[1] = fRandV;
vQuad[2].dvSX = wdt;
vQuad[2].dvSY = hgt;
vQuad[2].dvSZ = 0.0f;
vQuad[2].dvRHW = 1.0f;
vQuad[2].dcColor = col;
vQuad[2].dvTU[0] = 4.0f+fRandU;
vQuad[2].dvTU[1] = 4.0f+fRandV;
vQuad[3].dvSX = 0.0f;
vQuad[3].dvSY = hgt;
vQuad[3].dvSZ = 0.0f;
vQuad[3].dvRHW = 1.0f;
vQuad[3].dcColor = col;
vQuad[3].dvTU[0] = fRandU;
vQuad[3].dvTU[1] = 4.0f+fRandV;
// We are finished with accessing the vertex buffer
r->m_pQuadVB->Unlock();
// Bind our vertex as the first data stream of our device
r->m_pd3dDevice->SetStreamSource(0, r->m_pQuadVB, STRIDE_TR_D_1T);
// Set the vertex shader to the FVF fixed function shader
r->m_pd3dDevice->SetVertexShader(D3DFVF_TRVERTEX_D_1T);
// Render the two triangles from the data stream
//hr = r->m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
pID3DTexture->Release();
r->EF_PopMatrix();
r->m_matProj->Pop();
m = r->m_matProj->GetTop();
r->m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
}
h = r->m_pd3dDevice->SetRenderTarget(0, r->m_pBackBuffer);
iSystem->SetViewCamera(m_PrevCamera);
gRenDev->SetCamera(m_PrevCamera);
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
if (CRenderer::CV_r_nightmapsave)
{
CRenderer::CV_r_nightmapsave = 0;
Tex->SaveJPG("NightMap.jpg", false);
}
}
void CD3D8TexMan::StartNightMap(int Id)
{
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
STexPic *Tex = CTexMan::m_Text_NightVisMap;
if (Tex->m_Flags & FT_BUILD)
return;
CD3D8Renderer *r = gcpRendD3D;
if (CRenderer::CV_r_nightsize != gRenDev->m_RP.m_NightSize)
{
if (CRenderer::CV_r_nightsize <= 64)
CRenderer::CV_r_nightsize = 64;
else
if (CRenderer::CV_r_nightsize <= 128)
CRenderer::CV_r_nightsize = 128;
else
if (CRenderer::CV_r_nightsize <= 256)
CRenderer::CV_r_nightsize = 256;
else
if (CRenderer::CV_r_nightsize <= 512)
CRenderer::CV_r_nightsize = 512;
gRenDev->m_RP.m_NightSize = CRenderer::CV_r_nightsize;
Tex->m_Flags &= ~FT_ALLOCATED;
}
int nTexWidth = gRenDev->m_RP.m_NightSize;
int nTexHeight = gRenDev->m_RP.m_NightSize;
float fMaxDist = eng->GetMaxViewDistance();
float fMinDist = 0.25f;
Tex->m_Flags |= FT_BUILD;
if (!(Tex->m_Flags & FT_ALLOCATED))
{
Tex->m_Width = Tex->m_WidthReal = nTexWidth;
Tex->m_Height = Tex->m_HeightReal = nTexHeight;
Tex->m_Flags |= FT_ALLOCATED;
// Preallocate texture
byte *data = new byte [Tex->m_Width*Tex->m_Height*4];
Tex->m_Flags |= FT_NOMIPS;
Tex->m_Flags2 |= FT2_NODXT | FT2_RENDERTARGET;
Tex->m_Flags &= ~(FT_DXT);
AddToHash(Tex->m_Bind, Tex);
gRenDev->m_TexMan->CreateTexture(NULL, Tex->m_Width, Tex->m_Height, 1, FT_NOMIPS, FT2_NODXT | FT2_RENDERTARGET, data, eTT_Base, -1.0f, -1.0f, 0, Tex); delete [] data;
}
CCamera tmp_cam = gRenDev->GetCamera();
m_PrevCamera = tmp_cam;
//tmp_cam.Init(Tex->m_Width, Tex->m_Height, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
//tmp_cam.Update();
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
gRenDev->SetViewport( 0, 0, Tex->m_Width, Tex->m_Height );
gRenDev->EF_PushFog();
gRenDev->m_RP.m_bDrawToTexture = true;
iSystem->SetViewCamera(tmp_cam);
gRenDev->SetCamera(tmp_cam);
if (gRenDev->m_LogFile)
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** Start Draw scene to texture for heat ***\n");
STexPicD3D *tp = (STexPicD3D *)Tex;
LPDIRECT3DTEXTURE8 pID3DTargetTexture = (LPDIRECT3DTEXTURE8)tp->m_RefTex->m_VidTex;
LPDIRECT3DSURFACE8 pSrcSurf;
h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
h = r->m_pd3dDevice->SetRenderTarget(0, pSrcSurf);
pSrcSurf->Release();
DWORD cColor = D3DRGBA(gRenDev->m_vClearColor[0], gRenDev->m_vClearColor[1], gRenDev->m_vClearColor[2], 0);
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
r->m_RP.m_PersFlags |= RBPF_NOCLEARBUF | RBPF_DRAWNIGHTMAP;
//int nDrawFlags = DLD_INDOORS | DLD_ADD_LIGHTSOURCES | DLD_ENTITIES | DLD_PARTICLES | DLD_STATIC_OBJECTS | DLD_FAR_SPRITES | DLD_TERRAIN_FULLRES | DLD_TERRAIN_LIGHT;
//eng->DrawLowDetail(nDrawFlags);
}
//==================================================================================
void CD3D8TexMan::StartMotionMap(int Id, CCObject *pObject)
{
}
void CD3D8TexMan::EndMotionMap(void)
{
}
void CD3D8TexMan::StartScreenMap(int Id)
{
}
void CD3D8TexMan::EndScreenMap()
{
}
void CD3D8TexMan::DrawFlashBangMap(int Id, int RendFlags, CREFlashBang *pRE)
{
}
// tiago: added
void CD3D8TexMan::StartScreenTexMap(int Id)
{
}
void CD3D8TexMan::EndScreenTexMap()
{
}
//==================================================================================
int TexCallback( const VOID* arg1, const VOID* arg2 )
{
STexPic **pi1 = (STexPic **)arg1;
STexPic **pi2 = (STexPic **)arg2;
STexPic *ti1 = *pi1;
STexPic *ti2 = *pi2;
if (ti1->m_Size > ti2->m_Size)
return -1;
if (ti1->m_Size < ti2->m_Size)
return 1;
return 0;
}
void CD3D8TexMan::Update()
{
CD3D8Renderer *rd = gcpRendD3D;
int i;
char buf[256]="";
CheckTexLimits();
if (CRenderer::CV_r_logusedtextures == 1 || CRenderer::CV_r_logusedtextures == 3 || CRenderer::CV_r_logusedtextures == 4)
{
FILE *fp = NULL;
TArray<STexPic *> Texs;
int Size = 0;
int PartSize = 0;
static char *sTexType[] =
{
"Base","Bump","DSDTBump","Cubemap","AutoCubemap","Rectangle"
};
static char *sTexFormat[] =
{
"Unknown","Index8","HSV","0888","8888","RGBA","8000","0565","0555","4444","1555","DXT1","DXT3","DXT5","SIGNED_HILO16","SIGNED_HILO8","SIGNED_RGB8","RGB8","DSDT_MAG","DSDT","0088"
};
if (CRenderer::CV_r_logusedtextures == 1 || CRenderer::CV_r_logusedtextures == 3)
{
for (i=0; i<m_Textures.Num(); i++)
{
if (CRenderer::CV_r_logusedtextures == 3 && m_Textures[i] && m_Textures[i]->m_bBusy && m_Textures[i]->m_Bind == CTexMan::m_Text_NoTexture->m_Bind)
{
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
Texs.AddElem(m_Textures[i]);
}
else
if (CRenderer::CV_r_logusedtextures == 1 && m_Textures[i] && m_Textures[i]->m_bBusy && m_Textures[i]->m_Bind != CTexMan::m_Text_NoTexture->m_Bind && (m_Textures[i]->m_Flags2 & FT2_WASLOADED) && !(m_Textures[i]->m_Flags2 & FT2_WASUNLOADED))
{
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
Texs.AddElem(m_Textures[i]);
}
}
if (CRenderer::CV_r_logusedtextures == 3)
fp = fxopen("MissingTextures.txt", "w");
else
fp = fxopen("UsedTextures.txt", "w");
fprintf(fp, "*** All loaded textures: ***\n");
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
for (i=0; i<Texs.Num(); i++)
{
fprintf(fp, "%d\t\tType: %s\t\tFormat: %s\t\t(%s)\n", Texs[i]->m_Size, sTexType[Texs[i]->m_eTT], sTexFormat[Texs[i]->m_ETF], *Texs[i]->m_SearchName);
Size += Texs[i]->m_Size;
PartSize += Texs[i]->m_LoadedSize;
}
fprintf(fp, "*** Total Size: %d\n\n", Size, PartSize, PartSize);
Texs.Free();
}
for (i=0; i<m_Textures.Num(); i++)
{
if (m_Textures[i] && m_Textures[i]->m_bBusy && m_Textures[i]->m_Bind != CTexMan::m_Text_NoTexture->m_Bind && m_Textures[i]->m_AccessFrame == rd->GetFrameID())
{
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
Texs.AddElem(m_Textures[i]);
}
}
if (fp)
fprintf(fp, "\n\n*** Textures used in current frame: ***\n");
else
rd->TextToScreenColor(4,13, 1,1,0,1, "*** Textures used in current frame: ***");
int nY = 17;
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
Size = 0;
for (i=0; i<Texs.Num(); i++)
{
if (fp)
fprintf(fp, "%.3fKb\t\tType: %s\t\tFormat: %s\t\t(%s)\n", Texs[i]->m_Size/1024.0f, sTexType[Texs[i]->m_eTT], sTexFormat[Texs[i]->m_ETF], Texs[i]->m_SearchName.c_str());
else
{
sprintf(buf, "%.3fKb Type: %s Format: %s (%s)", Texs[i]->m_Size/1024.0f, sTexType[Texs[i]->m_eTT], sTexFormat[Texs[i]->m_ETF], Texs[i]->m_SearchName.c_str());
rd->TextToScreenColor(4,nY, 0,1,0,1, buf);
nY += 3;
}
Size += Texs[i]->m_Size;
}
if (fp)
{
fprintf(fp, "*** Total Size: %.3fMb\n\n", Size/(1024.0f*1024.0f));
fclose (fp);
}
else
{
sprintf(buf, "*** Total Size: %.3fMb", Size/(1024.0f*1024.0f));
rd->TextToScreenColor(4,nY+1, 0,1,1,1, buf);
}
if (CRenderer::CV_r_logusedtextures != 4)
CRenderer::CV_r_logusedtextures = 0;
}
else
if (CRenderer::CV_r_logusedtextures == 2)
{
//char *str = GetTexturesStatusText();
TArray<STexPic *> Texs;
TArray<STexPic *> TexsNM;
int i;
for (i=0; i<m_Textures.Num(); i++)
{
if (m_Textures[i] && m_Textures[i]->m_bBusy && m_Textures[i]->m_Bind != CTexMan::m_Text_NoTexture->m_Bind)
{
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
{
/*for (int nn = 0; nn<sTestStr.Num(); nn++)
{
if (sTestStr[nn] == m_Textures[i])
break;
}
if (nn == sTestStr.Num())
{
int nnn = 0;
}*/
Texs.AddElem(m_Textures[i]);
if (m_Textures[i]->m_eTT == eTT_Bumpmap)
TexsNM.AddElem(m_Textures[i]);
}
}
}
int nNOTO = 0;
for (i=0; i<TX_FIRSTBIND; i++)
{
STexPic *tp = GetByID(i);
if (!tp)
{
nNOTO++;
}
}
/*for (int nn = 0; nn<sTestTx.Num(); nn++)
{
for (i=0; i<Texs.Num(); i++)
{
if (sTestTx[nn] == Texs[i])
break;
}
if (i == Texs.Num())
{
int nnn = 0;
}
}*/
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
int AllSize = 0;
int AllSizeNM = 0;
int Size = 0;
int PartSize = 0;
int NonStrSize = 0;
int SizeNM = 0;
int PartSizeNM = 0;
int nLoaded = 0;
for (i=0; i<Texs.Num(); i++)
{
AllSize += Texs[i]->m_Size;
if (!Texs[i]->IsStreamed())
NonStrSize += Texs[i]->m_Size;
if (!(Texs[i]->m_Flags2 & FT2_WASUNLOADED))
{
nLoaded++;
Size += Texs[i]->m_Size;
if (Texs[i]->m_LoadedSize)
PartSize += Texs[i]->m_LoadedSize;
else
PartSize += Texs[i]->m_Size;
}
}
for (i=0; i<TexsNM.Num(); i++)
{
AllSizeNM += Texs[i]->m_Size;
if (!(Texs[i]->m_Flags2 & FT2_WASUNLOADED))
{
SizeNM += TexsNM[i]->m_Size;
if (TexsNM[i]->m_LoadedSize)
PartSizeNM += TexsNM[i]->m_LoadedSize;
else
PartSizeNM += TexsNM[i]->m_Size;
}
}
sprintf(buf, "All texture objects: %d (Size: %.3fMb, NonStreamed: %.3fMb)", Texs.Num(), AllSize/(1024.0f*1024.0f), NonStrSize/(1024.0f*1024.0f));
rd->TextToScreenColor(4,13, 1,1,0,1, buf);
sprintf(buf, "All loaded texture objects: %d (All MIPS: %.3fMb, Loaded MIPS: %.3fMb)", nLoaded, Size/(1024.0f*1024.0f), PartSize/(1024.0f*1024.0f));
rd->TextToScreenColor(4,16, 1,1,0,1, buf);
sprintf(buf, "All Normal Maps: %d (FullSize: %.3fMb, All MIPS: %.3fMb, Loaded MIPS: %.3fMb)", TexsNM.Num(), AllSizeNM/(1024.0f*1024.0f), SizeNM/(1024.0f*1024.0f), PartSizeNM/(1024.0f*1024.0f));
rd->TextToScreenColor(4,19, 1,1,0,1, buf);
Texs.Free();
for (i=0; i<m_Textures.Num(); i++)
{
if (m_Textures[i] && m_Textures[i]->m_bBusy && (m_Textures[i]->m_Flags2 & FT2_WASLOADED) && m_Textures[i]->m_Bind != CTexMan::m_Text_NoTexture->m_Bind && m_Textures[i]->m_AccessFrame == rd->GetFrameID())
{
if (m_Textures[i]->m_eTT != eTT_Cubemap || !m_Textures[i]->m_CubeSide)
Texs.AddElem(m_Textures[i]);
}
}
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
Size = 0;
PartSize = 0;
NonStrSize = 0;
for (i=0; i<Texs.Num(); i++)
{
Size += Texs[i]->m_Size;
if (Texs[i]->m_LoadedSize)
PartSize += Texs[i]->m_LoadedSize;
else
PartSize += Texs[i]->m_Size;
if (!Texs[i]->IsStreamed())
NonStrSize += Texs[i]->m_Size;
}
sprintf(buf, "Current tex. objects: %d (Size: %.3fMb, Loaded: %.3f, NonStreamed: %.3f)", Texs.Num(), Size/(1024.0f*1024.0f), PartSize/(1024.0f*1024.0f), NonStrSize/(1024.0f*1024.0f));
rd->TextToScreenColor(4,24, 1,0,0,1, buf);
}
}
char * CD3D8Renderer::GetTexturesStatusText()
{
static char buf[256]="";
TArray<STexPic *> Texs;
int i;
for (i=0; i<CTexMan::m_Textures.Num(); i++)
{
if (CTexMan::m_Textures[i] && CTexMan::m_Textures[i]->m_bBusy && CTexMan::m_Textures[i]->m_Bind != CTexMan::m_Text_NoTexture->m_Bind)
Texs.AddElem(CTexMan::m_Textures[i]);
}
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
int Size = 0;
for (i=0; i<Texs.Num(); i++)
{
Size += Texs[i]->m_Size;
}
sprintf(buf, "All loaded textures: %d (Size: %.3fMb)", Texs.Num(), Size*1e-6);
Texs.Free();
for (i=0; i<CTexMan::m_Textures.Num(); i++)
{
if (CTexMan::m_Textures[i] && CTexMan::m_Textures[i]->m_bBusy && CTexMan::m_Textures[i]->m_Bind != CTexMan::m_Text_NoTexture->m_Bind && CTexMan::m_Textures[i]->m_AccessFrame == GetFrameID())
Texs.AddElem(CTexMan::m_Textures[i]);
}
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
Size = 0;
for (i=0; i<Texs.Num(); i++)
{
Size += Texs[i]->m_Size;
}
sprintf(buf, "%s Current textures: %d (Size: %.3fMb)", buf, Texs.Num(), Size*1e-6);
return buf;
}
//==================================================================================
STexPic *CD3D8Renderer::EF_MakePhongTexture(int Exp)
{
char name[128];
sprintf(name, "(Phong_%d)", Exp);
STexPic *ti = m_TexMan->LoadTexture(name, 0, 0, eTT_Base);
if (ti->m_Flags & FT_ALLOCATED)
return ti;
ti->m_Flags |= FT_ALLOCATED;
ti->Set();
double shininess = Exp;
int imgsize = 256;
unsigned char * img = new unsigned char[imgsize*imgsize*4];
unsigned char * ip = img;
for(int j=0; j<imgsize; j++)
{
unsigned char a = (unsigned char)(255.99 * pow(j/(imgsize-1.0), shininess));
for(int i=0; i<imgsize; i++)
{
byte b = (unsigned char)(255.99 * (i/(imgsize-1.0)));
*ip++ = b;
*ip++ = b;
*ip++ = b;
*ip++ = a;
}
}
LPDIRECT3DTEXTURE8 pPhongTexture;
if(SUCCEEDED(D3DXCreateTexture(gcpRendD3D->mfGetD3DDevice(), imgsize, imgsize, D3DX_DEFAULT, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pPhongTexture)))
{
D3DLOCKED_RECT d3dlr;
// Lock the texture to copy the image data into the texture
HRESULT hr = pPhongTexture->LockRect(0, &d3dlr, NULL, 0);
if (SUCCEEDED(hr))
{
memcpy((byte *)d3dlr.pBits, img, imgsize*imgsize*4);
// Unlock the texture
pPhongTexture->UnlockRect(0);
hr = D3DXFilterTexture(pPhongTexture, NULL, 0, D3DX_FILTER_LINEAR);
}
}
ti->m_RefTex->m_VidTex = (void *)pPhongTexture;
ti->m_RefTex->m_MinFilter = m_TexMan->GetMinFilter();
ti->m_RefTex->m_MagFilter = m_TexMan->GetMagFilter();
ti->m_RefTex->m_DstFormat = D3DFMT_A8R8G8B8;
ti->m_RefTex->bRepeats = false;
ti->m_RefTex->m_AnisLevel = gcpRendD3D->GetAnisotropicLevel();
delete [] img;
m_TexMan->SetTexture(0, eTT_Base);
return ti;
}
float CD3D8TexMan::CalcFogVal(float fi, float fj)
{
float fDelta = fabsf(fj - fi);
if (fj > 0 && fi > 0)
return 0;
float fThr = -8;
if (fj < fThr && fi < fThr)
return 1.0f;
float f1, f2, ff;
if (fj > 0)
ff = fj;
else
if (fi > 0)
ff = fi;
else
ff = 0;
if (fi > fj)
{
f1 = fi;
f2 = fj;
}
else
{
f1 = fj;
f2 = fi;
}
if (f1 > 0)
f1 = 0;
if (f2 < fThr)
f2 = fThr;
fThr = 1.0f / 8.0f;
if (fDelta == 0)
return -(fThr * fi);
float fFog = (1.0f - ((f2 + f1) * fThr * -0.5f)) * (f1 - f2);
ff = ((fDelta - ff) - fFog) / fDelta;
float fMin = Min(fi, fj) / -30.0f;
if (fMin >= 1.0f)
return 1;
return (1.0f - fMin) * ff + fMin;
}
void CD3D8TexMan::GenerateFogMaps()
{
int i, j;
{
float fdata[256];
byte *Data1 = new byte[128*128*4];
float f = 1.0f;
for (i=0; i<256; i++)
{
fdata[i] = f;
f *= 0.982f;
}
fdata[0] = 0;
fdata[255] = 0;
for (i=0; i<128; i++)
{
int ni = i - 64;
for (j=0; j<128; j++)
{
int nj = j - 64;
float m = (float)(nj*nj + ni*ni);
float fsq = 1.0f / sqrtf(m);
int iIndexF = (int)((fsq * m) / 63.0f * 255.0f);
iIndexF = Clamp(iIndexF, 0, 255);
int iFog = (int)((1.0f - fdata[iIndexF]) * 255.0f);
if (!i || i==127 || !j || j==127)
iFog = 255;
Data1[j*128*4+i*4+0] = Data1[j*128*4+i*4+1] = Data1[j*128*4+i*4+2] = 255;
Data1[j*128*4+i*4+3] = (byte)iFog;
}
}
CTexMan::m_Text_Fog = CreateTexture("$Fog", 128, 128, 1, FT_CLAMP | FT_NOMIPS | FT_NOREMOVE | FT_HASALPHA, FT2_NODXT, Data1, eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
delete [] Data1;
/*byte Data2[64][64][4];
gcpOGL->EF_InitFogTables();
for (i=0; i<64; i++)
{
for (j=0; j<64; j++)
{
//float fFog = CalcFogVal((float)(i-32), (float)(j-32));
float fi = (float)i-63-10;
float fj = (float)j-32;
float fifi = fi/32.0f;
fifi *= fifi;
int nInd = (int)(((-fj/8.0f) * fifi) * 255.0f);
nInd = Clamp(nInd, 0, 255);
float fFog = SEvalFuncs::m_tFogFloats[nInd];
int iFog = Clamp(int(fFog*255.0f), 0, 255);
Data2[j][i][0] = Data2[j][i][1] = Data2[j][i][2] = 255;
Data2[j][i][3] = (byte)iFog;
}
}*/
//CTexMan::m_Text_Fog_Enter = DownloadTexture("(FogEnter)", 64, 64, FT_CLAMP | FT_NOMIPS | FT_NOREMOVE | FT_HASALPHA, FT2_NODXT, &Data2[0][0][0], eTT_Base, 0, NULL, 0, eTF_8888);
//CTexMan::m_Text_Fog_Enter->SaveTGA("FogEnter.tga", false);
CTexMan::m_Text_Fog_Enter = LoadTexture("Textures/FogEnter", FT_CLAMP | FT_NOMIPS | FT_NOREMOVE | FT_HASALPHA, FT2_NODXT);
}
}
void CD3D8TexMan::GenerateFlareMap()
{
int i, j;
byte data[4][32][4];
for (i=0; i<32; i++)
{
float f = 1.0f - ((fabsf((float)i - 15.5f) - 0.5f) / 16.0f);
int n = (int)(f*f*255.0f);
for (j=0; j<4; j++)
{
byte b = n;
if (n < 0)
b = 0;
else
if (n > 255)
b = 255;
data[j][i][0] = b;
data[j][i][1] = b;
data[j][i][2] = b;
data[j][i][3] = 255;
}
}
CTexMan::m_Text_Flare = CreateTexture("$Flare", 32, 4, 1, FT_CLAMP | FT_NOREMOVE, FT2_NODXT, &data[0][0][0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
}
#include "D3DCubemaps.h"
#ifdef _XBOX
static void MakeCubeMapXBox(LPDIRECT3DCUBETEXTURE8 pCubeMap, int dwSize, bool bMips)
{
// Allocate temp space for swizzling the cubemap surfaces
DWORD* pSourceBits = new DWORD[dwSize * dwSize];
// Fill all six sides of the cubemap
for(DWORD i=0; i<6; i++)
{
// Lock the i'th cubemap surface
LPDIRECT3DSURFACE8 pCubeMapFace;
pCubeMap->GetCubeMapSurface((D3DCUBEMAP_FACES)i, 0, &pCubeMapFace);
// Write the RGBA-encoded normals to the surface pixels
DWORD* pPixel = pSourceBits;
D3DXVECTOR3 n;
FLOAT w, h;
for(int y=0; y<dwSize; y++)
{
h = (FLOAT)y / (FLOAT)(dwSize-1); // 0 to 1
h = ( h * 2.0f ) - 1.0f; // -1 to 1
for(int x = 0; x < dwSize; x++)
{
w = (FLOAT)x / (FLOAT)(dwSize-1); // 0 to 1
w = ( w * 2.0f ) - 1.0f; // -1 to 1
// Calc the normal for this texel
switch( i )
{
case D3DCUBEMAP_FACE_POSITIVE_X: // +x
n.x = +1.0;
n.y = -h;
n.z = -w;
break;
case D3DCUBEMAP_FACE_NEGATIVE_X: // -x
n.x = -1.0;
n.y = -h;
n.z = +w;
break;
case D3DCUBEMAP_FACE_POSITIVE_Y: // y
n.x = +w;
n.y = +1.0;
n.z = +h;
break;
case D3DCUBEMAP_FACE_NEGATIVE_Y: // -y
n.x = +w;
n.y = -1.0;
n.z = -h;
break;
case D3DCUBEMAP_FACE_POSITIVE_Z: // +z
n.x = +w;
n.y = -h;
n.z = +1.0;
break;
case D3DCUBEMAP_FACE_NEGATIVE_Z: // -z
n.x = -w;
n.y = -h;
n.z = -1.0;
break;
}
// Store the normal as an RGBA color
D3DXVec3Normalize( &n, &n );
D3DCOLOR r = (D3DCOLOR)( ( n.x + 1.0f ) * 127.5f );
D3DCOLOR g = (D3DCOLOR)( ( n.y + 1.0f ) * 127.5f );
D3DCOLOR b = (D3DCOLOR)( ( n.z + 1.0f ) * 127.5f );
D3DCOLOR a = (D3DCOLOR)( 255.0f );
*pPixel++ = ((a<<24L) + (r<<16L) + (g<<8L) + (b<<0L));
}
}
// Swizzle the result into the cubemap face surface
D3DLOCKED_RECT lock;
pCubeMapFace->LockRect( &lock, 0, 0L );
XGSwizzleRect( pSourceBits, 0, NULL, lock.pBits, dwSize, dwSize, NULL, sizeof(DWORD) );
pCubeMapFace->UnlockRect();
// Release the cubemap face
pCubeMapFace->Release();
}
// Free temp space
SAFE_DELETE_ARRAY( pSourceBits );
}
#endif
void CD3D8TexMan::GenerateFuncTextures()
{
LPDIRECT3DCUBETEXTURE8 pNormCubeTexture;
LPDIRECT3DCUBETEXTURE8 pLightCubeTexture;
if (gRenDev->GetFeatures() & RFT_BUMP_DOT3)
{
SSingleLight f(32); // TO_LIGHT_CUBE_MAP
if(SUCCEEDED(D3DXCreateCubeTexture(gcpRendD3D->mfGetD3DDevice(), 64, D3DX_DEFAULT, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &pLightCubeTexture)))
{
int nl = pLightCubeTexture->GetLevelCount();
MakeCubeMap<SSingleLight>(f, pLightCubeTexture, 64, true);
}
SNormalizeVector norm; // TO_NORMALIZE_CUBE_MAP
if(SUCCEEDED(D3DXCreateCubeTexture(gcpRendD3D->mfGetD3DDevice(), 256, D3DX_DEFAULT, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &pNormCubeTexture)))
{
#ifndef _XBOX
MakeCubeMap<SNormalizeVector>(norm, pNormCubeTexture, 256, false);
#else
MakeCubeMapXBox(pNormCubeTexture, 256, false);
#endif
}
if (!CTexMan::m_Text_NormalizeCMap)
CTexMan::m_Text_NormalizeCMap = LoadTexture("$NormalizeCMap", FT_NOREMOVE, FT2_NODXT, eTT_Cubemap, -1.0f, -1.0f, TO_NORMALIZE_CUBE_MAP);
STexPicD3D *ti = (STexPicD3D *)CTexMan::m_Text_NormalizeCMap;
ti->m_RefTex->m_VidTex = (void *)pNormCubeTexture;
ti->m_RefTex->bMips = false;
ti->m_RefTex->m_DstFormat = D3DFMT_X8R8G8B8;
ti->m_RefTex->m_Type = TEXTGT_CUBEMAP;
ti->m_Width = 256;
ti->m_Height = 256;
CD3D8TexMan::CalcMipsAndSize(ti);
ti->m_Size *= 6;
AddToHash(ti->m_Bind, ti);
ti->Unlink();
ti->Link(&STexPic::m_Root);
CTexMan::m_StatsCurTexMem += ti->m_Size;
CheckTexLimits();
}
GenerateFogMaps();
GenerateFlareMap();
}