1 /*
2 * Copyright (C) 1997-2001 Id Software, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * See the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59
17 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20 /* r_main.c */
21 #include "gl_local.h"
22
23 #include "gl_refl.h" /* MPO */
24
25 /***************************************************************************** */
26 /* nVidia extensions */
27 /***************************************************************************** */
28 PFNGLCOMBINERPARAMETERFVNVPROC qglCombinerParameterfvNV;
29 PFNGLCOMBINERPARAMETERFNVPROC qglCombinerParameterfNV;
30 PFNGLCOMBINERPARAMETERIVNVPROC qglCombinerParameterivNV;
31 PFNGLCOMBINERPARAMETERINVPROC qglCombinerParameteriNV;
32 PFNGLCOMBINERINPUTNVPROC qglCombinerInputNV;
33 PFNGLCOMBINEROUTPUTNVPROC qglCombinerOutputNV;
34 PFNGLFINALCOMBINERINPUTNVPROC qglFinalCombinerInputNV;
35 PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC qglGetCombinerInputParameterfvNV;
36 PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC qglGetCombinerInputParameterivNV;
37 PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC qglGetCombinerOutputParameterfvNV;
38 PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC qglGetCombinerOutputParameterivNV;
39 PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC qglGetFinalCombinerInputParameterfvNV;
40 PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC qglGetFinalCombinerInputParameterivNV;
41
42 /***************************************************************************** */
43
44 int g_numGlLights = 0; /* dynamic lights for models .. */
45 int numberOfWallLights = 0; /* wall lights made into dynamic lights .. :) */
46 wallLight_t *wallLightArray[MAX_WALL_LIGHTS]; /* array of wall lights .. 500 should be enough */
47
48 void R_Clear(void);
49
50 #ifdef QMAX
51 #define random() ((rand () & 0x7fff) / ((float)0x7fff))
52 #define crandom() (2.0 * (random() - 0.5))
53 #endif
54
55 viddef_t vid;
56
57 refimport_t ri;
58
59 int GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2; /* MH add extra texture unit here */
60 int maxTextureUnits; /* MH max number of texture units */
61
62 model_t *r_worldmodel;
63
64 float gldepthmin, gldepthmax;
65
66 glconfig_t gl_config;
67 glstate_t gl_state;
68
69 #ifdef QMAX
70 image_t *r_particletextures[PARTICLE_TYPES]; /* list for particles */
71 image_t *r_particlebeam; /* used for beam ents */
72
73 #else
74 image_t *r_particletexture; /* little dot for particles */
75
76 #endif
77 image_t *r_notexture; /* use for bad textures */
78 image_t *r_shelltexture; /* c14 added shell texture */
79 image_t *r_radarmap; /* wall texture for radar texgen */
80 image_t *r_around;
81 image_t *r_caustictexture; /* Water caustic texture */
82 image_t *r_bholetexture;
83
84 entity_t *currententity;
85 model_t *currentmodel;
86
87 cplane_t frustum[4];
88
89 int r_visframecount;/* bumped when going to a new PVS */
90 int r_framecount; /* used for dlight push checking */
91
92 int c_brush_polys, c_alias_polys;
93
94 float v_blend[4]; /* final blending color */
95
96 void GL_Strings_f(void);
97
98 //
99 /* view origin */
100 //
101 vec3_t vup;
102 vec3_t vpn;
103 vec3_t vright;
104 vec3_t r_origin;
105
106 float r_world_matrix[16];
107 float r_base_world_matrix[16];
108
109 //
110 /* screen size info */
111 //
112 refdef_t r_refdef;
113
114 int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
115
116 cvar_t *skydistance; /* DMP - skybox size change */
117
118 #ifdef QMAX
119 cvar_t *gl_partscale;
120 cvar_t *gl_transrendersort;
121 cvar_t *gl_particlelighting;
122 cvar_t *gl_particledistance;
123 #else
124 cvar_t *gl_particle_min_size;
125 cvar_t *gl_particle_max_size;
126 cvar_t *gl_particle_size;
127 cvar_t *gl_particle_att_a;
128 cvar_t *gl_particle_att_b;
129 cvar_t *gl_particle_att_c;
130 cvar_t *gl_particles;
131 #endif
132
133 cvar_t *r_norefresh;
134 cvar_t *r_drawentities;
135 cvar_t *r_drawworld;
136 cvar_t *r_speeds;
137 cvar_t *r_fullbright;
138 cvar_t *r_novis;
139 cvar_t *r_nocull;
140 cvar_t *r_lerpmodels;
141 cvar_t *r_model_lightlerp;
142 cvar_t *r_model_alpha;
143 cvar_t *r_lefthand;
144
145 cvar_t *gl_stainmaps;
146
147 cvar_t *r_lightlevel; /* FIXME: This is a HACK to get the client's light level */
148
149 cvar_t *r_overbrightbits;
150
151 cvar_t *gl_nosubimage;
152
153 cvar_t *gl_vertex_arrays;
154
155 cvar_t *r_cellshading;
156 cvar_t *r_cellshading_width;
157
158 cvar_t *font_color;
159
160 cvar_t *gl_ext_multitexture;
161 cvar_t *gl_ext_pointparameters;
162 cvar_t *gl_ext_compiled_vertex_array;
163 cvar_t *gl_ext_palettedtexture;
164
165 cvar_t *gl_log;
166 cvar_t *gl_bitdepth;
167 cvar_t *gl_drawbuffer;
168 cvar_t *gl_driver;
169 cvar_t *gl_lightmap;
170 cvar_t *gl_shadows;
171 cvar_t *gl_shadows_alpha;
172 cvar_t *gl_shellstencil;
173 cvar_t *gl_mode;
174 cvar_t *gl_dynamic;
175 cvar_t *gl_monolightmap;
176 cvar_t *gl_modulate;
177 cvar_t *gl_nobind;
178 cvar_t *gl_round_down;
179 cvar_t *gl_picmip;
180 cvar_t *gl_skymip;
181 cvar_t *gl_showtris;
182 cvar_t *gl_finish;
183 cvar_t *gl_clear;
184 cvar_t *gl_cull;
185 cvar_t *gl_polyblend;
186 cvar_t *gl_flashblend;
187 cvar_t *gl_playermip;
188 cvar_t *gl_saturatelighting;
189 cvar_t *gl_texturemode;
190 cvar_t *gl_texturealphamode;
191 cvar_t *gl_texturesolidmode;
192 cvar_t *gl_lockpvs;
193
194 cvar_t *gl_3dlabs_broken;
195
196 cvar_t *gl_ext_texture_compression; /* Heffo - ARB Texture Compression */
197 cvar_t *gl_ext_mtexcombine;
198 cvar_t *gl_anisotropic;
199 cvar_t *gl_anisotropic_avail;
200 cvar_t *gl_ext_nv_multisample_filter_hint; /* r1ch extensions */
201 cvar_t *gl_nv_fog;
202 cvar_t *gl_lightmap_texture_saturation; /* jitsaturation */
203 cvar_t *gl_lightmap_saturation; /* jitsaturation */
204 cvar_t *gl_screenshot_jpeg; /* Heffo - JPEG Screenshots */
205 cvar_t *gl_screenshot_jpeg_quality; /* Heffo - JPEG Screenshots */
206 cvar_t *gl_water_waves; /* Water waves */
207 cvar_t *gl_water_caustics; /* Water Caustics */
208
209 /* Knightmare- allow disabling the nVidia water warp */
210 cvar_t *gl_water_pixel_shader_warp;
211 cvar_t *gl_blooms;
212 cvar_t *gl_motionblur; /* motionblur */
213 cvar_t *gl_motionblur_intensity; /* motionblur */
214
215 /* ========= Engine Fog ============== */
216 cvar_t *gl_fogenable; /* Enable */
217 cvar_t *gl_fogred; /* Red */
218 cvar_t *gl_foggreen; /* Green */
219 cvar_t *gl_fogblue; /* Blue */
220 cvar_t *gl_fogstart; /* Start */
221 cvar_t *gl_fogend; /* End */
222 cvar_t *gl_fogdensity; /* Density */
223 cvar_t *gl_fogunderwater; /* Under Water Fof */
224 /* ============ End =================== */
225
226 cvar_t *gl_shading;
227 cvar_t *gl_decals;
228 cvar_t *gl_decals_time;
229 cvar_t *gl_glares;
230 cvar_t *gl_glares_size;
231 cvar_t *gl_glares_intens;
232 cvar_t *gl_dlight_cutoff;
233
234 cvar_t *gl_minimap;
235 cvar_t *gl_minimap_size;
236 cvar_t *gl_minimap_zoom;
237 cvar_t *gl_minimap_style;
238 cvar_t *gl_minimap_x;
239 cvar_t *gl_minimap_y;
240
241 cvar_t *gl_alpha_surfaces;
242
243 cvar_t *gl_flares;
244 cvar_t *gl_flare_force_size;
245 cvar_t *gl_flare_force_style;
246 cvar_t *gl_flare_intensity;
247 cvar_t *gl_flare_maxdist;
248 cvar_t *gl_flare_scale;
249
250 cvar_t *gl_coloredlightmaps; /* NiceAss */
251
252 cvar_t *vid_fullscreen;
253 cvar_t *vid_gamma;
254 cvar_t *vid_ref;
255 cvar_t *cl_hudscale;
256 cvar_t *cl_big_maps;
257 cvar_t *cl_3dcam;
258 cvar_t *deathmatch;
259
260 cvar_t *gl_reflection_fragment_program;
261 cvar_t *gl_reflection; /* MPO alpha transparency, 1.0 is full bright */
262 cvar_t *gl_reflection_debug; /* MPO for debugging the reflection */
263 cvar_t *gl_reflection_max; /* MPO max number of water reflections */
264 cvar_t *gl_reflection_shader; /* MPO enable/disable fragment shaders */
265 cvar_t *gl_reflection_shader_image;
266 cvar_t *gl_reflection_water_surface; /* MPO enable/disable fragment shaders */
267
268 /* MH - detail textures begin */
269 cvar_t *gl_detailtextures;
270 /* MH - detail textures begin */
271
272 /* mpo - needed for fragment shaders */
273 void (APIENTRY * qglGenProgramsARB) (GLint n, GLuint * programs);
274 void (APIENTRY * qglDeleteProgramsARB) (GLint n, const GLuint * programs);
275 void (APIENTRY * qglBindProgramARB) (GLenum target, GLuint program);
276 void (APIENTRY * qglProgramStringARB) (GLenum target, GLenum format, GLint len, const void *string);
277 void (APIENTRY * qglProgramEnvParameter4fARB) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
278 void (APIENTRY * qglProgramLocalParameter4fARB) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
279
280 /* mpo - needed for fragment shaders */
281
282 /*
283 * ================= GL_Stencil
284 *
285 * setting stencil buffer =================
286 */
287 extern qboolean have_stencil;
288 void
GL_Stencil(qboolean enable)289 GL_Stencil(qboolean enable)
290 {
291 if (!have_stencil)
292 return;
293
294 if (enable) {
295 qglEnable(GL_STENCIL_TEST);
296 qglStencilFunc(GL_EQUAL, 1, 2);
297 qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
298 } else {
299 qglDisable(GL_STENCIL_TEST);
300 }
301 }
302
303 /*
304 * ================= R_CullBox
305 *
306 * Returns true if the box is completely outside the frustom =================
307 */
308 qboolean
R_CullBox(vec3_t mins,vec3_t maxs)309 R_CullBox(vec3_t mins, vec3_t maxs)
310 {
311 int i;
312
313 if (r_nocull->value)
314 return false;
315
316 for (i = 0; i < 4; i++)
317 if (BoxOnPlaneSide(mins, maxs, &frustum[i]) == 2)
318 return true;
319 return false;
320 }
321
322 void
R_RotateForEntity(entity_t * e)323 R_RotateForEntity(entity_t * e)
324 {
325 qglTranslatef(e->origin[0], e->origin[1], e->origin[2]);
326
327 qglRotatef(e->angles[1], 0, 0, 1);
328 qglRotatef(-e->angles[0], 0, 1, 0);
329 qglRotatef(-e->angles[2], 1, 0, 0);
330 }
331
332 /*
333 * =============================================================
334 *
335 * SPRITE MODELS
336 *
337 * =============================================================
338 */
339
340
341 /*
342 * ================= R_DrawSpriteModel
343 *
344 * =================
345 */
346 void
R_DrawSpriteModel(entity_t * e)347 R_DrawSpriteModel(entity_t * e)
348 {
349 float alpha = 1.0;
350 vec3_t point, up, right;
351 dsprframe_t *frame;
352 dsprite_t *psprite;
353
354 /* don't even bother culling, because it's just a single */
355 /* polygon without a surface cache */
356
357 psprite = (dsprite_t *) currentmodel->extradata;
358
359 e->frame %= psprite->numframes;
360
361 frame = &psprite->frames[e->frame];
362
363 if (!frame)
364 return;
365
366 /* normal sprite */
367 VectorCopy(vup, up);
368 VectorCopy(vright, right);
369
370
371 if (e->flags & RF_TRANSLUCENT)
372 alpha = e->alpha;
373
374 if (!currentmodel->skins[e->frame])
375 return;
376
377 GL_Bind(currentmodel->skins[e->frame]->texnum);
378
379 if ((currententity->flags & RF_TRANS_ADDITIVE) && (alpha != 1.0)) {
380 GLSTATE_ENABLE_BLEND
381 GL_TexEnv(GL_MODULATE);
382
383 GLSTATE_DISABLE_ALPHATEST
384 GL_BlendFunction(GL_SRC_ALPHA, GL_ONE);
385
386 qglColor4ub(255, 255, 255, alpha * 254);
387 } else {
388 if (alpha != 1.0)
389 GLSTATE_ENABLE_BLEND
390
391 GL_TexEnv(GL_MODULATE);
392
393 if (alpha == 1.0) {
394 GLSTATE_ENABLE_ALPHATEST
395 else
396 GLSTATE_DISABLE_ALPHATEST
397 }
398 qglColor4f(1, 1, 1, alpha);
399 }
400
401 qglBegin(GL_QUADS);
402
403 qglTexCoord2f(0, 1);
404 VectorMA(e->origin, -frame->origin_y, up, point);
405 VectorMA(point, -frame->origin_x, right, point);
406 qglVertex3fv(point);
407
408 qglTexCoord2f(0, 0);
409 VectorMA(e->origin, frame->height - frame->origin_y, up, point);
410 VectorMA(point, -frame->origin_x, right, point);
411 qglVertex3fv(point);
412
413 qglTexCoord2f(1, 0);
414 VectorMA(e->origin, frame->height - frame->origin_y, up, point);
415 VectorMA(point, frame->width - frame->origin_x, right, point);
416 qglVertex3fv(point);
417
418 qglTexCoord2f(1, 1);
419 VectorMA(e->origin, -frame->origin_y, up, point);
420 VectorMA(point, frame->width - frame->origin_x, right, point);
421 qglVertex3fv(point);
422
423 qglEnd();
424
425
426 GL_BlendFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
427 GLSTATE_DISABLE_ALPHATEST
428
429 GL_TexEnv(GL_REPLACE);
430
431 if (alpha != 1.0)
432 GLSTATE_DISABLE_BLEND
433
434 qglColor4f(1, 1, 1, 1);
435 }
436
437 /*
438 * ===========================================================================
439 * =======
440 */
441
442 /*
443 * ============= R_DrawNullModel =============
444 */
445 void
R_DrawNullModel(void)446 R_DrawNullModel(void)
447 {
448 vec3_t shadelight;
449 int i;
450
451 if (currententity->flags & RF_FULLBRIGHT)
452 shadelight[0] = shadelight[1] = shadelight[2] = 1.0;
453 else
454 R_LightPoint(currententity->origin, shadelight);
455
456 qglPushMatrix();
457 R_RotateForEntity(currententity);
458
459 qglDisable(GL_TEXTURE_2D);
460 qglColor3fv(shadelight);
461
462 qglBegin(GL_TRIANGLE_FAN);
463 qglVertex3f(0, 0, -16);
464 for (i = 0; i <= 4; i++)
465 qglVertex3f(16 * cos(i * M_PI / 2), 16 * sin(i * M_PI / 2), 0);
466 qglEnd();
467
468 qglBegin(GL_TRIANGLE_FAN);
469 qglVertex3f(0, 0, 16);
470 for (i = 4; i >= 0; i--)
471 qglVertex3f(16 * cos(i * M_PI / 2), 16 * sin(i * M_PI / 2), 0);
472 qglEnd();
473
474 qglColor3f(1, 1, 1);
475 qglPopMatrix();
476 qglEnable(GL_TEXTURE_2D);
477 }
478
479 /*
480 * ============= R_DrawEntitiesOnList =============
481 */
482 #ifdef QMAX
483 typedef struct sortedent_s {
484 entity_t *ent;
485 vec_t len;
486 qboolean inwater;
487 } sortedent_t;
488
489 sortedent_t theents[MAX_ENTITIES];
490
491 int
transCompare(const void * arg1,const void * arg2)492 transCompare(const void *arg1, const void *arg2)
493 {
494 const sortedent_t *a1, *a2;
495
496 a1 = (sortedent_t *) arg1;
497 a2 = (sortedent_t *) arg2;
498 return (a2->len - a1->len);
499 }
500
501 sortedent_t
NewSortEnt(entity_t * ent,qboolean waterstart)502 NewSortEnt(entity_t * ent, qboolean waterstart)
503 {
504 vec3_t result;
505 sortedent_t s_ent;
506
507 s_ent.ent = ent;
508
509 VectorSubtract(ent->origin, r_origin, result);
510 s_ent.len = (result[0] * result[0]) + (result[1] * result[1]) + (result[2] * result[2]);
511
512 s_ent.inwater = (Mod_PointInLeaf(ent->origin, r_worldmodel)->contents & MASK_WATER);
513 if (ent->flags & RF_WEAPONMODEL || ent->flags & RF_VIEWERMODEL)
514 s_ent.inwater = waterstart;
515
516 return s_ent;
517 }
518 void
R_SortEntitiesOnList(qboolean inwater)519 R_SortEntitiesOnList(qboolean inwater)
520 {
521 int i;
522
523 for (i = 0; i < r_refdef.num_entities; i++)
524 theents[i] = NewSortEnt(&r_refdef.entities[i], inwater);
525
526 qsort((void *)theents, r_refdef.num_entities, sizeof(sortedent_t), transCompare);
527 }
528
529 void
R_DrawEntitiesOnList(qboolean inWater,qboolean solids)530 R_DrawEntitiesOnList(qboolean inWater, qboolean solids)
531 {
532 vec3_t origin;
533 int i, j;
534
535 if (!r_drawentities->value)
536 return;
537
538 /* draw non-transparent first */
539 if (solids)
540 for (i = 0; i < r_refdef.num_entities; i++) {
541 currententity = &r_refdef.entities[i];
542
543 if (currententity->flags & RF_TRANSLUCENT || currententity->flags & RF_VIEWERMODEL)
544 continue;
545
546 for (j = 0; j < 3; j++)
547 origin[j] = currententity->origin[j];
548
549 if (currententity->flags & RF_BEAM) {
550 R_DrawBeam(currententity);
551 } else {
552 currentmodel = currententity->model;
553 if (!currentmodel) {
554 R_DrawNullModel();
555 continue;
556 }
557 switch (currentmodel->type) {
558 case mod_alias:
559 R_DrawAliasModel(currententity);
560 break;
561 /* Harven MD3 ++ */
562 case mod_alias_md3:
563 R_DrawAliasMD3Model(currententity);
564 break;
565 /* Harven MD3 -- */
566 case mod_brush:
567 R_DrawBrushModel(currententity);
568 break;
569 case mod_sprite:
570 R_DrawSpriteModel(currententity);
571 break;
572 default:
573 ri.Sys_Error(ERR_DROP, "Bad modeltype");
574 break;
575 }
576 }
577 }
578
579 qglDepthMask(0);
580 for (i = 0; i < r_refdef.num_entities; i++) {
581 if (gl_transrendersort->value && !(r_refdef.rdflags & RDF_NOWORLDMODEL)) {
582 currententity = theents[i].ent;
583
584 if (!(currententity->flags & RF_TRANSLUCENT || currententity->flags & RF_VIEWERMODEL) ||
585 (inWater && !theents[i].inwater) || (!inWater && theents[i].inwater))
586 continue; /* solid */
587 } else if (inWater) {
588 currententity = &r_refdef.entities[i];
589
590 if (!(currententity->flags & RF_TRANSLUCENT || currententity->flags & RF_VIEWERMODEL))
591 continue; /* solid */
592 } else
593 continue;
594
595 if (currententity->flags & RF_BEAM) {
596 R_DrawBeam(currententity);
597 } else {
598 currentmodel = currententity->model;
599
600 if (!currentmodel) {
601 R_DrawNullModel();
602 continue;
603 }
604 switch (currentmodel->type) {
605 case mod_alias:
606 R_DrawAliasModel(currententity);
607 break;
608 /* Harven MD3 ++ */
609 case mod_alias_md3:
610 R_DrawAliasMD3Model(currententity);
611 break;
612 /* Harven MD3 -- */
613 case mod_brush:
614 R_DrawBrushModel(currententity);
615 break;
616 case mod_sprite:
617 R_DrawSpriteModel(currententity);
618 break;
619 default:
620 ri.Sys_Error(ERR_DROP, "Bad modeltype");
621 break;
622 }
623 }
624 }
625 qglDepthMask(1); /* back to writing */
626
627 }
628 #else
629 void
R_DrawEntitiesOnList(void)630 R_DrawEntitiesOnList(void)
631 {
632 int i;
633
634 if (!r_drawentities->value)
635 return;
636
637 /* draw non-transparent first */
638 for (i = 0; i < r_refdef.num_entities; i++) {
639 currententity = &r_refdef.entities[i];
640 if (currententity->flags & RF_TRANSLUCENT)
641 continue; /* solid */
642
643 if (currententity->flags & RF_BEAM) {
644 R_DrawBeam(currententity);
645 } else {
646 currentmodel = currententity->model;
647 if (!currentmodel) {
648 R_DrawNullModel();
649 continue;
650 }
651 switch (currentmodel->type) {
652 case mod_alias:
653 R_DrawAliasModel(currententity);
654 break;
655 /* Harven MD3 ++ */
656 case mod_alias_md3:
657 R_DrawAliasMD3Model(currententity);
658 break;
659 /* Harven MD3 -- */
660 case mod_brush:
661 R_DrawBrushModel(currententity);
662 break;
663 case mod_sprite:
664 R_DrawSpriteModel(currententity);
665 break;
666 default:
667 ri.Sys_Error(ERR_DROP, "Bad modeltype");
668 break;
669 }
670 }
671 }
672
673 /* draw transparent entities */
674 /* we could sort these if it ever becomes a problem... */
675 qglDepthMask(0); /* no z writes */
676 for (i = 0; i < r_refdef.num_entities; i++) {
677 currententity = &r_refdef.entities[i];
678 if (!(currententity->flags & RF_TRANSLUCENT))
679 continue; /* solid */
680
681 if (currententity->flags & RF_BEAM) {
682 R_DrawBeam(currententity);
683 } else {
684 currentmodel = currententity->model;
685
686 if (!currentmodel) {
687 R_DrawNullModel();
688 continue;
689 }
690 switch (currentmodel->type) {
691 case mod_alias:
692 R_DrawAliasModel(currententity);
693 break;
694 /* Harven MD3 ++ */
695 case mod_alias_md3:
696 R_DrawAliasMD3Model(currententity);
697 break;
698 /* Harven MD3 -- */
699 case mod_brush:
700 R_DrawBrushModel(currententity);
701 break;
702 case mod_sprite:
703 R_DrawSpriteModel(currententity);
704 break;
705 default:
706 ri.Sys_Error(ERR_DROP, "Bad modeltype");
707 break;
708 }
709 }
710 }
711 qglDepthMask(1); /* back to writing */
712
713 }
714 #endif
715
716 /*
717 * * GL_DrawParticles *
718 *
719 */
720
721 #ifdef QMAX
722 typedef struct sortedpart_s {
723 particle_t *p;
724 vec_t len;
725 qboolean inwater;
726 } sortedpart_t;
727
728 sortedpart_t theparts[MAX_PARTICLES];
729
730 sortedpart_t
NewSortPart(particle_t * p)731 NewSortPart(particle_t * p)
732 {
733 vec3_t result;
734 sortedpart_t s_part;
735
736 s_part.p = p;
737 VectorSubtract(p->origin, r_origin, result);
738 s_part.len = (result[0] * result[0]) + (result[1] * result[1]) + (result[2] * result[2]);
739 s_part.inwater = (Mod_PointInLeaf(p->origin, r_worldmodel)->contents & MASK_WATER);
740
741 return s_part;
742 }
743
744 void
R_SortParticlesOnList(int num_particles,const particle_t particles[])745 R_SortParticlesOnList(int num_particles, const particle_t particles[])
746 {
747 int i;
748
749 for (i = 0; i < num_particles; i++)
750 theparts[i] = NewSortPart((particle_t *) & particles[i]);
751
752 qsort((void *)theparts, num_particles, sizeof(sortedpart_t), transCompare);
753 }
754
755 int
texParticle(int type)756 texParticle(int type)
757 {
758 image_t *part_img;
759
760 part_img = r_particletextures[type];
761
762 return part_img->texnum;
763 }
764
765 void
vectoanglerolled(vec3_t value1,float angleyaw,vec3_t angles)766 vectoanglerolled(vec3_t value1, float angleyaw, vec3_t angles)
767 {
768 float forward , yaw, pitch;
769
770 yaw = (int)(atan2(value1[1], value1[0]) * 180 / M_PI);
771 forward = sqrt(value1[0] * value1[0] + value1[1] * value1[1]);
772 pitch = (int)(atan2(value1[2], forward) * 180 / M_PI);
773
774 if (pitch < 0)
775 pitch += 360;
776
777 angles[PITCH] = -pitch;
778 angles[YAW] = yaw;
779 angles[ROLL] = -angleyaw;
780 }
781
782 float
AngleFind(float input)783 AngleFind(float input)
784 {
785 return 180.0 / input;
786 }
787 void
GL_DrawParticles(int num_particles,qboolean inWater)788 GL_DrawParticles(int num_particles, qboolean inWater)
789 {
790 int i;
791 float size, lighting = gl_particlelighting->value;
792 int oldrender = 0, rendertype = 0;
793
794 byte alpha;
795
796 vec3_t up = {vup[0] * 0.75, vup[1] * 0.75, vup[2] * 0.75};
797 vec3_t right = {vright[0] * 0.75, vright[1] * 0.75, vright[2] * 0.75};
798 vec3_t coord [4], shadelight;
799
800 particle_t *p;
801
802 VectorAdd(up, right, coord[0]);
803 VectorSubtract(right, up, coord[1]);
804 VectorNegate(coord[0], coord[2]);
805 VectorNegate(coord[1], coord[3]);
806
807 qglEnable(GL_TEXTURE_2D);
808 GL_TexEnv(GL_MODULATE);
809 qglDepthMask(false);
810 qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
811 qglEnable(GL_BLEND);
812 qglShadeModel(GL_SMOOTH);
813
814
815
816 for (i = 0; i < num_particles; i++) {
817 if (!(r_refdef.rdflags & RDF_NOWORLDMODEL)) {
818 if (gl_transrendersort->value == 2) { /* sorted with ents etc */
819 p = theparts[i].p;
820
821 if ((inWater && !theparts[i].inwater) || (!inWater && theparts[i].inwater))
822 continue;
823
824 if (gl_particledistance->value > 0 && theparts[i].len > (100.0 * gl_particledistance->value))
825 continue;
826 } else if (gl_transrendersort->value) { /* sorted by itself */
827 p = theparts[i].p;
828
829 if ((inWater && !theparts[i].inwater) || (!inWater && theparts[i].inwater))
830 continue;
831
832 if (gl_particledistance->value > 0 && theparts[i].len > (100.0 * gl_particledistance->value))
833 continue;
834 } else if (inWater)
835 p = &r_refdef.particles[i];
836 else
837 continue;
838 } else if (inWater)
839 p = &r_refdef.particles[i];
840 else
841 continue;
842
843 oldrender = rendertype;
844 rendertype = (p->flags & PART_TRANS) ? 1 : 0;
845 if (rendertype != oldrender) {
846 if (rendertype == 1)
847 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
848 else
849 qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
850 }
851 if (!(p->flags & PART_SPARK))
852 GL_Bind(texParticle(p->image));
853
854 alpha = p->alpha * 254.0;
855 size = (p->size > 0.1) ? p->size : 0.1;
856
857 if (p->flags & PART_SHADED) {
858 int j;
859 float lightest = 0;
860
861 R_LightPoint(p->origin, shadelight);
862
863 shadelight[0] = (lighting * shadelight[0] + (1 - lighting)) * p->red;
864 shadelight[1] = (lighting * shadelight[1] + (1 - lighting)) * p->green;
865 shadelight[2] = (lighting * shadelight[2] + (1 - lighting)) * p->blue;
866
867 /* this cleans up the lighting */
868 {
869 for (j = 0; j < 3; j++)
870 if (shadelight[j] > lightest)
871 lightest = shadelight[j];
872 if (lightest > 255)
873 for (j = 0; j < 3; j++)
874 shadelight[j] *= 255 / lightest;
875 }
876
877 qglColor4ub(shadelight[0], shadelight[1], shadelight[2], alpha);
878 } else
879 qglColor4ub(p->red, p->green, p->blue, alpha);
880
881 /*
882 * id move this somewhere less dirty, but im too damn lazy -
883 * psychospaz
884 */
885 #define DEPTHHACK_RANGE_SHORT 0.9985f
886 #define DEPTHHACK_RANGE_MID 0.975f
887 #define DEPTHHACK_RANGE_LONG 0.95f
888
889 if (p->flags & PART_DEPTHHACK_SHORT) /* nice little
890 * poly-peeking -
891 * psychospaz */
892 qglDepthRange(gldepthmin, gldepthmin + DEPTHHACK_RANGE_SHORT * (gldepthmax - gldepthmin));
893 if (p->flags & PART_DEPTHHACK_MID)
894 qglDepthRange(gldepthmin, gldepthmin + DEPTHHACK_RANGE_MID * (gldepthmax - gldepthmin));
895 if (p->flags & PART_DEPTHHACK_LONG)
896 qglDepthRange(gldepthmin, gldepthmin + DEPTHHACK_RANGE_LONG * (gldepthmax - gldepthmin));
897
898 if (p->flags & PART_SPARK) { /* QMB style particles */
899 int angle;
900 vec3_t v;
901
902 qglDisable(GL_TEXTURE_2D);
903
904 qglPushMatrix();
905 {
906 qglBegin(GL_TRIANGLE_FAN);
907 {
908 #define MAGICNUMBER 32
909 float magicnumber = AngleFind(MAGICNUMBER);
910
911
912 qglVertex3fv(p->origin);
913 qglColor4ub(0, 0, 0, 0);
914
915 for (angle = magicnumber * fabs(1 - MAGICNUMBER); angle >= 0; angle -= magicnumber) {
916 v[0] = p->origin[0] - p->angle[0] * size + (right[0] * cos(angle) + up[0] * sin(angle));
917 v[1] = p->origin[1] - p->angle[1] * size + (right[1] * cos(angle) + up[1] * sin(angle));
918 v[2] = p->origin[2] - p->angle[2] * size + (right[2] * cos(angle) + up[2] * sin(angle));
919 qglVertex3fv(v);
920 }
921 }
922 qglEnd();
923 }
924 qglPopMatrix();
925
926 qglEnable(GL_TEXTURE_2D);
927 } else if (p->flags & PART_BEAM) { /* given start and end
928 * positions, will have
929 * fun here :)
930 */
931 /* p->angle = start */
932 /* p->origin= end */
933 vec3_t angl_coord[4];
934 vec3_t ang_up, ang_right, vdelta;
935
936 VectorSubtract(p->origin, p->angle, vdelta);
937 VectorNormalize(vdelta);
938
939 VectorCopy(vdelta, ang_up);
940 VectorSubtract(r_refdef.vieworg, p->angle, vdelta);
941 CrossProduct(ang_up, vdelta, ang_right);
942 if (!VectorCompare(ang_right, vec3_origin))
943 VectorNormalize(ang_right);
944
945 VectorScale(ang_right, size, ang_right);
946
947 VectorAdd(p->origin, ang_right, angl_coord[0]);
948 VectorAdd(p->angle, ang_right, angl_coord[1]);
949 VectorSubtract(p->angle, ang_right, angl_coord[2]);
950 VectorSubtract(p->origin, ang_right, angl_coord[3]);
951
952 qglPushMatrix();
953 {
954 qglBegin(GL_QUADS);
955 {
956 qglTexCoord2f(0, 1);
957 qglVertex3fv(angl_coord[0]);
958 qglTexCoord2f(0, 0);
959 qglVertex3fv(angl_coord[1]);
960 qglTexCoord2f(1, 0);
961 qglVertex3fv(angl_coord[2]);
962 qglTexCoord2f(1, 1);
963 qglVertex3fv(angl_coord[3]);
964 }
965 qglEnd();
966
967 }
968 qglPopMatrix();
969 } else if (p->flags & PART_LIGHTNING) { /* given start and end
970 * positions, will have
971 * fun here :)
972 */
973 /* p->angle = start */
974 /* p->origin= end */
975 float tlen, halflen, len, dec = size, warpfactor,
976 warpadd, oldwarpadd, warpsize, time, i = 0,
977 factor;
978 vec3_t move, lastvec, thisvec, tempvec;
979 vec3_t angl_coord[4];
980 vec3_t ang_up, ang_right, vdelta;
981
982 oldwarpadd = 0;
983 warpsize = dec * 0.01;
984 warpfactor = M_PI * 1.0;
985 time = -r_refdef.time * 10.0;
986
987 VectorSubtract(p->origin, p->angle, move);
988 len = VectorNormalize(move);
989
990 VectorCopy(move, ang_up);
991 VectorSubtract(r_refdef.vieworg, p->angle, vdelta);
992 CrossProduct(ang_up, vdelta, ang_right);
993 if (!VectorCompare(ang_right, vec3_origin))
994 VectorNormalize(ang_right);
995
996 VectorScale(ang_right, dec, ang_right);
997 VectorScale(ang_up, dec, ang_up);
998
999 VectorScale(move, dec, move);
1000 VectorCopy(p->angle, lastvec);
1001 VectorAdd(lastvec, move, thisvec);
1002 VectorCopy(thisvec, tempvec);
1003
1004 /* lightning starts at point and then flares out */
1005 #define LIGHTNINGWARPFUNCTION 0.25*sin(time+i+warpfactor)*(dec/len)
1006
1007 warpadd = LIGHTNINGWARPFUNCTION;
1008 factor = 1;
1009 halflen = len / 2.0;
1010
1011
1012 thisvec[0] = (thisvec[0] * 2 + crandom() * 5) / 2;
1013 thisvec[1] = (thisvec[1] * 2 + crandom() * 5) / 2;
1014 thisvec[2] = (thisvec[2] * 2 + crandom() * 5) / 2;
1015
1016 /*
1017 * thisvec[0]= (thisvec[0]*2 + 5)/2; thisvec[1]=
1018 * (thisvec[1]*2 + 5)/2; thisvec[2]= (thisvec[2]*2 +
1019 * 5)/2;
1020 */
1021 while (len > dec) {
1022 i += warpsize;
1023
1024 VectorAdd(thisvec, ang_right, angl_coord[0]);
1025 VectorAdd(lastvec, ang_right, angl_coord[1]);
1026 VectorSubtract(lastvec, ang_right, angl_coord[2]);
1027 VectorSubtract(thisvec, ang_right, angl_coord[3]);
1028
1029 qglPushMatrix();
1030 {
1031 qglBegin(GL_QUADS);
1032 {
1033 qglTexCoord2f(0 + warpadd, 1);
1034 qglVertex3fv(angl_coord[0]);
1035 qglTexCoord2f(0 + oldwarpadd, 0);
1036 qglVertex3fv(angl_coord[1]);
1037 qglTexCoord2f(1 + oldwarpadd, 0);
1038 qglVertex3fv(angl_coord[2]);
1039 qglTexCoord2f(1 + warpadd, 1);
1040 qglVertex3fv(angl_coord[3]);
1041 }
1042 qglEnd();
1043
1044 }
1045 qglPopMatrix();
1046
1047 tlen = (len < halflen) ? fabs(len - halflen) : fabs(len - halflen);
1048 factor = tlen / (size * size);
1049
1050 if (factor > 4)
1051 factor = 4;
1052 else if (factor < 1)
1053 factor = 1;
1054
1055 oldwarpadd = warpadd;
1056 warpadd = LIGHTNINGWARPFUNCTION;
1057
1058 len -= dec;
1059 VectorCopy(thisvec, lastvec);
1060 VectorAdd(tempvec, move, tempvec);
1061 VectorAdd(lastvec, move, thisvec);
1062
1063
1064 /*
1065 * thisvec[0]= ((thisvec[0] +
1066 * (crandom()*size)) +
1067 * tempvec[0]*factor)/(factor+1); thisvec[1]=
1068 * ((thisvec[1] + (crandom()*size)) +
1069 * tempvec[1]*factor)/(factor+1); thisvec[2]=
1070 * ((thisvec[2] + (crandom()*size)) +
1071 * tempvec[2]*factor)/(factor+1);
1072 */
1073 thisvec[0] = ((thisvec[0] + (size)) + tempvec[0] * factor) / (factor + 1);
1074 thisvec[1] = ((thisvec[1] + (size)) + tempvec[1] * factor) / (factor + 1);
1075 thisvec[2] = ((thisvec[2] + (size)) + tempvec[2] * factor) / (factor + 1);
1076
1077 }
1078
1079 i += warpsize;
1080
1081 /* one more time */
1082 if (len > 0) {
1083 VectorAdd(p->origin, ang_right, angl_coord[0]);
1084 VectorAdd(lastvec, ang_right, angl_coord[1]);
1085 VectorSubtract(lastvec, ang_right, angl_coord[2]);
1086 VectorSubtract(p->origin, ang_right, angl_coord[3]);
1087
1088 qglPushMatrix();
1089 {
1090 qglBegin(GL_QUADS);
1091 {
1092 qglTexCoord2f(0 + warpadd, 1);
1093 qglVertex3fv(angl_coord[0]);
1094 qglTexCoord2f(0 + oldwarpadd, 0);
1095 qglVertex3fv(angl_coord[1]);
1096 qglTexCoord2f(1 + oldwarpadd, 0);
1097 qglVertex3fv(angl_coord[2]);
1098 qglTexCoord2f(1 + warpadd, 1);
1099 qglVertex3fv(angl_coord[3]);
1100 }
1101 qglEnd();
1102
1103 }
1104 qglPopMatrix();
1105 }
1106 } else if (p->flags & PART_DIRECTION) { /* streched out in
1107 * direction...tracers
1108 * etc... */
1109
1110 /*
1111 * never dissapears because of angle like other
1112 * engines :D
1113 */
1114 float len, dot;
1115 vec3_t angl_coord[4];
1116 vec3_t ang_up, ang_right, vdelta;
1117
1118 VectorCopy(p->angle, ang_up);
1119 len = VectorNormalize(ang_up);
1120 VectorSubtract(r_refdef.vieworg, p->origin, vdelta);
1121 CrossProduct(ang_up, vdelta, ang_right);
1122 if (!VectorCompare(ang_right, vec3_origin))
1123 VectorNormalize(ang_right);
1124
1125
1126 /*
1127 * the more you look into ang_up, the more it looks
1128 * like normal sprite (recalc ang_up)
1129 */
1130 if (false) {
1131 vec3_t temp_up [3], tempfor;
1132
1133 AngleVectors(r_refdef.viewangles, tempfor, NULL, NULL);
1134 dot = 1 - fabs(DotProduct(ang_up, tempfor));
1135
1136 /*
1137 * if (DotProduct (vdelta, ang_up)<0 ||
1138 * DotProduct (vdelta, ang_right)<0)
1139 */
1140 /* VectorScale(tempfor, -1.0, tempfor); */
1141
1142 VectorSubtract(p->origin, r_refdef.vieworg, vdelta);
1143 Com_Printf("up:%f right:%f\n", DotProduct(vdelta, ang_up), DotProduct(vdelta, ang_right));
1144
1145 ProjectPointOnPlane(temp_up[2], ang_up, tempfor);
1146 VectorNormalize(temp_up[2]);
1147
1148 VectorScale(ang_up, dot, temp_up[0]);
1149 VectorScale(temp_up[2], 1 - dot, temp_up[1]);
1150 VectorAdd(temp_up[1], temp_up[0], ang_up);
1151
1152 len = 1 + dot * (len - 1);
1153
1154 /* dont mess with stuff harder than needed */
1155 if (dot < 0.015) {
1156 len = 1;
1157 VectorCopy(up, ang_up);
1158 VectorCopy(right, ang_right);
1159 }
1160 }
1161 VectorScale(ang_right, 0.75, ang_right);
1162 VectorScale(ang_up, 0.75 * len, ang_up);
1163
1164 VectorAdd(ang_up, ang_right, angl_coord[0]);
1165 VectorSubtract(ang_right, ang_up, angl_coord[1]);
1166 VectorNegate(angl_coord[0], angl_coord[2]);
1167 VectorNegate(angl_coord[1], angl_coord[3]);
1168
1169 qglPushMatrix();
1170 {
1171 qglTranslatef(p->origin[0], p->origin[1], p->origin[2]);
1172 qglScalef(size, size, size);
1173
1174 qglBegin(GL_QUADS);
1175 {
1176 qglTexCoord2f(0, 1);
1177 qglVertex3fv(angl_coord[0]);
1178 qglTexCoord2f(0, 0);
1179 qglVertex3fv(angl_coord[1]);
1180 qglTexCoord2f(1, 0);
1181 qglVertex3fv(angl_coord[2]);
1182 qglTexCoord2f(1, 1);
1183 qglVertex3fv(angl_coord[3]);
1184 }
1185 qglEnd();
1186 }
1187 qglPopMatrix();
1188 } else if (p->flags & PART_ANGLED) { /* facing direction...
1189 * (decal wannabes) */
1190 vec3_t angl_coord[4];
1191 vec3_t ang_up, ang_right, ang_forward;
1192
1193 AngleVectors(p->angle, ang_forward, ang_right, ang_up);
1194
1195 VectorScale(ang_right, 0.75, ang_right);
1196 VectorScale(ang_up, 0.75, ang_up);
1197
1198 VectorAdd(ang_up, ang_right, angl_coord[0]);
1199 VectorSubtract(ang_right, ang_up, angl_coord[1]);
1200 VectorNegate(angl_coord[0], angl_coord[2]);
1201 VectorNegate(angl_coord[1], angl_coord[3]);
1202
1203 if (p->flags & PART_DEPTHHACK) {
1204 qglDisable(GL_CULL_FACE);
1205 qglPushMatrix();
1206 {
1207 if (p->flags & (PART_DEPTHHACK_SHORT | PART_DEPTHHACK_MID | PART_DEPTHHACK_LONG)) {
1208 VectorMA(p->origin, size, angl_coord[0], angl_coord[0]);
1209 VectorMA(p->origin, size, angl_coord[1], angl_coord[1]);
1210 VectorMA(p->origin, size, angl_coord[2], angl_coord[2]);
1211 VectorMA(p->origin, size, angl_coord[3], angl_coord[3]);
1212 } else {
1213 qglTranslatef(p->origin[0], p->origin[1], p->origin[2]);
1214 qglScalef(size, size, size);
1215 }
1216
1217 qglBegin(GL_QUADS);
1218 {
1219 qglTexCoord2f(0, 1);
1220 qglVertex3fv(angl_coord[0]);
1221 qglTexCoord2f(0, 0);
1222 qglVertex3fv(angl_coord[1]);
1223 qglTexCoord2f(1, 0);
1224 qglVertex3fv(angl_coord[2]);
1225 qglTexCoord2f(1, 1);
1226 qglVertex3fv(angl_coord[3]);
1227 }
1228 qglEnd();
1229 }
1230 qglPopMatrix();
1231 qglEnable(GL_CULL_FACE);
1232 }
1233 } else { /* normal sprites */
1234 qglPushMatrix();
1235 {
1236 if (!(p->flags & PART_DEPTHHACK)) {
1237 qglTranslatef(p->origin[0], p->origin[1], p->origin[2]);
1238 qglScalef(size, size, size);
1239 }
1240 qglBegin(GL_QUADS);
1241 {
1242 if (p->angle[2]) { /* if we have roll, we
1243 * do calcs */
1244 vec3_t angl_coord[4];
1245 vec3_t ang_up, ang_right,
1246 ang_forward;
1247
1248 VectorSubtract(p->origin, r_refdef.vieworg, angl_coord[0]);
1249
1250 vectoanglerolled(angl_coord[0], p->angle[2], angl_coord[1]);
1251 AngleVectors(angl_coord[1], ang_forward, ang_right, ang_up);
1252
1253 VectorScale(ang_forward, 0.75, ang_forward);
1254 VectorScale(ang_right, 0.75, ang_right);
1255 VectorScale(ang_up, 0.75, ang_up);
1256
1257 VectorAdd(ang_up, ang_right, angl_coord[0]);
1258 VectorSubtract(ang_right, ang_up, angl_coord[1]);
1259 VectorNegate(angl_coord[0], angl_coord[2]);
1260 VectorNegate(angl_coord[1], angl_coord[3]);
1261
1262 if (p->flags & PART_DEPTHHACK) {
1263 VectorMA(p->origin, size, angl_coord[0], angl_coord[0]);
1264 VectorMA(p->origin, size, angl_coord[1], angl_coord[1]);
1265 VectorMA(p->origin, size, angl_coord[2], angl_coord[2]);
1266 VectorMA(p->origin, size, angl_coord[3], angl_coord[3]);
1267 }
1268 qglTexCoord2f(0, 1);
1269 qglVertex3fv(angl_coord[0]);
1270 qglTexCoord2f(0, 0);
1271 qglVertex3fv(angl_coord[1]);
1272 qglTexCoord2f(1, 0);
1273 qglVertex3fv(angl_coord[2]);
1274 qglTexCoord2f(1, 1);
1275 qglVertex3fv(angl_coord[3]);
1276 } else if (p->flags & PART_DEPTHHACK) {
1277 vec3_t angl_coord[4];
1278
1279 VectorMA(p->origin, size, coord[0], angl_coord[0]);
1280 VectorMA(p->origin, size, coord[1], angl_coord[1]);
1281 VectorMA(p->origin, size, coord[2], angl_coord[2]);
1282 VectorMA(p->origin, size, coord[3], angl_coord[3]);
1283
1284 qglTexCoord2f(0, 1);
1285 qglVertex3fv(angl_coord[0]);
1286 qglTexCoord2f(0, 0);
1287 qglVertex3fv(angl_coord[1]);
1288 qglTexCoord2f(1, 0);
1289 qglVertex3fv(angl_coord[2]);
1290 qglTexCoord2f(1, 1);
1291 qglVertex3fv(angl_coord[3]);
1292 } else {
1293 qglTexCoord2f(0, 1);
1294 qglVertex3fv(coord[0]);
1295 qglTexCoord2f(0, 0);
1296 qglVertex3fv(coord[1]);
1297 qglTexCoord2f(1, 0);
1298 qglVertex3fv(coord[2]);
1299 qglTexCoord2f(1, 1);
1300 qglVertex3fv(coord[3]);
1301
1302 }
1303 }
1304 qglEnd();
1305 }
1306 qglPopMatrix();
1307 }
1308
1309 if (p->flags & PART_DEPTHHACK)
1310 qglDepthRange(gldepthmin, gldepthmax);
1311 }
1312
1313 qglDepthRange(gldepthmin, gldepthmax);
1314 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1315 GL_TexEnv(GL_MODULATE);
1316 qglDepthMask(true);
1317 qglDisable(GL_BLEND);
1318 qglColor4f(1, 1, 1, 1);
1319 }
1320 #else
1321 void
GL_DrawParticles(int num_particles,const particle_t particles[],const unsigned colortable[768])1322 GL_DrawParticles(int num_particles, const particle_t particles[], const unsigned colortable[768])
1323 {
1324 const particle_t *p;
1325 int i;
1326 vec3_t up, right;
1327 float scale;
1328 byte color[4];
1329
1330 GL_Bind(r_particletexture->texnum);
1331 qglDepthMask(GL_FALSE); /* no z buffering */
1332 qglEnable(GL_BLEND);
1333 GL_TexEnv(GL_MODULATE);
1334 qglBegin(GL_TRIANGLES);
1335
1336 VectorScale(vup, 1.5, up);
1337 VectorScale(vright, 1.5, right);
1338
1339 for (p = particles, i = 0; i < num_particles; i++, p++) {
1340 /* hack a scale up to keep particles from disapearing */
1341 scale = (p->origin[0] - r_origin[0]) * vpn[0] +
1342 (p->origin[1] - r_origin[1]) * vpn[1] +
1343 (p->origin[2] - r_origin[2]) * vpn[2];
1344
1345 if (scale < 20)
1346 scale = 1;
1347 else
1348 scale = 1 + scale * 0.004;
1349
1350 *(int *)color = colortable[p->color];
1351 color[3] = p->alpha * 255;
1352
1353 qglColor4ubv(color);
1354
1355 qglTexCoord2f(0.0625, 0.0625);
1356 qglVertex3fv(p->origin);
1357
1358 qglTexCoord2f(1.0625, 0.0625);
1359 qglVertex3f(p->origin[0] + up[0] * scale,
1360 p->origin[1] + up[1] * scale,
1361 p->origin[2] + up[2] * scale);
1362
1363 qglTexCoord2f(0.0625, 1.0625);
1364 qglVertex3f(p->origin[0] + right[0] * scale,
1365 p->origin[1] + right[1] * scale,
1366 p->origin[2] + right[2] * scale);
1367 }
1368
1369 qglEnd();
1370 qglDisable(GL_BLEND);
1371 qglColor4f(1, 1, 1, 1);
1372 qglDepthMask(1); /* back to normal Z buffering */
1373 GL_TexEnv(GL_REPLACE);
1374 }
1375 #endif
1376
1377 /*
1378 * =============== R_DrawParticles ===============
1379 */
1380 #ifdef QMAX
1381 void
R_DrawParticles(qboolean inWater)1382 R_DrawParticles(qboolean inWater)
1383 {
1384 qglDisable(GL_FOG); /* no fogging my precious */
1385
1386 GL_DrawParticles(r_refdef.num_particles, inWater);
1387
1388 /* Dont know if it was on... */
1389 /* qglEnable(GL_FOG); */
1390 }
1391 #else
1392 void
R_DrawParticles(void)1393 R_DrawParticles(void)
1394 {
1395 if (gl_particles->value) {
1396 const particle_t *p;
1397 int i, k;
1398 vec3_t up, right;
1399 float scale, size = 1.0, r, g, b;
1400
1401 qglDepthMask(GL_FALSE); /* no z buffering */
1402 qglEnable(GL_BLEND);
1403 GL_TexEnv(GL_MODULATE);
1404 qglEnable(GL_TEXTURE_2D);
1405 qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
1406
1407 /* Vertex arrays */
1408 qglEnableClientState(GL_VERTEX_ARRAY);
1409 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
1410 qglEnableClientState(GL_COLOR_ARRAY);
1411
1412 qglTexCoordPointer(2, GL_FLOAT, sizeof(tex_array[0]), tex_array[0]);
1413 qglVertexPointer(3, GL_FLOAT, sizeof(vert_array[0]), vert_array[0]);
1414 qglColorPointer(4, GL_FLOAT, sizeof(col_array[0]), col_array[0]);
1415
1416 GL_Bind(r_particletexture->texnum);
1417
1418 VectorScale(vup, size, up);
1419 VectorScale(vright, size, right);
1420
1421 for (p = r_refdef.particles, i = 0, k = 0; i < r_refdef.num_particles; i++, p++, k += 4) {
1422 /* hack a scale up to keep particles from disapearing */
1423 scale = (p->origin[0] - r_origin[0]) * vpn[0] +
1424 (p->origin[1] - r_origin[1]) * vpn[1] +
1425 (p->origin[2] - r_origin[2]) * vpn[2];
1426
1427 scale = (scale < 20) ? 1 : 1 + scale * 0.0004;
1428
1429 r = d_8to24tablef[p->color & 0xFF][0];
1430 g = d_8to24tablef[p->color & 0xFF][1];
1431 b = d_8to24tablef[p->color & 0xFF][2];
1432
1433 VA_SetElem2(tex_array[k], 0, 0);
1434 VA_SetElem4(col_array[k], r, g, b, p->alpha);
1435 VA_SetElem3(vert_array[k], p->origin[0] - (up[0] * scale) - (right[0] * scale), p->origin[1] - (up[1] * scale) - (right[1] * scale), p->origin[2] - (up[2] * scale) - (right[2] * scale));
1436
1437 VA_SetElem2(tex_array[k + 1], 1, 0);
1438 VA_SetElem4(col_array[k + 1], r, g, b, p->alpha);
1439 VA_SetElem3(vert_array[k + 1], p->origin[0] + (up[0] * scale) - (right[0] * scale), p->origin[1] + (up[1] * scale) - (right[1] * scale), p->origin[2] + (up[2] * scale) - (right[2] * scale));
1440
1441 VA_SetElem2(tex_array[k + 2], 1, 1);
1442 VA_SetElem4(col_array[k + 2], r, g, b, p->alpha);
1443 VA_SetElem3(vert_array[k + 2], p->origin[0] + (right[0] * scale) + (up[0] * scale), p->origin[1] + (right[1] * scale) + (up[1] * scale), p->origin[2] + (right[2] * scale) + (up[2] * scale));
1444
1445 VA_SetElem2(tex_array[k + 3], 0, 1);
1446 VA_SetElem4(col_array[k + 3], r, g, b, p->alpha);
1447 VA_SetElem3(vert_array[k + 3], p->origin[0] + (right[0] * scale) - (up[0] * scale), p->origin[1] + (right[1] * scale) - (up[1] * scale), p->origin[2] + (right[2] * scale) - (up[2] * scale));
1448 }
1449
1450 qglDrawArrays(GL_QUADS, 0, k);
1451
1452 qglDisable(GL_BLEND);
1453 qglColor3f(1, 1, 1);
1454 qglDepthMask(1);/* back to normal Z buffering */
1455 GL_TexEnv(GL_REPLACE);
1456 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1457 qglDisableClientState(GL_VERTEX_ARRAY);
1458 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
1459 qglDisableClientState(GL_COLOR_ARRAY);
1460 } else if (gl_ext_pointparameters->value && qglPointParameterfEXT) {
1461 int i;
1462 unsigned char color[4];
1463 const particle_t *p;
1464
1465 qglDepthMask(GL_FALSE);
1466 qglEnable(GL_BLEND);
1467 qglDisable(GL_TEXTURE_2D);
1468
1469 qglPointSize(gl_particle_size->value);
1470
1471 qglBegin(GL_POINTS);
1472 for (i = 0, p = r_refdef.particles; i < r_refdef.num_particles; i++, p++) {
1473 *(int *)color = d_8to24table[p->color];
1474 color[3] = p->alpha * 255;
1475
1476 qglColor4ubv(color);
1477
1478 qglVertex3fv(p->origin);
1479 }
1480 qglEnd();
1481
1482 qglDisable(GL_BLEND);
1483 qglColor4f(1.0, 1.0, 1.0, 1.0);
1484 qglDepthMask(GL_TRUE);
1485 qglEnable(GL_TEXTURE_2D);
1486
1487 } else {
1488 GL_DrawParticles(r_refdef.num_particles, r_refdef.particles, d_8to24table);
1489 }
1490 }
1491 #endif
1492
1493 /*
1494 * ============ R_PolyBlend ============
1495 */
1496 void
R_PolyBlend(void)1497 R_PolyBlend(void)
1498 {
1499 if (!gl_polyblend->value)
1500 return;
1501 if (!v_blend[3])
1502 return;
1503
1504 qglDisable(GL_ALPHA_TEST);
1505 qglEnable(GL_BLEND);
1506 qglDisable(GL_DEPTH_TEST);
1507 qglDisable(GL_TEXTURE_2D);
1508
1509 qglLoadIdentity();
1510
1511 /* FIXME: get rid of these */
1512 qglRotatef(-90, 1, 0, 0); /* put Z going up */
1513 qglRotatef(90, 0, 0, 1);/* put Z going up */
1514
1515 qglColor4fv(v_blend);
1516
1517 qglBegin(GL_QUADS);
1518
1519 qglVertex3f(10, 100, 100);
1520 qglVertex3f(10, -100, 100);
1521 qglVertex3f(10, -100, -100);
1522 qglVertex3f(10, 100, -100);
1523 qglEnd();
1524
1525 qglDisable(GL_BLEND);
1526 qglEnable(GL_TEXTURE_2D);
1527 qglEnable(GL_ALPHA_TEST);
1528
1529 qglColor4f(1, 1, 1, 1);
1530 }
1531
1532 /* ======================================================================= */
1533
1534 int
SignbitsForPlane(cplane_t * out)1535 SignbitsForPlane(cplane_t * out)
1536 {
1537 int bits, j;
1538
1539 /* for fast box on planeside test */
1540
1541 bits = 0;
1542 for (j = 0; j < 3; j++) {
1543 if (out->normal[j] < 0)
1544 bits |= 1 << j;
1545 }
1546 return bits;
1547 }
1548
1549
1550 void
R_SetFrustum(void)1551 R_SetFrustum(void)
1552 {
1553 int i;
1554
1555 /* rotate VPN right by FOV_X/2 degrees */
1556 RotatePointAroundVector(frustum[0].normal, vup, vpn, -(90 - r_refdef.fov_x / 2));
1557 /* rotate VPN left by FOV_X/2 degrees */
1558 RotatePointAroundVector(frustum[1].normal, vup, vpn, 90 - r_refdef.fov_x / 2);
1559 /* rotate VPN up by FOV_X/2 degrees */
1560 RotatePointAroundVector(frustum[2].normal, vright, vpn, 90 - r_refdef.fov_y / 2);
1561 /* rotate VPN down by FOV_X/2 degrees */
1562 RotatePointAroundVector(frustum[3].normal, vright, vpn, -(90 - r_refdef.fov_y / 2));
1563
1564 for (i = 0; i < 4; i++) {
1565 frustum[i].type = PLANE_ANYZ;
1566 frustum[i].dist = DotProduct(r_origin, frustum[i].normal);
1567 frustum[i].signbits = SignbitsForPlane(&frustum[i]);
1568 }
1569 }
1570
1571 /* ======================================================================= */
1572
1573 /*
1574 * =============== R_SetupFrame ===============
1575 */
1576 void
R_SetupFrame(void)1577 R_SetupFrame(void)
1578 {
1579 int i;
1580 mleaf_t *leaf;
1581
1582 r_framecount++;
1583
1584 /* build the transformation matrix for the given view angles */
1585 VectorCopy(r_refdef.vieworg, r_origin);
1586
1587 if (!g_drawing_refl) {
1588
1589 /* build the transformation matrix for the given view angles */
1590 AngleVectors(r_refdef.viewangles, vpn, vright, vup);
1591 }
1592 /* start MPO */
1593
1594 /*
1595 * we want to look from the mirrored origin's perspective when
1596 * drawing reflections
1597 */
1598 if (g_drawing_refl) {
1599 float distance;
1600
1601 distance = DotProduct(r_origin, waterNormals[g_active_refl]) - g_waterDistance2[g_active_refl];
1602 VectorMA(r_refdef.vieworg, distance * -2, waterNormals[g_active_refl], r_origin);
1603
1604 if (!(r_refdef.rdflags & RDF_NOWORLDMODEL)) {
1605 vec3_t temp;
1606
1607 temp[0] = g_refl_X[g_active_refl]; /* sets PVS over x */
1608 temp[1] = g_refl_Y[g_active_refl]; /* and y coordinate of water surface */
1609
1610 VectorCopy(r_origin, temp);
1611 if (r_refdef.rdflags & RDF_UNDERWATER) {
1612 temp[2] = g_refl_Z[g_active_refl] - 1; /* just above water level */
1613 } else {
1614 temp[2] = g_refl_Z[g_active_refl] + 1; /* just below water level */
1615 }
1616
1617 leaf = Mod_PointInLeaf(temp, r_worldmodel);
1618
1619 if (!(leaf->contents & CONTENTS_SOLID) &&
1620 (leaf->cluster != r_viewcluster)) {
1621 r_viewcluster2 = leaf->cluster;
1622 }
1623 }
1624 return;
1625 }
1626 /* stop MPO */
1627
1628 /* current viewcluster */
1629 if (!(r_refdef.rdflags & RDF_NOWORLDMODEL)) {
1630 r_oldviewcluster = r_viewcluster;
1631 r_oldviewcluster2 = r_viewcluster2;
1632 leaf = Mod_PointInLeaf(r_origin, r_worldmodel);
1633 r_viewcluster = r_viewcluster2 = leaf->cluster;
1634
1635 /*
1636 * check above and below so crossing solid water doesn't draw
1637 * wrong
1638 */
1639 if (!leaf->contents) { /* look down a bit */
1640 vec3_t temp;
1641
1642 VectorCopy(r_origin, temp);
1643 temp[2] -= 16;
1644 leaf = Mod_PointInLeaf(temp, r_worldmodel);
1645 if (!(leaf->contents & CONTENTS_SOLID) &&
1646 (leaf->cluster != r_viewcluster2))
1647 r_viewcluster2 = leaf->cluster;
1648 } else { /* look up a bit */
1649 vec3_t temp;
1650
1651 VectorCopy(r_origin, temp);
1652 temp[2] += 16;
1653 leaf = Mod_PointInLeaf(temp, r_worldmodel);
1654 if (!(leaf->contents & CONTENTS_SOLID) &&
1655 (leaf->cluster != r_viewcluster2))
1656 r_viewcluster2 = leaf->cluster;
1657 }
1658 }
1659 for (i = 0; i < 4; i++)
1660 v_blend[i] = r_refdef.blend[i];
1661
1662 c_brush_polys = 0;
1663 c_alias_polys = 0;
1664
1665 /* clear out the portion of the screen that the NOWORLDMODEL defines */
1666 if (r_refdef.rdflags & RDF_NOWORLDMODEL) {
1667 qglEnable(GL_SCISSOR_TEST);
1668 qglScissor(r_refdef.x, vid.height - r_refdef.height - r_refdef.y, r_refdef.width, r_refdef.height);
1669 if (!(r_refdef.rdflags & RDF_NOCLEAR)) {
1670 qglClearColor(0.3, 0.3, 0.3, 1);
1671 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1672 qglClearColor(1, 0, 0.5, 0.5);
1673 }
1674 qglDisable(GL_SCISSOR_TEST);
1675 }
1676 }
1677
1678
1679 void
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)1680 MYgluPerspective(GLdouble fovy, GLdouble aspect,
1681 GLdouble zNear, GLdouble zFar)
1682 {
1683 GLdouble xmin , xmax, ymin, ymax;
1684
1685 ymax = zNear * tan(fovy * M_PI / 360.0);
1686 ymin = -ymax;
1687
1688 xmin = ymin * aspect;
1689 xmax = ymax * aspect;
1690
1691 xmin += -(2 * gl_state.camera_separation) / zNear;
1692 xmax += -(2 * gl_state.camera_separation) / zNear;
1693
1694 qglFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
1695 }
1696
1697
1698 /*
1699 * ============= R_SetupGL =============
1700 */
1701 void
R_SetupGL(void)1702 R_SetupGL(void)
1703 {
1704 static GLdouble farz; /* DMP skybox size change */
1705 GLdouble boxsize;/* DMP skybox size change */
1706 int x, x2, y2, y, w, h;
1707 float screenaspect;
1708
1709 /* Knightmare- update gl_modulate in real time */
1710 /* FIXME NightHunters demos */
1711 if (gl_modulate->modified && (r_worldmodel)) { /* Don't do this if no map is loaded */
1712 msurface_t *surf;
1713 int i;
1714
1715 for (i=0,surf = r_worldmodel->surfaces; i<r_worldmodel->numsurfaces; i++,surf++)
1716 surf->cached_light[0]=0;
1717 gl_modulate->modified = 0;
1718 }
1719
1720 /* set up viewport */
1721 x = floor(r_refdef.x * vid.width / vid.width);
1722 x2 = ceil((r_refdef.x + r_refdef.width) * vid.width / vid.width);
1723 y = floor(vid.height - r_refdef.y * vid.height / vid.height);
1724 y2 = ceil(vid.height - (r_refdef.y + r_refdef.height) * vid.height / vid.height);
1725
1726 w = x2 - x;
1727 h = y - y2;
1728
1729 if (skydistance->modified) {
1730 skydistance->modified = false;
1731 boxsize = skydistance->value;
1732 boxsize -= 252 * ceil(boxsize / 2300);
1733 farz = 1.0;
1734 while (farz < boxsize) { /* DMP: make this value a
1735 * power-of-2 */
1736 farz *= 2.0;
1737 if (farz >= 65536.0) /* DMP: don't make it larger
1738 * than this */
1739 break;
1740 }
1741 farz *= 2.0; /* DMP: double since boxsize is distance from camera to */
1742 /* edge of skybox - not total size of skybox */
1743 ri.Con_Printf(PRINT_DEVELOPER, "farz now set to %g\n", farz);
1744 }
1745
1746 /*
1747 * MPO : we only want to set the viewport if we aren't drawing the
1748 * reflection
1749 */
1750 if (!g_drawing_refl) {
1751 qglViewport(x, y2, w, h); /* MPO : note this happens every
1752 * frame interestingly enough
1753 */
1754 } else {
1755 qglViewport(0, 0, g_reflTexW, g_reflTexH); /* width/height of texture size,
1756 * not screen size
1757 */
1758 }
1759 /* stop MPO */
1760
1761 /* set up projection matrix */
1762 screenaspect = (float)r_refdef.width / r_refdef.height;
1763
1764 /*
1765 * yfov =
1766 * 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI;
1767 */
1768 qglMatrixMode(GL_PROJECTION);
1769 qglLoadIdentity();
1770
1771 /* MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096); */
1772 MYgluPerspective(r_refdef.fov_y, screenaspect, 4, farz); /* DMP skybox */
1773
1774
1775 qglCullFace(GL_FRONT);
1776
1777 qglMatrixMode(GL_MODELVIEW);
1778 qglLoadIdentity();
1779
1780 qglRotatef(-90, 1, 0, 0); /* put Z going up */
1781 qglRotatef(90, 0, 0, 1);/* put Z going up */
1782
1783 /*
1784 * MPO : +Z is up, +X is forward, +Y is left according to my
1785 * calculations
1786 */
1787
1788 /* start MPO */
1789 /* standard transformation */
1790 if (!g_drawing_refl) {
1791
1792 qglRotatef(-r_refdef.viewangles[2], 1, 0, 0); /* MPO : this handles rolling (ie when we
1793 * strafe side to side we roll slightly) */
1794 qglRotatef(-r_refdef.viewangles[0], 0, 1, 0); /* MPO : this handles up/down rotation */
1795 qglRotatef(-r_refdef.viewangles[1], 0, 0, 1); /* MPO : this handles left/right rotation */
1796 qglTranslatef(-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
1797
1798 /*
1799 * MPO : this translate call puts the player at the proper
1800 * spot in the map
1801 */
1802 /* MPO : The map is drawn to absolute coordinates */
1803 }
1804 /* mirrored transformation for reflection */
1805 else {
1806
1807 R_DoReflTransform(true);
1808 }
1809 /* end MPO */
1810 if (gl_state.camera_separation != 0 && gl_state.stereo_enabled)
1811 qglTranslatef(gl_state.camera_separation, 0, 0);
1812
1813 qglGetFloatv(GL_MODELVIEW_MATRIX, r_world_matrix);
1814
1815 /* set drawing parms */
1816 if ((gl_cull->value) && (!g_drawing_refl)) /* MPO : we must disable culling when drawing the reflection */
1817 qglEnable(GL_CULL_FACE);
1818 else
1819 qglDisable(GL_CULL_FACE);
1820
1821 qglDisable(GL_BLEND);
1822 qglDisable(GL_ALPHA_TEST);
1823 qglEnable(GL_DEPTH_TEST);
1824 }
1825
1826 /*
1827 * ============= R_Clear =============
1828 */
1829 void
R_Clear(void)1830 R_Clear(void)
1831 {
1832
1833 if (gl_clear->value) {
1834 qglClearColor(0.5f, 0.5f, 0.5f, 1.0f);
1835 qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1836 }
1837 else {
1838 qglClear(GL_DEPTH_BUFFER_BIT);
1839 }
1840
1841 if (have_stencil) {
1842 qglClearStencil(1);
1843 qglClear(GL_STENCIL_BUFFER_BIT);
1844 }
1845
1846 gldepthmin = 0;
1847 gldepthmax = 1;
1848 qglDepthFunc(GL_LEQUAL);
1849
1850 qglDepthRange(gldepthmin, gldepthmax);
1851
1852 }
1853
1854 void
R_Flash(void)1855 R_Flash(void)
1856 {
1857 R_PolyBlend();
1858 }
1859
1860 void
setupModelLighting(void)1861 setupModelLighting(void)
1862 {
1863
1864 int lnum;
1865 int newNumGlLights;
1866 float vec4[4] = {1, 1, 1, 1};
1867
1868 lnum = 0;
1869 newNumGlLights = 0;
1870
1871 qglLightModelfv(GL_LIGHT_MODEL_AMBIENT, vec4);
1872 qglMaterialfv(GL_FRONT, GL_DIFFUSE, vec4);
1873 /* qglMaterialfv ( GL_FRONT, GL_AMBIENT, vec4 ); */
1874 qglColorMaterial(GL_FRONT, GL_AMBIENT);
1875
1876
1877 for (; (lnum < r_refdef.num_dlights) && (newNumGlLights < 8); lnum++) {
1878 dlight_t *dl = &r_refdef.dlights[lnum];
1879
1880 if (dl->intensity <= 64)
1881 continue;
1882
1883 memcpy(vec4, dl->origin, sizeof(dl->origin));
1884 qglLightfv(GL_LIGHT0 + newNumGlLights, GL_POSITION, vec4);
1885
1886 qglLightf(GL_LIGHT0 + newNumGlLights,
1887 GL_QUADRATIC_ATTENUATION,
1888 0.000000001 * dl->intensity);
1889
1890 memcpy(vec4, dl->color, sizeof(dl->color));
1891 vec4[0] *= gl_modulate->value;
1892 vec4[1] *= gl_modulate->value;
1893 vec4[2] *= gl_modulate->value;
1894 qglLightfv(GL_LIGHT0 + newNumGlLights, GL_DIFFUSE, vec4);
1895
1896 ++newNumGlLights;
1897 }
1898
1899 if (newNumGlLights < g_numGlLights) {
1900 while (g_numGlLights != newNumGlLights) {
1901 --g_numGlLights;
1902 qglDisable(GL_LIGHT0 + g_numGlLights);
1903 }
1904 } else if (g_numGlLights != newNumGlLights)
1905 g_numGlLights = newNumGlLights;
1906 }
1907
1908 /*
1909 * ================ R_RenderView
1910 *
1911 * r_refdef must be set before the first call ================
1912 */
1913 void
R_RenderView(refdef_t * fd)1914 R_RenderView(refdef_t * fd)
1915 {
1916 #ifdef QMAX
1917 qboolean inWater;
1918 #endif
1919 vec3_t colors; /* Fog */
1920
1921 if (r_norefresh->value)
1922 return;
1923
1924 r_refdef = *fd;
1925
1926 /* (gl_scale) NiceAss: Scale back up from client's false width/height */
1927 r_refdef.width *= cl_hudscale->value;
1928 r_refdef.height *= cl_hudscale->value;
1929 r_refdef.x *= cl_hudscale->value;
1930 r_refdef.y *= cl_hudscale->value;
1931
1932 if (!r_worldmodel && !(r_refdef.rdflags & RDF_NOWORLDMODEL))
1933 ri.Sys_Error(ERR_DROP, "R_RenderView: NULL worldmodel");
1934
1935 if (r_speeds->value) {
1936 c_brush_polys = 0;
1937 c_alias_polys = 0;
1938 }
1939 R_PushDlights();
1940
1941 if (gl_finish->value)
1942 qglFinish();
1943
1944 if ((r_refdef.num_newstains > 0) && (gl_stainmaps->value)) {
1945 R_ApplyStains();
1946 }
1947 R_SetupGL(); /* MPO moved here .. */
1948
1949 R_SetupFrame();
1950
1951 R_SetFrustum();
1952
1953 setupClippingPlanes(); /* MPO clipping planes for water */
1954
1955 /* R_SetupGL (); */
1956
1957 R_MarkLeaves(); /* done here so we know if we're in water */
1958
1959 drawPlayerReflection();
1960
1961 R_DrawWorld();
1962
1963 #ifdef QMAX
1964 if (r_refdef.rdflags & RDF_NOWORLDMODEL || !gl_transrendersort->value) {
1965 inWater = false;
1966 } else {
1967 inWater = Mod_PointInLeaf(fd->vieworg, r_worldmodel)->contents;
1968 }
1969 if (!(r_refdef.rdflags & RDF_NOWORLDMODEL) && gl_transrendersort->value) {
1970 R_SortParticlesOnList(r_refdef.num_particles, r_refdef.particles);
1971 R_SortEntitiesOnList(inWater);
1972 }
1973 #endif
1974
1975 R_AddDecals(); /* Decals */
1976
1977 if (gl_flares->value) {
1978 if (gl_fogenable->value /*|| gl_fogunderwater->value*/) {
1979 qglDisable(GL_FOG);
1980 R_RenderFlares();
1981 qglEnable(GL_FOG);
1982 }
1983 else {
1984 R_RenderFlares();
1985 }
1986 }
1987
1988 setupModelLighting(); /* dukey sets up opengl dynamic lighting for entitites. */
1989
1990 #ifdef QMAX
1991 R_DrawEntitiesOnList((inWater) ? false : true, true);
1992 #else
1993 R_DrawEntitiesOnList();
1994 #endif
1995
1996 /* R_RenderDlights (); */
1997 #ifdef QMAX
1998 R_DrawParticles((inWater) ? false : true);
1999 #else
2000
2001 if (!gl_ext_texture_compression->value) {
2002 R_BloomBlend(fd); /* BLOOMS */
2003 }
2004 R_DrawParticles();
2005 #endif
2006
2007 if (gl_alpha_surfaces->value) {
2008 R_DrawAlphaSurfaces_Jitspoe();
2009 } else {
2010 R_DrawAlphaSurfaces();
2011 }
2012
2013 #ifdef QMAX
2014 R_DrawEntitiesOnList((inWater) ? true : false, false);
2015
2016 if (!gl_ext_texture_compression->value) {
2017 R_BloomBlend(fd); /* BLOOMS */
2018 }
2019 R_DrawParticles((inWater) ? true : false);
2020 #else
2021 R_DrawParticles();
2022 #endif
2023
2024 /* start MPO */
2025 /* if we are doing a reflection, turn off clipping now */
2026 if (g_drawing_refl) {
2027 qglDisable(GL_CLIP_PLANE0);
2028 }
2029
2030 /*
2031 * if we aren't doing a reflection then we can do the flash and r
2032 * speeds
2033 */
2034 /* (we don't want them showing up in our reflection) */
2035 else {
2036 R_Flash();
2037 }
2038 /* stop MPO */
2039 /* ===================== Engine Fog ================= */
2040 qglDisable(GL_FOG);
2041
2042 if (gl_fogenable->value && !(r_refdef.rdflags & RDF_UNDERWATER)) {
2043 qglEnable(GL_FOG);
2044 qglFogi(GL_FOG_MODE, GL_BLEND);
2045 colors[0] = gl_fogred->value;
2046 colors[1] = gl_foggreen->value;
2047 colors[2] = gl_fogblue->value;
2048
2049 qglFogf(GL_FOG_DENSITY, gl_fogdensity->value);
2050 qglFogfv(GL_FOG_COLOR, colors);
2051 qglFogf(GL_FOG_START, gl_fogstart->value);
2052 qglFogf(GL_FOG_END, gl_fogend->value);
2053
2054 } else if (gl_fogunderwater->value && (r_refdef.rdflags & RDF_UNDERWATER)) {
2055 qglEnable(GL_FOG);
2056
2057 qglFogi(GL_FOG_MODE, GL_BLEND);
2058 colors[0] = gl_fogred->value;
2059 colors[1] = gl_foggreen->value;
2060 colors[2] = gl_fogblue->value;
2061
2062 qglFogf(GL_FOG_START, 0.0);
2063 qglFogf(GL_FOG_END, 2048);
2064 qglFogf(GL_FOG_DENSITY, 0.0);
2065
2066 if (inlava) {
2067 colors[0] = 0.7;
2068 }
2069 if (inslime) {
2070 colors[1] = 0.7;
2071 }
2072 if (inwater) {
2073 colors[2] = 0.6;
2074 }
2075
2076 qglFogf(GL_FOG_DENSITY, 0.001);
2077 qglFogf(GL_FOG_START, 0.0);
2078 qglFogfv(GL_FOG_COLOR, colors);
2079 qglFogf(GL_FOG_END, 450);
2080
2081 } else {
2082 qglDisable(GL_FOG);
2083 }
2084
2085 /* ====================== End ======================= */
2086
2087 if (!deathmatch->value && gl_minimap_size->value > 32 && !(r_refdef.rdflags & RDF_IRGOGGLES)) {
2088 {
2089 GLSTATE_DISABLE_ALPHATEST;
2090 GL_DrawRadar();
2091 }
2092 numRadarEnts = 0;
2093 }
2094 }
2095
2096 int
R_DrawRSpeeds(char * S)2097 R_DrawRSpeeds(char *S)
2098 {
2099 return sprintf(S, "%4i wpoly %4i epoly %i tex %i lmaps",
2100
2101 c_brush_polys,
2102 c_alias_polys,
2103 c_visible_textures,
2104 c_visible_lightmaps);
2105 }
2106
2107 unsigned int blurtex = 0;
2108 void
R_MotionBlur(void)2109 R_MotionBlur (void)
2110 {
2111
2112 if (!gl_state.tex_rectangle)
2113 return;
2114
2115 if (gl_state.tex_rectangle) {
2116 if (blurtex) {
2117 GL_TexEnv(GL_MODULATE);
2118 qglDisable(GL_TEXTURE_2D);
2119 qglEnable(GL_TEXTURE_RECTANGLE_NV);
2120 qglEnable(GL_BLEND);
2121 qglDisable(GL_ALPHA_TEST);
2122 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2123 if (gl_motionblur_intensity->value >= 1.0)
2124 qglColor4f(1.0, 1.0, 1.0, 0.45);
2125 else
2126 qglColor4f(1.0, 1.0, 1.0, gl_motionblur_intensity->value);
2127 qglBegin(GL_QUADS);
2128 {
2129 qglTexCoord2f(0, vid.height);
2130 qglVertex2f(0, 0);
2131 qglTexCoord2f(vid.width, vid.height);
2132 qglVertex2f(vid.width, 0);
2133 qglTexCoord2f(vid.width, 0);
2134 qglVertex2f(vid.width, vid.height);
2135 qglTexCoord2f(0, 0);
2136 qglVertex2f(0, vid.height);
2137 }
2138 qglEnd();
2139 qglDisable(GL_TEXTURE_RECTANGLE_NV);
2140 qglEnable(GL_TEXTURE_2D);
2141 }
2142 if (!blurtex)
2143 qglGenTextures(1, &blurtex);
2144 qglBindTexture(GL_TEXTURE_RECTANGLE_NV, blurtex);
2145 qglCopyTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, 0, 0, vid.width, vid.height, 0);
2146 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2147 qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2148 }
2149 }
2150
2151 void
R_SetGL2D(void)2152 R_SetGL2D(void)
2153 {
2154 /* set 2D virtual screen size */
2155 qglViewport(0, 0, vid.width, vid.height);
2156 qglMatrixMode(GL_PROJECTION);
2157 qglLoadIdentity();
2158 /* NiceAss: Scale the screen */
2159 qglOrtho(0, vid.width / cl_hudscale->value, vid.height / cl_hudscale->value, 0, -99999, 99999);
2160 /* qglOrtho (0, vid.width, vid.height, 0, -99999, 99999); */
2161
2162 qglMatrixMode(GL_MODELVIEW);
2163 qglLoadIdentity();
2164 qglDisable(GL_DEPTH_TEST);
2165 qglDisable(GL_CULL_FACE);
2166 if (gl_motionblur->value == 1 && r_refdef.rdflags & RDF_UNDERWATER)
2167 R_MotionBlur();
2168 else if (gl_motionblur->value == 2)
2169 R_MotionBlur();
2170 qglDisable(GL_BLEND);
2171 qglEnable(GL_ALPHA_TEST);
2172 qglColor4f(1, 1, 1, 1);
2173 /* ECHON */
2174 if (r_speeds->value) {
2175 char S[128];
2176 int n = 0;
2177 int i;
2178
2179 n = R_DrawRSpeeds(S);
2180
2181 for (i = 0; i < n; i++)
2182 Draw_Char(r_refdef.width - 4 + ((i - n) * 8), r_refdef.height - 40, 128 + S[i], 255);
2183 }
2184 }
2185
2186 static void
GL_DrawColoredStereoLinePair(float r,float g,float b,float y)2187 GL_DrawColoredStereoLinePair(float r, float g, float b, float y)
2188 {
2189 qglColor3f(r, g, b);
2190 qglVertex2f(0, y);
2191 qglVertex2f(vid.width, y);
2192 qglColor3f(0, 0, 0);
2193 qglVertex2f(0, y + 1);
2194 qglVertex2f(vid.width, y + 1);
2195 }
2196
2197 static void
GL_DrawStereoPattern(void)2198 GL_DrawStereoPattern(void)
2199 {
2200 int i;
2201
2202 if (!(gl_config.renderer & GL_RENDERER_INTERGRAPH))
2203 return;
2204
2205 if (!gl_state.stereo_enabled)
2206 return;
2207
2208 R_SetGL2D();
2209
2210 qglDrawBuffer(GL_BACK_LEFT);
2211
2212 for (i = 0; i < 20; i++) {
2213 qglBegin(GL_LINES);
2214 GL_DrawColoredStereoLinePair(1, 0, 0, 0);
2215 GL_DrawColoredStereoLinePair(1, 0, 0, 2);
2216 GL_DrawColoredStereoLinePair(1, 0, 0, 4);
2217 GL_DrawColoredStereoLinePair(1, 0, 0, 6);
2218 GL_DrawColoredStereoLinePair(0, 1, 0, 8);
2219 GL_DrawColoredStereoLinePair(1, 1, 0, 10);
2220 GL_DrawColoredStereoLinePair(1, 1, 0, 12);
2221 GL_DrawColoredStereoLinePair(0, 1, 0, 14);
2222 qglEnd();
2223
2224 GLimp_EndFrame();
2225 }
2226 }
2227
2228
2229 /*
2230 * ==================== R_SetLightLevel
2231 *
2232 * ====================
2233 */
2234 void
R_SetLightLevel(void)2235 R_SetLightLevel(void)
2236 {
2237 vec3_t shadelight;
2238
2239 if (r_refdef.rdflags & RDF_NOWORLDMODEL)
2240 return;
2241
2242 /* save off light value for server to look at (BIG HACK!) */
2243
2244 R_LightPoint(r_refdef.vieworg, shadelight);
2245
2246 /* pick the greatest component, which should be the same */
2247 /* as the mono value returned by software */
2248 if (shadelight[0] > shadelight[1]) {
2249 if (shadelight[0] > shadelight[2])
2250 r_lightlevel->value = 150 * shadelight[0];
2251 else
2252 r_lightlevel->value = 150 * shadelight[2];
2253 } else {
2254 if (shadelight[1] > shadelight[2])
2255 r_lightlevel->value = 150 * shadelight[1];
2256 else
2257 r_lightlevel->value = 150 * shadelight[2];
2258 }
2259
2260 }
2261
2262 /*
2263 * @@@@@@@@@@@@@@@@@@@@@ R_RenderFrame
2264 *
2265 * @@@@@@@@@@@@@@@@@@@@@
2266 */
2267 void
R_RenderFrame(refdef_t * fd)2268 R_RenderFrame(refdef_t * fd)
2269 {
2270 /* start MPO */
2271 if (gl_reflection->value) {
2272
2273 r_refdef = *fd; /* need to do this so eye coords
2274 * update b4 frame is drawn */
2275
2276 R_clear_refl(); /* clear our reflections found in last frame */
2277 R_RecursiveFindRefl(r_worldmodel->nodes); /* find reflections for
2278 * this frame */
2279 R_UpdateReflTex(fd); /* render reflections to textures */
2280 } else {
2281 R_clear_refl();
2282 }
2283 /* end MPO */
2284 R_PreRenderDynamic(fd);
2285 R_RenderView(fd);
2286 R_SetLightLevel();
2287 R_SetGL2D();
2288 R_RenderGlares(fd);
2289
2290 /* start MPO */
2291 /* if debugging is enabled and reflections are enabled.. draw it */
2292 if ((gl_reflection_debug->value) && (g_refl_enabled)) {
2293 R_DrawDebugReflTexture();
2294 }
2295 /* end MPO */
2296 }
2297
2298
2299 void
R_Register(void)2300 R_Register(void)
2301 {
2302
2303 cl_hudscale = ri.Cvar_Get("cl_hudscale", "1", CVAR_ARCHIVE);
2304 cl_big_maps = ri.Cvar_Get("cl_big_maps", "1", 0);
2305 cl_3dcam = ri.Cvar_Get("cl_3dcam", "0", CVAR_ARCHIVE);
2306
2307 deathmatch = ri.Cvar_Get("deathmatch", "0", 0);
2308
2309 font_color = ri.Cvar_Get("font_color", "default", CVAR_ARCHIVE);
2310
2311 #ifdef QMAX
2312 gl_partscale = ri.Cvar_Get("gl_partscale", "100", 0);
2313 gl_transrendersort = ri.Cvar_Get("gl_transrendersort", "1", 0);
2314 gl_particlelighting = ri.Cvar_Get("gl_particlelighting", "0.75", 0);
2315 gl_particledistance = ri.Cvar_Get("gl_particledistance", "0", 0);
2316 #else
2317 gl_particle_min_size = ri.Cvar_Get("gl_particle_min_size", "2", 0);
2318 gl_particle_max_size = ri.Cvar_Get("gl_particle_max_size", "40", 0);
2319 gl_particle_size = ri.Cvar_Get("gl_particle_size", "40", 0);
2320 gl_particle_att_a = ri.Cvar_Get("gl_particle_att_a", "0.01", 0);
2321 gl_particle_att_b = ri.Cvar_Get("gl_particle_att_b", "0.0", 0);
2322 gl_particle_att_c = ri.Cvar_Get("gl_particle_att_c", "0.01", 0);
2323 gl_particles = ri.Cvar_Get("gl_particles", "0", CVAR_ARCHIVE);
2324 #endif
2325 gl_stainmaps = ri.Cvar_Get("gl_stainmaps", "0", CVAR_ARCHIVE);
2326 gl_dlight_cutoff = ri.Cvar_Get("gl_dlight_cutoff", "0", CVAR_ARCHIVE);
2327 gl_shellstencil = ri.Cvar_Get("gl_shellstencil", "1", CVAR_ARCHIVE);
2328 gl_nosubimage = ri.Cvar_Get("gl_nosubimage", "0", 0);
2329 gl_modulate = ri.Cvar_Get("gl_modulate", "1", CVAR_ARCHIVE);
2330 gl_log = ri.Cvar_Get("gl_log", "0", 0);
2331 gl_bitdepth = ri.Cvar_Get("gl_bitdepth", "0", 0);
2332 gl_mode = ri.Cvar_Get("gl_mode", "4", CVAR_ARCHIVE);
2333 gl_lightmap = ri.Cvar_Get("gl_lightmap", "0", 0);
2334 gl_shadows = ri.Cvar_Get("gl_shadows", "0", CVAR_ARCHIVE);
2335 gl_shadows_alpha = ri.Cvar_Get("gl_shadows_alpha", "0.5", 0);
2336 gl_dynamic = ri.Cvar_Get("gl_dynamic", "1", 0);
2337 gl_nobind = ri.Cvar_Get("gl_nobind", "0", 0);
2338 gl_round_down = ri.Cvar_Get("gl_round_down", "1", 0);
2339 gl_picmip = ri.Cvar_Get("gl_picmip", "0", 0);
2340 gl_skymip = ri.Cvar_Get("gl_skymip", "0", 0);
2341 gl_showtris = ri.Cvar_Get("gl_showtris", "0", 0);
2342 gl_finish = ri.Cvar_Get("gl_finish", "0", 0);
2343 gl_clear = ri.Cvar_Get("gl_clear", "0", 0);
2344 gl_cull = ri.Cvar_Get("gl_cull", "1", 0);
2345 gl_polyblend = ri.Cvar_Get("gl_polyblend", "1", 0);
2346 gl_flashblend = ri.Cvar_Get("gl_flashblend", "0", 0);
2347 gl_playermip = ri.Cvar_Get("gl_playermip", "0", 0);
2348 gl_monolightmap = ri.Cvar_Get("gl_monolightmap", "0", 0);
2349 gl_driver = ri.Cvar_Get("gl_driver", "libGL.so", CVAR_ARCHIVE);
2350 gl_texturemode = ri.Cvar_Get("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE);
2351 gl_texturealphamode = ri.Cvar_Get("gl_texturealphamode", "default", CVAR_ARCHIVE);
2352 gl_texturesolidmode = ri.Cvar_Get("gl_texturesolidmode", "default", CVAR_ARCHIVE);
2353 gl_lockpvs = ri.Cvar_Get("gl_lockpvs", "0", 0);
2354 gl_ext_mtexcombine = ri.Cvar_Get("gl_ext_mtexcombine", "1", CVAR_ARCHIVE);
2355 gl_vertex_arrays = ri.Cvar_Get("gl_vertex_arrays", "0", CVAR_ARCHIVE);
2356 gl_ext_multitexture = ri.Cvar_Get("gl_ext_multitexture", "1", CVAR_ARCHIVE);
2357 gl_ext_pointparameters = ri.Cvar_Get("gl_ext_pointparameters", "1", CVAR_ARCHIVE);
2358 gl_ext_compiled_vertex_array = ri.Cvar_Get("gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE);
2359 gl_ext_palettedtexture = ri.Cvar_Get("gl_ext_palettedtexture", "0", 0);
2360 gl_drawbuffer = ri.Cvar_Get("gl_drawbuffer", "GL_BACK", 0);
2361 gl_saturatelighting = ri.Cvar_Get("gl_saturatelighting", "0", 0);
2362 gl_3dlabs_broken = ri.Cvar_Get("gl_3dlabs_broken", "1", CVAR_ARCHIVE);
2363 gl_ext_texture_compression = ri.Cvar_Get("gl_ext_texture_compression", "0", CVAR_ARCHIVE);
2364 gl_anisotropic = ri.Cvar_Get("gl_anisotropic", "0", CVAR_ARCHIVE);
2365 gl_anisotropic_avail = ri.Cvar_Get("gl_anisotropic_avail", "0", 0);
2366 gl_nv_fog = ri.Cvar_Get("gl_nv_fog", "0", CVAR_ARCHIVE);
2367 gl_ext_nv_multisample_filter_hint = ri.Cvar_Get("gl_ext_nv_multisample_filter_hint", "fastest", 0);
2368 gl_lightmap_texture_saturation = ri.Cvar_Get("gl_lightmap_texture_saturation", "1", 0);
2369 gl_lightmap_saturation = ri.Cvar_Get("gl_lightmap_saturation", "1", 0);
2370 gl_alpha_surfaces = ri.Cvar_Get("gl_alpha_surfaces", "0", 0);
2371 gl_screenshot_jpeg = ri.Cvar_Get("gl_screenshot_jpeg", "1", CVAR_ARCHIVE);
2372 gl_screenshot_jpeg_quality = ri.Cvar_Get("gl_screenshot_jpeg_quality", "95", CVAR_ARCHIVE);
2373 gl_water_waves = ri.Cvar_Get("gl_water_waves", "0", CVAR_ARCHIVE);
2374 gl_water_caustics = ri.Cvar_Get("gl_water_caustics", "1", CVAR_ARCHIVE);
2375 gl_water_pixel_shader_warp = ri.Cvar_Get("gl_water_pixel_shader_warp", "1", CVAR_ARCHIVE);
2376 gl_blooms = ri.Cvar_Get("gl_blooms", "0", CVAR_ARCHIVE);
2377 gl_motionblur = ri.Cvar_Get("gl_motionblur", "0", CVAR_ARCHIVE);
2378 gl_motionblur_intensity = ri.Cvar_Get("gl_motionblur_intensity", "0.6", CVAR_ARCHIVE);
2379 gl_fogenable = ri.Cvar_Get("gl_fogenable", "0", CVAR_ARCHIVE);
2380 gl_fogstart = ri.Cvar_Get("gl_fogstart", "50.0", CVAR_ARCHIVE);
2381 gl_fogend = ri.Cvar_Get("gl_fogend", "1500.0", CVAR_ARCHIVE);
2382 gl_fogdensity = ri.Cvar_Get("gl_fogdensity", "0.001", CVAR_ARCHIVE);
2383 gl_fogred = ri.Cvar_Get("gl_fogred", "0.4", CVAR_ARCHIVE);
2384 gl_foggreen = ri.Cvar_Get("gl_foggreen", "0.4", CVAR_ARCHIVE);
2385 gl_fogblue = ri.Cvar_Get("gl_fogblue", "0.4", CVAR_ARCHIVE);
2386 gl_fogunderwater = ri.Cvar_Get("gl_fogunderwater", "0", CVAR_ARCHIVE);
2387 gl_reflection_fragment_program = ri.Cvar_Get("gl_reflection_fragment_program", "0", CVAR_ARCHIVE);
2388 gl_reflection = ri.Cvar_Get("gl_reflection", "0", CVAR_ARCHIVE);
2389 gl_reflection_debug = ri.Cvar_Get("gl_reflection_debug", "0", 0);
2390 gl_reflection_max = ri.Cvar_Get("gl_reflection_max", "2", 0);
2391 gl_reflection_shader = ri.Cvar_Get("gl_reflection_shader", "0", CVAR_ARCHIVE);
2392 gl_reflection_shader_image = ri.Cvar_Get("gl_reflection_shader_image",
2393 "/textures/water/distortion.pcx", CVAR_ARCHIVE);
2394 gl_reflection_water_surface = ri.Cvar_Get("gl_reflection_water_surface", "1", 0);
2395 gl_minimap = ri.Cvar_Get("gl_minimap", "0", CVAR_ARCHIVE);
2396 gl_minimap_size = ri.Cvar_Get("gl_minimap_size", "400", CVAR_ARCHIVE);
2397 gl_minimap_zoom = ri.Cvar_Get("gl_minimap_zoom", "1.5", CVAR_ARCHIVE);
2398 gl_minimap_style = ri.Cvar_Get("gl_minimap_style", "1", CVAR_ARCHIVE);
2399 gl_minimap_x = ri.Cvar_Get("gl_minimap_x", "800", CVAR_ARCHIVE);
2400 gl_minimap_y = ri.Cvar_Get("gl_minimap_y", "400", CVAR_ARCHIVE);
2401 gl_detailtextures = ri.Cvar_Get("gl_detailtextures", "0.0", CVAR_ARCHIVE);
2402 gl_shading = ri.Cvar_Get("gl_shading", "1", CVAR_ARCHIVE);
2403 gl_decals = ri.Cvar_Get("gl_decals", "1", CVAR_ARCHIVE);
2404 gl_decals_time = ri.Cvar_Get("gl_decals_time", "30", CVAR_ARCHIVE);
2405 gl_glares = ri.Cvar_Get("gl_glares", "0", CVAR_ARCHIVE);
2406 gl_glares_size = ri.Cvar_Get("gl_glares_size", "128", CVAR_ARCHIVE);
2407 gl_glares_intens = ri.Cvar_Get("gl_glares_intens", "0.35", CVAR_ARCHIVE);
2408 gl_flares = ri.Cvar_Get("gl_flares", "1", CVAR_ARCHIVE);
2409 gl_flare_force_size = ri.Cvar_Get("gl_flare_force_size", "0", CVAR_ARCHIVE);
2410 gl_flare_force_style = ri.Cvar_Get("gl_flare_force_style", "1", CVAR_ARCHIVE);
2411 gl_flare_intensity = ri.Cvar_Get("gl_flare_intensity", "1", CVAR_ARCHIVE);
2412 gl_flare_maxdist = ri.Cvar_Get("gl_flare_maxdist", "150", CVAR_ARCHIVE);
2413 gl_flare_scale = ri.Cvar_Get("gl_flare_scale", "1.5", CVAR_ARCHIVE);
2414 gl_coloredlightmaps = ri.Cvar_Get( "gl_coloredlightmaps", "1", 0);
2415
2416 r_lefthand = ri.Cvar_Get("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
2417 r_norefresh = ri.Cvar_Get("r_norefresh", "0", 0);
2418 r_fullbright = ri.Cvar_Get("r_fullbright", "0", 0);
2419 r_drawentities = ri.Cvar_Get("r_drawentities", "1", 0);
2420 r_drawworld = ri.Cvar_Get("r_drawworld", "1", 0);
2421 r_novis = ri.Cvar_Get("r_novis", "0", 0);
2422 r_nocull = ri.Cvar_Get("r_nocull", "0", 0);
2423 r_lerpmodels = ri.Cvar_Get("r_lerpmodels", "1", 0);
2424 r_model_lightlerp = ri.Cvar_Get("r_model_lightlerp", "1", 0);
2425 r_model_alpha = ri.Cvar_Get("r_model_alpha", "0", 0);
2426 r_speeds = ri.Cvar_Get("r_speeds", "0", 0);
2427 r_lightlevel = ri.Cvar_Get("r_lightlevel", "0", 0);
2428 r_overbrightbits = ri.Cvar_Get("r_overbrightbits", "2", CVAR_ARCHIVE);
2429 r_cellshading = ri.Cvar_Get("r_cellshading", "0", CVAR_ARCHIVE);
2430 r_cellshading_width = ri.Cvar_Get("r_cellshading_width", "4", CVAR_ARCHIVE);
2431
2432 skydistance = ri.Cvar_Get("skydistance", "2300", CVAR_ARCHIVE);
2433
2434 vid_fullscreen = ri.Cvar_Get("vid_fullscreen", "1", CVAR_ARCHIVE);
2435 vid_gamma = ri.Cvar_Get("vid_gamma", "1.0", CVAR_ARCHIVE);
2436 vid_ref = ri.Cvar_Get("vid_ref", "q2glx", CVAR_ARCHIVE);
2437
2438 ri.Cmd_AddCommand("imagelist", GL_ImageList_f);
2439 ri.Cmd_AddCommand("screenshot", GL_ScreenShot_f);
2440 ri.Cmd_AddCommand("modellist", Mod_Modellist_f);
2441 ri.Cmd_AddCommand("gl_strings", GL_Strings_f);
2442 ri.Cmd_AddCommand("pngshot", GL_ScreenShot_PNG);
2443 }
2444
2445 /*
2446 * ================== R_SetMode ==================
2447 */
2448 qboolean
R_SetMode(void)2449 R_SetMode(void)
2450 {
2451 rserr_t err;
2452 qboolean fullscreen;
2453
2454 fullscreen = vid_fullscreen->value;
2455
2456 skydistance->modified = true; /* DMP skybox size change */
2457 vid_fullscreen->modified = false;
2458 gl_mode->modified = false;
2459 gl_coloredlightmaps->modified = false;
2460
2461 if ((err = GLimp_SetMode(&vid.width, &vid.height, gl_mode->value, fullscreen)) == rserr_ok) {
2462 gl_state.prev_mode = gl_mode->value;
2463 } else {
2464 if (err == rserr_invalid_fullscreen) {
2465 ri.Cvar_SetValue("vid_fullscreen", 0);
2466 vid_fullscreen->modified = false;
2467 ri.Con_Printf(PRINT_ALL, "Video ref::R_SetMode() - fullscreen unavailable in this mode\n");
2468 if ((err = GLimp_SetMode(&vid.width, &vid.height, gl_mode->value, false)) == rserr_ok)
2469 return true;
2470 } else if (err == rserr_invalid_mode) {
2471 ri.Cvar_SetValue("gl_mode", gl_state.prev_mode);
2472 gl_mode->modified = false;
2473 ri.Con_Printf(PRINT_ALL, "Video ref::R_SetMode() - invalid mode\n");
2474 }
2475 /* try setting it back to something safe */
2476 if ((err = GLimp_SetMode(&vid.width, &vid.height, gl_state.prev_mode, false)) != rserr_ok) {
2477 ri.Con_Printf(PRINT_ALL, "Video ref::R_SetMode() - could not revert to safe mode\n");
2478 return false;
2479 }
2480 }
2481 return true;
2482 }
2483
2484 /*
2485 * =============== R_Init ===============
2486 */
2487
2488 int
R_Init(void * hinstance,void * hWnd)2489 R_Init(void *hinstance, void *hWnd)
2490 {
2491 char renderer_buffer[1000];
2492 char vendor_buffer[1000];
2493 int err;
2494 int j;
2495 extern float r_turbsin[256];
2496 int init_time;
2497
2498 init_time = Sys_Milliseconds();
2499
2500 for (j = 0; j < 256; j++) {
2501 r_turbsin[j] *= 0.5;
2502 }
2503
2504 ri.Con_Printf(PRINT_ALL, "Video ref version: " REF_VERSION "\n");
2505
2506 Draw_GetPalette();
2507
2508 R_Register();
2509
2510 VLight_Init();
2511
2512 /* initialize our QGL dynamic bindings */
2513 if (!QGL_Init(gl_driver->string)) {
2514 QGL_Shutdown();
2515 ri.Con_Printf(PRINT_ALL, "Video ref::R_Init() - could not load \"%s\"\n", gl_driver->string);
2516 return -1;
2517 }
2518 /* initialize OS-specific parts of OpenGL */
2519 if (!GLimp_Init(hinstance, hWnd)) {
2520 QGL_Shutdown();
2521 return -1;
2522 }
2523 /* set our "safe" modes */
2524 gl_state.prev_mode = 3;
2525
2526 /* create the window and set up the context */
2527 if (!R_SetMode()) {
2528 QGL_Shutdown();
2529 ri.Con_Printf(PRINT_ALL, "Video ref::R_Init() - could not R_SetMode()\n");
2530 return -1;
2531 }
2532 ri.Vid_MenuInit();
2533
2534 /*
2535 * * get our various GL strings
2536 */
2537 gl_config.vendor_string = (char *)qglGetString(GL_VENDOR);
2538 ri.Con_Printf(PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string);
2539 gl_config.renderer_string = (char *)qglGetString(GL_RENDERER);
2540 ri.Con_Printf(PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string);
2541 gl_config.version_string = (char *)qglGetString(GL_VERSION);
2542 ri.Con_Printf(PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string);
2543 gl_config.extensions_string = (char *)qglGetString(GL_EXTENSIONS);
2544 ri.Con_Printf(PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string);
2545
2546 Q_strncpyz(renderer_buffer, gl_config.renderer_string, sizeof(renderer_buffer));
2547 Q_strlwr(renderer_buffer);
2548
2549 Q_strncpyz(vendor_buffer, gl_config.vendor_string, sizeof(vendor_buffer));
2550 Q_strlwr(vendor_buffer);
2551
2552 if (strcasecmp(renderer_buffer, "voodoo")) {
2553 if (!strcasecmp(renderer_buffer, "rush"))
2554 gl_config.renderer = GL_RENDERER_VOODOO;
2555 else
2556 gl_config.renderer = GL_RENDERER_VOODOO_RUSH;
2557 } else if (strcasecmp(vendor_buffer, "sgi"))
2558 gl_config.renderer = GL_RENDERER_SGI;
2559 else if (strcasecmp(renderer_buffer, "permedia"))
2560 gl_config.renderer = GL_RENDERER_PERMEDIA2;
2561 else if (strcasecmp(renderer_buffer, "glint"))
2562 gl_config.renderer = GL_RENDERER_GLINT_MX;
2563 else if (strcasecmp(renderer_buffer, "glzicd"))
2564 gl_config.renderer = GL_RENDERER_REALIZM;
2565 else if (strcasecmp(renderer_buffer, "gdi"))
2566 gl_config.renderer = GL_RENDERER_MCD;
2567 else if (strcasecmp(renderer_buffer, "pcx2"))
2568 gl_config.renderer = GL_RENDERER_PCX2;
2569 else if (strcasecmp(renderer_buffer, "verite"))
2570 gl_config.renderer = GL_RENDERER_RENDITION;
2571 else
2572 gl_config.renderer = GL_RENDERER_OTHER;
2573
2574 if (!(gl_monolightmap->string[1] == 'F' ||
2575 gl_monolightmap->string[1] == 'f')) {
2576 if (gl_config.renderer == GL_RENDERER_PERMEDIA2) {
2577 ri.Cvar_Set("gl_monolightmap", "A");
2578 ri.Con_Printf(PRINT_ALL, "...using gl_monolightmap 'a'\n");
2579 } else if (gl_config.renderer & GL_RENDERER_POWERVR) {
2580 ri.Cvar_Set("gl_monolightmap", "0");
2581 } else {
2582 ri.Cvar_Set("gl_monolightmap", "0");
2583 }
2584 }
2585
2586 /* power vr can't have anything stay in the framebuffer, so */
2587 /* the screen needs to redraw the tiled background every frame */
2588 if (gl_config.renderer & GL_RENDERER_POWERVR) {
2589 ri.Cvar_Set("scr_drawall", "1");
2590 } else {
2591 ri.Cvar_Set("scr_drawall", "0");
2592 }
2593
2594 #if defined (__unix__)
2595 ri.Cvar_SetValue("gl_finish", 1);
2596 #endif
2597
2598 /* MCD has buffering issues */
2599 if (gl_config.renderer == GL_RENDERER_MCD) {
2600 ri.Cvar_SetValue("gl_finish", 1);
2601 }
2602 if (gl_config.renderer & GL_RENDERER_3DLABS) {
2603 if (gl_3dlabs_broken->value)
2604 gl_config.allow_cds = false;
2605 else
2606 gl_config.allow_cds = true;
2607 } else {
2608 gl_config.allow_cds = true;
2609 }
2610
2611 if (gl_config.allow_cds)
2612 ri.Con_Printf(PRINT_ALL, "...allowing CDS\n");
2613 else
2614 ri.Con_Printf(PRINT_ALL, "...disabling CDS\n");
2615
2616 /*
2617 * * grab extensions
2618 */
2619 if (strstr(gl_config.extensions_string, "GL_EXT_compiled_vertex_array") ||
2620 strstr(gl_config.extensions_string, "GL_SGI_compiled_vertex_array")) {
2621 ri.Con_Printf(PRINT_ALL, "...enabling GL_EXT_compiled_vertex_array\n");
2622 qglLockArraysEXT = (void *)qwglGetProcAddress("glLockArraysEXT");
2623 qglUnlockArraysEXT = (void *)qwglGetProcAddress("glUnlockArraysEXT");
2624 } else {
2625 ri.Con_Printf(PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n");
2626 }
2627
2628 if (strstr(gl_config.extensions_string, "GL_EXT_point_parameters")) {
2629 if (gl_ext_pointparameters->value) {
2630 qglPointParameterfEXT = (void (APIENTRY *) (GLenum, GLfloat))qwglGetProcAddress("glPointParameterfEXT");
2631 qglPointParameterfvEXT = (void (APIENTRY *) (GLenum, const GLfloat *))qwglGetProcAddress("glPointParameterfvEXT");
2632 ri.Con_Printf(PRINT_ALL, "...using GL_EXT_point_parameters\n");
2633 } else {
2634 ri.Con_Printf(PRINT_ALL, "...ignoring GL_EXT_point_parameters\n");
2635 }
2636 } else {
2637 ri.Con_Printf(PRINT_ALL, "...GL_EXT_point_parameters not found\n");
2638 }
2639
2640 if (strstr(gl_config.extensions_string, "GL_ARB_multitexture")) {
2641 if (gl_ext_multitexture->value) {
2642 ri.Con_Printf(PRINT_ALL, "...using GL_ARB_multitexture\n");
2643 qglMTexCoord2fSGIS = (void *)qwglGetProcAddress("glMultiTexCoord2fARB");
2644 qglActiveTextureARB = (void *)qwglGetProcAddress("glActiveTextureARB");
2645 qglClientActiveTextureARB = (void *)qwglGetProcAddress("glClientActiveTextureARB");
2646 qglMultiTexCoord3fvARB = (void *)qwglGetProcAddress("glMultiTexCoord3fvARB"); /* mpo */
2647
2648 qglGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);/* MH - see how many
2649 * texture units card
2650 * supports */
2651 GL_TEXTURE0 = GL_TEXTURE0_ARB;
2652 GL_TEXTURE1 = GL_TEXTURE1_ARB;
2653 GL_TEXTURE2 = GL_TEXTURE2_ARB; /* MH - add extra
2654 * texture unit here */
2655
2656 ri.Con_Printf(PRINT_ALL, "Texture units available: %d\n", maxTextureUnits);
2657 } else {
2658 ri.Con_Printf(PRINT_ALL, "...ignoring GL_ARB_multitexture\n");
2659 }
2660 } else {
2661 ri.Con_Printf(PRINT_ALL, "...GL_ARB_multitexture not found\n");
2662 }
2663
2664 /* retreive information */
2665 qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_state.maxtexsize);
2666 if (gl_state.maxtexsize <= 0)
2667 gl_state.maxtexsize = 256;
2668
2669 Com_Printf("Maximum Texture Size: %ix%i\n", gl_state.maxtexsize, gl_state.maxtexsize);
2670
2671 if (strstr(gl_config.extensions_string, "GL_SGIS_multitexture")) {
2672 if (qglActiveTextureARB) {
2673 ri.Con_Printf(PRINT_ALL, "...GL_SGIS_multitexture deprecated in favor of ARB_multitexture\n");
2674 } else if (gl_ext_multitexture->value) {
2675 ri.Con_Printf(PRINT_ALL, "...using GL_SGIS_multitexture\n");
2676 qglMTexCoord2fSGIS = (void *)qwglGetProcAddress("glMTexCoord2fSGIS");
2677 qglSelectTextureSGIS = (void *)qwglGetProcAddress("glSelectTextureSGIS");
2678
2679 qglGetIntegerv(GL_MAX_TEXTURE_UNITS_SGIS, &maxTextureUnits); /* MH - see how many
2680 * texture units card
2681 * supports */
2682 GL_TEXTURE0 = GL_TEXTURE0_SGIS;
2683 GL_TEXTURE1 = GL_TEXTURE1_SGIS;
2684 GL_TEXTURE2 = GL_TEXTURE2_SGIS; /* MH - add extra
2685 * texture unit */
2686 } else {
2687 ri.Con_Printf(PRINT_ALL, "...ignoring GL_SGIS_multitexture\n");
2688 }
2689 } else {
2690 ri.Con_Printf(PRINT_ALL, "...GL_SGIS_multitexture not found\n");
2691 }
2692
2693 if (strstr(gl_config.extensions_string, "GL_SGIS_generate_mipmap")) {
2694 ri.Con_Printf(PRINT_ALL, "...using GL_SGIS_generate_mipmap\n");
2695 gl_state.sgis_mipmap = true;
2696 } else {
2697 ri.Con_Printf(PRINT_ALL, "...GL_SGIS_generate_mipmap not found\n");
2698 gl_state.sgis_mipmap = false;
2699 }
2700
2701 /* Vic - begin */
2702 gl_config.mtexcombine = false;
2703
2704 if (strstr(gl_config.extensions_string, "GL_ARB_texture_env_combine")) {
2705 if (gl_ext_mtexcombine->value) {
2706 Com_Printf("...using GL_ARB_texture_env_combine\n");
2707 gl_config.mtexcombine = true;
2708 } else {
2709 Com_Printf("...ignoring GL_ARB_texture_env_combine\n");
2710 }
2711 } else {
2712 Com_Printf("...GL_ARB_texture_env_combine not found\n");
2713 }
2714
2715 if (!gl_config.mtexcombine) {
2716 if (strstr(gl_config.extensions_string, "GL_EXT_texture_env_combine")) {
2717 if (gl_ext_mtexcombine->value) {
2718 Com_Printf("...using GL_EXT_texture_env_combine\n");
2719 gl_config.mtexcombine = true;
2720 } else {
2721 Com_Printf("...ignoring GL_EXT_texture_env_combine\n");
2722 }
2723 } else {
2724 Com_Printf("...GL_EXT_texture_env_combine not found\n");
2725 }
2726 }
2727 /* Vic - end */
2728
2729 /* NeVo - Anisotropic Filtering Support */
2730 gl_config.anisotropic = false;
2731 if (strstr(gl_config.extensions_string, "GL_EXT_texture_filter_anisotropic")) {
2732 ri.Con_Printf(PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic\n");
2733 gl_config.anisotropic = true;
2734 qglGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_config.max_anisotropy);
2735 ri.Cvar_SetValue("gl_anisotropic_avail", gl_config.max_anisotropy);
2736 } else {
2737 ri.Con_Printf(PRINT_ALL, "..GL_EXT_texture_filter_anisotropic not found\n");
2738 gl_config.anisotropic = false;
2739 gl_config.max_anisotropy = 0.0;
2740 ri.Cvar_SetValue("gl_anisotropic_avail", 0.0);
2741 }
2742 ri.Con_Printf(PRINT_ALL, "Maximum anisotropy level: %g\n", gl_config.max_anisotropy);
2743
2744 gl_state.nv_fog = false;
2745
2746 if (strstr(gl_config.extensions_string, "GL_NV_fog_distance")) {
2747 if (!gl_nv_fog->value) {
2748
2749 ri.Con_Printf(PRINT_ALL, "...ignoring GL_NV_fog_distance\n");
2750 gl_state.nv_fog = false;
2751
2752 } else {
2753
2754 ri.Con_Printf(PRINT_ALL, "...using GL_NV_fog_distance\n");
2755 gl_state.nv_fog = true;
2756 }
2757
2758 } else {
2759 ri.Con_Printf(PRINT_ALL, "...GL_NV_fog_distance not found\n");
2760 gl_state.nv_fog = false;
2761 ri.Cvar_Set("gl_nv_fog", "0");
2762
2763 }
2764
2765 /*
2766 * ri.Con_Printf( PRINT_ALL, "Initializing NVIDIA-only extensions:\n" );
2767 */
2768
2769 if (strstr(gl_config.extensions_string, "GL_NV_texture_rectangle")) {
2770 Com_Printf("...using GL_NV_texture_rectangle\n");
2771 gl_state.tex_rectangle = true;
2772 } else if (strstr(gl_config.extensions_string, "GL_EXT_texture_rectangle")) {
2773 Com_Printf("...using GL_EXT_texture_rectangle\n");
2774 gl_state.tex_rectangle = true;
2775 } else {
2776 Com_Printf("...GL_NV_texture_rectangle not found\n");
2777 gl_state.tex_rectangle = false;
2778 }
2779
2780 if (strstr(gl_config.extensions_string, "GL_NV_register_combiners")) {
2781 ri.Con_Printf(PRINT_ALL, "...using GL_NV_register_combiners\n");
2782
2783 qglCombinerParameterfvNV = (PFNGLCOMBINERPARAMETERFVNVPROC) qwglGetProcAddress("glCombinerParameterfvNV");
2784 qglCombinerParameterfNV = (PFNGLCOMBINERPARAMETERFNVPROC) qwglGetProcAddress("glCombinerParameterfNV");
2785 qglCombinerParameterivNV = (PFNGLCOMBINERPARAMETERIVNVPROC) qwglGetProcAddress("glCombinerParameterivNV");
2786 qglCombinerParameteriNV = (PFNGLCOMBINERPARAMETERINVPROC) qwglGetProcAddress("glCombinerParameteriNV");
2787 qglCombinerInputNV = (PFNGLCOMBINERINPUTNVPROC) qwglGetProcAddress("glCombinerInputNV");
2788 qglCombinerOutputNV = (PFNGLCOMBINEROUTPUTNVPROC) qwglGetProcAddress("glCombinerOutputNV");
2789 qglFinalCombinerInputNV = (PFNGLFINALCOMBINERINPUTNVPROC) qwglGetProcAddress("glFinalCombinerInputNV");
2790 qglGetCombinerInputParameterfvNV = (PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) qwglGetProcAddress("glGetCombinerInputParameterfvNV");
2791 qglGetCombinerInputParameterivNV = (PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) qwglGetProcAddress("glGetCombinerInputParameterivNV");
2792 qglGetCombinerOutputParameterfvNV = (PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) qwglGetProcAddress("glGetCombinerOutputParameterfvNV");
2793 qglGetCombinerOutputParameterivNV = (PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) qwglGetProcAddress("glGetCombinerOutputParameterivNV");
2794 qglGetFinalCombinerInputParameterfvNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) qwglGetProcAddress("glGetFinalCombinerInputParameterfvNV");
2795 qglGetFinalCombinerInputParameterivNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) qwglGetProcAddress("glGetFinalCombinerInputParameterivNV");
2796
2797 gl_state.reg_combiners = true;
2798 } else {
2799 ri.Con_Printf(PRINT_ALL, "...ignoring GL_NV_register_combiners\n");
2800 gl_state.reg_combiners = false;
2801 }
2802
2803 /* Texture Shader support - MrG */
2804 if (strstr(gl_config.extensions_string, "GL_NV_texture_shader")) {
2805 ri.Con_Printf(PRINT_ALL, "...using GL_NV_texture_shader\n");
2806 gl_config.NV_texshaders = true;
2807 } else {
2808 ri.Con_Printf(PRINT_ALL, "...GL_NV_texture_shader not found\n");
2809 gl_config.NV_texshaders = false;
2810 }
2811
2812 if (strstr(gl_config.extensions_string, "GL_NV_multisample_filter_hint")) {
2813 gl_config.GL_EXT_nv_multisample_filter_hint = true;
2814 ri.Con_Printf(PRINT_ALL, "...using GL_NV_multisample_filter_hint\n");
2815 } else {
2816 ri.Con_Printf(PRINT_ALL, "...GL_NV_multisample_filter_hint not found\n");
2817 gl_config.GL_EXT_nv_multisample_filter_hint = true;
2818 }
2819
2820 if (strstr(gl_config.extensions_string, "GL_ARB_texture_compression")) {
2821 if (!gl_ext_texture_compression->value) {
2822 ri.Con_Printf(PRINT_ALL, "...ignoring GL_ARB_texture_compression\n");
2823 gl_state.texture_compression = false;
2824 } else {
2825 ri.Con_Printf(PRINT_ALL, "...using GL_ARB_texture_compression\n");
2826 gl_state.texture_compression = true;
2827 }
2828 } else {
2829 ri.Con_Printf(PRINT_ALL, "...GL_ARB_texture_compression not found\n");
2830 gl_state.texture_compression = false;
2831 ri.Cvar_Set("gl_ext_texture_compression", "0");
2832 }
2833
2834 /* mpo === jitwater */
2835 if (strstr(gl_config.extensions_string, "GL_ARB_fragment_program")) {
2836
2837 if (maxTextureUnits >= 3 && (gl_reflection_fragment_program->value))
2838 gl_state.fragment_program = true;
2839
2840 ri.Con_Printf(PRINT_ALL, "...using GL_ARB_fragment_program\n");
2841
2842 qglGenProgramsARB = (void *)qwglGetProcAddress("glGenProgramsARB");
2843 qglDeleteProgramsARB = (void *)qwglGetProcAddress("glDeleteProgramsARB");
2844 qglBindProgramARB = (void *)qwglGetProcAddress("glBindProgramARB");
2845 qglProgramStringARB = (void *)qwglGetProcAddress("glProgramStringARB");
2846 qglProgramEnvParameter4fARB = (void *)qwglGetProcAddress("glProgramEnvParameter4fARB");
2847 qglProgramLocalParameter4fARB = (void *)qwglGetProcAddress("glProgramLocalParameter4fARB");
2848
2849 if (!gl_reflection_fragment_program->value) {
2850 gl_state.fragment_program = false;
2851 ri.Con_Printf(PRINT_ALL, "\x02" "GL_ARB_fragment_program available but disabled, set the variable gl_reflection_fragment_program to 1 and type vid_restart\n");
2852 }
2853
2854 if (!(qglGenProgramsARB &&
2855 qglDeleteProgramsARB &&
2856 qglBindProgramARB &&
2857 qglProgramStringARB &&
2858 qglProgramEnvParameter4fARB &&
2859 qglProgramLocalParameter4fARB)) {
2860 gl_state.fragment_program = false;
2861 ri.Cvar_Set("gl_reflection_fragment_program", "0");
2862 ri.Con_Printf(PRINT_ALL, "... Failed! Fragment programs disabled\n");
2863 }
2864 }
2865 else {
2866 gl_state.fragment_program = false;
2867 ri.Con_Printf(PRINT_ALL,"\x02" "GL_ARB_fragment_program not found\n");
2868 ri.Con_Printf(PRINT_ALL,"\x02" "Don't try to run water distorsion, it will crash\n");
2869 }
2870 /* mpo === jitwater */
2871
2872 GL_SetDefaultState();
2873
2874 /*
2875 * * draw our stereo patterns
2876 */
2877 /* #if 0 // commented out until H3D pays us the money they owe us */
2878 GL_DrawStereoPattern();
2879 /* #endif */
2880
2881 /* jitanisotropy(make sure nobody goes out of bounds) */
2882 if (gl_anisotropic->value < 0)
2883 ri.Cvar_Set("gl_anisotropic", "0");
2884 else if (gl_anisotropic->value > gl_config.max_anisotropy)
2885 ri.Cvar_SetValue("gl_anisotropic", gl_config.max_anisotropy);
2886
2887 if (gl_lightmap_texture_saturation->value > 1 || gl_lightmap_texture_saturation->value < 0)
2888 ri.Cvar_Set("gl_lightmap_texture_saturation", "1"); /* jitsaturation */
2889
2890 GL_InitImages();
2891 Mod_Init();
2892 R_InitParticleTexture();
2893 Draw_InitLocal();
2894
2895 ri.Con_Printf(PRINT_ALL, "-------------------------------\n");
2896 ri.Con_Printf(PRINT_ALL, "\x02" "Render Initialised in: %.2fs\n", (Sys_Milliseconds() - init_time) * 0.001);
2897 ri.Con_Printf(PRINT_ALL, "-------------------------------\n");
2898
2899 err = qglGetError();
2900 if (err != GL_NO_ERROR)
2901 ri.Con_Printf(PRINT_ALL, "glGetError() = 0x%x\n", err);
2902
2903 R_init_refl(gl_reflection_max->value); /* MPO : init reflections */
2904
2905 return 0;
2906 }
2907
2908 /*
2909 * =============== R_Shutdown ===============
2910 */
2911 void
R_Shutdown(void)2912 R_Shutdown(void)
2913 {
2914 ri.Cmd_RemoveCommand("modellist");
2915 ri.Cmd_RemoveCommand("screenshot");
2916 ri.Cmd_RemoveCommand("imagelist");
2917 ri.Cmd_RemoveCommand("gl_strings");
2918 ri.Cmd_RemoveCommand ("pngshot");
2919
2920 Mod_FreeAll();
2921
2922 GL_ShutdownImages();
2923
2924 /*
2925 * * shut down OS specific OpenGL stuff like contexts, etc.
2926 */
2927 GLimp_Shutdown();
2928
2929 /*
2930 * * shutdown our QGL subsystem
2931 */
2932 QGL_Shutdown();
2933
2934 /*
2935 * * shutdown our reflective arrays
2936 */
2937 R_shutdown_refl();
2938 }
2939
2940
2941
2942 /*
2943 * @@@@@@@@@@@@@@@@@@@@@ R_BeginFrame @@@@@@@@@@@@@@@@@@@@@
2944 */
2945 void RefreshFont(void);
2946 void
R_BeginFrame(float camera_separation)2947 R_BeginFrame(float camera_separation)
2948 {
2949
2950 gl_state.camera_separation = camera_separation;
2951
2952 if (font_color->modified) {
2953 RefreshFont();
2954 }
2955
2956 /*
2957 * * change modes if necessary
2958 */
2959 if (gl_mode->modified || vid_fullscreen->modified || gl_coloredlightmaps->modified) { /* FIXME: only restart if CDS is required */
2960 cvar_t *ref;
2961
2962 ref = ri.Cvar_Get("vid_ref", "q2glx", 0);
2963 ref->modified = true;
2964 }
2965 if (gl_ext_nv_multisample_filter_hint->modified) {
2966 gl_ext_nv_multisample_filter_hint->modified = false;
2967
2968 if (gl_config.GL_EXT_nv_multisample_filter_hint) {
2969 if (!strcmp(gl_ext_nv_multisample_filter_hint->string, "nicest"))
2970 qglHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
2971 else
2972 qglHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_FASTEST);
2973 }
2974 }
2975 /* NiceAss: scale -Maniac */
2976 if (cl_hudscale->modified) {
2977 int width , height;
2978
2979 if (cl_hudscale->value < 1.0)
2980 ri.Cvar_SetValue("cl_hudscale", 1.0);
2981
2982 /* get the current resolution */
2983 ri.Vid_GetModeInfo(&width, &height, gl_mode->value);
2984 /* lie to client about new scaled window size */
2985 ri.Vid_NewWindow(width / cl_hudscale->value, height / cl_hudscale->value);
2986
2987 cl_hudscale->modified = false;
2988 }
2989 if (gl_log->modified) {
2990 GLimp_EnableLogging(gl_log->value);
2991 gl_log->modified = false;
2992 }
2993 if (gl_log->value) {
2994 GLimp_LogNewFrame();
2995 }
2996
2997 /*
2998 * * update 3Dfx gamma -- it is expected that a user will do a
2999 * vid_restart * after tweaking this value
3000 */
3001 if (vid_gamma->modified) {
3002 vid_gamma->modified = false;
3003
3004 if (gl_state.hwgamma) {
3005 UpdateHardwareGamma();
3006 } else if (gl_config.renderer & (GL_RENDERER_VOODOO)) {
3007 char envbuffer[1024];
3008 float g;
3009
3010 g = 2.00 * (0.8 - (vid_gamma->value - 0.5)) + 1.0;
3011 Com_sprintf(envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g);
3012 putenv(envbuffer);
3013 Com_sprintf(envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g);
3014 putenv(envbuffer);
3015 }
3016 }
3017 #ifdef QMAX
3018 if (gl_particlelighting->modified) {
3019 gl_particlelighting->modified = false;
3020 if (gl_particlelighting->value < 0)
3021 gl_particlelighting->value = 0;
3022 if (gl_particlelighting->value > 1)
3023 gl_particlelighting->value = 1;
3024 }
3025 #endif
3026
3027 GLimp_BeginFrame(camera_separation);
3028
3029 /*
3030 * * go into 2D mode
3031 */
3032 qglViewport(0, 0, vid.width, vid.height);
3033 qglMatrixMode(GL_PROJECTION);
3034 qglLoadIdentity();
3035 /* NiceAss: Scale the screen */
3036 qglOrtho(0, vid.width / cl_hudscale->value, vid.height / cl_hudscale->value, 0, -99999, 99999);
3037 /* qglOrtho (0, vid.width, vid.height, 0, -99999, 99999); */
3038 qglMatrixMode(GL_MODELVIEW);
3039 qglLoadIdentity();
3040 qglDisable(GL_DEPTH_TEST);
3041 qglDisable(GL_CULL_FACE);
3042 qglDisable(GL_BLEND);
3043 qglEnable(GL_ALPHA_TEST);
3044 qglColor4f(1, 1, 1, 1);
3045
3046 /*
3047 * * draw buffer stuff
3048 */
3049 if (gl_drawbuffer->modified) {
3050 gl_drawbuffer->modified = false;
3051
3052 if (gl_state.camera_separation == 0 || !gl_state.stereo_enabled) {
3053 if (Q_stricmp(gl_drawbuffer->string, "GL_FRONT") == 0)
3054 qglDrawBuffer(GL_FRONT);
3055 else
3056 qglDrawBuffer(GL_BACK);
3057 }
3058 }
3059
3060 /*
3061 * * texturemode stuff
3062 */
3063 if (gl_texturemode->modified) {
3064 GL_TextureMode(gl_texturemode->string);
3065 gl_texturemode->modified = false;
3066 }
3067 if (gl_texturealphamode->modified) {
3068 GL_TextureAlphaMode(gl_texturealphamode->string);
3069 gl_texturealphamode->modified = false;
3070 }
3071 if (gl_texturesolidmode->modified) {
3072 GL_TextureSolidMode(gl_texturesolidmode->string);
3073 gl_texturesolidmode->modified = false;
3074 }
3075
3076 /* clear screen if desired */
3077 R_Clear();
3078 }
3079
3080 /*
3081 * ============= R_SetPalette =============
3082 */
3083 unsigned r_rawpalette[256];
3084
3085 void
R_SetPalette(const unsigned char * palette)3086 R_SetPalette(const unsigned char *palette)
3087 {
3088 int i;
3089
3090 byte *rp = (byte *) r_rawpalette;
3091
3092 if (palette) {
3093 for (i = 0; i < 256; i++) {
3094 rp[i * 4 + 0] = palette[i * 3 + 0];
3095 rp[i * 4 + 1] = palette[i * 3 + 1];
3096 rp[i * 4 + 2] = palette[i * 3 + 2];
3097 rp[i * 4 + 3] = 0xff;
3098 }
3099 } else {
3100 for (i = 0; i < 256; i++) {
3101 #ifdef QMAX
3102 rp[i * 4 + 0] = d_8to24table[i] & 0xff;
3103 rp[i * 4 + 1] = (d_8to24table[i] >> 8) & 0xff;
3104 rp[i * 4 + 2] = (d_8to24table[i] >> 16) & 0xff;
3105 #else
3106 rp[i * 4 + 0] = LittleLong(d_8to24table[i]) & 0xff;
3107 rp[i * 4 + 1] = (LittleLong(d_8to24table[i]) >> 8) & 0xff;
3108 rp[i * 4 + 2] = (LittleLong(d_8to24table[i]) >> 16) & 0xff;
3109 #endif
3110 rp[i * 4 + 3] = 0xff;
3111 }
3112 }
3113 #ifndef QMAX
3114 GL_SetTexturePalette(r_rawpalette);
3115 #endif
3116
3117 qglClearColor(0, 0, 0, 0);
3118 qglClear(GL_COLOR_BUFFER_BIT);
3119 qglClearColor(1, 0, 0.5, 0.5);
3120
3121 }
3122
3123 /*
3124 * * R_DrawBeam
3125 */
3126 #ifdef QMAX
3127 void R_RenderBeam(vec3_t start, vec3_t end, float size, float red, float green, float blue, float alpha);
3128 void
R_DrawBeam(entity_t * e)3129 R_DrawBeam(entity_t * e)
3130 {
3131
3132 R_RenderBeam(e->origin, e->oldorigin, e->frame,
3133 (d_8to24table[e->skinnum & 0xFF]) & 0xFF,
3134 (d_8to24table[e->skinnum & 0xFF] >> 8) & 0xFF,
3135 (d_8to24table[e->skinnum & 0xFF] >> 16) & 0xFF,
3136 e->alpha * 254);
3137 }
3138
3139 void
R_RenderBeam(vec3_t start,vec3_t end,float size,float red,float green,float blue,float alpha)3140 R_RenderBeam(vec3_t start, vec3_t end, float size, float red, float green, float blue, float alpha)
3141 {
3142 float len;
3143 vec3_t coord[4], ang_up, ang_right, vdelta;
3144
3145 GL_TexEnv(GL_MODULATE);
3146 qglDepthMask(false);
3147 qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
3148 qglEnable(GL_BLEND);
3149 qglShadeModel(GL_SMOOTH);
3150 GL_Bind(r_particlebeam->texnum);
3151 qglColor4ub(red, green, blue, alpha);
3152
3153 VectorSubtract(start, end, ang_up);
3154 len = VectorNormalize(ang_up);
3155
3156 VectorSubtract(r_refdef.vieworg, start, vdelta);
3157 CrossProduct(ang_up, vdelta, ang_right);
3158 if (!VectorCompare(ang_right, vec3_origin))
3159 VectorNormalize(ang_right);
3160
3161 VectorScale(ang_right, size * 3.0, ang_right);
3162
3163 VectorAdd(start, ang_right, coord[0]);
3164 VectorAdd(end, ang_right, coord[1]);
3165 VectorSubtract(end, ang_right, coord[2]);
3166 VectorSubtract(start, ang_right, coord[3]);
3167
3168 qglPushMatrix();
3169 {
3170 qglBegin(GL_QUADS);
3171 {
3172 qglTexCoord2f(0, 1);
3173 qglVertex3fv(coord[0]);
3174 qglTexCoord2f(0, 0);
3175 qglVertex3fv(coord[1]);
3176 qglTexCoord2f(1, 0);
3177 qglVertex3fv(coord[2]);
3178 qglTexCoord2f(1, 1);
3179 qglVertex3fv(coord[3]);
3180 }
3181 qglEnd();
3182 }
3183 qglPopMatrix();
3184
3185 qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3186 GL_TexEnv(GL_MODULATE);
3187 qglDepthMask(true);
3188 qglDisable(GL_BLEND);
3189 qglColor4f(1, 1, 1, 1);
3190 }
3191
3192 #else
3193 void
R_DrawBeam(entity_t * e)3194 R_DrawBeam(entity_t * e)
3195 {
3196 #define NUM_BEAM_SEGS 6
3197
3198 int i;
3199 float r , g, b;
3200
3201 vec3_t perpvec;
3202 vec3_t direction, normalized_direction;
3203 vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
3204 vec3_t oldorigin, origin;
3205
3206 oldorigin[0] = e->oldorigin[0];
3207 oldorigin[1] = e->oldorigin[1];
3208 oldorigin[2] = e->oldorigin[2];
3209
3210 origin[0] = e->origin[0];
3211 origin[1] = e->origin[1];
3212 origin[2] = e->origin[2];
3213
3214 normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
3215 normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
3216 normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
3217
3218 if (VectorNormalize(normalized_direction) == 0)
3219 return;
3220
3221 PerpendicularVector(perpvec, normalized_direction);
3222 VectorScale(perpvec, e->frame / 2, perpvec);
3223
3224 for (i = 0; i < 6; i++) {
3225 RotatePointAroundVector(start_points[i], normalized_direction, perpvec, (360.0 / NUM_BEAM_SEGS) * i);
3226 VectorAdd(start_points[i], origin, start_points[i]);
3227 VectorAdd(start_points[i], direction, end_points[i]);
3228 }
3229
3230 qglDisable(GL_TEXTURE_2D);
3231 qglEnable(GL_BLEND);
3232 qglDepthMask(GL_FALSE);
3233
3234 r = (LittleLong(d_8to24table[e->skinnum & 0xFF])) & 0xFF;
3235 g = (LittleLong(d_8to24table[e->skinnum & 0xFF]) >> 8) & 0xFF;
3236 b = (LittleLong(d_8to24table[e->skinnum & 0xFF]) >> 16) & 0xFF;
3237
3238 r *= 1 / 255.0;
3239 g *= 1 / 255.0;
3240 b *= 1 / 255.0;
3241
3242 qglColor4f(r, g, b, e->alpha);
3243
3244 qglBegin(GL_TRIANGLE_STRIP);
3245 for (i = 0; i < NUM_BEAM_SEGS; i++) {
3246 qglVertex3fv(start_points[i]);
3247 qglVertex3fv(end_points[i]);
3248 qglVertex3fv(start_points[(i + 1) % NUM_BEAM_SEGS]);
3249 qglVertex3fv(end_points[(i + 1) % NUM_BEAM_SEGS]);
3250 }
3251 qglEnd();
3252
3253 qglEnable(GL_TEXTURE_2D);
3254 qglDisable(GL_BLEND);
3255 qglDepthMask(GL_TRUE);
3256 }
3257
3258 #endif
3259 /* =================================================================== */
3260
3261
3262 void R_BeginRegistration(char *map);
3263 struct model_s *R_RegisterModel(char *name);
3264 struct image_s *R_RegisterSkin(char *name);
3265 void R_SetSky (char *name, float rotate, vec3_t axis);
3266 void R_EndRegistration(void);
3267
3268 void R_RenderFrame(refdef_t * fd);
3269
3270 struct image_s *Draw_FindPic(char *name);
3271
3272 void Draw_ScaledPic(int x, int y, float scale, float alpha, char *pic, float red, float green, float blue, qboolean fixcoords, qboolean repscale);
3273 void Draw_Pic (int x, int y, char *name, float alpha);
3274 void Draw_Char (int x, int y, int num, int alpha);
3275 void Draw_TileClear(int x, int y, int w, int h, char *name);
3276 void Draw_Fill (int x, int y, int w, int h, int c);
3277 void Draw_FadeScreen(void);
3278
3279 #ifdef QMAX
3280 void SetParticlePicture(int num, char *name);
3281
3282 #endif
3283
3284 /*
3285 * @@@@@@@@@@@@@@@@@@@@@ GetRefAPI
3286 *
3287 * @@@@@@@@@@@@@@@@@@@@@
3288 */
3289 refexport_t
GetRefAPI(refimport_t rimp)3290 GetRefAPI(refimport_t rimp)
3291 {
3292 refexport_t re;
3293
3294 ri = rimp;
3295
3296 re.api_version = API_VERSION;
3297
3298 re.BeginRegistration = R_BeginRegistration;
3299 re.RegisterModel = R_RegisterModel;
3300 re.RegisterSkin = R_RegisterSkin;
3301 re.RegisterPic = Draw_FindPic;
3302 re.SetSky = R_SetSky;
3303 re.EndRegistration = R_EndRegistration;
3304
3305 re.RenderFrame = R_RenderFrame;
3306 #ifdef QMAX
3307 re.SetParticlePicture = SetParticlePicture;
3308 #endif
3309
3310 re.DrawGetPicSize = Draw_GetPicSize;
3311 re.DrawScaledPic = Draw_ScaledPic;
3312 re.DrawPic = Draw_Pic;
3313 re.DrawStretchPic = Draw_StretchPic;
3314 re.DrawChar = Draw_Char;
3315 re.DrawTileClear = Draw_TileClear;
3316 re.DrawFill = Draw_Fill;
3317 re.DrawFadeScreen = Draw_FadeScreen;
3318
3319 re.DrawStretchRaw = Draw_StretchRaw;
3320
3321 re.Init = R_Init;
3322 re.Shutdown = R_Shutdown;
3323
3324 re.CinematicSetPalette = R_SetPalette;
3325 re.BeginFrame = R_BeginFrame;
3326 re.EndFrame = GLimp_EndFrame;
3327
3328 re.AppActivate = GLimp_AppActivate;
3329
3330 re.AddDecal = R_AddDecal;
3331
3332 Swap_Init();
3333
3334 return re;
3335 }
3336
3337
3338 #ifndef REF_HARD_LINKED
3339 /* this is only here so the functions in q_shared.c and q_shwin.c can link */
3340 void
Sys_Error(char * error,...)3341 Sys_Error(char *error,...)
3342 {
3343 va_list argptr;
3344 char text[1024];
3345
3346 va_start(argptr, error);
3347 vsprintf(text, error, argptr);
3348 va_end(argptr);
3349
3350 ri.Sys_Error(ERR_FATAL, "%s", text);
3351 }
3352
3353 void
Com_Printf(char * fmt,...)3354 Com_Printf(char *fmt,...)
3355 {
3356 va_list argptr;
3357 char text[1024];
3358
3359 va_start(argptr, fmt);
3360 vsprintf(text, fmt, argptr);
3361 va_end(argptr);
3362
3363 ri.Con_Printf(PRINT_ALL, "%s", text);
3364 }
3365
3366 #endif
3367