static void SCR_InstallParticlePalette( void ) { rgbdata_t *pic; int i; // first check 'palette.lmp' then 'palette.pal' pic = FS_LoadImage( "gfx/palette.lmp", NULL, 0 ); if( !pic ) pic = FS_LoadImage( "gfx/palette.pal", NULL, 0 ); // NOTE: imagelib required this fakebuffer for loading internal palette if( !pic ) pic = FS_LoadImage( "#valve.pal", ((byte *)&i), 768 ); if( pic ) { for( i = 0; i < 256; i++ ) { clgame.palette[i][0] = pic->palette[i*4+0]; clgame.palette[i][1] = pic->palette[i*4+1]; clgame.palette[i][2] = pic->palette[i*4+2]; } FS_FreeImage( pic ); } else { for( i = 0; i < 256; i++ ) { clgame.palette[i][0] = i; clgame.palette[i][1] = i; clgame.palette[i][2] = i; } MsgDev( D_WARN, "CL_InstallParticlePalette: failed. Force to grayscale\n" ); } }
/* ==================== CL_UpdateTexture Update texture top and bottom colors ==================== */ void CL_UpdateTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor ) { gltexture_t *glt; rgbdata_t *pic; texture_t *tx = NULL; char texname[128], name[128], mdlname[128]; int i, index; size_t size; byte paletteBackup[768]; byte *raw, *pal; // save of the real texture index glt = R_GetTexture( ptexture->index ); // build name of original texture Q_strncpy( mdlname, RI.currentmodel->name, sizeof( mdlname )); FS_FileBase( ptexture->name, name ); FS_StripExtension( mdlname ); Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name ); index = GL_FindTexture( texname ); if( !index ) return; // couldn't find texture // search for pixels for( i = 0; i < RI.currentmodel->numtextures; i++ ) { tx = RI.currentmodel->textures[i]; if( tx->gl_texturenum == index ) break; // found } ASSERT( tx != NULL ); // backup original palette pal = (byte *)(tx + 1) + (tx->width * tx->height); Q_memcpy( paletteBackup, pal, 768 ); raw = CL_CreateRawTextureFromPixels( tx, &size, topcolor, bottomcolor ); pic = FS_LoadImage( glt->name, raw, size ); if( !pic ) { MsgDev( D_ERROR, "Couldn't update texture %s\n", glt->name ); return; } index = GL_LoadTextureInternal( glt->name, pic, 0, true ); FS_FreeImage( pic ); // restore original palette Q_memcpy( pal, paletteBackup, 768 ); ASSERT( index == ptexture->index ); }
/* ============ ConvFNT ============ */ bool ConvFNT( const char *name, byte *buffer, size_t filesize, const char *ext ) { rgbdata_t *pic = FS_LoadImage( va( "#%s.fnt", name ), buffer, filesize ); if( pic ) { FS_SaveImage(va("%s/%s.%s", gs_gamedir, name, ext ), pic ); Msg("%s.fnt\n", name ); // echo to console FS_FreeImage( pic ); return true; } return false; }
/* ============= ConvPCX this also uses by SP2_ConvertFrame ============= */ bool ConvPCX( const char *name, byte *buffer, size_t filesize, const char *ext ) { rgbdata_t *pic = FS_LoadImage( va( "#%s.pcx", name ), buffer, filesize ); if( pic ) { FS_SaveImage( va("%s/%s.%s", gs_gamedir, name, ext ), pic ); // pcx images not required shader because it hud pics or sprite frames Msg( "%s.pcx\n", name ); // echo to console FS_FreeImage( pic ); return true; } return false; }
/* ============= ConvBMP ============= */ bool ConvBMP( const char *name, byte *buffer, size_t filesize, const char *ext ) { rgbdata_t *pic = FS_LoadImage( va( "#%s.bmp", name ), buffer, filesize ); if( pic ) { FS_SaveImage( va("%s/%s.%s", gs_gamedir, name, ext ), pic ); Conv_CreateShader( name, pic, ext, NULL, 0, 0 ); Msg( "%s.bmp\n", name, ext ); // echo to console FS_FreeImage( pic ); return true; } return false; }
/* ============ ConvWAL ============ */ bool ConvWAL( const char *name, byte *buffer, size_t filesize, const char *ext ) { rgbdata_t *pic = FS_LoadImage( va( "#%s.wal", name ), buffer, filesize ); if( pic ) { wal_t *wal = (wal_t *)buffer; FS_SaveImage( va("%s/%s.%s", gs_gamedir, name, ext ), pic ); Conv_CreateShader( name, pic, ext, wal->animname, wal->flags, wal->contents ); Msg("%s.wal\n", name ); // echo to console FS_FreeImage( pic ); return true; } return false; }
rgbdata_t *ImagePack( void ) { rgbdata_t *pack = Mem_Alloc( host.imagepool, sizeof( rgbdata_t )); // clear any force flags image.force_flags = 0; if( image.cubemap && image.num_sides != 6 ) { // this never be happens, just in case MsgDev( D_NOTE, "ImagePack: inconsistent cubemap pack %d\n", image.num_sides ); FS_FreeImage( pack ); return NULL; } if( image.cubemap ) { image.flags |= IMAGE_CUBEMAP; pack->buffer = image.cubemap; pack->width = image.source_width; pack->height = image.source_height; pack->type = image.source_type; pack->size = image.size * image.num_sides; } else { pack->buffer = image.rgba; pack->width = image.width; pack->height = image.height; pack->type = image.type; pack->size = image.size; } // copy fog params pack->fogParams[0] = image.fogParams[0]; pack->fogParams[1] = image.fogParams[1]; pack->fogParams[2] = image.fogParams[2]; pack->fogParams[3] = image.fogParams[3]; pack->flags = image.flags; pack->numMips = image.num_mips; pack->palette = image.palette; pack->depth = image.depth; return pack; }
void R_CreateDetailTexturesList( const char *filename ) { file_t *detail_txt = NULL; float xScale, yScale; const char *detail_name; texture_t *tex; rgbdata_t *pic; int i; for( i = 0; i < cl.worldmodel->numtextures; i++ ) { tex = cl.worldmodel->textures[i]; detail_name = R_DetailTextureForName( tex->name ); if( !detail_name ) continue; // detailtexture detected if( detail_name ) { if( !detail_txt ) detail_txt = FS_Open( filename, "w", false ); if( !detail_txt ) { MsgDev( D_ERROR, "Can't write %s\n", filename ); break; } pic = FS_LoadImage( va( "gfx/detail/%s", detail_name ), NULL, 0 ); if( pic ) { xScale = (pic->width / (float)tex->width) * gl_detailscale->value; yScale = (pic->height / (float)tex->height) * gl_detailscale->value; FS_FreeImage( pic ); } else xScale = yScale = 10.0f; // store detailtexture description FS_Printf( detail_txt, "%s detail/%s %.2f %.2f\n", tex->name, detail_name, xScale, yScale ); } } if( detail_txt ) FS_Close( detail_txt ); }
/* ================= LoadEntityIndexMap based on LoadAlphaMap() from terrain.c, a little more generic ================= */ void LoadEntityIndexMap( entity_t *e ) { int i, size, numLayers; const char *value, *indexMapFilename, *shader; char offset[ 4096 ], *search, *space; rgbdata_t *image; byte *pixels; uint *pixels32; indexMap_t *im; brush_t *b; parseMesh_t *p; if( e->brushes == NULL && e->patches == NULL ) return; value = ValueForKey( e, "_indexmap" ); if( value[0] == '\0' ) value = ValueForKey( e, "alphamap" ); if( value[0] == '\0' ) return; indexMapFilename = value; // get number of layers (support legacy "layers" key as well) value = ValueForKey( e, "_layers" ); if( value[0] == '\0' ) value = ValueForKey( e, "layers" ); if( value[0] == '\0' ) { Msg( "Warning: Entity with index/alpha map \"%s\" has missing \"_layers\" or \"layers\" key\n", indexMapFilename ); Msg( "Entity will not be textured properly. Check your keys/values.\n" ); return; } numLayers = com.atoi( value ); if( numLayers < 1 ) { Msg( "Warning: Entity with index/alpha map \"%s\" has < 1 layer (%d)\n", indexMapFilename, numLayers ); Msg( "Entity will not be textured properly. Check your keys/values.\n" ); return; } // get base shader name (support legacy "shader" key as well) value = ValueForKey( mapEnt, "_shader" ); if( value[0] == '\0' ) value = ValueForKey( e, "shader" ); if( value[0] == '\0' ) { Msg( "Warning: Entity with index/alpha map \"%s\" has missing \"_shader\" or \"shader\" key\n", indexMapFilename ); Msg( "Entity will not be textured properly. Check your keys/values.\n" ); return; } shader = value; MsgDev( D_NOTE, "Entity %d (%s) has shader index map \"%s\"\n", mapEnt->mapEntityNum, ValueForKey( e, "classname" ), indexMapFilename ); image = FS_LoadImage( indexMapFilename, NULL, 0 ); if( !image ) return; Image_Process( &image, 0, 0, IMAGE_FORCE_RGBA ); size = image->width * image->height; pixels = Malloc( size ); pixels32 = (uint *)image->buffer; for( i = 0; i < size; i++ ) { pixels[i] = ((pixels32[i] & 0xFF) * numLayers) / 256; if( pixels[i] >= numLayers ) pixels[i] = numLayers - 1; } // the index map must be at least 2x2 pixels if( image->width < 2 || image->height < 2 ) { Msg( "Warning: Entity with index/alpha map \"%s\" is smaller than 2x2 pixels\n", indexMapFilename ); Msg( "Entity will not be textured properly. Check your keys/values.\n" ); FS_FreeImage( image ); return; } // create a new index map im = Malloc( sizeof( *im )); im->w = image->width; im->h = image->height; im->numLayers = numLayers; com.strncpy( im->name, indexMapFilename, sizeof( im->name )); com.strncpy( im->shader, shader, sizeof( im->shader )); im->pixels = pixels; value = ValueForKey( mapEnt, "_offsets" ); if( value[0] == '\0' ) value = ValueForKey( e, "offsets" ); if( value[0] != '\0' ) { // value is a space-seperated set of numbers com.strncpy( offset, value, sizeof( offset )); search = offset; for( i = 0; i < 256 && *search != '\0'; i++ ) { space = com.strstr( search, " " ); if( space != NULL ) *space = '\0'; im->offsets[i] = com.atof( search ); if( space == NULL ) break; search = space + 1; } } // store the index map in every brush/patch in the entity for( b = e->brushes; b != NULL; b = b->next ) b->im = im; for( p = e->patches; p != NULL; p = p->next ) p->im = im; FS_FreeImage( image ); }
/* ================= VID_CubemapShot ================= */ qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot ) { rgbdata_t *r_shot, *r_side; byte *temp = NULL; byte *buffer = NULL; string basename; int i = 1, flags, result; if( !RI.drawWorld || !cl.worldmodel ) return false; // make sure the specified size is valid while( i < size ) i<<=1; if( i != size ) return false; if( size > glState.width || size > glState.height ) return false; // setup refdef RI.params |= RP_ENVVIEW; // do not render non-bmodel entities // alloc space temp = Mem_Alloc( r_temppool, size * size * 3 ); buffer = Mem_Alloc( r_temppool, size * size * 3 * 6 ); r_shot = Mem_Alloc( r_temppool, sizeof( rgbdata_t )); r_side = Mem_Alloc( r_temppool, sizeof( rgbdata_t )); // use client vieworg if( !vieworg ) vieworg = cl.refdef.vieworg; for( i = 0; i < 6; i++ ) { // go into 3d mode R_Set2DMode( false ); if( skyshot ) { R_DrawCubemapView( vieworg, r_skyBoxInfo[i].angles, size ); flags = r_skyBoxInfo[i].flags; } else { R_DrawCubemapView( vieworg, r_envMapInfo[i].angles, size ); flags = r_envMapInfo[i].flags; } pglReadPixels( 0, 0, size, size, GL_RGB, GL_UNSIGNED_BYTE, temp ); r_side->flags = IMAGE_HAS_COLOR; r_side->width = r_side->height = size; r_side->type = PF_RGB_24; r_side->size = r_side->width * r_side->height * 3; r_side->buffer = temp; if( flags ) Image_Process( &r_side, 0, 0, 0.0f, flags, NULL ); Q_memcpy( buffer + (size * size * 3 * i), r_side->buffer, size * size * 3 ); } RI.params &= ~RP_ENVVIEW; r_shot->flags = IMAGE_HAS_COLOR; r_shot->flags |= (skyshot) ? IMAGE_SKYBOX : IMAGE_CUBEMAP; r_shot->width = size; r_shot->height = size; r_shot->type = PF_RGB_24; r_shot->size = r_shot->width * r_shot->height * 3 * 6; r_shot->palette = NULL; r_shot->buffer = buffer; // make sure what we have right extension Q_strncpy( basename, base, MAX_STRING ); FS_StripExtension( basename ); FS_DefaultExtension( basename, ".tga" ); // write image as 6 sides result = FS_SaveImage( basename, r_shot ); FS_FreeImage( r_shot ); FS_FreeImage( r_side ); return result; }
qboolean VID_ScreenShot( const char *filename, int shot_type ) { rgbdata_t *r_shot; uint flags = IMAGE_FLIP_Y; int width = 0, height = 0; qboolean result; r_shot = Mem_Alloc( r_temppool, sizeof( rgbdata_t )); r_shot->width = (glState.width + 3) & ~3; r_shot->height = (glState.height + 3) & ~3; r_shot->flags = IMAGE_HAS_COLOR | IMAGE_HAS_ALPHA; r_shot->type = PF_RGBA_32; r_shot->size = r_shot->width * r_shot->height * PFDesc[r_shot->type].bpp; r_shot->palette = NULL; r_shot->buffer = Mem_Alloc( r_temppool, r_shot->size ); // get screen frame pglPixelStorei(GL_PACK_ALIGNMENT, 1); // PANDORA, just in case pglReadPixels( 0, 0, r_shot->width, r_shot->height, GL_RGBA, GL_UNSIGNED_BYTE, r_shot->buffer ); switch( shot_type ) { case VID_SCREENSHOT: if( !gl_overview->integer ) VID_ImageAdjustGamma( r_shot->buffer, r_shot->width, r_shot->height ); // scrshot gamma break; case VID_SNAPSHOT: if( !gl_overview->integer ) VID_ImageAdjustGamma( r_shot->buffer, r_shot->width, r_shot->height ); // scrshot gamma FS_AllowDirectPaths( true ); break; case VID_LEVELSHOT: flags |= IMAGE_RESAMPLE; if( glState.wideScreen ) { height = 480; width = 800; } else { height = 480; width = 640; } break; case VID_MINISHOT: flags |= IMAGE_RESAMPLE; height = 200; width = 320; break; case VID_MAPSHOT: V_WriteOverviewScript(); // store overview script too flags |= IMAGE_RESAMPLE|IMAGE_QUANTIZE; // GoldSrc request overviews in 8-bit format height = 768; width = 1024; break; } Image_Process( &r_shot, width, height, 0.0f, flags, NULL ); // write image result = FS_SaveImage( filename, r_shot ); host.write_to_clipboard = false; // disable write to clipboard FS_AllowDirectPaths( false ); // always reset after store screenshot FS_FreeImage( r_shot ); return result; }