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