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 void R_Clear (void);
24
25 viddef_t vid;
26
27 refimport_t ri;
28
29 int QGL_TEXTURE0, QGL_TEXTURE1;
30
31 model_t *r_worldmodel;
32
33 float gldepthmin, gldepthmax;
34
35 glconfig_t gl_config;
36 glstate_t gl_state;
37
38 image_t *r_notexture; // use for bad textures
39 image_t *r_particletexture; // little dot for particles
40
41 entity_t *currententity;
42 model_t *currentmodel;
43
44 cplane_t frustum[4];
45
46 int r_visframecount; // bumped when going to a new PVS
47 int r_framecount; // used for dlight push checking
48
49 int c_brush_polys, c_alias_polys;
50
51 float v_blend[4]; // final blending color
52
53 void GL_Strings_f( void );
54
55 //
56 // view origin
57 //
58 vec3_t vup;
59 vec3_t vpn;
60 vec3_t vright;
61 vec3_t r_origin;
62
63 float r_world_matrix[16];
64 float r_base_world_matrix[16];
65
66 //
67 // screen size info
68 //
69 refdef_t r_newrefdef;
70
71 int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
72
73 cvar_t *r_norefresh;
74 cvar_t *r_drawentities;
75 cvar_t *r_drawworld;
76 cvar_t *r_speeds;
77 cvar_t *r_fullbright;
78 cvar_t *r_novis;
79 cvar_t *r_nocull;
80 cvar_t *r_lerpmodels;
81 cvar_t *r_lefthand;
82
83 cvar_t *r_lightlevel; // FIXME: This is a HACK to get the client's light level
84
85 cvar_t *gl_nosubimage;
86 cvar_t *gl_allow_software;
87
88 cvar_t *gl_vertex_arrays;
89
90 cvar_t *gl_particle_min_size;
91 cvar_t *gl_particle_max_size;
92 cvar_t *gl_particle_size;
93 cvar_t *gl_particle_att_a;
94 cvar_t *gl_particle_att_b;
95 cvar_t *gl_particle_att_c;
96
97 cvar_t *gl_ext_swapinterval;
98 cvar_t *gl_ext_palettedtexture;
99 cvar_t *gl_ext_multitexture;
100 cvar_t *gl_ext_pointparameters;
101 cvar_t *gl_ext_compiled_vertex_array;
102
103 cvar_t *gl_log;
104 cvar_t *gl_bitdepth;
105 cvar_t *gl_drawbuffer;
106 cvar_t *gl_driver;
107 cvar_t *gl_lightmap;
108 cvar_t *gl_shadows;
109 cvar_t * gl_stencilshadow;
110 cvar_t *gl_mode;
111 cvar_t *gl_dynamic;
112 cvar_t *gl_monolightmap;
113 cvar_t *gl_modulate;
114 cvar_t *gl_nobind;
115 cvar_t *gl_round_down;
116 cvar_t *gl_picmip;
117 cvar_t *gl_skymip;
118 cvar_t *gl_showtris;
119 cvar_t *gl_ztrick;
120 cvar_t *gl_finish;
121 cvar_t *gl_clear;
122 cvar_t *gl_cull;
123 cvar_t *gl_polyblend;
124 cvar_t *gl_flashblend;
125 cvar_t *gl_playermip;
126 cvar_t *gl_saturatelighting;
127 cvar_t *gl_swapinterval;
128 cvar_t *gl_texturemode;
129 cvar_t *gl_texturealphamode;
130 cvar_t *gl_texturesolidmode;
131 cvar_t *gl_lockpvs;
132
133 cvar_t *gl_3dlabs_broken;
134
135 cvar_t *vid_fullscreen;
136 cvar_t *vid_gamma;
137 cvar_t *vid_ref;
138
139 /*
140 =================
141 R_CullBox
142
143 Returns true if the box is completely outside the frustom
144 =================
145 */
R_CullBox(vec3_t mins,vec3_t maxs)146 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
147 {
148 int i;
149
150 if (r_nocull->value)
151 return false;
152
153 for (i=0 ; i<4 ; i++)
154 if ( BOX_ON_PLANE_SIDE(mins, maxs, &frustum[i]) == 2)
155 return true;
156 return false;
157 }
158
159
R_RotateForEntity(entity_t * e)160 void R_RotateForEntity (entity_t *e)
161 {
162 qglTranslatef (e->origin[0], e->origin[1], e->origin[2]);
163
164 qglRotatef (e->angles[1], 0, 0, 1);
165 qglRotatef (-e->angles[0], 0, 1, 0);
166 qglRotatef (-e->angles[2], 1, 0, 0);
167 }
168
169 /*
170 =============================================================
171
172 SPRITE MODELS
173
174 =============================================================
175 */
176
177
178 /*
179 =================
180 R_DrawSpriteModel
181
182 =================
183 */
R_DrawSpriteModel(entity_t * e)184 void R_DrawSpriteModel (entity_t *e)
185 {
186 float alpha = 1.0F;
187 vec3_t point;
188 dsprframe_t *frame;
189 float *up, *right;
190 dsprite_t *psprite;
191
192 // don't even bother culling, because it's just a single
193 // polygon without a surface cache
194
195 psprite = (dsprite_t *)currentmodel->extradata;
196
197 #if 0
198 if (e->frame < 0 || e->frame >= psprite->numframes)
199 {
200 ri.Con_Printf (PRINT_ALL, "no such sprite frame %i\n", e->frame);
201 e->frame = 0;
202 }
203 #endif
204 e->frame %= psprite->numframes;
205
206 frame = &psprite->frames[e->frame];
207
208 #if 0
209 if (psprite->type == SPR_ORIENTED)
210 { // bullet marks on walls
211 vec3_t v_forward, v_right, v_up;
212
213 AngleVectors (currententity->angles, v_forward, v_right, v_up);
214 up = v_up;
215 right = v_right;
216 }
217 else
218 #endif
219 { // normal sprite
220 up = vup;
221 right = vright;
222 }
223
224 if ( e->flags & RF_TRANSLUCENT )
225 alpha = e->alpha;
226
227 if ( alpha != 1.0F )
228 qglEnable( GL_BLEND );
229
230 qglColor4f( 1, 1, 1, alpha );
231
232 GL_Bind(currentmodel->skins[e->frame]->texnum);
233
234 GL_TexEnv( GL_MODULATE );
235
236 if ( alpha == 1.0 )
237 qglEnable (GL_ALPHA_TEST);
238 else
239 qglDisable( GL_ALPHA_TEST );
240
241 qglBegin (GL_QUADS);
242
243 qglTexCoord2f (0, 1);
244 VectorMA (e->origin, -frame->origin_y, up, point);
245 VectorMA (point, -frame->origin_x, right, point);
246 qglVertex3fv (point);
247
248 qglTexCoord2f (0, 0);
249 VectorMA (e->origin, frame->height - frame->origin_y, up, point);
250 VectorMA (point, -frame->origin_x, right, point);
251 qglVertex3fv (point);
252
253 qglTexCoord2f (1, 0);
254 VectorMA (e->origin, frame->height - frame->origin_y, up, point);
255 VectorMA (point, frame->width - frame->origin_x, right, point);
256 qglVertex3fv (point);
257
258 qglTexCoord2f (1, 1);
259 VectorMA (e->origin, -frame->origin_y, up, point);
260 VectorMA (point, frame->width - frame->origin_x, right, point);
261 qglVertex3fv (point);
262
263 qglEnd ();
264
265 qglDisable (GL_ALPHA_TEST);
266 GL_TexEnv( GL_REPLACE );
267
268 if ( alpha != 1.0F )
269 qglDisable( GL_BLEND );
270
271 qglColor4f( 1, 1, 1, 1 );
272 }
273
274 //==================================================================================
275
276 /*
277 =============
278 R_DrawNullModel
279 =============
280 */
R_DrawNullModel(void)281 void R_DrawNullModel (void)
282 {
283 vec3_t shadelight;
284 int i;
285
286 if ( currententity->flags & RF_FULLBRIGHT )
287 shadelight[0] = shadelight[1] = shadelight[2] = 1.0F;
288 else
289 R_LightPoint (currententity->origin, shadelight);
290
291 qglPushMatrix ();
292 R_RotateForEntity (currententity);
293
294 qglDisable (GL_TEXTURE_2D);
295 qglColor3fv (shadelight);
296
297 qglBegin (GL_TRIANGLE_FAN);
298 qglVertex3f (0, 0, -16);
299 for (i=0 ; i<=4 ; i++)
300 qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0);
301 qglEnd ();
302
303 qglBegin (GL_TRIANGLE_FAN);
304 qglVertex3f (0, 0, 16);
305 for (i=4 ; i>=0 ; i--)
306 qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0);
307 qglEnd ();
308
309 qglColor3f (1,1,1);
310 qglPopMatrix ();
311 qglEnable (GL_TEXTURE_2D);
312 }
313
314 /*
315 =============
316 R_DrawEntitiesOnList
317 =============
318 */
R_DrawEntitiesOnList(void)319 void R_DrawEntitiesOnList (void)
320 {
321 int i;
322
323 if (!r_drawentities->value)
324 return;
325
326 // draw non-transparent first
327 for (i=0 ; i<r_newrefdef.num_entities ; i++)
328 {
329 currententity = &r_newrefdef.entities[i];
330 if (currententity->flags & RF_TRANSLUCENT)
331 continue; // solid
332
333 if ( currententity->flags & RF_BEAM )
334 {
335 R_DrawBeam( currententity );
336 }
337 else
338 {
339 currentmodel = currententity->model;
340 if (!currentmodel)
341 {
342 R_DrawNullModel ();
343 continue;
344 }
345 switch (currentmodel->type)
346 {
347 case mod_alias:
348 R_DrawAliasModel (currententity);
349 break;
350 case mod_brush:
351 R_DrawBrushModel (currententity);
352 break;
353 case mod_sprite:
354 R_DrawSpriteModel (currententity);
355 break;
356 default:
357 ri.Sys_Error (ERR_DROP, "Bad modeltype");
358 break;
359 }
360 }
361 }
362
363 // draw transparent entities
364 // we could sort these if it ever becomes a problem...
365 qglDepthMask (0); // no z writes
366 for (i=0 ; i<r_newrefdef.num_entities ; i++)
367 {
368 currententity = &r_newrefdef.entities[i];
369 if (!(currententity->flags & RF_TRANSLUCENT))
370 continue; // solid
371
372 if ( currententity->flags & RF_BEAM )
373 {
374 R_DrawBeam( currententity );
375 }
376 else
377 {
378 currentmodel = currententity->model;
379
380 if (!currentmodel)
381 {
382 R_DrawNullModel ();
383 continue;
384 }
385 switch (currentmodel->type)
386 {
387 case mod_alias:
388 R_DrawAliasModel (currententity);
389 break;
390 case mod_brush:
391 R_DrawBrushModel (currententity);
392 break;
393 case mod_sprite:
394 R_DrawSpriteModel (currententity);
395 break;
396 default:
397 ri.Sys_Error (ERR_DROP, "Bad modeltype");
398 break;
399 }
400 }
401 }
402 qglDepthMask (1); // back to writing
403
404 }
405
406 /*
407 ** GL_DrawParticles
408 **
409 */
GL_DrawParticles(int num_particles,const particle_t particles[],const unsigned colortable[768])410 void GL_DrawParticles( int num_particles, const particle_t particles[], const unsigned colortable[768] )
411 {
412 const particle_t *p;
413 int i;
414 vec3_t up, right;
415 float scale;
416 byte color[4];
417
418 GL_Bind(r_particletexture->texnum);
419 qglDepthMask( GL_FALSE ); // no z buffering
420 qglEnable( GL_BLEND );
421 GL_TexEnv( GL_MODULATE );
422 qglBegin( GL_TRIANGLES );
423
424 VectorScale (vup, 1.5, up);
425 VectorScale (vright, 1.5, right);
426
427 for ( p = particles, i=0 ; i < num_particles ; i++,p++)
428 {
429 // hack a scale up to keep particles from disapearing
430 scale = ( p->origin[0] - r_origin[0] ) * vpn[0] +
431 ( p->origin[1] - r_origin[1] ) * vpn[1] +
432 ( p->origin[2] - r_origin[2] ) * vpn[2];
433
434 if (scale < 20)
435 scale = 1;
436 else
437 scale = 1 + scale * 0.004;
438
439 *(int *)color = colortable[p->color];
440 color[3] = p->alpha*255;
441
442 qglColor4ubv( color );
443
444 qglTexCoord2f( 0.0625, 0.0625 );
445 qglVertex3fv( p->origin );
446
447 qglTexCoord2f( 1.0625, 0.0625 );
448 qglVertex3f( p->origin[0] + up[0]*scale,
449 p->origin[1] + up[1]*scale,
450 p->origin[2] + up[2]*scale);
451
452 qglTexCoord2f( 0.0625, 1.0625 );
453 qglVertex3f( p->origin[0] + right[0]*scale,
454 p->origin[1] + right[1]*scale,
455 p->origin[2] + right[2]*scale);
456 }
457
458 qglEnd ();
459 qglDisable( GL_BLEND );
460 qglColor4f( 1,1,1,1 );
461 qglDepthMask( 1 ); // back to normal Z buffering
462 GL_TexEnv( GL_REPLACE );
463 }
464
465 /*
466 ===============
467 R_DrawParticles
468 ===============
469 */
R_DrawParticles(void)470 void R_DrawParticles (void)
471 {
472 if ( gl_ext_pointparameters->value && qglPointParameterfEXT )
473 {
474 int i;
475 unsigned char color[4];
476 const particle_t *p;
477
478 qglDepthMask( GL_FALSE );
479 qglEnable( GL_BLEND );
480 qglDisable( GL_TEXTURE_2D );
481
482 qglPointSize( gl_particle_size->value );
483
484 qglBegin( GL_POINTS );
485 for ( i = 0, p = r_newrefdef.particles; i < r_newrefdef.num_particles; i++, p++ )
486 {
487 *(int *)color = d_8to24table[p->color];
488 color[3] = p->alpha*255;
489
490 qglColor4ubv( color );
491
492 qglVertex3fv( p->origin );
493 }
494 qglEnd();
495
496 qglDisable( GL_BLEND );
497 qglColor4f( 1.0F, 1.0F, 1.0F, 1.0F );
498 qglDepthMask( GL_TRUE );
499 qglEnable( GL_TEXTURE_2D );
500
501 }
502 else
503 {
504 GL_DrawParticles( r_newrefdef.num_particles, r_newrefdef.particles, d_8to24table );
505 }
506 }
507
508 /*
509 ============
510 R_PolyBlend
511 ============
512 */
R_PolyBlend(void)513 void R_PolyBlend (void)
514 {
515 if (!gl_polyblend->value)
516 return;
517 if (!v_blend[3])
518 return;
519
520 qglDisable (GL_ALPHA_TEST);
521 qglEnable (GL_BLEND);
522 qglDisable (GL_DEPTH_TEST);
523 qglDisable (GL_TEXTURE_2D);
524
525 qglLoadIdentity ();
526
527 // FIXME: get rid of these
528 qglRotatef (-90, 1, 0, 0); // put Z going up
529 qglRotatef (90, 0, 0, 1); // put Z going up
530
531 qglColor4fv (v_blend);
532
533 qglBegin (GL_QUADS);
534
535 qglVertex3f (10, 100, 100);
536 qglVertex3f (10, -100, 100);
537 qglVertex3f (10, -100, -100);
538 qglVertex3f (10, 100, -100);
539 qglEnd ();
540
541 qglDisable (GL_BLEND);
542 qglEnable (GL_TEXTURE_2D);
543 qglEnable (GL_ALPHA_TEST);
544
545 qglColor4f(1,1,1,1);
546 }
547
548 //=======================================================================
549
SignbitsForPlane(cplane_t * out)550 int SignbitsForPlane (cplane_t *out)
551 {
552 int bits, j;
553
554 // for fast box on planeside test
555
556 bits = 0;
557 for (j=0 ; j<3 ; j++)
558 {
559 if (out->normal[j] < 0)
560 bits |= 1<<j;
561 }
562 return bits;
563 }
564
565
R_SetFrustum(void)566 void R_SetFrustum (void)
567 {
568 int i;
569
570 #if 0
571 /*
572 ** this code is wrong, since it presume a 90 degree FOV both in the
573 ** horizontal and vertical plane
574 */
575 // front side is visible
576 VectorAdd (vpn, vright, frustum[0].normal);
577 VectorSubtract (vpn, vright, frustum[1].normal);
578 VectorAdd (vpn, vup, frustum[2].normal);
579 VectorSubtract (vpn, vup, frustum[3].normal);
580
581 // we theoretically don't need to normalize these vectors, but I do it
582 // anyway so that debugging is a little easier
583 VectorNormalize( frustum[0].normal );
584 VectorNormalize( frustum[1].normal );
585 VectorNormalize( frustum[2].normal );
586 VectorNormalize( frustum[3].normal );
587 #else
588 // rotate VPN right by FOV_X/2 degrees
589 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_newrefdef.fov_x / 2 ) );
590 // rotate VPN left by FOV_X/2 degrees
591 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_newrefdef.fov_x / 2 );
592 // rotate VPN up by FOV_X/2 degrees
593 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_newrefdef.fov_y / 2 );
594 // rotate VPN down by FOV_X/2 degrees
595 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_newrefdef.fov_y / 2 ) );
596 #endif
597
598 for (i=0 ; i<4 ; i++)
599 {
600 frustum[i].type = PLANE_ANYZ;
601 frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
602 frustum[i].signbits = SignbitsForPlane (&frustum[i]);
603 }
604 }
605
606 //=======================================================================
607
608 /*
609 ===============
610 R_SetupFrame
611 ===============
612 */
R_SetupFrame(void)613 void R_SetupFrame (void)
614 {
615 int i;
616 mleaf_t *leaf;
617
618 r_framecount++;
619
620 // build the transformation matrix for the given view angles
621 VectorCopy (r_newrefdef.vieworg, r_origin);
622
623 AngleVectors (r_newrefdef.viewangles, vpn, vright, vup);
624
625 // current viewcluster
626 if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
627 {
628 r_oldviewcluster = r_viewcluster;
629 r_oldviewcluster2 = r_viewcluster2;
630 leaf = Mod_PointInLeaf (r_origin, r_worldmodel);
631 r_viewcluster = r_viewcluster2 = leaf->cluster;
632
633 // check above and below so crossing solid water doesn't draw wrong
634 if (!leaf->contents)
635 { // look down a bit
636 vec3_t temp;
637
638 VectorCopy (r_origin, temp);
639 temp[2] -= 16;
640 leaf = Mod_PointInLeaf (temp, r_worldmodel);
641 if ( !(leaf->contents & CONTENTS_SOLID) &&
642 (leaf->cluster != r_viewcluster2) )
643 r_viewcluster2 = leaf->cluster;
644 }
645 else
646 { // look up a bit
647 vec3_t temp;
648
649 VectorCopy (r_origin, temp);
650 temp[2] += 16;
651 leaf = Mod_PointInLeaf (temp, r_worldmodel);
652 if ( !(leaf->contents & CONTENTS_SOLID) &&
653 (leaf->cluster != r_viewcluster2) )
654 r_viewcluster2 = leaf->cluster;
655 }
656 }
657
658 for (i=0 ; i<4 ; i++)
659 v_blend[i] = r_newrefdef.blend[i];
660
661 c_brush_polys = 0;
662 c_alias_polys = 0;
663
664 // clear out the portion of the screen that the NOWORLDMODEL defines
665 if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
666 {
667 qglEnable( GL_SCISSOR_TEST );
668 qglClearColor( 0.3, 0.3, 0.3, 1 );
669 qglScissor( r_newrefdef.x, vid.height - r_newrefdef.height - r_newrefdef.y, r_newrefdef.width, r_newrefdef.height );
670 qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
671 qglClearColor( 1, 0, 0.5, 0.5 );
672 qglDisable( GL_SCISSOR_TEST );
673 }
674 }
675
676
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)677 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
678 GLdouble zNear, GLdouble zFar )
679 {
680 GLdouble xmin, xmax, ymin, ymax;
681
682 ymax = zNear * tan( fovy * M_PI / 360.0 );
683 ymin = -ymax;
684
685 xmin = ymin * aspect;
686 xmax = ymax * aspect;
687
688 xmin += -( 2 * gl_state.camera_separation ) / zNear;
689 xmax += -( 2 * gl_state.camera_separation ) / zNear;
690
691 qglFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
692 }
693
694
695 /*
696 =============
697 R_SetupGL
698 =============
699 */
R_SetupGL(void)700 void R_SetupGL (void)
701 {
702 float screenaspect;
703 // float yfov;
704 int x, x2, y2, y, w, h;
705
706 //
707 // set up viewport
708 //
709 x = floor(r_newrefdef.x * vid.width / vid.width);
710 x2 = ceil((r_newrefdef.x + r_newrefdef.width) * vid.width / vid.width);
711 y = floor(vid.height - r_newrefdef.y * vid.height / vid.height);
712 y2 = ceil(vid.height - (r_newrefdef.y + r_newrefdef.height) * vid.height / vid.height);
713
714 w = x2 - x;
715 h = y - y2;
716
717 qglViewport (x, y2, w, h);
718
719 //
720 // set up projection matrix
721 //
722 screenaspect = (float)r_newrefdef.width/r_newrefdef.height;
723 // yfov = 2*atan((float)r_newrefdef.height/r_newrefdef.width)*180/M_PI;
724 qglMatrixMode(GL_PROJECTION);
725 qglLoadIdentity ();
726 MYgluPerspective (r_newrefdef.fov_y, screenaspect, 4, 4096);
727
728 qglCullFace(GL_FRONT);
729
730 qglMatrixMode(GL_MODELVIEW);
731 qglLoadIdentity ();
732
733 qglRotatef (-90, 1, 0, 0); // put Z going up
734 qglRotatef (90, 0, 0, 1); // put Z going up
735 qglRotatef (-r_newrefdef.viewangles[2], 1, 0, 0);
736 qglRotatef (-r_newrefdef.viewangles[0], 0, 1, 0);
737 qglRotatef (-r_newrefdef.viewangles[1], 0, 0, 1);
738 qglTranslatef (-r_newrefdef.vieworg[0], -r_newrefdef.vieworg[1], -r_newrefdef.vieworg[2]);
739
740 // if ( gl_state.camera_separation != 0 && gl_state.stereo_enabled )
741 // qglTranslatef ( gl_state.camera_separation, 0, 0 );
742
743 qglGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
744
745 //
746 // set drawing parms
747 //
748 if (gl_cull->value)
749 qglEnable(GL_CULL_FACE);
750 else
751 qglDisable(GL_CULL_FACE);
752
753 qglDisable(GL_BLEND);
754 qglDisable(GL_ALPHA_TEST);
755 qglEnable(GL_DEPTH_TEST);
756 }
757
758 /*
759 =============
760 R_Clear
761 =============
762 */
763 extern qboolean have_stencil;
764
R_Clear(void)765 void R_Clear (void)
766 {
767 if (gl_ztrick->value)
768 {
769 static int trickframe;
770
771 if (gl_clear->value)
772 qglClear (GL_COLOR_BUFFER_BIT);
773
774 trickframe++;
775 if (trickframe & 1)
776 {
777 gldepthmin = 0;
778 gldepthmax = 0.49999;
779 qglDepthFunc (GL_LEQUAL);
780 }
781 else
782 {
783 gldepthmin = 1;
784 gldepthmax = 0.5;
785 qglDepthFunc (GL_GEQUAL);
786 }
787 }
788 else
789 {
790 if (gl_clear->value)
791 qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
792 else
793 qglClear (GL_DEPTH_BUFFER_BIT);
794 gldepthmin = 0;
795 gldepthmax = 1;
796 qglDepthFunc (GL_LEQUAL);
797 }
798
799 qglDepthRange (gldepthmin, gldepthmax);
800
801 /* stencilbuffer shadows */
802 if (gl_shadows->value && have_stencil && gl_stencilshadow->value) {
803 qglClearStencil(1);
804 qglClear(GL_STENCIL_BUFFER_BIT);
805 }
806 }
807
R_Flash(void)808 void R_Flash( void )
809 {
810 R_PolyBlend ();
811 }
812
813 /*
814 ================
815 R_RenderView
816
817 r_newrefdef must be set before the first call
818 ================
819 */
R_RenderView(refdef_t * fd)820 void R_RenderView (refdef_t *fd)
821 {
822 if (r_norefresh->value)
823 return;
824
825 r_newrefdef = *fd;
826
827 if (!r_worldmodel && !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
828 ri.Sys_Error (ERR_DROP, "R_RenderView: NULL worldmodel");
829
830 if (r_speeds->value)
831 {
832 c_brush_polys = 0;
833 c_alias_polys = 0;
834 }
835
836 R_PushDlights ();
837
838 if (gl_finish->value)
839 qglFinish ();
840
841 R_SetupFrame ();
842
843 R_SetFrustum ();
844
845 R_SetupGL ();
846
847 R_MarkLeaves (); // done here so we know if we're in water
848
849 R_DrawWorld ();
850
851 R_DrawEntitiesOnList ();
852
853 R_RenderDlights ();
854
855 R_DrawParticles ();
856
857 R_DrawAlphaSurfaces ();
858
859 R_Flash();
860
861 if (r_speeds->value)
862 {
863 ri.Con_Printf (PRINT_ALL, "%4i wpoly %4i epoly %i tex %i lmaps\n",
864 c_brush_polys,
865 c_alias_polys,
866 c_visible_textures,
867 c_visible_lightmaps);
868 }
869 }
870
871
R_SetGL2D(void)872 void R_SetGL2D (void)
873 {
874 // set 2D virtual screen size
875 qglViewport (0,0, vid.width, vid.height);
876 qglMatrixMode(GL_PROJECTION);
877 qglLoadIdentity ();
878 qglOrtho (0, vid.width, vid.height, 0, -99999, 99999);
879 qglMatrixMode(GL_MODELVIEW);
880 qglLoadIdentity ();
881 qglDisable (GL_DEPTH_TEST);
882 qglDisable (GL_CULL_FACE);
883 qglDisable (GL_BLEND);
884 qglEnable (GL_ALPHA_TEST);
885 qglColor4f (1,1,1,1);
886 }
887
888 #if 0 // Not used.
889 static void GL_DrawColoredStereoLinePair( float r, float g, float b, float y )
890 {
891 qglColor3f( r, g, b );
892 qglVertex2f( 0, y );
893 qglVertex2f( vid.width, y );
894 qglColor3f( 0, 0, 0 );
895 qglVertex2f( 0, y + 1 );
896 qglVertex2f( vid.width, y + 1 );
897 }
898
899 static void GL_DrawStereoPattern( void )
900 {
901 int i;
902
903 if ( !( gl_config.renderer & GL_RENDERER_INTERGRAPH ) )
904 return;
905
906 if ( !gl_state.stereo_enabled )
907 return;
908
909 R_SetGL2D();
910
911 qglDrawBuffer( GL_BACK_LEFT );
912
913 for ( i = 0; i < 20; i++ )
914 {
915 qglBegin( GL_LINES );
916 GL_DrawColoredStereoLinePair( 1, 0, 0, 0 );
917 GL_DrawColoredStereoLinePair( 1, 0, 0, 2 );
918 GL_DrawColoredStereoLinePair( 1, 0, 0, 4 );
919 GL_DrawColoredStereoLinePair( 1, 0, 0, 6 );
920 GL_DrawColoredStereoLinePair( 0, 1, 0, 8 );
921 GL_DrawColoredStereoLinePair( 1, 1, 0, 10);
922 GL_DrawColoredStereoLinePair( 1, 1, 0, 12);
923 GL_DrawColoredStereoLinePair( 0, 1, 0, 14);
924 qglEnd();
925
926 GLimp_EndFrame();
927 }
928 }
929 #endif
930
931 /*
932 ====================
933 R_SetLightLevel
934
935 ====================
936 */
R_SetLightLevel(void)937 void R_SetLightLevel (void)
938 {
939 vec3_t shadelight;
940
941 if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
942 return;
943
944 // save off light value for server to look at (BIG HACK!)
945
946 R_LightPoint (r_newrefdef.vieworg, shadelight);
947
948 // pick the greatest component, which should be the same
949 // as the mono value returned by software
950 if (shadelight[0] > shadelight[1])
951 {
952 if (shadelight[0] > shadelight[2])
953 r_lightlevel->value = 150*shadelight[0];
954 else
955 r_lightlevel->value = 150*shadelight[2];
956 }
957 else
958 {
959 if (shadelight[1] > shadelight[2])
960 r_lightlevel->value = 150*shadelight[1];
961 else
962 r_lightlevel->value = 150*shadelight[2];
963 }
964
965 }
966
967 /*
968 @@@@@@@@@@@@@@@@@@@@@
969 R_RenderFrame
970
971 @@@@@@@@@@@@@@@@@@@@@
972 */
R_RenderFrame(refdef_t * fd)973 void R_RenderFrame (refdef_t *fd)
974 {
975 R_RenderView( fd );
976 R_SetLightLevel ();
977 R_SetGL2D ();
978 }
979
980
R_Register(void)981 void R_Register( void )
982 {
983 r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
984 r_norefresh = ri.Cvar_Get ("r_norefresh", "0", 0);
985 r_fullbright = ri.Cvar_Get ("r_fullbright", "0", 0);
986 r_drawentities = ri.Cvar_Get ("r_drawentities", "1", 0);
987 r_drawworld = ri.Cvar_Get ("r_drawworld", "1", 0);
988 r_novis = ri.Cvar_Get ("r_novis", "0", 0);
989 r_nocull = ri.Cvar_Get ("r_nocull", "0", 0);
990 r_lerpmodels = ri.Cvar_Get ("r_lerpmodels", "1", 0);
991 r_speeds = ri.Cvar_Get ("r_speeds", "0", 0);
992
993 r_lightlevel = ri.Cvar_Get ("r_lightlevel", "0", 0);
994
995 gl_nosubimage = ri.Cvar_Get( "gl_nosubimage", "0", 0 );
996 gl_allow_software = ri.Cvar_Get( "gl_allow_software", "0", 0 );
997
998 gl_particle_min_size = ri.Cvar_Get( "gl_particle_min_size", "2", CVAR_ARCHIVE );
999 gl_particle_max_size = ri.Cvar_Get( "gl_particle_max_size", "40", CVAR_ARCHIVE );
1000 gl_particle_size = ri.Cvar_Get( "gl_particle_size", "40", CVAR_ARCHIVE );
1001 gl_particle_att_a = ri.Cvar_Get( "gl_particle_att_a", "0.01", CVAR_ARCHIVE );
1002 gl_particle_att_b = ri.Cvar_Get( "gl_particle_att_b", "0.0", CVAR_ARCHIVE );
1003 gl_particle_att_c = ri.Cvar_Get( "gl_particle_att_c", "0.01", CVAR_ARCHIVE );
1004
1005 gl_modulate = ri.Cvar_Get ("gl_modulate", "1", CVAR_ARCHIVE );
1006 gl_log = ri.Cvar_Get( "gl_log", "0", 0 );
1007 gl_bitdepth = ri.Cvar_Get( "gl_bitdepth", "0", 0 );
1008 gl_mode = ri.Cvar_Get( "gl_mode", "3", CVAR_ARCHIVE );
1009 gl_lightmap = ri.Cvar_Get ("gl_lightmap", "0", 0);
1010 gl_shadows = ri.Cvar_Get ("gl_shadows", "0", CVAR_ARCHIVE );
1011 gl_stencilshadow = ri.Cvar_Get("gl_stencilshadow", "0", CVAR_ARCHIVE);
1012 gl_dynamic = ri.Cvar_Get ("gl_dynamic", "1", 0);
1013 gl_nobind = ri.Cvar_Get ("gl_nobind", "0", 0);
1014 gl_round_down = ri.Cvar_Get ("gl_round_down", "1", 0);
1015 gl_picmip = ri.Cvar_Get ("gl_picmip", "0", 0);
1016 gl_skymip = ri.Cvar_Get ("gl_skymip", "0", 0);
1017 gl_showtris = ri.Cvar_Get ("gl_showtris", "0", 0);
1018 gl_ztrick = ri.Cvar_Get ("gl_ztrick", "0", 0);
1019 gl_finish = ri.Cvar_Get ("gl_finish", "0", CVAR_ARCHIVE);
1020 gl_clear = ri.Cvar_Get ("gl_clear", "0", 0);
1021 gl_cull = ri.Cvar_Get ("gl_cull", "1", 0);
1022 gl_polyblend = ri.Cvar_Get ("gl_polyblend", "1", 0);
1023 gl_flashblend = ri.Cvar_Get ("gl_flashblend", "0", 0);
1024 gl_playermip = ri.Cvar_Get ("gl_playermip", "0", 0);
1025 gl_monolightmap = ri.Cvar_Get( "gl_monolightmap", "0", 0 );
1026 #ifdef _WIN32
1027 gl_driver = ri.Cvar_Get( "gl_driver", "opengl32", CVAR_ARCHIVE );
1028 #else
1029 gl_driver = ri.Cvar_Get( "gl_driver", "libGL.so", CVAR_ARCHIVE );
1030 #endif
1031 gl_texturemode = ri.Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE );
1032 gl_texturealphamode = ri.Cvar_Get( "gl_texturealphamode", "default", CVAR_ARCHIVE );
1033 gl_texturesolidmode = ri.Cvar_Get( "gl_texturesolidmode", "default", CVAR_ARCHIVE );
1034 gl_lockpvs = ri.Cvar_Get( "gl_lockpvs", "0", 0 );
1035
1036 gl_vertex_arrays = ri.Cvar_Get( "gl_vertex_arrays", "0", CVAR_ARCHIVE );
1037
1038 gl_ext_swapinterval = ri.Cvar_Get( "gl_ext_swapinterval", "1", CVAR_ARCHIVE );
1039 gl_ext_palettedtexture = ri.Cvar_Get( "gl_ext_palettedtexture", "1", CVAR_ARCHIVE );
1040 gl_ext_multitexture = ri.Cvar_Get( "gl_ext_multitexture", "1", CVAR_ARCHIVE );
1041 gl_ext_pointparameters = ri.Cvar_Get( "gl_ext_pointparameters", "1", CVAR_ARCHIVE );
1042 gl_ext_compiled_vertex_array = ri.Cvar_Get( "gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE );
1043
1044 gl_drawbuffer = ri.Cvar_Get( "gl_drawbuffer", "GL_BACK", 0 );
1045 gl_swapinterval = ri.Cvar_Get( "gl_swapinterval", "1", CVAR_ARCHIVE );
1046
1047 gl_saturatelighting = ri.Cvar_Get( "gl_saturatelighting", "0", 0 );
1048
1049 gl_3dlabs_broken = ri.Cvar_Get( "gl_3dlabs_broken", "1", CVAR_ARCHIVE );
1050
1051 vid_fullscreen = ri.Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE );
1052 vid_gamma = ri.Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE );
1053 vid_ref = ri.Cvar_Get( "vid_ref", "soft", CVAR_ARCHIVE );
1054
1055 ri.Cmd_AddCommand( "imagelist", GL_ImageList_f );
1056 ri.Cmd_AddCommand( "screenshot", GL_ScreenShot_f );
1057 ri.Cmd_AddCommand( "modellist", Mod_Modellist_f );
1058 ri.Cmd_AddCommand( "gl_strings", GL_Strings_f );
1059 }
1060
1061 /*
1062 ==================
1063 R_SetMode
1064 ==================
1065 */
R_SetMode(void)1066 qboolean R_SetMode (void)
1067 {
1068 rserr_t err;
1069 qboolean fullscreen;
1070
1071 #ifdef _WIN32
1072 if ( vid_fullscreen->modified && !gl_config.allow_cds )
1073 {
1074 ri.Con_Printf( PRINT_ALL, "R_SetMode() - CDS not allowed with this driver\n" );
1075 ri.Cvar_SetValue( "vid_fullscreen", !vid_fullscreen->value );
1076 vid_fullscreen->modified = false;
1077 }
1078 #endif
1079 fullscreen = vid_fullscreen->value;
1080
1081 vid_fullscreen->modified = false;
1082 gl_mode->modified = false;
1083
1084 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->value, fullscreen ) ) == rserr_ok )
1085 {
1086 gl_state.prev_mode = gl_mode->value;
1087 }
1088 else
1089 {
1090 if ( err == rserr_invalid_fullscreen )
1091 {
1092 ri.Cvar_SetValue( "vid_fullscreen", 0);
1093 vid_fullscreen->modified = false;
1094 ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - fullscreen unavailable in this mode\n" );
1095 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->value, false ) ) == rserr_ok )
1096 return true;
1097 }
1098 else if ( err == rserr_invalid_mode )
1099 {
1100 ri.Cvar_SetValue( "gl_mode", gl_state.prev_mode );
1101 gl_mode->modified = false;
1102 ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - invalid mode\n" );
1103 }
1104
1105 // try setting it back to something safe
1106 if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_state.prev_mode, false ) ) != rserr_ok )
1107 {
1108 ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - could not revert to safe mode\n" );
1109 return false;
1110 }
1111 }
1112 return true;
1113 }
1114
1115 /*
1116 ===============
1117 R_Init
1118 ===============
1119 */
R_Init(void * hinstance,void * hWnd)1120 int R_Init( void *hinstance, void *hWnd )
1121 {
1122 char renderer_buffer[1000];
1123 char vendor_buffer[1000];
1124 int err;
1125 int j;
1126 extern float r_turbsin[256];
1127
1128 for ( j = 0; j < 256; j++ )
1129 {
1130 r_turbsin[j] *= 0.5;
1131 }
1132
1133 ri.Con_Printf (PRINT_ALL, "ref_gl version: "REF_VERSION"\n");
1134
1135 Draw_GetPalette ();
1136
1137 R_Register();
1138
1139 // initialize our QGL dynamic bindings
1140 if ( !QGL_Init( gl_driver->string ) )
1141 {
1142 QGL_Shutdown();
1143 ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - could not load \"%s\"\n", gl_driver->string );
1144 return -1;
1145 }
1146
1147 // initialize OS-specific parts of OpenGL
1148 if ( !GLimp_Init( hinstance, hWnd ) )
1149 {
1150 QGL_Shutdown();
1151 return -1;
1152 }
1153
1154 // set our "safe" modes
1155 gl_state.prev_mode = 3;
1156
1157 // create the window and set up the context
1158 if ( !R_SetMode () )
1159 {
1160 QGL_Shutdown();
1161 ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - could not R_SetMode()\n" );
1162 return -1;
1163 }
1164
1165 ri.Vid_MenuInit();
1166
1167 /*
1168 ** get our various GL strings
1169 */
1170 gl_config.vendor_string = (char *)qglGetString (GL_VENDOR);
1171 ri.Con_Printf (PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string );
1172 gl_config.renderer_string = (char *)qglGetString (GL_RENDERER);
1173 ri.Con_Printf (PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string );
1174 gl_config.version_string = (char *)qglGetString (GL_VERSION);
1175 ri.Con_Printf (PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string );
1176 gl_config.extensions_string = (char *)qglGetString (GL_EXTENSIONS);
1177 ri.Con_Printf (PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string );
1178
1179 strncpy( renderer_buffer, gl_config.renderer_string, sizeof(renderer_buffer) );
1180 renderer_buffer[sizeof(renderer_buffer)-1] = 0;
1181 strlwr( renderer_buffer );
1182
1183 strncpy( vendor_buffer, gl_config.vendor_string, sizeof(vendor_buffer) );
1184 vendor_buffer[sizeof(vendor_buffer)-1] = 0;
1185 strlwr( vendor_buffer );
1186
1187 if ( strstr( renderer_buffer, "voodoo" ) )
1188 {
1189 if ( !strstr( renderer_buffer, "rush" ) )
1190 gl_config.renderer = GL_RENDERER_VOODOO;
1191 else
1192 gl_config.renderer = GL_RENDERER_VOODOO_RUSH;
1193 }
1194 else if ( strstr( vendor_buffer, "sgi" ) )
1195 gl_config.renderer = GL_RENDERER_SGI;
1196 else if ( strstr( renderer_buffer, "permedia" ) )
1197 gl_config.renderer = GL_RENDERER_PERMEDIA2;
1198 else if ( strstr( renderer_buffer, "glint" ) )
1199 gl_config.renderer = GL_RENDERER_GLINT_MX;
1200 else if ( strstr( renderer_buffer, "glzicd" ) )
1201 gl_config.renderer = GL_RENDERER_REALIZM;
1202 else if ( strstr( renderer_buffer, "gdi" ) )
1203 gl_config.renderer = GL_RENDERER_MCD;
1204 else if ( strstr( renderer_buffer, "pcx2" ) )
1205 gl_config.renderer = GL_RENDERER_PCX2;
1206 else if ( strstr( renderer_buffer, "verite" ) )
1207 gl_config.renderer = GL_RENDERER_RENDITION;
1208 else
1209 gl_config.renderer = GL_RENDERER_OTHER;
1210
1211 if ( toupper( gl_monolightmap->string[1] ) != 'F' )
1212 {
1213 if ( gl_config.renderer == GL_RENDERER_PERMEDIA2 )
1214 {
1215 ri.Cvar_Set( "gl_monolightmap", "A" );
1216 ri.Con_Printf( PRINT_ALL, "...using gl_monolightmap 'a'\n" );
1217 }
1218 else if ( gl_config.renderer & GL_RENDERER_POWERVR )
1219 {
1220 ri.Cvar_Set( "gl_monolightmap", "0" );
1221 }
1222 else
1223 {
1224 ri.Cvar_Set( "gl_monolightmap", "0" );
1225 }
1226 }
1227
1228 // power vr can't have anything stay in the framebuffer, so
1229 // the screen needs to redraw the tiled background every frame
1230 if ( gl_config.renderer & GL_RENDERER_POWERVR )
1231 {
1232 ri.Cvar_Set( "scr_drawall", "1" );
1233 }
1234 else
1235 {
1236 ri.Cvar_Set( "scr_drawall", "0" );
1237 }
1238
1239 #if 0 && defined(__linux__)
1240 ri.Cvar_SetValue( "gl_finish", 1 );
1241 #endif
1242
1243 // MCD has buffering issues
1244 if ( gl_config.renderer == GL_RENDERER_MCD )
1245 {
1246 ri.Cvar_SetValue( "gl_finish", 1 );
1247 }
1248
1249 if ( gl_config.renderer & GL_RENDERER_3DLABS )
1250 {
1251 if ( gl_3dlabs_broken->value )
1252 gl_config.allow_cds = false;
1253 else
1254 gl_config.allow_cds = true;
1255 }
1256 else
1257 {
1258 gl_config.allow_cds = true;
1259 }
1260
1261 #ifdef _WIN32
1262 if ( gl_config.allow_cds )
1263 ri.Con_Printf( PRINT_ALL, "...allowing CDS\n" );
1264 else
1265 ri.Con_Printf( PRINT_ALL, "...disabling CDS\n" );
1266 #endif
1267 /*
1268 ** grab extensions
1269 */
1270 if ( strstr( gl_config.extensions_string, "GL_EXT_compiled_vertex_array" ) ||
1271 strstr( gl_config.extensions_string, "GL_SGI_compiled_vertex_array" ) )
1272 {
1273 ri.Con_Printf( PRINT_ALL, "...enabling GL_EXT_compiled_vertex_array\n" );
1274 qglLockArraysEXT = ( void * ) qwglGetProcAddress( "glLockArraysEXT" );
1275 qglUnlockArraysEXT = ( void * ) qwglGetProcAddress( "glUnlockArraysEXT" );
1276 }
1277 else
1278 {
1279 ri.Con_Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
1280 }
1281
1282 #ifdef _WIN32
1283 if ( strstr( gl_config.extensions_string, "WGL_EXT_swap_control" ) )
1284 {
1285 qwglSwapIntervalEXT = ( BOOL (WINAPI *)(int)) qwglGetProcAddress( "wglSwapIntervalEXT" );
1286 ri.Con_Printf( PRINT_ALL, "...enabling WGL_EXT_swap_control\n" );
1287 }
1288 else
1289 {
1290 ri.Con_Printf( PRINT_ALL, "...WGL_EXT_swap_control not found\n" );
1291 }
1292 #endif
1293
1294 if ( strstr( gl_config.extensions_string, "GL_EXT_point_parameters" ) )
1295 {
1296 if ( gl_ext_pointparameters->value )
1297 {
1298 qglPointParameterfEXT = ( void (APIENTRY *)( GLenum, GLfloat ) ) qwglGetProcAddress( "glPointParameterfEXT" );
1299 qglPointParameterfvEXT = ( void (APIENTRY *)( GLenum, const GLfloat * ) ) qwglGetProcAddress( "glPointParameterfvEXT" );
1300 ri.Con_Printf( PRINT_ALL, "...using GL_EXT_point_parameters\n" );
1301 }
1302 else
1303 {
1304 ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_point_parameters\n" );
1305 }
1306 }
1307 else
1308 {
1309 ri.Con_Printf( PRINT_ALL, "...GL_EXT_point_parameters not found\n" );
1310 }
1311
1312 #ifdef __linux__
1313 if ( strstr( gl_config.extensions_string, "3DFX_set_global_palette" ))
1314 {
1315 if ( gl_ext_palettedtexture->value )
1316 {
1317 ri.Con_Printf( PRINT_ALL, "...using 3DFX_set_global_palette\n" );
1318 qgl3DfxSetPaletteEXT = ( void ( APIENTRY * ) (GLuint *) )qwglGetProcAddress( "gl3DfxSetPaletteEXT" );
1319 qglColorTableEXT = Fake_glColorTableEXT;
1320 }
1321 else
1322 {
1323 ri.Con_Printf( PRINT_ALL, "...ignoring 3DFX_set_global_palette\n" );
1324 }
1325 }
1326 else
1327 {
1328 ri.Con_Printf( PRINT_ALL, "...3DFX_set_global_palette not found\n" );
1329 }
1330 #endif
1331
1332 if ( !qglColorTableEXT &&
1333 strstr( gl_config.extensions_string, "GL_EXT_paletted_texture" ) &&
1334 strstr( gl_config.extensions_string, "GL_EXT_shared_texture_palette" ) )
1335 {
1336 if ( gl_ext_palettedtexture->value )
1337 {
1338 ri.Con_Printf( PRINT_ALL, "...using GL_EXT_shared_texture_palette\n" );
1339 qglColorTableEXT = ( void ( APIENTRY * ) ( GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid * ) ) qwglGetProcAddress( "glColorTableEXT" );
1340 }
1341 else
1342 {
1343 ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_shared_texture_palette\n" );
1344 }
1345 }
1346 else
1347 {
1348 ri.Con_Printf( PRINT_ALL, "...GL_EXT_shared_texture_palette not found\n" );
1349 }
1350
1351 if ( strstr( gl_config.extensions_string, "GL_ARB_multitexture" ) )
1352 {
1353 if ( gl_ext_multitexture->value )
1354 {
1355 ri.Con_Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
1356 qglMTexCoord2fSGIS = ( void * ) qwglGetProcAddress( "glMultiTexCoord2fARB" );
1357 qglActiveTextureARB = ( void * ) qwglGetProcAddress( "glActiveTextureARB" );
1358 qglClientActiveTextureARB = ( void * ) qwglGetProcAddress( "glClientActiveTextureARB" );
1359 QGL_TEXTURE0 = GL_TEXTURE0_ARB;
1360 QGL_TEXTURE1 = GL_TEXTURE1_ARB;
1361 }
1362 else
1363 {
1364 ri.Con_Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
1365 }
1366 }
1367 else
1368 {
1369 ri.Con_Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
1370 }
1371
1372 if ( strstr( gl_config.extensions_string, "GL_SGIS_multitexture" ) )
1373 {
1374 if ( qglActiveTextureARB )
1375 {
1376 ri.Con_Printf( PRINT_ALL, "...GL_SGIS_multitexture deprecated in favor of ARB_multitexture\n" );
1377 }
1378 else if ( gl_ext_multitexture->value )
1379 {
1380 ri.Con_Printf( PRINT_ALL, "...using GL_SGIS_multitexture\n" );
1381 qglMTexCoord2fSGIS = ( void * ) qwglGetProcAddress( "glMTexCoord2fSGIS" );
1382 qglSelectTextureSGIS = ( void * ) qwglGetProcAddress( "glSelectTextureSGIS" );
1383 QGL_TEXTURE0 = GL_TEXTURE0_SGIS;
1384 QGL_TEXTURE1 = GL_TEXTURE1_SGIS;
1385 }
1386 else
1387 {
1388 ri.Con_Printf( PRINT_ALL, "...ignoring GL_SGIS_multitexture\n" );
1389 }
1390 }
1391 else
1392 {
1393 ri.Con_Printf( PRINT_ALL, "...GL_SGIS_multitexture not found\n" );
1394 }
1395
1396 GL_SetDefaultState();
1397
1398 /*
1399 ** draw our stereo patterns
1400 */
1401 #if 0 // commented out until H3D pays us the money they owe us
1402 GL_DrawStereoPattern();
1403 #endif
1404
1405 GL_InitImages ();
1406 Mod_Init ();
1407 R_InitParticleTexture ();
1408 Draw_InitLocal ();
1409
1410 err = qglGetError();
1411 if ( err != GL_NO_ERROR )
1412 ri.Con_Printf (PRINT_ALL, "glGetError() = 0x%x\n", err);
1413
1414 return true;
1415 }
1416
1417 /*
1418 ===============
1419 R_Shutdown
1420 ===============
1421 */
R_Shutdown(void)1422 void R_Shutdown (void)
1423 {
1424 ri.Cmd_RemoveCommand ("modellist");
1425 ri.Cmd_RemoveCommand ("screenshot");
1426 ri.Cmd_RemoveCommand ("imagelist");
1427 ri.Cmd_RemoveCommand ("gl_strings");
1428
1429 Mod_FreeAll ();
1430
1431 GL_ShutdownImages ();
1432
1433 /*
1434 ** shut down OS specific OpenGL stuff like contexts, etc.
1435 */
1436 GLimp_Shutdown();
1437
1438 /*
1439 ** shutdown our QGL subsystem
1440 */
1441 QGL_Shutdown();
1442 }
1443
1444
1445
1446 /*
1447 @@@@@@@@@@@@@@@@@@@@@
1448 R_BeginFrame
1449 @@@@@@@@@@@@@@@@@@@@@
1450 */
1451 extern void UpdateHardwareGamma();
1452
R_BeginFrame(float camera_separation)1453 void R_BeginFrame( float camera_separation )
1454 {
1455
1456 gl_state.camera_separation = camera_separation;
1457
1458 /*
1459 ** change modes if necessary
1460 */
1461 if ( gl_mode->modified || vid_fullscreen->modified )
1462 { // FIXME: only restart if CDS is required
1463 cvar_t *ref;
1464
1465 ref = ri.Cvar_Get ("vid_ref", "gl", 0);
1466 ref->modified = true;
1467 }
1468
1469 if ( gl_log->modified )
1470 {
1471 GLimp_EnableLogging( gl_log->value );
1472 gl_log->modified = false;
1473 }
1474
1475 if ( gl_log->value )
1476 {
1477 GLimp_LogNewFrame();
1478 }
1479
1480 /*
1481 ** update 3Dfx gamma -- it is expected that a user will do a vid_restart
1482 ** after tweaking this value
1483 */
1484 if ( vid_gamma->modified )
1485 {
1486 vid_gamma->modified = false;
1487
1488 if ( gl_state.hwgamma ) {
1489 UpdateHardwareGamma();
1490 } else if ( gl_config.renderer & ( GL_RENDERER_VOODOO ) )
1491 {
1492 char envbuffer[1024];
1493 float g;
1494
1495 g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F;
1496 Com_sprintf( envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g );
1497 putenv( envbuffer );
1498 Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g );
1499 putenv( envbuffer );
1500 }
1501 }
1502
1503 GLimp_BeginFrame( camera_separation );
1504
1505 /*
1506 ** go into 2D mode
1507 */
1508 qglViewport (0,0, vid.width, vid.height);
1509 qglMatrixMode(GL_PROJECTION);
1510 qglLoadIdentity ();
1511 qglOrtho (0, vid.width, vid.height, 0, -99999, 99999);
1512 qglMatrixMode(GL_MODELVIEW);
1513 qglLoadIdentity ();
1514 qglDisable (GL_DEPTH_TEST);
1515 qglDisable (GL_CULL_FACE);
1516 qglDisable (GL_BLEND);
1517 qglEnable (GL_ALPHA_TEST);
1518 qglColor4f (1,1,1,1);
1519
1520 /*
1521 ** draw buffer stuff
1522 */
1523 if ( gl_drawbuffer->modified )
1524 {
1525 gl_drawbuffer->modified = false;
1526
1527 if ( gl_state.camera_separation == 0 || !gl_state.stereo_enabled )
1528 {
1529 if ( Q_stricmp( gl_drawbuffer->string, "GL_FRONT" ) == 0 )
1530 qglDrawBuffer( GL_FRONT );
1531 else
1532 qglDrawBuffer( GL_BACK );
1533 }
1534 }
1535
1536 /*
1537 ** texturemode stuff
1538 */
1539 if ( gl_texturemode->modified )
1540 {
1541 GL_TextureMode( gl_texturemode->string );
1542 gl_texturemode->modified = false;
1543 }
1544
1545 if ( gl_texturealphamode->modified )
1546 {
1547 GL_TextureAlphaMode( gl_texturealphamode->string );
1548 gl_texturealphamode->modified = false;
1549 }
1550
1551 if ( gl_texturesolidmode->modified )
1552 {
1553 GL_TextureSolidMode( gl_texturesolidmode->string );
1554 gl_texturesolidmode->modified = false;
1555 }
1556
1557 /*
1558 ** swapinterval stuff
1559 */
1560 GL_UpdateSwapInterval();
1561
1562 //
1563 // clear screen if desired
1564 //
1565 R_Clear ();
1566 }
1567
1568 /*
1569 =============
1570 R_SetPalette
1571 =============
1572 */
1573 unsigned r_rawpalette[256];
1574
R_SetPalette(const unsigned char * palette)1575 void R_SetPalette ( const unsigned char *palette)
1576 {
1577 int i;
1578
1579 byte *rp = ( byte * ) r_rawpalette;
1580
1581 if ( palette )
1582 {
1583 for ( i = 0; i < 256; i++ )
1584 {
1585 rp[i*4+0] = palette[i*3+0];
1586 rp[i*4+1] = palette[i*3+1];
1587 rp[i*4+2] = palette[i*3+2];
1588 rp[i*4+3] = 0xff;
1589 }
1590 }
1591 else
1592 {
1593 for ( i = 0; i < 256; i++ )
1594 {
1595 rp[i*4+0] = LittleLong(d_8to24table[i]) & 0xff;
1596 rp[i*4+1] = ( LittleLong(d_8to24table[i]) >> 8 ) & 0xff;
1597 rp[i*4+2] = ( LittleLong(d_8to24table[i]) >> 16 ) & 0xff;
1598 rp[i*4+3] = 0xff;
1599 }
1600 }
1601 GL_SetTexturePalette( r_rawpalette );
1602
1603 qglClearColor (0,0,0,0);
1604 qglClear (GL_COLOR_BUFFER_BIT);
1605 qglClearColor (1,0, 0.5 , 0.5);
1606 }
1607
1608 /*
1609 ** R_DrawBeam
1610 */
R_DrawBeam(entity_t * e)1611 void R_DrawBeam( entity_t *e )
1612 {
1613 #define NUM_BEAM_SEGS 6
1614
1615 int i;
1616 float r, g, b;
1617
1618 vec3_t perpvec;
1619 vec3_t direction, normalized_direction;
1620 vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
1621 vec3_t oldorigin, origin;
1622
1623 oldorigin[0] = e->oldorigin[0];
1624 oldorigin[1] = e->oldorigin[1];
1625 oldorigin[2] = e->oldorigin[2];
1626
1627 origin[0] = e->origin[0];
1628 origin[1] = e->origin[1];
1629 origin[2] = e->origin[2];
1630
1631 normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
1632 normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
1633 normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
1634
1635 if ( VectorNormalize( normalized_direction ) == 0 )
1636 return;
1637
1638 PerpendicularVector( perpvec, normalized_direction );
1639 VectorScale( perpvec, e->frame / 2, perpvec );
1640
1641 for ( i = 0; i < 6; i++ )
1642 {
1643 RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i );
1644 VectorAdd( start_points[i], origin, start_points[i] );
1645 VectorAdd( start_points[i], direction, end_points[i] );
1646 }
1647
1648 qglDisable( GL_TEXTURE_2D );
1649 qglEnable( GL_BLEND );
1650 qglDepthMask( GL_FALSE );
1651
1652 r = ( LittleLong(d_8to24table[e->skinnum & 0xFF]) ) & 0xFF;
1653 g = ( LittleLong(d_8to24table[e->skinnum & 0xFF]) >> 8 ) & 0xFF;
1654 b = ( LittleLong(d_8to24table[e->skinnum & 0xFF]) >> 16 ) & 0xFF;
1655
1656 r *= 1/255.0F;
1657 g *= 1/255.0F;
1658 b *= 1/255.0F;
1659
1660 qglColor4f( r, g, b, e->alpha );
1661
1662 qglBegin( GL_TRIANGLE_STRIP );
1663 for ( i = 0; i < NUM_BEAM_SEGS; i++ )
1664 {
1665 qglVertex3fv( start_points[i] );
1666 qglVertex3fv( end_points[i] );
1667 qglVertex3fv( start_points[(i+1)%NUM_BEAM_SEGS] );
1668 qglVertex3fv( end_points[(i+1)%NUM_BEAM_SEGS] );
1669 }
1670 qglEnd();
1671
1672 qglEnable( GL_TEXTURE_2D );
1673 qglDisable( GL_BLEND );
1674 qglDepthMask( GL_TRUE );
1675 }
1676
1677 //===================================================================
1678
1679
1680 void R_BeginRegistration (char *map);
1681 struct model_s *R_RegisterModel (char *name);
1682 struct image_s *R_RegisterSkin (char *name);
1683 void R_SetSky (char *name, float rotate, vec3_t axis);
1684 void R_EndRegistration (void);
1685
1686 void R_RenderFrame (refdef_t *fd);
1687
1688 struct image_s *Draw_FindPic (char *name);
1689
1690 void Draw_Pic (int x, int y, char *name);
1691 void Draw_Char (int x, int y, int c);
1692 void Draw_TileClear (int x, int y, int w, int h, char *name);
1693 void Draw_Fill (int x, int y, int w, int h, int c);
1694 void Draw_FadeScreen (void);
1695
1696 /*
1697 @@@@@@@@@@@@@@@@@@@@@
1698 GetRefAPI
1699
1700 @@@@@@@@@@@@@@@@@@@@@
1701 */
GetRefAPI(refimport_t rimp)1702 refexport_t GetRefAPI (refimport_t rimp )
1703 {
1704 refexport_t re;
1705
1706 ri = rimp;
1707
1708 re.api_version = API_VERSION;
1709
1710 re.BeginRegistration = R_BeginRegistration;
1711 re.RegisterModel = R_RegisterModel;
1712 re.RegisterSkin = R_RegisterSkin;
1713 re.RegisterPic = Draw_FindPic;
1714 re.SetSky = R_SetSky;
1715 re.EndRegistration = R_EndRegistration;
1716
1717 re.RenderFrame = R_RenderFrame;
1718
1719 re.DrawGetPicSize = Draw_GetPicSize;
1720 re.DrawPic = Draw_Pic;
1721 re.DrawStretchPic = Draw_StretchPic;
1722 re.DrawChar = Draw_Char;
1723 re.DrawTileClear = Draw_TileClear;
1724 re.DrawFill = Draw_Fill;
1725 re.DrawFadeScreen= Draw_FadeScreen;
1726
1727 re.DrawStretchRaw = Draw_StretchRaw;
1728
1729 re.Init = R_Init;
1730 re.Shutdown = R_Shutdown;
1731
1732 re.CinematicSetPalette = R_SetPalette;
1733 re.BeginFrame = R_BeginFrame;
1734 re.EndFrame = GLimp_EndFrame;
1735
1736 re.AppActivate = GLimp_AppActivate;
1737
1738 Swap_Init ();
1739
1740 return re;
1741 }
1742
1743
1744 #ifndef REF_HARD_LINKED
1745 // this is only here so the functions in q_shared.c and q_shwin.c can link
Sys_Error(char * error,...)1746 void Sys_Error (char *error, ...)
1747 {
1748 va_list argptr;
1749 char text[1024];
1750
1751 va_start (argptr, error);
1752 vsprintf (text, error, argptr);
1753 va_end (argptr);
1754
1755 ri.Sys_Error (ERR_FATAL, "%s", text);
1756 }
1757
Com_Printf(char * fmt,...)1758 void Com_Printf (char *fmt, ...)
1759 {
1760 va_list argptr;
1761 char text[1024];
1762
1763 va_start (argptr, fmt);
1764 vsprintf (text, fmt, argptr);
1765 va_end (argptr);
1766
1767 ri.Con_Printf (PRINT_ALL, "%s", text);
1768 }
1769
1770 #endif
1771