quakespasm/source/gl_draw.c
2023-09-07 14:16:49 -04:00

1427 lines
No EOL
32 KiB
C

/*
Copyright (C) 1996-2001 Id Software, Inc.
Copyright (C) 2002-2009 John Fitzgibbons and others
Copyright (C) 2007-2008 Kristian Duske
Copyright (C) 2010-2014 QuakeSpasm developers
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// draw.c -- 2d drawing
#include "quakedef.h"
//extern unsigned char d_15to8table[65536]; //johnfitz -- never used
cvar_t scr_conalpha = {"scr_conalpha", "0.5", CVAR_ARCHIVE}; //johnfitz
cvar_t gl_nobind = {"gl_nobind", "0"};
cvar_t gl_max_size = {"gl_max_size", "4096"};
cvar_t gl_picmip = {"gl_picmip", "0"};
qpic_t *draw_disc;
qpic_t *draw_backtile;
gltexture_t *char_texture; //johnfitz
qpic_t *pic_ovr, *pic_ins; //johnfitz -- new cursor handling
qpic_t *pic_nul; //johnfitz -- for missing gfx, don't crash
qpic_t *sniper_scope;
int zombie_skins[2][2];
//Loading Fill by Crow_bar
float loading_cur_step;
char loading_name[32];
float loading_num_step;
int loading_step;
float loading_cur_step_bk;
//johnfitz -- new pics
byte pic_ovr_data[8][8] =
{
{255,255,255,255,255,255,255,255},
{255, 15, 15, 15, 15, 15, 15,255},
{255, 15, 15, 15, 15, 15, 15, 2},
{255, 15, 15, 15, 15, 15, 15, 2},
{255, 15, 15, 15, 15, 15, 15, 2},
{255, 15, 15, 15, 15, 15, 15, 2},
{255, 15, 15, 15, 15, 15, 15, 2},
{255,255, 2, 2, 2, 2, 2, 2},
};
byte pic_ins_data[9][8] =
{
{ 15, 15,255,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{ 15, 15, 2,255,255,255,255,255},
{255, 2, 2,255,255,255,255,255},
};
byte pic_nul_data[8][8] =
{
{252,252,252,252, 0, 0, 0, 0},
{252,252,252,252, 0, 0, 0, 0},
{252,252,252,252, 0, 0, 0, 0},
{252,252,252,252, 0, 0, 0, 0},
{ 0, 0, 0, 0,252,252,252,252},
{ 0, 0, 0, 0,252,252,252,252},
{ 0, 0, 0, 0,252,252,252,252},
{ 0, 0, 0, 0,252,252,252,252},
};
byte pic_stipple_data[8][8] =
{
{255, 0, 0, 0,255, 0, 0, 0},
{ 0, 0,255, 0, 0, 0,255, 0},
{255, 0, 0, 0,255, 0, 0, 0},
{ 0, 0,255, 0, 0, 0,255, 0},
{255, 0, 0, 0,255, 0, 0, 0},
{ 0, 0,255, 0, 0, 0,255, 0},
{255, 0, 0, 0,255, 0, 0, 0},
{ 0, 0,255, 0, 0, 0,255, 0},
};
byte pic_crosshair_data[8][8] =
{
{255,255,255,255,255,255,255,255},
{255,255,255, 8, 9,255,255,255},
{255,255,255, 6, 8, 2,255,255},
{255, 6, 8, 8, 6, 8, 8,255},
{255,255, 2, 8, 8, 2, 2, 2},
{255,255,255, 7, 8, 2,255,255},
{255,255,255,255, 2, 2,255,255},
{255,255,255,255,255,255,255,255},
};
//johnfitz
typedef struct
{
gltexture_t *gltexture;
float sl, tl, sh, th;
} glpic_t;
int gl_lightmap_format = GL_RGBA;
int gl_solid_format = 3;
int gl_alpha_format = 4;
int gl_filter_min = GL_LINEAR;
int gl_filter_max = GL_LINEAR;
int texels;
extern int texture_extension_number;
canvastype currentcanvas = CANVAS_NONE; //johnfitz -- for GL_SetCanvas
//==============================================================================
//
// PIC CACHING
//
//==============================================================================
typedef struct cachepic_s
{
char name[MAX_QPATH];
qpic_t pic;
byte padding[32]; // for appended glpic
} cachepic_t;
#define MAX_CACHED_PICS 128
cachepic_t menu_cachepics[MAX_CACHED_PICS];
int menu_numcachepics;
byte menuplyr_pixels[4096];
// scrap allocation
// Allocate all the little status bar obejcts into a single texture
// to crutch up stupid hardware / drivers
#define MAX_SCRAPS 2
#define BLOCK_WIDTH 256
#define BLOCK_HEIGHT 256
int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT]; //johnfitz -- removed *4 after BLOCK_HEIGHT
qboolean scrap_dirty;
gltexture_t *scrap_textures[MAX_SCRAPS]; //johnfitz
/*
================
Scrap_AllocBlock
returns an index into scrap_texnums[] and the position inside it
================
*/
int Scrap_AllocBlock (int w, int h, int *x, int *y)
{
int i, j;
int best, best2;
int texnum;
for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++)
{
best = BLOCK_HEIGHT;
for (i=0 ; i<BLOCK_WIDTH-w ; i++)
{
best2 = 0;
for (j=0 ; j<w ; j++)
{
if (scrap_allocated[texnum][i+j] >= best)
break;
if (scrap_allocated[texnum][i+j] > best2)
best2 = scrap_allocated[texnum][i+j];
}
if (j == w)
{ // this is a valid spot
*x = i;
*y = best = best2;
}
}
if (best + h > BLOCK_HEIGHT)
continue;
for (i=0 ; i<w ; i++)
scrap_allocated[texnum][*x + i] = best + h;
return texnum;
}
Sys_Error ("Scrap_AllocBlock: full"); //johnfitz -- correct function name
return 0; //johnfitz -- shut up compiler
}
/*
================
Scrap_Upload -- johnfitz -- now uses TexMgr
================
*/
void Scrap_Upload (void)
{
char name[8];
int i;
for (i=0; i<MAX_SCRAPS; i++)
{
sprintf (name, "scrap%i", i);
scrap_textures[i] = TexMgr_LoadImage (NULL, name, BLOCK_WIDTH, BLOCK_HEIGHT, SRC_INDEXED, scrap_texels[i],
"", (src_offset_t)scrap_texels[i], TEXPREF_ALPHA | TEXPREF_OVERWRITE | TEXPREF_NOPICMIP);
}
scrap_dirty = false;
}
/*
================
Draw_PicFromWad
================
*/
qpic_t *Draw_PicFromWad (const char *name)
{
qpic_t *p;
glpic_t gl;
src_offset_t offset; //johnfitz
p = (qpic_t *) W_GetLumpName (name);
if (!p) return pic_nul; //johnfitz
// load little ones into the scrap
if (p->width < 64 && p->height < 64)
{
int x, y;
int i, j, k;
int texnum;
x = 0;
y = 0;
texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
scrap_dirty = true;
k = 0;
for (i=0 ; i<p->height ; i++)
{
for (j=0 ; j<p->width ; j++, k++)
scrap_texels[texnum][(y+i)*BLOCK_WIDTH + x + j] = p->data[k];
}
gl.gltexture = scrap_textures[texnum]; //johnfitz -- changed to an array
//johnfitz -- no longer go from 0.01 to 0.99
gl.sl = x/(float)BLOCK_WIDTH;
gl.sh = (x+p->width)/(float)BLOCK_WIDTH;
gl.tl = y/(float)BLOCK_WIDTH;
gl.th = (y+p->height)/(float)BLOCK_WIDTH;
}
else
{
char texturename[64]; //johnfitz
q_snprintf (texturename, sizeof(texturename), "%s:%s", WADFILENAME, name); //johnfitz
offset = (src_offset_t)p - (src_offset_t)wad_base + sizeof(int)*2; //johnfitz
gl.gltexture = TexMgr_LoadImage (NULL, texturename, p->width, p->height, SRC_INDEXED, p->data, WADFILENAME,
offset, TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP); //johnfitz -- TexMgr
gl.sl = 0;
gl.sh = (float)p->width/(float)TexMgr_PadConditional(p->width); //johnfitz
gl.tl = 0;
gl.th = (float)p->height/(float)TexMgr_PadConditional(p->height); //johnfitz
}
memcpy (p->data, &gl, sizeof(glpic_t));
return p;
}
/*
================
Draw_CachePic
================
*/
extern char cwd[MAX_OSPATH];
qpic_t *Draw_CachePic (const char *path)
{
cachepic_t *pic;
int i;
qpic_t *dat;
glpic_t gl;
if (!COM_FileExists(path, NULL))
return NULL;
for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++)
{
if (!strcmp (path, pic->name))
return &pic->pic;
}
if (menu_numcachepics == MAX_CACHED_PICS)
Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
menu_numcachepics++;
strcpy (pic->name, path);
// Determine whether or not we need to have a source by index or by something else
//
char extension[16];
char path_noext[2*MAX_OSPATH];
COM_StripExtension(path, path_noext, 2*MAX_OSPATH);
strcpy(extension, COM_FileGetExtension(path));
int src_type;
if (!strcmp("tga", extension)) {
src_type = SRC_TGA;
dat = (qpic_t *)LoadTGAPic(path_noext);
if (!dat) {
Host_Error ("Draw_CachePic: failed to load %s", path);
}
} else if (!strcmp("png", extension)) {
src_type = SRC_RGBA;
dat = (qpic_t *)LoadPNGPic(path_noext);
if (!dat) {
Host_Error ("Draw_CachePic: failed to load %s", path);
}
} else {
src_type = SRC_INDEXED;
dat = (qpic_t *)COM_LoadTempFile (path, NULL);
if (!dat) {
Host_Error ("Draw_CachePic: failed to load %s", path);
}
SwapPic (dat);
}
// HACK HACK HACK --- we need to keep the bytes for
// the translatable player picture just for the menu
// configuration dialog
if (!strcmp (path, "gfx/menuplyr.lmp"))
memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
pic->pic.width = dat->width;
pic->pic.height = dat->height;
// naievil -- modified to change extension
gl.gltexture = TexMgr_LoadImage (NULL, path, dat->width, dat->height, src_type, dat->data, path,
sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_PAD | TEXPREF_NOPICMIP); //johnfitz -- TexMgr
gl.sl = 0;
gl.sh = (float)dat->width/(float)TexMgr_PadConditional(dat->width); //johnfitz
gl.tl = 0;
gl.th = (float)dat->height/(float)TexMgr_PadConditional(dat->height); //johnfitz
memcpy (pic->pic.data, &gl, sizeof(glpic_t));
return &pic->pic;
}
/*
================
Draw_MakePic -- johnfitz -- generate pics from internal data
================
*/
qpic_t *Draw_MakePic (const char *name, int width, int height, byte *data)
{
int flags = TEXPREF_NEAREST | TEXPREF_ALPHA | TEXPREF_PERSIST | TEXPREF_NOPICMIP | TEXPREF_PAD;
qpic_t *pic;
glpic_t gl;
pic = (qpic_t *) Hunk_Alloc (sizeof(qpic_t) - 4 + sizeof (glpic_t));
pic->width = width;
pic->height = height;
gl.gltexture = TexMgr_LoadImage (NULL, name, width, height, SRC_INDEXED, data, "", (src_offset_t)data, flags);
gl.sl = 0;
gl.sh = (float)width/(float)TexMgr_PadConditional(width);
gl.tl = 0;
gl.th = (float)height/(float)TexMgr_PadConditional(height);
memcpy (pic->data, &gl, sizeof(glpic_t));
return pic;
}
//==============================================================================
//
// INIT
//
//==============================================================================
/*
===============
Draw_LoadPics -- johnfitz
===============
*/
void Draw_LoadPics (void)
{
qpic_t *dat;
dat = (qpic_t *)LoadTGAPic("gfx/charset");
char_texture = TexMgr_LoadImage (NULL, "gfx/charset", dat->width, dat->height, SRC_TGA, dat->data,
"gfx/charset", sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_NEAREST | TEXPREF_NOPICMIP | TEXPREF_CONCHARS);
draw_disc = Draw_PicFromWad ("disc");
draw_backtile = Draw_PicFromWad ("backtile");
}
/*
===============
Draw_NewGame -- johnfitz
===============
*/
void Draw_NewGame (void)
{
cachepic_t *pic;
int i;
// empty scrap and reallocate gltextures
memset(scrap_allocated, 0, sizeof(scrap_allocated));
memset(scrap_texels, 255, sizeof(scrap_texels));
Scrap_Upload (); //creates 2 empty gltextures
// reload wad pics
W_LoadWadFile (); //johnfitz -- filename is now hard-coded for honesty
Draw_LoadPics ();
SCR_LoadPics ();
Sbar_LoadPics ();
// empty lmp cache
for (pic = menu_cachepics, i = 0; i < menu_numcachepics; pic++, i++)
pic->name[0] = 0;
menu_numcachepics = 0;
}
/*
===============
Draw_Init -- johnfitz -- rewritten
===============
*/
void Draw_Init (void)
{
Cvar_RegisterVariable (&scr_conalpha);
// clear scrap and allocate gltextures
memset(scrap_allocated, 0, sizeof(scrap_allocated));
memset(scrap_texels, 255, sizeof(scrap_texels));
Scrap_Upload (); //creates 2 empty textures
// create internal pics
pic_ins = Draw_MakePic ("ins", 8, 9, &pic_ins_data[0][0]);
pic_ovr = Draw_MakePic ("ovr", 8, 8, &pic_ovr_data[0][0]);
pic_nul = Draw_MakePic ("nul", 8, 8, &pic_nul_data[0][0]);
sniper_scope = Draw_CachePic ("gfx/hud/scope.tga");
//zombie_skins[0][0] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR);
//zombie_skins[0][1] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR);
//zombie_skins[1][0] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR);
//zombie_skins[1][1] = loadtextureimage("/textures/ai/z0",0,0,qfalse,GU_LINEAR);
// load game pics
Draw_LoadPics ();
Clear_LoadingFill ();
}
//==============================================================================
//
// 2D DRAWING
//
//==============================================================================
/*
================
Draw_CharacterQuadScale
Draw_CharacterQuad with scale parm
================
*/
void Draw_CharacterQuadScale (int x, int y, char num, float s)
{
int row, col;
float frow, fcol, size;
row = num>>4;
col = num&15;
frow = row*0.0625;
fcol = col*0.0625;
size = 0.0625*s;
glTexCoord2f (fcol, frow);
glVertex2f (x, y);
glTexCoord2f (fcol + (float)(size/s), frow);
glVertex2f (x+(8*(s)), y);
glTexCoord2f (fcol + (float)(size/s), frow + (float)(size/s));
glVertex2f (x+(8*(s)), y+(8*(s)));
glTexCoord2f (fcol, frow + (float)(size/s));
glVertex2f (x, y+(8*(s)));
}
/*
================
Draw_CharacterQuad -- johnfitz -- seperate function to spit out verts
================
*/
void Draw_CharacterQuad (int x, int y, char num)
{
int row, col;
float frow, fcol, size;
row = num>>4;
col = num&15;
frow = row*0.0625;
fcol = col*0.0625;
size = 0.0625;
glTexCoord2f (fcol, frow);
glVertex2f (x, y);
glTexCoord2f (fcol + size, frow);
glVertex2f (x+8, y);
glTexCoord2f (fcol + size, frow + size);
glVertex2f (x+8, y+8);
glTexCoord2f (fcol, frow + size);
glVertex2f (x, y+8);
}
/*
================
Draw_Character -- johnfitz -- modified to call Draw_CharacterQuad
================
*/
void Draw_Character (int x, int y, int num)
{
if (y <= -8)
return; // totally off screen
num &= 255;
if (num == 32)
return; //don't waste verts on spaces
GL_Bind (char_texture);
glBegin (GL_QUADS);
Draw_CharacterQuad (x, y, (char) num);
glEnd ();
}
void Draw_CharacterScale (int x, int y, int num, float scale)
{
if (y <= -8)
return; // totally off screen
num &= 255;
if (num == 32)
return; //don't waste verts on spaces
GL_Bind (char_texture);
glBegin (GL_QUADS);
Draw_CharacterQuadScale (x, y, (char) num, scale);
glEnd ();
}
/*
================
Draw_CharacterRGBA
This is the same as Draw_Character, but with RGBA color codes.
- cypress and ported to Quakespasm by sB :)
================
*/
void Draw_CharacterRGBA(int x, int y, int num, float r, float g, float b, float a)
{
int row, col;
float frow, fcol, size;
if (y <= -8)
return; // totally off screen
num &= 255;
if (num == 32)
return; //don't waste verts on spaces
glEnable (GL_BLEND);
glColor4f(r, g, b, a);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind (char_texture);
glBegin (GL_QUADS);
row = num>>4;
col = num&15;
frow = row*0.0625;
fcol = col*0.0625;
size = 0.0625;
glTexCoord2f (fcol, frow);
glVertex2f (x, y);
glTexCoord2f (fcol + size, frow);
glVertex2f (x+8, y);
glTexCoord2f (fcol + size, frow + size);
glVertex2f (x+8, y+8);
glTexCoord2f (fcol, frow + size);
glVertex2f (x, y+8);
glEnd ();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
/*
================
Draw_String -- johnfitz -- modified to call Draw_CharacterQuad
================
*/
void Draw_String (int x, int y, const char *str)
{
if (y <= -8)
return; // totally off screen
GL_Bind (char_texture);
glBegin (GL_QUADS);
while (*str)
{
if (*str != 32) //don't waste verts on spaces
Draw_CharacterQuad (x, y, *str);
str++;
x += 8;
}
glEnd ();
}
/*
================
Draw_ColoredStringScale
Draw_ColoredString with scale parm
================
*/
void Draw_ColoredStringScale (int x, int y, const char *str, float r, float g, float b, float a, float s)
{
if (y <= -8)
return; // totally off screen
glEnable (GL_BLEND);
glColor4f(r, g, b, a);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind (char_texture);
glBegin (GL_QUADS);
while (*str)
{
if (*str != 32) //don't waste verts on spaces
Draw_CharacterQuadScale (x, y, *str, s);
str++;
x += 8*s;
}
glEnd ();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
/*
================
Draw_ColoredString
Assume that all rgba values are divided by 255 already
================
*/
void Draw_ColoredString (int x, int y, const char *str, float r, float g, float b, float a)
{
if (y <= -8)
return; // totally off screen
glEnable (GL_BLEND);
glColor4f(r, g, b, a);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
GL_Bind (char_texture);
glBegin (GL_QUADS);
while (*str)
{
if (*str != 32) //don't waste verts on spaces
Draw_CharacterQuad (x, y, *str);
str++;
x += 8;
}
glEnd ();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
/*
=============
Draw_ColorPic
=============
*/
void Draw_ColorPic (int x, int y, qpic_t *pic, float r, float g, float b, float alpha)
{
glpic_t *gl;
if (alpha <= 1.0) {
glEnable (GL_BLEND);
glColor4f (r,g,b,alpha);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+pic->width, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+pic->width, y+pic->height);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+pic->height);
glEnd ();
if (alpha <= 1.0)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
}
//sB needed a way to stretch round pics
void Draw_ColorStretchPic (int x, int y, int width, int height, qpic_t *pic, float r, float g, float b, float alpha)
{
glpic_t *gl;
if (alpha <= 1.0) {
glEnable (GL_BLEND);
glColor4f (r,g,b,alpha);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
#ifdef VITA
glTexCoord2f (0, 0);
glVertex2f (x, y);
glTexCoord2f (1, 0);
glVertex2f (x+width, y);
glTexCoord2f (1, 1);
glVertex2f (x+width, y+height);
glTexCoord2f (0, 1);
glVertex2f (x, y+height);
#else
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+width, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+width, y+height);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+height);
#endif
glEnd ();
if (alpha <= 1.0)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
}
/*
=============
Draw_StretchPic
=============
*/
void Draw_StretchPic (int x, int y, qpic_t *pic, int x_value, int y_value)
{
glpic_t *gl;
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
#ifdef VITA
glTexCoord2f (0, 0);
glVertex2f (x, y);
glTexCoord2f (1, 0);
glVertex2f (x+x_value, y);
glTexCoord2f (1, 1);
glVertex2f (x+x_value, y+y_value);
glTexCoord2f (0, 1);
glVertex2f (x, y+y_value);
#else
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+x_value, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+x_value, y+y_value);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+y_value);
#endif
glEnd ();
}
/*
=============
Draw_Pic -- johnfitz -- modified
=============
*/
void Draw_Pic (int x, int y, qpic_t *pic)
{
glpic_t *gl;
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+pic->width, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+pic->width, y+pic->height);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+pic->height);
glEnd ();
}
/*
=============
Draw_Pic -- johnfitz -- modified
=============
*/
void Draw_SubPic(int x, int y, int width, int height, int start_x, int start_y, int end_x, int end_y, qpic_t *pic)
{
glpic_t *gl;
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
#ifdef VITA
// Calculate texture coordinates for the subsection
float subTexLeft = (start_x / (float)pic->width);
float subTexRight = (end_x / (float)pic->width);
float subTexTop = (start_y / (float)pic->height);
float subTexBottom = (end_y / (float)pic->height);
#else
// Calculate texture coordinates for the subsection
float subTexLeft = gl->sl + (start_x / (float)pic->width);
float subTexRight = gl->sl + (end_x / (float)pic->width);
float subTexTop = gl->tl + (start_y / (float)pic->height);
float subTexBottom = gl->tl + (end_y / (float)pic->height);
#endif // VITA
glTexCoord2f(subTexLeft, subTexTop);
glVertex2f(x, y);
glTexCoord2f(subTexRight, subTexTop);
glVertex2f(x + width, y);
glTexCoord2f(subTexRight, subTexBottom);
glVertex2f(x + width, y + height);
glTexCoord2f(subTexLeft, subTexBottom);
glVertex2f(x, y + height);
glEnd ();
}
// cypress -- ultimate draw function!! probably annihilates gl calls so use wisely lol
// TODO: color shifting?
void Draw_AlphaStretchPic (int x, int y, int width, int height, float alpha, qpic_t *pic)
{
glpic_t *gl;
if (alpha <= 1.0) {
glEnable (GL_BLEND);
glColor4f (1,1,1,alpha);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
} else {
glDisable (GL_ALPHA_TEST);
glEnable (GL_BLEND);
glDepthMask(GL_FALSE);
}
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
#ifdef VITA
glTexCoord2f (0, 0);
glVertex2f (x, y);
glTexCoord2f (1, 0);
glVertex2f (x+width, y);
glTexCoord2f (1, 1);
glVertex2f (x+width, y+height);
glTexCoord2f (0, 1);
glVertex2f (x, y+height);
#else
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+width, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+width, y+height);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+height);
#endif
glEnd ();
if (alpha <= 1.0)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
} else {
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
}
}
void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
{
glpic_t *gl;
if (alpha <= 1.0) {
glEnable (GL_BLEND);
glColor4f (1,1,1,alpha);
glDisable (GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
glTexCoord2f (gl->sl, gl->tl);
glVertex2f (x, y);
glTexCoord2f (gl->sh, gl->tl);
glVertex2f (x+pic->width, y);
glTexCoord2f (gl->sh, gl->th);
glVertex2f (x+pic->width, y+pic->height);
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+pic->height);
glEnd ();
if (alpha <= 1.0)
{
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
}
/*
=============
Draw_TransPicTranslate -- johnfitz -- rewritten to use texmgr to do translation
Only used for the player color selection menu
=============
*/
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, int top, int bottom)
{
static int oldtop = -2;
static int oldbottom = -2;
if (top != oldtop || bottom != oldbottom)
{
glpic_t *p = (glpic_t *)pic->data;
gltexture_t *glt = p->gltexture;
oldtop = top;
oldbottom = bottom;
TexMgr_ReloadImage (glt, top, bottom);
}
Draw_Pic (x, y, pic);
}
/*
================
Draw_ConsoleBackground -- johnfitz -- rewritten
================
*/
void Draw_ConsoleBackground (void)
{
GL_SetCanvas (CANVAS_CONSOLE); //in case this is called from weird places
Draw_FillByColor (0, 0, vid.conwidth, vid.conheight, 1, 1, 1, 200);
}
/*
================
Draw_LoadingFill
By Crow_bar
================
*/
void Draw_LoadingFill(void)
{
if(!loading_num_step)
return;
#ifdef VITA
int size = 16;
int max_step = 500;
int x = (vid.width / 2) - (max_step / 2);
int y = vid.height - (size/ 2) - 40;
#else
int size = 8;
int max_step = 350;
int x = (640 / 2) - (max_step / 2);
int y = 360 - (size/ 2) - 29;
#endif // VITA
int l;
char str[64];
char* text;
if(loading_cur_step > loading_num_step)
loading_cur_step = loading_num_step;
if (loading_cur_step < loading_cur_step_bk)
loading_cur_step = loading_cur_step_bk;
if (loading_cur_step == loading_num_step && loading_cur_step_bk != loading_num_step)
loading_cur_step = loading_cur_step_bk;
float loadsize = loading_cur_step * (max_step / loading_num_step);
Draw_FillByColor (x - 2, y - 2, max_step + 4, size + 4, 69, 69, 69, 255);
Draw_FillByColor (x, y, loadsize, size, 0, 0, 0, 200);
switch(loading_step) {
case 1: text = "Loading Models.."; break;
case 2: text = "Loading World.."; break;
case 3: text = "Executing Spawn Functions.."; break;
case 4: text = "Loading Sounds.."; break;
default: text = "Initializing.."; break;
}
l = strlen (text);
#ifdef VITA
Draw_ColoredStringScale((vid.width - l*16)/2, y, text, 1, 1, 1, 1, 2.0f);
#else
Draw_String((640 - l*8)/2, y, text);
#endif // VITA
loading_cur_step_bk = loading_cur_step;
}
void Clear_LoadingFill (void)
{
//it is end loading
loading_cur_step = 0;
loading_cur_step_bk = 0;
loading_num_step = 0;
loading_step = -1;
memset(loading_name, 0, sizeof(loading_name));
}
/*
=============
Draw_TileClear
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
*/
void Draw_TileClear (int x, int y, int w, int h)
{
glpic_t *gl;
gl = (glpic_t *)draw_backtile->data;
glColor3f (1,1,1);
GL_Bind (gl->gltexture);
glBegin (GL_QUADS);
glTexCoord2f (x/64.0, y/64.0);
glVertex2f (x, y);
glTexCoord2f ( (x+w)/64.0, y/64.0);
glVertex2f (x+w, y);
glTexCoord2f ( (x+w)/64.0, (y+h)/64.0);
glVertex2f (x+w, y+h);
glTexCoord2f ( x/64.0, (y+h)/64.0 );
glVertex2f (x, y+h);
glEnd ();
}
/*
=============
Draw_Fill
Fills a box of pixels with a single color
=============
*/
void Draw_Fill (int x, int y, int w, int h, int c, float alpha) //johnfitz -- added alpha
{
byte *pal = (byte *)d_8to24table; //johnfitz -- use d_8to24table instead of host_basepal
glDisable (GL_TEXTURE_2D);
glEnable (GL_BLEND); //johnfitz -- for alpha
glDisable (GL_ALPHA_TEST); //johnfitz -- for alpha
glColor4f (pal[c*4]/255.0, pal[c*4+1]/255.0, pal[c*4+2]/255.0, alpha); //johnfitz -- added alpha
glBegin (GL_QUADS);
glVertex2f (x,y);
glVertex2f (x+w, y);
glVertex2f (x+w, y+h);
glVertex2f (x, y+h);
glEnd ();
glColor3f (1,1,1);
glDisable (GL_BLEND); //johnfitz -- for alpha
glEnable(GL_ALPHA_TEST); //johnfitz -- for alpha
glEnable (GL_TEXTURE_2D);
}
/*
=============
Draw_FillByColor
Fills a box of pixels with a single color not in basepal
=============
*/
void Draw_FillByColor (int x, int y, int w, int h, float r, float g, float b, float a)
{
glDisable (GL_TEXTURE_2D);
glEnable (GL_BLEND);
glDisable (GL_ALPHA_TEST);
glColor4f (r/255, g/255, b/255, a/255);
glBegin (GL_QUADS);
glVertex2f (x,y);
glVertex2f (x+w, y);
glVertex2f (x+w, y+h);
glVertex2f (x, y+h);
glEnd ();
glColor4f (1,1,1,1);
glDisable (GL_BLEND);
glEnable(GL_ALPHA_TEST);
glEnable (GL_TEXTURE_2D);
}
/*
================
Draw_FadeScreen -- johnfitz -- revised
================
*/
void Draw_FadeScreen (void)
{
GL_SetCanvas (CANVAS_DEFAULT);
glEnable (GL_BLEND);
glDisable (GL_ALPHA_TEST);
glDisable (GL_TEXTURE_2D);
glColor4f (0, 0, 0, 0.5);
glBegin (GL_QUADS);
glVertex2f (0,0);
glVertex2f (glwidth, 0);
glVertex2f (glwidth, glheight);
glVertex2f (0, glheight);
glEnd ();
glColor4f (1,1,1,1);
glEnable (GL_TEXTURE_2D);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
Sbar_Changed();
}
/*
================
GL_SetCanvas -- johnfitz -- support various canvas types
================
*/
void GL_SetCanvas (canvastype newcanvas)
{
extern vrect_t scr_vrect;
float s;
int lines;
if (newcanvas == currentcanvas)
return;
currentcanvas = newcanvas;
glMatrixMode(GL_PROJECTION);
glLoadIdentity ();
switch(newcanvas)
{
case CANVAS_DEFAULT:
glOrtho (0, glwidth, glheight, 0, -99999, 99999);
glViewport (glx, gly, glwidth, glheight);
break;
case CANVAS_CONSOLE:
lines = vid.conheight - (scr_con_current * vid.conheight / glheight);
glOrtho (0, vid.conwidth, vid.conheight + lines, lines, -99999, 99999);
glViewport (glx, gly, glwidth, glheight);
break;
case CANVAS_MENU:
s = q_min((float)glwidth / 320.0, (float)glheight / 200.0);
s = CLAMP (1.0, scr_menuscale.value, s);
// ericw -- doubled width to 640 to accommodate long keybindings
glOrtho (0, 640, 200, 0, -99999, 99999);
glViewport (glx + (glwidth - 320*s) / 2, gly + (glheight - 200*s) / 2, 640*s, 200*s);
break;
case CANVAS_SBAR:
s = CLAMP (1.0, scr_sbarscale.value, (float)glwidth / 320.0);
if (cl.gametype == GAME_DEATHMATCH)
{
glOrtho (0, glwidth / s, 48, 0, -99999, 99999);
glViewport (glx, gly, glwidth, 48*s);
}
else
{
glOrtho (0, 320, 48, 0, -99999, 99999);
glViewport (glx + (glwidth - 320*s) / 2, gly, 320*s, 48*s);
}
break;
case CANVAS_WARPIMAGE:
glOrtho (0, 128, 0, 128, -99999, 99999);
glViewport (glx, gly+glheight-gl_warpimagesize, gl_warpimagesize, gl_warpimagesize);
break;
case CANVAS_CROSSHAIR: //0,0 is center of viewport
s = CLAMP (1.0, scr_crosshairscale.value, 10.0);
glOrtho (scr_vrect.width/-2/s, scr_vrect.width/2/s, scr_vrect.height/2/s, scr_vrect.height/-2/s, -99999, 99999);
glViewport (scr_vrect.x, glheight - scr_vrect.y - scr_vrect.height, scr_vrect.width & ~1, scr_vrect.height & ~1);
break;
case CANVAS_BOTTOMLEFT: //used by devstats
s = (float)glwidth/vid.conwidth; //use console scale
glOrtho (0, 320, 200, 0, -99999, 99999);
glViewport (glx, gly, 320*s, 200*s);
break;
case CANVAS_BOTTOMRIGHT: //used by fps/clock
s = (float)glwidth/vid.conwidth; //use console scale
glOrtho (0, 320, 200, 0, -99999, 99999);
glViewport (glx+glwidth-320*s, gly, 320*s, 200*s);
break;
case CANVAS_TOPRIGHT: //used by disc
s = 1;
glOrtho (0, 320, 200, 0, -99999, 99999);
glViewport (glx+glwidth-320*s, gly+glheight-200*s, 320*s, 200*s);
break;
case CANVAS_USEPRINT:
s = (float)glwidth/vid.conwidth; //use console scale
glOrtho (0, glwidth, glheight, 0, -99999, 99999);
glViewport (glx, gly, glwidth*s, glheight*s);
break;
case CANVAS_HUD: // FIXME: Workaround for Vita build, would be better to rework completely gl_hud.c code.
s = (float)glwidth/vid.conwidth; //use console scale
s *= 2;
glOrtho (0, glwidth, glheight, 0, -99999, 99999);
glViewport (glx, gly, glwidth*s, glheight*s);
break;
default:
Sys_Error ("GL_SetCanvas: bad canvas type");
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
}
/*
================
GL_Set2D -- johnfitz -- rewritten
================
*/
void GL_Set2D (void)
{
currentcanvas = CANVAS_INVALID;
GL_SetCanvas (CANVAS_DEFAULT);
glDisable (GL_DEPTH_TEST);
glDisable (GL_CULL_FACE);
glDisable (GL_BLEND);
glEnable(GL_ALPHA_TEST);
glColor4f (1,1,1,1);
}
/*
================
GL_ResampleTexture
================
*/
void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out, int outwidth, int outheight)
{
int i, j;
unsigned *inrow;
unsigned frac, fracstep;
fracstep = inwidth*0x10000/outwidth;
for (i=0 ; i<outheight ; i++, out += outwidth)
{
inrow = in + inwidth*(i*inheight/outheight);
frac = fracstep >> 1;
for (j=0 ; j<outwidth ; j+=4)
{
out[j] = inrow[frac>>16];
frac += fracstep;
out[j+1] = inrow[frac>>16];
frac += fracstep;
out[j+2] = inrow[frac>>16];
frac += fracstep;
out[j+3] = inrow[frac>>16];
frac += fracstep;
}
}
}
/*
int loading_cur_step;
int loading_num_step;
void Clear_LoadingFill (void)
{
//it is end loading
loading_cur_step = 0;
loading_num_step = 0;
}
*/
/*
=============
loadtextureimage
=============
*/
gltexture_t *loadtextureimage (char* filename)
{
byte *data;
glpic_t gl;
int w, h;
data = Image_LoadImage (filename, &w, &h);
if(!data)
{
Sys_Error("loadtextureimage: Cannot load the image %s\n", filename);
//return 0;
}
gl.gltexture = TexMgr_LoadImage (NULL, filename, w, h, SRC_RGBA, data, filename, sizeof(int)*2, TEXPREF_ALPHA | TEXPREF_NEAREST | TEXPREF_NOPICMIP);
return gl.gltexture;
}