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 #include "gl_local.h"
22
23 #ifndef WIN32
24 #define __stdcall
25 #endif
26
27 //long (*Q_ftol)(float f);
28
29 void R_Clear (void);
30
31 viddef_t vid;
32
33 refimport_t ri;
34 refimportnew_t rx;
35
36 unsigned int GL_TEXTURE0, GL_TEXTURE1;
37
38 model_t *r_worldmodel;
39
40 double gldepthmin, gldepthmax;
41
42 double vid_scaled_width, vid_scaled_height;
43
44 glconfig_t gl_config;
45 glstate_t gl_state;
46
47 image_t *r_notexture; // use for bad textures
48 image_t *r_particletexture; // little dot for particles
49
50 entity_t *currententity;
51 model_t *currentmodel;
52
53 cplane_t frustum[4];
54
55 int r_visframecount; // bumped when going to a new PVS
56 int r_framecount; // used for dlight push checking
57
58 int c_brush_polys, c_alias_polys;
59
60 float v_blend[4]; // final blending color
61
62 void GL_Strings_f( void );
63
64 //
65 // view origin
66 //
67 vec3_t vup;
68 vec3_t vpn;
69 vec3_t vright;
70 vec3_t r_origin;
71
72 float r_world_matrix[16];
73 float r_base_world_matrix[16];
74
75 //
76 // screen size info
77 //
78 refdef_t r_newrefdef;
79
80 int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
81
82 cvar_t *r_norefresh;
83 cvar_t *r_drawentities;
84 cvar_t *r_drawworld;
85 cvar_t *r_speeds;
86 cvar_t *r_fullbright;
87 cvar_t *r_novis;
88 cvar_t *r_nocull;
89 cvar_t *r_lerpmodels;
90 cvar_t *r_lefthand;
91
92 cvar_t *r_lightlevel; // FIXME: This is a HACK to get the client's light level
93
94 //cvar_t *gl_nosubimage;
95 cvar_t *gl_allow_software;
96
97 cvar_t *gl_vertex_arrays;
98
99 cvar_t *gl_particle_min_size;
100 cvar_t *gl_particle_max_size;
101 cvar_t *gl_particle_size;
102 cvar_t *gl_particle_att_a;
103 cvar_t *gl_particle_att_b;
104 cvar_t *gl_particle_att_c;
105
106 //cvar_t *gl_ext_swapinterval;
107 cvar_t *gl_ext_palettedtexture;
108 cvar_t *gl_ext_multitexture;
109 cvar_t *gl_ext_pointparameters;
110 //cvar_t *gl_ext_compiled_vertex_array;
111
112 //r1ch: my extensions
113 //cvar_t *gl_ext_generate_mipmap;
114 cvar_t *gl_ext_point_sprite;
115 cvar_t *gl_ext_texture_filter_anisotropic;
116 cvar_t *gl_ext_texture_non_power_of_two;
117 cvar_t *gl_ext_max_anisotropy;
118 cvar_t *gl_ext_nv_multisample_filter_hint;
119 cvar_t *gl_ext_occlusion_query;
120
121 cvar_t *gl_colorbits;
122 cvar_t *gl_alphabits;
123 cvar_t *gl_depthbits;
124 cvar_t *gl_stencilbits;
125
126 cvar_t *gl_ext_multisample;
127 cvar_t *gl_ext_samples;
128
129 cvar_t *gl_zfar;
130 cvar_t *gl_hudscale;
131
132 cvar_t *cl_version;
133 cvar_t *gl_r1gl_test;
134 cvar_t *gl_doublelight_entities;
135 cvar_t *gl_noscrap;
136 cvar_t *gl_overbrights;
137 cvar_t *gl_linear_mipmaps;
138
139 cvar_t *vid_gamma_pics;
140
141 cvar_t *gl_forcewidth;
142 cvar_t *gl_forceheight;
143
144 cvar_t *vid_topmost;
145
146 //cvar_t *gl_log;
147 cvar_t *gl_bitdepth;
148 cvar_t *gl_drawbuffer;
149 cvar_t *gl_driver;
150 //cvar_t *gl_lightmap;
151 cvar_t *gl_shadows;
152 cvar_t *gl_mode;
153 cvar_t *gl_dynamic;
154 //cvar_t *gl_monolightmap;
155 cvar_t *gl_modulate;
156 cvar_t *gl_nobind;
157 cvar_t *gl_round_down;
158 cvar_t *gl_picmip;
159 cvar_t *gl_skymip;
160 cvar_t *gl_showtris;
161 cvar_t *gl_ztrick;
162 cvar_t *gl_finish;
163 cvar_t *gl_flush;
164 cvar_t *gl_clear;
165 cvar_t *gl_cull;
166 cvar_t *gl_polyblend;
167 cvar_t *gl_flashblend;
168 //cvar_t *gl_playermip;
169 //cvar_t *gl_saturatelighting;
170 cvar_t *gl_swapinterval;
171 cvar_t *gl_texturemode;
172 cvar_t *gl_texturealphamode;
173 cvar_t *gl_texturesolidmode;
174 cvar_t *gl_lockpvs;
175 cvar_t *gl_jpg_quality;
176 cvar_t *gl_coloredlightmaps;
177
178 //cvar_t *gl_3dlabs_broken;
179
180 cvar_t *vid_fullscreen;
181 cvar_t *vid_gamma;
182 cvar_t *vid_ref;
183 cvar_t *vid_forcedrefresh;
184 cvar_t *vid_optimalrefresh;
185 cvar_t *vid_nowgl;
186 cvar_t *vid_restore_on_switch;
187
188 cvar_t *gl_texture_formats;
189 cvar_t *gl_pic_formats;
190
191 cvar_t *gl_dlight_falloff;
192 cvar_t *gl_alphaskins;
193 cvar_t *gl_defertext;
194
195 cvar_t *gl_pic_scale;
196
197 //cvar_t *con_alpha;
198
199 vec4_t colorWhite = {1,1,1,1};
200
201 qboolean load_png_pics = true;
202 qboolean load_tga_pics = true;
203 qboolean load_jpg_pics = true;
204
205 qboolean load_png_wals = true;
206 qboolean load_tga_wals = true;
207 qboolean load_jpg_wals = true;
208
209 extern cvar_t *gl_contrast;
210
211 /*
212 =================
213 R_CullBox
214
215 Returns true if the box is completely outside the frustom
216 =================
217 */
R_CullBox(vec3_t mins,vec3_t maxs)218 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
219 {
220 int i;
221
222 if (FLOAT_NE_ZERO(r_nocull->value))
223 return false;
224
225 for (i=0 ; i<4 ; i++)
226 if (BOX_ON_PLANE_SIDE(mins, maxs, &frustum[i]) == 2)
227 return true;
228 return false;
229 }
230
231
R_RotateForEntity(entity_t * e)232 void R_RotateForEntity (entity_t *e)
233 {
234 qglTranslatef (e->origin[0], e->origin[1], e->origin[2]);
235
236 qglRotatef (e->angles[1], 0, 0, 1);
237 qglRotatef (-e->angles[0], 0, 1, 0);
238 qglRotatef (-e->angles[2], 1, 0, 0);
239 }
240
241 /*
242 =============================================================
243
244 SPRITE MODELS
245
246 =============================================================
247 */
248
249 /*
250 =================
251 R_DrawSpriteModel
252
253 =================
254 */
R_DrawSpriteModel(entity_t * e)255 void R_DrawSpriteModel (entity_t *e)
256 {
257 float alpha = 1.0F;
258 vec3_t point;
259 dsprframe_t *frame;
260 float *up, *right;
261 dsprite_t *psprite;
262
263 // don't even bother culling, because it's just a single
264 // polygon without a surface cache
265
266 psprite = (dsprite_t *)currentmodel->extradata;
267
268 #if 0
269 if (e->frame < 0 || e->frame >= psprite->numframes)
270 {
271 ri.Con_Printf (PRINT_ALL, "no such sprite frame %i\n", e->frame);
272 e->frame = 0;
273 }
274 #endif
275 e->frame %= psprite->numframes;
276
277 frame = &psprite->frames[e->frame];
278
279 #if 0
280 if (psprite->type == SPR_ORIENTED)
281 { // bullet marks on walls
282 vec3_t v_forward, v_right, v_up;
283
284 AngleVectors (currententity->angles, v_forward, v_right, v_up);
285 up = v_up;
286 right = v_right;
287 }
288 else
289 #endif
290 { // normal sprite
291 up = vup;
292 right = vright;
293 }
294
295 if ( e->flags & RF_TRANSLUCENT )
296 alpha = e->alpha;
297
298 if ( alpha != 1.0F )
299 qglEnable( GL_BLEND );
300
301 qglColor4f( 1, 1, 1, alpha );
302
303 GL_Bind(currentmodel->skins[e->frame]->texnum);
304
305 GL_TexEnv( GL_MODULATE );
306
307 if ( alpha == 1.0 )
308 qglEnable (GL_ALPHA_TEST);
309 else
310 qglDisable( GL_ALPHA_TEST );
311
312 qglBegin (GL_QUADS);
313
314 qglTexCoord2f (0, 1);
315 VectorMA (e->origin, -frame->origin_y, up, point);
316 VectorMA (point, -frame->origin_x, right, point);
317 qglVertex3fv (point);
318
319 qglTexCoord2f (0, 0);
320 VectorMA (e->origin, frame->height - frame->origin_y, up, point);
321 VectorMA (point, -frame->origin_x, right, point);
322 qglVertex3fv (point);
323
324 qglTexCoord2f (1, 0);
325 VectorMA (e->origin, frame->height - frame->origin_y, up, point);
326 VectorMA (point, frame->width - frame->origin_x, right, point);
327 qglVertex3fv (point);
328
329 qglTexCoord2f (1, 1);
330 VectorMA (e->origin, -frame->origin_y, up, point);
331 VectorMA (point, frame->width - frame->origin_x, right, point);
332 qglVertex3fv (point);
333
334 qglEnd ();
335
336 qglDisable (GL_ALPHA_TEST);
337 GL_TexEnv( GL_REPLACE );
338
339 if ( alpha != 1.0F )
340 qglDisable( GL_BLEND );
341
342 qglColor4fv(colorWhite);
343 }
344
345 //==================================================================================
346
347 /*
348 =============
349 R_DrawNullModel
350 =============
351 */
R_DrawNullModel(void)352 void R_DrawNullModel (void)
353 {
354 vec3_t shadelight;
355 int i;
356
357 if ( currententity->flags & RF_FULLBRIGHT )
358 shadelight[0] = shadelight[1] = shadelight[2] = 1.0F;
359 else
360 R_LightPoint (currententity->origin, shadelight);
361
362 qglPushMatrix ();
363 R_RotateForEntity (currententity);
364
365 qglDisable (GL_TEXTURE_2D);
366 qglColor3fv (shadelight);
367
368 qglBegin (GL_TRIANGLE_FAN);
369 qglVertex3f (0, 0, -16);
370 for (i=0 ; i<=4 ; i++)
371 qglVertex3f (16*(float)cos(i*M_PI_DIV_2), 16*(float)sin(i*M_PI_DIV_2), 0);
372 qglEnd ();
373
374 qglBegin (GL_TRIANGLE_FAN);
375 qglVertex3f (0, 0, 16);
376 for (i=4 ; i>=0 ; i--)
377 qglVertex3f (16*(float)cos(i*M_PI_DIV_2), 16*(float)sin(i*M_PI_DIV_2), 0);
378 qglEnd ();
379
380 qglColor3f (1,1,1);
381 qglPopMatrix ();
382 qglEnable (GL_TEXTURE_2D);
383 }
384
385 int visibleBits[MAX_ENTITIES];
386
387
R_Occlusion_Results(void)388 void R_Occlusion_Results (void)
389 {
390 int i, visible;
391 entity_t *ent;
392 //int numOccluded = 0;
393
394 // now we read back
395 for (i = 0; i < r_newrefdef.num_entities; i++)
396 {
397 int available;
398
399 ent = &r_newrefdef.entities[i];
400
401 if (!ent->model || ent->model->type == mod_brush)
402 {
403 visibleBits[i] = 500;
404 continue;
405 }
406
407 if (visibleBits[i] > 1)
408 {
409 visibleBits[i]--;
410 continue;
411 }
412
413 qglGetQueryObjectivARB (gl_config.r1gl_Queries[i], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
414 if (!available)
415 {
416 if (gl_ext_occlusion_query->value == 2.0f)
417 i--;
418 else
419 visibleBits[i] = 25;
420
421 continue;
422 }
423
424 // get the object and store it in the occlusion bits for the ent
425 qglGetQueryObjectivARB (gl_config.r1gl_Queries[i], GL_QUERY_RESULT, &visible);
426
427 if (!visible)
428 {
429 //ri.Con_Printf (PRINT_ALL, "Occluded %d, %s\n", i, ent->model->name);
430 visibleBits[i] = 0;
431 }
432 else
433 visibleBits[i] = 25;
434 }
435 }
436
R_Occlusion_Run(void)437 void R_Occlusion_Run (void)
438 {
439 int i;
440 entity_t *ent;
441 float mins[3];
442 float maxs[3];
443
444 static const byte boxindexes[] =
445 {
446 0, 1, 2, 3,
447 4, 5, 1, 0,
448 3, 2, 6, 7,
449 5, 4, 7, 6,
450 1, 5, 6, 2,
451 4, 0, 3, 7
452 };
453
454 float boxverts[24];
455
456 if (!r_newrefdef.num_entities)
457 return;
458
459 // disable texturing
460 qglDisable (GL_TEXTURE_2D);
461
462 // because we don;t know the orientation of the bbox in advance...
463 qglDisable (GL_CULL_FACE);
464
465 // disable framebuffer and depthbuffer writes
466 qglColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
467 qglDepthMask (GL_FALSE);
468
469 qglEnableClientState (GL_VERTEX_ARRAY);
470 qglVertexPointer (3, GL_FLOAT, 0, boxverts);
471
472 for (i = 0; i < r_newrefdef.num_entities; i++)
473 {
474 ent = &r_newrefdef.entities[i];
475
476 if (!ent->model || ent->model->type == mod_brush)
477 continue;
478
479 if (visibleBits[i] > 1)
480 continue;
481
482 // get mins and maxs points
483 VectorAdd (ent->origin, ent->model->mins, mins);
484 VectorAdd (ent->origin, ent->model->maxs, maxs);
485
486 // CPU grunt to the rescue!!!
487 boxverts[0] = boxverts[9] = boxverts[12] = boxverts[21] = mins[0];
488 boxverts[3] = boxverts[6] = boxverts[15] = boxverts[18] = maxs[0];
489 boxverts[1] = boxverts[4] = boxverts[13] = boxverts[16] = maxs[1];
490 boxverts[7] = boxverts[10] = boxverts[19] = boxverts[22] = mins[1];
491 boxverts[2] = boxverts[5] = boxverts[8] = boxverts[11] = maxs[2];
492 boxverts[14] = boxverts[17] = boxverts[20] = boxverts[23] = mins[2];
493
494 // begin the occlusion query
495 qglBeginQueryARB (GL_SAMPLES_PASSED, gl_config.r1gl_Queries[i]);
496
497 // draw as indexed varray
498 qglDrawElements (GL_QUADS, 24, GL_UNSIGNED_BYTE, boxindexes);
499
500 // end the query
501 // don't read back immediately so that we give the query time to be ready
502 qglEndQueryARB (GL_SAMPLES_PASSED);
503 }
504
505 qglDisableClientState (GL_VERTEX_ARRAY);
506
507 // restore basic state
508 qglEnable (GL_TEXTURE_2D);
509 qglEnable (GL_CULL_FACE);
510
511 // enable framebuffer and depthbuffer writes
512 qglColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
513 qglDepthMask (GL_TRUE);
514
515 // some implementations don't reset the primary colour properly after restoring the colormask
516 qglColor4f (1, 1, 1, 1);
517 }
518
519 /*
520 =============
521 R_DrawEntitiesOnList
522 =============
523 */
R_DrawEntitiesOnList(void)524 void R_DrawEntitiesOnList (void)
525 {
526 int i;
527
528 if (FLOAT_EQ_ZERO(r_drawentities->value))
529 return;
530
531 if (gl_config.r1gl_QueryBits)
532 R_Occlusion_Results ();
533
534 // draw non-transparent first
535 for (i=0 ; i<r_newrefdef.num_entities ; i++)
536 {
537 if (gl_config.r1gl_QueryBits && !visibleBits[i])
538 continue;
539
540 currententity = &r_newrefdef.entities[i];
541
542 if (currententity->flags & RF_TRANSLUCENT || (FLOAT_NE_ZERO(gl_alphaskins->value) && currententity->skin && currententity->skin->has_alpha))
543 continue; // solid
544
545 if ( currententity->flags & RF_BEAM )
546 {
547 R_DrawBeam( currententity );
548 }
549 else
550 {
551 currentmodel = currententity->model;
552 if (!currentmodel)
553 {
554 R_DrawNullModel ();
555 continue;
556 }
557
558 switch (currentmodel->type)
559 {
560 case mod_alias:
561 R_DrawAliasModel (currententity);
562 break;
563 case mod_brush:
564 R_DrawBrushModel (currententity);
565 break;
566 case mod_sprite:
567 R_DrawSpriteModel (currententity);
568 break;
569 default:
570 ri.Sys_Error (ERR_DROP, "Bad modeltype %d on %s", currentmodel->type, currentmodel->name);
571 break;
572 }
573 }
574 }
575
576 // draw transparent entities
577 // we could sort these if it ever becomes a problem...
578 qglDepthMask (0); // no z writes
579 for (i=0 ; i<r_newrefdef.num_entities ; i++)
580 {
581 currententity = &r_newrefdef.entities[i];
582 if (!(currententity->flags & RF_TRANSLUCENT || (FLOAT_NE_ZERO(gl_alphaskins->value) && currententity->skin && currententity->skin->has_alpha)))
583 continue; // solid
584
585 if ( currententity->flags & RF_BEAM )
586 {
587 R_DrawBeam( currententity );
588 }
589 else
590 {
591 currentmodel = currententity->model;
592
593 if (!currentmodel)
594 {
595 R_DrawNullModel ();
596 continue;
597 }
598 switch (currentmodel->type)
599 {
600 case mod_alias:
601 R_DrawAliasModel (currententity);
602 break;
603 case mod_brush:
604 R_DrawBrushModel (currententity);
605 break;
606 case mod_sprite:
607 R_DrawSpriteModel (currententity);
608 break;
609 default:
610 ri.Sys_Error (ERR_DROP, "Bad modeltype %d on %s", currentmodel->type, currentmodel->name);
611 break;
612 }
613 }
614 }
615 qglDepthMask (1); // back to writing
616
617 }
618
619 /*
620 ** GL_DrawParticles
621 **
622 */
GL_DrawParticles(int num_particles,const particle_t particles[])623 void GL_DrawParticles( int num_particles, const particle_t particles[])
624 {
625 const particle_t *p;
626 int i;
627 vec3_t up, right;
628 float scale;
629 //byte color[4];
630 vec4_t colorf;
631
632 GL_Bind(r_particletexture->texnum);
633 qglDepthMask( GL_FALSE ); // no z buffering
634 qglEnable( GL_BLEND );
635 GL_TexEnv( GL_MODULATE );
636 qglBegin( GL_TRIANGLES );
637
638 VectorScale (vup, 1.5f, up);
639 VectorScale (vright, 1.5f, right);
640
641 for ( p = particles, i=0 ; i < num_particles ; i++,p++)
642 {
643 // hack a scale up to keep particles from disapearing
644 scale = ( p->origin[0] - r_origin[0] ) * vpn[0] +
645 ( p->origin[1] - r_origin[1] ) * vpn[1] +
646 ( p->origin[2] - r_origin[2] ) * vpn[2];
647
648 if (scale < 20)
649 scale = 1;
650 else
651 scale = 1 + scale * 0.004f;
652
653 //*(int *)color = colortable[p->color];
654 //color[3] = (byte)Q_ftol(p->alpha*255);
655
656 FastVectorCopy (d_8to24float[p->color], colorf);
657 colorf[3] = p->alpha;
658
659 qglColor4fv( colorf );
660
661 qglTexCoord2f( 0.0625f, 0.0625f );
662 qglVertex3fv( p->origin );
663
664 qglTexCoord2f( 1.0625f, 0.0625f );
665 qglVertex3f( p->origin[0] + up[0]*scale,
666 p->origin[1] + up[1]*scale,
667 p->origin[2] + up[2]*scale);
668
669 qglTexCoord2f( 0.0625f, 1.0625f );
670 qglVertex3f( p->origin[0] + right[0]*scale,
671 p->origin[1] + right[1]*scale,
672 p->origin[2] + right[2]*scale);
673 }
674
675 qglEnd ();
676 qglDisable( GL_BLEND );
677 qglColor4fv(colorWhite);
678 qglDepthMask( 1 ); // back to normal Z buffering
679 GL_TexEnv( GL_REPLACE );
680 }
681
682 /*
683 ===============
684 R_DrawParticles
685 ===============
686 */
R_DrawParticles(void)687 void R_DrawParticles (void)
688 {
689 if (gl_config.r1gl_GL_ARB_point_sprite && FLOAT_NE_ZERO(gl_ext_point_sprite->value))
690 {
691 const float quadratic[] = { 1.0f, 0.0f, 0.0005f };
692
693 GL_Bind (r_particletexture->texnum);
694
695 GL_TexEnv( GL_MODULATE );
696 qglDepthMask( GL_FALSE );
697 //qglDisable( GL_TEXTURE_2D );
698
699 qglEnable( GL_BLEND );
700 qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
701
702 qglPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic );
703
704 qglPointSize( gl_particle_size->value );
705
706 // The alpha of a point is calculated to allow the fading of points
707 // instead of shrinking them past a defined threshold size. The threshold
708 // is defined by GL_POINT_FADE_THRESHOLD_SIZE_ARB and is not clamped to
709 // the minimum and maximum point sizes.
710 qglPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, gl_particle_max_size->value );
711
712 qglPointParameterfARB( GL_POINT_SIZE_MIN_ARB, gl_particle_min_size->value );
713 qglPointParameterfARB( GL_POINT_SIZE_MAX_ARB, gl_particle_max_size->value );
714
715 // Specify point sprite texture coordinate replacement mode for each texture unit
716 qglTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
717
718 //
719 // Render point sprites...
720 //
721
722 qglEnable( GL_POINT_SPRITE_ARB );
723 qglBegin( GL_POINTS );
724 {
725 const particle_t *p;
726 int i;
727 //unsigned char color[4];
728 vec4_t colorf;
729
730 for ( i = 0, p = r_newrefdef.particles; i < r_newrefdef.num_particles; i++, p++ )
731 {
732 //*(int *)color = d_8to24table[p->color];
733 //color[3] = (byte)Q_ftol(p->alpha*255);
734
735 //qglColor4ubv( color );
736
737 FastVectorCopy (d_8to24float[p->color], colorf);
738 colorf[3] = p->alpha;
739 qglColor4fv( colorf );
740
741 qglVertex3fv( p->origin );
742 }
743 }
744 qglEnd();
745
746 qglDisable( GL_POINT_SPRITE_ARB );
747 qglDisable( GL_BLEND );
748 qglColor4fv(colorWhite);
749 qglDepthMask( GL_TRUE );
750 qglEnable( GL_TEXTURE_2D );
751 qglDepthMask( 1 ); // back to normal Z buffering
752 GL_TexEnv( GL_REPLACE );
753 }
754 else if ( qglPointParameterfEXT && FLOAT_NE_ZERO(gl_ext_pointparameters->value))
755 {
756 int i;
757 vec4_t colorf;
758 //unsigned char color[4];
759 const particle_t *p;
760
761 qglDepthMask( GL_FALSE );
762 qglEnable( GL_BLEND );
763 qglDisable( GL_TEXTURE_2D );
764
765 qglPointSize( gl_particle_size->value );
766
767 qglBegin( GL_POINTS );
768
769 for ( i = 0, p = r_newrefdef.particles; i < r_newrefdef.num_particles; i++, p++ )
770 {
771 //*(vec4_t **)&colorf = *(vec4_t *)&d_8to24float[p->color];
772 //memcpy (colorf, d_8to24float[p->color], sizeof(colorf));
773 FastVectorCopy (d_8to24float[p->color], colorf);
774 colorf[3] = p->alpha;
775
776 //*(int *)color = d_8to24table[p->color];
777 //color[3] = (byte)Q_ftol (p->alpha * 255);
778 //qglColor4ubv( color );
779 qglColor4fv( colorf );
780 qglVertex3fv( p->origin );
781 }
782
783 qglEnd();
784
785 qglDisable( GL_BLEND );
786 qglColor4fv(colorWhite);
787 qglDepthMask( GL_TRUE );
788 qglEnable( GL_TEXTURE_2D );
789
790 }
791 else
792 {
793 GL_DrawParticles( r_newrefdef.num_particles, r_newrefdef.particles );
794 }
795 }
796
797 /*
798 ============
799 R_PolyBlend
800 ============
801 */
R_PolyBlend(void)802 void R_PolyBlend (void)
803 {
804 if (FLOAT_EQ_ZERO(gl_polyblend->value))
805 return;
806
807 if (FLOAT_EQ_ZERO(v_blend[3]))
808 return;
809
810 qglDisable (GL_ALPHA_TEST);
811 qglEnable (GL_BLEND);
812 qglDisable (GL_DEPTH_TEST);
813 qglDisable (GL_TEXTURE_2D);
814
815 qglLoadIdentity ();
816
817 // FIXME: get rid of these
818 qglRotatef (-90, 1, 0, 0); // put Z going up
819 qglRotatef (90, 0, 0, 1); // put Z going up
820
821 qglColor4fv (v_blend);
822
823 qglBegin (GL_QUADS);
824
825 qglVertex3f (10, 100, 100);
826 qglVertex3f (10, -100, 100);
827 qglVertex3f (10, -100, -100);
828 qglVertex3f (10, 100, -100);
829 qglEnd ();
830
831 qglDisable (GL_BLEND);
832 qglEnable (GL_TEXTURE_2D);
833 qglEnable (GL_ALPHA_TEST);
834
835 qglColor4fv(colorWhite);
836 }
837
838 //=======================================================================
839
SignbitsForPlane(cplane_t * out)840 int SignbitsForPlane (cplane_t *out)
841 {
842 int bits, j;
843
844 // for fast box on planeside test
845
846 bits = 0;
847 for (j=0 ; j<3 ; j++)
848 {
849 if (FLOAT_LT_ZERO(out->normal[j]))
850 bits |= 1<<j;
851 }
852 return bits;
853 }
854
855
R_SetFrustum(void)856 void R_SetFrustum (void)
857 {
858 int i;
859
860 #if 0
861 /*
862 ** this code is wrong, since it presume a 90 degree FOV both in the
863 ** horizontal and vertical plane
864 */
865 // front side is visible
866 VectorAdd (vpn, vright, frustum[0].normal);
867 VectorSubtract (vpn, vright, frustum[1].normal);
868 VectorAdd (vpn, vup, frustum[2].normal);
869 VectorSubtract (vpn, vup, frustum[3].normal);
870
871 // we theoretically don't need to normalize these vectors, but I do it
872 // anyway so that debugging is a little easier
873 VectorNormalize( frustum[0].normal );
874 VectorNormalize( frustum[1].normal );
875 VectorNormalize( frustum[2].normal );
876 VectorNormalize( frustum[3].normal );
877 #else
878 // rotate VPN right by FOV_X/2 degrees
879 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_newrefdef.fov_x / 2 ) );
880 // rotate VPN left by FOV_X/2 degrees
881 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_newrefdef.fov_x / 2 );
882 // rotate VPN up by FOV_X/2 degrees
883 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_newrefdef.fov_y / 2 );
884 // rotate VPN down by FOV_X/2 degrees
885 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_newrefdef.fov_y / 2 ) );
886 #endif
887
888 for (i=0 ; i<4 ; i++)
889 {
890 frustum[i].type = PLANE_ANYZ;
891 frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
892 frustum[i].signbits = SignbitsForPlane (&frustum[i]);
893 }
894 }
895
896 //=======================================================================
897
898 /*
899 ===============
900 R_SetupFrame
901 ===============
902 */
R_SetupFrame(void)903 void R_SetupFrame (void)
904 {
905 mleaf_t *leaf;
906
907 r_framecount++;
908
909 // build the transformation matrix for the given view angles
910 FastVectorCopy (r_newrefdef.vieworg, r_origin);
911
912 AngleVectors (r_newrefdef.viewangles, vpn, vright, vup);
913
914 // current viewcluster
915 if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
916 {
917 r_oldviewcluster = r_viewcluster;
918 r_oldviewcluster2 = r_viewcluster2;
919 leaf = Mod_PointInLeaf (r_origin, r_worldmodel);
920 r_viewcluster = r_viewcluster2 = leaf->cluster;
921
922 // check above and below so crossing solid water doesn't draw wrong
923 if (!leaf->contents)
924 { // look down a bit
925 vec3_t temp;
926
927 FastVectorCopy (r_origin, temp);
928 temp[2] -= 16;
929 leaf = Mod_PointInLeaf (temp, r_worldmodel);
930 if ( !(leaf->contents & CONTENTS_SOLID) &&
931 (leaf->cluster != r_viewcluster2) )
932 r_viewcluster2 = leaf->cluster;
933 }
934 else
935 { // look up a bit
936 vec3_t temp;
937
938 FastVectorCopy (r_origin, temp);
939 temp[2] += 16;
940 leaf = Mod_PointInLeaf (temp, r_worldmodel);
941 if ( !(leaf->contents & CONTENTS_SOLID) &&
942 (leaf->cluster != r_viewcluster2) )
943 r_viewcluster2 = leaf->cluster;
944 }
945 }
946
947 v_blend[0] = r_newrefdef.blend[0];
948 v_blend[1] = r_newrefdef.blend[1];
949 v_blend[2] = r_newrefdef.blend[2];
950 v_blend[3] = r_newrefdef.blend[3];
951
952 c_brush_polys = 0;
953 c_alias_polys = 0;
954
955 // clear out the portion of the screen that the NOWORLDMODEL defines
956 /*if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
957 {
958 qglEnable( GL_SCISSOR_TEST );
959 qglClearColor( 0.3f, 0.3f, 0.3f, 1 );
960
961 qglScissor( r_newrefdef.x, vid.height - r_newrefdef.height - r_newrefdef.y, r_newrefdef.width, r_newrefdef.height );
962 qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
963
964 qglClearColor( 1, 0, 0.5f, 0.5f );
965
966 qglDisable( GL_SCISSOR_TEST );
967 }*/
968 if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
969 {
970 qglEnable(GL_SCISSOR_TEST);
971 qglClearColor(0.3f, 0.3f, 0.3f, 1);
972 qglScissor(r_newrefdef.x, vid.height - r_newrefdef.height - r_newrefdef.y, r_newrefdef.width,
973 r_newrefdef.height);
974 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
975 qglClearColor(0, 0, 0, 1);
976 qglDisable(GL_SCISSOR_TEST);
977 }
978 }
979
980
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)981 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
982 GLdouble zNear, GLdouble zFar )
983 {
984 GLdouble xmin, xmax, ymin, ymax;
985
986 ymax = zNear * tan( fovy * M_PI / 360.0 );
987 ymin = -ymax;
988
989 xmin = ymin * aspect;
990 xmax = ymax * aspect;
991
992 #ifdef STERO_SUPPORT
993 xmin += -( 2 * gl_state.camera_separation ) / zNear;
994 xmax += -( 2 * gl_state.camera_separation ) / zNear;
995 #endif
996
997 qglFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
998 }
999
1000
1001 /*
1002 =============
1003 R_SetupGL
1004 =============
1005 */
R_SetupGL(void)1006 void R_SetupGL (void)
1007 {
1008 float screenaspect;
1009 // float yfov;
1010 int x, x2, y2, y, w, h;
1011
1012 //
1013 // set up viewport
1014 //
1015 x = (int)floor(r_newrefdef.x * vid.width / vid.width);
1016 x2 = (int)ceil((r_newrefdef.x + r_newrefdef.width) * vid.width / vid.width);
1017 y = (int)floor(vid.height - r_newrefdef.y * vid.height / vid.height);
1018 y2 = (int)ceil(vid.height - (r_newrefdef.y + r_newrefdef.height) * vid.height / vid.height);
1019
1020 w = x2 - x;
1021 h = y - y2;
1022
1023 qglViewport (x, y2, w, h);
1024
1025 //
1026 // set up projection matrix
1027 //
1028 screenaspect = (float)r_newrefdef.width/r_newrefdef.height;
1029 // yfov = 2*atan((float)r_newrefdef.height/r_newrefdef.width)*180/M_PI;
1030 qglMatrixMode(GL_PROJECTION);
1031 qglLoadIdentity ();
1032 MYgluPerspective (r_newrefdef.fov_y, screenaspect, 4, gl_zfar->value);
1033
1034 qglCullFace(GL_FRONT);
1035
1036 qglMatrixMode(GL_MODELVIEW);
1037 qglLoadIdentity ();
1038
1039 qglRotatef (-90, 1, 0, 0); // put Z going up
1040 qglRotatef (90, 0, 0, 1); // put Z going up
1041 qglRotatef (-r_newrefdef.viewangles[2], 1, 0, 0);
1042 qglRotatef (-r_newrefdef.viewangles[0], 0, 1, 0);
1043 qglRotatef (-r_newrefdef.viewangles[1], 0, 0, 1);
1044 qglTranslatef (-r_newrefdef.vieworg[0], -r_newrefdef.vieworg[1], -r_newrefdef.vieworg[2]);
1045
1046 // if ( gl_state.camera_separation != 0 && gl_state.stereo_enabled )
1047 // qglTranslatef ( gl_state.camera_separation, 0, 0 );
1048
1049 qglGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
1050
1051 //
1052 // set drawing parms
1053 //
1054 if (FLOAT_NE_ZERO(gl_cull->value))
1055 qglEnable(GL_CULL_FACE);
1056 else
1057 qglDisable(GL_CULL_FACE);
1058
1059 //qglDisable(GL_BLEND);
1060 qglDisable(GL_ALPHA_TEST);
1061 //qglEnable(GL_ALPHA_TEST);
1062 qglEnable(GL_DEPTH_TEST);
1063 }
1064
1065 /*
1066 =============
1067 R_Clear
1068 =============
1069 */
1070
ref_frand(void)1071 float ref_frand(void)
1072 {
1073 return (((rand()&32767)) * .0000305185094759971922971282082583086642f);
1074 }
1075
R_Clear(void)1076 void R_Clear (void)
1077 {
1078 if (FLOAT_NE_ZERO(gl_ztrick->value) && r_worldmodel != NULL)
1079 {
1080 static int trickframe;
1081
1082 if (FLOAT_NE_ZERO(gl_clear->value))
1083 {
1084 if (gl_clear->value == 2)
1085 {
1086 qglClearColor (ref_frand(), ref_frand(), ref_frand(), 1.0);
1087 GL_CheckForError ();
1088 }
1089 qglClear (GL_COLOR_BUFFER_BIT);
1090 GL_CheckForError ();
1091 }
1092
1093 trickframe++;
1094 if (trickframe & 1)
1095 {
1096 gldepthmin = 0;
1097 gldepthmax = 0.49999;
1098 qglDepthFunc (GL_LEQUAL);
1099 GL_CheckForError ();
1100 }
1101 else
1102 {
1103 gldepthmin = 1;
1104 gldepthmax = 0.5;
1105 qglDepthFunc (GL_GEQUAL);
1106 GL_CheckForError ();
1107 }
1108 }
1109 else
1110 {
1111 if (FLOAT_NE_ZERO(gl_clear->value))
1112 {
1113 if (gl_clear->value == 2)
1114 {
1115 qglClearColor (ref_frand(), ref_frand(), ref_frand(), 1.0);
1116 GL_CheckForError ();
1117 }
1118
1119 qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1120 GL_CheckForError ();
1121 }
1122 else
1123 {
1124 qglClear (GL_DEPTH_BUFFER_BIT);
1125 GL_CheckForError ();
1126 }
1127
1128 gldepthmin = 0;
1129 gldepthmax = 1;
1130 qglDepthFunc (GL_LEQUAL);
1131 GL_CheckForError ();
1132 }
1133
1134 qglDepthRange (gldepthmin, gldepthmax);
1135 GL_CheckForError ();
1136 }
1137
1138 /*void R_Flash( void )
1139 {
1140 R_PolyBlend ();
1141 }*/
1142
1143 /*
1144 ================
1145 R_RenderView
1146
1147 r_newrefdef must be set before the first call
1148 ================
1149 */
R_RenderView(refdef_t * fd)1150 void R_RenderView (refdef_t *fd)
1151 {
1152 if (FLOAT_NE_ZERO(r_norefresh->value))
1153 return;
1154
1155 r_newrefdef = *fd;
1156
1157 if (FLOAT_NE_ZERO(gl_hudscale->value))
1158 {
1159 r_newrefdef.width = (int)(r_newrefdef.width * gl_hudscale->value);
1160 r_newrefdef.height = (int)(r_newrefdef.height * gl_hudscale->value);
1161 r_newrefdef.x = (int)(r_newrefdef.x * gl_hudscale->value);
1162 r_newrefdef.y = (int)(r_newrefdef.y * gl_hudscale->value);
1163 }
1164
1165 if (!r_worldmodel && !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
1166 ri.Sys_Error (ERR_DROP, "R_RenderView: NULL worldmodel");
1167
1168 //if (FLOAT_NE_ZERO(r_speeds->value))
1169 //{
1170 c_brush_polys = 0;
1171 c_alias_polys = 0;
1172 //}
1173
1174 R_PushDlights ();
1175
1176 if (FLOAT_NE_ZERO(gl_flush->value))
1177 qglFlush ();
1178
1179 if (FLOAT_NE_ZERO(gl_finish->value))
1180 qglFinish ();
1181
1182 R_SetupFrame ();
1183
1184 R_SetFrustum ();
1185
1186 R_SetupGL ();
1187
1188 R_MarkLeaves (); // done here so we know if we're in water
1189
1190 if (gl_config.r1gl_QueryBits)
1191 R_Occlusion_Run ();
1192
1193 R_DrawWorld ();
1194
1195 R_DrawEntitiesOnList ();
1196
1197 R_RenderDlights ();
1198
1199 R_DrawParticles ();
1200
1201 R_DrawAlphaSurfaces ();
1202
1203 R_PolyBlend();
1204
1205 if (FLOAT_NE_ZERO(r_speeds->value))
1206 {
1207 ri.Con_Printf (PRINT_ALL, "%4i wpoly %4i epoly %i tex %i lmaps\n",
1208 c_brush_polys,
1209 c_alias_polys,
1210 c_visible_textures,
1211 c_visible_lightmaps);
1212 }
1213 }
1214
1215
R_SetGL2D(void)1216 void R_SetGL2D (void)
1217 {
1218 // set 2D virtual screen size
1219 qglViewport (0,0, vid.width, vid.height);
1220 qglMatrixMode(GL_PROJECTION);
1221 qglLoadIdentity ();
1222 //qglOrtho (0, vid.width, vid.height, 0, -99999, 99999);
1223 qglOrtho(0, vid_scaled_width, vid_scaled_height, 0, -99999, 99999);
1224 qglMatrixMode(GL_MODELVIEW);
1225 qglLoadIdentity ();
1226 qglDisable (GL_DEPTH_TEST);
1227 qglDisable (GL_CULL_FACE);
1228 //GLPROFqglDisable (GL_BLEND);
1229 qglEnable (GL_ALPHA_TEST);
1230 qglColor4fv(colorWhite);
1231 }
1232
1233 #ifdef STEREO_SUPPORT
GL_DrawColoredStereoLinePair(float r,float g,float b,float y)1234 static void GL_DrawColoredStereoLinePair( float r, float g, float b, float y )
1235 {
1236 qglColor3f( r, g, b );
1237 qglVertex2f( 0, y );
1238 qglVertex2f( vid.width, y );
1239 qglColor3f( 0, 0, 0 );
1240 qglVertex2f( 0, y + 1 );
1241 qglVertex2f( vid.width, y + 1 );
1242 }
1243
GL_DrawStereoPattern(void)1244 static void GL_DrawStereoPattern( void )
1245 {
1246 int i;
1247
1248 if ( !( gl_config.renderer & GL_RENDERER_INTERGRAPH ) )
1249 return;
1250
1251 if ( !gl_state.stereo_enabled )
1252 return;
1253
1254 R_SetGL2D();
1255
1256 qglDrawBuffer( GL_BACK_LEFT );
1257
1258 for ( i = 0; i < 20; i++ )
1259 {
1260 qglBegin( GL_LINES );
1261 GL_DrawColoredStereoLinePair( 1, 0, 0, 0 );
1262 GL_DrawColoredStereoLinePair( 1, 0, 0, 2 );
1263 GL_DrawColoredStereoLinePair( 1, 0, 0, 4 );
1264 GL_DrawColoredStereoLinePair( 1, 0, 0, 6 );
1265 GL_DrawColoredStereoLinePair( 0, 1, 0, 8 );
1266 GL_DrawColoredStereoLinePair( 1, 1, 0, 10);
1267 GL_DrawColoredStereoLinePair( 1, 1, 0, 12);
1268 GL_DrawColoredStereoLinePair( 0, 1, 0, 14);
1269 qglEnd();
1270
1271 GLimp_EndFrame();
1272 }
1273 }
1274 #endif
1275
1276
1277 /*
1278 ====================
1279 R_SetLightLevel
1280
1281 ====================
1282 */
R_SetLightLevel(void)1283 void R_SetLightLevel (void)
1284 {
1285 vec3_t shadelight;
1286
1287 if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
1288 return;
1289
1290 // save off light value for server to look at (BIG HACK!)
1291
1292 R_LightPoint (r_newrefdef.vieworg, shadelight);
1293
1294 // pick the greatest component, which should be the same
1295 // as the mono value returned by software
1296 if (shadelight[0] > shadelight[1])
1297 {
1298 if (shadelight[0] > shadelight[2])
1299 r_lightlevel->value = 150*shadelight[0];
1300 else
1301 r_lightlevel->value = 150*shadelight[2];
1302 }
1303 else
1304 {
1305 if (shadelight[1] > shadelight[2])
1306 r_lightlevel->value = 150*shadelight[1];
1307 else
1308 r_lightlevel->value = 150*shadelight[2];
1309 }
1310
1311 }
1312
1313 /*
1314 @@@@@@@@@@@@@@@@@@@@@
1315 R_RenderFrame
1316
1317 @@@@@@@@@@@@@@@@@@@@@
1318 */
R_RenderFrame(refdef_t * fd)1319 void EXPORT R_RenderFrame (refdef_t *fd)
1320 {
1321 R_RenderView( fd );
1322 R_SetLightLevel ();
1323 R_SetGL2D ();
1324 }
1325
1326 void Cmd_HashStats_f (void);
R_Register(void)1327 void R_Register( void )
1328 {
1329 r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
1330 r_norefresh = ri.Cvar_Get ("r_norefresh", "0", 0);
1331 r_fullbright = ri.Cvar_Get ("r_fullbright", "0", 0);
1332 r_drawentities = ri.Cvar_Get ("r_drawentities", "1", 0);
1333 r_drawworld = ri.Cvar_Get ("r_drawworld", "1", 0);
1334 r_novis = ri.Cvar_Get ("r_novis", "0", 0);
1335 r_nocull = ri.Cvar_Get ("r_nocull", "0", 0);
1336 r_lerpmodels = ri.Cvar_Get ("r_lerpmodels", "1", 0);
1337 r_speeds = ri.Cvar_Get ("r_speeds", "0", 0);
1338
1339 r_lightlevel = ri.Cvar_Get ("r_lightlevel", "0", CVAR_NOSET);
1340
1341 //gl_nosubimage = ri.Cvar_Get( "gl_nosubimage", "0", 0 );
1342 gl_allow_software = ri.Cvar_Get( "gl_allow_software", "0", 0 );
1343
1344 gl_particle_min_size = ri.Cvar_Get( "gl_particle_min_size", "2", CVAR_ARCHIVE );
1345 gl_particle_max_size = ri.Cvar_Get( "gl_particle_max_size", "40", CVAR_ARCHIVE );
1346 gl_particle_size = ri.Cvar_Get( "gl_particle_size", "40", CVAR_ARCHIVE );
1347 gl_particle_att_a = ri.Cvar_Get( "gl_particle_att_a", "0.01", CVAR_ARCHIVE );
1348 gl_particle_att_b = ri.Cvar_Get( "gl_particle_att_b", "0.0", CVAR_ARCHIVE );
1349 gl_particle_att_c = ri.Cvar_Get( "gl_particle_att_c", "0.01", CVAR_ARCHIVE );
1350
1351 gl_modulate = ri.Cvar_Get ("gl_modulate", "2", CVAR_ARCHIVE );
1352 //gl_log = ri.Cvar_Get( "gl_log", "0", 0 );
1353 gl_bitdepth = ri.Cvar_Get( "gl_bitdepth", "0", 0 );
1354 gl_mode = ri.Cvar_Get( "gl_mode", "3", CVAR_ARCHIVE );
1355 //gl_lightmap = ri.Cvar_Get ("gl_lightmap", "0", 0);
1356 gl_shadows = ri.Cvar_Get ("gl_shadows", "0", CVAR_ARCHIVE );
1357 gl_dynamic = ri.Cvar_Get ("gl_dynamic", "1", 0);
1358 gl_nobind = ri.Cvar_Get ("gl_nobind", "0", 0);
1359 gl_round_down = ri.Cvar_Get ("gl_round_down", "0", 0);
1360 gl_picmip = ri.Cvar_Get ("gl_picmip", "0", 0);
1361 gl_skymip = ri.Cvar_Get ("gl_skymip", "0", 0);
1362 gl_showtris = ri.Cvar_Get ("gl_showtris", "0", 0);
1363 gl_ztrick = ri.Cvar_Get ("gl_ztrick", "0", 0);
1364 gl_finish = ri.Cvar_Get ("gl_finish", "0", CVAR_ARCHIVE);
1365 gl_flush = ri.Cvar_Get ("gl_flush", "0", CVAR_ARCHIVE);
1366 gl_clear = ri.Cvar_Get ("gl_clear", "0", 0);
1367 gl_cull = ri.Cvar_Get ("gl_cull", "1", 0);
1368 gl_polyblend = ri.Cvar_Get ("gl_polyblend", "1", 0);
1369 gl_flashblend = ri.Cvar_Get ("gl_flashblend", "0", 0);
1370 //gl_playermip = ri.Cvar_Get ("gl_playermip", "0", 0);
1371 //gl_monolightmap = ri.Cvar_Get( "gl_monolightmap", "0", 0 );
1372 gl_driver = ri.Cvar_Get( "gl_driver", "opengl32", CVAR_ARCHIVE );
1373 gl_texturemode = ri.Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE );
1374 gl_texturealphamode = ri.Cvar_Get( "gl_texturealphamode", "default", CVAR_ARCHIVE );
1375 gl_texturesolidmode = ri.Cvar_Get( "gl_texturesolidmode", "default", CVAR_ARCHIVE );
1376 gl_lockpvs = ri.Cvar_Get( "gl_lockpvs", "0", 0 );
1377
1378 gl_vertex_arrays = ri.Cvar_Get( "gl_vertex_arrays", "1", CVAR_ARCHIVE );
1379
1380 //gl_ext_swapinterval = ri.Cvar_Get( "gl_ext_swapinterval", "1", CVAR_ARCHIVE );
1381 //gl_ext_palettedtexture = ri.Cvar_Get( "gl_ext_palettedtexture", "0", CVAR_ARCHIVE );
1382 gl_ext_multitexture = ri.Cvar_Get( "gl_ext_multitexture", "1", CVAR_ARCHIVE );
1383
1384 //note, pointparams moved to init to handle defaults
1385 //gl_ext_compiled_vertex_array = ri.Cvar_Get( "gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE );
1386
1387 //r1ch: my extensions
1388 //gl_ext_generate_mipmap = ri.Cvar_Get ("gl_ext_generate_mipmap", "0", 0);
1389 gl_ext_point_sprite = ri.Cvar_Get ("gl_ext_point_sprite", "0", 0);
1390 gl_ext_texture_filter_anisotropic = ri.Cvar_Get ("gl_ext_texture_filter_anisotropic", "0", 0);
1391 gl_ext_texture_non_power_of_two = ri.Cvar_Get ("gl_ext_texture_non_power_of_two", "0", 0);
1392 gl_ext_max_anisotropy = ri.Cvar_Get ("gl_ext_max_anisotropy", "2", 0);
1393 gl_ext_occlusion_query = ri.Cvar_Get ("gl_ext_occlusion_query", "0", 0);
1394
1395 gl_ext_nv_multisample_filter_hint = ri.Cvar_Get ("gl_ext_nv_multisample_filter_hint", "fastest", 0);
1396
1397 gl_colorbits = ri.Cvar_Get ("gl_colorbits", "0", 0);
1398 gl_stencilbits = ri.Cvar_Get ("gl_stencilbits", "", 0);
1399 gl_alphabits = ri.Cvar_Get ("gl_alphabits", "", 0);
1400 gl_depthbits = ri.Cvar_Get ("gl_depthbits", "", 0);
1401
1402 gl_ext_multisample = ri.Cvar_Get ("gl_ext_multisample", "0", 0);
1403 gl_ext_samples = ri.Cvar_Get ("gl_ext_samples", "2", 0);
1404
1405 gl_zfar = ri.Cvar_Get ("gl_zfar", "8192", 0);
1406 gl_hudscale = ri.Cvar_Get ("gl_hudscale", "1", 0);
1407
1408 cl_version = ri.Cvar_Get ("cl_version", REF_VERSION, CVAR_NOSET);
1409
1410 gl_r1gl_test = ri.Cvar_Get ("gl_r1gl_test", "0", 0);
1411 gl_doublelight_entities = ri.Cvar_Get ("gl_doublelight_entities", "1", 0);
1412 gl_noscrap = ri.Cvar_Get ("gl_noscrap", "1", 0);
1413 gl_overbrights = ri.Cvar_Get ("gl_overbrights", "0", 0);
1414 gl_linear_mipmaps = ri.Cvar_Get ("gl_linear_mipmaps", "0", 0);
1415
1416 vid_forcedrefresh = ri.Cvar_Get ("vid_forcedrefresh", "0", 0);
1417 vid_optimalrefresh = ri.Cvar_Get ("vid_optimalrefresh", "0", 0);
1418 vid_gamma_pics = ri.Cvar_Get ("vid_gamma_pics", "0", 0);
1419 vid_nowgl = ri.Cvar_Get ("vid_nowgl", "0", 0);
1420 vid_restore_on_switch = ri.Cvar_Get ("vid_flip_on_switch", "0", 0);
1421
1422 gl_forcewidth = ri.Cvar_Get ("vid_forcewidth", "0", 0);
1423 gl_forceheight = ri.Cvar_Get ("vid_forceheight", "0", 0);
1424
1425 vid_topmost = ri.Cvar_Get ("vid_topmost", "0", 0);
1426
1427 gl_pic_scale = ri.Cvar_Get ("gl_pic_scale", "1", 0);
1428 //r1ch end my shit
1429
1430 gl_drawbuffer = ri.Cvar_Get( "gl_drawbuffer", "GL_BACK", 0 );
1431 gl_swapinterval = ri.Cvar_Get( "gl_swapinterval", "1", CVAR_ARCHIVE );
1432
1433 //gl_saturatelighting = ri.Cvar_Get( "gl_saturatelighting", "0", 0 );
1434
1435 gl_jpg_quality = ri.Cvar_Get ("gl_jpg_quality", "90", 0);
1436 gl_coloredlightmaps = ri.Cvar_Get ("gl_coloredlightmaps", "1", 0);
1437 usingmodifiedlightmaps = (gl_coloredlightmaps->value != 1.0f);
1438
1439 //gl_3dlabs_broken = ri.Cvar_Get( "gl_3dlabs_broken", "1", CVAR_ARCHIVE );
1440
1441 vid_fullscreen = ri.Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE );
1442 vid_gamma = ri.Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE );
1443 vid_ref = ri.Cvar_Get( "vid_ref", "r1gl", CVAR_ARCHIVE );
1444
1445 gl_texture_formats = ri.Cvar_Get ("gl_texture_formats", "png jpg tga", 0);
1446 gl_pic_formats = ri.Cvar_Get ("gl_pic_formats", "png jpg tga", 0);
1447
1448 load_png_wals = strstr (gl_texture_formats->string, "png") ? true : false;
1449 load_jpg_wals = strstr (gl_texture_formats->string, "jpg") ? true : false;
1450 load_tga_wals = strstr (gl_texture_formats->string, "tga") ? true : false;
1451
1452 load_png_pics = strstr (gl_pic_formats->string, "png") ? true : false;
1453 load_jpg_pics = strstr (gl_pic_formats->string, "jpg") ? true : false;
1454 load_tga_pics = strstr (gl_pic_formats->string, "tga") ? true : false;
1455
1456 gl_dlight_falloff = ri.Cvar_Get ("gl_dlight_falloff", "0", 0);
1457 gl_alphaskins = ri.Cvar_Get ("gl_alphaskins", "0", 0);
1458 gl_defertext = ri.Cvar_Get ("gl_defertext", "0", 0);
1459 defer_drawing = (int)gl_defertext->value;
1460
1461 //con_alpha = ri.Cvar_Get ("con_alpha", "1.0", 0);
1462
1463 ri.Cmd_AddCommand( "imagelist", GL_ImageList_f );
1464 ri.Cmd_AddCommand( "screenshot", GL_ScreenShot_f );
1465 ri.Cmd_AddCommand( "modellist", Mod_Modellist_f );
1466 ri.Cmd_AddCommand( "gl_strings", GL_Strings_f );
1467 ri.Cmd_AddCommand( "hash_stats", Cmd_HashStats_f );
1468
1469
1470 #ifdef R1GL_RELEASE
1471 ri.Cmd_AddCommand ("r1gl_version", GL_Version_f);
1472 #endif
1473 }
1474
1475 /*
1476 ==================
1477 R_SetMode
1478 ==================
1479 */
R_SetMode(void)1480 int R_SetMode (void)
1481 {
1482 int err;
1483 qboolean fullscreen;
1484
1485 fullscreen = FLOAT_EQ_ZERO(vid_fullscreen->value) ? false : true;
1486
1487 vid_fullscreen->modified = false;
1488 gl_mode->modified = false;
1489
1490 if (FLOAT_NE_ZERO(gl_forcewidth->value))
1491 vid.width = (int)gl_forcewidth->value;
1492
1493 if (FLOAT_NE_ZERO(gl_forceheight->value))
1494 vid.height = (int)gl_forceheight->value;
1495
1496 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, Q_ftol(gl_mode->value), fullscreen ) ) == VID_ERR_NONE )
1497 {
1498 gl_state.prev_mode = Q_ftol(gl_mode->value);
1499 }
1500 else
1501 {
1502 if ( err & VID_ERR_RETRY_QGL)
1503 {
1504 return err;
1505 }
1506 else if ( err & VID_ERR_FULLSCREEN_FAILED )
1507 {
1508 ri.Cvar_SetValue( "vid_fullscreen", 0);
1509 vid_fullscreen->modified = false;
1510 ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - fullscreen unavailable in this mode\n" );
1511 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, Q_ftol(gl_mode->value), false ) ) == VID_ERR_NONE )
1512 return VID_ERR_NONE;
1513 }
1514 else if ( err & VID_ERR_FAIL )
1515 {
1516 ri.Cvar_SetValue( "gl_mode", (float)gl_state.prev_mode );
1517 gl_mode->modified = false;
1518 ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - invalid mode\n" );
1519 }
1520
1521 // try setting it back to something safe
1522 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_state.prev_mode, false ) ) != VID_ERR_NONE )
1523 {
1524 ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - could not revert to safe mode\n" );
1525 return VID_ERR_FAIL;
1526 }
1527 }
1528 return VID_ERR_NONE;
1529 }
1530
1531 /*
1532 ===============
1533 R_Init
1534 ===============
1535 */
R_Init(void * hinstance,void * hWnd)1536 int EXPORT R_Init( void *hinstance, void *hWnd )
1537 {
1538 char renderer_buffer[1000];
1539 char vendor_buffer[1000];
1540 int err;
1541 int j;
1542 extern float r_turbsin[256];
1543
1544 for ( j = 0; j < 256; j++ )
1545 {
1546 r_turbsin[j] *= 0.5;
1547 }
1548
1549 ri.Cmd_ExecuteText (EXEC_NOW, "exec r1gl.cfg\n");
1550
1551 ri.Con_Printf (PRINT_ALL, "ref_gl version: "REF_VERSION"\n");
1552
1553 ri.Con_Printf (PRINT_DEVELOPER, "Draw_GetPalette()\n");
1554 Draw_GetPalette ();
1555
1556 ri.Con_Printf (PRINT_DEVELOPER, "R_Register()\n");
1557 R_Register();
1558
1559 gl_overbrights->modified = false;
1560
1561 retryQGL:
1562
1563 // initialize our QGL dynamic bindings
1564 ri.Con_Printf (PRINT_DEVELOPER, "QGL_Init()\n");
1565 if ( !QGL_Init( gl_driver->string ) )
1566 {
1567 QGL_Shutdown();
1568
1569 ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - could not load \"%s\"\n", gl_driver->string );
1570
1571 #ifdef _WIN32
1572 if (strcmp (gl_driver->string, "opengl32"))
1573 {
1574 ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - retrying with gl_driver opengl32\n");
1575 ri.Cvar_Set ("gl_driver", "opengl32");
1576 goto retryQGL;
1577 }
1578 #endif
1579
1580 return -1;
1581 }
1582
1583 // initialize OS-specific parts of OpenGL
1584 ri.Con_Printf (PRINT_DEVELOPER, "GLimp_Init()\n");
1585 if ( !GLimp_Init( hinstance, hWnd ) )
1586 {
1587 ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init(): GLimp_Init() failed\n");
1588 QGL_Shutdown();
1589 return -1;
1590 }
1591
1592 // set our "safe" modes
1593 gl_state.prev_mode = 3;
1594
1595 // create the window and set up the context
1596 ri.Con_Printf (PRINT_DEVELOPER, "R_SetMode()\n");
1597 err = R_SetMode ();
1598 if (err != VID_ERR_NONE)
1599 {
1600 QGL_Shutdown();
1601 if (err & VID_ERR_RETRY_QGL)
1602 goto retryQGL;
1603
1604 ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - could not R_SetMode()\n" );
1605 return -1;
1606 }
1607
1608 ri.Con_Printf (PRINT_DEVELOPER, "Vid_MenuInit()\n");
1609 ri.Vid_MenuInit();
1610
1611 /*
1612 ** get our various GL strings
1613 */
1614 gl_config.vendor_string = (const char *) qglGetString (GL_VENDOR);
1615 ri.Con_Printf (PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string );
1616 gl_config.renderer_string = (const char *) qglGetString (GL_RENDERER);
1617 ri.Con_Printf (PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string );
1618 gl_config.version_string = (const char *) qglGetString (GL_VERSION);
1619 ri.Con_Printf (PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string );
1620 gl_config.extensions_string = (const char *) qglGetString (GL_EXTENSIONS);
1621 //ri.Con_Printf (PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string );
1622
1623 Q_strncpy( renderer_buffer, gl_config.renderer_string, sizeof(renderer_buffer)-1);
1624 Q_strlwr( renderer_buffer );
1625
1626 Q_strncpy( vendor_buffer, gl_config.vendor_string, sizeof(vendor_buffer)-1);
1627 Q_strlwr( vendor_buffer );
1628
1629 if ( strstr( renderer_buffer, "voodoo" ) )
1630 {
1631 if ( !strstr( renderer_buffer, "rush" ) )
1632 gl_config.renderer = GL_RENDERER_VOODOO;
1633 else
1634 gl_config.renderer = GL_RENDERER_VOODOO_RUSH;
1635 }
1636 else if ( strstr( vendor_buffer, "sgi" ) )
1637 gl_config.renderer = GL_RENDERER_SGI;
1638 else if ( strstr( renderer_buffer, "permedia" ) )
1639 gl_config.renderer = GL_RENDERER_PERMEDIA2;
1640 else if ( strstr( renderer_buffer, "glint" ) )
1641 gl_config.renderer = GL_RENDERER_GLINT_MX;
1642 else if ( strstr( renderer_buffer, "glzicd" ) )
1643 gl_config.renderer = GL_RENDERER_REALIZM;
1644 else if ( strstr( renderer_buffer, "gdi" ) )
1645 gl_config.renderer = GL_RENDERER_MCD;
1646 else if ( strstr( renderer_buffer, "pcx2" ) )
1647 gl_config.renderer = GL_RENDERER_PCX2;
1648 else if ( strstr( renderer_buffer, "verite" ) )
1649 gl_config.renderer = GL_RENDERER_RENDITION;
1650 else if ( strstr (vendor_buffer, "ati tech"))
1651 gl_config.renderer = GL_RENDERER_ATI;
1652 else if ( strstr (vendor_buffer, "nvidia corp"))
1653 gl_config.renderer = GL_RENDERER_NV;
1654 else
1655 gl_config.renderer = GL_RENDERER_OTHER;
1656
1657 /*if ( toupper( gl_monolightmap->string[1] ) != 'F' )
1658 {
1659 if ( gl_config.renderer == GL_RENDERER_PERMEDIA2 )
1660 {
1661 ri.Cvar_Set( "gl_monolightmap", "A" );
1662 ri.Con_Printf( PRINT_ALL, "...using gl_monolightmap 'a'\n" );
1663 }
1664 else if ( gl_config.renderer & GL_RENDERER_POWERVR )
1665 {
1666 ri.Cvar_Set( "gl_monolightmap", "0" );
1667 }
1668 else
1669 {
1670 ri.Cvar_Set( "gl_monolightmap", "0" );
1671 }
1672 }*/
1673
1674 // power vr can't have anything stay in the framebuffer, so
1675 // the screen needs to redraw the tiled background every frame
1676 if ( gl_config.renderer & GL_RENDERER_POWERVR )
1677 {
1678 ri.Cvar_Set( "scr_drawall", "1" );
1679 }
1680 else
1681 {
1682 ri.Cvar_Set( "scr_drawall", "0" );
1683 }
1684
1685 // MCD has buffering issues
1686 if ( gl_config.renderer == GL_RENDERER_MCD )
1687 {
1688 ri.Cvar_SetValue( "gl_finish", 1 );
1689 }
1690
1691 /*
1692 ** grab extensions
1693 */
1694 if ( strstr( gl_config.extensions_string, "GL_EXT_compiled_vertex_array" ) ||
1695 strstr( gl_config.extensions_string, "GL_SGI_compiled_vertex_array" ) )
1696 {
1697 ri.Con_Printf( PRINT_ALL, "...enabling GL_EXT_compiled_vertex_array\n" );
1698 qglLockArraysEXT = ( void (__stdcall *)(int, int) ) qwglGetProcAddress( "glLockArraysEXT" );
1699 qglUnlockArraysEXT = ( void (__stdcall *)(void) ) qwglGetProcAddress( "glUnlockArraysEXT" );
1700 }
1701 else
1702 {
1703 ri.Con_Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
1704 }
1705
1706 #ifdef _WIN32
1707 if ( strstr( gl_config.extensions_string, "WGL_EXT_swap_control" ) )
1708 {
1709 qwglSwapIntervalEXT = ( BOOL (WINAPI *)(int)) qwglGetProcAddress( "wglSwapIntervalEXT" );
1710 ri.Con_Printf( PRINT_ALL, "...enabling WGL_EXT_swap_control\n" );
1711 }
1712 else
1713 {
1714 ri.Con_Printf( PRINT_ALL, "...WGL_EXT_swap_control not found\n" );
1715 }
1716 #endif
1717
1718 if ( strstr( gl_config.extensions_string, "GL_EXT_point_parameters" ) )
1719 {
1720 if (gl_config.renderer == GL_RENDERER_ATI)
1721 gl_ext_pointparameters = ri.Cvar_Get( "gl_ext_pointparameters", "0", CVAR_ARCHIVE );
1722 else
1723 gl_ext_pointparameters = ri.Cvar_Get( "gl_ext_pointparameters", "1", CVAR_ARCHIVE );
1724
1725 if ( FLOAT_NE_ZERO(gl_ext_pointparameters->value) && (gl_config.renderer != GL_RENDERER_ATI || gl_ext_pointparameters->value == 2) )
1726 {
1727 qglPointParameterfEXT = ( void (APIENTRY *)( GLenum, GLfloat ) ) qwglGetProcAddress( "glPointParameterfEXT" );
1728 qglPointParameterfvEXT = ( void (APIENTRY *)( GLenum, const GLfloat * ) ) qwglGetProcAddress( "glPointParameterfvEXT" );
1729 ri.Con_Printf( PRINT_ALL, "...using GL_EXT_point_parameters\n" );
1730 }
1731 else
1732 {
1733 ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_point_parameters\n" );
1734 }
1735 }
1736 else
1737 {
1738 ri.Con_Printf( PRINT_ALL, "...GL_EXT_point_parameters not found\n" );
1739 }
1740
1741 /*if ( !qglColorTableEXT &&
1742 strstr( gl_config.extensions_string, "GL_EXT_paletted_texture" ) &&
1743 strstr( gl_config.extensions_string, "GL_EXT_shared_texture_palette" ) )
1744 {
1745 if ( gl_ext_palettedtexture->value )
1746 {
1747 ri.Con_Printf( PRINT_ALL, "...using GL_EXT_shared_texture_palette\n" );
1748 qglColorTableEXT = ( void ( APIENTRY * ) ( int, int, int, int, int, const void * ) ) qwglGetProcAddress( "glColorTableEXT" );
1749 }
1750 else
1751 {
1752 ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_shared_texture_palette\n" );
1753 }
1754 }
1755 else
1756 {
1757 ri.Con_Printf( PRINT_ALL, "...GL_EXT_shared_texture_palette not found\n" );
1758 }*/
1759
1760 if ( strstr( gl_config.extensions_string, "GL_ARB_multitexture" ) )
1761 {
1762 if ( FLOAT_NE_ZERO(gl_ext_multitexture->value) )
1763 {
1764 ri.Con_Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
1765 qglMTexCoord2fSGIS = ( void (__stdcall *)(GLenum, GLfloat, GLfloat) ) qwglGetProcAddress( "glMultiTexCoord2fARB" );
1766 qglMTexCoord2fvSGIS = ( void (__stdcall *)(GLenum, GLfloat*) ) qwglGetProcAddress( "glMultiTexCoord2fvARB" );
1767 qglActiveTextureARB = ( void (__stdcall *)(GLenum) ) qwglGetProcAddress( "glActiveTextureARB" );
1768 qglClientActiveTextureARB = ( void (__stdcall *)(GLenum) ) qwglGetProcAddress( "glClientActiveTextureARB" );
1769 GL_TEXTURE0 = GL_TEXTURE0_ARB;
1770 GL_TEXTURE1 = GL_TEXTURE1_ARB;
1771 }
1772 else
1773 {
1774 ri.Con_Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
1775 }
1776 }
1777 else
1778 {
1779 ri.Con_Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
1780 }
1781
1782 if ( strstr( gl_config.extensions_string, "GL_SGIS_multitexture" ) )
1783 {
1784 if ( qglActiveTextureARB )
1785 {
1786 ri.Con_Printf( PRINT_ALL, "...GL_SGIS_multitexture deprecated in favor of ARB_multitexture\n" );
1787 }
1788 else if ( FLOAT_NE_ZERO(gl_ext_multitexture->value) )
1789 {
1790 ri.Con_Printf( PRINT_ALL, "...using GL_SGIS_multitexture\n" );
1791 qglMTexCoord2fSGIS = ( void (__stdcall *)(GLenum, GLfloat, GLfloat) ) qwglGetProcAddress( "glMTexCoord2fSGIS" );
1792 qglMTexCoord2fvSGIS = ( void (__stdcall *)(GLenum, GLfloat*) ) qwglGetProcAddress( "glMTexCoord2fvSGIS" );
1793 qglSelectTextureSGIS = ( void (__stdcall *)(GLenum) ) qwglGetProcAddress( "glSelectTextureSGIS" );
1794 GL_TEXTURE0 = GL_TEXTURE0_SGIS;
1795 GL_TEXTURE1 = GL_TEXTURE1_SGIS;
1796 }
1797 else
1798 {
1799 ri.Con_Printf( PRINT_ALL, "...ignoring GL_SGIS_multitexture\n" );
1800 }
1801 }
1802 else
1803 {
1804 ri.Con_Printf( PRINT_ALL, "...GL_SGIS_multitexture not found\n" );
1805 }
1806
1807 ri.Con_Printf( PRINT_ALL, "Initializing r1gl extensions:\n" );
1808
1809 /*gl_config.r1gl_GL_SGIS_generate_mipmap = false;
1810 if ( strstr( gl_config.extensions_string, "GL_SGIS_generate_mipmap" ) ) {
1811 if ( gl_ext_generate_mipmap->value ) {
1812 ri.Con_Printf( PRINT_ALL, "...using GL_SGIS_generate_mipmap\n" );
1813 gl_config.r1gl_GL_SGIS_generate_mipmap = true;
1814 } else {
1815 ri.Con_Printf( PRINT_ALL, "...ignoring GL_SGIS_generate_mipmap\n" );
1816 }
1817 } else {
1818 ri.Con_Printf( PRINT_ALL, "...GL_SGIS_generate_mipmap not found\n" );
1819 }*/
1820
1821 gl_config.r1gl_GL_ARB_point_sprite = false;
1822 if ( strstr( gl_config.extensions_string, "GL_ARB_point_sprite" ) )
1823 {
1824 //if ( gl_ext_point_sprite->value ) {
1825 qglPointParameterfARB = (void (__stdcall *)(GLenum,GLfloat))qwglGetProcAddress("glPointParameterfARB");
1826 qglPointParameterfvARB = (void (__stdcall *)(GLenum,const GLfloat *))qwglGetProcAddress("glPointParameterfvARB");
1827 if (!qglPointParameterfARB)
1828 {
1829 ri.Con_Printf( PRINT_ALL, "!!! qglGetProcAddress for GL_ARB_point_sprite failed\n" );
1830 }
1831 else
1832 {
1833 ri.Con_Printf( PRINT_ALL, "...using GL_ARB_point_sprite\n" );
1834 gl_config.r1gl_GL_ARB_point_sprite = true;
1835 }
1836 //} else {
1837 // ri.Con_Printf( PRINT_ALL, "...ignoring GL_ARB_point_sprite\n" );
1838 //}
1839 } else {
1840 ri.Con_Printf( PRINT_ALL, "...GL_ARB_point_sprite not found\n" );
1841 }
1842
1843 gl_config.r1gl_GL_EXT_texture_filter_anisotropic = false;
1844 if ( strstr( gl_config.extensions_string, "GL_EXT_texture_filter_anisotropic" ) )
1845 {
1846 if ( gl_ext_texture_filter_anisotropic->value ) {
1847 ri.Con_Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic\n" );
1848 gl_config.r1gl_GL_EXT_texture_filter_anisotropic = true;
1849 } else {
1850 ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_texture_filter_anisotropic\n" );
1851 }
1852 } else {
1853 ri.Con_Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not found\n" );
1854 }
1855 gl_ext_texture_filter_anisotropic->modified = false;
1856
1857 gl_config.r1gl_GL_ARB_texture_non_power_of_two = false;
1858 if ( strstr( gl_config.extensions_string, "GL_ARB_texture_non_power_of_two" ) ) {
1859 if (FLOAT_NE_ZERO (gl_ext_texture_non_power_of_two->value) ) {
1860 ri.Con_Printf( PRINT_ALL, "...using GL_ARB_texture_non_power_of_two\n" );
1861 gl_config.r1gl_GL_ARB_texture_non_power_of_two = true;
1862 } else {
1863 ri.Con_Printf( PRINT_ALL, "...ignoring GL_ARB_texture_non_power_of_two\n" );
1864 }
1865 } else {
1866 ri.Con_Printf( PRINT_ALL, "...GL_ARB_texture_non_power_of_two not found\n" );
1867 }
1868
1869 if ( strstr (gl_config.extensions_string, "GL_ARB_occlusion_query"))
1870 {
1871 //r1: occlusion queries
1872 if (FLOAT_NE_ZERO (gl_ext_occlusion_query->value) )
1873 {
1874 qglGenQueriesARB = (void (__stdcall *)(GLsizei,GLuint *))qwglGetProcAddress ("glGenQueriesARB");
1875 qglGetQueryivARB = (void (__stdcall *)(GLenum,GLenum,GLint *))qwglGetProcAddress ("glGetQueryivARB");
1876 qglGetQueryObjectivARB = (void (__stdcall *)(GLuint,GLenum,GLint *))qwglGetProcAddress ("glGetQueryObjectivARB");
1877 qglBeginQueryARB = (void (__stdcall *)(GLenum,GLuint))qwglGetProcAddress ("glBeginQueryARB");
1878 qglEndQueryARB = (void (__stdcall *)(GLenum))qwglGetProcAddress ("glEndQueryARB");
1879
1880 qglGetQueryivARB (GL_SAMPLES_PASSED, GL_QUERY_COUNTER_BITS, &gl_config.r1gl_QueryBits);
1881 ri.Con_Printf (PRINT_ALL, "...using GL_ARB_occlusion_query (%d bits)\n", gl_config.r1gl_QueryBits);
1882 if (gl_config.r1gl_QueryBits)
1883 qglGenQueriesARB (MAX_ENTITIES, gl_config.r1gl_Queries);
1884 }
1885 else
1886 {
1887 ri.Con_Printf (PRINT_ALL, "...ignoring GL_ARB_occlusion_query\n");
1888 gl_config.r1gl_QueryBits = 0;
1889 }
1890 }
1891 else
1892 {
1893 gl_config.r1gl_QueryBits = 0;
1894 ri.Con_Printf (PRINT_ALL, "...GL_ARB_occlusion_query not found\n");
1895 }
1896
1897 ri.Con_Printf( PRINT_ALL, "Initializing r1gl NVIDIA-only extensions:\n" );
1898 gl_config.r1gl_GL_EXT_nv_multisample_filter_hint = false;
1899 if ( strstr( gl_config.extensions_string, "GL_NV_multisample_filter_hint" ) ) {
1900 gl_config.r1gl_GL_EXT_nv_multisample_filter_hint = true;
1901 ri.Con_Printf( PRINT_ALL, "...allowing GL_NV_multisample_filter_hint\n" );
1902 } else {
1903 ri.Con_Printf( PRINT_ALL, "...GL_NV_multisample_filter_hint not found\n" );
1904 }
1905
1906 ri.Con_Printf( PRINT_DEVELOPER, "GL_SetDefaultState()\n" );
1907 GL_SetDefaultState();
1908
1909 //r1: setup cached screensizes
1910 vid_scaled_width = vid.width / gl_hudscale->value;
1911 vid_scaled_height = vid.height / gl_hudscale->value;
1912
1913 /*
1914 ** draw our stereo patterns
1915 */
1916 #if 0 // commented out until H3D pays us the money they owe us
1917 GL_DrawStereoPattern();
1918 #endif
1919
1920 ri.Con_Printf( PRINT_DEVELOPER, "GL_InitImages()\n" );
1921 GL_InitImages ();
1922
1923 ri.Con_Printf( PRINT_DEVELOPER, "Mod_Init()\n" );
1924 Mod_Init ();
1925
1926 ri.Con_Printf( PRINT_DEVELOPER, "R_InitParticleTexture()\n" );
1927 R_InitParticleTexture ();
1928
1929 ri.Con_Printf( PRINT_DEVELOPER, "Draw_InitLocal()\n" );
1930 Draw_InitLocal ();
1931
1932 err = qglGetError();
1933 if ( err != GL_NO_ERROR )
1934 ri.Con_Printf (PRINT_ALL, "glGetError() = 0x%x\n", err);
1935
1936 ri.Con_Printf( PRINT_DEVELOPER, "R_Init() complete.\n" );
1937 return 0;
1938 }
1939
1940 /*
1941 ===============
1942 R_Shutdown
1943 ===============
1944 */
R_Shutdown(void)1945 void EXPORT R_Shutdown (void)
1946 {
1947 ri.Cmd_RemoveCommand ("modellist");
1948 ri.Cmd_RemoveCommand ("screenshot");
1949 ri.Cmd_RemoveCommand ("imagelist");
1950 ri.Cmd_RemoveCommand ("gl_strings");
1951 ri.Cmd_RemoveCommand ("hash_stats");
1952
1953 #ifdef R1GL_RELEASE
1954 ri.Cmd_RemoveCommand ("r1gl_version");
1955 #endif
1956
1957 Mod_FreeAll ();
1958
1959 GL_ShutdownImages ();
1960
1961 /*
1962 ** shut down OS specific OpenGL stuff like contexts, etc.
1963 */
1964 GLimp_Shutdown();
1965
1966 /*
1967 ** shutdown our QGL subsystem
1968 */
1969 QGL_Shutdown();
1970 }
1971
GL_UpdateAnisotropy(void)1972 void GL_UpdateAnisotropy (void)
1973 {
1974 int i;
1975 image_t *glt;
1976 float value;
1977
1978 if (!gl_config.r1gl_GL_EXT_texture_filter_anisotropic)
1979 value = 1;
1980 else
1981 value = gl_ext_max_anisotropy->value;
1982
1983 for (i=0, glt=gltextures ; i<numgltextures ; i++, glt++)
1984 {
1985 if (glt->type != it_pic && glt->type != it_sky)
1986 {
1987 GL_Bind (glt->texnum);
1988 qglTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, value);
1989 }
1990 }
1991 }
1992
1993
1994 /*
1995 @@@@@@@@@@@@@@@@@@@@@
1996 R_BeginFrame
1997 @@@@@@@@@@@@@@@@@@@@@
1998 */
R_BeginFrame(float camera_separation)1999 void EXPORT R_BeginFrame( float camera_separation )
2000 {
2001 #ifdef STEREO_SUPPORT
2002 gl_state.camera_separation = camera_separation;
2003 #endif
2004
2005 /*
2006 ** change modes if necessary
2007 */
2008 if ( gl_mode->modified || vid_fullscreen->modified )
2009 { // FIXME: only restart if CDS is required
2010 cvar_t *ref;
2011
2012 ref = ri.Cvar_Get ("vid_ref", "r1gl", 0);
2013 ref->modified = true;
2014 }
2015
2016 /*if ( gl_log->modified )
2017 {
2018 GLimp_EnableLogging( gl_log->value );
2019 gl_log->modified = false;
2020 }
2021
2022 if ( gl_log->value )
2023 {
2024 GLimp_LogNewFrame();
2025 }*/
2026
2027 if (gl_ext_nv_multisample_filter_hint->modified)
2028 {
2029 gl_ext_nv_multisample_filter_hint->modified = false;
2030
2031 if (gl_config.r1gl_GL_EXT_nv_multisample_filter_hint)
2032 {
2033 if (!strcmp (gl_ext_nv_multisample_filter_hint->string, "nicest"))
2034 qglHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
2035 else
2036 qglHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_FASTEST);
2037 }
2038 }
2039
2040 if (gl_contrast->modified)
2041 {
2042 if (gl_contrast->value < 0.5f)
2043 ri.Cvar_SetValue ("gl_contrast", 0.5f);
2044 else if (gl_contrast->value > 1.5f)
2045 ri.Cvar_SetValue ("gl_contrast", 1.5f);
2046
2047 gl_contrast->modified = false;
2048 }
2049
2050
2051
2052 /*
2053 ** update 3Dfx gamma -- it is expected that a user will do a vid_restart
2054 ** after tweaking this value
2055 */
2056 #if 0
2057 if ( vid_gamma->modified )
2058 {
2059 vid_gamma->modified = false;
2060
2061 if ( gl_config.renderer & ( GL_RENDERER_VOODOO ) )
2062 {
2063 char envbuffer[1024];
2064 float g;
2065
2066 g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F;
2067 Com_sprintf( envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g );
2068 putenv( envbuffer );
2069 Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g );
2070 putenv( envbuffer );
2071 }
2072 }
2073 #endif
2074
2075 #ifdef STEREO_SUPPORT
2076 GLimp_BeginFrame( camera_separation );
2077 #else
2078 GLimp_BeginFrame ();
2079 #endif
2080
2081 /*
2082 ** go into 2D mode
2083 */
2084 qglViewport (0,0, vid.width, vid.height);
2085 qglMatrixMode(GL_PROJECTION);
2086 qglLoadIdentity ();
2087 //qglOrtho (0, vid.width, vid.height, 0, -99999, 99999);
2088 qglOrtho(0, vid_scaled_width, vid_scaled_height, 0, -99999, 99999);
2089 qglMatrixMode(GL_MODELVIEW);
2090 qglLoadIdentity ();
2091 //qglDisable (GL_DEPTH_TEST);
2092 //GLPROFqglDisable (GL_CULL_FACE);
2093 //GLPROFqglDisable (GL_BLEND);
2094 //GLPROFqglEnable (GL_ALPHA_TEST);
2095 qglColor4fv(colorWhite);
2096
2097 //qglEnable(GL_MULTISAMPLE_ARB);
2098
2099 /*
2100 ** draw buffer stuff
2101 */
2102 if ( gl_drawbuffer->modified )
2103 {
2104 gl_drawbuffer->modified = false;
2105
2106 #ifdef STEREO_SUPPORT
2107 if ( gl_state.camera_separation == 0 || !gl_state.stereo_enabled )
2108 #endif
2109 {
2110 if ( Q_stricmp( gl_drawbuffer->string, "GL_FRONT" ) == 0 )
2111 qglDrawBuffer( GL_FRONT );
2112 else
2113 qglDrawBuffer( GL_BACK );
2114 }
2115 }
2116
2117 /*
2118 ** texturemode stuff
2119 */
2120 if ( gl_texturemode->modified )
2121 {
2122 GL_TextureMode( gl_texturemode->string );
2123 gl_texturemode->modified = false;
2124 }
2125
2126 if (gl_ext_max_anisotropy->modified && gl_config.r1gl_GL_EXT_texture_filter_anisotropic)
2127 {
2128 GL_UpdateAnisotropy ();
2129 gl_ext_max_anisotropy->modified = false;
2130 }
2131
2132 if (gl_ext_texture_filter_anisotropic->modified)
2133 {
2134 gl_config.r1gl_GL_EXT_texture_filter_anisotropic = false;
2135 if ( strstr( gl_config.extensions_string, "GL_EXT_texture_filter_anisotropic" ) )
2136 {
2137 if ( gl_ext_texture_filter_anisotropic->value )
2138 {
2139 ri.Con_Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic\n" );
2140 gl_config.r1gl_GL_EXT_texture_filter_anisotropic = true;
2141 GL_UpdateAnisotropy ();
2142 }
2143 else
2144 {
2145 ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_texture_filter_anisotropic\n" );
2146 GL_UpdateAnisotropy ();
2147 }
2148 }
2149 else
2150 {
2151 ri.Con_Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not found\n" );
2152 }
2153
2154 gl_ext_texture_filter_anisotropic->modified = false;
2155 }
2156
2157 if (gl_hudscale->modified)
2158 {
2159 int width, height;
2160
2161 gl_hudscale->modified = false;
2162
2163 if (gl_hudscale->value < 1.0f)
2164 {
2165 ri.Cvar_Set ("gl_hudscale", "1.0");
2166 }
2167 else
2168 {
2169 //r1: hudscaling
2170 width = (int)ceilf((float)vid.width / gl_hudscale->value);
2171 height = (int)ceilf((float)vid.height / gl_hudscale->value);
2172
2173 //round to powers of 8/2 to avoid blackbars
2174 width = (width+7)&~7;
2175 height = (height+1)&~1;
2176
2177 gl_hudscale->modified = false;
2178
2179 vid_scaled_width = vid.width / gl_hudscale->value;
2180 vid_scaled_height = vid.height / gl_hudscale->value;
2181
2182 // let the sound and input subsystems know about the new window
2183 ri.Vid_NewWindow (width, height);
2184 }
2185 }
2186
2187 #if 0
2188 if ( gl_texturealphamode->modified )
2189 {
2190 GL_TextureAlphaMode( gl_texturealphamode->string );
2191 gl_texturealphamode->modified = false;
2192 }
2193
2194 if ( gl_texturesolidmode->modified )
2195 {
2196 GL_TextureSolidMode( gl_texturesolidmode->string );
2197 gl_texturesolidmode->modified = false;
2198 }
2199 #endif
2200
2201 if (gl_texture_formats->modified)
2202 {
2203 load_png_wals = strstr (gl_texture_formats->string, "png") ? true : false;
2204 load_jpg_wals = strstr (gl_texture_formats->string, "jpg") ? true : false;
2205 load_tga_wals = strstr (gl_texture_formats->string, "tga") ? true : false;
2206 gl_texture_formats->modified = false;
2207 }
2208
2209 if (gl_pic_formats->modified)
2210 {
2211 load_png_pics = strstr (gl_pic_formats->string, "png") ? true : false;
2212 load_jpg_pics = strstr (gl_pic_formats->string, "jpg") ? true : false;
2213 load_tga_pics = strstr (gl_pic_formats->string, "tga") ? true : false;
2214 gl_pic_formats->modified = false;
2215 }
2216
2217 /*
2218 ** swapinterval stuff
2219 */
2220 GL_UpdateSwapInterval();
2221
2222 //
2223 // clear screen if desired
2224 //
2225 R_Clear ();
2226 }
2227
2228 /*
2229 =============
2230 R_SetPalette
2231 =============
2232 */
2233 unsigned r_rawpalette[256];
2234
R_SetPalette(const unsigned char * palette)2235 void EXPORT R_SetPalette ( const unsigned char *palette)
2236 {
2237 /*int i;
2238
2239 byte *rp = ( byte * ) r_rawpalette;
2240
2241 if ( palette )
2242 {
2243 for ( i = 0; i < 256; i++ )
2244 {
2245 rp[i*4+0] = palette[i*3+0];
2246 rp[i*4+1] = palette[i*3+1];
2247 rp[i*4+2] = palette[i*3+2];
2248 rp[i*4+3] = 0xff;
2249 }
2250 }
2251 else
2252 {
2253 for ( i = 0; i < 256; i++ )
2254 {
2255 rp[i*4+0] = d_8to24table[i] & 0xff;
2256 rp[i*4+1] = ( d_8to24table[i] >> 8 ) & 0xff;
2257 rp[i*4+2] = ( d_8to24table[i] >> 16 ) & 0xff;
2258 rp[i*4+3] = 0xff;
2259 }
2260 }
2261 GL_SetTexturePalette( r_rawpalette );*/
2262
2263 qglClearColor (0,0,0,0);
2264 qglClear (GL_COLOR_BUFFER_BIT);
2265 qglClearColor (1,0, 0.5 , 0.5);
2266 }
2267
2268 /*
2269 ** R_DrawBeam
2270 */
R_DrawBeam(entity_t * e)2271 void R_DrawBeam( entity_t *e )
2272 {
2273 #define NUM_BEAM_SEGS 6
2274
2275 int i;
2276 float r, g, b;
2277
2278 vec3_t perpvec;
2279 vec3_t direction, normalized_direction;
2280 vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
2281 vec3_t oldorigin, origin;
2282
2283 oldorigin[0] = e->oldorigin[0];
2284 oldorigin[1] = e->oldorigin[1];
2285 oldorigin[2] = e->oldorigin[2];
2286
2287 origin[0] = e->origin[0];
2288 origin[1] = e->origin[1];
2289 origin[2] = e->origin[2];
2290
2291 normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
2292 normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
2293 normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
2294
2295 if ( VectorNormalize( normalized_direction ) == 0 )
2296 return;
2297
2298 PerpendicularVector( perpvec, normalized_direction );
2299 VectorScale( perpvec, e->frame / 2, perpvec );
2300
2301 for ( i = 0; i < 6; i++ )
2302 {
2303 RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0f/NUM_BEAM_SEGS)*i );
2304 VectorAdd( start_points[i], origin, start_points[i] );
2305 VectorAdd( start_points[i], direction, end_points[i] );
2306 }
2307
2308 qglDisable( GL_TEXTURE_2D );
2309 qglEnable( GL_BLEND );
2310 qglDepthMask( GL_FALSE );
2311
2312 r = (float)(( d_8to24table[e->skinnum & 0xFF] ) & 0xFF);
2313 g = (float)(( d_8to24table[e->skinnum & 0xFF] >> 8 ) & 0xFF);
2314 b = (float)(( d_8to24table[e->skinnum & 0xFF] >> 16 ) & 0xFF);
2315
2316 r *= 1/255.0F;
2317 g *= 1/255.0F;
2318 b *= 1/255.0F;
2319
2320 qglColor4f( r, g, b, e->alpha );
2321
2322 qglBegin( GL_TRIANGLE_STRIP );
2323 for ( i = 0; i < NUM_BEAM_SEGS; i++ )
2324 {
2325 qglVertex3fv( start_points[i] );
2326 qglVertex3fv( end_points[i] );
2327 qglVertex3fv( start_points[(i+1)%NUM_BEAM_SEGS] );
2328 qglVertex3fv( end_points[(i+1)%NUM_BEAM_SEGS] );
2329 }
2330 qglEnd();
2331
2332 qglEnable( GL_TEXTURE_2D );
2333 qglDisable( GL_BLEND );
2334 qglDepthMask( GL_TRUE );
2335 }
2336
2337 //===================================================================
2338
2339
2340 void EXPORT R_BeginRegistration (char *map);
2341 struct model_s * EXPORT R_RegisterModel (char *name);
2342 struct image_s * EXPORT R_RegisterSkin (char *name);
2343 void EXPORT R_SetSky (char *name, float rotate, vec3_t axis);
2344 void EXPORT R_EndRegistration (void);
2345
2346 void EXPORT R_RenderFrame (refdef_t *fd);
2347
2348 struct image_s * EXPORT Draw_FindPic (char *name);
2349
2350 void EXPORT Draw_Pic (int x, int y, char *name);
2351 void EXPORT Draw_Char (int x, int y, int c);
2352 void EXPORT Draw_TileClear (int x, int y, int w, int h, char *name);
2353 void EXPORT Draw_Fill (int x, int y, int w, int h, int c);
2354 void EXPORT Draw_FadeScreen (void);
2355
2356 /*
2357 @@@@@@@@@@@@@@@@@@@@@
2358 GetRefAPI
2359
2360 @@@@@@@@@@@@@@@@@@@@@
2361 */
GetExtraAPI(refimportnew_t rimp)2362 void EXPORT GetExtraAPI (refimportnew_t rimp )
2363 {
2364 if (rimp.APIVersion != EXTENDED_API_VERSION)
2365 {
2366 ri.Con_Printf (PRINT_ALL, "R1GL: ExtraAPI version number mismatch, expected version %d, got version %d.\n", EXTENDED_API_VERSION, rimp.APIVersion);
2367 return;
2368 }
2369
2370 memcpy (&rx, &rimp, sizeof(rx));
2371 }
2372
GetRefAPI(refimport_t rimp)2373 refexport_t EXPORT GetRefAPI (refimport_t rimp )
2374 {
2375 refexport_t re;
2376
2377 ri = rimp;
2378
2379 re.api_version = API_VERSION;
2380
2381 re.BeginRegistration = R_BeginRegistration;
2382 re.RegisterModel = R_RegisterModel;
2383 re.RegisterSkin = R_RegisterSkin;
2384 re.RegisterPic = Draw_FindPic;
2385 re.SetSky = R_SetSky;
2386 re.EndRegistration = R_EndRegistration;
2387
2388 re.RenderFrame = R_RenderFrame;
2389
2390 re.DrawGetPicSize = Draw_GetPicSize;
2391 re.DrawPic = Draw_Pic;
2392 re.DrawStretchPic = Draw_StretchPic;
2393 re.DrawChar = Draw_Char;
2394 re.DrawTileClear = Draw_TileClear;
2395 re.DrawFill = Draw_Fill;
2396 re.DrawFadeScreen= Draw_FadeScreen;
2397
2398 re.DrawStretchRaw = Draw_StretchRaw;
2399
2400 re.Init = R_Init;
2401 re.Shutdown = R_Shutdown;
2402
2403 re.CinematicSetPalette = R_SetPalette;
2404 re.BeginFrame = R_BeginFrame;
2405 re.EndFrame = GLimp_EndFrame;
2406
2407 re.AppActivate = GLimp_AppActivate;
2408
2409 Swap_Init ();
2410
2411 return re;
2412 }
2413
2414
2415 #ifndef REF_HARD_LINKED
2416 // this is only here so the functions in q_shared.c and q_shwin.c can link
Sys_Error(const char * error,...)2417 void Sys_Error (const char *error, ...)
2418 {
2419 va_list argptr;
2420 char text[1024];
2421
2422 va_start (argptr, error);
2423 vsprintf (text, error, argptr);
2424 va_end (argptr);
2425
2426 ri.Sys_Error (ERR_FATAL, "%s", text);
2427 }
2428
Com_Printf(const char * fmt,int level,...)2429 void Com_Printf (const char *fmt, int level, ...)
2430 {
2431 va_list argptr;
2432 char text[1024];
2433
2434 va_start (argptr, level);
2435 vsprintf (text, fmt, argptr);
2436 va_end (argptr);
2437
2438 ri.Con_Printf (PRINT_ALL, "%s", text);
2439 }
2440
2441 #endif
2442