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

4483 lines
130 KiB
C++

/*=============================================================================
DriverD3D9.cpp : Direct3D Render interface implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "DriverD3D9.h"
#include "D3DCGVProgram.h"
#include "D3DCGPShader.h"
#include <windows.h>
#include "IStatObj.h"
CD3D9Renderer *gcpRendD3D;
int CD3D9Renderer::CV_d3d9_texture_filter_anisotropic;
int CD3D9Renderer::CV_d3d9_nodeviceid;
int CD3D9Renderer::CV_d3d9_nvperfhud;
int CD3D9Renderer::CV_d3d9_palettedtextures;
int CD3D9Renderer::CV_d3d9_vbpools;
int CD3D9Renderer::CV_d3d9_vbpoolsize;
int CD3D9Renderer::CV_d3d9_nv30_ps20;
int CD3D9Renderer::CV_d3d9_occlusion_query;
int CD3D9Renderer::CV_d3d9_compressedtextures;
int CD3D9Renderer::CV_d3d9_usebumpmap;
int CD3D9Renderer::CV_d3d9_clipplanes;
int CD3D9Renderer::CV_d3d9_triplebuffering;
int CD3D9Renderer::CV_d3d9_resetdeviceafterloading;
int CD3D9Renderer::CV_d3d9_savedepthmaps;
int CD3D9Renderer::CV_d3d9_forcesoftware;
int CD3D9Renderer::CV_d3d9_texturebits;
int CD3D9Renderer::CV_d3d9_texmipfilter; // 0-point; 1-box; 2-linear; 3-triangle;
int CD3D9Renderer::CV_d3d9_mipprocedures;
int CD3D9Renderer::CV_d3d9_squaretextures;
ICVar *CD3D9Renderer::CV_d3d9_device;
int CD3D9Renderer::CV_d3d9_allowsoftware;
float CD3D9Renderer::CV_d3d9_pip_buff_size;
int CD3D9Renderer::CV_d3d9_rb_verts;
int CD3D9Renderer::CV_d3d9_rb_tris;
int CD3D9Renderer::CV_d3d9_decaloffset;
int CD3D9Renderer::CV_d3d9_nodepthmaps;
float CD3D9Renderer::CV_d3d9_normalmapscale;
ICVar *CD3D9Renderer::CV_d3d9_texturefilter;
char *resourceName[] = {
"UNKNOWN",
"Surfaces",
"Volumes",
"Textures",
"Volume Textures",
"Cube Textures",
"Vertex Buffers",
"Index Buffers"
};
// Direct 3D console variables
CD3D9Renderer::CD3D9Renderer()
{
m_bInitialized = false;
gcpRendD3D = this;
gRenDev = this;
m_TexMan = new CD3D9TexMan;
m_TexMan->m_bRGBA = false;
m_LogFile = NULL;
RegisterVariables();
m_pD3D = NULL;
m_pd3dDevice = NULL;
m_hWnd = NULL;
m_bActive = FALSE;
m_bReady = FALSE;
m_dwCreateFlags = 0L;
m_pVB2D = NULL;
m_pVB3D[0] = NULL;
m_pVB3D[1] = NULL;
m_pVB3D[2] = NULL;
m_fLineWidth = 1.0f;
m_strDeviceStats[0] = 0;
m_MinDepthBits = 16;
m_MinStencilBits = 0;
m_eCull = (ECull)-1;
m_Features = RFT_DIRECTACCESSTOVIDEOMEMORY | RFT_SUPPORTZBIAS;
iConsole->Register("d3d9_Texture_Filter_Anisotropic", &CV_d3d9_texture_filter_anisotropic, 0);
iConsole->Register("d3d9_NodeviceId", &CV_d3d9_nodeviceid, 0);
iConsole->Register("d3d9_NVPerfHUD", &CV_d3d9_nvperfhud, 0);
iConsole->Register("d3d9_PalettedTextures", &CV_d3d9_palettedtextures, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_VBPools", &CV_d3d9_vbpools, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_VBPoolSize", &CV_d3d9_vbpoolsize, 256*1024);
iConsole->Register("d3d9_NV30_PS20", &CV_d3d9_nv30_ps20, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_Occlusion_Query", &CV_d3d9_occlusion_query, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_CompressedTextures", &CV_d3d9_compressedtextures, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_UseBumpmap", &CV_d3d9_usebumpmap, 1);
iConsole->Register("d3d9_ClipPlanes", &CV_d3d9_clipplanes, 1);
iConsole->Register("d3d9_TripleBuffering", &CV_d3d9_triplebuffering, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_ResetDeviceAfterLoading", &CV_d3d9_resetdeviceafterloading, 1);
iConsole->Register("d3d9_SaveDepthmaps", &CV_d3d9_savedepthmaps, 0);
iConsole->Register("d3d9_ForceSoftware", &CV_d3d9_forcesoftware, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_TextureBits", &CV_d3d9_texturebits, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_MipProcedures", &CV_d3d9_mipprocedures, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_TexMipFilter", &CV_d3d9_texmipfilter, 1, VF_REQUIRE_LEVEL_RELOAD); // 0-point; 1-linear;
CV_d3d9_texturefilter = iConsole->CreateVariable("d3d9_TextureFilter", "TRILINEAR", VF_DUMPTODISK,
"Specifies D3D specific texture filtering type.\n"
"Usage: d3d9_TexMipFilter [TRILINEAR/BILINEAR/LINEAR/NEAREST]\n");
iConsole->Register("d3d9_SquareTextures", &CV_d3d9_squaretextures, 0);
CV_d3d9_device = iConsole->CreateVariable("d3d9_Device", "Auto", 0,
"Specifies D3D specific device name.\n"
"Usage: d3d9_Device [Auto/Second/Primary]\n");
iConsole->Register("d3d9_AllowSoftware", &CV_d3d9_allowsoftware, 1, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_pip_buff_size", &CV_d3d9_pip_buff_size, 50, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_rb_Verts", &CV_d3d9_rb_verts, 2048, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_rb_Tris", &CV_d3d9_rb_tris, 4096, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_DecalOffset", &CV_d3d9_decaloffset, 15);
iConsole->Register("d3d9_NoDepthMaps", &CV_d3d9_nodepthmaps, 0, VF_REQUIRE_APP_RESTART);
iConsole->Register("d3d9_NormalMapScale", &CV_d3d9_normalmapscale, 0.15f, VF_REQUIRE_LEVEL_RELOAD);
}
CD3D9Renderer::~CD3D9Renderer()
{
//FreeResources(FRR_ALL);
ShutDown();
}
void CD3D9Renderer::ShareResources( IRenderer *renderer )
{
}
void CD3D9Renderer::MakeCurrent()
{
if (m_CurrContext == m_RContexts[0])
return;
m_CurrContext = m_RContexts[0];
CVProgram::m_LastVP = NULL;
CPShader::m_CurRC = NULL;
}
bool CD3D9Renderer::SetCurrentContext(WIN_HWND hWnd)
{
int i;
for (i=0; i<m_RContexts.Num(); i++)
{
if (m_RContexts[i]->m_hWnd == hWnd)
break;
}
if (i == m_RContexts.Num())
return false;
if (m_CurrContext == m_RContexts[i])
return true;
m_CurrContext = m_RContexts[i];
CVProgram::m_LastVP = NULL;
CPShader::m_CurRC = NULL;
return true;
}
bool CD3D9Renderer::CreateContext(WIN_HWND hWnd, bool bAllowFSAA)
{
int i;
for (i=0; i<m_RContexts.Num(); i++)
{
if (m_RContexts[i]->m_hWnd == hWnd)
break;
}
if (i != m_RContexts.Num())
return true;
SD3DContext *pContext = new SD3DContext;
pContext->m_hWnd = (HWND)hWnd;
pContext->m_X = 0;
pContext->m_Y = 0;
pContext->m_Width = m_width;
pContext->m_Height = m_height;
m_CurrContext = pContext;
m_RContexts.AddElem(pContext);
return true;
}
bool CD3D9Renderer::DeleteContext(WIN_HWND hWnd)
{
int i, j;
for (i=0; i<m_RContexts.Num(); i++)
{
if (m_RContexts[i]->m_hWnd == hWnd)
break;
}
if (i == m_RContexts.Num())
return false;
if (m_CurrContext == m_RContexts[i])
{
for (j=0; j<m_RContexts.Num(); j++)
{
if (m_RContexts[j]->m_hWnd != hWnd)
{
m_CurrContext = m_RContexts[j];
break;
}
}
if (j == m_RContexts.Num())
m_CurrContext = NULL;
}
delete m_RContexts[i];
m_RContexts.Remove(i, 1);
return true;
}
//-----------------------------------------------------------------------------
// Name: CD3D9Renderer::DeleteDeviceObjects()
// Desc: Called when the app is exiting, or the device is being changed,
// this function deletes any device dependent objects.
//-----------------------------------------------------------------------------
HRESULT CD3D9Renderer::DeleteDeviceObjects()
{
return S_OK;
}
void CD3D9Renderer::RegisterVariables()
{
}
void CD3D9Renderer::UnRegisterVariables()
{
}
void CD3D9Renderer::WaitForDevice()
{
if (m_bEditor)
return;
int *nLost = (int *)EF_Query(EFQ_DeviceLost, 0);
if (!*nLost)
return;
if (m_hWnd)
{
MSG msg;
// Don't make any steps while 3D device is lost
while (true)
{
while (PeekMessage(&msg, (HWND)m_hWnd, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
nLost = (int *)EF_Query(EFQ_DeviceLost, 0);
if (!*nLost)
break;
}
}
}
void CD3D9Renderer::Reset (void)
{
if (!CV_d3d9_resetdeviceafterloading)
return;
HRESULT hReturn;
m_bDeviceLost = true;
//iLog->Log("...Reset");
if (m_bFullScreen)
RestoreGamma();
if(FAILED(hReturn = Reset3DEnvironment()))
return;
m_bDeviceLost = false;
if (m_bFullScreen)
SetGamma(CV_r_gamma+m_fDeltaGamma, CV_r_brightness, CV_r_contrast, false);
hReturn = m_pd3dDevice->BeginScene();
}
bool CD3D9Renderer::ChangeResolution(int nNewWidth, int nNewHeight, int nNewColDepth, int nNewRefreshHZ, bool bFullScreen)
{
HRESULT hReturn;
iLog->Log("Change resolution: %dx%dx%d (%s)", nNewWidth, nNewHeight, nNewColDepth, bFullScreen ? "Fullscreen" : "Windowed");
int nPrevWidth = CRenderer::m_width;
int nPrevHeight = CRenderer::m_height;
int nPrevColorDepth = CRenderer::m_cbpp;
bool bPrevFullScreen = m_bFullScreen;
if (nNewWidth < 512)
nNewWidth = 512;
if (nNewHeight < 300)
nNewHeight = 300;
if (nNewColDepth < 24)
nNewColDepth = 16;
else
nNewColDepth = 32;
if (!bFullScreen)
{
if (nNewWidth > m_deskwidth-16)
nNewWidth = m_deskwidth-16;
if (nNewHeight > m_deskheight-32)
nNewHeight = m_deskheight-32;
}
// Save the new dimensions
CRenderer::m_width = nNewWidth;
CRenderer::m_height = nNewHeight;
CRenderer::m_cbpp = nNewColDepth;
m_bFullScreen = bFullScreen;
if (bFullScreen && nNewColDepth == 16)
{
CRenderer::m_zbpp = 16;
CRenderer::m_sbpp = 0;
}
DeleteContext(m_hWnd);
ChooseDevice();
D3DAdapterInfo* pAdapterInfo = m_D3DSettings.PAdapterInfo();
D3DDeviceInfo* pDeviceInfo = m_D3DSettings.PDeviceInfo();
D3DDISPLAYMODE ModeInfo = m_D3DSettings.DisplayMode();
// Prepare window for possible windowed/fullscreen change
AdjustWindowForChange();
SetRendParms(&ModeInfo, pDeviceInfo);
// Set up the presentation parameters
int nFlags = m_d3dpp.Flags;
BuildPresentParamsFromSettings();
m_d3dpp.Flags = nFlags;
if (m_bFullScreen)
RestoreGamma();
m_bDeviceLost = true;
if(FAILED(hReturn = Reset3DEnvironment()))
{
if (m_nRecurs)
return false;
m_nRecurs = 1;
ChangeResolution(nPrevWidth, nPrevHeight, nPrevColorDepth, 0, bPrevFullScreen);
return false;
}
if (!bFullScreen)
{
int x = (m_deskwidth-CRenderer::m_width)/2;
int y = (m_deskheight-CRenderer::m_height)/2;
int wdt = GetSystemMetrics(SM_CXDLGFRAME)*2 + CRenderer::m_width;
int hgt = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXDLGFRAME)*2 + CRenderer::m_height;
SetWindowPos(m_hWnd, HWND_NOTOPMOST, x, y, wdt, hgt, SWP_SHOWWINDOW);
}
// Save window properties
GetWindowRect( m_hWnd, &m_rcWindowBounds );
GetClientRect( m_hWnd, &m_rcWindowClient );
hReturn = m_pd3dDevice->BeginScene();
ICryFont *pCryFont = iSystem->GetICryFont();
if (pCryFont)
{
IFFont *pFont = pCryFont->GetFont("Default");
}
if (m_CVWidth)
m_CVWidth->Set(CRenderer::m_width);
if (m_CVHeight)
m_CVHeight->Set(CRenderer::m_height);
if (m_CVFullScreen)
m_CVFullScreen->Set(m_bFullScreen);
if (m_CVColorBits)
m_CVColorBits->Set(CRenderer::m_cbpp);
ChangeViewport(0, 0, CRenderer::m_width, CRenderer::m_height);
m_bDeviceLost = false;
if (m_bFullScreen)
SetGamma(CV_r_gamma+m_fDeltaGamma, CV_r_brightness, CV_r_contrast, true);
return true;
}
int CD3D9Renderer::EnumDisplayFormats(TArray<SDispFormat>& Formats, bool bReset)
{
int i;
if (bReset)
{
Formats.Free();
return 0;
}
SDispFormat DF;
D3DAdapterInfo *pAI = m_D3DSettings.PAdapterInfo();
for (i=0; i<pAI->pDisplayModeList->Num(); i++)
{
D3DDISPLAYMODE *pDM = &pAI->pDisplayModeList->Get(i);
DF.m_Width = pDM->Width;
DF.m_Height = pDM->Height;
DF.m_BPP = ColorBits(pDM->Format);
if (DF.m_BPP == 24)
DF.m_BPP = 32;
//DF.m_RefreshRate = pDM->RefreshRate;
Formats.AddElem(DF);
}
return Formats.Num();
}
/*bool CD3D9Renderer::IsSuitableDevice(int a, bool bAllowSoft)
{
if (a > m_dwNumAdapters)
a = m_dwNumAdapters-1;
if (a < 0)
a = 0;
for( DWORD d=0; d < m_Adapters[a].dwNumDevices; d++ )
{
SD3DDeviceInfo* pDevice;
SD3DAdapterInfo* pAdapter = &m_Adapters[a];
pDevice = &pAdapter->devices[d];
if (pDevice->DeviceType != D3DDEVTYPE_HAL && !bAllowSoft)
continue;
if (!m_bFullScreen && !pDevice->bCanDoWindowed)
continue;
if (m_bFullScreen)
{
int BestError = 999999;
int Best;
int BestCD;
for (DWORD m=0; m<pDevice->dwNumModes; m++)
{
SD3DModeInfo *mi = &pDevice->modes[m];
int thisCD = sCDFromFormat(mi->Format);
if (thisCD == -1)
continue;
int ThisError = Abs((int)mi->Width-(int)CRenderer::m_width) + Abs((int)mi->Height-(int)CRenderer::m_height) + Abs((int)thisCD-(int)CRenderer::m_cbpp);
if (ThisError < BestError)
{
Best = m;
BestCD = thisCD;
BestError = ThisError;
}
}
if( BestError == 999999 )
continue;
m_Adapters[a].dwCurrentDevice = d;
m_dwAdapter = a;
pDevice->dwCurrentMode = Best;
CRenderer::m_cbpp = BestCD;
SD3DModeInfo *mi = &pDevice->modes[Best];
CRenderer::m_width = mi->Width;
CRenderer::m_height = mi->Height;
iLog->Log ("Best-match display mode: %ix%ix%i (Error=%i)\n",CRenderer::m_width,CRenderer::m_height,CRenderer::m_cbpp,BestError);
if (CV_d3d9_texturebits)
m_TextureBits = CV_d3d9_texturebits;
else
m_TextureBits = CRenderer::m_cbpp;
}
else
{
if (CV_d3d9_texturebits)
m_TextureBits = CV_d3d9_texturebits;
else
m_TextureBits = CRenderer::m_cbpp;
}
break;
}
if (d == m_Adapters[a].dwNumDevices)
return false;
m_dwAdapter = a;
m_Adapters[a].dwCurrentDevice = d;
return true;
}*/
bool CD3D9Renderer::ChangeDisplay(unsigned int width,unsigned int height,unsigned int cbpp)
{
return false;
}
void CD3D9Renderer::ChangeViewport(unsigned int x,unsigned int y,unsigned int width,unsigned int height)
{
if (m_bDeviceLost)
return;
assert(m_CurrContext);
m_CurrContext->m_X = x;
m_CurrContext->m_Y = y;
m_CurrContext->m_Width = width;
m_CurrContext->m_Height = height;
m_width = width;
m_height = height;
m_VWidth = width;
m_VHeight = height;
m_VX = x;
m_VY = y;
if (m_pd3dDevice)
{
m_d3dpp.BackBufferWidth = width;
m_d3dpp.BackBufferHeight = height;
m_Viewport.X = x;
m_Viewport.Y = y;
m_Viewport.Width = width;
m_Viewport.Height = height;
m_pd3dDevice->SetViewport(&m_Viewport);
//m_pd3dDevice->Reset(&m_d3dpp);
}
}
void CD3D9Renderer::ChangeLog()
{
if (CV_r_log && !m_LogFile)
{
if (CV_r_log == 3)
SetLogFuncs(true);
m_LogFile = fxopen ("Direct3DLog.txt", "w");
if (m_LogFile)
{
iLog->Log("Direct3D log file '%s' opened\n", "Direct3DLog.txt");
char time[128];
char date[128];
_strtime( time );
_strdate( date );
fprintf(m_LogFile, "\n==========================================\n");
fprintf(m_LogFile, "Direct3D Log file opened: %s (%s)\n", date, time);
fprintf(m_LogFile, "==========================================\n");
}
}
else
if (!CV_r_log && m_LogFile)
{
SetLogFuncs(false);
char time[128];
char date[128];
_strtime( time );
_strdate( date );
fprintf(m_LogFile, "\n==========================================\n");
fprintf(m_LogFile, "Direct3D Log file closed: %s (%s)\n", date, time);
fprintf(m_LogFile, "==========================================\n");
fclose(m_LogFile);
m_LogFile = NULL;
iLog->Log("Direct3D log file '%s' closed\n", "Direct3DLog.txt");
}
if (CV_r_logTexStreaming && !m_LogFileStr)
{
m_LogFileStr = fxopen ("Direct3DLogStreaming.txt", "w");
if (m_LogFileStr)
{
iLog->Log("Direct3D texture streaming log file '%s' opened\n", "Direct3DLogStreaming.txt");
char time[128];
char date[128];
_strtime( time );
_strdate( date );
fprintf(m_LogFileStr, "\n==========================================\n");
fprintf(m_LogFileStr, "Direct3D Textures streaming Log file opened: %s (%s)\n", date, time);
fprintf(m_LogFileStr, "==========================================\n");
}
}
else
if (!CV_r_logTexStreaming && m_LogFileStr)
{
char time[128];
char date[128];
_strtime( time );
_strdate( date );
fprintf(m_LogFileStr, "\n==========================================\n");
fprintf(m_LogFileStr, "Direct3D Textures streaming Log file closed: %s (%s)\n", date, time);
fprintf(m_LogFileStr, "==========================================\n");
fclose(m_LogFileStr);
m_LogFileStr = NULL;
iLog->Log("Direct3D texture streaming log file '%s' closed\n", "Direct3DLogStreaming.txt");
}
}
void CD3D9Renderer::BeginFrame()
{
//////////////////////////////////////////////////////////////////////
// Set up everything so we can start rendering
//////////////////////////////////////////////////////////////////////
assert(m_pd3dDevice);
g_bProfilerEnabled = iSystem->GetIProfileSystem()->IsProfiling();
PROFILE_FRAME(Screen_Begin);
//////////////////////////////////////////////////////////////////////
// Build the matrices
//////////////////////////////////////////////////////////////////////
m_matView->LoadIdentity();
m_pd3dDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX *)m_matView->GetTop());
if (!m_bDeviceLost)
{
if (CV_r_gamma+m_fDeltaGamma != m_fLastGamma || CV_r_brightness != m_fLastBrightness || CV_r_contrast != m_fLastContrast)
SetGamma(CV_r_gamma+m_fDeltaGamma, CV_r_brightness, CV_r_contrast, false);
}
if (CV_r_fsaa != m_FSAA || CV_r_fsaa_samples != m_FSAA_samples || CV_r_fsaa_quality != m_FSAA_quality)
{
if (m_bEditor && (m_Features & RFT_SUPPORTFSAA))
{
m_FSAA = CV_r_fsaa;
if (!m_FSAA)
m_pd3dDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);
else
m_pd3dDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
}
else
if (!m_bEditor)
{
if (CV_r_fsaa)
{
TArray<SAAFormat> Formats;
int nNum = GetAAFormat(Formats, false);
iLog->Log(" Full scene AA: Enabled: %s (%d Quality)\n", Formats[nNum].szDescr, Formats[nNum].nQuality);
bool bChanged = false;
if (Formats[nNum].nQuality != m_FSAA_quality || Formats[nNum].nSamples != m_FSAA_samples)
{
bChanged = true;
ICVar *pVar = iConsole->GetCVar("r_FSAA_quality");
if (pVar)
pVar->Set(Formats[nNum].nQuality);
pVar = iConsole->GetCVar("r_FSAA_samples");
if (pVar)
pVar->Set(Formats[nNum].nSamples);
}
else
if (m_FSAA != CV_r_fsaa)
bChanged = true;
GetAAFormat(Formats, true);
if (bChanged)
ChangeResolution(m_CVWidth->GetIVal(), m_CVHeight->GetIVal(), m_CVColorBits->GetIVal(), 75, m_CVFullScreen->GetIVal()!=0);
}
else
if (CV_r_fsaa != m_FSAA)
{
ChangeResolution(m_CVWidth->GetIVal(), m_CVHeight->GetIVal(), m_CVColorBits->GetIVal(), 75, m_CVFullScreen->GetIVal()!=0);
iLog->Log(" Full scene AA: Disabled\n");
}
}
m_FSAA = CV_r_fsaa;
m_FSAA_quality = CV_r_fsaa_quality;
m_FSAA_samples = CV_r_fsaa_samples;
}
bool bChanged2X = false;
bool bChanged30 = false;
ICVar *var;
if (CV_r_sm30path != m_sm30path)
{
bChanged30 = true;
m_sm30path = CV_r_sm30path;
if (m_sm30path >= 0 && !m_bDeviceSupports_PS30)
{
iLog->Log("Device doesn't support pixel shaders 3.0 (or it's disabled)");
var = iConsole->GetCVar("r_SM30PATH");
if (var)
var->Set(0);
m_sm30path = 0;
}
if (m_sm30path >= 0)
{
var = iConsole->GetCVar("r_NoPS30");
if (var)
var->Set(m_sm30path ? 0 : 1);
}
}
if (CV_r_sm2xpath != m_sm2xpath)
{
bChanged2X = true;
m_sm2xpath = CV_r_sm2xpath;
if (m_sm2xpath >= 0 && !m_bDeviceSupports_PS2X)
{
int nGPU = m_Features & RFT_HW_MASK;
if (nGPU == RFT_HW_GFFX)
iLog->Log("Device doesn't support pixel shaders 2.0a (or it's disabled)");
else
iLog->Log("Device doesn't support pixel shaders 2.0b (or it's disabled)");
var = iConsole->GetCVar("r_SM2XPATH");
if (var)
var->Set(0);
m_sm2xpath = 0;
}
if (m_sm2xpath >= 0)
{
var = iConsole->GetCVar("r_NoPS2X");
if (var)
var->Set(m_sm2xpath ? 0 : 1);
}
}
if (!m_bDeviceSupportsInstancing)
{
if (CV_r_geominstancing)
{
iLog->Log("Device doesn't support HW geometry instancing (or it's disabled)");
var = iConsole->GetCVar("r_GeomInstancing");
if (var)
var->Set(0);
}
}
else
{
if (bChanged2X && m_sm2xpath >= 0)
{
var = iConsole->GetCVar("r_GeomInstancing");
if (var)
var->Set(m_sm2xpath ? 1 : 0);
}
else
if (bChanged30 && m_sm30path >= 0)
{
var = iConsole->GetCVar("r_GeomInstancing");
if (var)
var->Set(m_sm30path ? 1 : 0);
}
}
if (CV_r_reloadshaders)
{
m_cEF.mfReloadAllShaders(CV_r_reloadshaders);
CV_r_reloadshaders = 0;
}
if (CV_r_nops30 != m_NoPS30)
{
m_NoPS30 = CV_r_nops30;
if (m_bDeviceSupports_PS30)
{
if (m_NoPS30)
{
m_nEnabled_PS30 = 0;
m_Features &= ~RFT_HW_PS30;
}
else
{
m_nEnabled_PS30 = 1;
m_Features |= RFT_HW_PS30;
}
m_cEF.mfReloadAllShaders(FRO_SHADERS | FRO_FORCERELOAD);
CV_r_reloadshaders = 0;
}
else
{
iLog->Log("Device doesn't support pixel shaders 3.0 (or it's disabled)");
ICVar *var = iConsole->GetCVar("r_SM30PATH");
if (var)
var->Set(0);
m_sm30path = 0;
}
}
if (CV_r_nops2x != m_NoPS2X)
{
m_NoPS2X = CV_r_nops2x;
if (m_bDeviceSupports_PS2X)
{
if (m_NoPS2X)
m_nEnabled_PS2X = 0;
else
m_nEnabled_PS2X = 1;
m_cEF.mfReloadAllShaders(FRO_SHADERS | FRO_FORCERELOAD);
CV_r_reloadshaders = 0;
}
else
{
if ((GetFeatures() & RFT_HW_MASK) == RFT_HW_GFFX)
iLog->Log("Device doesn't support pixel shaders 2.0a (or it's disabled)");
else
iLog->Log("Device doesn't support pixel shaders 2.0b (or it's disabled)");
ICVar *var = iConsole->GetCVar("r_SM2XPATH");
if (var)
var->Set(0);
m_sm2xpath = 0;
}
}
if (CV_r_vsync != m_VSync)
{
m_VSync = CV_r_vsync;
EnableVSync(m_VSync?true:false);
}
if (!m_bEditor)
{
if (m_CVWidth && m_CVHeight && m_CVFullScreen && m_CVColorBits)
{
if (m_CVWidth->GetIVal() != CRenderer::m_width || m_CVHeight->GetIVal() != CRenderer::m_height || m_CVFullScreen->GetIVal() != (int)m_bFullScreen || m_CVColorBits->GetIVal() != CRenderer::m_cbpp)
ChangeResolution(m_CVWidth->GetIVal(), m_CVHeight->GetIVal(), m_CVColorBits->GetIVal(), 75, m_CVFullScreen->GetIVal()!=0);
}
}
gRenDev->m_cEF.mfBeginFrame();
if (CV_r_PolygonMode!=m_polygon_mode)
SetPolygonMode(CV_r_PolygonMode);
m_bWasCleared = false;
// EF_ClearBuffer(false, NULL);
//////////////////////////////////////////////////////////////////////
// Begin the scene
//////////////////////////////////////////////////////////////////////
SetMaterialColor(1,1,1,1);
if (strcmp(CV_d3d9_texturefilter->GetString(), m_TexMan->m_CurTexFilter) || CV_r_texture_anisotropic_level != m_TexMan->m_CurAnisotropic)
m_TexMan->SetFilter(CV_d3d9_texturefilter->GetString());
ChangeLog ();
ResetToDefault();
if (CRenderer::CV_r_logTexStreaming)
{
LogStrv(0, "******************************* EndFrame ********************************\n");
LogStrv(0, "Loaded: %.3f Kb, UpLoaded: %.3f Kb, UploadTime: %.3fMs\n\n", gRenDev->m_TexMan->m_LoadBytes/1024.0f, gRenDev->m_TexMan->m_UpLoadBytes/1024.0f, m_RP.m_PS.m_fTexUploadTime);
}
if (gRenDev->m_TexMan->m_LoadBytes > 3.0f*1024.0f*1024.0f)
gRenDev->m_TexMan->m_fStreamDistFactor = min(2048.0f, gRenDev->m_TexMan->m_fStreamDistFactor*1.2f);
else
gRenDev->m_TexMan->m_fStreamDistFactor = max(1.0f, gRenDev->m_TexMan->m_fStreamDistFactor/1.2f);
gRenDev->m_TexMan->m_UpLoadBytes = 0;
gRenDev->m_TexMan->m_LoadBytes = 0;
m_MatDepth = 0;
m_nPolygons = 0;
m_nFrameID++;
m_nFrameUpdateID++;
m_nShadowVolumePolys=0;
m_RP.m_RealTime = iTimer->GetCurrTime();
m_RP.m_PersFlags &= ~RBPF_HDR;
TArray<CRETempMesh *> *tm = &m_RP.m_TempMeshes[m_nFrameID & 1];
for (int i=0; i<tm->Num(); i++)
{
CRETempMesh *re = tm->Get(i);
if (!re)
continue;
if (re->m_VBuffer)
{
ReleaseBuffer(re->m_VBuffer);
re->m_VBuffer = NULL;
}
ReleaseIndexBuffer(&re->m_Inds);
}
tm->SetUse(0);
m_RP.m_CurTempMeshes = tm;
if (CRenderer::CV_r_log)
Logv(0, "******************************* BeginFrame %d ********************************\n", m_nFrameID);
if (CRenderer::CV_r_logTexStreaming)
LogStrv(0, "******************************* BeginFrame %d ********************************\n", m_nFrameID);
FlushHardware();
CheckDeviceLost();
}
bool CD3D9Renderer::CheckDeviceLost()
{
HRESULT hReturn;
// Test the cooperative level to see if it's okay to render
if (FAILED(hReturn = m_pd3dDevice->TestCooperativeLevel()))
{
// If the device was lost, do not render until we get it back
if (D3DERR_DEVICELOST == hReturn)
{
RestoreGamma();
m_bDeviceLost = true;
return true;
}
// Check if the device needs to be reset.
if(D3DERR_DEVICENOTRESET == hReturn)
{
m_bDeviceLost = true;
if(FAILED(hReturn = Reset3DEnvironment()))
return true;
m_bDeviceLost = false;
SetGamma(CV_r_gamma+m_fDeltaGamma, CV_r_brightness, CV_r_contrast, true);
hReturn = m_pd3dDevice->BeginScene();
}
}
return false;
}
void CD3D9Renderer::FlushHardware()
{
if (m_bDeviceLost)
return;
HRESULT hr;
if (CV_r_flush)
{
if (m_pQuery)
{
BOOL bQuery = false;
double time = sCycles2();
bool bInfinite = false;
do
{
double dif = sCycles2()+34-time;
if (dif*1000.0*g_SecondsPerCycle > 5000)
{
// 5 seconds in the loop
bInfinite = true;
break;
}
hr = m_pQuery->GetData((void *)&bQuery, sizeof(BOOL), D3DGETDATA_FLUSH);
} while(hr == S_FALSE);
if (bInfinite)
iLog->Log("Error: Seems like infinite loop in GPU sync query");
m_pQuery->Issue(D3DISSUE_END);
}
else
{
IDirect3DSurface9 * pTar = mfGetBackSurface();
if (pTar)
{
D3DLOCKED_RECT lockedRect;
RECT sourceRect;
sourceRect.bottom = 1;
sourceRect.top = 0;
sourceRect.left = 0;
sourceRect.right = 4;
hr = pTar->LockRect(&lockedRect,&sourceRect,D3DLOCK_READONLY);
if (!FAILED(hr))
{
volatile unsigned long a;
memcpy((void *)&a,(unsigned char*)lockedRect.pBits,sizeof(a));
hr = pTar->UnlockRect();
}
}
}
}
}
void CD3D9Renderer::Update()
{
//////////////////////////////////////////////////////////////////////
// End the scene and update
//////////////////////////////////////////////////////////////////////
// Check for the presence of a D3D device
assert(m_pd3dDevice);
if (!m_SceneRecurseCount)
{
iLog->Log("EndScene without BeginScene\n");
return;
}
int i;
{
//IDirect3DSurface9 * pTar = gcpRendD3D->mfGetBackSurface();
//D3DLOCKED_RECT rc;
//HRESULT ddrval = pTar->LockRect( &rc, NULL, D3DLOCK_READONLY );
//ddrval = pTar->UnlockRect();
}
PROFILE_FRAME(Screen_Update);
HRESULT hReturn;
m_prevCamera = m_cam;
if (CV_r_showtimegraph)
{
static byte *fg;
static float fPrevTime = iTimer->GetCurrTime();
static int sPrevWidth = 0;
static int sPrevHeight = 0;
static int nC;
float fCurTime = iTimer->GetCurrTime();
float frametime = fCurTime - fPrevTime;
fPrevTime = fCurTime;
int wdt = m_width;
int hgt = m_height;
if (sPrevHeight != hgt || sPrevWidth != wdt)
{
if (fg)
{
delete [] fg;
fg = NULL;
}
sPrevWidth = wdt;
sPrevHeight = hgt;
}
if (!fg)
{
fg = new byte[wdt];
memset(fg, -1, wdt);
}
int type = CV_r_showtimegraph;
float f;
float fScale;
if (type > 2)
{
type = 2;
fScale = (float)CV_r_showtimegraph / 1000.0f;
}
else
fScale = 0.1f;
f = frametime / fScale;
f = 255.0f - CLAMP(f*255.0f, 0, 255.0f);
if (fg)
{
fg[nC] = (byte)f;
Graph(fg, 0, hgt-280, wdt, 256, nC, type, "Frame Time", Col_Green, fScale);
}
nC++;
if (nC == wdt)
nC = 0;
}
else
if (CV_r_showtextimegraph)
{
static byte *fgUpl;
static byte *fgStreamSync;
static byte *fgTimeUpl;
static byte *fgDistFact;
static byte *fgCustMip;
static byte *fgTotalMem;
static byte *fgCurMem;
static float fScaleUpl = 1; // in Mb
static float fScaleStreamSync = 1; // in Mb
static float fScaleTimeUpl = 75; // in Ms
static float fScaleDistFact = 200; // in Meters
static float fScaleCustMip = 4; // in Mips levels
static FLOAT fScaleTotalMem = 0; // in Mb
static float fScaleCurMem = 80; // in Mb
static CFColor ColUpl = Col_White;
static CFColor ColStreamSync = Col_Cyan;
static CFColor ColTimeUpl = Col_SeaGreen;
static CFColor ColDistFact = Col_Orchid;
static CFColor ColCustMip = Col_Orange;
static CFColor ColTotalMem = Col_Red;
static CFColor ColCurMem = Col_Yellow;
static int sMask = -1;
if (GetAsyncKeyState('1') & 0x1)
sMask ^= 1;
if (GetAsyncKeyState('2') & 0x1)
sMask ^= 2;
if (GetAsyncKeyState('3') & 0x1)
sMask ^= 4;
if (GetAsyncKeyState('4') & 0x1)
sMask ^= 8;
if (GetAsyncKeyState('5') & 0x1)
sMask ^= 16;
if (GetAsyncKeyState('6') & 0x1)
sMask ^= 32;
if (GetAsyncKeyState('7') & 0x1)
sMask ^= 64;
if (!fScaleTotalMem)
fScaleTotalMem = (float)CRenderer::CV_r_texturesstreampoolsize;
static float fPrevTime = iTimer->GetCurrTime();
static int sPrevWidth = 0;
static int sPrevHeight = 0;
static int nC;
int wdt = m_width;
int hgt = m_height;
int type = 3;
if (sPrevHeight != hgt || sPrevWidth != wdt)
{
SAFE_DELETE_ARRAY(fgUpl);
SAFE_DELETE_ARRAY(fgStreamSync);
SAFE_DELETE_ARRAY(fgTimeUpl);
SAFE_DELETE_ARRAY(fgDistFact);
SAFE_DELETE_ARRAY(fgCustMip);
SAFE_DELETE_ARRAY(fgTotalMem);
SAFE_DELETE_ARRAY(fgCurMem);
sPrevWidth = wdt;
sPrevHeight = hgt;
}
if (!fgUpl)
{
fgUpl = new byte[wdt];
memset(fgUpl, -1, wdt);
fgStreamSync = new byte[wdt];
memset(fgStreamSync, -1, wdt);
fgTimeUpl = new byte[wdt];
memset(fgTimeUpl, -1, wdt);
fgDistFact = new byte[wdt];
memset(fgDistFact, -1, wdt);
fgCustMip = new byte[wdt];
memset(fgCustMip, -1, wdt);
fgTotalMem = new byte[wdt];
memset(fgTotalMem, -1, wdt);
fgCurMem = new byte[wdt];
memset(fgCurMem, -1, wdt);
}
CXFont *cf = iConsole->GetFont();
Set2DMode(true, m_width, m_height);
CFColor col = Col_White;
int num = gRenDev->m_TexMan->m_Text_White->GetTextureID();
DrawImage((float)nC, (float)(hgt-280), 1, 256, num, 0, 0, 1, 1, col.r, col.g, col.b, col.a);
Set2DMode(false, m_width, m_height);
float f;
if (sMask & 1)
{
f = (gRenDev->m_TexMan->m_UpLoadBytes/1024.0f/1024.0f) / fScaleUpl;
f = 255.0f - CLAMP(f*255.0f, 0, 255.0f);
fgUpl[nC] = (byte)f;
Graph(fgUpl, 0, hgt-280, wdt, 256, nC, type, NULL, ColUpl, fScaleUpl);
col = ColUpl;
WriteXY(cf,4,hgt-280, 0.5f,1,col.r,col.g,col.b,1, "UploadMB (%d-%d)", (int)(gRenDev->m_TexMan->m_UpLoadBytes/1024.0f/1024.0f), (int)fScaleUpl);
}
if (sMask & 2)
{
f = m_RP.m_PS.m_fTexUploadTime / fScaleTimeUpl;
f = 255.0f - CLAMP(f*255.0f, 0, 255.0f);
fgTimeUpl[nC] = (byte)f;
Graph(fgTimeUpl, 0, hgt-280, wdt, 256, nC, type, NULL, ColTimeUpl, fScaleTimeUpl);
col = ColTimeUpl;
WriteXY(cf,4,hgt-280+16, 0.5f,1,col.r,col.g,col.b,1, "Upload Time (%.3fMs - %.3fMs)", m_RP.m_PS.m_fTexUploadTime, fScaleTimeUpl);
}
if (sMask & 4)
{
f = (gRenDev->m_TexMan->m_LoadBytes/1024.0f/1024.0f) / fScaleStreamSync;
f = 255.0f - CLAMP(f*255.0f, 0, 255.0f);
fgStreamSync[nC] = (byte)f;
Graph(fgStreamSync, 0, hgt-280, wdt, 256, nC, type, NULL, ColStreamSync, fScaleStreamSync);
col = ColStreamSync;
WriteXY(cf,4,hgt-280+16*2, 0.5f,1,col.r,col.g,col.b,1, "StreamMB (%d-%d)", (int)(gRenDev->m_TexMan->m_LoadBytes/1024.0f/1024.0f), (int)fScaleStreamSync);
}
if (sMask & 8)
{
f = gRenDev->m_TexMan->m_fStreamDistFactor / fScaleDistFact;
f = 255.0f - CLAMP(f*255.0f, 0, 255.0f);
fgDistFact[nC] = (byte)f;
Graph(fgDistFact, 0, hgt-280, wdt, 256, nC, type, NULL, ColDistFact, fScaleDistFact);
col = ColDistFact;
WriteXY(cf,4,hgt-280+16*3, 0.5f,1,col.r,col.g,col.b,1, "Dist Factor (Upload) (%.3f-%d)", gRenDev->m_TexMan->m_fStreamDistFactor, (int)fScaleDistFact);
}
if (sMask & 16)
{
f = m_TexMan->m_nCustomMip / fScaleCustMip;
f = 255.0f - CLAMP(f*255.0f, 0, 255.0f);
fgCustMip[nC] = (byte)f;
Graph(fgCustMip, 0, hgt-280, wdt, 256, nC, type, NULL, ColCustMip, fScaleCustMip);
col = ColCustMip;
WriteXY(cf,4,hgt-280+16*4, 0.5f,1,col.r,col.g,col.b,1, "Custom Mip (Thrash) (%d-%d)", m_TexMan->m_nCustomMip, (int)fScaleCustMip);
}
if (sMask & 32)
{
f = (gRenDev->m_TexMan->m_StatsCurTexMem/1024.0f/1024.0f) / fScaleTotalMem;
f = 255.0f - CLAMP(f*255.0f, 0, 255.0f);
fgTotalMem[nC] = (byte)f;
Graph(fgTotalMem, 0, hgt-280, wdt, 256, nC, type, NULL, ColTotalMem, fScaleTotalMem);
col = ColTotalMem;
WriteXY(cf,4,hgt-280+16*5, 0.5f,1,col.r,col.g,col.b,1, "Cur Pool Size (Mb) (%d-%d)", (int)(gRenDev->m_TexMan->m_StatsCurTexMem/1024.0f/1024.0f), (int)fScaleTotalMem);
}
if (sMask & 64)
{
f = (m_RP.m_PS.m_TexturesSize/1024.0f/1024.0f) / fScaleCurMem;
f = 255.0f - CLAMP(f*255.0f, 0, 255.0f);
fgCurMem[nC] = (byte)f;
Graph(fgCurMem, 0, hgt-280, wdt, 256, nC, type, NULL, ColCurMem, fScaleCurMem);
col = ColCurMem;
WriteXY(cf,4,hgt-280+16*6, 0.5f,1,col.r,col.g,col.b,1, "Cur Scene Size (Mb) (%d-%d)", (int)(m_RP.m_PS.m_TexturesSize/1024.0f/1024.0f), (int)fScaleCurMem);
}
nC++;
if (nC == wdt)
nC = 0;
}
if (CV_r_envlightcmdebug)
{
SEnvTexture *cm = NULL;
Vec3d Pos = m_cam.GetPos();
cm = m_cEF.mfFindSuitableEnvLCMap(Pos, true, 0, 0);
if (cm)
{
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
EF_SetState(GS_NODEPTHTEST);
gRenDev->m_TexMan->m_Text_White->Set();
DrawQuad(0,0,64,64,CFColor(cm->m_EnvColors[0].bcolor), 1.0f);
DrawQuad(64,0,128,64,CFColor(cm->m_EnvColors[2].bcolor), 1.0f);
DrawQuad(128,0,192,64,CFColor(cm->m_EnvColors[4].bcolor), 1.0f);
DrawQuad(0,64,64,128,CFColor(cm->m_EnvColors[1].bcolor), 1.0f);
DrawQuad(64,64,128,128,CFColor(cm->m_EnvColors[3].bcolor), 1.0f);
DrawQuad(128,64,192,128,CFColor(cm->m_EnvColors[5].bcolor), 1.0f);
PrintToScreen(5,5,4,"Pos X");
PrintToScreen(5+64,5,4,"Pos Y");
PrintToScreen(5+128,5,4,"Pos Z");
PrintToScreen(5,5+64,4,"Neg X");
PrintToScreen(5+64,5+64,4,"Neg Y");
PrintToScreen(5+128,5+64,4,"Neg Z");
}
}
double time = 0;
ticks(time);
if (CV_r_measureoverdraw)
{
gRenDev->Set2DMode(true, 800, 600);
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
vQuad[0].xyz.x = 0;
vQuad[0].xyz.y = 0;
vQuad[0].xyz.z = 1;
vQuad[0].color.dcolor = -1;
vQuad[0].st[0] = 0;
vQuad[0].st[1] = 0;
vQuad[1].xyz.x = 800;
vQuad[1].xyz.y = 0;
vQuad[1].xyz.z = 1;
vQuad[1].color.dcolor = -1;
vQuad[1].st[0] = 1;
vQuad[1].st[1] = 0;
vQuad[2].xyz.x = 800;
vQuad[2].xyz.y = 600;
vQuad[2].xyz.z = 1;
vQuad[2].color.dcolor = -1;
vQuad[2].st[0] = 1;
vQuad[2].st[1] = 1;
vQuad[3].xyz.x = 0;
vQuad[3].xyz.y = 600;
vQuad[3].xyz.z = 1;
vQuad[3].color.dcolor = -1;
vQuad[3].st[0] = 0;
vQuad[3].st[1] = 1;
m_RP.m_PersFlags &= ~RBPF_MEASUREOVERDRAW;
SetCullMode(R_CULL_DISABLE);
EF_SetState(GS_NODEPTHTEST);
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
UnlockVB3D();
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
EF_SetGlobalColor(0,0,0,0);
// Render the two triangles from the data stream
HRESULT hr = m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
EF_SetStencilState(STENCOP_FAIL(FSS_STENCOP_KEEP) |
STENCOP_ZFAIL(FSS_STENCOP_KEEP) |
STENCOP_PASS(FSS_STENCOP_KEEP) |
STENC_FUNC(FSS_STENCFUNC_LEQUAL),
0, -1);
EF_SetState(GS_BLSRC_ONE | GS_BLDST_ONE | GS_NODEPTHTEST | GS_STENCIL);
float fColor = 0.015625f;
EF_SetGlobalColor(fColor,fColor,fColor,fColor);
float fStencil = 1;
float fStencInc = 1;
for (int i=0; i<64; i++)
{
m_pd3dDevice->SetRenderState(D3DRS_STENCILREF, (int)fStencil);
// Render the two triangles from the data stream
hr = m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
fStencil += fStencInc;
}
m_pd3dDevice->SetRenderState(D3DRS_STENCILREF, 0);
}
if (iConsole)
{
CRenderer *crend=gRenDev;
CXFont *cf=iConsole->GetFont();
/*if (CV_r_sm30path > 0)
{
CFColor col = Col_Yellow;
#ifdef USE_HDR
if (CV_r_hdrrendering)
crend->Draw2dLabel(300,10, 2.0f, &col[0], true, "SM30 HDR Path Beta");
else
#endif
crend->Draw2dLabel(300,10, 2.0f, &col[0], true, "SM30 Path Beta");
}
else
if (CV_r_sm2xpath > 0)
{
CFColor col = Col_Yellow;
#ifdef USE_HDR
if (CV_r_hdrrendering)
{
if ((gRenDev->GetFeatures() & RFT_HW_MASK) == RFT_HW_GFFX)
crend->Draw2dLabel(300,10, 2.0f, &col[0], true, "SM20b HDR Path Beta");
else
crend->Draw2dLabel(300,10, 2.0f, &col[0], true, "SM20a HDR Path Beta");
}
else
#endif
{
if ((gRenDev->GetFeatures() & RFT_HW_MASK) == RFT_HW_GFFX)
crend->Draw2dLabel(300,10, 2.0f, &col[0], true, "SM20a Path Beta");
else
crend->Draw2dLabel(300,10, 2.0f, &col[0], true, "SM20b Path Beta");
}
}*/
switch (CV_r_stats)
{
case 1:
crend->WriteXY(cf,10,270, 0.5f,1,1,1,1,1, "Unique Render Items=%d (%d)",m_RP.m_PS.m_NumRendItems, m_RP.m_PS.m_NumRendBatches);
crend->WriteXY(cf,10,335, 0.5f,1,1,1,1,1, "Unique CVShaders=%d",m_RP.m_PS.m_NumVShaders);
crend->WriteXY(cf,10,350, 0.5f,1,1,1,1,1, "Unique CPShaders=%d",m_RP.m_PS.m_NumPShaders);
crend->WriteXY(cf,10,365, 0.5f,1,1,1,1,1,"Unique Textures=%d",m_RP.m_PS.m_NumTextures);
crend->WriteXY(cf,10,385, 0.5f,1,1,1,1,1,"TexturesSize=%.03f Kb",m_RP.m_PS.m_TexturesSize/1024.0f);
crend->WriteXY(cf,10,400, 0.5f,1,1,1,1,1,"Mesh update=%.03f Kb",m_RP.m_PS.m_MeshUpdateBytes/1024.0f);
break;
case 2:
{
crend->WriteXY(cf,550,140, 0.5f,1,1,1,1,1,"FFTTables=%0.3f",CREOcean::m_RS.m_StatsTimeFFTTable);
crend->WriteXY(cf,550,155, 0.5f,1,1,1,1,1,"FFT=%0.3f",CREOcean::m_RS.m_StatsTimeFFT);
crend->WriteXY(cf,550,170, 0.5f,1,1,1,1,1,"UpdateVerts=%0.3f",CREOcean::m_RS.m_StatsTimeUpdateVerts);
crend->WriteXY(cf,550,185, 0.5f,1,1,1,1,1,"BumpTexUpdate=%0.3f",CREOcean::m_RS.m_StatsTimeTexUpdate);
crend->WriteXY(cf,550,200, 0.5f,1,1,1,1,1,"RendOcean=%0.3f",CREOcean::m_RS.m_StatsTimeRendOcean);
crend->WriteXY(cf,550,215, 0.5f,1,1,1,1,1,"NumRendSectors=%d",CREOcean::m_RS.m_StatsNumRendOceanSectors);
crend->WriteXY(cf,550,230, 0.5f,1,1,1,1,1,"NumAllocatedSectors=%d",CREOcean::m_RS.m_StatsAllocatedSectors);
}
break;
case 3:
{
CLeafBuffer *pLB = CLeafBuffer::m_Root.m_Prev;
int nMem = 0;
while (pLB != &CLeafBuffer::m_Root)
{
nMem += pLB->GetAllocatedBytes(true);
pLB = pLB->m_Prev;
}
crend->WriteXY(cf,550,140, 0.5f,1,1,1,1,1,"LeafBuffer Vert. size=%0.3fMb",(float)nMem/1024.0f/1024.0f);
}
break;
case 4:
{
int i;
int nSize = 0;
int n = 0;
for (i=0; i<SShader::m_Shaders_known.GetSize(); i++)
{
SShader *pSH = SShader::m_Shaders_known[i];
if (!pSH)
continue;
nSize += pSH->Size(0);
n++;
}
crend->WriteXY(cf,550,160, 0.5f,1,1,1,1,1,"Shaders: %d, size=%0.3fMb",n , (float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<SShader::m_ShaderResources_known.Num(); i++)
{
SRenderShaderResources *pSR = SShader::m_ShaderResources_known[i];
if (!pSR)
continue;
nSize += pSR->Size();
n++;
}
crend->WriteXY(cf,550,175, 0.5f,1,1,1,1,1,"Shader Res: %d, size=%0.3fMb",n , (float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<SParamComp::m_ParamComps.Num(); i++)
{
nSize += SParamComp::m_ParamComps[i]->Size();
n++;
}
crend->WriteXY(cf,550,190, 0.5f,1,1,1,1,1,"Shader Comps: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<CVProgram::m_VPrograms.Num(); i++)
{
if (CVProgram::m_VPrograms[i])
{
nSize += CVProgram::m_VPrograms[i]->Size();
n++;
}
}
crend->WriteXY(cf,550,205, 0.5f,1,1,1,1,1,"VProgramms: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<CPShader::m_PShaders.Num(); i++)
{
if (CPShader::m_PShaders[i])
{
nSize += CPShader::m_PShaders[i]->Size();
n++;
}
}
crend->WriteXY(cf,550,220, 0.5f,1,1,1,1,1,"PShaders: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<CLightStyle::m_LStyles.Num(); i++)
{
nSize += CLightStyle::m_LStyles[i]->Size();
n++;
}
crend->WriteXY(cf,550,235, 0.5f,1,1,1,1,1,"LStyles: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<SLightMaterial::known_materials.Num(); i++)
{
nSize += SLightMaterial::known_materials[i]->Size();
n++;
}
crend->WriteXY(cf,550,250, 0.5f,1,1,1,1,1,"LMaterials: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
int nSizeVid = 0;
int nSizeInds = 0;
n = 0;
int nVB = 0;
int nVI = 0;
CLeafBuffer *pLB = CLeafBuffer::m_RootGlobal.m_NextGlobal;
while (pLB != &CLeafBuffer::m_RootGlobal)
{
n++;
nSize += pLB->Size(0);
if (pLB->m_pVertexBuffer)
{
nSizeVid += pLB->m_pVertexBuffer->Size(0, pLB->m_SecVertCount);
nVB++;
}
if (pLB->m_Indices.m_VertBuf.m_pPtr)
{
nSizeInds += pLB->m_Indices.m_nItems*2;
nVI++;
}
pLB = pLB->m_NextGlobal;
}
crend->WriteXY(cf,550,280, 0.5f,1,1,1,1,1,"Mesh (LB): %d, SysSize=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
crend->WriteXY(cf,550,295, 0.5f,1,1,1,1,1,"VidBuf: %d, Size: %0.3fMb", nVB, (float)nSizeVid/1024.0f/1024.0f);
crend->WriteXY(cf,550,310, 0.5f,1,1,1,1,1,"VidInds: %d, Size: %0.3fMb", nVI, (float)nSizeInds/1024.0f/1024.0f);
nSize = 0;
n = 0;
CRendElement *pRE = CRendElement::m_RootGlobal.m_NextGlobal;
while (pRE != &CRendElement::m_RootGlobal)
{
n++;
nSize += pRE->Size();
pRE = pRE->m_NextGlobal;
}
crend->WriteXY(cf,550,325, 0.5f,1,1,1,1,1,"Rend. Elements: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
int nObjSize = 0;
n = 0;
for (i=0; i<gRenDev->m_TexMan->m_Textures.Num(); i++)
{
STexPic *tp = gRenDev->m_TexMan->m_Textures[i];
if (!tp || tp->m_Bind == TX_FIRSTBIND)
continue;
n++;
nObjSize += tp->Size(0);
nSize += tp->m_Size;
}
crend->WriteXY(cf,550,350, 0.5f,1,1,1,1,1,"Textures: %d, ObjSize=%0.3fMb",n,(float)nObjSize/1024.0f/1024.0f);
crend->WriteXY(cf,550,365, 0.5f,1,1,1,1,1,"TexturesDataSize=%.03f Mb",nSize/1024.0f/1024.0f);
crend->WriteXY(cf,550,380, 0.5f,1,1,1,1,1,"CurTexturesDataSize=%.03f Mb",m_RP.m_PS.m_TexturesSize/1024.0f/1024.0f);
crend->WriteXY(cf,550,405, 0.5f,1,1,1,1,1,"Mesh update=%.03f Kb",m_RP.m_PS.m_MeshUpdateBytes/1024.0f);
}
break;
}
}
m_TexMan->Update();
if (CV_r_profileshaders)
EF_PrintProfileInfo();
EF_SetState(GS_DEPTHWRITE);
// draw debug bboxes and lines
std :: vector<BBoxInfo>::iterator itBBox = m_arrBoxesToDraw.begin(), itBBoxEnd = m_arrBoxesToDraw.end();
for( ; itBBox != itBBoxEnd; ++itBBox)
{
BBoxInfo& rBBox = *itBBox;
SetMaterialColor( rBBox.fColor[0], rBBox.fColor[1],
rBBox.fColor[2], rBBox.fColor[3] );
// set blend for transparent objects
if(rBBox.fColor[3]!=1.f)
{
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
}
switch(rBBox.nPrimType)
{
case DPRIM_LINE:
DrawLine(rBBox.vMins, rBBox.vMaxs);
break;
case DPRIM_WHIRE_BOX:
Flush3dBBox(rBBox.vMins, rBBox.vMaxs, false);
break;
case DPRIM_SOLID_BOX:
Flush3dBBox(rBBox.vMins, rBBox.vMaxs, true);
break;
case DPRIM_SOLID_SPHERE:
{
Vec3d vPos = (rBBox.vMins+rBBox.vMaxs)*0.5f;
float fRadius = (rBBox.vMins-rBBox.vMaxs).Length();
DrawBall(vPos, fRadius);
}
break;
}
if(rBBox.fColor[3]!=1.f)
{
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
}
}
EF_SetState(GS_NODEPTHTEST);
m_arrBoxesToDraw.clear();
{ // print shadow volume stats
static ICVar *pVar = iConsole->GetCVar("e_stencil_shadows");
if(pVar && pVar->GetIVal()==3)
CRETriMeshShadow::PrintStats();
}
{ // print shadow maps on the screen
static ICVar *pVar = iConsole->GetCVar("e_shadow_maps_debug");
if(pVar && pVar->GetIVal()==2)
DrawAllShadowsOnTheScreen();
}
#ifdef USE_HDR
if (CV_r_hdrdebug)
HDR_DrawDebug();
#endif
/*{
Vec3 vPos = Vec3(-50, 865, 0);
vPos.z = CREOcean::m_pStaticOcean->GetWaterZElevation(vPos.x, vPos.y);
float fRadius = 1;
EF_SetState(GS_DEPTHWRITE);
D3DSetCull(eCULL_None);
DrawBall(vPos, fRadius);
}*/
{
/*EF_SetState(GS_NODEPTHTEST);
int iTmpX, iTmpY, iTempWidth, iTempHeight;
GetViewport(&iTmpX, &iTmpY, &iTempWidth, &iTempHeight);
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
Set2DMode(true, 1, 1);
SetViewport(10, 400, 100, 100);
DrawImage(0, 0, 1, 1, 0x12bf, 0, 1, 1, 0, 1,1,1,1);
SetViewport(120, 400, 100, 100);
DrawImage(0, 0, 1, 1, 0x12cf, 0, 1, 1, 0, 1,1,1,1);
*/
/*{
CFurNormalMap *fnm = (CFurNormalMap *)m_TexMan->m_Text_FurNormalMap->m_pFuncMap;
SetViewport(10, 400, 100, 100);
DrawImage(0, 0, 1, 1, fnm->m_pTexOffset0->m_Bind, 0, 1, 1, 0, 1,1,1,1);
SetViewport(120, 400, 100, 100);
DrawImage(0, 0, 1, 1, fnm->m_pTexOffset1->m_Bind, 0, 1, 1, 0, 1,1,1,1);
SetViewport(230, 400, 100, 100);
DrawImage(0, 0, 1, 1, fnm->m_pTex->m_Bind, 0, 1, 1, 0, 1,1,1,1);
SetViewport(340, 400, 100, 100);
DrawImage(0, 0, 1, 1, fnm->m_pTexClamp->m_Bind, 0, 1, 1, 0, 1,1,1,1);
SetViewport(450, 400, 100, 100);
DrawImage(0, 0, 1, 1, fnm->m_pTexNormalize->m_Bind, 0, 1, 1, 0, 1,1,1,1);
}*/
/*SetViewport(10, 400, 100, 100);
DrawImage(0, 0, 1, 1, m_TexMan->m_Text_ScreenMap->m_Bind, 0, 1, 1, 0, 1,1,1,1);
SetViewport(120, 400, 100, 100);
DrawImage(0, 0, 1, 1, m_TexMan->m_Text_ScreenLowMap->m_Bind, 0, 1, 1, 0, 1,1,1,1);
SetViewport(230, 400, 100, 100);
DrawImage(0, 0, 1, 1, m_TexMan->m_Text_ScreenAvg1x1->m_Bind, 0, 1, 1, 0, 1,1,1,1);
SetViewport(340, 400, 100, 100);
DrawImage(0, 0, 1, 1, m_TexMan->m_Text_ScreenCurrLuminosityMap->m_Bind, 0, 1, 1, 0, 1,1,1,1);
SetViewport(450, 400, 100, 100);
DrawImage(0, 0, 1, 1, m_TexMan->m_Text_Glare->m_Bind, 0, 1, 1, 0, 1,1,1,1);
SetViewport(560, 400, 100, 100);
DrawImage(0, 0, 1, 1, m_TexMan->m_Text_PrevScreenMap->m_Bind, 0, 1, 1, 0, 1,1,1,1);*/
//Set2DMode(false, 1, 1);
//SetViewport(iTmpX, iTmpY, iTempWidth, iTempHeight);
}
if (CRenderer::CV_r_log)
Logv(0, "******************************* EndFrame ********************************\n");
// End the scene
m_pd3dDevice->EndScene();
m_SceneRecurseCount--;
if (CV_r_ShowVideoMemoryStats)
{
HRESULT hr;
CV_r_ShowVideoMemoryStats = FALSE;
IDirect3DQuery9 *resourceQuery;
BOOL timeOut;
D3DDEVINFO_RESOURCEMANAGER resourceStats;
hr = m_pd3dDevice->CreateQuery(D3DQUERYTYPE_RESOURCEMANAGER, &resourceQuery);
if (hr == D3D_OK)
{
resourceQuery->Issue(D3DISSUE_END);
float timeoutTime = iTimer->GetCurrTime() + 2.0f;
timeOut = FALSE;
// D3DGETDATA_FLUSH
while (resourceQuery->GetData((void *)&resourceStats, sizeof(D3DDEVINFO_RESOURCEMANAGER), 0) != S_OK)
{
if (iTimer->GetCurrTime() < timeoutTime)
{
timeOut = TRUE;
break;
}
}
resourceQuery->Release();
// make sure succeeded
if (!timeOut)
{
for (i=0; i<D3DRTYPECOUNT; i++)
{
iLog->Log("%s - Thrashing = %s, Approx Bytes Downloaded %d, Number Evictions %d",
resourceName[i], resourceStats.stats[i].bThrashing ? "TRUE" : "FALSE",
resourceStats.stats[i].ApproxBytesDownloaded, resourceStats.stats[i].NumEvicts);
iLog->Log(" Number Video Creates %d, Last Priority %d",
resourceStats.stats[i].NumVidCreates, resourceStats.stats[i].LastPri);
iLog->Log(" Number set to Device %d, Number used In Vid mem %d",
resourceStats.stats[i].NumUsed, resourceStats.stats[i].NumUsedInVidMem);
iLog->Log("%s - %d object(s) with %d bytes in video memory.\n",
resourceName[i], resourceStats.stats[i].WorkingSet, resourceStats.stats[i].WorkingSetBytes);
iLog->Log("%s - %d object(s) with %d bytes in managed memory.\n",
resourceName[i], resourceStats.stats[i].TotalManaged, resourceStats.stats[i].TotalBytes);
}
}
}
}
// Flip the back buffer to the front
if(m_bSwapBuffers)
{
if (!m_bEditor)
hReturn = m_pd3dDevice->Present(NULL, NULL, NULL, NULL);
else
{
RECT ClientRect;
ClientRect.top = 0;
ClientRect.left = 0;
ClientRect.right = m_CurrContext->m_Width;
ClientRect.bottom = m_CurrContext->m_Height;
hReturn = m_pd3dDevice->Present(&ClientRect,&ClientRect,m_CurrContext->m_hWnd,NULL);
}
}
hReturn = m_pd3dDevice->BeginScene();
CheckDeviceLost();
if (CV_r_GetScreenShot)
{
ScreenShot();
CV_r_GetScreenShot = 0;
}
m_SceneRecurseCount++;
}
void CD3D9Renderer::ScreenShot(const char *filename)
{
char scname[512];
int i;
FILE *fp;
if (!filename)
{
for (i=0 ; i<10000; i++)
{
#ifdef WIN64
sprintf(scname,"FarCry%04d.tga",i);
#else
sprintf(scname,"FarCry%04d.jpg",i);
#endif
fp = fxopen(scname,"rb");
if (!fp)
break; // file doesn't exist
fclose(fp);
}
if (i==10000)
{
iLog->Log("Cannot save ScreenShot: Too many JPG files\n");
return;
}
}
else
strcpy(scname,filename);
iLog->Log("ScreenShot %s\n",scname);
LPDIRECT3DSURFACE9 pSysDeskSurf;
D3DLOCKED_RECT d3dlrSys;
int wdt = m_deskwidth;
int hgt = m_deskheight;
if (m_bFullScreen)
{
wdt = m_width;
hgt = m_height;
}
HRESULT h = m_pd3dDevice->CreateOffscreenPlainSurface(wdt, hgt, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pSysDeskSurf, NULL);
if (FAILED(h))
return;
h = m_pd3dDevice->GetFrontBufferData(0, pSysDeskSurf);
if (FAILED(h))
return;
POINT WndP;
WndP.x = 0;
WndP.y = 0;
ClientToScreen(m_hWnd, &WndP);
h = pSysDeskSurf->LockRect(&d3dlrSys, NULL, D3DLOCK_READONLY);
if (FAILED(h))
return;
byte *src = (byte *)d3dlrSys.pBits;
int height = m_height;
int width = m_width;
if (WndP.y < 0)
{
height += WndP.y;
WndP.y = 0;
}
if (WndP.x < 0)
{
width += WndP.x;
WndP.x = 0;
}
if (width+WndP.x >= wdt)
width = wdt-WndP.x;
if (height+WndP.y >= hgt)
height = hgt-WndP.y;
//iLog->Log("wdt: %d, hgt: %d, width: %d, height: %d, WndP.x: %d, WndP.y: %d", wdt, hgt, width, height, WndP.x, WndP.y);
unsigned char *pic=new unsigned char [width*height*4];
byte *dst = pic;
src += WndP.y*d3dlrSys.Pitch;
for (i=0; i<height; i++)
{
for (int j=0; j<width; j++)
{
*(uint *)&dst[j*4] = *(uint *)&src[(WndP.x+j)*4];
Exchange(dst[j*4+0], dst[j*4+2]);
}
dst += width*4;
src += d3dlrSys.Pitch;
}
pSysDeskSurf->UnlockRect();
SAFE_RELEASE(pSysDeskSurf);
#ifdef WIN64
//TODO: we need a lib for AMD64 to create JPEG-files
//for TGA we need to flip picture before we store it
uint32* fb1=(uint32*)pic;
uint32* fb2=(uint32*)malloc(height*width*32);
uint32* buffer=fb2;
for(uint32 y=height; y>0; y--) {
uint32* fbuf=fb1+((y-1)*width);
for(uint32 x=0; x<width; x++) { fb2[x]=fbuf[x]; }
fb2+=width;
}
WriteTGA((uint8*)buffer, width, height, scname, 32);
free(buffer);
#else
::WriteJPG(pic, width, height, scname);
#endif
delete [] pic;
}
int CD3D9Renderer::CreateRenderTarget (int nWidth, int nHeight, ETEX_Format eTF)
{
if (!m_RTargets.Num())
m_RTargets.AddIndex(1);
int n = m_RTargets.Num();
for (int i=1; i<m_RTargets.Num(); i++)
{
if (!m_RTargets[i].m_pRT && m_RTargets[i].m_pZB)
{
n = i;
break;
}
}
if (n == m_RTargets.Num())
m_RTargets.AddIndex(1);
SD3DRenderTarget rt;
D3DFORMAT fmt;
switch (eTF)
{
case eTF_8888:
default:
fmt = D3DFMT_A8R8G8B8;
break;
case eTF_0888:
fmt = D3DFMT_X8R8G8B8;
break;
case eTF_4444:
fmt = D3DFMT_A4R4G4B4;
break;
case eTF_0565:
fmt = D3DFMT_R5G6B5;
break;
}
HRESULT hr = m_pd3dDevice->CreateRenderTarget(nWidth, nHeight, fmt, D3DMULTISAMPLE_NONE, 0, TRUE, &rt.m_pRT, NULL);
if ( FAILED(hr) )
return -1;
hr = m_pd3dDevice->CreateDepthStencilSurface(nWidth, nHeight, m_d3dsdZBuffer.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &rt.m_pZB, NULL);
if ( FAILED(hr) )
{
SAFE_RELEASE(rt.m_pRT);
return -1;
}
m_RTargets[n] = rt;
return n;
}
bool CD3D9Renderer::DestroyRenderTarget (int nHandle)
{
if (nHandle <= m_RTargets.Num())
return false;
SD3DRenderTarget *rt = &m_RTargets[nHandle];
SAFE_RELEASE(rt->m_pRT);
SAFE_RELEASE(rt->m_pZB);
return true;
}
bool CD3D9Renderer::SetRenderTarget (int nHandle)
{
if (nHandle == 0)
{
EF_RestoreRenderTarget();
return true;
}
if (nHandle <= m_RTargets.Num())
return false;
SD3DRenderTarget *rt = &m_RTargets[nHandle];
HRESULT hr = S_OK;
if (rt->m_pRT != m_pCurBackBuffer)
{
hr = m_pd3dDevice->SetRenderTarget(0, rt->m_pRT);
m_pCurBackBuffer = rt->m_pRT;
}
if (FAILED(hr))
return false;
if (m_pCurZBuffer != rt->m_pZB)
{
hr = m_pd3dDevice->SetDepthStencilSurface(rt->m_pZB);
m_pCurZBuffer = rt->m_pZB;
}
if (FAILED(hr))
return false;
return true;
}
void CD3D9Renderer::ReadFrameBuffer(unsigned char * pRGB, int nSizeX, int nSizeY, bool bBackBuffer, bool bRGBA, int nScaledX, int nScaledY)
{
int i;
LPDIRECT3DSURFACE9 pSysSurf = NULL;
LPDIRECT3DSURFACE9 pTmpSurface = NULL;
D3DLOCKED_RECT d3dlrSys;
D3DSURFACE_DESC desc;
HRESULT hr;
if (bBackBuffer)
{
if (!m_pCurBackBuffer)
return;
hr = m_pCurBackBuffer->GetDesc(&desc);
if (FAILED(hr))
return;
POINT WndP;
WndP.x = 0;
WndP.y = 0;
//if (m_bEditor)
// ClientToScreen(m_hWnd, &WndP);
RECT srcRect, dstRect;
srcRect.left = WndP.x;
srcRect.right = nSizeX;
srcRect.top = WndP.y;
srcRect.bottom = nSizeY;
if (nScaledX <= 0)
{
nScaledX = nSizeX;
nScaledY = nSizeY;
}
dstRect.left = 0;
dstRect.right = nScaledX;
dstRect.top = 0;
dstRect.bottom = nScaledY;
hr = m_pd3dDevice->CreateRenderTarget(nScaledX, nScaledY, desc.Format, D3DMULTISAMPLE_NONE, 0, TRUE, &pTmpSurface, NULL );
if ( FAILED(hr) )
return;
hr = m_pd3dDevice->StretchRect(m_pCurBackBuffer, &srcRect, pTmpSurface, &dstRect, D3DTEXF_NONE);
if ( FAILED(hr) )
return;
if (desc.Format != D3DFMT_X8R8G8B8 && desc.Format != D3DFMT_A8R8G8B8)
{
// Create a buffer the same size and format
hr = m_pd3dDevice->CreateOffscreenPlainSurface(nScaledX, nScaledY, desc.Format, D3DPOOL_SYSTEMMEM, &pSysSurf, NULL);
D3DXLoadSurfaceFromSurface(pSysSurf, NULL, NULL, pTmpSurface, NULL, NULL, D3DX_FILTER_NONE, 0);
hr = pSysSurf->LockRect(&d3dlrSys, NULL, 0);
}
else
hr = pTmpSurface->LockRect(&d3dlrSys, NULL, 0);
byte *src = (byte *)d3dlrSys.pBits;
byte *dst = pRGB;
if (bRGBA)
{
for (i=0; i<nScaledY; i++)
{
int ni0 = (nScaledY-i-1)*nSizeX*4;
int ni1 = i * d3dlrSys.Pitch;
for (int j=0; j<nScaledX; j++)
{
dst[ni0+j*4+0] = src[ni1+j*4+2];
dst[ni0+j*4+1] = src[ni1+j*4+1];
dst[ni0+j*4+2] = src[ni1+j*4+0];
dst[ni0+j*4+3] = 255;
}
}
}
else
{
for (i=0; i<nScaledY; i++)
{
int ni0 = (nScaledY-i-1)*nScaledX*3;
int ni1 = i * d3dlrSys.Pitch;
for (int j=0; j<nScaledX; j++)
{
dst[ni0+j*3+0] = src[ni1+j*4+0];
dst[ni0+j*3+1] = src[ni1+j*4+1];
dst[ni0+j*3+2] = src[ni1+j*4+2];
}
}
}
if (pSysSurf)
pSysSurf->UnlockRect();
else
if (pTmpSurface)
pTmpSurface->UnlockRect();
}
else
{
hr = m_pd3dDevice->CreateOffscreenPlainSurface(m_deskwidth, m_deskheight, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pSysSurf, NULL);
hr = m_pd3dDevice->GetFrontBufferData(0, pSysSurf);
POINT WndP;
WndP.x = 0;
WndP.y = 0;
ClientToScreen(m_hWnd, &WndP);
hr = pSysSurf->LockRect(&d3dlrSys, NULL, 0);
byte *src = (byte *)d3dlrSys.pBits;
byte *dst = pRGB;
for (i=0; i<nSizeY; i++)
{
int ni0 = (nSizeY-i-1)*nSizeX*4;
for (int j=0; j<nSizeX; j++)
{
*(uint *)&dst[ni0+j*4] = *(uint *)&src[WndP.y*d3dlrSys.Pitch+(WndP.x+j)*4];
Exchange(dst[ni0+j*4+0], dst[ni0+j*4+2]);
}
src += d3dlrSys.Pitch;
}
pSysSurf->UnlockRect();
}
SAFE_RELEASE(pTmpSurface);
SAFE_RELEASE(pSysSurf);
}
int CD3D9Renderer::ScreenToTexture()
{
return 0;
}
void CD3D9Renderer::Draw2dImage(float xpos,float ypos,float w,float h,int textureid,float s0,float t0,float s1,float t1,float angle,float r,float g,float b,float a,float z)
{
if (textureid > TX_FIRSTBIND && unsigned(textureid - TX_FIRSTBIND) >= m_TexMan->m_Textures.size())
{
iLog->LogError ("\001CD3D9Renderer::Draw2dImage(x=%g,y=%g,w=%g,h=%g,texid=%d): invalid texid, should be between %u and %u",
xpos, ypos, w,h, textureid, TX_FIRSTBIND, m_TexMan->m_Textures.size() + TX_FIRSTBIND);
return;
}
if (CV_d3d9_forcesoftware)
return;
if (m_bDeviceLost)
return;
//////////////////////////////////////////////////////////////////////
// Draw a textured quad, texture is assumed to be in video memory
//////////////////////////////////////////////////////////////////////
// Check for the presence of a D3D device
assert(m_pd3dDevice);
if (!m_SceneRecurseCount)
{
iLog->Log("ERROR: CD3D9Renderer::Draw2dImage before BeginScene");
return;
}
PROFILE_FRAME(Draw_2DImage);
DWORD col = D3DRGBA(r,g,b,a);
bool bSaveZTest = ((m_CurState & GS_NODEPTHTEST) == 0);
SetCullMode(R_CULL_DISABLE);
HRESULT hReturn;
xpos = (float)ScaleCoordX(xpos); w = (float)ScaleCoordX(w);
ypos = (float)ScaleCoordY(ypos); h = (float)ScaleCoordY(h);
float fx = xpos-0.5f;
float fy = ypos-0.5f;
float fw = w;
float fh = h;
EF_SelectTMU(0);
if(textureid>0)
SetTexture(textureid);
else
EnableTMU(false);
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
m_matProj->Push();
D3DXMATRIX *m = m_matProj->GetTop();
D3DXMatrixOrthoOffCenterLH(m, 0.0f, (float)m_width, (float)m_height, 0.0f, -1e30f, 1e30f);
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
EF_PushMatrix();
m = m_matView->GetTop();
m_matView->LoadIdentity();
m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
// Lock the entire buffer and obtain a pointer to the location where we have to
// write the vertex data. Note that we specify zero here to lock the entire
// buffer.
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
if (!vQuad)
return;
// Now that we have write access to the buffer, we can copy our vertices
// into it
if (angle!=0)
{
float xsub=(float)(xpos+w/2.0f);
float ysub=(float)(ypos+h/2.0f);
float x,y,x1,y1;
float mcos=cry_cosf(DEG2RAD(angle));
float msin=cry_sinf(DEG2RAD(angle));
x=xpos-xsub;
y=ypos-ysub;
x1=x*mcos-y*msin;
y1=x*msin+y*mcos;
x1+=xsub;y1+=ysub;
// Define the quad
vQuad[0].xyz.x = x1;
vQuad[0].xyz.y = y1;
x=xpos+w-xsub;
y=ypos-ysub;
x1=x*mcos-y*msin;
y1=x*msin+y*mcos;
x1+=xsub;y1+=ysub;
vQuad[1].xyz.x = x1;//fx + fw;
vQuad[1].xyz.y = y1;// fy;
x=xpos+w-xsub;
y=ypos+h-ysub;
x1=x*mcos-y*msin;
y1=x*msin+y*mcos;
x1+=xsub;y1+=ysub;
vQuad[2].xyz.x = x1;//fx + fw;
vQuad[2].xyz.y = y1;//fy + fh;
x=xpos-xsub;
y=ypos+h-ysub;
x1=x*mcos-y*msin;
y1=x*msin+y*mcos;
x1+=xsub;y1+=ysub;
vQuad[3].xyz.x = x1;//fx;
vQuad[3].xyz.y = y1;//fy + fh;
}
else
{
// Define the quad
vQuad[0].xyz.x = fx;
vQuad[0].xyz.y = fy;
vQuad[1].xyz.x = fx + fw;
vQuad[1].xyz.y = fy;
vQuad[2].xyz.x = fx + fw;
vQuad[2].xyz.y = fy + fh;
vQuad[3].xyz.x = fx;
vQuad[3].xyz.y = fy + fh;
}
// set uv's
vQuad[0].st[0] = s0;
vQuad[0].st[1] = 1.0f-t0;
vQuad[1].st[0] = s1;
vQuad[1].st[1] = 1.0f-t0;
vQuad[2].st[0] = s1;
vQuad[2].st[1] = 1.0f-t1;
vQuad[3].st[0] = s0;
vQuad[3].st[1] = 1.0f-t1;
// set data
for(int i=0;i<4;i++)
{
vQuad[i].color.dcolor = col;
vQuad[i].xyz.z = z;
}
// We are finished with accessing the vertex buffer
UnlockVB3D();
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
// Render the two triangles from the data stream
hReturn = m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
EF_PopMatrix();
m_matProj->Pop();
m = m_matProj->GetTop();
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
if (FAILED(hReturn))
{
assert(hReturn);
return;
}
}
void CD3D9Renderer::DrawImage(float xpos,float ypos,float w,float h,int texture_id,float s0,float t0,float s1,float t1,float r,float g,float b,float a)
{
if (m_bDeviceLost)
return;
//////////////////////////////////////////////////////////////////////
// Draw a textured quad, texture is assumed to be in video memory
//////////////////////////////////////////////////////////////////////
// Check for the presence of a D3D device
assert(m_pd3dDevice);
if (!m_SceneRecurseCount)
{
iLog->LogError("CD3D9Renderer::DrawImage before BeginScene");
return;
}
PROFILE_FRAME(Draw_2DImage);
HRESULT hReturn;
float fx = xpos;
float fy = ypos;
float fw = w;
float fh = h;
//if (!pID3DTexture)
// D3DXCreateTextureFromFile(m_pd3dDevice, "d:\\Textures\\Console\\DefaultConsole.tga", &pID3DTexture);
SetCullMode(R_CULL_DISABLE);
EnableTMU(true);
// Lock the entire buffer and obtain a pointer to the location where we have to
// write the vertex data. Note that we specify zero here to lock the entire
// buffer.
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
DWORD col = D3DRGBA(r,g,b,a);
// Now that we have write access to the buffer, we can copy our vertices
// into it
// Define the quad
vQuad[0].xyz.x = xpos;
vQuad[0].xyz.y = ypos;
vQuad[0].xyz.z = 1.0f;
vQuad[0].color.dcolor = col;
vQuad[0].st[0] = s0;
vQuad[0].st[1] = 1.0f-t0;
vQuad[1].xyz.x = xpos + w;
vQuad[1].xyz.y = ypos;
vQuad[1].xyz.z = 1.0f;
vQuad[1].color.dcolor = col;
vQuad[1].st[0] = s1;
vQuad[1].st[1] = 1.0f-t0;
vQuad[2].xyz.x = xpos + w;
vQuad[2].xyz.y = ypos + h;
vQuad[2].xyz.z = 1.0f;
vQuad[2].color.dcolor = col;
vQuad[2].st[0] = s1;
vQuad[2].st[1] = 1.0f-t1;
vQuad[3].xyz.x = xpos;
vQuad[3].xyz.y = ypos + h;
vQuad[3].xyz.z = 1.0f;
vQuad[3].color.dcolor = col;
vQuad[3].st[0] = s0;
vQuad[3].st[1] = 1.0f-t1;
// We are finished with accessing the vertex buffer
UnlockVB3D();
// Activate the image texture
SetTexture(texture_id);
//if (pID3DTexture)
// m_pd3dDevice->SetTexture(0, pID3DTexture);
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
// Render the two triangles from the data stream
hReturn = m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
if (FAILED(hReturn))
{
assert(hReturn);
return;
}
}
void CD3D9Renderer::Draw2dLine(float x1, float y1, float x2, float y2)
{
if (m_bDeviceLost)
return;
SetCullMode(R_CULL_DISABLE);
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
float x1pos=(float)(int)ScaleCoordX(x1);
float y1pos=(float)(int)ScaleCoordY(y1);
float x2pos=(float)(int)ScaleCoordX(x2);
float y2pos=(float)(int)ScaleCoordY(y2);
// Lock the entire buffer and obtain a pointer to the location where we have to
// write the vertex data. Note that we specify zero here to lock the entire
// buffer.
int nOffs;
struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F *vQuad = GetVBPtr2D(2, nOffs);
// Define the line
vQuad[0].x = x1pos;
vQuad[0].y = y1pos;
vQuad[0].z = 1.0f;
vQuad[0].rhw = 1.0f;
vQuad[0].color.dcolor = 0;
vQuad[1].x = x2pos;
vQuad[1].y = y2pos;
vQuad[1].z = 1.0f;
vQuad[1].rhw = 1.0f;
vQuad[1].color.dcolor = 0;
// We are finished with accessing the vertex buffer
UnlockVB2D();
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pVB2D, 0, sizeof(struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_TRP3F_COL4UB_TEX2F);
// Render the two triangles from the data stream
HRESULT hr = m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, nOffs, 1);
if (FAILED(hr))
{
assert(hr);
return;
}
}
void CD3D9Renderer::DrawPoints(Vec3d v[], int nump, CFColor& col, int flags)
{
if (m_bDeviceLost)
return;
}
void CD3D9Renderer::DrawLines(Vec3d v[], int nump, CFColor& col, int flags, float fGround)
{
if (m_bDeviceLost)
return;
if (nump <= 1)
return;
int i;
int st;
EF_SetVertColor();
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
st = GS_NODEPTHTEST;
if (flags & 1)
st |= GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA;
else
st = flags | GS_NODEPTHTEST;
EF_SetState(st);
gRenDev->m_TexMan->m_Text_White->Set();
DWORD c = D3DRGBA(col.r, col.g, col.b, col.a);
int nOffs;
if (fGround >= 0)
{
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(nump*2, nOffs);
for (i=0; i<nump; i++)
{
vQuad[i*2+0].xyz.x = v[i][0]; vQuad[i*2+0].xyz.y = fGround; vQuad[i*2+0].xyz.z = 0;
vQuad[i*2+0].color.dcolor = c;
vQuad[i*2+0].st[0] = 0; vQuad[i*2+0].st[1] = 0;
vQuad[i*2+1].xyz = v[i];
vQuad[i*2+1].color.dcolor = c;
vQuad[i*2+1].st[0] = 0; vQuad[i*2+1].st[1] = 0;
}
// We are finished with accessing the vertex buffer
UnlockVB3D();
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
HRESULT hr = m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, nOffs, nump);
if (FAILED(hr))
{
assert(hr);
return;
}
}
else
{
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(nump, nOffs);
for (i=0; i<nump; i++)
{
vQuad[i].xyz = v[i];
vQuad[i].color.dcolor = c;
vQuad[i].st[0] = 0; vQuad[i].st[1] = 0;
}
// We are finished with accessing the vertex buffer
UnlockVB3D();
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
HRESULT hr = m_pd3dDevice->DrawPrimitive(D3DPT_LINESTRIP, nOffs, nump-1);
if (FAILED(hr))
{
assert(hr);
return;
}
}
}
void CD3D9Renderer::DrawLine(const Vec3d & vPos1, const Vec3d & vPos2)
{
if (m_bDeviceLost)
return;
if (!m_SceneRecurseCount)
{
iLog->Log("ERROR: CD3D9Renderer::DrawLine before BeginScene");
return;
}
SetCullMode(R_CULL_DISABLE);
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
// Lock the entire buffer and obtain a pointer to the location where we have to
// write the vertex data. Note that we specify zero here to lock the entire
// buffer.
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(2, nOffs);
// Define the line
vQuad[0].xyz = vPos1;
vQuad[0].color.dcolor = 0xffffffff;
vQuad[1].xyz = vPos2;
vQuad[1].color.dcolor = 0xffffffff;
// We are finished with accessing the vertex buffer
UnlockVB3D();
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
HRESULT hr = m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, nOffs, 1);
if (FAILED(hr))
{
assert(hr);
return;
}
}
void CD3D9Renderer::DrawLineColor(const Vec3d & vPos1, const CFColor & vColor1, const Vec3d & vPos2, const CFColor & vColor2)
{
if (m_bDeviceLost)
return;
if (!m_SceneRecurseCount)
{
iLog->Log("ERROR: CD3D9Renderer::DrawLine before BeginScene");
return;
}
HRESULT hr;
//hr = D3DXCreateLine(m_pd3dDevice, &m_pLine);
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
// tiago - fixed, it wasn't passing alpha parameter...
DWORD col1 = D3DRGBA(vColor1[0],vColor1[1],vColor1[2], vColor1[3]);
DWORD col2 = D3DRGBA(vColor2[0],vColor2[1],vColor2[2], vColor1[3]);
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(2, nOffs);
if (!vQuad)
return;
// Define the line
vQuad[0].xyz = vPos1;
vQuad[0].color.dcolor = col1;
vQuad[1].xyz = vPos2;
vQuad[1].color.dcolor = col2;
// We are finished with accessing the vertex buffer
UnlockVB3D();
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
hr = m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, nOffs, 1);
if (FAILED(hr))
{
assert(hr);
return;
}
}
//*********************************************************************
void CD3D9Renderer::GetModelViewMatrix(float * mat)
{
memcpy(mat, (D3DXMATRIX *)m_matView->GetTop(), 4*4*sizeof(float));
}
void CD3D9Renderer::GetProjectionMatrix(float * mat)
{
memcpy(mat, (D3DXMATRIX *)m_matProj->GetTop(), 4*4*sizeof(float));
}
///////////////////////////////////////////
void CD3D9Renderer::PushMatrix()
{
assert(m_pd3dDevice);
EF_PushMatrix();
}
///////////////////////////////////////////
void CD3D9Renderer::PopMatrix()
{
assert(m_pd3dDevice);
EF_PopMatrix();
}
///////////////////////////////////////////
void CD3D9Renderer::RotateMatrix(float a,float x,float y,float z)
{
assert(m_pd3dDevice);
D3DXVECTOR3 v;
v[0] = x;
v[1] = y;
v[2] = z;
m_matView->RotateAxisLocal(&v, a * PI/180.0f);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m_matView->GetTop());
m_bInvertedMatrix = false;
}
void CD3D9Renderer::LoadMatrix(const Matrix44 *src)
{
if(src)
m_matView->LoadMatrix((D3DXMATRIX *)src);
else
m_matView->LoadIdentity();
m_bInvertedMatrix = false;
}
void CD3D9Renderer::RotateMatrix(const Vec3d & angles)
{
D3DXMATRIX mat;
D3DXMATRIX *m = m_matView->GetTop();
D3DXMatrixRotationZ(&mat, angles.z * PI/180);
m_matView->MultMatrixLocal(&mat);
D3DXMatrixRotationY(&mat, angles.y * PI/180);
m_matView->MultMatrixLocal(&mat);
D3DXMatrixRotationX(&mat, angles.x * PI/180);
m_matView->MultMatrixLocal(&mat);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m_matView->GetTop());
m_bInvertedMatrix = false;
}
void CD3D9Renderer::MultMatrix(float * mat)
{
m_matView->MultMatrixLocal((D3DXMATRIX *)mat);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m_matView->GetTop());
m_bInvertedMatrix = false;
}
///////////////////////////////////////////
void CD3D9Renderer::ScaleMatrix(float x,float y,float z)
{
assert(m_pd3dDevice);
m_matView->ScaleLocal(x, y, z);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m_matView->GetTop());
m_bInvertedMatrix = false;
}
///////////////////////////////////////////
void CD3D9Renderer::TranslateMatrix(float x,float y,float z)
{
assert(m_pd3dDevice);
m_matView->TranslateLocal(x, y, z);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m_matView->GetTop());
m_bInvertedMatrix = false;
}
void CD3D9Renderer::TranslateMatrix(const Vec3d &pos)
{
assert(m_pd3dDevice);
float x = pos[0];
float y = pos[1];
float z = pos[2];
m_matView->TranslateLocal(x,y,z);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m_matView->GetTop());
m_bInvertedMatrix = false;
}
void CD3D9Renderer::SetPerspective(const CCamera &cam)
{
D3DXMATRIX *m = m_matProj->GetTop();
D3DXMatrixPerspectiveFovRH(m, cam.GetFov()*cam.GetProjRatio(), 1.0f/cam.GetProjRatio(), cam.GetZMin(), cam.GetZMax());
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
}
//-----------------------------------------------------------------------------
// coded by ivo:
// calculate parameter for an off-center projection matrix.
// the projection matrix itself is calculated by D3D9.
//-----------------------------------------------------------------------------
D3DXMATRIX OffCenterProjection(const CCamera& cam, const Vec3& nv, unsigned short max, unsigned short win_width, unsigned short win_height) {
//get the size of near plane
float l=+nv.x;
float r=-nv.x;
float b=-nv.z;
float t=+nv.z;
//---------------------------------------------------
float max_x=(float)max;
float max_z=(float)max;
float win_x=(float)win_width;
float win_z=(float)win_height;
if ((win_x<max_x) && (win_z<max_z) ) {
//calculate parameters for off-center projection-matrix
float ext_x=-nv.x*2;
float ext_z=+nv.z*2;
l=+nv.x+(ext_x/max_x)*win_x;
r=+nv.x+(ext_x/max_x)*(win_x+1);
t=+nv.z-(ext_z/max_z)*win_z;
b=+nv.z-(ext_z/max_z)*(win_z+1);
}
D3DXMATRIX m;
D3DXMatrixPerspectiveOffCenterRH(&m, l,r,b,t, cam.GetZMin(), cam.GetZMax());
return m;
}
void CD3D9Renderer::SetCamera(const CCamera &cam)
{
assert(m_pd3dDevice);
Matrix44 mat = cam.GetVCMatrixD3D9();
D3DXMATRIX *m = m_matView->GetTop();
m_matView->LoadMatrix((D3DXMATRIX *)&mat);
if (m_RP.m_PersFlags & RBPF_DRAWMIRROR)
m_matView->Scale(1,-1,1);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
D3DXMatrixInverse(&m_matViewInv, NULL, m);
m = m_matProj->GetTop();
m_eCull = (ECull)-1;
float fov=cam.GetFov()*cam.GetProjRatio();
D3DXMatrixPerspectiveFovRH(m, fov, 1.0f/cam.GetProjRatio(), cam.GetZMin(), cam.GetZMax());
//IVO: code to check, if off-center projection works
if (0)
{
unsigned short win_width =0xffff;
unsigned short win_height =0xffff;
//DEBUG_STUFF: Vladimir please remove this
if ((GetAsyncKeyState('I') & 0x8000)) { win_width=0; win_height=0; }
if ((GetAsyncKeyState('O') & 0x8000)) { win_width=1; win_height=0; }
if ((GetAsyncKeyState('K') & 0x8000)) { win_width=0; win_height=1; }
if ((GetAsyncKeyState('L') & 0x8000)) { win_width=1; win_height=1; }
//get edge information of frustum
Vec3 edge_plt=cam.GetEdgeP();
Vec3 edge_nlt=cam.GetEdgeN();;
//adjust distance of projection-plane to camera (width & height is fixed)
edge_plt.y = cry_cosf(fov*0.5f) / cry_sinf(fov*0.5f) * edge_plt.z;
//recalculate size of near-plane (distance is fixed)
edge_nlt.x = (edge_nlt.y/edge_plt.y)*edge_plt.x;
edge_nlt.z = (edge_nlt.y/edge_plt.y)*edge_plt.z;
//overwrite the original projection matrix
//parametes: max:xz win:xz
//if values in win are bigger/equal to max, then functions returns no part-screen mat
*m=OffCenterProjection(cam, edge_nlt, 0x02, win_width, win_height );
}
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
m_bInvertedMatrix = false;
EF_SetCameraInfo();
m_cam = cam;
}
void CD3D9Renderer::SetViewport(int x, int y, int width, int height)
{
//SAFE_RELEASE(m_pLine);
if (!x && !y && !width && !height)
{
m_Viewport.X = m_VX;
m_Viewport.Y = m_VY;
m_Viewport.Width = m_VWidth;
m_Viewport.Height = m_VHeight;
m_Viewport.MinZ = 0.0;
m_Viewport.MaxZ = 1.0;
m_pd3dDevice->SetViewport(&m_Viewport);
//HRESULT hr = D3DXCreateLine(m_pd3dDevice, &m_pLine);
return;
}
m_VX = x;
m_VY = y;
m_VWidth = width;
m_VHeight = height;
m_Viewport.X = m_VX;
m_Viewport.Y = m_VY;
m_Viewport.Width = m_VWidth;
m_Viewport.Height = m_VHeight;
m_Viewport.MinZ = 0.0;
m_Viewport.MaxZ = 1.0;
m_pd3dDevice->SetViewport(&m_Viewport);
//HRESULT hr = D3DXCreateLine(m_pd3dDevice, &m_pLine);
}
void CD3D9Renderer::SetScissor(int x, int y, int width, int height)
{
if (!x && !y && !width && !height)
EF_Scissor(false, x, y, width, height);
else
EF_Scissor(true, x, y, width, height);
}
void CD3D9Renderer::Flush3dBBox(const Vec3d &mins,const Vec3d &maxs,const bool bSolid)
{
SetCullMode(R_CULL_DISABLE);
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
HRESULT hr;
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad;
if(bSolid)
{
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = maxs.x; vQuad[0].xyz.y = mins.y; vQuad[0].xyz.z = mins.z; //3
vQuad[1].xyz.x = maxs.x; vQuad[1].xyz.y = mins.y; vQuad[1].xyz.z = maxs.z; //2
vQuad[2].xyz.x = mins.x; vQuad[2].xyz.y = mins.y; vQuad[2].xyz.z = maxs.z; //1
vQuad[3].xyz.x = mins.x; vQuad[3].xyz.y = mins.y; vQuad[3].xyz.z = mins.z; //0
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = mins.x; vQuad[0].xyz.y = mins.y; vQuad[0].xyz.z = mins.z; //0
vQuad[1].xyz.x = mins.x; vQuad[1].xyz.y = mins.y; vQuad[1].xyz.z = maxs.z; //1
vQuad[2].xyz.x = mins.x; vQuad[2].xyz.y = maxs.y; vQuad[2].xyz.z = maxs.z; //6
vQuad[3].xyz.x = mins.x; vQuad[3].xyz.y = maxs.y; vQuad[3].xyz.z = mins.z; //4
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = mins.x; vQuad[0].xyz.y = maxs.y; vQuad[0].xyz.z = mins.z; //4
vQuad[1].xyz.x = mins.x; vQuad[1].xyz.y = maxs.y; vQuad[1].xyz.z = maxs.z; //6
vQuad[2].xyz.x = maxs.x; vQuad[2].xyz.y = maxs.y; vQuad[2].xyz.z = maxs.z; //7
vQuad[3].xyz.x = maxs.x; vQuad[3].xyz.y = maxs.y; vQuad[3].xyz.z = mins.z; //5
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = maxs.x; vQuad[0].xyz.y = maxs.y; vQuad[0].xyz.z = mins.z; //54
vQuad[1].xyz.x = maxs.x; vQuad[1].xyz.y = maxs.y; vQuad[1].xyz.z = maxs.z; //73
vQuad[2].xyz.x = maxs.x; vQuad[2].xyz.y = mins.y; vQuad[2].xyz.z = maxs.z; //22
vQuad[3].xyz.x = maxs.x; vQuad[3].xyz.y = mins.y; vQuad[3].xyz.z = mins.z; //31
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
// top
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = maxs.x; vQuad[0].xyz.z = maxs.z; vQuad[0].xyz.y = mins.y; //3
vQuad[1].xyz.x = maxs.x; vQuad[1].xyz.z = maxs.z; vQuad[1].xyz.y = maxs.y; //2
vQuad[2].xyz.x = mins.x; vQuad[2].xyz.z = maxs.z; vQuad[2].xyz.y = maxs.y; //1
vQuad[3].xyz.x = mins.x; vQuad[3].xyz.z = maxs.z; vQuad[3].xyz.y = mins.y; //0
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
// bottom
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = maxs.x; vQuad[0].xyz.z = mins.z; vQuad[0].xyz.y = mins.y; //3
vQuad[1].xyz.x = maxs.x; vQuad[1].xyz.z = mins.z; vQuad[1].xyz.y = maxs.y; //2
vQuad[2].xyz.x = mins.x; vQuad[2].xyz.z = mins.z; vQuad[2].xyz.y = maxs.y; //1
vQuad[3].xyz.x = mins.x; vQuad[3].xyz.z = mins.z; vQuad[3].xyz.y = mins.y; //0
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
}
else
{
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = maxs.x; vQuad[0].xyz.y = mins.y; vQuad[0].xyz.z = mins.z; //3
vQuad[1].xyz.x = maxs.x; vQuad[1].xyz.y = mins.y; vQuad[1].xyz.z = maxs.z; //2
vQuad[2].xyz.x = mins.x; vQuad[2].xyz.y = mins.y; vQuad[2].xyz.z = maxs.z; //1
vQuad[3].xyz.x = mins.x; vQuad[3].xyz.y = mins.y; vQuad[3].xyz.z = mins.z; //0
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, nOffs, 2);
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = mins.x; vQuad[0].xyz.y = mins.y; vQuad[0].xyz.z = mins.z; //0
vQuad[1].xyz.x = mins.x; vQuad[1].xyz.y = mins.y; vQuad[1].xyz.z = maxs.z; //1
vQuad[2].xyz.x = mins.x; vQuad[2].xyz.y = maxs.y; vQuad[2].xyz.z = maxs.z; //6
vQuad[3].xyz.x = mins.x; vQuad[3].xyz.y = maxs.y; vQuad[3].xyz.z = mins.z; //4
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, nOffs, 2);
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = mins.x; vQuad[0].xyz.y = maxs.y; vQuad[0].xyz.z = mins.z; //4
vQuad[1].xyz.x = mins.x; vQuad[1].xyz.y = maxs.y; vQuad[1].xyz.z = maxs.z; //6
vQuad[2].xyz.x = maxs.x; vQuad[2].xyz.y = maxs.y; vQuad[2].xyz.z = maxs.z; //7
vQuad[3].xyz.x = maxs.x; vQuad[3].xyz.y = maxs.y; vQuad[3].xyz.z = mins.z; //5
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, nOffs, 2);
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = maxs.x; vQuad[0].xyz.y = mins.y; vQuad[0].xyz.z = mins.z; //54
vQuad[1].xyz.x = maxs.x; vQuad[1].xyz.y = mins.y; vQuad[1].xyz.z = maxs.z; //73
vQuad[2].xyz.x = maxs.x; vQuad[2].xyz.y = maxs.y; vQuad[2].xyz.z = maxs.z; //22
vQuad[3].xyz.x = maxs.x; vQuad[3].xyz.y = maxs.y; vQuad[3].xyz.z = mins.z; //31
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, nOffs, 2);
// top
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(5, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = maxs.x; vQuad[0].xyz.z = maxs.z; vQuad[0].xyz.y = mins.y; //3
vQuad[1].xyz.x = maxs.x; vQuad[1].xyz.z = maxs.z; vQuad[1].xyz.y = maxs.y; //2
vQuad[2].xyz.x = mins.x; vQuad[2].xyz.z = maxs.z; vQuad[2].xyz.y = maxs.y; //1
vQuad[3].xyz.x = mins.x; vQuad[3].xyz.z = maxs.z; vQuad[3].xyz.y = mins.y; //0
vQuad[4].xyz.x = maxs.x; vQuad[4].xyz.z = maxs.z; vQuad[4].xyz.y = mins.y; //3
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_LINESTRIP, nOffs, 4);
// bottom
vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(5, nOffs);
hr = m_pd3dDevice->SetStreamSource( 0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
vQuad[0].xyz.x = maxs.x; vQuad[0].xyz.z = mins.z; vQuad[0].xyz.y = mins.y; //3
vQuad[1].xyz.x = maxs.x; vQuad[1].xyz.z = mins.z; vQuad[1].xyz.y = maxs.y; //2
vQuad[2].xyz.x = mins.x; vQuad[2].xyz.z = mins.z; vQuad[2].xyz.y = maxs.y; //1
vQuad[3].xyz.x = mins.x; vQuad[3].xyz.z = mins.z; vQuad[3].xyz.y = mins.y; //0
vQuad[4].xyz.x = maxs.x; vQuad[4].xyz.z = mins.z; vQuad[4].xyz.y = mins.y; //3
UnlockVB3D();
m_pd3dDevice->DrawPrimitive(D3DPT_LINESTRIP, nOffs, 4);
}
}
void CD3D9Renderer::Draw3dBBox(const Vec3d &mins,const Vec3d &maxs, int nPrimType)
{
Draw3dPrim(mins, maxs, nPrimType);
}
void CD3D9Renderer::Draw3dPrim(const Vec3d &mins,const Vec3d &maxs, int nPrimType, const float* pRGBA)
{
BBoxInfo info;
info.vMins = mins;
info.vMaxs = maxs;
info.nPrimType = nPrimType;
if (pRGBA)
{
for (int i = 0; i < 4; ++i)
info.fColor[i] = pRGBA[i];
}
else
{
info.fColor[0] = m_RP.m_CurGlobalColor.bcolor[0] / 255.0f;
info.fColor[1] = m_RP.m_CurGlobalColor.bcolor[1] / 255.0f;
info.fColor[2] = m_RP.m_CurGlobalColor.bcolor[2] / 255.0f;
info.fColor[3] = m_RP.m_CurGlobalColor.bcolor[3] / 255.0f;
}
m_arrBoxesToDraw.push_back(info);
}
void CD3D9Renderer::SetCullMode(int mode)
{
//////////////////////////////////////////////////////////////////////
// Change the culling mode
//////////////////////////////////////////////////////////////////////
assert(m_pd3dDevice);
switch (mode)
{
case R_CULL_DISABLE:
D3DSetCull(eCULL_None);
break;
case R_CULL_BACK:
D3DSetCull(eCULL_Back);
break;
case R_CULL_FRONT:
D3DSetCull(eCULL_Front);
break;
}
}
void CD3D9Renderer::SetFog(float density, float fogstart, float fogend, const float *color, int fogmode)
{
//////////////////////////////////////////////////////////////////////
// Configure the fog settings
//////////////////////////////////////////////////////////////////////
D3DCOLOR dwColor;
assert(m_pd3dDevice);
m_pd3dDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
m_FS.m_FogDensity = density;
m_FS.m_FogStart = fogstart;
m_FS.m_FogEnd = fogend;
m_FS.m_nFogMode = fogmode;
m_FS.m_nCurFogMode = fogmode;
CFColor col = CFColor(color[0], color[1], color[2], 1.0f);
if (m_bHeatVision)
col = CFColor(0.0f, 0.0f, 0.0f, 1.0f);
m_FS.m_FogColor = col;
// Fog color
dwColor = D3DRGBA(col[0],col[1],col[2],col[3]);
EF_SetFogColor(dwColor, true, false);
// Fog start and end
m_pd3dDevice->SetRenderState(D3DRS_FOGSTART, *((LPDWORD)&fogstart));
m_pd3dDevice->SetRenderState(D3DRS_FOGEND, *((LPDWORD) &fogend));
// Fog mode
switch (fogmode)
{
case R_FOGMODE_LINEAR:
m_pd3dDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
density = 1;
m_pd3dDevice->SetRenderState(D3DRS_FOGDENSITY, *((LPDWORD) (&density)));
break;
case R_FOGMODE_EXP2:
m_pd3dDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_EXP2);
m_pd3dDevice->SetRenderState(D3DRS_FOGDENSITY, *((LPDWORD) (&density)));
break;
default:
// Invalid mode
// Disable
m_pd3dDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
break;
}
}
void CD3D9Renderer::SetFogColor(float * color)
{
m_FS.m_FogColor = CFColor(color);
D3DCOLOR dwColor;
// Fog color
dwColor = D3DRGBA(color[0],color[1],color[2],color[3]);
EF_SetFogColor(dwColor, true, false);
}
bool CD3D9Renderer::EnableFog(bool enable)
{
//////////////////////////////////////////////////////////////////////
// Enable or disable fog
//////////////////////////////////////////////////////////////////////
assert(m_pd3dDevice);
bool bPrevFog = m_FS.m_bEnable; // remember fog value
if (bPrevFog != enable)
m_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, enable);
m_FS.m_bEnable = enable;
return bPrevFog;
}
///////////////////////////////////////////
void CD3D9Renderer::EnableTexGen(bool enable)
{
if (enable)
m_pd3dDevice->SetTextureStageState( m_TexMan->m_CurStage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | m_TexMan->m_CurStage);
else
{
D3DXMATRIX mat;
D3DXMatrixIdentity(&mat);
m_pd3dDevice->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+m_TexMan->m_CurStage), &mat );
m_pd3dDevice->SetTextureStageState( m_TexMan->m_CurStage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | m_TexMan->m_CurStage);
m_pd3dDevice->SetTextureStageState( m_TexMan->m_CurStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
}
m_RP.m_TexStages[m_TexMan->m_CurStage].TCIndex = m_TexMan->m_CurStage;
}
void CD3D9Renderer::SetTexgen3D(float x1, float y1, float z1, float x2, float y2, float z2)
{
assert(m_pd3dDevice);
D3DXMATRIX mat, *mi;
mat._11 = x1; mat._12 = x2; mat._13 = 0.0f; mat._14 = 0.0f;
mat._21 = y1; mat._22 = y2; mat._23 = 0.0f; mat._24 = 0.0f;
mat._31 = z1; mat._32 = z2; mat._33 = 0.0f; mat._34 = 0.0f;
mat._41 = 0; mat._42 = 0; mat._43 = 0.0f; mat._44 = 1.0f;
mi = EF_InverseMatrix();
D3DXMatrixMultiply(&mat, mi, &mat);
m_pd3dDevice->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+m_TexMan->m_CurStage), &mat );
m_pd3dDevice->SetTextureStageState( m_TexMan->m_CurStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
m_pd3dDevice->SetTextureStageState( m_TexMan->m_CurStage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | m_TexMan->m_CurStage);
m_RP.m_TexStages[m_TexMan->m_CurStage].TCIndex = m_TexMan->m_CurStage;
}
void CD3D9Renderer::SetTexgen(float scaleX, float scaleY,float translateX,float translateY)
{
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
assert(m_pd3dDevice);
D3DXMATRIX mat, *mi;
mat._11 = 0.0f; mat._12 = scaleX; mat._13 = 0.0f; mat._14 = 0.0f;
mat._21 = scaleY; mat._22 = 0.0f; mat._23 = 0.0f; mat._24 = 0.0f;
mat._31 = 0.0f; mat._32 = 0.0f; mat._33 = 1.0f; mat._34 = 0.0f;
mat._41 = translateY; mat._42 = translateX; mat._43 = 0.0f; mat._44 = 1.0f;
mi = EF_InverseMatrix();
D3DXMatrixMultiply(&mat, mi, &mat);
m_pd3dDevice->SetTransform( (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+m_TexMan->m_CurStage), &mat );
m_pd3dDevice->SetTextureStageState( m_TexMan->m_CurStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
m_pd3dDevice->SetTextureStageState( m_TexMan->m_CurStage, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | m_TexMan->m_CurStage);
m_RP.m_TexStages[m_TexMan->m_CurStage].TCIndex = m_TexMan->m_CurStage;
}
void CD3D9Renderer::SetLodBias(float value)
{
//////////////////////////////////////////////////////////////////////
// Set the mip-map LOD bias
//////////////////////////////////////////////////////////////////////
assert(m_pd3dDevice);
value = -value;
m_pd3dDevice->SetSamplerState(m_TexMan->m_CurStage, D3DSAMP_MIPMAPLODBIAS, *((LPDWORD)(&value)));
}
void CD3D9Renderer::SelectTMU(int tnum)
{
m_TexMan->m_CurStage = tnum;
}
void CD3D9Renderer::EnableTMU(bool enable)
{
assert(m_pd3dDevice);
byte eCO = (enable ? eCO_MODULATE : eCO_DISABLE);
EF_SetColorOp(eCO, eCO, 255, 255);
if (!enable)
{
m_pd3dDevice->SetTexture(m_TexMan->m_CurStage, NULL);
m_RP.m_TexStages[m_TexMan->m_CurStage].Texture = NULL;
}
}
///////////////////////////////////////////
void CD3D9Renderer::CheckError(const char *comment)
{
}
///////////////////////////////////////////
int CD3D9Renderer::SetPolygonMode(int mode)
{
int prev_mode = m_polygon_mode;
m_polygon_mode = mode;
if (CV_d3d9_forcesoftware)
return prev_mode;
if(m_polygon_mode == R_WIREFRAME_MODE)
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
else
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
return prev_mode;
}
///////////////////////////////////////////
void CD3D9Renderer::EnableVSync(bool enable)
{
}
void CD3D9Renderer::DrawQuad(const Vec3d &right, const Vec3d &up, const Vec3d &origin,int nFlipMode/*=0*/)
{
PROFILE_FRAME(Draw_2DImage);
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F Verts[4];
Vec3d curr;
curr=origin+(-right-up);
Verts[0].xyz[0] = curr[0]; Verts[0].xyz[1] = curr[1]; Verts[0].xyz[2] = curr[2];
Verts[0].st[0] = -1; Verts[0].st[1] = 0;
curr=origin+(right-up);
Verts[1].xyz[0] = curr[0]; Verts[1].xyz[1] = curr[1]; Verts[1].xyz[2] = curr[2];
Verts[1].st[0] = 0; Verts[1].st[1] = 0;
curr=origin+(right+up);
Verts[2].xyz[0] = curr[0]; Verts[2].xyz[1] = curr[1]; Verts[2].xyz[2] = curr[2];
Verts[2].st[0] = 0; Verts[2].st[1] = 1;
curr=origin+(-right+up);
Verts[3].xyz[0] = curr[0]; Verts[3].xyz[1] = curr[1]; Verts[3].xyz[2] = curr[2];
Verts[3].st[0] = -1; Verts[3].st[1] = 1;
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
memcpy(vQuad, Verts, 4*sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
UnlockVB3D();
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
m_nPolygons += 2;
}
void CD3D9Renderer::DrawQuad(float dy,float dx, float dz, float x, float y, float z)
{
PROFILE_FRAME(Draw_2DImage);
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F Verts[4];
Verts[0].xyz[0] = -dx+x; Verts[0].xyz[1] = dy+y; Verts[0].xyz[2] = -dz+z;
Verts[0].st[0] = 0; Verts[0].st[1] = 0;
Verts[1].xyz[0] = dx+x; Verts[1].xyz[1] = -dy+y; Verts[1].xyz[2] = -dz+z;
Verts[1].st[0] = 1; Verts[1].st[1] = 0;
Verts[2].xyz[0] = dx+x; Verts[2].xyz[1] = -dy+y; Verts[2].xyz[2] = dz+z;
Verts[2].st[0] = 1; Verts[2].st[1] = 1;
Verts[3].xyz[0] = -dx+x; Verts[3].xyz[1] = dy+y; Verts[3].xyz[2] = dz+z;
Verts[3].st[0] = 0; Verts[3].st[1] = 1;
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
memcpy(vQuad, Verts, 4*sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
UnlockVB3D();
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
m_nPolygons += 2;
}
void CD3D9Renderer::DrawQuad(float x0, float y0, float x1, float y1, const CFColor & color, float z)
{
PROFILE_FRAME(Draw_2DImage);
LPDIRECT3DDEVICE9 dv = mfGetD3DDevice();
DWORD col = D3DRGBA(color.r, color.g, color.b, color.a);
int nOffs;
struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F *vQuad = GetVBPtr2D(4, nOffs);
float ftx0 = 0;
float fty0 = 0;
float ftx1 = 1;
float fty1 = 1;
// Define the quad
vQuad[0].x = x0;
vQuad[0].y = y0;
vQuad[0].z = z;
vQuad[0].rhw = 1.0f;
vQuad[0].color.dcolor = col;
vQuad[0].st[0] = ftx0;
vQuad[0].st[1] = fty0;
vQuad[1].x = x1;
vQuad[1].y = y0;
vQuad[1].z = z;
vQuad[1].rhw = 1.0f;
vQuad[1].color.dcolor = col;
vQuad[1].st[0] = ftx1;
vQuad[1].st[1] = fty0;
vQuad[2].x = x1;
vQuad[2].y = y1;
vQuad[2].z = z;
vQuad[2].rhw = 1.0f;
vQuad[2].color.dcolor = col;
vQuad[2].st[0] = ftx1;
vQuad[2].st[1] = fty1;
vQuad[3].x = x0;
vQuad[3].y = y1;
vQuad[3].z = z;
vQuad[3].rhw = 1.0f;
vQuad[3].color.dcolor = col;
vQuad[3].st[0] = ftx0;
vQuad[3].st[1] = fty1;
UnlockVB2D();
dv->SetStreamSource(0, m_pVB2D, 0, sizeof(struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_TRP3F_COL4UB_TEX2F);
dv->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
m_nPolygons += 2;
}
void CD3D9Renderer::DrawQuad3D(const Vec3d & v0, const Vec3d & v1, const Vec3d & v2, const Vec3d & v3,
const CFColor & color, float ftx0, float fty0, float ftx1, float fty1)
{
LPDIRECT3DDEVICE9 dv = mfGetD3DDevice();
DWORD col = D3DRGBA(color.r, color.g, color.b, color.a);
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(4, nOffs);
// Define the quad
vQuad[0].xyz.x = v0.x;
vQuad[0].xyz.y = v0.y;
vQuad[0].xyz.z = v0.z;
vQuad[0].color.dcolor = col;
vQuad[0].st[0] = ftx0;
vQuad[0].st[1] = fty0;
//vQuad[0].st[2] = ftx0;
//vQuad[0].st[3] = fty0;
vQuad[1].xyz.x = v1.x;
vQuad[1].xyz.y = v1.y;
vQuad[1].xyz.z = v1.z;
vQuad[1].color.dcolor = col;
vQuad[1].st[0] = ftx1;
vQuad[1].st[1] = fty0;
//vQuad[1].st[2] = ftx1;
//vQuad[1].st[3] = fty0;
vQuad[2].xyz.x = v2.x;
vQuad[2].xyz.y = v2.y;
vQuad[2].xyz.z = v2.z;
vQuad[2].color.dcolor = col;
vQuad[2].st[0] = ftx1;
vQuad[2].st[1] = fty1;
//vQuad[2].st[2] = ftx1;
//vQuad[2].st[3] = fty1;
vQuad[3].xyz.x = v3.x;
vQuad[3].xyz.y = v3.y;
vQuad[3].xyz.z = v3.z;
vQuad[3].color.dcolor = col;
vQuad[3].st[0] = ftx0;
vQuad[3].st[1] = fty1;
//vQuad[3].st[2] = ftx0;
//vQuad[3].st[3] = fty1;
UnlockVB3D();
dv->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
dv->DrawPrimitive(D3DPT_TRIANGLEFAN, nOffs, 2);
m_nPolygons += 2;
}
void CD3D9Renderer::DrawPoint(float x, float y, float z, float fSize)
{
if (!m_SceneRecurseCount)
{
iLog->Log("ERROR: CD3D9Renderer::DrawPoint before BeginScene");
return;
}
m_pd3dDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&fSize));
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *Verts = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(1, nOffs);
Verts[0].xyz[0] = x; Verts[0].xyz[1] = y; Verts[0].xyz[2] = z;
UnlockVB3D();
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
EF_SetVertexDeclaration(0, VERTEX_FORMAT_P3F_COL4UB_TEX2F);
m_pd3dDevice->DrawPrimitive(D3DPT_POINTLIST, nOffs, 1);
m_nPolygons += 1;
}
///////////////////////////////////////////
void CD3D9Renderer::DrawTriStrip(CVertexBuffer *src, int vert_num)
{
if (!m_SceneRecurseCount)
{
iLog->Log("ERROR: CD3D9Renderer::DrawTriStrip before BeginScene");
return;
}
HRESULT h;
EF_SetVertexDeclaration(0, src->m_vertexformat);
switch (src->m_vertexformat)
{
case VERTEX_FORMAT_P3F_TEX2F:
{
struct_VERTEX_FORMAT_P3F_TEX2F *dt = (struct_VERTEX_FORMAT_P3F_TEX2F *)src->m_VS[VSF_GENERAL].m_VData;
h = m_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, vert_num-2, dt, sizeof(struct_VERTEX_FORMAT_P3F_TEX2F));
}
break;
case VERTEX_FORMAT_P3F_COL4UB:
{
struct_VERTEX_FORMAT_P3F_COL4UB *dt = (struct_VERTEX_FORMAT_P3F_COL4UB *)src->m_VS[VSF_GENERAL].m_VData;
EF_SetVertColor();
h = m_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, vert_num-2, dt, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB));
}
break;
case VERTEX_FORMAT_P3F_COL4UB_TEX2F:
{
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *dt = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)src->m_VS[VSF_GENERAL].m_VData;
EF_SetVertColor();
int nOffs;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *Verts = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *)GetVBPtr3D(vert_num, nOffs);
cryMemcpy(Verts, dt, vert_num*sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, nOffs, vert_num-2);
}
break;
case VERTEX_FORMAT_P3F_COL4UB_TEX2F_TEX2F:
{
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F_TEX2F *dt = (struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F_TEX2F *)src->m_VS[VSF_GENERAL].m_VData;
EF_SetVertColor();
h = m_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, vert_num-2, dt, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F_TEX2F));
}
break;
case VERTEX_FORMAT_TRP3F_COL4UB_TEX2F:
{
struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F *dt = (struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F *)src->m_VS[VSF_GENERAL].m_VData;
EF_SetVertColor();
int nOffs;
struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F *Verts = (struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F *)GetVBPtr2D(vert_num, nOffs);
cryMemcpy(Verts, dt, vert_num*sizeof(struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F));
m_pd3dDevice->SetStreamSource(0, m_pVB3D[0], 0, sizeof(struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F));
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, nOffs, vert_num-2);
}
break;
default:
assert(0);
break;
}
m_nPolygons += vert_num-2;
}
///////////////////////////////////////////
void CD3D9Renderer::ResetToDefault()
{
if (m_LogFile)
Logv(SRendItem::m_RecurseLevel, ".... ResetToDefault ....\n");
EF_Scissor(false, 0, 0, 0, 0);
if (m_RP.m_ClipPlaneWasOverrided == 2)
{
m_pd3dDevice->SetClipPlane(0, &m_RP.m_CurClipPlane.m_Normal[0]);
m_RP.m_ClipPlaneWasOverrided = 0;
}
for (int i=0; i<m_numtmus; i++)
{
EF_SelectTMU(i);
m_eCurColorOp[i] = -1;
m_eCurAlphaOp[i] = -1;
m_eCurColorArg[i] = -1;
m_eCurAlphaArg[i] = -1;
m_pd3dDevice->SetTextureStageState( i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
m_RP.m_TexStages[i].Projected = false;
m_RP.m_TexStages[i].TCIndex = i;
m_pd3dDevice->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i);
// tiago: added
SetLodBias(CRenderer::CV_r_maxtexlod_bias);
if (!i)
{
EnableTMU(true);
}
else
{
EnableTMU(false);
}
EnableTexGen(false);
}
EF_SelectTMU(0);
gRenDev->m_TexMan->m_Text_White->Set();
gRenDev->m_TexMan->m_nCurStages = 1;
m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
if (m_d3dCaps.RasterCaps & (D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS))
m_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0xf);
m_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, FALSE);
EF_SetVertColor();
m_RP.m_FlagsModificators = 0;
m_RP.m_PersFlags &= ~(RBPF_VSNEEDSET | RBPF_PS1NEEDSET);
m_RP.m_PersFlags &= ~RBPF_WASWORLDSPACE;
m_RP.m_CurrentVLights = 0;
EF_CommitShadersState();
EF_CommitVLightsState();
m_CurState = GS_DEPTHWRITE;
m_eCull = (ECull)-1;
D3DSetCull(eCULL_Back);
m_FS.m_nCurFogMode = m_FS.m_nFogMode;
m_pd3dDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
if (m_LogFile && CV_r_log == 3)
Logv(SRendItem::m_RecurseLevel, ".... End ResetToDefault ....\n");
CPShader::m_CurRC = NULL;
CVProgram::m_LastVP = NULL;
CPShader::m_LastVP = NULL;
}
//////////////////////////////////////////
int CD3D9Renderer::GenerateAlphaGlowTexture(float k)
{
// float k = 6;
const int tex_size = 256;
static byte data[tex_size][tex_size];
memset(&data[0][0], 255, tex_size*tex_size);
for(int x=0; x<tex_size; x++)
for(int y=0; y<tex_size; y++)
{
float _x = (float)(x-tex_size/2);
float _y = (float)(y-tex_size/2);
float val = (float)k*2.f*((float)tex_size/2 - (float)(cry_sqrtf(_x*_x+_y*_y)));
val = CLAMP(val, 0.0f, 255.0f);
data[x][y] = (int)(val);
}
return DownLoadToVideoMemory((unsigned char*)data,tex_size,tex_size,eTF_8000,eTF_8000,true,true,FILTER_LINEAR, 0, "$AlphaGlow");
}
///////////////////////////////////////////
void CD3D9Renderer::SetMaterialColor(float r, float g, float b, float a)
{
EF_SetGlobalColor(r, g, b, a);
}
///////////////////////////////////////////
int CD3D9Renderer::LoadAnimatedTexture(const char * szFileNameFormat,const int nCount)
{
if(nCount<1)
return 0;
for(int t=0; t<m_LoadedAnimatedTextures.Count(); t++)
{
if(strcmp(m_LoadedAnimatedTextures[t]->sName, szFileNameFormat) == 0)
if(m_LoadedAnimatedTextures[t]->nFramesCount == nCount)
{
m_LoadedAnimatedTextures[t]->nRefCounter++;
return t+1;
}
}
{
char szFileName[256];
sprintf(szFileName,szFileNameFormat,0);
iLog->LogToFile("Loading animated texture %s", szFileName);
}
// load new textures
AnimTexInfo * pInfo = new AnimTexInfo();
pInfo->pBindIds = new int[nCount];
memset(pInfo->pBindIds,0,nCount*sizeof(int));
pInfo->nFramesCount = 0;
strncpy(pInfo->sName, szFileNameFormat, sizeof(pInfo->sName));
if (strstr(szFileNameFormat,"%") != 0)
{
// Formatted filename.
for (int i=0; i<nCount; i++)
{
char filename[80]="";
sprintf(filename, szFileNameFormat, i);
pInfo->pBindIds[i] = LoadTexture( filename );
if (!pInfo->pBindIds[i])
break;
pInfo->nFramesCount++;
}
}
else
{
char szFileName[_MAX_PATH];
char szFileFormat[_MAX_PATH];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath( szFileNameFormat,drive,dir,fname,ext );
int numDigits = 0;
int namelen = strlen(fname);
int i = namelen-1;
// Find out number of digits in the end of the filename.
while (i >= 0 && isdigit(fname[i]))
{
numDigits++;
i--;
}
int firstFrame = 0;
if (numDigits > 0)
{
const char *sNum = fname + namelen - numDigits;
firstFrame = atoi(sNum);
fname[namelen-numDigits] = 0;
// Make format string.
sprintf( fname+strlen(fname),"%%.%dd",numDigits );
}
_makepath( szFileFormat,drive,dir,fname,ext );
for (int i=0; i<nCount; i++)
{
sprintf( szFileName,szFileFormat,firstFrame + i );
pInfo->pBindIds[i] = LoadTexture( szFileName );
if (!pInfo->pBindIds[i])
break;
pInfo->nFramesCount++;
}
}
iLog->LogToFilePlus(" (%d)", nCount);
pInfo->nRefCounter=1;
m_LoadedAnimatedTextures.Add(pInfo);
return (int)m_LoadedAnimatedTextures.Count();
}
///////////////////////////////////////////
char * CD3D9Renderer::GetStatusText(ERendStats type)
{
return "No status yet";
}
void sLogTexture (char *name, int Size);
void CD3D9Renderer::ProjectToScreen(float ptx, float pty, float ptz,float *sx, float *sy, float *sz )
{
D3DXVECTOR3 vOut, vIn;
vIn.x = ptx;
vIn.y = pty;
vIn.z = ptz;
D3DXMATRIX mIdent;
D3DXMatrixIdentity(&mIdent);
D3DXVec3Project(&vOut, &vIn, &m_Viewport, m_matProj->GetTop(), m_matView->GetTop(), &mIdent);
*sx = vOut.x * 100/m_width;
*sy = vOut.y * 100/m_height;
*sz = vOut.z;
}
void CD3D9Renderer::DrawBall(float x, float y, float z, float radius)
{
if (m_bDeviceLost)
return;
assert (m_pSphere);
EF_PushMatrix();
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
TranslateMatrix(x, y, z);
ScaleMatrix(radius, radius, radius);
m_pSphere->DrawSubset(0);
m_pLastVDeclaration = NULL;
EF_PopMatrix();
}
void CD3D9Renderer::DrawBall(const Vec3d & pos, float radius)
{
if (m_bDeviceLost)
return;
assert (m_pSphere);
EF_PushMatrix();
EnableTMU(true);
gRenDev->m_TexMan->m_Text_White->Set();
TranslateMatrix(pos.x, pos.y, pos.z);
ScaleMatrix(radius, radius, radius);
m_pSphere->DrawSubset(0);
m_pLastVDeclaration = NULL;
EF_PopMatrix();
}
#define A(row,col) a[(col<<2)+row]
#define B(row,col) b[(col<<2)+row]
#define P(row,col) product[(col<<2)+row]
static void matmul4( float *product, const float *a, const float *b )
{
int i;
for (i=0; i<4; i++)
{
float ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
}
}
#undef A
#undef B
#undef P
/*
* Transform a point (column vector) by a 4x4 matrix. I.e. out = m * in
* Input: m - the 4x4 matrix
* in - the 4x1 vector
* Output: out - the resulting 4x1 vector.
*/
static void transform_point(float out[4], const float m[16], const float in[4])
{
#define M(row,col) m[col*4+row]
out[0] = M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
out[1] = M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
out[2] = M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
out[3] = M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
#undef M
}
static int sUnProject(float winx, float winy, float winz, const float model[16], const float proj[16], const int viewport[4], float * objx, float * objy, float * objz)
{
/* matrice de transformation */
float m[16], A[16];
float in[4], out[4];
/* transformation coordonnees normalisees entre -1 et 1 */
in[0] = (winx - viewport[0]) * 2 / viewport[2] - 1.0f;
in[1] = (winy - viewport[1]) * 2 / viewport[3] - 1.0f;
in[2] = winz;//2.0f * winz - 1.0f;
in[3] = 1.0;
/* calcul transformation inverse */
matmul4(A, proj, model);
QQinvertMatrixf(m, A);
/* d'ou les coordonnees objets */
transform_point(out, m, in);
if (out[3] == 0.0)
return false;
*objx = out[0] / out[3];
*objy = out[1] / out[3];
*objz = out[2] / out[3];
return true;
}
int CD3D9Renderer::UnProject(float sx, float sy, float sz, float *px, float *py, float *pz, const float modelMatrix[16], const float projMatrix[16], const int viewport[4])
{
return sUnProject(sx, sy, sz, modelMatrix, projMatrix, viewport, px, py, pz);
}
int CD3D9Renderer::UnProjectFromScreen( float sx, float sy, float sz, float *px, float *py, float *pz)
{
float modelMatrix[16];
float projMatrix[16];
int viewport[4];
GetModelViewMatrix(modelMatrix);
GetProjectionMatrix(projMatrix);
GetViewport(&viewport[0], &viewport[1], &viewport[2], &viewport[3]);
return sUnProject(sx, sy, sz, modelMatrix, projMatrix, viewport, px, py, pz);
}
//////////////////////////////////////////////////////////////////////
void CD3D9Renderer::ClearDepthBuffer()
{
m_bWasCleared = true;
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0, 0, 0, 0), 1.0f, 0);
}
void CD3D9Renderer::ClearColorBuffer(const Vec3d vColor)
{
m_bWasCleared = true;
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DRGBA(vColor[0], vColor[1], vColor[2], 1.0f), 1.0f, 0);
}
void CD3D9Renderer::EnableAALines(bool bEnable)
{
assert(0);
}
void CD3D9Renderer::Set2DMode(bool enable, int ortox, int ortoy)
{
D3DXMATRIX *m;
if(enable)
{
m_matProj->Push();
m = m_matProj->GetTop();
D3DXMatrixOrthoOffCenterLH(m, 0.0, (float)ortox, (float)ortoy, 0.0, -1e30f, 1e30f);
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
EF_PushMatrix();
m = m_matView->GetTop();
m_matView->LoadIdentity();
m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
}
else
{
HRESULT hr = m_matProj->Pop();
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m_matProj->GetTop());
EF_PopMatrix();
}
EF_SetCameraInfo();
}
unsigned int CD3D9Renderer::MakeTexture(const char * _filename,int *_tex_type/*,unsigned int def_tid*/)
{
return LoadTexture(_filename,_tex_type);
}
void CD3D9Renderer::SetTexClampMode(bool clamp)
{
byte bRepeat = !clamp;
if (m_TexMan->m_LastTex)
{
STexPicD3D *ti = (STexPicD3D *)m_TexMan->m_LastTex;
ti->m_RefTex.bRepeats = bRepeat;
}
if (bRepeat != m_RP.m_TexStages[m_TexMan->m_CurStage].Repeat)
{
m_RP.m_TexStages[m_TexMan->m_CurStage].Repeat = bRepeat;
m_pd3dDevice->SetSamplerState(m_TexMan->m_CurStage, D3DSAMP_ADDRESSU, clamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP);
m_pd3dDevice->SetSamplerState(m_TexMan->m_CurStage, D3DSAMP_ADDRESSV, clamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP);
}
}
void CD3D9Renderer::TransformTextureMatrix(float x, float y, float angle, float scale)
{
D3DXMATRIX *m = &m_TexMatrix[m_TexMan->m_CurStage];
D3DXMATRIX ma;
D3DXMatrixTranslation(&ma, x, y, 0);
D3DXMatrixMultiply(m, &ma, m);
D3DXMatrixTranslation(&ma, 0.5, 0.5, 0);
D3DXMatrixMultiply(m, &ma, m);
D3DXMatrixRotationZ(&ma, angle);
D3DXMatrixMultiply(m, &ma, m);
D3DXMatrixScaling(&ma, scale, scale, scale);
D3DXMatrixMultiply(m, &ma, m);
D3DXMatrixTranslation(&ma, -0.5, -0.5, 0);
D3DXMatrixMultiply(m, &ma, m);
m->_31 = m->_41;
m->_32 = m->_42;
m_pd3dDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+m_TexMan->m_CurStage), m);
m_pd3dDevice->SetTextureStageState(m_TexMan->m_CurStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
}
void CD3D9Renderer::ResetTextureMatrix()
{
D3DXMATRIX *mt = &m_TexMatrix[m_TexMan->m_CurStage];
D3DXMatrixIdentity(mt);
m_pd3dDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+m_TexMan->m_CurStage), mt);
m_pd3dDevice->SetTextureStageState(m_TexMan->m_CurStage, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
}
void CD3D9Renderer::RemoveTexture(ITexPic * pTexPic)
{
STexPic * pSTexPic = (STexPic *)pTexPic;
pSTexPic->Release(false);
}
void CD3D9Renderer::RemoveTexture(unsigned int TextureId)
{
CD3D9TexMan *tm = (CD3D9TexMan *)m_TexMan;
TTextureMapItor it = tm->m_RefTexs.find(TextureId);
STexPic *t;
if (it == tm->m_RefTexs.end())
return;
t = it->second;
if (t)
t->Release(false);
else
m_TexMan->RemoveFromHash(TextureId, NULL);
// free shadow maps slot
for(int i=0; i<MAX_DYNAMIC_SHADOW_MAPS_COUNT; i++)
{
if(m_ShadowTexIDBuffer[i].nTexId0 == TextureId)
{
iLog->Log("Warning: CD3D9Renderer::RemoveTexture: shadowmap tex slot freed");
m_ShadowTexIDBuffer[i].nTexId0 = 0;
}
}
}
unsigned int CD3D9Renderer::LoadTexture(const char * _filename,int *tex_type,unsigned int def_tid,bool compresstodisk,bool bWarn)
{
if (def_tid == 0)
def_tid = -1;
ITexPic * pPic = EF_LoadTexture((char*)_filename,0,0,eTT_Base, -1, -1, def_tid);
return pPic->IsTextureLoaded() ? pPic->GetTextureID() : 0;
}
void CD3D9Renderer::UpdateTextureInVideoMemory(uint tnum, unsigned char *newdata,int posx,int posy,int w,int h,ETEX_Format eTFSrc)
{
if (m_bDeviceLost)
return;
SetTexture(tnum);
D3DFORMAT srcformat = D3DFMT_UNKNOWN;
if (eTFSrc == eTF_DXT1)
srcformat = D3DFMT_DXT1;
else
if (eTFSrc == eTF_0888)
srcformat = D3DFMT_X8R8G8B8;
else
if (eTFSrc==eTF_8888)
srcformat = D3DFMT_A8R8G8B8;
else
if (eTFSrc==eTF_4444)
srcformat = D3DFMT_A4R4G4B4;
if(srcformat==D3DFMT_UNKNOWN)
assert(0);
if (tnum > TX_FIRSTBIND && srcformat != D3DFMT_UNKNOWN)
{
STexPicD3D *tp = (STexPicD3D *)(m_TexMan->m_Textures[tnum-TX_FIRSTBIND]);
if (!tp)
return;
IDirect3DTexture9 * tex = (IDirect3DTexture9 *) tp->m_RefTex.m_VidTex;
IDirect3DSurface9 * pSurf;
tex->GetSurfaceLevel(0, &pSurf);
if(pSurf)
{
RECT rc={posx,posy,posx+w,posy+h};
D3DSURFACE_DESC desc;
pSurf->GetDesc(&desc);
if((eTFSrc==eTF_8888 || eTFSrc==eTF_0888) && (desc.Format==D3DFMT_A8R8G8B8 || desc.Format==D3DFMT_X8R8G8B8))
{
D3DLOCKED_RECT lr;
if(pSurf->LockRect(&lr, &rc, 0)==D3D_OK)
{
byte * p = (byte*) lr.pBits;
for(int y=0; y<h; y++)
{
cryMemcpy(&p[y*lr.Pitch], &newdata[y*w*4], w*4);
}
pSurf->UnlockRect();
}
}
else
{
int size = CD3D9TexMan::TexSize(w, h, srcformat);
int nPitch;
if (eTFSrc != eTF_DXT1 && eTFSrc != eTF_DXT3 && eTFSrc != eTF_DXT5)
nPitch = size / h;
else
{
int blockSize = (eTFSrc == eTF_DXT1) ? 8 : 16;
nPitch = (w+3)/4 * blockSize;
}
if((eTFSrc==eTF_8888 || eTFSrc==eTF_0888) && (desc.Format==D3DFMT_R5G6B5))
{
D3DLOCKED_RECT lr;
if(pSurf->LockRect(&lr, &rc, 0)==D3D_OK)
{
byte *pBits = (byte *)lr.pBits;
for (int i=0; i<h; i++)
{
uint *src = (uint *)&newdata[i*w*4];
ushort *dst = (ushort *)&pBits[i*lr.Pitch];
for (int j=0; j<w; j++)
{
uint argb = *src++;
*dst++ = ((argb >> 8) & 0xF800) |
((argb >> 5) & 0x07E0) |
((argb >> 3) & 0x001F);
}
}
pSurf->UnlockRect();
}
}
else
{
HRESULT hr = D3DXLoadSurfaceFromMemory(pSurf, NULL, &rc, newdata, srcformat, nPitch, NULL, &rc, D3DX_FILTER_NONE, 0);
}
SAFE_RELEASE(pSurf);
}
}
}
}
unsigned int CD3D9Renderer::DownLoadToVideoMemory(unsigned char *data,int w, int h, ETEX_Format eTFSrc, ETEX_Format eTFDst, int nummipmap, bool repeat, int filter, int Id, char *szCacheName, int flags)
{
char name[128];
if (!szCacheName)
sprintf(name, "$AutoDownload_%d", m_TexGenID++);
else
{
// WORKAROUND: NVidia driver bug during playing of video file
// Solution: Never remove video texture
/*if (!strcmp(szCacheName, "$VideoPanel"))
{
if (m_TexMan->IsTextureLoaded(szCacheName))
{
STexPic *tp = m_TexMan->GetByName(szCacheName);
return tp->GetTextureID();
}
}*/
strcpy(name, szCacheName);
}
int flags2 = FT2_NODXT;
if (!nummipmap)
{
if (filter != FILTER_BILINEAR && filter != FILTER_TRILINEAR)
flags |= FT_NOMIPS;
}
int DXTSize = 0;
int blockSize = 0;
if (eTFDst == eTF_DXT1)
{
flags |= FT_DXT1;
blockSize = 8;
}
else
if (eTFDst == eTF_DXT3)
{
flags |= FT_DXT3;
blockSize = 16;
}
else
if (eTFDst == eTF_DXT5)
{
flags |= FT_DXT5;
blockSize = 16;
}
if (blockSize)
{
if (!nummipmap)
nummipmap = 1;
int wdt = w;
int hgt = h;
for (int i=0; i<nummipmap; i++)
{
DXTSize += ((wdt+3)/4)*((hgt+3)/4)*blockSize;
wdt >>= 1;
hgt >>= 1;
if (!wdt)
wdt = 1;
if (!hgt)
hgt = 1;
}
}
if (eTFSrc == eTF_RGBA)
{
for (int i=0; i<h; i++)
{
byte *dst = &data[i*w*4];
for (int j=0; j<w; j++)
{
Exchange(dst[j*4], dst[j*4+2]);
}
}
}
if (!repeat)
flags |= FT_CLAMP;
if (eTFDst == eTF_RGBA)
flags |= FT_HASALPHA;
if (!szCacheName)
flags |= FT_NOSTREAM;
else
flags2 |= FT2_DISCARDINCACHE;
flags2 |= FT2_NOANISO;
STexPic *tp;
int tnum = Id;
unsigned char * pData = 0;
if(eTFSrc == eTFDst)
pData = data;
else
pData = new unsigned char[w * h * 4];
if (tnum > TX_FIRSTBIND)
{
tp = (STexPicD3D *)(m_TexMan->m_Textures[tnum-TX_FIRSTBIND]);
tp = m_TexMan->CreateTexture(name, w, h, 1, flags, flags2, pData , eTT_Base, -1.0f, -1.0f, DXTSize, tp, 0, eTFDst);
}
else
{
tp = m_TexMan->CreateTexture(name, w, h, 1, flags, flags2, pData , eTT_Base, -1.0f, -1.0f, DXTSize, NULL, 0, eTFDst);
}
if(data && eTFSrc != eTFDst && !m_bDeviceLost)
UpdateTextureInVideoMemory( tp->m_Bind, data, 0 , 0, w, h, eTFSrc);
if(pData && eTFSrc != eTFDst)
delete[] pData;
//tp->SaveJPG("bug.jpg", false);
return (tp->m_Bind);
}
void CD3D9Renderer::SetTexture(int tnum, ETexType Type)
{
m_TexMan->SetTexture(tnum, Type);
}
bool CD3D9Renderer::EF_SetLightHole(Vec3d vPos, Vec3d vNormal, int idTex, float fScale, bool bAdditive)
{
return false;
}
char* CD3D9Renderer::GetVertexProfile(bool bSupportedProfile)
{
CGprofile pr = CG_PROFILE_VS_1_1;
if (bSupportedProfile)
{
#ifndef WIN64
pr = cgD3D9GetLatestVertexProfile();
#else
if (GetFeatures() & RFT_HW_PS20)
pr = CG_PROFILE_VS_2_0;
#endif
}
switch(pr)
{
case CG_PROFILE_VS_1_1:
return "PROFILE_VS_1_1";
case CG_PROFILE_VS_2_0:
case CG_PROFILE_VS_2_X:
return "PROFILE_VS_2_0";
default:
return "Unknown";
}
}
char* CD3D9Renderer::GetPixelProfile(bool bSupportedProfile)
{
CGprofile pr = CG_PROFILE_PS_1_1;
if (bSupportedProfile)
{
#ifndef WIN64
pr = cgD3D9GetLatestPixelProfile();
if (pr == CG_PROFILE_PS_1_2 || pr == CG_PROFILE_PS_1_3)
pr = CG_PROFILE_PS_1_1;
#else
if (GetFeatures() & RFT_HW_PS20)
{
if ((GetFeatures() & RFT_HW_MASK) == RFT_HW_GFFX)
pr = CG_PROFILE_PS_2_X;
else
pr = CG_PROFILE_PS_2_0;
}
#endif
}
switch(pr)
{
case CG_PROFILE_PS_1_1:
case CG_PROFILE_PS_1_2:
case CG_PROFILE_PS_1_3:
return "PROFILE_PS_1_1";
case CG_PROFILE_PS_2_0:
case CG_PROFILE_PS_2_X:
return "PROFILE_PS_2_0";
default:
return "Unknown";
}
}
void CD3D9Renderer::EF_PolygonOffset(bool bEnable, float fFactor, float fUnits)
{
if (bEnable)
{
float fOffs = -(float)fFactor;
m_pd3dDevice->SetRenderState( D3DRS_DEPTHBIAS, *(DWORD*)&fOffs );
}
else
{
m_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
}
}
void CD3D9Renderer::GetMemoryUsage(ICrySizer* Sizer)
{
int i, nSize;
assert (Sizer);
//SIZER_COMPONENT_NAME(Sizer, "GLRenderer");
{
SIZER_COMPONENT_NAME(Sizer, "Renderer static");
for (i=0; i<NUMRI_LISTS; i++)
{
Sizer->AddObject(&SRendItem::m_RendItems[i], SRendItem::m_RendItems[i].GetMemoryUsage());
}
}
{
SIZER_COMPONENT_NAME(Sizer, "Renderer dynamic");
Sizer->Add(*this);
Sizer->AddObject(&CCObject::m_Waves, CCObject::m_Waves.GetMemoryUsage());
Sizer->AddObject(m_RP.m_VisObjects, MAX_REND_OBJECTS*sizeof(CCObject *));
Sizer->AddObject(&m_RP.m_TempObjects, m_RP.m_TempObjects.GetMemoryUsage());
Sizer->AddObject(&m_RP.m_Objects, m_RP.m_Objects.GetMemoryUsage());
Sizer->AddObject(&m_RP.m_ObjectsPool, m_RP.m_nNumObjectsInPool * sizeof(CCObject));
Sizer->AddObject(&m_RP.m_DLights, m_RP.m_DLights[1].GetMemoryUsage());
Sizer->AddObject(&m_RP.m_Splashes, m_RP.m_Splashes.GetMemoryUsage());
nSize = 0;
for (i=0; i<4; i++)
{
nSize += CREClientPoly::mPolysStorage[i].GetMemoryUsage();
}
nSize += CREClientPoly2D::mPolysStorage.GetMemoryUsage();
Sizer->AddObject(&CREClientPoly2D::mPolysStorage, nSize);
Sizer->AddObject(&m_RP.m_Sprites, m_RP.m_Sprites.GetMemoryUsage());
nSize = 0;
for (i=0; i<2; i++)
{
nSize += m_RP.m_TempMeshes[i].GetMemoryUsage();
}
Sizer->AddObject(&m_RP.m_TempMeshes, nSize);
Sizer->AddObject(&gCurLightStyles, gCurLightStyles.GetMemoryUsage());
Sizer->AddObject(&CName::mDuplicate, CName::Size());
}
{
SIZER_COMPONENT_NAME(Sizer, "Shaders");
nSize = SShader::m_Shaders_known.GetMemoryUsage();
Sizer->AddObject(&SShader::m_Shaders_known, nSize);
for (i=0; i<SShader::m_Shaders_known.Num(); i++)
{
SShader *pSH = SShader::m_Shaders_known[i];
if (!pSH)
continue;
nSize = pSH->Size(0);
Sizer->AddObject(pSH, nSize);
}
{
SIZER_COMPONENT_NAME(Sizer, "Shader manager");
Sizer->AddObject(&m_cEF, m_cEF.Size());
}
{
SIZER_COMPONENT_NAME(Sizer, "Shader resources");
nSize = SShader::m_ShaderResources_known.GetMemoryUsage();
Sizer->AddObject(&SShader::m_ShaderResources_known, nSize);
for (i=0; i<SShader::m_ShaderResources_known.Num(); i++)
{
SRenderShaderResources *pSHR = SShader::m_ShaderResources_known[i];
if (!pSHR)
continue;
nSize = pSHR->Size();
Sizer->AddObject(pSHR, nSize);
}
}
{
SIZER_COMPONENT_NAME(Sizer, "Shader shared components");
for (i=0; i<SParamComp::m_ParamComps.Num(); i++)
{
nSize = SParamComp::m_ParamComps[i]->Size();
Sizer->AddObject(SParamComp::m_ParamComps[i], nSize);
}
for (i=0; i<CVProgram::m_VPrograms.Num(); i++)
{
if (CVProgram::m_VPrograms[i])
{
nSize = CVProgram::m_VPrograms[i]->Size();
Sizer->AddObject(CVProgram::m_VPrograms[i], nSize);
}
}
// Shared vshaders scripts
nSize = CCGVProgram_D3D::m_CGScripts.GetMemoryUsage();
for (i=0; i<CCGVProgram_D3D::m_CGScripts.Num(); i++)
{
if (CCGVProgram_D3D::m_CGScripts[i])
nSize += CCGVProgram_D3D::m_CGScripts[i]->Size(true);
}
Sizer->AddObject(&CCGVProgram_D3D::m_CGScripts, nSize);
for (i=0; i<CPShader::m_PShaders.Num(); i++)
{
if (CPShader::m_PShaders[i])
{
nSize = CPShader::m_PShaders[i]->Size();
Sizer->AddObject(CPShader::m_PShaders[i], nSize);
}
}
for (i=0; i<CLightStyle::m_LStyles.Num(); i++)
{
nSize = CLightStyle::m_LStyles[i]->Size();
Sizer->AddObject(CLightStyle::m_LStyles[i], nSize);
}
for (i=0; i<SLightMaterial::known_materials.Num(); i++)
{
if (SLightMaterial::known_materials[i])
{
nSize = SLightMaterial::known_materials[i]->Size();
Sizer->AddObject(SLightMaterial::known_materials[i], nSize);
}
}
}
}
{
SIZER_COMPONENT_NAME(Sizer, "Mesh");
CLeafBuffer *pLB = CLeafBuffer::m_RootGlobal.m_NextGlobal;
int nNums = 0;
int nSizeTotal = 0;
while (pLB != &CLeafBuffer::m_RootGlobal)
{
nSize = pLB->Size(0);
Sizer->AddObject(pLB, nSize);
pLB = pLB->m_NextGlobal;
nSizeTotal += nSize;
nNums++;
}
{
SIZER_COMPONENT_NAME(Sizer, "API Mesh size");
nNums = 0;
nSize = 0;
CLeafBuffer *pLB = CLeafBuffer::m_Root.m_Next;
while (pLB != &CLeafBuffer::m_Root)
{
nSize += pLB->Size(1);
pLB = pLB->m_Next;
nNums++;
}
Sizer->AddObject(&CLeafBuffer::m_Root.m_Next, nSize);
}
{
SIZER_COMPONENT_NAME(Sizer, "API Mesh indices size");
nNums = 0;
nSize = 0;
CLeafBuffer *pLB = CLeafBuffer::m_Root.m_Next;
while (pLB != &CLeafBuffer::m_Root)
{
nSize += pLB->Size(2);
pLB = pLB->m_Next;
nNums++;
}
Sizer->AddObject(&CLeafBuffer::m_Root.m_Prev, nSize);
}
}
{
SIZER_COMPONENT_NAME(Sizer, "Render elements");
CRendElement *pRE = CRendElement::m_RootGlobal.m_NextGlobal;
while (pRE != &CRendElement::m_RootGlobal)
{
nSize = pRE->Size();
Sizer->AddObject(pRE, nSize);
pRE = pRE->m_NextGlobal;
}
}
{
SIZER_COMPONENT_NAME(Sizer, "Texture Objects");
for (i=0; i<gRenDev->m_TexMan->m_Textures.Num(); i++)
{
STexPic *tp = gRenDev->m_TexMan->m_Textures[i];
if (!tp)
continue;
nSize = tp->Size(0);
Sizer->AddObject(tp, nSize);
}
Sizer->AddObject(&gRenDev->m_TexMan->m_Textures[0], gRenDev->m_TexMan->m_Textures.GetMemoryUsage());
Sizer->AddObject(&gRenDev->m_TexMan->m_FreeSlots[0], gRenDev->m_TexMan->m_FreeSlots.GetMemoryUsage());
Sizer->AddObject(&gRenDev->m_TexMan->m_TexData[0], 256*256*4);
Sizer->AddObject(&gRenDev->m_TexMan->m_EnvCMaps[0], sizeof(SEnvTexture)*MAX_ENVCUBEMAPS);
Sizer->AddObject(&gRenDev->m_TexMan->m_EnvTexts[0], sizeof(SEnvTexture)*MAX_ENVTEXTURES);
Sizer->AddObject(&gRenDev->m_TexMan->m_CustomCMaps[0], sizeof(SEnvTexture)*16);
Sizer->AddObject(&gRenDev->m_TexMan->m_CustomTextures[0], sizeof(SEnvTexture)*16);
Sizer->AddObject(&gRenDev->m_TexMan->m_Templates[0], sizeof(STexPic)*EFTT_MAX);
}
{
SIZER_COMPONENT_NAME(Sizer, "API Texture memory");
nSize = 0;
for (i=0; i<gRenDev->m_TexMan->m_Textures.Num(); i++)
{
STexPic *tp = gRenDev->m_TexMan->m_Textures[i];
if (!tp || !tp->m_bBusy)
continue;
nSize += tp->m_Size;
}
Sizer->AddObject(&gRenDev->m_TexMan->m_Textures[0]->m_Size, nSize);
}
}
//====================================================================
ILog *iLog;
IConsole *iConsole;
ITimer *iTimer;
ISystem *iSystem;
int *pTest_int;
IPhysicalWorld *pIPhysicalWorld;
ISystem *GetISystem()
{
return iSystem;
}
extern "C" DLL_EXPORT IRenderer* PackageRenderConstructor(int argc, char* argv[], SCryRenderInterface *sp);
DLL_EXPORT IRenderer* PackageRenderConstructor(int argc, char* argv[], SCryRenderInterface *sp)
{
gbRgb = false;
iConsole = sp->ipConsole;
iLog = sp->ipLog;
iTimer = sp->ipTimer;
iSystem = sp->ipSystem;
pTest_int = sp->ipTest_int;
pIPhysicalWorld = sp->pIPhysicalWorld;
#ifdef DEBUGALLOC
#undef new
#endif
gRenDev = (CRenderer *) (new CD3D9Renderer());
#ifdef DEBUGALLOC
#define new DEBUG_CLIENTBLOCK
#endif
srand( GetTickCount() );
g_SecondsPerCycle = iSystem->GetSecondsPerCycle();
g_CpuFlags = iSystem->GetCPUFlags();
return gRenDev;
}
void *gGet_D3DDevice()
{
return (void *)gcpRendD3D->m_pd3dDevice;
}
void *gGet_glReadPixels()
{
return NULL;
}
//=========================================================================================
//=========================================================================================