1 /*
2 * Copyright(c) 1997-2001 Id Software, Inc.
3 * Copyright(c) 2002 The Quakeforge Project.
4 * Copyright(c) 2006 Quetoo.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or(at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 *
15 * See the GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include <ctype.h>
23
24 #include "client.h"
25
26 viddef_t viddef;
27
28 int QGL_TEXTURE0, QGL_TEXTURE1;
29
30 model_t *r_worldmodel;
31
32 float gldepthmin, gldepthmax;
33
34 glconfig_t gl_config;
35 glstate_t gl_state;
36
37 image_t *r_notexture; // use for bad textures
38 image_t *r_particletexture; // little dot for particles
39
40 entity_t *currententity;
41 model_t *currentmodel;
42
43 cplane_t frustum[4];
44
45 int r_visframecount; // bumped when going to a new PVS
46
47 int c_brush_polys, c_alias_polys;
48
49 byte color_white[4] = {255, 255, 255, 255};
50 byte color_black[4] = {0, 0, 0, 128};
51
52 // view origin
53 vec3_t vup;
54 vec3_t vpn;
55 vec3_t vright;
56 vec3_t r_origin;
57
58 float r_world_matrix[16];
59 float r_base_world_matrix[16];
60
61 // screen size info
62 viewdef_t r_viewdef;
63
64 int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
65
66 cvar_t *r_drawentities;
67 cvar_t *r_speeds;
68 cvar_t *r_fullbright;
69 cvar_t *r_novis;
70 cvar_t *r_nocull;
71 cvar_t *r_lerpmodels;
72
73 cvar_t *gl_vertex_arrays;
74 cvar_t *gl_ext_multitexture;
75 cvar_t *gl_ext_compiled_vertex_array;
76
77 cvar_t *gl_log;
78 cvar_t *gl_drawbuffer;
79 cvar_t *gl_driver;
80 cvar_t *gl_lightmap;
81 cvar_t *gl_monolightmap;
82 cvar_t *gl_loadtga;
83 cvar_t *gl_modulate;
84 cvar_t *gl_intensity;
85 cvar_t *gl_rounddown;
86 cvar_t *gl_picmip;
87 cvar_t *gl_skymip;
88 cvar_t *gl_playermip;
89 cvar_t *gl_wireframe;
90 cvar_t *gl_ztrick;
91 cvar_t *gl_finish;
92 cvar_t *gl_clear;
93 cvar_t *gl_cull;
94 cvar_t *gl_texturemode;
95 cvar_t *gl_texturealphamode;
96 cvar_t *gl_texturesolidmode;
97 cvar_t *gl_lockpvs;
98
99 cvar_t *vid_width;
100 cvar_t *vid_height;
101 cvar_t *vid_fullscreen;
102 cvar_t *vid_gamma;
103
104 cvar_t *skydistance;
105
106 /*
107 GL_CullBox
108
109 Returns true if the box is completely outside the frustum
110 */
GL_CullBox(vec3_t mins,vec3_t maxs)111 qboolean GL_CullBox(vec3_t mins, vec3_t maxs){
112 int i;
113
114 if(r_nocull->value)
115 return false;
116
117 for(i = 0; i < 4; i++)
118 if(BOX_ON_PLANE_SIDE(mins, maxs, &frustum[i]) == 2)
119 return true;
120 return false;
121 }
122
123
GL_RotateForEntity(entity_t * e)124 void GL_RotateForEntity(entity_t *e){
125 qglTranslatef(e->origin[0], e->origin[1], e->origin[2]);
126
127 qglRotatef(e->angles[1], 0, 0, 1);
128 qglRotatef(-e->angles[0], 0, 1, 0);
129 qglRotatef(-e->angles[2], 1, 0, 0);
130 }
131
132 /*
133
134 SPRITE MODELS
135
136 */
137
138
139 /*
140 GL_DrawSpriteModel
141
142 */
GL_DrawSpriteModel(entity_t * e)143 void GL_DrawSpriteModel(entity_t *e){
144 float alpha = 1.0F;
145 vec3_t point;
146 dsprframe_t *frame;
147 float *up, *right;
148 dsprite_t *psprite;
149
150 // don't even bother culling, because it's just a single
151 // polygon without a surface cache
152
153 psprite = (dsprite_t *)currentmodel->extradata;
154
155 e->frame %= psprite->numframes;
156
157 frame = &psprite->frames[e->frame];
158
159 up = vup;
160 right = vright;
161
162 if(e->flags & RF_TRANSLUCENT)
163 alpha = e->alpha;
164
165 if(alpha != 1.0F){
166 qglEnable(GL_BLEND);
167 color_white[3] = alpha * 255;
168 }
169 qglColor4ubv(color_white);
170
171 GL_Bind(currentmodel->skins[e->frame]->texnum);
172
173 GL_TexEnv(GL_MODULATE);
174
175 if(alpha == 1.0)
176 qglEnable(GL_ALPHA_TEST);
177 else
178 qglDisable(GL_ALPHA_TEST);
179
180 qglBegin(GL_QUADS);
181
182 qglTexCoord2f(0, 1);
183 VectorMA(e->origin, -frame->origin_y, up, point);
184 VectorMA(point, -frame->origin_x, right, point);
185 qglVertex3fv(point);
186
187 qglTexCoord2f(0, 0);
188 VectorMA(e->origin, frame->height - frame->origin_y, up, point);
189 VectorMA(point, -frame->origin_x, right, point);
190 qglVertex3fv(point);
191
192 qglTexCoord2f(1, 0);
193 VectorMA(e->origin, frame->height - frame->origin_y, up, point);
194 VectorMA(point, frame->width - frame->origin_x, right, point);
195 qglVertex3fv(point);
196
197 qglTexCoord2f(1, 1);
198 VectorMA(e->origin, -frame->origin_y, up, point);
199 VectorMA(point, frame->width - frame->origin_x, right, point);
200 qglVertex3fv(point);
201
202 qglEnd();
203
204 qglDisable(GL_ALPHA_TEST);
205 GL_TexEnv(GL_REPLACE);
206
207 if(alpha != 1.0F){
208 qglDisable(GL_BLEND);
209 color_white[3] = 255;
210 }
211 qglColor4ubv(color_white);
212 }
213
214
215 /*
216 GL_DrawNullModel
217 */
GL_DrawNullModel(void)218 void GL_DrawNullModel(void){
219 vec3_t shadelight;
220 int i;
221
222 if(currententity->flags & RF_FULLBRIGHT)
223 shadelight[0] = shadelight[1] = shadelight[2] = 1.0F;
224 else
225 GL_LightPoint(currententity->origin, shadelight);
226
227 qglPushMatrix();
228 GL_RotateForEntity(currententity);
229
230 qglDisable(GL_TEXTURE_2D);
231 qglColor3fv(shadelight);
232
233 qglBegin(GL_TRIANGLE_FAN);
234 qglVertex3f(0, 0, -16);
235 for(i = 0; i <= 4; i++)
236 qglVertex3f(16*cos(i*M_PI / 2), 16*sin(i*M_PI / 2), 0);
237 qglEnd();
238
239 qglBegin(GL_TRIANGLE_FAN);
240 qglVertex3f(0, 0, 16);
241 for(i = 4; i >= 0; i--)
242 qglVertex3f(16*cos(i*M_PI / 2), 16*sin(i*M_PI / 2), 0);
243 qglEnd();
244
245 qglColor3ubv(color_white);
246 qglPopMatrix();
247 qglEnable(GL_TEXTURE_2D);
248 }
249
250
251 /*
252 GL_DrawBeam
253 */
GL_DrawBeam(entity_t * e)254 void GL_DrawBeam(entity_t *e){
255 #define NUM_BEAM_SEGS 6
256 int i;
257 float r, g, b;
258
259 vec3_t perpvec;
260 vec3_t direction, normalized_direction;
261 vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
262 vec3_t oldorigin, origin;
263
264 oldorigin[0] = e->oldorigin[0];
265 oldorigin[1] = e->oldorigin[1];
266 oldorigin[2] = e->oldorigin[2];
267
268 origin[0] = e->origin[0];
269 origin[1] = e->origin[1];
270 origin[2] = e->origin[2];
271
272 normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
273 normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
274 normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
275
276 if(VectorNormalize(normalized_direction) == 0)
277 return;
278
279 PerpendicularVector(perpvec, normalized_direction);
280 VectorScale(perpvec, e->frame / 2, perpvec);
281
282 for(i = 0; i < 6; i++){
283 RotatePointAroundVector(start_points[i], normalized_direction, perpvec,(360.0 / NUM_BEAM_SEGS)*i);
284 VectorAdd(start_points[i], origin, start_points[i]);
285 VectorAdd(start_points[i], direction, end_points[i]);
286 }
287
288 qglDisable(GL_TEXTURE_2D);
289 qglEnable(GL_BLEND);
290 qglDepthMask(GL_FALSE);
291
292 r = (d_8to24table[e->skinnum & 0xFF]) & 0xFF;
293 g = (d_8to24table[e->skinnum & 0xFF] >> 8) & 0xFF;
294 b = (d_8to24table[e->skinnum & 0xFF] >> 16) & 0xFF;
295
296 r *= 1 / 255.0F;
297 g *= 1 / 255.0F;
298 b *= 1 / 255.0F;
299
300 qglColor4f(r, g, b, e->alpha);
301
302 qglBegin(GL_TRIANGLE_STRIP);
303 for(i = 0; i < NUM_BEAM_SEGS; i++){
304 qglVertex3fv(start_points[i]);
305 qglVertex3fv(end_points[i]);
306 qglVertex3fv(start_points[(i + 1) % NUM_BEAM_SEGS]);
307 qglVertex3fv(end_points[(i + 1) % NUM_BEAM_SEGS]);
308 }
309 qglEnd();
310
311 qglEnable(GL_TEXTURE_2D);
312 qglDisable(GL_BLEND);
313 qglDepthMask(GL_TRUE);
314 }
315
316
317 /*
318 GL_DrawEntitiesOnList
319 */
GL_DrawEntitiesOnList(void)320 void GL_DrawEntitiesOnList(void){
321 int i;
322
323 if(!r_drawentities->value)
324 return;
325
326 // draw non-transparent first
327 for(i = 0; i < r_viewdef.num_entities; i++){
328 currententity = &r_viewdef.entities[i];
329 if(currententity->flags & RF_TRANSLUCENT)
330 continue; // solid
331
332 if(currententity->flags & RF_BEAM){
333 GL_DrawBeam(currententity);
334 } else {
335 currentmodel = currententity->model;
336 if(!currentmodel){
337 GL_DrawNullModel();
338 continue;
339 }
340 switch(currentmodel->type){
341 case mod_alias:
342 GL_DrawAliasModel(currententity);
343 break;
344 case mod_brush:
345 GL_DrawBrushModel(currententity);
346 break;
347 case mod_sprite:
348 GL_DrawSpriteModel(currententity);
349 break;
350 default:
351 Com_Error(ERR_DROP, "Bad modeltype");
352 break;
353 }
354 }
355 }
356
357 // draw transparent entities
358 // we could sort these if it ever becomes a problem...
359 qglDepthMask(0); // no z writes
360 for(i = 0; i < r_viewdef.num_entities; i++){
361 currententity = &r_viewdef.entities[i];
362 if(!(currententity->flags & RF_TRANSLUCENT))
363 continue; // solid
364
365 if(currententity->flags & RF_BEAM){
366 GL_DrawBeam(currententity);
367 } else {
368 currentmodel = currententity->model;
369
370 if(!currentmodel){
371 GL_DrawNullModel();
372 continue;
373 }
374 switch(currentmodel->type){
375 case mod_alias:
376 GL_DrawAliasModel(currententity);
377 break;
378 case mod_brush:
379 GL_DrawBrushModel(currententity);
380 break;
381 case mod_sprite:
382 GL_DrawSpriteModel(currententity);
383 break;
384 default:
385 Com_Error(ERR_DROP, "Bad modeltype");
386 break;
387 }
388 }
389 }
390 qglDepthMask(1); // back to writing
391
392 }
393
394 /*
395 GL_DrawParticles
396 */
GL_DrawParticles(void)397 void GL_DrawParticles(void){
398 const particle_t *p;
399 int i;
400 vec3_t up, right, up_right_scale, down_right_scale, VA[4];
401 float scale;
402 byte color[4];
403
404 GL_Bind(r_particletexture->texnum);
405 qglDepthMask(GL_FALSE); // no z buffering
406 qglEnable(GL_BLEND);
407 GL_TexEnv(GL_MODULATE);
408 qglBegin(GL_QUADS);
409
410 for(p = r_viewdef.particles, i = 0; i < r_viewdef.num_particles; i++, p++){
411 // hack a scale up to keep particles from disapearing
412 scale = (p->origin[0] - r_origin[0]) * vpn[0] +
413 (p->origin[1] - r_origin[1]) * vpn[1] +
414 (p->origin[2] - r_origin[2]) * vpn[2];
415
416 scale *= 0.002;
417
418 VectorScale(vup, scale, up);
419 VectorScale(vright, scale, right);
420 VectorAdd(up, right, up_right_scale);
421 VectorSubtract(right, up, down_right_scale);
422 VectorSubtract(p->origin, down_right_scale, VA[0]);
423 VectorAdd(p->origin, up_right_scale, VA[1]);
424 VectorAdd(p->origin, down_right_scale, VA[2]);
425 VectorSubtract(p->origin, up_right_scale, VA[3]);
426
427 *(int *)color = d_8to24table[p->color];
428 color[3] = p->alpha * 255;
429 qglColor4ubv(color);
430
431 qglTexCoord2f(0.0, 0.0);
432 qglVertex3fv(VA[0]);
433
434 qglTexCoord2f(1.0, 0.0);
435 qglVertex3fv(VA[1]);
436
437 qglTexCoord2f(1.0, 1.0);
438 qglVertex3fv(VA[2]);
439
440 qglTexCoord2f(0.0, 1.0);
441 qglVertex3fv(VA[3]);
442 }
443
444 qglEnd();
445 qglDisable(GL_BLEND);
446 qglColor4ubv(color_white);
447 qglDepthMask(GL_TRUE); // back to normal Z buffering
448 GL_TexEnv(GL_REPLACE);
449 }
450
451
SignbitsForPlane(cplane_t * out)452 int SignbitsForPlane(cplane_t *out){
453 int bits, j;
454
455 // for fast box on planeside test
456
457 bits = 0;
458 for(j = 0; j < 3; j++){
459 if(out->normal[j] < 0)
460 bits |= 1 << j;
461 }
462 return bits;
463 }
464
465
GL_SetFrustum(void)466 void GL_SetFrustum(void){
467 int i;
468
469 // rotate VPN right by FOV_X/2 degrees
470 RotatePointAroundVector(frustum[0].normal, vup, vpn, -(90 - r_viewdef.fov_x / 2));
471 // rotate VPN left by FOV_X/2 degrees
472 RotatePointAroundVector(frustum[1].normal, vup, vpn, 90 - r_viewdef.fov_x / 2);
473 // rotate VPN up by FOV_X/2 degrees
474 RotatePointAroundVector(frustum[2].normal, vright, vpn, 90 - r_viewdef.fov_y / 2);
475 // rotate VPN down by FOV_X/2 degrees
476 RotatePointAroundVector(frustum[3].normal, vright, vpn, -(90 - r_viewdef.fov_y / 2));
477
478 for(i = 0; i < 4; i++){
479 frustum[i].type = PLANE_ANYZ;
480 frustum[i].dist = DotProduct(r_origin, frustum[i].normal);
481 frustum[i].signbits = SignbitsForPlane(&frustum[i]);
482 }
483 }
484
485
486 /*
487 GL_SetupFrame
488 */
GL_SetupFrame(void)489 void GL_SetupFrame(void){
490 mleaf_t *leaf;
491
492 // build the transformation matrix for the given view angles
493 VectorCopy(r_viewdef.vieworg, r_origin);
494
495 AngleVectors(r_viewdef.viewangles, vpn, vright, vup);
496
497 // current viewcluster
498 if(!(r_viewdef.rdflags & RDF_NOWORLDMODEL)){
499 r_oldviewcluster = r_viewcluster;
500 r_oldviewcluster2 = r_viewcluster2;
501 leaf = Mod_PointInLeaf(r_origin, r_worldmodel);
502 r_viewcluster = r_viewcluster2 = leaf->cluster;
503
504 // check above and below so crossing solid water doesn't draw wrong
505 if(!leaf->contents){ // look down a bit
506 vec3_t temp;
507
508 VectorCopy(r_origin, temp);
509 temp[2] -= 16;
510 leaf = Mod_PointInLeaf(temp, r_worldmodel);
511 if(!(leaf->contents & CONTENTS_SOLID) &&
512 (leaf->cluster != r_viewcluster2))
513 r_viewcluster2 = leaf->cluster;
514 } else { // look up a bit
515 vec3_t temp;
516
517 VectorCopy(r_origin, temp);
518 temp[2] += 16;
519 leaf = Mod_PointInLeaf(temp, r_worldmodel);
520 if(!(leaf->contents & CONTENTS_SOLID) &&
521 (leaf->cluster != r_viewcluster2))
522 r_viewcluster2 = leaf->cluster;
523 }
524 }
525
526 c_brush_polys = 0;
527 c_alias_polys = 0;
528 }
529
530
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)531 void MYgluPerspective(GLdouble fovy, GLdouble aspect,
532 GLdouble zNear, GLdouble zFar){
533 GLdouble xmin, xmax, ymin, ymax;
534
535 ymax = zNear * tan(fovy * M_PI / 360.0);
536 ymin = -ymax;
537
538 xmin = ymin * aspect;
539 xmax = ymax * aspect;
540
541 qglFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
542 }
543
544
545 /*
546 GL_SetupGL
547 */
GL_SetupGL(void)548 void GL_SetupGL(void){
549 float screenaspect;
550 int x, x2, y2, y, w, h;
551 /* skybox vars */
552 static GLdouble farz;
553 GLdouble boxsize;
554
555 // set up viewport
556 x = floor(r_viewdef.x * viddef.width / viddef.width);
557 x2 = ceil((r_viewdef.x + r_viewdef.width) * viddef.width / viddef.width);
558 y = floor(viddef.height - r_viewdef.y * viddef.height / viddef.height);
559 y2 = ceil(viddef.height -(r_viewdef.y + r_viewdef.height) * viddef.height / viddef.height);
560
561 w = x2 - x;
562 h = y - y2;
563
564 qglViewport(x, y2, w, h);
565
566 // block of code for SkyBox Size change
567 if(skydistance->modified){
568 skydistance->modified = false;
569 boxsize = skydistance->value;
570 boxsize -= 252 * ceil(boxsize / 2300);
571 farz = 1.0;
572 while(farz < boxsize){ // make this value a power-of-2
573 farz *= 2.0;
574 if(farz >= 65536.0) // don't make it larger than this
575 break;
576 }
577 // double since boxsize is distance from camera to
578 // edge of skybox - not total size of skybox
579 farz *= 2.0;
580 Com_DPrintf("farz now set to %g\n", farz);
581 }
582
583 // set up projection matrix
584 screenaspect = (float)r_viewdef.width / r_viewdef.height;
585 qglMatrixMode(GL_PROJECTION);
586 qglLoadIdentity();
587 MYgluPerspective(r_viewdef.fov_y, screenaspect, 4, farz);
588
589 qglCullFace(GL_FRONT);
590
591 qglMatrixMode(GL_MODELVIEW);
592 qglLoadIdentity();
593
594 qglRotatef(-90, 1, 0, 0); // put Z going up
595 qglRotatef(90, 0, 0, 1); // put Z going up
596 qglRotatef(-r_viewdef.viewangles[2], 1, 0, 0);
597 qglRotatef(-r_viewdef.viewangles[0], 0, 1, 0);
598 qglRotatef(-r_viewdef.viewangles[1], 0, 0, 1);
599 qglTranslatef(-r_viewdef.vieworg[0], -r_viewdef.vieworg[1], -r_viewdef.vieworg[2]);
600
601 qglGetFloatv(GL_MODELVIEW_MATRIX, r_world_matrix);
602
603 // set drawing parms
604 if(gl_cull->value)
605 qglEnable(GL_CULL_FACE);
606 else
607 qglDisable(GL_CULL_FACE);
608
609 qglDisable(GL_BLEND);
610 qglDisable(GL_ALPHA_TEST);
611 qglEnable(GL_DEPTH_TEST);
612 }
613
614
615 /*
616 GL_Clear
617 */
GL_Clear(void)618 void GL_Clear(void){
619 if(gl_ztrick->value && cls.state == ca_active){
620 static int trickframe;
621
622 if(gl_clear->value)
623 qglClear(GL_COLOR_BUFFER_BIT);
624
625 trickframe++;
626 if(trickframe & 1){
627 gldepthmin = 0;
628 gldepthmax = 0.49999;
629 qglDepthFunc(GL_LEQUAL);
630 } else {
631 gldepthmin = 1;
632 gldepthmax = 0.5;
633 qglDepthFunc(GL_GEQUAL);
634 }
635 } else {
636 if(gl_clear->value)
637 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
638 else
639 qglClear(GL_DEPTH_BUFFER_BIT);
640 gldepthmin = 0;
641 gldepthmax = 1;
642 qglDepthFunc(GL_LEQUAL);
643 }
644
645 qglDepthRange(gldepthmin, gldepthmax);
646 }
647
648
649 /*
650 GL_RenderFrame
651
652 r_viewdef must be set before the first call
653 */
GL_RenderFrame(viewdef_t * fd)654 void GL_RenderFrame(viewdef_t *fd){
655
656 if(cls.state != ca_active)
657 return;
658
659 if(!cl.view_prepped)
660 return; // still loading
661
662 r_viewdef = *fd;
663
664 if(!r_worldmodel && !(r_viewdef.rdflags & RDF_NOWORLDMODEL))
665 Com_Error(ERR_DROP, "GL_RenderView: NULL worldmodel");
666
667 if(r_speeds->value){
668 c_brush_polys = 0;
669 c_alias_polys = 0;
670 }
671
672 if(gl_finish->value)
673 qglFinish();
674
675 GL_SetupFrame();
676
677 GL_SetFrustum();
678
679 GL_SetupGL();
680
681 GL_MarkLeafs(); // done here so we know if we're in water
682
683 if(gl_wireframe->value){
684 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
685 qglClear(GL_COLOR_BUFFER_BIT);
686 }
687
688 GL_DrawWorld();
689
690 if(gl_wireframe->value)
691 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
692
693 GL_DrawEntitiesOnList();
694
695 GL_DrawParticles();
696
697 GL_DrawAlphaSurfaces();
698
699 if(r_speeds->value){
700 Com_Printf( "%4i wpoly %4i epoly %i tex %i lmaps\n",
701 c_brush_polys, c_alias_polys, c_visible_textures, c_visible_lightmaps);
702 }
703 }
704
705
706 /*
707 GL_SetGL2D
708 */
GL_SetGL2D(void)709 void GL_SetGL2D(void){
710 qglViewport(0, 0, viddef.width, viddef.height);
711 qglMatrixMode(GL_PROJECTION);
712 qglLoadIdentity();
713 qglOrtho(0, viddef.width, viddef.height, 0, -99999, 99999);
714 qglMatrixMode(GL_MODELVIEW);
715 qglLoadIdentity();
716 qglDisable(GL_DEPTH_TEST);
717 qglDisable(GL_CULL_FACE);
718 qglDisable(GL_BLEND);
719 qglEnable(GL_ALPHA_TEST);
720 qglEnable(GL_TEXTURE_2D);
721 qglColor4f(1, 1, 1, 1);
722 }
723
724
725 /*
726 GL_SetMode
727 */
GL_SetMode(void)728 qboolean GL_SetMode(void){
729
730 if(GL_InitGraphics(vid_width->value, vid_height->value, vid_fullscreen->value)){
731
732 viddef.width = (int)vid_width->value;
733 viddef.height = (int)vid_height->value;
734
735 gl_state.prev_width = vid_width->value;
736 gl_state.prev_height = vid_height->value;
737
738 return true;
739 }
740
741 Cvar_SetValue("vid_width", gl_state.prev_width); //failed, revert
742 Cvar_SetValue("vid_height", gl_state.prev_height);
743
744 GL_InitGraphics(gl_state.prev_width, gl_state.prev_height, false);
745
746 return false;
747 }
748
strlwr(char * s)749 char *strlwr(char *s){
750 char *p = s;
751 while(*s){
752 *s = tolower(*s);
753 s++;
754 }
755 return p;
756 }
757
758 /*
759 GL_Init
760 */
GL_Init(void)761 void GL_Init(void){
762 char renderer_buffer[MAX_STRING_CHARS];
763 char vendor_buffer[MAX_STRING_CHARS];
764 int j, err;
765
766 extern float r_turbsin[256];
767 for(j = 0; j < 256; j++){
768 r_turbsin[j] *= 0.5;
769 }
770
771 Com_Printf("Video initialization..\n");
772 GL_Register();
773
774 // initialize our QGL dynamic bindings
775 if(!QGL_Init(gl_driver->string)){
776 Com_Printf("Failed to load GL driver %s.\n", gl_driver->string);
777 QGL_Shutdown();
778 return;
779 }
780
781 gl_state.prev_width = 640;
782 gl_state.prev_height = 480;
783
784 // create the window and set up the context
785 if(!GL_SetMode()){
786 Com_Printf("Failed to set video mode.\n");
787 QGL_Shutdown();
788 return;
789 }
790
791 gl_config.renderer_string = (char *)qglGetString(GL_RENDERER);
792 gl_config.vendor_string = (char *)qglGetString(GL_VENDOR);
793 gl_config.version_string = (char *)qglGetString(GL_VERSION);
794 gl_config.extensions_string = (char *)qglGetString(GL_EXTENSIONS);
795
796 strncpy(renderer_buffer, gl_config.renderer_string, sizeof(renderer_buffer));
797 strncpy(vendor_buffer, gl_config.vendor_string, sizeof(vendor_buffer));
798
799 strlwr(renderer_buffer);
800 strlwr(vendor_buffer);
801
802 // enable available extensions
803 if(strstr(gl_config.extensions_string, "GL_EXT_compiled_vertex_array") ||
804 strstr(gl_config.extensions_string, "GL_SGI_compiled_vertex_array")){
805 qglLockArraysEXT = (void(APIENTRY*)(int, int)) qwglGetProcAddress("glLockArraysEXT");
806 qglUnlockArraysEXT = (void(APIENTRY*)(void)) qwglGetProcAddress("glUnlockArraysEXT");
807 Com_Printf(" GL_EXT_compiled_vertex_array\n");
808 }
809
810 if(strstr(gl_config.extensions_string, "GL_ARB_multitexture") && gl_ext_multitexture->value){
811 qglMultiTexCoord2fARB = (void(APIENTRY*)(GLenum, GLfloat, GLfloat)) qwglGetProcAddress("glMultiTexCoord2fARB");
812 qglActiveTextureARB = (void(APIENTRY*)(GLenum)) qwglGetProcAddress("glActiveTextureARB");
813 qglClientActiveTextureARB = (void(APIENTRY*)(GLenum)) qwglGetProcAddress("glClientActiveTextureARB");
814 QGL_TEXTURE0 = GL_TEXTURE0_ARB;
815 QGL_TEXTURE1 = GL_TEXTURE1_ARB;
816 Com_Printf(" GL_ARB_multitexture\n");
817 }
818
819 GL_SetDefaultState();
820
821 GL_InitImages();
822
823 Mod_Init();
824 GL_InitParticleTexture();
825 GL_InitNoTexture();
826 Draw_InitLocal();
827
828 err = qglGetError();
829 if(err != GL_NO_ERROR)
830 Com_Printf( "glGetError() = 0x%x\n", err);
831
832 Com_Printf("Video initialized %dx%d %s.\n", viddef.width, viddef.height,
833 (vid_fullscreen->value ? "fullscreen" : "windowed"));
834 }
835
836 /*
837 GL_Shutdown
838 */
GL_Shutdown(void)839 void GL_Shutdown(void){
840 Cmd_RemoveCommand("screenshot");
841 Cmd_RemoveCommand("imagelist");
842
843 Mod_FreeAll();
844
845 GL_ShutdownImages();
846
847 // shut down OS specific OpenGL stuff like contexts, etc.
848 GL_ShutdownGraphics();
849
850 // shutdown our QGL subsystem
851 QGL_Shutdown();
852 }
853
854
855 /*
856 GL_BeginFrame
857 */
GL_BeginFrame(void)858 void GL_BeginFrame(void){
859
860 if(gl_log->modified){
861 GL_EnableLogging(gl_log->value);
862 gl_log->modified = false;
863 }
864
865 if(gl_log->value){
866 GL_LogNewFrame();
867 }
868
869 // draw buffer stuff
870 if(gl_drawbuffer->modified){
871 gl_drawbuffer->modified = false;
872
873 if(!Q_stricmp(gl_drawbuffer->string, "GL_FRONT"))
874 qglDrawBuffer(GL_FRONT);
875 else qglDrawBuffer(GL_BACK);
876 }
877
878 // texturemode stuff
879 if(gl_texturemode->modified){
880 GL_TextureMode(gl_texturemode->string);
881 gl_texturemode->modified = false;
882 }
883
884 if(gl_texturealphamode->modified){
885 GL_TextureAlphaMode(gl_texturealphamode->string);
886 gl_texturealphamode->modified = false;
887 }
888
889 if(gl_texturesolidmode->modified){
890 GL_TextureSolidMode(gl_texturesolidmode->string);
891 gl_texturesolidmode->modified = false;
892 }
893
894 // clear screen if desired
895 GL_Clear();
896 }
897
898
899 /*
900 GL_Reload_f
901 */
GL_Reload_f(void)902 void GL_Reload_f(void){
903
904 cl.view_prepped = false;
905
906 Draw_Fill(0, 0, r_viewdef.width, r_viewdef.height, 0);
907
908 GL_ShutdownImages();
909 GL_InitImages();
910
911 GL_InitParticleTexture();
912 GL_InitNoTexture();
913
914 Draw_InitLocal();
915
916 V_RegisterViewMedia();
917 }
918
919
920 /*
921 Vid_Restart_f
922 */
VID_Restart_f(void)923 void VID_Restart_f(void){
924 extern qboolean update_viewdef;
925
926 GL_SetMode();
927 update_viewdef = true;
928 }
929
930
931 /*
932 GL_Register
933 */
GL_Register(void)934 void GL_Register(void){
935
936 r_fullbright = Cvar_Get("r_fullbright", "0", 0);
937 r_drawentities = Cvar_Get("r_drawentities", "1", 0);
938 r_novis = Cvar_Get("r_novis", "0", 0);
939 r_nocull = Cvar_Get("r_nocull", "0", 0);
940 r_lerpmodels = Cvar_Get("r_lerpmodels", "1", 0);
941 r_speeds = Cvar_Get("r_speeds", "0", 0);
942
943 gl_log = Cvar_Get("gl_log", "0", 0);
944 gl_modulate = Cvar_Get("gl_modulate", "1", CVAR_ARCHIVE);
945 gl_intensity = Cvar_Get("gl_intensity", "2", CVAR_ARCHIVE);
946 gl_lightmap = Cvar_Get("gl_lightmap", "0", 0);
947 gl_monolightmap = Cvar_Get("gl_monolightmap", "0", 0);
948 gl_loadtga = Cvar_Get("gl_loadtga", "1", CVAR_ARCHIVE);
949 gl_rounddown = Cvar_Get("gl_rounddown", "1", 0);
950 gl_picmip = Cvar_Get("gl_picmip", "0", 0);
951 gl_skymip = Cvar_Get("gl_skymip", "0", 0);
952 gl_playermip = Cvar_Get("gl_playermip", "0", 0);
953 gl_wireframe = Cvar_Get("gl_wireframe", "0", 0);
954 gl_ztrick = Cvar_Get("gl_ztrick", "1", CVAR_ARCHIVE);
955 gl_finish = Cvar_Get("gl_finish", "0", CVAR_ARCHIVE);
956 gl_clear = Cvar_Get("gl_clear", "0", 0);
957 gl_cull = Cvar_Get("gl_cull", "1", 0);
958
959 #ifdef _WIN32
960 gl_driver = Cvar_Get("gl_driver", "opengl32", CVAR_ARCHIVE);
961 #else
962 gl_driver = Cvar_Get("gl_driver", "libGL.so.1", CVAR_ARCHIVE);
963 #endif
964
965 gl_texturemode = Cvar_Get("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE);
966 gl_texturealphamode = Cvar_Get("gl_texturealphamode", "default", CVAR_ARCHIVE);
967 gl_texturesolidmode = Cvar_Get("gl_texturesolidmode", "default", CVAR_ARCHIVE);
968
969 gl_lockpvs = Cvar_Get("gl_lockpvs", "0", 0);
970
971 gl_vertex_arrays = Cvar_Get("gl_vertex_arrays", "1", CVAR_ARCHIVE);
972 gl_ext_multitexture = Cvar_Get("gl_ext_multitexture", "1", CVAR_ARCHIVE);
973 gl_ext_compiled_vertex_array = Cvar_Get("gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE);
974
975 gl_drawbuffer = Cvar_Get("gl_drawbuffer", "GL_BACK", 0);
976
977 vid_width = Cvar_Get("vid_width", "640", CVAR_ARCHIVE);
978 vid_height = Cvar_Get("vid_height", "480", CVAR_ARCHIVE);
979 vid_fullscreen = Cvar_Get("vid_fullscreen", "0", CVAR_ARCHIVE);
980 vid_gamma = Cvar_Get("vid_gamma", "1.0", CVAR_ARCHIVE);
981
982 skydistance = Cvar_Get("skydistance", "2300", CVAR_ARCHIVE);
983
984 Cmd_AddCommand("imagelist", GL_ImageList_f);
985 Cmd_AddCommand("screenshot", GL_Screenshot_f);
986
987 Cmd_AddCommand("gl_reload", GL_Reload_f);
988
989 Cmd_AddCommand("vid_restart", VID_Restart_f);
990 }
991