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