/*============================================================================= 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 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; nSm_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; im_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; imfSetTexture(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; im_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; im_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; jUnlockRect((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; jUnlockRect(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; iGetSurfaceLevel(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; im_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; iLockBox(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>= 1; h >>= 1; d >>= 1; pID3DVolTexture->UnlockBox(i); } } else { for (i=0; im_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; im_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; im_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; lm_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; lm_nMips; l++) { if (!w) w = 1; if (!h) h = 1; for (i=0; i>= 1; h >>= 1; } } else { dst1 = new byte [wdt*hgt*4]; byte *ds1 = dst1; byte *ds = dst; for (i=0; im_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; im_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 (jm_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; iUnlockRect(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; im_TexSize; i++) { byte *pSrc = &pData[d3dlr.Pitch*i]; for (j=0; jm_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; nm_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; iUnlockRect(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; nm_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; iUnlockRect(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); } // <> 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; im_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 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; im_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; im_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; im_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; im_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; im_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; im_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; im_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; im_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 Texs; TArray TexsNM; int i; for (i=0; im_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; nnm_eTT == eTT_Bumpmap) TexsNM.AddElem(m_Textures[i]); } } } int nNOTO = 0; for (i=0; im_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; im_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; im_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; im_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; jmfGetD3DDevice(), 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_nCurInstm_Layers.Num() * max(0.0f, min(0.9999f, layer))); fl->m_Layers[temp]->Set(); } void CFurMap::Update(int nNumLayers) { int nInst; for (nInst=0; nInstm_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; im_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; xGetTrue(); 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 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 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_nCurInstm_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; nInstm_Trans-pos).Length() < 0.25f) break; } if (nInst == m_Inst.Num()) { int nFr = -1; for (i=1; i (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; km_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=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(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(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(); } }