Skip to content

Allow loading an image multiple times with different params #1695

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions src/engine/renderer/tr_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <iomanip>
#include "Material.h"

static Cvar::Cvar<bool> r_allowImageParamMismatch(
"r_allowImageParamMismatch", "reuse images when requested with different parameters",
Cvar::NONE, false);

int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
int gl_filter_max = GL_LINEAR;

Expand Down Expand Up @@ -1813,26 +1817,32 @@ image_t *R_FindImageFile( const char *imageName, imageParams_t &imageParams )
{
if ( !Q_strnicmp( imageName, image->name, sizeof( image->name ) ) )
{
// The white image can be used with any set of parms, but other mismatches are errors.
if ( Q_stricmp( imageName, "_white" ) )
if ( imageParams == image->initialParams || r_allowImageParamMismatch.Get() )
{
unsigned int diff = imageParams.bits ^ image->bits;

if ( diff & IF_NOPICMIP )
{
Log::Warn("reused image '%s' with mixed allowPicmip parm for shader", imageName );
}
return image;
}

if ( image->wrapType != imageParams.wrapType )
{
Log::Warn("reused image '%s' with mixed glWrapType parm for shader", imageName);
}
// Built-in images can't be reloaded with different parameters, so return them as-is.
// For most of the usable ones e.g. _white, parameters wouldn't make a difference anyway.
// HACK: detect built-in images by naming convention, though nothing stops users from using such names
if ( image->name[ 0 ] == '_' && !strchr( image->name, '/' ) )
{
return image;
}

return image;
Log::Verbose( "image params mismatch for %s: 0x%X %d %d/%d %d %d vs. 0x%X %d %d/%d %d %d",
imageName,
image->initialParams.bits, Util::ordinal( image->initialParams.filterType ),
Util::ordinal( image->initialParams.wrapType.s ), Util::ordinal( image->initialParams.wrapType.t ),
image->initialParams.minDimension, image->initialParams.maxDimension,
imageParams.bits, Util::ordinal( imageParams.filterType ),
Util::ordinal( imageParams.wrapType.s ), Util::ordinal( imageParams.wrapType.t ),
imageParams.minDimension, imageParams.maxDimension );
}
}

const imageParams_t initialParams = imageParams;

// Load and create the image.
int width = 0, height = 0, numLayers = 0, numMips = 0;
byte *pic[ MAX_TEXTURE_MIPS * MAX_TEXTURE_LAYERS ];
Expand All @@ -1859,6 +1869,7 @@ image_t *R_FindImageFile( const char *imageName, imageParams_t &imageParams )
}

image_t *image = R_CreateImage( imageName, (const byte **)pic, width, height, numMips, imageParams );
image->initialParams = initialParams;

Z_Free( *pic );

Expand Down
8 changes: 8 additions & 0 deletions src/engine/renderer/tr_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -523,12 +523,20 @@ enum class ssaoMode {
wrapType_t wrapType;
int minDimension = 0;
int maxDimension = 0;

bool operator==(const imageParams_t &o) const
{
return o.bits == bits && o.filterType == filterType && o.wrapType == wrapType
&& o.minDimension == minDimension && o.maxDimension == maxDimension;
}
};

struct image_t
{
char name[ MAX_QPATH ];

imageParams_t initialParams; // may not match final values

GLenum type;
GLuint texnum; // gl texture binding
Texture *texture;
Expand Down