📄 gl_image.c
字号:
qglTexImage2D( GL_TEXTURE_2D,
0,
GL_COLOR_INDEX8_EXT,
scaled_width,
scaled_height,
0,
GL_COLOR_INDEX,
GL_UNSIGNED_BYTE,
paletted_texture );
}
else
{
qglTexImage2D (GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
goto done;
}
memcpy (scaled, data, width*height*4);
}
else
GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
GL_LightScaleTexture (scaled, scaled_width, scaled_height, !mipmap );
if ( qglColorTableEXT && gl_ext_palettedtexture->value && ( samples == gl_solid_format ) )
{
uploaded_paletted = true;
GL_BuildPalettedTexture( paletted_texture, ( unsigned char * ) scaled, scaled_width, scaled_height );
qglTexImage2D( GL_TEXTURE_2D,
0,
GL_COLOR_INDEX8_EXT,
scaled_width,
scaled_height,
0,
GL_COLOR_INDEX,
GL_UNSIGNED_BYTE,
paletted_texture );
}
else
{
qglTexImage2D( GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled );
}
if (mipmap)
{
int miplevel;
miplevel = 0;
while (scaled_width > 1 || scaled_height > 1)
{
GL_MipMap ((byte *)scaled, scaled_width, scaled_height);
scaled_width >>= 1;
scaled_height >>= 1;
if (scaled_width < 1)
scaled_width = 1;
if (scaled_height < 1)
scaled_height = 1;
miplevel++;
if ( qglColorTableEXT && gl_ext_palettedtexture->value && samples == gl_solid_format )
{
uploaded_paletted = true;
GL_BuildPalettedTexture( paletted_texture, ( unsigned char * ) scaled, scaled_width, scaled_height );
qglTexImage2D( GL_TEXTURE_2D,
miplevel,
GL_COLOR_INDEX8_EXT,
scaled_width,
scaled_height,
0,
GL_COLOR_INDEX,
GL_UNSIGNED_BYTE,
paletted_texture );
}
else
{
qglTexImage2D (GL_TEXTURE_2D, miplevel, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
}
}
}
done: ;
#endif
if (mipmap)
{
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
else
{
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
return (samples == gl_alpha_format);
}
/*
===============
GL_Upload8
Returns has_alpha
===============
*/
/*
static qboolean IsPowerOf2( int value )
{
int i = 1;
while ( 1 )
{
if ( value == i )
return true;
if ( i > value )
return false;
i <<= 1;
}
}
*/
qboolean GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean is_sky )
{
unsigned trans[512*256];
int i, s;
int p;
s = width*height;
if (s > sizeof(trans)/4)
ri.Sys_Error (ERR_DROP, "GL_Upload8: too large");
if ( qglColorTableEXT &&
gl_ext_palettedtexture->value &&
is_sky )
{
qglTexImage2D( GL_TEXTURE_2D,
0,
GL_COLOR_INDEX8_EXT,
width,
height,
0,
GL_COLOR_INDEX,
GL_UNSIGNED_BYTE,
data );
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
else
{
for (i=0 ; i<s ; i++)
{
p = data[i];
trans[i] = d_8to24table[p];
if (p == 255)
{ // transparent, so scan around for another color
// to avoid alpha fringes
// FIXME: do a full flood fill so mips work...
if (i > width && data[i-width] != 255)
p = data[i-width];
else if (i < s-width && data[i+width] != 255)
p = data[i+width];
else if (i > 0 && data[i-1] != 255)
p = data[i-1];
else if (i < s-1 && data[i+1] != 255)
p = data[i+1];
else
p = 0;
// copy rgb components
((byte *)&trans[i])[0] = ((byte *)&d_8to24table[p])[0];
((byte *)&trans[i])[1] = ((byte *)&d_8to24table[p])[1];
((byte *)&trans[i])[2] = ((byte *)&d_8to24table[p])[2];
}
}
return GL_Upload32 (trans, width, height, mipmap);
}
}
/*
================
GL_LoadPic
This is also used as an entry point for the generated r_notexture
================
*/
image_t *GL_LoadPic (char *name, byte *pic, int width, int height, imagetype_t type, int bits)
{
image_t *image;
int i;
// find a free image_t
for (i=0, image=gltextures ; i<numgltextures ; i++,image++)
{
if (!image->texnum)
break;
}
if (i == numgltextures)
{
if (numgltextures == MAX_GLTEXTURES)
ri.Sys_Error (ERR_DROP, "MAX_GLTEXTURES");
numgltextures++;
}
image = &gltextures[i];
if (strlen(name) >= sizeof(image->name))
ri.Sys_Error (ERR_DROP, "Draw_LoadPic: \"%s\" is too long", name);
strcpy (image->name, name);
image->registration_sequence = registration_sequence;
image->width = width;
image->height = height;
image->type = type;
if (type == it_skin && bits == 8)
R_FloodFillSkin(pic, width, height);
// load little pics into the scrap
if (image->type == it_pic && bits == 8
&& image->width < 64 && image->height < 64)
{
int x, y;
int i, j, k;
int texnum;
texnum = Scrap_AllocBlock (image->width, image->height, &x, &y);
if (texnum == -1)
goto nonscrap;
scrap_dirty = true;
// copy the texels into the scrap block
k = 0;
for (i=0 ; i<image->height ; i++)
for (j=0 ; j<image->width ; j++, k++)
scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = pic[k];
image->texnum = TEXNUM_SCRAPS + texnum;
image->scrap = true;
image->has_alpha = true;
image->sl = (x+0.01)/(float)BLOCK_WIDTH;
image->sh = (x+image->width-0.01)/(float)BLOCK_WIDTH;
image->tl = (y+0.01)/(float)BLOCK_WIDTH;
image->th = (y+image->height-0.01)/(float)BLOCK_WIDTH;
}
else
{
nonscrap:
image->scrap = false;
image->texnum = TEXNUM_IMAGES + (image - gltextures);
GL_Bind(image->texnum);
if (bits == 8)
image->has_alpha = GL_Upload8 (pic, width, height, (image->type != it_pic && image->type != it_sky), image->type == it_sky );
else
image->has_alpha = GL_Upload32 ((unsigned *)pic, width, height, (image->type != it_pic && image->type != it_sky) );
image->upload_width = upload_width; // after power of 2 and scales
image->upload_height = upload_height;
image->paletted = uploaded_paletted;
image->sl = 0;
image->sh = 1;
image->tl = 0;
image->th = 1;
}
return image;
}
/*
================
GL_LoadWal
================
*/
image_t *GL_LoadWal (char *name)
{
miptex_t *mt;
int width, height, ofs;
image_t *image;
ri.FS_LoadFile (name, (void **)&mt);
if (!mt)
{
ri.Con_Printf (PRINT_ALL, "GL_FindImage: can't load %s\n", name);
return r_notexture;
}
width = LittleLong (mt->width);
height = LittleLong (mt->height);
ofs = LittleLong (mt->offsets[0]);
image = GL_LoadPic (name, (byte *)mt + ofs, width, height, it_wall, 8);
ri.FS_FreeFile ((void *)mt);
return image;
}
/*
===============
GL_FindImage
Finds or loads the given image
===============
*/
image_t *GL_FindImage (char *name, imagetype_t type)
{
image_t *image;
int i, len;
byte *pic, *palette;
int width, height;
if (!name)
return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: NULL name");
len = strlen(name);
if (len<5)
return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: bad name: %s", name);
// look for it
for (i=0, image=gltextures ; i<numgltextures ; i++,image++)
{
if (!strcmp(name, image->name))
{
image->registration_sequence = registration_sequence;
return image;
}
}
//
// load the pic from disk
//
pic = NULL;
palette = NULL;
if (!strcmp(name+len-4, ".pcx"))
{
LoadPCX (name, &pic, &palette, &width, &height);
if (!pic)
return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: can't load %s", name);
image = GL_LoadPic (name, pic, width, height, type, 8);
}
else if (!strcmp(name+len-4, ".wal"))
{
image = GL_LoadWal (name);
}
else if (!strcmp(name+len-4, ".tga"))
{
LoadTGA (name, &pic, &width, &height);
if (!pic)
return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: can't load %s", name);
image = GL_LoadPic (name, pic, width, height, type, 32);
}
else
return NULL; // ri.Sys_Error (ERR_DROP, "GL_FindImage: bad extension on: %s", name);
if (pic)
free(pic);
if (palette)
free(palette);
return image;
}
/*
===============
R_RegisterSkin
===============
*/
struct image_s *R_RegisterSkin (char *name)
{
return GL_FindImage (name, it_skin);
}
/*
================
GL_FreeUnusedImages
Any image that was not touched on this registration sequence
will be freed.
================
*/
void GL_FreeUnusedImages (void)
{
int i;
image_t *image;
// never free r_notexture or particle texture
r_notexture->registration_sequence = registration_sequence;
r_particletexture->registration_sequence = registration_sequence;
for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
{
if (image->registration_sequence == registration_sequence)
continue; // used this sequence
if (!image->registration_sequence)
continue; // free image_t slot
if (image->type == it_pic)
continue; // don't free pics
// free it
qglDeleteTextures (1, &image->texnum);
memset (image, 0, sizeof(*image));
}
}
/*
===============
Draw_GetPalette
===============
*/
int Draw_GetPalette (void)
{
int i;
int r, g, b;
unsigned v;
byte *pic, *pal;
int width, height;
// get the palette
LoadPCX ("pics/colormap.pcx", &pic, &pal, &width, &height);
if (!pal)
ri.Sys_Error (ERR_FATAL, "Couldn't load pics/colormap.pcx");
for (i=0 ; i<256 ; i++)
{
r = pal[i*3+0];
g = pal[i*3+1];
b = pal[i*3+2];
v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
d_8to24table[i] = LittleLong(v);
}
d_8to24table[255] &= LittleLong(0xffffff); // 255 is transparent
free (pic);
free (pal);
return 0;
}
/*
===============
GL_InitImages
===============
*/
void GL_InitImages (void)
{
int i, j;
float g = vid_gamma->value;
registration_sequence = 1;
// init intensity conversions
intensity = ri.Cvar_Get ("intensity", "2", 0);
if ( intensity->value <= 1 )
ri.Cvar_Set( "intensity", "1" );
gl_state.inverse_intensity = 1 / intensity->value;
Draw_GetPalette ();
if ( qglColorTableEXT )
{
ri.FS_LoadFile( "pics/16to8.dat", &gl_state.d_16to8table );
if ( !gl_state.d_16to8table )
ri.Sys_Error( ERR_FATAL, "Couldn't load pics/16to8.pcx");
}
if ( gl_config.renderer & ( GL_RENDERER_VOODOO | GL_RENDERER_VOODOO2 ) )
{
g = 1.0F;
}
for ( i = 0; i < 256; i++ )
{
if ( g == 1 )
{
gammatable[i] = i;
}
else
{
float inf;
inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
gammatable[i] = inf;
}
}
for (i=0 ; i<256 ; i++)
{
j = i*intensity->value;
if (j > 255)
j = 255;
intensitytable[i] = j;
}
}
/*
===============
GL_ShutdownImages
===============
*/
void GL_ShutdownImages (void)
{
int i;
image_t *image;
for (i=0, image=gltextures ; i<numgltextures ; i++, image++)
{
if (!image->registration_sequence)
continue; // free image_t slot
// free it
qglDeleteTextures (1, &image->texnum);
memset (image, 0, sizeof(*image));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -