X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=gl_rmain.c;h=6816a436f5ef56e215767781c27e48ac557d8ba3;hb=ea4fc545e8444f579d88d8f096b054dcd7bc482f;hp=f90e467adc45881d4e619b25814411689bd30e84;hpb=a0f204979928fb1f1e2fd6ebf56e4873fc54b07f;p=xonotic%2Fdarkplaces.git diff --git a/gl_rmain.c b/gl_rmain.c index f90e467a..6816a436 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -20,177 +20,155 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // r_main.c #include "quakedef.h" +#include "r_shadow.h" -entity_t r_worldentity; +// used for dlight push checking and other things +int r_framecount; -qboolean r_cache_thrash; // compatability +// used for visibility checking +qbyte r_pvsbits[(MAX_MAP_LEAFS+7)>>3]; -vec3_t modelorg, r_entorigin; -entity_t *currententity; +mplane_t frustum[4]; -int r_visframecount; // bumped when going to a new PVS -int r_framecount; // used for dlight push checking +matrix4x4_t r_identitymatrix; -mplane_t frustum[4]; +int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights; -int c_brush_polys, c_alias_polys; +// true during envmap command capture +qboolean envmap; -qboolean envmap; // true during envmap command capture +// maximum visible distance (recalculated from world box each frame) +float r_farclip; +// brightness of world lightmaps and related lighting +// (often reduced when world rtlights are enabled) +float r_lightmapintensity; +// whether to draw world lights realtime, dlights realtime, and their shadows +qboolean r_rtworld; +qboolean r_rtworldshadows; +qboolean r_rtdlight; +qboolean r_rtdlightshadows; -// LordHavoc: moved all code related to particles into r_part.c -//int particletexture; // little dot for particles -int playertextures; // up to 16 color translated skins -extern qboolean isG200, isRagePro; // LordHavoc: special card hacks +// forces all rendering to draw triangle outlines +int r_showtrispass; -// // view origin -// -vec3_t vup; -vec3_t vpn; -vec3_t vright; -vec3_t r_origin; - -float r_world_matrix[16]; -float r_base_world_matrix[16]; +vec3_t r_vieworigin; +vec3_t r_viewforward; +vec3_t r_viewleft; +vec3_t r_viewright; +vec3_t r_viewup; +int r_view_x; +int r_view_y; +int r_view_z; +int r_view_width; +int r_view_height; +int r_view_depth; +float r_view_fov_x; +float r_view_fov_y; +matrix4x4_t r_view_matrix; // // screen size info // -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 - - -void R_MarkLeaves (void); - -//cvar_t r_norefresh = {"r_norefresh","0"}; -cvar_t r_drawentities = {"r_drawentities","1"}; -cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; -cvar_t r_speeds = {"r_speeds","0"}; -cvar_t r_speeds2 = {"r_speeds2","0"}; -cvar_t r_fullbright = {"r_fullbright","0"}; -//cvar_t r_lightmap = {"r_lightmap","0"}; -//cvar_t r_shadows = {"r_shadows","0"}; -cvar_t r_wateralpha = {"r_wateralpha","1"}; -//cvar_t r_dynamic = {"r_dynamic","1"}; -cvar_t r_novis = {"r_novis","0"}; -cvar_t r_waterripple = {"r_waterripple","0"}; -cvar_t r_fullbrights = {"r_fullbrights", "1"}; - -//cvar_t gl_cull = {"gl_cull","1"}; -//cvar_t gl_affinemodels = {"gl_affinemodels","0"}; -//cvar_t gl_polyblend = {"gl_polyblend","1"}; -//cvar_t gl_flashblend = {"gl_flashblend","0"}; -cvar_t gl_playermip = {"gl_playermip","0"}; -//cvar_t gl_nocolors = {"gl_nocolors","0"}; -//cvar_t gl_keeptjunctions = {"gl_keeptjunctions","1"}; -//cvar_t gl_reporttjunctions = {"gl_reporttjunctions","0"}; -cvar_t contrast = {"contrast", "1.0", TRUE}; // LordHavoc: a method of operating system independent color correction -cvar_t brightness = {"brightness", "1.0", TRUE}; // LordHavoc: a method of operating system independent color correction -cvar_t gl_lightmode = {"gl_lightmode", "1", TRUE}; // LordHavoc: overbright lighting -//cvar_t r_particles = {"r_particles", "1"}; -//cvar_t r_dynamicwater = {"r_dynamicwater", "1"}; -//cvar_t r_smokealpha = {"r_smokealpha", "0.25"}; -//cvar_t r_dynamicbothsides = {"r_dynamicbothsides", "1"}; // LordHavoc: can disable dynamic lighting of backfaces, but quake maps are weird so it doesn't always work right... - -cvar_t gl_fogenable = {"gl_fogenable", "0"}; -cvar_t gl_fogdensity = {"gl_fogdensity", "0.25"}; -cvar_t gl_fogred = {"gl_fogred","0.3"}; -cvar_t gl_foggreen = {"gl_foggreen","0.3"}; -cvar_t gl_fogblue = {"gl_fogblue","0.3"}; -cvar_t gl_fogstart = {"gl_fogstart", "0"}; -cvar_t gl_fogend = {"gl_fogend","0"}; -cvar_t glfog = {"glfog", "0"}; - -int chrometexture; - -void makechrometextures() +refdef_t r_refdef; + +// 8.8 fraction of base light value +unsigned short d_lightstylevalue[256]; + +cvar_t r_showtris = {0, "r_showtris", "0"}; +cvar_t r_drawentities = {0, "r_drawentities","1"}; +cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"}; +cvar_t r_speeds = {0, "r_speeds","0"}; +cvar_t r_fullbright = {0, "r_fullbright","0"}; +cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"}; +cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"}; +cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"}; +cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"}; + +cvar_t gl_fogenable = {0, "gl_fogenable", "0"}; +cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"}; +cvar_t gl_fogred = {0, "gl_fogred","0.3"}; +cvar_t gl_foggreen = {0, "gl_foggreen","0.3"}; +cvar_t gl_fogblue = {0, "gl_fogblue","0.3"}; +cvar_t gl_fogstart = {0, "gl_fogstart", "0"}; +cvar_t gl_fogend = {0, "gl_fogend","0"}; + +cvar_t r_textureunits = {0, "r_textureunits", "32"}; + +cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"}; +cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"}; +cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"}; +cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"}; + + +void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b) { - int x, y, g, g2, amplitude, noise[64][64], min, max; - byte data[64][64][4]; - // - // particle texture - // - chrometexture = texture_extension_number++; - glBindTexture(GL_TEXTURE_2D, chrometexture); - -#define n(x,y) noise[(y)&63][(x)&63] - - amplitude = 16777215; - g2 = 64; - noise[0][0] = 0; - for (;(g = g2 >> 1) >= 1;g2 >>= 1) + int i; + for (i = 0;i < verts;i++) { - // subdivide, diamond-square algorythm (really this has little to do with squares) - // diamond - for (y = 0;y < 64;y += g2) - for (x = 0;x < 64;x += g2) - n(x+g,y+g) = (n(x,y) + n(x+g2,y) + n(x,y+g2) + n(x+g2,y+g2)) >> 2; - // square - for (y = 0;y < 64;y += g2) - for (x = 0;x < 64;x += g2) - { - n(x+g,y) = (n(x,y) + n(x+g2,y) + n(x+g,y-g) + n(x+g,y+g)) >> 2; - n(x,y+g) = (n(x,y) + n(x,y+g2) + n(x-g,y+g) + n(x+g,y+g)) >> 2; - } - // brownian motion theory - amplitude >>= 1; - for (y = 0;y < 64;y += g) - for (x = 0;x < 64;x += g) - noise[y][x] += rand()&litude; + out[0] = in[0] * r; + out[1] = in[1] * g; + out[2] = in[2] * b; + out[3] = in[3]; + in += 4; + out += 4; } - // normalize the noise range - min = max = 0; - for (y = 0;y < 64;y++) - for (x = 0;x < 64;x++) - { - if (n(x,y) < min) min = n(x,y); - if (n(x,y) > max) max = n(x,y); - } - max -= min; - for (y = 0;y < 64;y++) - for (x = 0;x < 64;x++) - n(x,y) = (n(x,y) - min) * 255 / max; - -#undef n +} - // convert to RGBA data - for (y = 0;y < 64;y++) - for (x = 0;x < 64;x++) - { - data[y][x][0] = data[y][x][1] = data[y][x][2] = (byte) noise[y][x]; - data[y][x][3] = 255; - } +void R_FillColors(float *out, int verts, float r, float g, float b, float a) +{ + int i; + for (i = 0;i < verts;i++) + { + out[0] = r; + out[1] = g; + out[2] = b; + out[3] = a; + out += 4; + } +} - glTexImage2D (GL_TEXTURE_2D, 0, 4, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); +/* +==================== +R_TimeRefresh_f - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +For program optimization +==================== +*/ +qboolean intimerefresh = 0; +static void R_TimeRefresh_f (void) +{ + int i; + float timestart, timedelta, oldangles[3]; - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -} + intimerefresh = 1; + VectorCopy(cl.viewangles, oldangles); + VectorClear(cl.viewangles); -extern qboolean isRagePro; + timestart = Sys_DoubleTime(); + for (i = 0;i < 128;i++) + { + Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], 0, i / 128.0 * 360.0, 0, 1); + CL_UpdateScreen(); + } + timedelta = Sys_DoubleTime() - timestart; -qboolean lighthalf; + VectorCopy(oldangles, cl.viewangles); + intimerefresh = 0; + Con_Printf("%f seconds (%f fps)\n", timedelta, 128/timedelta); +} vec3_t fogcolor; vec_t fogdensity; float fog_density, fog_red, fog_green, fog_blue; qboolean fogenabled; qboolean oldgl_fogenable; -void FOG_framebegin() +void R_UpdateFog(void) { - if (nehahra) + if (gamemode == GAME_NEHAHRA) { -// if (!Nehahrademcompatibility) -// gl_fogenable.value = 0; - if (gl_fogenable.value) + if (gl_fogenable.integer) { oldgl_fogenable = true; fog_density = gl_fogdensity.value; @@ -207,62 +185,26 @@ void FOG_framebegin() fog_blue = 0; } } - if (glfog.value) + if (fog_density) { - if(fog_density) - { - // LordHavoc: Borland C++ 5.0 was choking on this line, stupid compiler... - //GLfloat colors[4] = {(GLfloat) gl_fogred.value, (GLfloat) gl_foggreen.value, (GLfloat) gl_fogblue.value, (GLfloat) 1}; - GLfloat colors[4]; - colors[0] = fog_red; - colors[1] = fog_green; - colors[2] = fog_blue; - colors[3] = 1; - if (lighthalf) - { - colors[0] *= 0.5f; - colors[1] *= 0.5f; - colors[2] *= 0.5f; - } - - glFogi (GL_FOG_MODE, GL_EXP2); - glFogf (GL_FOG_DENSITY, (GLfloat) fog_density / 100); - glFogfv (GL_FOG_COLOR, colors); - glEnable (GL_FOG); - } - else - glDisable(GL_FOG); + fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f); + fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f); + fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f); } - else + if (fog_density) { - if (fog_density) - { - fogenabled = true; - fogdensity = -4096.0f / (fog_density * fog_density); - fogcolor[0] = fog_red = bound(0.0f, fog_red , 1.0f); - fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f); - fogcolor[2] = fog_blue = bound(0.0f, fog_blue , 1.0f); - if (lighthalf) - { - fogcolor[0] *= 0.5f; - fogcolor[1] *= 0.5f; - fogcolor[2] *= 0.5f; - } - } - else - fogenabled = false; + fogenabled = true; + fogdensity = -4000.0f / (fog_density * fog_density); + // fog color was already set } + else + fogenabled = false; } -void FOG_frameend() -{ - if (glfog.value) - glDisable(GL_FOG); -} - -void FOG_clear() +// FIXME: move this to client? +void FOG_clear(void) { - if (nehahra) + if (gamemode == GAME_NEHAHRA) { Cvar_Set("gl_fogenable", "0"); Cvar_Set("gl_fogdensity", "0.2"); @@ -273,1343 +215,756 @@ void FOG_clear() fog_density = fog_red = fog_green = fog_blue = 0.0f; } -void FOG_registercvars() +// FIXME: move this to client? +void FOG_registercvars(void) { - Cvar_RegisterVariable (&glfog); - if (nehahra) + if (gamemode == GAME_NEHAHRA) { Cvar_RegisterVariable (&gl_fogenable); Cvar_RegisterVariable (&gl_fogdensity); Cvar_RegisterVariable (&gl_fogred); - Cvar_RegisterVariable (&gl_foggreen); + Cvar_RegisterVariable (&gl_foggreen); Cvar_RegisterVariable (&gl_fogblue); Cvar_RegisterVariable (&gl_fogstart); Cvar_RegisterVariable (&gl_fogend); } } -void glpoly_init(); -void glrsurf_init(); -void rlight_init(); - -// LordHavoc: vertex array -float *aliasvert; -float *aliasvertnorm; -byte *aliasvertcolor; - -void rmain_registercvars() +void gl_main_start(void) { - // allocate vertex processing arrays - aliasvert = malloc(sizeof(float[MD2MAX_VERTS][3])); - aliasvertnorm = malloc(sizeof(float[MD2MAX_VERTS][3])); - aliasvertcolor = malloc(sizeof(byte[MD2MAX_VERTS][4])); - - FOG_registercvars(); - Cvar_RegisterVariable (&r_speeds2); - Cvar_RegisterVariable (&contrast); - Cvar_RegisterVariable (&brightness); - Cvar_RegisterVariable (&gl_lightmode); -// Cvar_RegisterVariable (&r_dynamicwater); -// Cvar_RegisterVariable (&r_particles); -// Cvar_RegisterVariable (&r_smokealpha); -// Cvar_RegisterVariable (&r_dynamicbothsides); - Cvar_RegisterVariable (&r_fullbrights); - if (nehahra) - Cvar_SetValue("r_fullbrights", 0); -// if (gl_vendor && strstr(gl_vendor, "3Dfx")) -// gl_lightmode.value = 0; - Cvar_RegisterVariable (&r_fullbright); - makechrometextures(); - glpoly_init(); - glrsurf_init(); - rlight_init(); } -/* -void R_RotateForEntity (entity_t *e) +void gl_main_shutdown(void) { - glTranslatef (e->origin[0], e->origin[1], e->origin[2]); - - glRotatef (e->angles[1], 0, 0, 1); - glRotatef (-e->angles[0], 0, 1, 0); - glRotatef (e->angles[2], 1, 0, 0); - - glScalef (e->scale, e->scale, e->scale); // LordHavoc: model scale } -*/ -// LordHavoc: if not for the fact BRIGHTFIELD particles require this, it would be removed... -#define NUMVERTEXNORMALS 162 - -float r_avertexnormals[NUMVERTEXNORMALS][3] = { -#include "anorms.h" -}; - -// LordHavoc: moved this shading stuff up because the sprites need shading stuff -vec3_t shadevector; -vec3_t shadecolor; - -float modelalpha; - -void R_LightPoint (vec3_t color, vec3_t p); -void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits); -void R_DynamicLightPointNoMask(vec3_t color, vec3_t org); - -float R_CalcAnimLerp(int pose, float lerpscale) +extern void CL_ParseEntityLump(char *entitystring); +void gl_main_newmap(void) { - if (currententity->draw_lastmodel == currententity->model && currententity->draw_lerpstart <= cl.time) - { - if (pose != currententity->draw_pose) + int l; + char *entities, entname[MAX_QPATH]; + r_framecount = 1; + if (cl.worldmodel) + { + strcpy(entname, cl.worldmodel->name); + l = strlen(entname) - 4; + if (l >= 0 && !strcmp(entname + l, ".bsp")) { - currententity->draw_lastpose = currententity->draw_pose; - currententity->draw_pose = pose; - currententity->draw_lerpstart = cl.time; - return 0; + strcpy(entname + l, ".ent"); + if ((entities = FS_LoadFile(entname, tempmempool, true))) + { + CL_ParseEntityLump(entities); + Mem_Free(entities); + return; + } } - else - return ((cl.time - currententity->draw_lerpstart) * lerpscale); - } - else // uninitialized - { - currententity->draw_lastmodel = currententity->model; - currententity->draw_lastpose = currententity->draw_pose = pose; - currententity->draw_lerpstart = cl.time; - return 0; + if (cl.worldmodel->brush.entities) + CL_ParseEntityLump(cl.worldmodel->brush.entities); } } -/* -============================================================= - - SPRITE MODELS - -============================================================= -*/ - -/* -================ -R_GetSpriteFrame -================ -*/ -void R_GetSpriteFrame (entity_t *currententity, mspriteframe_t **oldframe, mspriteframe_t **newframe, float *framelerp) +void GL_Main_Init(void) { - msprite_t *psprite; - mspritegroup_t *pspritegroup; - int i, j, numframes, frame; - float *pintervals, fullinterval, targettime, time, jtime, jinterval; - - psprite = currententity->model->cache.data; - frame = currententity->frame; - - if ((frame >= psprite->numframes) || (frame < 0)) - { - Con_Printf ("R_DrawSprite: no such frame %d\n", frame); - frame = 0; - } - - if (psprite->frames[frame].type == SPR_SINGLE) - { - if (currententity->draw_lastmodel == currententity->model && currententity->draw_lerpstart < cl.time) - { - if (frame != currententity->draw_pose) - { - currententity->draw_lastpose = currententity->draw_pose; - currententity->draw_pose = frame; - currententity->draw_lerpstart = cl.time; - *framelerp = 0; - } - else - *framelerp = (cl.time - currententity->draw_lerpstart) * 10.0; - } - else // uninitialized - { - currententity->draw_lastmodel = currententity->model; - currententity->draw_lastpose = currententity->draw_pose = frame; - currententity->draw_lerpstart = cl.time; - *framelerp = 0; - } - *oldframe = psprite->frames[currententity->draw_lastpose].frameptr; - *newframe = psprite->frames[frame].frameptr; - } - else - { - pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; - pintervals = pspritegroup->intervals; - numframes = pspritegroup->numframes; - fullinterval = pintervals[numframes-1]; + Matrix4x4_CreateIdentity(&r_identitymatrix); +// FIXME: move this to client? + FOG_registercvars(); + Cmd_AddCommand("timerefresh", R_TimeRefresh_f); + Cvar_RegisterVariable(&r_showtris); + Cvar_RegisterVariable(&r_drawentities); + Cvar_RegisterVariable(&r_drawviewmodel); + Cvar_RegisterVariable(&r_speeds); + Cvar_RegisterVariable(&r_fullbrights); + Cvar_RegisterVariable(&r_wateralpha); + Cvar_RegisterVariable(&r_dynamic); + Cvar_RegisterVariable(&r_fullbright); + Cvar_RegisterVariable(&r_textureunits); + Cvar_RegisterVariable(&r_lerpsprites); + Cvar_RegisterVariable(&r_lerpmodels); + Cvar_RegisterVariable(&r_waterscroll); + Cvar_RegisterVariable(&r_watershader); + Cvar_RegisterVariable(&r_drawcollisionbrushes); + if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE) + Cvar_SetValue("r_fullbrights", 0); + R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap); +} - time = cl.time + currententity->syncbase; +static vec3_t r_farclip_origin; +static vec3_t r_farclip_direction; +static vec_t r_farclip_directiondist; +static vec_t r_farclip_meshfarclip; +static int r_farclip_directionbit0; +static int r_farclip_directionbit1; +static int r_farclip_directionbit2; - // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values - // are positive, so we don't have to worry about division by 0 - targettime = time - ((int)(time / fullinterval)) * fullinterval; +// enlarge farclip to accomodate box +static void R_FarClip_Box(vec3_t mins, vec3_t maxs) +{ + float d; + d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0] + + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1] + + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2]; + if (r_farclip_meshfarclip < d) + r_farclip_meshfarclip = d; +} - // LordHavoc: since I can't measure the time properly when it loops from numframes-1 to 0, - // I instead measure the time of the first frame, hoping it is consistent - j = numframes-1;jtime = 0;jinterval = pintervals[1] - pintervals[0]; - for (i=0 ; i<(numframes-1) ; i++) - { - if (pintervals[i] > targettime) - break; - j = i;jinterval = pintervals[i] - jtime;jtime = pintervals[i]; - } - *framelerp = (targettime - jtime) / jinterval; +// return farclip value +static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip) +{ + int i; - *oldframe = pspritegroup->frames[j]; - *newframe = pspritegroup->frames[i]; - } + VectorCopy(origin, r_farclip_origin); + VectorCopy(direction, r_farclip_direction); + r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction); + r_farclip_directionbit0 = r_farclip_direction[0] < 0; + r_farclip_directionbit1 = r_farclip_direction[1] < 0; + r_farclip_directionbit2 = r_farclip_direction[2] < 0; + r_farclip_meshfarclip = r_farclip_directiondist + startfarclip; + + if (cl.worldmodel) + R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs); + for (i = 0;i < r_refdef.numentities;i++) + R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs); + + return r_farclip_meshfarclip - r_farclip_directiondist; } -void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, int red, int green, int blue, int alpha) +extern void R_Textures_Init(void); +extern void Mod_RenderInit(void); +extern void GL_Draw_Init(void); +extern void GL_Main_Init(void); +extern void R_Shadow_Init(void); +extern void GL_Models_Init(void); +extern void R_Sky_Init(void); +extern void GL_Surf_Init(void); +extern void R_Crosshairs_Init(void); +extern void R_Light_Init(void); +extern void R_Particles_Init(void); +extern void R_Explosion_Init(void); +extern void ui_init(void); +extern void gl_backend_init(void); +extern void Sbar_Init(void); +extern void R_LightningBeams_Init(void); + +void Render_Init(void) { - // LordHavoc: rewrote this to use the transparent poly system - transpolybegin(frame->gl_texturenum, 0, frame->gl_fogtexturenum, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA); - transpolyvert(origin[0] + frame->down * up[0] + frame->left * right[0], origin[1] + frame->down * up[1] + frame->left * right[1], origin[2] + frame->down * up[2] + frame->left * right[2], 0, 1, red, green, blue, alpha); - transpolyvert(origin[0] + frame->up * up[0] + frame->left * right[0], origin[1] + frame->up * up[1] + frame->left * right[1], origin[2] + frame->up * up[2] + frame->left * right[2], 0, 0, red, green, blue, alpha); - transpolyvert(origin[0] + frame->up * up[0] + frame->right * right[0], origin[1] + frame->up * up[1] + frame->right * right[1], origin[2] + frame->up * up[2] + frame->right * right[2], 1, 0, red, green, blue, alpha); - transpolyvert(origin[0] + frame->down * up[0] + frame->right * right[0], origin[1] + frame->down * up[1] + frame->right * right[1], origin[2] + frame->down * up[2] + frame->right * right[2], 1, 1, red, green, blue, alpha); - transpolyend(); + R_Textures_Init(); + Mod_RenderInit(); + gl_backend_init(); + R_MeshQueue_Init(); + GL_Draw_Init(); + GL_Main_Init(); + R_Shadow_Init(); + GL_Models_Init(); + R_Sky_Init(); + GL_Surf_Init(); + R_Crosshairs_Init(); + R_Light_Init(); + R_Particles_Init(); + R_Explosion_Init(); + //ui_init(); + UI_Init(); + Sbar_Init(); + R_LightningBeams_Init(); } -extern qboolean isG200, isRagePro, lighthalf; - /* -================= -R_DrawSpriteModel - -================= +=============== +GL_Init +=============== */ -void R_DrawSpriteModel (entity_t *e) +extern char *ENGINE_EXTENSIONS; +void GL_Init (void) { - mspriteframe_t *oldframe, *newframe; - float *up, *right, lerp, ilerp; - vec3_t v_forward, v_right, v_up, org; - msprite_t *psprite; - - // don't even bother culling, because it's just a single - // polygon without a surface cache - R_GetSpriteFrame (e, &oldframe, &newframe, &lerp); - if (lerp < 0) lerp = 0; - if (lerp > 1) lerp = 1; - if (isRagePro) // LordHavoc: no alpha scaling supported on per pixel alpha images on ATI Rage Pro... ACK! - lerp = 1; - ilerp = 1.0 - lerp; - psprite = e->model->cache.data; - - if (psprite->type == SPR_ORIENTED) - { // bullet marks on walls - AngleVectors (e->angles, v_forward, v_right, v_up); - up = v_up; - right = v_right; - VectorSubtract(e->origin, vpn, org); - } - else - { // normal sprite - up = vup; - right = vright; - VectorCopy(e->origin, org); - } - if (e->scale != 1) - { - VectorScale(up, e->scale, up); - VectorScale(right, e->scale, right); - } - - if (e->model->flags & EF_FULLBRIGHT || e->effects & EF_FULLBRIGHT) - { - if (lighthalf) - { - shadecolor[0] = e->colormod[0] * 128; - shadecolor[1] = e->colormod[1] * 128; - shadecolor[2] = e->colormod[2] * 128; - } - else - { - shadecolor[0] = e->colormod[0] * 255; - shadecolor[1] = e->colormod[1] * 255; - shadecolor[2] = e->colormod[2] * 255; - } - } - else - { - R_LightPoint (shadecolor, e->origin); - R_DynamicLightPointNoMask(shadecolor, e->origin); - if (lighthalf) - { - shadecolor[0] *= e->colormod[0] * 0.5; - shadecolor[1] *= e->colormod[1] * 0.5; - shadecolor[2] *= e->colormod[2] * 0.5; - } - } + VID_CheckExtensions(); - // LordHavoc: interpolated sprite rendering - if (ilerp != 0) - GL_DrawSpriteImage(oldframe, org, up, right, shadecolor[0],shadecolor[1],shadecolor[2],e->alpha*255*ilerp); - if (lerp != 0) - GL_DrawSpriteImage(newframe, org, up, right, shadecolor[0],shadecolor[1],shadecolor[2],e->alpha*255*lerp); + // LordHavoc: report supported extensions + Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS); } -/* -============================================================= - - ALIAS MODELS - -============================================================= -*/ - -extern vec3_t softwaretransform_x; -extern vec3_t softwaretransform_y; -extern vec3_t softwaretransform_z; -extern vec_t softwaretransform_scale; -extern vec3_t softwaretransform_offset; -void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2) +int R_CullBox(const vec3_t mins, const vec3_t maxs) { int i; - vec3_t point, matrix_x, matrix_y, matrix_z; - float *av, *avn; - av = aliasvert; - avn = aliasvertnorm; - if (lerp < 0) lerp = 0; - if (lerp > 1) lerp = 1; - if (lerp != 0) - { - float ilerp, ilerp127, lerp127, scalex1, scalex2, translatex, scaley1, scaley2, translatey, scalez1, scalez2, translatez; - if (lerp < 0) lerp = 0; - if (lerp > 1) lerp = 1; - ilerp = 1 - lerp; - ilerp127 = ilerp * (1.0 / 127.0); - lerp127 = lerp * (1.0 / 127.0); - VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x); - VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y); - VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z); - // calculate combined interpolation variables - scalex1 = scale1[0] * ilerp;scalex2 = scale2[0] * lerp;translatex = translate1[0] * ilerp + translate2[0] * lerp; - scaley1 = scale1[1] * ilerp;scaley2 = scale2[1] * lerp;translatey = translate1[1] * ilerp + translate2[1] * lerp; - scalez1 = scale1[2] * ilerp;scalez2 = scale2[2] * lerp;translatez = translate1[2] * ilerp + translate2[2] * lerp; - // generate vertices - for (i = 0;i < vertcount;i++) - { - // rotate, scale, and translate the vertex locations - point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex; - point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey; - point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez; - *av++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0]; - *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1]; - *av++ = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2]; - // rotate the normals - point[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127; - point[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127; - point[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127; - *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0]; - *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1]; - *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2]; - verts1++;verts2++; - } - } - else + mplane_t *p; + for (i = 0;i < 4;i++) { - float i127; - i127 = 1.0f / 127.0f; - VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x); - VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y); - VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z); - // generate vertices - for (i = 0;i < vertcount;i++) + p = frustum + i; + switch(p->signbits) { - // rotate, scale, and translate the vertex locations - point[0] = verts1->v[0] * scale1[0] + translate1[0]; - point[1] = verts1->v[1] * scale1[1] + translate1[1]; - point[2] = verts1->v[2] * scale1[2] + translate1[2]; - *av++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0]; - *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1]; - *av++ = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2]; - // rotate the normals - point[0] = verts1->n[0] * i127; - point[1] = verts1->n[1] * i127; - point[2] = verts1->n[2] * i127; - *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0]; - *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1]; - *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2]; - verts1++; + default: + case 0: + if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist) + return true; + break; + case 1: + if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist) + return true; + break; + case 2: + if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist) + return true; + break; + case 3: + if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist) + return true; + break; + case 4: + if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist) + return true; + break; + case 5: + if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist) + return true; + break; + case 6: + if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist) + return true; + break; + case 7: + if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist) + return true; + break; } } + return false; } -/* -================= -R_DrawAliasFrame +//================================================================================== -================= -*/ -extern vec3_t lightspot; -void R_LightModel(int numverts, vec3_t center); -extern cvar_t gl_vertexarrays; -void R_DrawAliasFrame (aliashdr_t *paliashdr) +static void R_MarkEntities (void) { - int i, pose, frame = currententity->frame; - float lerpscale, lerp; - - softwaretransformforentity(currententity); - - if ((frame >= paliashdr->numframes) || (frame < 0)) - { - Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); - frame = 0; - } - - pose = paliashdr->frames[frame].firstpose; - - if (paliashdr->frames[frame].numposes > 1) - { - lerpscale = 1.0 / paliashdr->frames[frame].interval; - pose += (int)(cl.time * lerpscale) % paliashdr->frames[frame].numposes; - } - else - lerpscale = 10.0; - - lerp = R_CalcAnimLerp(pose, lerpscale); - - R_AliasLerpVerts(paliashdr->numverts, lerp, (trivert2 *)((byte *)paliashdr + paliashdr->posedata) + currententity->draw_lastpose * paliashdr->numverts, paliashdr->scale, paliashdr->scale_origin, (trivert2 *)((byte *)paliashdr + paliashdr->posedata) + currententity->draw_pose * paliashdr->numverts, paliashdr->scale, paliashdr->scale_origin); + int i; + entity_render_t *ent; - R_LightModel(paliashdr->numverts, currententity->origin); + ent = &cl_entities[0].render; + Matrix4x4_CreateIdentity(&ent->matrix); + Matrix4x4_CreateIdentity(&ent->inversematrix); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glShadeModel(GL_SMOOTH); - if (currententity->effects & EF_ADDITIVE) - { - glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering - glEnable(GL_BLEND); - glDepthMask(0); - } - else if (modelalpha != 1.0) - { - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glDepthMask(0); - } - else - { - glDisable(GL_BLEND); - glDepthMask(1); - } + if (!r_drawentities.integer) + return; - if (gl_vertexarrays.value) - { - // LordHavoc: I would use InterleavedArrays here, - // but the texture coordinates are a seperate array, - // and it would be wasteful to copy them into the main array... - // glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha); - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - // draw the front faces - qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + (int) paliashdr)); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglDrawElements(GL_TRIANGLES, paliashdr->frontfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr)); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - // draw the back faces - qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) paliashdr->texcoords + sizeof(float[2]) * paliashdr->numverts + (int) paliashdr)); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - qglDrawElements(GL_TRIANGLES, paliashdr->backfaces * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + sizeof(unsigned short[3]) * paliashdr->frontfaces + (int) paliashdr)); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); + for (i = 0;i < r_refdef.numentities;i++) + { + ent = r_refdef.entities[i]; + Mod_CheckLoaded(ent->model); + // some of the renderer still relies on origin... + Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin); + // some of the renderer still relies on scale... + ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix); + R_LerpAnimation(ent); + R_UpdateEntLights(ent); + if ((chase_active.integer || !(ent->flags & RENDER_EXTERIORMODEL)) + && !VIS_CullBox(ent->mins, ent->maxs) + && (!envmap || !(ent->flags & (RENDER_VIEWMODEL | RENDER_EXTERIORMODEL)))) + ent->visframe = r_framecount; } - else - { - unsigned short *in, index; - float *tex; - in = (void *)((int) paliashdr->vertindices + (int) paliashdr); - glBegin(GL_TRIANGLES); - // draw the front faces - tex = (void *)((int) paliashdr->texcoords + (int) paliashdr); - //if (isG200) - //{ - for (i = 0;i < paliashdr->frontfaces * 3;i++) - { - index = *in++; - glTexCoord2f(tex[index*2], tex[index*2+1]); - glColor4f(aliasvertcolor[index*4] * (1.0f / 255.0f), aliasvertcolor[index*4+1] * (1.0f / 255.0f), aliasvertcolor[index*4+2] * (1.0f / 255.0f), aliasvertcolor[index*4+3] * (1.0f / 255.0f)); - glVertex3fv(&aliasvert[index*3]); - } - /* - } - else - { - for (i = 0;i < paliashdr->frontfaces * 3;i++) - { - index = *in++; - glTexCoord2f(tex[index*2], tex[index*2+1]); - glColor4ub(aliasvertcolor[index*4], aliasvertcolor[index*4+1], aliasvertcolor[index*4+2], aliasvertcolor[index*4+3]); - glVertex3fv(&aliasvert[index*3]); - } - } - */ - // draw the back faces - tex += 2 * paliashdr->numverts; - //if (isG200) - //{ - for (i = 0;i < paliashdr->backfaces * 3;i++) - { - index = *in++; - glTexCoord2f(tex[index*2], tex[index*2+1]); - glColor4f(aliasvertcolor[index*4] * (1.0f / 255.0f), aliasvertcolor[index*4+1] * (1.0f / 255.0f), aliasvertcolor[index*4+2] * (1.0f / 255.0f), aliasvertcolor[index*4+3] * (1.0f / 255.0f)); - glVertex3fv(&aliasvert[index*3]); - } - /* - } - else - { - for (i = 0;i < paliashdr->backfaces * 3;i++) - { - index = *in++; - glTexCoord2f(tex[index*2], tex[index*2+1]); - glColor4ub(aliasvertcolor[index*4], aliasvertcolor[index*4+1], aliasvertcolor[index*4+2], aliasvertcolor[index*4+3]); - glVertex3fv(&aliasvert[index*3]); - } - } - */ - glEnd(); - } - - if (fogenabled) - { - vec3_t diff; - glDisable (GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(0); // disable zbuffer updates - - VectorSubtract(currententity->origin, r_refdef.vieworg, diff); - glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff))); +} - if (gl_vertexarrays.value) - { - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - qglDrawElements(GL_TRIANGLES, paliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr)); - glDisableClientState(GL_VERTEX_ARRAY); - } - else - { - unsigned short *in; - in = (void *)((int) paliashdr->vertindices + (int) paliashdr); - glBegin(GL_TRIANGLES); - for (i = 0;i < paliashdr->numtris * 3;i++) - glVertex3fv(&aliasvert[*in++ * 3]); - glEnd(); - } +// only used if skyrendermasked, and normally returns false +int R_DrawBrushModelsSky (void) +{ + int i, sky; + entity_render_t *ent; - glEnable (GL_TEXTURE_2D); - glColor3f (1,1,1); - } + if (!r_drawentities.integer) + return false; - /* - if (r_shadows.value && !(currententity->effects & EF_ADDITIVE) && currententity != &cl.viewent) + sky = false; + for (i = 0;i < r_refdef.numentities;i++) { - // flatten it to make a shadow - float *av = aliasvert + 2, l = lightspot[2] + 0.125; - av = aliasvert + 2; - for (i = 0;i < paliashdr->numverts;i++, av+=3) - if (*av > l) - *av = l; - glDisable (GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(0); // disable zbuffer updates - glColor4f (0,0,0,0.5 * modelalpha); - - if (gl_vertexarrays.value) + ent = r_refdef.entities[i]; + if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky) { - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - qglDrawElements(GL_TRIANGLES, paliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) paliashdr->vertindices + (int) paliashdr)); - glDisableClientState(GL_VERTEX_ARRAY); + ent->model->DrawSky(ent); + sky = true; } - else - { - unsigned short *in; - in = (void *)((int) paliashdr->vertindices + (int) paliashdr); - glBegin(GL_TRIANGLES); - for (i = 0;i < paliashdr->numtris * 3;i++) - glVertex3fv(&aliasvert[*in++ * 3]); - glEnd(); - } - - glEnable (GL_TEXTURE_2D); - glColor3f (1,1,1); } - */ - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(1); + return sky; } -/* -================= -R_DrawQ2AliasFrame - -================= -*/ -void R_DrawQ2AliasFrame (md2mem_t *pheader) +void R_DrawNoModel(entity_render_t *ent); +void R_DrawModels(void) { - int *order, count, frame = currententity->frame; - float lerp; - md2memframe_t *frame1, *frame2; - - softwaretransformforentity(currententity); - - if ((frame >= pheader->num_frames) || (frame < 0)) - { - Con_DPrintf ("R_SetupQ2AliasFrame: no such frame %d\n", frame); - frame = 0; - } - - lerp = R_CalcAnimLerp(frame, 10); - - frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * currententity->draw_lastpose)); - frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * currententity->draw_pose)); - R_AliasLerpVerts(pheader->num_xyz, lerp, frame1->verts, frame1->scale, frame1->translate, frame2->verts, frame2->scale, frame2->translate); - - R_LightModel(pheader->num_xyz, currententity->origin); + int i; + entity_render_t *ent; - if (gl_vertexarrays.value) - { - // LordHavoc: big mess... - // using arrays only slightly, although it is enough to prevent duplicates - // (saving half the transforms) - //glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha); - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - order = (int *)((int)pheader + pheader->ofs_glcmds); - while(1) - { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); - else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - glTexCoord2f(((float *)order)[0], ((float *)order)[1]); - qglArrayElement(order[2]); - order += 3; - } - while (count--); - } + if (!r_drawentities.integer) + return; - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - } - else + for (i = 0;i < r_refdef.numentities;i++) { - order = (int *)((int)pheader + pheader->ofs_glcmds); - while(1) + ent = r_refdef.entities[i]; + if (ent->visframe == r_framecount) { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); + if (ent->model && ent->model->Draw != NULL) + ent->model->Draw(ent); else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - //if (isG200) - //{ - do - { - glTexCoord2f(((float *)order)[0], ((float *)order)[1]); - glColor4f(aliasvertcolor[order[2] * 4] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 1] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 2] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 3] * (1.0f / 255.0f)); - glVertex3fv(&aliasvert[order[2] * 3]); - order += 3; - } - while (count--); - /* - } - else - { - do - { - glTexCoord2f(((float *)order)[0], ((float *)order)[1]); - glColor4ub(aliasvertcolor[order[2] * 4], aliasvertcolor[order[2] * 4 + 1], aliasvertcolor[order[2] * 4 + 2], aliasvertcolor[order[2] * 4 + 3]); - glVertex3fv(&aliasvert[order[2] * 3]); - order += 3; - } - while (count--); - } - */ - } - } - - if (fogenabled) - { - glDisable (GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(0); // disable zbuffer updates - { - vec3_t diff; - VectorSubtract(currententity->origin, r_refdef.vieworg, diff); - glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff))); + R_DrawNoModel(ent); } - - if (gl_vertexarrays.value) - { - // LordHavoc: big mess... - // using arrays only slightly, although it is enough to prevent duplicates - // (saving half the transforms) - //glColor4f(shadecolor[0], shadecolor[1], shadecolor[2], modelalpha); - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - - order = (int *)((int)pheader + pheader->ofs_glcmds); - while(1) - { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); - else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - qglArrayElement(order[2]); - order += 3; - } - while (count--); - } - - glDisableClientState(GL_VERTEX_ARRAY); - } - else - { - order = (int *)((int)pheader + pheader->ofs_glcmds); - while(1) - { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); - else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - glVertex3fv(&aliasvert[order[2] * 3]); - order += 3; - } - while (count--); - } - } - - glEnable (GL_TEXTURE_2D); - glColor3f (1,1,1); } - - /* - if (r_shadows.value && !(currententity->effects & EF_ADDITIVE) && currententity != &cl.viewent) - { - int i; - float *av = aliasvert + 2, l = lightspot[2] + 0.125; - av = aliasvert + 2; - for (i = 0;i < pheader->num_xyz;i++, av+=3) - if (*av > l) - *av = l; - glDisable (GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(0); // disable zbuffer updates - glColor4f (0,0,0,0.5 * modelalpha); - - if (gl_vertexarrays.value) - { - qglVertexPointer(3, GL_FLOAT, 0, aliasvert); - glEnableClientState(GL_VERTEX_ARRAY); - - while(1) - { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); - else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - qglArrayElement(order[2]); - order += 3; - } - while (count--); - } - - glDisableClientState(GL_VERTEX_ARRAY); - } - else - { - while(1) - { - if (!(count = *order++)) - break; - if (count > 0) - glBegin(GL_TRIANGLE_STRIP); - else - { - glBegin(GL_TRIANGLE_FAN); - count = -count; - } - do - { - glVertex3fv(&aliasvert[order[2] * 3]); - order += 3; - } - while (count--); - } - } - - glEnable (GL_TEXTURE_2D); - glColor3f (1,1,1); - } - */ - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable (GL_BLEND); - glDepthMask(1); } -/* -================= -R_DrawAliasModel - -================= -*/ -void R_DrawAliasModel (entity_t *e, int cull) +static void R_SetFrustum(void) { - int i; - model_t *clmodel; - vec3_t mins, maxs; - aliashdr_t *paliashdr; - md2mem_t *pheader; - int anim; - - if (modelalpha < (1.0 / 64.0)) - return; // basically completely transparent - - clmodel = currententity->model; + // break apart the view matrix into vectors for various purposes + Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin); + VectorNegate(r_viewleft, r_viewright); + + // LordHavoc: note to all quake engine coders, the special case for 90 + // degrees assumed a square view (wrong), so I removed it, Quake2 has it + // disabled as well. + + // rotate R_VIEWFORWARD right by FOV_X/2 degrees + RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2)); + frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal); + PlaneClassify(&frustum[0]); + + // rotate R_VIEWFORWARD left by FOV_X/2 degrees + RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2)); + frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal); + PlaneClassify(&frustum[1]); + + // rotate R_VIEWFORWARD up by FOV_X/2 degrees + RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2)); + frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal); + PlaneClassify(&frustum[2]); + + // rotate R_VIEWFORWARD down by FOV_X/2 degrees + RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2)); + frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal); + PlaneClassify(&frustum[3]); +} - VectorAdd (currententity->origin, clmodel->mins, mins); - VectorAdd (currententity->origin, clmodel->maxs, maxs); +static void R_BlendView(void) +{ + rmeshstate_t m; + float r; + float vertex3f[3*3]; - if (cull && R_CullBox (mins, maxs)) + if (r_refdef.viewblend[3] < 0.01f) return; - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - - // get lighting information - - if (currententity->model->flags & EF_FULLBRIGHT || currententity->effects & EF_FULLBRIGHT) - { - shadecolor[0] = currententity->colormod[0] * 256; - shadecolor[1] = currententity->colormod[1] * 256; - shadecolor[2] = currententity->colormod[2] * 256; - } - else - { - R_LightPoint (shadecolor, currententity->origin); - - // HACK HACK HACK -- no fullbright colors, so make torches full light - if (!strcmp (currententity->model->name, "progs/flame2.mdl") || !strcmp (currententity->model->name, "progs/flame.mdl") ) - shadecolor[0] = shadecolor[1] = shadecolor[2] = 128; - - shadecolor[0] *= currententity->colormod[0]; - shadecolor[1] *= currententity->colormod[1]; - shadecolor[2] *= currententity->colormod[2]; - } - - // locate the proper data - if (clmodel->aliastype == ALIASTYPE_MD2) - { - pheader = (void *)Mod_Extradata (currententity->model); - c_alias_polys += pheader->num_tris; - } - else - { - paliashdr = (void *)Mod_Extradata (currententity->model); - c_alias_polys += paliashdr->numtris; - } + R_Mesh_Matrix(&r_identitymatrix); + + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + R_Mesh_State(&m); + + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(true); + GL_DepthTest(false); // magic + GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]); + r = 64; + vertex3f[0] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r - r_viewup[0] * r; + vertex3f[1] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r - r_viewup[1] * r; + vertex3f[2] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r - r_viewup[2] * r; + vertex3f[3] = r_vieworigin[0] + r_viewforward[0] * 1.5 + r_viewleft[0] * r + r_viewup[0] * r * 3; + vertex3f[4] = r_vieworigin[1] + r_viewforward[1] * 1.5 + r_viewleft[1] * r + r_viewup[1] * r * 3; + vertex3f[5] = r_vieworigin[2] + r_viewforward[2] * 1.5 + r_viewleft[2] * r + r_viewup[2] * r * 3; + vertex3f[6] = r_vieworigin[0] + r_viewforward[0] * 1.5 - r_viewleft[0] * r * 3 - r_viewup[0] * r; + vertex3f[7] = r_vieworigin[1] + r_viewforward[1] * 1.5 - r_viewleft[1] * r * 3 - r_viewup[1] * r; + vertex3f[8] = r_vieworigin[2] + r_viewforward[2] * 1.5 - r_viewleft[2] * r * 3 - r_viewup[2] * r; + R_Mesh_Draw(3, 1, polygonelements); +} - // draw all the triangles +void R_UpdateWorld(void) +{ + if (!r_refdef.entities/* || !cl.worldmodel*/) + return; //Host_Error ("R_RenderView: NULL worldmodel"); - if (clmodel->aliastype == ALIASTYPE_MD2) - { - if (currententity->skinnum < 0 || currententity->skinnum >= pheader->num_skins) - { - currententity->skinnum = 0; - Con_DPrintf("invalid skin number %d for model %s\n", currententity->skinnum, clmodel->name); - } - glBindTexture(GL_TEXTURE_2D, pheader->gl_texturenum[currententity->skinnum]); - } - else + /* + if (r_shadow_realtime_world.integer && !gl_stencil) { - if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins) - { - currententity->skinnum = 0; - Con_DPrintf("invalid skin number %d for model %s\n", currententity->skinnum, clmodel->name); - } - anim = (int)(cl.time*10) & 3; - glBindTexture(GL_TEXTURE_2D, paliashdr->gl_texturenum[currententity->skinnum][anim]); + Con_Print("Realtime world lighting requires 32bit color; turning off r_shadow_realtime_world, please type vid_bitsperpixel 32;vid_restart and try again\n"); + Cvar_SetValueQuick(&r_shadow_realtime_world, 0); } - glDisable(GL_ALPHA_TEST); - glEnable (GL_TEXTURE_2D); + */ - // we can't dynamically colormap textures, so they are cached - // seperately for the players. Heads are just uncolored. - if (currententity->colormap != vid.colormap/* && !gl_nocolors.value*/) + // don't allow cheats in multiplayer + if (!cl.islocalgame && cl.worldmodel) { - i = currententity - cl_entities; - if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) - glBindTexture(GL_TEXTURE_2D, playertextures - 1 + i); + if (r_fullbright.integer != 0) + Cvar_Set ("r_fullbright", "0"); + if (r_ambient.value != 0) + Cvar_Set ("r_ambient", "0"); } -// if (gl_affinemodels.value) -// glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - if (clmodel->aliastype == ALIASTYPE_MD2) - R_DrawQ2AliasFrame (pheader); - else - R_DrawAliasFrame (paliashdr); - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + R_Textures_Frame(); + R_UpdateFog(); + R_UpdateLights(); } -//================================================================================== - -void R_DrawBrushModel (entity_t *e); +void R_RenderScene(void); /* -============= -R_DrawEntitiesOnList -============= +================ +R_RenderView +================ */ -// LordHavoc: split so bmodels are rendered before any other objects -void R_DrawEntitiesOnList1 (void) +void R_RenderView(void) { - int i; - - if (!r_drawentities.value) - return; - - for (i=0 ; imodel->type != mod_brush) - continue; - currententity = cl_visedicts[i]; - modelalpha = currententity->alpha; - - R_DrawBrushModel (currententity); - } + if (!r_refdef.entities/* || !cl.worldmodel*/) + return; //Host_Error ("R_RenderView: NULL worldmodel"); + + r_view_width = bound(0, r_refdef.width, vid.realwidth); + r_view_height = bound(0, r_refdef.height, vid.realheight); + r_view_depth = 1; + r_view_x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width); + r_view_y = bound(0, r_refdef.y, vid.realheight - r_refdef.height); + r_view_z = 0; + r_view_fov_x = bound(1, r_refdef.fov_x, 170); + r_view_fov_y = bound(1, r_refdef.fov_y, 170); + r_view_matrix = r_refdef.viewentitymatrix; + GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1); + r_rtworld = r_shadow_realtime_world.integer; + r_rtworldshadows = r_rtworld && r_shadow_realtime_world_shadows.integer; + r_rtdlight = r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer; + r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer); + r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1; + + // GL is weird because it's bottom to top, r_view_y is top to bottom + qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height); + GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height); + GL_ScissorTest(true); + GL_DepthMask(true); + R_ClearScreen(); + R_TimeReport("setup"); + + qglDepthFunc(GL_LEQUAL); + qglPolygonOffset(0, 0); + qglEnable(GL_POLYGON_OFFSET_FILL); + + R_RenderScene(); + + qglPolygonOffset(0, 0); + qglDisable(GL_POLYGON_OFFSET_FILL); + + R_BlendView(); + R_TimeReport("blendview"); + + GL_Scissor(0, 0, vid.realwidth, vid.realheight); + GL_ScissorTest(false); } -void R_DrawEntitiesOnList2 (void) +extern void R_DrawLightningBeams (void); +void R_RenderScene(void) { - int i; + entity_render_t *world; + + // don't let sound skip if going slow + if (!intimerefresh && !r_speeds.integer) + S_ExtraUpdate (); - if (!r_drawentities.value) - return; + r_framecount++; - for (i=0 ; ialpha; + R_MeshQueue_BeginScene(); - switch (currententity->model->type) - { - case mod_alias: - R_DrawAliasModel (currententity, true); - break; + GL_ShowTrisColor(0.05, 0.05, 0.05, 1); - case mod_sprite: - R_DrawSpriteModel (currententity); - break; + R_SetFrustum(); - default: - break; - } - } -} + r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f; + if (gl_stencil && (r_rtworldshadows || r_rtdlightshadows)) + GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f); + else + GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip); -/* -============= -R_DrawViewModel -============= -*/ -void R_DrawViewModel (void) -{ - if (!r_drawviewmodel.value || chase_active.value || envmap || !r_drawentities.value || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.model) - return; + GL_SetupView_Orientation_FromEntity(&r_view_matrix); - currententity = &cl.viewent; - currententity->alpha = modelalpha = cl_entities[cl.viewentity].alpha; // LordHavoc: if the player is transparent, so is his gun - currententity->effects = cl_entities[cl.viewentity].effects; - currententity->scale = 1; - VectorCopy(cl_entities[cl.viewentity].colormod, currententity->colormod); + R_SkyStartFrame(); - // hack the depth range to prevent view model from poking into walls - glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); - R_DrawAliasModel (currententity, FALSE); - glDepthRange (gldepthmin, gldepthmax); -} + if (cl.worldmodel && cl.worldmodel->brush.FatPVS) + cl.worldmodel->brush.FatPVS(cl.worldmodel, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits)); + world = &cl_entities[0].render; + R_WorldVisibility(world); + R_TimeReport("worldvis"); -void R_DrawBrushModel (entity_t *e); + R_MarkEntities(); + R_TimeReport("markentity"); -void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ); + R_Shadow_UpdateWorldLightSelection(); -void R_SetFrustum (void) -{ - int i; + // don't let sound skip if going slow + if (!intimerefresh && !r_speeds.integer) + S_ExtraUpdate (); - if (r_refdef.fov_x == 90) + GL_ShowTrisColor(0.025, 0.025, 0, 1); + if (world->model && world->model->DrawSky) { - // front side is visible + world->model->DrawSky(world); + R_TimeReport("worldsky"); + } - VectorAdd (vpn, vright, frustum[0].normal); - VectorSubtract (vpn, vright, frustum[1].normal); + if (R_DrawBrushModelsSky()) + R_TimeReport("bmodelsky"); - VectorAdd (vpn, vup, frustum[2].normal); - VectorSubtract (vpn, vup, frustum[3].normal); - } - else + GL_ShowTrisColor(0.05, 0.05, 0.05, 1); + if (world->model && world->model->Draw) { - // 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 - RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 ); - // rotate VPN up by FOV_X/2 degrees - RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 ); - // rotate VPN down by FOV_X/2 degrees - RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) ); + world->model->Draw(world); + R_TimeReport("world"); } - for (i=0 ; i<4 ; i++) - { - frustum[i].type = PLANE_ANYZ; - frustum[i].dist = DotProduct (r_origin, frustum[i].normal); -// frustum[i].signbits = SignbitsForPlane (&frustum[i]); - BoxOnPlaneSideClassify(&frustum[i]); - } -} + // don't let sound skip if going slow + if (!intimerefresh && !r_speeds.integer) + S_ExtraUpdate (); -void R_AnimateLight (void); -void V_CalcBlend (void); + GL_ShowTrisColor(0, 0.015, 0, 1); -/* -=============== -R_SetupFrame -=============== -*/ -void R_SetupFrame (void) -{ -// don't allow cheats in multiplayer - if (cl.maxclients > 1) - Cvar_Set ("r_fullbright", "0"); + R_DrawModels(); + R_TimeReport("models"); - R_AnimateLight (); + // don't let sound skip if going slow + if (!intimerefresh && !r_speeds.integer) + S_ExtraUpdate (); - r_framecount++; + GL_ShowTrisColor(0, 0, 0.033, 1); + R_ShadowVolumeLighting(false); + R_TimeReport("rtlights"); -// build the transformation matrix for the given view angles - VectorCopy (r_refdef.vieworg, r_origin); + // don't let sound skip if going slow + if (!intimerefresh && !r_speeds.integer) + S_ExtraUpdate (); - AngleVectors (r_refdef.viewangles, vpn, vright, vup); + GL_ShowTrisColor(0.1, 0, 0, 1); -// current viewleaf - r_oldviewleaf = r_viewleaf; - r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); + R_DrawLightningBeams(); + R_TimeReport("lightning"); - V_SetContentsColor (r_viewleaf->contents); - V_CalcBlend (); + R_DrawParticles(); + R_TimeReport("particles"); - r_cache_thrash = false; + R_DrawExplosions(); + R_TimeReport("explosions"); - c_brush_polys = 0; - c_alias_polys = 0; + R_MeshQueue_RenderTransparent(); + R_TimeReport("drawtrans"); -} + R_DrawCoronas(); + R_TimeReport("coronas"); + R_DrawWorldCrosshair(); + R_TimeReport("crosshair"); -void MYgluPerspective( GLdouble fovy, GLdouble aspect, - GLdouble zNear, GLdouble zFar ) -{ - GLdouble xmin, xmax, ymin, ymax; + R_MeshQueue_Render(); + R_MeshQueue_EndScene(); - ymax = zNear * tan( fovy * M_PI / 360.0 ); - ymin = -ymax; + if (r_shadow_visiblevolumes.integer && !r_showtrispass) + { + R_ShadowVolumeLighting(true); + R_TimeReport("shadowvolume"); + } - xmin = ymin * aspect; - xmax = ymax * aspect; + GL_ShowTrisColor(0.05, 0.05, 0.05, 1); - glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); + // don't let sound skip if going slow + if (!intimerefresh && !r_speeds.integer) + S_ExtraUpdate (); } - -extern char skyname[]; - /* -============= -R_SetupGL -============= -*/ -void R_SetupGL (void) +void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca) { - float screenaspect; - extern int glwidth, glheight; - int x, x2, y2, y, w, h; - - // - // set up viewpoint - // - glMatrixMode(GL_PROJECTION); - glLoadIdentity (); - x = r_refdef.vrect.x * glwidth/vid.width; - x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width; - y = (vid.height-r_refdef.vrect.y) * glheight/vid.height; - y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height; - - // fudge around because of frac screen scale - if (x > 0) - x--; - if (x2 < glwidth) - x2++; - if (y2 < 0) - y2--; - if (y < glheight) - y++; - - w = x2 - x; - h = y - y2; - - if (envmap) + int i; + float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4]; + rmeshstate_t m; + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); + GL_DepthTest(true); + R_Mesh_Matrix(&r_identitymatrix); + + vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; + vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2]; + vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2]; + vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2]; + vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2]; + vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2]; + vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2]; + vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2]; + R_FillColors(color, 8, cr, cg, cb, ca); + if (fogenabled) { - x = y2 = 0; - w = h = 256; - } - - 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; -// if (skyname[0]) // skybox enabled? -// MYgluPerspective (r_refdef.fov_y, screenaspect, 4, r_skyboxsize.value*1.732050807569 + 256); // this is size*sqrt(3) + 256 -// else - MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 6144); - - glCullFace(GL_FRONT); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); - - glRotatef (-90, 1, 0, 0); // put Z going up - glRotatef (90, 0, 0, 1); // put Z going up - glRotatef (-r_refdef.viewangles[2], 1, 0, 0); - glRotatef (-r_refdef.viewangles[0], 0, 1, 0); - glRotatef (-r_refdef.viewangles[1], 0, 0, 1); - glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); - - glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); - - // - // set drawing parms - // -// if (gl_cull.value) - glEnable(GL_CULL_FACE); -// else -// glDisable(GL_CULL_FACE); - - glEnable(GL_BLEND); // was Disable - glDisable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.5); - glEnable(GL_DEPTH_TEST); - glDepthMask(1); - glShadeModel(GL_SMOOTH); + for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4) + { + VectorSubtract(v, r_vieworigin, diff); + f2 = exp(fogdensity/DotProduct(diff, diff)); + f1 = 1 - f2; + c[0] = c[0] * f1 + fogcolor[0] * f2; + c[1] = c[1] * f1 + fogcolor[1] * f2; + c[2] = c[2] * f1 + fogcolor[2] * f2; + } + } + memset(&m, 0, sizeof(m)); + m.pointer_vertex = vertex3f; + m.pointer_color = color; + R_Mesh_State(&m); + R_Mesh_Draw(8, 12); } +*/ -void R_DrawWorld (void); -//void R_RenderDlights (void); -void R_DrawParticles (void); +int nomodelelements[24] = +{ + 5, 2, 0, + 5, 1, 2, + 5, 0, 3, + 5, 3, 1, + 0, 2, 4, + 2, 1, 4, + 3, 0, 4, + 1, 3, 4 +}; -/* -============= -R_Clear -============= -*/ -void R_Clear (void) +float nomodelvertex3f[6*3] = { -// glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen - gldepthmin = 0; - gldepthmax = 1; - glDepthFunc (GL_LEQUAL); + -16, 0, 0, + 16, 0, 0, + 0, -16, 0, + 0, 16, 0, + 0, 0, -16, + 0, 0, 16 +}; - glDepthRange (gldepthmin, gldepthmax); -} +float nomodelcolor4f[6*4] = +{ + 0.0f, 0.0f, 0.5f, 1.0f, + 0.0f, 0.0f, 0.5f, 1.0f, + 0.0f, 0.5f, 0.0f, 1.0f, + 0.0f, 0.5f, 0.0f, 1.0f, + 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, 0.0f, 0.0f, 1.0f +}; -// LordHavoc: my trick to *FIX* GLQuake lighting once and for all :) -void GL_Brighten() +void R_DrawNoModelCallback(const void *calldata1, int calldata2) { - glMatrixMode(GL_PROJECTION); - glLoadIdentity (); - glOrtho (0, vid.width, vid.height, 0, -99999, 99999); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); - glDisable (GL_DEPTH_TEST); - glDisable (GL_CULL_FACE); - glDisable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc (GL_DST_COLOR, GL_ONE); - glBegin (GL_TRIANGLES); - glColor3f (1, 1, 1); - glVertex2f (-5000, -5000); - glVertex2f (10000, -5000); - glVertex2f (-5000, 10000); - glEnd (); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glEnable (GL_DEPTH_TEST); - glEnable (GL_CULL_FACE); -} + const entity_render_t *ent = calldata1; + int i; + float f1, f2, *c, diff[3]; + float color4f[6*4]; + rmeshstate_t m; + R_Mesh_Matrix(&ent->matrix); -extern cvar_t contrast; -extern cvar_t brightness; -extern cvar_t gl_lightmode; + memset(&m, 0, sizeof(m)); + m.pointer_vertex = nomodelvertex3f; -void GL_BlendView() -{ - glMatrixMode(GL_PROJECTION); - glLoadIdentity (); - glOrtho (0, vid.width, vid.height, 0, -99999, 99999); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); - glDisable (GL_DEPTH_TEST); - glDisable (GL_CULL_FACE); - glDisable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - if (lighthalf) + if (ent->flags & EF_ADDITIVE) { - glBlendFunc (GL_DST_COLOR, GL_ONE); - glBegin (GL_TRIANGLES); - glColor3f (1, 1, 1); - glVertex2f (-5000, -5000); - glVertex2f (10000, -5000); - glVertex2f (-5000, 10000); - glEnd (); + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); + GL_DepthMask(false); } - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - contrast.value = bound(0.2, contrast.value, 1.0); - if (/*gl_polyblend.value && */v_blend[3]) + else if (ent->alpha < 1) { - glBegin (GL_TRIANGLES); - glColor4fv (v_blend); - glVertex2f (-5000, -5000); - glVertex2f (10000, -5000); - glVertex2f (-5000, 10000); - glEnd (); + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_DepthMask(false); } - - glEnable (GL_CULL_FACE); - glEnable (GL_DEPTH_TEST); - glDisable(GL_BLEND); - glEnable(GL_TEXTURE_2D); -} - -#define TIMEREPORT(DESC) \ - if (r_speeds2.value)\ - {\ - temptime = -currtime;\ - currtime = Sys_FloatTime();\ - temptime += currtime;\ - Con_Printf(DESC " %.4fms ", temptime * 1000.0);\ + else + { + GL_BlendFunc(GL_ONE, GL_ZERO); + GL_DepthMask(true); } + GL_DepthTest(true); + if (fogenabled) + { + memcpy(color4f, nomodelcolor4f, sizeof(float[6*4])); + m.pointer_color = color4f; + VectorSubtract(ent->origin, r_vieworigin, diff); + f2 = exp(fogdensity/DotProduct(diff, diff)); + f1 = 1 - f2; + for (i = 0, c = color4f;i < 6;i++, c += 4) + { + c[0] = (c[0] * f1 + fogcolor[0] * f2); + c[1] = (c[1] * f1 + fogcolor[1] * f2); + c[2] = (c[2] * f1 + fogcolor[2] * f2); + c[3] *= ent->alpha; + } + } + else if (ent->alpha != 1) + { + memcpy(color4f, nomodelcolor4f, sizeof(float[6*4])); + m.pointer_color = color4f; + for (i = 0, c = color4f;i < 6;i++, c += 4) + c[3] *= ent->alpha; + } + else + m.pointer_color = nomodelcolor4f; + R_Mesh_State(&m); + R_Mesh_Draw(6, 8, nomodelelements); +} -/* -================ -R_RenderView - -r_refdef must be set before the first call -================ -*/ -void R_RenderView (void) +void R_DrawNoModel(entity_render_t *ent) { - double currtime, temptime; -// if (r_norefresh.value) -// return; + //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1)) + R_MeshQueue_AddTransparent(ent->origin, R_DrawNoModelCallback, ent, 0); + //else + // R_DrawNoModelCallback(ent, 0); +} - if (!r_worldentity.model || !cl.worldmodel) - Sys_Error ("R_RenderView: NULL worldmodel"); +void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width) +{ + vec3_t right1, right2, diff, normal; + + VectorSubtract (org2, org1, normal); + VectorNormalizeFast (normal); + + // calculate 'right' vector for start + VectorSubtract (r_vieworigin, org1, diff); + VectorNormalizeFast (diff); + CrossProduct (normal, diff, right1); + + // calculate 'right' vector for end + VectorSubtract (r_vieworigin, org2, diff); + VectorNormalizeFast (diff); + CrossProduct (normal, diff, right2); + + vert[ 0] = org1[0] + width * right1[0]; + vert[ 1] = org1[1] + width * right1[1]; + vert[ 2] = org1[2] + width * right1[2]; + vert[ 3] = org1[0] - width * right1[0]; + vert[ 4] = org1[1] - width * right1[1]; + vert[ 5] = org1[2] - width * right1[2]; + vert[ 6] = org2[0] - width * right2[0]; + vert[ 7] = org2[1] - width * right2[1]; + vert[ 8] = org2[2] - width * right2[2]; + vert[ 9] = org2[0] + width * right2[0]; + vert[10] = org2[1] + width * right2[1]; + vert[11] = org2[2] + width * right2[2]; +} - lighthalf = gl_lightmode.value; +float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1}; - FOG_framebegin(); - transpolyclear(); - wallpolyclear(); +void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca) +{ + float diff[3]; + rmeshstate_t m; - if (r_speeds2.value) + if (fogenabled) { - currtime = Sys_FloatTime(); - Con_Printf("render time: "); - } - R_Clear(); - TIMEREPORT("R_Clear") - - // render normal view - - R_SetupFrame (); - TIMEREPORT("R_SetupFrame") - R_SetFrustum (); - TIMEREPORT("R_SetFrustum") - R_SetupGL (); - TIMEREPORT("R_SetupGL") - R_MarkLeaves (); // done here so we know if we're in water - TIMEREPORT("R_MarkLeaves") - R_DrawWorld (); // adds static entities to the list - TIMEREPORT("R_DrawWorld") - S_ExtraUpdate (); // don't let sound get messed up if going slow - TIMEREPORT("S_ExtraUpdate") - R_DrawEntitiesOnList1 (); // BSP models - TIMEREPORT("R_DrawEntitiesOnList1") - wallpolyrender(); - TIMEREPORT("wallpolyrender") - R_DrawEntitiesOnList2 (); // other models - TIMEREPORT("R_DrawEntitiesOnList2") -// R_RenderDlights (); - R_DrawViewModel (); - TIMEREPORT("R_DrawViewModel") - R_DrawParticles (); - TIMEREPORT("R_DrawParticles") - transpolyrender(); - TIMEREPORT("transpolyrender") - - FOG_frameend(); - GL_BlendView(); - TIMEREPORT("GL_BlendView") - if (r_speeds2.value) - Con_Printf("\n"); + VectorSubtract(origin, r_vieworigin, diff); + ca *= 1 - exp(fogdensity/DotProduct(diff,diff)); + } + + R_Mesh_Matrix(&r_identitymatrix); + GL_BlendFunc(blendfunc1, blendfunc2); + GL_DepthMask(false); + GL_DepthTest(!depthdisable); + + varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1; + varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1; + varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1; + varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2; + varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2; + varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2; + varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2; + varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2; + varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2; + varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1; + varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1; + varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1; + + memset(&m, 0, sizeof(m)); + m.tex[0] = R_GetTexture(texture); + m.pointer_texcoord[0] = spritetexcoord2f; + m.pointer_vertex = varray_vertex3f; + R_Mesh_State(&m); + GL_Color(cr, cg, cb, ca); + R_Mesh_Draw(4, 2, polygonelements); } +