that's most of newtree's gl stuff ported over. Three bugs: wound up with

newtree's slow skys, some models are not getting lit, and dlights don't seem
to be working :(
This commit is contained in:
Bill Currie 2000-08-27 10:03:31 +00:00
parent 8538ec49d1
commit 8302413276
7 changed files with 1066 additions and 1693 deletions

View file

@ -163,6 +163,7 @@ extern qboolean envmap;
extern int currenttexture;
extern int cnttextures[2];
extern int particletexture;
extern int netgraphtexture;
extern int playertextures;
extern int skytexturenum; // index in cl.loadmodel, not gl texture object
@ -178,8 +179,10 @@ extern cvar_t *r_lightmap;
extern cvar_t *r_shadows;
extern cvar_t *r_mirroralpha;
extern cvar_t *r_wateralpha;
extern cvar_t *r_waterripple;
extern cvar_t *r_dynamic;
extern cvar_t *r_novis;
extern cvar_t *r_netgraph;
extern cvar_t *gl_clear;
extern cvar_t *gl_cull;
@ -200,6 +203,7 @@ extern cvar_t *gl_clear;
extern cvar_t *gl_subdivide_size;
extern cvar_t *gl_particles;
extern cvar_t *gl_fires;
extern cvar_t *gl_fb_models;
extern int gl_lightmap_format;
extern int gl_solid_format;
@ -208,6 +212,9 @@ extern int gl_alpha_format;
extern cvar_t *gl_max_size;
extern cvar_t *gl_playermip;
extern cvar_t *r_skyname;
extern cvar_t *gl_skymultipass;
extern int mirrortexturenum; // quake texturenum, not gltexturenum
extern qboolean mirror;
extern qboolean lighthalf;
@ -256,9 +263,13 @@ void EmitWaterPolys (msurface_t *fa);
void EmitSkyPolys (msurface_t *fa);
void EmitBothSkyLayers (msurface_t *fa);
void R_DrawSkyChain (msurface_t *s);
qboolean R_CullBox (vec3_t mins, vec3_t maxs);
void R_LoadSkys (char *);
void R_DrawSky (void);
void R_RotateForEntity (entity_t *e);
qboolean R_CullBox (vec3_t mins, vec3_t maxs);
void AddLightBlend (float, float, float, float);
typedef struct {

View file

@ -476,8 +476,8 @@ void Draw_Init (void)
draw_backtile = Draw_PicFromWad ("backtile");
// LordHavoc: call init code for other GL renderer modules;
//XXXglrmain_init();
//XXXglrsurf_init();
glrmain_init();
glrsurf_init();
}
@ -1414,20 +1414,3 @@ static int GL_LoadPicTexture (qpic_t *pic)
{
return GL_LoadTexture ("", pic->width, pic->height, pic->data, false, true, 1);
}
/****************************************/
static GLenum oldtarget = TEXTURE0_SGIS;
void GL_SelectTexture (GLenum target)
{
if (!gl_mtexable)
return;
qglSelectTextureSGIS(target);
if (target == oldtarget)
return;
cnttextures[oldtarget-TEXTURE0_SGIS] = currenttexture;
currenttexture = cnttextures[target-TEXTURE0_SGIS];
oldtarget = target;
}

View file

@ -1,7 +1,7 @@
/*
gl_rmain.c
@description@
(description)
Copyright (C) 1996-1997 Id Software, Inc.
@ -30,13 +30,23 @@
# include "config.h"
#endif
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "compat.h"
#include "qargs.h"
#include "console.h"
#include "r_local.h"
#include "view.h"
#include "qdefs.h"
#include "glquake.h"
#include "client.h"
#include "model.h"
#include "render.h"
#include "sys.h"
#include "console.h"
#include "chase.h"
#include "view.h"
#include "r_local.h"
entity_t r_worldentity;
@ -45,6 +55,10 @@ qboolean r_cache_thrash; // compatability
vec3_t modelorg, r_entorigin;
entity_t *currententity;
int currenttexture = -1; // to avoid unnecessary texture sets
int cnttextures[2] = {-1, -1}; // cached
int r_visframecount; // bumped when going to a new PVS
int r_framecount; // used for dlight push checking
@ -54,9 +68,6 @@ int c_brush_polys, c_alias_polys;
qboolean envmap; // true during envmap command capture
int currenttexture = -1; // to avoid unnecessary texture sets
int cnttextures[2] = {-1, -1}; // cached
int particletexture; // little dot for particles
int playertextures; // up to 16 color translated skins
@ -83,8 +94,6 @@ refdef_t r_refdef;
mleaf_t *r_viewleaf, *r_oldviewleaf;
texture_t *r_notexture_mip;
int d_lightstylevalue[256]; // 8.8 fraction of base light value
@ -99,10 +108,11 @@ cvar_t *r_lightmap;
cvar_t *r_shadows;
cvar_t *r_mirroralpha;
cvar_t *r_wateralpha;
cvar_t *r_waterripple;
cvar_t *r_dynamic;
cvar_t *r_novis;
cvar_t *r_netgraph;
cvar_t *gl_finish;
cvar_t *gl_clear;
cvar_t *gl_cull;
cvar_t *gl_texsort;
@ -114,9 +124,65 @@ cvar_t *gl_playermip;
cvar_t *gl_nocolors;
cvar_t *gl_keeptjunctions;
cvar_t *gl_reporttjunctions;
cvar_t *gl_doubleeyes;
cvar_t *gl_particles;
cvar_t *gl_fires;
cvar_t *r_skyname;
cvar_t *gl_skymultipass;
cvar_t *gl_fb_models;
cvar_t *gl_fb_bmodels;
extern cvar_t *scr_fov;
extern byte gammatable[256];
extern qboolean lighthalf;
static float vid_gamma = 1.0;
// LordHavoc: place for gl_rmain setup code
void glrmain_init()
{
};
/*
GL_CheckGamma
More or less redesigned by LordHavoc
*/
void
GL_CheckGamma (unsigned char *pal)
{
float inf;
int i;
if ((i = COM_CheckParm("-gamma")) == 0) {
if ((gl_renderer && strstr(gl_renderer, "Voodoo")) ||
(gl_vendor && strstr(gl_vendor, "3Dfx")))
vid_gamma = 1;
else
vid_gamma = 0.7; // default to 0.7 on non-3dfx hardware
} else
vid_gamma = atof(com_argv[i+1]);
// build the gamma table
if (vid_gamma == 1)
{
// 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;
}
}
// correct the palette
for (i = 0; i < 768; i++)
pal[i] = gammatable[pal[i]];
}
/*
=================
@ -142,6 +208,7 @@ void R_RotateForEntity (entity_t *e)
glRotatef (e->angles[1], 0, 0, 1);
glRotatef (-e->angles[0], 0, 1, 0);
//ZOID: fixed z angle
glRotatef (e->angles[2], 1, 0, 0);
}
@ -158,7 +225,7 @@ void R_RotateForEntity (entity_t *e)
R_GetSpriteFrame
================
*/
mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
static mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
{
msprite_t *psprite;
mspritegroup_t *pspritegroup;
@ -211,7 +278,7 @@ R_DrawSpriteModel
=================
*/
void R_DrawSpriteModel (entity_t *e)
static void R_DrawSpriteModel (entity_t *e)
{
vec3_t point;
mspriteframe_t *frame;
@ -236,15 +303,19 @@ void R_DrawSpriteModel (entity_t *e)
right = vright;
}
glColor3f (1,1,1);
GL_DisableMultitexture();
if (lighthalf)
glColor4f(0.5,0.5,0.5,1);
else
glColor4f(1,1,1,1);
glBindTexture (GL_TEXTURE_2D, frame->gl_texturenum);
glEnable (GL_ALPHA_TEST);
glBegin (GL_QUADS);
glEnable (GL_ALPHA_TEST);
glBegin (GL_QUADS);
glTexCoord2f (0, 1);
VectorMA (e->origin, frame->down, up, point);
VectorMA (point, frame->left, right, point);
@ -303,14 +374,14 @@ int lastposenum;
GL_DrawAliasFrame
=============
*/
void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
static void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum, qboolean fb)
{
float l;
trivertx_t *verts;
int *order;
int count;
lastposenum = posenum;
lastposenum = posenum;
verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
verts += posenum * paliashdr->poseverts;
@ -336,9 +407,20 @@ lastposenum = posenum;
glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
order += 2;
// normals and vertexes come from the frame list
l = shadedots[verts->lightnormalindex] * shadelight;
glColor3f (l, l, l);
if (fb) {
glColor4f (1, 1, 1, 1);
} else {
// normals and vertexes come from the frame list
l = shadedots[verts->lightnormalindex] * shadelight;
// LordHavoc: cleanup after Endy
if (!lighthalf) {
glColor4f(2 * l, 2 * l, 2 * l, 1);
} else {
glColor4f(l, l, l, 1);
}
}
glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
verts++;
} while (--count);
@ -355,7 +437,7 @@ GL_DrawAliasShadow
*/
extern vec3_t lightspot;
void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
static void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
{
trivertx_t *verts;
int *order;
@ -418,7 +500,7 @@ R_SetupAliasFrame
=================
*/
void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
static void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr, qboolean fb)
{
int pose, numposes;
float interval;
@ -438,18 +520,17 @@ void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
pose += (int)(cl.time / interval) % numposes;
}
GL_DrawAliasFrame (paliashdr, pose);
GL_DrawAliasFrame (paliashdr, pose, fb);
}
/*
=================
R_DrawAliasModel
=================
*/
void R_DrawAliasModel (entity_t *e)
static void R_DrawAliasModel (entity_t *e)
{
int i;
int lnum;
@ -469,7 +550,6 @@ void R_DrawAliasModel (entity_t *e)
if (R_CullBox (mins, maxs))
return;
VectorCopy (currententity->origin, r_entorigin);
VectorSubtract (r_origin, r_entorigin, modelorg);
@ -490,9 +570,10 @@ void R_DrawAliasModel (entity_t *e)
VectorSubtract (currententity->origin,
cl_dlights[lnum].origin,
dist);
add = cl_dlights[lnum].radius - Length(dist);
add = (cl_dlights[lnum].radius * cl_dlights[lnum].radius * 8) / (Length(dist) * Length(dist)); // FIXME Deek
if (add > 0) {
if (add > 0)
{
ambientlight += add;
//ZOID models should be affected by dlights as well
shadelight += add;
@ -507,15 +588,16 @@ void R_DrawAliasModel (entity_t *e)
shadelight = 192 - ambientlight;
// ZOID: never allow players to go totally black
i = currententity - cl_entities;
if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
if (!strcmp(clmodel->name, "progs/player.mdl"))
{
if (ambientlight < 8)
ambientlight = shadelight = 8;
// HACK HACK HACK -- no fullbright colors, so make torches full light
if (!strcmp (clmodel->name, "progs/flame2.mdl")
|| !strcmp (clmodel->name, "progs/flame.mdl") )
} else if (!gl_fb_models->value && (
!strcmp (clmodel->name, "progs/flame.mdl") ||
!strcmp (clmodel->name, "progs/flame2.mdl"))) {
// HACK HACK HACK -- no fullbright colors, so make torches full light
ambientlight = shadelight = 256;
}
shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
shadelight = shadelight / 200.0;
@ -537,16 +619,17 @@ void R_DrawAliasModel (entity_t *e)
// draw all the triangles
//
GL_DisableMultitexture();
glPushMatrix ();
glPushMatrix ();
R_RotateForEntity (e);
if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes->value) {
if (!strcmp (clmodel->name, "progs/eyes.mdl") )
{
glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
// double size of eyes, since they are really hard to see in gl
// double size of eyes, since they are really hard to see in gl
glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
} else {
}
else
{
glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
}
@ -565,14 +648,25 @@ 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);
R_SetupAliasFrame (currententity->frame, paliashdr, false);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
// This block is GL fullbright support for objects...
if (clmodel->hasfullbrights && gl_fb_models->value &&
paliashdr->gl_fb_texturenum[currententity->skinnum][anim]) {
/*
glEnable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
*/
glBindTexture (GL_TEXTURE_2D, paliashdr->gl_fb_texturenum[currententity->skinnum][anim]);
R_SetupAliasFrame (currententity->frame, paliashdr, true);
//glDisable (GL_BLEND);
}
glShadeModel (GL_FLAT);
if (gl_affinemodels->value)
@ -585,12 +679,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);
glColor4f (0.5, 0.5, 0.5, 1);
glPopMatrix ();
}
@ -603,46 +695,39 @@ void R_DrawAliasModel (entity_t *e)
R_DrawEntitiesOnList
=============
*/
void R_DrawEntitiesOnList (void)
static void R_DrawEntitiesOnList (void)
{
int i;
if (!r_drawentities->value)
return;
// draw sprites seperately, because of alpha blending
// LordHavoc: split into 3 loops to simplify state changes
for (i=0 ; i<cl_numvisedicts ; i++)
{
if (cl_visedicts[i]->model->type != mod_brush)
continue;
currententity = cl_visedicts[i];
switch (currententity->model->type)
{
case mod_alias:
R_DrawAliasModel (currententity);
break;
case mod_brush:
R_DrawBrushModel (currententity);
break;
default:
break;
}
R_DrawBrushModel (currententity);
}
for (i=0 ; i<cl_numvisedicts ; i++)
{
if (cl_visedicts[i]->model->type != mod_alias)
continue;
currententity = cl_visedicts[i];
switch (currententity->model->type)
{
case mod_sprite:
R_DrawSpriteModel (currententity);
break;
case mod_brush:
case mod_alias:
break;
}
R_DrawAliasModel (currententity);
}
for (i=0 ; i<cl_numvisedicts ; i++)
{
if (cl_visedicts[i]->model->type != mod_sprite)
continue;
currententity = cl_visedicts[i];
R_DrawSpriteModel (currententity);
}
}
@ -651,113 +736,25 @@ void R_DrawEntitiesOnList (void)
R_DrawViewModel
=============
*/
void R_DrawViewModel (void)
static void R_DrawViewModel (void)
{
float ambient[4], diffuse[4];
int j;
int lnum;
vec3_t dist;
float add;
dlight_t *dl;
int ambientlight, shadelight;
if (!r_drawviewmodel->value)
return;
if (chase_active->value)
return;
if (envmap)
return;
if (!r_drawentities->value)
return;
if (cl.items & IT_INVISIBILITY)
return;
if (cl.stats[STAT_HEALTH] <= 0)
return;
currententity = &cl.viewent;
if (!currententity->model)
if (!r_drawviewmodel->value
|| chase_active->value
|| envmap
|| !r_drawentities->value
|| (cl.items & IT_INVISIBILITY)
|| cl.stats[STAT_HEALTH] <= 0
|| !currententity->model)
return;
j = R_LightPoint (currententity->origin);
if (j < 24)
j = 24; // allways give some light on gun
ambientlight = j;
shadelight = j;
// add dynamic lights
for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
{
dl = &cl_dlights[lnum];
if (!dl->radius)
continue;
if (!dl->radius)
continue;
if (dl->die < cl.time)
continue;
VectorSubtract (currententity->origin, dl->origin, dist);
add = dl->radius - Length(dist);
if (add > 0)
ambientlight += add;
}
ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128;
diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;
// hack the depth range to prevent view model from poking into walls
glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
R_DrawAliasModel (currententity);
glDepthRange (gldepthmin, gldepthmax);
}
/*
============
R_PolyBlend
============
*/
void R_PolyBlend (void)
{
if (!gl_polyblend->value)
return;
if (!v_blend[3])
return;
GL_DisableMultitexture();
glDisable (GL_ALPHA_TEST);
glEnable (GL_BLEND);
glDisable (GL_DEPTH_TEST);
glDisable (GL_TEXTURE_2D);
glLoadIdentity ();
glRotatef (-90, 1, 0, 0); // put Z going up
glRotatef (90, 0, 0, 1); // put Z going up
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);
}
int SignbitsForPlane (mplane_t *out)
static int SignbitsForPlane (mplane_t *out)
{
int bits, j;
@ -773,7 +770,7 @@ int SignbitsForPlane (mplane_t *out)
}
void R_SetFrustum (void)
static void R_SetFrustum (void)
{
int i;
@ -789,6 +786,7 @@ void R_SetFrustum (void)
}
else
{
// rotate VPN right by FOV_X/2 degrees
RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
// rotate VPN left by FOV_X/2 degrees
@ -814,11 +812,11 @@ void R_SetFrustum (void)
R_SetupFrame
===============
*/
void R_SetupFrame (void)
static void R_SetupFrame (void)
{
// don't allow cheats in multiplayer
if (cl.maxclients > 1)
Cvar_Set(r_fullbright, "0");
r_fullbright->value = 0;
r_lightmap->value = 0;
R_AnimateLight ();
@ -844,7 +842,7 @@ void R_SetupFrame (void)
}
void MYgluPerspective( GLdouble fovy, GLdouble aspect,
static void MYgluPerspective( GLdouble fovy, GLdouble aspect,
GLdouble zNear, GLdouble zFar )
{
GLdouble xmin, xmax, ymin, ymax;
@ -864,7 +862,7 @@ void MYgluPerspective( GLdouble fovy, GLdouble aspect,
R_SetupGL
=============
*/
void R_SetupGL (void)
static void R_SetupGL (void)
{
float screenaspect;
extern int glwidth, glheight;
@ -902,6 +900,9 @@ void R_SetupGL (void)
glViewport (glx + x, gly + y2, w, h);
screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
// yfov = (2.0 * tan (scr_fov->value/360*M_PI)) / screenaspect;
// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov->value*2)/M_PI;
// MYgluPerspective (yfov, screenaspect, 4, 4096);
MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096);
if (mirror)
@ -931,13 +932,15 @@ void R_SetupGL (void)
// set drawing parms
//
if (gl_cull->value)
glEnable(GL_CULL_FACE);
glEnable (GL_CULL_FACE);
else
glDisable(GL_CULL_FACE);
glDisable (GL_CULL_FACE);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
glEnable (GL_BLEND);
glDisable (GL_ALPHA_TEST);
glAlphaFunc (GL_GREATER, 0.5);
glEnable (GL_DEPTH_TEST);
glShadeModel (GL_SMOOTH);
}
/*
@ -947,7 +950,7 @@ R_RenderScene
r_refdef must be set before the first call
================
*/
void R_RenderScene (void)
static void R_RenderScene (void)
{
R_SetupFrame ();
@ -963,16 +966,9 @@ void R_RenderScene (void)
R_DrawEntitiesOnList ();
GL_DisableMultitexture();
R_RenderDlights ();
R_UpdateFires ();
R_DrawParticles ();
#ifdef GLTEST
Test_Draw ();
#endif
}
@ -981,32 +977,20 @@ void R_RenderScene (void)
R_Clear
=============
*/
void R_Clear (void)
static void R_Clear (void)
{
if (r_mirroralpha->value != 1.0)
{
if (gl_clear->value)
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
glClear (GL_DEPTH_BUFFER_BIT);
gldepthmin = 0;
gldepthmax = 0.5;
glDepthFunc (GL_LEQUAL);
}
if (gl_clear->value)
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
{
if (gl_clear->value)
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
else
glClear (GL_DEPTH_BUFFER_BIT);
gldepthmin = 0;
gldepthmax = 1;
glDepthFunc (GL_LEQUAL);
}
glClear (GL_DEPTH_BUFFER_BIT);
gldepthmin = 0;
gldepthmax = 1;
glDepthFunc (GL_LEQUAL);
glDepthRange (gldepthmin, gldepthmax);
}
#if 0 //!!! FIXME, Zoid, mirror is disabled for now
/*
=============
R_Mirror
@ -1048,13 +1032,13 @@ void R_Mirror (void)
R_RenderScene ();
R_DrawWaterSurfaces ();
gldepthmin = 0;
gldepthmax = 0.5;
glDepthRange (gldepthmin, gldepthmax);
glDepthFunc (GL_LEQUAL);
// blend on top
glEnable (GL_BLEND);
glMatrixMode(GL_PROJECTION);
if (mirror_plane->normal[2])
glScalef (1,-1,1);
@ -1070,9 +1054,9 @@ 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
/*
================
@ -1083,56 +1067,23 @@ r_refdef must be set before the first call
*/
void R_RenderView (void)
{
double time1=0, time2;
if (r_norefresh->value)
return;
if (!r_worldentity.model || !cl.worldmodel)
Sys_Error ("R_RenderView: NULL worldmodel");
if (r_speeds->value)
{
glFinish ();
time1 = Sys_DoubleTime ();
c_brush_polys = 0;
c_alias_polys = 0;
}
// glFinish ();
mirror = false;
if (gl_finish->value)
glFinish ();
R_Clear ();
// render normal view
/***** Experimental silly looking fog ******
****** Use r_fullbright if you enable ******
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogfv(GL_FOG_COLOR, colors);
glFogf(GL_FOG_END, 512.0);
glEnable(GL_FOG);
********************************************/
R_RenderScene ();
R_DrawViewModel ();
R_DrawWaterSurfaces ();
// More fog right here :)
// glDisable(GL_FOG);
// End of all fog code...
// render mirror view
R_Mirror ();
R_PolyBlend ();
if (r_speeds->value)
{
// glFinish ();
time2 = Sys_DoubleTime ();
Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys);
}
// R_Mirror ();
}

View file

@ -1,7 +1,7 @@
/*
gl_rmisc.c
@description@
(description)
Copyright (C) 1996-1997 Id Software, Inc.
@ -30,11 +30,37 @@
# include "config.h"
#endif
#include "glquake.h"
#include "client.h"
#include "r_local.h"
#include <string.h>
#include <stdio.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#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"
#include "render.h" // needed by: client.h, gl_model.h, glquake.h
#include "client.h" // need cls in this file
#include "model.h" // needed by: glquake.h
#include "console.h"
#include "glquake.h"
#include "r_local.h"
qboolean VID_Is8bit(void);
void R_InitBubble();
void R_FireColor_f(void);
cvar_t *gl_fires;
qboolean allowskybox; // allow skyboxes? --KB
/*
==================
@ -175,16 +201,37 @@ void R_Envmap_f (void)
GL_EndRendering ();
}
/*
R_LoadSky_f
*/
void
R_LoadSky_f (void)
{
if (Cmd_Argc () != 2)
{
Con_Printf ("loadsky <name> : load a skybox\n");
return;
}
R_LoadSkys (Cmd_Argv(1));
}
/*
===============
R_Init
===============
*/
void R_Init (void)
{
{
allowskybox = false; // server will decide if this is allowed --KB
Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
Cmd_AddCommand ("envmap", R_Envmap_f);
Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
Cmd_AddCommand ("loadsky", R_LoadSky_f);
Cmd_AddCommand ("r_firecolor", R_FireColor_f);
r_norefresh = Cvar_Get("r_norefresh", "0", CVAR_NONE, "None");
r_lightmap = Cvar_Get("r_lightmap", "0", CVAR_NONE, "None");
@ -194,14 +241,15 @@ void R_Init (void)
r_shadows = Cvar_Get("r_shadows", "0", CVAR_NONE, "None");
r_mirroralpha = Cvar_Get("r_mirroralpha", "1", CVAR_NONE, "None");
r_wateralpha = Cvar_Get("r_wateralpha", "1", CVAR_NONE, "None");
r_waterripple = Cvar_Get ("r_waterripple", "0", CVAR_NONE, "None");
r_dynamic = Cvar_Get("r_dynamic", "1", CVAR_NONE, "None");
r_novis = Cvar_Get("r_novis", "0", CVAR_NONE, "None");
r_speeds = Cvar_Get("r_speeds", "0", CVAR_NONE, "None");
r_netgraph = Cvar_Get("r_netgraph", "0", CVAR_NONE, "None");
gl_finish = Cvar_Get("gl_finish", "0", CVAR_NONE, "None");
gl_clear = Cvar_Get("gl_clear", "0", CVAR_NONE, "None");
gl_texsort = Cvar_Get("gl_texsort", "1", CVAR_NONE, "None");
if (gl_mtexable)
Cvar_SetValue(gl_texsort, 0.0);
@ -209,7 +257,7 @@ void R_Init (void)
gl_smoothmodels = Cvar_Get("gl_smoothmodels", "1", CVAR_NONE, "None");
gl_affinemodels = Cvar_Get("gl_affinemodels", "0", CVAR_NONE, "None");
gl_polyblend = Cvar_Get("gl_polyblend", "1", CVAR_NONE, "None");
gl_flashblend = Cvar_Get("gl_flashblend", "1", CVAR_NONE, "None");
gl_flashblend = Cvar_Get("gl_flashblend", "0", CVAR_NONE, "None");
gl_playermip = Cvar_Get("gl_playermip", "0", CVAR_NONE, "None");
gl_nocolors = Cvar_Get("gl_nocolors", "0", CVAR_NONE, "None");
@ -219,18 +267,23 @@ void R_Init (void)
gl_particles = Cvar_Get ("gl_particles", "1", CVAR_ARCHIVE,
"whether or not to draw particles");
gl_keeptjunctions = Cvar_Get("gl_keeptjunctions", "0", CVAR_NONE, "None");
gl_fb_models = Cvar_Get ("gl_fb_models", "1", CVAR_ARCHIVE,
"Toggles fullbright color support for models.. "
"This is very handy, but costs me 2 FPS.. (=:]");
gl_keeptjunctions = Cvar_Get("gl_keeptjunctions", "1", CVAR_NONE, "None");
gl_reporttjunctions = Cvar_Get("gl_reporttjunctions", "0", CVAR_NONE, "None");
r_skyname = Cvar_Get("r_skyname", "none", CVAR_NONE,
"name of the current skybox");
gl_skymultipass = Cvar_Get("gl_skymultipass", "1", CVAR_NONE,
"controls wether the skydome is single or double pass");
gl_doubleeyes = Cvar_Get("gl_doubleeys", "1", CVAR_NONE, "None");
R_InitBubble();
R_InitParticles ();
R_InitParticleTexture ();
#ifdef GLTEST
Test_Init ();
#endif
playertextures = texture_extension_number;
texture_extension_number += 16;
}
@ -257,8 +310,6 @@ void R_TranslatePlayerSkin (int playernum)
byte *inrow;
unsigned frac, fracstep;
GL_DisableMultitexture();
top = cl.scores[playernum].colors & 0xf0;
bottom = (cl.scores[playernum].colors &15)<<4;
@ -284,10 +335,10 @@ void R_TranslatePlayerSkin (int playernum)
currententity = &cl_entities[1+playernum];
model = currententity->model;
if (!model)
return; // player doesn't have a model yet
return; // player doesn't have a model yet
if (model->type != mod_alias)
return; // only translate skins on alias models
paliashdr = (aliashdr_t *)Mod_Extradata (model);
s = paliashdr->skinwidth * paliashdr->skinheight;
if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins) {
@ -297,13 +348,13 @@ void R_TranslatePlayerSkin (int playernum)
original = (byte *)paliashdr + paliashdr->texels[currententity->skinnum];
if (s & 3)
Sys_Error ("R_TranslateSkin: s&3");
inwidth = paliashdr->skinwidth;
inheight = paliashdr->skinheight;
// because this happens during gameplay, do it fast
// instead of sending it through gl_upload 8
glBindTexture (GL_TEXTURE_2D, playertextures + playernum);
glBindTexture (GL_TEXTURE_2D, playertextures + playernum);
#if 0
byte translated[320*200];
@ -381,10 +432,8 @@ void R_TranslatePlayerSkin (int playernum)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
#endif
}
/*
===============
R_NewMap
@ -393,6 +442,7 @@ R_NewMap
void R_NewMap (void)
{
int i;
cvar_t *r_skyname;
for (i=0 ; i<256 ; i++)
d_lightstylevalue[i] = 264; // normal light value
@ -423,9 +473,11 @@ void R_NewMap (void)
mirrortexturenum = i;
cl.worldmodel->textures[i]->texturechain = NULL;
}
#ifdef QUAKE2
R_LoadSkys ();
#endif
r_skyname = Cvar_FindVar ("r_skyname");
if (r_skyname != NULL)
R_LoadSkys (r_skyname->string);
else
R_LoadSkys ("none");
}
@ -436,28 +488,34 @@ R_TimeRefresh_f
For program optimization
====================
*/
// LordHavoc: improved appearance and accuracy of timerefresh
void R_TimeRefresh_f (void)
{
int i;
float start, stop, time;
double start, stop, time;
glDrawBuffer (GL_FRONT);
// glDrawBuffer (GL_FRONT);
glFinish ();
GL_EndRendering ();
start = Sys_DoubleTime ();
for (i=0 ; i<128 ; i++)
{
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
r_refdef.viewangles[1] = i/128.0*360.0;
R_RenderView ();
glFinish ();
GL_EndRendering ();
}
glFinish ();
// glFinish ();
stop = Sys_DoubleTime ();
time = stop-start;
Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
glDrawBuffer (GL_BACK);
GL_EndRendering ();
// glDrawBuffer (GL_BACK);
// GL_EndRendering ();
GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
}
void D_FlushCaches (void)

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*
gl_warp.c
@description@
sky and water polygons
Copyright (C) 1996-1997 Id Software, Inc.
@ -30,20 +30,38 @@
# include "config.h"
#endif
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include "qtypes.h"
#include "console.h"
#include "model.h"
#include "quakefs.h"
#include "glquake.h"
#include "sys.h"
#include "host.h"
extern double realtime;
extern model_t *loadmodel;
int skytexturenum;
extern int skytexturenum;
extern qboolean lighthalf;
int solidskytexture;
int alphaskytexture;
float speedscale; // for top sky and bottom sky
int solidskytexture;
int alphaskytexture;
float speedscale; // for top sky and bottom sky
// Set to true if a valid skybox is loaded --KB
qboolean skyloaded = false;
msurface_t *warpface;
extern cvar_t *gl_subdivide_size;
void BoundPoly (int numverts, float *verts, vec3_t mins, vec3_t maxs)
{
int i, j;
@ -190,7 +208,7 @@ void GL_SubdivideSurface (msurface_t *fa)
// speed up sin calculations - Ed
float turbsin[] =
{
#include "gl_warp_sin.h"
# include "gl_warp_sin.h"
};
#define TURBSCALE (256.0 / (2 * M_PI))
@ -207,7 +225,7 @@ void EmitWaterPolys (msurface_t *fa)
float *v;
int i;
float s, t, os, ot;
vec3_t nv;
for (p=fa->polys ; p ; p=p->next)
{
@ -224,116 +242,20 @@ void EmitWaterPolys (msurface_t *fa)
t *= (1.0/64);
glTexCoord2f (s, t);
glVertex3fv (v);
VectorCopy (v, nv);
nv[2] += r_waterripple->value
* turbsin[(int)((v[3]*0.125+realtime) * TURBSCALE) & 255]
* turbsin[(int)((v[4]*0.125+realtime) * TURBSCALE) & 255]
* (1.0 / 64.0);
glVertex3fv (nv);
}
glEnd ();
}
}
/*
=============
EmitSkyPolys
=============
*/
void EmitSkyPolys (msurface_t *fa)
{
glpoly_t *p;
float *v;
int i;
float s, t;
vec3_t dir;
float length;
for (p=fa->polys ; p ; p=p->next)
{
glBegin (GL_POLYGON);
for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
{
VectorSubtract (v, r_origin, dir);
dir[2] *= 3; // flatten the sphere
length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
length = sqrt (length);
length = 6*63/length;
dir[0] *= length;
dir[1] *= length;
s = (speedscale + dir[0]) * (1.0/128);
t = (speedscale + dir[1]) * (1.0/128);
glTexCoord2f (s, t);
glVertex3fv (v);
}
glEnd ();
}
}
/*
===============
EmitBothSkyLayers
Does a sky warp on the pre-fragmented glpoly_t chain
This will be called for brushmodels, the world
will have them chained together.
===============
*/
void EmitBothSkyLayers (msurface_t *fa)
{
GL_DisableMultitexture();
glBindTexture (GL_TEXTURE_2D, solidskytexture);
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127 ;
EmitSkyPolys (fa);
glEnable (GL_BLEND);
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127 ;
EmitSkyPolys (fa);
glDisable (GL_BLEND);
}
#ifndef QUAKE2
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
msurface_t *fa;
GL_DisableMultitexture();
// used when gl_texsort is on
glBindTexture (GL_TEXTURE_2D, solidskytexture);
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127 ;
for (fa=s ; fa ; fa=fa->texturechain)
EmitSkyPolys (fa);
glEnable (GL_BLEND);
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127 ;
for (fa=s ; fa ; fa=fa->texturechain)
EmitSkyPolys (fa);
glDisable (GL_BLEND);
}
#endif
/*
=================================================================
@ -342,107 +264,8 @@ void R_DrawSkyChain (msurface_t *s)
=================================================================
*/
#ifdef QUAKE2
#define SKY_TEX 2000
/*
=================================================================
PCX Loading
=================================================================
*/
typedef struct
{
char manufacturer;
char version;
char encoding;
char bits_per_pixel;
unsigned short xmin,ymin,xmax,ymax;
unsigned short hres,vres;
unsigned char palette[48];
char reserved;
char color_planes;
unsigned short bytes_per_line;
unsigned short palette_type;
char filler[58];
unsigned data; // unbounded
} pcx_t;
byte *pcx_rgb;
/*
============
LoadPCX
============
*/
void LoadPCX (FILE *f)
{
pcx_t *pcx, pcxbuf;
byte palette[768];
byte *pix;
int x, y;
int dataByte, runLength;
int count;
//
// parse the PCX file
//
fread (&pcxbuf, 1, sizeof(pcxbuf), f);
pcx = &pcxbuf;
if (pcx->manufacturer != 0x0a
|| pcx->version != 5
|| pcx->encoding != 1
|| pcx->bits_per_pixel != 8
|| pcx->xmax >= 320
|| pcx->ymax >= 256)
{
Con_Printf ("Bad pcx file\n");
return;
}
// seek to palette
fseek (f, -768, SEEK_END);
fread (palette, 1, 768, f);
fseek (f, sizeof(pcxbuf) - 4, SEEK_SET);
count = (pcx->xmax+1) * (pcx->ymax+1);
pcx_rgb = malloc( count * 4);
for (y=0 ; y<=pcx->ymax ; y++)
{
pix = pcx_rgb + 4*y*(pcx->xmax+1);
for (x=0 ; x<=pcx->ymax ; )
{
dataByte = fgetc(f);
if((dataByte & 0xC0) == 0xC0)
{
runLength = dataByte & 0x3F;
dataByte = fgetc(f);
}
else
runLength = 1;
while(runLength-- > 0)
{
pix[0] = palette[dataByte*3];
pix[1] = palette[dataByte*3+1];
pix[2] = palette[dataByte*3+2];
pix[3] = 255;
pix += 4;
x++;
}
}
}
}
/*
=========================================================
@ -496,6 +319,7 @@ void LoadTGA (FILE *fin)
int columns, rows, numPixels;
byte *pixbuf;
int row, column;
unsigned char red = 0, green = 0, blue = 0, alphabyte = 0;
targa_header.id_length = fgetc(fin);
targa_header.colormap_type = fgetc(fin);
@ -532,7 +356,6 @@ void LoadTGA (FILE *fin)
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; column++) {
unsigned char red,green,blue,alphabyte;
switch (targa_header.pixel_size) {
case 24:
@ -559,7 +382,7 @@ void LoadTGA (FILE *fin)
}
}
else if (targa_header.image_type==10) { // Runlength encoded RGB images
unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
unsigned char packetHeader, packetSize, j;
for(row=rows-1; row>=0; row--) {
pixbuf = targa_rgba + row*columns*4;
for(column=0; column<columns; ) {
@ -645,388 +468,241 @@ R_LoadSkys
==================
*/
char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"};
void R_LoadSkys (void)
void R_LoadSkys (char * skyname)
{
int i;
FILE *f;
char name[64];
if (stricmp (skyname, "none") == 0)
{
skyloaded = false;
return;
}
skyloaded = true;
for (i=0 ; i<6 ; i++)
{
glBindTexture (GL_TEXTURE_2D, SKY_TEX + i);
sprintf (name, "gfx/env/bkgtst%s.tga", suf[i]);
snprintf (name, sizeof(name),"env/%s%s.tga", skyname, suf[i]);
COM_FOpenFile (name, &f);
if (!f)
{
Con_Printf ("Couldn't load %s\n", name);
Con_DPrintf ("Couldn't load %s\n", name);
skyloaded = false;
continue;
}
LoadTGA (f);
// LoadPCX (f);
glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, targa_rgba);
// glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, pcx_rgb);
free (targa_rgba);
// free (pcx_rgb);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (!skyloaded)
Con_Printf ("Unable to load skybox %s, using normal sky\n",
skyname);
}
vec3_t skyclip[6] = {
{1,1,0},
{1,-1,0},
{0,-1,1},
{0,1,1},
{1,0,1},
{-1,0,1}
};
int c_sky;
// 1 = s, 2 = t, 3 = 2048
int st_to_vec[6][3] =
void
R_SkyBoxPolyVec(vec5_t v)
{
{3,-1,2},
{-3,1,2},
{1,3,2},
{-1,-3,2},
{-2,-1,3}, // 0 degrees yaw, look straight up
{2,-1,-3} // look straight down
// {-1,2,3},
// {1,2,-3}
};
// s = [0]/[2], t = [1]/[2]
int vec_to_st[6][3] =
{
{-2,3,1},
{2,3,-1},
{1,3,2},
{-1,3,-2},
{-2,-1,3},
{-2,1,-3}
// {-1,2,3},
// {1,2,-3}
};
float skymins[2][6], skymaxs[2][6];
void DrawSkyPolygon (int nump, vec3_t vecs)
{
int i,j;
vec3_t v, av;
float s, t, dv;
int axis;
float *vp;
c_sky++;
#if 0
glBegin (GL_POLYGON);
for (i=0 ; i<nump ; i++, vecs+=3)
{
VectorAdd(vecs, r_origin, v);
glVertex3fv (v);
// avoid interpolation seams
// s = s * (254.0/256.0) + (1.0/256.0);
// t = t * (254.0/256.0) + (1.0/256.0);
glTexCoord2fv (v);
glVertex3f (r_refdef.vieworg[0] + v[2],
r_refdef.vieworg[1] + v[3],
r_refdef.vieworg[2] + v[4]);
}
glEnd();
return;
#endif
// decide which face it maps to
VectorCopy (vec3_origin, v);
for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
#define ftc(x) (x * (254.0/256.0) + (1.0/256.0))
vec5_t skyvec[6][4] = {
{
VectorAdd (vp, v, v);
}
av[0] = fabs(v[0]);
av[1] = fabs(v[1]);
av[2] = fabs(v[2]);
if (av[0] > av[1] && av[0] > av[2])
// right
{ftc(1), ftc(0), 1024, 1024, 1024},
{ftc(1), ftc(1), 1024, 1024, -1024},
{ftc(0), ftc(1), -1024, 1024, -1024},
{ftc(0), ftc(0), -1024, 1024, 1024}
},
{
if (v[0] < 0)
axis = 1;
else
axis = 0;
}
else if (av[1] > av[2] && av[1] > av[0])
// back
{ftc(1), ftc(0), -1024, 1024, 1024},
{ftc(1), ftc(1), -1024, 1024, -1024},
{ftc(0), ftc(1), -1024, -1024, -1024},
{ftc(0), ftc(0), -1024, -1024, 1024}
},
{
if (v[1] < 0)
axis = 3;
else
axis = 2;
// left
{ftc(1), ftc(0), -1024, -1024, 1024},
{ftc(1), ftc(1), -1024, -1024, -1024},
{ftc(0), ftc(1), 1024, -1024, -1024},
{ftc(0), ftc(0), 1024, -1024, 1024}
},
{
// front
{ftc(1), ftc(0), 1024, -1024, 1024},
{ftc(1), ftc(1), 1024, -1024, -1024},
{ftc(0), ftc(1), 1024, 1024, -1024},
{ftc(0), ftc(0), 1024, 1024, 1024}
},
{
// up
{ftc(1), ftc(0), 1024, -1024, 1024},
{ftc(1), ftc(1), 1024, 1024, 1024},
{ftc(0), ftc(1), -1024, 1024, 1024},
{ftc(0), ftc(0), -1024, -1024, 1024}
},
{
// down
{ftc(1), ftc(0), 1024, 1024, -1024},
{ftc(1), ftc(1), 1024, -1024, -1024},
{ftc(0), ftc(1), -1024, -1024, -1024},
{ftc(0), ftc(0), -1024, 1024, -1024}
}
};
#undef ftc
void
R_DrawSkyBox (void)
{
int i, j;
glEnable (GL_DEPTH_TEST);
glDepthFunc (GL_ALWAYS);
// glDisable (GL_BLEND);
// glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glDepthRange (gldepthmax, gldepthmax);
if (lighthalf)
glColor3f(0.5,0.5,0.5);
else
glColor3f(1,1,1);
for (i = 0; i < 6; i++)
{
if (v[2] < 0)
axis = 5;
else
axis = 4;
glBindTexture(GL_TEXTURE_2D, SKY_TEX + i);
glBegin(GL_QUADS);
for (j = 0; j < 4; j++)
R_SkyBoxPolyVec(skyvec[i][j]);
glEnd();
}
// project new texture coords
for (i=0 ; i<nump ; i++, vecs+=3)
{
j = vec_to_st[axis][2];
if (j > 0)
dv = vecs[j - 1];
else
dv = -vecs[-j - 1];
j = vec_to_st[axis][0];
if (j < 0)
s = -vecs[-j -1] / dv;
else
s = vecs[j-1] / dv;
j = vec_to_st[axis][1];
if (j < 0)
t = -vecs[-j -1] / dv;
else
t = vecs[j-1] / dv;
if (s < skymins[0][axis])
skymins[0][axis] = s;
if (t < skymins[1][axis])
skymins[1][axis] = t;
if (s > skymaxs[0][axis])
skymaxs[0][axis] = s;
if (t > skymaxs[1][axis])
skymaxs[1][axis] = t;
}
}
#define MAX_CLIP_VERTS 64
void ClipSkyPolygon (int nump, vec3_t vecs, int stage)
{
float *norm;
float *v;
qboolean front, back;
float d, e;
float dists[MAX_CLIP_VERTS];
int sides[MAX_CLIP_VERTS];
vec3_t newv[2][MAX_CLIP_VERTS];
int newc[2];
int i, j;
if (nump > MAX_CLIP_VERTS-2)
Sys_Error ("ClipSkyPolygon: MAX_CLIP_VERTS");
if (stage == 6)
{ // fully clipped, so draw it
DrawSkyPolygon (nump, vecs);
return;
}
front = back = false;
norm = skyclip[stage];
for (i=0, v = vecs ; i<nump ; i++, v+=3)
{
d = DotProduct (v, norm);
if (d > ON_EPSILON)
{
front = true;
sides[i] = SIDE_FRONT;
}
else if (d < ON_EPSILON)
{
back = true;
sides[i] = SIDE_BACK;
}
else
sides[i] = SIDE_ON;
dists[i] = d;
}
if (!front || !back)
{ // not clipped
ClipSkyPolygon (nump, vecs, stage+1);
return;
}
// clip it
sides[i] = sides[0];
dists[i] = dists[0];
VectorCopy (vecs, (vecs+(i*3)) );
newc[0] = newc[1] = 0;
for (i=0, v = vecs ; i<nump ; i++, v+=3)
{
switch (sides[i])
{
case SIDE_FRONT:
VectorCopy (v, newv[0][newc[0]]);
newc[0]++;
break;
case SIDE_BACK:
VectorCopy (v, newv[1][newc[1]]);
newc[1]++;
break;
case SIDE_ON:
VectorCopy (v, newv[0][newc[0]]);
newc[0]++;
VectorCopy (v, newv[1][newc[1]]);
newc[1]++;
break;
}
if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
d = dists[i] / (dists[i] - dists[i+1]);
for (j=0 ; j<3 ; j++)
{
e = v[j] + d*(v[j+3] - v[j]);
newv[0][newc[0]][j] = e;
newv[1][newc[1]][j] = e;
}
newc[0]++;
newc[1]++;
}
// continue
ClipSkyPolygon (newc[0], newv[0][0], stage+1);
ClipSkyPolygon (newc[1], newv[1][0], stage+1);
}
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
msurface_t *fa;
int i;
vec3_t verts[MAX_CLIP_VERTS];
glpoly_t *p;
c_sky = 0;
glBindTexture (GL_TEXTURE_2D, solidskytexture);
// calculate vertex values for sky box
for (fa=s ; fa ; fa=fa->texturechain)
{
for (p=fa->polys ; p ; p=p->next)
{
for (i=0 ; i<p->numverts ; i++)
{
VectorSubtract (p->verts[i], r_origin, verts[i]);
}
ClipSkyPolygon (p->numverts, verts[0], 0);
}
}
glColor3f (1,1,1);
glDepthFunc (GL_LEQUAL);
glEnable (GL_DEPTH_TEST);
glDepthRange(gldepthmin, gldepthmax);
}
/*
==============
R_ClearSkyBox
==============
*/
void R_ClearSkyBox (void)
vec3_t domescale;
void
R_DrawSkyLayer (float s)
{
int i;
for (i=0 ; i<6 ; i++)
int a, b;
float x, y, a1x, a1y, a2x, a2y;
vec3_t v;
for (a = 0; a < 16; a++)
{
skymins[0][i] = skymins[1][i] = 9999;
skymaxs[0][i] = skymaxs[1][i] = -9999;
}
}
a1x = bubble_costable[a*2];
a1y = -bubble_sintable[a*2];
a2x = bubble_costable[(a+1)*2];
a2y = -bubble_sintable[(a+1)*2];
glBegin (GL_TRIANGLE_STRIP);
glTexCoord2f(0.5 + s * (1.0 / 128.0), 0.5 + s * (1.0 / 128.0));
glVertex3f(r_refdef.vieworg[0],
r_refdef.vieworg[1],
r_refdef.vieworg[2]+domescale[2]);
for (b = 1; b < 8; b++)
{
x = bubble_costable[b*2+16];
y = -bubble_sintable[b*2+16];
void MakeSkyVec (float s, float t, int axis)
{
vec3_t v, b;
int j, k;
v[0] = a1x*x * domescale[0];
v[1] = a1y*x * domescale[1];
v[2] = y * domescale[2];
glTexCoord2f((v[0] + s) * (1.0 / 128.0),
(v[1] + s) * (1.0 / 128.0));
glVertex3f(v[0] + r_refdef.vieworg[0],
v[1] + r_refdef.vieworg[1],
v[2] + r_refdef.vieworg[2]);
b[0] = s*2048;
b[1] = t*2048;
b[2] = 2048;
for (j=0 ; j<3 ; j++)
{
k = st_to_vec[axis][j];
if (k < 0)
v[j] = -b[-k - 1];
else
v[j] = b[k - 1];
v[j] += r_origin[j];
}
// avoid bilerp seam
s = (s+1)*0.5;
t = (t+1)*0.5;
if (s < 1.0/512)
s = 1.0/512;
else if (s > 511.0/512)
s = 511.0/512;
if (t < 1.0/512)
t = 1.0/512;
else if (t > 511.0/512)
t = 511.0/512;
t = 1.0 - t;
glTexCoord2f (s, t);
glVertex3fv (v);
}
/*
==============
R_DrawSkyBox
==============
*/
int skytexorder[6] = {0,2,1,3,4,5};
void R_DrawSkyBox (void)
{
int i, j, k;
vec3_t v;
float s, t;
#if 0
glEnable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glColor4f (1,1,1,0.5);
glDisable (GL_DEPTH_TEST);
#endif
for (i=0 ; i<6 ; i++)
{
if (skymins[0][i] >= skymaxs[0][i]
|| skymins[1][i] >= skymaxs[1][i])
continue;
glBindTexture (GL_TEXTURE_2D, SKY_TEX+skytexorder[i]);
#if 0
skymins[0][i] = -1;
skymins[1][i] = -1;
skymaxs[0][i] = 1;
skymaxs[1][i] = 1;
#endif
glBegin (GL_QUADS);
MakeSkyVec (skymins[0][i], skymins[1][i], i);
MakeSkyVec (skymins[0][i], skymaxs[1][i], i);
MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i);
MakeSkyVec (skymaxs[0][i], skymins[1][i], i);
v[0] = a2x*x * domescale[0];
v[1] = a2y*x * domescale[1];
v[2] = y * domescale[2];
glTexCoord2f((v[0] + s) * (1.0 / 128.0),
(v[1] + s) * (1.0 / 128.0));
glVertex3f(v[0] + r_refdef.vieworg[0],
v[1] + r_refdef.vieworg[1],
v[2] + r_refdef.vieworg[2]);
}
glTexCoord2f(0.5 + s * (1.0 / 128.0), 0.5 + s * (1.0 / 128.0));
glVertex3f(r_refdef.vieworg[0],
r_refdef.vieworg[1],
r_refdef.vieworg[2]-domescale[2]);
glEnd ();
}
#if 0
glDisable (GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4f (1,1,1,0.5);
glEnable (GL_DEPTH_TEST);
#endif
}
#endif
void
R_DrawSkyDome (void)
{
glEnable (GL_DEPTH_TEST);
glDepthFunc (GL_ALWAYS);
// glDisable (GL_BLEND);
// glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthRange (gldepthmax, gldepthmax);
glDisable (GL_BLEND);
if (lighthalf)
glColor3f(0.5,0.5,0.5);
else
glColor3f(1,1,1);
// base sky
glBindTexture (GL_TEXTURE_2D, solidskytexture);
domescale[0] = 512;
domescale[1] = 512;
domescale[2] = 128;
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127;
R_DrawSkyLayer (speedscale);
glEnable (GL_BLEND);
// clouds
if (gl_skymultipass->value) {
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
domescale[0] = 512;
domescale[1] = 512;
domescale[2] = 128;
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127;
R_DrawSkyLayer (speedscale);
}
// glDisable (GL_BLEND);
glColor3f (1,1,1);
glDepthFunc (GL_LEQUAL);
glEnable (GL_DEPTH_TEST);
glDepthRange (gldepthmin, gldepthmax);
}
void
R_DrawSky ( void )
{
if (skyloaded)
R_DrawSkyBox();
else
R_DrawSkyDome();
}
//===============================================================
@ -1095,3 +771,96 @@ void R_InitSky (texture_t *mt)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
/*
=============
EmitSkyPolys
=============
*/
void EmitSkyPolys (msurface_t *fa)
{
glpoly_t *p;
float *v;
int i;
float s, t;
vec3_t dir;
float length;
for (p=fa->polys ; p ; p=p->next)
{
glBegin (GL_POLYGON);
for (i=0,v=p->verts[0] ; i<p->numverts ; i++, v+=VERTEXSIZE)
{
VectorSubtract (v, r_origin, dir);
dir[2] *= 3; // flatten the sphere
length = dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2];
length = sqrt (length);
length = 6*63/length;
dir[0] *= length;
dir[1] *= length;
s = (speedscale + dir[0]) * (1.0/128);
t = (speedscale + dir[1]) * (1.0/128);
glTexCoord2f (s, t);
glVertex3fv (v);
}
glEnd ();
}
}
/*
=================
R_DrawSkyChain
=================
*/
void R_DrawSkyChain (msurface_t *s)
{
msurface_t *fa;
// used when gl_texsort is on
glBindTexture (GL_TEXTURE_2D, solidskytexture);
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127 ;
for (fa=s ; fa ; fa=fa->texturechain)
EmitSkyPolys (fa);
glEnable (GL_BLEND);
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127 ;
for (fa=s ; fa ; fa=fa->texturechain)
EmitSkyPolys (fa);
glDisable (GL_BLEND);
}
/*
===============
EmitBothSkyLayers
Does a sky warp on the pre-fragmented glpoly_t chain
This will be called for brushmodels, the world
will have them chained together.
===============
*/
void EmitBothSkyLayers (msurface_t *fa)
{
glBindTexture (GL_TEXTURE_2D, solidskytexture);
speedscale = realtime*8;
speedscale -= (int)speedscale & ~127 ;
EmitSkyPolys (fa);
glEnable (GL_BLEND);
glBindTexture (GL_TEXTURE_2D, alphaskytexture);
speedscale = realtime*16;
speedscale -= (int)speedscale & ~127 ;
EmitSkyPolys (fa);
glDisable (GL_BLEND);
}

View file

@ -705,7 +705,7 @@ void VID_Init(unsigned char *palette)
snprintf(gldir, sizeof(gldir), "%s/glquake", com_gamedir);
Sys_mkdir (gldir);
//XXXGL_CheckGamma (palette);
GL_CheckGamma (palette);
VID_SetPalette (palette);
// Check for 3DFX Extensions and initialize them.