1024 lines
30 KiB
C++
1024 lines
30 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//===========================================================================//
|
|
|
|
#define PROTECTED_THINGS_DISABLE
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
#include "materialsystem/imaterialsystem.h"
|
|
#include "materialsystem/IMaterialSystemHardwareConfig.h"
|
|
#include "materialsystem/imaterialproxyfactory.h"
|
|
#include "filesystem.h"
|
|
#include "bitmap/imageformat.h"
|
|
#include "materialsystem/MaterialSystem_Config.h"
|
|
#include "tier0/icommandline.h"
|
|
#include "tier1/strtools.h"
|
|
#include "mathlib/mathlib.h"
|
|
#include "materialsystem/imesh.h"
|
|
#include "materialsystem/imaterial.h"
|
|
#include "materialsystem/imaterialvar.h"
|
|
#include "bitmap/tgawriter.h"
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <direct.h>
|
|
#include "vstdlib/cvar.h"
|
|
#include "KeyValues.h"
|
|
#include "tier1/utlbuffer.h"
|
|
#include "tier2/tier2.h"
|
|
|
|
#define CHECKERBOARD_DIMS 16
|
|
|
|
IMaterial *g_pProceduralMaterial = NULL;
|
|
|
|
static char g_pCommandLine[1024];
|
|
static int g_ArgC = 0;
|
|
static char* g_ppArgV[32];
|
|
static HWND g_HWnd = 0;
|
|
static CreateInterfaceFn g_MaterialsFactory;
|
|
|
|
static CSysModule *g_MaterialsDLL = NULL;
|
|
|
|
static int g_RenderWidth = 640;
|
|
static int g_RenderHeight = 480;
|
|
static int g_RefreshRate = 60;
|
|
|
|
static bool g_Exiting = false;
|
|
|
|
void CreateLightmapPages( void );
|
|
void RenderFrame( void );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Command-line...
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int FindCommand( const char *pCommand )
|
|
{
|
|
for ( int i = 0; i < g_ArgC; i++ )
|
|
{
|
|
if ( !stricmp( pCommand, g_ppArgV[i] ) )
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
const char* CommandArgument( const char *pCommand )
|
|
{
|
|
int cmd = FindCommand( pCommand );
|
|
if ((cmd != -1) && (cmd < g_ArgC - 1))
|
|
{
|
|
return g_ppArgV[cmd+1];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void SetupCommandLine( const char* pCommandLine )
|
|
{
|
|
Q_strncpy( g_pCommandLine, pCommandLine, sizeof( g_pCommandLine ) );
|
|
|
|
g_ArgC = 0;
|
|
|
|
char* pStr = g_pCommandLine;
|
|
while ( *pStr )
|
|
{
|
|
pStr = strtok( pStr, " " );
|
|
if( !pStr )
|
|
{
|
|
break;
|
|
}
|
|
g_ppArgV[g_ArgC++] = pStr;
|
|
pStr += strlen(pStr) + 1;
|
|
}
|
|
}
|
|
//-----------------------------------------------------------------------------
|
|
// DummyMaterialProxyFactory...
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class DummyMaterialProxyFactory : public IMaterialProxyFactory
|
|
{
|
|
public:
|
|
virtual IMaterialProxy *CreateProxy( const char *proxyName ) {return NULL;}
|
|
virtual void DeleteProxy( IMaterialProxy *pProxy ) {}
|
|
};
|
|
static DummyMaterialProxyFactory g_DummyMaterialProxyFactory;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Spew function!
|
|
//-----------------------------------------------------------------------------
|
|
SpewRetval_t SpewFunc( SpewType_t spewType, char const *pMsg )
|
|
{
|
|
OutputDebugString( pMsg );
|
|
switch( spewType )
|
|
{
|
|
case SPEW_MESSAGE:
|
|
case SPEW_WARNING:
|
|
case SPEW_LOG:
|
|
OutputDebugString( pMsg );
|
|
return SPEW_CONTINUE;
|
|
|
|
case SPEW_ASSERT:
|
|
case SPEW_ERROR:
|
|
default:
|
|
::MessageBox( NULL, pMsg, "Error!", MB_OK );
|
|
return SPEW_DEBUGGER;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Error...
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void DisplayError( const char* pError, ... )
|
|
{
|
|
va_list argptr;
|
|
char msg[1024];
|
|
|
|
va_start( argptr, pError );
|
|
Q_vsnprintf( msg, sizeof( msg ), pError, argptr );
|
|
va_end( argptr );
|
|
|
|
MessageBox( 0, msg, 0, MB_OK );
|
|
}
|
|
|
|
|
|
|
|
IFileSystem *g_pFileSystem;
|
|
static CSysModule *g_pFileSystemModule = NULL;
|
|
static CreateInterfaceFn g_pFileSystemFactory = NULL;
|
|
static bool FileSystem_LoadDLL( void )
|
|
{
|
|
g_pFileSystemModule = Sys_LoadModule( "filesystem_stdio.dll" );
|
|
Assert( g_pFileSystemModule );
|
|
if( !g_pFileSystemModule )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
g_pFileSystemFactory = Sys_GetFactory( g_pFileSystemModule );
|
|
if( !g_pFileSystemFactory )
|
|
{
|
|
return false;
|
|
}
|
|
g_pFileSystem = ( IFileSystem * )g_pFileSystemFactory( FILESYSTEM_INTERFACE_VERSION, NULL );
|
|
Assert( g_pFileSystem );
|
|
if( !g_pFileSystem )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void FileSystem_UnloadDLL( void )
|
|
{
|
|
if ( !g_pFileSystemModule )
|
|
return;
|
|
|
|
Sys_UnloadModule( g_pFileSystemModule );
|
|
g_pFileSystemModule = 0;
|
|
}
|
|
|
|
void FileSystem_Init( )
|
|
{
|
|
if( !FileSystem_LoadDLL() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
g_pFileSystem->RemoveSearchPath( NULL, "GAME" );
|
|
g_pFileSystem->AddSearchPath( "hl2", "GAME", PATH_ADD_TO_HEAD );
|
|
}
|
|
|
|
void FileSystem_Shutdown( void )
|
|
{
|
|
g_pFileSystem->Shutdown();
|
|
|
|
FileSystem_UnloadDLL();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Unloads the material system .dll
|
|
//-----------------------------------------------------------------------------
|
|
void UnloadMaterialSystem( void )
|
|
{
|
|
if ( !g_MaterialsFactory )
|
|
return;
|
|
|
|
Sys_UnloadModule( g_MaterialsDLL );
|
|
g_MaterialsDLL = NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Loads the material system dll
|
|
//-----------------------------------------------------------------------------
|
|
void LoadMaterialSystem( void )
|
|
{
|
|
if( g_MaterialsFactory )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Assert( !g_MaterialsDLL );
|
|
|
|
g_MaterialsDLL = Sys_LoadModule( "MaterialSystem.dll" );
|
|
|
|
g_MaterialsFactory = Sys_GetFactory( g_MaterialsDLL );
|
|
if ( !g_MaterialsFactory )
|
|
{
|
|
DisplayError( "LoadMaterialSystem: Failed to load MaterialSystem.DLL\n" );
|
|
return;
|
|
}
|
|
|
|
if ( g_MaterialsFactory )
|
|
{
|
|
g_pMaterialSystem = (IMaterialSystem *)g_MaterialsFactory( MATERIAL_SYSTEM_INTERFACE_VERSION, NULL );
|
|
if ( !g_pMaterialSystem )
|
|
{
|
|
DisplayError( "Could not get the material system interface from materialsystem.dll (a)" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DisplayError( "Could not find factory interface in library MaterialSystem.dll" );
|
|
}
|
|
}
|
|
|
|
void InitMaterialSystemConfig(MaterialSystem_Config_t *pConfig)
|
|
{
|
|
}
|
|
|
|
CreateInterfaceFn g_MaterialSystemClientFactory;
|
|
void Shader_Init( HWND mainWindow )
|
|
{
|
|
LoadMaterialSystem();
|
|
Assert( g_pMaterialSystem );
|
|
|
|
// FIXME: Where do we put this?
|
|
const char* pDLLName;
|
|
pDLLName = "shaderapidx9";
|
|
|
|
// assume that IFileSystem paths have already been set via g_pFileSystem
|
|
g_MaterialSystemClientFactory = g_pMaterialSystem->Init(
|
|
pDLLName, &g_DummyMaterialProxyFactory, g_pFileSystemFactory, VStdLib_GetICVarFactory() );
|
|
if (!g_MaterialSystemClientFactory)
|
|
{
|
|
DisplayError( "Unable to init shader system\n" );
|
|
}
|
|
|
|
// Get the adapter from the command line....
|
|
MaterialVideoMode_t mode;
|
|
memset( &mode, 0, sizeof( mode ) );
|
|
mode.m_Width = g_RenderWidth;
|
|
mode.m_Height = g_RenderHeight;
|
|
mode.m_Format = IMAGE_FORMAT_BGRX8888;
|
|
mode.m_RefreshRate = g_RefreshRate;
|
|
// bool modeSet = g_pMaterialSystem->SetMode( (void*)mainWindow, mode, modeFlags );
|
|
// if (!modeSet)
|
|
// {
|
|
// DisplayError( "Unable to set mode\n" );
|
|
// }
|
|
|
|
g_pMaterialSystemHardwareConfig = (IMaterialSystemHardwareConfig*)
|
|
g_MaterialSystemClientFactory( MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION, 0 );
|
|
if ( !g_pMaterialSystemHardwareConfig )
|
|
{
|
|
DisplayError( "Could not get the material system hardware config interface!" );
|
|
}
|
|
|
|
MaterialSystem_Config_t config;
|
|
InitMaterialSystemConfig(&config);
|
|
g_pMaterialSystem->OverrideConfig( config, false );
|
|
if( FindCommand( "-stub" ) != -1 )
|
|
{
|
|
g_pMaterialSystem->SetInStubMode( true );
|
|
}
|
|
}
|
|
|
|
void Shader_Shutdown( HWND hwnd )
|
|
{
|
|
// Recursive shutdown
|
|
if ( !g_pMaterialSystem )
|
|
return;
|
|
|
|
g_pMaterialSystem->Shutdown( );
|
|
g_pMaterialSystem = NULL;
|
|
UnloadMaterialSystem();
|
|
}
|
|
|
|
static void CalcWindowSize( int desiredRenderingWidth, int desiredRenderingHeight,
|
|
int *windowWidth, int *windowHeight )
|
|
{
|
|
int borderX, borderY;
|
|
borderX = (GetSystemMetrics(SM_CXFIXEDFRAME) + 1) * 2;
|
|
borderY = (GetSystemMetrics(SM_CYFIXEDFRAME) + 1) * 2 + GetSystemMetrics(SM_CYSIZE) + 1;
|
|
*windowWidth = desiredRenderingWidth + borderX;
|
|
*windowHeight = desiredRenderingHeight + borderY;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Window create, destroy...
|
|
//-----------------------------------------------------------------------------
|
|
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch( msg )
|
|
{
|
|
case WM_PAINT:
|
|
RenderFrame();
|
|
break;
|
|
// abort when ESC is hit
|
|
case WM_CHAR:
|
|
switch(wParam)
|
|
{
|
|
case VK_ESCAPE:
|
|
SendMessage( g_HWnd, WM_CLOSE, 0, 0 );
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
g_Exiting = true;
|
|
PostQuitMessage( 0 );
|
|
return 0;
|
|
}
|
|
|
|
return DefWindowProc( hWnd, msg, wParam, lParam );
|
|
}
|
|
|
|
bool CreateAppWindow( const char* pAppName, int width, int height )
|
|
{
|
|
// Register the window class
|
|
WNDCLASSEX windowClass =
|
|
{
|
|
sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
|
|
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
|
|
pAppName, NULL
|
|
};
|
|
|
|
RegisterClassEx( &windowClass );
|
|
|
|
// Create the application's window
|
|
g_HWnd = CreateWindow( pAppName, pAppName,
|
|
WS_OVERLAPPEDWINDOW,
|
|
0, 0, width, height,
|
|
GetDesktopWindow(), NULL, windowClass.hInstance, NULL );
|
|
|
|
ShowWindow (g_HWnd, SW_SHOWDEFAULT);
|
|
|
|
return (g_HWnd != 0);
|
|
}
|
|
|
|
void DestroyAppWindow()
|
|
{
|
|
if (g_HWnd)
|
|
DestroyWindow( g_HWnd );
|
|
}
|
|
bool Init( const char* pCommands)
|
|
{
|
|
// Store off the command line...
|
|
SetupCommandLine( pCommands );
|
|
FileSystem_Init( );
|
|
|
|
/* figure out g_Renderwidth and g_RenderHeight */
|
|
g_RenderWidth = -1;
|
|
g_RenderHeight = -1;
|
|
|
|
g_RenderWidth = 640;
|
|
g_RenderHeight = 480;
|
|
|
|
int windowWidth, windowHeight;
|
|
CalcWindowSize( g_RenderWidth, g_RenderHeight, &windowWidth, &windowHeight );
|
|
|
|
if( !CreateAppWindow( "matsys_regressiontest", windowWidth, windowHeight ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Shader_Init( g_HWnd );
|
|
g_pMaterialSystem->CacheUsedMaterials();
|
|
CreateLightmapPages();
|
|
return true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Return the directory where this .exe is running from
|
|
// Output : char
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static char *GetBaseDir( const char *pszBuffer )
|
|
{
|
|
static char basedir[ MAX_PATH ];
|
|
char szBuffer[ MAX_PATH ];
|
|
int j;
|
|
char *pBuffer = NULL;
|
|
|
|
Q_strncpy( szBuffer, pszBuffer, sizeof( szBuffer ) );
|
|
|
|
pBuffer = strrchr( szBuffer,'\\' );
|
|
if ( pBuffer )
|
|
{
|
|
*(pBuffer+1) = '\0';
|
|
}
|
|
|
|
Q_strncpy( basedir, szBuffer, sizeof( basedir ) );
|
|
|
|
j = strlen( basedir );
|
|
if (j > 0)
|
|
{
|
|
if ( ( basedir[ j-1 ] == '\\' ) ||
|
|
( basedir[ j-1 ] == '/' ) )
|
|
{
|
|
basedir[ j-1 ] = 0;
|
|
}
|
|
}
|
|
|
|
return basedir;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Shutdown
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void Shutdown()
|
|
{
|
|
// Close the window
|
|
DestroyAppWindow();
|
|
|
|
Shader_Shutdown( g_HWnd );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Pump windows messages
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void PumpWindowsMessages ()
|
|
{
|
|
MSG msg;
|
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
InvalidateRect(g_HWnd, NULL, false);
|
|
UpdateWindow(g_HWnd);
|
|
}
|
|
|
|
MaterialSystem_SortInfo_t *g_pMaterialSortInfo = NULL;
|
|
struct LightmapInfo_t
|
|
{
|
|
int m_LightmapDims[2];
|
|
int m_LightmapPageDims[2];
|
|
int m_OffsetIntoLightmapPage[2];
|
|
int m_SortID;
|
|
};
|
|
|
|
LightmapInfo_t g_CheckerboardLightmapInfo;
|
|
|
|
void AllocateLightmap( LightmapInfo_t& lightmapInfo, int width, int height )
|
|
{
|
|
lightmapInfo.m_LightmapDims[0] = width;
|
|
lightmapInfo.m_LightmapDims[1] = height;
|
|
// HACK! We don't ever use this material for anything. . just need it for allocating lightmaps.
|
|
CMatRenderContextPtr pRenderContext( materials );
|
|
IMaterial *pHackMaterial = g_pMaterialSystem->FindMaterial( "shadertest/lightmappedgeneric", TEXTURE_GROUP_OTHER );
|
|
pRenderContext->Bind( pHackMaterial );
|
|
lightmapInfo.m_SortID =
|
|
g_pMaterialSystem->AllocateLightmap( 16, 16, lightmapInfo.m_OffsetIntoLightmapPage, pHackMaterial );
|
|
}
|
|
|
|
void Lightmap_PostAllocation( LightmapInfo_t& lightmapInfo )
|
|
{
|
|
g_pMaterialSystem->GetLightmapPageSize( lightmapInfo.m_SortID,
|
|
&lightmapInfo.m_LightmapPageDims[0], &lightmapInfo.m_LightmapPageDims[1] );
|
|
}
|
|
|
|
void UpdateLightmap( LightmapInfo_t& lightmapInfo, float *data )
|
|
{
|
|
g_pMaterialSystem->UpdateLightmap( g_pMaterialSortInfo[lightmapInfo.m_SortID].lightmapPageID,
|
|
lightmapInfo.m_LightmapDims, lightmapInfo.m_OffsetIntoLightmapPage, data, NULL, NULL, NULL );
|
|
}
|
|
|
|
void CreateLightmapPages( void )
|
|
{
|
|
g_pMaterialSystem->BeginLightmapAllocation();
|
|
|
|
AllocateLightmap( g_CheckerboardLightmapInfo, CHECKERBOARD_DIMS, CHECKERBOARD_DIMS );
|
|
|
|
g_pMaterialSystem->EndLightmapAllocation();
|
|
int numSortIDs = g_pMaterialSystem->GetNumSortIDs();
|
|
g_pMaterialSortInfo = new MaterialSystem_SortInfo_t[numSortIDs];
|
|
g_pMaterialSystem->GetSortInfo( g_pMaterialSortInfo );
|
|
|
|
Lightmap_PostAllocation( g_CheckerboardLightmapInfo );
|
|
|
|
float checkerboardImage[CHECKERBOARD_DIMS*CHECKERBOARD_DIMS*4];
|
|
int x, y;
|
|
for( y = 0; y < CHECKERBOARD_DIMS; y++ )
|
|
{
|
|
for( x = 0; x < CHECKERBOARD_DIMS; x++ )
|
|
{
|
|
if( ( x + y ) & 1 )
|
|
{
|
|
checkerboardImage[(y*CHECKERBOARD_DIMS+x)*4+0] = 1.0f;
|
|
checkerboardImage[(y*CHECKERBOARD_DIMS+x)*4+1] = 1.0f;
|
|
checkerboardImage[(y*CHECKERBOARD_DIMS+x)*4+2] = 1.0f;
|
|
checkerboardImage[(y*CHECKERBOARD_DIMS+x)*4+3] = 1.0f;
|
|
}
|
|
else
|
|
{
|
|
checkerboardImage[(y*CHECKERBOARD_DIMS+x)*4+0] = 0.0f;
|
|
checkerboardImage[(y*CHECKERBOARD_DIMS+x)*4+1] = 0.0f;
|
|
checkerboardImage[(y*CHECKERBOARD_DIMS+x)*4+2] = 0.0f;
|
|
checkerboardImage[(y*CHECKERBOARD_DIMS+x)*4+3] = 1.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
UpdateLightmap( g_CheckerboardLightmapInfo, checkerboardImage );
|
|
}
|
|
|
|
void LightmapTexCoord( CMeshBuilder& meshBuilder, LightmapInfo_t lightmapInfo, float s, float t )
|
|
{
|
|
// add a one texel border.
|
|
float newS = ( s * ( lightmapInfo.m_LightmapDims[0] - 2 ) ) + 1;
|
|
float newT = ( t * ( lightmapInfo.m_LightmapDims[1] - 2 ) ) + 1;
|
|
newS += lightmapInfo.m_OffsetIntoLightmapPage[0];
|
|
newT += lightmapInfo.m_OffsetIntoLightmapPage[1];
|
|
newS *= 1.0f / lightmapInfo.m_LightmapPageDims[0];
|
|
newT *= 1.0f / lightmapInfo.m_LightmapPageDims[1];
|
|
meshBuilder.TexCoord2f( 1, newS, newT );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Update
|
|
//-----------------------------------------------------------------------------
|
|
bool Update()
|
|
{
|
|
PumpWindowsMessages();
|
|
return g_Exiting;
|
|
}
|
|
|
|
void ScreenShot( const char *pFilename )
|
|
{
|
|
// bitmap bits
|
|
unsigned char *pImage = ( unsigned char * )malloc( g_RenderWidth * 3 * g_RenderHeight );
|
|
|
|
// Get Bits from the material system
|
|
CMatRenderContextPtr pRenderContext( materials );
|
|
pRenderContext->ReadPixels( 0, 0, g_RenderWidth, g_RenderHeight, pImage, IMAGE_FORMAT_RGB888 );
|
|
|
|
CUtlBuffer outBuf;
|
|
if( !TGAWriter::WriteToBuffer( pImage, outBuf, g_RenderWidth, g_RenderHeight, IMAGE_FORMAT_RGB888,
|
|
IMAGE_FORMAT_RGB888 ) )
|
|
{
|
|
Error( "Couldn't write %s\n", pFilename );
|
|
}
|
|
if ( !g_pFullFileSystem->WriteFile( pFilename, NULL, outBuf ) )
|
|
{
|
|
Error( "Couldn't write %s\n", pFilename );
|
|
}
|
|
|
|
free( pImage );
|
|
}
|
|
|
|
void SetVar( const char *pVarName, const char *pStringValue )
|
|
{
|
|
IMaterialVar *pVar = g_pProceduralMaterial->FindVar( pVarName, NULL );
|
|
if( pStringValue )
|
|
{
|
|
pVar->SetStringValue( pStringValue );
|
|
}
|
|
else
|
|
{
|
|
pVar->SetUndefined();
|
|
}
|
|
}
|
|
|
|
void SetVar( const char *pVarName, int val )
|
|
{
|
|
IMaterialVar *pVar = g_pProceduralMaterial->FindVar( pVarName, NULL );
|
|
pVar->SetIntValue( val );
|
|
}
|
|
|
|
void SetFlag( MaterialVarFlags_t flag, int val )
|
|
{
|
|
g_pProceduralMaterial->SetMaterialVarFlag( flag, val ? true : false );
|
|
}
|
|
|
|
void DrawBackground( void )
|
|
{
|
|
CMatRenderContextPtr pRenderContext( materials );
|
|
IMaterial *pMaterial = g_pMaterialSystem->FindMaterial( "matsys_regressiontest/background", TEXTURE_GROUP_OTHER );
|
|
pRenderContext->Bind( pMaterial );
|
|
|
|
IMesh *pMesh = pRenderContext->GetDynamicMesh();
|
|
CMeshBuilder meshBuilder;
|
|
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
|
|
|
|
#define X 500.0f
|
|
#define Y 500.0f
|
|
#define Z -500.0f
|
|
|
|
meshBuilder.Position3f( -X, Y, Z );
|
|
meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
|
|
meshBuilder.AdvanceVertex();
|
|
|
|
meshBuilder.Position3f( X, Y, Z );
|
|
meshBuilder.TexCoord2f( 0, 1.0f, 0.0f );
|
|
meshBuilder.AdvanceVertex();
|
|
|
|
meshBuilder.Position3f( X, -Y, Z );
|
|
meshBuilder.TexCoord2f( 0, 1.0f, 1.0f );
|
|
meshBuilder.AdvanceVertex();
|
|
|
|
meshBuilder.Position3f( -X, -Y, Z );
|
|
meshBuilder.TexCoord2f( 0, 0.0f, 1.0f );
|
|
meshBuilder.AdvanceVertex();
|
|
|
|
meshBuilder.End();
|
|
pMesh->Draw();
|
|
|
|
#undef X
|
|
#undef Y
|
|
#undef Z
|
|
}
|
|
|
|
void BeginFrame( void )
|
|
{
|
|
g_pMaterialSystem->BeginFrame( 0 );
|
|
|
|
CMatRenderContextPtr pRenderContext( materials );
|
|
pRenderContext->ClearColor3ub( 255, 0, 0 );
|
|
pRenderContext->ClearBuffers( true, true );
|
|
pRenderContext->Viewport( 0, 0, g_RenderWidth, g_RenderHeight );
|
|
|
|
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
|
pRenderContext->LoadIdentity();
|
|
pRenderContext->PerspectiveX( 90.0f, ( g_RenderWidth / g_RenderHeight), 1.0f, 500000.0f );
|
|
|
|
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
|
pRenderContext->LoadIdentity();
|
|
|
|
pRenderContext->MatrixMode( MATERIAL_MODEL );
|
|
pRenderContext->LoadIdentity();
|
|
}
|
|
|
|
void EndFrame( void )
|
|
{
|
|
g_pMaterialSystem->EndFrame();
|
|
g_pMaterialSystem->SwapBuffers();
|
|
}
|
|
|
|
void DrawQuad( const LightmapInfo_t& lightmapInfo )
|
|
{
|
|
CMatRenderContextPtr pRenderContext( materials );
|
|
pRenderContext->BindLightmapPage( g_pMaterialSortInfo[lightmapInfo.m_SortID].lightmapPageID );
|
|
|
|
pRenderContext->Bind( g_pProceduralMaterial );
|
|
|
|
IMesh *pMesh = pRenderContext->GetDynamicMesh();
|
|
CMeshBuilder meshBuilder;
|
|
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
|
|
|
|
#define X 350.0f
|
|
#define Y (X*(4.0f/3.0f))
|
|
#define Z -500.0f
|
|
|
|
meshBuilder.Position3f( -X, Y, Z );
|
|
meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
|
|
LightmapTexCoord( meshBuilder, lightmapInfo, 0.0f, 0.0f );
|
|
meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
|
|
meshBuilder.Color4f( 1.0f, 0.0f, 0.0f, 1.0f );
|
|
meshBuilder.AdvanceVertex();
|
|
|
|
meshBuilder.Position3f( X, Y, Z );
|
|
meshBuilder.TexCoord2f( 0, 1.0f, 0.0f );
|
|
LightmapTexCoord( meshBuilder, lightmapInfo, 1.0f, 0.0f );
|
|
meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
|
|
meshBuilder.Color4f( 1.0f, 1.0f, 0.0f, 1.0f );
|
|
meshBuilder.AdvanceVertex();
|
|
|
|
meshBuilder.Position3f( X, -Y, Z );
|
|
meshBuilder.TexCoord2f( 0, 1.0f, 1.0f );
|
|
LightmapTexCoord( meshBuilder, lightmapInfo, 1.0f, 1.0f );
|
|
meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
|
|
meshBuilder.Color4f( 1.0f, 1.0f, 1.0f, 0.0f );
|
|
meshBuilder.AdvanceVertex();
|
|
|
|
meshBuilder.Position3f( -X, -Y, Z );
|
|
meshBuilder.TexCoord2f( 0, 0.0f, 1.0f );
|
|
LightmapTexCoord( meshBuilder, lightmapInfo, 0.0f, 1.0f );
|
|
meshBuilder.Normal3f( 0.0f, 0.0f, 1.0f );
|
|
meshBuilder.Color4f( 0.0f, 1.0f, 1.0f, 1.0f );
|
|
meshBuilder.AdvanceVertex();
|
|
|
|
meshBuilder.End();
|
|
pMesh->Draw();
|
|
|
|
#undef X
|
|
#undef Y
|
|
#undef Z
|
|
}
|
|
|
|
void TestLightmappedGeneric_dx80( void )
|
|
{
|
|
/*
|
|
based on lightmappedgeneric_vs11.fxc:
|
|
// STATIC: "DETAIL" "0..1"
|
|
// STATIC: "ENVMAP" "0..1"
|
|
// STATIC: "ENVMAPCAMERASPACE" "0..1"
|
|
// STATIC: "ENVMAPSPHERE" "0..1"
|
|
// STATIC: "VERTEXCOLOR" "0..1"
|
|
// DYNAMIC: "FOGTYPE" "0..1"
|
|
|
|
// SKIP: $ENVMAPCAMERASPACE && $ENVMAPSPHERE
|
|
// SKIP: !$ENVMAP && ( $ENVMAPCAMERASPACE || $ENVMAPSPHERE )
|
|
|
|
based on lightmappedgeneric_ps11.fxc:
|
|
// STATIC: "BASETEXTURE" "0..1"
|
|
// STATIC: "ENVMAP" "0..1"
|
|
// STATIC: "ENVMAPMASK" "0..1"
|
|
// STATIC: "SELFILLUM" "0..1"
|
|
// STATIC: "BASEALPHAENVMAPMASK" "0..1"
|
|
|
|
// SKIP: !$ENVMAP && ( $BASEALPHAENVMAPMASK || $ENVMAPMASK )
|
|
// SKIP: !$BASETEXTURE && $BASEALPHAENVMAPMASK
|
|
// SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK
|
|
// SKIP: !$BASETEXTURE && $BASEALPHAENVMAPMASK
|
|
// SKIP: $SELFILLUM && $BASEALPHAENVMAPMASK
|
|
// SKIP: !$BASETEXTURE && $SELFILLUM
|
|
|
|
|
|
Versions with DETAIL aren't implemented yet in HLSL, but we'll go ahead and test those.
|
|
*/
|
|
// The following are shader combos from lightmappedgeneric_ps20
|
|
for( int BUMPMAP = 0; BUMPMAP <= 1; BUMPMAP++ )
|
|
{
|
|
for( int NORMALMAPALPHAENVMAPMASK = 0; NORMALMAPALPHAENVMAPMASK <= 1; NORMALMAPALPHAENVMAPMASK++ )
|
|
{
|
|
// The following are shader combos from lightmappedgeneric_ps11 (that aren't in lightmappedgenerc_vs11)
|
|
for( int BASETEXTURE = 0; BASETEXTURE <= 1; BASETEXTURE++ )
|
|
{
|
|
for( int ENVMAPMASK = 0; ENVMAPMASK <= 1; ENVMAPMASK++ )
|
|
{
|
|
for( int SELFILLUM = 0; SELFILLUM <= 1; SELFILLUM++ )
|
|
{
|
|
for( int BASEALPHAENVMAPMASK = 0; BASEALPHAENVMAPMASK <= 1; BASEALPHAENVMAPMASK++ )
|
|
{
|
|
// The following are shader combos from lightmappedgeneric_vs11
|
|
for( int DETAIL = 0; DETAIL <= 1; DETAIL++ )
|
|
{
|
|
for( int ENVMAP = 0; ENVMAP <= 1; ENVMAP++ )
|
|
{
|
|
for( int ENVMAPCAMERASPACE = 0; ENVMAPCAMERASPACE <= 1; ENVMAPCAMERASPACE++ )
|
|
{
|
|
for( int ENVMAPSPHERE = 0; ENVMAPSPHERE <= 1; ENVMAPSPHERE++ )
|
|
{
|
|
for( int VERTEXCOLOR = 0; VERTEXCOLOR <= 1; VERTEXCOLOR++ )
|
|
{
|
|
// for( int FOGTYPE = 0; FOGTYPE <= 1; FOGTYPE++ )
|
|
{
|
|
// conditional beneath here are flags, not shader combos
|
|
for( int ALPHATEST = 0; ALPHATEST <= 1; ALPHATEST++ )
|
|
{
|
|
for( int TRANSLUCENT = 0; TRANSLUCENT <= 1; TRANSLUCENT++ )
|
|
{
|
|
for( int COLORMODULATE = 0; COLORMODULATE <= 1; COLORMODULATE++ )
|
|
{
|
|
for( int ALPHAMODULATE = 0; ALPHAMODULATE <= 1; ALPHAMODULATE++ )
|
|
{
|
|
#if 0
|
|
BUMPMAP = 0;
|
|
NORMALMAPALPHAENVMAPMASK = 0;
|
|
BASETEXTURE = 1;
|
|
ENVMAPMASK = 0;
|
|
SELFILLUM = 0;
|
|
BASEALPHAENVMAPMASK = 1;
|
|
DETAIL = 0;
|
|
ENVMAP = 1;
|
|
ENVMAPCAMERASPACE = 0;
|
|
ENVMAPSPHERE = 0;
|
|
VERTEXCOLOR = 0;
|
|
ALPHATEST = 0;
|
|
TRANSLUCENT = 0;
|
|
COLORMODULATE = 0;
|
|
ALPHAMODULATE = 0;
|
|
#endif
|
|
// skip commands from shader lightmappedgeneric_vs11
|
|
if( ENVMAPCAMERASPACE && ENVMAPSPHERE ) continue;
|
|
if( !ENVMAP && ( ENVMAPCAMERASPACE || ENVMAPSPHERE ) ) continue;
|
|
|
|
// skip commands from shader lihgtmappedgeneric_ps11
|
|
if( !ENVMAP && ( BASEALPHAENVMAPMASK || ENVMAPMASK ) ) continue;
|
|
if( !BASETEXTURE && BASEALPHAENVMAPMASK ) continue;
|
|
if( BASEALPHAENVMAPMASK && ENVMAPMASK ) continue;
|
|
if( !BASETEXTURE && BASEALPHAENVMAPMASK ) continue;
|
|
if( SELFILLUM && BASEALPHAENVMAPMASK ) continue;
|
|
if( !BASETEXTURE && SELFILLUM ) continue;
|
|
|
|
// skip commands from shader lightmappedgeneric_ps20
|
|
if( DETAIL && BUMPMAP ) continue;
|
|
if( ENVMAPMASK && BUMPMAP ) continue;
|
|
if( NORMALMAPALPHAENVMAPMASK && BASEALPHAENVMAPMASK ) continue;
|
|
if( NORMALMAPALPHAENVMAPMASK && ENVMAPMASK ) continue;
|
|
if( BASEALPHAENVMAPMASK && ENVMAPMASK ) continue;
|
|
if( BASEALPHAENVMAPMASK && SELFILLUM ) continue;
|
|
|
|
// skip commands from flags that don't make sense (or we don't want to test)
|
|
if( !BASETEXTURE && ( ALPHATEST || TRANSLUCENT ) ) continue;
|
|
if( TRANSLUCENT && ALPHATEST ) continue;
|
|
|
|
KeyValues *pKeyValues = new KeyValues( "lightmappedgeneric" );
|
|
if ( BASETEXTURE )
|
|
{
|
|
pKeyValues->SetString( "$basetexture", "matsys_regressiontest/basetexture" );
|
|
}
|
|
if ( ENVMAPMASK )
|
|
{
|
|
pKeyValues->SetString( "$envmapmask", "matsys_regressiontest/specularmask" );
|
|
}
|
|
if ( SELFILLUM )
|
|
{
|
|
pKeyValues->SetInt( "$selfillum", 1 );
|
|
}
|
|
if ( BASEALPHAENVMAPMASK )
|
|
{
|
|
pKeyValues->SetInt( "$basealphaenvmapmask", 1 );
|
|
}
|
|
if ( BUMPMAP )
|
|
{
|
|
pKeyValues->SetString( "$bumpmap", "matsys_regressiontest/normalmap_normal" );
|
|
}
|
|
if ( DETAIL )
|
|
{
|
|
pKeyValues->SetString( "$detail", "matsys_regressiontest/detail" );
|
|
pKeyValues->SetFloat( "$detailscale", 0.5f );
|
|
}
|
|
if ( ENVMAP )
|
|
{
|
|
pKeyValues->SetString( "$envmap", "matsys_regressiontest/cubemap" );
|
|
}
|
|
if ( BASEALPHAENVMAPMASK )
|
|
{
|
|
pKeyValues->SetInt( "$basealphaenvmapmask", 1 );
|
|
}
|
|
if ( NORMALMAPALPHAENVMAPMASK )
|
|
{
|
|
pKeyValues->SetInt( "$normalmapalphaenvmapmask", 1 );
|
|
}
|
|
if ( TRANSLUCENT )
|
|
{
|
|
pKeyValues->SetInt( "$translucent", 1 );
|
|
}
|
|
if ( ENVMAPCAMERASPACE )
|
|
{
|
|
pKeyValues->SetInt( "$envmapcameraspace", 1 );
|
|
}
|
|
if ( ENVMAPSPHERE )
|
|
{
|
|
pKeyValues->SetInt( "$envmapsphere", 1 );
|
|
}
|
|
if ( VERTEXCOLOR )
|
|
{
|
|
pKeyValues->SetInt( "$vertexcolor", 1 );
|
|
}
|
|
if ( ALPHATEST )
|
|
{
|
|
pKeyValues->SetInt( "$alphatest", 1 );
|
|
}
|
|
if ( COLORMODULATE )
|
|
{
|
|
pKeyValues->SetString( "$color", "[1.0 0.8 0.5]" );
|
|
}
|
|
if ( ALPHAMODULATE )
|
|
{
|
|
pKeyValues->SetFloat( "$alpha", 0.6f );
|
|
}
|
|
|
|
// FIXME: ignoring fogtype for now.
|
|
// hack hack - LEAK - need to figure out how to clear a material out.
|
|
g_pProceduralMaterial = g_pMaterialSystem->CreateMaterial( "test", pKeyValues );
|
|
g_pProceduralMaterial->Refresh();
|
|
|
|
BeginFrame();
|
|
DrawBackground();
|
|
DrawQuad( g_CheckerboardLightmapInfo );
|
|
EndFrame();
|
|
char filename[MAX_PATH];
|
|
sprintf( filename, "%s\\lightmappedgeneric_dx80", CommandLine()->ParmValue( "-targetdir" ) );
|
|
|
|
if( BUMPMAP ) Q_strcat( filename, "_BUMPMAP", sizeof(filename) );
|
|
if( NORMALMAPALPHAENVMAPMASK ) Q_strcat( filename, "_NORMALMAPALPHAENVMAPMASK", sizeof(filename) );
|
|
|
|
if( BASETEXTURE ) Q_strcat( filename, "_BASE", sizeof(filename) );
|
|
if( ENVMAPMASK ) Q_strcat( filename, "_ENVMAPMASK", sizeof(filename) );
|
|
if( SELFILLUM ) Q_strcat( filename, "_SELFILLUM", sizeof(filename) );
|
|
if( BASEALPHAENVMAPMASK ) Q_strcat( filename, "_BASEALPHAENVMAPMASK", sizeof(filename) );
|
|
|
|
if( DETAIL ) Q_strcat( filename, "_DETAIL", sizeof(filename) );
|
|
if( ENVMAP ) Q_strcat( filename, "_ENVMAP", sizeof(filename) );
|
|
if( ENVMAPCAMERASPACE ) Q_strcat( filename, "_ENVMAPCAMERASPACE", sizeof(filename) );
|
|
if( ENVMAPSPHERE ) Q_strcat( filename, "_ENVMAPSPHERE", sizeof(filename) );
|
|
if( VERTEXCOLOR ) Q_strcat( filename, "_VERTEXCOLOR", sizeof(filename) );
|
|
// if( FOGTYPE ) Q_strcat( filename, "_FOGTYPE", sizeof(filename) );
|
|
if( ALPHATEST ) Q_strcat( filename, "_ALPHATEST", sizeof(filename) );
|
|
if( TRANSLUCENT ) Q_strcat( filename, "_TRANSLUCENT", sizeof(filename) );
|
|
if( COLORMODULATE ) Q_strcat( filename, "_COLORMODULATE", sizeof(filename) );
|
|
if( ALPHAMODULATE ) Q_strcat( filename, "_ALPHAMODULATE", sizeof(filename) );
|
|
|
|
if( BUMPMAP ) Q_strcat( filename, "_BUMPMAP", sizeof(filename) );
|
|
Q_strcat( filename, ".tga", sizeof(filename) );
|
|
ScreenShot( filename );
|
|
|
|
g_pProceduralMaterial->DecrementReferenceCount();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Render a frame
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void RenderFrame( void )
|
|
{
|
|
TestLightmappedGeneric_dx80();
|
|
}
|
|
|
|
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hInstance, LPSTR pCommands, INT )
|
|
{
|
|
SpewOutputFunc( SpewFunc );
|
|
CommandLine()->CreateCmdLine( ::GetCommandLine() );
|
|
InitDefaultFileSystem();
|
|
|
|
if( !CommandLine()->ParmValue( "-targetdir" ) )
|
|
{
|
|
Error( "Must specify -targetdir on command line!\n" );
|
|
}
|
|
|
|
struct _stat statbuf;
|
|
if( 0 != _stat( CommandLine()->ParmValue( "-targetdir" ), &statbuf ) )
|
|
{
|
|
if( 0 != _mkdir( CommandLine()->ParmValue( "-targetdir" ) ) )
|
|
{
|
|
Error( "Couldn't create path %s\n", CommandLine()->ParmValue( "-targetdir" ) );
|
|
}
|
|
}
|
|
|
|
// Must add 'bin' to the path....
|
|
char* pPath = getenv("PATH");
|
|
|
|
// Use the .EXE name to determine the root directory
|
|
char moduleName[ MAX_PATH ];
|
|
char szBuffer[ 4096 ];
|
|
if ( !GetModuleFileName( hInstance, moduleName, MAX_PATH ) )
|
|
{
|
|
MessageBox( 0, "Failed calling GetModuleFileName", "Launcher Error", MB_OK );
|
|
return 0;
|
|
}
|
|
|
|
// Get the root directory the .exe is in
|
|
char* pRootDir = GetBaseDir( moduleName );
|
|
|
|
#ifdef DBGFLAG_ASSERT
|
|
int len =
|
|
#endif
|
|
|
|
Q_snprintf( szBuffer, sizeof( szBuffer ), "PATH=%s;%s", pRootDir, pPath );
|
|
Assert( len < 4096 );
|
|
_putenv( szBuffer );
|
|
|
|
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
|
|
|
|
if (!Init( pCommands ) )
|
|
return false;
|
|
|
|
/*
|
|
bool done = false;
|
|
while( !done )
|
|
{
|
|
done = Update();
|
|
}
|
|
*/
|
|
RenderFrame();
|
|
Shutdown();
|
|
|
|
return 0;
|
|
}
|
|
|