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