5868 lines
169 KiB
C++
5868 lines
169 KiB
C++
/*=============================================================================
|
|
D3DTextures.cpp : Direct3D specific texture manager implementation.
|
|
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
|
|
|
Revision history:
|
|
* Created by Honitch Andrey
|
|
|
|
=============================================================================*/
|
|
|
|
#include "RenderPCH.h"
|
|
#include "DriverD3D9.h"
|
|
#include "I3dengine.h"
|
|
#include "CryHeaders.h"
|
|
#include "../Common/RendElements/CREScreenCommon.h"
|
|
|
|
// tiago: added
|
|
#include "D3DCGPShader.h"
|
|
#include "D3DCGVProgram.h"
|
|
|
|
//TArray<SDynTX> gDTX;
|
|
|
|
int CD3D9TexMan::m_Format = D3DFMT_A8R8G8B8;
|
|
int CD3D9TexMan::m_FirstBind = 1;
|
|
FILE *STexPicD3D::m_TexUseLogFile = NULL;
|
|
int STexPicD3D::CV_r_LogTextureUsage;
|
|
|
|
//TTextureMap CD3D9TexMan::m_RefTexs;
|
|
|
|
//#define TEXPOOL D3DPOOL_DEFAULT
|
|
#define TEXPOOL D3DPOOL_MANAGED
|
|
//===============================================================================
|
|
|
|
void STexPic::ReleaseDriverTexture()
|
|
{
|
|
}
|
|
|
|
void STexPic::SetFilter()
|
|
{
|
|
}
|
|
|
|
void STexPic::SetWrapping()
|
|
{
|
|
}
|
|
|
|
void STexPic::Set(int nTexSlot)
|
|
{
|
|
}
|
|
void STexPic::SetClamp(bool bEnable)
|
|
{
|
|
}
|
|
|
|
bool STexPic::SetFilter(int nFilter)
|
|
{
|
|
switch(nFilter)
|
|
{
|
|
case FILTER_NONE:
|
|
m_RefTex.m_MinFilter = D3DTEXF_POINT;
|
|
m_RefTex.m_MagFilter = D3DTEXF_POINT;
|
|
m_RefTex.m_MipFilter = D3DTEXF_NONE;
|
|
break;
|
|
case FILTER_LINEAR:
|
|
m_RefTex.m_MinFilter = D3DTEXF_LINEAR;
|
|
m_RefTex.m_MagFilter = D3DTEXF_LINEAR;
|
|
m_RefTex.m_MipFilter = D3DTEXF_NONE;
|
|
break;
|
|
case FILTER_BILINEAR:
|
|
m_RefTex.m_MinFilter = D3DTEXF_LINEAR;
|
|
m_RefTex.m_MagFilter = D3DTEXF_LINEAR;
|
|
m_RefTex.m_MipFilter = D3DTEXF_POINT;
|
|
break;
|
|
case FILTER_TRILINEAR:
|
|
m_RefTex.m_MinFilter = D3DTEXF_LINEAR;
|
|
m_RefTex.m_MagFilter = D3DTEXF_LINEAR;
|
|
m_RefTex.m_MipFilter = D3DTEXF_LINEAR;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void STexPicD3D::Release(bool bForce)
|
|
{
|
|
STexPic::Release(bForce);
|
|
}
|
|
|
|
void STexPicD3D::ReleaseDriverTexture()
|
|
{
|
|
if (!(m_Flags2 & FT2_WASUNLOADED) && (m_Bind && m_Bind != TX_FIRSTBIND))
|
|
{
|
|
m_Flags2 &= ~FT2_PARTIALLYLOADED;
|
|
if (m_LoadedSize >= 0)
|
|
{
|
|
if (m_LoadedSize)
|
|
gRenDev->m_TexMan->m_StatsCurTexMem -= m_LoadedSize;
|
|
else
|
|
gRenDev->m_TexMan->m_StatsCurTexMem -= m_Size;
|
|
}
|
|
if (m_Mips[0])
|
|
{
|
|
int nSides = m_eTT == eTT_Cubemap ? 6 : 1;
|
|
for (int nS=0; nS<nSides; nS++)
|
|
{
|
|
if (!m_Mips[nS])
|
|
continue;
|
|
for (int i=0; i<m_nMips; i++)
|
|
{
|
|
SMipmap *mp = m_Mips[nS][i];
|
|
if (!mp)
|
|
continue;
|
|
mp->m_bUploaded = false;
|
|
}
|
|
}
|
|
}
|
|
Unlink();
|
|
|
|
//gRenDev->m_TexMan->ValidateTexSize();
|
|
|
|
m_LoadedSize = 0;
|
|
if (m_pPoolItem)
|
|
{
|
|
STexPoolItem *pPool = m_pPoolItem;
|
|
//assert(pPool->m_pAPITexture == m_RefTex.m_VidTex);
|
|
RemoveFromPool();
|
|
pPool->Unlink();
|
|
delete pPool;
|
|
}
|
|
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
LPDIRECT3DDEVICE9 dv = r->mfGetD3DDevice();
|
|
IDirect3DBaseTexture9 *pTex = (IDirect3DBaseTexture9*)m_RefTex.m_VidTex;
|
|
//sRemoveTX(this);
|
|
SAFE_RELEASE(pTex);
|
|
m_RefTex.m_VidTex = NULL;
|
|
}
|
|
else
|
|
if (m_Bind == TX_FIRSTBIND && !m_Id)
|
|
{
|
|
if (m_LoadedSize)
|
|
gRenDev->m_TexMan->m_StatsCurTexMem -= m_LoadedSize;
|
|
else
|
|
gRenDev->m_TexMan->m_StatsCurTexMem -= m_Size;
|
|
}
|
|
}
|
|
|
|
byte *STexPic::GetData32()
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
byte *STexPicD3D::GetData32()
|
|
{
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
LPDIRECT3DDEVICE9 dv = r->mfGetD3DDevice();
|
|
IDirect3DTexture9 *pID3DTexture = NULL;
|
|
IDirect3DCubeTexture9 *pID3DCubeTexture = NULL;
|
|
LPDIRECT3DTEXTURE9 pID3DDstTexture = NULL;
|
|
D3DLOCKED_RECT d3dlr;
|
|
int wdt = m_Width;
|
|
int hgt = m_Height;
|
|
HRESULT h;
|
|
LPDIRECT3DSURFACE9 pDestSurf;
|
|
LPDIRECT3DSURFACE9 pSourceSurf;
|
|
|
|
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DDstTexture)))
|
|
return NULL;
|
|
h = pID3DDstTexture->GetSurfaceLevel(0, &pDestSurf);
|
|
|
|
int nPrevStr = CRenderer::CV_r_texturesstreamingsync;
|
|
if (m_Flags2 & (FT2_WASUNLOADED | FT2_PARTIALLYLOADED))
|
|
{
|
|
CRenderer::CV_r_texturesstreamingsync = 1;
|
|
LoadFromCache(FPR_IMMEDIATELLY, 0);
|
|
}
|
|
|
|
if (m_eTT == eTT_Cubemap)
|
|
pID3DCubeTexture = (IDirect3DCubeTexture9*)m_RefTex.m_VidTex;
|
|
else
|
|
pID3DTexture = (IDirect3DTexture9*)m_RefTex.m_VidTex;
|
|
byte *pDst = NULL;
|
|
|
|
if (pID3DCubeTexture)
|
|
{
|
|
pDst = new byte [wdt*hgt*4*6];
|
|
for (int CubeSide=0; CubeSide<6; CubeSide++)
|
|
{
|
|
h = pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)CubeSide, 0, &pSourceSurf);
|
|
h = D3DXLoadSurfaceFromSurface(pDestSurf, NULL, NULL, pSourceSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
|
|
pDestSurf->LockRect(&d3dlr, NULL, 0);
|
|
cryMemcpy(&pDst[wdt*hgt*4*CubeSide], d3dlr.pBits, wdt*hgt*4);
|
|
pDestSurf->UnlockRect();
|
|
SAFE_RELEASE(pDestSurf);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pDst = new byte [wdt*hgt*4];
|
|
h = pID3DTexture->GetSurfaceLevel(0, &pSourceSurf);
|
|
h = D3DXLoadSurfaceFromSurface(pDestSurf, NULL, NULL, pSourceSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
|
|
pDestSurf->LockRect(&d3dlr, NULL, 0);
|
|
cryMemcpy(pDst, d3dlr.pBits, wdt*hgt*4);
|
|
pDestSurf->UnlockRect();
|
|
SAFE_RELEASE(pSourceSurf);
|
|
}
|
|
SAFE_RELEASE(pDestSurf);
|
|
SAFE_RELEASE(pID3DDstTexture);
|
|
|
|
CRenderer::CV_r_texturesstreamingsync = nPrevStr;
|
|
|
|
return pDst;
|
|
}
|
|
|
|
|
|
void STexPicD3D::SetClamp(bool bEnable)
|
|
{
|
|
if (!m_RefTex.m_VidTex)
|
|
return;
|
|
if (bEnable)
|
|
m_RefTex.bRepeats = false;
|
|
else
|
|
m_RefTex.bRepeats = true;
|
|
}
|
|
|
|
void CD3D9TexMan::SetTexture(int Id, ETexType eTT)
|
|
{
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
LPDIRECT3DDEVICE9 dv = r->mfGetD3DDevice();
|
|
int tmu = r->m_TexMan->m_CurStage;
|
|
|
|
STexPic *t = NULL;
|
|
if (Id >= TX_FIRSTBIND)
|
|
{
|
|
STexPicD3D *tp = (STexPicD3D *)m_Textures[Id-TX_FIRSTBIND];
|
|
if (tp && tp->m_Bind == Id)
|
|
{
|
|
tp->Set();
|
|
return;
|
|
}
|
|
}
|
|
TTextureMapItor it = m_RefTexs.find(Id);
|
|
if (it == m_RefTexs.end())
|
|
{
|
|
dv->SetTexture(tmu, NULL);
|
|
r->m_RP.m_TexStages[tmu].Texture = NULL;
|
|
return;
|
|
}
|
|
STexPic *tp = it->second;
|
|
assert(tp);
|
|
if (tp)
|
|
tp->Set();
|
|
}
|
|
|
|
void STexPicD3D::Set(int nTexSlot)
|
|
{
|
|
//PROFILE_FRAME(Texture_Changes);
|
|
|
|
static int sRecursion = 0;
|
|
if (!sRecursion)
|
|
{
|
|
if (CRenderer::CV_r_texbindmode>=1)
|
|
{
|
|
if (CRenderer::CV_r_texbindmode==1 && !(m_Flags & FT_FONT))
|
|
{
|
|
sRecursion++;
|
|
gRenDev->m_TexMan->m_Text_NoTexture->Set();
|
|
sRecursion--;
|
|
return;
|
|
}
|
|
else
|
|
if (CRenderer::CV_r_texbindmode==2 && (m_Flags2 & FT2_WASLOADED) && !(m_Flags & FT_NOREMOVE) && m_eTT == eTT_Base)
|
|
{
|
|
sRecursion++;
|
|
gRenDev->m_TexMan->SetGridTexture(this);
|
|
sRecursion--;
|
|
return;
|
|
}
|
|
if (CRenderer::CV_r_texbindmode==3 && (m_Flags2 & FT2_WASLOADED) && !(m_Flags & FT_NOREMOVE))
|
|
{
|
|
sRecursion++;
|
|
if (m_eTT == eTT_Bumpmap)
|
|
gRenDev->m_TexMan->SetGridTexture(this);
|
|
else
|
|
gRenDev->m_TexMan->m_Text_Gray->Set();
|
|
sRecursion--;
|
|
return;
|
|
}
|
|
if (CRenderer::CV_r_texbindmode==4 && (m_Flags2 & FT2_WASLOADED) && !(m_Flags & FT_NOREMOVE) && m_eTT == eTT_Base)
|
|
{
|
|
sRecursion++;
|
|
gRenDev->m_TexMan->m_Text_Gray->Set();
|
|
sRecursion--;
|
|
return;
|
|
}
|
|
if (CRenderer::CV_r_texbindmode==5 && (m_Flags2 & FT2_WASLOADED) && !(m_Flags & FT_NOREMOVE) && m_eTT == eTT_Bumpmap)
|
|
{
|
|
sRecursion++;
|
|
gRenDev->m_TexMan->m_Text_WhiteBump->Set();
|
|
sRecursion--;
|
|
return;
|
|
}
|
|
if (CRenderer::CV_r_texbindmode==6 && nTexSlot==EFTT_DIFFUSE)
|
|
{
|
|
sRecursion++;
|
|
gRenDev->m_TexMan->m_Text_White->Set();
|
|
sRecursion--;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
int tmu = r->m_TexMan->m_CurStage;
|
|
if ((m_Flags2 & (FT2_WASUNLOADED | FT2_PARTIALLYLOADED | FT2_NEEDTORELOAD)))
|
|
{
|
|
PROFILE_FRAME(Texture_ChangesUpload);
|
|
int Size = m_LoadedSize;
|
|
Restore();
|
|
if (Size != m_LoadedSize)
|
|
r->m_RP.m_TexStages[tmu].Texture = NULL;
|
|
}
|
|
else
|
|
Relink(&STexPic::m_Root);
|
|
|
|
if (!m_RefTex.m_VidTex)
|
|
return;
|
|
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log >= 3)
|
|
r->Logv(SRendItem::m_RecurseLevel, "STexPic::Set(): (%d) \"%s\"\n", tmu, m_SourceName.c_str());
|
|
#endif
|
|
|
|
#ifdef DO_RENDERSTATS
|
|
int nFrameID = r->m_nFrameUpdateID;
|
|
if (m_AccessFrame != nFrameID)
|
|
{
|
|
m_AccessFrame = nFrameID;
|
|
r->m_RP.m_PS.m_NumTextures++;
|
|
if (m_LoadedSize)
|
|
r->m_RP.m_PS.m_TexturesSize += m_LoadedSize;
|
|
else
|
|
r->m_RP.m_PS.m_TexturesSize += m_Size;
|
|
}
|
|
#endif
|
|
|
|
HRESULT hr;
|
|
if (r->m_RP.m_TexStages[tmu].Texture == this)
|
|
return;
|
|
r->m_RP.m_TexStages[tmu].Texture = this;
|
|
r->m_RP.m_PS.m_NumTextChanges++;
|
|
LPDIRECT3DDEVICE9 dv = r->mfGetD3DDevice();
|
|
hr = dv->SetTexture(tmu, (IDirect3DBaseTexture9*)m_RefTex.m_VidTex);
|
|
|
|
if (m_RefTex.m_Pal>0 && (m_Flags & FT_PALETTED) && r->m_RP.m_TexStages[tmu].Palette != m_RefTex.m_Pal)
|
|
{
|
|
r->m_RP.m_TexStages[tmu].Palette = m_RefTex.m_Pal;
|
|
dv->SetCurrentTexturePalette(m_RefTex.m_Pal);
|
|
}
|
|
|
|
if(m_RefTex.m_MipFilter!=r->m_RP.m_TexStages[tmu].nMipFilter)
|
|
{
|
|
r->m_RP.m_TexStages[tmu].nMipFilter = m_RefTex.m_MipFilter;
|
|
dv->SetSamplerState(tmu, D3DSAMP_MIPFILTER, m_RefTex.m_MipFilter);
|
|
}
|
|
if(m_RefTex.m_MinFilter!=r->m_RP.m_TexStages[tmu].MinFilter || m_RefTex.m_MagFilter!=r->m_RP.m_TexStages[tmu].MagFilter || r->m_RP.m_TexStages[tmu].Anisotropic!=m_RefTex.m_AnisLevel)
|
|
{
|
|
r->m_RP.m_TexStages[tmu].MinFilter = m_RefTex.m_MinFilter;
|
|
r->m_RP.m_TexStages[tmu].MagFilter = m_RefTex.m_MagFilter;
|
|
r->m_RP.m_TexStages[tmu].Anisotropic = m_RefTex.m_AnisLevel;
|
|
dv->SetSamplerState(tmu, D3DSAMP_MINFILTER, m_RefTex.m_MinFilter);
|
|
dv->SetSamplerState(tmu, D3DSAMP_MAGFILTER, m_RefTex.m_MagFilter);
|
|
if (m_RefTex.m_MinFilter == D3DTEXF_ANISOTROPIC)
|
|
dv->SetSamplerState( tmu, D3DSAMP_MAXANISOTROPY, m_RefTex.m_AnisLevel);
|
|
}
|
|
if (m_RefTex.bRepeats != r->m_RP.m_TexStages[tmu].Repeat)
|
|
{
|
|
r->m_RP.m_TexStages[tmu].Repeat = m_RefTex.bRepeats;
|
|
if (m_RefTex.bRepeats == 2)
|
|
{
|
|
dv->SetSamplerState(tmu, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRRORONCE);
|
|
dv->SetSamplerState(tmu, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRRORONCE);
|
|
}
|
|
else
|
|
if (m_RefTex.bRepeats == 0)
|
|
{
|
|
dv->SetSamplerState(tmu, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
|
dv->SetSamplerState(tmu, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
|
}
|
|
else
|
|
if (m_RefTex.bRepeats == 1)
|
|
{
|
|
dv->SetSamplerState(tmu, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
|
|
dv->SetSamplerState(tmu, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
|
|
}
|
|
if (m_RefTex.m_Type == TEXTGT_CUBEMAP || m_RefTex.m_Type == TEXTGT_3D)
|
|
{
|
|
if (m_RefTex.bRepeats == 1)
|
|
dv->SetSamplerState(tmu, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP);
|
|
else
|
|
dv->SetSamplerState(tmu, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
|
|
}
|
|
}
|
|
if (m_RefTex.bProjected != r->m_RP.m_TexStages[tmu].Projected)
|
|
{
|
|
r->m_RP.m_TexStages[tmu].Projected = m_RefTex.bProjected;
|
|
int nFlags = m_RefTex.bProjected ? D3DTTFF_PROJECTED : D3DTTFF_DISABLE;
|
|
if (m_RefTex.bProjected && !(r->m_RP.m_FlagsPerFlush & RBSI_USEVP))
|
|
{
|
|
if (m_RefTex.m_Type == TEXTGT_CUBEMAP)
|
|
nFlags |= D3DTTFF_COUNT4;
|
|
else
|
|
nFlags |= D3DTTFF_COUNT3;
|
|
}
|
|
dv->SetTextureStageState(tmu, D3DTSS_TEXTURETRANSFORMFLAGS, nFlags);
|
|
}
|
|
//SaveJPG("BugCube.jpg", false);
|
|
|
|
r->m_TexMan->m_LastTex = this;
|
|
}
|
|
|
|
int SShaderTexUnit::mfSetTexture(int nt)
|
|
{
|
|
CD3D9Renderer *rd = gcpRendD3D;
|
|
|
|
rd->m_TexMan->m_CurStage = nt;
|
|
|
|
SShaderTexUnit *pSTU = this;
|
|
int nSetID = -1;
|
|
int nTexSlot = -1;
|
|
if (m_TexPic && m_TexPic->m_Bind < EFTT_MAX)
|
|
{
|
|
if (m_TexPic->m_Bind >= EFTT_LIGHTMAP && m_TexPic->m_Bind <= EFTT_OCCLUSION)
|
|
{
|
|
if (m_TexPic->m_Bind == EFTT_LIGHTMAP && rd->m_RP.m_pCurObject->m_nLMId)
|
|
{
|
|
rd->m_RP.m_FlagsPerFlush |= RBSI_USE_LM;
|
|
nSetID = rd->m_RP.m_pCurObject->m_nLMId;
|
|
}
|
|
else
|
|
if (m_TexPic->m_Bind == EFTT_LIGHTMAP_DIR && rd->m_RP.m_pCurObject->m_nLMDirId)
|
|
nSetID = rd->m_RP.m_pCurObject->m_nLMDirId;
|
|
else
|
|
if (m_TexPic->m_Bind == EFTT_OCCLUSION && rd->m_RP.m_pCurObject->m_nOcclId)
|
|
nSetID = rd->m_RP.m_pCurObject->m_nOcclId;
|
|
}
|
|
else
|
|
if (nSetID < 0)
|
|
{
|
|
if (!rd->m_RP.m_pShaderResources || !rd->m_RP.m_pShaderResources->m_Textures[m_TexPic->m_Bind])
|
|
Warning( VALIDATOR_FLAG_TEXTURE,0,"SShaderTexUnit::mfSetTexture: Missed template texture '%s' for shader '%s'\n", gRenDev->m_cEF.mfTemplateTexIdToName(m_TexPic->m_Bind), rd->m_RP.m_pShader->GetName());
|
|
else
|
|
{
|
|
nTexSlot = m_TexPic->m_Bind;
|
|
pSTU = &rd->m_RP.m_pShaderResources->m_Textures[nTexSlot]->m_TU;
|
|
rd->m_RP.m_pShaderResources->m_Textures[nTexSlot]->Update(nt);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pSTU->m_AnimInfo)
|
|
pSTU->mfUpdate();
|
|
|
|
if (pSTU->m_TexPic)
|
|
{
|
|
if (nSetID > 0)
|
|
{
|
|
gRenDev->m_TexMan->SetTexture(nSetID, eTT_Base);
|
|
}
|
|
else
|
|
{
|
|
int bind = pSTU->m_TexPic->m_Bind;
|
|
if (bind >= TX_FIRSTBIND)
|
|
{
|
|
if (pSTU->m_TexPic->m_Flags & FT_3DC)
|
|
rd->m_RP.m_FlagsPerFlush |= RBSI_USE_3DC;
|
|
pSTU->m_TexPic->Set(nTexSlot);
|
|
//pSTU->m_TexPic->SaveTGA("Phong1.tga", false);
|
|
}
|
|
else
|
|
switch (bind)
|
|
{
|
|
case TO_FROMRE0:
|
|
case TO_FROMRE1:
|
|
case TO_FROMRE2:
|
|
case TO_FROMRE3:
|
|
case TO_FROMRE4:
|
|
case TO_FROMRE5:
|
|
case TO_FROMRE6:
|
|
case TO_FROMRE7:
|
|
{
|
|
if (rd->m_RP.m_pRE)
|
|
bind = rd->m_RP.m_pRE->m_CustomTexBind[bind-TO_FROMRE0];
|
|
else
|
|
bind = rd->m_RP.m_RECustomTexBind[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 0;
|
|
rd->SetTexture(bind, eTT_Base);
|
|
}
|
|
break;
|
|
|
|
case TO_FROMLIGHT:
|
|
{
|
|
bool bRes = false;
|
|
if (rd->m_RP.m_nCurLight < rd->m_RP.m_DLights[SRendItem::m_RecurseLevel].Num())
|
|
{
|
|
CDLight *dl = rd->m_RP.m_pCurLight;
|
|
if (dl && dl->m_pLightImage!=0)
|
|
{
|
|
bRes = true;
|
|
STexPic *tp = (STexPic *)((ITexPic*)dl->m_pLightImage);
|
|
if (dl->m_NumCM >= 0)
|
|
tp = rd->m_TexMan->m_CustomCMaps[dl->m_NumCM].m_Tex;
|
|
else
|
|
if (dl->m_fAnimSpeed)
|
|
{
|
|
int n = 0;
|
|
STexPic *t = tp;
|
|
while (t)
|
|
{
|
|
t = t->m_NextTxt;
|
|
n++;
|
|
}
|
|
if (n > 1)
|
|
{
|
|
int m = (int)(rd->m_RP.m_RealTime / dl->m_fAnimSpeed) % n;
|
|
for (int i=0; i<m; i++)
|
|
{
|
|
tp = tp->m_NextTxt;
|
|
}
|
|
}
|
|
}
|
|
tp->Set();
|
|
}
|
|
}
|
|
if (!bRes && !(rd->m_RP.m_PersFlags & RBPF_MULTILIGHTS))
|
|
Warning( VALIDATOR_FLAG_TEXTURE,0,"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 = rd->m_cEF.mfFindSuitableEnvCMap(rd->m_RP.m_pCurObject->GetTranslation(), true, 0, 0);
|
|
if (cm && cm->m_Tex)
|
|
cm->m_Tex->Set();
|
|
else
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
case TO_ENVIRONMENT_LIGHTCUBE_MAP:
|
|
{
|
|
SEnvTexture *cm = NULL;
|
|
cm = rd->m_cEF.mfFindSuitableEnvLCMap(rd->m_RP.m_pCurObject->GetTranslation(), true, 0, 0);
|
|
if (cm && cm->m_Tex)
|
|
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();
|
|
bool bReflect = false;
|
|
if ((rd->m_RP.m_pShader->m_Flags3 & (EF3_CLIPPLANE_FRONT | EF3_REFLECTION)))
|
|
bReflect = true;
|
|
cm = rd->m_cEF.mfFindSuitableEnvTex(Pos, Angs, true, 0, false, rd->m_RP.m_pShader, rd->m_RP.m_pShaderResources, rd->m_RP.m_pCurObject, bReflect, gRenDev->m_RP.m_pRE);
|
|
if (cm)
|
|
cm->m_Tex->Set();
|
|
else
|
|
return false;
|
|
}
|
|
break;
|
|
|
|
case TO_SCREENMAP:
|
|
if (rd->m_RP.m_PersFlags & RBPF_HDR)
|
|
rd->m_TexMan->m_Text_ScreenMap_HDR->Set();
|
|
else
|
|
rd->m_TexMan->m_Text_ScreenMap->Set();
|
|
break;
|
|
|
|
default:
|
|
{
|
|
if (bind >= TO_CUSTOM_CUBE_MAP_FIRST && bind <= TO_CUSTOM_CUBE_MAP_LAST)
|
|
{
|
|
SEnvTexture *cm = &gRenDev->m_TexMan->m_CustomCMaps[bind-TO_CUSTOM_CUBE_MAP_FIRST];
|
|
if (!cm->m_bReady)
|
|
{
|
|
Warning( VALIDATOR_FLAG_TEXTURE,0,"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 = &gRenDev->m_TexMan->m_CustomTextures[bind-TO_CUSTOM_TEXTURE_FIRST];
|
|
if (!cm->m_bReady)
|
|
{
|
|
Warning( VALIDATOR_FLAG_TEXTURE,0,"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;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rd->m_pd3dDevice->SetTexture(nt, NULL);
|
|
rd->m_RP.m_TexStages[nt].Texture = NULL;
|
|
}
|
|
|
|
// Override texture sampler settings
|
|
if (m_nFlags & (FTU_CLAMP | FTU_NOMIPS | FTU_PROJECTED | FTU_FILTERBILINEAR | FTU_FILTERTRILINEAR | FTU_FILTERNEAREST))
|
|
{
|
|
STexPicD3D *tp = (STexPicD3D *)rd->m_TexMan->m_LastTex;
|
|
LPDIRECT3DDEVICE9 dv = rd->mfGetD3DDevice();
|
|
if ((m_nFlags & FTU_CLAMP) && rd->m_RP.m_TexStages[nt].Repeat)
|
|
{
|
|
rd->m_RP.m_TexStages[nt].Repeat = false;
|
|
dv->SetSamplerState(nt, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
|
dv->SetSamplerState(nt, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
|
if (tp->m_RefTex.m_Type == TEXTGT_CUBEMAP)
|
|
dv->SetSamplerState(nt, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
|
|
}
|
|
if ((m_nFlags & FTU_FILTERNEAREST) && (rd->m_RP.m_TexStages[nt].nMipFilter != D3DTEXF_NONE || rd->m_RP.m_TexStages[nt].MinFilter != D3DTEXF_POINT || rd->m_RP.m_TexStages[nt].MagFilter != D3DTEXF_POINT))
|
|
{
|
|
rd->m_RP.m_TexStages[nt].nMipFilter = D3DTEXF_NONE;
|
|
rd->m_RP.m_TexStages[nt].MagFilter = D3DTEXF_POINT;
|
|
rd->m_RP.m_TexStages[nt].MinFilter = D3DTEXF_POINT;
|
|
dv->SetSamplerState(nt, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
|
|
dv->SetSamplerState(nt, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
|
dv->SetSamplerState(nt, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
|
}
|
|
if ((m_nFlags & FTU_NOMIPS) && rd->m_RP.m_TexStages[nt].nMipFilter)
|
|
{
|
|
rd->m_RP.m_TexStages[nt].nMipFilter = 0;
|
|
dv->SetSamplerState(nt, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
|
|
}
|
|
else
|
|
{
|
|
if ((m_nFlags & FTU_FILTERBILINEAR) && rd->m_RP.m_TexStages[nt].nMipFilter != D3DTEXF_POINT)
|
|
{
|
|
rd->m_RP.m_TexStages[nt].nMipFilter = D3DTEXF_POINT;
|
|
dv->SetSamplerState(nt, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
|
|
}
|
|
else
|
|
if ((m_nFlags & FTU_FILTERTRILINEAR) && rd->m_RP.m_TexStages[nt].nMipFilter != D3DTEXF_LINEAR)
|
|
{
|
|
rd->m_RP.m_TexStages[nt].nMipFilter = D3DTEXF_LINEAR;
|
|
dv->SetSamplerState(nt, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
|
|
}
|
|
}
|
|
if ((m_nFlags & FTU_PROJECTED) && !rd->m_RP.m_TexStages[nt].Projected)
|
|
{
|
|
rd->m_RP.m_TexStages[nt].Projected = true;
|
|
int nFlags = D3DTTFF_PROJECTED;
|
|
if (!(rd->m_RP.m_FlagsPerFlush & RBSI_USEVP))
|
|
{
|
|
if (tp->m_RefTex.m_Type == TEXTGT_CUBEMAP)
|
|
nFlags |= D3DTTFF_COUNT4;
|
|
else
|
|
nFlags |= D3DTTFF_COUNT3;
|
|
}
|
|
dv->SetTextureStageState(nt, D3DTSS_TEXTURETRANSFORMFLAGS, nFlags);
|
|
}
|
|
}
|
|
|
|
// Set tex. transforms/tex. gen modes (for fixed pipeline)
|
|
if (m_GTC)
|
|
{
|
|
if (!m_GTC->mfSet(true))
|
|
return 0;
|
|
if (m_GTC->m_bDependsOnObject)
|
|
{
|
|
rd->m_RP.m_pGTC[nt] = m_GTC;
|
|
rd->m_RP.m_FrameGTC = rd->m_RP.m_Frame;
|
|
}
|
|
else
|
|
rd->m_RP.m_pGTC[nt] = NULL;
|
|
}
|
|
else
|
|
rd->m_RP.m_pGTC[nt] = NULL;
|
|
|
|
// Set texture color ops. (for fixed pipeline)
|
|
if (m_eColorOp != eCO_NOSET)
|
|
{
|
|
if (m_eHDRColorOp && rd->m_nHDRType==1 && (rd->m_RP.m_PersFlags & RBPF_HDR))
|
|
rd->m_RP.m_TexStages[nt].m_CO = m_eHDRColorOp;
|
|
else
|
|
rd->m_RP.m_TexStages[nt].m_CO = m_eColorOp;
|
|
rd->m_RP.m_TexStages[nt].m_AO = m_eAlphaOp;
|
|
rd->m_RP.m_TexStages[nt].m_CA = m_eColorArg;
|
|
rd->m_RP.m_TexStages[nt].m_AA = m_eAlphaArg;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
bool SShaderPass::mfSetTextures()
|
|
{
|
|
int i;
|
|
CD3D9Renderer *rd = gcpRendD3D;
|
|
rd->m_RP.m_FlagsPerFlush &= ~(RBSI_USE_LM | RBSI_USE_HDRLM | RBSI_USE_SPECANTIALIAS);
|
|
for (i=0; i<m_TUnits.Num(); i++)
|
|
{
|
|
SShaderTexUnit *tl = &m_TUnits[i];
|
|
tl->mfSetTexture(i);
|
|
if (rd->m_RP.m_FlagsPerFlush & RBSI_USEVP)
|
|
{
|
|
if (rd->m_RP.m_TexStages[i].TCIndex != i)
|
|
{
|
|
rd->m_RP.m_TexStages[i].TCIndex = i;
|
|
rd->m_pd3dDevice->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i);
|
|
}
|
|
}
|
|
}
|
|
if (rd->m_RP.m_FlagsPerFlush & (RBSI_USE_LM | RBSI_USE_3DC | RBSI_USE_SPECANTIALIAS))
|
|
{
|
|
if ((rd->m_RP.m_FlagsPerFlush & RBSI_USE_LM) && (rd->m_RP.m_PersFlags & RBPF_HDR) && rd->m_RP.m_pCurObject->m_nHDRLMId)
|
|
{
|
|
rd->m_RP.m_FlagsPerFlush |= RBSI_USE_HDRLM;
|
|
rd->EF_SelectTMU(i);
|
|
rd->m_TexMan->SetTexture(rd->m_RP.m_pCurObject->m_nHDRLMId, eTT_Base);
|
|
i++;
|
|
}
|
|
if ((rd->m_RP.m_FlagsPerFlush & RBSI_USE_3DC) && (rd->m_RP.m_pShader->m_Flags & EF_OFFSETBUMP))
|
|
{
|
|
if (rd->m_RP.m_pShaderResources && rd->m_RP.m_pShaderResources->m_Textures[EFTT_BUMP_HEIGHT])
|
|
{
|
|
rd->m_RP.m_FlagsPerFlush |= RBSI_USE_3DC_A;
|
|
rd->EF_SelectTMU(i);
|
|
rd->m_RP.m_pShaderResources->m_Textures[EFTT_BUMP_HEIGHT]->m_TU.m_TexPic->Set();
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
CD3D9TexMan::BindNULL(i);
|
|
return true;
|
|
}
|
|
|
|
void SShaderPass::mfResetTextures()
|
|
{
|
|
int i;
|
|
for (i=0; i<m_TUnits.Num(); i++)
|
|
{
|
|
SShaderTexUnit *tl = &m_TUnits[i];
|
|
if (tl->m_GTC)
|
|
{
|
|
gcpRendD3D->EF_SelectTMU(i);
|
|
tl->m_GTC->mfSet(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=========================================================================
|
|
|
|
STexPic *CD3D9TexMan::GetByID(int Id)
|
|
{
|
|
if (Id >= TX_FIRSTBIND)
|
|
{
|
|
int n = Id - TX_FIRSTBIND;
|
|
if (n < m_Textures.Num())
|
|
{
|
|
STexPic *tp = m_Textures[n];
|
|
if (tp && tp->m_Bind == Id)
|
|
return tp;
|
|
}
|
|
}
|
|
TTextureMapItor it = m_RefTexs.find(Id);
|
|
if (it != m_RefTexs.end())
|
|
return it->second;
|
|
return NULL;
|
|
}
|
|
|
|
STexPic *CD3D9TexMan::AddToHash(int Id, STexPic *ti)
|
|
{
|
|
TTextureMapItor it = m_RefTexs.find(Id);
|
|
if (it == m_RefTexs.end())
|
|
m_RefTexs.insert(TTextureMapItor::value_type(Id, ti));
|
|
else
|
|
{
|
|
STexPic *tpOther = it->second;
|
|
assert(ti == tpOther);
|
|
}
|
|
return ti;
|
|
}
|
|
|
|
void CD3D9TexMan::RemoveFromHash(int Id, STexPic *ti)
|
|
{
|
|
TTextureMapItor it = m_RefTexs.find(Id);
|
|
if (it != m_RefTexs.end())
|
|
{
|
|
if (ti)
|
|
assert(ti == it->second);
|
|
IDirect3DBaseTexture9* vt = (IDirect3DBaseTexture9*)ti->m_RefTex.m_VidTex;
|
|
//if (vt)
|
|
// sRemoveTX(ti);
|
|
SAFE_RELEASE (vt);
|
|
ti->m_RefTex.m_VidTex = NULL;
|
|
m_RefTexs.erase(Id);
|
|
}
|
|
}
|
|
|
|
CD3D9TexMan::~CD3D9TexMan()
|
|
{
|
|
if (STexPicD3D::m_TexUseLogFile != NULL)
|
|
{
|
|
fclose(STexPicD3D::m_TexUseLogFile);
|
|
}
|
|
|
|
STexPicD3D::m_TexUseLogFile = NULL;
|
|
SAFE_DELETE(m_TexCache);
|
|
}
|
|
|
|
|
|
STexPic *CD3D9TexMan::CreateTexture()
|
|
{
|
|
#ifdef DEBUGALLOC
|
|
#undef new
|
|
#endif
|
|
return new STexPicD3D;
|
|
#ifdef DEBUGALLOC
|
|
#define new DEBUG_CLIENTBLOCK
|
|
#endif
|
|
}
|
|
|
|
bool CD3D9TexMan::SetFilter(char *tex)
|
|
{
|
|
int i;
|
|
struct textype
|
|
{
|
|
char *name;
|
|
uint typemin;
|
|
uint typemag;
|
|
uint typemip;
|
|
};
|
|
|
|
static textype tt[] =
|
|
{
|
|
{"NEAREST", D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE},
|
|
{"LINEAR", D3DTEXF_LINEAR, D3DTEXF_LINEAR, D3DTEXF_NONE},
|
|
{"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);
|
|
if (!(gRenDev->GetFeatures() & RFT_ALLOWANISOTROPIC))
|
|
m_CurAnisotropic = 1;
|
|
CRenderer::CV_r_texture_anisotropic_level = m_CurAnisotropic;
|
|
strcpy(m_CurTexFilter, CD3D9Renderer::CV_d3d9_texturefilter->GetString());
|
|
if ((gRenDev->GetFeatures() & RFT_ALLOWANISOTROPIC) && m_CurAnisotropic > 1)
|
|
tex = "TRILINEAR";
|
|
|
|
for (i=0; i<4; i++)
|
|
{
|
|
if (!stricmp(tex, tt[i].name) )
|
|
{
|
|
m_MinFilter = tt[i].typemin;
|
|
m_MagFilter = tt[i].typemag;
|
|
m_MipFilter = tt[i].typemip;
|
|
if (i == 3 && m_CurAnisotropic > 1)
|
|
iLog->Log("Apply anisotropic texture filtering (level: %d)", m_CurAnisotropic);
|
|
else
|
|
iLog->Log("Apply %s texture filtering", tex);
|
|
|
|
for (i=0; i<m_Textures.Num(); i++)
|
|
{
|
|
if (m_Textures[i] && m_Textures[i]->m_bBusy)
|
|
{
|
|
if ((m_Textures[i]->m_Flags & FT_NOMIPS) && i > 1)
|
|
continue;
|
|
STexPicD3D *pTP = (STexPicD3D *)m_Textures[i];
|
|
if (m_CurAnisotropic > 1 && !(pTP->m_Flags2 & FT2_NOANISO) && !(pTP->m_Flags & FT_NOMIPS))
|
|
pTP->m_RefTex.m_AnisLevel = m_CurAnisotropic;
|
|
else
|
|
pTP->m_RefTex.m_AnisLevel = 1;
|
|
if (pTP->m_RefTex.m_AnisLevel > 1)
|
|
{
|
|
if (gcpRendD3D->m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
|
|
pTP->m_RefTex.m_MinFilter = D3DTEXF_ANISOTROPIC;
|
|
else
|
|
pTP->m_RefTex.m_MinFilter = D3DTEXF_LINEAR;
|
|
if (gcpRendD3D->m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC)
|
|
pTP->m_RefTex.m_MagFilter = D3DTEXF_ANISOTROPIC;
|
|
else
|
|
pTP->m_RefTex.m_MagFilter = D3DTEXF_LINEAR;
|
|
if (gcpRendD3D->m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR)
|
|
pTP->m_RefTex.m_MipFilter = D3DTEXF_LINEAR;
|
|
else
|
|
pTP->m_RefTex.m_MipFilter = D3DTEXF_POINT;
|
|
}
|
|
else
|
|
{
|
|
pTP->m_RefTex.m_MinFilter = GetMinFilter();
|
|
pTP->m_RefTex.m_MagFilter = GetMagFilter();
|
|
pTP->m_RefTex.m_MipFilter = GetMipFilter();
|
|
}
|
|
if (pTP->m_Flags & FT_NOMIPS)
|
|
pTP->m_RefTex.m_MipFilter = D3DTEXF_NONE;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
Warning( VALIDATOR_FLAG_TEXTURE,0,"Bad texture filter name <%s>\n", tex);
|
|
return false;
|
|
}
|
|
|
|
int STexPic::DstFormatFromTexFormat(ETEX_Format eTF)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int STexPicD3D::DstFormatFromTexFormat(ETEX_Format eTF)
|
|
{
|
|
switch(eTF)
|
|
{
|
|
case eTF_8888:
|
|
return D3DFMT_A8R8G8B8;
|
|
break;
|
|
case eTF_0888:
|
|
if (m_Flags & FT_HASALPHA)
|
|
return D3DFMT_A8R8G8B8;
|
|
else
|
|
return D3DFMT_X8R8G8B8;
|
|
break;
|
|
case eTF_DXT1:
|
|
return D3DFMT_DXT1;
|
|
case eTF_DXT3:
|
|
return D3DFMT_DXT3;
|
|
case eTF_DXT5:
|
|
return D3DFMT_DXT5;
|
|
case eTF_DSDT_MAG:
|
|
return D3DFMT_X8L8V8U8;
|
|
default:
|
|
assert(0);
|
|
return D3DFMT_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
int STexPic::TexSize(int Width, int Height, int DstFormat)
|
|
{
|
|
return 0;
|
|
}
|
|
int STexPicD3D::TexSize(int Width, int Height, int DstFormat)
|
|
{
|
|
return CD3D9TexMan::TexSize(Width, Height, DstFormat);
|
|
}
|
|
|
|
int CD3D9TexMan::TexSize(int wdt, int hgt, int mode)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case D3DFMT_X8R8G8B8:
|
|
case D3DFMT_X8L8V8U8:
|
|
case D3DFMT_Q8W8V8U8:
|
|
case D3DFMT_D24S8:
|
|
return wdt * hgt * 4;
|
|
|
|
case D3DFMT_V8U8:
|
|
return wdt * hgt * 2;
|
|
case D3DFMT_CxV8U8:
|
|
return wdt * hgt * 2;
|
|
|
|
case D3DFMT_V16U16:
|
|
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_A8L8:
|
|
return wdt * hgt * 2;
|
|
|
|
case D3DFMT_A4R4G4B4:
|
|
case D3DFMT_A1R5G5B5:
|
|
case D3DFMT_X1R5G5B5:
|
|
case D3DFMT_R5G6B5:
|
|
case D3DFMT_D16:
|
|
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 MAKEFOURCC('A', 'T', 'I', '2'):
|
|
{
|
|
int blockSize = 16;
|
|
return ((wdt+3)/4)*((hgt+3)/4)*blockSize;
|
|
}
|
|
|
|
case D3DFMT_P8:
|
|
return wdt * hgt;
|
|
|
|
case D3DFMT_A16B16G16R16F:
|
|
case D3DFMT_A16B16G16R16:
|
|
return wdt * hgt * 8;
|
|
|
|
case D3DFMT_G16R16:
|
|
case D3DFMT_G16R16F:
|
|
return wdt * hgt * 4;
|
|
|
|
case D3DFMT_R16F:
|
|
return wdt * hgt * 2;
|
|
|
|
case D3DFMT_R32F:
|
|
return wdt * hgt * 4;
|
|
|
|
default:
|
|
assert(0);
|
|
break;
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CD3D9TexMan::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_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;
|
|
}
|
|
ti->m_Size *= ti->m_Depth;
|
|
}
|
|
|
|
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_VidTex)
|
|
return;
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
LPDIRECT3DDEVICE9 dv = r->mfGetD3DDevice();
|
|
IDirect3DTexture9 *pID3DTexture = NULL;
|
|
IDirect3DCubeTexture9 *pID3DCubeTexture = NULL;
|
|
if (m_eTT == eTT_Cubemap)
|
|
pID3DCubeTexture = (IDirect3DCubeTexture9*)m_RefTex.m_VidTex;
|
|
else
|
|
pID3DTexture = (IDirect3DTexture9*)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, 32);
|
|
// 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_VidTex)
|
|
return;
|
|
char name[64];
|
|
StripExtension(nam, name);
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
LPDIRECT3DDEVICE9 dv = r->mfGetD3DDevice();
|
|
IDirect3DTexture9 *pID3DTexture = NULL;
|
|
IDirect3DTexture9 *pID3DSrcTexture = NULL;
|
|
IDirect3DCubeTexture9 *pID3DCubeTexture = NULL;
|
|
LPDIRECT3DSURFACE9 pDestSurf;
|
|
LPDIRECT3DSURFACE9 pSourceSurf;
|
|
if (m_eTT == eTT_Cubemap)
|
|
pID3DCubeTexture = (IDirect3DCubeTexture9*)m_RefTex.m_VidTex;
|
|
else
|
|
pID3DTexture = (IDirect3DTexture9*)m_RefTex.m_VidTex;
|
|
HRESULT h;
|
|
D3DLOCKED_RECT d3dlr;
|
|
D3DSURFACE_DESC ddsdDescDest;
|
|
|
|
int wdt = m_Width;
|
|
int hgt = m_Height;
|
|
if(FAILED(h = D3DXCreateTexture(dv, wdt, hgt, m_nMips, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSrcTexture)))
|
|
return;
|
|
|
|
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]);
|
|
|
|
h = pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)CubeSide, 0, &pDestSurf);
|
|
h = pID3DSrcTexture->GetSurfaceLevel(0, &pSourceSurf);
|
|
h = D3DXLoadSurfaceFromSurface(pSourceSurf, NULL, NULL, pDestSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
|
|
SAFE_RELEASE(pDestSurf);
|
|
SAFE_RELEASE(pSourceSurf);
|
|
|
|
pID3DCubeTexture->GetLevelDesc(0, &ddsdDescDest);
|
|
|
|
// Lock the texture to copy the image data into the texture
|
|
h = pID3DSrcTexture->LockRect(0, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
byte *pSrc = (byte *)d3dlr.pBits;
|
|
#ifndef _XBOX
|
|
WriteJPG(pSrc, ddsdDescDest.Width, ddsdDescDest.Height, nm);
|
|
#endif
|
|
// Unlock the texture
|
|
pID3DSrcTexture->UnlockRect(0);
|
|
}
|
|
}
|
|
else
|
|
if (!bMips)
|
|
{
|
|
char nm[128];
|
|
sprintf(nm, "%s.jpg", name);
|
|
|
|
h = pID3DTexture->GetSurfaceLevel(0, &pDestSurf);
|
|
h = pID3DSrcTexture->GetSurfaceLevel(0, &pSourceSurf);
|
|
h = D3DXLoadSurfaceFromSurface(pSourceSurf, NULL, NULL, pDestSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
|
|
SAFE_RELEASE(pDestSurf);
|
|
SAFE_RELEASE(pSourceSurf);
|
|
|
|
pID3DTexture->GetLevelDesc(0, &ddsdDescDest);
|
|
|
|
// Lock the texture to copy the image data into the texture
|
|
h = pID3DSrcTexture->LockRect(0, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
byte *pSrc = (byte *)d3dlr.pBits;
|
|
#ifndef _XBOX
|
|
WriteJPG(pSrc, ddsdDescDest.Width, ddsdDescDest.Height, (char *)nm);
|
|
#endif
|
|
// Unlock the texture
|
|
pID3DSrcTexture->UnlockRect(0);
|
|
}
|
|
else
|
|
{
|
|
for (int i=0; i<m_nMips; i++)
|
|
{
|
|
char nm[128];
|
|
sprintf(nm, "%s[%d].jpg", name, i);
|
|
|
|
h = pID3DTexture->GetSurfaceLevel(i, &pDestSurf);
|
|
h = pID3DSrcTexture->GetSurfaceLevel(i, &pSourceSurf);
|
|
h = D3DXLoadSurfaceFromSurface(pSourceSurf, NULL, NULL, pDestSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
|
|
SAFE_RELEASE(pDestSurf);
|
|
SAFE_RELEASE(pSourceSurf);
|
|
|
|
pID3DTexture->GetLevelDesc(i, &ddsdDescDest);
|
|
// Lock the texture to copy the image data into the texture
|
|
h = pID3DTexture->LockRect(i, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
byte *pSrc = (byte *)d3dlr.pBits;
|
|
#ifndef _XBOX
|
|
WriteJPG(pSrc, ddsdDescDest.Width, ddsdDescDest.Height, (char *)nm);
|
|
#endif
|
|
// Unlock the texture
|
|
pID3DSrcTexture->UnlockRect(i);
|
|
}
|
|
}
|
|
SAFE_RELEASE(pID3DSrcTexture);
|
|
}
|
|
|
|
LPDIRECT3DTEXTURE9 CD3D9TexMan::D3DCreateSrcTexture(STexPicD3D *ti, byte *src, D3DFORMAT srcFormat, int SizeSrc, int DXTSize)
|
|
{
|
|
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
|
|
LPDIRECT3DTEXTURE9 pID3DSrcTexture = NULL;
|
|
D3DLOCKED_RECT d3dlr;
|
|
int wdt = ti->m_Width;
|
|
int hgt = ti->m_Height;
|
|
int i;
|
|
int offset = 0;
|
|
int size;
|
|
HRESULT hr;
|
|
|
|
if( FAILED( hr = D3DXCreateTexture(dv, wdt, hgt, ti->m_nMips ? ti->m_nMips : 1, 0, srcFormat, D3DPOOL_SYSTEMMEM, &pID3DSrcTexture ) ) )
|
|
return NULL;
|
|
if (ti->m_nMips)
|
|
{
|
|
int w = wdt;
|
|
int h = hgt;
|
|
for (i=0; i<ti->m_nMips; i++)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
if (ti->m_Flags & FT_DXT)
|
|
{
|
|
if (offset >= DXTSize)
|
|
break;
|
|
int blockSize = (ti->m_Flags & FT_DXT1) ? 8 : 16;
|
|
size = ((w+3)/4)*((h+3)/4)*blockSize;
|
|
|
|
// Lock the texture to copy the image data into the texture
|
|
hr = pID3DSrcTexture->LockRect(i, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
cryMemcpy(d3dlr.pBits, &src[offset], size);
|
|
// Unlock the texture
|
|
pID3DSrcTexture->UnlockRect(i);
|
|
|
|
offset += size;
|
|
}
|
|
else
|
|
if (srcFormat == D3DFMT_X8R8G8B8 || srcFormat == D3DFMT_A8R8G8B8 || srcFormat == D3DFMT_X8L8V8U8 || srcFormat == D3DFMT_Q8W8V8U8)
|
|
{
|
|
size = w * h * 4;
|
|
// Lock the texture to copy the image data into the texture
|
|
hr = pID3DSrcTexture->LockRect(i, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
cryMemcpy(d3dlr.pBits, src, size);
|
|
// Unlock the texture
|
|
pID3DSrcTexture->UnlockRect(i);
|
|
src += size;
|
|
}
|
|
else
|
|
if (srcFormat == D3DFMT_P8)
|
|
{
|
|
size = w * h;
|
|
// Lock the texture to copy the image data into the texture
|
|
hr = pID3DSrcTexture->LockRect(i, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
cryMemcpy(d3dlr.pBits, src, size);
|
|
// Unlock the texture
|
|
pID3DSrcTexture->UnlockRect(i);
|
|
src += size;
|
|
}
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Lock the texture to copy the image data into the texture
|
|
hr = pID3DSrcTexture->LockRect(0, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
cryMemcpy(d3dlr.pBits, src, SizeSrc);
|
|
// Unlock the texture
|
|
pID3DSrcTexture->UnlockRect(0);
|
|
}
|
|
return pID3DSrcTexture;
|
|
}
|
|
|
|
void CD3D9TexMan::D3DCreateVideoTexture(int tgt, byte *src, int wdt, int hgt, int depth, D3DFORMAT SrcFormat, D3DFORMAT DstFormat, STexPicD3D *ti, bool bMips, int CubeSide, PALETTEENTRY *pe, int DXTSize)
|
|
{
|
|
int i = 0;
|
|
int offset = 0;
|
|
int size;
|
|
|
|
LPDIRECT3DSURFACE9 pDestSurf;
|
|
|
|
byte *pTemp = NULL;
|
|
|
|
HRESULT hr;
|
|
D3DLOCKED_RECT d3dlr;
|
|
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
|
|
|
|
LPDIRECT3DTEXTURE9 pID3DTexture = NULL;
|
|
LPDIRECT3DCUBETEXTURE9 pID3DCubeTexture = NULL;
|
|
LPDIRECT3DTEXTURE9 pID3DSrcTexture = NULL;
|
|
LPDIRECT3DVOLUMETEXTURE9 pID3DVolTexture = NULL;
|
|
|
|
ti->m_DstFormat = DstFormat;
|
|
ti->m_CubeSide = CubeSide;
|
|
int D3DUsage = 0;
|
|
D3DPOOL D3DPool = TEXPOOL;
|
|
bool bGenMip = false;
|
|
if (ti->m_eTT == eTT_Cubemap && CubeSide)
|
|
{
|
|
D3DSURFACE_DESC desc;
|
|
pID3DCubeTexture = (LPDIRECT3DCUBETEXTURE9)m_pCurCubeTexture;
|
|
pID3DCubeTexture->GetLevelDesc(0, &desc);
|
|
if (bMips && !(desc.Usage & D3DUSAGE_AUTOGENMIPMAP) && ti->m_nMips <= 1)
|
|
bGenMip = true;
|
|
}
|
|
else
|
|
if (bMips && ti->m_nMips <= 1)
|
|
bGenMip = true;
|
|
|
|
if (bGenMip)
|
|
{
|
|
if(FAILED(hr = D3DXCreateTexture(dv, wdt, hgt, D3DX_DEFAULT, 0, SrcFormat, D3DPOOL_SYSTEMMEM, &pID3DSrcTexture)))
|
|
return;
|
|
size = TexSize(wdt, hgt, SrcFormat);
|
|
hr = pID3DSrcTexture->LockRect(0, &d3dlr, NULL, 0);
|
|
// Copy data to src texture
|
|
cryMemcpy((byte *)d3dlr.pBits, src, size);
|
|
// Unlock the system texture
|
|
pID3DSrcTexture->UnlockRect(0);
|
|
hr = D3DXFilterTexture(pID3DSrcTexture, NULL, 0, D3DX_FILTER_LINEAR);
|
|
size = 0;
|
|
int w = wdt;
|
|
int h = hgt;
|
|
while (w || h)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
size += TexSize(w, h, SrcFormat);
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
pTemp = new byte[size];
|
|
int n = pID3DSrcTexture->GetLevelCount();
|
|
w = wdt;
|
|
h = hgt;
|
|
int offs = 0;
|
|
i = 0;
|
|
while (w || h)
|
|
{
|
|
size = TexSize(w, h, SrcFormat);
|
|
hr = pID3DSrcTexture->LockRect(i, &d3dlr, NULL, 0);
|
|
// Copy data to src texture
|
|
cryMemcpy(&pTemp[offs], (byte *)d3dlr.pBits, size);
|
|
// Unlock the system texture
|
|
hr = pID3DSrcTexture->UnlockRect(i);
|
|
w >>= 1;
|
|
h >>= 1;
|
|
offs += size;
|
|
i++;
|
|
}
|
|
ti->m_nMips = i;
|
|
i = 0;
|
|
src = pTemp;
|
|
SAFE_RELEASE(pID3DSrcTexture);
|
|
}
|
|
|
|
if (bMips && ti->m_nMips <= 1 && !bGenMip)
|
|
D3DUsage |= D3DUSAGE_AUTOGENMIPMAP;
|
|
if (ti->m_Flags & FT_DYNAMIC)
|
|
{
|
|
//D3DUsage |= D3DUSAGE_DYNAMIC;
|
|
// NVidia workaround
|
|
// Use 16 bit video playing
|
|
if ((gRenDev->GetFeatures() & RFT_HW_MASK) == RFT_HW_GF2)
|
|
{
|
|
DstFormat = D3DFMT_R5G6B5;
|
|
ti->m_DstFormat = DstFormat;
|
|
}
|
|
D3DPool = D3DPOOL_MANAGED;
|
|
}
|
|
if (ti->m_Flags2 & FT2_RENDERTARGET)
|
|
{
|
|
D3DUsage |= D3DUSAGE_RENDERTARGET;
|
|
D3DPool = D3DPOOL_DEFAULT;
|
|
}
|
|
if (DstFormat == D3DFMT_D24S8 || DstFormat == D3DFMT_D16)
|
|
{
|
|
D3DUsage |= D3DUSAGE_DEPTHSTENCIL;
|
|
D3DUsage &= ~D3DUSAGE_RENDERTARGET;
|
|
D3DPool = D3DPOOL_DEFAULT;
|
|
}
|
|
|
|
if (ti->m_eTT == eTT_Cubemap)
|
|
{
|
|
if (!ti->m_CubeSide)
|
|
{
|
|
IDirect3DBaseTexture9 *pTex = (IDirect3DBaseTexture9*)ti->m_RefTex.m_VidTex;
|
|
SAFE_RELEASE(pTex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IDirect3DBaseTexture9 *pTex = (IDirect3DBaseTexture9*)ti->m_RefTex.m_VidTex;
|
|
SAFE_RELEASE(pTex);
|
|
}
|
|
|
|
D3DTEXTUREFILTERTYPE MipFilter;
|
|
switch (gcpRendD3D->CV_d3d9_texmipfilter)
|
|
{
|
|
case 0:
|
|
MipFilter = D3DTEXF_POINT;
|
|
break;
|
|
case 1:
|
|
MipFilter = D3DTEXF_LINEAR;
|
|
break;
|
|
}
|
|
|
|
// Create the video texture
|
|
if (tgt == TEXTGT_2D)
|
|
{
|
|
if (!(ti->m_Flags & FT_3DC) || gcpRendD3D->m_bDeviceSupportsComprNormalmaps > 1)
|
|
{
|
|
if( FAILED( hr = D3DXCreateTexture(dv, wdt, hgt, bMips ? D3DX_DEFAULT : 1, D3DUsage, DstFormat, D3DPool, &pID3DTexture ) ) )
|
|
{
|
|
iLog->Log("Error: CD3D9TexMan::D3DCreateVideoTexture: failed to create the texture %s (%s)", ti->m_SourceName.c_str(), gcpRendD3D->D3DError(hr));
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int nMips = 0;
|
|
int w = wdt;
|
|
int h = hgt;
|
|
while (w && h)
|
|
{
|
|
if (!w)
|
|
w = 1;
|
|
if (!h)
|
|
h = 1;
|
|
if (w >= 4 && h >= 4)
|
|
nMips++;
|
|
w >>= 1;
|
|
h >>= 1;
|
|
}
|
|
if (FAILED(hr=dv->CreateTexture(wdt, hgt, nMips, D3DUsage, DstFormat, D3DPool, &pID3DTexture, NULL)))
|
|
{
|
|
iLog->Log("Error: CD3D9TexMan::D3DCreateVideoTexture: failed to create the texture %s (%s)", ti->m_SourceName.c_str(), gcpRendD3D->D3DError(hr));
|
|
return;
|
|
}
|
|
}
|
|
if (D3DUsage & D3DUSAGE_AUTOGENMIPMAP)
|
|
hr = pID3DTexture->SetAutoGenFilterType(MipFilter);
|
|
ti->m_RefTex.m_VidTex = pID3DTexture;
|
|
//if (D3DPool == D3DPOOL_DEFAULT)
|
|
// sAddTX(ti, NULL);
|
|
if (D3DUsage & D3DUSAGE_RENDERTARGET)
|
|
return;
|
|
if (DstFormat == D3DFMT_D24S8 || DstFormat == D3DFMT_D16)
|
|
return;
|
|
}
|
|
else
|
|
if (tgt == TEXTGT_CUBEMAP)
|
|
{
|
|
int nMips = bMips ? D3DX_DEFAULT : 1;
|
|
if (!(gcpRendD3D->m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
|
|
{
|
|
nMips = 1;
|
|
ti->m_nMips = 1;
|
|
bMips = false;
|
|
}
|
|
if (CubeSide == 0)
|
|
{
|
|
if( FAILED(hr = D3DXCreateCubeTexture(dv, wdt, bMips ? D3DX_DEFAULT : 1, D3DUsage, DstFormat, D3DPool, &pID3DCubeTexture )))
|
|
return;
|
|
ti->m_RefTex.m_VidTex = pID3DCubeTexture;
|
|
if (D3DUsage & D3DUSAGE_AUTOGENMIPMAP)
|
|
hr = pID3DCubeTexture->SetAutoGenFilterType(MipFilter);
|
|
m_pCurCubeTexture = pID3DCubeTexture;
|
|
//if (D3DPool == D3DPOOL_DEFAULT)
|
|
// sAddTX(ti, NULL);
|
|
}
|
|
else
|
|
pID3DCubeTexture = (LPDIRECT3DCUBETEXTURE9)m_pCurCubeTexture;
|
|
if (ti->m_Flags2 & FT2_RENDERTARGET)
|
|
return;
|
|
}
|
|
else
|
|
if (tgt == TEXTGT_3D)
|
|
{
|
|
int nMips = bMips ? D3DX_DEFAULT : 1;
|
|
if (!(gcpRendD3D->m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
|
|
{
|
|
nMips = 1;
|
|
ti->m_nMips = 1;
|
|
bMips = false;
|
|
}
|
|
if( FAILED(hr = D3DXCreateVolumeTexture(dv, wdt, hgt, depth, bMips ? D3DX_DEFAULT : 1, D3DUsage, DstFormat, D3DPool, &pID3DVolTexture )))
|
|
return;
|
|
ti->m_RefTex.m_VidTex = pID3DVolTexture;
|
|
if (D3DUsage & D3DUSAGE_AUTOGENMIPMAP)
|
|
hr = pID3DVolTexture->SetAutoGenFilterType(MipFilter);
|
|
//if (D3DPool == D3DPOOL_DEFAULT)
|
|
// sAddTX(ti, NULL);
|
|
if (ti->m_Flags2 & FT2_RENDERTARGET)
|
|
return;
|
|
}
|
|
|
|
#if 0
|
|
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
|
|
cryMemcpy((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;
|
|
}
|
|
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))
|
|
{
|
|
Warning( VALIDATOR_FLAG_TEXTURE,ti->m_SearchName.c_str(),"Couldn't create palette for texture '%s'\n",ti->m_SearchName.c_str() );
|
|
}
|
|
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
|
|
cryMemcpy((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
|
|
if ((SrcFormat == D3DFMT_A8R8G8B8 || SrcFormat == D3DFMT_X8R8G8B8 || SrcFormat == D3DFMT_X8L8V8U8) && (DstFormat == D3DFMT_A8R8G8B8 || DstFormat == D3DFMT_X8R8G8B8 || DstFormat == D3DFMT_X8L8V8U8))
|
|
{
|
|
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;
|
|
|
|
// 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
|
|
cryMemcpy((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 (i >= ti->m_nMips)
|
|
break;
|
|
}
|
|
if (pID3DCubeTexture)
|
|
ti->m_RefTex.m_VidTex = pID3DCubeTexture;
|
|
else
|
|
ti->m_RefTex.m_VidTex = pID3DTexture;
|
|
}
|
|
else
|
|
#else
|
|
{
|
|
int nMips = (bMips && ti->m_nMips) ? ti->m_nMips : 1;
|
|
offset = 0;
|
|
if (tgt == TEXTGT_3D)
|
|
{
|
|
assert(SrcFormat == DstFormat);
|
|
|
|
// Fill the volume texture
|
|
D3DLOCKED_BOX LockedBox;
|
|
|
|
int w = wdt;
|
|
int h = hgt;
|
|
int d = depth;
|
|
offset = 0;
|
|
for (i=0; i<nMips; i++)
|
|
{
|
|
hr = pID3DVolTexture->LockBox(i, &LockedBox, 0, 0);
|
|
if (!w && !h && !d)
|
|
break;
|
|
if (!w) w = 1;
|
|
if (!h) h = 1;
|
|
if (!d) d = 1;
|
|
size = TexSize(w, 1, SrcFormat);
|
|
for (int r=0; r<d; r++)
|
|
{
|
|
byte* pSliceStart = (byte*)LockedBox.pBits;
|
|
for (int t=0; t<h; t++)
|
|
{
|
|
cryMemcpy((byte *)LockedBox.pBits, &src[offset], size);
|
|
LockedBox.pBits = (BYTE*)LockedBox.pBits + LockedBox.RowPitch;
|
|
offset += size;
|
|
}
|
|
LockedBox.pBits = pSliceStart + LockedBox.SlicePitch;
|
|
}
|
|
w >>= 1;
|
|
h >>= 1;
|
|
d >>= 1;
|
|
|
|
pID3DVolTexture->UnlockBox(i);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i=0; i<nMips; i++)
|
|
{
|
|
if (!wdt && !hgt)
|
|
break;
|
|
if (!wdt)
|
|
wdt = 1;
|
|
if (!hgt)
|
|
hgt = 1;
|
|
size = TexSize(wdt, hgt, SrcFormat);
|
|
|
|
if ((ti->m_Flags & FT_3DC) && gcpRendD3D->m_bDeviceSupportsComprNormalmaps == 1)
|
|
{
|
|
DWORD lockFlag = 0;
|
|
if (i == 0) // Figure out our locking flags, we can only discard on level 0
|
|
lockFlag |= D3DLOCK_DISCARD;
|
|
hr = pID3DTexture->LockRect(i, &d3dlr, NULL, lockFlag);
|
|
// 3DC Workaround: we can't load mips less than 4x4 size
|
|
if (wdt >= 4 && hgt >= 4)
|
|
memcpy(d3dlr.pBits, &src[offset], size);
|
|
hr = pID3DTexture->UnlockRect(i);
|
|
}
|
|
else
|
|
{
|
|
if (pID3DCubeTexture)
|
|
hr = pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)CubeSide, i, &pDestSurf);
|
|
else
|
|
if (pID3DTexture)
|
|
hr = pID3DTexture->GetSurfaceLevel(i, &pDestSurf);
|
|
else
|
|
assert(0);
|
|
|
|
RECT srcRect;
|
|
srcRect.left = 0;
|
|
srcRect.top = 0;
|
|
srcRect.right = wdt;
|
|
srcRect.bottom = hgt;
|
|
int nPitch;
|
|
if (!(ti->m_Flags & FT_DXT))
|
|
nPitch = size / hgt;
|
|
else
|
|
{
|
|
int blockSize = (ti->m_Flags & FT_DXT1) ? 8 : 16;
|
|
nPitch = (wdt+3)/4 * blockSize;
|
|
}
|
|
/*D3DSURFACE_DESC ddsdDescDest;
|
|
pID3DTexture->GetLevelDesc(0, &ddsdDescDest);
|
|
hr = pDestSurf->LockRect(&d3dlr, NULL, 0);
|
|
hr = pDestSurf->UnlockRect();*/
|
|
|
|
assert(pDestSurf);
|
|
hr = D3DXLoadSurfaceFromMemory(pDestSurf, NULL, NULL, &src[offset], SrcFormat, nPitch, NULL, &srcRect, D3DX_FILTER_NONE, 0);
|
|
|
|
SAFE_RELEASE(pDestSurf);
|
|
}
|
|
|
|
offset += size;
|
|
wdt >>= 1;
|
|
hgt >>= 1;
|
|
}
|
|
if (nMips > 1 && (wdt || hgt))
|
|
{
|
|
if (wdt <= 2 && hgt <= 2)
|
|
{
|
|
offset -= size;
|
|
while (wdt>0 || hgt>0)
|
|
{
|
|
if (wdt == 0)
|
|
wdt = 1;
|
|
if (hgt == 0)
|
|
hgt = 1;
|
|
if (pID3DCubeTexture)
|
|
hr = pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)CubeSide, i, &pDestSurf);
|
|
else
|
|
hr = pID3DTexture->GetSurfaceLevel(i, &pDestSurf);
|
|
RECT srcRect;
|
|
srcRect.left = 0;
|
|
srcRect.top = 0;
|
|
srcRect.right = wdt;
|
|
srcRect.bottom = hgt;
|
|
int nPitch;
|
|
if (!(ti->m_Flags & FT_DXT))
|
|
nPitch = size / hgt;
|
|
else
|
|
{
|
|
int blockSize = (ti->m_Flags & FT_DXT1) ? 8 : 16;
|
|
nPitch = (wdt+3)/4 * blockSize;
|
|
}
|
|
hr = D3DXLoadSurfaceFromMemory(pDestSurf, NULL, NULL, &src[offset], SrcFormat, nPitch, NULL, &srcRect, D3DX_FILTER_NONE, 0);
|
|
SAFE_RELEASE(pDestSurf);
|
|
i++;
|
|
|
|
wdt >>= 1;
|
|
hgt >>= 1;
|
|
}
|
|
}
|
|
assert (!wdt && !hgt);
|
|
if(wdt || hgt)
|
|
Warning(0, ti->GetName(), "CD3D9TexMan::BuildMips: Texture has no requested mips: %s", ti->GetName());
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (pID3DCubeTexture)
|
|
ti->m_RefTex.m_VidTex = pID3DCubeTexture;
|
|
else
|
|
if (pID3DVolTexture)
|
|
ti->m_RefTex.m_VidTex = pID3DVolTexture;
|
|
else
|
|
ti->m_RefTex.m_VidTex = pID3DTexture;
|
|
|
|
SAFE_DELETE_ARRAY(pTemp);
|
|
}
|
|
|
|
void CD3D9TexMan::D3DCompressTexture(int tgt, STexPicD3D *ti, int CubeSide)
|
|
{
|
|
D3DSURFACE_DESC desc;
|
|
D3DFORMAT Format;
|
|
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
|
|
int i;
|
|
|
|
LPDIRECT3DTEXTURE9 pID3DSrcTexture = NULL;
|
|
LPDIRECT3DCUBETEXTURE9 pID3DSrcCubeTexture = NULL;
|
|
LPDIRECT3DTEXTURE9 pID3DTexture = NULL;
|
|
LPDIRECT3DCUBETEXTURE9 pID3DCubeTexture = NULL;
|
|
if (tgt == TEXTGT_2D)
|
|
pID3DSrcTexture = (LPDIRECT3DTEXTURE9)ti->m_RefTex.m_VidTex;
|
|
else
|
|
{
|
|
if (CubeSide < 5)
|
|
return;
|
|
pID3DSrcCubeTexture = (LPDIRECT3DCUBETEXTURE9)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;
|
|
|
|
HRESULT h;
|
|
|
|
if (pID3DSrcTexture)
|
|
{
|
|
// Create the video texture
|
|
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, ti->m_RefTex.m_MipFilter ? D3DX_DEFAULT : 1, 0, Format, D3DPOOL_MANAGED, &pID3DTexture)))
|
|
return;
|
|
|
|
for (i=0; i<(int)pID3DSrcTexture->GetLevelCount(); i++)
|
|
{
|
|
LPDIRECT3DSURFACE9 pDestSurf;
|
|
LPDIRECT3DSURFACE9 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.m_MipFilter ? 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++)
|
|
{
|
|
LPDIRECT3DSURFACE9 pDestSurf;
|
|
LPDIRECT3DSURFACE9 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 *CD3D9TexMan::GenerateDXT_HW(STexPic *ti, EImFormat eF, byte *dst, int *numMips, int *DXTSize, bool bMips)
|
|
{
|
|
D3DFORMAT Format, srcFormat;
|
|
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
|
|
int i;
|
|
D3DLOCKED_RECT d3dlr;
|
|
|
|
srcFormat = D3DFMT_A8R8G8B8;
|
|
|
|
int wdt = ti->m_Width;
|
|
int hgt = ti->m_Height;
|
|
|
|
int Size = wdt * hgt * 4;
|
|
|
|
LPDIRECT3DTEXTURE9 pID3DSrcTexture = NULL;
|
|
LPDIRECT3DTEXTURE9 pID3DTexture = NULL;
|
|
|
|
HRESULT h;
|
|
|
|
if( FAILED( h = D3DXCreateTexture(dv, wdt, hgt, bMips ? D3DX_DEFAULT : 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSrcTexture ) ) )
|
|
return NULL;
|
|
// Lock the texture to copy the image data into the texture
|
|
h = pID3DSrcTexture->LockRect(0, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
cryMemcpy(d3dlr.pBits, dst, Size);
|
|
// Unlock the texture
|
|
pID3DSrcTexture->UnlockRect(0);
|
|
|
|
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_d3d9_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++)
|
|
{
|
|
LPDIRECT3DSURFACE9 pDestSurf;
|
|
LPDIRECT3DSURFACE9 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);
|
|
cryMemcpy(&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 *CD3D9TexMan::CopyTexture(const char *name, STexPic *tiSrc, int CubeSide)
|
|
{
|
|
STexPic *ti = TextureInfoForName(name, -1, tiSrc->m_eTT, tiSrc->m_Flags, tiSrc->m_Flags2, 0);
|
|
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
|
|
|
|
ti->m_bBusy = true;
|
|
ti->m_Flags = tiSrc->m_Flags;
|
|
ti->m_Flags2 = tiSrc->m_Flags2;
|
|
ti->m_Bind = TX_FIRSTBIND + ti->m_Id;
|
|
AddToHash(ti->m_Bind, ti);
|
|
ti->m_Width = tiSrc->m_Width;
|
|
ti->m_Height = tiSrc->m_Height;
|
|
ti->m_nMips = tiSrc->m_nMips;
|
|
ti->m_ETF = tiSrc->m_ETF;
|
|
ti->m_CubeSide = CubeSide;
|
|
ti->m_DstFormat = tiSrc->m_DstFormat;
|
|
|
|
LPDIRECT3DSURFACE9 pDestSurf;
|
|
LPDIRECT3DSURFACE9 pSrcSurf;
|
|
LPDIRECT3DCUBETEXTURE9 pID3DCubeTexture = NULL;
|
|
LPDIRECT3DTEXTURE9 pID3DTexture = NULL;
|
|
HRESULT h;
|
|
|
|
if (tiSrc->m_eTT == eTT_Cubemap)
|
|
{
|
|
pID3DCubeTexture = (LPDIRECT3DCUBETEXTURE9)tiSrc->m_RefTex.m_VidTex;
|
|
for (int i=0; i<tiSrc->m_nMips; i++)
|
|
{
|
|
h = pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)ti->m_CubeSide, i, &pDestSurf);
|
|
h = pID3DCubeTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)tiSrc->m_CubeSide, i, &pSrcSurf);
|
|
h = D3DXLoadSurfaceFromSurface(pDestSurf, NULL, NULL, pSrcSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
|
|
SAFE_RELEASE(pDestSurf);
|
|
SAFE_RELEASE(pSrcSurf);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( FAILED( h = D3DXCreateTexture(dv, ti->m_Width, ti->m_Height, tiSrc->m_nMips, 0, (D3DFORMAT)ti->m_DstFormat, D3DPOOL_MANAGED, &pID3DTexture)))
|
|
return NULL;
|
|
ti->m_RefTex.m_VidTex = (void *)pID3DTexture;
|
|
LPDIRECT3DTEXTURE9 pID3DSrcTexture = (LPDIRECT3DTEXTURE9)tiSrc->m_RefTex.m_VidTex;
|
|
for (int i=0; i<tiSrc->m_nMips; i++)
|
|
{
|
|
h = pID3DTexture->GetSurfaceLevel(i, &pDestSurf);
|
|
h = pID3DSrcTexture->GetSurfaceLevel(i, &pSrcSurf);
|
|
h = D3DXLoadSurfaceFromSurface(pDestSurf, NULL, NULL, pSrcSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
|
|
SAFE_RELEASE(pDestSurf);
|
|
SAFE_RELEASE(pSrcSurf);
|
|
}
|
|
}
|
|
return ti;
|
|
}
|
|
|
|
STexPic *CD3D9TexMan::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;
|
|
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
|
|
LPDIRECT3DTEXTURE9 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, -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 = hgt;
|
|
tp->m_Width = wdt;
|
|
tp->m_Depth = depth;
|
|
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) || ti->m_nMips == 1)
|
|
{
|
|
bMips = false;
|
|
ti->m_Flags |= FT_NOMIPS;
|
|
}
|
|
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 = ConvertRGB_Gray(dst, ti, ti->m_Flags, eTF);
|
|
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_UNKNOWN;
|
|
D3DFORMAT srcFormat = D3DFMT_X8R8G8B8;
|
|
int SizeSrc = 0;
|
|
if (eTF == eTF_8888 || eTF == eTF_RGBA)
|
|
{
|
|
srcFormat = D3DFMT_A8R8G8B8;
|
|
SizeSrc = wdt * hgt * 4;
|
|
}
|
|
else
|
|
if (eTF == eTF_0888)
|
|
{
|
|
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] = 255;
|
|
}
|
|
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] = 255;
|
|
}
|
|
}
|
|
dst = dst1;
|
|
SizeSrc = wdt * hgt * 4;
|
|
srcFormat = D3DFMT_X8R8G8B8;
|
|
eTF = eTF_8888;
|
|
}
|
|
else
|
|
if (eTF == eTF_8000)
|
|
{
|
|
SizeSrc = wdt * hgt * depth;
|
|
srcFormat = D3DFMT_A8;
|
|
format = D3DFMT_A8;
|
|
ti->m_Flags |= FT_HASALPHA;
|
|
}
|
|
else
|
|
if (eTF == eTF_0088)
|
|
{
|
|
SizeSrc = wdt * hgt * depth * 2;
|
|
srcFormat = D3DFMT_A8L8;
|
|
format = D3DFMT_A8L8;
|
|
ti->m_Flags |= FT_HASALPHA;
|
|
}
|
|
else
|
|
if (eTF == eTF_DEPTH)
|
|
{
|
|
SizeSrc = wdt * hgt * 4;
|
|
if (gcpRendD3D->mFormatDepth16.BitsPerPixel)
|
|
{
|
|
srcFormat = gcpRendD3D->mFormatDepth16.Format;
|
|
format = gcpRendD3D->mFormatDepth16.Format;
|
|
}
|
|
else
|
|
if (gcpRendD3D->mFormatDepth24.BitsPerPixel)
|
|
{
|
|
srcFormat = gcpRendD3D->mFormatDepth24.Format;
|
|
format = gcpRendD3D->mFormatDepth24.Format;
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
else
|
|
if (eTF == eTF_DXT1 || eTF == eTF_DXT3 || eTF == eTF_DXT5)
|
|
{
|
|
if (eTF == eTF_DXT1)
|
|
srcFormat = D3DFMT_DXT1;
|
|
else
|
|
if (eTF == eTF_DXT3)
|
|
srcFormat = D3DFMT_DXT3;
|
|
else
|
|
if (eTF == eTF_DXT5)
|
|
srcFormat = D3DFMT_DXT5;
|
|
}
|
|
else
|
|
if (eTF == eTF_0565 || eTF == eTF_0555)
|
|
{
|
|
srcFormat = D3DFMT_R5G6B5;
|
|
}
|
|
else
|
|
if (eTF == eTF_4444)
|
|
{
|
|
srcFormat = D3DFMT_A4R4G4B4;
|
|
format = D3DFMT_A4R4G4B4;
|
|
}
|
|
|
|
if (!(ti->m_Flags & FT_DXT) && !ti->m_pPalette)
|
|
{
|
|
if (format != D3DFMT_A8 && !(gRenDev->GetFeatures() & RFT_HWGAMMA))
|
|
{
|
|
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;
|
|
}
|
|
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
|
|
{
|
|
Warning( VALIDATOR_FLAG_TEXTURE,ti->m_SearchName.c_str(),"Unknown DXT format for texture %s", ti->m_SearchName.c_str());
|
|
format = D3DFMT_DXT1;
|
|
}
|
|
srcFormat = format;
|
|
SizeSrc = DxtOneSize;
|
|
}
|
|
if (ti->m_Flags & FT_3DC)
|
|
{
|
|
if (gcpRendD3D->m_bDeviceSupportsComprNormalmaps == 1)
|
|
{
|
|
format = (D3DFORMAT)(MAKEFOURCC('A', 'T', 'I', '2'));
|
|
srcFormat = format;
|
|
int DxtBlockSize = 16;
|
|
SizeSrc = ((ti->m_Width+3)/4)*((ti->m_Height+3)/4)*DxtBlockSize;
|
|
}
|
|
else
|
|
if (gcpRendD3D->m_bDeviceSupportsComprNormalmaps > 1)
|
|
{
|
|
if (gcpRendD3D->m_bDeviceSupportsComprNormalmaps == 2)
|
|
format = D3DFMT_V8U8;
|
|
else
|
|
if (gcpRendD3D->m_bDeviceSupportsComprNormalmaps == 3)
|
|
format = D3DFMT_CxV8U8;
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
srcFormat = format;
|
|
SizeSrc = ti->m_Width*ti->m_Height*2;
|
|
}
|
|
}
|
|
else
|
|
if (format == D3DFMT_UNKNOWN)
|
|
{
|
|
if (ti->m_Flags & FT_DYNAMIC)
|
|
{
|
|
if (ti->m_Flags & FT_HASALPHA)
|
|
format = D3DFMT_A8R8G8B8;
|
|
else
|
|
format = D3DFMT_X8R8G8B8;
|
|
}
|
|
else
|
|
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)
|
|
{
|
|
if (ti->m_Flags & FT_HASALPHA)
|
|
format = D3DFMT_A8R8G8B8;
|
|
else
|
|
format = D3DFMT_X8R8G8B8;
|
|
}
|
|
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_Q8W8V8U8;
|
|
}
|
|
else
|
|
if (ti->m_eTT == eTT_DSDTBump)
|
|
{
|
|
format = D3DFMT_X8L8V8U8;
|
|
srcFormat = D3DFMT_X8L8V8U8;
|
|
}
|
|
else
|
|
if (srcFormat == D3DFMT_R5G6B5)
|
|
format = srcFormat;
|
|
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 ((ti->m_Flags & FT_FONT))
|
|
format = D3DFMT_A8;
|
|
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;
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
// Create the src texture in system memory
|
|
#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_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;
|
|
}
|
|
else
|
|
if (ti->m_eTT == eTT_3D)
|
|
tgt = TEXTGT_3D;
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (ti->m_Flags & FT_HDR)
|
|
format = D3DFMT_A16B16G16R16F;
|
|
ti->m_RefTex.m_MipFilter = bMips ? GetMipFilter() : 0;
|
|
if (dst)
|
|
D3DCreateVideoTexture(tgt, dst, wdt, hgt, depth, srcFormat, format, ti, bMips, CubeSide, pe, DXTSize);
|
|
ti->m_RefTex.bProjected = (ti->m_Flags & FT_PROJECTED) ? true : false;
|
|
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();
|
|
if (ti->m_Flags2 & FT2_NOANISO)
|
|
ti->m_RefTex.m_AnisLevel = 1;
|
|
if (ti->m_RefTex.m_AnisLevel > 1 && ti->m_RefTex.m_MipFilter == D3DTEXF_LINEAR)
|
|
{
|
|
if (gcpRendD3D->m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
|
|
ti->m_RefTex.m_MinFilter = D3DTEXF_ANISOTROPIC;
|
|
else
|
|
ti->m_RefTex.m_MinFilter = D3DTEXF_LINEAR;
|
|
if (gcpRendD3D->m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC)
|
|
ti->m_RefTex.m_MagFilter = D3DTEXF_ANISOTROPIC;
|
|
else
|
|
ti->m_RefTex.m_MagFilter = D3DTEXF_LINEAR;
|
|
}
|
|
}
|
|
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 = GetMinFilter();
|
|
ti->m_RefTex.m_AnisLevel = gcpRendD3D->GetAnisotropicLevel();
|
|
if (ti->m_Flags2 & FT2_NOANISO)
|
|
ti->m_RefTex.m_AnisLevel = 1;
|
|
if (ti->m_RefTex.m_AnisLevel > 1 && ti->m_RefTex.m_MipFilter == D3DTEXF_LINEAR)
|
|
{
|
|
if (gcpRendD3D->m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
|
|
ti->m_RefTex.m_MinFilter = D3DTEXF_ANISOTROPIC;
|
|
else
|
|
ti->m_RefTex.m_MinFilter = D3DTEXF_LINEAR;
|
|
if (gcpRendD3D->m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC)
|
|
ti->m_RefTex.m_MagFilter = D3DTEXF_ANISOTROPIC;
|
|
else
|
|
ti->m_RefTex.m_MagFilter = D3DTEXF_LINEAR;
|
|
}
|
|
}
|
|
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;
|
|
//m_CurCubeFaces[i]->SaveJPG("Cube.jpg", false);
|
|
}
|
|
else
|
|
m_CurCubeFaces[i]->m_RefTex.m_VidTex = NULL;
|
|
}
|
|
}
|
|
|
|
} // if (!gIsDedicated)
|
|
} // if (dst)
|
|
|
|
CD3D9TexMan::CalcMipsAndSize(ti);
|
|
|
|
if (ti->m_Flags & FT_NOMIPS)
|
|
ti->m_nMips = 1;
|
|
if (ti->m_eTT == eTT_Cubemap)
|
|
{
|
|
ti->m_Size *= 6;
|
|
if (CubeSide == 0)
|
|
m_FirstCMSide = ti;
|
|
else
|
|
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)
|
|
{
|
|
gRenDev->m_TexMan->m_StatsCurTexMem += ti->m_Size;
|
|
ti->Unlink();
|
|
ti->Link(&STexPic::m_Root);
|
|
//sTestStr.AddElem(ti);
|
|
}
|
|
CheckTexLimits(NULL);
|
|
|
|
if (ti->m_eTT != eTT_Cubemap || ti->m_CubeSide == 5)
|
|
{
|
|
if (m_Streamed == 1)
|
|
{
|
|
if (ti->m_eTT != eTT_Cubemap)
|
|
ti->Unload();
|
|
else
|
|
m_FirstCMSide->Unload();
|
|
}
|
|
}
|
|
|
|
if (dst1)
|
|
delete [] dst1;
|
|
|
|
return ti;
|
|
}
|
|
|
|
//============================================================================
|
|
|
|
void CD3D9TexMan::BuildMipsSub(byte* src, int wdt, int hgt)
|
|
{
|
|
}
|
|
|
|
void CD3D9TexMan::UpdateTextureRegion(STexPic *pic, byte *data, int X, int Y, int USize, int VSize)
|
|
{
|
|
STexPicD3D *ti = (STexPicD3D *)pic;
|
|
LPDIRECT3DTEXTURE9 pID3DTexture = NULL;
|
|
LPDIRECT3DCUBETEXTURE9 pID3DCubeTexture = NULL;
|
|
int CubeSide = ti->m_CubeSide;
|
|
HRESULT h;
|
|
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
|
|
LPDIRECT3DSURFACE9 pDestSurf;
|
|
if (ti->m_RefTex.m_Type == TEXTGT_2D)
|
|
{
|
|
pID3DTexture = (LPDIRECT3DTEXTURE9)ti->m_RefTex.m_VidTex;
|
|
assert(pID3DTexture);
|
|
}
|
|
else
|
|
{
|
|
pID3DCubeTexture = (LPDIRECT3DCUBETEXTURE9)ti->m_RefTex.m_VidTex;
|
|
assert(pID3DCubeTexture);
|
|
}
|
|
RECT rc;
|
|
rc.left = X;
|
|
rc.right = X + USize;
|
|
rc.top = Y;
|
|
rc.bottom = Y + VSize;
|
|
RECT rcs;
|
|
rcs.left = 0;
|
|
rcs.right = USize;
|
|
rcs.top = 0;
|
|
rcs.bottom = VSize;
|
|
h = pID3DTexture->GetSurfaceLevel(0, &pDestSurf);
|
|
h = D3DXLoadSurfaceFromMemory(pDestSurf, NULL, &rc, data, D3DFMT_A8R8G8B8, USize*4, NULL, &rcs, D3DX_FILTER_NONE, 0);
|
|
SAFE_RELEASE(pDestSurf);
|
|
}
|
|
|
|
void CD3D9TexMan::UpdateTextureData(STexPic *pic, byte *data, int USize, int VSize, bool bProc, int State, bool bPal)
|
|
{
|
|
STexPicD3D *ti = (STexPicD3D *)pic;
|
|
LPDIRECT3DTEXTURE9 pID3DTexture = NULL;
|
|
LPDIRECT3DCUBETEXTURE9 pID3DCubeTexture = NULL;
|
|
int CubeSide = ti->m_CubeSide;
|
|
HRESULT h;
|
|
D3DLOCKED_RECT d3dlr;
|
|
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
|
|
D3DSURFACE_DESC ddsdDescDest;
|
|
if (ti->m_RefTex.m_Type == TEXTGT_2D)
|
|
{
|
|
pID3DTexture = (LPDIRECT3DTEXTURE9)ti->m_RefTex.m_VidTex;
|
|
assert(pID3DTexture);
|
|
}
|
|
else
|
|
{
|
|
pID3DCubeTexture = (LPDIRECT3DCUBETEXTURE9)ti->m_RefTex.m_VidTex;
|
|
assert(pID3DCubeTexture);
|
|
}
|
|
if (bPal)
|
|
{
|
|
bool bMips;
|
|
if (CD3D9Renderer::CV_d3d9_mipprocedures && !(pic->m_Flags & FT_NOMIPS))
|
|
bMips = true;
|
|
else
|
|
bMips = false;
|
|
if (!ti->m_RefTex.m_MipFilter)
|
|
bMips = false;
|
|
ti->m_RefTex.m_MipFilter = bMips ? m_MipFilter : 0;
|
|
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
|
|
cryMemcpy((byte *)d3dlr.pBits, data, ddsdDescDest.Width*ddsdDescDest.Height);
|
|
// 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 (CD3D9Renderer::CV_d3d9_mipprocedures && !(pic->m_Flags & FT_NOMIPS))
|
|
bMips = true;
|
|
else
|
|
bMips = false;
|
|
if (!ti->m_RefTex.m_MipFilter)
|
|
bMips = false;
|
|
ti->m_RefTex.m_MipFilter = bMips ? m_MipFilter : 0;
|
|
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
|
|
cryMemcpy((byte *)d3dlr.pBits, data, ddsdDescDest.Width*ddsdDescDest.Height*4);
|
|
// 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)
|
|
{
|
|
}
|
|
|
|
void CD3D9TexMan::ClearBuffer(int Width, int Height, bool bEnd, STexPic *pImage, int Side)
|
|
{
|
|
gcpRendD3D->EF_ClearBuffers(true, true, NULL);
|
|
}
|
|
|
|
//===================================================================================
|
|
|
|
void CD3D9TexMan::DrawCubeSide( const float *angle, Vec3d& Pos, int tex_size, int side, int RendFlags, float fMaxDist)
|
|
{
|
|
if (!iSystem)
|
|
return;
|
|
|
|
CRenderer * renderer = gRenDev;
|
|
CCamera tmp_camera = renderer->GetCamera();
|
|
CCamera prevCamera = tmp_camera;
|
|
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
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();
|
|
gRenDev->m_RP.m_PersFlags |= RBPF_DRAWMIRROR;
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
|
|
iSystem->SetViewCamera(tmp_camera);
|
|
gRenDev->SetCamera(tmp_camera);
|
|
|
|
gRenDev->SetViewport(0, 0, tex_size, tex_size);
|
|
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. DrawLowDetail .. (DrawCubeSide %d)\n", side);
|
|
#endif
|
|
|
|
//RendFlags &= ~DLD_TERRAIN_FULLRES;
|
|
eng->DrawLowDetail(RendFlags);
|
|
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. End DrawLowDetail .. (DrawCubeSide %d)\n", side);
|
|
#endif
|
|
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
gRenDev->m_RP.m_PersFlags &= ~RBPF_DRAWMIRROR;
|
|
iSystem->SetViewCamera(prevCamera);
|
|
gRenDev->SetCamera(prevCamera);
|
|
}
|
|
|
|
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
|
|
};
|
|
|
|
bool CD3D9TexMan::ScanEnvironmentCM (const char *name, int size, Vec3d& Pos)
|
|
{
|
|
char szName[256];
|
|
|
|
int RendFlags = -1;
|
|
RendFlags &= ~DLD_ENTITIES;
|
|
int vX, vY, vWidth, vHeight;
|
|
gRenDev->GetViewport(&vX, &vY, &vWidth, &vHeight);
|
|
StripExtension(name, szName);
|
|
//gRenDev->EF_SaveDLights();
|
|
|
|
bool bBegin = false;
|
|
if (!gcpRendD3D->m_SceneRecurseCount)
|
|
{
|
|
gcpRendD3D->m_nFrameID++;
|
|
gcpRendD3D->m_pd3dDevice->BeginScene();
|
|
bBegin = true;
|
|
}
|
|
gcpRendD3D->m_SceneRecurseCount++;
|
|
|
|
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
|
|
LPDIRECT3DCUBETEXTURE9 pID3DTexture = NULL;
|
|
LPDIRECT3DSURFACE9 pSrcSurf;
|
|
LPDIRECT3DTEXTURE9 pID3DSysTexture;
|
|
LPDIRECT3DSURFACE9 pSysSurf;
|
|
D3DLOCKED_RECT d3dlrSys;
|
|
HRESULT h;
|
|
|
|
if( FAILED( h = D3DXCreateCubeTexture(dv, size, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pID3DTexture )))
|
|
return false;
|
|
|
|
if( FAILED( h = D3DXCreateTexture(dv, size, size, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSysTexture )))
|
|
return false;
|
|
h = pID3DSysTexture->GetSurfaceLevel(0, &pSysSurf);
|
|
|
|
int *pFR = (int *)gRenDev->EF_Query(EFQ_Pointer2FrameID);
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
for(int n=0; n<6; n++)
|
|
{
|
|
(*pFR)++;
|
|
|
|
h = pID3DTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)n, 0, &pSrcSurf);
|
|
gcpRendD3D->EF_SetRenderTarget(pSrcSurf, true);
|
|
|
|
D3DCOLOR cColor = D3DRGBA(0.0f,0.0f,0.0f,0.0f);
|
|
// render object
|
|
dv->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
|
|
|
|
DrawCubeSide( &sAngles[n][0], Pos, size, n, RendFlags, fMaxDist);
|
|
SAFE_RELEASE(pSrcSurf);
|
|
gcpRendD3D->EF_RestoreRenderTarget();
|
|
h = pID3DTexture->GetCubeMapSurface((D3DCUBEMAP_FACES)n, 0, &pSrcSurf);
|
|
static char* cubefaces[6] = {"posx","negx","posy","negy","posz","negz"};
|
|
char str[256];
|
|
int width = size;
|
|
int height = size;
|
|
h = dv->GetRenderTargetData(pSrcSurf, pSysSurf);
|
|
h = pID3DSysTexture->LockRect(0, &d3dlrSys, NULL, 0);
|
|
byte *pic = new byte [size*size*4];
|
|
byte *src = (byte *)d3dlrSys.pBits;
|
|
for (int i=0; i<size; i++)
|
|
{
|
|
for (int j=0; j<size; j++)
|
|
{
|
|
*(uint *)&pic[i*size*4+j*4] = *(uint *)&src[j*4];
|
|
Exchange(pic[i*size*4+j*4], pic[i*size*4+j*4+2]);
|
|
}
|
|
src += d3dlrSys.Pitch;
|
|
}
|
|
h = pID3DSysTexture->UnlockRect(0);
|
|
sprintf(str, "%s_%s.jpg", szName, cubefaces[n]);
|
|
WriteJPG(pic, size, size, str);
|
|
delete [] pic;
|
|
|
|
SAFE_RELEASE(pSrcSurf);
|
|
}
|
|
gcpRendD3D->EF_RestoreRenderTarget();
|
|
gRenDev->SetViewport(vX, vY, vWidth, vHeight);
|
|
//gRenDev->EF_RestoreDLights();
|
|
|
|
SAFE_RELEASE(pSysSurf);
|
|
SAFE_RELEASE(pID3DSysTexture);
|
|
SAFE_RELEASE(pID3DTexture);
|
|
|
|
if (bBegin)
|
|
{
|
|
gcpRendD3D->m_SceneRecurseCount--;
|
|
if (!gcpRendD3D->m_SceneRecurseCount)
|
|
gcpRendD3D->m_pd3dDevice->EndScene();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CD3D9TexMan::GetAverageColor(SEnvTexture *cm, int nSide)
|
|
{
|
|
assert (nSide>=0 && nSide<=5);
|
|
|
|
if (!cm->m_RenderTargets[nSide])
|
|
return;
|
|
|
|
int i, j;
|
|
HRESULT hr;
|
|
LPDIRECT3DSURFACE9 pTargSurf = (LPDIRECT3DSURFACE9)cm->m_RenderTargets[nSide];
|
|
D3DLOCKED_RECT d3dlr;
|
|
hr = pTargSurf->LockRect(&d3dlr, NULL, D3DLOCK_READONLY);
|
|
|
|
CFColor Col;
|
|
int r = 0;
|
|
int g = 0;
|
|
int b = 0;
|
|
int a = 0;
|
|
byte *pData = (byte *)d3dlr.pBits;
|
|
for (i=0; i<cm->m_TexSize; i++)
|
|
{
|
|
byte *pSrc = &pData[d3dlr.Pitch*i];
|
|
for (j=0; j<cm->m_TexSize; j++)
|
|
{
|
|
b += pSrc[0];
|
|
g += pSrc[1];
|
|
r += pSrc[2];
|
|
a += pSrc[3];
|
|
|
|
pSrc += 4;
|
|
}
|
|
}
|
|
pTargSurf->UnlockRect();
|
|
int size = cm->m_TexSize * cm->m_TexSize;
|
|
cm->m_nFrameCreated[nSide] = -1;
|
|
cm->m_EnvColors[nSide].bcolor[0] = r / size;
|
|
cm->m_EnvColors[nSide].bcolor[1] = g / size;
|
|
cm->m_EnvColors[nSide].bcolor[2] = b / size;
|
|
cm->m_EnvColors[nSide].bcolor[3] = a / size;
|
|
}
|
|
|
|
void CD3D9TexMan::ScanEnvironmentCube(SEnvTexture *cm, int RendFlags, int Size, bool bLightCube)
|
|
{
|
|
int i;
|
|
|
|
if (cm->m_bInprogress)
|
|
return;
|
|
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
int tex_size = Size;
|
|
int nSizeTemp = 0;
|
|
HRESULT hr;
|
|
if (tex_size > 0)
|
|
{
|
|
int nlogSize = ilog2(tex_size);
|
|
if (nlogSize != tex_size)
|
|
tex_size = nlogSize;
|
|
nSizeTemp = tex_size*2;
|
|
if(nSizeTemp < 16)
|
|
nSizeTemp = 16;
|
|
if (!cm->m_RenderTargets[0] || cm->m_nFrameReset != r->m_nFrameReset || cm->m_TexSize != tex_size)
|
|
{
|
|
cm->m_nFrameReset = r->m_nFrameReset;
|
|
cm->m_TexSize = tex_size;
|
|
for (i=0; i<6; i++)
|
|
{
|
|
IDirect3DSurface9* pSurface;
|
|
hr = r->mfGetD3DDevice()->CreateRenderTarget(tex_size,tex_size, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pSurface, NULL);
|
|
if (!FAILED(hr))
|
|
{
|
|
cm->m_RenderTargets[i] = pSurface;
|
|
cm->m_Tex->m_Flags |= FT_ALLOCATED;
|
|
}
|
|
}
|
|
}
|
|
if (!cm->m_TexTemp || cm->m_TexTemp->GetWidth() != nSizeTemp)
|
|
{
|
|
if (cm->m_TexTemp)
|
|
cm->m_TexTemp->Release(false);
|
|
char name[128];
|
|
sprintf(name, "$TempLCMap%d", cm->m_Id);
|
|
byte *data = new byte [nSizeTemp*nSizeTemp*4];
|
|
cm->m_TexTemp = gRenDev->m_TexMan->CreateTexture(name, nSizeTemp, nSizeTemp, 1, FT_NOMIPS, FT2_NODXT | FT2_RENDERTARGET, data, eTT_Base, -1.0f, -1.0f, 0, NULL);
|
|
delete [] data;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (tex_size <= 0)
|
|
{
|
|
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>r->GetWidth() || tex_size>r->GetHeight())
|
|
tex_size >>= 1;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
|
|
int n;
|
|
Vec3d cur_pos;
|
|
|
|
cm->m_bInprogress = true;
|
|
int tid;
|
|
if (bLightCube)
|
|
tid = TO_ENVIRONMENT_LIGHTCUBE_MAP_REAL + cm->m_Id;
|
|
else
|
|
tid = TO_ENVIRONMENT_CUBE_MAP_REAL + cm->m_Id;
|
|
if (!cm->m_RenderTargets[0])
|
|
{
|
|
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;
|
|
if (!cm->m_TexTemp)
|
|
cm->m_Tex->m_Flags2 |= FT2_RENDERTARGET;
|
|
else
|
|
cm->m_Tex->m_Flags |= FT_DYNAMIC;
|
|
cm->m_Tex->m_nMips = 0;
|
|
cm->m_Tex->m_Width = tex_size;
|
|
cm->m_Tex->m_Height = 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, cm->m_Tex->m_Flags2, data, eTT_Cubemap, -1.0f, -1.0f, 0, cm->m_Tex);
|
|
SetTexture(0, eTT_Cubemap);
|
|
delete [] data;
|
|
}
|
|
}
|
|
cm->m_TexSize = tex_size;
|
|
|
|
STexPicD3D *tp = (STexPicD3D *)cm->m_Tex;
|
|
STexPicD3D *tpTemp = (STexPicD3D *)cm->m_TexTemp;
|
|
LPDIRECT3DCUBETEXTURE9 pID3DTargetTextureCM = NULL;
|
|
LPDIRECT3DTEXTURE9 pID3DTargetTexture = NULL;
|
|
if (tpTemp)
|
|
pID3DTargetTexture = (LPDIRECT3DTEXTURE9)tpTemp->m_RefTex.m_VidTex;
|
|
if (tp)
|
|
pID3DTargetTextureCM = (LPDIRECT3DCUBETEXTURE9)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;
|
|
}
|
|
//Start = 0;
|
|
//End = 6;
|
|
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;
|
|
// assert(cm->m_Id == 0);
|
|
|
|
HRESULT h;
|
|
int *pFR = (int *)gRenDev->EF_Query(EFQ_Pointer2FrameID);
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
if (bLightCube)
|
|
fMaxDist *= 0.25f;
|
|
for(n=Start; n<End; n++)
|
|
{
|
|
(*pFR)++;
|
|
LPDIRECT3DSURFACE9 pTargSurf, pSrcSurf;
|
|
if (pID3DTargetTexture)
|
|
{
|
|
// Get average texture color before drawing to it
|
|
if (cm->m_nFrameCreated[n]>0)
|
|
{
|
|
cm->m_nFrameCreated[n] = -1;
|
|
gRenDev->m_TexMan->GetAverageColor(cm, n);
|
|
}
|
|
h = pID3DTargetTexture->GetSurfaceLevel(0, &pTargSurf);
|
|
}
|
|
else
|
|
if (pID3DTargetTextureCM)
|
|
h = pID3DTargetTextureCM->GetCubeMapSurface((D3DCUBEMAP_FACES)n, 0, &pTargSurf);
|
|
h = r->EF_SetRenderTarget(pTargSurf, true);
|
|
|
|
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);
|
|
if (pID3DTargetTexture)
|
|
DrawCubeSide( &sAngles[n][0], Pos, nSizeTemp, n, RendFlags, fMaxDist);
|
|
else
|
|
if (pID3DTargetTextureCM)
|
|
DrawCubeSide( &sAngles[n][0], Pos, tex_size, n, RendFlags, fMaxDist);
|
|
SAFE_RELEASE(pTargSurf);
|
|
|
|
// Post process (bluring)
|
|
if (pID3DTargetTexture && tpTemp)
|
|
{
|
|
/*{
|
|
int width = nSizeTemp;
|
|
int height = nSizeTemp;
|
|
byte *pic = new byte [width * height * 4];
|
|
LPDIRECT3DSURFACE9 pSysSurf, pTargetSurf;
|
|
LPDIRECT3DTEXTURE9 pID3DSysTexture;
|
|
D3DLOCKED_RECT d3dlrSys;
|
|
h = pID3DTargetTexture->GetSurfaceLevel(0, &pTargetSurf);
|
|
h = D3DXCreateTexture(r->m_pd3dDevice, nSizeTemp, nSizeTemp, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSysTexture );
|
|
h = pID3DSysTexture->GetSurfaceLevel(0, &pSysSurf);
|
|
h = r->m_pd3dDevice->GetRenderTargetData(pTargetSurf, pSysSurf);
|
|
h = pID3DSysTexture->LockRect(0, &d3dlrSys, NULL, 0);
|
|
byte *src = (byte *)d3dlrSys.pBits;
|
|
for (int i=0; i<width*height; i++)
|
|
{
|
|
*(uint *)&pic[i*4] = *(uint *)&src[i*4];
|
|
Exchange(pic[i*4+0], pic[i*4+2]);
|
|
}
|
|
h = pID3DSysTexture->UnlockRect(0);
|
|
WriteJPG(pic, width, height, "Cube1.jpg");
|
|
delete [] pic;
|
|
SAFE_RELEASE (pTargetSurf);
|
|
SAFE_RELEASE (pSysSurf);
|
|
SAFE_RELEASE (pID3DSysTexture);
|
|
}*/
|
|
cm->m_nFrameCreated[n] = r->GetFrameID();
|
|
assert(cm->m_RenderTargets[n]);
|
|
pSrcSurf = (LPDIRECT3DSURFACE9)cm->m_RenderTargets[n];
|
|
h = r->EF_SetRenderTarget(pSrcSurf, true);
|
|
r->SetViewport(0, 0, tex_size, tex_size);
|
|
//r->Set2DMode(true,tex_size,tex_size);
|
|
r->SetState(GS_NODEPTHTEST);
|
|
r->SetColorOp(eCO_MODULATE,eCO_MODULATE,DEF_TEXARG0,DEF_TEXARG0);
|
|
|
|
// Now blur the texture
|
|
CREScreenProcess *sp = gRenDev->m_pREScreenProcess;
|
|
CScreenVars *pVars = gRenDev->m_pREScreenProcess->GetVars();
|
|
|
|
// set current vertex/fragment program
|
|
// get vertex/fragment program
|
|
/*CCGVProgram_D3D *vpBlur=(CCGVProgram_D3D *) pVars->m_pVPBlur;
|
|
CCGPShader_D3D *fpBlur=(CCGPShader_D3D *) pVars->m_pRCBlur;
|
|
vpBlur->mfSet(true, 0);
|
|
fpBlur->mfSet(true, 0);
|
|
// setup texture offsets, for texture neighboors sampling
|
|
float s1=1.0f/(float) tex_size;
|
|
float t1=1.0f/(float) tex_size;
|
|
s1 *= 2;
|
|
t1 *= 2;
|
|
float pfOffset0[]={ s1*0.5f, t1, 0.0f, 0.0f};
|
|
float pfOffset1[]={ -s1, t1*0.5f, 0.0f, 0.0f};
|
|
float pfOffset2[]={ -s1*0.5f, -t1, 0.0f, 0.0f};
|
|
float pfOffset3[]={ s1, -t1*0.5f, 0.0f, 0.0f}; */
|
|
r->SelectTMU(0);
|
|
tpTemp->Set();
|
|
/*r->SelectTMU(1);
|
|
tpTemp->Set();
|
|
r->SelectTMU(2);
|
|
tpTemp->Set();
|
|
r->SelectTMU(3);
|
|
tpTemp->Set();
|
|
r->SelectTMU(0);
|
|
vpBlur->mfParameter4f("Offset0", pfOffset0);
|
|
vpBlur->mfParameter4f("Offset1", pfOffset1);
|
|
vpBlur->mfParameter4f("Offset2", pfOffset2);
|
|
vpBlur->mfParameter4f("Offset3", pfOffset3);
|
|
float s_off=s1*0.5f;
|
|
float t_off=t1*0.5f;
|
|
|
|
// setup screen aligned quad
|
|
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F pScreenBlur[] =
|
|
{
|
|
0,0,-1, 255,255,255,255, s_off, t_off,
|
|
0,tex_size,-1, 255,255,255,255, s_off, 1+t_off,
|
|
tex_size,0,-1, 255,255,255,255, 1+s_off, t_off,
|
|
tex_size,tex_size,-1, 255,255,255,255, 1+s_off, 1+t_off,
|
|
};*/
|
|
int iBlurAmount = 1;
|
|
for(int iBlurPasses=1; iBlurPasses<=iBlurAmount; iBlurPasses++)
|
|
{
|
|
// set texture coordinates scale (needed for rectangular textures in gl ..)
|
|
//float pfScale[]={ 1.0f, 1.0f, 1.0f, (float) iBlurPasses};
|
|
//vpBlur->mfParameter4f("vTexCoordScale", pfScale);
|
|
|
|
// set current rendertarget
|
|
//pRenderer->m_pd3dDevice->SetRenderTarget( 0, pTexSurf);
|
|
// render screen aligned quad...
|
|
r->DrawQuad(0,0,(float)tex_size,(float)tex_size,Col_White,1);
|
|
//gRenDev->DrawTriStrip(&(CVertexBuffer (pScreenBlur,VERTEX_FORMAT_P3F_COL4UB_TEX2F)), 4);
|
|
}
|
|
//vpBlur->mfSet(false, 0);
|
|
//fpBlur->mfSet(false, 0);
|
|
//r->SelectTMU(3);
|
|
//r->EnableTMU(false);
|
|
//r->SelectTMU(2);
|
|
//r->EnableTMU(false);
|
|
//r->SelectTMU(1);
|
|
//r->EnableTMU(false);
|
|
//r->SelectTMU(0);
|
|
//SAFE_RELEASE(pSrcSurf);
|
|
//r->Set2DMode(false,1,1);
|
|
}
|
|
}
|
|
r->EF_RestoreRenderTarget();
|
|
|
|
if (CRenderer::CV_r_envcmwrite)
|
|
{
|
|
for(n=Start; n<End; n++)
|
|
{
|
|
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];
|
|
LPDIRECT3DSURFACE9 pSysSurf, pTargetSurf;
|
|
LPDIRECT3DTEXTURE9 pID3DSysTexture;
|
|
D3DLOCKED_RECT d3dlrSys;
|
|
if (!pID3DTargetTextureCM)
|
|
pTargetSurf = (LPDIRECT3DSURFACE9)cm->m_RenderTargets[n];
|
|
else
|
|
h = pID3DTargetTextureCM->GetCubeMapSurface((D3DCUBEMAP_FACES)n, 0, &pTargetSurf);
|
|
h = D3DXCreateTexture(r->m_pd3dDevice, tex_size, tex_size, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSysTexture );
|
|
h = pID3DSysTexture->GetSurfaceLevel(0, &pSysSurf);
|
|
if (pID3DTargetTexture)
|
|
h = D3DXLoadSurfaceFromSurface(pSysSurf, NULL, NULL, pTargetSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
|
|
else
|
|
h = r->m_pd3dDevice->GetRenderTargetData(pTargetSurf, pSysSurf);
|
|
h = pID3DSysTexture->LockRect(0, &d3dlrSys, NULL, 0);
|
|
byte *src = (byte *)d3dlrSys.pBits;
|
|
for (int i=0; i<width*height; i++)
|
|
{
|
|
*(uint *)&pic[i*4] = *(uint *)&src[i*4];
|
|
Exchange(pic[i*4+0], pic[i*4+2]);
|
|
}
|
|
h = pID3DSysTexture->UnlockRect(0);
|
|
sprintf(str, "Cube_%s.jpg", cubefaces[n]);
|
|
WriteJPG(pic, width, height, str);
|
|
delete [] pic;
|
|
if (pID3DTargetTextureCM)
|
|
SAFE_RELEASE (pTargetSurf);
|
|
SAFE_RELEASE (pSysSurf);
|
|
SAFE_RELEASE (pID3DSysTexture);
|
|
}
|
|
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();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
static Matrix44 sMatrixLookAt( const Vec3d &dir,const Vec3d &up,float rollAngle=0 )
|
|
{
|
|
Matrix44 M;
|
|
// LookAt transform.
|
|
Vec3d xAxis,yAxis,zAxis;
|
|
Vec3d upVector = up;
|
|
|
|
yAxis = GetNormalized(-dir);
|
|
|
|
//if (zAxis.x == 0.0 && zAxis.z == 0) up.Set( -zAxis.y,0,0 ); else up.Set( 0,1.0f,0 );
|
|
|
|
xAxis = GetNormalized((upVector.Cross(yAxis)));
|
|
zAxis = GetNormalized((xAxis.Cross(yAxis)));
|
|
|
|
// OpenGL kind of matrix.
|
|
M[0][0] = xAxis.x;
|
|
M[1][0] = yAxis.x;
|
|
M[2][0] = zAxis.x;
|
|
M[3][0] = 0;
|
|
|
|
M[0][1] = xAxis.y;
|
|
M[1][1] = yAxis.y;
|
|
M[2][1] = zAxis.y;
|
|
M[3][1] = 0;
|
|
|
|
M[0][2] = xAxis.z;
|
|
M[1][2] = yAxis.z;
|
|
M[2][2] = zAxis.z;
|
|
M[3][2] = 0;
|
|
|
|
M[0][3] = 0;
|
|
M[1][3] = 0;
|
|
M[2][3] = 0;
|
|
M[3][3] = 1;
|
|
|
|
if (rollAngle != 0)
|
|
{
|
|
Matrix44 RollMtx;
|
|
RollMtx.SetIdentity();
|
|
|
|
float cossin[2];
|
|
cry_sincosf(rollAngle*gf_DEGTORAD, cossin);
|
|
|
|
RollMtx[0][0] = cossin[0]; RollMtx[2][0] = -cossin[1];
|
|
RollMtx[0][2] = cossin[1]; RollMtx[2][2] = cossin[0];
|
|
|
|
// Matrix multiply.
|
|
M = RollMtx * M;
|
|
}
|
|
|
|
return M;
|
|
}
|
|
|
|
void CD3D9TexMan::ScanEnvironmentTexture(SEnvTexture *cm, SShader *pSH, SRenderShaderResources *pRes, int RendFlags, bool bUseExistingREs)
|
|
{
|
|
static 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 (cm->m_bInprogress)
|
|
return;
|
|
|
|
// increase frame id to support multiple reflections
|
|
gcpRendD3D->m_nFrameID++;
|
|
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
bool bUseClipPlanes = false;
|
|
bool bUseReflection = false;
|
|
if (pSH)
|
|
{
|
|
if (pSH->m_Flags3 & (EF3_CLIPPLANE_BACK | EF3_CLIPPLANE_FRONT))
|
|
bUseClipPlanes = true;
|
|
if (bUseClipPlanes || (pSH->m_Flags3 & EF3_REFLECTION))
|
|
bUseReflection = true;
|
|
}
|
|
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
float fMinDist = 0.25f;
|
|
|
|
ECull eCull = eCULL_None;
|
|
if (pSH)
|
|
eCull = pSH->m_eCull;
|
|
if (pRes && (pRes->m_ResFlags & MTLFLAG_2SIDED))
|
|
eCull = eCULL_None;
|
|
|
|
bool bWater = (pSH && ((pSH->m_nPreprocess & FSPR_SCANTEXWATER) != 0));
|
|
Plane Pl, PlTr;
|
|
float plane[4];
|
|
CCObject *obj = gRenDev->m_RP.m_pCurObject;
|
|
if (bUseClipPlanes || bUseReflection)
|
|
{
|
|
if (!bWater)
|
|
r->m_RP.m_pRE->mfGetPlane(Pl);
|
|
else
|
|
{
|
|
Pl.n = Vec3d(0,0,1);
|
|
Pl.d = eng->GetWaterLevel();
|
|
}
|
|
if (r->m_RP.m_pCurObject)
|
|
{
|
|
r->m_RP.m_FrameObject++;
|
|
PlTr = TransformPlane(obj->GetMatrix(), Pl);
|
|
}
|
|
else
|
|
PlTr = Pl;
|
|
if (pSH->m_Flags3 & EF3_CLIPPLANE_BACK)
|
|
{
|
|
PlTr.n = -PlTr.n;
|
|
PlTr.d = -PlTr.d;
|
|
}
|
|
if (eCull != eCULL_None)
|
|
{
|
|
CCamera tmp_camera = r->GetCamera();
|
|
Vec3d pos = tmp_camera.GetPos();
|
|
float dot = pos.Dot(PlTr.n) - PlTr.d;
|
|
if (dot <= 0.1f)
|
|
return;
|
|
}
|
|
plane[0] = PlTr.n[0];
|
|
plane[1] = PlTr.n[1];
|
|
plane[2] = PlTr.n[2];
|
|
plane[3] = -PlTr.d;
|
|
|
|
if (!bWater)
|
|
fMinDist = r->m_RP.m_pRE->mfMinDistanceToCamera(obj);
|
|
// fMinDist = 0.25f;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
Vec3d cur_pos;
|
|
|
|
int nHDRFl = (r->m_RP.m_PersFlags & RBPF_HDR) ? FT_HDR : 0;
|
|
|
|
cm->m_Tex->m_Flags |= FT_BUILD;
|
|
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_HDR) != nHDRFl)
|
|
{
|
|
cm->m_Tex->m_Flags |= nHDRFl;
|
|
cm->m_Tex->m_Flags |= FT_ALLOCATED | FT_NOMIPS | FT_CLAMP;
|
|
cm->m_Tex->m_Flags &= ~FT_DXT;
|
|
cm->m_Tex->m_Flags2 |= FT2_NODXT | FT2_RENDERTARGET;
|
|
AddToHash(cm->m_Tex->m_Bind, cm->m_Tex);
|
|
cm->m_TexSize = tex_size;
|
|
cm->m_Tex->m_Width = cm->m_Tex->m_Height = tex_size;
|
|
cm->m_Tex->m_nMips = 0;
|
|
byte *data = new byte [tex_size*tex_size*4];
|
|
r->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, cm->m_Tex);
|
|
delete [] data;
|
|
}
|
|
|
|
STexPicD3D *tp = (STexPicD3D *)cm->m_Tex;
|
|
if (!tp->m_RefTex.m_VidTex)
|
|
return;
|
|
|
|
LPDIRECT3DTEXTURE9 pID3DTargetTexture = (LPDIRECT3DTEXTURE9)tp->m_RefTex.m_VidTex;
|
|
LPDIRECT3DSURFACE9 pSrcSurf;
|
|
HRESULT h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
|
|
r->EF_SetRenderTarget(pSrcSurf, true);
|
|
|
|
DWORD cColor = D3DRGBA(gRenDev->m_vClearColor[0], gRenDev->m_vClearColor[1], gRenDev->m_vClearColor[2], 0);
|
|
if (r->m_sbpp)
|
|
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, cColor, 1.0f, 0);
|
|
else
|
|
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
|
|
|
|
int vX, vY, vWidth, vHeight;
|
|
r->GetViewport(&vX, &vY, &vWidth, &vHeight);
|
|
r->EF_PushFog();
|
|
//r->EF_SaveDLights();
|
|
r->m_RP.m_bDrawToTexture = true;
|
|
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
int prevFlags = gRenDev->m_RP.m_PersFlags;
|
|
|
|
{
|
|
CCamera tmp_camera = r->GetCamera();
|
|
CCamera prevCamera = tmp_camera;
|
|
|
|
// camera reflection by plane
|
|
if ((pSH && (pSH->m_Flags3 & EF3_CLIPPLANE_FRONT)) || bUseReflection)
|
|
{
|
|
// mirror case
|
|
Vec3d vPrevPos = tmp_camera.GetPos();
|
|
Matrix44 camMat = tmp_camera.GetVCMatrixD3D9();
|
|
Vec3d vPrevDir = Vec3d(-camMat(0,2), -camMat(1,2), -camMat(2,2));
|
|
Vec3d vPrevUp = Vec3d(camMat(0,1), camMat(1,1), camMat(2,1));
|
|
Vec3d vNewDir = PlTr.MirrorVector(vPrevDir);
|
|
Vec3d vNewUp = PlTr.MirrorVector(vPrevUp);
|
|
Matrix44 m = sMatrixLookAt( vNewDir, vNewUp, tmp_camera.GetAngles()[1] );
|
|
|
|
float fDot = vPrevPos.Dot(PlTr.n) - PlTr.d;
|
|
Vec3d vNewPos = vPrevPos - PlTr.n * 2.0f*fDot;
|
|
Vec3d vNewOccPos;// = vPrevPos - PlTr.n * 0.99f*fDot;
|
|
gRenDev->m_RP.m_pRE->mfCenter(vNewOccPos, gRenDev->m_RP.m_pCurObject);
|
|
if (fDot < 0)
|
|
{
|
|
plane[0] = -plane[0];
|
|
plane[1] = -plane[1];
|
|
plane[2] = -plane[2];
|
|
plane[3] = -plane[3];
|
|
}
|
|
|
|
//QUAT_CHANGED_BY_IVO
|
|
// CryQuat q(m);
|
|
CryQuat q = Quat( GetTransposed44(m) );
|
|
|
|
Vec3d vNewAngs = Ang3::GetAnglesXYZ(Matrix33(q));
|
|
vNewAngs = RAD2DEG(vNewAngs);
|
|
|
|
tmp_camera.SetAngle(vNewAngs);
|
|
tmp_camera.SetPos(vNewPos);
|
|
tmp_camera.SetOccPos(vNewOccPos);
|
|
tmp_camera.Init(tex_size, tex_size, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
|
|
tmp_camera.Update();
|
|
|
|
iSystem->SetViewCamera(tmp_camera);
|
|
gRenDev->SetCamera(tmp_camera);
|
|
}
|
|
else
|
|
{
|
|
//tmp_camera.Init(tex_size, tex_size, DEFAULT_FOV, fMaxDist, 1.0f, fMinDist);
|
|
iSystem->SetViewCamera(tmp_camera);
|
|
r->SetCamera(tmp_camera);
|
|
}
|
|
if (bUseClipPlanes || bUseReflection)
|
|
{
|
|
Plane p;
|
|
p.n.Set(plane[0], plane[1], plane[2]);
|
|
p.d = plane[3];
|
|
tmp_camera.SetFrustumPlane(FR_PLANE_NEAR, p);
|
|
}
|
|
|
|
if (!cm->m_Tex->m_Matrix)
|
|
cm->m_Tex->m_Matrix = new float[16];
|
|
|
|
Matrix44 m, m1;
|
|
m = (Matrix44&)Smat;
|
|
D3DXMATRIXA16 *matProj = (D3DXMATRIXA16 *)gcpRendD3D->m_matProj->GetTop();
|
|
D3DXMATRIXA16 *matView = (D3DXMATRIXA16 *)gcpRendD3D->m_matView->GetTop();
|
|
D3DXMatrixMultiply((D3DXMATRIX *)&m1(0,0), matProj, (D3DXMATRIX *)&m(0,0));
|
|
D3DXMatrixMultiply((D3DXMATRIX *)cm->m_Tex->m_Matrix, matView, (D3DXMATRIX *)&m1(0,0));
|
|
//D3DXMatrixMultiply((D3DXMATRIX *)cm->m_Tex->m_Matrix, (D3DXMATRIX *)&r->m_ObjMatrix.m_values[0][0], (D3DXMATRIX *)&m1.m_values[0][0]);
|
|
|
|
if (bUseClipPlanes)
|
|
r->EF_SetClipPlane(true, plane, bWater);
|
|
|
|
r->SetViewport(0, 0, tex_size, tex_size);
|
|
|
|
r->m_RP.m_PersFlags |= RBPF_NOCLEARBUF;
|
|
|
|
if (r->m_LogFile)
|
|
r->Logv(SRendItem::m_RecurseLevel, "*** Begin Draw environment to texture ***\n");
|
|
|
|
if (bUseExistingREs)
|
|
gcpRendD3D->EF_RenderPipeLine(CD3D9Renderer::EF_Flush);
|
|
else
|
|
{
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetIProcess();
|
|
eng->DrawLowDetail(RendFlags);
|
|
}
|
|
|
|
if (r->m_LogFile)
|
|
r->Logv(SRendItem::m_RecurseLevel, "*** End Draw environment to texture ***\n");
|
|
|
|
r->m_RP.m_PersFlags &= ~RBPF_NOCLEARBUF;
|
|
|
|
iSystem->SetViewCamera(prevCamera);
|
|
r->SetCamera(prevCamera);
|
|
}
|
|
|
|
SAFE_RELEASE(pSrcSurf);
|
|
r->EF_RestoreRenderTarget();
|
|
|
|
if (bUseClipPlanes)
|
|
r->EF_SetClipPlane(false, NULL, false);
|
|
|
|
if (r->m_sbpp)
|
|
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, cColor, 1.0f, 0);
|
|
else
|
|
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
|
|
|
|
r->m_RP.m_PersFlags &= ~(RBPF_DRAWMIRROR | RBPF_DRAWPORTAL);
|
|
r->m_RP.m_PersFlags |= prevFlags & (RBPF_DRAWMIRROR | RBPF_DRAWPORTAL);
|
|
|
|
/*{
|
|
LPDIRECT3DTEXTURE9 pID3DSysTexture;
|
|
D3DLOCKED_RECT d3dlr;
|
|
LPDIRECT3DSURFACE9 pTargetSurf;
|
|
h = pID3DTargetTexture->GetSurfaceLevel(0, &pTargetSurf);
|
|
LPDIRECT3DSURFACE9 pSysSurf;
|
|
h = D3DXCreateTexture(r->m_pd3dDevice, tex_size, tex_size, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSysTexture );
|
|
h = pID3DSysTexture->GetSurfaceLevel(0, &pSysSurf);
|
|
h = r->m_pd3dDevice->GetRenderTargetData(pTargetSurf, pSysSurf);
|
|
h = pID3DSysTexture->LockRect(0, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
WriteTGA((byte *)d3dlr.pBits, tex_size, tex_size, "Problem.tga");
|
|
// Unlock the texture
|
|
pID3DSysTexture->UnlockRect(0);
|
|
pSysSurf->Release();
|
|
pTargetSurf->Release();
|
|
SAFE_RELEASE (pID3DSysTexture);
|
|
}*/
|
|
|
|
r->SetViewport(vX, vY, vWidth, vHeight);
|
|
r->EF_PopFog();
|
|
//r->EF_RestoreDLights();
|
|
|
|
cm->m_bInprogress = false;
|
|
cm->m_bReady = true;
|
|
cm->m_MaskReady = 1;
|
|
r->m_RP.m_bDrawToTexture = false;
|
|
}
|
|
|
|
//========================================================================================
|
|
|
|
void CD3D9TexMan::StartCubeSide(CCObject *obj)
|
|
{
|
|
}
|
|
|
|
void CD3D9TexMan::EndCubeSide(CCObject *obj, bool bNeedClear)
|
|
{
|
|
}
|
|
|
|
void CD3D9TexMan::DrawToTexture(Plane& Pl, STexPic *Tex, int RendFlags)
|
|
{
|
|
static 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;
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
float plane[4];
|
|
|
|
plane[0] = Pl.n[0];
|
|
plane[1] = Pl.n[1];
|
|
plane[2] = Pl.n[2];
|
|
plane[3] = -Pl.d;
|
|
|
|
int nWidth = sLimitSizeByScreenRes(512);
|
|
int nHeight = nWidth;
|
|
if (nWidth != Tex->m_Width || nHeight != Tex->m_Height)
|
|
{
|
|
int nSize = min(nWidth, nHeight);
|
|
Tex->m_Width = nSize;
|
|
Tex->m_Height = nSize;
|
|
Tex->m_Flags &= ~FT_ALLOCATED;
|
|
}
|
|
|
|
//#define WATTEST
|
|
int nHDRFl = (r->m_RP.m_PersFlags & RBPF_HDR) ? FT_HDR : 0;
|
|
|
|
Tex->m_Flags |= FT_BUILD;
|
|
if (!(Tex->m_Flags & FT_ALLOCATED) || (Tex->m_Flags & FT_HDR) != nHDRFl)
|
|
{
|
|
Tex->m_Flags |= nHDRFl;
|
|
Tex->m_Flags |= FT_ALLOCATED;
|
|
Tex->m_Flags &= ~FT_DXT;
|
|
// 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);
|
|
#ifndef WATTEST
|
|
Tex->m_Flags |= FT_NOMIPS | FT_CLAMP;
|
|
Tex->m_Flags2 |= FT2_NODXT | FT2_RENDERTARGET;
|
|
#else
|
|
Tex->m_Flags |= FT_NOMIPS | FT_ALLOCATED | FT_CLAMP;
|
|
Tex->m_Flags2 |= FT2_NODXT;
|
|
#endif
|
|
|
|
Tex->m_nMips = 0;
|
|
AddToHash(Tex->m_Bind, Tex);
|
|
#ifndef WATTEST
|
|
r->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);
|
|
#else
|
|
STexPic *tp =
|
|
r->m_TexMan->CreateTexture(NULL, tex_size, tex_size, 1, FT_NOMIPS | FT_ALLOCATED, FT2_NODXT, data, eTT_Base, -1.0f, -1.0f, 0, Tex);
|
|
|
|
IDirect3DSurface9 * pTar = r->mfGetBackSurface();
|
|
D3DSURFACE_DESC dc;
|
|
pTar->GetDesc(&dc);
|
|
if(tp->m_RefTex.m_VidTex)
|
|
((LPDIRECT3DTEXTURE9)tp->m_RefTex.m_VidTex)->Release();
|
|
HRESULT h = D3DXCreateTexture(((CD3D9Renderer *)gRenDev)->mfGetD3DDevice(), tex_size, tex_size, 1, D3DUSAGE_DYNAMIC, dc.Format, D3DPOOL_DEFAULT, ((LPDIRECT3DTEXTURE9* )& tp->m_RefTex.m_VidTex ));
|
|
#endif
|
|
delete [] data;
|
|
}
|
|
if (!Tex->m_RefTex.m_VidTex)
|
|
return;
|
|
|
|
//gRenDev->EF_SaveDLights();
|
|
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
|
|
float fMinDist = min(SKY_BOX_SIZE*0.5f, eng->GetDistanceToSectorWithWater()); // 16 is half of skybox size
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
|
|
CCamera tmp_cam = r->GetCamera();
|
|
CCamera prevCamera = tmp_cam;
|
|
|
|
Vec3d vPrevPos = tmp_cam.GetPos();
|
|
Vec3d vPrevAngles = tmp_cam.GetAngles();
|
|
Matrix44 camMat = tmp_cam.GetVCMatrixD3D9();
|
|
Vec3d vPrevDir = Vec3d(-camMat(0,2), -camMat(1,2), -camMat(2,2));
|
|
Vec3d vPrevUp = Vec3d(camMat(0,1), camMat(1,1), camMat(2,1));
|
|
Vec3d vNewDir = Pl.MirrorVector(vPrevDir);
|
|
Vec3d vNewUp = Pl.MirrorVector(vPrevUp);
|
|
Matrix44 mMir = sMatrixLookAt( vNewDir, vNewUp, vPrevAngles[1] );
|
|
|
|
float fDot = vPrevPos.Dot(Pl.n) - Pl.d;
|
|
Vec3d vNewPos = vPrevPos - Pl.n * 2.0f*fDot;
|
|
Vec3d vOccPos = vPrevPos - Pl.n * 0.99f*fDot;
|
|
|
|
CryQuat q = Quat( GetTransposed44(mMir) );
|
|
|
|
Vec3d vNewAngs = Ang3::GetAnglesXYZ(Matrix33(q));
|
|
vNewAngs = RAD2DEG(vNewAngs);
|
|
|
|
// increase frame id to support multiple recursive draws
|
|
r->m_nFrameID++;
|
|
|
|
//vNewAngs[0] = -vPrevAngles[0];
|
|
tmp_cam.SetAngle(vNewAngs);
|
|
tmp_cam.SetPos(vNewPos);
|
|
tmp_cam.SetOccPos(vOccPos);
|
|
tmp_cam.Init(Tex->m_Width, Tex->m_Height, tmp_cam.GetFov(), fMaxDist, 1.0f, fMinDist);
|
|
tmp_cam.Update();
|
|
|
|
#ifndef WATTEST
|
|
STexPicD3D *tp = (STexPicD3D *)Tex;
|
|
LPDIRECT3DTEXTURE9 pID3DTargetTexture = (LPDIRECT3DTEXTURE9)tp->m_RefTex.m_VidTex;
|
|
LPDIRECT3DSURFACE9 pSrcSurf;
|
|
HRESULT h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
|
|
h = r->EF_SetRenderTarget(pSrcSurf, true);
|
|
#endif
|
|
|
|
int TempX, TempY, TempWidth, TempHeight;
|
|
r->GetViewport(&TempX, &TempY, &TempWidth, &TempHeight);
|
|
r->SetViewport( 0, 0, Tex->m_Width, Tex->m_Height );
|
|
r->EF_PushFog();
|
|
r->m_RP.m_bDrawToTexture = true;
|
|
|
|
Vec3d vCol = r->m_vClearColor;
|
|
DWORD cColor = D3DRGBA(r->m_vClearColor[0], r->m_vClearColor[1], r->m_vClearColor[2], 0);
|
|
if (r->m_sbpp)
|
|
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, cColor, 1.0f, 0);
|
|
else
|
|
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
|
|
|
|
eng->SetCamera(tmp_cam,false);
|
|
|
|
if (!Tex->m_Matrix)
|
|
Tex->m_Matrix = new float[16];
|
|
|
|
float matProj[16], matView[16];
|
|
r->GetModelViewMatrix(matView);
|
|
r->GetProjectionMatrix(matProj);
|
|
Matrix44 m;
|
|
D3DXMatrixMultiply((D3DXMATRIX *)&m(0,0), (D3DXMATRIX *)matProj, (D3DXMATRIX *)Smat);
|
|
D3DXMatrixMultiply((D3DXMATRIX *)Tex->m_Matrix, (D3DXMATRIX *)matView, (D3DXMATRIX *)&m(0,0));
|
|
|
|
r->m_RP.m_PersFlags |= RBPF_NOCLEARBUF;
|
|
|
|
r->EF_SetClipPlane(true, plane, false);
|
|
|
|
/*static int sRFlags;
|
|
sRFlags |= RendFlags & ~DLD_TERRAIN_FULLRES;
|
|
//RendFlags &= ~DLD_TERRAIN_FULLRES;
|
|
if ((GetAsyncKeyState('F') & 0x8000))
|
|
sRFlags |= DLD_TERRAIN_FULLRES;
|
|
if ((GetAsyncKeyState('U') & 0x8000))
|
|
sRFlags &= ~DLD_TERRAIN_FULLRES;*/
|
|
eng->DrawLowDetail(RendFlags);
|
|
|
|
/*{
|
|
int tex_size = Tex->m_Width;
|
|
LPDIRECT3DTEXTURE9 pID3DSysTexture;
|
|
D3DLOCKED_RECT d3dlr;
|
|
LPDIRECT3DSURFACE9 pTargetSurf;
|
|
h = pID3DTargetTexture->GetSurfaceLevel(0, &pTargetSurf);
|
|
LPDIRECT3DSURFACE9 pSysSurf;
|
|
h = D3DXCreateTexture(r->m_pd3dDevice, tex_size, tex_size, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSysTexture );
|
|
h = pID3DSysTexture->GetSurfaceLevel(0, &pSysSurf);
|
|
h = r->m_pd3dDevice->GetRenderTargetData(pTargetSurf, pSysSurf);
|
|
h = pID3DSysTexture->LockRect(0, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
::WriteJPG((byte *)d3dlr.pBits, tex_size, tex_size, "Problem.jpg");
|
|
// Unlock the texture
|
|
pID3DSysTexture->UnlockRect(0);
|
|
pSysSurf->Release();
|
|
pTargetSurf->Release();
|
|
SAFE_RELEASE (pID3DSysTexture);
|
|
}*/
|
|
|
|
#ifdef DO_RENDERLOG
|
|
if (CRenderer::CV_r_log)
|
|
r->Logv(SRendItem::m_RecurseLevel, ".. DrawLowDetail .. (End DrawToTexture)\n");
|
|
#endif
|
|
|
|
vCol = gRenDev->m_vClearColor;
|
|
|
|
r->m_RP.m_PersFlags &= ~RBPF_NOCLEARBUF;
|
|
r->EF_SetClipPlane(false, plane, false);
|
|
Tex->m_Flags &= ~FT_BUILD;
|
|
|
|
#ifndef WATTEST
|
|
h = r->EF_RestoreRenderTarget();
|
|
SAFE_RELEASE(pSrcSurf);
|
|
#else
|
|
|
|
r->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0x00, 0x00, 0x00, 0x00), 1.0f, 0);
|
|
|
|
STexPicD3D *tp = (STexPicD3D *)Tex;
|
|
LPDIRECT3DTEXTURE9 pID3DTargetTexture = (LPDIRECT3DTEXTURE9)tp->m_RefTex.m_VidTex;
|
|
LPDIRECT3DSURFACE9 pSrcSurf;
|
|
h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
|
|
|
|
IDirect3DSurface9 * pTar = r->mfGetBackSurface();
|
|
POINT p = {0,0};
|
|
r->m_pd3dDevice->UpdateSurface(pTar, 0, pSrcSurf, 0);
|
|
pSrcSurf->Release();
|
|
#endif
|
|
|
|
r->SetCamera(prevCamera);
|
|
iSystem->SetViewCamera(prevCamera);
|
|
|
|
r->SetViewport(TempX, TempY, TempWidth, TempHeight);
|
|
r->m_RP.m_bDrawToTexture = false;
|
|
r->EF_PopFog();
|
|
//gRenDev->EF_RestoreDLights();
|
|
}
|
|
|
|
void CD3D9TexMan::DrawToTextureForRainMap(int Id)
|
|
{
|
|
I3DEngine *eng = (I3DEngine *)iSystem->GetI3DEngine();
|
|
|
|
STexPic *Tex = gRenDev->m_TexMan->m_Text_RainMap;
|
|
if (Tex->m_Flags & FT_BUILD)
|
|
return;
|
|
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
|
|
if (CRenderer::CV_r_rainmapsize != gRenDev->m_RP.m_RainMapSize)
|
|
{
|
|
if (CRenderer::CV_r_rainmapsize <= 64)
|
|
CRenderer::CV_r_rainmapsize = 64;
|
|
else
|
|
if (CRenderer::CV_r_rainmapsize <= 128)
|
|
CRenderer::CV_r_rainmapsize = 128;
|
|
else
|
|
if (CRenderer::CV_r_rainmapsize <= 256)
|
|
CRenderer::CV_r_rainmapsize = 256;
|
|
else
|
|
if (CRenderer::CV_r_rainmapsize <= 512)
|
|
CRenderer::CV_r_rainmapsize = 512;
|
|
|
|
gRenDev->m_RP.m_RainMapSize = CRenderer::CV_r_rainmapsize;
|
|
Tex->m_Flags &= ~FT_ALLOCATED;
|
|
}
|
|
int nTexWidth = gRenDev->m_RP.m_RainMapSize;
|
|
int nTexHeight = gRenDev->m_RP.m_RainMapSize;
|
|
|
|
float fMaxDist = eng->GetMaxViewDistance();
|
|
float fMinDist = 0.25f;
|
|
|
|
Tex->m_Flags |= FT_BUILD;
|
|
|
|
if (!(Tex->m_Flags & FT_ALLOCATED))
|
|
{
|
|
Tex->m_Width = nTexWidth;
|
|
Tex->m_Height = nTexHeight;
|
|
Tex->m_Flags |= FT_ALLOCATED;
|
|
Tex->m_Flags &= ~FT_DXT;
|
|
// Preallocate texture
|
|
byte *data = new byte [Tex->m_Width*Tex->m_Height*4];
|
|
Tex->m_Flags |= FT_NOMIPS|FT_HASALPHA;
|
|
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|FT_HASALPHA, FT2_NODXT | FT2_RENDERTARGET, data, eTT_Base, -1.0f, -1.0f, 0, Tex);
|
|
delete [] data;
|
|
}
|
|
|
|
//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();
|
|
|
|
int TempX, TempY, TempWidth, TempHeight;
|
|
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;
|
|
|
|
eng->SetCamera(tmp_cam,false);
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** Draw scene to texture for rainmap ***\n");
|
|
|
|
STexPicD3D *tp = (STexPicD3D *)Tex;
|
|
LPDIRECT3DTEXTURE9 pID3DTargetTexture = (LPDIRECT3DTEXTURE9)tp->m_RefTex.m_VidTex;
|
|
LPDIRECT3DSURFACE9 pSrcSurf;
|
|
HRESULT h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
|
|
h = r->EF_SetRenderTarget(pSrcSurf, true);
|
|
|
|
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;
|
|
|
|
eng->DrawRain();
|
|
|
|
if (gRenDev->m_LogFile)
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, ".. End DrawLowDetail .. (DrawToTextureForRainMap)\n");
|
|
|
|
r->m_RP.m_PersFlags &= ~RBPF_NOCLEARBUF;
|
|
Tex->m_Flags &= ~FT_BUILD;
|
|
|
|
SAFE_RELEASE(pSrcSurf);
|
|
h = r->EF_RestoreRenderTarget();
|
|
|
|
/*{
|
|
int tex_size = Tex->m_Width;
|
|
LPDIRECT3DTEXTURE9 pID3DSysTexture;
|
|
D3DLOCKED_RECT d3dlr;
|
|
LPDIRECT3DSURFACE9 pTargetSurf;
|
|
h = pID3DTargetTexture->GetSurfaceLevel(0, &pTargetSurf);
|
|
LPDIRECT3DSURFACE9 pSysSurf;
|
|
h = D3DXCreateTexture(r->m_pd3dDevice, tex_size, tex_size, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSysTexture );
|
|
h = pID3DSysTexture->GetSurfaceLevel(0, &pSysSurf);
|
|
h = r->m_pd3dDevice->GetRenderTargetData(pTargetSurf, pSysSurf);
|
|
h = pID3DSysTexture->LockRect(0, &d3dlr, NULL, 0);
|
|
// Copy data to the texture
|
|
WriteTGA((byte *)d3dlr.pBits, tex_size, tex_size, "Problem.tga", 32);
|
|
// Unlock the texture
|
|
pID3DSysTexture->UnlockRect(0);
|
|
pSysSurf->Release();
|
|
pTargetSurf->Release();
|
|
SAFE_RELEASE (pID3DSysTexture);
|
|
}*/
|
|
|
|
iSystem->SetViewCamera(prevCamera);
|
|
gRenDev->SetCamera(prevCamera);
|
|
|
|
gRenDev->SetViewport(TempX, TempY, TempWidth, TempHeight);
|
|
|
|
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();
|
|
|
|
CD3D9Renderer *r = gcpRendD3D;
|
|
int nOffs;
|
|
struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F *vQuad = gcpRendD3D->GetVBPtr2D(4, nOffs);
|
|
|
|
// Define the quad
|
|
vQuad[0].x = 0.0f;
|
|
vQuad[0].y = 0.0f;
|
|
vQuad[0].z = 0.0f;
|
|
vQuad[0].rhw = 1.0f;
|
|
vQuad[0].color.dcolor = col;
|
|
vQuad[0].st[0] = 0.0f;
|
|
vQuad[0].st[1] = 0.0f;
|
|
|
|
vQuad[1].x = wdt;
|
|
vQuad[1].y = 0.0f;
|
|
vQuad[1].z = 0.0f;
|
|
vQuad[1].rhw = 1.0f;
|
|
vQuad[1].color.dcolor = col;
|
|
vQuad[1].st[0] = 1.0f;
|
|
vQuad[1].st[1] = 0.0f;
|
|
|
|
vQuad[2].x = wdt;
|
|
vQuad[2].y = hgt;
|
|
vQuad[2].z = 0.0f;
|
|
vQuad[2].rhw = 1.0f;
|
|
vQuad[2].color.dcolor = col;
|
|
vQuad[2].st[0] = 1.0f;
|
|
vQuad[2].st[1] = 1.0f;
|
|
|
|
vQuad[3].x = 0.0f;
|
|
vQuad[3].y = hgt;
|
|
vQuad[3].z = 0.0f;
|
|
vQuad[3].rhw = 1.0f;
|
|
vQuad[3].color.dcolor = col;
|
|
vQuad[3].st[0] = 0.0f;
|
|
vQuad[3].st[1] = 1.0f;
|
|
|
|
// We are finished with accessing the vertex buffer
|
|
r->UnlockVB2D();
|
|
// Bind our vertex as the first data stream of our device
|
|
r->m_pd3dDevice->SetStreamSource(0, r->m_pVB2D, 0, sizeof(struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F));
|
|
r->EF_SetVertexDeclaration(0, VERTEX_FORMAT_TRP3F_COL4UB_TEX2F);
|
|
// Render the two triangles from the data stream
|
|
HRESULT hr = r->m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
|
|
}
|
|
|
|
// <<TODO>> Clean redundant code
|
|
|
|
void CD3D9TexMan::EndHeatMap()
|
|
{
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
}
|
|
|
|
void CD3D9TexMan::StartHeatMap(int Id)
|
|
{
|
|
}
|
|
|
|
void CD3D9TexMan::EndNightMap()
|
|
{
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
}
|
|
|
|
void CD3D9TexMan::StartNightMap(int Id)
|
|
{
|
|
}
|
|
|
|
|
|
void CD3D9TexMan::StartScreenMap(int Id)
|
|
{
|
|
}
|
|
|
|
void CD3D9TexMan::EndScreenMap()
|
|
{
|
|
}
|
|
|
|
void CD3D9TexMan::StartRefractMap(int Id)
|
|
{
|
|
}
|
|
void CD3D9TexMan::EndRefractMap()
|
|
{
|
|
}
|
|
|
|
// ===============================================================
|
|
// DrawToTextureForGlare - glare fx
|
|
// Last Update: 28/06/2003
|
|
|
|
void CD3D9TexMan::DrawToTextureForGlare(int Id)
|
|
{
|
|
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
}
|
|
|
|
// ===============================================================
|
|
// DrawFlashBangMap - flashbang fx's
|
|
// Last Update: 04/06/2003
|
|
|
|
void CD3D9TexMan::DrawFlashBangMap(int Id, int RendFlags, CREFlashBang *pRE)
|
|
{
|
|
// set flags
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
}
|
|
|
|
// ===============================================================
|
|
// ScreenTexMap - get screen sized texture, for shared use
|
|
// Last Update: 19/09/2003
|
|
|
|
// prepare and set rendertarget
|
|
void CD3D9TexMan::StartScreenTexMap(int Id)
|
|
{
|
|
if(gRenDev)
|
|
{
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** StartScreenTexMap ***\n");
|
|
}
|
|
|
|
// get data
|
|
STexPic *pTex =GetByID(Id);
|
|
// this SHOULD be always valid, but ok...
|
|
assert(pTex);
|
|
|
|
CD3D9Renderer *pRenderer = gcpRendD3D;
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
int iWidth = m_TempWidth, iHeight = m_TempHeight;
|
|
|
|
// recreate texture when necessary
|
|
if(pTex->m_Width!=iWidth || pTex->m_Height!=iHeight)
|
|
{
|
|
pTex->m_Flags &= ~FT_ALLOCATED;
|
|
}
|
|
|
|
// if not created yet, create texture
|
|
if (!(pTex->m_Flags & FT_ALLOCATED))
|
|
{
|
|
// set rendertarget flags
|
|
pTex->m_Flags |= FT_ALLOCATED | FT_NOMIPS | FT_HASALPHA;
|
|
pTex->m_Flags &= ~FT_DXT;
|
|
pTex->m_Flags2 |= FT2_NODXT | FT2_RENDERTARGET;
|
|
|
|
pTex->m_Width = iWidth;
|
|
pTex->m_Height = iHeight;
|
|
pTex->m_nMips = 0;
|
|
|
|
// must pass empty buffer into create texture..
|
|
byte *pData = new byte [pTex->m_Width*pTex->m_Height*4];
|
|
|
|
if(!pRenderer->m_TexMan->CreateTexture(NULL, pTex->m_Width, pTex->m_Height, 1, pTex->m_Flags, pTex->m_Flags2, pData, eTT_Base, -1.0f, -1.0f, 0, pTex))
|
|
{
|
|
// error creating texure
|
|
delete [] pData;
|
|
return;
|
|
}
|
|
|
|
delete [] pData;
|
|
}
|
|
|
|
gRenDev->GetViewport(&m_TempX, &m_TempY, &m_TempWidth, &m_TempHeight);
|
|
gRenDev->SetViewport(m_TempX, m_TempY, m_TempWidth, m_TempHeight);
|
|
|
|
// set flags
|
|
gRenDev->m_RP.m_bDrawToTexture = true;
|
|
gRenDev->m_RP.m_PersFlags |= RBPF_DRAWSCREENTEXMAP; //|RBPF_NOCLEARBUF;
|
|
|
|
D3DCOLOR cColor = D3DRGBA(0.0f,0.0f,0.0f,0.0f);
|
|
// render object
|
|
//pRenderer->m_pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
|
|
}
|
|
|
|
// restore back-buffer
|
|
void CD3D9TexMan::EndScreenTexMap()
|
|
{
|
|
if(gRenDev)
|
|
{
|
|
gRenDev->Logv(SRendItem::m_RecurseLevel, "*** EndScreenTexMap ***\n");
|
|
}
|
|
|
|
// get data
|
|
STexPic *tx = NULL;
|
|
if (gRenDev->m_RP.m_PersFlags & RBPF_HDR)
|
|
tx = gRenDev->m_TexMan->m_Text_ScreenMap_HDR;
|
|
else
|
|
tx = gRenDev->m_TexMan->m_Text_ScreenMap;
|
|
|
|
// this SHOULD be always valid, but ok...
|
|
assert(tx);
|
|
|
|
CD3D9Renderer *pRenderer = gcpRendD3D;
|
|
|
|
int iTempX, iTempY, iWidth, iHeight;
|
|
gRenDev->GetViewport(&iTempX, &iTempY, &iWidth, &iHeight);
|
|
|
|
// get texture surface
|
|
LPDIRECT3DSURFACE9 pTexSurfCopy;
|
|
// this SHOULD be always valid, but ok...
|
|
assert(tx->m_RefTex.m_VidTex);
|
|
LPDIRECT3DTEXTURE9 plD3DTextureCopy = (LPDIRECT3DTEXTURE9) tx->m_RefTex.m_VidTex;
|
|
HRESULT hr = plD3DTextureCopy->GetSurfaceLevel(0, &pTexSurfCopy);
|
|
|
|
if (FAILED(hr))
|
|
return;
|
|
|
|
// Beware with e_widescreen usage. Only copy visible screen area.
|
|
RECT pSrcRect={iTempX, iTempY, iTempX+iWidth, iTempY+iHeight };
|
|
RECT pDstRect={0, 0, iWidth, iHeight };
|
|
|
|
if (pRenderer->m_RP.m_PersFlags & RBPF_HDR)
|
|
{
|
|
hr = pRenderer->m_pd3dDevice->StretchRect(pRenderer->m_pHDRTargetSurf, &pSrcRect, pTexSurfCopy, &pDstRect, D3DTEXF_NONE);
|
|
}
|
|
else
|
|
{
|
|
hr = pRenderer->m_pd3dDevice->StretchRect(pRenderer->m_pCurBackBuffer, &pSrcRect, pTexSurfCopy, &pDstRect, D3DTEXF_NONE);
|
|
}
|
|
|
|
// reset flags/free data
|
|
gRenDev->m_RP.m_PersFlags &= ~(RBPF_DRAWSCREENTEXMAP); //|RBPF_NOCLEARBUF);
|
|
gRenDev->m_RP.m_bDrawToTexture = false;
|
|
SAFE_RELEASE(pTexSurfCopy)
|
|
}
|
|
|
|
// =====================================================================
|
|
// DrawToTextureForDof - generate depth of field, focal distance texture
|
|
// Last Update: 18/03/2004
|
|
|
|
void CD3D9TexMan::DrawToTextureForDof(int Id)
|
|
{
|
|
}
|
|
|
|
//==================================================================================
|
|
|
|
int __cdecl 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 CD3D9TexMan::Update()
|
|
{
|
|
CD3D9Renderer *rd = gcpRendD3D;
|
|
int i;
|
|
char buf[256]="";
|
|
|
|
CheckTexLimits(NULL);
|
|
|
|
bool bChangedNormalMapCompressed = false;
|
|
#ifdef USE_3DC
|
|
if (rd->m_bDeviceSupportsComprNormalmaps && CRenderer::CV_r_texnormalmapcompressed != m_CurTexNormalMapCompressed)
|
|
bChangedNormalMapCompressed = true;
|
|
#endif
|
|
|
|
if (bChangedNormalMapCompressed || CRenderer::CV_r_texresolution != m_CurTexResolution || CRenderer::CV_r_texbumpresolution != m_CurTexBumpResolution || CRenderer::CV_r_texquality != m_CurTexQuality || CRenderer::CV_r_texbumpquality != m_CurTexBumpQuality)
|
|
{
|
|
for (i=0; i<m_Textures.Num(); i++)
|
|
{
|
|
STexPic *tp = m_Textures[i];
|
|
if (!tp || !tp->m_bBusy)
|
|
continue;
|
|
if (!(tp->m_Flags2 & FT2_WASLOADED))
|
|
continue;
|
|
if (tp->m_Flags & FT_NOREMOVE)
|
|
continue;
|
|
if (bChangedNormalMapCompressed && !(tp->m_Flags & FT_ALLOW3DC))
|
|
continue;
|
|
if (tp->m_eTT == eTT_Cubemap)
|
|
{
|
|
//if (tp->m_CubeSide > 0)
|
|
continue;
|
|
if (CRenderer::CV_r_texresolution != m_CurTexResolution || CRenderer::CV_r_texquality != m_CurTexQuality)
|
|
{
|
|
gRenDev->EF_LoadTexture(tp->m_SearchName.c_str(), tp->m_Flags, tp->m_Flags2 | FT2_RELOAD, tp->m_eTT, tp->m_fAmount1, tp->m_fAmount2, tp->m_Id);
|
|
}
|
|
}
|
|
else
|
|
if (tp->m_eTT == eTT_Bumpmap || tp->m_eTT == eTT_DSDTBump)
|
|
{
|
|
int nFlags = tp->m_Flags;
|
|
bool bReload = false;
|
|
#ifdef USE_3DC
|
|
if (bChangedNormalMapCompressed && (nFlags & FT_ALLOW3DC))
|
|
{
|
|
bReload = true;
|
|
if (CRenderer::CV_r_texnormalmapcompressed)
|
|
nFlags |= FT_3DC;
|
|
else
|
|
nFlags &= ~FT_3DC;
|
|
}
|
|
#endif
|
|
if (bReload || CRenderer::CV_r_texbumpresolution != m_CurTexBumpResolution || CRenderer::CV_r_texbumpquality != m_CurTexBumpQuality )
|
|
{
|
|
gRenDev->EF_LoadTexture(tp->m_SearchName.c_str(), nFlags, tp->m_Flags2 | FT2_RELOAD, tp->m_eTT, tp->m_fAmount1, tp->m_fAmount2, tp->m_Id);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (CRenderer::CV_r_texresolution != m_CurTexResolution || CRenderer::CV_r_texquality != m_CurTexQuality)
|
|
{
|
|
gRenDev->EF_LoadTexture(tp->m_SearchName.c_str(), tp->m_Flags, tp->m_Flags2 | FT2_RELOAD, tp->m_eTT, tp->m_fAmount1, tp->m_fAmount2, tp->m_Id);
|
|
}
|
|
}
|
|
}
|
|
m_CurTexResolution = CRenderer::CV_r_texresolution;
|
|
m_CurTexBumpResolution = CRenderer::CV_r_texbumpresolution;
|
|
m_CurTexQuality = CRenderer::CV_r_texquality;
|
|
m_CurTexBumpQuality = CRenderer::CV_r_texbumpquality;
|
|
#ifdef USE_3DC
|
|
m_CurTexNormalMapCompressed = CRenderer::CV_r_texnormalmapcompressed;
|
|
#endif
|
|
}
|
|
|
|
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","Cubemap","AutoCubemap","Bump","DSDTBump","Rectangle","3D"
|
|
};
|
|
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","V8U8","V16U16","0088","DEPTH"
|
|
};
|
|
|
|
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 == gRenDev->m_TexMan->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 != gRenDev->m_TexMan->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 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], (Texs[i]->m_Flags & FT_3DC) ? "3DC" : 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 != gRenDev->m_TexMan->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], (Texs[i]->m_Flags & FT_3DC) ? "3DC" : 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], (Texs[i]->m_Flags & FT_3DC) ? "3DC" : 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));
|
|
}
|
|
else
|
|
{
|
|
sprintf(buf, "*** Total Size: %.3fMb", Size/(1024.0f*1024.0f));
|
|
rd->TextToScreenColor(4,nY+1, 0,1,1,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_Bind != gRenDev->m_TexMan->m_Text_NoTexture->m_Bind && !(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 (fp)
|
|
fprintf(fp, "\n\n*** Textures loaded: ***\n");
|
|
else
|
|
rd->TextToScreenColor(4,13, 1,1,0,1, "*** Textures loaded: ***");
|
|
qsort(&Texs[0], Texs.Num(), sizeof(STexPic *), TexCallback );
|
|
Size = 0;
|
|
for (i=0; i<Texs.Num(); i++)
|
|
{
|
|
if (strstr(Texs[i]->m_SourceName.c_str(), "efault"))
|
|
{
|
|
int nnn = 0;
|
|
}
|
|
if (Texs[i]->m_Flags2 & FT2_WASUNLOADED)
|
|
continue;
|
|
if (fp)
|
|
fprintf(fp, "%.3fKb %d mips (%.3fKb)\t\tType: %s \t\tFormat: %s\t\t(%s)\n", Texs[i]->m_Size/1024.0f, Texs[i]->m_nMips, Texs[i]->m_LoadedSize/1024.0f, sTexType[Texs[i]->m_eTT], (Texs[i]->m_Flags & FT_3DC) ? "3DC" : 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], (Texs[i]->m_Flags & FT_3DC) ? "3DC" : sTexFormat[Texs[i]->m_ETF], Texs[i]->m_SearchName.c_str());
|
|
rd->TextToScreenColor(4,nY, 0,1,0,1, buf);
|
|
nY += 3;
|
|
}
|
|
if (Texs[i]->m_LoadedSize)
|
|
Size += Texs[i]->m_LoadedSize;
|
|
else
|
|
Size += Texs[i]->m_Size;
|
|
}
|
|
if (fp)
|
|
{
|
|
fprintf(fp, "*** Total Size: %.3fMb\n\n", Size/(1024.0f*1024.0f));
|
|
}
|
|
else
|
|
{
|
|
sprintf(buf, "*** Total Size: %.3fMb", Size/(1024.0f*1024.0f));
|
|
rd->TextToScreenColor(4,nY+1, 0,1,1,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_Bind != gRenDev->m_TexMan->m_Text_NoTexture->m_Bind && !m_Textures[i]->IsStreamed())
|
|
{
|
|
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 non-streamed: ***\n");
|
|
else
|
|
rd->TextToScreenColor(4,13, 1,1,0,1, "*** Textures non-streamed: ***");
|
|
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], (Texs[i]->m_Flags & FT_3DC) ? "3DC" : 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], (Texs[i]->m_Flags & FT_3DC) ? "3DC" : 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 != gRenDev->m_TexMan->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;
|
|
int nNoStr = 0;
|
|
for (i=0; i<Texs.Num(); i++)
|
|
{
|
|
AllSize += Texs[i]->m_Size;
|
|
if (!Texs[i]->IsStreamed())
|
|
{
|
|
NonStrSize += Texs[i]->m_Size;
|
|
nNoStr++;
|
|
}
|
|
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 += TexsNM[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: %d (Size: %.3fMb)", Texs.Num(), AllSize/(1024.0f*1024.0f), nNoStr, 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 Loaded Size: %.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_Bind != gRenDev->m_TexMan->m_Text_NoTexture->m_Bind && m_Textures[i]->m_AccessFrame == rd->m_nFrameUpdateID)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
//==================================================================================
|
|
|
|
STexPic *CD3D9Renderer::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();
|
|
|
|
float shininess = (float)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), (double)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;
|
|
}
|
|
}
|
|
LPDIRECT3DTEXTURE9 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))
|
|
{
|
|
cryMemcpy((byte *)d3dlr.pBits, img, imgsize*imgsize*4);
|
|
|
|
// Unlock the texture
|
|
pPhongTexture->UnlockRect(0);
|
|
hr = D3DXFilterTexture(pPhongTexture, NULL, 0, D3DX_FILTER_LINEAR);
|
|
}
|
|
}
|
|
//::WriteTGA(img, imgsize, imgsize, "Phong.tga", 32);
|
|
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.bRepeats = false;
|
|
ti->m_RefTex.m_AnisLevel = gcpRendD3D->GetAnisotropicLevel();
|
|
|
|
delete [] img;
|
|
|
|
m_TexMan->SetTexture(0, eTT_Base);
|
|
|
|
return ti;
|
|
}
|
|
|
|
static float sfExp;
|
|
|
|
static float spec_func(float s, float NaH, float NaNa)
|
|
{
|
|
float toksvig = sqrt(NaNa)/(sqrt(NaNa)+s*(1-sqrt(NaNa)));
|
|
return (1.0f+toksvig*s)/(1.0f+s)*pow(NaH/sqrt(NaNa), toksvig*s);
|
|
}
|
|
|
|
VOID WINAPI FillSpecularTexture(D3DXVECTOR4* pOut, const D3DXVECTOR2* pTexCoord, const D3DXVECTOR2* pTexelSize, LPVOID pData)
|
|
{
|
|
float f = spec_func(sfExp,pTexCoord->x,pTexCoord->y);
|
|
pOut->x = f;
|
|
pOut->y = f;
|
|
pOut->z = f;
|
|
pOut->w = 0;
|
|
}
|
|
|
|
STexPic *CD3D9Renderer::EF_MakeSpecularTexture(float fExp)
|
|
{
|
|
char name[128];
|
|
|
|
bool bMips = false;
|
|
sprintf(name, "$Specular_%d", (int)fExp);
|
|
int nFlags = FT_NOREMOVE | FT_NOSTREAM | FT_CLAMP;
|
|
CD3D9TexMan *tm = (CD3D9TexMan *)m_TexMan;
|
|
STexPicD3D *ti = (STexPicD3D *)tm->LoadTexture(name, nFlags, FT2_NODXT | FT2_NOANISO, eTT_Base, -1.0f, -1.0f);
|
|
if (ti->m_RefTex.m_VidTex)
|
|
return ti;
|
|
LPDIRECT3DTEXTURE9 pTexture;
|
|
D3DFORMAT d3dFMT = D3DFMT_G16R16F;
|
|
int nWidth = 256;
|
|
int nHeight = 256;
|
|
// Create attenuation texture
|
|
if (FAILED(gcpRendD3D->mfGetD3DDevice()->CreateTexture(nWidth, nHeight, 1, 0, d3dFMT, D3DPOOL_MANAGED, &pTexture, NULL)))
|
|
return NULL;
|
|
sfExp = fExp*2;
|
|
if (FAILED(D3DXFillTexture(pTexture, FillSpecularTexture, 0)))
|
|
return NULL;
|
|
|
|
if (!bMips)
|
|
nFlags |= FT_NOMIPS;
|
|
ti->m_RefTex.m_VidTex = (void *)pTexture;
|
|
ti->m_RefTex.m_MipFilter = bMips ? D3DTEXF_POINT : D3DTEXF_NONE;
|
|
if (m_bDeviceSupportsFP16Filter)
|
|
{
|
|
ti->m_RefTex.m_MinFilter = D3DTEXF_LINEAR;
|
|
ti->m_RefTex.m_MagFilter = D3DTEXF_LINEAR;
|
|
}
|
|
else
|
|
{
|
|
ti->m_RefTex.m_MinFilter = D3DTEXF_POINT;
|
|
ti->m_RefTex.m_MagFilter = D3DTEXF_POINT;
|
|
}
|
|
ti->m_RefTex.m_AnisLevel = 1;
|
|
ti->m_RefTex.m_Type = TEXTGT_2D;
|
|
ti->m_DstFormat = d3dFMT;
|
|
ti->m_Width = nWidth;
|
|
ti->m_Height = nHeight;
|
|
CD3D9TexMan::CalcMipsAndSize(ti);
|
|
tm->AddToHash(ti->m_Bind, ti);
|
|
ti->Unlink();
|
|
ti->Link(&STexPic::m_Root);
|
|
gRenDev->m_TexMan->m_StatsCurTexMem += ti->m_Size;
|
|
|
|
return ti;
|
|
}
|
|
|
|
float CD3D9TexMan::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 CD3D9TexMan::GenerateFogMaps()
|
|
{
|
|
int i, j;
|
|
{
|
|
float fdata[256];
|
|
byte Data1[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;
|
|
int nRes = nj*nj + ni*ni;
|
|
float m = (float)(nRes);
|
|
float fsq;
|
|
if (nRes == 0)
|
|
fsq = 1.0f;
|
|
else
|
|
fsq = 1.0f / cry_sqrtf(m); // [marco] crash, division by zero
|
|
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][i][0] = Data1[j][i][1] = Data1[j][i][2] = 255;
|
|
Data1[j][i][3] = (byte)iFog;
|
|
}
|
|
}
|
|
gRenDev->m_TexMan->m_Text_Fog = CreateTexture("$Fog", 128, 128, 1, FT_CLAMP | FT_NOMIPS | FT_NOREMOVE | FT_HASALPHA, FT2_NODXT | FT2_NOANISO, &Data1[0][0][0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
|
|
//gRenDev->m_TexMan->m_Text_Fog->SaveTGA("Fog.tga", false);
|
|
|
|
/*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;
|
|
}
|
|
}*/
|
|
|
|
//gRenDev->m_TexMan->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);
|
|
//gRenDev->m_TexMan->m_Text_Fog_Enter->SaveTGA("FogEnter.tga", false);
|
|
gRenDev->m_TexMan->m_Text_Fog_Enter = LoadTexture("Textures/FogEnter", FT_CLAMP | FT_NOMIPS | FT_NOREMOVE | FT_HASALPHA, FT2_NODXT | FT2_NOANISO);
|
|
gRenDev->m_TexMan->m_Text_VFog = LoadTexture("Textures/FogTex", FT_CLAMP | FT_NOMIPS | FT_NOREMOVE | FT_HASALPHA, FT2_NODXT | FT2_NOANISO);
|
|
//gRenDev->m_TexMan->m_Text_Fog_Enter->SaveTGA("FogEnter.tga", false);
|
|
//gRenDev->m_TexMan->m_Text_Fog_Enter->SaveTGA("FogEnter.tga", false);
|
|
}
|
|
}
|
|
|
|
//==============================================================================================================
|
|
|
|
VOID CFnMap9::Fill2DWrapper(D3DXVECTOR4* pOut, const D3DXVECTOR2* pTexCoord, const D3DXVECTOR2* pTexelSize, LPVOID pData)
|
|
{
|
|
CFnMap9* map = (CFnMap9*)pData;
|
|
const D3DXCOLOR& c = map->Function( pTexCoord, pTexelSize );
|
|
*pOut = D3DXVECTOR4((const float*)c);
|
|
}
|
|
|
|
HRESULT CFnMap9::Initialize()
|
|
{
|
|
LPDIRECT3DTEXTURE9 pTexture;
|
|
HRESULT hr;
|
|
LPDIRECT3DDEVICE9 dv = gcpRendD3D->mfGetD3DDevice();
|
|
|
|
if ( FAILED( hr = D3DXCheckTextureRequirements(dv, &m_dwWidth, &m_dwHeight, &m_dwLevels, 0, &m_Format, D3DPOOL_MANAGED)))
|
|
{
|
|
OutputDebugString("Can't find valid texture format.\n");
|
|
return hr;
|
|
}
|
|
|
|
if (FAILED (hr = dv->CreateTexture(m_dwWidth, m_dwHeight, 0, 0, m_Format, D3DPOOL_MANAGED, &pTexture, NULL)))
|
|
{
|
|
OutputDebugString("Can't create texture\n");
|
|
return hr;
|
|
}
|
|
|
|
if (FAILED (hr = D3DXFillTexture(pTexture, Fill2DWrapper, (void*)this)))
|
|
return hr;
|
|
|
|
STexPicD3D *tp = (STexPicD3D *)m_pTex;
|
|
SAFE_DELETE(tp->m_pFuncMap);
|
|
tp->m_pFuncMap = this;
|
|
tp->m_RefTex.m_VidTex = pTexture;
|
|
tp->m_Width = m_dwWidth;
|
|
tp->m_Height = m_dwHeight;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CD3D9TexMan::GenerateGhostMap()
|
|
{
|
|
CGhostMap *pGhostMap = new CGhostMap(256, m_Text_Ghost);
|
|
pGhostMap->Initialize();
|
|
}
|
|
|
|
const float INV_RAND_MAX = 1.0 / (RAND_MAX + 1);
|
|
inline float frnd(float max=1.0) { return max * INV_RAND_MAX * rand(); }
|
|
inline float frnd(float min, float max) { return min + (max - min) * INV_RAND_MAX * rand(); }
|
|
|
|
void CFurMap::Bind(float layer, int nTMU)
|
|
{
|
|
gcpRendD3D->EF_SelectTMU(nTMU);
|
|
assert(m_nCurInst>=0 && m_nCurInst<m_Inst.Num());
|
|
SFurLayers *fl = m_Inst[m_nCurInst];
|
|
int temp = (int)floor(fl->m_Layers.Num() * max(0.0f, min(0.9999f, layer)));
|
|
fl->m_Layers[temp]->Set();
|
|
}
|
|
|
|
void CFurMap::Update(int nNumLayers)
|
|
{
|
|
int nInst;
|
|
|
|
for (nInst=0; nInst<m_Inst.Num(); nInst++)
|
|
{
|
|
if (m_Inst[nInst]->m_Layers.Num() == nNumLayers)
|
|
{
|
|
m_nCurInst = nInst;
|
|
return;
|
|
}
|
|
}
|
|
SFurLayers *fl = new SFurLayers;
|
|
m_nCurInst = nInst;
|
|
m_Inst.AddElem(fl);
|
|
Initialize(timeGetTime(), 128, nNumLayers, fl);
|
|
}
|
|
|
|
HRESULT CFurMap::Initialize(int seed, int size, int num, SFurLayers *fl)
|
|
{
|
|
srand(seed);
|
|
|
|
if (num > 60)
|
|
num = 60;
|
|
for (int i=0; i<fl->m_Layers.Num(); i++)
|
|
{
|
|
STexPic *tp = fl->m_Layers[i];
|
|
if (tp)
|
|
tp->Release(false);
|
|
}
|
|
fl->m_Layers.Free();
|
|
|
|
CFColor *data = new CFColor[num*size*size];
|
|
#define DATA(layer, x, y) data[size*size*(layer) + size*(y) + (x)]
|
|
|
|
for (int x=0; x<size; x++)
|
|
{
|
|
for (int y=0; y<size; y++)
|
|
{
|
|
int layer;
|
|
CFColor color;
|
|
float t;
|
|
|
|
// hair color
|
|
color.r = 1.0f;
|
|
color.g = 1.0f;
|
|
color.b = 1.0f;
|
|
if (frnd() < 0.15f)
|
|
color *= frnd(0.2f, 0.4f);
|
|
else
|
|
color *= frnd(0.7f, 1.0f);
|
|
|
|
for (layer=0; layer<num; layer++)
|
|
{
|
|
// lower layer is darker
|
|
t = max(0, 1 - 2 * float(layer) / (num-1));
|
|
DATA(layer, x, y) = color * float(1 - 0.7f * powf(t, 1.5f));
|
|
}
|
|
|
|
// length of the hair
|
|
int length = 1 + uint(num * powf(frnd(), 3.0f));
|
|
length = min(num, length);
|
|
|
|
for (layer=0; layer<length; layer++)
|
|
{
|
|
// tip of the hair is semi-transparent
|
|
t = max(0, -1 + 2 * float(layer+1) / length);
|
|
DATA(layer, x, y).a = 1 - 0.85f * powf(t, 2.0f);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int layer=0; layer<num; layer++)
|
|
{
|
|
DWORD *pixels = new DWORD[size*size];
|
|
DWORD *p = pixels;
|
|
CFColor *pColor = &DATA(layer, 0, 0);
|
|
for(int i=0; i<size*size; i++)
|
|
{
|
|
*p++ = pColor->GetTrue();
|
|
pColor++;
|
|
}
|
|
char name[128];
|
|
sprintf(name, "$AutoFur_%d", gcpRendD3D->m_TexGenID++);
|
|
STexPic *tp = gcpRendD3D->m_TexMan->CreateTexture(name, size, size, 1, FT_HASALPHA, 0, (byte *)pixels, eTT_Base);
|
|
fl->m_Layers.AddElem(tp);
|
|
|
|
delete [] pixels;
|
|
}
|
|
|
|
delete [] data;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CD3D9TexMan::GenerateFurMap()
|
|
{
|
|
STexPic *ti = gcpRendD3D->m_TexMan->LoadTexture("$Fur", 0, 0, eTT_Base);
|
|
CFurMap *pFurMap = new CFurMap(ti);
|
|
ti->m_pFuncMap = pFurMap;
|
|
}
|
|
|
|
HRESULT CFurNormalMap::Initialize()
|
|
{
|
|
// texture map for clamping
|
|
{
|
|
int size = 64;
|
|
byte *pixels = new byte[size*size*4];
|
|
byte *p = pixels;
|
|
|
|
for (int j=0; j<size; j++)
|
|
for (int i=0; i<size; i++)
|
|
{
|
|
D3DXVECTOR2 vec;
|
|
vec.x = -1 + 2 * i / float(size - 1);
|
|
vec.y = -1 + 2 * j / float(size - 1);
|
|
float len = D3DXVec2Length(&vec);
|
|
if (len > 1.0)
|
|
vec /= len;
|
|
*p++ = 0;
|
|
*p++ = (unsigned char)(128 + 127 * vec.y);
|
|
*p++ = (unsigned char)(128 + 127 * vec.x);
|
|
*p++ = 0;
|
|
}
|
|
m_pTexClamp = gcpRendD3D->m_TexMan->CreateTexture("$FurTexClamp", size, size, 1, FT_CLAMP | FT_NOMIPS, 0, pixels, eTT_Base);
|
|
|
|
delete [] pixels;
|
|
}
|
|
|
|
// texture map for normalization
|
|
{
|
|
int size = 64;
|
|
byte *pixels = new byte[size*size*4];
|
|
byte *p = pixels;
|
|
|
|
for (int j=0; j<size; j++)
|
|
for (int i=0; i<size; i++)
|
|
{
|
|
D3DXVECTOR3 n;
|
|
n.x = -1 + 2 * i / float(size - 1);
|
|
n.y = -1 + 2 * j / float(size - 1);
|
|
n.z = 0;
|
|
float len = D3DXVec3Length(&n);
|
|
if (len > 1.0) n /= len;
|
|
n.z = 1.0;
|
|
D3DXVec3Normalize(&n, &n);
|
|
*p++ = (unsigned char)(128 + 127 * n.z);
|
|
*p++ = (unsigned char)(128 + 127 * n.y);
|
|
*p++ = (unsigned char)(128 + 127 * n.x);
|
|
*p++ = 0;
|
|
}
|
|
|
|
m_pTexNormalize = gcpRendD3D->m_TexMan->CreateTexture("$FurTexNormalize", size, size, 1, FT_CLAMP | FT_NOMIPS, 0, pixels, eTT_Base);
|
|
|
|
delete [] pixels;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CFurNormalMap::Bind(int nTMU)
|
|
{
|
|
assert(m_nCurInst>=0 && m_nCurInst<m_Inst.Num());
|
|
|
|
SDynFurInstance *fr = &m_Inst[m_nCurInst];
|
|
assert(fr->m_bPrepared && fr->m_pTexNormal);
|
|
gcpRendD3D->EF_SelectTMU(nTMU);
|
|
fr->m_pTexNormal->Set();
|
|
}
|
|
|
|
void CFurNormalMap::Update(EShaderPassType eShPass, float dt, SShaderPassHW *slw, bool bUseSimulation)
|
|
{
|
|
SParamComp_User user;
|
|
int i;
|
|
|
|
CD3D9Renderer *rd = gcpRendD3D;
|
|
SDynFurInstance *fr;
|
|
|
|
Vec3 pos = rd->m_RP.m_pCurObject->GetTranslation();
|
|
int nInst;
|
|
if (!bUseSimulation)
|
|
nInst = 0;
|
|
else
|
|
{
|
|
for (nInst=1; nInst<m_Inst.Num(); nInst++)
|
|
{
|
|
fr = &m_Inst[nInst];
|
|
if ((fr->m_Trans-pos).Length() < 0.25f)
|
|
break;
|
|
}
|
|
if (nInst == m_Inst.Num())
|
|
{
|
|
int nFr = -1;
|
|
for (i=1; i<m_Inst.Num(); i++)
|
|
{
|
|
fr = &m_Inst[i];
|
|
if (nFr > (int)fr->m_nUsedFrame)
|
|
{
|
|
nFr = fr->m_nUsedFrame;
|
|
nInst = i;
|
|
}
|
|
}
|
|
if (nFr > rd->GetFrameID()-40)
|
|
{
|
|
nInst = m_Inst.Num();
|
|
if (nInst == 0)
|
|
nInst = 1;
|
|
}
|
|
}
|
|
}
|
|
if (nInst >= m_Inst.Num())
|
|
m_Inst.ReserveNew(nInst+1);
|
|
fr = &m_Inst[nInst];
|
|
if (!fr->m_bPrepared)
|
|
{
|
|
if (!nInst)
|
|
fr->m_pTexNormal = rd->m_TexMan->LoadTexture("Textures/white_ddn", 0, 0, eTT_Bumpmap);
|
|
else
|
|
{
|
|
char name[128];
|
|
byte *pixels = new byte[m_dwWidth*m_dwHeight*4];
|
|
memset(pixels, 128, m_dwWidth*m_dwHeight*4);
|
|
int num = rd->m_TexGenID++;
|
|
sprintf(name, "$FurTexOffset0_%d", num);
|
|
fr->m_pTexOffset0 = rd->m_TexMan->CreateTexture(name, m_dwWidth, m_dwHeight, 1, FT_NOMIPS, FT2_FILTER_NEAREST | FT2_RENDERTARGET, pixels, eTT_Base);
|
|
sprintf(name, "$FurTexOffset0_%d", num);
|
|
fr->m_pTexOffset1 = rd->m_TexMan->CreateTexture(name, m_dwWidth, m_dwHeight, 1, FT_NOMIPS, FT2_FILTER_NEAREST | FT2_RENDERTARGET, pixels, eTT_Base);
|
|
sprintf(name, "$FurNormalMap_%d", num);
|
|
fr->m_pTexNormal = rd->m_TexMan->CreateTexture(name, m_dwWidth, m_dwHeight, 1, FT_NOMIPS, FT2_RENDERTARGET, pixels, eTT_Base);
|
|
delete [] pixels;
|
|
ClearRenderTarget(rd->m_pd3dDevice, fr->m_pTexOffset0, 128, 128, 128, 128);
|
|
ClearRenderTarget(rd->m_pd3dDevice, fr->m_pTexOffset1, 128, 128, 128, 128);
|
|
ClearRenderTarget(rd->m_pd3dDevice, fr->m_pTexNormal, 128, 128, 128, 128);
|
|
}
|
|
fr->m_bPrepared = true;
|
|
}
|
|
fr->m_nUsedFrame = rd->GetFrameID();
|
|
fr->m_Trans = pos;
|
|
m_nCurInst = nInst;
|
|
// Inst 0 only for non-simulated fur
|
|
if (!nInst)
|
|
return;
|
|
|
|
static bool bUseGravity = true;
|
|
if ((GetAsyncKeyState('G') & 0x8000))
|
|
bUseGravity = true;
|
|
if ((GetAsyncKeyState('N') & 0x8000))
|
|
bUseGravity = false;
|
|
|
|
// gravity in model space
|
|
Vec3 gravity;
|
|
if (!bUseGravity)
|
|
gravity = Vec3(0,0,-0.01f);
|
|
else
|
|
{
|
|
user.m_Name = "furgravityx";
|
|
gravity.x = user.mfGet();
|
|
user.m_Name = "furgravityy";
|
|
gravity.y = user.mfGet();
|
|
user.m_Name = "furgravityz";
|
|
gravity.z = user.mfGet();
|
|
}
|
|
|
|
Vec3 velocity(0,0,0);
|
|
Vec3 omega(0,0,0);
|
|
Vec3 trGravity, trVelocity, trOmega;
|
|
Matrix44 &m = rd->m_RP.m_pCurObject->GetInvMatrix();
|
|
trGravity = m.TransformVectorOLD(gravity);
|
|
trVelocity = m.TransformVectorOLD(velocity);
|
|
trOmega = m.TransformVectorOLD(omega);
|
|
|
|
STexPic *pTexTarg, *pTexCur;
|
|
if (!(fr->m_nFrame & 1))
|
|
{
|
|
pTexTarg = fr->m_pTexOffset0;
|
|
pTexCur = fr->m_pTexOffset1;
|
|
}
|
|
else
|
|
{
|
|
pTexTarg = fr->m_pTexOffset1;
|
|
pTexCur = fr->m_pTexOffset0;
|
|
}
|
|
float filter = min(0.25f, dt/0.1f);
|
|
static float dt2 = 0.025f;
|
|
dt2 = 0.9f * dt2 + 0.1f * dt;
|
|
|
|
CD3D9TexMan::BindNULL(2);
|
|
|
|
// translational m_Acceleration
|
|
fr->m_Accel = (1.0f - filter) * fr->m_Accel + filter * ((trVelocity - fr->m_PrevVel) / dt2);
|
|
fr->m_PrevVel = trVelocity;
|
|
|
|
// angular m_Acceleration
|
|
fr->m_OmegaAccel = (1.0f - filter) * fr->m_OmegaAccel + filter * ((trOmega - fr->m_PrevOmega) / dt2);
|
|
fr->m_PrevOmega = trOmega;
|
|
|
|
float damping = max(0.0625f, min(0.5f, dt/0.3f));
|
|
|
|
// get current viewport
|
|
int iTmpX, iTmpY, iTempWidth, iTempHeight;
|
|
rd->GetViewport(&iTmpX, &iTmpY, &iTempWidth, &iTempHeight);
|
|
rd->SetViewport(0, 0, pTexTarg->m_Width, pTexTarg->m_Height);
|
|
|
|
LPDIRECT3DSURFACE9 pTexSurf;
|
|
LPDIRECT3DTEXTURE9 plD3DTexture;
|
|
plD3DTexture = (LPDIRECT3DTEXTURE9)pTexTarg->m_RefTex.m_VidTex;
|
|
plD3DTexture->GetSurfaceLevel(0, &pTexSurf);
|
|
// set current rendertarget
|
|
rd->EF_SetRenderTarget(pTexSurf, 1);
|
|
SAFE_RELEASE(pTexSurf);
|
|
|
|
int nFlags = rd->m_RP.m_FlagsModificators;
|
|
rd->m_RP.m_FlagsModificators = RBMF_TANGENTSUSED;
|
|
|
|
CCGVProgram_D3D *vpOffsGen = (CCGVProgram_D3D *)rd->m_RP.m_VPFur_OffsGen;
|
|
CCGPShader_D3D *fpOffsGen = (CCGPShader_D3D *)rd->m_RP.m_RCFur_OffsGen;
|
|
if (vpOffsGen && fpOffsGen)
|
|
{
|
|
vpOffsGen->mfSet(true, 0);
|
|
fpOffsGen->mfSet(true, 0);
|
|
|
|
vpOffsGen->mfParameter4f("Force", sfparam(trGravity - 0.12f*trVelocity - 0.018f*fr->m_Accel));
|
|
vpOffsGen->mfParameter4f("Omega", sfparam(0.12f*trOmega + 0.018f*fr->m_OmegaAccel));
|
|
vpOffsGen->mfParameter4f("Damping", sfparam(damping));
|
|
|
|
float v[4];
|
|
CREOcLeaf *re = (CREOcLeaf *)rd->m_RP.m_pRE;
|
|
CLeafBuffer *lb = re->m_pBuffer;
|
|
v[2] = -lb->m_fMinU;
|
|
v[0] = 1.0f / (lb->m_fMaxU + v[2]);
|
|
v[3] = -lb->m_fMinV;
|
|
v[1] = 1.0f / (lb->m_fMaxV + v[3]);
|
|
vpOffsGen->mfParameter4f("ScaleBiasTC", v);
|
|
|
|
rd->EF_SelectTMU(0);
|
|
pTexCur->Set();
|
|
rd->EF_SelectTMU(1);
|
|
m_pTexClamp->Set();
|
|
|
|
rd->SetCullMode(R_CULL_NONE);
|
|
rd->EF_SetState(GS_NODEPTHTEST);
|
|
rd->EF_Draw(rd->m_RP.m_pShader, NULL);
|
|
|
|
vpOffsGen->mfSet(false, 0);
|
|
fpOffsGen->mfSet(false, 0);
|
|
}
|
|
plD3DTexture = (LPDIRECT3DTEXTURE9)fr->m_pTexNormal->m_RefTex.m_VidTex;
|
|
plD3DTexture->GetSurfaceLevel(0, &pTexSurf);
|
|
// set current rendertarget
|
|
rd->EF_SetRenderTarget(pTexSurf, 1);
|
|
SAFE_RELEASE(pTexSurf);
|
|
|
|
CCGVProgram_D3D *vpNormGen = (CCGVProgram_D3D *)rd->m_RP.m_VPFur_NormGen;
|
|
CCGPShader_D3D *fpNormGen = (CCGPShader_D3D *)rd->m_RP.m_RCFur_NormGen;
|
|
if (vpNormGen && fpNormGen)
|
|
{
|
|
vpNormGen->mfSet(true, 0);
|
|
fpNormGen->mfSet(true, 0);
|
|
|
|
rd->EF_SelectTMU(0);
|
|
pTexTarg->Set();
|
|
rd->EF_SelectTMU(1);
|
|
m_pTexNormalize->Set();
|
|
|
|
// setup screen aligned quad
|
|
struct_VERTEX_FORMAT_P3F_TEX2F pScreen[] =
|
|
{
|
|
Vec3(-1, -1, 0), 0, 1,
|
|
Vec3(-1, 1, 0), 0, 0,
|
|
Vec3(1, -1, 0), 1, 1,
|
|
Vec3(1, 1, 0), 1, 0,
|
|
};
|
|
rd->DrawTriStrip(&(CVertexBuffer (pScreen,VERTEX_FORMAT_P3F_TEX2F)), 4);
|
|
|
|
vpNormGen->mfSet(false, 0);
|
|
fpNormGen->mfSet(false, 0);
|
|
}
|
|
rd->EF_RestoreRenderTarget();
|
|
rd->SetViewport(iTmpX, iTmpY, iTempWidth, iTempHeight);
|
|
rd->m_RP.m_FlagsModificators = nFlags;
|
|
|
|
fr->m_nFrame++;
|
|
}
|
|
|
|
void CD3D9TexMan::GenerateFurNormalMap()
|
|
{
|
|
gRenDev->m_TexMan->m_Text_FurNormalMap = LoadTexture("$FurNormalMap", FT_CLAMP | FT_NOREMOVE, FT2_NODXT);
|
|
|
|
CFurNormalMap *pFurNormalMap = new CFurNormalMap(gRenDev->m_TexMan->m_Text_FurNormalMap, 64, 32);
|
|
gRenDev->m_TexMan->m_Text_FurNormalMap->m_pFuncMap = pFurNormalMap;
|
|
pFurNormalMap->Initialize();
|
|
}
|
|
|
|
void CD3D9TexMan::GenerateFurLightMap()
|
|
{
|
|
// texture size (as small as possible in order to minimize cache miss rate)
|
|
int s_size = 16;
|
|
int t_size = 32;
|
|
int r_size = 16;
|
|
|
|
// exponents for diffuse and specular
|
|
float diff_power = 6;
|
|
float spec_power = 32;
|
|
|
|
byte *pixels = new byte[2*s_size*t_size*r_size];
|
|
byte *p = pixels;
|
|
|
|
for(int k=0; k<r_size; k++)
|
|
for(int j=0; j<t_size; j++)
|
|
for(int i=0; i<s_size; i++)
|
|
{
|
|
float LN = float(i)/(s_size-1); // s = L dot N
|
|
float HN = float(j)/(t_size-1); // t = H dot N
|
|
float Lz = float(2*k)/(r_size-1) - 1; // r = L.z
|
|
|
|
float diffuse = 0.2f + 0.2f * max(0, Lz) + 0.6f * powf(1 - LN*LN, 0.5f*diff_power);
|
|
float specular = powf(1 - HN*HN, 0.5f*spec_power);
|
|
float shadow = powf(cosf(D3DX_PI/2 * CLAMP(-0.2f-1.4f*Lz, 0.0f, 1.0f)), 4);
|
|
|
|
*p++ = (unsigned char)(255 * CLAMP(diffuse, 0.0f, 1.0f));
|
|
*p++ = (unsigned char)(255 * CLAMP(specular*shadow, 0.0f, 1.0f));
|
|
}
|
|
|
|
gRenDev->m_TexMan->m_Text_FurLightMap = CreateTexture("$FurLightMap", s_size, t_size, r_size, FT_CLAMP | FT_NOMIPS, FT2_NODXT, pixels, eTT_3D, -1, -1, 0, NULL, 0, eTF_0088);
|
|
gRenDev->m_TexMan->m_Text_FurLightMap->m_RefTex.bRepeats = 2;
|
|
}
|
|
|
|
//========================================================================
|
|
|
|
void CD3D9TexMan::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;
|
|
}
|
|
}
|
|
gRenDev->m_TexMan->m_Text_Flare = CreateTexture("$Flare", 32, 4, 1, FT_CLAMP | FT_NOREMOVE, FT2_NODXT | FT2_NOANISO, &data[0][0][0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
|
|
}
|
|
|
|
#define NOISE_DIMENSION 128
|
|
#define NOISE_MIP_LEVELS 1
|
|
|
|
static float s_Noise[NOISE_DIMENSION][NOISE_DIMENSION][NOISE_DIMENSION];
|
|
static double drand48(void)
|
|
{
|
|
double dVal;
|
|
dVal=(double)rand()/(double)RAND_MAX;
|
|
|
|
return dVal;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: InitWhiteNoiseArray()
|
|
// Desc: Initializes a user memory array of white noise which will be used
|
|
// during noise texture generation
|
|
//-----------------------------------------------------------------------------
|
|
static void InitWhiteNoiseArray (void)
|
|
{
|
|
int i,j,k;
|
|
|
|
for (i=0; i<NOISE_DIMENSION; i++)
|
|
{
|
|
for (j=0; j<NOISE_DIMENSION; j++)
|
|
{
|
|
for (k=0; k<NOISE_DIMENSION; k++)
|
|
{
|
|
s_Noise[i][j][k] = (float)drand48();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: lerpNoise()
|
|
// Desc: Helper function which does wrapped interpolation of noise. This is
|
|
// necessary for generating tilable noise
|
|
//-----------------------------------------------------------------------------
|
|
float lerpNoise(float x, float y,float z, int wrapX, int wrapY, int wrapZ)
|
|
{
|
|
int ix,iy,iz,ixd,iyd,izd; // integer parts of index into texture array
|
|
float rx,ry,rz; // fractional part of xyz
|
|
float accum; // value returned
|
|
|
|
ix=((int)x);
|
|
iy=((int)y);
|
|
iz=((int)z);
|
|
|
|
rx=x-(float)ix;
|
|
ry=y-(float)iy;
|
|
rz=z-(float)iz;
|
|
ix=ix&(wrapX-1);
|
|
iy=iy&(wrapY-1);
|
|
iz=iz&(wrapZ-1);
|
|
ixd=(ix+1)&(wrapX-1);
|
|
iyd=(iy+1)&(wrapY-1);
|
|
izd=(iz+1)&(wrapZ-1);
|
|
|
|
accum=0;
|
|
accum+=rx*ry*rz*s_Noise[izd][iyd][ixd];
|
|
accum+=(1-rx)*ry*rz*s_Noise[izd][iyd][ix];
|
|
accum+=rx*(1-ry)*rz*s_Noise[izd][iy][ixd];
|
|
accum+=(1-rx)*(1-ry)*rz*s_Noise[izd][iy][ix];
|
|
|
|
accum+=rx*ry*(1-rz)*s_Noise[iz][iyd][ixd];
|
|
accum+=(1-rx)*ry*(1-rz)*s_Noise[iz][iyd][ix];
|
|
accum+=rx*(1-ry)*(1-rz)*s_Noise[iz][iy][ixd];
|
|
accum+=(1-rx)*(1-ry)*(1-rz)*s_Noise[iz][iy][ix];
|
|
|
|
return accum;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: turbulence()
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
float turbulence(float x, float y, float z, int wrapX, int wrapY, int wrapZ, float maxScale)
|
|
{
|
|
float t=0;
|
|
float scale = maxScale;
|
|
|
|
while(scale>=1)
|
|
{
|
|
t+=lerpNoise(x/scale, y/scale, z/scale, wrapX/(int)scale, wrapY/(int)scale, wrapZ/(int)scale) * 128*(scale/maxScale);
|
|
scale/=2.0f;
|
|
}
|
|
|
|
return(t);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name: turbulenceFill()
|
|
// Desc: Passed to D3DXFillVolumeTexture to fill in noise volume texture
|
|
//-----------------------------------------------------------------------------
|
|
VOID WINAPI turbulenceFill (D3DXVECTOR4* pOut, const D3DXVECTOR3* pTexCoord, const D3DXVECTOR3* pTexelSize, LPVOID pData)
|
|
{
|
|
float fSX = 1.0f / pTexelSize->x;
|
|
float fSY = 1.0f / pTexelSize->y;
|
|
float fSZ = 1.0f / pTexelSize->z;
|
|
float turb = turbulence(pTexCoord->x*fSX, pTexCoord->y*fSY, pTexCoord->z*fSZ, (int)fSX, (int)fSY, (int)fSZ, fSZ/4) / 256.0f; // Get turbulence from tilable noise
|
|
|
|
turb = max(0.0f, min(1.0f, turb)); // Clamp
|
|
|
|
*pOut = D3DXVECTOR4(turb, turb, turb, turb);
|
|
}
|
|
|
|
void CD3D9TexMan::GenerateNoiseVolumeMap()
|
|
{
|
|
InitWhiteNoiseArray();
|
|
|
|
HRESULT hr;
|
|
LPDIRECT3DVOLUMETEXTURE9 pID3DVolTexture = NULL;
|
|
|
|
if (FAILED(hr=D3DXCreateVolumeTexture (gcpRendD3D->mfGetD3DDevice(), NOISE_DIMENSION, NOISE_DIMENSION, NOISE_DIMENSION, NOISE_MIP_LEVELS, 0, D3DFMT_A8, D3DPOOL_MANAGED ,&pID3DVolTexture)))
|
|
return;
|
|
|
|
if (FAILED(hr=D3DXFillVolumeTexture (pID3DVolTexture, turbulenceFill, NULL)))
|
|
return;
|
|
|
|
if (!gRenDev->m_TexMan->m_Text_NoiseVolumeMap)
|
|
gRenDev->m_TexMan->m_Text_NoiseVolumeMap = LoadTexture("$NoiseVolume", FT_NOREMOVE | FT_NOSTREAM | FT_NOMIPS, FT2_NODXT, eTT_3D, -1.0f, -1.0f, -1);
|
|
STexPicD3D *ti = (STexPicD3D *)gRenDev->m_TexMan->m_Text_NoiseVolumeMap;
|
|
ti->m_RefTex.m_VidTex = (void *)pID3DVolTexture;
|
|
ti->m_RefTex.m_MipFilter = D3DTEXF_NONE;
|
|
ti->m_RefTex.m_MinFilter = D3DTEXF_LINEAR;
|
|
ti->m_RefTex.m_MagFilter = D3DTEXF_LINEAR;
|
|
ti->m_RefTex.m_AnisLevel = 1;
|
|
ti->m_RefTex.bRepeats = true;
|
|
ti->m_RefTex.m_Type = TEXTGT_3D;
|
|
ti->m_DstFormat = D3DFMT_A8;
|
|
ti->m_Width = NOISE_DIMENSION;
|
|
ti->m_Height = NOISE_DIMENSION;
|
|
ti->m_Depth = NOISE_DIMENSION;
|
|
CD3D9TexMan::CalcMipsAndSize(ti);
|
|
AddToHash(ti->m_Bind, ti);
|
|
ti->Unlink();
|
|
ti->Link(&STexPic::m_Root);
|
|
gRenDev->m_TexMan->m_StatsCurTexMem += ti->m_Size;
|
|
}
|
|
|
|
//=================================================================================
|
|
|
|
VOID WINAPI FillAttenuationTexture(D3DXVECTOR4* pOut, const D3DXVECTOR2* pTexCoord, const D3DXVECTOR2* pTexelSize, LPVOID pData)
|
|
{
|
|
const unsigned int index = unsigned int(pTexCoord->y * float(NUM_ATTENUATION_FUNCTIONS) * float(BILERP_PROTECTION));
|
|
const unsigned int matNum = index / BILERP_PROTECTION;
|
|
|
|
if ( matNum <= AF_LINEAR )
|
|
{
|
|
// just flip things over so at distance 0 attenuation = 1
|
|
float atten = 1.f - pTexCoord->x;
|
|
pOut->x = atten;
|
|
}
|
|
else
|
|
if ( matNum <= AF_SQUARED )
|
|
{
|
|
// square the flipped input
|
|
float atten = 1.f - pTexCoord->x;
|
|
atten = atten * atten;
|
|
pOut->x = atten;
|
|
}
|
|
else
|
|
if ( matNum <= AF_SHAPE1 )
|
|
{
|
|
// a constant start (for 0.5f)then linear to 0 at in->x = 1
|
|
float atten = 1.f - pTexCoord->x;
|
|
atten = (atten * 1.5f);
|
|
if( atten > 1 )
|
|
atten = 1;
|
|
pOut->x = atten;
|
|
}
|
|
else
|
|
if ( matNum <= AF_SHAPE2 )
|
|
{
|
|
// a constant start (for 0.3f) then squared to 0 at in->x = 1
|
|
float atten = 1.f - pTexCoord->x;
|
|
atten = (atten * 1.3f);
|
|
if( atten > 1 )
|
|
atten = 1;
|
|
atten /= 1.3f;
|
|
atten = atten * atten;
|
|
pOut->x = atten;
|
|
}
|
|
if( pTexCoord->x > 0.9999f )
|
|
{
|
|
pOut->x = 0;
|
|
}
|
|
pOut->y = pOut->x;
|
|
pOut->z = pOut->x;
|
|
pOut->w = pOut->x;
|
|
}
|
|
|
|
void CD3D9TexMan::GenerateAttenMap()
|
|
{
|
|
LPDIRECT3DTEXTURE9 pTexture;
|
|
|
|
if (!gcpRendD3D->mFormatU16V16.BitsPerPixel)
|
|
return;
|
|
|
|
CD3D9Renderer *rd = gcpRendD3D;
|
|
bool bMips = false;
|
|
D3DFORMAT d3dFMT;
|
|
if (rd->mFormatA8L8.BitsPerPixel)
|
|
d3dFMT = D3DFMT_A8L8;
|
|
else
|
|
if (rd->mFormatA8.BitsPerPixel)
|
|
d3dFMT = D3DFMT_A8;
|
|
int nWidth = ATTENUATION_WIDTH;
|
|
int nHeight = NUM_ATTENUATION_FUNCTIONS * BILERP_PROTECTION;
|
|
// Create attenuation texture
|
|
if (FAILED(gcpRendD3D->mfGetD3DDevice()->CreateTexture(nWidth, nHeight, 1, 0, d3dFMT, D3DPOOL_MANAGED, &pTexture, NULL)))
|
|
return;
|
|
if (FAILED(D3DXFillTexture(pTexture, FillAttenuationTexture, 0)))
|
|
return;
|
|
|
|
int nFlags = FT_NOREMOVE | FT_NOSTREAM | FT_CLAMP;
|
|
if (!bMips)
|
|
nFlags |= FT_NOMIPS;
|
|
STexPicD3D *ti = (STexPicD3D *)LoadTexture("$Attenuation1D", nFlags, FT2_NODXT | FT2_NOANISO, eTT_Base, -1.0f, -1.0f);
|
|
ti->m_RefTex.m_VidTex = (void *)pTexture;
|
|
ti->m_RefTex.m_MipFilter = bMips ? GetMipFilter() : D3DTEXF_NONE;
|
|
ti->m_RefTex.m_MinFilter = GetMinFilter();
|
|
ti->m_RefTex.m_MagFilter = GetMagFilter();
|
|
ti->m_RefTex.m_AnisLevel = 1;
|
|
ti->m_RefTex.m_Type = TEXTGT_2D;
|
|
ti->m_DstFormat = d3dFMT;
|
|
ti->m_Width = nWidth;
|
|
ti->m_Height = nHeight;
|
|
CD3D9TexMan::CalcMipsAndSize(ti);
|
|
AddToHash(ti->m_Bind, ti);
|
|
ti->Unlink();
|
|
ti->Link(&STexPic::m_Root);
|
|
gRenDev->m_TexMan->m_StatsCurTexMem += ti->m_Size;
|
|
gRenDev->m_TexMan->m_Text_Atten1D = ti;
|
|
}
|
|
|
|
void CD3D9TexMan::GenerateDepthLookup()
|
|
{
|
|
int i;
|
|
|
|
DWORD data[2048];
|
|
DWORD* pMap = data;
|
|
for (i=0; i<2048; i++)
|
|
{
|
|
*pMap++ = D3DCOLOR_RGBA(i&0xFF, (i&0xFF00)>>3, 0, 0);
|
|
}
|
|
gRenDev->m_TexMan->m_Text_DepthLookup = CreateTexture("$DepthMap", 2048, 1, 1, FT_CLAMP | FT_NOREMOVE | FT_HASALPHA | FT_NOMIPS | FT_PROJECTED, FT2_NODXT | FT2_NOANISO, (byte *)&data[0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
|
|
|
|
|
|
DWORD data2[4][4];
|
|
pMap = &data2[0][0];
|
|
for (i=0; i<4*4; i++)
|
|
{
|
|
*pMap++ = D3DCOLOR_RGBA(0xff, 0xe0, 0, 0 );
|
|
}
|
|
gRenDev->m_TexMan->m_Text_Depth = CreateTexture("$Depth", 4, 4, 1, FT_CLAMP | FT_NOREMOVE | FT_HASALPHA | FT_NOMIPS, FT2_NODXT, (byte *)&data2[0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
|
|
|
|
pMap = &data2[0][0];
|
|
for (i=0; i<4*4; i++)
|
|
{
|
|
*pMap++ = D3DCOLOR_RGBA(0xff, 0xff, 0xff, 0 );
|
|
}
|
|
gRenDev->m_TexMan->m_Text_WhiteShadow = CreateTexture("$WhiteShadow", 4, 4, 1, FT_CLAMP | FT_NOREMOVE | FT_HASALPHA | FT_NOMIPS, FT2_NODXT | FT2_NOANISO, (byte *)&data2[0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
|
|
|
|
byte data3[256];
|
|
byte *pbMap = &data3[0];
|
|
for (i=0; i<256; i++)
|
|
{
|
|
*pbMap++ = i;
|
|
}
|
|
gRenDev->m_TexMan->m_Text_Gradient = CreateTexture("$AlphaGradient", 256, 1, 1, FT_NOREMOVE | FT_HASALPHA | FT_NOMIPS, FT2_NODXT | FT2_NOANISO, (byte *)&data3[0], eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8000);
|
|
//gRenDev->m_TexMan->m_Text_Depth->SaveTGA("Depth.tga", false);
|
|
}
|
|
|
|
#include "D3DCubemaps.h"
|
|
|
|
void CD3D9TexMan::GenerateFuncTextures()
|
|
{
|
|
LPDIRECT3DCUBETEXTURE9 pNormCubeTexture;
|
|
LPDIRECT3DCUBETEXTURE9 pLightCubeTexture;
|
|
if (gRenDev->GetFeatures() & RFT_BUMP)
|
|
{
|
|
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)))
|
|
MakeCubeMap<SNormalizeVector>(norm, pNormCubeTexture, 256, true);
|
|
if (!gRenDev->m_TexMan->m_Text_NormalizeCMap)
|
|
gRenDev->m_TexMan->m_Text_NormalizeCMap = LoadTexture("$NormalizeCMap", FT_NOREMOVE | FT_NOSTREAM, FT2_NODXT, eTT_Cubemap, -1.0f, -1.0f, TO_NORMALIZE_CUBE_MAP);
|
|
STexPicD3D *ti = (STexPicD3D *)gRenDev->m_TexMan->m_Text_NormalizeCMap;
|
|
ti->m_RefTex.m_VidTex = (void *)pNormCubeTexture;
|
|
ti->m_RefTex.m_MipFilter = GetMipFilter();
|
|
ti->m_RefTex.m_MinFilter = GetMinFilter();
|
|
ti->m_RefTex.m_MagFilter = GetMagFilter();
|
|
ti->m_RefTex.m_AnisLevel = 1;
|
|
ti->m_RefTex.m_Type = TEXTGT_CUBEMAP;
|
|
ti->m_DstFormat = D3DFMT_X8R8G8B8;
|
|
ti->m_Width = 256;
|
|
ti->m_Height = 256;
|
|
CD3D9TexMan::CalcMipsAndSize(ti);
|
|
ti->m_Size *= 6;
|
|
AddToHash(ti->m_Bind, ti);
|
|
ti->Unlink();
|
|
ti->Link(&STexPic::m_Root);
|
|
gRenDev->m_TexMan->m_StatsCurTexMem += ti->m_Size;
|
|
CheckTexLimits(NULL);
|
|
}
|
|
|
|
GenerateFogMaps();
|
|
GenerateFlareMap();
|
|
GenerateGhostMap();
|
|
GenerateDepthLookup();
|
|
GenerateAttenMap();
|
|
if (CRenderer::CV_r_Quality_BumpMapping > 2 && (gRenDev->GetFeatures() & RFT_HW_PS20))
|
|
{
|
|
//GenerateNoiseVolumeMap();
|
|
GenerateFurMap();
|
|
GenerateFurNormalMap();
|
|
GenerateFurLightMap();
|
|
}
|
|
|
|
//byte *dat = new byte[16*16*2];
|
|
//gRenDev->DownLoadToVideoMemory(dat, 16, 16, eTF_4444, eTF_4444, 1);
|
|
}
|
|
|
|
void STexPic::Preload (int Flags)
|
|
{
|
|
}
|
|
void STexPicD3D::Preload (int Flags)
|
|
{
|
|
IDirect3DTexture9 *pID3DTexture = NULL;
|
|
IDirect3DCubeTexture9 *pID3DCubeTexture = NULL;
|
|
if (m_Flags2 & FT2_RENDERTARGET)
|
|
return;
|
|
if (m_eTT == eTT_Cubemap)
|
|
{
|
|
pID3DCubeTexture = (IDirect3DCubeTexture9*)m_RefTex.m_VidTex;
|
|
if (pID3DCubeTexture)
|
|
pID3DCubeTexture->PreLoad();
|
|
}
|
|
else
|
|
{
|
|
pID3DTexture = (IDirect3DTexture9*)m_RefTex.m_VidTex;
|
|
if (pID3DTexture)
|
|
pID3DTexture->PreLoad();
|
|
}
|
|
}
|