engine: image: fix blue halo around sprays

This commit is contained in:
Sergey Degtyar
2026-04-06 04:59:21 +03:00
committed by a1batross
parent 7e015a268b
commit e87f307ac1
7 changed files with 37 additions and 3 deletions

View File

@@ -116,6 +116,8 @@ typedef enum
IMAGE_MULTILAYER = BIT(8), // to differentiate from 3D texture IMAGE_MULTILAYER = BIT(8), // to differentiate from 3D texture
IMAGE_ONEBIT_ALPHA = BIT(9), // binary alpha IMAGE_ONEBIT_ALPHA = BIT(9), // binary alpha
IMAGE_QUAKEPAL = BIT(10), // image has quake1 palette IMAGE_QUAKEPAL = BIT(10), // image has quake1 palette
IMAGE_PREMULTIPLIED = BIT(11),
IMAGE_PLAYERDECAL = BIT(12), // loaded with IL_LOAD_PLAYER_DECAL (custom player spray)
// Image_Process manipulation flags // Image_Process manipulation flags
IMAGE_FLIP_X = BIT(16), // flip the image by width IMAGE_FLIP_X = BIT(16), // flip the image by width

View File

@@ -101,7 +101,7 @@ typedef enum
TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D
TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page
TF_ALPHACONTRAST = (1<<22), // special texture mode for A2C TF_ALPHACONTRAST = (1<<22), // special texture mode for A2C
// reserved TF_PREMULTIPLIED = (1<<23), // RGBA was stored premultiplied (HL gradient / indexalpha)
// reserved // reserved
TF_IMG_UPLOADED = (1<<25), // this is set for first time when called glTexImage, otherwise it will be call glTexSubImage TF_IMG_UPLOADED = (1<<25), // this is set for first time when called glTexImage, otherwise it will be call glTexSubImage
TF_ARB_FLOAT = (1<<26), // float textures TF_ARB_FLOAT = (1<<26), // float textures

View File

@@ -173,6 +173,9 @@ static MALLOC_LIKE( FS_FreeImage, 1 ) rgbdata_t *ImagePack( const char *name )
Image_ReportLookupsCount( name ); Image_ReportLookupsCount( name );
if( Image_CheckFlag( IL_LOAD_PLAYER_DECAL ))
SetBits( image.flags, IMAGE_PLAYERDECAL );
// clear any force flags // clear any force flags
image.force_flags = 0; image.force_flags = 0;

View File

@@ -250,6 +250,8 @@ qboolean Image_LoadSPR( const char *name, const byte *buffer, fs_offset_t filesi
SetBits( image.flags, IMAGE_ONEBIT_ALPHA ); SetBits( image.flags, IMAGE_ONEBIT_ALPHA );
// intentionally fallthrough // intentionally fallthrough
case LUMP_GRADIENT: case LUMP_GRADIENT:
SetBits( image.flags, IMAGE_HAS_ALPHA );
break;
case LUMP_QUAKE1: case LUMP_QUAKE1:
SetBits( image.flags, IMAGE_HAS_ALPHA ); SetBits( image.flags, IMAGE_HAS_ALPHA );
break; break;

View File

@@ -868,6 +868,10 @@ void DrawSingleDecal( decal_t *pDecal, msurface_t *fa )
GL_Bind( XASH_TEXTURE0, pDecal->texture ); GL_Bind( XASH_TEXTURE0, pDecal->texture );
if( FBitSet( R_GetTexture( pDecal->texture )->flags, TF_PREMULTIPLIED ))
pglBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
else pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
pglBegin( GL_POLYGON ); pglBegin( GL_POLYGON );
for( i = 0; i < numVerts; i++, v += VERTEXSIZE ) for( i = 0; i < numVerts; i++, v += VERTEXSIZE )

View File

@@ -1238,6 +1238,8 @@ static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic )
// force upload texture as RGB or RGBA (detail textures requires this) // force upload texture as RGB or RGBA (detail textures requires this)
if( tex->flags & TF_FORCE_COLOR ) pic->flags |= IMAGE_HAS_COLOR; if( tex->flags & TF_FORCE_COLOR ) pic->flags |= IMAGE_HAS_COLOR;
if( pic->flags & IMAGE_HAS_ALPHA ) tex->flags |= TF_HAS_ALPHA; if( pic->flags & IMAGE_HAS_ALPHA ) tex->flags |= TF_HAS_ALPHA;
if( FBitSet( pic->flags, IMAGE_PREMULTIPLIED ))
SetBits( tex->flags, TF_PREMULTIPLIED );
tex->encode = pic->encode; // share encode method tex->encode = pic->encode; // share encode method
@@ -1275,6 +1277,23 @@ static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic )
// processing image before uploading (force to rgba, make luma etc) // processing image before uploading (force to rgba, make luma etc)
if( pic->buffer ) gEngfuncs.Image_Process( &pic, 0, 0, img_flags, 0 ); if( pic->buffer ) gEngfuncs.Image_Process( &pic, 0, 0, img_flags, 0 );
if( FBitSet( pic->flags, IMAGE_PLAYERDECAL ) && pic->buffer && pic->type == PF_RGBA_32 && FBitSet( pic->flags, IMAGE_HAS_ALPHA )
&& !FBitSet( pic->flags, IMAGE_PREMULTIPLIED ))
{
int i, cnt = (int)( pic->width * pic->height );
byte *p = pic->buffer;
for( i = 0; i < cnt; i++, p += 4 )
{
int a = p[3];
p[0] = ( p[0] * a + 127 ) / 255;
p[1] = ( p[1] * a + 127 ) / 255;
p[2] = ( p[2] * a + 127 ) / 255;
}
SetBits( pic->flags, IMAGE_PREMULTIPLIED );
SetBits( tex->flags, TF_PREMULTIPLIED );
}
if( FBitSet( tex->flags, TF_LUMINANCE )) if( FBitSet( tex->flags, TF_LUMINANCE ))
ClearBits( pic->flags, IMAGE_HAS_COLOR ); ClearBits( pic->flags, IMAGE_HAS_COLOR );
} }

View File

@@ -2775,7 +2775,9 @@ static void R_DrawDlightedDecals( vboarray_t *vbo, msurface_t *newsurf, msurface
if( glt->fogParams[3] > 230 ) if( glt->fogParams[3] > 230 )
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
else pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); else pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); if( FBitSet( glt->flags, TF_PREMULTIPLIED ))
pglBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
else pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
} }
else else
{ {
@@ -3197,7 +3199,9 @@ static void R_DrawStaticDecals( vboarray_t *vbo, qboolean drawlightmap, int ilig
if( glt->fogParams[3] > 230 ) if( glt->fogParams[3] > 230 )
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
else pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); else pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); if( FBitSet( glt->flags, TF_PREMULTIPLIED ))
pglBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
else pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
} }
else else
{ {