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

5611 lines
163 KiB
C++

/*=============================================================================
DriverD3D8.cpp : Direct3D Render interface implementation.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Khonich Andrey
=============================================================================*/
#include "stdafx.h"
#include "DriverD3D8.h"
#include "D3DCGVProgram.h"
#include "D3DCGPShader.h"
#ifndef _XBOX
#include <windows.h>
#endif
#include "IStatObj.h"
CD3D8Renderer *gcpRendD3D;
HRESULT h;
int CD3D8Renderer::CV_d3d8_texture_filter_anisotropic;
int CD3D8Renderer::CV_d3d8_nodeviceid;
int CD3D8Renderer::CV_d3d8_palettedtextures;
int CD3D8Renderer::CV_d3d8_compressedtextures;
int CD3D8Renderer::CV_d3d8_usebumpmap;
int CD3D8Renderer::CV_d3d8_bumptype;
int CD3D8Renderer::CV_d3d8_forcesoftwarevp;
int CD3D8Renderer::CV_d3d8_texturebits;
int CD3D8Renderer::CV_d3d8_texmipfilter; // 0-point; 1-box; 2-linear; 3-triangle;
int CD3D8Renderer::CV_d3d8_mipprocedures;
int CD3D8Renderer::CV_d3d8_squaretextures;
ICVar *CD3D8Renderer::CV_d3d8_device;
int CD3D8Renderer::CV_d3d8_allowsoftware;
float CD3D8Renderer::CV_d3d8_gamma;
int CD3D8Renderer::CV_d3d8_rb_verts;
int CD3D8Renderer::CV_d3d8_rb_tris;
int CD3D8Renderer::CV_d3d8_decaloffset;
float CD3D8Renderer::CV_d3d8_normalmapscale;
ICVar *CD3D8Renderer::CV_d3d8_texturefilter;
// Direct 3D console variables
CD3D8Renderer::CD3D8Renderer()
{
m_bInitialized = false;
gcpRendD3D = this;
gRenDev = this;
m_nFrameID = 0;
m_TexMan = new CD3D8TexMan;
m_TexMan->m_bRGBA = false;
m_LogFile = NULL;
RegisterVariables();
m_dwNumAdapters = 0;
m_dwAdapter = 0L;
m_pD3D = NULL;
m_pd3dDevice = NULL;
m_hWnd = NULL;
m_bActive = FALSE;
m_bReady = FALSE;
m_dwCreateFlags = 0L;
m_pQuadVB = NULL;
m_pLineVB = 0;
m_strDeviceStats[0] = 0;
m_MinDepthBits = 16;
m_MinStencilBits = 0;
m_eCull = (ECull)-1;
m_EnableLights = 0;
m_Features = RFT_DIRECTACCESSTOVIDEOMEMORY | RFT_SUPPORTZBIAS;
iConsole->Register("d3d8_Texture_Filter_Anisotropic", &CV_d3d8_texture_filter_anisotropic, 0);
iConsole->Register("d3d8_NodeviceId", &CV_d3d8_nodeviceid, 0);
iConsole->Register("d3d8_PalettedTextures", &CV_d3d8_palettedtextures, 1);
iConsole->Register("d3d8_CompressedTextures", &CV_d3d8_compressedtextures, 1);
iConsole->Register("d3d8_UseBumpmap", &CV_d3d8_usebumpmap, 1);
iConsole->Register("d3d8_BumpType", &CV_d3d8_bumptype, 1);
iConsole->Register("d3d8_ForceSoftwareVP", &CV_d3d8_forcesoftwarevp, 0);
iConsole->Register("d3d8_TextureBits", &CV_d3d8_texturebits, 0);
iConsole->Register("d3d8_MipProcedures", &CV_d3d8_mipprocedures, 0);
iConsole->Register("d3d8_TexMipFilter", &CV_d3d8_texmipfilter, 2); // 0-point; 1-box; 2-linear; 3-triangle;
CV_d3d8_texturefilter = iConsole->CreateVariable("d3d8_TextureFilter", "TRILINEAR", NULL);
iConsole->Register("d3d8_SquareTextures", &CV_d3d8_squaretextures, 0);
CV_d3d8_device = iConsole->CreateVariable("d3d8_Device", "Auto", NULL);
iConsole->Register("d3d8_AllowSoftware", &CV_d3d8_allowsoftware, 1L);
iConsole->Register("d3d8_Gamma", &CV_d3d8_gamma, 1.2f);
iConsole->Register("d3d8_rb_Verts", &CV_d3d8_rb_verts, 500);
iConsole->Register("d3d8_rb_Tris", &CV_d3d8_rb_tris, 1000);
iConsole->Register("d3d8_DecalOffset", &CV_d3d8_decaloffset, 15);
iConsole->Register("d3d8_NormalMapScale", &CV_d3d8_normalmapscale, 0.15f);
}
CD3D8Renderer::~CD3D8Renderer()
{
FreeResources(FRR_ALL);
ShutDown();
}
void CD3D8Renderer::ShareResources( IRenderer *renderer )
{
}
void CD3D8Renderer::MakeCurrent()
{
}
bool CD3D8Renderer::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;
CPShader::m_CurPS = NULL;
return true;
}
bool CD3D8Renderer::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;
m_CurrContext = pContext;
m_RContexts.AddElem(pContext);
return true;
}
bool CD3D8Renderer::DeleteContext(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])
{
for (int 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: CD3D8Renderer::DeleteDeviceObjects()
// Desc: Called when the app is exiting, or the device is being changed,
// this function deletes any device dependent objects.
//-----------------------------------------------------------------------------
HRESULT CD3D8Renderer::DeleteDeviceObjects()
{
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: FinalCleanup()
// Desc: Called before the app exits, this function gives the app the chance
// to cleanup after itself.
//-----------------------------------------------------------------------------
HRESULT CD3D8Renderer::FinalCleanup()
{
return S_OK;
}
void CD3D8Renderer::DestroyWindow(void)
{
guard(CD3D8Renderer::DestroyWindow);
#ifndef _XBOX
if (m_hWnd)
{
::DestroyWindow(m_hWnd);
m_hWnd = NULL;
}
#endif
unguard
}
void CD3D8Renderer::RestoreGamma(void)
{
if (!m_pd3dDevice)
return;
if (m_bGammaCalibrate)
m_pd3dDevice->SetGammaRamp(D3DSGR_CALIBRATE, &m_SystemGammaRamp);
else
m_pd3dDevice->SetGammaRamp(D3DSGR_NO_CALIBRATION, &m_SystemGammaRamp);
}
void CD3D8Renderer::SetGamma(float fGamma, float fBrightness, float fContrast)
{
fGamma = Clamp(fGamma, 0.5f, 3.0f);
if (m_fLastGamma == fGamma && m_fLastBrightness == fBrightness && m_fLastContrast == fContrast)
return;
float Gamma = CV_d3d8_gamma;
D3DGAMMARAMP Ramp;
int m;
for( int x=0; x<256; x++ )
{
if ( Gamma == 1.0f )
m = x;
else
{
float f = (float)x;
m = (int)(pow(f/255.0, 1.0/Gamma) * 255.0 + 0.5);
}
if ( m < 0 )
m = 0;
if ( m > 255 )
m = 255;
m <<= 8;
Ramp.red[x] = Ramp.green[x] = Ramp.blue[x] = m;
}
if( m_Features & RFT_HWGAMMA )
{
if (m_bGammaCalibrate)
m_pd3dDevice->SetGammaRamp(D3DSGR_CALIBRATE, &Ramp);
else
m_pd3dDevice->SetGammaRamp(D3DSGR_NO_CALIBRATION, &Ramp);
}
m_fLastGamma = fGamma;
m_fLastBrightness = fBrightness;
m_fLastContrast = fContrast;
Gamma = CV_d3d8_gamma;
for (int i=0; i<256; i++)
{
m_GammmaTable[i] = (byte)floor( pow(i / 255.f, 1.0f / Gamma) * 255.f + 0.5f);
}
}
//-----------------------------------------------------------------------------
// Name: InvalidateDeviceObjects()
// Desc: Called when the device-dependent objects are about to be lost.
//-----------------------------------------------------------------------------
HRESULT CD3D8Renderer::InvalidateDeviceObjects()
{
return S_OK;
}
void CD3D8Renderer::UnSetRes()
{
m_Features = RFT_DIRECTACCESSTOVIDEOMEMORY | RFT_SUPPORTZBIAS;
m_bActive = FALSE;
m_bReady = FALSE;
SAFE_RELEASE(m_pQuadVB);
SAFE_RELEASE(m_pLineVB);
if( m_pd3dDevice )
{
InvalidateDeviceObjects();
DeleteDeviceObjects();
m_pd3dDevice->Release();
m_pD3D->Release();
m_pd3dDevice = NULL;
m_pD3D = NULL;
}
FinalCleanup();
}
void CD3D8Renderer::ShutDown(bool bReInit)
{
guardnw(CD3D8Renderer::ShutDown);
UnSetRes();
FreeResources(FRR_ALL);
EF_PipelineShutdown();
CName::mfExitSubsystem();
#ifndef _XBOX
if (m_CGContext)
{
cgDestroyContext(m_CGContext);
m_CGContext = NULL;
}
#endif
unguardnw;
}
void CD3D8Renderer::RefreshResources(int nFlags)
{
}
void CD3D8Renderer::RegisterVariables()
{
}
void CD3D8Renderer::UnRegisterVariables()
{
}
int CD3D8Renderer::EnumDisplayFormats(TArray<SDispFormat>& Formats, bool bReset)
{
Formats.Free();
return 0;
}
bool CD3D8Renderer::SetWindow(int width, int height, bool fullscreen, WIN_HWND hWnd)
{
guard(CD3D8Renderer::mfSetWindow);
#ifndef _XBOX
RECT rc;
DWORD style, exstyle;
int x, y, wdt, hgt;
if (width < 640)
width = 640;
if (height < 480)
height = 480;
m_dwWindowStyle = WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
if (fullscreen)
{
#ifdef _DEBUG
exstyle = 0;
#else
exstyle = WS_EX_TOPMOST;
#endif
style = WS_POPUP | WS_VISIBLE;
}
else
{
exstyle = WS_EX_APPWINDOW;
style = m_dwWindowStyle;
}
rc.left = 0;
rc.right = width;
rc.top = 0;
rc.bottom = height;
AdjustWindowRect(&rc, style, false);
wdt = rc.right - rc.left;
hgt = rc.bottom - rc.top;
x = y = 0;
if (!hWnd)
{
m_hWnd = CreateWindowEx(exstyle,
"CryENGINE",
m_WinTitle,
style,
x,
y,
wdt,
hgt,
NULL,
NULL,
m_hInst,
NULL);
}
else
m_hWnd = (HWND)hWnd;
m_width = width;
m_height = height;
if (!m_hWnd)
iConsole->Exit("Couldn't create window\n");
if (fullscreen)
{
// Hide the cursor
SetCursor(NULL);
ShowCursor(FALSE);
}
else
if (!m_FullScreen)
SetWindowPos(m_hWnd, HWND_NOTOPMOST, (GetSystemMetrics(SM_CXFULLSCREEN)-width)/2, (GetSystemMetrics(SM_CYFULLSCREEN)-height)/2, GetSystemMetrics(SM_CXDLGFRAME)*2 + width, GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXDLGFRAME)*2 + height, SWP_SHOWWINDOW);
if (!hWnd)
{
ShowWindow(m_hWnd, SW_SHOW);
UpdateWindow(m_hWnd);
SetForegroundWindow(m_hWnd);
SetFocus(m_hWnd);
}
#endif
unguard
return true;
}
#ifndef PS2
WIN_HWND CD3D8Renderer::Init(int x,int y,int width,int height,unsigned int cbpp, int zbpp, int sbits, bool fullscreen,WIN_HINSTANCE hinst, WIN_HWND Glhwnd, WIN_HDC Glhdc, WIN_HGLRC hGLrc, bool bReInit)
{
guard(CD3D8Renderer::Init);
if (m_IsDedicated)
{
m_MaxTextureSize = 256;
return 0;
}
bool b = false;
#ifdef _XBOX
fullscreen = true;
#endif
iLog->Log ( "Direct3D8 driver is opening...\n");
iLog->Log ( "\nCrytek Direct3D8 driver version %4.2f (%s <%s>).\n", VERSION_D3D, __DATE__, __TIME__);
//strcpy(m_WinTitle, "- Far Cry -");
sprintf(m_WinTitle,"- Far Cry - %s (%s)",__DATE__, __TIME__);
m_hInst = (HINSTANCE)hinst;
// Save the new dimensions
CRenderer::m_width = width;
CRenderer::m_height = height;
CRenderer::m_cbpp = cbpp;
CRenderer::m_zbpp = zbpp;
CRenderer::m_sbpp = sbits;
m_bFullScreen = fullscreen;
while (true)
{
if (!SetWindow(width, height, fullscreen, Glhwnd))
{
ShutDown();
return 0;
}
if (SetRes())
break;
ShutDown();
if (b)
return 0;
m_bFullScreen ? m_bFullScreen = 0 : m_bFullScreen = 1;
b = 1;
}
D3DADAPTER_IDENTIFIER8 *ai = &m_Adapters[m_dwAdapter].d3dAdapterIdentifier;
SD3DDeviceInfo *di = &m_Adapters[m_dwAdapter].devices[m_Adapters[m_dwAdapter].dwCurrentDevice];
iLog->Log("\n ****** D3D8 Render Stats ******\n");
iLog->Log(" Driver description: %s\n", ai->Description);
iLog->Log(" Full stats: %s\n", m_strDeviceStats);
iLog->Log(" Hardware acceleration: %s\n", (di->DeviceType == D3DDEVTYPE_HAL) ? "Yes" : "No");
iLog->Log(" Full screen only: %s\n", (di->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED) ? "No" : "Yes");
iLog->Log(" Detail textures: %s\n", (GetFeatures() & RFT_DETAILTEXTURE) ? "Yes" : "No");
iLog->Log(" Z Buffer Locking: %s\n", (GetFeatures() & RFT_ZLOCKABLE) ? "Yes" : "No");
iLog->Log(" Use multitexture mode: %s (%d texture(s))\n", (GetFeatures() & RFT_MULTITEXTURE) ? "Yes" : "No", di->d3dCaps.MaxSimultaneousTextures);
iLog->Log(" Use bumpmapping : %s\n", (GetFeatures() & RFT_BUMP) ? ((GetFeatures() & RFT_BUMP_DOT3) ? "Yes (DOT3)" : "Yes (EMBM)") : "No");
iLog->Log(" Use paletted textures : %s\n", (GetFeatures() & RFT_PALTEXTURE) ? "Yes" : "No");
iLog->Log(" Current Resolution: %dx%dx%d %s\n", CRenderer::m_width, CRenderer::m_height, CRenderer::m_cbpp, m_bFullScreen ? "Full Screen" : "Windowed");
iLog->Log(" Maximum Resolution: %dx%d\n", m_Adapters[m_dwAdapter].mMaxWidth, m_Adapters[m_dwAdapter].mMaxHeight);
iLog->Log(" Maximum Texture size: %dx%d (Max Aspect: %d)\n", di->d3dCaps.MaxTextureWidth, di->d3dCaps.MaxTextureHeight, di->d3dCaps.MaxTextureAspectRatio);
iLog->Log(" Texture filtering type: %s\n", CV_d3d8_texturefilter->GetString());
iLog->Log(" Use %d bits textures\n", m_TextureBits);
iLog->Log(" Gamma control: %s\n", (GetFeatures() & RFT_HWGAMMA) ? "Hardware" : "Software");
#ifdef _XBOX
iLog->Log(" Use Hardware Shaders for XBox\n");
#else
if (GetFeatures() & RFT_HW_GF2)
iLog->Log(" Use Hardware Shaders for NV1x GPU\n");
else
if (GetFeatures() & RFT_HW_GF3)
iLog->Log(" Use Hardware Shaders for NV2x GPU\n");
else
if (GetFeatures() & RFT_HW_RADEON8500)
iLog->Log(" Use Hardware Shaders for ATI R300 GPU\n");
else
iLog->Log(" Hardware Shaders not supported\n");
#endif
iLog->Log(" *****************************************\n\n");
iLog->Log("Init Shaders\n");
m_numtmus = di->d3dCaps.MaxSimultaneousTextures;
gcEf.mfInit();
EF_Init();
m_bInitialized = true;
// Cry_memcheck();
// Success, return the window handle
#ifndef _XBOX
return (m_hWnd);
#else
return (WIN_HWND)1;
#endif
unguard;
}
#else
bool CD3D8Renderer::Init(int x,int y,int width,int height,unsigned int cbpp, int zbpp, int sbits, bool fullscreen)
{
return false;
}
#endif
static char sErr[256];
char *CD3D8Renderer::D3DError( HRESULT h )
{
D3DXGetErrorString(h, sErr, 256);
return sErr;
}
bool CD3D8Renderer::Error(char *Msg, HRESULT h)
{
guard(CD3D8Renderer::mfError);
char *str = D3DError(h);
iLog->Log("Error: %s (%s)", Msg, str);
//UnSetRes();
//if (Msg)
// iConsole->Exit("%s (%s)\n", Msg, str);
//else
// iConsole->Exit("(%s)\n", str);
return false;
unguard;
}
//-----------------------------------------------------------------------------
// Name: CD3D8Renderer::mfConfirmDevice()
// Desc: Called during device intialization, this code checks the device
// for some minimum set of capabilities
//-----------------------------------------------------------------------------
HRESULT CD3D8Renderer::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format )
{
return S_OK;
}
// Name: SortModesCallback()
// Desc: Callback function for sorting display modes (used by BuildDevicesList).
//-----------------------------------------------------------------------------
int SortModesCallback( const VOID* arg1, const VOID* arg2 )
{
D3DDISPLAYMODE* p1 = (D3DDISPLAYMODE*)arg1;
D3DDISPLAYMODE* p2 = (D3DDISPLAYMODE*)arg2;
if( p1->Format > p2->Format ) return -1;
if( p1->Format < p2->Format ) return +1;
if( p1->Width < p2->Width ) return -1;
if( p1->Width > p2->Width ) return +1;
if( p1->Height < p2->Height ) return -1;
if( p1->Height > p2->Height ) return +1;
return 0;
}
//-----------------------------------------------------------------------------
// Name: CD3D8Renderer::mfFindDepthStencilFormat()
// Desc: Finds a depth/stencil format for the given device that is compatible
// with the render target format and meets the needs of the app.
//-----------------------------------------------------------------------------
bool CD3D8Renderer::FindDepthStencilFormat( UINT iAdapter, D3DDEVTYPE DeviceType, D3DFORMAT TargetFormat, D3DFORMAT* pDepthStencilFormat )
{
if( m_MinDepthBits <= 16 && m_MinStencilBits == 0 )
{
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16_LOCKABLE ) ) )
{
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D16_LOCKABLE ) ) )
{
*pDepthStencilFormat = D3DFMT_D16_LOCKABLE;
return TRUE;
}
}
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D16 ) ) )
{
*pDepthStencilFormat = D3DFMT_D16;
return TRUE;
}
}
}
if( m_MinDepthBits <= 15 && m_MinStencilBits <= 1 )
{
#ifndef _XBOX
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D15S1 ) ) )
{
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D15S1 ) ) )
{
*pDepthStencilFormat = D3DFMT_D15S1;
return TRUE;
}
}
#endif
}
if( m_MinDepthBits <= 24 && m_MinStencilBits == 0 )
{
#ifndef _XBOX
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D24X8 ) ) )
{
*pDepthStencilFormat = D3DFMT_D24X8;
return TRUE;
}
}
#endif
}
if( m_MinDepthBits <= 24 && m_MinStencilBits <= 8 )
{
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D24S8 ) ) )
{
*pDepthStencilFormat = D3DFMT_D24S8;
return TRUE;
}
}
}
if( m_MinDepthBits <= 24 && m_MinStencilBits <= 4 )
{
#ifndef _XBOX
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X4S4 ) ) )
{
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D24X4S4 ) ) )
{
*pDepthStencilFormat = D3DFMT_D24X4S4;
return TRUE;
}
}
#endif
}
if( m_MinDepthBits <= 32 && m_MinStencilBits == 0 )
{
#ifndef _XBOX
if( SUCCEEDED( m_pD3D->CheckDeviceFormat( iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32 ) ) )
{
if( SUCCEEDED( m_pD3D->CheckDepthStencilMatch( iAdapter, DeviceType, TargetFormat, TargetFormat, D3DFMT_D32 ) ) )
{
*pDepthStencilFormat = D3DFMT_D32;
return TRUE;
}
}
#endif
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Name: CD3D8Renderer::mfBuildDevicesList()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3D8Renderer::BuildDevicesList()
{
const DWORD dwNumDeviceTypes = 2;
const TCHAR* strDeviceDescs[] = {"HAL", "REF"};
const D3DDEVTYPE DeviceTypes[] = { D3DDEVTYPE_HAL, D3DDEVTYPE_REF };
m_bHALExists = FALSE;
m_bHALIsWindowedCompatible = FALSE;
m_bHALIsDesktopCompatible = FALSE;
m_bHALIsSampleCompatible = FALSE;
m_dwNumAdapters = 0;
// Loop through all the adapters on the system (usually, there's just one
// unless more than one graphics card is present).
for( UINT iAdapter = 0; iAdapter < m_pD3D->GetAdapterCount(); iAdapter++ )
{
// Fill in adapter info
SD3DAdapterInfo* pAdapter = &m_Adapters[m_dwNumAdapters];
m_pD3D->GetAdapterIdentifier( iAdapter, 0, &pAdapter->d3dAdapterIdentifier );
m_pD3D->GetAdapterDisplayMode( iAdapter, &pAdapter->d3ddmDesktop );
pAdapter->dwNumDevices = 0;
pAdapter->dwCurrentDevice = 0;
pAdapter->mMaxWidth = 0;
pAdapter->mMaxHeight = 0;
// Enumerate all display modes on this adapter
D3DDISPLAYMODE modes[100];
D3DFORMAT formats[20];
DWORD dwNumFormats = 0;
DWORD dwNumModes = 0;
DWORD dwNumAdapterModes = m_pD3D->GetAdapterModeCount( iAdapter );
// Add the adapter's current desktop format to the list of formats
formats[dwNumFormats++] = pAdapter->d3ddmDesktop.Format;
for( UINT iMode = 0; iMode < dwNumAdapterModes; iMode++ )
{
// Get the display mode attributes
D3DDISPLAYMODE DisplayMode;
m_pD3D->EnumAdapterModes( iAdapter, iMode, &DisplayMode );
// Check if the mode already exists (to filter out refresh rates)
for( DWORD m=0L; m<dwNumModes; m++ )
{
if( ( modes[m].Width == DisplayMode.Width ) &&
( modes[m].Height == DisplayMode.Height ) &&
( modes[m].Format == DisplayMode.Format ) )
break;
}
// If we found a new mode, add it to the list of modes
if( m == dwNumModes )
{
modes[dwNumModes].Width = DisplayMode.Width;
modes[dwNumModes].Height = DisplayMode.Height;
modes[dwNumModes].Format = DisplayMode.Format;
modes[dwNumModes].RefreshRate = 0;
if ((int)modes[dwNumModes].Width > pAdapter->mMaxWidth)
pAdapter->mMaxWidth = modes[dwNumModes].Width;
if ((int)modes[dwNumModes].Height > pAdapter->mMaxHeight)
pAdapter->mMaxHeight = modes[dwNumModes].Height;
dwNumModes++;
// Check if the mode's format already exists
for( DWORD f=0; f<dwNumFormats; f++ )
{
if( DisplayMode.Format == formats[f] )
break;
}
// If the format is new, add it to the list
if( f== dwNumFormats )
formats[dwNumFormats++] = DisplayMode.Format;
}
}
// Sort the list of display modes (by format, then width, then height)
qsort( modes, dwNumModes, sizeof(D3DDISPLAYMODE), SortModesCallback );
// Add devices to adapter
for( UINT iDevice = 0; iDevice < dwNumDeviceTypes; iDevice++ )
{
// Fill in device info
SD3DDeviceInfo* pDevice;
pDevice = &pAdapter->devices[pAdapter->dwNumDevices];
pDevice->DeviceType = DeviceTypes[iDevice];
m_pD3D->GetDeviceCaps( iAdapter, DeviceTypes[iDevice], &pDevice->d3dCaps );
pDevice->strDesc = strDeviceDescs[iDevice];
pDevice->dwNumModes = 0;
pDevice->dwCurrentMode = 0;
pDevice->bCanDoWindowed = FALSE;
pDevice->bWindowed = !m_bFullScreen;
pDevice->MultiSampleType = D3DMULTISAMPLE_NONE;
// Examine each format supported by the adapter to see if it will
// work with this device and meets the needs of the application.
BOOL bFormatConfirmed[20];
DWORD dwBehavior[20];
D3DFORMAT fmtDepthStencil[20];
for( DWORD f=0; f<dwNumFormats; f++ )
{
bFormatConfirmed[f] = FALSE;
fmtDepthStencil[f] = D3DFMT_UNKNOWN;
// Skip formats that cannot be used as render targets on this device
if( FAILED( m_pD3D->CheckDeviceType( iAdapter, pDevice->DeviceType, formats[f], formats[f], FALSE ) ) )
continue;
if( pDevice->DeviceType == D3DDEVTYPE_HAL )
{
// This system has a HAL device
m_bHALExists = TRUE;
if( pDevice->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED )
{
// HAL can run in a window for some mode
m_bHALIsWindowedCompatible = TRUE;
if( f == 0 )
{
// HAL can run in a window for the current desktop mode
m_bHALIsDesktopCompatible = TRUE;
}
}
}
// Confirm the device/format for HW vertex processing
if( pDevice->d3dCaps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
if( pDevice->d3dCaps.DevCaps&D3DDEVCAPS_PUREDEVICE )
{
dwBehavior[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE;
if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f], formats[f] ) ) )
bFormatConfirmed[f] = TRUE;
}
if ( FALSE == bFormatConfirmed[f] )
{
dwBehavior[f] = D3DCREATE_HARDWARE_VERTEXPROCESSING;
if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f], formats[f] ) ) )
bFormatConfirmed[f] = TRUE;
}
if ( FALSE == bFormatConfirmed[f] )
{
dwBehavior[f] = D3DCREATE_MIXED_VERTEXPROCESSING;
if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f], formats[f] ) ) )
bFormatConfirmed[f] = TRUE;
}
}
// Confirm the device/format for SW vertex processing
if( FALSE == bFormatConfirmed[f] )
{
dwBehavior[f] = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
if( SUCCEEDED( ConfirmDevice( &pDevice->d3dCaps, dwBehavior[f], formats[f] ) ) )
bFormatConfirmed[f] = TRUE;
}
// Find a suitable depth/stencil buffer format for this device/format
if( bFormatConfirmed[f] )
{
m_MinDepthBits = Clamp(CRenderer::m_zbpp, 15, 32);
m_MinStencilBits = Clamp(CRenderer::m_sbpp, 0, 8);
if( !FindDepthStencilFormat( iAdapter, pDevice->DeviceType, formats[f], &fmtDepthStencil[f] ) )
{
m_MinStencilBits = 0;
if( FindDepthStencilFormat( iAdapter, pDevice->DeviceType, formats[f], &fmtDepthStencil[f] ) )
goto ok;
for (m_MinDepthBits=32; m_MinDepthBits>=15; m_MinDepthBits-=8)
{
for (m_MinStencilBits=8; m_MinStencilBits>=0; m_MinStencilBits-=4)
{
if( FindDepthStencilFormat( iAdapter, pDevice->DeviceType, formats[f], &fmtDepthStencil[f] ) )
goto ok;
}
}
bFormatConfirmed[f] = FALSE;
}
}
ok:
int nn = 0;
}
// Add all enumerated display modes with confirmed formats to the
// device's list of valid modes
for( DWORD m=0L; m<dwNumModes; m++ )
{
for( DWORD f=0; f<dwNumFormats; f++ )
{
if( modes[m].Format == formats[f] )
{
if( bFormatConfirmed[f] == TRUE )
{
// Add this mode to the device's list of valid modes
pDevice->modes[pDevice->dwNumModes].Width = modes[m].Width;
pDevice->modes[pDevice->dwNumModes].Height = modes[m].Height;
pDevice->modes[pDevice->dwNumModes].Format = modes[m].Format;
pDevice->modes[pDevice->dwNumModes].dwBehavior = dwBehavior[f];
pDevice->modes[pDevice->dwNumModes].DepthStencilFormat = fmtDepthStencil[f];
pDevice->dwNumModes++;
if( pDevice->DeviceType == D3DDEVTYPE_HAL )
m_bHALIsSampleCompatible = TRUE;
}
}
}
}
// Check if the device is compatible with the desktop display mode
// (which was added initially as formats[0])
if( bFormatConfirmed[0] && (pDevice->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED) )
{
pDevice->bCanDoWindowed = TRUE;
}
else
if( bFormatConfirmed[0] && !(pDevice->d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED) )
pDevice->bWindowed = FALSE;
// If valid modes were found, keep this device
if( pDevice->dwNumModes > 0 )
pAdapter->dwNumDevices++;
}
// If valid devices were found, keep this adapter
if( pAdapter->dwNumDevices > 0 )
m_dwNumAdapters++;
}
// Return an error if no compatible devices were found
if( 0L == m_dwNumAdapters )
return D3DAPPERR_NOCOMPATIBLEDEVICES;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CD3D8Renderer::mfAdjustWindowForChange()
// Desc: Prepare the window for a possible change between windowed mode and
// fullscreen mode. This function is virtual and thus can be overridden
// to provide different behavior, such as switching to an entirely
// different window for fullscreen mode (as in the MFC sample apps).
//-----------------------------------------------------------------------------
HRESULT CD3D8Renderer::AdjustWindowForChange()
{
#ifndef _XBOX
if( !m_bFullScreen )
{
// Set windowed-mode style
SetWindowLong( m_hWnd, GWL_STYLE, m_dwWindowStyle );
}
else
{
// Set fullscreen-mode style
SetWindowLong( m_hWnd, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE );
}
#endif
return S_OK;
}
HRESULT CD3D8Renderer::InitDeviceObjects()
{
// Gamma correction support
if (m_d3dCaps.Caps2 & D3DCAPS2_FULLSCREENGAMMA)
m_Features |= RFT_HWGAMMA;
if (m_d3dCaps.Caps2 & D3DCAPS2_CANCALIBRATEGAMMA)
m_bGammaCalibrate = true;
else
m_bGammaCalibrate = false;
// Device Id's
D3DADAPTER_IDENTIFIER8 *ai = &m_Adapters[m_dwAdapter].d3dAdapterIdentifier;
iLog->Log ( "D3D Adapter: Driver name: %s\n", ai->Driver);
iLog->Log ( "D3D Adapter: Driver description: %s\n", ai->Description);
iLog->Log ( "D3D Adapter: Driver version: %d.%02d.%02d.%04d\n", HIWORD( ai->DriverVersion.u.HighPart ), LOWORD( ai->DriverVersion.u.HighPart ), HIWORD(ai->DriverVersion.u.LowPart), LOWORD(ai->DriverVersion.u.LowPart));
// Unique driver/device identifier:
GUID *pGUID = &ai->DeviceIdentifier;
iLog->Log ( "D3D Adapter: Driver GUID: %08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X\n", pGUID->Data1, pGUID->Data2, pGUID->Data3, pGUID->Data4[0], pGUID->Data4[1], pGUID->Data4[2], pGUID->Data4[3], pGUID->Data4[4], pGUID->Data4[5], pGUID->Data4[6], pGUID->Data4[7] );
iLog->Log ( "D3D Adapter: VendorId = %i\n", ai->VendorId);
iLog->Log ( "D3D Adapter: DeviceId = %i\n", ai->DeviceId);
iLog->Log ( "D3D Adapter: SubSysId = %i\n", ai->SubSysId);
iLog->Log ( "D3D Adapter: Revision = %i\n", ai->Revision);
// Hardware-specific initialization and workarounds for driver bugs.
guard(DeviceIdentification)
{
bool ConstrainAspect = 1;
if( CV_d3d8_nodeviceid )
{
iLog->Log ("D3D Detected: -nodeviceid specified, 3D device identification skipped\n");
}
else
if( ai->VendorId==4098 )
{
iLog->Log ("D3D Detected: ATI video card\n");
if( ai->DeviceId==18242 )
{
iLog->Log ("D3D Detected: ATI Rage Pro\n");
}
else
if( ai->DeviceId==21062 )
{
iLog->Log ("D3D Detected: ATI Rage 128\n");
}
else
if( ai->DeviceId==20812 )
{
iLog->Log ("D3D Detected: ATI Radeon 8500\n");
m_Features |= RFT_HW_RADEON8500;
}
else
if( ai->DeviceId==20036 )
{
iLog->Log ("D3D Detected: ATI Radeon 9700\n");
m_Features |= RFT_HW_RADEON8500;
}
}
else
if( ai->VendorId==4634 )
{
iLog->Log ("D3D Detected: 3dfx video card\n");
if( ai->DeviceId==1 )
{
iLog->Log ("D3D Detected: 3dfx Voodoo\n");
}
else
if( ai->DeviceId==2 )
{
iLog->Log ("D3D Detected: 3dfx Voodoo2\n");
}
else
if( ai->DeviceId==3 )
{
iLog->Log ("D3D Detected: 3dfx Voodoo Banshee\n");
}
else
if( ai->DeviceId==5 )
{
iLog->Log ("D3D Detected: 3dfx Voodoo3\n");
}
}
else
if( ai->VendorId==32902 )
{
iLog->Log ("D3D Detected: Intel video card\n");
if( ai->DeviceId==30720 )
{
iLog->Log ("D3D Detected: Intel i740\n");
}
if( ai->DeviceId==7121 )
{
iLog->Log ("D3D Detected: Intel 810L\n");
}
if( ai->DeviceId==7123 )
{
iLog->Log ("D3D Detected: Intel 810 DC100\n");
}
if( ai->DeviceId==7125 )
{
iLog->Log ("D3D Detected: Intel 810E\n");
}
}
else
if( ai->VendorId==4318 )
{
iLog->Log ("D3D Detected: NVidia video card\n");
if( ai->DeviceId==0x20 )
{
iLog->Log ("D3D Detected: Riva TNT\n");
ConstrainAspect = 0;
}
if( ai->DeviceId==0x40 )
{
iLog->Log ("D3D Detected: Riva TNT2\n");
ConstrainAspect = 0;
}
if( ai->DeviceId==0x29)
{
iLog->Log ("D3D Detected: Riva TNT2 Ultra\n");
ConstrainAspect = 0;
}
if( ai->DeviceId==0x2c)
{
iLog->Log ("D3D Detected: Vanta/Vanta LT\n");
ConstrainAspect = 0;
}
if( ai->DeviceId==0x2d)
{
iLog->Log ("D3D Detected: Riva TNT2 Model 64/Model 64 Pro\n");
ConstrainAspect = 0;
}
if( ai->DeviceId==0xa0)
{
iLog->Log ("D3D Detected: Aladdin TNT2\n");
ConstrainAspect = 0;
}
if (ai->DeviceId == 0x100)
{
iLog->Log ("D3D Detected: GeForce SDR\n");
}
if (ai->DeviceId == 0x101)
{
iLog->Log ("D3D Detected: GeForce DDR\n");
}
if (ai->DeviceId == 0x103)
{
iLog->Log ("D3D Detected: Quadro\n");
}
if (ai->DeviceId == 0x110)
{
iLog->Log ("D3D Detected: GeForce2 MX/MX 400\n");
}
if (ai->DeviceId == 0x111)
{
iLog->Log ("D3D Detected: GeForce2 MX 100/MX 200\n");
}
if (ai->DeviceId == 0x112)
{
iLog->Log ("D3D Detected: GeForce2 Go\n");
}
if (ai->DeviceId == 0x113)
{
iLog->Log ("D3D Detected: Quadro2 MXR/EX/Go\n");
}
if (ai->DeviceId == 0x150)
{
iLog->Log ("D3D Detected: GeForce2 GTS\n");
}
if (ai->DeviceId == 0x151)
{
iLog->Log ("D3D Detected: GeForce2 Ti\n");
}
if (ai->DeviceId == 0x152)
{
iLog->Log ("D3D Detected: GeForce2 Ultra\n");
}
if (ai->DeviceId == 0x153)
{
iLog->Log ("D3D Detected: Quadro2 Pro\n");
}
if (ai->DeviceId == 0x170)
{
iLog->Log ("D3D Detected: GeForce4 MX 460\n");
}
if (ai->DeviceId == 0x171)
{
iLog->Log ("D3D Detected: GeForce4 MX 440\n");
}
if (ai->DeviceId == 0x172)
{
iLog->Log ("D3D Detected: GeForce4 MX 420\n");
}
if (ai->DeviceId == 0x174)
{
iLog->Log ("D3D Detected: GeForce4 440 Go\n");
}
if (ai->DeviceId == 0x175)
{
iLog->Log ("D3D Detected: GeForce4 420 Go\n");
}
if (ai->DeviceId == 0x176)
{
iLog->Log ("D3D Detected: GeForce4 420 Go 32M\n");
}
if (ai->DeviceId == 0x177)
{
iLog->Log ("D3D Detected: GeForce4 440 Go 64M\n");
}
if (ai->DeviceId == 0x178)
{
iLog->Log ("D3D Detected: Quadro4 500 XGL\n");
}
if (ai->DeviceId == 0x179)
{
iLog->Log ("D3D Detected: Quadro4 550 XGL\n");
}
if (ai->DeviceId == 0x17a)
{
iLog->Log ("D3D Detected: Quadro4 200 NVS\n");
}
if (ai->DeviceId == 0x1a0)
{
iLog->Log ("D3D Detected: GeForce2 Integrated GPU\n");
}
if (ai->DeviceId == 0x200)
{
iLog->Log ("D3D Detected: GeForce3\n");
}
if (ai->DeviceId == 0x201)
{
iLog->Log ("D3D Detected: GeForce3 Ti 200\n");
}
if (ai->DeviceId == 0x202)
{
iLog->Log ("D3D Detected: GeForce3 Ti 500\n");
}
if (ai->DeviceId == 0x203)
{
iLog->Log ("D3D Detected: Quadro DCC\n");
}
if (ai->DeviceId == 0x250)
{
iLog->Log ("D3D Detected: GeForce4 Ti 4600\n");
}
if (ai->DeviceId == 0x251)
{
iLog->Log ("D3D Detected: GeForce4 Ti 4400\n");
}
if (ai->DeviceId == 0x253)
{
iLog->Log ("D3D Detected: GeForce4 Ti 4200\n");
}
if (ai->DeviceId == 0x258)
{
iLog->Log ("D3D Detected: Quadro4 900 XGL\n");
}
if (ai->DeviceId == 0x259)
{
iLog->Log ("D3D Detected: Quadro4 750 XGL\n");
}
if (ai->DeviceId == 0x25b)
{
iLog->Log ("D3D Detected: Quadro4 700 XGL\n");
}
}
else
if( ai->VendorId==4818 )
{
iLog->Log ("D3D Detected: NVidia video card\n");
if( ai->DeviceId==0x18 || ai->DeviceId==0x19)
{
iLog->Log ("D3D Detected: Riva 128\n");
ConstrainAspect = 0;
}
}
else
if( ai->VendorId==4139 )
{
iLog->Log ("D3D Detected: Matrox video card\n");
if( ai->DeviceId==1313 )
iLog->Log ("D3D Detected: Matrox G200\n");
else
if( ai->DeviceId==1317 )
iLog->Log ("D3D Detected: Matrox G400\n");
//G400 lies about texture stages, last one is for bump only
}
else
{
iLog->Log ("D3D Detected: Generic 3D accelerator\n");
}
}
unguardnw
// Set viewport.
guardnw(SetViewport);
SetViewport(0,0,CRenderer::m_width, CRenderer::m_height);
unguardnw;
// Check multitexture caps.
iLog->Log ( "D3D Driver: MaxTextureBlendStages = %i\n", m_d3dCaps.MaxTextureBlendStages);
iLog->Log ( "D3D Driver: MaxSimultaneousTextures = %i\n", m_d3dCaps.MaxSimultaneousTextures);
if( m_d3dCaps.MaxSimultaneousTextures>=2 )
m_Features |= RFT_MULTITEXTURE;
// Handle the texture formats we need.
guardnw(InitTextureFormats);
{
// Zero them all.
mFormat8000.Init(); // A
mFormat8888.Init(); // BGRA
mFormat4444.Init(); // BGRA
mFormat0565.Init(); // BGR
mFormat0555.Init(); // BGR
mFormat1555.Init(); // BGRA
mFormatU8V8.Init(); // Bump
mFormatU5V5L6.Init(); // Bump
mFormatDXT1.Init(); // DXT1
mFormatDXT3.Init(); // DXT3
mFormatDXT5.Init(); // DXT5
mFormatPal8.Init(); // Paletted8
// Find the needed texture formats.
guardnw(FindTextureFormats);
{
mFirstPixelFormat = NULL;
if(m_TextureBits >= 24)
{
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8)))
RecognizePixelFormat(mFormat8888, D3DFMT_A8R8G8B8, 32, "8888");
}
if( !mFirstPixelFormat )
{
m_TextureBits = 16;
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_A1R5G5B5)))
RecognizePixelFormat(mFormat1555, D3DFMT_A1R5G5B5, 16, "1555");
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_A4R4G4B4)))
RecognizePixelFormat(mFormat4444, D3DFMT_A4R4G4B4, 16, "4444");
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_R5G6B5)))
RecognizePixelFormat(mFormat0565, D3DFMT_R5G6B5, 16, "0565");
else
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_X1R5G5B5)))
RecognizePixelFormat(mFormat0555, D3DFMT_X1R5G5B5, 16, "0555");
}
// Alpha formats
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_A8)))
RecognizePixelFormat(mFormat8000, D3DFMT_A8, 8, "Alpha8");
// Bump formats
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_V8U8)))
RecognizePixelFormat(mFormatU8V8, D3DFMT_V8U8, 16, "BumpU8V8");
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_Q8W8V8U8)))
RecognizePixelFormat(mFormatU8V8, D3DFMT_Q8W8V8U8, 32, "BumpQ8W8U8V8");
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_X8L8V8U8)))
RecognizePixelFormat(mFormatU8V8, D3DFMT_X8L8V8U8, 32, "BumpX8L8U8V8");
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_L6V5U5)))
RecognizePixelFormat(mFormatU5V5L6, D3DFMT_L6V5U5, 16, "BumpU5V5L6");
// Paletted formats
if (CV_d3d8_palettedtextures)
{
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_P8)))
{
RecognizePixelFormat(mFormatPal8, D3DFMT_P8, 8, "Paletted8");
m_Features |= RFT_PALTEXTURE;
}
}
// Compressed formats
if (CV_d3d8_compressedtextures)
{
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)))
{
RecognizePixelFormat(mFormatDXT1, D3DFMT_DXT1, 8, "DXT1");
m_Features |= RFT_COMPRESSTEXTURE;
}
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)))
{
RecognizePixelFormat(mFormatDXT3, D3DFMT_DXT3, 8, "DXT3");
m_Features |= RFT_COMPRESSTEXTURE;
}
if(SUCCEEDED(m_pD3D->CheckDeviceFormat( m_dwAdapter, m_d3dCaps.DeviceType, m_d3dpp.BackBufferFormat, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)))
{
RecognizePixelFormat(mFormatDXT5, D3DFMT_DXT5, 8, "DXT5");
m_Features |= RFT_COMPRESSTEXTURE;
}
}
}
unguardnw;
}
unguardnw;
// Verify mipmapping supported.
if (!(m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP))
{
iLog->Log ("D3D Driver: Mipmapping not available with this driver\n");
m_Features |= RFT_NOMIPS;
}
else
{
if( m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR )
iLog->Log ("D3D Driver: Supports trilinear texture filtering\n");
}
if( m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE )
{
iLog->Log ("D3D Driver: Supports alpha palettes\n");
m_bAllowAlphaPalettes = true;
}
if( m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
{
m_d3dCaps.MaxTextureAspectRatio = 1;
iLog->Log ("D3D Driver: Requires square textures\n");
}
else
if( !m_d3dCaps.MaxTextureAspectRatio )
m_d3dCaps.MaxTextureAspectRatio = Max<int>(1,Max<int>(m_d3dCaps.MaxTextureWidth,m_d3dCaps.MaxTextureHeight));
if( !(m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_POW2) )
iLog->Log ("D3D Driver: Supports non-power-of-2 textures\n");
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS )
iLog->Log ("D3D Driver: Supports LOD biasing\n");
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_ZBIAS )
iLog->Log ("D3D Driver: Supports Z biasing\n");
else
m_Features &= ~RFT_SUPPORTZBIAS;
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_ADDSIGNED2X )
iLog->Log ("D3D Driver: Supports D3DTOP_ADDSIGNED2X TextureOp\n");
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP )
iLog->Log ("D3D Driver: Supports D3DTOP_BUMPENVMAP TextureOp\n");
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAPLUMINANCE )
iLog->Log ("D3D Driver: Supports D3DTOP_BUMPENVMAPLUMINANCE TextureOp\n");
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3 )
iLog->Log ("D3D Driver: Supports D3DTOP_DOTPRODUCT3 TextureOp\n");
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR )
iLog->Log ("D3D Driver: Supports D3DTOP_MODULATEALPHA_ADDCOLOR TextureOp\n");
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA )
iLog->Log ("D3D Driver: Supports D3DTOP_MODULATECOLOR_ADDALPHA TextureOp\n");
if( m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_ADD )
iLog->Log ("D3D Driver: Supports D3DTOP_ADD TextureOp\n");
m_MaxAnisotropyLevel = 1;
m_AnisotropyLevel = 1;
// Check the device for supported filtering methods
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY )
{
m_MaxAnisotropyLevel = m_AnisotropyLevel = m_d3dCaps.MaxAnisotropy;
iLog->Log ("D3D Driver: Supports MaxAnisotropy level %d\n", m_AnisotropyLevel);
m_Features |= RFT_ALLOWANISOTROPIC;
}
if( m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFAFLATCUBIC )
{
m_bDeviceDoesFlatCubic = TRUE;
iLog->Log ("D3D Driver: Supports FlatCubic Filter\n");
}
if( m_d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC )
{
m_bDeviceDoesGaussianCubic = TRUE;
iLog->Log ("D3D Driver: Supports GaussianCubic Filter\n");
}
if( m_d3dCaps.StencilCaps & (D3DSTENCILCAPS_KEEP|D3DSTENCILCAPS_INCR|D3DSTENCILCAPS_DECR) )
iLog->Log ("D3D Driver: Supports Stencil shadows\n");
else
CRenderer::m_sbpp = 0;
iLog->Log ("D3D Driver: Textures (%ix%i)-(%ix%i), Max aspect %i\n", mMinTextureWidth, mMinTextureHeight, m_d3dCaps.MaxTextureWidth, m_d3dCaps.MaxTextureHeight, m_d3dCaps.MaxTextureAspectRatio );
// Depth buffering.
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
if ( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_WBUFFER )
{
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_USEW );
m_bUseWBuffer = true;
iLog->Log ("D3D Driver: Supports w-buffering\n");
}
else
m_bUseWBuffer = false;
m_Features &= ~RFT_BUMP;
if( CV_d3d8_usebumpmap && (GetFeatures() & RFT_MULTITEXTURE))
{
int type = CV_d3d8_bumptype;
if (type == 0 && (m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP) && m_d3dCaps.MaxTextureBlendStages>=3)
m_Features |= RFT_BUMP_EMBM;
else
if (type == 1 && (m_d3dCaps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3) && (m_d3dCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) && mFormat8888.BitsPerPixel)
m_Features |= RFT_BUMP_DOT3;
}
// Init render states.
guardnw(InitRenderState);
{
m_pd3dDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_COLORVERTEX, TRUE );
D3DSetCull(eCULL_None);
m_pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 127 );
m_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATER );
if( m_d3dCaps.RasterCaps & D3DPRASTERCAPS_ZBIAS )
m_pd3dDevice->SetRenderState( D3DRS_ZBIAS, 0 );
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );
m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE);
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE);
m_pd3dDevice->SetRenderState( D3DRS_FOGCOLOR, 0 );
m_pd3dDevice->SetRenderState( D3DRS_FOGTABLEMODE, D3DFOG_LINEAR );
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE, FALSE);
#ifndef _XBOX
m_pd3dDevice->SetRenderState( D3DRS_CLIPPING, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, FALSE );
m_pd3dDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE );
#else
//m_pd3dDevice->SetBackBufferScale(1.0f, 1.0f);
m_pd3dDevice->SetPixelShader( NULL );
m_pd3dDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, FALSE );
m_pd3dDevice->SetRenderState( D3DRS_POINTSCALEENABLE, FALSE );
#endif
m_pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, FALSE );
}
unguardnw;
msCurState = GS_DEPTHWRITE | GS_NODEPTHTEST;
for (int i=0; i<MAX_TMU; i++)
{
eCurColorOp[i] = eCO_DISABLE;
}
// Init texture stage state.
guardnw(InitTextureStageState);
{
FLOAT LodBias=-0.5;
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPMAPLODBIAS, *(DWORD*)&LodBias );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
EF_SetColorOp(eCO_MODULATE);
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
mStages[0].MinFilter = D3DTEXF_LINEAR;
mStages[0].MagFilter = D3DTEXF_LINEAR;
mStages[0].UseMips = 1;
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
#ifdef _XBOX
m_pd3dDevice->SetTextureStageState(0, D3DTSS_RESULTARG, D3DTA_CURRENT);
#endif
guardnw( TextureStagesSetup )
{
// Set stage 0 state.
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
if( GetFeatures() & RFT_MULTITEXTURE )
{
for( i=1; i<(int)m_d3dCaps.MaxSimultaneousTextures; i++ )
{
m_TexMan->m_CurStage = i;
// Set stage i state.
m_pd3dDevice->SetTextureStageState( i, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
m_pd3dDevice->SetTextureStageState( i, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
m_pd3dDevice->SetTextureStageState( i, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( i, D3DTSS_COLORARG2, D3DTA_CURRENT );
EF_SetColorOp(eCO_DISABLE);
m_pd3dDevice->SetTextureStageState( i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( i, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
m_pd3dDevice->SetTextureStageState( i, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
m_pd3dDevice->SetTextureStageState( i, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( i, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( i, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( i, D3DTSS_TEXCOORDINDEX, i );
mStages[i].MinFilter = D3DTEXF_LINEAR;
mStages[i].MagFilter = D3DTEXF_LINEAR;
mStages[i].UseMips = 1;
#ifdef _XBOX
m_pd3dDevice->SetTextureStageState(0, D3DTSS_RESULTARG, D3DTA_CURRENT);
#endif
}
}
}
unguardnw;
}
unguardnw;
m_TexMan->m_CurStage = 0;
m_TexMan->SetFilter(CV_d3d8_texturefilter->GetString());
// For safety, lots of drivers don't handle tiny texture sizes too tell.
mMinTextureWidth = 8;
mMinTextureHeight = 8;
m_d3dCaps.MaxTextureAspectRatio = Min<int>( m_d3dCaps.MaxTextureAspectRatio, 2 );//8 is safe, this is just more efficient
m_MaxTextureSize = Min(m_d3dCaps.MaxTextureHeight, m_d3dCaps.MaxTextureWidth); //Min(wdt, hgt);
return S_OK;
}
void CD3D8Renderer::RecognizePixelFormat(SPixFormat& Dest, D3DFORMAT FromD3D, INT InBitsPerPixel, const TCHAR* InDesc)
{
guard(CD3D8Renderer::RecognizePixelFormat);
Dest.Init();
Dest.Format = FromD3D;
Dest.MaxWidth = m_d3dCaps.MaxTextureWidth;
Dest.MaxHeight = m_d3dCaps.MaxTextureHeight;
Dest.Desc = InDesc;
Dest.BitsPerPixel = InBitsPerPixel;
Dest.Next = mFirstPixelFormat;
mFirstPixelFormat = &Dest;
iLog->Log(" Using '%s' pixel texture format\n", InDesc);
unguard;
}
HRESULT CD3D8Renderer::RestoreDeviceObjects()
{
//InitTexFillers();
//Flush();
for (int i=0; i<MAX_TMU; i++)
{
mStages[i].Flush();
}
return S_OK;
}
void CD3D8Renderer::SetRendParms(SD3DModeInfo *pModeInfo, SD3DDeviceInfo *pDeviceInfo)
{
m_bFullScreen = !pDeviceInfo->bWindowed;
m_AlphaDepth = 0;
if (m_bFullScreen)
{
CRenderer::m_width = pModeInfo->Width;
CRenderer::m_height = pModeInfo->Height;
}
else
{
pModeInfo->Width = CRenderer::m_width;
pModeInfo->Height = CRenderer::m_height;
if (m_cbpp == 32)
pModeInfo->Format = D3DFMT_A8R8G8B8;
else
if (m_cbpp == 24)
pModeInfo->Format = D3DFMT_X8R8G8B8;
else
pModeInfo->Format = D3DFMT_R5G6B5;
}
m_AlphaDepth = 0;
switch (pModeInfo->Format)
{
case D3DFMT_X8R8G8B8:
CRenderer::m_cbpp = 24;
break;
case D3DFMT_A8R8G8B8:
m_AlphaDepth = 8;
CRenderer::m_cbpp = 32;
break;
case D3DFMT_A1R5G5B5:
m_AlphaDepth = 1;
CRenderer::m_cbpp = 16;
break;
case D3DFMT_A4R4G4B4:
m_AlphaDepth = 4;
CRenderer::m_cbpp = 16;
break;
case D3DFMT_R5G6B5:
case D3DFMT_X1R5G5B5:
CRenderer::m_cbpp = 16;
break;
#ifdef _XBOX
case D3DFMT_LIN_X8R8G8B8:
CRenderer::m_cbpp = 24;
break;
case D3DFMT_LIN_X1R5G5B5:
case D3DFMT_LIN_R5G6B5:
CRenderer::m_cbpp = 16;
break;
case D3DFMT_LIN_A8R8G8B8:
CRenderer::m_cbpp = 32;
break;
#endif
}
CRenderer::m_sbpp = 0;
CRenderer::m_zbpp = 0;
switch (pModeInfo->DepthStencilFormat)
{
case D3DFMT_D16:
CRenderer::m_zbpp = 16;
break;
#ifndef _XBOX
case D3DFMT_D32:
CRenderer::m_zbpp = 32;
break;
case D3DFMT_D15S1:
CRenderer::m_sbpp = 1;
CRenderer::m_zbpp = 16;
break;
#endif
case D3DFMT_D24S8:
CRenderer::m_sbpp = 8;
CRenderer::m_zbpp = 24;
break;
#ifndef _XBOX
case D3DFMT_D24X8:
CRenderer::m_zbpp = 24;
break;
case D3DFMT_D24X4S4:
CRenderer::m_zbpp = 24;
CRenderer::m_sbpp = 4;
break;
#endif
}
}
//-----------------------------------------------------------------------------
// Name: CD3D8Renderer::mfInitialize3DEnvironment()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3D8Renderer::Initialize3DEnvironment()
{
HRESULT hr;
SD3DAdapterInfo* pAdapterInfo = &m_Adapters[m_dwAdapter];
SD3DDeviceInfo* pDeviceInfo = &pAdapterInfo->devices[pAdapterInfo->dwCurrentDevice];
SD3DModeInfo* pModeInfo = &pDeviceInfo->modes[pDeviceInfo->dwCurrentMode];
SetRendParms(pModeInfo, pDeviceInfo);
// Prepare window for possible windowed/fullscreen change
AdjustWindowForChange();
// Set up the presentation parameters
ZeroMemory( &m_d3dpp, sizeof(m_d3dpp) );
m_d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
m_d3dpp.Windowed = pDeviceInfo->bWindowed;
m_d3dpp.BackBufferCount = 1;
m_d3dpp.MultiSampleType = pDeviceInfo->MultiSampleType;
// Anti-aliasing
//m_d3dpp.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_LINEAR;
#ifdef _XBOX
m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
#else
m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
#endif
m_d3dpp.EnableAutoDepthStencil = TRUE;
m_d3dpp.AutoDepthStencilFormat = pModeInfo->DepthStencilFormat;
m_d3dpp.hDeviceWindow = (HWND)m_hWnd;
if( !m_bFullScreen )
{
m_d3dpp.BackBufferWidth = m_width; // m_rcWindowClient.right - m_rcWindowClient.left;
m_d3dpp.BackBufferHeight = m_height; //m_rcWindowClient.bottom - m_rcWindowClient.top;
m_d3dpp.BackBufferFormat = pAdapterInfo->d3ddmDesktop.Format;
}
else
{
#ifndef _DEBUG
//m_d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;//D3DPRESENT_RATE_UNLIMITED;
//m_d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
#endif
m_d3dpp.BackBufferWidth = pModeInfo->Width;
m_d3dpp.BackBufferHeight = pModeInfo->Height;
m_d3dpp.BackBufferFormat = pModeInfo->Format;
}
pModeInfo->dwBehavior &=~(D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_HARDWARE_VERTEXPROCESSING);
if((pModeInfo->dwBehavior & D3DCREATE_PUREDEVICE) == 0)
{
D3DCAPS8 caps;
// Query caps
hr = m_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, pDeviceInfo->DeviceType, &caps);
if((m_d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) != 0)
{
if(D3DSHADER_VERSION_MAJOR(caps.VertexShaderVersion) < 1)
{
pModeInfo->dwBehavior |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
m_bUseSWVP = true;
}
else
{
if (CV_d3d8_forcesoftwarevp)
{
m_bUseSWVP = true;
pModeInfo->dwBehavior |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
else
{
m_bUseSWVP = false;
pModeInfo->dwBehavior |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
}
}
else
{
pModeInfo->dwBehavior |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
m_bUseSWVP = true;
}
}
else
{
pModeInfo->dwBehavior |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
#ifdef _XBOX
pModeInfo->dwBehavior = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE;
#endif
// Allow unlimited frame rate
if (m_bFullScreen)
m_d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
// Create the device
hr = m_pD3D->CreateDevice( m_dwAdapter, pDeviceInfo->DeviceType,
(HWND)m_CurrContext->m_hWnd, pModeInfo->dwBehavior, &m_d3dpp,
&m_pd3dDevice );
if( SUCCEEDED(hr) )
{
// When moving from fullscreen to windowed mode, it is important to
// adjust the window size after recreating the device rather than
// beforehand to ensure that you get the window size you want. For
// example, when switching from 640x480 fullscreen to windowed with
// a 1000x600 window on a 1024x768 desktop, it is impossible to set
// the window size to 1000x600 until after the display mode has
// changed to 1024x768, because windows cannot be larger than the
// desktop.
#ifndef _XBOX
m_pd3dDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, m_bUseSWVP);
if( !m_bFullScreen )
{
SetWindowPos( m_hWnd, HWND_NOTOPMOST,
m_rcWindowBounds.left, m_rcWindowBounds.top,
( m_rcWindowBounds.right - m_rcWindowBounds.left ),
( m_rcWindowBounds.bottom - m_rcWindowBounds.top ),
SWP_SHOWWINDOW );
}
#endif
// Store device Caps
m_pd3dDevice->GetDeviceCaps( &m_d3dCaps );
m_dwCreateFlags = pModeInfo->dwBehavior;
if (m_d3dCaps.MaxSimultaneousTextures == 2 && D3DSHADER_VERSION_MAJOR(m_d3dCaps.VertexShaderVersion) == 1 && D3DSHADER_VERSION_MINOR(m_d3dCaps.VertexShaderVersion) == 1)
m_Features |= RFT_HW_GF2;
if (m_d3dCaps.MaxSimultaneousTextures == 4 && D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) == 1 && D3DSHADER_VERSION_MINOR(m_d3dCaps.PixelShaderVersion) == 1 && m_d3dCaps.MaxTextureBlendStages == 8)
m_Features |= RFT_HW_GF3 | RFT_HW_TS | RFT_HW_VS;
else
if (m_d3dCaps.MaxSimultaneousTextures == 4 && D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) == 1 && D3DSHADER_VERSION_MINOR(m_d3dCaps.PixelShaderVersion) >= 1 && m_d3dCaps.MaxTextureBlendStages >= 8)
m_Features |= RFT_HW_GF3 | RFT_HW_TS | RFT_HW_VS;
else
if (m_d3dCaps.MaxSimultaneousTextures > 4 && D3DSHADER_VERSION_MAJOR(m_d3dCaps.PixelShaderVersion) == 1 && D3DSHADER_VERSION_MINOR(m_d3dCaps.PixelShaderVersion) >= 3 && m_d3dCaps.MaxTextureBlendStages >= 8)
m_Features |= RFT_HW_RADEON8500 | RFT_HW_TS | RFT_HW_VS;
#ifdef _XBOX
m_Features |= RFT_HW_GF3 | RFT_HW_TS | RFT_HW_VS;
#endif
// Store device description
if( pDeviceInfo->DeviceType == D3DDEVTYPE_REF )
lstrcpy( m_strDeviceStats, TEXT("REF") );
else
if( pDeviceInfo->DeviceType == D3DDEVTYPE_HAL )
lstrcpy( m_strDeviceStats, TEXT("HAL") );
else
if( pDeviceInfo->DeviceType == D3DDEVTYPE_SW )
lstrcpy( m_strDeviceStats, TEXT("SW") );
if( (pModeInfo->dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING) && (pModeInfo->dwBehavior & D3DCREATE_PUREDEVICE) )
{
if( pDeviceInfo->DeviceType == D3DDEVTYPE_HAL )
lstrcat( m_strDeviceStats, TEXT(" (pure hw vp)") );
else
lstrcat( m_strDeviceStats, TEXT(" (simulated pure hw vp)") );
}
else
if( pModeInfo->dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING )
{
if( pDeviceInfo->DeviceType == D3DDEVTYPE_HAL )
lstrcat( m_strDeviceStats, TEXT(" (hw vp)") );
else
lstrcat( m_strDeviceStats, TEXT(" (simulated hw vp)") );
}
else
if( pModeInfo->dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING )
{
if( pDeviceInfo->DeviceType == D3DDEVTYPE_HAL )
lstrcat( m_strDeviceStats, TEXT(" (mixed vp)") );
else
lstrcat( m_strDeviceStats, TEXT(" (simulated mixed vp)") );
}
else
if( pModeInfo->dwBehavior & D3DCREATE_SOFTWARE_VERTEXPROCESSING )
{
lstrcat( m_strDeviceStats, TEXT(" (sw vp)") );
}
if( pDeviceInfo->DeviceType == D3DDEVTYPE_HAL )
{
lstrcat( m_strDeviceStats, TEXT(": ") );
lstrcat( m_strDeviceStats, pAdapterInfo->d3dAdapterIdentifier.Description );
}
// Store render target surface desc
m_pd3dDevice->GetDepthStencilSurface( &m_pZBuffer );
m_pZBuffer->GetDesc( &m_d3dsdZBuffer );
CD3D8TexMan *pTM = (CD3D8TexMan *)m_TexMan;
m_pd3dDevice->CreateDepthStencilSurface(512, 512, m_d3dsdZBuffer.Format, D3DMULTISAMPLE_NONE, &pTM->m_pZSurf);
if (m_d3dsdZBuffer.Format == D3DFMT_D16_LOCKABLE)
m_Features |= RFT_ZLOCKABLE;
#ifdef _XBOX
m_Features |= RFT_ZLOCKABLE;
#endif
m_pd3dDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer );
// Initialize the app's device-dependent objects
hr = InitDeviceObjects();
if( SUCCEEDED(hr) )
{
hr = RestoreDeviceObjects();
if( SUCCEEDED(hr) )
{
m_bActive = TRUE;
return S_OK;
}
}
}
return hr;
}
static int sCDFromFormat(D3DFORMAT fmt)
{
switch (fmt)
{
case D3DFMT_X8R8G8B8:
return 24;
case D3DFMT_A8R8G8B8:
return 32;
case D3DFMT_R5G6B5:
return 16;
#ifdef _XBOX
case D3DFMT_LIN_X8R8G8B8:
return 24;
case D3DFMT_LIN_X1R5G5B5:
case D3DFMT_LIN_R5G6B5:
return 16;
case D3DFMT_LIN_A8R8G8B8:
return 32;
#endif
}
return -1;
}
bool CD3D8Renderer::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_d3d8_texturebits)
m_TextureBits = CV_d3d8_texturebits;
else
m_TextureBits = CRenderer::m_cbpp;
}
else
{
if (CV_d3d8_texturebits)
m_TextureBits = CV_d3d8_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 CD3D8Renderer::SetRes(void)
{
HRESULT hr;
guardnw(CD3D8Renderer::SetRes);
UnSetRes();
// Create the Direct3D object
m_pD3D = Direct3DCreate8( D3D_SDK_VERSION );
if( m_pD3D == NULL )
return Error("Direct3D8 not installed", 0);
// Build a list of Direct3D adapters, modes and devices. The
// ConfirmDevice() callback is used to confirm that only devices that
// meet the app's requirements are considered.
if( FAILED( hr = BuildDevicesList() ) )
{
if (h == D3DAPPERR_NOWINDOWABLEDEVICES)
{
if (!m_bFullScreen)
return Error("Couldn't build list of D3D devices", h);
}
else
return Error("Couldn't build list of D3D devices", h);
}
char drv[64];
strcpy(drv, CV_d3d8_device->GetString());
int numAdap;
bool bAuto = false;
int numDev = 0;
if (!strnicmp(drv, "auto", 4))
bAuto = true;
else
if (!strnicmp(drv, "primary", 7))
numAdap = 0;
else
if (!strnicmp(drv, "3dfx", 4) || !strnicmp(drv, "second", 6) || !strnicmp(drv, "Voodoo", 6))
numAdap = 1;
else
if (drv[0] && isdigit(drv[0]))
numAdap = atol(drv);
else
{
iLog->Log ( "Unknown device name '%s' (use AutoDetect)\n", drv);
iLog->Log ( "Only 'Auto', 'Primary', '3dfx' or digital number of device are supported\n");
bAuto = true;
}
if (numDev < 0)
numDev = 0;
m_dwAdapter = -1;
bool bAllowSoft = false;
trysoft:
if (bAuto)
{
for( int a=0; a<m_dwNumAdapters; a++ )
{
if (IsSuitableDevice(a, bAllowSoft))
break;
}
}
else
{
IsSuitableDevice(numDev, bAllowSoft);
}
if (m_dwAdapter < 0)
{
if (!bAllowSoft)
{
if (CV_d3d8_allowsoftware)
{
bAllowSoft = true;
goto trysoft;
}
}
return Error("Can't find any suitable D3D device\n", 0);
}
int a = m_dwAdapter;
int d = m_Adapters[a].dwCurrentDevice;
// Display a warning message
if( !m_bHALExists )
iLog->Log ( "No hardware-accelerated Direct3D devices were found.\n");
else
if( !m_bHALIsSampleCompatible )
iLog->Log ( "FarCry requires functionality that is not available on your Direct3D hardware accelerator.\n");
else
if( !m_bHALIsWindowedCompatible )
iLog->Log ( "Your Direct3D hardware accelerator cannot render into a window.\n");
else
if( !m_bHALIsDesktopCompatible )
iLog->Log ( "Your Direct3D hardware accelerator cannot render into a window with the current desktop display settings.\n");
// The focus window can be a specified to be a different window than the
// device window. If not, use the device window as the focus window.
if( m_CurrContext == NULL )
CreateContext(m_hWnd);
#ifndef _XBOX
// Save window properties
GetWindowRect( m_hWnd, &m_rcWindowBounds );
GetClientRect( m_hWnd, &m_rcWindowClient );
#endif
// Initialize the 3D environment for the app
if( FAILED( hr = Initialize3DEnvironment() ) )
return Error("Couldn't initialize 3D environment", h);
if (FAILED (hr = D3DXCreateMatrixStack(0, &m_matView)))
return false;
if (FAILED (hr = D3DXCreateMatrixStack(0, &m_matProj)))
return false;
D3DXMatrixIdentity(&m_TexMatrix[0]);
D3DXMatrixIdentity(&m_TexMatrix[1]);
D3DXMatrixIdentity(&m_TexMatrix[2]);
D3DXMatrixIdentity(&m_TexMatrix[3]);
hr = m_pd3dDevice->CreateVertexBuffer(300 * STRIDE_TR_D_1T, D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFVF_TRVERTEX_D_1T, D3DPOOL_DEFAULT, &m_pQuadVB);
if (FAILED(hr))
return false;
hr = m_pd3dDevice->CreateVertexBuffer(8 * STRIDE_D, D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, D3DFVF_VERTEX_D, D3DPOOL_DEFAULT, &m_pLineVB);
if (FAILED(hr))
return false;
memset(&m_Material, 0, sizeof(m_Material));
for (int i=0; i<16; i++)
{
D3DLIGHT8 *l = &m_Lights[i];
memset(l, 0, sizeof(D3DLIGHT8));
l->Type = D3DLIGHT_DIRECTIONAL;
l->Attenuation0 = 1.0f;
}
return true;
unguardnw;
}
bool CD3D8Renderer::ChangeDisplay(unsigned int width,unsigned int height,unsigned int cbpp)
{
return false;
}
void CD3D8Renderer::ChangeViewport(unsigned int x,unsigned int y,unsigned int width,unsigned int height)
{
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;
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);
}
}
float glLodCorrection;
void CD3D8Renderer::BeginFrame()
{
//////////////////////////////////////////////////////////////////////
// Set up everything so we can start rendering
//////////////////////////////////////////////////////////////////////
HRESULT hReturn;
ASSERT(m_pd3dDevice);
if (m_SceneRecurseCount++)
return;
if (CV_r_vsync != m_VSync)
{
m_VSync = CV_r_vsync;
EnableVSync(m_VSync?true:false);
}
if (CV_r_reloadshaders)
{
gcEf.mfReloadAllShaders(CV_r_reloadshaders);
CV_r_reloadshaders = 0;
}
//////////////////////////////////////////////////////////////////////
// Build the matrices
//////////////////////////////////////////////////////////////////////
// Set the world matrix to an indetity matrix
//D3DXMatrixIdentity(&matWorld);
m_matView->LoadIdentity();
m_pd3dDevice->SetTransform(D3DTS_WORLD, (D3DMATRIX *)m_matView->GetTop());
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);
gcEf.mfBeginFrame();
if (CV_r_PolygonMode!=m_polygon_mode)
SetPolygonMode(CV_r_PolygonMode);
m_bWasCleared = false;
// EF_ClearBuffer(false, NULL);
//////////////////////////////////////////////////////////////////////
// Begin the scene
//////////////////////////////////////////////////////////////////////
hReturn = m_pd3dDevice->BeginScene();
if (FAILED(hReturn))
return;
{ // Calculate lod correction if more than 100 000 poly used
float k = ((float)m_nPolygons-100000.f)/10000.f;
float d = 0.01f;
if(fabs(k)<1)
d/=10;
if(k<-0.1f)
glLodCorrection-=d;
if(k> 0.1f)
glLodCorrection+=d;
if(glLodCorrection<0)
glLodCorrection=0;
}
SetMaterialColor(1,1,1,1);
if (strcmp(CV_d3d8_texturefilter->GetString(), m_TexMan->m_CurTexFilter) || CV_r_texture_anisotropic_level != m_TexMan->m_CurAnisotropic)
m_TexMan->SetFilter(CV_d3d8_texturefilter->GetString());
if (CV_r_log && !m_LogFile)
{
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)
{
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");
}
ResetToDefault();
m_MatDepth = 0;
m_nPolygons = 0;
m_nFrameID++;
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;
}
}
tm->SetUse(0);
m_RP.m_CurTempMeshes = tm;
}
void CD3D8Renderer::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;
}
m_SceneRecurseCount--;
if (m_SceneRecurseCount)
return;
if (CV_r_measureoverdraw)
{
/*byte *buf = new byte [m_width*m_height];
glReadPixels(0, 0, m_width, m_height, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf);
int size = m_width * m_height;
int acc = 0;
for (int i=0; i<size; i++)
{
acc += buf[i];
}
delete [] buf;
m_RP.m_PS.m_fOverdraw += (float)acc; */
}
if (iConsole && iConsole->GetFont())
{
CRenderer *crend=gRenDev;
CXFont *cf=iConsole->GetFont();
if (CV_r_measureoverdraw)
crend->WriteXY(cf,550,75, 0.5f,1,1,1,1,1,"Overdraw=%0.3f",m_RP.m_PS.m_fOverdraw / (float)(m_width * m_height));
switch (CV_r_stats)
{
case 1:
crend->WriteXY(cf,550,40, 0.5f,1,1,1,1,1, "Shaders=%d",m_RP.m_PS.m_NumRendShaders);
crend->WriteXY(cf,550,55, 0.5f,1,1,1,1,1, "VPrograms=%d",m_RP.m_PS.m_NumVShaders);
crend->WriteXY(cf,550,70, 0.5f,1,1,1,1,1, "RCombiners=%d",m_RP.m_PS.m_NumRCombiners);
crend->WriteXY(cf,550,85, 0.5f,1,1,1,1,1, "PShaders=%d",m_RP.m_PS.m_NumPShaders);
crend->WriteXY(cf,550,100, 0.5f,1,1,1,1,1, "CGVShaders=%d",m_RP.m_PS.m_NumCGVShaders);
crend->WriteXY(cf,550,115, 0.5f,1,1,1,1,1, "CGPShaders=%d",m_RP.m_PS.m_NumCGPShaders);
crend->WriteXY(cf,550,140, 0.5f,1,1,1,1,1,"Textures=%d",m_RP.m_PS.m_NumTextures);
crend->WriteXY(cf,550,155, 0.5f,1,1,1,1,1,"TexturesSize=%.03f Kb",m_RP.m_PS.m_TexturesSize/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<gcEf.m_ShaderResources.Num(); i++)
{
SRenderShaderResources *pSR = gcEf.m_ShaderResources[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++)
{
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++)
{
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;
n = 0;
CLeafBuffer *pLB = CLeafBuffer::m_RootGlobal.m_NextGlobal;
while (pLB != &CLeafBuffer::m_RootGlobal)
{
n++;
nSize += pLB->Size(0);
pLB = pLB->m_NextGlobal;
}
crend->WriteXY(cf,550,280, 0.5f,1,1,1,1,1,"Mesh: %d, size=%0.3fMb",n,(float)nSize/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,295, 0.5f,1,1,1,1,1,"Rend. Elements: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
nSize = 0;
n = 0;
for (i=0; i<CTexMan::m_Textures.Num(); i++)
{
STexPic *tp = CTexMan::m_Textures[i];
if (!tp)
continue;
n++;
nSize += tp->Size(0);
}
crend->WriteXY(cf,550,310, 0.5f,1,1,1,1,1,"Textures: %d, size=%0.3fMb",n,(float)nSize/1024.0f/1024.0f);
}
break;
}
//crend->WriteXY(cf,55,200, 0.5f,1,1,1,1,1,"Time ftol=%0.4f, Time fistp=%0.4f, Time QRound=%0.4f", timeFtoL, timeFtoI, timeQRound);
}
m_TexMan->Update();
if (CV_r_profileshaders)
EF_PrintProfileInfo();
// 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)
{
///glEnable(GL_BLEND);
EnableBlend(true);
///glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
SetBlendMode(R_BLEND_MODE__SRC_ALPHA__ONE_MINUS_SRC_ALPHA);
///glDepthMask(GL_FALSE);
EnableDepthWrites(false);
}
switch(rBBox.nPrimType)
{
case DPRIM_LINE:
///glDisable(GL_TEXTURE_2D);
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
m_pd3dDevice->SetTexture( 0, 0 );
///glBegin(GL_LINE_LOOP);
///glVertex3f(rBBox.vMins.x,rBBox.vMins.y,rBBox.vMins.z);
///glVertex3f(rBBox.vMaxs.x,rBBox.vMaxs.y,rBBox.vMaxs.z);
///glEnd();
SPipeVertex_D * pVerts;
#ifdef _XBOX
HRESULT hr = m_pLineVB->Lock(0, 0, (BYTE **) &pVerts, 0);
#else
HRESULT hr = m_pLineVB->Lock(0, 0, (BYTE **) &pVerts, D3DLOCK_DISCARD);
#endif
DWORD dwCol = (DWORD(rBBox.fColor[0] * 255) << 24) |
(DWORD(rBBox.fColor[1] * 255) << 16) |
(DWORD(rBBox.fColor[2] * 255) << 8) |
(DWORD(rBBox.fColor[3] * 255));
if(hr==S_OK)
{
pVerts[0].xyz.x = rBBox.vMins.x;
pVerts[0].xyz.y = rBBox.vMins.y;
pVerts[0].xyz.z = rBBox.vMins.z;
pVerts[0].color.dcolor = dwCol;
pVerts[1].xyz.x = rBBox.vMaxs.x;
pVerts[1].xyz.y = rBBox.vMaxs.y;
pVerts[1].xyz.z = rBBox.vMaxs.z;
pVerts[1].color.dcolor = dwCol;
m_pLineVB->Unlock();
m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX_D );
m_pd3dDevice->SetStreamSource(0, m_pLineVB, STRIDE_D);
hr = m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, 0, 1);
}
///glEnable(GL_TEXTURE_2D);
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
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)
{
///glDisable(GL_BLEND);
EnableBlend(false);
///glDepthMask(GL_TRUE);
EnableDepthWrites(true);
}
}
m_arrBoxesToDraw.clear();
// print shadow volume stats
ICVar *pVar = iConsole->GetCVar("e_stencil_shadows");
if(pVar && pVar->GetIVal()==3)
CRETriMeshShadow::PrintStats();
// End the scene
HRESULT hReturn = m_pd3dDevice->EndScene();
if (FAILED(hReturn))
{
return;
}
// Flip the back buffer to the front
m_pd3dDevice->Present(NULL, NULL, NULL, NULL);
if (CV_r_GetScreenShot)
{
ScreenShot();
CV_r_GetScreenShot = 0;
}
}
void CD3D8Renderer::Print(CXFont *currfont,float x, float y, const char *buf,float xscale,float yscale,float r,float g,float b,float a)
{
// Check for the presence of a D3D device
ASSERT(m_pd3dDevice);
if (iConsole && iConsole->GetFont())
{
CXFont *cf=iConsole->GetFont();
IFFont *pFont = iSystem->GetICryFont()->GetFont("Default");
if (pFont)
{
pFont->SetColor(cry::color4f(r,g,b,a));
pFont->SetEffect("buttonfocus");
pFont->SetSameSize(true);
pFont->SetCharWidthScale(2.0f/3.0f);
pFont->SetSize(vector2f(12,16));
pFont->DrawString(x, y, buf);
}
}
}
void CD3D8Renderer::PrintToScreen(float x, float y, float size, const char *buf)
{
Print(iConsole->GetFont(),0,0,buf,size*0.5f/8, size*1.f/8, 1,1,1,1);
}
void CD3D8Renderer::WriteXY(CXFont *currfont, int x, int y, float xscale, float yscale, float r, float g, float b, float a, const char *message, ...)
{
//////////////////////////////////////////////////////////////////////
// Write a string to the screen
//////////////////////////////////////////////////////////////////////
va_list ArgList;
char szStringBuffer[4096];
// Check for the presence of a D3D device
ASSERT(m_pd3dDevice);
// Format the string
va_start(ArgList, message);
vsprintf(szStringBuffer, message, ArgList);
va_end(ArgList);
Print(currfont,(float)(x),(float)(y),szStringBuffer,xscale,yscale,r,g,b,a);
}
void CD3D8Renderer::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)
{
//////////////////////////////////////////////////////////////////////
// Draw a textured quad, texture is assumed to be in video memory
//////////////////////////////////////////////////////////////////////
// Check for the presence of a D3D device
assert(m_pd3dDevice);
assert(m_SceneRecurseCount);
DWORD col = D3DRGBA(r,g,b,a);
xpos = (float)(int)ScaleCoordX(xpos); w = (float)(int)ScaleCoordX(w);
ypos = (float)(int)ScaleCoordY(ypos); h = (float)(int)ScaleCoordY(h);
VOID *pVertices;
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);
EnableDepthTest(0);
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.
#ifdef _XBOX
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, 0);
#else
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, D3DLOCK_DISCARD);
#endif
#ifdef _XBOX
SPipeTRVertex_D_1T *vQuad = (SPipeTRVertex_D_1T *)pVertices;
#else
SPipeTRVertex_D_1T *vQuad = (SPipeTRVertex_D_1T *)pVertices;
#endif
// Now that we have write access to the buffer, we can copy our vertices
// into it
// Define the quad
vQuad[0].dvSX = fx;
vQuad[0].dvSY = fy;
vQuad[0].dvSZ = 1.0f;
vQuad[0].dvRHW = 1.0f;
vQuad[0].dcColor = col;
vQuad[0].dvTU[0] = s0;
vQuad[0].dvTU[1] = 1.0f-t0;
vQuad[1].dvSX = fx + fw;
vQuad[1].dvSY = fy;
vQuad[1].dvSZ = 1.0f;
vQuad[1].dvRHW = 1.0f;
vQuad[1].dcColor = col;
vQuad[1].dvTU[0] = s1;
vQuad[1].dvTU[1] = 1.0f-t0;
vQuad[2].dvSX = fx + fw;
vQuad[2].dvSY = fy + fh;
vQuad[2].dvSZ = 1.0f;
vQuad[2].dvRHW = 1.0f;
vQuad[2].dcColor = col;
vQuad[2].dvTU[0] = s1;
vQuad[2].dvTU[1] = 1.0f-t1;
vQuad[3].dvSX = fx;
vQuad[3].dvSY = fy + fh;
vQuad[3].dvSZ = 1.0f;
vQuad[3].dvRHW = 1.0f;
vQuad[3].dcColor = col;
vQuad[3].dvTU[0] = s0;
vQuad[3].dvTU[1] = 1.0f-t1;
// We are finished with accessing the vertex buffer
m_pQuadVB->Unlock();
// Activate the image texture
SetTexture(textureid);
//if (pID3DTexture)
// m_pd3dDevice->SetTexture(0, pID3DTexture);
// Bind our vertex as the first data stream of our device
#ifdef _XBOX
m_pd3dDevice->SetStreamSource(0, m_pQuadVB, STRIDE_TR_D_1T);
// Set the vertex shader to the FVF fixed function shader
m_pd3dDevice->SetVertexShader(D3DFVF_TRVERTEX_D_1T);
#else
m_pd3dDevice->SetStreamSource(0, m_pQuadVB, STRIDE_TR_D_1T);
// Set the vertex shader to the FVF fixed function shader
m_pd3dDevice->SetVertexShader(D3DFVF_TRVERTEX_D_1T);
#endif
// Render the two triangles from the data stream
hReturn = m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
if (FAILED(hReturn))
{
ASSERT(hReturn);
return;
}
EnableDepthTest(1);
}
void CD3D8Renderer::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)
{
//////////////////////////////////////////////////////////////////////
// Draw a textured quad, texture is assumed to be in video memory
//////////////////////////////////////////////////////////////////////
// Check for the presence of a D3D device
assert(m_pd3dDevice);
assert(m_SceneRecurseCount);
xpos = (float)(int)ScaleCoordX(xpos); w = (float)(int)ScaleCoordX(w);
ypos = (float)(int)ScaleCoordY(ypos); h = (float)(int)ScaleCoordY(h);
VOID *pVertices;
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);
EnableDepthTest(0);
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.
#ifdef _XBOX
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, 0);
#else
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, D3DLOCK_DISCARD);
#endif
#ifdef _XBOX
SPipeTRVertex_D_1T *vQuad = (SPipeTRVertex_D_1T *)pVertices;
#else
SPipeTRVertex_D_1T *vQuad = (SPipeTRVertex_D_1T *)pVertices;
#endif
if (a<0)
{
// always blend over the screen
EnableBlend(true);
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
a = 1.0f;
}
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].dvSX = xpos;
vQuad[0].dvSY = ypos;
vQuad[0].dvSZ = 1.0f;
vQuad[0].dvRHW = 1.0f;
vQuad[0].dcColor = col;
vQuad[0].dvTU[0] = s0;
vQuad[0].dvTU[1] = 1.0f-t0;
vQuad[1].dvSX = xpos + w;
vQuad[1].dvSY = ypos;
vQuad[1].dvSZ = 1.0f;
vQuad[1].dvRHW = 1.0f;
vQuad[1].dcColor = col;
vQuad[1].dvTU[0] = s1;
vQuad[1].dvTU[1] = 1.0f-t0;
vQuad[2].dvSX = xpos + w;
vQuad[2].dvSY = ypos + h;
vQuad[2].dvSZ = 1.0f;
vQuad[2].dvRHW = 1.0f;
vQuad[2].dcColor = col;
vQuad[2].dvTU[0] = s1;
vQuad[2].dvTU[1] = 1.0f-t1;
vQuad[3].dvSX = xpos;
vQuad[3].dvSY = ypos + h;
vQuad[3].dvSZ = 1.0f;
vQuad[3].dvRHW = 1.0f;
vQuad[3].dcColor = col;
vQuad[3].dvTU[0] = s0;
vQuad[3].dvTU[1] = 1.0f-t1;
// We are finished with accessing the vertex buffer
m_pQuadVB->Unlock();
// 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
#ifdef _XBOX
m_pd3dDevice->SetStreamSource(0, m_pQuadVB, STRIDE_TR_D_1T);
// Set the vertex shader to the FVF fixed function shader
m_pd3dDevice->SetVertexShader(D3DFVF_TRVERTEX_D_1T);
#else
m_pd3dDevice->SetStreamSource(0, m_pQuadVB, STRIDE_TR_D_1T);
// Set the vertex shader to the FVF fixed function shader
m_pd3dDevice->SetVertexShader(D3DFVF_TRVERTEX_D_1T);
#endif
// Render the two triangles from the data stream
hReturn = m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
if (FAILED(hReturn))
{
ASSERT(hReturn);
return;
}
EnableDepthTest(1);
}
void CD3D8Renderer::Draw2dLine(float x1, float y1, float x2, float y2)
{
SetCullMode(R_CULL_DISABLE);
EnableDepthTest(0);
EnableTMU(false);
float x1pos=(float)(int)ScaleCoordX(x1);
float y1pos=(float)(int)ScaleCoordY(y1);
float x2pos=(float)(int)ScaleCoordX(x2);
float y2pos=(float)(int)ScaleCoordY(y2);
VOID *pVertices;
// 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.
#ifdef _XBOX
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, 0);
#else
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, D3DLOCK_DISCARD);
#endif
SPipeTRVertex_D_1T *vQuad = (SPipeTRVertex_D_1T *)pVertices;
// Define the line
vQuad[0].dvSX = x1pos;
vQuad[0].dvSY = y1pos;
vQuad[0].dvSZ = 1.0f;
vQuad[0].dvRHW = 1.0f;
vQuad[0].dcColor = 0;
vQuad[1].dvSX = x2pos;
vQuad[1].dvSY = y2pos;
vQuad[1].dvSZ = 1.0f;
vQuad[1].dvRHW = 1.0f;
vQuad[1].dcColor = 0;
// We are finished with accessing the vertex buffer
m_pQuadVB->Unlock();
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pQuadVB, STRIDE_TR_D_1T);
// Set the vertex shader to the FVF fixed function shader
m_pd3dDevice->SetVertexShader(D3DFVF_TRVERTEX_D_1T);
// Render the two triangles from the data stream
hr = m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, 0, 1);
if (FAILED(hr))
{
ASSERT(hr);
return;
}
EnableTMU(true);
}
void CD3D8Renderer::DrawPoints(Vec3d v[], int nump, CFColor& col, int flags)
{
}
void CD3D8Renderer::DrawLines(Vec3d v[], int nump, CFColor& col, int flags)
{
}
void CD3D8Renderer::DrawLine(const Vec3d & vPos1, const Vec3d & vPos2)
{
float fX1 = (float)(int)ScaleCoordX(vPos1.x);
float fY1 = (float)(int)ScaleCoordY(vPos1.y);
float fX2 = (float)(int)ScaleCoordX(vPos2.x);
float fY2 = (float)(int)ScaleCoordY(vPos2.y);
SetCullMode(R_CULL_DISABLE);
EnableDepthTest(0);
EnableTMU(false);
VOID *pVertices;
// 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.
#ifdef _XBOX
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, 0);
#else
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, D3DLOCK_DISCARD);
#endif
SPipeTRVertex_D_1T *vQuad = (SPipeTRVertex_D_1T *)pVertices;
// Define the line
vQuad[0].dvSX = fX1;
vQuad[0].dvSY = fY1;
vQuad[0].dvSZ = vPos1.z;
vQuad[0].dvRHW = 1.0f;
vQuad[0].dcColor = 0xffffffff;
vQuad[1].dvSX = fX2;
vQuad[1].dvSY = fY2;
vQuad[1].dvSZ = vPos2.z;
vQuad[1].dvRHW = 1.0f;
vQuad[1].dcColor = 0xffffffff;
// We are finished with accessing the vertex buffer
m_pQuadVB->Unlock();
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pQuadVB, STRIDE_TR_D_1T);
// Set the vertex shader to the FVF fixed function shader
m_pd3dDevice->SetVertexShader(D3DFVF_TRVERTEX_D_1T);
// Render the two triangles from the data stream
m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TFACTOR );
hr = m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, 0, 1);
m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE );
if (FAILED(hr))
{
ASSERT(hr);
return;
}
EnableTMU(true);
}
void CD3D8Renderer::DrawLineColor(const Vec3d & vPos1, const CFColor & vColor1, const Vec3d & vPos2, const CFColor & vColor2)
{
float fX1 = (float)(int)ScaleCoordX(vPos1.x);
float fY1 = (float)(int)ScaleCoordY(vPos1.y);
float fX2 = (float)(int)ScaleCoordX(vPos2.x);
float fY2 = (float)(int)ScaleCoordY(vPos2.y);
EnableTMU(false);
VOID *pVertices;
// 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.
#ifdef _XBOX
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, 0);
#else
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &pVertices, D3DLOCK_DISCARD);
#endif
SPipeTRVertex_D_1T *vQuad = (SPipeTRVertex_D_1T *)pVertices;
DWORD col1 = D3DRGBA(vColor1[0],vColor1[1],vColor1[2],1.0f);
DWORD col2 = D3DRGBA(vColor2[0],vColor2[1],vColor2[2],1.0f);
// Define the line
vQuad[0].dvSX = fX1;
vQuad[0].dvSY = fY1;
vQuad[0].dvSZ = vPos1.z;
vQuad[0].dvRHW = 1.0f;
vQuad[0].dcColor = col1;
vQuad[1].dvSX = fX2;
vQuad[1].dvSY = fY2;
vQuad[1].dvSZ = vPos2.z;
vQuad[1].dvRHW = 1.0f;
vQuad[1].dcColor = col2;
// We are finished with accessing the vertex buffer
m_pQuadVB->Unlock();
// Bind our vertex as the first data stream of our device
m_pd3dDevice->SetStreamSource(0, m_pQuadVB, STRIDE_TR_D_1T);
// Set the vertex shader to the FVF fixed function shader
m_pd3dDevice->SetVertexShader(D3DFVF_TRVERTEX_D_1T);
// Render the two triangles from the data stream
hr = m_pd3dDevice->DrawPrimitive(D3DPT_LINELIST, 0, 1);
if (FAILED(hr))
{
ASSERT(hr);
return;
}
EnableTMU(true);
}
//*********************************************************************
void CD3D8Renderer::GetModelViewMatrix(float * mat)
{
memcpy(mat, (D3DXMATRIX *)m_matView->GetTop(), 4*4*sizeof(float));
}
void CD3D8Renderer::GetProjectionMatrix(float * mat)
{
memcpy(mat, (D3DXMATRIX *)m_matProj->GetTop(), 4*4*sizeof(float));
}
///////////////////////////////////////////
void CD3D8Renderer::PushMatrix()
{
ASSERT(m_pd3dDevice);
EF_PushMatrix();
}
///////////////////////////////////////////
void CD3D8Renderer::PopMatrix()
{
ASSERT(m_pd3dDevice);
EF_PopMatrix();
}
///////////////////////////////////////////
void CD3D8Renderer::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 CD3D8Renderer::LoadMatrix(const Matrix *src)
{
if(src)
m_matView->LoadMatrix((D3DXMATRIX *)src);
else
m_matView->LoadIdentity();
m_bInvertedMatrix = false;
}
void CD3D8Renderer::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 CD3D8Renderer::MultMatrix(float * mat)
{
m_matView->MultMatrixLocal((D3DXMATRIX *)mat);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m_matView->GetTop());
m_bInvertedMatrix = false;
}
///////////////////////////////////////////
void CD3D8Renderer::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 CD3D8Renderer::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 CD3D8Renderer::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 CD3D8Renderer::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);
}
void CD3D8Renderer::SetCamera(const CCamera &cam)
{
ASSERT(m_pd3dDevice);
Matrix mat = cam.GetMatrix();
D3DXMATRIX *m = m_matView->GetTop();
m_matView->LoadMatrix((D3DXMATRIX *)&mat);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
D3DXMatrixInverse(&m_matViewInv, NULL, m);
m = m_matProj->GetTop();
D3DXMatrixPerspectiveFovRH(m, cam.GetFov()*cam.GetProjRatio(), 1.0f/cam.GetProjRatio(), cam.GetZMin(), cam.GetZMax());
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
m_bInvertedMatrix = false;
m_cam = cam;
}
void CD3D8Renderer::SetViewport(int x, int y, int width, int height)
{
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);
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);
}
void CD3D8Renderer::SetScissor(int x, int y, int width, int height)
{
/*D3DCLIPSTATUS8 Clip;
Clip.ClipUnion = D3DCS_BOTTOM | D3DCS_TOP | D3DCS_LEFT | D3DCS_RIGHT;
Clip.ClipIntersection = Clip.ClipUnion;
if (FAILED(h=m_pd3dDevice->SetClipStatus(&Clip)))
{
Error("SetClipStatus failed\n",h);
return;
}*/
}
void CD3D8Renderer::Draw3dBBox(const Vec3d &mins,const Vec3d &maxs, int nPrimType)
{
Draw3dPrim (mins, maxs, nPrimType);
}
void CD3D8Renderer::Draw3dPrim(const Vec3d &mins,const Vec3d &maxs, int nPrimType, const float* fRGBA)
{
BBoxInfo info;
info.vMins = mins;
info.vMaxs = maxs;
info.nPrimType = nPrimType;
//glGetFloatv(GL_CURRENT_COLOR, (float*)info.fColor);
if (fRGBA)
{
for (int i = 0;i < 4; ++i)
info.fColor[i] = fRGBA[i];
}
else
{
for (int i = 0;i < 4; ++i)
info.fColor[i] = 1.0f;
}
m_arrBoxesToDraw.push_back(info);
}
/*
void CD3D8Renderer::Draw3dBBox(const Vec3d &mins,const Vec3d &maxs, int nPrimType)
{
//////////////////////////////////////////////////////////////////////
// Draw an AABB in wireframe mode
//
// TODO: Box creation
//////////////////////////////////////////////////////////////////////
//assert(!bDrawLine); // draw line is not supported in dx
D3DXMATRIX *m = m_matView->GetTop();
ID3DXMesh *pID3DBoxMesh = NULL;
ASSERT(m_pd3dDevice);
// Create the box
D3DXCreateBox(m_pd3dDevice, 10, 10, 10, &pID3DBoxMesh, NULL);
// Switch into wireframe mode
//m_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
// Render it
pID3DBoxMesh->DrawSubset(0);
// Switch out of wireframe mode
//m_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
// Release the mesh
DX_RELEASE(pID3DBoxMesh)
}
*/
void CD3D8Renderer::SetCullMode(int mode)
{
//////////////////////////////////////////////////////////////////////
// Change the culling mode
//////////////////////////////////////////////////////////////////////
ASSERT(m_pd3dDevice);
switch (mode)
{
case R_CULL_DISABLE:
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
break;
case R_CULL_BACK:
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
break;
case R_CULL_FRONT:
m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
break;
}
}
void CD3D8Renderer::EnableBlend(bool enable)
{
//////////////////////////////////////////////////////////////////////
// Enable or disable blending
//////////////////////////////////////////////////////////////////////
ASSERT(m_pd3dDevice);
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, enable);
}
void CD3D8Renderer::SetBlendMode(int mode)
{
//////////////////////////////////////////////////////////////////////
// Set D3D Blending mode
//////////////////////////////////////////////////////////////////////
ASSERT(m_pd3dDevice);
int src, dst;
switch (mode)
{
case R_BLEND_MODE__ZERO__SRC_COLOR:
src = D3DBLEND_ZERO;
dst = D3DBLEND_SRCCOLOR;
break;
case R_BLEND_MODE__SRC_COLOR__ZERO:
src = D3DBLEND_SRCCOLOR;
dst = D3DBLEND_ZERO;
break;
case R_BLEND_MODE__SRC_COLOR__ONE_MINUS_SRC_COLOR:
src = D3DBLEND_SRCCOLOR;
dst = D3DBLEND_INVSRCCOLOR;
break;
case R_BLEND_MODE__SRC_ALPHA__ONE_MINUS_SRC_ALPHA:
src = D3DBLEND_SRCALPHA;
dst = D3DBLEND_INVSRCALPHA;
break;
case R_BLEND_MODE__SRC_ALPHA__ONE:
src = D3DBLEND_SRCALPHA;
dst = D3DBLEND_ONE;
break;
case R_BLEND_MODE__ONE__ONE:
src = D3DBLEND_ONE;
dst = D3DBLEND_ONE;
break;
case R_BLEND_MODE__DST_COLOR__SRC_COLOR:
src = D3DBLEND_DESTCOLOR;
dst = D3DBLEND_SRCCOLOR;
break;
case R_BLEND_MODE__ZERO__ONE_MINUS_SRC_COLOR:
src = D3DBLEND_ZERO;
dst = D3DBLEND_INVSRCCOLOR;
break;
case R_BLEND_MODE__ONE__ONE_MINUS_SRC_COLOR:
src = D3DBLEND_ONE;
dst = D3DBLEND_INVSRCCOLOR;
break;
case R_BLEND_MODE__ONE__ONE_MINUS_SRC_ALPHA:
src = D3DBLEND_ONE;
dst = D3DBLEND_INVSRCALPHA;
break;
case R_BLEND_MODE__DST_ALPHA__ONE_MINUS_DST_ALPHA:
src = D3DBLEND_DESTALPHA;
dst = D3DBLEND_INVDESTALPHA;
break;
case R_BLEND_MODE__ONE__ZERO:
src = D3DBLEND_ONE;
dst = D3DBLEND_INVDESTALPHA;
break;
case R_BLEND_MODE__ZERO__ZERO:
src = D3DBLEND_ZERO;
dst = D3DBLEND_ZERO;
break;
case R_BLEND_MODE__ADD_SIGNED:
src = D3DBLEND_DESTCOLOR;
dst = D3DBLEND_SRCCOLOR;
EF_SetColorOp(eCO_BLENDDIFFUSEALPHA);
break;
default:
iLog->Log("Unknown blend mode %d\n", mode);
return;
}
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, src);
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, dst);
}
void CD3D8Renderer::SetFog(float density, float fogstart, float fogend, const float *color, int fogmode)
{
//////////////////////////////////////////////////////////////////////
// Configure the fog settings
//////////////////////////////////////////////////////////////////////
D3DCOLOR dwColor;
ASSERT(m_pd3dDevice);
#ifndef _XBOX
m_pd3dDevice->SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
#endif
m_FS.m_FogDensity = density;
m_FS.m_FogStart = fogstart;
m_FS.m_FogEnd = fogend;
m_FS.m_nFogMode = 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(color[0],color[1],color[2],color[3]);
m_pd3dDevice->SetRenderState(D3DRS_FOGCOLOR, dwColor);
//fogstart /= m_cam.GetZMax();
//fogend /= m_cam.GetZMax();
// Fog start and end
m_pd3dDevice->SetRenderState(D3DRS_FOGSTART, *((LPDWORD) (&fogstart)));
m_pd3dDevice->SetRenderState(D3DRS_FOGEND, *((LPDWORD) (&fogend)));
// Fog density
m_pd3dDevice->SetRenderState(D3DRS_FOGDENSITY, *((LPDWORD) (&density)));
// Fog mode
switch (fogmode)
{
case R_FOGMODE_LINEAR:
m_pd3dDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
break;
case R_FOGMODE_EXP2:
m_pd3dDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_EXP2);
break;
default:
// Invalid mode
// Disable
m_pd3dDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
break;
}
}
void CD3D8Renderer::SetFogColor(float * color)
{
m_FS.m_FogColor = CFColor(color);
D3DCOLOR dwColor;
// Fog color
dwColor = D3DRGBA(color[0],color[1],color[2],color[3]);
m_pd3dDevice->SetRenderState(D3DRS_FOGCOLOR, dwColor);
}
bool CD3D8Renderer::EnableFog(bool enable)
{
//////////////////////////////////////////////////////////////////////
// Enable or disable fog
//////////////////////////////////////////////////////////////////////
ASSERT(m_pd3dDevice);
bool bPrevFog = m_FS.m_bEnable; // remember fog value
m_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, enable);
m_FS.m_bEnable = enable;
return bPrevFog;
}
///////////////////////////////////////////
void CD3D8Renderer::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);
}
}
void CD3D8Renderer::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);
}
void CD3D8Renderer::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);
}
void CD3D8Renderer::SetSphericalTexgen()
{
assert(0);
}
void CD3D8Renderer::SetLodBias(float value)
{
//////////////////////////////////////////////////////////////////////
// Set the mip-map LOD bias
//////////////////////////////////////////////////////////////////////
ASSERT(m_pd3dDevice);
value = -value;
m_pd3dDevice->SetTextureStageState(m_TexMan->m_CurStage, D3DTSS_MIPMAPLODBIAS, *((LPDWORD)(&value)));
}
void CD3D8Renderer::SelectTMU(int tnum)
{
m_TexMan->m_CurStage = tnum;
}
void CD3D8Renderer::EnableTMU(bool enable)
{
ASSERT(m_pd3dDevice);
EF_SetColorOp((enable ? eCO_MODULATE : eCO_DISABLE));
if (!enable)
{
m_pd3dDevice->SetTexture(m_TexMan->m_CurStage, NULL);
mStages[m_TexMan->m_CurStage].Texture = NULL;
}
}
void CD3D8Renderer::SetEnviMode(int mode)
{
//////////////////////////////////////////////////////////////////////
// Change the textrue environment operation
//////////////////////////////////////////////////////////////////////
ASSERT(m_pd3dDevice);
switch (mode)
{
case R_MODE_DECAL:
EF_SetColorOp(eCO_DECAL);
break;
case R_MODE_MODULATE:
EF_SetColorOp(eCO_MODULATE);
break;
case R_MODE_BLEND:
EF_SetColorOp(eCO_BLENDTEXTUREALPHA);
break;
case R_MODE_ADD_SIGNED:
EF_SetColorOp(eCO_ADDSIGNED);
break;
default:
// Invalid mode
iLog->Log("Unknown ColorOp %d\n", mode);
break;
}
}
///////////////////////////////////////////
void CD3D8Renderer::CreateIndexBuffer(SVertexStream *dest,const void *src,int indexcount)
{
if (dest->m_VertBuf.m_pPtr)
{
IDirect3DIndexBuffer8 *pIndBuf = (IDirect3DIndexBuffer8 *)dest->m_VertBuf.m_pPtr;
SAFE_RELEASE(pIndBuf);
}
dest->m_nItems = 0;
if (indexcount)
{
IDirect3DIndexBuffer8 *ibuf=NULL;
int size = indexcount*sizeof(ushort);
int flags = D3DUSAGE_WRITEONLY;
D3DPOOL Pool = D3DPOOL_MANAGED;
if (dest->m_bDynamic)
{
flags |= D3DUSAGE_DYNAMIC;
Pool = D3DPOOL_DEFAULT;
}
HRESULT hReturn = m_pd3dDevice->CreateIndexBuffer(size, flags, D3DFMT_INDEX16, Pool, &ibuf);
if (FAILED(hReturn))
{
iLog->Log("Failed to create index buffer\n");
return;
}
dest->m_VertBuf.m_pPtr = ibuf;
dest->m_nItems = indexcount;
}
if (src && indexcount)
UpdateIndexBuffer(dest, src, indexcount, true);
}
void CD3D8Renderer::UpdateIndexBuffer(SVertexStream *dest,const void *src,int indexcount, bool bUnLock)
{
HRESULT hReturn;
IDirect3DIndexBuffer8 *ibuf;
if (src && indexcount)
{
if (dest->m_nItems < indexcount)
{
if (dest->m_nItems)
ReleaseIndexBuffer(dest);
CreateIndexBuffer(dest, NULL, indexcount);
}
ushort *dst;
ibuf = (IDirect3DIndexBuffer8 *)dest->m_VertBuf.m_pPtr;
hReturn = ibuf->Lock(0, 0, (BYTE **) &dst, 0);
int size = indexcount*sizeof(ushort);
cryMemcpy(dst, src, size);
dest->m_VData = dst;
if (bUnLock)
{
hReturn = ibuf->Unlock();
dest->m_bLocked = false;
}
else
dest->m_bLocked = true;
}
else
if( dest->m_VertBuf.m_pPtr )
{
if (bUnLock && dest->m_bLocked)
{
ibuf = (IDirect3DIndexBuffer8 *)dest->m_VertBuf.m_pPtr;
hReturn = ibuf->Unlock();
dest->m_bLocked = false;
}
else
if (!bUnLock && !dest->m_bLocked)
{
ibuf = (IDirect3DIndexBuffer8 *)dest->m_VertBuf.m_pPtr;
ushort *dst;
hReturn = ibuf->Lock(0, 0, (BYTE **) &dst, 0);
dest->m_bLocked = true;
dest->m_VData = dst;
}
}
}
void CD3D8Renderer::ReleaseIndexBuffer(SVertexStream *dest)
{
IDirect3DIndexBuffer8 *ibuf = (IDirect3DIndexBuffer8 *)dest->m_VertBuf.m_pPtr;
SAFE_RELEASE(ibuf);
dest->Reset();
}
void CD3D8Renderer::CreateBuffer(int size, int vertexformat, CVertexBuffer *buf, int Type, const char *szSource)
{
IDirect3DVertexBuffer8 *vptr = NULL;
int fvf = m_RP.m_D3DFixedPipeline[Type][vertexformat+16].m_Handle;
int Flags = D3DUSAGE_WRITEONLY;
D3DPOOL Pool = D3DPOOL_MANAGED;
if (buf->m_bDynamic)
{
Flags |= D3DUSAGE_DYNAMIC;
Pool = D3DPOOL_DEFAULT;
}
HRESULT hReturn = m_pd3dDevice->CreateVertexBuffer(size, Flags, fvf, Pool, &vptr);
if (FAILED(hReturn))
return;
void *dst;
buf->m_VS[Type].m_VertBuf.m_pPtr = vptr;
hReturn = vptr->Lock(0, 0, (BYTE **) &dst, 0);
buf->m_VS[Type].m_VData = dst;
hReturn = vptr->Unlock();
m_CurVertBufferSize += size;
}
CVertexBuffer *CD3D8Renderer::CreateBuffer(int vertexcount,int vertexformat, const char *szSource, bool bDynamic)
{
IDirect3DVertexBuffer8 *vptr = NULL;
int fvf = m_RP.m_D3DFixedPipeline[0][vertexformat+16].m_Handle;
int Flags = D3DUSAGE_WRITEONLY;
D3DPOOL Pool = D3DPOOL_MANAGED;
if (bDynamic)
{
Flags |= D3DUSAGE_DYNAMIC;
Pool = D3DPOOL_DEFAULT;
}
int size = m_VertexSize[vertexformat]*vertexcount;
if (size+m_CurVertBufferSize > m_MaxVertBufferSize)
{
CLeafBuffer *pLB = CLeafBuffer::m_Root.m_Prev;
while (size+m_CurVertBufferSize > m_MaxVertBufferSize)
{
if (pLB == &CLeafBuffer::m_Root)
iConsole->Exit("Error: Pipeline buffer overflow. Current geometry is too-oo-oo big (%s)", gRenDev->GetStatusText(eRS_VidBuffer));
CLeafBuffer *Next = pLB->m_Prev;
pLB->Unload();
pLB = Next;
}
}
HRESULT hReturn = m_pd3dDevice->CreateVertexBuffer(m_VertexSize[vertexformat]*vertexcount, Flags, fvf, Pool, &vptr);
if (FAILED(hReturn))
return (NULL);
m_CurVertBufferSize += m_VertexSize[vertexformat]*vertexcount;
CVertexBuffer *newbuf = new CVertexBuffer;
newbuf->m_bDynamic = bDynamic;
newbuf->m_VS[VSF_GENERAL].m_bLocked = false;
newbuf->m_VS[VSF_GENERAL].m_VertBuf.m_pPtr = vptr;
newbuf->m_fence=0;
newbuf->m_NumVerts = vertexcount;
newbuf->m_vertexformat = vertexformat;
return(newbuf);
}
#include "../Common/NvTriStrip/NVTriStrip.h"
///////////////////////////////////////////
void CD3D8Renderer::DrawBuffer(CVertexBuffer *src,SVertexStream *indicies,int numindices,int offsindex, int prmode,int vert_start,int vert_stop, CMatInfo *mi)
{
int size = numindices * sizeof(short);
if (src->m_VS[VSF_GENERAL].m_bLocked)
{
IDirect3DVertexBuffer8 *tvert = (IDirect3DVertexBuffer8 *)src->m_VS[VSF_GENERAL].m_VertBuf.m_pPtr;
tvert->Unlock();
src->m_VS[VSF_GENERAL].m_bLocked = false;
}
IDirect3DIndexBuffer8 *ibuf = (IDirect3DIndexBuffer8 *)indicies->m_VertBuf.m_pPtr;
assert(ibuf);
h = m_pd3dDevice->SetVertexShader(m_RP.m_D3DFixedPipeline[0][src->m_vertexformat+0x10].m_Handle);
h = m_pd3dDevice->SetStreamSource( 0, (IDirect3DVertexBuffer8 *)src->m_VS[VSF_GENERAL].m_VertBuf.m_pPtr, m_VertexSize[src->m_vertexformat]);
h = m_pd3dDevice->SetIndices(ibuf, 0);
int NumVerts = src->m_NumVerts;
if (vert_stop)
NumVerts = vert_stop;
switch(prmode)
{
case R_PRIMV_TRIANGLES:
h = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,NumVerts,offsindex,numindices/3);
m_nPolygons+=numindices/3;
break;
case R_PRIMV_TRIANGLE_STRIP:
h = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,0,NumVerts,offsindex,numindices-2);
m_nPolygons+=numindices-2;
break;
case R_PRIMV_MULTI_GROUPS:
{
if (mi)
{
int offs = mi->nFirstIndexId;
int nGroups = mi->m_dwNumSections;
SPrimitiveGroup *gr = mi->m_pPrimitiveGroups;
if (gr)
{
for (int i=0; i<nGroups; i++)
{
SPrimitiveGroup *g = &gr[i];
switch (g->type)
{
case PT_STRIP:
if (FAILED(h=m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP, 0, mi->nNumVerts, g->offsIndex+offs, g->numIndices - 2)))
{
Error("CD3D8Renderer::DrawBuffer: DrawIndexedPrimitive error", h);
return;
}
m_nPolygons += (g->numIndices - 2);
break;
case PT_LIST:
if (FAILED(h=m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, mi->nNumVerts, g->offsIndex+offs, g->numIndices / 3)))
{
Error("CD3D8Renderer::DrawBuffer: DrawIndexedPrimitive error", h);
return;
}
m_nPolygons += (g->numIndices / 3);
break;
case PT_FAN:
if (FAILED(h=m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN, 0, mi->nNumVerts, g->offsIndex+offs, g->numIndices - 2)))
{
Error("CD3D8Renderer::DrawBuffer: DrawIndexedPrimitive error", h);
return;
}
m_nPolygons += (g->numIndices - 2);
break;
}
}
}
}
}
break;
}
}
///////////////////////////////////////////
void CD3D8Renderer::UpdateBuffer(CVertexBuffer *dest, const void *src, int vertexcount, bool bUnLock, int offs, int Type)
{
VOID *pVertices;
HRESULT hr = 0;
IDirect3DVertexBuffer8 *tvert;
int size;
if (!src)
{
if (!Type)
{
tvert=(IDirect3DVertexBuffer8 *)dest->m_VS[VSF_GENERAL].m_VertBuf.m_pPtr;
size = m_VertexSize[dest->m_vertexformat];
if (bUnLock)
{
// video buffer update
if (dest->m_VS[VSF_GENERAL].m_bLocked)
{
dest->m_VS[VSF_GENERAL].m_bLocked = false;
hr = tvert->Unlock();
}
}
else
{
// video buffer update
if (!dest->m_VS[VSF_GENERAL].m_bLocked)
{
dest->m_VS[VSF_GENERAL].m_bLocked = true;
#ifdef _XBOX
hr = tvert->Lock(0, 0, (BYTE **) &pVertices, 0);
#else
hr=tvert->Lock(0, 0, (BYTE **) &pVertices, dest->m_bDynamic ? D3DLOCK_DISCARD : 0);
#endif
dest->m_VS[VSF_GENERAL].m_VData = pVertices;
}
}
}
else
{
for (int i=0; i<VSF_NUM-1; i++)
{
tvert = (IDirect3DVertexBuffer8 *)dest->m_VS[i].m_VertBuf.m_pPtr;
if (!tvert)
continue;
if (!((1<<i) & Type))
continue;
if (bUnLock)
{
if (dest->m_VS[i].m_bLocked)
{
dest->m_VS[i].m_bLocked = false;
hr = tvert->Unlock();
}
}
else
{
if (!dest->m_VS[i].m_bLocked)
{
dest->m_VS[i].m_bLocked = true;
#ifndef _XBOX
hr=tvert->Lock(0, 0, (BYTE **) &pVertices, dest->m_bDynamic ? D3DLOCK_DISCARD : 0);
#else
hr=tvert->Lock(0, 0, (BYTE **) &pVertices, 0);
#endif
dest->m_VS[i].m_VData = pVertices;
}
}
}
}
return;
}
if (Type == VSF_GENERAL)
{
tvert = (IDirect3DVertexBuffer8 *)dest->m_VS[VSF_GENERAL].m_VertBuf.m_pPtr;
size = m_VertexSize[dest->m_vertexformat];
}
else
if (Type == VSF_TANGENTS)
{
tvert = (IDirect3DVertexBuffer8 *)dest->m_VS[VSF_TANGENTS].m_VertBuf.m_pPtr;
size = sizeof(SPipTangents);
}
else
if (Type == VSF_LMTC)
{
tvert = (IDirect3DVertexBuffer8 *)dest->m_VS[VSF_LMTC].m_VertBuf.m_pPtr;
size = sizeof(SMRendTexVert);
}
if (!tvert) // system buffer update
{
memcpy(dest->m_VS[VSF_GENERAL].m_VData, src, m_VertexSize[dest->m_vertexformat]*vertexcount);
dest->m_VS[Type].m_bLocked = 0;
return;
}
// video buffer update
if (!dest->m_VS[Type].m_bLocked)
{
dest->m_VS[Type].m_bLocked = true;
#ifndef _XBOX
hr=tvert->Lock(0, 0, (BYTE **) &pVertices, dest->m_bDynamic ? D3DLOCK_DISCARD : 0);
#else
hr=tvert->Lock(0, 0, (BYTE **) &pVertices, 0);
#endif
dest->m_VS[Type].m_VData = pVertices;
}
if (SUCCEEDED(hr) && src)
{
memcpy(dest->m_VS[Type].m_VData, src, size*vertexcount);
tvert->Unlock();
dest->m_VS[Type].m_bLocked = false;
}
else
if (dest->m_VS[Type].m_bLocked && bUnLock)
{
tvert->Unlock();
dest->m_VS[Type].m_bLocked = false;
}
}
void CD3D8Renderer::UnlockBuffer(CVertexBuffer *buf, int Type)
{
if (!buf->m_VS[Type].m_bLocked)
return;
IDirect3DVertexBuffer8 *tvert = (IDirect3DVertexBuffer8 *)buf->m_VS[Type].m_VertBuf.m_pPtr;
tvert->Unlock();
buf->m_VS[Type].m_bLocked = false;
}
///////////////////////////////////////////
void CD3D8Renderer::ReleaseBuffer(CVertexBuffer *bufptr)
{
if (bufptr)
{
m_CurVertBufferSize -= m_VertexSize[bufptr->m_vertexformat]*bufptr->m_NumVerts;
if (bufptr->m_VS[VSF_TANGENTS].m_VertBuf.m_pPtr)
m_CurVertBufferSize -= sizeof(SPipTangents)*bufptr->m_NumVerts;
if (bufptr->m_VS[VSF_LMTC].m_VertBuf.m_pPtr)
m_CurVertBufferSize -= sizeof(SMRendTexVert)*bufptr->m_NumVerts;
if (bufptr->m_VS[VSF_GENERAL].m_VertBuf.m_pPtr)
{
IDirect3DVertexBuffer8 *vtemp = (IDirect3DVertexBuffer8 *)bufptr->m_VS[VSF_GENERAL].m_VertBuf.m_pPtr;
SAFE_RELEASE(vtemp);
bufptr->m_VS[VSF_GENERAL].m_VertBuf.m_pPtr = NULL;
vtemp = (IDirect3DVertexBuffer8 *)bufptr->m_VS[VSF_TANGENTS].m_VertBuf.m_pPtr;
SAFE_RELEASE(vtemp);
bufptr->m_VS[VSF_TANGENTS].m_VertBuf.m_pPtr = NULL;
vtemp = (IDirect3DVertexBuffer8 *)bufptr->m_VS[VSF_LMTC].m_VertBuf.m_pPtr;
SAFE_RELEASE(vtemp);
bufptr->m_VS[VSF_LMTC].m_VertBuf.m_pPtr = NULL;
}
delete bufptr;
}
}
///////////////////////////////////////////
void CD3D8Renderer::CheckError(const char *comment)
{
}
///////////////////////////////////////////
int CD3D8Renderer::SetPolygonMode(int mode)
{
int prev_mode = m_polygon_mode;
m_polygon_mode = 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 CD3D8Renderer::EnableVSync(bool enable)
{
}
void CD3D8Renderer::EnableDepthTest(bool enable)
{
ASSERT(m_pd3dDevice);
m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, enable ? TRUE : FALSE);
}
void CD3D8Renderer::EnableDepthWrites(bool enable)
{
ASSERT(m_pd3dDevice);
m_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, enable ? TRUE : FALSE);
}
///////////////////////////////////////////
///////////////////////////////////////////
void CD3D8Renderer::EnableAlphaTest(bool enable,float alphavalue)
{
if (enable)
{
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
m_pd3dDevice->SetRenderState(D3DRS_ALPHAREF, (unsigned long)(256.0f*alphavalue));
m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
}
else
m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
}
void CD3D8Renderer::DrawQuadInFogVolume(float dy,float dx, float dz, float x, float y, float z, float fFogLevel, float fFogViewDist)
{
}
#include "I3DEngine.h"
#include "../Cry3DEngine/Terrain.h"
#include "../Cry3DEngine/StatObj.h"
#include "../Cry3DEngine/ObjMan.h"
#ifdef WIN32
// duplicated definition (first one is in 3dengine)
ISystem * Cry3DEngineBase::m_pSys=0;
IRenderer * Cry3DEngineBase::m_pRenderer=0;
ITimer * Cry3DEngineBase::m_pTimer=0;
ILog * Cry3DEngineBase::m_pLog=0;
IPhysicalWorld * Cry3DEngineBase::m_pPhysicalWorld=0;
IConsole * Cry3DEngineBase::m_pConsole=0;
I3DEngine * Cry3DEngineBase::m_p3DEngine=0;
CVars * Cry3DEngineBase::m_pCVars=0;
ICryPak * Cry3DEngineBase::m_pCryPak=0;
#endif // WIN32
/*
static _inline int Compare(CStatObjInst *& p1, CStatObjInst *& p2)
{
if(p1->m_fDistance > p2->m_fDistance)
return 1;
else
if(p1->m_fDistance < p2->m_fDistance)
return -1;
return 0;
}
*/
void CD3D8Renderer::DrawObjSprites (list2<CStatObjInst*> *pList, float fMaxViewDist, CObjManager *pObjMan)
{
HRESULT hr;
ResetToDefault();
EnableBlend(true);
EnableAlphaTest(true,0.125f);
SetEnviMode(R_MODE_MODULATE);
EnableDepthWrites(true);
SetCullMode(R_CULL_DISABLE);
// Sorting far objects front to back since we use alphablending
// ::Sort(&(*pList)[0], pList->Count());
//pList->SortByDistanceMember_(true);
float max_view_dist = fMaxViewDist*0.8f;
const Vec3d & vCamPos = m_RP.m_ViewOrg;
const float rad2deg = 180.0f/PI;
const float far_tex_angle = (FAR_TEX_ANGLE*0.5f);
CD3D8TexMan::BindNULL(1);
m_TexMan->SetTexture(TX_FIRSTBIND, eTT_Base);
float v[4];
v[3] = 1.0f;
CCGVProgram_D3D *pVP = NULL;
CCGVProgram_D3D *pVP_FV = NULL;
// If device supports vertex shaders use advanced bending for sprites
if (!m_RP.m_VPPlantBendingSpr && (GetFeatures() & RFT_HW_VS))
{
//pVP = (CVProgram_D3D *)CVProgram::mfForName("VProgSimple_Plant_Bended_Sprite", false);
pVP = (CCGVProgram_D3D *)CVProgram::mfForName("CGVProgSimple_Plant_Bended_Sprite", true);
pVP_FV = (CCGVProgram_D3D *)CVProgram::mfForName("CGVProgSimple_Plant_Bended_Sprite_FV", true);
m_RP.m_VPPlantBendingSpr = pVP;
m_RP.m_VPPlantBendingSpr_FV = pVP_FV;
}
else
{
pVP = (CCGVProgram_D3D *)m_RP.m_VPPlantBendingSpr;
pVP_FV = (CCGVProgram_D3D *)m_RP.m_VPPlantBendingSpr_FV;
}
//pVP = NULL;
//m_pd3dDevice->SetVertexShader(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
SCGBind *pBindBend = NULL;
SCGBind *pBindPos = NULL;
int nf = VERTEX_FORMAT_P3F_COL4UB_TEX2F;
m_RP.m_CurD3DVFormat = nf + 0x10;
m_RP.m_FlagsModificators &= ~7;
SMFog *fb = NULL;
SCGBind *pBindTG00, *pBindTG01, *pBindTG10, *pBindTG11;
SCGBind *pBindBend_FV = NULL;
SCGBind *pBindPos_FV = NULL;
CFColor FogColor;
Plane plane00, plane01, plane10, plane11;
SCGBind *pCurBindBend = NULL;
SCGBind *pCurBindPos = NULL;
CCGVProgram_D3D *lastvpD3D = NULL;
SWaveForm2 wfMain;
if (pVP)
{
wfMain.m_eWFType = eWF_Sin;
wfMain.m_Amp = 0.002f;
wfMain.m_Level = 0;
pVP->mfSet(true, NULL);
lastvpD3D = pVP;
pBindBend = pVP->mfGetParameterBind("Bend");
pBindPos = pVP->mfGetParameterBind("ObjPos");
pCurBindBend = pBindBend;
pCurBindPos = pBindPos;
}
//struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F *vQuad = NULL;
struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F vQuad[6];
//int nFirst = 0;
//int nLast = 0;
//LPDIRECT3DVERTEXBuffer9 pVB = m_RP.mVBSprites.VBPtr_D_T2F->GetInterface();
//pVB->Lock(0, 0, (BYTE **)&vQuad, D3DLOCK_DISCARD | D3DLOCK_NOSYSLOCK);
//hr = m_pd3dDevice->SetStreamSource(0, pVB, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
Vec3d vWorldColor = pObjMan->GetSystem()->GetI3DEngine()->GetWorldColor();
int prev_tid=-1;
if (m_bHeatVision)
{
float param[4];
if (!m_RP.m_RCSprites_Heat)
m_RP.m_RCSprites_Heat = CPShader::mfForName("RCHeat_TreesSprites", false);
if (m_RP.m_RCSprites_Heat)
{
m_RP.m_RCSprites_Heat->mfSet(true);
param[0] = param[1] = 0;
param[2] = 1.0f;
param[3] = 1.0f;
CPShader_D3D::mfSetFloat4f(0, param);
}
}
for( int i=pList->Count()-1; i>=0; i-- )
{
CStatObjInst * o = pList->GetAt(i);
CStatObj * pStatObj = pObjMan->m_lstStaticTypes[o->m_nObjectTypeID].GetStatObj();
float fMaxDist = o->m_fMaxViewDist;//o->m_fMaxDist*pObjMan->m_lstStaticTypes[o->m_nObjectTypeID].fMaxViewDistRatio; //o->scale*pStatObj->GetRadius()*80;
// note: move into sort by size
if(fMaxDist > max_view_dist)
fMaxDist = max_view_dist;
assert(SRendItem::m_RecurseLevel>=1 && SRendItem::m_RecurseLevel-1<=2);
float fDistance = (*(((*(IEntityRender*)(&*o))).m_pEntityRenderState)).arrfDistance[SRendItem::m_RecurseLevel-1];
float alpha = (1.f-(fDistance*pObjMan->m_fZoomFactor)/(fMaxDist))*8.f;
if (alpha <= 0)
continue;
if(alpha>1.f)
alpha=1.f;
/*
Vec3d vBright;
if(o->m_bBright)
vBright.Set(1.f,1.f,1.f);// = pObjMan->m_fOutdoorAmbientLevel + (1.f - pObjMan->m_fOutdoorAmbientLevel);
else
vBright = pObjMan->m_vOutdoorAmbientColor * pObjMan->m_lstStaticTypes[o->m_nObjectTypeID].fAmbScale;
*/
Vec3d vBright = Vec3d(0.01f,0.01f,0.01f)*o->m_ucBright;
// use brightness from vegetation group settings
vBright *= pObjMan->m_lstStaticTypes[o->m_nObjectTypeID].fBrightness;
float DX = o->m_vPos.x - vCamPos.x;
float DY = o->m_vPos.y - vCamPos.y;
int angle = FtoI(rad2deg*atan2f( DX, DY )+far_tex_angle);
while(angle<0) angle+=360;
assert(angle>=0 && angle/FAR_TEX_ANGLE<FAR_TEX_COUNT);
int tid = pStatObj->m_arrSpriteTexID[(int)(angle/FAR_TEX_ANGLE)];
if(prev_tid != tid)
{
m_TexMan->SetTexture(tid, eTT_Base);
prev_tid = tid;
}
float r = vWorldColor.x*vBright.x;
float g = vWorldColor.y*vBright.y;
float b = vWorldColor.z*vBright.z;
DWORD cCol = D3DRGBA(r,g,b,alpha);
float fSpriteScaleV = o->m_fScale*pStatObj->GetRadiusVert()*1.04f*alpha;
float fSpriteScaleH = o->m_fScale*pStatObj->GetRadiusHors()*pObjMan->m_fZoomFactor*1.050f*alpha;
Vec3d vPos = o->m_vPos + pStatObj->GetCenter()*o->m_fScale;
if(o->GetEntityRS()->nFogVolumeID>0 && CV_r_VolumetricFog)
{
// setup Volume Fog Texgen planes
if (!pBindBend_FV)
{
if (lastvpD3D)
{
lastvpD3D->mfSet(false, NULL);
lastvpD3D = NULL;
}
pVP_FV->mfSet(true, NULL);
pBindBend_FV = pVP_FV->mfGetParameterBind("Bend");
pBindPos_FV = pVP_FV->mfGetParameterBind("ObjPos");
if (!m_RP.m_RCSprites_FV)
m_RP.m_RCSprites_FV = CPShader::mfForName("RCTreeSprites_FV", false);
fb = &m_RP.m_FogVolumes[o->GetEntityRS()->nFogVolumeID];
if (fb->m_FogInfo.m_WaveFogGen.m_eWFType)
{
float f = SEvalFuncs::EvalWaveForm(&fb->m_FogInfo.m_WaveFogGen);
fb->m_fMaxDist = f;
}
float intens = fb->m_fMaxDist;
if (intens <= 0)
intens = 1.0f;
intens = -0.25f / intens;
plane00.n.x = intens*m_CameraMatrix(0,2);
plane00.n.y = intens*m_CameraMatrix(1,2);
plane00.n.z = intens*m_CameraMatrix(2,2);
plane00.d = intens*m_CameraMatrix(3,2);
plane00.d += 0.5f;
pBindTG00 = pVP_FV->mfGetParameterBind("TexGen00");
plane01.n.x = plane01.n.y = plane01.n.z = 0;
plane01.d = 0.49f;
pBindTG01 = pVP_FV->mfGetParameterBind("TexGen01");
plane11.n.x = 0;
plane11.n.y = 0;
plane11.n.z = 0;
plane11.d = fb->m_Normal.Dot(m_RP.m_ViewOrg) - fb->m_Dist;
float fSmooth;
FogColor = fb->m_Color;
if (plane11.d < -0.5f)
fSmooth = 1.0f;
else
fSmooth = 0.1f;
plane11.d *= fSmooth;
plane11.d += 0.5f;
pBindTG10 = pVP_FV->mfGetParameterBind("TexGen10");
plane10.n.x = fb->m_Normal.x * fSmooth;
plane10.n.y = fb->m_Normal.y * fSmooth;
plane10.n.z = fb->m_Normal.z * fSmooth;
plane10.d = -(fb->m_Dist) * fSmooth;
plane10.d += 0.5f;
pBindTG11 = pVP_FV->mfGetParameterBind("TexGen11");
}
if (lastvpD3D != pVP_FV)
{
pCurBindBend = pBindBend_FV;
pCurBindPos = pBindPos_FV;
if (lastvpD3D)
lastvpD3D->mfSet(false, NULL);
lastvpD3D = pVP_FV;
if (pVP_FV)
{
pVP_FV->mfSet(true, NULL);
if (pBindTG00)
pVP_FV->mfParameter4f(pBindTG00, &plane00.n.x);
if (pBindTG01)
pVP_FV->mfParameter4f(pBindTG01, &plane01.n.x);
if (pBindTG10)
pVP_FV->mfParameter4f(pBindTG10, &plane11.n.x);
if (pBindTG11)
pVP_FV->mfParameter4f(pBindTG11, &plane10.n.x);
}
EF_SelectTMU(1);
CTexMan::m_Text_Fog->Set();
EF_SelectTMU(2);
CTexMan::m_Text_Fog_Enter->Set();
EF_SelectTMU(0);
float param[4];
if (m_RP.m_RCSprites_FV)
{
m_RP.m_RCSprites_FV->mfSet(true);
param[0] = m_WorldColor[0]; param[1] = m_WorldColor[1]; param[2] = m_WorldColor[2]; param[3] = m_WorldColor[3];
CPShader_D3D::mfSetFloat4f(0, param);
param[0] = FogColor[0]; param[1] = FogColor[1]; param[2] = FogColor[2]; param[3] = FogColor[3];
CPShader_D3D::mfSetFloat4f(1, param);
}
EF_PushFog();
EnableFog(false);
}
}
else
{
if (lastvpD3D != pVP)
{
pCurBindBend = pBindBend;
pCurBindPos = pBindPos;
if (lastvpD3D)
lastvpD3D->mfSet(false, NULL);
if (lastvpD3D == pVP_FV)
{
EF_PopFog();
if (m_RP.m_RCSprites_FV)
m_RP.m_RCSprites_FV->mfSet(false);
}
lastvpD3D = pVP;
if (pVP)
pVP->mfSet(true, NULL);
EF_SelectTMU(1);
EnableTMU(false);
EF_SelectTMU(2);
EnableTMU(false);
EF_SelectTMU(0);
}
}
float dy = DX*fSpriteScaleH/fDistance;
float dx = DY*fSpriteScaleH/fDistance;
if (pVP)
{
float fGroupBending = pObjMan->m_lstStaticTypes[o->m_nObjectTypeID].fBending;
float fIrv = 1.0f / pStatObj->GetRadiusVert();
float fIScale = 1.0f / o->m_fScale;
wfMain.m_Freq = fIrv/8.0f+0.2f;
wfMain.m_Phase = vPos.x/8.0f;
v[2] = (o->m_fCurrentBending + pObjMan->m_fWindForce*fGroupBending*6.0f)*fIrv; // Bending factor
v[0] = SEvalFuncs::EvalWaveForm(&wfMain) * fIScale; // x amount
wfMain.m_Freq = fIrv/7.0f+0.2f;
wfMain.m_Phase = vPos.y/8.0f;
v[1] = SEvalFuncs::EvalWaveForm(&wfMain) * fIScale; // y amount
//pVP->mfParameter(20, v);
if (pCurBindBend)
pVP->mfParameter4f(pCurBindBend, v);
v[0] = o->m_vPos.x;
v[1] = o->m_vPos.y;
v[2] = o->m_vPos.z;
//pVP->mfParameter(21, v); // Object position
if (pCurBindPos)
pVP->mfParameter4f(pCurBindPos, v);
}
// Define the tris
vQuad[0].x = dx+vPos.x;
vQuad[0].y = -dy+vPos.y;
vQuad[0].z = -fSpriteScaleV+vPos.z;
*(DWORD *)(&vQuad[0].r) = cCol;
vQuad[0].s = 0;
vQuad[0].t = 0;
vQuad[1].x = -dx+vPos.x;
vQuad[1].y = dy+vPos.y;
vQuad[1].z = -fSpriteScaleV+vPos.z;
*(DWORD *)(&vQuad[1].r) = cCol;
vQuad[1].s = -1;
vQuad[1].t = 0;
vQuad[2].x = dx+vPos.x;
vQuad[2].y = -dy+vPos.y;
vQuad[2].z = vPos.z;
*(DWORD *)(&vQuad[2].r) = cCol;
vQuad[2].s = 0;
vQuad[2].t = 0.5f;
vQuad[3].x = -dx+vPos.x;
vQuad[3].y = dy+vPos.y;
vQuad[3].z = vPos.z;
*(DWORD *)(&vQuad[3].r) = cCol;
vQuad[3].s = -1;
vQuad[3].t = 0.5f;
vQuad[4].x = dx+vPos.x;
vQuad[4].y = -dy+vPos.y;
vQuad[4].z = fSpriteScaleV+vPos.z;
*(DWORD *)(&vQuad[4].r) = cCol;
vQuad[4].s = 0;
vQuad[4].t = 1.0f;
vQuad[5].x = -dx+vPos.x;
vQuad[5].y = dy+vPos.y;
vQuad[5].z = fSpriteScaleV+vPos.z;
*(DWORD *)(&vQuad[5].r) = cCol;
vQuad[5].s = -1.0f;
vQuad[5].t = 1.0f;
//nLast += 6;
//pVB->Unlock();
hr = m_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 4, vQuad, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F));
//hr = m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, nFirst, nLast-nFirst-2);
//nFirst = nLast;
/*if (nLast + 6 >= m_RP.MaxVerts)
{
nFirst = nLast = 0;
pVB->Lock(0, 6*sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F), (BYTE **)vQuad, D3DLOCK_DISCARD | D3DLOCK_NOSYSLOCK);
}
else
pVB->Lock(nFirst*sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F), 6*sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_TEX2F), (BYTE **)vQuad, D3DLOCK_NOOVERWRITE | D3DLOCK_NOSYSLOCK);*/
m_nPolygons += 4;
}
if (pVP)
pVP->mfSet(false, NULL);
if (m_bHeatVision)
{
if (m_RP.m_RCSprites_Heat)
m_RP.m_RCSprites_Heat->mfSet(false);
}
//pVB->Unlock();
m_TexMan->SetTexture(0, eTT_Base);
}
void CD3D8Renderer::DrawQuad(const Vec3d &right, const Vec3d &up, const Vec3d &origin,int nFlipMode/*=0*/)
{
SPipeVertex_D_1T_2F 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;
m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX_D_1T_2F );
h = m_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, Verts, STRIDE_D_1T_2F);
}
void CD3D8Renderer::DrawQuad(float dy,float dx, float dz, float x, float y, float z)
{
SPipeVertex_D_1T_2F 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;
m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX_D_1T_2F );
h = m_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, Verts, STRIDE_D_1T_2F);
}
void CD3D8Renderer::DrawPoint(float x, float y, float z, float fSize)
{
SPipeVertex_D_1T_2F Verts[1];
SetCullMode(R_CULL_DISABLE);
EnableDepthTest(0);
EnableTMU(false);
m_pd3dDevice->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&fSize));
Verts[0].xyz[0] = x; Verts[0].xyz[1] = y; Verts[0].xyz[2] = z;
Verts[0].color.dcolor = 0xffffffff;
m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TFACTOR );
m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX_D_1T_2F );
h = m_pd3dDevice->DrawPrimitiveUP(D3DPT_POINTLIST, 1, Verts, STRIDE_D_1T_2F);
m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE );
EnableTMU(true);
}
///////////////////////////////////////////
void CD3D8Renderer::DrawTriStrip(CVertexBuffer *src, int vert_num)
{
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;
int n = src->m_vertexformat + 16;
m_pd3dDevice->SetVertexShader( m_RP.m_D3DFixedPipeline[0][n].m_Handle );
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();
int n = src->m_vertexformat + 16;
m_pd3dDevice->SetVertexShader( m_RP.m_D3DFixedPipeline[0][n].m_Handle );
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 n = src->m_vertexformat + 16;
m_pd3dDevice->SetVertexShader( m_RP.m_D3DFixedPipeline[0][n].m_Handle );
h = m_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, vert_num-2, dt, sizeof(struct_VERTEX_FORMAT_P3F_COL4UB_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 n = src->m_vertexformat + 16;
m_pd3dDevice->SetVertexShader( m_RP.m_D3DFixedPipeline[0][n].m_Handle );
h = m_pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, vert_num-2, dt, sizeof(struct_VERTEX_FORMAT_TRP3F_COL4UB_TEX2F));
}
break;
default:
assert(0);
break;
}
m_nPolygons += vert_num-2;
}
///////////////////////////////////////////
void CD3D8Renderer::ResetToDefault()
{
if (m_LogFile)
Logv(SRendItem::m_RecurseLevel, ".... ResetToDefault ....\n");
EnableDepthTest(true);
EnableAlphaTest(false);
SetCullMode(R_CULL_BACK);
EnableBlend(false);
SetBlendMode(R_BLEND_MODE__SRC_ALPHA__ONE_MINUS_SRC_ALPHA);
for (int i=0; i<m_numtmus; i++)
{
EF_SelectTMU(i);
eCurColorOp[i] = -1;
if (!i)
{
EnableTMU(true);
}
else
{
EnableTMU(false);
}
EnableTexGen(false);
}
EF_SelectTMU(0);
CTexMan::m_nCurStages = 1;
SetMaterialColor(1,1,1,1);
EnableLighting(false);
SetDepthFunc(R_LEQUAL);
EnableDepthWrites(true);
m_pd3dDevice->SetRenderState(D3DRS_ZBIAS, 0);
#ifdef _XBOX
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALL);
#else
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0xf);
#endif
m_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, FALSE);
EF_SetVertColor();
mCurState = GS_DEPTHWRITE;
m_eCull = (ECull)-1;
if (m_LogFile && CV_r_log == 3)
Logv(SRendItem::m_RecurseLevel, ".... End ResetToDefault ....\n");
}
//////////////////////////////////////////
int CD3D8Renderer::GenerateAlphaGlowTexture(float k)
{
// float k = 6;
const int tex_size = 256;
byte *data = new byte [tex_size*tex_size];
memset(data, 255, tex_size*tex_size);
for(int x=0; x<tex_size; x++)
for(int y=0; y<tex_size; y++)
{
int _x = x-tex_size/2;
int _y = y-tex_size/2;
float val = k*2.f*((float)tex_size/2 - (float)(sqrt(double(_x*_x+_y*_y))));
val = Clamp(val, 0.0f, 255.0f);
data[x*256+y] = (int)(val);
}
int nRes = DownLoadToVideoMemory((unsigned char*)data,tex_size,tex_size,eTF_8000,eTF_8000,true,true,FILTER_LINEAR);
delete [] data;
return nRes;
}
uint CD3D8Renderer::Make3DSprite(int nTexSize, float fAngleStep, IStatObj * pStatObj)
{
return 0;
}
uint CD3D8Renderer::MakeSprite(float object_scale, int tex_size, float angle, IStatObj * pStatObj, uchar * _pTmpBuffer, uint def_tid)
{
D3DCOLOR cColor = D3DRGBA(0.3f,0.3f,0.3f,0.0f);
HRESULT h;
// calc vertical/horisontal radiuses
float dxh = (float)max( fabs(pStatObj->GetBoxMax().x), fabs(pStatObj->GetBoxMin().x));
float dyh = (float)max( fabs(pStatObj->GetBoxMax().y), fabs(pStatObj->GetBoxMin().y));
float fRadiusHors = (float)sqrt(dxh*dxh + dyh*dyh);//max(dxh,dyh);
float fRadiusVert = (pStatObj->GetBoxMax().z-pStatObj->GetBoxMin().z)/2;
float fDrawDist = fRadiusVert*25.f*8.f;
EF_PushFog();
EnableFog(false);
D3DXMATRIX *m = m_matProj->GetTop();
D3DXMatrixPerspectiveFovRH(m, 0.58f*(gf_PI/180.0f), fRadiusHors/fRadiusVert, fDrawDist-fRadiusHors*2, fDrawDist+fRadiusHors*2);
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
m_bInvertedMatrix = false;
if (!m_SceneRecurseCount)
m_pd3dDevice->BeginScene();
m_SceneRecurseCount++;
m_Viewport.X = 0;
m_Viewport.Y = 0;
m_Viewport.Width = tex_size;
m_Viewport.Height = tex_size;
m_Viewport.MinZ = 0.0f;
m_Viewport.MaxZ = 1.0f;
m_pd3dDevice->SetViewport(&m_Viewport);
Vec3d vCenter = (pStatObj->GetBoxMax()+pStatObj->GetBoxMin())*0.5f;
D3DXVECTOR3 Eye = D3DXVECTOR3(0,0,0);
D3DXVECTOR3 At = D3DXVECTOR3(-1,0,0);
D3DXVECTOR3 Up = D3DXVECTOR3(0,0,1);
m = m_matView->GetTop();
D3DXMatrixLookAtRH(m, &Eye, &At, &Up);
m_matView->TranslateLocal(-fDrawDist,0,0);
D3DXVECTOR3 Axis = D3DXVECTOR3(0,0,1);
m_matView->RotateAxisLocal(&Axis, angle*(gf_PI/180.0f));
m_matView->TranslateLocal(-vCenter.x,-vCenter.y,-vCenter.z);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
byte *data = new byte[tex_size*tex_size*4];
char name[128];
sprintf(name, "$AutoSprites_%d", m_TexGenID++);
int flags = FT_NOMIPS | FT_HASALPHA;
STexPic *tp = m_TexMan->CreateTexture(name, tex_size, tex_size, 1, flags, FT2_NODXT, data, eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF_8888);
STexPicD3D *t = (STexPicD3D *)tp;
LPDIRECT3DTEXTURE8 pID3DTexture = NULL;
LPDIRECT3DTEXTURE8 pID3DTargetTexture = NULL;
delete [] data;
if (!t->m_RefTex)
return 0;
pID3DTexture = (LPDIRECT3DTEXTURE8)t->m_RefTex->m_VidTex;
if (!pID3DTexture)
return 0;
#ifndef _XBOX
if( FAILED( h = m_pd3dDevice->CreateTexture( tex_size, tex_size, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pID3DTargetTexture )))
return 0;
#else
if( FAILED( h = m_pd3dDevice->CreateTexture( tex_size, tex_size, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pID3DTargetTexture )))
return 0;
#endif
LPDIRECT3DSURFACE8 pSrcSurf;
h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
m_pd3dDevice->SetRenderTarget( pSrcSurf, m_pZBuffer );
pSrcSurf->Release();
// render object
if (m_sbpp)
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, cColor, 1.0f, 0);
else
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
EF_SetWorldColor(0.5f,0.5f,0.5f);
EF_StartEf();
SRendParams rParms;
rParms.nShaderTemplate = -1;
pStatObj->Render(rParms);
EF_EndEf3D(true);
m_pd3dDevice->SetRenderTarget( m_pBackBuffer, m_pZBuffer );
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, cColor, 1.0f, 0);
// Copy data
{
LPDIRECT3DTEXTURE8 pID3DSrcTexture;
LPDIRECT3DSURFACE8 pDstSurf, pSrcSurf;
D3DLOCKED_RECT d3dlrSrc, d3dlrDst;
h = pID3DTargetTexture->GetSurfaceLevel(0, &pSrcSurf);
h = D3DXCreateTexture(m_pd3dDevice, tex_size, tex_size, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSrcTexture );
h = pID3DSrcTexture->GetSurfaceLevel(0, &pDstSurf);
h = m_pd3dDevice->CopyRects(pSrcSurf, NULL, 0, pDstSurf, NULL);
h = pID3DSrcTexture->LockRect(0, &d3dlrSrc, NULL, 0);
h = pID3DTexture->LockRect(0, &d3dlrDst, NULL, 0);
byte *ds = new byte [tex_size*tex_size*4];
#ifndef _XBOX
// Copy data to the texture
memcpy(ds, d3dlrSrc.pBits, tex_size*tex_size*4);
#else
XGUnswizzleRect( d3dlrSrc.pBits, tex_size, tex_size, NULL, ds, d3dlrSrc.Pitch, NULL, 4 );
#endif
SetTextureAlphaChannelFromRGB(ds, tex_size);
#ifndef _XBOX
byte *dst = (byte *)d3dlrDst.pBits;
#else
byte *dst = new byte [tex_size*tex_size*4];
#endif
for (int i=0; i<tex_size; i++)
{
int ni0 = (tex_size-i-1)*tex_size*4;
int ni1 = (i * tex_size)*4;
cryMemcpy(&dst[ni0], &ds[ni1], tex_size*4);
}
//cryMemcpy(dst, ds, tex_size*tex_size*4);
/*char buff[32]="";
static int imid=0;
sprintf(buff, "sprite%d_D3D.tga", imid);
imid++;
::WriteTGA((byte *)dst, tex_size, tex_size, buff, 32);*/
delete [] ds;
#ifdef _XBOX
XGSwizzleRect( dst, 0, NULL, d3dlrDst.pBits, tex_size, tex_size, NULL, sizeof(DWORD) );
delete [] dst;
#endif
h = pID3DTexture->UnlockRect(0);
pID3DSrcTexture->UnlockRect(0);
SAFE_RELEASE (pSrcSurf);
SAFE_RELEASE (pDstSurf);
SAFE_RELEASE (pID3DSrcTexture);
SAFE_RELEASE (pID3DTargetTexture);
}
m_matProj->LoadIdentity();
m = m_matProj->GetTop();
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
m_matView->LoadIdentity();
m = m_matView->GetTop();
m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
SetViewport();
EF_PopFog();
m_SceneRecurseCount--;
if (!m_SceneRecurseCount)
m_pd3dDevice->EndScene();
return tp->m_Bind;
}
///////////////////////////////////////////
void CD3D8Renderer::SetMaterialColor(float r, float g, float b, float a)
{
EF_SetGlobalColor(r, g, b, a);
}
///////////////////////////////////////////
int CD3D8Renderer::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)
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 = nCount;
strncpy(pInfo->sName, szFileNameFormat, sizeof(pInfo->sName));
for (int i=0; i<nCount; i++)
{
char filename[80]="";
sprintf(filename, szFileNameFormat, i);
pInfo->pBindIds[i] = LoadTexture( filename );
}
iLog->LogToFilePlus(" (%d)", nCount);
m_LoadedAnimatedTextures.Add(pInfo);
return (int)m_LoadedAnimatedTextures.Count();
}
///////////////////////////////////////////
char * CD3D8Renderer::GetStatusText(ERendStats type)
{
return "No status yet";
}
void sLogTexture (char *name, int Size);
///////////////////////////////////////////
void CD3D8Renderer::EnableLight (int id, bool enable)
{
m_pd3dDevice->LightEnable(id, enable);
}
void CD3D8Renderer::SetLightPos (int id, Vec3d &pos, bool bDirectional)
{
D3DLIGHT8 *Light = &m_Lights[id];;
Light->Position.x = pos[0];
Light->Position.y = pos[1];
Light->Position.z = pos[2];
Vec3d n = pos;
n.Normalize();
Light->Direction.x = n[0];
Light->Direction.y = n[1];
Light->Direction.z = n[2];
m_pd3dDevice->SetLight(id, Light);
}
void CD3D8Renderer::SetLightDiffuse (int id, Vec3d &color)
{
D3DLIGHT8 *Light = &m_Lights[id];;
Light->Diffuse.r = color[0];
Light->Diffuse.g = color[1];
Light->Diffuse.b = color[2];
Light->Diffuse.a = 1.0f;
m_pd3dDevice->SetLight(id, Light);
}
void CD3D8Renderer::SetLightAmbient (int id, Vec3d &color)
{
D3DLIGHT8 *Light = &m_Lights[id];;
Light->Ambient.r = color[0];
Light->Ambient.g = color[1];
Light->Ambient.b = color[2];
Light->Ambient.a = 1.0f;
m_pd3dDevice->SetLight(id, Light);
}
void CD3D8Renderer::SetLightSpecular(int id, Vec3d &color)
{
D3DLIGHT8 *Light = &m_Lights[id];;
Light->Specular.r = color[0];
Light->Specular.g = color[1];
Light->Specular.b = color[2];
Light->Specular.a = 1.0f;
m_pd3dDevice->SetLight(id, Light);
}
void CD3D8Renderer::SetLightAttenuat(int id, float att)
{
D3DLIGHT8 *Light = &m_Lights[id];;
Light->Attenuation0 = att;
m_pd3dDevice->SetLight(id, Light);
}
void CD3D8Renderer::EnableLighting (bool enable)
{
m_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, enable);
m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, enable);
m_pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0xffffffff);
}
void CD3D8Renderer::SetMaterialDiffuse (Vec3d &color)
{
m_Material.Diffuse.r = color[0];
m_Material.Diffuse.g = color[1];
m_Material.Diffuse.b = color[2];
m_Material.Diffuse.a = 1.0f;
m_pd3dDevice->SetMaterial( &m_Material );
}
void CD3D8Renderer::SetMaterialAmbient (Vec3d &color)
{
m_Material.Ambient.r = color[0];
m_Material.Ambient.g = color[1];
m_Material.Ambient.b = color[2];
m_Material.Ambient.a = 1.0f;
m_pd3dDevice->SetMaterial( &m_Material );
}
void CD3D8Renderer::SetMaterialSpecular(Vec3d &color)
{
m_Material.Specular.r = color[0];
m_Material.Specular.g = color[1];
m_Material.Specular.b = color[2];
m_Material.Specular.a = 1.0f;
m_pd3dDevice->SetMaterial( &m_Material );
}
void CD3D8Renderer::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;
*sy = vOut.y;
*sz = vOut.z;
}
void CD3D8Renderer::DrawBall(float x, float y, float z, float radius)
{
LPD3DXMESH pMesh;
HRESULT hr = D3DXCreateSphere(m_pd3dDevice, radius, 16, 16, &pMesh, NULL);
if (FAILED(hr))
return;
EF_PushMatrix();
EnableTMU(false);
TranslateMatrix(x, y, z);
pMesh->DrawSubset(0);
SAFE_RELEASE(pMesh);
EnableTMU(true);
EF_PopMatrix();
}
void CD3D8Renderer::DrawBall(const Vec3d & pos, float radius)
{
assert(0);
}
#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] = 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 CD3D8Renderer::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 CD3D8Renderer::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 CD3D8Renderer::SetColorMask(unsigned char r,unsigned char g,unsigned char b,unsigned char a)
{
UINT flag = 0;
if(r)
flag |= D3DCOLORWRITEENABLE_RED;
if(g)
flag |= D3DCOLORWRITEENABLE_GREEN;
if(b)
flag |= D3DCOLORWRITEENABLE_BLUE;
if(a)
flag |= D3DCOLORWRITEENABLE_ALPHA;
m_pd3dDevice->SetRenderState (D3DRS_COLORWRITEENABLE, flag);
}
//////////////////////////////////////////////////////////////////////
void CD3D8Renderer::ClearDepthBuffer()
{
m_bWasCleared = true;
m_pd3dDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(0, 0, 0, 0), 1.0f, 0);
}
void CD3D8Renderer::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 CD3D8Renderer::ReadFrameBuffer(unsigned char * pRGB, int nSizeX, int nSizeY, bool bBackBuffer, bool bRGBA)
{
assert(0);
}
void CD3D8Renderer::SetDepthFunc(int mode)
{
switch (mode)
{
case R_NEVER:
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_NEVER);
break;
case R_LESS:
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS);
break;
case R_EQUAL:
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_EQUAL);
break;
case R_LEQUAL:
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
break;
case R_GREATER:
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATER);
break;
case R_NOTEQUAL:
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_NOTEQUAL);
break;
case R_GEQUAL:
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_GREATEREQUAL);
break;
case R_ALWAYS:
m_pd3dDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
break;
default:
iLog->Log("Unknown DepthFunc 0x%x\n", mode);
}
}
void CD3D8Renderer::EnableStencilTest(bool enable)
{
mfGetD3DDevice()->SetRenderState(D3DRS_STENCILENABLE, enable);
}
void CD3D8Renderer::SetStencilMask(unsigned char value)
{
assert(0);
}
void CD3D8Renderer::SetStencilFunc(int func,int ref,int mask)
{
assert(0);
}
void CD3D8Renderer::SetStencilOp(int fail,int zfail,int pass)
{
assert(0);
}
void CD3D8Renderer::DrawTransparentQuad2D(float color)
{
assert(0);
}
void CD3D8Renderer::EnableAALines(bool bEnable)
{
assert(0);
}
void CD3D8Renderer::DrawCircle(float fX, float fY, float fZ, float fRadius)
{
assert(0);
}
void CD3D8Renderer::PrepareDepthMap(ShadowMapFrustum * lof, bool make_new_tid)
{
//assert(0);
}
//======================================================================
void CD3D8Renderer::ConfigCombinersForShadowPass()
{
assert(0);
}
void CD3D8Renderer::ConfigCombinersForHardwareShadowPass(int withTexture, float * lightDimColor)
{
assert(0);
}
void CD3D8Renderer::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, -9999.0, 9999.0);
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
EF_PushMatrix();
m = m_matView->GetTop();
m_matView->LoadIdentity();
m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
}
else
{
m_matProj->Pop();
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m_matProj->GetTop());
EF_PopMatrix();
}
}
unsigned int CD3D8Renderer::MakeTexture(const char * _filename,int *_tex_type/*,unsigned int def_tid*/)
{
return LoadTexture(_filename,_tex_type);
}
void CD3D8Renderer::SetTexClampMode(bool clamp)
{
if (m_TexMan->m_LastTex)
{
STexPicD3D *ti = (STexPicD3D *)m_TexMan->m_LastTex;
if (ti->m_RefTex)
ti->m_RefTex->bRepeats = !clamp;
}
mStages[m_TexMan->m_CurStage].Repeat = !clamp;
m_pd3dDevice->SetTextureStageState(m_TexMan->m_CurStage, D3DTSS_ADDRESSU, clamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP);
m_pd3dDevice->SetTextureStageState(m_TexMan->m_CurStage, D3DTSS_ADDRESSV, clamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP);
}
void CD3D8Renderer::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_pd3dDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+m_TexMan->m_CurStage), m);
}
void CD3D8Renderer::ResetTextureMatrix()
{
D3DXMATRIX *mt = &m_TexMatrix[m_TexMan->m_CurStage];
D3DXMatrixIdentity(mt);
m_pd3dDevice->SetTransform((D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0+m_TexMan->m_CurStage), mt);
}
void CD3D8Renderer::RemoveTexture(ITexPic * pTexPic)
{
STexPic * pSTexPic = (STexPic *)pTexPic;
pSTexPic->Release(false);
}
void CD3D8Renderer::RemoveTexture(unsigned int TextureId)
{
CD3D8TexMan *tm = (CD3D8TexMan *)m_TexMan;
TTextureMapItor it = tm->m_RefTexs.find(TextureId);
SRefTex *rt;
if (it == tm->m_RefTexs.end())
return;
rt = it->second;
if (rt->m_SrcTex)
rt->m_SrcTex->Release(false);
else
m_TexMan->RemoveFromHash(TextureId, NULL);
}
unsigned int CD3D8Renderer::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,FT_NOREMOVE, 0, eTT_Base, -1, -1, def_tid);
return pPic->IsTextureLoaded() ? pPic->GetTextureID() : 0;
}
unsigned int CD3D8Renderer::DownLoadToVideoMemory(unsigned char *data,int w, int h, ETEX_Format eTFSrc, ETEX_Format eTFDst, int nummipmap, bool repeat, int filter, int Id)
{
char name[128];
sprintf(name, "$AutoDownload_%d", m_TexGenID++);
int flags = nummipmap ? 0 : FT_NOMIPS;
int DXTSize = 0;
int blockSize = 0;
if (eTFSrc == eTF_DXT1)
{
flags |= FT_DXT1;
blockSize = 8;
}
else
if (eTFSrc == eTF_DXT3)
{
flags |= FT_DXT3;
blockSize = 16;
}
else
if (eTFSrc == 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 (!repeat)
flags |= FT_CLAMP;
STexPic *tp = m_TexMan->CreateTexture(name, w, h, 1, flags, FT2_NODXT, data, eTT_Base, -1.0f, -1.0f, DXTSize, NULL, 0, eTFSrc);
return (tp->m_Bind);
}
void CD3D8Renderer::SetTexture(int tnum, ETexType Type)
{
m_TexMan->SetTexture(tnum, Type);
}
bool CD3D8Renderer::EF_SetLightHole(Vec3d vPos, Vec3d vNormal, int idTex, float fScale, bool bAdditive)
{
return false;
}
bool CD3D8Renderer::SetGammaDelta(const float fGamma)
{
return true;
}
void CD3D8Renderer::GetMemoryUsage(ICrySizer* Sizer)
{
}
void CD3D8Renderer::DrawQuad(float x0, float y0, float x1, float y1, const CFColor & color, float ftx0, float fty0, float ftx1, float fty1)
{
LPDIRECT3DDEVICE8 dv = mfGetD3DDevice();
DWORD col = (DWORD(color.a * 255) << 24) | (DWORD(color.r * 255) << 16) |
(DWORD(color.g * 255)<<8) | DWORD(color.b * 255);
SPipeTRVertex_D_1T *vQuad;
#ifdef _XBOX
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &vQuad, 0);
#else
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &vQuad, D3DLOCK_DISCARD);
#endif
// Define the quad
vQuad[0].dvSX = x0;
vQuad[0].dvSY = y0;
vQuad[0].dvSZ = 1.0f;
vQuad[0].dvRHW = 1.0f;
vQuad[0].dcColor = col;
vQuad[0].dvTU[0] = ftx0;
vQuad[0].dvTU[1] = fty0;
vQuad[1].dvSX = x1;
vQuad[1].dvSY = y0;
vQuad[1].dvSZ = 1.0f;
vQuad[1].dvRHW = 1.0f;
vQuad[1].dcColor = col;
vQuad[1].dvTU[0] = ftx1;
vQuad[1].dvTU[1] = fty0;
vQuad[2].dvSX = x1;
vQuad[2].dvSY = y1;
vQuad[2].dvSZ = 1.0f;
vQuad[2].dvRHW = 1.0f;
vQuad[2].dcColor = col;
vQuad[2].dvTU[0] = ftx1;
vQuad[2].dvTU[1] = fty1;
vQuad[3].dvSX = x0;
vQuad[3].dvSY = y1;
vQuad[3].dvSZ = 1.0f;
vQuad[3].dvRHW = 1.0f;
vQuad[3].dcColor = col;
vQuad[3].dvTU[0] = ftx0;
vQuad[3].dvTU[1] = fty1;
m_pQuadVB->Unlock();
dv->SetStreamSource(0, m_pQuadVB, sizeof(SPipeTRVertex_D_1T));
dv->SetVertexShader((D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1));
dv->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
m_nPolygons += 2;
}
void CD3D8Renderer::DrawQuad3D(const Vec3d & v0, const Vec3d & v1, const Vec3d & v2, const Vec3d & v3,
const CFColor & color, float ftx0, float fty0, float ftx1, float fty1,
float ftx2, float fty2, float ftx3, float fty3)
{
LPDIRECT3DDEVICE8 dv = mfGetD3DDevice();
DWORD col = (DWORD(color.a * 255) << 24) | (DWORD(color.r * 255) << 16) |
(DWORD(color.g * 255)<<8) | DWORD(color.b * 255);
SPipeVertex_D_1T *vQuad;
#ifdef _XBOX
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &vQuad, 0);
#else
HRESULT hr = m_pQuadVB->Lock(0, 0, (BYTE **) &vQuad, D3DLOCK_DISCARD);
#endif
// 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] = ftx2;
vQuad[0].st[3] = fty2;
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] = ftx3;
vQuad[1].st[3] = fty2;
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] = ftx3;
vQuad[2].st[3] = fty3;
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] = ftx2;
vQuad[3].st[3] = fty3;
m_pQuadVB->Unlock();
dv->SetStreamSource(0, m_pQuadVB, STRIDE_D_1T);
dv->SetVertexShader((D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2));
dv->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
m_nPolygons += 2;
}
char* CD3D8Renderer::GetVertexProfile()
{
}
char* CD3D8Renderer::GetPixelProfile()
{
}
//====================================================================
ILog *iLog;
IConsole *iConsole;
ITimer *iTimer;
ISystem *iSystem;
int *pTest_int;
IPhysicalWorld *pIPhysicalWorld;
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 CD3D8Renderer());
#ifdef DEBUGALLOC
#define new DEBUG_CLIENTBLOCK
#endif
srand( GetTickCount() );
return gRenDev;
}
//=========================================================================================