added /imageinfo and /shadermixeduse

This commit is contained in:
myT 2022-11-25 03:32:41 +01:00
parent d43a016e61
commit cfdba32b24
6 changed files with 193 additions and 26 deletions

View file

@ -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

View file

@ -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++;
}

View file

@ -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" },

View file

@ -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 );
/*
====================================================================

View file

@ -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 );
}

View file

@ -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;