64b0e9b85df044a45684f37323e15fe12c7bf9ad
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23
24 entity_t        r_worldentity;
25
26 qboolean        r_cache_thrash;         // compatability
27
28 vec3_t          modelorg, r_entorigin;
29 entity_t        *currententity;
30
31 int                     r_visframecount;        // bumped when going to a new PVS
32 int                     r_framecount;           // used for dlight push checking
33
34 mplane_t        frustum[4];
35
36 int                     c_brush_polys, c_alias_polys, c_light_polys, c_nodes, c_leafs;
37
38 qboolean        envmap;                         // true during envmap command capture 
39
40 // LordHavoc: moved all code related to particles into r_part.c
41 //int                   particletexture;        // little dot for particles
42 //int                   playertextures;         // up to 16 color translated skins
43
44 extern qboolean isG200, isRagePro; // LordHavoc: special card hacks
45
46 //
47 // view origin
48 //
49 vec3_t  vup;
50 vec3_t  vpn;
51 vec3_t  vright;
52 vec3_t  r_origin;
53
54 float   r_world_matrix[16];
55 float   r_base_world_matrix[16];
56
57 //
58 // screen size info
59 //
60 refdef_t        r_refdef;
61
62 mleaf_t         *r_viewleaf, *r_oldviewleaf;
63
64 texture_t       *r_notexture_mip;
65
66 unsigned short  d_lightstylevalue[256]; // 8.8 fraction of base light value
67
68
69 void R_MarkLeaves (void);
70
71 //cvar_t        r_norefresh = {"r_norefresh","0"};
72 cvar_t  r_drawentities = {"r_drawentities","1"};
73 cvar_t  r_drawviewmodel = {"r_drawviewmodel","1"};
74 cvar_t  r_speeds = {"r_speeds","0"};
75 cvar_t  r_speeds2 = {"r_speeds2","0"};
76 cvar_t  r_fullbright = {"r_fullbright","0"};
77 //cvar_t        r_lightmap = {"r_lightmap","0"};
78 cvar_t  r_shadows = {"r_shadows","0"};
79 cvar_t  r_wateralpha = {"r_wateralpha","1"};
80 cvar_t  r_dynamic = {"r_dynamic","1"};
81 cvar_t  r_novis = {"r_novis","0"};
82 cvar_t  r_waterripple = {"r_waterripple","0"};
83 cvar_t  r_fullbrights = {"r_fullbrights", "1"};
84
85 cvar_t  contrast = {"contrast", "1.0", TRUE}; // LordHavoc: a method of operating system independent color correction
86 cvar_t  brightness = {"brightness", "1.0", TRUE}; // LordHavoc: a method of operating system independent color correction
87 cvar_t  gl_lightmode = {"gl_lightmode", "1", TRUE}; // LordHavoc: overbright lighting
88 //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...
89 cvar_t  r_farclip = {"r_farclip", "6144"};
90
91 cvar_t  gl_fogenable = {"gl_fogenable", "0"};
92 cvar_t  gl_fogdensity = {"gl_fogdensity", "0.25"};
93 cvar_t  gl_fogred = {"gl_fogred","0.3"};
94 cvar_t  gl_foggreen = {"gl_foggreen","0.3"};
95 cvar_t  gl_fogblue = {"gl_fogblue","0.3"};
96 cvar_t  gl_fogstart = {"gl_fogstart", "0"};
97 cvar_t  gl_fogend = {"gl_fogend","0"};
98 cvar_t  glfog = {"glfog", "0"};
99
100 extern qboolean isRagePro;
101
102 qboolean lighthalf;
103
104 vec3_t fogcolor;
105 vec_t fogdensity;
106 float fog_density, fog_red, fog_green, fog_blue;
107 qboolean fogenabled;
108 qboolean oldgl_fogenable;
109 void FOG_framebegin()
110 {
111         if (nehahra)
112         {
113 //              if (!Nehahrademcompatibility)
114 //                      gl_fogenable.value = 0;
115                 if (gl_fogenable.value)
116                 {
117                         oldgl_fogenable = true;
118                         fog_density = gl_fogdensity.value;
119                         fog_red = gl_fogred.value;
120                         fog_green = gl_foggreen.value;
121                         fog_blue = gl_fogblue.value;
122                 }
123                 else if (oldgl_fogenable)
124                 {
125                         oldgl_fogenable = false;
126                         fog_density = 0;
127                         fog_red = 0;
128                         fog_green = 0;
129                         fog_blue = 0;
130                 }
131         }
132         if (glfog.value)
133         {
134                 if (!r_render.value)
135                         return;
136                 if(fog_density)
137                 {
138                         // LordHavoc: Borland C++ 5.0 was choking on this line, stupid compiler...
139                         //GLfloat colors[4] = {(GLfloat) gl_fogred.value, (GLfloat) gl_foggreen.value, (GLfloat) gl_fogblue.value, (GLfloat) 1};
140                         GLfloat colors[4];
141                         colors[0] = fog_red;
142                         colors[1] = fog_green;
143                         colors[2] = fog_blue;
144                         colors[3] = 1;
145                         if (lighthalf)
146                         {
147                                 colors[0] *= 0.5f;
148                                 colors[1] *= 0.5f;
149                                 colors[2] *= 0.5f;
150                         }
151
152                         glFogi (GL_FOG_MODE, GL_EXP2);
153                         glFogf (GL_FOG_DENSITY, (GLfloat) fog_density / 100); 
154                         glFogfv (GL_FOG_COLOR, colors);
155                         glEnable (GL_FOG);
156                 }
157                 else
158                         glDisable(GL_FOG);
159         }
160         else
161         {
162                 if (fog_density)
163                 {
164                         fogenabled = true;
165                         fogdensity = -4000.0f / (fog_density * fog_density);
166                         fogcolor[0] = fog_red   = bound(0.0f, fog_red  , 1.0f);
167                         fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
168                         fogcolor[2] = fog_blue  = bound(0.0f, fog_blue , 1.0f);
169                         if (lighthalf)
170                         {
171                                 fogcolor[0] *= 0.5f;
172                                 fogcolor[1] *= 0.5f;
173                                 fogcolor[2] *= 0.5f;
174                         }
175                 }
176                 else
177                         fogenabled = false;
178         }
179 }
180
181 void FOG_frameend()
182 {
183         if (glfog.value)
184                 glDisable(GL_FOG);
185 }
186
187 void FOG_clear()
188 {
189         if (nehahra)
190         {
191                 Cvar_Set("gl_fogenable", "0");
192                 Cvar_Set("gl_fogdensity", "0.2");
193                 Cvar_Set("gl_fogred", "0.3");
194                 Cvar_Set("gl_foggreen", "0.3");
195                 Cvar_Set("gl_fogblue", "0.3");
196         }
197         fog_density = fog_red = fog_green = fog_blue = 0.0f;
198 }
199
200 void FOG_registercvars()
201 {
202         Cvar_RegisterVariable (&glfog);
203         if (nehahra)
204         {
205                 Cvar_RegisterVariable (&gl_fogenable);
206                 Cvar_RegisterVariable (&gl_fogdensity);
207                 Cvar_RegisterVariable (&gl_fogred);
208                 Cvar_RegisterVariable (&gl_foggreen); 
209                 Cvar_RegisterVariable (&gl_fogblue);
210                 Cvar_RegisterVariable (&gl_fogstart);
211                 Cvar_RegisterVariable (&gl_fogend);
212         }
213 }
214
215 void glmain_start()
216 {
217 }
218
219 void glmain_shutdown()
220 {
221 }
222
223 void GL_Main_Init()
224 {
225         FOG_registercvars();
226         Cvar_RegisterVariable (&r_speeds2);
227         Cvar_RegisterVariable (&contrast);
228         Cvar_RegisterVariable (&brightness);
229         Cvar_RegisterVariable (&gl_lightmode);
230 //      Cvar_RegisterVariable (&r_dynamicwater);
231 //      Cvar_RegisterVariable (&r_dynamicbothsides);
232         Cvar_RegisterVariable (&r_fullbrights);
233         if (nehahra)
234                 Cvar_SetValue("r_fullbrights", 0);
235 //      if (gl_vendor && strstr(gl_vendor, "3Dfx"))
236 //              gl_lightmode.value = 0;
237         Cvar_RegisterVariable (&r_fullbright);
238         R_RegisterModule("GL_Main", glmain_start, glmain_shutdown);
239 }
240
241 extern void GL_Draw_Init();
242 extern void GL_Main_Init();
243 extern void GL_Models_Init();
244 extern void GL_Poly_Init();
245 extern void GL_Surf_Init();
246 extern void GL_Screen_Init();
247 extern void GL_Misc_Init();
248 extern void R_Crosshairs_Init();
249 extern void R_Light_Init();
250 extern void R_Particles_Init();
251
252 void Render_Init()
253 {
254         R_ShutdownModules();
255         GL_Draw_Init();
256         GL_Main_Init();
257         GL_Models_Init();
258         GL_Poly_Init();
259         GL_Surf_Init();
260         GL_Screen_Init();
261         GL_Misc_Init();
262         R_Crosshairs_Init();
263         R_Light_Init();
264         R_Particles_Init();
265         R_StartModules();
266 }
267
268 /*
269 void R_RotateForEntity (entity_t *e)
270 {
271         glTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
272
273         glRotatef (e->angles[1],  0, 0, 1);
274         glRotatef (-e->angles[0],  0, 1, 0);
275         glRotatef (e->angles[2],  1, 0, 0);
276
277         glScalef (e->scale, e->scale, e->scale); // LordHavoc: model scale
278 }
279 */
280
281 // LordHavoc: if not for the fact BRIGHTFIELD particles require this, it would be removed...
282 #define NUMVERTEXNORMALS        162
283
284 float   r_avertexnormals[NUMVERTEXNORMALS][3] = {
285 #include "anorms.h"
286 };
287
288 // LordHavoc: moved this shading stuff up because the sprites need shading stuff
289 vec3_t  shadevector;
290 vec3_t  shadecolor;
291
292 float   modelalpha;
293
294 extern void R_LightPoint (vec3_t color, vec3_t p);
295 extern void R_DynamicLightPoint(vec3_t color, vec3_t org, int *dlightbits);
296 extern void R_DynamicLightPointNoMask(vec3_t color, vec3_t org);
297
298 /*
299 =============================================================
300
301   SPRITE MODELS
302
303 =============================================================
304 */
305
306 /*
307 ================
308 R_GetSpriteFrame
309 ================
310 */
311 void R_GetSpriteFrame (entity_t *currententity, mspriteframe_t **oldframe, mspriteframe_t **newframe, float *framelerp)
312 {
313         msprite_t               *psprite;
314         mspritegroup_t  *pspritegroup;
315         int                             i, j, numframes, frame;
316         float                   *pintervals, fullinterval, targettime, time, jtime, jinterval;
317
318         psprite = currententity->model->cache.data;
319         frame = currententity->frame;
320
321         if ((frame >= psprite->numframes) || (frame < 0))
322         {
323                 Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
324                 frame = 0;
325         }
326
327         if (psprite->frames[frame].type == SPR_SINGLE)
328         {
329                 if (currententity->draw_lastmodel == currententity->model && currententity->draw_lerpstart < cl.time)
330                 {
331                         if (frame != currententity->draw_pose)
332                         {
333                                 currententity->draw_lastpose = currententity->draw_pose;
334                                 currententity->draw_pose = frame;
335                                 currententity->draw_lerpstart = cl.time;
336                                 *framelerp = 0;
337                         }
338                         else
339                                 *framelerp = (cl.time - currententity->draw_lerpstart) * 10.0;
340                 }
341                 else // uninitialized
342                 {
343                         currententity->draw_lastmodel = currententity->model;
344                         currententity->draw_lastpose = currententity->draw_pose = frame;
345                         currententity->draw_lerpstart = cl.time;
346                         *framelerp = 0;
347                 }
348                 *oldframe = psprite->frames[currententity->draw_lastpose].frameptr;
349                 *newframe = psprite->frames[frame].frameptr;
350         }
351         else
352         {
353                 pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
354                 pintervals = pspritegroup->intervals;
355                 numframes = pspritegroup->numframes;
356                 fullinterval = pintervals[numframes-1];
357
358                 time = cl.time + currententity->syncbase;
359
360         // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
361         // are positive, so we don't have to worry about division by 0
362                 targettime = time - ((int)(time / fullinterval)) * fullinterval;
363
364                 // LordHavoc: since I can't measure the time properly when it loops from numframes-1 to 0,
365                 //            I instead measure the time of the first frame, hoping it is consistent
366                 j = numframes-1;jtime = 0;jinterval = pintervals[1] - pintervals[0];
367                 for (i=0 ; i<(numframes-1) ; i++)
368                 {
369                         if (pintervals[i] > targettime)
370                                 break;
371                         j = i;jinterval = pintervals[i] - jtime;jtime = pintervals[i];
372                 }
373                 *framelerp = (targettime - jtime) / jinterval;
374
375                 *oldframe = pspritegroup->frames[j];
376                 *newframe = pspritegroup->frames[i];
377         }
378 }
379
380 void GL_DrawSpriteImage (mspriteframe_t *frame, vec3_t origin, vec3_t up, vec3_t right, int red, int green, int blue, int alpha)
381 {
382         // LordHavoc: rewrote this to use the transparent poly system
383         transpolybegin(frame->gl_texturenum, 0, frame->gl_fogtexturenum, currententity->effects & EF_ADDITIVE ? TPOLYTYPE_ADD : TPOLYTYPE_ALPHA);
384         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);
385         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);
386         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);
387         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);
388         transpolyend();
389 }
390
391 extern qboolean isG200, isRagePro, lighthalf;
392
393 /*
394 =================
395 R_DrawSpriteModel
396
397 =================
398 */
399 void R_DrawSpriteModel (entity_t *e)
400 {
401         mspriteframe_t  *oldframe, *newframe;
402         float           *up, *right, lerp, ilerp;
403         vec3_t          v_forward, v_right, v_up, org;
404         msprite_t               *psprite;
405
406         // don't even bother culling, because it's just a single
407         // polygon without a surface cache
408         R_GetSpriteFrame (e, &oldframe, &newframe, &lerp);
409         if (lerp < 0) lerp = 0;
410         if (lerp > 1) lerp = 1;
411         if (isRagePro) // LordHavoc: no alpha scaling supported on per pixel alpha images on ATI Rage Pro... ACK!
412                 lerp = 1;
413         ilerp = 1.0 - lerp;
414         psprite = e->model->cache.data;
415
416         if (psprite->type == SPR_ORIENTED)
417         {       // bullet marks on walls
418                 AngleVectors (e->angles, v_forward, v_right, v_up);
419                 up = v_up;
420                 right = v_right;
421                 VectorSubtract(e->origin, vpn, org);
422         }
423         else
424         {       // normal sprite
425                 up = vup;
426                 right = vright;
427                 VectorCopy(e->origin, org);
428         }
429         if (e->scale != 1)
430         {
431                 VectorScale(up, e->scale, up);
432                 VectorScale(right, e->scale, right);
433         }
434
435         if (e->model->flags & EF_FULLBRIGHT || e->effects & EF_FULLBRIGHT)
436         {
437                 shadecolor[0] = e->colormod[0] * 255;
438                 shadecolor[1] = e->colormod[1] * 255;
439                 shadecolor[2] = e->colormod[2] * 255;
440         }
441         else
442         {
443                 R_LightPoint (shadecolor, e->origin);
444                 R_DynamicLightPointNoMask(shadecolor, e->origin);
445         }
446
447         // LordHavoc: interpolated sprite rendering
448         if (ilerp != 0)
449                 GL_DrawSpriteImage(oldframe, org, up, right, shadecolor[0],shadecolor[1],shadecolor[2],e->alpha*255*ilerp);
450         if (lerp != 0)
451                 GL_DrawSpriteImage(newframe, org, up, right, shadecolor[0],shadecolor[1],shadecolor[2],e->alpha*255*lerp);
452 }
453
454 //==================================================================================
455
456 void R_DrawBrushModel (entity_t *e);
457
458 /*
459 =============
460 R_DrawEntitiesOnList
461 =============
462 */
463 // LordHavoc: split so bmodels are rendered before any other objects
464 void R_DrawEntitiesOnList1 (void)
465 {
466         int             i;
467
468         if (!r_drawentities.value)
469                 return;
470
471         for (i=0 ; i<cl_numvisedicts ; i++)
472         {
473                 if (cl_visedicts[i]->model->type != mod_brush)
474                         continue;
475                 currententity = cl_visedicts[i];
476                 modelalpha = currententity->alpha;
477
478                 R_DrawBrushModel (currententity);
479         }
480 }
481
482 void R_DrawEntitiesOnList2 (void)
483 {
484         int             i;
485
486         if (!r_drawentities.value)
487                 return;
488
489         for (i=0 ; i<cl_numvisedicts ; i++)
490         {
491                 currententity = cl_visedicts[i];
492                 modelalpha = currententity->alpha;
493
494                 switch (currententity->model->type)
495                 {
496                 case mod_alias:
497                         R_DrawAliasModel (currententity, true, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->effects, currententity->model->flags, currententity->colormap);
498                         break;
499
500                 case mod_sprite:
501                         R_DrawSpriteModel (currententity);
502                         break;
503
504                 default:
505                         break;
506                 }
507         }
508 }
509
510 /*
511 =============
512 R_DrawViewModel
513 =============
514 */
515 void R_DrawViewModel (void)
516 {
517         if (!r_drawviewmodel.value || chase_active.value || envmap || !r_drawentities.value || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.model)
518                 return;
519
520         currententity = &cl.viewent;
521         currententity->alpha = modelalpha = cl_entities[cl.viewentity].alpha; // LordHavoc: if the player is transparent, so is his gun
522         currententity->effects = cl_entities[cl.viewentity].effects;
523         currententity->scale = 1;
524         VectorCopy(cl_entities[cl.viewentity].colormod, currententity->colormod);
525
526         // hack the depth range to prevent view model from poking into walls
527         glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
528         R_DrawAliasModel (currententity, FALSE, modelalpha, currententity->model, currententity->frame, currententity->skinnum, currententity->origin, currententity->effects, currententity->model->flags, currententity->colormap);
529         glDepthRange (gldepthmin, gldepthmax);
530 }
531
532 void R_DrawBrushModel (entity_t *e);
533
534 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
535
536 void R_SetFrustum (void)
537 {
538         int             i;
539
540         if (r_refdef.fov_x == 90) 
541         {
542                 // front side is visible
543
544                 VectorAdd (vpn, vright, frustum[0].normal);
545                 VectorSubtract (vpn, vright, frustum[1].normal);
546
547                 VectorAdd (vpn, vup, frustum[2].normal);
548                 VectorSubtract (vpn, vup, frustum[3].normal);
549         }
550         else
551         {
552                 // rotate VPN right by FOV_X/2 degrees
553                 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
554                 // rotate VPN left by FOV_X/2 degrees
555                 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
556                 // rotate VPN up by FOV_X/2 degrees
557                 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
558                 // rotate VPN down by FOV_X/2 degrees
559                 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
560         }
561
562         for (i=0 ; i<4 ; i++)
563         {
564                 frustum[i].type = PLANE_ANYZ;
565                 frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
566 //              frustum[i].signbits = SignbitsForPlane (&frustum[i]);
567                 BoxOnPlaneSideClassify(&frustum[i]);
568         }
569 }
570
571 void R_AnimateLight (void);
572 void V_CalcBlend (void);
573
574 /*
575 ===============
576 R_SetupFrame
577 ===============
578 */
579 void R_SetupFrame (void)
580 {
581 // don't allow cheats in multiplayer
582         if (cl.maxclients > 1)
583         {
584                 Cvar_Set ("r_fullbright", "0");
585                 Cvar_Set ("r_ambient", "0");
586         }
587
588         R_AnimateLight ();
589
590         r_framecount++;
591
592 // build the transformation matrix for the given view angles
593         VectorCopy (r_refdef.vieworg, r_origin);
594
595         AngleVectors (r_refdef.viewangles, vpn, vright, vup);
596
597 // current viewleaf
598         r_oldviewleaf = r_viewleaf;
599         r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
600
601         V_SetContentsColor (r_viewleaf->contents);
602         V_CalcBlend ();
603
604         r_cache_thrash = false;
605
606         c_brush_polys = 0;
607         c_alias_polys = 0;
608         c_light_polys = 0;
609         c_nodes = 0;
610         c_leafs = 0;
611
612 }
613
614
615 void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
616 {
617    GLdouble xmin, xmax, ymin, ymax;
618
619    ymax = zNear * tan( fovy * M_PI / 360.0 );
620    ymin = -ymax;
621
622    xmin = ymin * aspect;
623    xmax = ymax * aspect;
624
625    glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
626 }
627
628
629 extern char skyname[];
630
631 /*
632 =============
633 R_SetupGL
634 =============
635 */
636 void R_SetupGL (void)
637 {
638         float   screenaspect;
639         extern  int glwidth, glheight;
640         int             x, x2, y2, y, w, h;
641
642         if (!r_render.value)
643                 return;
644         //
645         // set up viewpoint
646         //
647         glMatrixMode(GL_PROJECTION);
648     glLoadIdentity ();
649         x = r_refdef.vrect.x * glwidth/vid.width;
650         x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
651         y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
652         y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
653
654         // fudge around because of frac screen scale
655         if (x > 0)
656                 x--;
657         if (x2 < glwidth)
658                 x2++;
659         if (y2 < 0)
660                 y2--;
661         if (y < glheight)
662                 y++;
663
664         w = x2 - x;
665         h = y - y2;
666
667         if (envmap)
668         {
669                 x = y2 = 0;
670                 w = h = 256;
671         }
672
673         glViewport (glx + x, gly + y2, w, h);
674     screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
675 //      yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
676 //      if (skyname[0]) // skybox enabled?
677 //              MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  r_skyboxsize.value*1.732050807569 + 256); // this is size*sqrt(3) + 256
678 //      else
679                 MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  r_farclip.value);
680
681         glCullFace(GL_FRONT);
682
683         glMatrixMode(GL_MODELVIEW);
684     glLoadIdentity ();
685
686     glRotatef (-90,  1, 0, 0);      // put Z going up
687     glRotatef (90,  0, 0, 1);       // put Z going up
688     glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
689     glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
690     glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
691     glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
692
693         glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
694
695         //
696         // set drawing parms
697         //
698 //      if (gl_cull.value)
699                 glEnable(GL_CULL_FACE);
700 //      else
701 //              glDisable(GL_CULL_FACE);
702
703         glEnable(GL_BLEND); // was Disable
704         glDisable(GL_ALPHA_TEST);
705         glAlphaFunc(GL_GREATER, 0.5);
706         glEnable(GL_DEPTH_TEST);
707         glDepthMask(1);
708         glShadeModel(GL_SMOOTH);
709 }
710
711 void R_DrawWorld (void);
712 //void R_RenderDlights (void);
713 void R_DrawParticles (void);
714
715 /*
716 =============
717 R_Clear
718 =============
719 */
720 void R_Clear (void)
721 {
722         if (!r_render.value)
723                 return;
724 //      glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // LordHavoc: moved to SCR_UpdateScreen
725         gldepthmin = 0;
726         gldepthmax = 1;
727         glDepthFunc (GL_LEQUAL);
728
729         glDepthRange (gldepthmin, gldepthmax);
730 }
731
732 // LordHavoc: my trick to *FIX* GLQuake lighting once and for all :)
733 void GL_Brighten()
734 {
735         if (!r_render.value)
736                 return;
737         glMatrixMode(GL_PROJECTION);
738     glLoadIdentity ();
739         glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
740         glMatrixMode(GL_MODELVIEW);
741     glLoadIdentity ();
742         glDisable (GL_DEPTH_TEST);
743         glDisable (GL_CULL_FACE);
744         glDisable(GL_TEXTURE_2D);
745         glEnable(GL_BLEND);
746         glBlendFunc (GL_DST_COLOR, GL_ONE);
747         glBegin (GL_TRIANGLES);
748         glColor3f (1, 1, 1);
749         glVertex2f (-5000, -5000);
750         glVertex2f (10000, -5000);
751         glVertex2f (-5000, 10000);
752         glEnd ();
753         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
754         glDisable(GL_BLEND);
755         glEnable(GL_TEXTURE_2D);
756         glEnable (GL_DEPTH_TEST);
757         glEnable (GL_CULL_FACE);
758 }
759
760 extern cvar_t contrast;
761 extern cvar_t brightness;
762 extern cvar_t gl_lightmode;
763
764 void GL_BlendView()
765 {
766         if (!r_render.value)
767                 return;
768         glMatrixMode(GL_PROJECTION);
769     glLoadIdentity ();
770         glOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
771         glMatrixMode(GL_MODELVIEW);
772     glLoadIdentity ();
773         glDisable (GL_DEPTH_TEST);
774         glDisable (GL_CULL_FACE);
775         glDisable(GL_TEXTURE_2D);
776         glEnable(GL_BLEND);
777         if (lighthalf)
778         {
779                 glBlendFunc (GL_DST_COLOR, GL_ONE);
780                 glBegin (GL_TRIANGLES);
781                 glColor3f (1, 1, 1);
782                 glVertex2f (-5000, -5000);
783                 glVertex2f (10000, -5000);
784                 glVertex2f (-5000, 10000);
785                 glEnd ();
786         }
787         glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
788         contrast.value = bound(0.2, contrast.value, 1.0);
789         if (/*gl_polyblend.value && */v_blend[3])
790         {
791                 glBegin (GL_TRIANGLES);
792                 glColor4fv (v_blend);
793                 glVertex2f (-5000, -5000);
794                 glVertex2f (10000, -5000);
795                 glVertex2f (-5000, 10000);
796                 glEnd ();
797         }
798
799         glEnable (GL_CULL_FACE);
800         glEnable (GL_DEPTH_TEST);
801         glDisable(GL_BLEND);
802         glEnable(GL_TEXTURE_2D);
803 }
804
805 #define TIMEREPORT(DESC) \
806         if (r_speeds2.value)\
807         {\
808                 temptime = -currtime;\
809                 currtime = Sys_FloatTime();\
810                 temptime += currtime;\
811                 Con_Printf(DESC " %.4fms ", temptime * 1000.0);\
812         }
813
814 /*
815 ================
816 R_RenderView
817
818 r_refdef must be set before the first call
819 ================
820 */
821 extern qboolean intimerefresh;
822 extern qboolean skyisvisible;
823 extern void R_Sky();
824 extern void UploadLightmaps();
825 void R_RenderView (void)
826 {
827 //      double currtime, temptime;
828 //      if (r_norefresh.value)
829 //              return;
830
831         if (!r_worldentity.model || !cl.worldmodel)
832                 Sys_Error ("R_RenderView: NULL worldmodel");
833
834         lighthalf = gl_lightmode.value;
835
836         FOG_framebegin();
837
838 //      if (r_speeds2.value)
839 //      {
840 //              currtime = Sys_FloatTime();
841 //              Con_Printf("render time: ");
842 //      }
843         R_Clear();
844 //      TIMEREPORT("R_Clear")
845
846         // render normal view
847
848         R_SetupFrame ();
849         R_SetFrustum ();
850         R_SetupGL ();
851
852         skypolyclear();
853         wallpolyclear();
854         transpolyclear();
855         skyisvisible = false;
856
857         R_MarkLeaves ();        // done here so we know if we're in water
858         R_DrawWorld ();         // adds static entities to the list
859         if (!intimerefresh)
860                 S_ExtraUpdate ();       // don't let sound get messed up if going slow
861         R_DrawEntitiesOnList1 (); // BSP models
862
863         skypolyrender(); // fogged sky polys, affects depth
864         if (skyname[0] && skyisvisible && !fogenabled)
865                 R_Sky(); // does not affect depth, draws over the sky polys
866
867         UploadLightmaps();
868         wallpolyrender();
869
870         R_DrawEntitiesOnList2 (); // other models
871 //      R_RenderDlights ();
872         R_DrawViewModel ();
873         R_DrawParticles ();
874
875         transpolyrender();
876
877         FOG_frameend();
878         GL_BlendView();
879 //      if (r_speeds2.value)
880 //              Con_Printf("\n");
881 }