1 /*
2 Copyright (C) 1997-2001 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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "r_local.h"
27 #include "r_script.h"
28 #include "r_ragdoll.h"
29 #include "r_text.h"
30
31
32 void R_Clear (void);
33
34 viddef_t vid;
35
36 int r_viewport[4];
37
38 int GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2, GL_TEXTURE3, GL_TEXTURE4, GL_TEXTURE5, GL_TEXTURE6, GL_TEXTURE7;
39
40 model_t *r_worldmodel;
41
42 float gldepthmin, gldepthmax;
43 float r_frametime;
44
45 glconfig_t gl_config;
46 glstate_t gl_state;
47
48 cvar_t *gl_normalmaps;
49 cvar_t *gl_bspnormalmaps;
50 cvar_t *gl_shadowmaps;
51 cvar_t *gl_arb_fragment_program;
52 cvar_t *gl_glsl_shaders;
53 cvar_t *gl_fog;
54
55 entity_t *currententity;
56 model_t *currentmodel;
57
58 cplane_t frustum[4];
59
60 int r_visframecount; // bumped when going to a new PVS
61 int r_framecount; // used for dlight push checking
62 int r_shadowmapcount; // number of shadowmaps rendered this frame
63
64 // performance counters for r_speeds reports
65 int last_c_brush_polys, c_brush_polys;
66 int last_c_alias_polys, c_alias_polys;
67 int c_flares;
68 int c_grasses;
69 int c_beams;
70 extern int c_vbo_batches;
71 extern int c_visible_lightmaps;
72 extern int c_visible_textures;
73
74 float v_blend[4]; // final blending color
75
76 float r_farclip, r_farclip_min, r_farclip_bias = 256.0f;
77
78 void GL_Strings_f( void );
79
80 //
81 // view origin
82 //
83 vec3_t vup;
84 vec3_t vpn;
85 vec3_t vright;
86 vec3_t r_origin;
87 int r_origin_leafnum;
88
89 float r_world_matrix[16];
90 float r_project_matrix[16];
91
92 //
93 // screen size info
94 //
95 refdef_t r_newrefdef;
96
97 int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
98
99 cvar_t *r_norefresh;
100 cvar_t *r_drawentities;
101 cvar_t *r_drawworld;
102 cvar_t *r_fullbright;
103 cvar_t *r_novis;
104 cvar_t *r_nocull;
105 cvar_t *r_lerpmodels;
106 cvar_t *r_lefthand;
107
108 cvar_t *r_wave; // Water waves
109
110 cvar_t *r_shadowmapscale;
111
112 cvar_t *r_overbrightbits;
113
114 cvar_t *gl_vlights;
115
116 cvar_t *gl_nosubimage;
117
118 cvar_t *gl_usevbo;
119
120 cvar_t *gl_particle_min_size;
121 cvar_t *gl_particle_max_size;
122 cvar_t *gl_particle_size;
123 cvar_t *gl_particle_att_a;
124 cvar_t *gl_particle_att_b;
125 cvar_t *gl_particle_att_c;
126
127 cvar_t *gl_ext_pointparameters;
128
129 cvar_t *gl_log;
130 cvar_t *gl_bitdepth;
131 cvar_t *gl_drawbuffer;
132 cvar_t *gl_driver;
133 cvar_t *gl_lightmap;
134 cvar_t *gl_mode;
135 cvar_t *gl_dynamic;
136 cvar_t *gl_modulate;
137 cvar_t *gl_nobind;
138 cvar_t *gl_picmip;
139 cvar_t *gl_skymip;
140 cvar_t *gl_showtris;
141 cvar_t *gl_showpolys;
142 cvar_t *gl_finish;
143 cvar_t *gl_clear;
144 cvar_t *gl_cull;
145 cvar_t *gl_polyblend;
146 cvar_t *gl_swapinterval;
147 cvar_t *gl_texturemode;
148 cvar_t *gl_texturealphamode;
149 cvar_t *gl_texturesolidmode;
150 cvar_t *gl_lockpvs;
151
152 cvar_t *vid_fullscreen;
153 cvar_t *vid_gamma;
154 cvar_t *vid_contrast;
155 cvar_t *vid_ref;
156
157 cvar_t *r_anisotropic;
158 cvar_t *r_alphamasked_anisotropic;
159 cvar_t *r_ext_max_anisotropy;
160
161 cvar_t *r_shaders;
162 cvar_t *r_bloom;
163 cvar_t *r_lensflare;
164 cvar_t *r_lensflare_intens;
165 cvar_t *r_drawsun;
166 cvar_t *r_lightbeam;
167 cvar_t *r_godrays;
168 cvar_t *r_godray_intensity;
169 cvar_t *r_optimize;
170
171 cvar_t *r_lightmapfiles;
172
173 qboolean map_fog;
174
175 cvar_t *con_font;
176
177 cvar_t *r_minimap_size;
178 cvar_t *r_minimap_zoom;
179 cvar_t *r_minimap_style;
180 cvar_t *r_minimap;
181
182 cvar_t *sys_affinity;
183 cvar_t *sys_priority;
184
185 cvar_t *gl_screenshot_type;
186 cvar_t *gl_screenshot_jpeg_quality;
187
188 //no blood
189 extern cvar_t *cl_noblood;
190
191 //first time running game
192 cvar_t *r_firstrun;
193
194 //for testing
195 cvar_t *r_test;
196
197 //ODE initialization error check
198 int r_odeinit_success; // 0 if dODEInit2() fails, 1 otherwise.
199
200 //fog script stuff
201 struct r_fog
202 {
203 float red;
204 float green;
205 float blue;
206 float start;
207 float end;
208 float density;
209 } fog;
210 unsigned r_weather;
211 unsigned r_nosun;
212 float r_sunX;
213 float r_sunY;
214 float r_sunZ;
215
216 /*
217 =================
218 R_ReadFogScript
219 =================
220 */
221
R_ReadFogScript(char * config_file)222 void R_ReadFogScript( char *config_file )
223 {
224 FILE *fp;
225 int length;
226 char a_string[128];
227 char *buffer;
228 char *s;
229 size_t result;
230
231 if((fp = fopen(config_file, "rb" )) == NULL)
232 {
233 return;
234 }
235
236 length = FS_filelength( fp );
237
238 buffer = malloc( length + 1 );
239 if ( buffer != NULL )
240 {
241 buffer[length] = 0;
242 result = fread( buffer, length, 1, fp );
243 if ( result == 1 )
244 {
245 s = buffer;
246
247 strcpy( a_string, COM_Parse( &s ) );
248 fog.red = atof(a_string);
249 strcpy( a_string, COM_Parse( &s ) );
250 fog.green = atof(a_string);
251 strcpy( a_string, COM_Parse( &s ) );
252 fog.blue = atof(a_string);
253 strcpy( a_string, COM_Parse( &s ) );
254 fog.start = atof(a_string);
255 strcpy( a_string, COM_Parse( &s ) );
256 fog.end = atof(a_string);
257 strcpy( a_string, COM_Parse( &s ) );
258 fog.density = atof(a_string);
259 strcpy( a_string, COM_Parse( &s ) );
260 r_weather = atoi(a_string);
261 strcpy( a_string, COM_Parse( &s ) );
262 r_nosun = atoi(a_string);
263 strcpy( a_string, COM_Parse( &s ) );
264 r_sunX = atof(a_string);
265 strcpy( a_string, COM_Parse( &s ) );
266 r_sunY = atof(a_string);
267 strcpy( a_string, COM_Parse( &s ) );
268 r_sunZ = atof(a_string);
269
270 if(fog.density > 0)
271 map_fog = true;
272
273 }
274 else
275 {
276 Com_DPrintf("R_ReadFogScript: read fail: %s\n", config_file);
277 }
278 free( buffer );
279 }
280 fclose( fp );
281
282 if (gl_fog->integer < 1)
283 {
284 map_fog = false;
285 r_weather = false;
286 }
287
288 return;
289 }
290
291 /*
292 =================
293 R_ReadMusicScript
294 =================
295 */
296
297 //to do - read in secondary music location(for CTF music shift)
R_ReadMusicScript(char * config_file)298 void R_ReadMusicScript( char *config_file )
299 {
300 FILE *fp;
301 int length;
302 char *buffer;
303 char *s;
304 size_t result;
305
306 if((fp = fopen(config_file, "rb" )) == NULL)
307 {
308 return;
309 }
310
311 length = FS_filelength( fp );
312
313 buffer = malloc( length + 1 );
314 if ( buffer != NULL )
315 {
316 result = fread( buffer, length, 1, fp );
317 if ( result == 1 )
318 {
319 buffer[length] = 0;
320 s = buffer;
321 strcpy( map_music, COM_Parse( &s ) );
322 map_music[length] = 0; //clear any possible garbage
323 }
324 else
325 {
326 Com_DPrintf("R_ReadMusicScript: read fail: %s\n", config_file);
327 }
328
329 free( buffer );
330 }
331 fclose( fp );
332
333 return;
334 }
335
336 /*
337 =================
338 R_CullBox
339
340 Returns true if the box is completely outside the frustom
341 =================
342 */
R_CullBox(vec3_t mins,vec3_t maxs)343 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
344 {
345 int i;
346 cplane_t *p;
347
348 if (r_nocull->integer)
349 return false;
350
351 for (i=0,p=frustum ; i<4; i++,p++)
352 {
353 switch (p->signbits)
354 {
355 case 0:
356 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
357 return true;
358 break;
359 case 1:
360 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
361 return true;
362 break;
363 case 2:
364 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
365 return true;
366 break;
367 case 3:
368 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
369 return true;
370 break;
371 case 4:
372 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
373 return true;
374 break;
375 case 5:
376 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
377 return true;
378 break;
379 case 6:
380 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
381 return true;
382 break;
383 case 7:
384 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
385 return true;
386 break;
387 default:
388 return false;
389 }
390 }
391
392 return false;
393 }
394
395 /*
396 =================
397 R_CullOrigin
398
399 Returns true if the origin is completely outside the frustom
400 =================
401 */
402
R_CullOrigin(vec3_t origin)403 qboolean R_CullOrigin(vec3_t origin)
404 {
405 int i;
406
407 for (i = 0; i < 4; i++)
408 if (BOX_ON_PLANE_SIDE(origin, origin, &frustum[i]) == 2)
409 return true;
410 return false;
411 }
412
R_CullSphere(const vec3_t centre,const float radius,const int clipflags)413 qboolean R_CullSphere( const vec3_t centre, const float radius, const int clipflags )
414 {
415 int i;
416 cplane_t *p;
417
418 if (r_nocull->value)
419 return false;
420
421 for (i=0,p=frustum ; i<4; i++,p++)
422 {
423 if ( !(clipflags & (1<<i)) ) {
424 continue;
425 }
426
427 if ( DotProduct ( centre, p->normal ) - p->dist <= -radius )
428 return true;
429 }
430
431 return false;
432 }
433
R_RotateForEntity(entity_t * e)434 void R_RotateForEntity (entity_t *e)
435 {
436 qglTranslatef (e->origin[0], e->origin[1], e->origin[2]);
437
438 qglRotatef (e->angles[1], 0, 0, 1);
439 qglRotatef (-e->angles[0], 0, 1, 0);
440
441 qglRotatef (-e->angles[2], 1, 0, 0);
442 }
443
444 /*
445 =============
446 R_DrawNullModel
447 =============
448 */
R_DrawNullModel(void)449 void R_DrawNullModel (void)
450 {
451 vec3_t shadelight;
452 int i;
453
454 if ( currententity->flags & RF_FULLBRIGHT )
455 shadelight[0] = shadelight[1] = shadelight[2] = 1.0F;
456 else
457 R_LightPoint (currententity->origin, shadelight, true);
458
459 qglPushMatrix ();
460 R_RotateForEntity (currententity);
461
462 qglDisable (GL_TEXTURE_2D);
463 qglColor3fv (shadelight);
464
465 qglBegin (GL_TRIANGLE_FAN);
466 qglVertex3f (0, 0, -16);
467 for (i=0 ; i<=4 ; i++)
468 qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0);
469 qglEnd ();
470
471 qglBegin (GL_TRIANGLE_FAN);
472 qglVertex3f (0, 0, 16);
473 for (i=4 ; i>=0 ; i--)
474 qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0);
475 qglEnd ();
476
477 qglColor3f (1,1,1);
478 qglPopMatrix ();
479 qglEnable (GL_TEXTURE_2D);
480 }
481
482 #include "r_lodcalc.h"
483
484 /*
485 =============
486 R_DrawEntitiesOnList
487 =============
488 */
489 extern cvar_t *cl_simpleitems;
R_DrawEntitiesOnList(void)490 void R_DrawEntitiesOnList (void)
491 {
492 int i;
493 rscript_t *rs = NULL;
494 vec3_t dist;
495
496 if (!r_drawentities->integer)
497 return;
498
499 if ( !r_odeinit_success )
500 { // ODE init failed, force ragdolls off
501 r_ragdolls = Cvar_ForceSet("r_ragdolls", "0");
502 }
503
504 // draw non-transparent first
505 for (i=0 ; i<r_newrefdef.num_entities ; i++)
506 {
507 currententity = &r_newrefdef.entities[i];
508 if (currententity->flags & RF_TRANSLUCENT)
509 continue; // transluscent
510
511 if (currententity->model && r_shaders->integer)
512 {
513 rs=(rscript_t *)currententity->model->script;
514
515 //custom player skin (must be done here)
516 if (currententity->skin)
517 {
518 rs = currententity->skin->script;
519 if(rs)
520 RS_ReadyScript(rs);
521 }
522
523 if (rs)
524 currententity->script = rs;
525 else
526 currententity->script = NULL;
527 }
528
529 currentmodel = currententity->model;
530
531 if (cl_simpleitems->integer && currentmodel && currentmodel->simple_texnum)
532 continue;
533
534 //get distance
535 VectorSubtract(r_origin, currententity->origin, dist);
536
537 //set lod if available
538 if(VectorLength(dist) > LOD_DIST*2.0)
539 {
540 if(currententity->lod2)
541 currentmodel = currententity->lod2;
542 }
543 else if(VectorLength(dist) > LOD_DIST)
544 {
545 if(currententity->lod1)
546 currentmodel = currententity->lod1;
547 }
548
549 if (!currentmodel)
550 {
551 R_DrawNullModel ();
552 continue;
553 }
554 switch (currentmodel->type)
555 {
556 case mod_alias:
557 R_DrawAliasModel ();
558 break;
559 case mod_brush:
560 R_DrawBrushModel ();
561 break;
562 case mod_iqm:
563 R_DrawINTERQUAKEMODEL ();
564 break;
565 default:
566 Com_Error(ERR_DROP, "Bad modeltype");
567 break;
568 }
569 }
570
571 // draw transparent entities
572 // we could sort these if it ever becomes a problem...
573 qglDepthMask (0); // no z writes
574 for (i=0 ; i<r_newrefdef.num_entities ; i++)
575 {
576 currententity = &r_newrefdef.entities[i];
577 if (!(currententity->flags & RF_TRANSLUCENT))
578 continue; // solid
579
580 if (currententity->model && r_shaders->integer)
581 {
582 rs=(rscript_t *)currententity->model->script;
583
584 //custom player skin (must be done here)
585 if (currententity->skin)
586 {
587 rs = currententity->skin->script;
588 if(rs)
589 RS_ReadyScript(rs);
590 }
591
592 if (rs)
593 currententity->script = rs;
594 else
595 currententity->script = NULL;
596 }
597
598 currentmodel = currententity->model;
599 fadeShadow = 1.0;
600
601 if (!currentmodel)
602 {
603 R_DrawNullModel ();
604 continue;
605 }
606 switch (currentmodel->type)
607 {
608 case mod_alias:
609 R_DrawAliasModel ();
610 break;
611 case mod_brush:
612 R_DrawBrushModel ();
613 break;
614 case mod_iqm:
615 R_DrawINTERQUAKEMODEL ();
616 break;
617 default:
618 Com_Error (ERR_DROP, "Bad modeltype");
619 break;
620 }
621 }
622 qglDepthMask (1); // back to writing
623 }
624
R_DrawViewEntitiesOnList(void)625 void R_DrawViewEntitiesOnList (void)
626 {
627 int i;
628 rscript_t *rs = NULL;
629
630 if (!r_drawentities->integer)
631 return;
632
633 if(r_newrefdef.rdflags & RDF_NOWORLDMODEL)
634 return;
635
636 // draw non-transparent first
637 for (i=0 ; i<r_newrefdef.num_viewentities ; i++)
638 {
639 currententity = &r_newrefdef.viewentities[i];
640 if (currententity->flags & RF_TRANSLUCENT)
641 continue; // transluscent
642
643 if (currententity->model && r_shaders->integer)
644 {
645 rs=(rscript_t *)currententity->model->script;
646
647 //custom player skin (must be done here)
648 if (currententity->skin)
649 {
650 rs = currententity->skin->script;
651 if(rs)
652 RS_ReadyScript(rs);
653 }
654
655 if (rs)
656 currententity->script = rs;
657 else
658 currententity->script = NULL;
659 }
660
661 currentmodel = currententity->model;
662
663 if (!currentmodel)
664 {
665 R_DrawNullModel ();
666 continue;
667 }
668 switch (currentmodel->type)
669 {
670 case mod_alias:
671 R_DrawAliasModel ();
672 break;
673 case mod_iqm:
674 R_DrawINTERQUAKEMODEL ();
675 break;
676 default:
677 Com_Error(ERR_DROP, "Bad modeltype");
678 break;
679 }
680 }
681
682 // draw transparent entities
683 // we could sort these if it ever becomes a problem...
684 qglDepthMask (0); // no z writes
685 for (i=0 ; i<r_newrefdef.num_viewentities ; i++)
686 {
687 currententity = &r_newrefdef.viewentities[i];
688 if (!(currententity->flags & RF_TRANSLUCENT))
689 continue; // solid
690
691 if (currententity->model && r_shaders->integer)
692 {
693 rs=(rscript_t *)currententity->model->script;
694
695 //custom player skin (must be done here)
696 if (currententity->skin)
697 {
698 rs = currententity->skin->script;
699 if(rs)
700 RS_ReadyScript(rs);
701 }
702
703 if (rs)
704 currententity->script = rs;
705 else
706 currententity->script = NULL;
707 }
708
709 currentmodel = currententity->model;
710
711 if (!currentmodel)
712 {
713 R_DrawNullModel ();
714 continue;
715 }
716 switch (currentmodel->type)
717 {
718 case mod_alias:
719 R_DrawAliasModel ();
720 break;
721 case mod_iqm:
722 R_DrawINTERQUAKEMODEL ();
723 break;
724 default:
725 Com_Error (ERR_DROP, "Bad modeltype");
726 break;
727 }
728 }
729 qglDepthMask (1); // back to writing
730 }
731
732 extern int r_drawing_fbeffect;
733 extern int r_fbFxType;
734 extern float r_fbeffectTime;
735 extern cvar_t *cl_paindist;
736 /*
737 ============
738 R_PolyBlend
739 ============
740 */
R_PolyBlend(void)741 void R_PolyBlend (void)
742 {
743 if (!gl_polyblend->integer)
744 return;
745 if (!v_blend[3])
746 return;
747
748 if(!r_drawing_fbeffect && cl_paindist->integer) {
749 if(v_blend[0] > 2*v_blend[1] && v_blend[0] > 2*v_blend[2]) {
750 r_drawing_fbeffect = true;
751 r_fbFxType = 2; //FLASH DISTORTION
752 r_fbeffectTime = rs_realtime;
753 }
754 }
755
756 qglDisable (GL_ALPHA_TEST);
757 qglEnable (GL_BLEND);
758 qglDisable (GL_DEPTH_TEST);
759 qglDisable (GL_TEXTURE_2D);
760
761 qglMatrixMode(GL_PROJECTION);
762 qglLoadIdentity ();
763 qglOrtho (0, 1, 1, 0, -99999, 99999);
764
765 qglMatrixMode(GL_MODELVIEW);
766 qglLoadIdentity ();
767
768 qglColor4fv (v_blend);
769
770 qglBegin (GL_TRIANGLES);
771 qglVertex2f (-5, -5);
772 qglVertex2f (10, -5);
773 qglVertex2f (-5, 10);
774 qglEnd ();
775
776 qglDisable (GL_BLEND);
777 qglEnable (GL_TEXTURE_2D);
778 qglEnable (GL_ALPHA_TEST);
779
780 qglColor4f(1,1,1,1);
781 }
782
783 //=======================================================================
784
SignbitsForPlane(cplane_t * out)785 int SignbitsForPlane (cplane_t *out)
786 {
787 int bits, j;
788
789 // for fast box on planeside test
790
791 bits = 0;
792 for (j=0 ; j<3 ; j++)
793 {
794 if (out->normal[j] < 0)
795 bits |= 1<<j;
796 }
797 return bits;
798 }
799
800
R_SetFrustum(void)801 void R_SetFrustum (void)
802 {
803 int i;
804
805 // rotate VPN right by FOV_X/2 degrees
806 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_newrefdef.fov_x / 2 ) );
807 // rotate VPN left by FOV_X/2 degrees
808 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_newrefdef.fov_x / 2 );
809 // rotate VPN up by FOV_X/2 degrees
810 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_newrefdef.fov_y / 2 );
811 // rotate VPN down by FOV_X/2 degrees
812 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_newrefdef.fov_y / 2 ) );
813
814 for (i=0 ; i<4 ; i++)
815 {
816 frustum[i].type = PLANE_ANYZ;
817 frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
818 frustum[i].signbits = SignbitsForPlane (&frustum[i]);
819 }
820 }
821
822 //=======================================================================
823
824 /*
825 ===============
826 R_SetupFrame
827 ===============
828 */
R_SetupFrame(void)829 void R_SetupFrame (void)
830 {
831 int i;
832 mleaf_t *leaf;
833
834 r_framecount++;
835
836 // build the transformation matrix for the given view angles
837 VectorCopy (r_newrefdef.vieworg, r_origin);
838
839 AngleVectors (r_newrefdef.viewangles, vpn, vright, vup);
840
841 // current viewcluster
842 if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
843 {
844 r_oldviewcluster = r_viewcluster;
845 r_oldviewcluster2 = r_viewcluster2;
846 r_viewleaf = leaf = Mod_PointInLeaf (r_origin, r_worldmodel);
847 r_origin_leafnum = CM_PointLeafnum (r_origin);
848 r_viewcluster = r_viewcluster2 = leaf->cluster;
849
850 // check above and below so crossing solid water doesn't draw wrong
851 if (!leaf->contents)
852 { // look down a bit
853 vec3_t temp;
854
855 VectorCopy (r_origin, temp);
856 temp[2] -= 16;
857 r_viewleaf2 = leaf = Mod_PointInLeaf (temp, r_worldmodel);
858 if ( !(leaf->contents & CONTENTS_SOLID) &&
859 (leaf->cluster != r_viewcluster2) )
860 r_viewcluster2 = leaf->cluster;
861 }
862 else
863 { // look up a bit
864 vec3_t temp;
865
866 VectorCopy (r_origin, temp);
867 temp[2] += 16;
868 r_viewleaf2 = leaf = Mod_PointInLeaf (temp, r_worldmodel);
869 if ( !(leaf->contents & CONTENTS_SOLID) &&
870 (leaf->cluster != r_viewcluster2) )
871 r_viewcluster2 = leaf->cluster;
872 }
873 }
874
875 for (i=0 ; i<4 ; i++)
876 v_blend[i] = r_newrefdef.blend[i];
877
878 c_brush_polys = 0;
879 c_alias_polys = 0;
880
881 }
882
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)883 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
884 GLdouble zNear, GLdouble zFar )
885 {
886 GLdouble xmin, xmax, ymin, ymax;
887
888 ymax = zNear * tan( fovy * M_PI / 360.0 );
889 ymin = -ymax;
890
891 xmin = ymin * aspect;
892 xmax = ymax * aspect;
893
894 xmin += -( 2 * gl_state.camera_separation ) / zNear;
895 xmax += -( 2 * gl_state.camera_separation ) / zNear;
896
897 qglFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
898
899 }
900
901
902
903 /*
904 =============
905 R_SetupViewport
906 =============
907 */
R_SetupViewport(void)908 void R_SetupViewport (void)
909 {
910 int x, y, w, h;
911
912 // The viewport info in r_newrefdef is constructed with the upper left
913 // corner as the origin, whereas glViewport treats the lower left corner
914 // as the origin. So we have to do some math to fix the y-coordinates.
915
916 x = r_newrefdef.x;
917 w = r_newrefdef.width;
918 y = vid.height - r_newrefdef.y - r_newrefdef.height;
919 h = r_newrefdef.height;
920
921 qglViewport (x, y, w, h); // MPO : note this happens every frame interestingly enough
922 }
923
924
925
926 /*
927 =============
928 R_SetupGL
929 =============
930 */
R_SetupGL(void)931 void R_SetupGL (void)
932 {
933 float screenaspect;
934
935 R_SetupViewport ();
936
937 //
938 // set up projection matrix
939 //
940 screenaspect = (float)r_newrefdef.width/r_newrefdef.height;
941 qglMatrixMode(GL_PROJECTION);
942 qglLoadIdentity ();
943
944 if(r_newrefdef.fov_y < 90)
945 MYgluPerspective (r_newrefdef.fov_y, screenaspect, 4, 128000);
946 else
947 MYgluPerspective(r_newrefdef.fov_y, screenaspect, 4 * 74 / r_newrefdef.fov_y, 15000); //Phenax
948
949 qglCullFace(GL_FRONT);
950
951 qglMatrixMode(GL_MODELVIEW);
952 qglLoadIdentity ();
953
954 qglRotatef (-90, 1, 0, 0); // put Z going up
955 qglRotatef (90, 0, 0, 1); // put Z going up
956
957 qglRotatef (-r_newrefdef.viewangles[2], 1, 0, 0);
958 qglRotatef (-r_newrefdef.viewangles[0], 0, 1, 0);
959 qglRotatef (-r_newrefdef.viewangles[1], 0, 0, 1);
960 qglTranslatef (-r_newrefdef.vieworg[0], -r_newrefdef.vieworg[1], -r_newrefdef.vieworg[2]);
961
962 qglGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
963 qglGetFloatv(GL_PROJECTION_MATRIX, r_project_matrix);
964 qglGetIntegerv(GL_VIEWPORT, (int *) r_viewport);
965
966 //
967 // set drawing parms
968 //
969
970 if (gl_cull->integer)
971 qglEnable(GL_CULL_FACE);
972
973 qglDisable(GL_BLEND);
974
975 qglDisable(GL_ALPHA_TEST);
976 qglEnable(GL_DEPTH_TEST);
977 }
978
979 /*
980 =============
981 R_Clear
982 =============
983 */
984 extern cvar_t *info_spectator;
985 extern cvar_t *cl_add_blend;
986 extern qboolean have_stencil;
R_Clear(void)987 void R_Clear (void)
988 {
989 qglClearColor(0,0,0,1);
990 if (gl_clear->integer)
991 qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
992 else if (!cl_add_blend->integer && info_spectator->integer && (CM_PointContents(r_newrefdef.vieworg, 0) & CONTENTS_SOLID))
993 qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //out of map
994 else
995 qglClear (GL_DEPTH_BUFFER_BIT);
996
997 gldepthmin = 0;
998 gldepthmax = 1;
999 qglDepthFunc (GL_LEQUAL);
1000
1001 qglDepthRange (gldepthmin, gldepthmax);
1002
1003 //our shadow system uses a combo of shadmaps and stencil volumes.
1004 if (have_stencil && gl_shadowmaps->integer) {
1005
1006 qglClearStencil(0);
1007 qglClear(GL_STENCIL_BUFFER_BIT);
1008 }
1009 }
1010
R_Flash(void)1011 void R_Flash( void )
1012 {
1013 R_PolyBlend ();
1014 }
1015
1016 /*
1017 ================
1018 R_RenderView
1019
1020 r_newrefdef must be set before the first call
1021 ================
1022 */
1023
R_RenderView(refdef_t * fd)1024 void R_RenderView (refdef_t *fd)
1025 {
1026 GLfloat colors[4] = {(GLfloat) fog.red, (GLfloat) fog.green, (GLfloat) fog.blue, (GLfloat) 0.1};
1027
1028 numRadarEnts = 0;
1029
1030 if (r_norefresh->integer)
1031 return;
1032
1033 r_newrefdef = *fd;
1034
1035 //shadowmaps
1036 if(gl_shadowmaps->integer) {
1037
1038 qglEnable(GL_DEPTH_TEST);
1039 qglClearColor(0,0,0,1.0f);
1040
1041 qglEnable(GL_CULL_FACE);
1042
1043 qglHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
1044
1045 R_DrawDynamicCaster();
1046
1047 R_DrawVegetationCaster();
1048
1049 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
1050
1051 //Enabling color write (previously disabled for light POV z-buffer rendering)
1052 qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1053 }
1054
1055 if (!r_worldmodel && !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
1056 Com_Error (ERR_DROP, "R_RenderView: NULL worldmodel");
1057
1058 // init r_speeds counters
1059 last_c_brush_polys = c_brush_polys;
1060 last_c_alias_polys = c_alias_polys;
1061 c_brush_polys = 0;
1062 c_alias_polys = 0;
1063 c_flares = 0;
1064 c_grasses = 0;
1065 c_beams = 0;
1066 c_vbo_batches = 0;
1067
1068 R_PushDlights ();
1069
1070 R_SetupFrame ();
1071
1072 R_SetFrustum ();
1073
1074 R_MarkWorldSurfs (); // done here so we know if we're in water
1075
1076 if (gl_finish->integer)
1077 qglFinish ();
1078
1079 // OpenGL calls come after here
1080
1081 R_SetupGL ();
1082
1083 if(map_fog)
1084 {
1085 qglFogi(GL_FOG_MODE, GL_LINEAR);
1086 qglFogfv(GL_FOG_COLOR, colors);
1087 qglFogf(GL_FOG_START, fog.start);
1088 qglFogf(GL_FOG_END, fog.end);
1089 qglFogf(GL_FOG_DENSITY, fog.density);
1090 qglEnable(GL_FOG);
1091 }
1092
1093 R_DrawWorldSurfs ();
1094
1095 if(r_lensflare->integer)
1096 R_RenderFlares ();
1097
1098 R_DrawEntitiesOnList ();
1099
1100 R_DrawVegetationSurface ();
1101
1102 R_DrawSimpleItems ();
1103
1104 R_CastShadow();
1105
1106 R_RenderAllRagdolls(); //move back ahead of r_castshadow when we figure out shadow jitter bug
1107
1108 R_DrawViewEntitiesOnList ();
1109
1110 R_DrawAlphaSurfaces ();
1111
1112 if (r_lightbeam->integer)
1113 R_DrawBeamSurface ();
1114
1115 R_DrawParticles ();
1116
1117 if(gl_mirror->integer)
1118 {
1119 int ms = Sys_Milliseconds ();
1120 if ( ms < r_newrefdef.last_mirrorupdate_time ||
1121 (ms-r_newrefdef.last_mirrorupdate_time) >= 16)
1122 {
1123 GL_SelectTexture (GL_TEXTURE0);
1124 GL_Bind (r_mirrortexture->texnum);
1125 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0,
1126 0, 0, 0, r_mirrortexture->upload_height/2,
1127 r_mirrortexture->upload_width,
1128 r_mirrortexture->upload_height);
1129 r_newrefdef.last_mirrorupdate_time = ms;
1130 }
1131 }
1132
1133
1134 R_BloomBlend( &r_newrefdef );//BLOOMS
1135
1136 R_RenderSun();
1137
1138 R_GLSLPostProcess();
1139
1140 R_DrawVehicleHUD();
1141
1142 R_Flash();
1143
1144 if(map_fog)
1145 qglDisable(GL_FOG);
1146
1147 R_DrawRadar();
1148
1149 *fd = r_newrefdef;
1150 }
1151
R_SetGL2D(void)1152 void R_SetGL2D (void)
1153 {
1154 // set 2D virtual screen size
1155 qglViewport (0,0, vid.width, vid.height);
1156 qglMatrixMode(GL_PROJECTION);
1157 qglLoadIdentity ();
1158 qglOrtho (0, vid.width, vid.height, 0, -99999, 99999);
1159 qglMatrixMode(GL_MODELVIEW);
1160 qglLoadIdentity ();
1161 qglDisable (GL_DEPTH_TEST);
1162 qglDisable (GL_CULL_FACE);
1163 qglDisable (GL_BLEND);
1164 qglEnable (GL_ALPHA_TEST);
1165 qglColor4f (1,1,1,1);
1166 }
1167
1168 /*
1169 @@@@@@@@@@@@@@@@@@@@@
1170 R_RenderFrame
1171
1172 @@@@@@@@@@@@@@@@@@@@@
1173 */
1174
R_RenderFrame(refdef_t * fd)1175 void R_RenderFrame (refdef_t *fd)
1176 {
1177 R_RenderView( fd );
1178
1179 R_SetGL2D ();
1180 }
1181
R_RenderFramePlayerSetup(refdef_t * rfdf)1182 void R_RenderFramePlayerSetup( refdef_t *rfdf )
1183 {
1184
1185 numRadarEnts = 0;
1186
1187 r_newrefdef = *rfdf;
1188
1189 R_SetupFrame();
1190 R_SetFrustum();
1191 R_SetupGL();
1192 R_DrawEntitiesOnList();
1193
1194 R_SetGL2D();
1195
1196 }
1197
R_Register(void)1198 void R_Register( void )
1199 {
1200
1201 con_font = Cvar_Get ("con_font", "default", CVAR_ARCHIVE);
1202
1203 r_lefthand = Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE | CVARDOC_INT);
1204 Cvar_Describe (r_lefthand, "0 means show gun on the right, 1 means show gun on the left, 2 means hide the gun altogether.");
1205 r_norefresh = Cvar_Get ("r_norefresh", "0", 0);
1206 r_fullbright = Cvar_Get ("r_fullbright", "0", 0);
1207 r_drawentities = Cvar_Get ("r_drawentities", "1", 0);
1208 r_drawworld = Cvar_Get ("r_drawworld", "1", 0);
1209 r_novis = Cvar_Get ("r_novis", "0", 0);
1210 r_nocull = Cvar_Get ("r_nocull", "0", 0);
1211 r_lerpmodels = Cvar_Get ("r_lerpmodels", "1", 0);
1212
1213 r_wave = Cvar_Get ("r_wave", "2", CVAR_ARCHIVE); // Water waves
1214
1215 gl_nosubimage = Cvar_Get( "gl_nosubimage", "0", 0 );
1216
1217 gl_particle_min_size = Cvar_Get( "gl_particle_min_size", ".2", CVAR_ARCHIVE );
1218 gl_particle_max_size = Cvar_Get( "gl_particle_max_size", "40", CVAR_ARCHIVE );
1219 gl_particle_size = Cvar_Get( "gl_particle_size", "40", CVAR_ARCHIVE );
1220 gl_particle_att_a = Cvar_Get( "gl_particle_att_a", "0.01", CVAR_ARCHIVE );
1221 gl_particle_att_b = Cvar_Get( "gl_particle_att_b", "0.0", CVAR_ARCHIVE );
1222 gl_particle_att_c = Cvar_Get( "gl_particle_att_c", "0.01", CVAR_ARCHIVE );
1223
1224 gl_modulate = Cvar_Get ("gl_modulate", "2", CVAR_ARCHIVE|CVARDOC_INT );
1225 Cvar_Describe (gl_modulate, "Brightness setting. Higher means brighter.");
1226 gl_log = Cvar_Get( "gl_log", "0", 0 );
1227 gl_bitdepth = Cvar_Get( "gl_bitdepth", "0", 0 );
1228 gl_mode = Cvar_Get( "gl_mode", "3", CVAR_ARCHIVE );
1229 gl_lightmap = Cvar_Get ("gl_lightmap", "0", 0);
1230 gl_nobind = Cvar_Get ("gl_nobind", "0", 0);
1231 gl_picmip = Cvar_Get ("gl_picmip", "0", CVAR_ARCHIVE|CVARDOC_INT);
1232 Cvar_Describe (gl_picmip, "Texture detail. 0 means full detail. Each higher setting has 1/4 less detail.");
1233 gl_skymip = Cvar_Get ("gl_skymip", "0", 0);
1234 gl_showtris = Cvar_Get ("gl_showtris", "0", 0);
1235 gl_showpolys = Cvar_Get ("gl_showpolys", "0", CVARDOC_INT);
1236 Cvar_Describe (gl_showpolys, "Useful tool for mappers. 1 means show world polygon outlines for visible surfaces. 2 means show outlines for all surfaces in the PVS, even if they are hidden. Only works with gl_usevbo 0.");
1237 gl_finish = Cvar_Get ("gl_finish", "0", CVAR_ARCHIVE|CVARDOC_BOOL);
1238 Cvar_Describe (gl_finish, "Waits for graphics driver to finish drawing each frame before drawing the next one. Hurts performance but may improve smoothness on very low-end machines.");
1239 gl_clear = Cvar_Get ("gl_clear", "0", CVARDOC_BOOL);
1240 gl_cull = Cvar_Get ("gl_cull", "1", CVARDOC_BOOL);
1241 Cvar_Describe (gl_cull, "Avoid rendering anything that's off the edge of the screen. Good for performance, recommend leaving it on.");
1242 gl_polyblend = Cvar_Get ("gl_polyblend", "1", 0);
1243
1244 // OPENGL_DRIVER defined by in config.h
1245 gl_driver = Cvar_Get( "gl_driver", OPENGL_DRIVER, 0 );
1246
1247 gl_texturemode = Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE );
1248 gl_texturealphamode = Cvar_Get( "gl_texturealphamode", "default", CVAR_ARCHIVE );
1249 gl_texturesolidmode = Cvar_Get( "gl_texturesolidmode", "default", CVAR_ARCHIVE );
1250 gl_lockpvs = Cvar_Get( "gl_lockpvs", "0", 0 );
1251
1252 gl_ext_pointparameters = Cvar_Get( "gl_ext_pointparameters", "0", CVAR_ARCHIVE );
1253
1254 gl_drawbuffer = Cvar_Get( "gl_drawbuffer", "GL_BACK", 0 );
1255 gl_swapinterval = Cvar_Get( "gl_swapinterval", "1", CVAR_ARCHIVE|CVARDOC_BOOL );
1256 Cvar_Describe (gl_swapinterval, "Sync to Vblank. Eliminates \"tearing\" effects, but it can hurt framerates.");
1257
1258 r_shaders = Cvar_Get ("r_shaders", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1259
1260 r_overbrightbits = Cvar_Get( "r_overbrightbits", "2", CVAR_ARCHIVE );
1261
1262 gl_usevbo = Cvar_Get("gl_usevbo", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1263 Cvar_Describe (gl_usevbo, "Use VBOs for mesh and world geometry. Leave this on unless you've got a very old graphics card.");
1264
1265 gl_mirror = Cvar_Get("gl_mirror", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1266
1267 vid_fullscreen = Cvar_Get( "vid_fullscreen", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1268 vid_gamma = Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE );
1269 vid_contrast = Cvar_Get( "vid_contrast", "1.0", CVAR_ARCHIVE);
1270 //TODO: remove, unless we decide to add GL ES support or something.
1271 vid_ref = Cvar_Get( "vid_ref", "gl", CVAR_ARCHIVE|CVAR_ROM );
1272
1273 gl_vlights = Cvar_Get("gl_vlights", "1", CVAR_ARCHIVE);
1274
1275 gl_normalmaps = Cvar_Get("gl_normalmaps", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1276 gl_bspnormalmaps = Cvar_Get("gl_bspnormalmaps", "0", CVAR_ARCHIVE|CVARDOC_BOOL);
1277 gl_shadowmaps = Cvar_Get("gl_shadowmaps", "0", CVAR_ARCHIVE|CVARDOC_BOOL);
1278 gl_fog = Cvar_Get ("gl_fog", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1279 Cvar_Describe (gl_fog, "Fog and weather effects.");
1280
1281 r_shadowmapscale = Cvar_Get( "r_shadowmapscale", "1", CVAR_ARCHIVE );
1282 r_shadowcutoff = Cvar_Get( "r_shadowcutoff", "880", CVAR_ARCHIVE );
1283
1284 r_lensflare = Cvar_Get( "r_lensflare", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1285 r_lensflare_intens = Cvar_Get ("r_lensflare_intens", "3", CVAR_ARCHIVE|CVARDOC_INT);
1286 r_drawsun = Cvar_Get("r_drawsun", "2", CVAR_ARCHIVE);
1287 r_lightbeam = Cvar_Get ("r_lightbeam", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1288 r_godrays = Cvar_Get ("r_godrays", "0", CVAR_ARCHIVE|CVARDOC_BOOL);
1289 r_godray_intensity = Cvar_Get ("r_godray_intensity", "1.0", CVAR_ARCHIVE);
1290 r_optimize = Cvar_Get ("r_optimize", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1291 Cvar_Describe (r_optimize, "Skip BSP recursion unless you move. Good for performance, recommend leaving it on.");
1292
1293 r_lightmapfiles = Cvar_Get("r_lightmapfiles", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1294 Cvar_Describe (r_lightmapfiles, "Enables the loading of .lightmap files, with more detailed light and shadow. Turn this off if video RAM is limited.");
1295
1296 r_minimap_size = Cvar_Get ("r_minimap_size", "256", CVAR_ARCHIVE );
1297 r_minimap_zoom = Cvar_Get ("r_minimap_zoom", "1", CVAR_ARCHIVE );
1298 r_minimap_style = Cvar_Get ("r_minimap_style", "1", CVAR_ARCHIVE );
1299 r_minimap = Cvar_Get ("r_minimap", "0", CVAR_ARCHIVE|CVARDOC_BOOL );
1300
1301 r_ragdolls = Cvar_Get ("r_ragdolls", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1302 r_ragdoll_debug = Cvar_Get("r_ragdoll_debug", "0", CVAR_ARCHIVE|CVARDOC_BOOL);
1303
1304 sys_priority = Cvar_Get("sys_priority", "0", CVAR_ARCHIVE);
1305 sys_affinity = Cvar_Get("sys_affinity", "1", CVAR_ARCHIVE);
1306
1307 gl_screenshot_type = Cvar_Get("gl_screenshot_type", "jpeg", CVAR_ARCHIVE|CVARDOC_STR);
1308 gl_screenshot_jpeg_quality = Cvar_Get("gl_screenshot_jpeg_quality", "85", CVAR_ARCHIVE|CVARDOC_INT);
1309
1310 r_firstrun = Cvar_Get("r_firstrun", "0", CVAR_ARCHIVE|CVARDOC_BOOL); //first time running the game
1311 Cvar_Describe (r_firstrun, "Set this to 0 if you want the game to auto detect your graphics settings next time you run it.");
1312
1313 r_test = Cvar_Get("r_test", "0", CVAR_ARCHIVE); //for testing things
1314
1315 // FIXME HACK copied over from the video menu code. These are initialized
1316 // again elsewhere. TODO: work out any complications that may arise from
1317 // deleting these duplicate initializations.
1318 Cvar_Get( "r_bloom", "0", CVAR_ARCHIVE );
1319 Cvar_Get( "r_bloom_intensity", "0.5", CVAR_ARCHIVE);
1320 Cvar_Get( "r_overbrightbits", "2", CVAR_ARCHIVE);
1321 Cvar_Get( "vid_width", "640", CVAR_ARCHIVE);
1322 Cvar_Get( "vid_height", "400", CVAR_ARCHIVE);
1323 Cvar_Get( "gl_glsl_shaders", "1", CVAR_ARCHIVE);
1324
1325 Cmd_AddCommand( "imagelist", GL_ImageList_f );
1326 Cmd_AddCommand( "screenshot", GL_ScreenShot_f );
1327 Cmd_AddCommand( "modellist", Mod_Modellist_f );
1328 Cmd_AddCommand( "gl_strings", GL_Strings_f );
1329 }
1330
1331 /*
1332 ==================
1333 R_SetMode
1334 ==================
1335 */
R_SetMode(void)1336 qboolean R_SetMode (void)
1337 {
1338 rserr_t err;
1339 qboolean fullscreen;
1340
1341 if ( vid_fullscreen->modified && !gl_config.allow_cds )
1342 {
1343 Com_Printf ("R_SetMode() - CDS not allowed with this driver\n" );
1344 Cvar_SetValue( "vid_fullscreen", !vid_fullscreen->integer );
1345 vid_fullscreen->modified = false;
1346 }
1347
1348 fullscreen = vid_fullscreen->integer;
1349
1350 vid_fullscreen->modified = false;
1351 gl_mode->modified = false;
1352
1353 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->integer, fullscreen ) ) == rserr_ok )
1354 {
1355 gl_state.prev_mode = gl_mode->integer;
1356 }
1357 else
1358 {
1359 if ( err == rserr_invalid_fullscreen )
1360 {
1361 Cvar_SetValue( "vid_fullscreen", 0);
1362 vid_fullscreen->modified = false;
1363 Com_Printf ("ref_gl::R_SetMode() - fullscreen unavailable in this mode\n" );
1364 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->integer, false ) ) == rserr_ok )
1365 return true;
1366 }
1367 else if ( err == rserr_invalid_mode )
1368 {
1369 Cvar_SetValue( "gl_mode", gl_state.prev_mode );
1370 gl_mode->modified = false;
1371 Com_Printf ("ref_gl::R_SetMode() - invalid mode\n" );
1372 }
1373
1374 // try setting it back to something safe
1375 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_state.prev_mode, false ) ) != rserr_ok )
1376 {
1377 Com_Printf ("ref_gl::R_SetMode() - could not revert to safe mode\n" );
1378 return false;
1379 }
1380 }
1381 return true;
1382 }
1383
1384 /*
1385 ===============
1386 R_SetCompatibility
1387 ===============
1388 */
1389
R_SetCompatibility(void)1390 void R_SetCompatibility(void)
1391 {
1392 Cmd_ExecuteString ("exec graphical_presets/compatibility.cfg");
1393 Cbuf_Execute ();
1394 Com_Printf("...autodetected MAX COMPATIBILITY game setting\n");
1395 }
1396
1397 /*
1398 ===============
1399 R_SetMaxPerformance
1400 ===============
1401 */
1402
R_SetMaxPerformance(void)1403 void R_SetMaxPerformance( void )
1404 {
1405 Cmd_ExecuteString ("exec graphical_presets/maxperformance.cfg");
1406 Cbuf_Execute ();
1407 Com_Printf("...autodetected MAX PERFORMANCE game setting\n");
1408 }
1409
1410 /*
1411 ===============
1412 R_SetPerformance
1413 ===============
1414 */
1415
R_SetPerformance(void)1416 void R_SetPerformance( void )
1417 {
1418 Cmd_ExecuteString ("exec graphical_presets/performance.cfg");
1419 Cbuf_Execute ();
1420 Com_Printf("...autodetected PERFORMANCE game setting\n");
1421 }
1422
1423 /*
1424 ===============
1425 R_SetQuality
1426 ===============
1427 */
1428
R_SetQuality(void)1429 void R_SetQuality( void )
1430 {
1431 Cmd_ExecuteString ("exec graphical_presets/quality.cfg");
1432 Cbuf_Execute ();
1433 Com_Printf("...autodetected QUALITY game setting\n");
1434 }
1435
1436 /*
1437 ===============
1438 R_SetMaxQuality
1439 ===============
1440 */
1441
R_SetMaxQuality(void)1442 void R_SetMaxQuality( void )
1443 {
1444 Cmd_ExecuteString ("exec graphical_presets/maxquality.cfg");
1445 Cbuf_Execute ();
1446 Com_Printf("...autodetected MAX QUALITY game setting\n");
1447 }
1448
1449 #if defined WIN32_VARIANT
CPUSpeed()1450 double CPUSpeed()
1451 {
1452
1453
1454 DWORD BufSize = _MAX_PATH;
1455 DWORD dwMHz = _MAX_PATH;
1456 HKEY hKey; // open the key where the proc speed is hidden:
1457
1458 long lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1459 "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
1460 0,
1461 KEY_READ,
1462 &hKey);
1463
1464 if(lError != ERROR_SUCCESS)
1465 return 0;
1466
1467 // query the key:
1468 RegQueryValueEx(hKey, "~MHz", NULL, NULL, (LPBYTE) &dwMHz, &BufSize);
1469 return (double)dwMHz;
1470
1471 }
1472 #endif
1473
1474 /*
1475 ===============
1476 R_Init
1477 ===============
1478 */
R_Init(void * hinstance,void * hWnd)1479 int R_Init( void *hinstance, void *hWnd )
1480 {
1481 int err;
1482 int j;
1483 extern float r_turbsin[256];
1484
1485 for ( j = 0; j < 256; j++ )
1486 {
1487 r_turbsin[j] *= 0.5;
1488 }
1489
1490 Draw_GetPalette ();
1491
1492 R_Register();
1493
1494 // initialize our QGL dynamic bindings
1495 if ( !QGL_Init( gl_driver->string ) )
1496 {
1497 QGL_Shutdown();
1498 Com_Printf ("ref_gl::R_Init() - could not load \"%s\"\n", gl_driver->string );
1499 return -1;
1500 }
1501
1502 // initialize OS-specific parts of OpenGL
1503 if ( !GLimp_Init( hinstance, hWnd ) )
1504 {
1505 QGL_Shutdown();
1506 return -1;
1507 }
1508
1509 // set our "safe" modes
1510 gl_state.prev_mode = 3;
1511
1512 // create the window and set up the context
1513 if ( !R_SetMode () )
1514 {
1515 QGL_Shutdown();
1516 Com_Printf ("ref_gl::R_Init() - could not R_SetMode()\n" );
1517 return -1;
1518 }
1519
1520 // Initialise TrueType fonts
1521 if ( ! FNT_Initialise( ) ) {
1522 QGL_Shutdown( );
1523 Com_Printf( "ref_gl::R_Init() - could not initialise text drawing front-end\n" );
1524 return -1;
1525 }
1526
1527 /*
1528 ** get our various GL strings
1529 */
1530 gl_config.vendor_string = (const char*)qglGetString (GL_VENDOR);
1531 Com_Printf ("GL_VENDOR: %s\n", gl_config.vendor_string );
1532 gl_config.renderer_string = (const char*)qglGetString (GL_RENDERER);
1533 Com_Printf ("GL_RENDERER: %s\n", gl_config.renderer_string );
1534 gl_config.version_string = (const char*)qglGetString (GL_VERSION);
1535 Com_Printf ("GL_VERSION: %s\n", gl_config.version_string );
1536 gl_config.extensions_string = (const char*)qglGetString (GL_EXTENSIONS);
1537 Com_Printf ("GL_EXTENSIONS: %s\n", gl_config.extensions_string );
1538
1539 gl_config.allow_cds = true;
1540 Com_Printf ("...allowing CDS\n" );
1541
1542 /*
1543 ** grab extensions
1544 */
1545 if ( strstr( gl_config.extensions_string, "GL_EXT_compiled_vertex_array" ) ||
1546 strstr( gl_config.extensions_string, "GL_SGI_compiled_vertex_array" ) )
1547 {
1548 Com_Printf ("...enabling GL_EXT_compiled_vertex_array\n" );
1549 qglLockArraysEXT = ( void * ) qwglGetProcAddress( "glLockArraysEXT" );
1550 qglUnlockArraysEXT = ( void * ) qwglGetProcAddress( "glUnlockArraysEXT" );
1551 }
1552 else
1553 {
1554 Com_Printf ("...GL_EXT_compiled_vertex_array not found\n" );
1555 }
1556
1557 #if defined WIN32_VARIANT
1558 if ( strstr( gl_config.extensions_string, "WGL_EXT_swap_control" ) )
1559 {
1560 qwglSwapIntervalEXT = ( BOOL (WINAPI *)(int)) qwglGetProcAddress( "wglSwapIntervalEXT" );
1561 Com_Printf ("...enabling WGL_EXT_swap_control\n" );
1562 }
1563 else
1564 {
1565 Com_Printf ("...WGL_EXT_swap_control not found\n" );
1566 }
1567 #endif
1568
1569 if (strstr(gl_config.extensions_string, "GL_EXT_point_parameters"))
1570 {
1571 if(gl_ext_pointparameters->integer)
1572 {
1573 qglPointParameterfEXT = (void(APIENTRY*)(GLenum, GLfloat))qwglGetProcAddress("glPointParameterfEXT");
1574 qglPointParameterfvEXT = (void(APIENTRY*)(GLenum, const GLfloat*))qwglGetProcAddress("glPointParameterfvEXT");
1575 }
1576 else
1577 {
1578 Com_Printf ("...ignoring GL_EXT_point_parameters\n" );
1579 }
1580 }
1581 else
1582 {
1583 Com_Printf ("...GL_EXT_point_parameters not found\n" );
1584 }
1585
1586 R_InitImageSubsystem();
1587
1588 R_InitShadowSubsystem();
1589
1590 R_LoadVBOSubsystem();
1591
1592 #if defined DARWIN_SPECIAL_CASE
1593 /*
1594 * development workaround for Mac OS X / Darwin using X11
1595 * problems seen with 2.1 NVIDIA-1.6.18 when calling
1596 * glCreateProgramObjectARB()
1597 * For now, just go with low settings.
1598 */
1599 gl_state.fragment_program = false;
1600 gl_arb_fragment_program = Cvar_Get("gl_arb_fragment_program", "0", CVAR_ARCHIVE);
1601 gl_state.glsl_shaders = false;
1602 gl_glsl_shaders = Cvar_Get("gl_glsl_shaders", "0", CVAR_ARCHIVE);
1603 gl_dynamic = Cvar_Get ("gl_dynamic", "0", CVAR_ARCHIVE);
1604 Cvar_SetValue("r_firstrun", 1);
1605 R_SetMaxPerformance();
1606 Com_Printf("...Development Workaround. Low game settings forced.\n");
1607 #else
1608
1609 //always do this check for ATI drivers - they are somewhat bugged in regards to shadowmapping and use of shadow2dproj command
1610 if(!strcmp(gl_config.vendor_string, "ATI Technologies Inc."))
1611 gl_state.ati = true;
1612
1613 //load shader programs
1614 R_LoadARBPrograms();
1615
1616 R_LoadGLSLPrograms();
1617
1618 //if running for the very first time, automatically set video settings
1619 if(!r_firstrun->integer)
1620 {
1621 qboolean ati_nvidia = false;
1622 double CPUTotalSpeed = 4000.0; //default to this
1623 double OGLVer = atof(&gl_config.version_string[0]);
1624 //int OGLSubVer = atoi(&gl_config.version_string[2]);
1625
1626 #if defined WIN32_VARIANT
1627 SYSTEM_INFO sysInfo;
1628 GetSystemInfo(&sysInfo);
1629
1630 Com_Printf("...CPU: %4.2f Cores: %d\n", CPUSpeed(), sysInfo.dwNumberOfProcessors);
1631
1632 CPUTotalSpeed = sysInfo.dwNumberOfProcessors * CPUSpeed();
1633
1634 #else
1635 FILE *fp;
1636 char res[128];
1637 int cores;
1638 size_t szrslt;
1639 int irslt;
1640 fp = popen("/bin/cat /proc/cpuinfo | grep -c '^processor'","r");
1641 if ( fp == NULL )
1642 goto cpuinfo_error;
1643 szrslt = fread(res, 1, sizeof(res)-1, fp);
1644 res[szrslt] = 0;
1645 pclose(fp);
1646 if ( !szrslt )
1647 goto cpuinfo_error;
1648 cores = atoi( &res[0] );
1649 fp = popen("/bin/cat /proc/cpuinfo | grep '^cpu MHz'","r");
1650 if ( fp == NULL )
1651 goto cpuinfo_error;
1652 szrslt = fread(res, 1, sizeof(res)-1, fp); // about 20 bytes/cpu
1653 res[szrslt] = 0;
1654 pclose(fp);
1655 if ( !szrslt )
1656 goto cpuinfo_error;
1657 irslt = sscanf( res, "cpu MHz : %lf", &CPUTotalSpeed );
1658 if ( !irslt )
1659 goto cpuinfo_error;
1660 Com_Printf("...CPU: %4.2f Cores: %d\n", CPUTotalSpeed, cores);
1661 CPUTotalSpeed *= cores;
1662 goto cpuinfo_exit;
1663 cpuinfo_error:
1664 Com_Printf("...Reading /proc/cpuinfo failed.\n");
1665 cpuinfo_exit:
1666 #endif
1667
1668 //check to see if we are using ATI or NVIDIA, otherwise, we don't want to
1669 //deal with high settings on offbrand GPU's like Intel or Unichrome
1670 if(!strcmp(gl_config.vendor_string, "ATI Technologies Inc.") || !strcmp(gl_config.vendor_string, "NVIDIA Corporation"))
1671 ati_nvidia = true;
1672
1673 if(OGLVer < 2.1)
1674 {
1675 //weak GPU, set to maximum compatibility
1676 R_SetCompatibility();
1677 }
1678 else if(OGLVer >= 3)
1679 {
1680 //GPU is modern, check CPU
1681 if(CPUTotalSpeed > 3800.0 && ati_nvidia)
1682 R_SetMaxQuality();
1683 else
1684 R_SetQuality();
1685 }
1686 else
1687 {
1688 if(CPUTotalSpeed > 3800.0 && ati_nvidia)
1689 R_SetQuality();
1690 else
1691 R_SetPerformance();
1692 }
1693
1694 //never run again
1695 Cvar_SetValue("r_firstrun", 1);
1696 }
1697 #endif
1698
1699 GL_SetDefaultState();
1700
1701 R_CheckFBOExtensions ();
1702
1703 GL_InitImages ();
1704 Mod_Init ();
1705 R_InitParticleTexture ();
1706 Draw_InitLocal ();
1707
1708 R_GenerateShadowFBO();
1709 VLight_Init();
1710
1711 //Initialize ODE
1712 // ODE assert failures sometimes occur, this may or may not help.
1713 r_odeinit_success = dInitODE2(0);
1714 //ODE - clear out any ragdolls;
1715 if ( r_odeinit_success )
1716 {
1717 Com_Printf("...ODE initialized.\n");
1718 R_ClearAllRagdolls();
1719 Com_Printf("...Ragdolls initialized.\n");
1720 }
1721 else
1722 {
1723 Com_Printf("...ODE initialization failed.\n...Ragdolls are disabled.\n");
1724 }
1725
1726 scr_playericonalpha = 0.0;
1727
1728 err = qglGetError();
1729 if ( err != GL_NO_ERROR )
1730 Com_Printf ("glGetError() = 0x%x\n", err);
1731
1732 return 0;
1733 }
1734
1735 /*
1736 ===============
1737 R_Shutdown
1738 ===============
1739 */
R_Shutdown(void)1740 void R_Shutdown (void)
1741 {
1742 Cmd_RemoveCommand ("modellist");
1743 Cmd_RemoveCommand ("screenshot");
1744 Cmd_RemoveCommand ("imagelist");
1745 Cmd_RemoveCommand ("gl_strings");
1746
1747 R_VCShutdown();
1748
1749 Mod_FreeAll ();
1750
1751 FNT_Shutdown( );
1752 GL_ShutdownImages ();
1753
1754 /*
1755 ** shut down OS specific OpenGL stuff like contexts, etc.
1756 */
1757 GLimp_Shutdown();
1758
1759 /*
1760 ** shutdown our QGL subsystem
1761 */
1762 if(gl_state.glsl_shaders) {
1763 glDeleteObjectARB( g_vertexShader );
1764 glDeleteObjectARB( g_fragmentShader );
1765 glDeleteObjectARB( g_programObj );
1766 }
1767
1768 QGL_Shutdown();
1769
1770 //Shutdown ODE
1771 // ODE might fail assert on close when not intialized
1772 if ( r_odeinit_success )
1773 {
1774 Com_DPrintf("Closing ODE\n");
1775 dCloseODE();
1776 }
1777 }
1778
1779
1780
1781 /*
1782 @@@@@@@@@@@@@@@@@@@@@
1783 R_BeginFrame
1784 @@@@@@@@@@@@@@@@@@@@@
1785 */
R_BeginFrame(float camera_separation)1786 void R_BeginFrame( float camera_separation )
1787 {
1788
1789 gl_state.camera_separation = camera_separation;
1790
1791 if (con_font->modified)
1792 RefreshFont ();
1793
1794 /*
1795 ** change modes if necessary
1796 */
1797 if ( gl_mode->modified || vid_fullscreen->modified )
1798 { // FIXME: only restart if CDS is required
1799 cvar_t *ref;
1800
1801 ref = Cvar_Get ("vid_ref", "gl", 0);
1802 ref->modified = true;
1803 }
1804
1805 if ( gl_log->modified )
1806 {
1807 GLimp_EnableLogging( gl_log->integer );
1808 gl_log->modified = false;
1809 }
1810
1811 if ( gl_log->integer )
1812 {
1813 GLimp_LogNewFrame();
1814 }
1815
1816 GLimp_BeginFrame( camera_separation );
1817
1818 /*
1819 ** go into 2D mode
1820 */
1821 R_SetGL2D ();
1822
1823 /*
1824 ** draw buffer stuff
1825 */
1826 if ( gl_drawbuffer->modified )
1827 {
1828 gl_drawbuffer->modified = false;
1829
1830 if ( gl_state.camera_separation == 0 || !gl_state.stereo_enabled )
1831 {
1832 if ( Q_strcasecmp( gl_drawbuffer->string, "GL_FRONT" ) == 0 )
1833 qglDrawBuffer( GL_FRONT );
1834 else
1835 qglDrawBuffer( GL_BACK );
1836 }
1837 }
1838
1839 /*
1840 ** texturemode stuff
1841 */
1842 if ( gl_texturemode->modified )
1843 {
1844 GL_TextureMode( gl_texturemode->string );
1845 gl_texturemode->modified = false;
1846 }
1847
1848 if ( gl_texturealphamode->modified )
1849 {
1850 GL_TextureAlphaMode( gl_texturealphamode->string );
1851 gl_texturealphamode->modified = false;
1852 }
1853
1854 if ( gl_texturesolidmode->modified )
1855 {
1856 GL_TextureSolidMode( gl_texturesolidmode->string );
1857 gl_texturesolidmode->modified = false;
1858 }
1859
1860 /*
1861 ** swapinterval stuff
1862 */
1863 GL_UpdateSwapInterval();
1864
1865 //
1866 // clear screen if desired
1867 //
1868 R_Clear ();
1869 }
1870
1871 /*
1872 =============
1873 R_AppActivate
1874 =============
1875 */
R_AppActivate(qboolean active)1876 void R_AppActivate( qboolean active )
1877 {
1878 GLimp_AppActivate (active);
1879 }
1880
1881 /*
1882 =============
1883 R_EndFrame
1884 =============
1885 */
R_EndFrame(void)1886 void R_EndFrame (void)
1887 {
1888 GLimp_EndFrame ();
1889 }
1890
1891 /*
1892 =============
1893 R_SetPalette
1894 =============
1895 */
1896 unsigned r_rawpalette[256];
1897
R_SetPalette(const unsigned char * palette)1898 void R_SetPalette ( const unsigned char *palette)
1899 {
1900 int i;
1901
1902 byte *rp = ( byte * ) r_rawpalette;
1903
1904 if ( palette )
1905 {
1906 for ( i = 0; i < 256; i++ )
1907 {
1908 rp[i*4+0] = palette[i*3+0];
1909 rp[i*4+1] = palette[i*3+1];
1910 rp[i*4+2] = palette[i*3+2];
1911 rp[i*4+3] = 0xff;
1912 }
1913 }
1914 else
1915 {
1916 for ( i = 0; i < 256; i++ )
1917 {
1918 rp[i*4+0] = d_8to24table[i] & 0xff;
1919 rp[i*4+1] = ( d_8to24table[i] >> 8 ) & 0xff;
1920 rp[i*4+2] = ( d_8to24table[i] >> 16 ) & 0xff;
1921 rp[i*4+3] = 0xff;
1922 }
1923 }
1924
1925 if ( qglClear && qglClearColor)
1926 {
1927 // only run this if we haven't uninitialised
1928 // OpenGL already
1929 qglClearColor (0,0,0,0);
1930 qglClear (GL_COLOR_BUFFER_BIT);
1931 qglClearColor (1,0, 0.5 , 0.5);
1932 }
1933 }
1934
1935 /*
1936 ===============
1937 R_FarClip
1938 ===============
1939 */
R_FarClip(void)1940 float R_FarClip( void )
1941 {
1942 float farclip, farclip_dist;
1943 int i;
1944 vec_t mins[4];
1945 vec_t maxs[4];
1946 vec_t dist;
1947
1948 farclip_dist = DotProduct( r_origin, vpn );
1949
1950 if(r_farclip_min > 256.0f)
1951 farclip = farclip_dist + r_farclip_min;
1952 else
1953 farclip = farclip_dist + 256.0f;
1954
1955 if( r_worldmodel && !(r_newrefdef.rdflags & RDF_NOWORLDMODEL) ) {
1956
1957 for (i = 0; i < 3; i++) {
1958 mins[i] = r_worldmodel->nodes[0].minmaxs[i];
1959 maxs[i] = r_worldmodel->nodes[0].minmaxs[3+i];
1960 }
1961 dist = (vpn[0] < 0 ? mins[0] : maxs[0]) * vpn[0] +
1962 (vpn[1] < 0 ? mins[1] : maxs[1]) * vpn[1] +
1963 (vpn[2] < 0 ? mins[2] : maxs[2]) * vpn[2];
1964 if( dist > farclip )
1965 farclip = dist;
1966 }
1967
1968 if((farclip - farclip_dist + r_farclip_bias) > r_farclip)
1969 return ( farclip - farclip_dist + r_farclip_bias);
1970 else
1971 return r_farclip;
1972 }
1973
1974 /*
1975 =============
1976 R_SetupProjectionMatrix
1977 =============
1978 */
R_SetupProjectionMatrix(refdef_t * rd,mat4x4_t m)1979 void R_SetupProjectionMatrix( refdef_t *rd, mat4x4_t m )
1980 {
1981 double xMin, xMax, yMin, yMax, zNear, zFar;
1982
1983 r_farclip = R_FarClip ();
1984
1985 zNear = 4;
1986 zFar = r_farclip;
1987
1988 yMax = zNear * tan( rd->fov_y * M_PI / 360.0 );
1989 yMin = -yMax;
1990
1991 xMin = yMin * rd->width / rd->height;
1992 xMax = yMax * rd->width / rd->height;
1993
1994 xMin += -( 2 * gl_state.camera_separation ) / zNear;
1995 xMax += -( 2 * gl_state.camera_separation ) / zNear;
1996
1997 m[0] = (2.0 * zNear) / (xMax - xMin);
1998 m[1] = 0.0f;
1999 m[2] = 0.0f;
2000 m[3] = 0.0f;
2001 m[4] = 0.0f;
2002 m[5] = (2.0 * zNear) / (yMax - yMin);
2003 m[6] = 0.0f;
2004 m[7] = 0.0f;
2005 m[8] = (xMax + xMin) / (xMax - xMin);
2006 m[9] = (yMax + yMin) / (yMax - yMin);
2007 m[10] = -(zFar + zNear) / (zFar - zNear);
2008 m[11] = -1.0f;
2009 m[12] = 0.0f;
2010 m[13] = 0.0f;
2011 m[14] = -(2.0 * zFar * zNear) / (zFar - zNear);
2012 m[15] = 0.0f;
2013 }
2014 /*
2015 =============
2016 R_SetupModelviewMatrix
2017 =============
2018 */
R_SetupModelviewMatrix(refdef_t * rd,mat4x4_t m)2019 void R_SetupModelviewMatrix( refdef_t *rd, mat4x4_t m )
2020 {
2021 Vector4Set( &m[0], 0, 0, -1, 0 );
2022 Vector4Set( &m[4], -1, 0, 0, 0 );
2023 Vector4Set( &m[8], 0, 1, 0, 0 );
2024 Vector4Set( &m[12], 0, 0, 0, 1 );
2025
2026 Matrix4_Rotate( m, -rd->viewangles[2], 1, 0, 0 );
2027 Matrix4_Rotate( m, -rd->viewangles[0], 0, 1, 0 );
2028 Matrix4_Rotate( m, -rd->viewangles[1], 0, 0, 1 );
2029 Matrix4_Translate( m, -rd->vieworg[0], -rd->vieworg[1], -rd->vieworg[2] );
2030 }
2031
R_TransformVectorToScreen(refdef_t * rd,vec3_t in,vec2_t out)2032 void R_TransformVectorToScreen( refdef_t *rd, vec3_t in, vec2_t out )
2033 {
2034 mat4x4_t p, m;
2035 vec4_t temp, temp2;
2036
2037 if( !rd || !in || !out )
2038 return;
2039
2040 temp[0] = in[0];
2041 temp[1] = in[1];
2042 temp[2] = in[2];
2043 temp[3] = 1.0f;
2044
2045 R_SetupProjectionMatrix( rd, p );
2046 R_SetupModelviewMatrix( rd, m );
2047
2048 Matrix4_Multiply_Vector( m, temp, temp2 );
2049 Matrix4_Multiply_Vector( p, temp2, temp );
2050
2051 if( !temp[3] )
2052 return;
2053 out[0] = rd->x + (temp[0] / temp[3] + 1.0f) * rd->width * 0.5f;
2054 out[1] = rd->y + (temp[1] / temp[3] + 1.0f) * rd->height * 0.5f;
2055 }
2056