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.
This commit is contained in:
Joseph Carter 2000-06-03 19:56:09 +00:00
parent 76d586a081
commit 8d08bc4d86
12 changed files with 297 additions and 440 deletions

View file

@ -477,6 +477,7 @@ void Draw_Character (int x, int y, int num)
GL_Bind (char_texture);
glColor3f (0.5, 0.5, 0.5);
glBegin (GL_QUADS);
glTexCoord2f (fcol, frow);
glVertex2f (x, y);
@ -529,7 +530,6 @@ void Draw_Crosshair(void)
x = scr_vrect.x + scr_vrect.width/2 - 3 + cl_crossx->value;
y = scr_vrect.y + scr_vrect.height/2 - 3 + cl_crossy->value;
glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
pColor = (unsigned char *) &d_8to24table[(byte) crosshaircolor->value];
glColor4ubv ( pColor );
GL_Bind (cs_texture);
@ -545,7 +545,6 @@ void Draw_Crosshair(void)
glVertex2f (x - 4, y+12);
glEnd ();
glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
} else if (crosshair->value)
Draw_Character (scr_vrect.x + scr_vrect.width/2-4 + cl_crossx->value,
scr_vrect.y + scr_vrect.height/2-4 + cl_crossy->value, '+');
@ -577,7 +576,7 @@ void Draw_Pic (int x, int y, qpic_t *pic)
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
glColor4f (1,1,1,1);
glColor3f (0.4, 0.4, 0.4);
GL_Bind (gl->texnum);
glBegin (GL_QUADS);
glTexCoord2f (gl->sl, gl->tl);
@ -603,12 +602,7 @@ void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
if (scrap_dirty)
Scrap_Upload ();
gl = (glpic_t *)pic->data;
glDisable(GL_ALPHA_TEST);
glEnable (GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glCullFace(GL_FRONT);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // FIXME deek: these cause problems with text. Looking for the real problem
glColor4f (1,1,1,alpha);
glColor4f (0.4, 0.4, 0.4, alpha);
GL_Bind (gl->texnum);
glBegin (GL_QUADS);
glTexCoord2f (gl->sl, gl->tl);
@ -620,10 +614,7 @@ void Draw_AlphaPic (int x, int y, qpic_t *pic, float alpha)
glTexCoord2f (gl->sl, gl->th);
glVertex2f (x, y+pic->height);
glEnd ();
glColor4f (1,1,1,1);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // FIXME
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor3f (0.5, 0.5, 0.5);
}
void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height)
@ -645,7 +636,7 @@ void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int h
newtl = gl->tl + (srcy*oldglheight)/pic->height;
newth = newtl + (height*oldglheight)/pic->height;
glColor4f (1,1,1,1);
glColor3f (0.4, 0.4, 0.4);
GL_Bind (gl->texnum);
glBegin (GL_QUADS);
glTexCoord2f (newsl, newtl);
@ -714,7 +705,7 @@ void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glColor3f (1,1,1);
glColor3f (0.4, 0.4, 0.4);
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (x, y);
@ -772,21 +763,16 @@ Draw_ConsoleBackground ( int lines )
else
ofs = (vid.conheight - lines)/(float)vid.conheight;
y = (vid.height * 3) >> 2;
y = vid.height >> 1;
if (lines > y)
{
alpha = 1.0;
} else {
// set up to draw alpha console
alpha = (float)(gl_conalpha->value * 2 * lines)/y;
glDisable(GL_ALPHA_TEST);
glEnable (GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glCullFace(GL_FRONT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
alpha = (float)(gl_conalpha->value * lines)/y;
}
glColor4f (1.0, 1.0, 1.0, alpha);
glColor4f (0.5, 0.5, 0.5, alpha);
// draw the console texture
GL_Bind (gl->texnum);
@ -804,10 +790,7 @@ Draw_ConsoleBackground ( int lines )
// turn off alpha blending
if (alpha < 1.0)
{
glColor4f (1.0, 1.0, 1.0, 1.0);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_ALPHA_TEST);
glDisable (GL_BLEND);
glColor3f (0.5, 0.5, 0.5);
}
if (gl_conspin->value)
@ -834,7 +817,7 @@ refresh window.
*/
void Draw_TileClear (int x, int y, int w, int h)
{
glColor3f (1,1,1);
glColor3f (0.5, 0.5, 0.5);
GL_Bind (*(int *)draw_backtile->data);
glBegin (GL_QUADS);
glTexCoord2f (x/64.0, y/64.0);
@ -859,9 +842,9 @@ 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);
glColor3f (host_basepal[c*3]/255.0,
host_basepal[c*3+1]/255.0,
host_basepal[c*3+2]/255.0);
glColor3f (host_basepal[c*3]/510.0,
host_basepal[c*3+1]/510.0,
host_basepal[c*3+2]/510.0);
glBegin (GL_QUADS);
@ -871,7 +854,7 @@ void Draw_Fill (int x, int y, int w, int h, int c)
glVertex2f (x, y+h);
glEnd ();
glColor3f (1,1,1);
glColor3f (0.5, 0.5, 0.5);
glEnable (GL_TEXTURE_2D);
}
//=============================================================================
@ -884,9 +867,8 @@ Draw_FadeScreen
*/
void Draw_FadeScreen (void)
{
glEnable (GL_BLEND);
glDisable (GL_TEXTURE_2D);
glColor4f (0, 0, 0, 0.8);
glColor4f (0, 0, 0, 0.7);
glBegin (GL_QUADS);
glVertex2f (0,0);
@ -895,9 +877,8 @@ void Draw_FadeScreen (void)
glVertex2f (0, vid.height);
glEnd ();
glColor4f (1,1,1,1);
glColor3f (0.5, 0.5, 0.5);
glEnable (GL_TEXTURE_2D);
glDisable (GL_BLEND);
Sbar_Changed();
}
@ -952,13 +933,16 @@ void GL_Set2D (void)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
GL_DisableMultitexture ();
glEnable (GL_BLEND);
glDisable (GL_DEPTH_TEST);
glDisable (GL_CULL_FACE);
glDisable (GL_BLEND);
glEnable (GL_ALPHA_TEST);
// glDisable (GL_ALPHA_TEST);
glColor4f (1,1,1,1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor3f (0.5, 0.5, 0.5);
}
//====================================================================

View file

@ -492,13 +492,32 @@ Mod_LoadLighting
*/
void Mod_LoadLighting (lump_t *l)
{
int i;
byte *in, *out;
byte d;
char litfilename[1024];
if (!l->filelen)
{
loadmodel->lightdata = NULL;
return;
}
loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
strcpy(litfilename, loadmodel->name);
COM_StripExtension(litfilename, litfilename);
strcat(litfilename, ".lit");
loadmodel->lightdata = Hunk_AllocName ( l->filelen*3, litfilename);
in = loadmodel->lightdata + l->filelen*2; // place the file at the end, so it will not be overwritten until the very last write
out = loadmodel->lightdata;
memcpy (in, mod_base + l->fileofs, l->filelen);
for (i = 0;i < l->filelen;i++)
{
d = *in++;
*out++ = d;
*out++ = d;
*out++ = d;
}
}
@ -790,7 +809,7 @@ void Mod_LoadFaces (lump_t *l)
if (i == -1)
out->samples = NULL;
else
out->samples = loadmodel->lightdata + i;
out->samples = loadmodel->lightdata + (i * 3);
// set the drawing flags flag

View file

@ -160,7 +160,7 @@ void R_NetGraph (void)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
x = 8;
glColor3f (1,1,1);
glColor3f (0.5, 0.5, 0.5);
glBegin (GL_QUADS);
glTexCoord2f (0, 0);
glVertex2f (x, y);

View file

@ -499,8 +499,6 @@ void R_DrawParticles (void)
if (alphaTestEnabled)
glDisable(GL_ALPHA_TEST);
glEnable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBegin (GL_TRIANGLES);
VectorScale (vup, 1.5, up);
@ -625,9 +623,7 @@ void R_DrawParticles (void)
}
glEnd ();
glDisable (GL_BLEND);
if (alphaTestEnabled)
glEnable(GL_ALPHA_TEST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}

View file

@ -101,7 +101,7 @@ void AddLightBlend (float r, float g, float b, float a2)
a2 = a2/a;
v_blend[0] = v_blend[1]*(1-a2) + r*a2;
v_blend[0] = v_blend[0]*(1-a2) + r*a2;
v_blend[1] = v_blend[1]*(1-a2) + g*a2;
v_blend[2] = v_blend[2]*(1-a2) + b*a2;
//Con_Printf("AddLightBlend(): %4.2f %4.2f %4.2f %4.6f\n", v_blend[0], v_blend[1], v_blend[2], v_blend[3]);
@ -183,7 +183,6 @@ void R_RenderDlights (void)
glDepthMask (0);
glDisable (GL_TEXTURE_2D);
glShadeModel (GL_SMOOTH);
glEnable (GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE);
l = cl_dlights;
@ -195,7 +194,6 @@ void R_RenderDlights (void)
}
glColor3f (1,1,1);
glDisable (GL_BLEND);
glEnable (GL_TEXTURE_2D);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask (1);

View file

@ -125,13 +125,18 @@ cvar_t *r_skyname;
extern cvar_t *gl_ztrick;
extern cvar_t *scr_fov;
byte gammatable[256];
static float vid_gamma = 1.0;
/*
GL_CheckGamma
More or less redesigned by LordHavoc
*/
void
GL_CheckGamma (unsigned char *pal)
{
float f, inf;
unsigned char palette[768];
float inf;
int i;
if ((i = COM_CheckParm("-gamma")) == 0) {
@ -143,18 +148,24 @@ GL_CheckGamma (unsigned char *pal)
} else
vid_gamma = atof(com_argv[i+1]);
for (i=0 ; i<768 ; i++)
// build the gamma table
if (vid_gamma == 1)
{
f = pow ( (pal[i]+1)/256.0 , vid_gamma );
inf = f*255 + 0.5;
if (inf < 0)
inf = 0;
if (inf > 255)
inf = 255;
palette[i] = inf;
// screw the math
for (i = 0; i < 256; i++)
gammatable[i] = i;
} else {
for (i = 0; i < 256; i++)
{
inf = pow((i+1)/256.0, vid_gamma)*255 + 0.5;
inf = bound(0, inf, 255);
gammatable[i] = inf;
}
}
memcpy (pal, palette, sizeof(palette));
// correct the palette
for (i = 0; i < 768; i++)
pal[i] = gammatable[pal[i]];
}
@ -277,7 +288,7 @@ void R_DrawSpriteModel (entity_t *e)
right = vright;
}
glColor3f (1,1,1);
glColor3f (0.5, 0.5, 0.5);
GL_DisableMultitexture();
@ -612,15 +623,12 @@ void R_DrawAliasModel (entity_t *e)
if (gl_smoothmodels->value)
glShadeModel (GL_SMOOTH);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
if (gl_affinemodels->value)
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
R_SetupAliasFrame (currententity->frame, paliashdr);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glShadeModel (GL_FLAT);
if (gl_affinemodels->value)
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
@ -632,12 +640,10 @@ void R_DrawAliasModel (entity_t *e)
glPushMatrix ();
R_RotateForEntity (e);
glDisable (GL_TEXTURE_2D);
glEnable (GL_BLEND);
glColor4f (0,0,0,0.5);
GL_DrawAliasShadow (paliashdr, lastposenum);
glEnable (GL_TEXTURE_2D);
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
glColor3f (0.5, 0.5, 0.5);
glPopMatrix ();
}
@ -777,29 +783,27 @@ void R_PolyBlend (void)
GL_DisableMultitexture();
glDisable (GL_ALPHA_TEST);
glEnable (GL_BLEND);
glDisable (GL_DEPTH_TEST);
glDisable (GL_TEXTURE_2D);
glLoadIdentity ();
glLoadIdentity ();
glRotatef (-90, 1, 0, 0); // put Z going up
glRotatef (90, 0, 0, 1); // put Z going up
glRotatef (-90, 1, 0, 0); // put Z going up
glRotatef (90, 0, 0, 1); // put Z going up
// software alpha is about GL alpha squared --KB
v_blend[3] = sqrt(v_blend[3]);
glColor4fv (v_blend);
glBegin (GL_QUADS);
glVertex3f (10, 100, 100);
glVertex3f (10, -100, 100);
glVertex3f (10, -100, -100);
glVertex3f (10, 100, -100);
glEnd ();
glDisable (GL_BLEND);
glEnable (GL_TEXTURE_2D);
glEnable (GL_ALPHA_TEST);
}
@ -987,9 +991,11 @@ void R_SetupGL (void)
else
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glEnable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
}
/*
@ -1129,7 +1135,6 @@ void R_Mirror (void)
glDepthFunc (GL_LEQUAL);
// blend on top
glEnable (GL_BLEND);
glMatrixMode(GL_PROJECTION);
if (mirror_plane->normal[2])
glScalef (1,-1,1);
@ -1147,7 +1152,6 @@ void R_Mirror (void)
for ( ; s ; s=s->texturechain)
R_RenderBrushPoly (s);
cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
glDisable (GL_BLEND);
glColor4f (1,1,1,1);
}
#endif

View file

@ -68,14 +68,14 @@ int lightmap_bytes; // 1 or 4
int lightmap_textures;
unsigned blocklights[4][18*18];
unsigned blocklights[18*18*3];
cvar_t *gl_colorlights;
#define BLOCK_WIDTH 128
#define BLOCK_HEIGHT 128
#define MAX_LIGHTMAPS 64
#define MAX_LIGHTMAPS 256
int active_lightmaps;
typedef struct glRect_s {
@ -99,21 +99,23 @@ msurface_t *waterchain = NULL;
void R_RenderDynamicLightmaps (msurface_t *fa);
/*
===============
R_AddDynamicLights
===============
R_AddDynamicLights
LordHavoc's redesigned this function completely
*/
void R_AddDynamicLights (msurface_t *surf)
void
R_AddDynamicLights (msurface_t *surf)
{
int lnum;
int sd, td;
float dist, rad, minlight;
float dist, rada, radb;
float red, green, blue, brightness;
vec3_t impact, local;
int s, t;
int i;
int smax, tmax;
mtexinfo_t *tex;
dlight_t *dl;
unsigned *bl;
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
@ -124,63 +126,73 @@ void R_AddDynamicLights (msurface_t *surf)
if ( !(surf->dlightbits & (1<<lnum) ) )
continue; // not lit by this light
rad = cl_dlights[lnum].radius;
dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
surf->plane->dist;
rad -= fabs(dist);
minlight = cl_dlights[lnum].minlight;
if (rad < minlight)
continue;
minlight = rad - minlight;
dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal)
- surf->plane->dist;
for (i=0 ; i<3 ; i++)
{
impact[i] = cl_dlights[lnum].origin[i] -
surf->plane->normal[i]*dist;
}
local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3]
- surf->texturemins[0];
local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3]
- surf->texturemins[1];
local[0] -= surf->texturemins[0];
local[1] -= surf->texturemins[1];
s = bound (0, local[0]+0.5, (smax-1)*16);
t = bound (0, local[1]+0.5, (tmax-1)*16);
sd = local[0] - s;
td = local[1] - t;
dist *= dist;
// get brightest color's value
red = cl_dlights[lnum].color[0];
green = cl_dlights[lnum].color[1];
blue = cl_dlights[lnum].color[2];
brightness = max(red, max(green, blue));
for (t = 0 ; t<tmax ; t++)
rada = cl_dlights[lnum].radius * cl_dlights[lnum].radius
* (4.0/16.0); // comparison to min acceptable light
if (rada*brightness >= (sd*sd + td*td + dist))
{
td = local[1] - t*16;
if (td < 0)
td = -td;
for (s=0 ; s<smax ; s++)
radb = cl_dlights[lnum].radius
* cl_dlights[lnum].radius * (256.0*4.0);
bl = blocklights;
for (t = 0; t < tmax; t++)
{
sd = local[0] - s*16;
if (sd < 0)
sd = -sd;
if (sd > td)
dist = sd + (td>>1);
else
dist = td + (sd>>1);
if (dist < minlight)
td = local[1] - t*16;
td = td*td + dist;
if (rada >= td) // any visible this line?
{
dl = &cl_dlights[lnum];
blocklights[0][t*smax + s] += (rad - dist)*(dl->color[0]*256);;
blocklights[1][t*smax + s] += (rad - dist)*(dl->color[1]*256);;
blocklights[2][t*smax + s] += (rad - dist)*(dl->color[2]*256);;
blocklights[3][t*smax + s] += (rad - dist)*256;
}
for (s = 0; s < smax; s++)
{
sd = local[0] - s*16;
if (rada >= (sd*sd+td)) // minimum light
{
brightness = radb / (sd*sd+td);
*bl++ += brightness * red;
*bl++ += brightness * green;
*bl++ += brightness * blue;
} else
bl+=3; // skip pixel
}
} else
bl+=smax*3; // skip line
}
}
}
}
/*
===============
R_BuildLightMap
R_BuildLightMap
Combine and scale multiple lightmaps into the 8.8 format in blocklights
===============
Combine and scale multiple lightmaps
After talking it over with LordHavoc, I've decided to switch to using
GL_RGB for colored lights and averaging them out for plain white
lighting if needed. Much cleaner that way. --KB
*/
void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
void
R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
{
int smax, tmax;
int t;
@ -188,7 +200,8 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
byte *lightmap;
unsigned scale;
int maps;
unsigned *rbl, *gbl, *bbl, *bl;
float t2;
unsigned *bl;
surf->cached_dlight = (surf->dlightframe == r_framecount);
@ -197,79 +210,84 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
size = smax*tmax;
lightmap = surf->samples;
// set to full bright if no light data
if (/* r_fullbright->value || */ !cl.worldmodel->lightdata)
// set to full bright if no light data
if (/*r_fullbright->value ||*/ !cl.worldmodel->lightdata)
{
bl = blocklights;
for (i=0 ; i<size ; i++)
blocklights[0][i] =
blocklights[1][i] =
blocklights[2][i] =
blocklights[3][i] = 255*256;
{
*bl++ = 255*256;
*bl++ = 255*256;
*bl++ = 255*256;
}
goto store;
}
// clear to no light
// clear to no light
bl = blocklights;
for (i=0 ; i<size ; i++)
blocklights[0][i] =
blocklights[1][i] =
blocklights[2][i] =
blocklights[3][i] = 0;
{
*bl++ = 0;
*bl++ = 0;
*bl++ = 0;
}
bl = blocklights;
// add all the lightmaps
// add all the lightmaps
if (lightmap)
for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
for (maps = 0;
maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
surf->cached_light[maps] = scale; // 8.8 fraction
bl = blocklights;
for (i=0 ; i<size ; i++)
{
blocklights[0][i] += lightmap[i] * scale;
blocklights[1][i] += lightmap[i] * scale;
blocklights[2][i] += lightmap[i] * scale;
blocklights[3][i] += lightmap[i] * scale;
*bl++ += *lightmap++ * scale;
*bl++ += *lightmap++ * scale;
*bl++ += *lightmap++ * scale;
}
lightmap += size; // skip to next lightmap
}
// add all the dynamic lights
// add all the dynamic lights
if (surf->dlightframe == r_framecount)
R_AddDynamicLights (surf);
// bound, invert, and shift
store:
// bound and shift
if (gl_colorlights->value)
{
stride -= (smax<<2);
rbl = blocklights[0];
gbl = blocklights[1];
bbl = blocklights[2];
bl = blocklights[3];
for (i=0 ; i<tmax ; i++, dest += stride)
stride -= smax * 3;
bl = blocklights;
for (i = 0; i < tmax; i++, dest += stride)
for (j=0 ; j<smax ; j++)
{
t = *rbl++;
dest[0] = 255 - min(t >> 7, 255);
t = *gbl++;
dest[1] = 255 - min(t >> 7, 255);
t = *bbl++;
dest[2] = 255 - min(t >> 7, 255);
t = *bl++;
dest[3] = 255 - min(t >> 7, 255);
dest += 4;
t = (int) *bl++ >> 8;
*dest++ = bound(0, t, 255);
t = (int) *bl++ >> 8;
*dest++ = bound(0, t, 255);
t = (int) *bl++ >> 8;
*dest++ = bound(0, t, 255);
}
} else {
bl = blocklights[3];
for (i=0 ; i<tmax ; i++, dest += stride)
stride -= smax;
bl = blocklights;
for (i = 0; i < tmax; i++, dest += stride)
for (j=0 ; j<smax ; j++)
{
t = *bl++;
dest[j] = 255 - min(t >> 7, 255);
t = (int) *bl++ >> 8;
t2 = bound(0, t, 255);
t = (int) *bl++ >> 8;
t2 += bound(0, t, 255);
t = (int) *bl++ >> 8;
t2 += bound(0, t, 255);
t2 *= (1.0/3.0);
*dest++ = t2;
}
}
}
/*
===============
R_TextureAnimation
@ -350,108 +368,6 @@ void GL_EnableMultitexture(void)
}
}
#ifndef _WIN32
/*
================
R_DrawSequentialPoly
Systems that have fast state and texture changes can
just do everything as it passes with no need to sort
================
*/
void R_DrawSequentialPoly (msurface_t *s)
{
glpoly_t *p;
// float *v;
// int i;
texture_t *t;
//
// normal lightmaped poly
//
#if 0
if ((!(s->flags & (SURF_DRAWSKY|SURF_DRAWTURB)))
&& ((r_viewleaf->contents!=CONTENTS_EMPTY && (s->flags & SURF_UNDERWATER)) ||
(r_viewleaf->contents==CONTENTS_EMPTY && !(s->flags & SURF_UNDERWATER))))
{
p = s->polys;
t = R_TextureAnimation (s->texinfo->texture);
GL_Bind (t->gl_texturenum);
glBegin (GL_POLYGON);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
glTexCoord2f (v[3], v[4]);
glVertex3fv (v);
}
glEnd ();
GL_Bind (lightmap_textures + s->lightmaptexturenum);
glEnable (GL_BLEND);
glBegin (GL_POLYGON);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
{
glTexCoord2f (v[5], v[6]);
glVertex3fv (v);
}
glEnd ();
glDisable (GL_BLEND);
return;
}
#endif
//
// subdivided water surface warp
//
if (s->flags & SURF_DRAWTURB)
{
GL_Bind (s->texinfo->texture->gl_texturenum);
EmitWaterPolys (s);
return;
}
//
// subdivided sky warp
//
if (s->flags & SURF_DRAWSKY)
{
GL_Bind (solidskytexture);
speedscale = realtime*8;
speedscale -= (int)speedscale;
EmitSkyPolys (s);
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_Bind (alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale;
EmitSkyPolys (s);
if (!gl_colorlights->value)
glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
glDisable (GL_BLEND);
}
//
// underwater warped with lightmap
//
p = s->polys;
t = R_TextureAnimation (s->texinfo->texture);
GL_Bind (t->gl_texturenum);
DrawGLWaterPoly (p);
GL_Bind (lightmap_textures + s->lightmaptexturenum);
glEnable (GL_BLEND);
DrawGLWaterPolyLightmap (p);
glDisable (GL_BLEND);
}
#else
/*
================
R_DrawSequentialPoly
@ -466,10 +382,8 @@ void R_DrawSequentialPoly (msurface_t *s)
float *v;
int i;
texture_t *t;
vec3_t nv, dir;
float ss, ss2, length;
float s1, t1;
glRect_t *theRect;
// vec3_t nv;
// glRect_t *theRect;
//
// normal lightmaped poly
@ -478,14 +392,15 @@ void R_DrawSequentialPoly (msurface_t *s)
if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
{
R_RenderDynamicLightmaps (s);
if (gl_mtexable) {
p = s->polys;
if (0) //gl_mtexable)
{
/* p = s->polys;
t = R_TextureAnimation (s->texinfo->texture);
// Binds world to texture env 0
GL_SelectTexture(TEXTURE0_SGIS);
GL_Bind (t->gl_texturenum);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// Binds lightmap to texenv 1
GL_EnableMultitexture(); // Same as SelectTexture (TEXTURE1)
GL_Bind (lightmap_textures + s->lightmaptexturenum);
@ -512,7 +427,7 @@ void R_DrawSequentialPoly (msurface_t *s)
glVertex3fv (v);
}
glEnd ();
return;
return; */
} else {
p = s->polys;
@ -528,7 +443,6 @@ void R_DrawSequentialPoly (msurface_t *s)
glEnd ();
GL_Bind (lightmap_textures + s->lightmaptexturenum);
glEnable (GL_BLEND);
glBegin (GL_POLYGON);
v = p->verts[0];
for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
@ -537,10 +451,7 @@ void R_DrawSequentialPoly (msurface_t *s)
glVertex3fv (v);
}
glEnd ();
glDisable (GL_BLEND);
}
return;
}
@ -568,13 +479,11 @@ void R_DrawSequentialPoly (msurface_t *s)
EmitSkyPolys (s);
glEnable (GL_BLEND);
GL_Bind (alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127;
EmitSkyPolys (s);
glDisable (GL_BLEND);
return;
}
@ -582,13 +491,13 @@ void R_DrawSequentialPoly (msurface_t *s)
// underwater warped with lightmap
//
R_RenderDynamicLightmaps (s);
if (gl_mtexable) {
p = s->polys;
if (0) //gl_mtexable)
{
/* p = s->polys;
t = R_TextureAnimation (s->texinfo->texture);
GL_SelectTexture(TEXTURE0_SGIS);
GL_Bind (t->gl_texturenum);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
GL_EnableMultitexture();
GL_Bind (lightmap_textures + s->lightmaptexturenum);
i = s->lightmaptexturenum;
@ -619,7 +528,7 @@ void R_DrawSequentialPoly (msurface_t *s)
glVertex3fv (nv);
}
glEnd ();
*/
} else {
p = s->polys;
@ -628,12 +537,9 @@ void R_DrawSequentialPoly (msurface_t *s)
DrawGLWaterPoly (p);
GL_Bind (lightmap_textures + s->lightmaptexturenum);
glEnable (GL_BLEND);
DrawGLWaterPolyLightmap (p);
glDisable (GL_BLEND);
}
}
#endif
/*
@ -727,12 +633,7 @@ void R_BlendLightmaps (void)
glDepthMask (0); // don't bother writing Z
glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
if (!r_lightmap->value)
{
glEnable (GL_BLEND);
}
glBlendFunc (GL_ZERO, GL_SRC_COLOR);
for (i=0 ; i<MAX_LIGHTMAPS ; i++)
{
@ -784,8 +685,6 @@ void R_BlendLightmaps (void)
}
}
glDisable (GL_BLEND);
// Return to normal blending --KB
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -943,56 +842,6 @@ void R_MirrorChain (msurface_t *s)
}
#if 0
/*
================
R_DrawWaterSurfaces
================
*/
void R_DrawWaterSurfaces (void)
{
int i;
msurface_t *s;
texture_t *t;
if (r_wateralpha->value == 1.0)
return;
//
// go back to the world matrix
//
glLoadMatrixf (r_world_matrix);
glEnable (GL_BLEND);
glColor4f (1, 1, 1, r_wateralpha->value);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
for (i=0 ; i<cl.worldmodel->numtextures ; i++)
{
t = cl.worldmodel->textures[i];
if (!t)
continue;
s = t->texturechain;
if (!s)
continue;
if ( !(s->flags & SURF_DRAWTURB) )
continue;
// set modulate mode explicitly
GL_Bind (t->gl_texturenum);
for ( ; s ; s=s->texturechain)
R_RenderBrushPoly (s);
t->texturechain = NULL;
}
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4f (1,1,1,1);
glDisable (GL_BLEND);
}
#else
/*
================
R_DrawWaterSurfaces
@ -1014,8 +863,7 @@ void R_DrawWaterSurfaces (void)
glLoadMatrixf (r_world_matrix);
if (r_wateralpha->value < 1.0) {
glEnable (GL_BLEND);
glColor4f (1, 1, 1, r_wateralpha->value);
glColor4f (0.5, 0.5, 0.5, r_wateralpha->value);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
@ -1054,16 +902,10 @@ void R_DrawWaterSurfaces (void)
}
if (r_wateralpha->value < 1.0) {
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4f (1,1,1,1);
glDisable (GL_BLEND);
}
if (r_wateralpha->value < 1.0)
glColor3f (0.5, 0.5, 0.5);
}
#endif
/*
================
@ -1154,7 +996,7 @@ void R_DrawBrushModel (entity_t *e)
if (R_CullBox (mins, maxs))
return;
glColor3f (1,1,1);
glColor3f (1.0, 1.0, 1.0);
memset (lightmap_polys, 0, sizeof(lightmap_polys));
VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
@ -1172,8 +1014,8 @@ void R_DrawBrushModel (entity_t *e)
psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
// calculate dynamic lighting for bmodel if it's not an
// instanced model
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (clmodel->firstmodelsurface != 0 && !gl_flashblend->value)
{
for (k=0 ; k<MAX_DLIGHTS ; k++)
@ -1187,22 +1029,22 @@ void R_DrawBrushModel (entity_t *e)
}
}
glPushMatrix ();
e->angles[0] = -e->angles[0]; // stupid quake bug
glPushMatrix ();
e->angles[0] = -e->angles[0]; // stupid quake bug
R_RotateForEntity (e);
e->angles[0] = -e->angles[0]; // stupid quake bug
e->angles[0] = -e->angles[0]; // stupid quake bug
//
// draw texture
//
for (i=0 ; i<clmodel->nummodelsurfaces ; i++, psurf++)
{
// find which side of the node we are on
// find which side of the node we are on
pplane = psurf->plane;
dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
// draw the polygon
// draw the polygon
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
{
@ -1247,7 +1089,7 @@ void R_RecursiveWorldNode (mnode_t *node)
if (R_CullBox (node->minmaxs, node->minmaxs+3))
return;
// if a leaf node, draw stuff
// if a leaf node, draw stuff
if (node->contents < 0)
{
pleaf = (mleaf_t *)node;
@ -1271,9 +1113,9 @@ void R_RecursiveWorldNode (mnode_t *node)
return;
}
// node is just a decision point, so go down the apropriate sides
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
// find which side of the node we are on
plane = node->plane;
switch (plane->type)
@ -1297,10 +1139,10 @@ void R_RecursiveWorldNode (mnode_t *node)
else
side = 1;
// recurse down the children, front side first
// recurse down the children, front side first
R_RecursiveWorldNode (node->children[side]);
// draw stuff
// draw stuff
c = node->numsurfaces;
if (c)
@ -1348,7 +1190,7 @@ void R_RecursiveWorldNode (mnode_t *node)
}
// recurse down the back side
// recurse down the back side
R_RecursiveWorldNode (node->children[!side]);
}
@ -1371,20 +1213,21 @@ void R_DrawWorld (void)
currententity = &ent;
currenttexture = -1;
glColor3f (1,1,1);
glColor3f (1.0, 1.0, 1.0);
memset (lightmap_polys, 0, sizeof(lightmap_polys));
// Be sure to clear the skybox --KB
R_ClearSkyBox ();
R_RecursiveWorldNode (cl.worldmodel->nodes);
DrawTextureChains ();
DrawTextureChains ();
R_BlendLightmaps ();
// Adjust the depth range and draw the skybox, ensuring it's behind
// everhting else. This fixes the problem where some things are
// drawn as sky when something else should be drawn. --KB
glColor3f (0.5, 0.5, 0.5);
glDepthRange (gldepthmax, gldepthmax);
R_DrawSkyBox ();
glDepthRange (gldepthmin, gldepthmax);
@ -1469,7 +1312,8 @@ int AllocBlock (int w, int h, int *x, int *y)
best2 = allocated[texnum][i+j];
}
if (j == w)
{ // this is a valid spot
{
// this is a valid spot
*x = i;
*y = best = best2;
}
@ -1659,8 +1503,8 @@ void GL_BuildLightmaps (void)
if (gl_colorlights->value)
{
gl_lightmap_format = GL_RGBA;
lightmap_bytes = 4;
gl_lightmap_format = GL_RGB;
lightmap_bytes = 3;
} else {
gl_lightmap_format = GL_LUMINANCE;
lightmap_bytes = 1;
@ -1682,6 +1526,7 @@ void GL_BuildLightmaps (void)
continue;
if ( m->surfaces[i].flags & SURF_DRAWSKY )
continue;
GL_CreateSurfaceLightmap (m->surfaces + i);
BuildSurfaceDisplayList (m->surfaces + i);
}
}
@ -1704,9 +1549,10 @@ void GL_BuildLightmaps (void)
GL_Bind(lightmap_textures + i);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
, BLOCK_WIDTH, BLOCK_HEIGHT, 0,
gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes, BLOCK_WIDTH,
BLOCK_HEIGHT, 0, gl_lightmap_format,
GL_UNSIGNED_BYTE, lightmaps +
i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
}
if (!gl_texsort->value)

View file

@ -1175,7 +1175,7 @@ void SCR_UpdateScreen (void)
// do 3D refresh drawing, and then update the screen
//
SCR_SetUpToDrawConsole ();
V_RenderView ();
GL_Set2D ();
@ -1225,6 +1225,20 @@ void SCR_UpdateScreen (void)
M_Draw ();
}
// LordHavoc's lighting fix
glDisable (GL_TEXTURE_2D);
glColor3f (1.0, 1.0, 1.0);
glBlendFunc (GL_DST_COLOR, GL_ONE);
glBegin (GL_QUADS);
glVertex2f (0,0);
glVertex2f (vid.width, 0);
glVertex2f (vid.width, vid.height);
glVertex2f (0, vid.height);
glEnd ();
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
V_UpdatePalette ();
GL_EndRendering ();

View file

@ -67,50 +67,54 @@ void V_CalcPowerupCshift (void);
qboolean V_CheckGamma (void);
/*
=============
V_CalcBlend
=============
V_CalcBlend
LordHavoc made this a real, (messy,) true alpha blend. Cleaned it up
a bit, but otherwise this is his code. --KB
*/
void V_CalcBlend (void)
void
V_CalcBlend (void)
{
float r, g, b, a, a2;
int j;
float r, g, b, a, a2, a3;
int j;
r = 0;
g = 0;
b = 0;
a = 0;
r = 0;
g = 0;
b = 0;
a = 0;
for (j=0 ; j<NUM_CSHIFTS ; j++)
{
/* if (!gl_cshiftpercent.value)
CVAR_FIXME */
if (!gl_cshiftpercent->value)
continue;
for (j=0 ; j<NUM_CSHIFTS ; j++)
{
if (!gl_cshiftpercent->value)
continue;
/* a2 = ((cl.cshifts[j].percent * gl_cshiftpercent.value) / 100.0) / 255.0;
CVAR_FIXME */
a2 = ((cl.cshifts[j].percent * gl_cshiftpercent->value) / 100.0) / 255.0;
a2 = ((cl.cshifts[j].percent * gl_cshiftpercent->value) / 100.0) / 255.0;
// a2 = (cl.cshifts[j].percent/2)/255.0;
if (!a2)
continue;
a = a + a2*(1-a);
//Con_Printf ("j:%i a:%f\n", j, a);
a2 = a2/a;
r = r*(1-a2) + cl.cshifts[j].destcolor[0]*a2;
g = g*(1-a2) + cl.cshifts[j].destcolor[1]*a2;
b = b*(1-a2) + cl.cshifts[j].destcolor[2]*a2;
}
if (!a2)
continue;
v_blend[0] = r/255.0;
v_blend[1] = g/255.0;
v_blend[2] = b/255.0;
v_blend[3] = a;
if (v_blend[3] > 1)
v_blend[3] = 1;
if (v_blend[3] < 0)
v_blend[3] = 0;
a2 = min(a2, 1.0);
r += (cl.cshifts[j].destcolor[0]-r) * a2;
g += (cl.cshifts[j].destcolor[1]-g) * a2;
b += (cl.cshifts[j].destcolor[2]-b) * a2;
a3 = (1.0 - a) * (1.0 - a2);
a = 1.0 - a3;
}
if (a > 1.0)
{
a2 = 1.0 / a;
r *= a2;
g *= a2;
b *= a2;
a = 1.0;
}
v_blend[0] = min(r, 255.0)/255.0;
v_blend[1] = min(g, 255.0)/255.0;
v_blend[2] = min(b, 255.0)/255.0;
v_blend[3] = bound (0.0, a, 1.0);
}
/*
@ -174,15 +178,9 @@ void V_UpdatePalette (void)
a = 1-a;
for (i=0 ; i<256 ; i++)
{
ir = i*a + r;
ig = i*a + g;
ib = i*a + b;
if (ir > 255)
ir = 255;
if (ig > 255)
ig = 255;
if (ib > 255)
ib = 255;
ir = min(i*a + r, 255);
ig = min(i*a + g, 255);
ib = min(i*a + b, 255);
ramps[0][i] = gammatable[ir];
ramps[1][i] = gammatable[ig];
@ -207,3 +205,4 @@ void V_UpdatePalette (void)
VID_ShiftPalette (pal);
}

View file

@ -309,14 +309,11 @@ void EmitBothSkyLayers (msurface_t *fa)
EmitSkyPolys (fa);
glEnable (GL_BLEND);
GL_Bind (alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127 ;
EmitSkyPolys (fa);
glDisable (GL_BLEND);
}
/*
@ -901,15 +898,12 @@ void R_DrawSkyChain (msurface_t *s)
for (fa=s ; fa ; fa=fa->texturechain)
EmitSkyPolys (fa);
glEnable (GL_BLEND);
GL_Bind (alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127 ;
for (fa=s ; fa ; fa=fa->texturechain)
EmitSkyPolys (fa);
glDisable (GL_BLEND);
}
}

View file

@ -242,7 +242,7 @@ void VID_SetPalette (unsigned char *palette)
v = (255<<24) + (r<<0) + (g<<8) + (b<<16);
*table++ = v;
}
d_8to24table[255] &= 0xffffff; // 255 is transparent
d_8to24table[255] &= 0; // 255 is transparent
// JACK: 3D distance calcs - k is last closest, l is the distance.
// FIXME: Precalculate this and cache to disk.
@ -330,8 +330,7 @@ void GL_Init (void)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
/*

View file

@ -663,8 +663,7 @@ void GL_Init (void)
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
#if 0
CheckArrayExtensions ();
@ -818,6 +817,11 @@ void VID_Shutdown (void)
wglMakeCurrent(NULL, NULL);
// LordHavoc: free textures before closing (may help NVIDIA)
for (i = 0;i < 8192;i++)
temp[i] = i;
glDeleteTextures(8192, temp);
if (hRC)
wglDeleteContext(hRC);