mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-26 22:11:51 +00:00
added /imageinfo and /shadermixeduse
This commit is contained in:
parent
d43a016e61
commit
cfdba32b24
6 changed files with 193 additions and 26 deletions
|
@ -4,6 +4,10 @@ See the end of this file for known issues.
|
|||
|
||||
DD Mmm 20 - 1.53
|
||||
|
||||
add: /imageinfo <imagepath> prints where the image was loaded from and shaders that reference it
|
||||
|
||||
add: /shadermixeduse prints all images referenced in shaders with conflicting global directives
|
||||
|
||||
add: cl_demoPlayer <0|1> (default: 1) selects the demo playback system to use
|
||||
cl_demoPlayer 0 = always uses the original demo player
|
||||
cl_demoPlayer 1 = uses the new demo player with time rewind support when the mod supports it
|
||||
|
|
|
@ -134,6 +134,45 @@ void R_ImageList_f( void )
|
|||
}
|
||||
|
||||
|
||||
void R_ImageInfo_f()
|
||||
{
|
||||
if ( Cmd_Argc() <= 1 ) {
|
||||
ri.Printf( PRINT_ALL, "usage: %s <imagepath>\n", Cmd_Argv(0) );
|
||||
return;
|
||||
}
|
||||
|
||||
const char* const name = Cmd_Argv(1);
|
||||
const image_t* image = NULL;
|
||||
for ( int i = 0; i < tr.numImages; i++ ) {
|
||||
if ( !Q_stricmp( tr.images[i]->name, name ) ) {
|
||||
image = tr.images[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char pakName[256];
|
||||
if ( FS_GetPakPath( pakName, sizeof( pakName ), image->pakChecksum ) ) {
|
||||
ri.Printf( PRINT_ALL, "%s/%s\n", pakName, image->name );
|
||||
}
|
||||
|
||||
ri.Printf( PRINT_ALL, "Used in these shaders:\n" );
|
||||
for ( int s = 0; s < image->numShaders; ++s ) {
|
||||
const shader_t* const shader = tr.imageShaders[image->firstShaderIndex + s];
|
||||
const qbool nmmS = shader->imgflags & IMG_NOMIPMAP;
|
||||
const qbool npmS = shader->imgflags & IMG_NOPICMIP;
|
||||
ri.Printf( PRINT_ALL, "%s %s %s\n",
|
||||
nmmS ? "NMM" : " ",
|
||||
npmS ? "NPM" : " ",
|
||||
shader->name );
|
||||
|
||||
const char* const shaderPath = R_GetShaderPath( shader );
|
||||
if ( shaderPath != NULL ) {
|
||||
ri.Printf( PRINT_ALL, " -> %s\n", shaderPath );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
@ -726,7 +765,7 @@ static const imageLoader_t imageLoaders[] = {
|
|||
};
|
||||
|
||||
|
||||
static void R_LoadImage( const char* name, byte** pic, int* w, int* h, textureFormat_t* format )
|
||||
static void R_LoadImage( int* pakChecksum, const char* name, byte** pic, int* w, int* h, textureFormat_t* format )
|
||||
{
|
||||
*pic = NULL;
|
||||
*w = 0;
|
||||
|
@ -736,7 +775,7 @@ static void R_LoadImage( const char* name, byte** pic, int* w, int* h, textureFo
|
|||
char altName[MAX_QPATH];
|
||||
|
||||
byte* buffer;
|
||||
int bufferSize = ri.FS_ReadFile( name, (void**)&buffer );
|
||||
int bufferSize = ri.FS_ReadFilePak( name, (void**)&buffer, pakChecksum );
|
||||
if ( buffer == NULL ) {
|
||||
const char* lastDot = strrchr( name, '.' );
|
||||
const int nameLength = lastDot != NULL ? (int)(lastDot - name) : (int)strlen( name );
|
||||
|
@ -747,7 +786,7 @@ static void R_LoadImage( const char* name, byte** pic, int* w, int* h, textureFo
|
|||
memcpy( altName, name, nameLength );
|
||||
altName[nameLength] = '\0';
|
||||
Q_strcat( altName, sizeof(altName), imageLoaders[i].extension );
|
||||
bufferSize = ri.FS_ReadFile( altName, (void**)&buffer );
|
||||
bufferSize = ri.FS_ReadFilePak( altName, (void**)&buffer, pakChecksum );
|
||||
if ( buffer != NULL ) {
|
||||
name = altName;
|
||||
break;
|
||||
|
@ -786,7 +825,7 @@ static const forcedLoadImage_t g_forcedLoadImages[] = {
|
|||
|
||||
// finds or loads the given image - returns NULL if it fails, not a default image
|
||||
|
||||
const image_t* R_FindImageFile( const char* name, int flags, textureWrap_t glWrapClampMode )
|
||||
image_t* R_FindImageFile( const char* name, int flags, textureWrap_t glWrapClampMode )
|
||||
{
|
||||
if ( !name )
|
||||
return NULL;
|
||||
|
@ -837,14 +876,15 @@ const image_t* R_FindImageFile( const char* name, int flags, textureWrap_t glWra
|
|||
// load the pic from disk
|
||||
//
|
||||
byte* pic;
|
||||
int width, height;
|
||||
int width, height, pakChecksum;
|
||||
textureFormat_t format;
|
||||
R_LoadImage( name, &pic, &width, &height, &format );
|
||||
R_LoadImage( &pakChecksum, name, &pic, &width, &height, &format );
|
||||
|
||||
if ( !pic )
|
||||
return NULL;
|
||||
|
||||
image_t* const image = R_CreateImage( name, pic, width, height, format, flags, glWrapClampMode );
|
||||
image->pakChecksum = pakChecksum;
|
||||
ri.Free( pic );
|
||||
return image;
|
||||
}
|
||||
|
@ -1128,3 +1168,25 @@ void R_SkinList_f( void )
|
|||
ri.Printf( PRINT_ALL, "%i skins found\n", skinCount );
|
||||
ri.Printf( PRINT_ALL, "------------------\n" );
|
||||
}
|
||||
|
||||
|
||||
void R_AddImageShader( image_t* image, shader_t* shader )
|
||||
{
|
||||
assert( shader != NULL );
|
||||
if (image == NULL || shader == NULL)
|
||||
return;
|
||||
|
||||
assert( tr.numImageShaders < ARRAY_LEN( tr.imageShaders ) );
|
||||
if (tr.numImageShaders >= ARRAY_LEN( tr.imageShaders ))
|
||||
return;
|
||||
|
||||
// we consider index 0 to be invalid
|
||||
if (tr.numImageShaders == 0)
|
||||
tr.numImageShaders++;
|
||||
|
||||
tr.imageShaders[tr.numImageShaders] = shader;
|
||||
if (image->firstShaderIndex == 0)
|
||||
image->firstShaderIndex = tr.numImageShaders;
|
||||
image->numShaders++;
|
||||
tr.numImageShaders++;
|
||||
}
|
||||
|
|
|
@ -339,8 +339,10 @@ static const cmdTableItem_t r_cmds[] =
|
|||
{
|
||||
{ "gfxinfo", GfxInfo_f, NULL, "prints display mode info" },
|
||||
{ "imagelist", R_ImageList_f, NULL, "prints loaded images" },
|
||||
{ "imageinfo", R_ImageInfo_f, NULL, "prints info for a specific image" },
|
||||
{ "shaderlist", R_ShaderList_f, NULL, "prints loaded shaders" },
|
||||
{ "shaderinfo", R_ShaderInfo_f, R_CompleteShaderName_f, "prints info for a specific shader" },
|
||||
{ "shadermixeduse", R_MixedUse_f, NULL, "prints all mixed use issues" },
|
||||
{ "skinlist", R_SkinList_f, NULL, "prints loaded skins" },
|
||||
{ "modellist", R_Modellist_f, NULL, "prints loaded models" },
|
||||
{ "screenshot", R_ScreenShotTGA_f, NULL, "takes a TARGA (.tga) screenshot" },
|
||||
|
|
|
@ -87,6 +87,8 @@ typedef unsigned int textureHandle_t; // what this number actually means is up t
|
|||
#define MAX_TEXTURE_SIZE 2048
|
||||
|
||||
|
||||
struct shader_t;
|
||||
|
||||
struct image_t {
|
||||
image_t* next;
|
||||
|
||||
|
@ -98,6 +100,12 @@ struct image_t {
|
|||
textureWrap_t wrapClampMode;
|
||||
|
||||
char name[MAX_QPATH]; // game path, including extension
|
||||
|
||||
// used to index into tr.imageShaders
|
||||
int firstShaderIndex;
|
||||
int numShaders;
|
||||
|
||||
int pakChecksum;
|
||||
};
|
||||
|
||||
|
||||
|
@ -272,7 +280,7 @@ typedef struct {
|
|||
#define MAX_IMAGE_ANIMATIONS 8
|
||||
|
||||
typedef struct {
|
||||
const image_t* image[MAX_IMAGE_ANIMATIONS];
|
||||
image_t* image[MAX_IMAGE_ANIMATIONS];
|
||||
int numImageAnimations;
|
||||
double imageAnimationSpeed;
|
||||
qbool isVideoMap; // shit code - no reason to have both of these
|
||||
|
@ -344,7 +352,7 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
float cloudHeight;
|
||||
const image_t *outerbox[6], *innerbox[6];
|
||||
image_t *outerbox[6], *innerbox[6];
|
||||
} skyParms_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -904,6 +912,9 @@ typedef struct {
|
|||
int numImages;
|
||||
image_t* images[MAX_DRAWIMAGES];
|
||||
|
||||
shader_t* imageShaders[2048];
|
||||
int numImageShaders;
|
||||
|
||||
// shader indexes from other modules will be looked up in tr.shaders[]
|
||||
// shader indexes from drawsurfs will be looked up in sortedShaders[]
|
||||
// lower indexed sortedShaders must be rendered first (opaque surfaces before translucent)
|
||||
|
@ -1150,15 +1161,18 @@ void R_ConfigureVideoMode( int desktopWidth, int desktopHeight ); // writes to g
|
|||
#define IMG_EXTLMATLAS 0x0010 // external lightmap atlas => no mip-mapping, no anisotropic
|
||||
#define IMG_NOAF 0x0020 // never enable anisotropic filtering
|
||||
|
||||
const image_t* R_FindImageFile( const char* name, int flags, textureWrap_t glWrapClampMode );
|
||||
image_t* R_FindImageFile( const char* name, int flags, textureWrap_t glWrapClampMode );
|
||||
image_t* R_CreateImage( const char* name, byte* pic, int width, int height, textureFormat_t format, int flags, textureWrap_t wrapClampMode );
|
||||
void R_UploadLightmapTile( image_t* image, byte* pic, int x, int y, int width, int height );
|
||||
|
||||
void R_SetColorMappings();
|
||||
|
||||
void R_ImageList_f( void );
|
||||
void R_ImageInfo_f( void );
|
||||
void R_SkinList_f( void );
|
||||
|
||||
void R_AddImageShader( image_t* image, shader_t* shader );
|
||||
|
||||
void R_InitFogTable();
|
||||
float R_FogFactor( float s, float t );
|
||||
void R_InitImages();
|
||||
|
@ -1181,14 +1195,16 @@ void R_MipMap( byte** outD, const byte* inD, int inW, int inH, textureWrap_t tw
|
|||
//
|
||||
qhandle_t RE_RegisterShader( const char* name );
|
||||
qhandle_t RE_RegisterShaderNoMip( const char* name );
|
||||
qhandle_t RE_RegisterShaderFromImage( const char* name, const image_t* image );
|
||||
qhandle_t RE_RegisterShaderFromImage( const char* name, image_t* image );
|
||||
|
||||
shader_t *R_FindShader( const char *name, int lightmapIndex, qbool mipRawImage );
|
||||
const shader_t* R_GetShaderByHandle( qhandle_t hShader );
|
||||
void R_InitShaders();
|
||||
void R_ShaderList_f( void );
|
||||
void R_ShaderInfo_f();
|
||||
void R_MixedUse_f();
|
||||
void R_CompleteShaderName_f( int startArg, int compArg );
|
||||
const char* R_GetShaderPath( const shader_t* shader );
|
||||
|
||||
/*
|
||||
====================================================================
|
||||
|
|
|
@ -2319,6 +2319,28 @@ static qbool IsReplaceBlendMode( unsigned int stateBits )
|
|||
}
|
||||
|
||||
|
||||
static void BuildPerImageShaderList( shader_t* newShader )
|
||||
{
|
||||
if ( newShader->isSky ) {
|
||||
image_t** const boxes[2] = { (image_t**)newShader->sky.outerbox, (image_t**)newShader->sky.innerbox };
|
||||
for ( int b = 0; b < 2; ++b ) {
|
||||
image_t** const images = boxes[b];
|
||||
for ( int i = 0; i < 6; ++i ) {
|
||||
R_AddImageShader( images[i], newShader );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for ( int s = 0; s < newShader->numStages; ++s ) {
|
||||
shaderStage_t* const newStage = newShader->stages[s];
|
||||
const int numImages = max( newStage->bundle.numImageAnimations, 1 );
|
||||
for ( int i = 0; i < numImages; ++i ) {
|
||||
R_AddImageShader( newStage->bundle.image[i], newShader );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// returns a freshly allocated shader with info
|
||||
// copied from the current global working shader
|
||||
|
||||
|
@ -2536,7 +2558,11 @@ static shader_t* FinishShader()
|
|||
|
||||
ProcessGreyscale();
|
||||
|
||||
return GeneratePermanentShader();
|
||||
shader_t* const newShader = GeneratePermanentShader();
|
||||
|
||||
BuildPerImageShaderList( newShader );
|
||||
|
||||
return newShader;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2669,7 +2695,7 @@ shader_t* R_FindShader( const char *name, int lightmapIndex, qbool mipRawImage )
|
|||
Q_strncpyz( fileName, name, sizeof( fileName ) );
|
||||
COM_DefaultExtension( fileName, sizeof( fileName ), ".tga" );
|
||||
|
||||
const image_t* image;
|
||||
image_t* image;
|
||||
if (mipRawImage)
|
||||
image = R_FindImageFile( fileName, 0, TW_REPEAT );
|
||||
else
|
||||
|
@ -2727,7 +2753,7 @@ shader_t* R_FindShader( const char *name, int lightmapIndex, qbool mipRawImage )
|
|||
// shaders registered from raw data should be "anonymous" and unsearchable
|
||||
// because they don't have the supercession concept of "real" shaders
|
||||
|
||||
qhandle_t RE_RegisterShaderFromImage( const char* name, const image_t* image )
|
||||
qhandle_t RE_RegisterShaderFromImage( const char* name, image_t* image )
|
||||
{
|
||||
const shader_t* sh;
|
||||
|
||||
|
@ -2925,17 +2951,9 @@ void R_ShaderInfo_f()
|
|||
return;
|
||||
}
|
||||
|
||||
const int fileIndex = shader->fileIndex;
|
||||
if ( fileIndex >= 0 && fileIndex < s_numShaderFiles ) {
|
||||
const int nameOffset = s_shaderFileNameOffsets[fileIndex];
|
||||
const char* const fileName = s_shaderFileNames + nameOffset;
|
||||
ri.Printf( PRINT_ALL, "File: scripts/%s\n", fileName );
|
||||
|
||||
char pakName[256];
|
||||
const int pakChecksum = s_shaderPakChecksums[fileIndex];
|
||||
if( FS_GetPakPath( pakName, sizeof(pakName), pakChecksum ) ) {
|
||||
ri.Printf( PRINT_ALL, "Pak : %s\n", pakName );
|
||||
}
|
||||
const char* const shaderPath = R_GetShaderPath( shader );
|
||||
if ( shaderPath != NULL ) {
|
||||
ri.Printf( PRINT_ALL, "%s\n", shaderPath );
|
||||
}
|
||||
|
||||
if ( Q_stricmp( Cmd_Argv(2), "code" ) ) {
|
||||
|
@ -2970,6 +2988,51 @@ void R_ShaderInfo_f()
|
|||
}
|
||||
|
||||
|
||||
void R_MixedUse_f()
|
||||
{
|
||||
for ( int i = 0; i < tr.numImages; ++i ) {
|
||||
image_t* const image = tr.images[i];
|
||||
if ( image->numShaders < 2 || !Q_stricmp(image->name, "*white") ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const qbool nmm0 = tr.imageShaders[image->firstShaderIndex]->imgflags & IMG_NOMIPMAP;
|
||||
const qbool npm0 = tr.imageShaders[image->firstShaderIndex]->imgflags & IMG_NOPICMIP;
|
||||
|
||||
qbool mixed = qfalse;
|
||||
for ( int s = 1; s < image->numShaders; ++s ) {
|
||||
const shader_t* const shader = tr.imageShaders[image->firstShaderIndex + s];
|
||||
const qbool nmmS = shader->imgflags & IMG_NOMIPMAP;
|
||||
const qbool npmS = shader->imgflags & IMG_NOPICMIP;
|
||||
if ( nmmS != nmm0 || npmS != npm0 ) {
|
||||
mixed = qtrue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !mixed ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ri.Printf( PRINT_ALL, "^5%s:\n", image->name );
|
||||
for ( int s = 0; s < image->numShaders; ++s ) {
|
||||
const shader_t* const shader = tr.imageShaders[image->firstShaderIndex + s];
|
||||
const qbool nmmS = shader->imgflags & IMG_NOMIPMAP;
|
||||
const qbool npmS = shader->imgflags & IMG_NOPICMIP;
|
||||
ri.Printf( PRINT_ALL, "%s %s %s\n",
|
||||
nmmS ? "NMM" : " ",
|
||||
npmS ? "NPM" : " ",
|
||||
shader->name);
|
||||
|
||||
const char* const shaderPath = R_GetShaderPath( shader );
|
||||
if ( shaderPath != NULL ) {
|
||||
ri.Printf( PRINT_ALL, " -> %s\n", shaderPath );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// finds and loads all .shader files, combining them into
|
||||
// a single large text block that can be scanned for shader names
|
||||
// note that this does a lot of things very badly, e.g. still loads superceded shaders
|
||||
|
@ -3012,7 +3075,7 @@ static void ScanAndLoadShaderFiles()
|
|||
ri.Error( ERR_DROP, "Couldn't load %s", filename );
|
||||
len[i] = COM_Compress( buffers[i] );
|
||||
sum += len[i];
|
||||
sumNames += strlen( shaderFileNames[i] );
|
||||
sumNames += strlen( shaderFileNames[i] ) + 1;
|
||||
}
|
||||
|
||||
s_shaderText = RI_New<char>( sum + numShaderFiles + 1 );
|
||||
|
@ -3112,3 +3175,23 @@ void R_InitShaders()
|
|||
|
||||
ScanAndLoadShaderFiles();
|
||||
}
|
||||
|
||||
|
||||
const char* R_GetShaderPath( const shader_t* shader )
|
||||
{
|
||||
const int fileIndex = shader->fileIndex;
|
||||
if ( fileIndex < 0 || fileIndex >= s_numShaderFiles ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const int nameOffset = s_shaderFileNameOffsets[fileIndex];
|
||||
const char* const fileName = s_shaderFileNames + nameOffset;
|
||||
|
||||
char pakName[256];
|
||||
const int pakChecksum = s_shaderPakChecksums[fileIndex];
|
||||
if( FS_GetPakPath( pakName, sizeof(pakName), pakChecksum ) ) {
|
||||
return va( "%s/scripts/%s", pakName, fileName );
|
||||
}
|
||||
|
||||
return va( "scripts/%s", fileName );
|
||||
}
|
||||
|
|
|
@ -494,7 +494,7 @@ void R_InitSkyTexCoords( float heightCloud )
|
|||
|
||||
static void DrawSkyBox()
|
||||
{
|
||||
const image_t*const* skyImages = &tess.shader->sky.outerbox[0];
|
||||
image_t* const* skyImages = &tess.shader->sky.outerbox[0];
|
||||
RB_PushSingleStageShader( GLS_DEPTHMASK_TRUE, CT_TWO_SIDED );
|
||||
shaderStage_t* const stage = tess.shader->stages[0];
|
||||
stage->rgbGen = CGEN_IDENTITY_LIGHTING;
|
||||
|
|
Loading…
Reference in a new issue