2000-05-10 20:33:16 +00:00
|
|
|
/*
|
2000-05-11 16:03:29 +00:00
|
|
|
gl_draw.c
|
2000-05-10 20:33:16 +00:00
|
|
|
|
2000-05-12 16:16:29 +00:00
|
|
|
Draw functions for chars, textures, etc
|
2000-05-10 20:33:16 +00:00
|
|
|
|
2000-05-11 16:03:29 +00:00
|
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
2000-05-10 20:33:16 +00:00
|
|
|
|
2000-05-11 16:03:29 +00:00
|
|
|
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.
|
2000-05-10 20:33:16 +00:00
|
|
|
|
2000-05-11 16:03:29 +00:00
|
|
|
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.
|
2000-05-10 20:33:16 +00:00
|
|
|
|
2000-05-11 16:03:29 +00:00
|
|
|
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:
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-05-11 16:03:29 +00:00
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
$Id$
|
|
|
|
*/
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-05-17 10:03:19 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2000-05-23 17:05:34 +00:00
|
|
|
# include "config.h"
|
2000-05-17 10:03:19 +00:00
|
|
|
#endif
|
2000-05-23 17:05:34 +00:00
|
|
|
|
2000-05-12 16:16:29 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2000-05-26 03:55:27 +00:00
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
#include <strings.h>
|
|
|
|
#endif
|
2000-05-12 16:16:29 +00:00
|
|
|
|
|
|
|
#include "bothdefs.h" // needed by: common.h, net.h, client.h
|
|
|
|
|
2000-09-22 15:08:28 +00:00
|
|
|
#include "crc.h" // LordHavoc: for texture update validation
|
2000-05-12 16:16:29 +00:00
|
|
|
#include "bspfile.h" // needed by: glquake.h
|
|
|
|
#include "vid.h"
|
|
|
|
#include "sys.h"
|
|
|
|
#include "mathlib.h" // needed by: protocol.h, render.h, client.h,
|
|
|
|
// modelgen.h, glmodel.h
|
|
|
|
#include "wad.h"
|
|
|
|
#include "draw.h"
|
|
|
|
#include "cvar.h"
|
|
|
|
#include "net.h" // needed by: client.h
|
|
|
|
#include "protocol.h" // needed by: client.h
|
|
|
|
#include "cmd.h"
|
|
|
|
#include "sbar.h"
|
2000-05-13 20:47:01 +00:00
|
|
|
#include "render.h" // needed by: client.h, model.h, glquake.h
|
2000-05-12 16:16:29 +00:00
|
|
|
#include "client.h" // need cls in this file
|
2000-05-13 20:47:01 +00:00
|
|
|
#include "model.h" // needed by: glquake.h
|
2000-05-12 16:16:29 +00:00
|
|
|
#include "console.h"
|
|
|
|
#include "glquake.h"
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
static int GL_LoadPicTexture (qpic_t *pic);
|
2000-06-26 02:35:40 +00:00
|
|
|
|
2000-05-12 19:17:02 +00:00
|
|
|
extern byte *host_basepal;
|
2000-05-10 11:29:38 +00:00
|
|
|
extern unsigned char d_15to8table[65536];
|
2000-05-16 04:47:41 +00:00
|
|
|
extern cvar_t *crosshair, *cl_crossx, *cl_crossy, *crosshaircolor;
|
|
|
|
|
|
|
|
cvar_t *gl_max_size;
|
|
|
|
cvar_t *gl_picmip;
|
|
|
|
|
2000-05-29 10:16:04 +00:00
|
|
|
cvar_t *gl_constretch;
|
|
|
|
cvar_t *gl_conalpha;
|
|
|
|
cvar_t *gl_conspin;
|
2000-05-16 04:47:41 +00:00
|
|
|
cvar_t *cl_verstring;
|
2000-07-02 05:16:10 +00:00
|
|
|
cvar_t *gl_lightmode; // LordHavoc: lighting mode
|
2000-05-13 20:51:02 +00:00
|
|
|
|
2000-05-14 07:40:41 +00:00
|
|
|
extern byte *draw_chars; // 8*8 graphic characters
|
2000-05-10 11:29:38 +00:00
|
|
|
qpic_t *draw_disc;
|
|
|
|
qpic_t *draw_backtile;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
static int translate_texture;
|
|
|
|
static int char_texture;
|
|
|
|
static int cs_texture; // crosshair texturea
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
static byte cs_data[64] = {
|
|
|
|
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int texnum;
|
2000-06-26 02:35:40 +00:00
|
|
|
int bytesperpixel;
|
2000-05-10 11:29:38 +00:00
|
|
|
float sl, tl, sh, th;
|
|
|
|
} glpic_t;
|
|
|
|
|
|
|
|
int gl_lightmap_format = 4;
|
|
|
|
int gl_solid_format = 3;
|
|
|
|
int gl_alpha_format = 4;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
static int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST;
|
|
|
|
static int gl_filter_max = GL_LINEAR;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
int texnum;
|
|
|
|
char identifier[64];
|
|
|
|
int width, height;
|
2000-06-23 08:43:32 +00:00
|
|
|
int bytesperpixel;
|
2000-05-10 11:29:38 +00:00
|
|
|
qboolean mipmap;
|
2000-09-22 15:08:28 +00:00
|
|
|
unsigned short crc; // LordHavoc: CRC for texture validation
|
2000-05-10 11:29:38 +00:00
|
|
|
} gltexture_t;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
static gltexture_t gltextures[MAX_GLTEXTURES];
|
|
|
|
static int numgltextures = 0;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
=============================================================================
|
|
|
|
|
|
|
|
scrap allocation
|
|
|
|
|
|
|
|
Allocate all the little status bar obejcts into a single texture
|
|
|
|
to crutch up stupid hardware / drivers
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
Note, this is a kluge, which may slow down sane cards..
|
|
|
|
As such its all contained in ifdefs..
|
|
|
|
|
2000-05-10 11:29:38 +00:00
|
|
|
=============================================================================
|
|
|
|
*/
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
#undef gl_draw_scraps
|
|
|
|
|
|
|
|
#ifdef gl_draw_scraps
|
|
|
|
|
2000-05-10 11:29:38 +00:00
|
|
|
#define MAX_SCRAPS 1
|
|
|
|
#define BLOCK_WIDTH 256
|
|
|
|
#define BLOCK_HEIGHT 256
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
static int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH];
|
|
|
|
static byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH*BLOCK_HEIGHT*4];
|
|
|
|
static qboolean scrap_dirty;
|
|
|
|
static int scrap_texnum;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
// returns a texture number and the position inside it
|
2000-08-14 04:53:45 +00:00
|
|
|
static int Scrap_AllocBlock (int w, int h, int *x, int *y)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
int best, best2;
|
|
|
|
int texnum;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
for (texnum=0 ; texnum<MAX_SCRAPS ; texnum++) {
|
2000-05-10 11:29:38 +00:00
|
|
|
best = BLOCK_HEIGHT;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
for (i=0 ; i<BLOCK_WIDTH-w ; i++) {
|
2000-05-10 11:29:38 +00:00
|
|
|
best2 = 0;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
for (j=0 ; j<w ; j++) {
|
2000-05-10 11:29:38 +00:00
|
|
|
if (scrap_allocated[texnum][i+j] >= best)
|
|
|
|
break;
|
|
|
|
if (scrap_allocated[texnum][i+j] > best2)
|
|
|
|
best2 = scrap_allocated[texnum][i+j];
|
|
|
|
}
|
2000-08-14 04:53:45 +00:00
|
|
|
if (j == w) { // this is a valid spot
|
2000-05-10 11:29:38 +00:00
|
|
|
*x = i;
|
|
|
|
*y = best = best2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (best + h > BLOCK_HEIGHT)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for (i=0 ; i<w ; i++)
|
|
|
|
scrap_allocated[texnum][*x + i] = best + h;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
scrap_dirty = true;
|
2000-05-10 11:29:38 +00:00
|
|
|
return texnum;
|
|
|
|
}
|
|
|
|
|
|
|
|
Sys_Error ("Scrap_AllocBlock: full");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
static void Scrap_Upload (void)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
2000-06-17 10:39:28 +00:00
|
|
|
glBindTexture (GL_TEXTURE_2D, scrap_texnum);
|
2000-05-10 11:29:38 +00:00
|
|
|
GL_Upload8 (scrap_texels[0], BLOCK_WIDTH, BLOCK_HEIGHT, false, true);
|
|
|
|
scrap_dirty = false;
|
|
|
|
}
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
#endif
|
|
|
|
|
2000-05-10 11:29:38 +00:00
|
|
|
//=============================================================================
|
|
|
|
/* Support Routines */
|
|
|
|
|
|
|
|
typedef struct cachepic_s
|
|
|
|
{
|
|
|
|
char name[MAX_QPATH];
|
2000-06-23 18:36:59 +00:00
|
|
|
qboolean dirty;
|
2000-05-10 11:29:38 +00:00
|
|
|
qpic_t pic;
|
|
|
|
byte padding[32]; // for appended glpic
|
|
|
|
} cachepic_t;
|
|
|
|
|
|
|
|
#define MAX_CACHED_PICS 128
|
2000-08-14 04:53:45 +00:00
|
|
|
static cachepic_t cachepics[MAX_CACHED_PICS];
|
|
|
|
static int numcachepics;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
static byte menuplyr_pixels[4096];
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
qpic_t *Draw_PicFromWad (char *name)
|
|
|
|
{
|
|
|
|
qpic_t *p;
|
|
|
|
glpic_t *gl;
|
|
|
|
|
|
|
|
p = W_GetLumpName (name);
|
|
|
|
gl = (glpic_t *)p->data;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
#ifdef gl_draw_scraps
|
2000-05-10 11:29:38 +00:00
|
|
|
// load little ones into the scrap
|
2000-08-14 04:53:45 +00:00
|
|
|
if (p->width < 64 && p->height < 64) {
|
2000-05-10 11:29:38 +00:00
|
|
|
int x, y;
|
|
|
|
int i, j, k;
|
|
|
|
int texnum;
|
|
|
|
|
|
|
|
texnum = Scrap_AllocBlock (p->width, p->height, &x, &y);
|
|
|
|
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];
|
|
|
|
texnum += scrap_texnum;
|
|
|
|
gl->texnum = texnum;
|
|
|
|
gl->sl = (x+0.01)/(float)BLOCK_WIDTH;
|
|
|
|
gl->sh = (x+p->width-0.01)/(float)BLOCK_WIDTH;
|
|
|
|
gl->tl = (y+0.01)/(float)BLOCK_WIDTH;
|
|
|
|
gl->th = (y+p->height-0.01)/(float)BLOCK_WIDTH;
|
|
|
|
}
|
|
|
|
else
|
2000-08-14 04:53:45 +00:00
|
|
|
#endif
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
gl->texnum = GL_LoadPicTexture (p);
|
|
|
|
gl->sl = 0;
|
|
|
|
gl->sh = 1;
|
|
|
|
gl->tl = 0;
|
|
|
|
gl->th = 1;
|
|
|
|
}
|
2000-08-14 04:53:45 +00:00
|
|
|
|
2000-05-10 11:29:38 +00:00
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2000-06-23 18:36:59 +00:00
|
|
|
void
|
|
|
|
Draw_ClearCache (void)
|
|
|
|
{
|
|
|
|
cachepic_t *pic;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (pic=cachepics, i=0 ; i<numcachepics ; pic++, i++)
|
|
|
|
pic->dirty = true;
|
|
|
|
}
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_CachePic
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
qpic_t *Draw_CachePic (char *path)
|
|
|
|
{
|
|
|
|
cachepic_t *pic;
|
|
|
|
int i;
|
|
|
|
qpic_t *dat;
|
|
|
|
glpic_t *gl;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
// First, check and see if its cached..
|
2000-06-23 18:36:59 +00:00
|
|
|
for (pic=cachepics, i=0 ; i<numcachepics ; pic++, i++)
|
2000-08-14 04:53:45 +00:00
|
|
|
if ((!strcmp (path, pic->name)) && !pic->dirty)
|
|
|
|
return &pic->pic;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
// Its not cached, lets make sure we have space in the cache..
|
|
|
|
if (numcachepics == MAX_CACHED_PICS)
|
|
|
|
Sys_Error ("menu_numcachepics == MAX_CACHED_PICS");
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
// Load the picture..
|
2000-05-10 11:29:38 +00:00
|
|
|
dat = (qpic_t *)COM_LoadTempFile (path);
|
|
|
|
if (!dat)
|
|
|
|
Sys_Error ("Draw_CachePic: failed to load %s", path);
|
2000-08-14 04:53:45 +00:00
|
|
|
|
|
|
|
// Adjust for endian..
|
2000-05-10 11:29:38 +00:00
|
|
|
SwapPic (dat);
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
// Ok, the image is here, lets load it up into the cache..
|
|
|
|
|
|
|
|
// First the image name..
|
|
|
|
strncpy (pic->name, path, sizeof(pic->name));
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
// Now the width and height.
|
2000-05-10 11:29:38 +00:00
|
|
|
pic->pic.width = dat->width;
|
|
|
|
pic->pic.height = dat->height;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
// Now feed it to the GL stuff and get a texture number..
|
2000-05-10 11:29:38 +00:00
|
|
|
gl = (glpic_t *)pic->pic.data;
|
|
|
|
gl->texnum = GL_LoadPicTexture (dat);
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
// Alignment stuff..
|
|
|
|
gl->sl = 0; gl->sh = 1; gl->tl = 0; gl->th = 1;
|
|
|
|
|
|
|
|
// Now lets mark this cache entry as used..
|
|
|
|
pic->dirty = false;
|
|
|
|
numcachepics++;
|
|
|
|
|
|
|
|
// FIXME:
|
|
|
|
// A really ugly kluge, keep a specific image in memory
|
|
|
|
// for the menu system.
|
|
|
|
//
|
|
|
|
// Some days I really dislike legacy support..
|
|
|
|
|
|
|
|
if (!strcmp (path, "gfx/menuplyr.lmp"))
|
|
|
|
memcpy (menuplyr_pixels, dat->data, dat->width*dat->height);
|
|
|
|
|
|
|
|
// And now we are done, return what was asked for..
|
2000-05-10 11:29:38 +00:00
|
|
|
return &pic->pic;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
int minimize, maximize;
|
|
|
|
} glmode_t;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
static glmode_t modes[] = {
|
2000-05-10 11:29:38 +00:00
|
|
|
{"GL_NEAREST", GL_NEAREST, GL_NEAREST},
|
|
|
|
{"GL_LINEAR", GL_LINEAR, GL_LINEAR},
|
|
|
|
{"GL_NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST},
|
|
|
|
{"GL_LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR},
|
|
|
|
{"GL_NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST},
|
|
|
|
{"GL_LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR}
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Draw_TextureMode_f
|
|
|
|
===============
|
|
|
|
*/
|
2000-08-14 04:53:45 +00:00
|
|
|
static void Draw_TextureMode_f (void)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
gltexture_t *glt;
|
|
|
|
|
|
|
|
if (Cmd_Argc() == 1)
|
|
|
|
{
|
|
|
|
for (i=0 ; i< 6 ; i++)
|
|
|
|
if (gl_filter_min == modes[i].minimize)
|
|
|
|
{
|
|
|
|
Con_Printf ("%s\n", modes[i].name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Con_Printf ("current filter is unknown???\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0 ; i< 6 ; i++)
|
|
|
|
{
|
2000-05-23 17:05:34 +00:00
|
|
|
if (!stricmp (modes[i].name, Cmd_Argv(1) ) )
|
2000-05-10 11:29:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == 6)
|
|
|
|
{
|
|
|
|
Con_Printf ("bad filter name\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gl_filter_min = modes[i].minimize;
|
|
|
|
gl_filter_max = modes[i].maximize;
|
|
|
|
|
|
|
|
// change all the existing mipmap texture objects
|
|
|
|
for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
|
|
|
|
{
|
|
|
|
if (glt->mipmap)
|
|
|
|
{
|
2000-06-17 10:39:28 +00:00
|
|
|
glBindTexture (GL_TEXTURE_2D, glt->texnum);
|
|
|
|
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
|
|
|
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-07-02 05:16:10 +00:00
|
|
|
extern void glrmain_init();
|
|
|
|
extern void glrsurf_init();
|
2000-05-10 11:29:38 +00:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Draw_Init
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void Draw_Init (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2000-07-02 05:16:10 +00:00
|
|
|
// LordHavoc: lighting mode
|
|
|
|
gl_lightmode = Cvar_Get("gl_lightmode", "1", CVAR_ARCHIVE,
|
|
|
|
"Lighting mode (0 = GLQuake style, 1 = new style)");
|
2000-05-29 10:16:04 +00:00
|
|
|
gl_max_size = Cvar_Get("gl_max_size", "1024", CVAR_NONE,
|
|
|
|
"None"); // CVAR_FIXME - set a description
|
|
|
|
gl_picmip = Cvar_Get("gl_picmip", "0", CVAR_NONE,
|
|
|
|
"None"); // CVAR_FIXME - set a description
|
|
|
|
|
|
|
|
// Console effects --KB
|
|
|
|
gl_constretch = Cvar_Get ("gl_constretch", "0", CVAR_ARCHIVE,
|
|
|
|
"whether slide the console or stretch it");
|
|
|
|
gl_conalpha = Cvar_Get ("gl_conalpha", "0.6", CVAR_ARCHIVE,
|
|
|
|
"alpha value for the console background");
|
|
|
|
gl_conspin = Cvar_Get ("gl_conspin", "0", CVAR_ARCHIVE,
|
|
|
|
"speed at which the console spins");
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-05-29 10:16:04 +00:00
|
|
|
cl_verstring = Cvar_Get("cl_verstring", PROGRAM " " VERSION, CVAR_NONE,
|
|
|
|
"client version string");
|
2000-05-13 20:51:02 +00:00
|
|
|
|
2000-05-10 11:29:38 +00:00
|
|
|
// 3dfx can only handle 256 wide textures
|
2000-05-21 08:24:45 +00:00
|
|
|
if (!strncasecmp ((char *)gl_renderer, "3dfx",4) ||
|
|
|
|
!strncasecmp ((char *)gl_renderer, "Mesa",4))
|
2000-05-17 23:16:23 +00:00
|
|
|
Cvar_Set (gl_max_size, "256");
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-07-02 05:16:10 +00:00
|
|
|
// LordHavoc: 3DFX's dithering has terrible artifacting when using lightmode 1
|
|
|
|
if (!strncasecmp ((char *)gl_renderer, "3dfx",4))
|
|
|
|
Cvar_Set (gl_lightmode, "0");
|
|
|
|
lighthalf = gl_lightmode->value != 0; // to avoid re-rendering all lightmaps on first frame
|
2000-09-28 00:22:24 +00:00
|
|
|
if (lighthalf) {
|
|
|
|
lighthalf_v[0] = lighthalf_v[1] = lighthalf_v[2] = 128;
|
|
|
|
} else {
|
|
|
|
lighthalf_v[0] = lighthalf_v[1] = lighthalf_v[2] = 255;
|
|
|
|
}
|
2000-07-02 05:16:10 +00:00
|
|
|
|
2000-05-10 11:29:38 +00:00
|
|
|
Cmd_AddCommand ("gl_texturemode", &Draw_TextureMode_f);
|
|
|
|
|
|
|
|
// load the console background and the charset
|
|
|
|
// by hand, because we need to write the version
|
|
|
|
// string into the background before turning
|
|
|
|
// it into a texture
|
|
|
|
draw_chars = W_GetLumpName ("conchars");
|
|
|
|
for (i=0 ; i<256*64 ; i++)
|
|
|
|
if (draw_chars[i] == 0)
|
|
|
|
draw_chars[i] = 255; // proper transparent color
|
|
|
|
|
|
|
|
// now turn them into textures
|
2000-08-17 20:15:20 +00:00
|
|
|
char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1); // 1999-12-27 Conwidth/height charset fix by TcT
|
2000-09-22 09:12:03 +00:00
|
|
|
cs_texture = GL_LoadTexture ("crosshair", 8, 8, cs_data, false, true, 1);
|
|
|
|
// char_texture = GL_LoadTexture ("charset", 128, 128, draw_chars, false, true, 1); // 1999-12-27 Conwidth/height charset fix by TcT
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
|
|
|
|
// save a texture slot for translated picture
|
|
|
|
translate_texture = texture_extension_number++;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
#ifdef gl_draw_scraps
|
2000-05-10 11:29:38 +00:00
|
|
|
// save slots for scraps
|
|
|
|
scrap_texnum = texture_extension_number;
|
|
|
|
texture_extension_number += MAX_SCRAPS;
|
2000-08-14 04:53:45 +00:00
|
|
|
#endif
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// get the other pics we need
|
|
|
|
//
|
|
|
|
draw_disc = Draw_PicFromWad ("disc");
|
|
|
|
draw_backtile = Draw_PicFromWad ("backtile");
|
2000-07-02 05:16:10 +00:00
|
|
|
|
|
|
|
// LordHavoc: call init code for other GL renderer modules;
|
|
|
|
glrmain_init();
|
|
|
|
glrsurf_init();
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
2000-06-05 01:05:25 +00:00
|
|
|
Draw_Character8
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
Draws one 8*8 graphics character with 0 being transparent.
|
|
|
|
It can be clipped to the top of the screen to allow the console to be
|
|
|
|
smoothly scrolled off.
|
|
|
|
================
|
|
|
|
*/
|
2000-06-05 01:05:25 +00:00
|
|
|
void Draw_Character8 (int x, int y, int num)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
int row, col;
|
|
|
|
float frow, fcol, size;
|
|
|
|
|
|
|
|
if (num == 32)
|
|
|
|
return; // space
|
|
|
|
|
|
|
|
num &= 255;
|
|
|
|
|
|
|
|
if (y <= -8)
|
|
|
|
return; // totally off screen
|
|
|
|
|
|
|
|
row = num>>4;
|
|
|
|
col = num&15;
|
|
|
|
|
|
|
|
frow = row*0.0625;
|
|
|
|
fcol = col*0.0625;
|
|
|
|
size = 0.0625;
|
|
|
|
|
2000-06-17 10:39:28 +00:00
|
|
|
glBindTexture (GL_TEXTURE_2D, char_texture);
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
2000-06-05 01:05:25 +00:00
|
|
|
Draw_String8
|
2000-05-10 11:29:38 +00:00
|
|
|
================
|
|
|
|
*/
|
2000-06-05 01:05:25 +00:00
|
|
|
void Draw_String8 (int x, int y, char *str)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
while (*str)
|
|
|
|
{
|
2000-06-05 01:05:25 +00:00
|
|
|
Draw_Character8 (x, y, *str);
|
2000-05-10 11:29:38 +00:00
|
|
|
str++;
|
|
|
|
x += 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
2000-06-05 01:05:25 +00:00
|
|
|
Draw_AltString8
|
2000-05-10 11:29:38 +00:00
|
|
|
================
|
|
|
|
*/
|
2000-06-05 01:05:25 +00:00
|
|
|
void Draw_AltString8 (int x, int y, char *str)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
while (*str)
|
|
|
|
{
|
2000-06-05 01:05:25 +00:00
|
|
|
Draw_Character8 (x, y, (*str) | 0x80);
|
2000-05-10 11:29:38 +00:00
|
|
|
str++;
|
|
|
|
x += 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Draw_Crosshair(void)
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
extern vrect_t scr_vrect;
|
|
|
|
unsigned char *pColor;
|
|
|
|
|
2000-08-31 17:36:02 +00:00
|
|
|
switch ((int) crosshair->value) {
|
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
default:
|
|
|
|
Draw_Character8 (
|
|
|
|
scr_vrect.x + scr_vrect.width/2-4 + cl_crossx->value,
|
|
|
|
scr_vrect.y + scr_vrect.height/2-4 + cl_crossy->value, '+');
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
x = scr_vrect.x + scr_vrect.width/2 - 3 + cl_crossx->value;
|
|
|
|
y = scr_vrect.y + scr_vrect.height/2 - 3 + cl_crossy->value;
|
|
|
|
|
|
|
|
pColor = (unsigned char *) &d_8to24table[(byte) crosshaircolor->value];
|
|
|
|
if (lighthalf)
|
|
|
|
glColor4ub((byte) ((int) pColor[0] >> 1),(byte) ((int) pColor[1] >> 1), (byte) ((int) pColor[2] >> 1), pColor[3]);
|
|
|
|
else
|
|
|
|
glColor4ubv(pColor);
|
|
|
|
glBindTexture (GL_TEXTURE_2D, cs_texture);
|
|
|
|
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glTexCoord2f (0, 0);
|
|
|
|
glVertex2f (x - 4, y - 4);
|
|
|
|
glTexCoord2f (1, 0);
|
|
|
|
glVertex2f (x+12, y-4);
|
|
|
|
glTexCoord2f (1, 1);
|
|
|
|
glVertex2f (x+12, y+12);
|
|
|
|
glTexCoord2f (0, 1);
|
|
|
|
glVertex2f (x - 4, y+12);
|
|
|
|
glEnd ();
|
2000-09-28 00:22:24 +00:00
|
|
|
glColor3ubv(lighthalf_v);
|
2000-08-31 17:36:02 +00:00
|
|
|
break;
|
2000-06-23 18:36:59 +00:00
|
|
|
}
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_Pic
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void Draw_Pic (int x, int y, qpic_t *pic)
|
|
|
|
{
|
|
|
|
glpic_t *gl;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
#ifdef gl_draw_scraps
|
2000-05-10 11:29:38 +00:00
|
|
|
if (scrap_dirty)
|
|
|
|
Scrap_Upload ();
|
2000-08-14 04:53:45 +00:00
|
|
|
#endif
|
2000-05-10 11:29:38 +00:00
|
|
|
gl = (glpic_t *)pic->data;
|
2000-07-02 05:16:10 +00:00
|
|
|
if (lighthalf)
|
|
|
|
glColor3f(0.4,0.4,0.4);
|
|
|
|
else
|
|
|
|
glColor3f(0.8,0.8,0.8);
|
2000-06-17 10:39:28 +00:00
|
|
|
glBindTexture (GL_TEXTURE_2D, gl->texnum);
|
2000-05-10 11:29:38 +00:00
|
|
|
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 ();
|
2000-09-28 00:22:24 +00:00
|
|
|
glColor3ubv(lighthalf_v);
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height)
|
|
|
|
{
|
|
|
|
glpic_t *gl;
|
|
|
|
float newsl, newtl, newsh, newth;
|
|
|
|
float oldglwidth, oldglheight;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
#ifdef gl_draw_scraps
|
2000-05-10 11:29:38 +00:00
|
|
|
if (scrap_dirty)
|
|
|
|
Scrap_Upload ();
|
2000-08-14 04:53:45 +00:00
|
|
|
#endif
|
2000-05-10 11:29:38 +00:00
|
|
|
gl = (glpic_t *)pic->data;
|
|
|
|
|
|
|
|
oldglwidth = gl->sh - gl->sl;
|
|
|
|
oldglheight = gl->th - gl->tl;
|
|
|
|
|
|
|
|
newsl = gl->sl + (srcx*oldglwidth)/pic->width;
|
|
|
|
newsh = newsl + (width*oldglwidth)/pic->width;
|
|
|
|
|
|
|
|
newtl = gl->tl + (srcy*oldglheight)/pic->height;
|
|
|
|
newth = newtl + (height*oldglheight)/pic->height;
|
|
|
|
|
2000-07-02 05:16:10 +00:00
|
|
|
if (lighthalf)
|
|
|
|
glColor3f(0.4,0.4,0.4);
|
|
|
|
else
|
|
|
|
glColor3f(0.8,0.8,0.8);
|
2000-06-17 10:39:28 +00:00
|
|
|
glBindTexture (GL_TEXTURE_2D, gl->texnum);
|
2000-05-10 11:29:38 +00:00
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glTexCoord2f (newsl, newtl);
|
|
|
|
glVertex2f (x, y);
|
|
|
|
glTexCoord2f (newsh, newtl);
|
|
|
|
glVertex2f (x+width, y);
|
|
|
|
glTexCoord2f (newsh, newth);
|
|
|
|
glVertex2f (x+width, y+height);
|
|
|
|
glTexCoord2f (newsl, newth);
|
|
|
|
glVertex2f (x, y+height);
|
|
|
|
glEnd ();
|
2000-09-28 00:22:24 +00:00
|
|
|
glColor3ubv(lighthalf_v);
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_TransPic
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void Draw_TransPic (int x, int y, qpic_t *pic)
|
|
|
|
{
|
|
|
|
|
2000-09-22 09:08:08 +00:00
|
|
|
if (x < 0 || (unsigned int)(x + pic->width) > vid.width || y < 0 ||
|
|
|
|
(unsigned int)(y + pic->height) > vid.height)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
Sys_Error ("Draw_TransPic: bad coordinates");
|
|
|
|
}
|
|
|
|
|
|
|
|
Draw_Pic (x, y, pic);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_TransPicTranslate
|
|
|
|
|
|
|
|
Only used for the player color selection menu
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
|
|
|
|
{
|
|
|
|
int v, u, c;
|
2000-09-22 09:08:08 +00:00
|
|
|
unsigned int trans[64*64], *dest;
|
2000-05-10 11:29:38 +00:00
|
|
|
byte *src;
|
|
|
|
int p;
|
|
|
|
|
2000-06-17 10:39:28 +00:00
|
|
|
glBindTexture (GL_TEXTURE_2D, translate_texture);
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
c = pic->width * pic->height;
|
|
|
|
|
|
|
|
dest = trans;
|
|
|
|
for (v=0 ; v<64 ; v++, dest += 64)
|
|
|
|
{
|
|
|
|
src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
|
|
|
|
for (u=0 ; u<64 ; u++)
|
|
|
|
{
|
|
|
|
p = src[(u*pic->width)>>6];
|
|
|
|
if (p == 255)
|
|
|
|
dest[u] = p;
|
|
|
|
else
|
|
|
|
dest[u] = d_8to24table[translation[p]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
|
|
|
|
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
|
2000-07-02 05:16:10 +00:00
|
|
|
if (lighthalf)
|
|
|
|
glColor3f(0.4,0.4,0.4);
|
|
|
|
else
|
|
|
|
glColor3f(0.8,0.8,0.8);
|
2000-05-10 11:29:38 +00:00
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glTexCoord2f (0, 0);
|
|
|
|
glVertex2f (x, y);
|
|
|
|
glTexCoord2f (1, 0);
|
|
|
|
glVertex2f (x+pic->width, y);
|
|
|
|
glTexCoord2f (1, 1);
|
|
|
|
glVertex2f (x+pic->width, y+pic->height);
|
|
|
|
glTexCoord2f (0, 1);
|
|
|
|
glVertex2f (x, y+pic->height);
|
|
|
|
glEnd ();
|
2000-09-28 00:22:24 +00:00
|
|
|
glColor3ubv(lighthalf_v);
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2000-05-29 10:16:04 +00:00
|
|
|
Draw_ConsoleBackground
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-05-29 10:16:04 +00:00
|
|
|
Draws console background (obviously!) Completely rewritten to use
|
|
|
|
several simple yet very cool GL effects. --KB
|
2000-05-10 11:29:38 +00:00
|
|
|
*/
|
2000-05-29 10:16:04 +00:00
|
|
|
void
|
|
|
|
Draw_ConsoleBackground ( int lines )
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
2000-05-29 10:16:04 +00:00
|
|
|
int y;
|
|
|
|
qpic_t *conback;
|
|
|
|
glpic_t *gl;
|
|
|
|
float ofs;
|
|
|
|
float alpha;
|
|
|
|
|
|
|
|
// This can be a CachePic now, just like in software
|
|
|
|
conback = Draw_CachePic ("gfx/conback.lmp");
|
|
|
|
gl = (glpic_t *)conback->data;
|
|
|
|
|
|
|
|
// spin the console? - effect described in a QER tutorial
|
|
|
|
if (gl_conspin->value)
|
|
|
|
{
|
|
|
|
static float xangle = 0;
|
|
|
|
static float xfactor = .3f;
|
|
|
|
static float xstep = .005f;
|
|
|
|
|
|
|
|
glPushMatrix ();
|
|
|
|
glMatrixMode (GL_TEXTURE);
|
|
|
|
glPushMatrix ();
|
|
|
|
glLoadIdentity ();
|
|
|
|
xangle += gl_conspin->value;
|
|
|
|
xfactor += xstep;
|
|
|
|
if (xfactor > 8 || xfactor < .3f)
|
|
|
|
xstep = -xstep;
|
|
|
|
glRotatef (xangle, 0, 0, 1);
|
|
|
|
glScalef (xfactor, xfactor, xfactor);
|
|
|
|
}
|
|
|
|
|
|
|
|
// slide console up/down or stretch it?
|
|
|
|
if (gl_constretch->value)
|
|
|
|
ofs = 0;
|
|
|
|
else
|
|
|
|
ofs = (vid.conheight - lines)/(float)vid.conheight;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
This is a NON-TRIVIAL update which took LordHavoc and I about 3 days to
make work properly:
Win32 thing.. If you don't free textures explicitly, you can cause a
problem with nVidia drivers.
Colored lighting is now RGB instead of RGBA. The alpha is kinda pointless
on a lightmap and the effect's not all that great. Plus people stuck with
16 bit OpenGL (any other 3dfx people out there?) will be quite pleased
with the improvement in image quality. This does include LordHavoc's
dynamic light optimization code which takes most of the pain out of having
gl_flashblend off.
All glColor*'s are now half of what they used to be, except where they
aren't. If that doesn't make sense, don't worry. If you see one that's
only half what you'd expect, don't worry---it probably is meant to be like
that.. (More below)
glDisable (GL_BLEND) is now a thing of the GL_PAST. As is GL_REPLACE.
Instead, we _always_ use GL_MODULATE and leave GL_BLEND turned on. This
seems at first like it might be a performance hit, but I swear it's much
more expensive to change blending modes and texture functions 20-30 times
every screen frame!
Win32 issue.. Even though we check for multitexture, we currently don't
use it. Reason is that I am planning to replace SGIS_multitexture with
the preferred ARB_multitexture extension which is supported in most GL 1.1
implementations and is a requirement for GL 1.2 anyway. I also wanted to
get rid of some duplicated code. Since Linux doesn't support multitexture
yet, I just commented out the code keeping me from compiling to get it to
work. Win32 should work without it until it's fixed, which shouldn't be
long since the differences between SGIS and ARB multitextures as far as
Quake is concerned is minimal AT BEST.
LordHavoc and I have been working tirelessly (well not quite, we both did
manage to sleep sometime during this ordeal) to fix the lighting in the GL
renderers! It looks DAMNED CLOSE to software's lighting now, including
the ability to overbright a color. You've gotta see this to know what I'm
talking about. That's why the glColor*'s are halved in most places. The
gamma table code and the general way it works is LordHavoc's design, but
over the course of re-implementing it in QF we did come up with a few more
small optimizations.
A lot of people have noticed that QF's fps count has gone to shit lately.
No promises that this undid whatever the problem was. That means there
could be a huge optimization lurking somewhere in the shadows, waiting for
us to fix it for a massive FPS boost. Even if there's not, the code in
this commit DOUBLED MY FPS COUNT. Granted I was getting pathetic FPS as
it was (around 30, which is pathetic even for a Voodoo3 in Linux) but
still---60 is a big improvement over 30!
Please be sure to "test" this code thuroughly.
2000-06-03 19:56:09 +00:00
|
|
|
y = vid.height >> 1;
|
2000-05-10 11:29:38 +00:00
|
|
|
if (lines > y)
|
2000-05-29 10:16:04 +00:00
|
|
|
{
|
|
|
|
alpha = 1.0;
|
|
|
|
} else {
|
|
|
|
// set up to draw alpha console
|
This is a NON-TRIVIAL update which took LordHavoc and I about 3 days to
make work properly:
Win32 thing.. If you don't free textures explicitly, you can cause a
problem with nVidia drivers.
Colored lighting is now RGB instead of RGBA. The alpha is kinda pointless
on a lightmap and the effect's not all that great. Plus people stuck with
16 bit OpenGL (any other 3dfx people out there?) will be quite pleased
with the improvement in image quality. This does include LordHavoc's
dynamic light optimization code which takes most of the pain out of having
gl_flashblend off.
All glColor*'s are now half of what they used to be, except where they
aren't. If that doesn't make sense, don't worry. If you see one that's
only half what you'd expect, don't worry---it probably is meant to be like
that.. (More below)
glDisable (GL_BLEND) is now a thing of the GL_PAST. As is GL_REPLACE.
Instead, we _always_ use GL_MODULATE and leave GL_BLEND turned on. This
seems at first like it might be a performance hit, but I swear it's much
more expensive to change blending modes and texture functions 20-30 times
every screen frame!
Win32 issue.. Even though we check for multitexture, we currently don't
use it. Reason is that I am planning to replace SGIS_multitexture with
the preferred ARB_multitexture extension which is supported in most GL 1.1
implementations and is a requirement for GL 1.2 anyway. I also wanted to
get rid of some duplicated code. Since Linux doesn't support multitexture
yet, I just commented out the code keeping me from compiling to get it to
work. Win32 should work without it until it's fixed, which shouldn't be
long since the differences between SGIS and ARB multitextures as far as
Quake is concerned is minimal AT BEST.
LordHavoc and I have been working tirelessly (well not quite, we both did
manage to sleep sometime during this ordeal) to fix the lighting in the GL
renderers! It looks DAMNED CLOSE to software's lighting now, including
the ability to overbright a color. You've gotta see this to know what I'm
talking about. That's why the glColor*'s are halved in most places. The
gamma table code and the general way it works is LordHavoc's design, but
over the course of re-implementing it in QF we did come up with a few more
small optimizations.
A lot of people have noticed that QF's fps count has gone to shit lately.
No promises that this undid whatever the problem was. That means there
could be a huge optimization lurking somewhere in the shadows, waiting for
us to fix it for a massive FPS boost. Even if there's not, the code in
this commit DOUBLED MY FPS COUNT. Granted I was getting pathetic FPS as
it was (around 30, which is pathetic even for a Voodoo3 in Linux) but
still---60 is a big improvement over 30!
Please be sure to "test" this code thuroughly.
2000-06-03 19:56:09 +00:00
|
|
|
alpha = (float)(gl_conalpha->value * lines)/y;
|
2000-05-29 10:16:04 +00:00
|
|
|
}
|
|
|
|
|
2000-07-02 05:16:10 +00:00
|
|
|
if (lighthalf)
|
|
|
|
glColor4f(0.4,0.4,0.4,alpha);
|
|
|
|
else
|
|
|
|
glColor4f(0.8,0.8,0.8,alpha);
|
2000-05-29 10:16:04 +00:00
|
|
|
|
|
|
|
// draw the console texture
|
2000-06-17 10:39:28 +00:00
|
|
|
glBindTexture (GL_TEXTURE_2D, gl->texnum);
|
2000-05-29 10:16:04 +00:00
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glTexCoord2f (gl->sl, gl->tl + ofs);
|
|
|
|
glVertex2f (0, 0);
|
|
|
|
glTexCoord2f (gl->sh, gl->tl + ofs);
|
|
|
|
glVertex2f (vid.conwidth, 0);
|
|
|
|
glTexCoord2f (gl->sh, gl->th);
|
|
|
|
glVertex2f (vid.conwidth, lines);
|
|
|
|
glTexCoord2f (gl->sl, gl->th);
|
|
|
|
glVertex2f (0, lines);
|
|
|
|
glEnd ();
|
|
|
|
|
|
|
|
// turn off alpha blending
|
|
|
|
if (alpha < 1.0)
|
|
|
|
{
|
2000-07-02 05:16:10 +00:00
|
|
|
if (lighthalf)
|
|
|
|
glColor3f(0.4,0.4,0.4);
|
|
|
|
else
|
|
|
|
glColor3f(0.8,0.8,0.8);
|
2000-05-29 10:16:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (gl_conspin->value)
|
|
|
|
{
|
|
|
|
glPopMatrix ();
|
|
|
|
glMatrixMode (GL_MODELVIEW);
|
|
|
|
glPopMatrix ();
|
|
|
|
}
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-05-29 10:16:04 +00:00
|
|
|
// draw version string if not downloading
|
|
|
|
if (!cls.download)
|
2000-06-05 01:05:25 +00:00
|
|
|
Draw_AltString8 (vid.conwidth - strlen(cl_verstring->string)*8 - 11,
|
2000-05-16 04:47:41 +00:00
|
|
|
lines-14, cl_verstring->string);
|
2000-09-28 00:22:24 +00:00
|
|
|
glColor3ubv(lighthalf_v);
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
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)
|
|
|
|
{
|
2000-07-02 05:16:10 +00:00
|
|
|
if (lighthalf)
|
|
|
|
glColor3f(0.4,0.4,0.4);
|
|
|
|
else
|
|
|
|
glColor3f(0.8,0.8,0.8);
|
2000-06-17 10:39:28 +00:00
|
|
|
glBindTexture (GL_TEXTURE_2D, *(int *)draw_backtile->data);
|
2000-05-10 11:29:38 +00:00
|
|
|
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 ();
|
2000-09-28 00:22:24 +00:00
|
|
|
glColor3ubv(lighthalf_v);
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
Draw_Fill
|
|
|
|
|
|
|
|
Fills a box of pixels with a single color
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void Draw_Fill (int x, int y, int w, int h, int c)
|
|
|
|
{
|
|
|
|
glDisable (GL_TEXTURE_2D);
|
2000-07-02 05:16:10 +00:00
|
|
|
if (lighthalf)
|
|
|
|
glColor3f (host_basepal[c*3]/510.0, host_basepal[c*3+1]/510.0, host_basepal[c*3+2]/510.0);
|
|
|
|
else
|
|
|
|
glColor3f (host_basepal[c*3]/255.0, host_basepal[c*3+1]/255.0, host_basepal[c*3+2]/255.0);
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
|
|
|
|
glVertex2f (x,y);
|
|
|
|
glVertex2f (x+w, y);
|
|
|
|
glVertex2f (x+w, y+h);
|
|
|
|
glVertex2f (x, y+h);
|
|
|
|
|
|
|
|
glEnd ();
|
2000-09-28 00:22:24 +00:00
|
|
|
glColor3ubv(lighthalf_v);
|
2000-05-10 11:29:38 +00:00
|
|
|
glEnable (GL_TEXTURE_2D);
|
|
|
|
}
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_FadeScreen
|
|
|
|
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void Draw_FadeScreen (void)
|
|
|
|
{
|
|
|
|
glDisable (GL_TEXTURE_2D);
|
This is a NON-TRIVIAL update which took LordHavoc and I about 3 days to
make work properly:
Win32 thing.. If you don't free textures explicitly, you can cause a
problem with nVidia drivers.
Colored lighting is now RGB instead of RGBA. The alpha is kinda pointless
on a lightmap and the effect's not all that great. Plus people stuck with
16 bit OpenGL (any other 3dfx people out there?) will be quite pleased
with the improvement in image quality. This does include LordHavoc's
dynamic light optimization code which takes most of the pain out of having
gl_flashblend off.
All glColor*'s are now half of what they used to be, except where they
aren't. If that doesn't make sense, don't worry. If you see one that's
only half what you'd expect, don't worry---it probably is meant to be like
that.. (More below)
glDisable (GL_BLEND) is now a thing of the GL_PAST. As is GL_REPLACE.
Instead, we _always_ use GL_MODULATE and leave GL_BLEND turned on. This
seems at first like it might be a performance hit, but I swear it's much
more expensive to change blending modes and texture functions 20-30 times
every screen frame!
Win32 issue.. Even though we check for multitexture, we currently don't
use it. Reason is that I am planning to replace SGIS_multitexture with
the preferred ARB_multitexture extension which is supported in most GL 1.1
implementations and is a requirement for GL 1.2 anyway. I also wanted to
get rid of some duplicated code. Since Linux doesn't support multitexture
yet, I just commented out the code keeping me from compiling to get it to
work. Win32 should work without it until it's fixed, which shouldn't be
long since the differences between SGIS and ARB multitextures as far as
Quake is concerned is minimal AT BEST.
LordHavoc and I have been working tirelessly (well not quite, we both did
manage to sleep sometime during this ordeal) to fix the lighting in the GL
renderers! It looks DAMNED CLOSE to software's lighting now, including
the ability to overbright a color. You've gotta see this to know what I'm
talking about. That's why the glColor*'s are halved in most places. The
gamma table code and the general way it works is LordHavoc's design, but
over the course of re-implementing it in QF we did come up with a few more
small optimizations.
A lot of people have noticed that QF's fps count has gone to shit lately.
No promises that this undid whatever the problem was. That means there
could be a huge optimization lurking somewhere in the shadows, waiting for
us to fix it for a massive FPS boost. Even if there's not, the code in
this commit DOUBLED MY FPS COUNT. Granted I was getting pathetic FPS as
it was (around 30, which is pathetic even for a Voodoo3 in Linux) but
still---60 is a big improvement over 30!
Please be sure to "test" this code thuroughly.
2000-06-03 19:56:09 +00:00
|
|
|
glColor4f (0, 0, 0, 0.7);
|
2000-05-10 11:29:38 +00:00
|
|
|
glBegin (GL_QUADS);
|
|
|
|
|
|
|
|
glVertex2f (0,0);
|
|
|
|
glVertex2f (vid.width, 0);
|
|
|
|
glVertex2f (vid.width, vid.height);
|
|
|
|
glVertex2f (0, vid.height);
|
|
|
|
|
|
|
|
glEnd ();
|
2000-09-28 00:22:24 +00:00
|
|
|
glColor3ubv(lighthalf_v);
|
2000-05-10 11:29:38 +00:00
|
|
|
glEnable (GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
Sbar_Changed();
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_BeginDisc
|
|
|
|
|
|
|
|
Draws the little blue disc in the corner of the screen.
|
|
|
|
Call before beginning any disc IO.
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void Draw_BeginDisc (void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
Draw_EndDisc
|
|
|
|
|
|
|
|
Erases the disc icon.
|
|
|
|
Call after completing any disc IO
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void Draw_EndDisc (void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_Set2D
|
|
|
|
|
|
|
|
Setup as if the screen was 320*200
|
|
|
|
================
|
|
|
|
*/
|
|
|
|
void GL_Set2D (void)
|
|
|
|
{
|
|
|
|
glViewport (glx, gly, glwidth, glheight);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
|
|
|
glOrtho (0, vid.width, vid.height, 0, -99999, 99999);
|
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity ();
|
|
|
|
|
|
|
|
glDisable (GL_DEPTH_TEST);
|
|
|
|
glDisable (GL_CULL_FACE);
|
|
|
|
|
2000-09-28 00:22:24 +00:00
|
|
|
glColor3ubv(lighthalf_v);
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//====================================================================
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_ResampleTexture
|
|
|
|
================
|
|
|
|
*/
|
2000-09-22 09:08:08 +00:00
|
|
|
static void GL_ResampleTexture (unsigned int *in, int inwidth, int inheight, unsigned int *out, int outwidth, int outheight)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
2000-09-22 09:08:08 +00:00
|
|
|
unsigned int *inrow;
|
|
|
|
unsigned int frac, fracstep;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_Resample8BitTexture -- JACK
|
|
|
|
================
|
|
|
|
*/
|
2000-08-14 04:53:45 +00:00
|
|
|
static void GL_Resample8BitTexture (unsigned char *in, int inwidth, int inheight, unsigned char *out, int outwidth, int outheight)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
2000-09-22 09:08:08 +00:00
|
|
|
unsigned char *inrow;
|
|
|
|
unsigned int frac, fracstep;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_MipMap
|
|
|
|
|
|
|
|
Operates in place, quartering the size of the texture
|
|
|
|
================
|
|
|
|
*/
|
2000-08-14 04:53:45 +00:00
|
|
|
static void GL_MipMap (byte *in, int width, int height)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
byte *out;
|
|
|
|
|
|
|
|
width <<=2;
|
|
|
|
height >>= 1;
|
|
|
|
out = in;
|
|
|
|
for (i=0 ; i<height ; i++, in+=width)
|
|
|
|
{
|
|
|
|
for (j=0 ; j<width ; j+=8, out+=4, in+=8)
|
|
|
|
{
|
|
|
|
out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
|
|
|
|
out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
|
|
|
|
out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
|
|
|
|
out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_MipMap8Bit
|
|
|
|
|
|
|
|
Mipping for 8 bit textures
|
|
|
|
================
|
|
|
|
*/
|
2000-08-14 04:53:45 +00:00
|
|
|
static void GL_MipMap8Bit (byte *in, int width, int height)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
byte *out;
|
|
|
|
unsigned short r,g,b;
|
|
|
|
byte *at1, *at2, *at3, *at4;
|
|
|
|
|
|
|
|
height >>= 1;
|
|
|
|
out = in;
|
|
|
|
for (i=0 ; i<height ; i++, in+=width)
|
|
|
|
for (j=0 ; j<width ; j+=2, out+=1, in+=2)
|
|
|
|
{
|
|
|
|
at1 = (byte *) &d_8to24table[in[0]];
|
|
|
|
at2 = (byte *) &d_8to24table[in[1]];
|
|
|
|
at3 = (byte *) &d_8to24table[in[width+0]];
|
|
|
|
at4 = (byte *) &d_8to24table[in[width+1]];
|
|
|
|
|
|
|
|
r = (at1[0]+at2[0]+at3[0]+at4[0]); r>>=5;
|
|
|
|
g = (at1[1]+at2[1]+at3[1]+at4[1]); g>>=5;
|
|
|
|
b = (at1[2]+at2[2]+at3[2]+at4[2]); b>>=5;
|
|
|
|
|
|
|
|
out[0] = d_15to8table[(r<<0) + (g<<5) + (b<<10)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
GL_Upload32
|
|
|
|
===============
|
|
|
|
*/
|
2000-09-22 09:08:08 +00:00
|
|
|
static void GL_Upload32 (unsigned int *data, int width, int height, qboolean mipmap, qboolean alpha)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
2000-09-22 09:08:08 +00:00
|
|
|
unsigned int *scaled;
|
|
|
|
int scaled_width, scaled_height, samples;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-09-22 09:08:08 +00:00
|
|
|
// Snap the height and width to a power of 2.
|
|
|
|
for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) ;
|
|
|
|
for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) ;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-05-16 04:47:41 +00:00
|
|
|
scaled_width >>= (int)gl_picmip->value;
|
|
|
|
scaled_height >>= (int)gl_picmip->value;
|
|
|
|
|
2000-05-23 17:05:34 +00:00
|
|
|
scaled_width = min(scaled_width, gl_max_size->value);
|
|
|
|
scaled_height = min(scaled_height, gl_max_size->value);
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-09-22 09:08:08 +00:00
|
|
|
if (!(scaled = malloc(scaled_width * scaled_height * 4 * sizeof(unsigned int))))
|
2000-05-10 11:29:38 +00:00
|
|
|
Sys_Error ("GL_LoadTexture: too big");
|
|
|
|
|
|
|
|
samples = alpha ? gl_alpha_format : gl_solid_format;
|
|
|
|
|
2000-09-22 09:08:08 +00:00
|
|
|
// If the real width/height and the 'scaled' width/height then we
|
|
|
|
// rescale it.
|
|
|
|
if (scaled_width == width && scaled_height == height) {
|
2000-05-10 11:29:38 +00:00
|
|
|
memcpy (scaled, data, width*height*4);
|
2000-09-22 09:08:08 +00:00
|
|
|
} else {
|
2000-05-10 11:29:38 +00:00
|
|
|
GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
|
2000-09-22 09:08:08 +00:00
|
|
|
}
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
|
2000-09-22 09:08:08 +00:00
|
|
|
|
|
|
|
if (mipmap) {
|
2000-05-10 11:29:38 +00:00
|
|
|
int miplevel;
|
|
|
|
|
|
|
|
miplevel = 0;
|
2000-09-22 09:08:08 +00:00
|
|
|
while (scaled_width > 1 || scaled_height > 1) {
|
2000-05-10 11:29:38 +00:00
|
|
|
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++;
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, miplevel, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-09-22 09:08:08 +00:00
|
|
|
if (mipmap) {
|
2000-05-10 11:29:38 +00:00
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
2000-09-22 09:08:08 +00:00
|
|
|
} else {
|
2000-05-10 11:29:38 +00:00
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
|
|
|
}
|
2000-09-22 09:08:08 +00:00
|
|
|
|
|
|
|
free(scaled);
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GL_Upload8_EXT (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
|
|
|
|
{
|
2000-09-22 09:08:08 +00:00
|
|
|
#ifdef HAVE_GL_COLOR_INDEX8_EXT
|
|
|
|
byte *scaled;
|
|
|
|
int scaled_width, scaled_height;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-09-22 09:08:08 +00:00
|
|
|
// Snap the height and width to a power of 2.
|
|
|
|
for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1) ;
|
|
|
|
for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1) ;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-05-16 04:47:41 +00:00
|
|
|
scaled_width >>= (int)gl_picmip->value;
|
|
|
|
scaled_height >>= (int)gl_picmip->value;
|
|
|
|
|
2000-05-23 17:05:34 +00:00
|
|
|
scaled_width = min(scaled_width, gl_max_size->value);
|
|
|
|
scaled_height = min(scaled_height, gl_max_size->value);
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-09-22 09:08:08 +00:00
|
|
|
if (!(scaled = malloc(scaled_width * scaled_height)))
|
2000-05-10 11:29:38 +00:00
|
|
|
Sys_Error ("GL_LoadTexture: too big");
|
|
|
|
|
2000-09-22 09:08:08 +00:00
|
|
|
// If the real width/height and the 'scaled' width/height then we
|
|
|
|
// rescale it.
|
|
|
|
if (scaled_width == width && scaled_height == height) {
|
2000-05-10 11:29:38 +00:00
|
|
|
memcpy (scaled, data, width*height);
|
2000-09-22 09:08:08 +00:00
|
|
|
} else {
|
2000-05-10 11:29:38 +00:00
|
|
|
GL_Resample8BitTexture (data, width, height, scaled, scaled_width, scaled_height);
|
2000-09-22 09:08:08 +00:00
|
|
|
}
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
|
2000-09-22 09:08:08 +00:00
|
|
|
|
|
|
|
if (mipmap) {
|
2000-05-10 11:29:38 +00:00
|
|
|
int miplevel;
|
|
|
|
|
|
|
|
miplevel = 0;
|
2000-09-22 09:08:08 +00:00
|
|
|
while (scaled_width > 1 || scaled_height > 1) {
|
2000-05-10 11:29:38 +00:00
|
|
|
GL_MipMap8Bit ((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++;
|
|
|
|
glTexImage2D (GL_TEXTURE_2D, miplevel, GL_COLOR_INDEX8_EXT, scaled_width, scaled_height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, scaled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-09-22 09:08:08 +00:00
|
|
|
if (mipmap) {
|
2000-05-10 11:29:38 +00:00
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
2000-09-22 09:08:08 +00:00
|
|
|
} else {
|
2000-05-10 11:29:38 +00:00
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
|
|
|
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
|
|
|
|
}
|
2000-09-22 09:08:08 +00:00
|
|
|
|
|
|
|
free(scaled);
|
|
|
|
#else
|
|
|
|
Sys_Error ("GL_Upload8_EXT without HAVE_GL_COLOR_INDEX8_EXT");
|
|
|
|
#endif
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extern qboolean VID_Is8bit();
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
GL_Upload8
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
void GL_Upload8 (byte *data, int width, int height, qboolean mipmap, qboolean alpha)
|
|
|
|
{
|
2000-09-22 09:08:08 +00:00
|
|
|
#if 1
|
|
|
|
unsigned int *trans = NULL;
|
|
|
|
int i, s, p;
|
|
|
|
|
|
|
|
s = width*height;
|
|
|
|
trans = malloc(s * sizeof(unsigned int));
|
|
|
|
// if there are no transparent pixels, make it a 3 component
|
|
|
|
// texture even if it was specified as otherwise
|
|
|
|
if (alpha) {
|
|
|
|
alpha = false;
|
|
|
|
for (i=0 ; i<s ; i++) {
|
|
|
|
p = data[i];
|
|
|
|
if (p == 255) alpha = true;
|
|
|
|
trans[i] = d_8to24table[p];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (s&3)
|
|
|
|
Sys_Error ("GL_Upload8: s&3");
|
|
|
|
for (i=0 ; i<s ; i+=4) {
|
|
|
|
trans[i] = d_8to24table[data[i]];
|
|
|
|
trans[i+1] = d_8to24table[data[i+1]];
|
|
|
|
trans[i+2] = d_8to24table[data[i+2]];
|
|
|
|
trans[i+3] = d_8to24table[data[i+3]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef gl_draw_scraps
|
|
|
|
if (VID_Is8bit() && !alpha && (data!=scrap_texels[0]))
|
|
|
|
#else
|
|
|
|
if (VID_Is8bit() && !alpha)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
GL_Upload8_EXT (data, width, height, mipmap, alpha);
|
|
|
|
} else {
|
|
|
|
GL_Upload32 (trans, width, height, mipmap, alpha);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(trans);
|
|
|
|
#else
|
|
|
|
static unsigned int trans[640*480]; // FIXME, temporary
|
|
|
|
int i, s;
|
|
|
|
qboolean noalpha;
|
|
|
|
int p;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
s = width*height;
|
|
|
|
// if there are no transparent pixels, make it a 3 component
|
|
|
|
// texture even if it was specified as otherwise
|
|
|
|
if (alpha)
|
|
|
|
{
|
|
|
|
noalpha = true;
|
|
|
|
for (i=0 ; i<s ; i++)
|
|
|
|
{
|
|
|
|
p = data[i];
|
|
|
|
if (p == 255)
|
|
|
|
noalpha = false;
|
|
|
|
trans[i] = d_8to24table[p];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (alpha && noalpha)
|
|
|
|
alpha = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (s&3)
|
|
|
|
Sys_Error ("GL_Upload8: s&3");
|
|
|
|
for (i=0 ; i<s ; i+=4)
|
|
|
|
{
|
|
|
|
trans[i] = d_8to24table[data[i]];
|
|
|
|
trans[i+1] = d_8to24table[data[i+1]];
|
|
|
|
trans[i+2] = d_8to24table[data[i+2]];
|
|
|
|
trans[i+3] = d_8to24table[data[i+3]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
#ifdef gl_draw_scraps
|
2000-09-22 09:08:08 +00:00
|
|
|
if (VID_Is8bit() && !alpha && (data!=scrap_texels[0]))
|
2000-08-14 04:53:45 +00:00
|
|
|
#else
|
2000-09-22 09:08:08 +00:00
|
|
|
if (VID_Is8bit() && !alpha)
|
2000-08-14 04:53:45 +00:00
|
|
|
#endif
|
2000-09-22 09:08:08 +00:00
|
|
|
{
|
|
|
|
GL_Upload8_EXT (data, width, height, mipmap, alpha);
|
|
|
|
return;
|
|
|
|
}
|
2000-05-10 11:29:38 +00:00
|
|
|
|
|
|
|
GL_Upload32 (trans, width, height, mipmap, alpha);
|
2000-09-22 09:08:08 +00:00
|
|
|
#endif
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_LoadTexture
|
|
|
|
================
|
|
|
|
*/
|
2000-06-23 08:43:32 +00:00
|
|
|
int GL_LoadTexture (char *identifier, int width, int height, byte *data, qboolean mipmap, qboolean alpha, int bytesperpixel)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
2000-09-22 15:08:28 +00:00
|
|
|
int i, crc;
|
2000-08-14 04:53:45 +00:00
|
|
|
gltexture_t *glt;
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-09-22 15:08:28 +00:00
|
|
|
// LordHavoc: now just using a standard CRC for texture validation
|
|
|
|
crc = CRC_Block(data, width*height*bytesperpixel);
|
|
|
|
|
2000-05-10 11:29:38 +00:00
|
|
|
// see if the texture is allready present
|
|
|
|
if (identifier[0])
|
|
|
|
{
|
|
|
|
for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
|
|
|
|
{
|
|
|
|
if (!strcmp (identifier, glt->identifier))
|
|
|
|
{
|
2000-09-22 15:08:28 +00:00
|
|
|
if (crc != glt->crc
|
2000-06-09 22:28:08 +00:00
|
|
|
|| width != glt->width
|
2000-06-23 08:43:32 +00:00
|
|
|
|| height != glt->height
|
|
|
|
|| bytesperpixel != glt->bytesperpixel)
|
2000-06-09 22:28:08 +00:00
|
|
|
goto SetupTexture;
|
|
|
|
else
|
|
|
|
return gltextures[i].texnum;
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-06-09 22:28:08 +00:00
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
if (numgltextures == MAX_GLTEXTURES)
|
|
|
|
Sys_Error ("numgltextures == MAX_GLTEXTURES");
|
|
|
|
|
2000-06-09 22:28:08 +00:00
|
|
|
glt = &gltextures[numgltextures];
|
2000-05-10 11:29:38 +00:00
|
|
|
numgltextures++;
|
|
|
|
|
2000-08-14 04:53:45 +00:00
|
|
|
strncpy (glt->identifier, identifier, sizeof(glt->identifier) - 1);
|
|
|
|
glt->identifier[sizeof(glt->identifier) - 1] = '\0';
|
|
|
|
|
2000-05-10 11:29:38 +00:00
|
|
|
glt->texnum = texture_extension_number;
|
2000-06-09 22:28:08 +00:00
|
|
|
texture_extension_number++;
|
|
|
|
|
|
|
|
SetupTexture:
|
2000-09-22 15:08:28 +00:00
|
|
|
glt->crc = crc;
|
2000-05-10 11:29:38 +00:00
|
|
|
glt->width = width;
|
|
|
|
glt->height = height;
|
2000-06-23 08:43:32 +00:00
|
|
|
glt->bytesperpixel = bytesperpixel;
|
2000-05-10 11:29:38 +00:00
|
|
|
glt->mipmap = mipmap;
|
|
|
|
|
2000-06-17 10:39:28 +00:00
|
|
|
glBindTexture (GL_TEXTURE_2D, glt->texnum);
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-06-23 08:43:32 +00:00
|
|
|
switch (glt->bytesperpixel)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
GL_Upload8 (data, width, height, mipmap, alpha);
|
|
|
|
break;
|
|
|
|
case 4:
|
2000-09-22 09:08:08 +00:00
|
|
|
GL_Upload32 ((unsigned int *) data, width, height, mipmap, alpha);
|
2000-06-23 08:43:32 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Sys_Error ("SetupTexture: unknown bytesperpixel %i",
|
|
|
|
glt->bytesperpixel);
|
|
|
|
}
|
2000-05-10 11:29:38 +00:00
|
|
|
|
2000-06-09 22:28:08 +00:00
|
|
|
return glt->texnum;
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|
|
|
|
|
2000-06-23 08:43:32 +00:00
|
|
|
|
2000-05-10 11:29:38 +00:00
|
|
|
/*
|
|
|
|
================
|
|
|
|
GL_LoadPicTexture
|
|
|
|
================
|
|
|
|
*/
|
2000-08-14 04:53:45 +00:00
|
|
|
static int GL_LoadPicTexture (qpic_t *pic)
|
2000-05-10 11:29:38 +00:00
|
|
|
{
|
2000-06-23 08:43:32 +00:00
|
|
|
return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
|
2000-05-10 11:29:38 +00:00
|
|
|
}
|