/* ================ VGUI_UploadTexture Upload texture into video memory ================ */ void VGUI_UploadTexture( int id, const char *buffer, int width, int height ) { rgbdata_t r_image; char texName[32]; if( id <= 0 || id >= VGUI_MAX_TEXTURES ) { MsgDev( D_ERROR, "VGUI_UploadTexture: bad texture %i. Ignored\n", id ); return; } Q_snprintf( texName, sizeof( texName ), "*vgui%i", id ); Q_memset( &r_image, 0, sizeof( r_image )); r_image.width = width; r_image.height = height; r_image.type = PF_RGBA_32; r_image.size = r_image.width * r_image.height * 4; r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA; r_image.buffer = (byte *)buffer; g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE, false ); GL_SetTextureType( g_textures[id], TEX_VGUI ); g_iBoundTexture = id; }
/* ================ R_AllocateMirrorTexture Allocate the screen texture and make copy ================ */ int R_AllocateMirrorTexture( void ) { rgbdata_t r_screen; int i, texture; char txName[16]; i = tr.num_mirrors_used; if( i >= MAX_MIRRORS ) { MsgDev( D_ERROR, "R_AllocateMirrorTexture: mirror textures limit exceeded!\n" ); return 0; // disable } texture = tr.mirrorTextures[i]; tr.num_mirrors_used++; if( !texture ) { // not initialized ? Q_memset( &r_screen, 0, sizeof( r_screen )); Q_snprintf( txName, sizeof( txName ), "*screen%i", i ); r_screen.width = RI.viewport[2]; r_screen.height = RI.viewport[3]; r_screen.type = PF_RGBA_32; r_screen.size = r_screen.width * r_screen.height * 4; r_screen.flags = IMAGE_HAS_COLOR; r_screen.buffer = NULL; // create empty texture for now tr.mirrorTextures[i] = GL_LoadTextureInternal( txName, &r_screen, TF_IMAGE, false ); GL_SetTextureType( tr.mirrorTextures[i], TEX_SCREENCOPY ); texture = tr.mirrorTextures[i]; } GL_Bind( GL_TEXTURE0, texture ); pglCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3], 0 ); return texture; }
/* ================ VGUI_CreateTexture Create empty rgba texture and upload them into video memory ================ */ void VGUI_CreateTexture( int id, int width, int height ) { rgbdata_t r_image; char texName[32]; if( id <= 0 || id >= VGUI_MAX_TEXTURES ) { MsgDev( D_ERROR, "VGUI_CreateTexture: bad texture %i. Ignored\n", id ); return; } Q_snprintf( texName, sizeof( texName ), "*vgui%i", id ); r_image.width = width; r_image.height = height; r_image.type = PF_RGBA_32; r_image.size = r_image.width * r_image.height * 4; r_image.flags = IMAGE_HAS_ALPHA; r_image.buffer = NULL; g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE|TF_NEAREST, false ); GL_SetTextureType( g_textures[id], TEX_VGUI ); g_iBoundTexture = id; }
/* ==================== CL_DuplicateTexture Dupliacte texture with remap pixels ==================== */ void CL_DuplicateTexture( mstudiotexture_t *ptexture, int topcolor, int bottomcolor ) { gltexture_t *glt; texture_t *tx = NULL; char texname[128]; int i, index; size_t size; byte paletteBackup[768]; byte *raw, *pal; // save off the real texture index index = ptexture->index; glt = R_GetTexture( index ); Q_snprintf( texname, sizeof( texname ), "#%i_%s", RI.currententity->curstate.number, glt->name + 1 ); // 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 ); ptexture->index = GL_LoadTexture( texname, raw, size, TF_FORCE_COLOR, NULL ); // do copy GL_SetTextureType( ptexture->index, TEX_REMAP ); // restore original palette Q_memcpy( pal, paletteBackup, 768 ); }
void R_ParseDetailTextures( const char *filename ) { char *afile, *pfile; string token, texname, detail_texname; float xScale, yScale; texture_t *tex; int i; if( r_detailtextures->integer >= 2 && !FS_FileExists( filename, false )) { // use built-in generator for detail textures R_CreateDetailTexturesList( filename ); } afile = FS_LoadFile( filename, NULL, false ); if( !afile ) return; pfile = afile; // format: 'texturename' 'detailtexture' 'xScale' 'yScale' while(( pfile = COM_ParseFile( pfile, token )) != NULL ) { texname[0] = '\0'; // read texname if( token[0] == '{' ) { // NOTE: COM_ParseFile handled some symbols seperately // this code will be fix it pfile = COM_ParseFile( pfile, token ); Q_strncat( texname, "{", sizeof( texname )); Q_strncat( texname, token, sizeof( texname )); } else Q_strncpy( texname, token, sizeof( texname )); // read detailtexture name pfile = COM_ParseFile( pfile, token ); Q_snprintf( detail_texname, sizeof( detail_texname ), "gfx/%s.tga", token ); // read scales pfile = COM_ParseFile( pfile, token ); xScale = Q_atof( token ); pfile = COM_ParseFile( pfile, token ); yScale = Q_atof( token ); if( xScale <= 0.0f || yScale <= 0.0f ) continue; // search for existing texture and uploading detail texture for( i = 0; i < cl.worldmodel->numtextures; i++ ) { tex = cl.worldmodel->textures[i]; if( Q_stricmp( tex->name, texname )) continue; tex->dt_texturenum = GL_LoadTexture( detail_texname, NULL, 0, TF_FORCE_COLOR ); // texture is loaded if( tex->dt_texturenum ) { gltexture_t *glt; GL_SetTextureType( tex->dt_texturenum, TEX_DETAIL ); glt = R_GetTexture( tex->gl_texturenum ); glt->xscale = xScale; glt->yscale = yScale; } break; } } Mem_Free( afile ); }