diff --git a/include/glquake.h b/include/glquake.h index 17b2265..bc7d408 100644 --- a/include/glquake.h +++ b/include/glquake.h @@ -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 { diff --git a/source/gl_draw.c b/source/gl_draw.c index 65546ed..7768a80 100644 --- a/source/gl_draw.c +++ b/source/gl_draw.c @@ -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; -} - diff --git a/source/gl_rmain.c b/source/gl_rmain.c index b2955d9..2eac6f6 100644 --- a/source/gl_rmain.c +++ b/source/gl_rmain.c @@ -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 +#include +#include +#include + +#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 ; imodel->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 ; imodel->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 ; imodel->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 ; lnumradius) - 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 (); } diff --git a/source/gl_rmisc.c b/source/gl_rmisc.c index 56c26c8..0000e25 100644 --- a/source/gl_rmisc.c +++ b/source/gl_rmisc.c @@ -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 +#include +#ifdef HAVE_STRINGS_H +#include +#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 : 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) diff --git a/source/gl_rsurf.c b/source/gl_rsurf.c index 5a14e8e..7f73256 100644 --- a/source/gl_rsurf.c +++ b/source/gl_rsurf.c @@ -1,9 +1,10 @@ /* gl_rsurf.c - @description@ + surface-related refresh code Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2000 Joseph Carter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -30,31 +31,48 @@ # include "config.h" #endif -#include "glquake.h" -#include "qargs.h" -#include "qdefs.h" -#include "host.h" -#include "r_local.h" -#include "client.h" -#include "sys.h" +#include +#include +#include +#include "compat.h" +#include "r_local.h" +#include "qargs.h" +#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" + +extern double realtime; int skytexturenum; -#ifndef GL_RGBA4 -#define GL_RGBA4 0 -#endif - - -int lightmap_bytes; // 1, 2, or 4 +extern vec3_t shadecolor; // Ender (Extend) Colormod +int lightmap_bytes; // 1 or 3 int lightmap_textures; -unsigned blocklights[18*18]; +unsigned blocklights[18*18*3]; + +cvar_t *gl_colorlights; #define BLOCK_WIDTH 128 #define BLOCK_HEIGHT 128 -#define MAX_LIGHTMAPS 64 +// LordHavoc: since lightmaps are now allocated only as needed, allow a ridiculous number :) +#define MAX_LIGHTMAPS 1024 int active_lightmaps; typedef struct glRect_s { @@ -69,16 +87,46 @@ int allocated[MAX_LIGHTMAPS][BLOCK_WIDTH]; // the lightmap texture data needs to be kept in // main memory so texsubimage can update properly -byte lightmaps[4*MAX_LIGHTMAPS*BLOCK_WIDTH*BLOCK_HEIGHT]; +// LordHavoc: changed to be allocated at runtime (typically lower memory usage) +byte *lightmaps[MAX_LIGHTMAPS]; -// For gl_texsort 0 -msurface_t *skychain = NULL; msurface_t *waterchain = NULL; -lpMTexFUNC qglMTexCoord2f = NULL; -lpSelTexFUNC qglSelectTexture = NULL; +extern qboolean lighthalf; -void R_RenderDynamicLightmaps (msurface_t *fa); +// LordHavoc: place for gl_rsurf setup code +void glrsurf_init() +{ + memset(&lightmaps, 0, sizeof(lightmaps)); +} + +void recursivelightupdate(mnode_t *node) +{ + int c; + msurface_t *surf; + if (node->children[0]->contents >= 0) + recursivelightupdate(node->children[0]); + if (node->children[1]->contents >= 0) + recursivelightupdate(node->children[1]); + if ((c = node->numsurfaces)) + for (surf = cl.worldmodel->surfaces + node->firstsurface; c ; c--, surf++) + surf->cached_dlight = true; +} + +// LordHavoc: function to force all lightmaps to be updated +void R_ForceLightUpdate() +{ + if (cl.worldmodel && cl.worldmodel->nodes && cl.worldmodel->nodes->contents >= 0) + recursivelightupdate(cl.worldmodel->nodes); +} + +/* + R_AddDynamicLights + + LordHavoc: completely rewrote this, relies on 64bit integer math... +*/ +int dlightdivtable[8192]; +int dlightdivtableinitialized = 0; /* =============== @@ -87,75 +135,104 @@ R_AddDynamicLights */ void R_AddDynamicLights (msurface_t *surf) { - int lnum; - int sd, td; - float dist, rad, minlight; + int sdtable[18], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, red, green, blue, j; + unsigned *bl; + float dist, f; vec3_t impact, local; - int s, t; - int i; - int smax, tmax; - mtexinfo_t *tex; + // use 64bit integer... shame it's not very standardized... +#if _MSC_VER || __BORLANDC__ + __int64 k; +#else + long long k; +#endif + + if (!dlightdivtableinitialized) + { + dlightdivtable[0] = 1048576 >> 7; + for (s = 1;s < 8192;s++) + dlightdivtable[s] = 1048576 / (s << 7); + dlightdivtableinitialized = 1; + } smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; - tex = surf->texinfo; for (lnum=0 ; lnumdlightbits & (1<plane->normal) - - surf->plane->dist; - rad -= fabs(dist); - minlight = cl_dlights[lnum].minlight; - if (rad < minlight) - continue; - minlight = rad - minlight; - + VectorSubtract(cl_dlights[lnum].origin, currententity->origin, local); + dist = DotProduct (local, surf->plane->normal) - surf->plane->dist; for (i=0 ; i<3 ; i++) - { - impact[i] = cl_dlights[lnum].origin[i] - - surf->plane->normal[i]*dist; + impact[i] = cl_dlights[lnum].origin[i] - surf->plane->normal[i]*dist; + + f = DotProduct (impact, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3] - surf->texturemins[0]; + i = f; + + // reduce calculations + t = dist*dist; + for (s = 0;s < smax;s++, i -= 16) + sdtable[s] = i*i + t; + + f = DotProduct (impact, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3] - surf->texturemins[1]; + i = f; + + maxdist = (int) (cl_dlights[lnum].radius*cl_dlights[lnum].radius); // for comparisons to minimum acceptable light + // clamp radius to avoid exceeding 8192 entry division table + if (maxdist > 1048576) + maxdist = 1048576; + maxdist3 = maxdist - (int) (dist*dist); + // convert to 8.8 blocklights format +// if (!cl_dlights[lnum].dark) +// { + f = cl_dlights[lnum].color[0] * maxdist;red = f; + f = cl_dlights[lnum].color[1] * maxdist;green = f; + f = cl_dlights[lnum].color[2] * maxdist;blue = f; + /* } - - local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3]; - local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3]; - - local[0] -= surf->texturemins[0]; - local[1] -= surf->texturemins[1]; - - for (t = 0 ; t td) - dist = sd + (td>>1); - else - dist = td + (sd>>1); - if (dist < minlight) - blocklights[t*smax + s] += (rad - dist)*256; + maxdist2 = maxdist - td; + for (s = 0;s < smax;s++) + { + if (sdtable[s] < maxdist2) + { + j = dlightdivtable[(sdtable[s]+td) >> 7]; + k = (red * j) >> 7;bl[0] += k; + k = (green * j) >> 7;bl[1] += k; + k = (blue * j) >> 7;bl[2] += k; + } + bl += 3; + } } + 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; @@ -163,6 +240,7 @@ void R_BuildLightMap (msurface_t *surf, byte *dest, int stride) byte *lightmap; unsigned scale; int maps; + float t2; unsigned *bl; surf->cached_dlight = (surf->dlightframe == r_framecount); @@ -172,76 +250,120 @@ 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 ; istyles[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 ; idlightframe == r_framecount) R_AddDynamicLights (surf); -// bound, invert, and shift store: - switch (gl_lightmap_format) + // bound and shift + if (gl_colorlights->value) { - case GL_RGBA: - stride -= (smax<<2); + stride -= smax * 3; bl = blocklights; - for (i=0 ; i>= 7; - if (t > 255) - t = 255; - dest[3] = 255-t; - dest += 4; - } + for (i = 0; i < tmax; i++, dest += stride) + for (j=0 ; j> 8; + *dest++ = bound(0, t, 255); + t = (int) *bl++ >> 8; + *dest++ = bound(0, t, 255); + t = (int) *bl++ >> 8; + *dest++ = bound(0, t, 255); + } } - break; - case GL_ALPHA: - case GL_LUMINANCE: - case GL_INTENSITY: + else + { + for (i = 0; i < tmax; i++, dest += stride) + for (j=0 ; j> 7; + *dest++ = bound(0, t, 255); + t = (int) *bl++ >> 7; + *dest++ = bound(0, t, 255); + t = (int) *bl++ >> 7; + *dest++ = bound(0, t, 255); + } + } + } + else + { + stride -= smax; bl = blocklights; - for (i=0 ; i>= 7; - if (t > 255) - t = 255; - dest[j] = 255-t; - } + for (i = 0; i < tmax; i++, dest += stride) + for (j=0 ; j> 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; + } + } + else + { + for (i = 0; i < tmax; i++, dest += stride) + for (j=0 ; j> 7; + t2 = bound(0, t, 255); + t = (int) *bl++ >> 7; + t2 += bound(0, t, 255); + t = (int) *bl++ >> 7; + t2 += bound(0, t, 255); + t2 *= (1.0/3.0); + *dest++ = t2; + } } - break; - default: - Sys_Error ("Bad lightmap format"); } } - /* =============== R_TextureAnimation @@ -251,7 +373,7 @@ Returns the proper texture for a given time and base texture */ texture_t *R_TextureAnimation (texture_t *base) { - int reletive; + int relative; int count; if (currententity->frame) @@ -263,10 +385,10 @@ texture_t *R_TextureAnimation (texture_t *base) if (!base->anim_total) return base; - reletive = (int)(cl.time*10) % base->anim_total; + relative = (int)(cl.time*10) % base->anim_total; count = 0; - while (base->anim_min > reletive || base->anim_max <= reletive) + while (base->anim_min > relative || base->anim_max <= relative) { base = base->anim_next; if (!base) @@ -292,35 +414,14 @@ extern int solidskytexture; extern int alphaskytexture; extern float speedscale; // for top sky and bottom sky -void DrawGLWaterPoly (glpoly_t *p); -void DrawGLWaterPolyLightmap (glpoly_t *p); +lpMTexFUNC qglMTexCoord2f = NULL; +lpSelTexFUNC qglSelectTexture = NULL; -lpMTexFUNC qglMTexCoord2fSGIS = NULL; -lpSelTexFUNC qglSelectTextureSGIS = NULL; - -qboolean mtexenabled = false; - -void GL_SelectTexture (GLenum target); - -void GL_DisableMultitexture(void) +void GL_UploadLightmap(int i, int x, int y, int w, int h) { - if (mtexenabled) { - glDisable(GL_TEXTURE_2D); - GL_SelectTexture(TEXTURE0_SGIS); - mtexenabled = false; - } + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, BLOCK_WIDTH, h, gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps[i] + (y * BLOCK_WIDTH) * lightmap_bytes); } -void GL_EnableMultitexture(void) -{ - if (gl_mtexable) { - GL_SelectTexture(TEXTURE1_SGIS); - glEnable(GL_TEXTURE_2D); - mtexenabled = true; - } -} - -#if 0 /* ================ R_DrawSequentialPoly @@ -329,351 +430,58 @@ 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) +void R_DrawMultitexturePoly (msurface_t *s) { - glpoly_t *p; + int maps; float *v; int i; - texture_t *t; - // - // normal lightmaped poly - // - if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) ) + c_brush_polys++; + + i = s->lightmaptexturenum; + + glColor3f(1,1,1); + // Binds world to texture env 0 + qglSelectTexture (gl_mtex_enum+0); + glBindTexture (GL_TEXTURE_2D, R_TextureAnimation (s->texinfo->texture)->gl_texturenum); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glEnable(GL_TEXTURE_2D); + // Binds lightmap to texenv 1 + qglSelectTexture (gl_mtex_enum+1); + glBindTexture (GL_TEXTURE_2D, lightmap_textures + i); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glEnable(GL_TEXTURE_2D); + + // check for lightmap modification + if (r_dynamic->value) { - p = s->polys; + for (maps = 0;maps < MAXLIGHTMAPS && s->styles[maps] != 255;maps++) + if (d_lightstylevalue[s->styles[maps]] != s->cached_light[maps]) + goto dynamic; - t = R_TextureAnimation (s->texinfo->texture); - glBindTexture (GL_TEXTURE_2D, t->gl_texturenum); - glBegin (GL_POLYGON); - v = p->verts[0]; - for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) + if (s->dlightframe == r_framecount // dynamic this frame + || s->cached_dlight) // dynamic previously { - glTexCoord2f (v[3], v[4]); - glVertex3fv (v); +dynamic: + R_BuildLightMap (s, lightmaps[s->lightmaptexturenum] + (s->light_t * BLOCK_WIDTH + s->light_s) * lightmap_bytes, BLOCK_WIDTH*lightmap_bytes); + GL_UploadLightmap(i, s->light_s, s->light_t, (s->extents[0]>>4)+1, (s->extents[1]>>4)+1); } - glEnd (); - - glBindTexture (GL_TEXTURE_2D, lightmap_textures + s->lightmaptexturenum); - glEnable (GL_BLEND); - glBegin (GL_POLYGON); - v = p->verts[0]; - for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) - { - glTexCoord2f (v[5], v[6]); - glVertex3fv (v); - } - glEnd (); - - glDisable (GL_BLEND); - - return; } - // - // subdivided water surface warp - // - if (s->flags & SURF_DRAWTURB) + glBegin(GL_POLYGON); + v = s->polys->verts[0]; + for (i=0 ; ipolys->numverts ; i++, v+= VERTEXSIZE) { - glBindTexture (GL_TEXTURE_2D, s->texinfo->texture->gl_texturenum); - EmitWaterPolys (s); - return; - } - - // - // subdivided sky warp - // - if (s->flags & SURF_DRAWSKY) - { - glBindTexture (GL_TEXTURE_2D, solidskytexture); - speedscale = realtime*8; - speedscale -= (int)speedscale; - - EmitSkyPolys (s); - - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture (GL_TEXTURE_2D, alphaskytexture); - speedscale = realtime*16; - speedscale -= (int)speedscale; - EmitSkyPolys (s); - if (gl_lightmap_format == GL_LUMINANCE) - glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR); - - glDisable (GL_BLEND); - } - - // - // underwater warped with lightmap - // - p = s->polys; - - t = R_TextureAnimation (s->texinfo->texture); - glBindTexture (GL_TEXTURE_2D, t->gl_texturenum); - DrawGLWaterPoly (p); - - glBindTexture (GL_TEXTURE_2D, lightmap_textures + s->lightmaptexturenum); - glEnable (GL_BLEND); - DrawGLWaterPolyLightmap (p); - glDisable (GL_BLEND); -} -#else -/* -================ -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; - vec3_t nv; - glRect_t *theRect; - - // - // normal lightmaped poly - // - - if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) ) - { - R_RenderDynamicLightmaps (s); - if (gl_mtexable) { - p = s->polys; - - t = R_TextureAnimation (s->texinfo->texture); - // Binds world to texture env 0 - GL_SelectTexture(TEXTURE0_SGIS); - glBindTexture (GL_TEXTURE_2D, t->gl_texturenum); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - // Binds lightmap to texenv 1 - GL_EnableMultitexture(); // Same as SelectTexture (TEXTURE1) - glBindTexture (GL_TEXTURE_2D, lightmap_textures + s->lightmaptexturenum); - i = s->lightmaptexturenum; - if (lightmap_modified[i]) - { - lightmap_modified[i] = false; - theRect = &lightmap_rectchange[i]; - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE, - lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes); - theRect->l = BLOCK_WIDTH; - theRect->t = BLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; - } - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); - glBegin(GL_POLYGON); - v = p->verts[0]; - for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) - { - qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]); - qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]); - glVertex3fv (v); - } - glEnd (); - return; - } else { - p = s->polys; - - t = R_TextureAnimation (s->texinfo->texture); - glBindTexture (GL_TEXTURE_2D, t->gl_texturenum); - glBegin (GL_POLYGON); - v = p->verts[0]; - for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) - { - glTexCoord2f (v[3], v[4]); - glVertex3fv (v); - } - glEnd (); - - glBindTexture (GL_TEXTURE_2D, lightmap_textures + s->lightmaptexturenum); - glEnable (GL_BLEND); - glBegin (GL_POLYGON); - v = p->verts[0]; - for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) - { - glTexCoord2f (v[5], v[6]); - glVertex3fv (v); - } - glEnd (); - - glDisable (GL_BLEND); - } - - return; - } - - // - // subdivided water surface warp - // - - if (s->flags & SURF_DRAWTURB) - { - GL_DisableMultitexture(); - glBindTexture (GL_TEXTURE_2D, s->texinfo->texture->gl_texturenum); - EmitWaterPolys (s); - return; - } - - // - // subdivided sky warp - // - if (s->flags & SURF_DRAWSKY) - { - GL_DisableMultitexture(); - glBindTexture (GL_TEXTURE_2D, solidskytexture); - speedscale = realtime*8; - speedscale -= (int)speedscale & ~127; - - EmitSkyPolys (s); - - glEnable (GL_BLEND); - glBindTexture (GL_TEXTURE_2D, alphaskytexture); - speedscale = realtime*16; - speedscale -= (int)speedscale & ~127; - EmitSkyPolys (s); - - glDisable (GL_BLEND); - return; - } - - // - // underwater warped with lightmap - // - R_RenderDynamicLightmaps (s); - if (gl_mtexable) { - p = s->polys; - - t = R_TextureAnimation (s->texinfo->texture); - GL_SelectTexture(TEXTURE0_SGIS); - glBindTexture (GL_TEXTURE_2D, t->gl_texturenum); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - GL_EnableMultitexture(); - glBindTexture (GL_TEXTURE_2D, lightmap_textures + s->lightmaptexturenum); - i = s->lightmaptexturenum; - if (lightmap_modified[i]) - { - lightmap_modified[i] = false; - theRect = &lightmap_rectchange[i]; - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE, - lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes); - theRect->l = BLOCK_WIDTH; - theRect->t = BLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; - } - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); - glBegin (GL_TRIANGLE_FAN); - v = p->verts[0]; - for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) - { - qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]); - qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]); - - nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime); - nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime); - nv[2] = v[2]; - - glVertex3fv (nv); - } - glEnd (); - - } else { - p = s->polys; - - t = R_TextureAnimation (s->texinfo->texture); - glBindTexture (GL_TEXTURE_2D, t->gl_texturenum); - DrawGLWaterPoly (p); - - glBindTexture (GL_TEXTURE_2D, lightmap_textures + s->lightmaptexturenum); - glEnable (GL_BLEND); - DrawGLWaterPolyLightmap (p); - glDisable (GL_BLEND); - } -} -#endif - - -/* -================ -DrawGLWaterPoly - -Warp the vertex coordinates -================ -*/ -void DrawGLWaterPoly (glpoly_t *p) -{ - int i; - float *v; - vec3_t nv; - - GL_DisableMultitexture(); - - glBegin (GL_TRIANGLE_FAN); - v = p->verts[0]; - for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) - { - glTexCoord2f (v[3], v[4]); - - nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime); - nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime); - nv[2] = v[2]; - - glVertex3fv (nv); - } - glEnd (); -} - -void DrawGLWaterPolyLightmap (glpoly_t *p) -{ - int i; - float *v; - vec3_t nv; - - GL_DisableMultitexture(); - - glBegin (GL_TRIANGLE_FAN); - v = p->verts[0]; - for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) - { - glTexCoord2f (v[5], v[6]); - - nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime); - nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime); - nv[2] = v[2]; - - glVertex3fv (nv); - } - glEnd (); -} - -/* -================ -DrawGLPoly -================ -*/ -void DrawGLPoly (glpoly_t *p) -{ - int i; - float *v; - - glBegin (GL_POLYGON); - v = p->verts[0]; - for (i=0 ; inumverts ; i++, v+= VERTEXSIZE) - { - glTexCoord2f (v[3], v[4]); + qglMTexCoord2f (gl_mtex_enum + 0, v[3], v[4]); + qglMTexCoord2f (gl_mtex_enum + 1, v[5], v[6]); glVertex3fv (v); } glEnd (); + glDisable(GL_TEXTURE_2D); + qglSelectTexture (gl_mtex_enum+0); + glEnable(GL_TEXTURE_2D); } - /* ================ R_BlendLightmaps @@ -684,28 +492,12 @@ void R_BlendLightmaps (void) int i, j; glpoly_t *p; float *v; - glRect_t *theRect; - - if (r_fullbright->value) - return; - if (!gl_texsort->value) - return; glDepthMask (0); // don't bother writing Z - if (gl_lightmap_format == GL_LUMINANCE) - glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR); - else if (gl_lightmap_format == GL_INTENSITY) - { - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glColor4f (0,0,0,1); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - if (!r_lightmap->value) - { - glEnable (GL_BLEND); - } + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBlendFunc (GL_ZERO, GL_SRC_COLOR); + glEnable(GL_BLEND); for (i=0 ; ih, 0, -// gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+(i*BLOCK_HEIGHT+theRect->t)*BLOCK_WIDTH*lightmap_bytes); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t, - BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE, - lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes); - theRect->l = BLOCK_WIDTH; - theRect->t = BLOCK_HEIGHT; - theRect->h = 0; - theRect->w = 0; } - for ( ; p ; p=p->chain) + for (;p;p = p->chain) { - if (p->flags & SURF_UNDERWATER) - DrawGLWaterPolyLightmap (p); - else + glBegin (GL_POLYGON); + v = p->verts[0]; + for (j=0 ; jnumverts ; j++, v+= VERTEXSIZE) { - glBegin (GL_POLYGON); - v = p->verts[0]; - for (j=0 ; jnumverts ; j++, v+= VERTEXSIZE) - { - glTexCoord2f (v[5], v[6]); - glVertex3fv (v); - } - glEnd (); + glTexCoord2fv (&v[5]); + glVertex3fv (v); } + glEnd (); } } - glDisable (GL_BLEND); - if (gl_lightmap_format == GL_LUMINANCE) - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - else if (gl_lightmap_format == GL_INTENSITY) - { - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glColor4f (1,1,1,1); - } + // Return to normal blending --KB + glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask (1); // back to normal Z buffering } @@ -768,33 +536,25 @@ R_RenderBrushPoly */ void R_RenderBrushPoly (msurface_t *fa) { - texture_t *t; byte *base; int maps; - glRect_t *theRect; - int smax, tmax; + glRect_t *theRect; + int i; + float *v; + int smax, tmax; c_brush_polys++; - if (fa->flags & SURF_DRAWSKY) - { // warp texture, no lightmaps - EmitBothSkyLayers (fa); - return; - } - - t = R_TextureAnimation (fa->texinfo->texture); - glBindTexture (GL_TEXTURE_2D, t->gl_texturenum); + glBindTexture (GL_TEXTURE_2D, R_TextureAnimation (fa->texinfo->texture)->gl_texturenum); - if (fa->flags & SURF_DRAWTURB) - { // warp texture, no lightmaps - EmitWaterPolys (fa); - return; + glBegin (GL_POLYGON); + v = fa->polys->verts[0]; + for (i = 0;i < fa->polys->numverts;i++, v += VERTEXSIZE) + { + glTexCoord2fv (&v[3]); + glVertex3fv (v); } - - if (fa->flags & SURF_UNDERWATER) - DrawGLWaterPoly (fa->polys); - else - DrawGLPoly (fa->polys); + glEnd (); // add the poly to the proper lightmap chain @@ -831,135 +591,30 @@ dynamic: theRect->w = (fa->light_s-theRect->l)+smax; if ((theRect->h + theRect->t) < (fa->light_t + tmax)) theRect->h = (fa->light_t-theRect->t)+tmax; - base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT; - base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; + base = lightmaps[fa->lightmaptexturenum] + (fa->light_t * BLOCK_WIDTH + fa->light_s) * lightmap_bytes; R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes); } } } -/* -================ -R_RenderDynamicLightmaps -Multitexture -================ -*/ -void R_RenderDynamicLightmaps (msurface_t *fa) +void GL_WaterSurface(msurface_t *s) { - byte *base; - int maps; - glRect_t *theRect; - int smax, tmax; - - c_brush_polys++; - - if (fa->flags & ( SURF_DRAWSKY | SURF_DRAWTURB) ) - return; - - fa->polys->chain = lightmap_polys[fa->lightmaptexturenum]; - lightmap_polys[fa->lightmaptexturenum] = fa->polys; - - // check for lightmap modification - for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ; - maps++) - if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps]) - goto dynamic; - - if (fa->dlightframe == r_framecount // dynamic this frame - || fa->cached_dlight) // dynamic previously - { -dynamic: - if (r_dynamic->value) - { - lightmap_modified[fa->lightmaptexturenum] = true; - theRect = &lightmap_rectchange[fa->lightmaptexturenum]; - if (fa->light_t < theRect->t) { - if (theRect->h) - theRect->h += theRect->t - fa->light_t; - theRect->t = fa->light_t; - } - if (fa->light_s < theRect->l) { - if (theRect->w) - theRect->w += theRect->l - fa->light_s; - theRect->l = fa->light_s; - } - smax = (fa->extents[0]>>4)+1; - tmax = (fa->extents[1]>>4)+1; - if ((theRect->w + theRect->l) < (fa->light_s + smax)) - theRect->w = (fa->light_s-theRect->l)+smax; - if ((theRect->h + theRect->t) < (fa->light_t + tmax)) - theRect->h = (fa->light_t-theRect->t)+tmax; - base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT; - base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; - R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes); - } - } -} - -/* -================ -R_MirrorChain -================ -*/ -void R_MirrorChain (msurface_t *s) -{ - if (mirror) - return; - mirror = true; - mirror_plane = s->plane; -} - - -#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 ; inumtextures ; i++) + if (lighthalf) + glColor4f(0.5,0.5,0.5, r_wateralpha->value); + else + glColor4f(1,1,1, r_wateralpha->value); + if (r_wateralpha->value < 1.0) { - t = cl.worldmodel->textures[i]; - if (!t) - continue; - s = t->texturechain; - if (!s) - continue; - if ( !(s->flags & SURF_DRAWTURB) ) - continue; - - // set modulate mode explicitly - glBindTexture (GL_TEXTURE_2D, t->gl_texturenum); - - for ( ; s ; s=s->texturechain) - R_RenderBrushPoly (s); - - t->texturechain = NULL; + glDepthMask(0); + EmitWaterPolys (s); + glDepthMask(1); } - + else + EmitWaterPolys (s); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - glColor4f (1,1,1,1); - glDisable (GL_BLEND); } -#else + /* ================ R_DrawWaterSurfaces @@ -969,68 +624,40 @@ void R_DrawWaterSurfaces (void) { int i; msurface_t *s; - texture_t *t; - if (r_wateralpha->value == 1.0 && gl_texsort->value) + if (!waterchain) return; - // // go back to the world matrix - // - glLoadMatrixf (r_world_matrix); + glLoadMatrixf (r_world_matrix); - if (r_wateralpha->value < 1.0) { - glEnable (GL_BLEND); - glColor4f (1,1,1,r_wateralpha->value); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + if (lighthalf) + glColor4f(0.5,0.5,0.5, r_wateralpha->value); + else + glColor4f(1,1,1, r_wateralpha->value); + if (r_wateralpha->value < 1.0) + glDepthMask(0); - if (!gl_texsort->value) { - if (!waterchain) - return; - - for ( s = waterchain ; s ; s=s->texturechain) { - glBindTexture (GL_TEXTURE_2D, s->texinfo->texture->gl_texturenum); - EmitWaterPolys (s); - } - - waterchain = NULL; - } else { - - for (i=0 ; inumtextures ; i++) + i = -1; + for (s = waterchain;s;s = s->texturechain) + { + if (i != s->texinfo->texture->gl_texturenum) { - t = cl.worldmodel->textures[i]; - if (!t) - continue; - s = t->texturechain; - if (!s) - continue; - if ( !(s->flags & SURF_DRAWTURB ) ) - continue; - - // set modulate mode explicitly - - glBindTexture (GL_TEXTURE_2D, t->gl_texturenum); - - for ( ; s ; s=s->texturechain) - EmitWaterPolys (s); - - t->texturechain = NULL; + i = s->texinfo->texture->gl_texturenum; + glBindTexture (GL_TEXTURE_2D, i); } - - } - - if (r_wateralpha->value < 1.0) { - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - glColor4f (1,1,1,1); - glDisable (GL_BLEND); + EmitWaterPolys (s); } + + waterchain = NULL; + glColor3f(1,1,1); + if (r_wateralpha->value < 1.0) + glDepthMask(1); } -#endif /* ================ @@ -1041,43 +668,15 @@ void DrawTextureChains (void) { int i; msurface_t *s; - texture_t *t; - - if (!gl_texsort->value) { - GL_DisableMultitexture(); - - if (skychain) { - R_DrawSkyChain(skychain); - skychain = NULL; - } - - return; - } for (i=0 ; inumtextures ; i++) { - t = cl.worldmodel->textures[i]; - if (!t) + if (!cl.worldmodel->textures[i]) continue; - s = t->texturechain; - if (!s) - continue; - if (i == skytexturenum) - R_DrawSkyChain (s); - else if (i == mirrortexturenum && r_mirroralpha->value != 1.0) - { - R_MirrorChain (s); - continue; - } - else - { - if ((s->flags & SURF_DRAWTURB) && r_wateralpha->value != 1.0) - continue; // draw translucent water later - for ( ; s ; s=s->texturechain) - R_RenderBrushPoly (s); - } + for (s = cl.worldmodel->textures[i]->texturechain;s;s = s->texturechain) + R_RenderBrushPoly (s); - t->texturechain = NULL; + cl.worldmodel->textures[i]->texturechain = NULL; } } @@ -1088,9 +687,9 @@ R_DrawBrushModel */ void R_DrawBrushModel (entity_t *e) { + int i; int k; vec3_t mins, maxs; - int i; msurface_t *psurf; float dot; mplane_t *pplane; @@ -1098,7 +697,6 @@ void R_DrawBrushModel (entity_t *e) qboolean rotated; currententity = e; - currenttexture = -1; clmodel = e->model; @@ -1121,7 +719,8 @@ void R_DrawBrushModel (entity_t *e) if (R_CullBox (mins, maxs)) return; - glColor3f (1,1,1); + glColor3f (1, 1, 1); + memset (lightmap_polys, 0, sizeof(lightmap_polys)); VectorSubtract (r_refdef.vieworg, e->origin, modelorg); @@ -1139,8 +738,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) { vec3_t lightorigin; @@ -1151,38 +750,54 @@ void R_DrawBrushModel (entity_t *e) continue; VectorSubtract(cl_dlights[k].origin, e->origin, lightorigin); - R_MarkLights (lightorigin,&cl_dlights[k], 1<nodes + clmodel->hulls[0].firstclipnode); } } - 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 + + // LordHavoc: anyone without multitexture won't want texsort 0 anyway... + if (!gl_mtexable) + gl_texsort->value = 1; + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // // draw texture // for (i=0 ; inummodelsurfaces ; i++, psurf++) { - // find which side of the node we are on + if (psurf->flags & SURF_DRAWSKY) + return; + + // 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))) { - if (gl_texsort->value) + if (psurf->flags & SURF_DRAWTURB) + GL_WaterSurface(psurf); + else if (gl_texsort->value) R_RenderBrushPoly (psurf); else - R_DrawSequentialPoly (psurf); + R_DrawMultitexturePoly (psurf); } } - R_BlendLightmaps (); + if (gl_texsort->value) + R_BlendLightmaps (); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); glPopMatrix (); } @@ -1209,23 +824,21 @@ void R_RecursiveWorldNode (mnode_t *node) double dot; if (node->contents == CONTENTS_SOLID) - return; // solid + return; // solid if (node->visframe != r_visframecount) return; if (R_CullBox (node->minmaxs, node->minmaxs+3)) return; - + // if a leaf node, draw stuff if (node->contents < 0) { pleaf = (mleaf_t *)node; - mark = pleaf->firstmarksurface; - c = pleaf->nummarksurfaces; - - if (c) + if ((c = pleaf->nummarksurfaces)) { + mark = pleaf->firstmarksurface; do { (*mark)->visframe = r_framecount; @@ -1261,60 +874,54 @@ void R_RecursiveWorldNode (mnode_t *node) break; } - if (dot >= 0) - side = 0; - else - side = 1; + side = dot < 0; // recurse down the children, front side first - R_RecursiveWorldNode (node->children[side]); + // LordHavoc: save a stack frame by avoiding a call + if (node->children[side]->contents != CONTENTS_SOLID && node->children[side]->visframe == r_visframecount && !R_CullBox (node->children[side]->minmaxs, node->children[side]->minmaxs+3)) + R_RecursiveWorldNode (node->children[side]); // draw stuff - c = node->numsurfaces; - - if (c) + if ((c = node->numsurfaces)) { surf = cl.worldmodel->surfaces + node->firstsurface; - if (dot < 0 -BACKFACE_EPSILON) + if (dot < -BACKFACE_EPSILON) side = SURF_PLANEBACK; else if (dot > BACKFACE_EPSILON) side = 0; + + for ( ; c ; c--, surf++) { - for ( ; c ; c--, surf++) + if (surf->visframe != r_framecount) + continue; + + if ((dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) + continue; // wrong side + + if (surf->flags & SURF_DRAWSKY) + continue; + + if (surf->flags & SURF_DRAWTURB) { - if (surf->visframe != r_framecount) - continue; - - // don't backface underwater surfaces, because they warp - if ( !(surf->flags & SURF_UNDERWATER) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) ) - continue; // wrong side - - // if sorting by texture, just store it out - if (gl_texsort->value) - { - if (!mirror - || surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum]) - { - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; - } - } else if (surf->flags & SURF_DRAWSKY) { - surf->texturechain = skychain; - skychain = surf; - } else if (surf->flags & SURF_DRAWTURB) { - surf->texturechain = waterchain; - waterchain = surf; - } else - R_DrawSequentialPoly (surf); - + surf->texturechain = waterchain; + waterchain = surf; } + else if (gl_texsort->value) + { + surf->texturechain = surf->texinfo->texture->texturechain; + surf->texinfo->texture->texturechain = surf; + } + else + R_DrawMultitexturePoly (surf); } - } // recurse down the back side - R_RecursiveWorldNode (node->children[!side]); + // LordHavoc: save a stack frame by avoiding a call + side = !side; + if (node->children[side]->contents != CONTENTS_SOLID && node->children[side]->visframe == r_visframecount && !R_CullBox (node->children[side]->minmaxs, node->children[side]->minmaxs+3)) + R_RecursiveWorldNode (node->children[side]); } @@ -1334,23 +941,29 @@ void R_DrawWorld (void) VectorCopy (r_refdef.vieworg, modelorg); currententity = &ent; - currenttexture = -1; - glColor3f (1,1,1); + // LordHavoc: anyone without multitexture won't want texsort 0 anyway... + if (!gl_mtexable) + gl_texsort->value = 1; + + glColor3f (1.0, 1.0, 1.0); memset (lightmap_polys, 0, sizeof(lightmap_polys)); -#ifdef QUAKE2 - R_ClearSkyBox (); -#endif + // Be sure to clear the skybox --KB + R_DrawSky (); + + glDisable(GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); R_RecursiveWorldNode (cl.worldmodel->nodes); DrawTextureChains (); - R_BlendLightmaps (); + if (gl_texsort->value) + R_BlendLightmaps (); -#ifdef QUAKE2 - R_DrawSkyBox (); -#endif + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); } @@ -1432,7 +1045,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; } @@ -1441,6 +1055,10 @@ int AllocBlock (int w, int h, int *x, int *y) if (best + h > BLOCK_HEIGHT) continue; + // LordHavoc: allocate lightmaps only as needed + if (!lightmaps[texnum]) + lightmaps[texnum] = calloc(BLOCK_WIDTH * BLOCK_HEIGHT, 3); + for (i=0 ; iextents[1]>>4)+1; surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t); - base = lightmaps + surf->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT; - base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes; + base = lightmaps[surf->lightmaptexturenum] + (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes; R_BuildLightMap (surf, base, BLOCK_WIDTH*lightmap_bytes); } @@ -1616,32 +1234,18 @@ void GL_BuildLightmaps (void) texture_extension_number += MAX_LIGHTMAPS; } - gl_lightmap_format = GL_LUMINANCE; + gl_colorlights = Cvar_Get ("gl_colorlights", "1", CVAR_ROM, + "Whether to use RGB lightmaps or not"); - if (COM_CheckParm ("-lm_1")) - gl_lightmap_format = GL_LUMINANCE; - if (COM_CheckParm ("-lm_a")) - gl_lightmap_format = GL_ALPHA; - if (COM_CheckParm ("-lm_i")) - gl_lightmap_format = GL_INTENSITY; - if (COM_CheckParm ("-lm_2")) - gl_lightmap_format = GL_RGBA4; - if (COM_CheckParm ("-lm_4")) - gl_lightmap_format = GL_RGBA; - - switch (gl_lightmap_format) + if (gl_colorlights->value) { - case GL_RGBA: - lightmap_bytes = 4; - break; - case GL_RGBA4: - lightmap_bytes = 2; - break; - case GL_LUMINANCE: - case GL_INTENSITY: - case GL_ALPHA: + gl_lightmap_format = GL_RGB; + lightmap_bytes = 3; + } + else + { + gl_lightmap_format = GL_LUMINANCE; lightmap_bytes = 1; - break; } for (j=1 ; jnumsurfaces ; i++) { - GL_CreateSurfaceLightmap (m->surfaces + i); if ( m->surfaces[i].flags & SURF_DRAWTURB ) continue; -#ifndef QUAKE2 if ( m->surfaces[i].flags & SURF_DRAWSKY ) continue; -#endif + GL_CreateSurfaceLightmap (m->surfaces + i); BuildSurfaceDisplayList (m->surfaces + i); } } - if (!gl_texsort->value) - GL_SelectTexture(TEXTURE1_SGIS); + if (gl_mtexable && !gl_texsort->value) + qglSelectTexture (gl_mtex_enum+1); // // upload all lightmaps that were filled @@ -1684,13 +1286,12 @@ void GL_BuildLightmaps (void) glBindTexture (GL_TEXTURE_2D, 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]); } - if (!gl_texsort->value) - GL_SelectTexture(TEXTURE0_SGIS); - + if (gl_mtexable && !gl_texsort->value) + qglSelectTexture (gl_mtex_enum+0); } diff --git a/source/gl_warp.c b/source/gl_warp.c index b79d721..2cc7424 100644 --- a/source/gl_warp.c +++ b/source/gl_warp.c @@ -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 +#include +#include +#include +#ifdef HAVE_STRINGS_H +#include +#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] ; inumverts ; 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=0; row--) { pixbuf = targa_rgba + row*columns*4; for(column=0; column 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 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 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 ; itexturechain) - { - for (p=fa->polys ; p ; p=p->next) - { - for (i=0 ; inumverts ; 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] ; inumverts ; 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); +} diff --git a/source/vid_glx.c b/source/vid_glx.c index 5ba1f9d..a6377c7 100644 --- a/source/vid_glx.c +++ b/source/vid_glx.c @@ -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.