]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
moved mod_shared.c detail texture and distortion texture stuff to gl_rmain.c (renamed...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "r_shadow.h"
24
25 // used for dlight push checking and other things
26 int r_framecount;
27
28 mplane_t frustum[4];
29
30 matrix4x4_t r_identitymatrix;
31
32 int c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights, c_meshs, c_meshelements, c_rt_lights, c_rt_clears, c_rt_scissored, c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris, c_rtcached_shadowmeshes, c_rtcached_shadowtris, c_bloom, c_bloomcopies, c_bloomcopypixels, c_bloomdraws, c_bloomdrawpixels;
33
34 // true during envmap command capture
35 qboolean envmap;
36
37 // maximum visible distance (recalculated from world box each frame)
38 float r_farclip;
39 // brightness of world lightmaps and related lighting
40 // (often reduced when world rtlights are enabled)
41 float r_lightmapintensity;
42 // whether to draw world lights realtime, dlights realtime, and their shadows
43 qboolean r_rtworld;
44 qboolean r_rtworldshadows;
45 qboolean r_rtdlight;
46 qboolean r_rtdlightshadows;
47
48
49 // forces all rendering to draw triangle outlines
50 int r_showtrispass;
51
52 // view origin
53 vec3_t r_vieworigin;
54 vec3_t r_viewforward;
55 vec3_t r_viewleft;
56 vec3_t r_viewright;
57 vec3_t r_viewup;
58 int r_view_x;
59 int r_view_y;
60 int r_view_z;
61 int r_view_width;
62 int r_view_height;
63 int r_view_depth;
64 float r_view_fov_x;
65 float r_view_fov_y;
66 matrix4x4_t r_view_matrix;
67
68 //
69 // screen size info
70 //
71 refdef_t r_refdef;
72
73 // 8.8 fraction of base light value
74 unsigned short d_lightstylevalue[256];
75
76 cvar_t r_showtris = {0, "r_showtris", "0"};
77 cvar_t r_drawentities = {0, "r_drawentities","1"};
78 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
79 cvar_t r_speeds = {0, "r_speeds","0"};
80 cvar_t r_fullbright = {0, "r_fullbright","0"};
81 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
82 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
83 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
84 cvar_t r_drawcollisionbrushes = {0, "r_drawcollisionbrushes", "0"};
85
86 cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
87 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
88 cvar_t gl_fogred = {0, "gl_fogred","0.3"};
89 cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
90 cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
91 cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
92 cvar_t gl_fogend = {0, "gl_fogend","0"};
93
94 cvar_t r_textureunits = {0, "r_textureunits", "32"};
95
96 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1"};
97 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1"};
98 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1"};
99 cvar_t r_watershader = {CVAR_SAVE, "r_watershader", "1"};
100
101 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0"};
102 cvar_t r_bloom_intensity = {CVAR_SAVE, "r_bloom_intensity", "2"};
103 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "8"};
104 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320"};
105 cvar_t r_bloom_power = {CVAR_SAVE, "r_bloom_power", "4"};
106
107 cvar_t developer_texturelogging = {0, "developer_texturelogging", "1"};
108
109 rtexturepool_t *r_main_texturepool;
110 rtexture_t *r_bloom_texture_screen;
111 rtexture_t *r_bloom_texture_bloom;
112 rtexture_t *r_texture_blanknormalmap;
113 rtexture_t *r_texture_white;
114 rtexture_t *r_texture_black;
115 rtexture_t *r_texture_notexture;
116 rtexture_t *r_texture_whitecube;
117 rtexture_t *r_texture_normalizationcube;
118 rtexture_t *r_texture_detailtextures[NUM_DETAILTEXTURES];
119 rtexture_t *r_texture_distorttexture[64];
120
121 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
122 {
123         int i;
124         for (i = 0;i < verts;i++)
125         {
126                 out[0] = in[0] * r;
127                 out[1] = in[1] * g;
128                 out[2] = in[2] * b;
129                 out[3] = in[3];
130                 in += 4;
131                 out += 4;
132         }
133 }
134
135 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
136 {
137         int i;
138         for (i = 0;i < verts;i++)
139         {
140                 out[0] = r;
141                 out[1] = g;
142                 out[2] = b;
143                 out[3] = a;
144                 out += 4;
145         }
146 }
147
148 vec3_t fogcolor;
149 vec_t fogdensity;
150 float fog_density, fog_red, fog_green, fog_blue;
151 qboolean fogenabled;
152 qboolean oldgl_fogenable;
153 void R_UpdateFog(void)
154 {
155         if (gamemode == GAME_NEHAHRA)
156         {
157                 if (gl_fogenable.integer)
158                 {
159                         oldgl_fogenable = true;
160                         fog_density = gl_fogdensity.value;
161                         fog_red = gl_fogred.value;
162                         fog_green = gl_foggreen.value;
163                         fog_blue = gl_fogblue.value;
164                 }
165                 else if (oldgl_fogenable)
166                 {
167                         oldgl_fogenable = false;
168                         fog_density = 0;
169                         fog_red = 0;
170                         fog_green = 0;
171                         fog_blue = 0;
172                 }
173         }
174         if (fog_density)
175         {
176                 fogcolor[0] = fog_red   = bound(0.0f, fog_red  , 1.0f);
177                 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
178                 fogcolor[2] = fog_blue  = bound(0.0f, fog_blue , 1.0f);
179         }
180         if (fog_density)
181         {
182                 fogenabled = true;
183                 fogdensity = -4000.0f / (fog_density * fog_density);
184                 // fog color was already set
185         }
186         else
187                 fogenabled = false;
188 }
189
190 // FIXME: move this to client?
191 void FOG_clear(void)
192 {
193         if (gamemode == GAME_NEHAHRA)
194         {
195                 Cvar_Set("gl_fogenable", "0");
196                 Cvar_Set("gl_fogdensity", "0.2");
197                 Cvar_Set("gl_fogred", "0.3");
198                 Cvar_Set("gl_foggreen", "0.3");
199                 Cvar_Set("gl_fogblue", "0.3");
200         }
201         fog_density = fog_red = fog_green = fog_blue = 0.0f;
202 }
203
204 // FIXME: move this to client?
205 void FOG_registercvars(void)
206 {
207         if (gamemode == GAME_NEHAHRA)
208         {
209                 Cvar_RegisterVariable (&gl_fogenable);
210                 Cvar_RegisterVariable (&gl_fogdensity);
211                 Cvar_RegisterVariable (&gl_fogred);
212                 Cvar_RegisterVariable (&gl_foggreen);
213                 Cvar_RegisterVariable (&gl_fogblue);
214                 Cvar_RegisterVariable (&gl_fogstart);
215                 Cvar_RegisterVariable (&gl_fogend);
216         }
217 }
218
219 static void R_BuildDetailTextures (void)
220 {
221         int i, x, y, light;
222         float vc[3], vx[3], vy[3], vn[3], lightdir[3];
223 #define DETAILRESOLUTION 256
224         qbyte data[DETAILRESOLUTION][DETAILRESOLUTION][4], noise[DETAILRESOLUTION][DETAILRESOLUTION];
225         lightdir[0] = 0.5;
226         lightdir[1] = 1;
227         lightdir[2] = -0.25;
228         VectorNormalize(lightdir);
229         for (i = 0;i < NUM_DETAILTEXTURES;i++)
230         {
231                 fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4);
232                 for (y = 0;y < DETAILRESOLUTION;y++)
233                 {
234                         for (x = 0;x < DETAILRESOLUTION;x++)
235                         {
236                                 vc[0] = x;
237                                 vc[1] = y;
238                                 vc[2] = noise[y][x] * (1.0f / 32.0f);
239                                 vx[0] = x + 1;
240                                 vx[1] = y;
241                                 vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f);
242                                 vy[0] = x;
243                                 vy[1] = y + 1;
244                                 vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f);
245                                 VectorSubtract(vx, vc, vx);
246                                 VectorSubtract(vy, vc, vy);
247                                 CrossProduct(vx, vy, vn);
248                                 VectorNormalize(vn);
249                                 light = 128 - DotProduct(vn, lightdir) * 128;
250                                 light = bound(0, light, 255);
251                                 data[y][x][0] = data[y][x][1] = data[y][x][2] = light;
252                                 data[y][x][3] = 255;
253                         }
254                 }
255                 r_texture_detailtextures[i] = R_LoadTexture2D(r_main_texturepool, va("detailtexture%i", i), DETAILRESOLUTION, DETAILRESOLUTION, &data[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE, NULL);
256         }
257 }
258
259 static qbyte R_MorphDistortTexture (double y0, double y1, double y2, double y3, double morph)
260 {
261         int m = (int)(((y1 + y3 - (y0 + y2)) * morph * morph * morph) +
262                         ((2 * (y0 - y1) + y2 - y3) * morph * morph) +
263                         ((y2 - y0) * morph) +
264                         (y1));
265         return (qbyte)bound(0, m, 255);
266 }
267
268 static void R_BuildDistortTexture (void)
269 {
270         int x, y, i, j;
271 #define DISTORTRESOLUTION 32
272         qbyte data[5][DISTORTRESOLUTION][DISTORTRESOLUTION][2];
273
274         for (i=0; i<4; i++)
275         {
276                 for (y=0; y<DISTORTRESOLUTION; y++)
277                 {
278                         for (x=0; x<DISTORTRESOLUTION; x++)
279                         {
280                                 data[i][y][x][0] = rand () & 255;
281                                 data[i][y][x][1] = rand () & 255;
282                         }
283                 }
284         }
285
286         for (i=0; i<4; i++)
287         {
288                 for (j=0; j<16; j++)
289                 {
290                         r_texture_distorttexture[i*16+j] = NULL;
291                         if (gl_textureshader)
292                         {
293                                 for (y=0; y<DISTORTRESOLUTION; y++)
294                                 {
295                                         for (x=0; x<DISTORTRESOLUTION; x++)
296                                         {
297                                                 data[4][y][x][0] = R_MorphDistortTexture (data[(i-1)&3][y][x][0], data[i][y][x][0], data[(i+1)&3][y][x][0], data[(i+2)&3][y][x][0], 0.0625*j);
298                                                 data[4][y][x][1] = R_MorphDistortTexture (data[(i-1)&3][y][x][1], data[i][y][x][1], data[(i+1)&3][y][x][1], data[(i+2)&3][y][x][1], 0.0625*j);
299                                         }
300                                 }
301                                 r_texture_distorttexture[i*16+j] = R_LoadTexture2D(r_main_texturepool, va("distorttexture%i", i*16+j), DISTORTRESOLUTION, DISTORTRESOLUTION, &data[4][0][0][0], TEXTYPE_DSDT, TEXF_PRECACHE, NULL);
302                         }
303                 }
304         }
305 }
306
307 static void R_BuildBlankTextures(void)
308 {
309         qbyte data[4];
310         data[0] = 128; // normal X
311         data[1] = 128; // normal Y
312         data[2] = 255; // normal Z
313         data[3] = 128; // height
314         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
315         data[0] = 255;
316         data[1] = 255;
317         data[2] = 255;
318         data[3] = 255;
319         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
320         data[0] = 0;
321         data[1] = 0;
322         data[2] = 0;
323         data[3] = 255;
324         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
325 }
326
327 static void R_BuildNoTexture(void)
328 {
329         int x, y;
330         qbyte pix[16][16][4];
331         // this makes a light grey/dark grey checkerboard texture
332         for (y = 0;y < 16;y++)
333         {
334                 for (x = 0;x < 16;x++)
335                 {
336                         if ((y < 8) ^ (x < 8))
337                         {
338                                 pix[y][x][0] = 128;
339                                 pix[y][x][1] = 128;
340                                 pix[y][x][2] = 128;
341                                 pix[y][x][3] = 255;
342                         }
343                         else
344                         {
345                                 pix[y][x][0] = 64;
346                                 pix[y][x][1] = 64;
347                                 pix[y][x][2] = 64;
348                                 pix[y][x][3] = 255;
349                         }
350                 }
351         }
352         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
353 }
354
355 static void R_BuildWhiteCube(void)
356 {
357         qbyte data[6*1*1*4];
358         data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
359         data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
360         data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
361         data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
362         data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
363         data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
364         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
365 }
366
367 static void R_BuildNormalizationCube(void)
368 {
369         int x, y, side;
370         vec3_t v;
371         vec_t s, t, intensity;
372 #define NORMSIZE 64
373         qbyte data[6][NORMSIZE][NORMSIZE][4];
374         for (side = 0;side < 6;side++)
375         {
376                 for (y = 0;y < NORMSIZE;y++)
377                 {
378                         for (x = 0;x < NORMSIZE;x++)
379                         {
380                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
381                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382                                 switch(side)
383                                 {
384                                 case 0:
385                                         v[0] = 1;
386                                         v[1] = -t;
387                                         v[2] = -s;
388                                         break;
389                                 case 1:
390                                         v[0] = -1;
391                                         v[1] = -t;
392                                         v[2] = s;
393                                         break;
394                                 case 2:
395                                         v[0] = s;
396                                         v[1] = 1;
397                                         v[2] = t;
398                                         break;
399                                 case 3:
400                                         v[0] = s;
401                                         v[1] = -1;
402                                         v[2] = -t;
403                                         break;
404                                 case 4:
405                                         v[0] = s;
406                                         v[1] = -t;
407                                         v[2] = 1;
408                                         break;
409                                 case 5:
410                                         v[0] = -s;
411                                         v[1] = -t;
412                                         v[2] = -1;
413                                         break;
414                                 }
415                                 intensity = 127.0f / sqrt(DotProduct(v, v));
416                                 data[side][y][x][0] = 128.0f + intensity * v[0];
417                                 data[side][y][x][1] = 128.0f + intensity * v[1];
418                                 data[side][y][x][2] = 128.0f + intensity * v[2];
419                                 data[side][y][x][3] = 255;
420                         }
421                 }
422         }
423         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
424 }
425
426 void gl_main_start(void)
427 {
428         r_main_texturepool = R_AllocTexturePool();
429         r_bloom_texture_screen = NULL;
430         r_bloom_texture_bloom = NULL;
431         R_BuildBlankTextures();
432         R_BuildNoTexture();
433         R_BuildDetailTextures();
434         R_BuildDistortTexture();
435         if (gl_texturecubemap)
436         {
437                 R_BuildWhiteCube();
438                 R_BuildNormalizationCube();
439         }
440 }
441
442 void gl_main_shutdown(void)
443 {
444         R_FreeTexturePool(&r_main_texturepool);
445         r_bloom_texture_screen = NULL;
446         r_bloom_texture_bloom = NULL;
447         r_texture_blanknormalmap = NULL;
448         r_texture_white = NULL;
449         r_texture_black = NULL;
450         r_texture_whitecube = NULL;
451         r_texture_normalizationcube = NULL;
452 }
453
454 extern void CL_ParseEntityLump(char *entitystring);
455 void gl_main_newmap(void)
456 {
457         // FIXME: move this code to client
458         int l;
459         char *entities, entname[MAX_QPATH];
460         r_framecount = 1;
461         if (cl.worldmodel)
462         {
463                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
464                 l = strlen(entname) - 4;
465                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
466                 {
467                         strcpy(entname + l, ".ent");
468                         if ((entities = FS_LoadFile(entname, tempmempool, true)))
469                         {
470                                 CL_ParseEntityLump(entities);
471                                 Mem_Free(entities);
472                                 return;
473                         }
474                 }
475                 if (cl.worldmodel->brush.entities)
476                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
477         }
478 }
479
480 void GL_Main_Init(void)
481 {
482         Matrix4x4_CreateIdentity(&r_identitymatrix);
483 // FIXME: move this to client?
484         FOG_registercvars();
485         Cvar_RegisterVariable(&r_showtris);
486         Cvar_RegisterVariable(&r_drawentities);
487         Cvar_RegisterVariable(&r_drawviewmodel);
488         Cvar_RegisterVariable(&r_speeds);
489         Cvar_RegisterVariable(&r_fullbrights);
490         Cvar_RegisterVariable(&r_wateralpha);
491         Cvar_RegisterVariable(&r_dynamic);
492         Cvar_RegisterVariable(&r_fullbright);
493         Cvar_RegisterVariable(&r_textureunits);
494         Cvar_RegisterVariable(&r_lerpsprites);
495         Cvar_RegisterVariable(&r_lerpmodels);
496         Cvar_RegisterVariable(&r_waterscroll);
497         Cvar_RegisterVariable(&r_watershader);
498         Cvar_RegisterVariable(&r_drawcollisionbrushes);
499         Cvar_RegisterVariable(&r_bloom);
500         Cvar_RegisterVariable(&r_bloom_intensity);
501         Cvar_RegisterVariable(&r_bloom_blur);
502         Cvar_RegisterVariable(&r_bloom_resolution);
503         Cvar_RegisterVariable(&r_bloom_power);
504         Cvar_RegisterVariable(&developer_texturelogging);
505         if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
506                 Cvar_SetValue("r_fullbrights", 0);
507         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
508 }
509
510 static vec3_t r_farclip_origin;
511 static vec3_t r_farclip_direction;
512 static vec_t r_farclip_directiondist;
513 static vec_t r_farclip_meshfarclip;
514 static int r_farclip_directionbit0;
515 static int r_farclip_directionbit1;
516 static int r_farclip_directionbit2;
517
518 // enlarge farclip to accomodate box
519 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
520 {
521         float d;
522         d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
523           + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
524           + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
525         if (r_farclip_meshfarclip < d)
526                 r_farclip_meshfarclip = d;
527 }
528
529 // return farclip value
530 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
531 {
532         int i;
533
534         VectorCopy(origin, r_farclip_origin);
535         VectorCopy(direction, r_farclip_direction);
536         r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
537         r_farclip_directionbit0 = r_farclip_direction[0] < 0;
538         r_farclip_directionbit1 = r_farclip_direction[1] < 0;
539         r_farclip_directionbit2 = r_farclip_direction[2] < 0;
540         r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
541
542         if (r_refdef.worldmodel)
543                 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
544         for (i = 0;i < r_refdef.numentities;i++)
545                 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
546
547         return r_farclip_meshfarclip - r_farclip_directiondist;
548 }
549
550 extern void R_Textures_Init(void);
551 extern void Mod_RenderInit(void);
552 extern void GL_Draw_Init(void);
553 extern void GL_Main_Init(void);
554 extern void R_Shadow_Init(void);
555 extern void GL_Models_Init(void);
556 extern void R_Sky_Init(void);
557 extern void GL_Surf_Init(void);
558 extern void R_Crosshairs_Init(void);
559 extern void R_Light_Init(void);
560 extern void R_Particles_Init(void);
561 extern void R_Explosion_Init(void);
562 extern void ui_init(void);
563 extern void gl_backend_init(void);
564 extern void Sbar_Init(void);
565 extern void R_LightningBeams_Init(void);
566
567 void Render_Init(void)
568 {
569         R_Textures_Init();
570         Mod_RenderInit();
571         gl_backend_init();
572         R_MeshQueue_Init();
573         GL_Draw_Init();
574         GL_Main_Init();
575         R_Shadow_Init();
576         GL_Models_Init();
577         R_Sky_Init();
578         GL_Surf_Init();
579         R_Crosshairs_Init();
580         R_Light_Init();
581         R_Particles_Init();
582         R_Explosion_Init();
583         //ui_init();
584         UI_Init();
585         Sbar_Init();
586         R_LightningBeams_Init();
587 }
588
589 /*
590 ===============
591 GL_Init
592 ===============
593 */
594 extern char *ENGINE_EXTENSIONS;
595 void GL_Init (void)
596 {
597         VID_CheckExtensions();
598
599         // LordHavoc: report supported extensions
600         Con_DPrintf("\nengine extensions: %s\n", ENGINE_EXTENSIONS);
601
602         // clear to black (loading plaque will be seen over this)
603         qglClearColor(0,0,0,1);
604         qglClear(GL_COLOR_BUFFER_BIT);
605 }
606
607 int R_CullBox(const vec3_t mins, const vec3_t maxs)
608 {
609         int i;
610         mplane_t *p;
611         for (i = 0;i < 4;i++)
612         {
613                 p = frustum + i;
614                 switch(p->signbits)
615                 {
616                 default:
617                 case 0:
618                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
619                                 return true;
620                         break;
621                 case 1:
622                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
623                                 return true;
624                         break;
625                 case 2:
626                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
627                                 return true;
628                         break;
629                 case 3:
630                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
631                                 return true;
632                         break;
633                 case 4:
634                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
635                                 return true;
636                         break;
637                 case 5:
638                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
639                                 return true;
640                         break;
641                 case 6:
642                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
643                                 return true;
644                         break;
645                 case 7:
646                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
647                                 return true;
648                         break;
649                 }
650         }
651         return false;
652 }
653
654 //==================================================================================
655
656 static void R_MarkEntities (void)
657 {
658         int i, renderimask;
659         entity_render_t *ent;
660
661         if (!r_drawentities.integer)
662                 return;
663
664         r_refdef.worldentity->visframe = r_framecount;
665         renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
666         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
667         {
668                 // worldmodel can check visibility
669                 for (i = 0;i < r_refdef.numentities;i++)
670                 {
671                         ent = r_refdef.entities[i];
672                         Mod_CheckLoaded(ent->model);
673                         // some of the renderer still relies on origin...
674                         Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
675                         // some of the renderer still relies on scale...
676                         ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
677                         if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && ((ent->effects & EF_NODEPTHTEST) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_worldleafvisible, ent->mins, ent->maxs)))
678                         {
679                                 R_UpdateEntLights(ent);
680                                 ent->visframe = r_framecount;
681                         }
682                 }
683         }
684         else
685         {
686                 // no worldmodel or it can't check visibility
687                 for (i = 0;i < r_refdef.numentities;i++)
688                 {
689                         ent = r_refdef.entities[i];
690                         Mod_CheckLoaded(ent->model);
691                         // some of the renderer still relies on origin...
692                         Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
693                         // some of the renderer still relies on scale...
694                         ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
695                         if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
696                         {
697                                 R_UpdateEntLights(ent);
698                                 ent->visframe = r_framecount;
699                         }
700                 }
701         }
702 }
703
704 // only used if skyrendermasked, and normally returns false
705 int R_DrawBrushModelsSky (void)
706 {
707         int i, sky;
708         entity_render_t *ent;
709
710         if (!r_drawentities.integer)
711                 return false;
712
713         sky = false;
714         for (i = 0;i < r_refdef.numentities;i++)
715         {
716                 ent = r_refdef.entities[i];
717                 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
718                 {
719                         ent->model->DrawSky(ent);
720                         sky = true;
721                 }
722         }
723         return sky;
724 }
725
726 void R_DrawNoModel(entity_render_t *ent);
727 void R_DrawModels(void)
728 {
729         int i;
730         entity_render_t *ent;
731
732         if (!r_drawentities.integer)
733                 return;
734
735         for (i = 0;i < r_refdef.numentities;i++)
736         {
737                 ent = r_refdef.entities[i];
738                 if (ent->visframe == r_framecount)
739                 {
740                         if (ent->model && ent->model->Draw != NULL)
741                                 ent->model->Draw(ent);
742                         else
743                                 R_DrawNoModel(ent);
744                 }
745         }
746 }
747
748 static void R_SetFrustum(void)
749 {
750         // break apart the view matrix into vectors for various purposes
751         Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
752         VectorNegate(r_viewleft, r_viewright);
753
754         // LordHavoc: note to all quake engine coders, the special case for 90
755         // degrees assumed a square view (wrong), so I removed it, Quake2 has it
756         // disabled as well.
757
758         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
759         RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
760         frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
761         PlaneClassify(&frustum[0]);
762
763         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
764         RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
765         frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
766         PlaneClassify(&frustum[1]);
767
768         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
769         RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
770         frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
771         PlaneClassify(&frustum[2]);
772
773         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
774         RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
775         frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
776         PlaneClassify(&frustum[3]);
777 }
778
779 static void R_BlendView(void)
780 {
781         rmeshstate_t m;
782
783         if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
784                 return;
785
786         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
787         GL_DepthMask(true);
788         GL_DepthTest(false);
789         R_Mesh_Matrix(&r_identitymatrix);
790         // vertex coordinates for a quad that covers the screen exactly
791         varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
792         varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
793         varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
794         varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
795         if (r_bloom.integer && r_bloom_resolution.value >= 32 && r_bloom_power.integer >= 1 && r_bloom_power.integer < 100 && r_bloom_blur.value >= 0 && r_bloom_blur.value < 512)
796         {
797                 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
798                 float xoffset, yoffset, r;
799                 c_bloom++;
800                 // set the (poorly named) screenwidth and screenheight variables to
801                 // a power of 2 at least as large as the screen, these will define the
802                 // size of the texture to allocate
803                 for (screenwidth = 1;screenwidth < vid.realwidth;screenwidth *= 2);
804                 for (screenheight = 1;screenheight < vid.realheight;screenheight *= 2);
805                 // allocate textures as needed
806                 if (!r_bloom_texture_screen)
807                         r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
808                 if (!r_bloom_texture_bloom)
809                         r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
810                 // set bloomwidth and bloomheight to the bloom resolution that will be
811                 // used (often less than the screen resolution for faster rendering)
812                 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
813                 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
814                 // set up a texcoord array for the full resolution screen image
815                 // (we have to keep this around to copy back during final render)
816                 varray_texcoord2f[0][0] = 0;
817                 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
818                 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
819                 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
820                 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
821                 varray_texcoord2f[0][5] = 0;
822                 varray_texcoord2f[0][6] = 0;
823                 varray_texcoord2f[0][7] = 0;
824                 // set up a texcoord array for the reduced resolution bloom image
825                 // (which will be additive blended over the screen image)
826                 varray_texcoord2f[1][0] = 0;
827                 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
828                 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
829                 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
830                 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
831                 varray_texcoord2f[1][5] = 0;
832                 varray_texcoord2f[1][6] = 0;
833                 varray_texcoord2f[1][7] = 0;
834                 memset(&m, 0, sizeof(m));
835                 m.pointer_vertex = varray_vertex3f;
836                 m.pointer_texcoord[0] = varray_texcoord2f[0];
837                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
838                 R_Mesh_State(&m);
839                 // copy view into the full resolution screen image texture
840                 GL_ActiveTexture(0);
841                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
842                 c_bloomcopies++;
843                 c_bloomcopypixels += r_view_width * r_view_height;
844                 // now scale it down to the bloom size and raise to a power of itself
845                 // to darken it (this leaves the really bright stuff bright, and
846                 // everything else becomes very dark)
847                 // TODO: optimize with multitexture or GLSL
848                 qglViewport(r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
849                 GL_BlendFunc(GL_ONE, GL_ZERO);
850                 GL_Color(1, 1, 1, 1);
851                 R_Mesh_Draw(0, 4, 2, polygonelements);
852                 c_bloomdraws++;
853                 c_bloomdrawpixels += bloomwidth * bloomheight;
854                 // render multiple times with a multiply blendfunc to raise to a power
855                 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
856                 for (x = 1;x < r_bloom_power.integer;x++)
857                 {
858                         R_Mesh_Draw(0, 4, 2, polygonelements);
859                         c_bloomdraws++;
860                         c_bloomdrawpixels += bloomwidth * bloomheight;
861                 }
862                 // we now have a darkened bloom image in the framebuffer, copy it into
863                 // the bloom image texture for more processing
864                 memset(&m, 0, sizeof(m));
865                 m.pointer_vertex = varray_vertex3f;
866                 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
867                 m.pointer_texcoord[0] = varray_texcoord2f[2];
868                 R_Mesh_State(&m);
869                 GL_ActiveTexture(0);
870                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
871                 c_bloomcopies++;
872                 c_bloomcopypixels += bloomwidth * bloomheight;
873                 // blend on at multiple vertical offsets to achieve a vertical blur
874                 // TODO: do offset blends using GLSL
875                 range = r_bloom_blur.integer * bloomwidth / 320;
876                 GL_BlendFunc(GL_ONE, GL_ZERO);
877                 for (x = -range;x <= range;x++)
878                 {
879                         xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
880                         yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
881                         // compute a texcoord array with the specified x and y offset
882                         varray_texcoord2f[2][0] = xoffset+0;
883                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
884                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
885                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
886                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
887                         varray_texcoord2f[2][5] = yoffset+0;
888                         varray_texcoord2f[2][6] = xoffset+0;
889                         varray_texcoord2f[2][7] = yoffset+0;
890                         // this r value looks like a 'dot' particle, fading sharply to
891                         // black at the edges
892                         // (probably not realistic but looks good enough)
893                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
894                         if (r < 0.01f)
895                                 continue;
896                         GL_Color(r, r, r, 1);
897                         R_Mesh_Draw(0, 4, 2, polygonelements);
898                         c_bloomdraws++;
899                         c_bloomdrawpixels += bloomwidth * bloomheight;
900                         GL_BlendFunc(GL_ONE, GL_ONE);
901                 }
902                 // copy the vertically blurred bloom view to a texture
903                 GL_ActiveTexture(0);
904                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
905                 c_bloomcopies++;
906                 c_bloomcopypixels += bloomwidth * bloomheight;
907                 // blend the vertically blurred image at multiple offsets horizontally
908                 // to finish the blur effect
909                 // TODO: do offset blends using GLSL
910                 range = r_bloom_blur.integer * bloomwidth / 320;
911                 GL_BlendFunc(GL_ONE, GL_ZERO);
912                 for (x = -range;x <= range;x++)
913                 {
914                         xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
915                         yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
916                         // compute a texcoord array with the specified x and y offset
917                         varray_texcoord2f[2][0] = xoffset+0;
918                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
919                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
920                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
921                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
922                         varray_texcoord2f[2][5] = yoffset+0;
923                         varray_texcoord2f[2][6] = xoffset+0;
924                         varray_texcoord2f[2][7] = yoffset+0;
925                         // this r value looks like a 'dot' particle, fading sharply to
926                         // black at the edges
927                         // (probably not realistic but looks good enough)
928                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
929                         if (r < 0.01f)
930                                 continue;
931                         GL_Color(r, r, r, 1);
932                         R_Mesh_Draw(0, 4, 2, polygonelements);
933                         c_bloomdraws++;
934                         c_bloomdrawpixels += bloomwidth * bloomheight;
935                         GL_BlendFunc(GL_ONE, GL_ONE);
936                 }
937                 // copy the blurred bloom view to a texture
938                 GL_ActiveTexture(0);
939                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.realheight - (r_view_y + bloomheight), bloomwidth, bloomheight);
940                 c_bloomcopies++;
941                 c_bloomcopypixels += bloomwidth * bloomheight;
942                 // go back to full view area
943                 qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
944                 // put the original screen image back in place and blend the bloom
945                 // texture on it
946                 memset(&m, 0, sizeof(m));
947                 m.pointer_vertex = varray_vertex3f;
948                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
949                 m.pointer_texcoord[0] = varray_texcoord2f[0];
950 #if 0
951                 dobloomblend = false;
952 #else
953                 // do both in one pass if possible
954                 if (r_textureunits.integer >= 2 && gl_combine.integer)
955                 {
956                         dobloomblend = false;
957                         m.texcombinergb[1] = GL_ADD;
958                         m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
959                         m.pointer_texcoord[1] = varray_texcoord2f[1];
960                 }
961                 else
962                         dobloomblend = true;
963 #endif
964                 R_Mesh_State(&m);
965                 GL_BlendFunc(GL_ONE, GL_ZERO);
966                 GL_Color(1,1,1,1);
967                 R_Mesh_Draw(0, 4, 2, polygonelements);
968                 c_bloomdraws++;
969                 c_bloomdrawpixels += r_view_width * r_view_height;
970                 // now blend on the bloom texture if multipass
971                 if (dobloomblend)
972                 {
973                         memset(&m, 0, sizeof(m));
974                         m.pointer_vertex = varray_vertex3f;
975                         m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
976                         m.pointer_texcoord[0] = varray_texcoord2f[1];
977                         R_Mesh_State(&m);
978                         GL_BlendFunc(GL_ONE, GL_ONE);
979                         GL_Color(1,1,1,1);
980                         R_Mesh_Draw(0, 4, 2, polygonelements);
981                         c_bloomdraws++;
982                         c_bloomdrawpixels += r_view_width * r_view_height;
983                 }
984         }
985         if (r_refdef.viewblend[3] >= 0.01f)
986         {
987                 // apply a color tint to the whole view
988                 memset(&m, 0, sizeof(m));
989                 m.pointer_vertex = varray_vertex3f;
990                 R_Mesh_State(&m);
991                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
992                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
993                 R_Mesh_Draw(0, 4, 2, polygonelements);
994         }
995 }
996
997 void R_RenderScene(void);
998
999 /*
1000 ================
1001 R_RenderView
1002 ================
1003 */
1004 void R_RenderView(void)
1005 {
1006         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1007                 return; //Host_Error ("R_RenderView: NULL worldmodel");
1008
1009         r_view_width = bound(0, r_refdef.width, vid.realwidth);
1010         r_view_height = bound(0, r_refdef.height, vid.realheight);
1011         r_view_depth = 1;
1012         r_view_x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width);
1013         r_view_y = bound(0, r_refdef.y, vid.realheight - r_refdef.height);
1014         r_view_z = 0;
1015         r_view_fov_x = bound(1, r_refdef.fov_x, 170);
1016         r_view_fov_y = bound(1, r_refdef.fov_y, 170);
1017         r_view_matrix = r_refdef.viewentitymatrix;
1018         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1019         r_rtworld = r_shadow_realtime_world.integer;
1020         r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1021         r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1022         r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1023         r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1024
1025         // GL is weird because it's bottom to top, r_view_y is top to bottom
1026         qglViewport(r_view_x, vid.realheight - (r_view_y + r_view_height), r_view_width, r_view_height);
1027         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1028         GL_ScissorTest(true);
1029         GL_DepthMask(true);
1030         R_ClearScreen();
1031         R_Textures_Frame();
1032         R_UpdateFog();
1033         R_UpdateLights();
1034         R_TimeReport("setup");
1035
1036         qglDepthFunc(GL_LEQUAL);
1037         qglPolygonOffset(0, 0);
1038         qglEnable(GL_POLYGON_OFFSET_FILL);
1039
1040         R_RenderScene();
1041
1042         qglPolygonOffset(0, 0);
1043         qglDisable(GL_POLYGON_OFFSET_FILL);
1044
1045         R_BlendView();
1046         R_TimeReport("blendview");
1047
1048         GL_Scissor(0, 0, vid.realwidth, vid.realheight);
1049         GL_ScissorTest(false);
1050 }
1051
1052 extern void R_DrawLightningBeams (void);
1053 void R_RenderScene(void)
1054 {
1055         // don't let sound skip if going slow
1056         if (r_refdef.extraupdate)
1057                 S_ExtraUpdate ();
1058
1059         r_framecount++;
1060
1061         R_MeshQueue_BeginScene();
1062
1063         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1064
1065         R_SetFrustum();
1066
1067         r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1068         if (r_rtworldshadows || r_rtdlightshadows)
1069                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1070         else
1071                 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1072
1073         GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1074
1075         R_SkyStartFrame();
1076
1077         R_WorldVisibility();
1078         R_TimeReport("worldvis");
1079
1080         R_MarkEntities();
1081         R_TimeReport("markentity");
1082
1083         R_Shadow_UpdateWorldLightSelection();
1084
1085         // don't let sound skip if going slow
1086         if (r_refdef.extraupdate)
1087                 S_ExtraUpdate ();
1088
1089         GL_ShowTrisColor(0.025, 0.025, 0, 1);
1090         if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1091         {
1092                 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1093                 R_TimeReport("worldsky");
1094         }
1095
1096         if (R_DrawBrushModelsSky())
1097                 R_TimeReport("bmodelsky");
1098
1099         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1100         if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1101         {
1102                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1103                 R_TimeReport("world");
1104         }
1105
1106         // don't let sound skip if going slow
1107         if (r_refdef.extraupdate)
1108                 S_ExtraUpdate ();
1109
1110         GL_ShowTrisColor(0, 0.015, 0, 1);
1111
1112         R_DrawModels();
1113         R_TimeReport("models");
1114
1115         // don't let sound skip if going slow
1116         if (r_refdef.extraupdate)
1117                 S_ExtraUpdate ();
1118
1119         GL_ShowTrisColor(0, 0, 0.033, 1);
1120         R_ShadowVolumeLighting(false);
1121         R_TimeReport("rtlights");
1122
1123         // don't let sound skip if going slow
1124         if (r_refdef.extraupdate)
1125                 S_ExtraUpdate ();
1126
1127         GL_ShowTrisColor(0.1, 0, 0, 1);
1128
1129         R_DrawLightningBeams();
1130         R_TimeReport("lightning");
1131
1132         R_DrawParticles();
1133         R_TimeReport("particles");
1134
1135         R_DrawExplosions();
1136         R_TimeReport("explosions");
1137
1138         R_MeshQueue_RenderTransparent();
1139         R_TimeReport("drawtrans");
1140
1141         R_DrawCoronas();
1142         R_TimeReport("coronas");
1143
1144         R_DrawWorldCrosshair();
1145         R_TimeReport("crosshair");
1146
1147         R_MeshQueue_Render();
1148         R_MeshQueue_EndScene();
1149
1150         if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1151         {
1152                 R_ShadowVolumeLighting(true);
1153                 R_TimeReport("visiblevolume");
1154         }
1155
1156         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1157
1158         // don't let sound skip if going slow
1159         if (r_refdef.extraupdate)
1160                 S_ExtraUpdate ();
1161 }
1162
1163 /*
1164 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1165 {
1166         int i;
1167         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1168         rmeshstate_t m;
1169         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1170         GL_DepthMask(false);
1171         GL_DepthTest(true);
1172         R_Mesh_Matrix(&r_identitymatrix);
1173
1174         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1175         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1176         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1177         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1178         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1179         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1180         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1181         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1182         R_FillColors(color, 8, cr, cg, cb, ca);
1183         if (fogenabled)
1184         {
1185                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1186                 {
1187                         VectorSubtract(v, r_vieworigin, diff);
1188                         f2 = exp(fogdensity/DotProduct(diff, diff));
1189                         f1 = 1 - f2;
1190                         c[0] = c[0] * f1 + fogcolor[0] * f2;
1191                         c[1] = c[1] * f1 + fogcolor[1] * f2;
1192                         c[2] = c[2] * f1 + fogcolor[2] * f2;
1193                 }
1194         }
1195         memset(&m, 0, sizeof(m));
1196         m.pointer_vertex = vertex3f;
1197         m.pointer_color = color;
1198         R_Mesh_State(&m);
1199         R_Mesh_Draw(8, 12);
1200 }
1201 */
1202
1203 int nomodelelements[24] =
1204 {
1205         5, 2, 0,
1206         5, 1, 2,
1207         5, 0, 3,
1208         5, 3, 1,
1209         0, 2, 4,
1210         2, 1, 4,
1211         3, 0, 4,
1212         1, 3, 4
1213 };
1214
1215 float nomodelvertex3f[6*3] =
1216 {
1217         -16,   0,   0,
1218          16,   0,   0,
1219           0, -16,   0,
1220           0,  16,   0,
1221           0,   0, -16,
1222           0,   0,  16
1223 };
1224
1225 float nomodelcolor4f[6*4] =
1226 {
1227         0.0f, 0.0f, 0.5f, 1.0f,
1228         0.0f, 0.0f, 0.5f, 1.0f,
1229         0.0f, 0.5f, 0.0f, 1.0f,
1230         0.0f, 0.5f, 0.0f, 1.0f,
1231         0.5f, 0.0f, 0.0f, 1.0f,
1232         0.5f, 0.0f, 0.0f, 1.0f
1233 };
1234
1235 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1236 {
1237         const entity_render_t *ent = calldata1;
1238         int i;
1239         float f1, f2, *c, diff[3];
1240         float color4f[6*4];
1241         rmeshstate_t m;
1242         R_Mesh_Matrix(&ent->matrix);
1243
1244         memset(&m, 0, sizeof(m));
1245         m.pointer_vertex = nomodelvertex3f;
1246
1247         if (ent->flags & EF_ADDITIVE)
1248         {
1249                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1250                 GL_DepthMask(false);
1251         }
1252         else if (ent->alpha < 1)
1253         {
1254                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1255                 GL_DepthMask(false);
1256         }
1257         else
1258         {
1259                 GL_BlendFunc(GL_ONE, GL_ZERO);
1260                 GL_DepthMask(true);
1261         }
1262         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1263         if (fogenabled)
1264         {
1265                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1266                 m.pointer_color = color4f;
1267                 VectorSubtract(ent->origin, r_vieworigin, diff);
1268                 f2 = exp(fogdensity/DotProduct(diff, diff));
1269                 f1 = 1 - f2;
1270                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1271                 {
1272                         c[0] = (c[0] * f1 + fogcolor[0] * f2);
1273                         c[1] = (c[1] * f1 + fogcolor[1] * f2);
1274                         c[2] = (c[2] * f1 + fogcolor[2] * f2);
1275                         c[3] *= ent->alpha;
1276                 }
1277         }
1278         else if (ent->alpha != 1)
1279         {
1280                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1281                 m.pointer_color = color4f;
1282                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1283                         c[3] *= ent->alpha;
1284         }
1285         else
1286                 m.pointer_color = nomodelcolor4f;
1287         R_Mesh_State(&m);
1288         R_Mesh_Draw(0, 6, 8, nomodelelements);
1289 }
1290
1291 void R_DrawNoModel(entity_render_t *ent)
1292 {
1293         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1294                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1295         //else
1296         //      R_DrawNoModelCallback(ent, 0);
1297 }
1298
1299 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1300 {
1301         vec3_t right1, right2, diff, normal;
1302
1303         VectorSubtract (org2, org1, normal);
1304
1305         // calculate 'right' vector for start
1306         VectorSubtract (r_vieworigin, org1, diff);
1307         CrossProduct (normal, diff, right1);
1308         VectorNormalize (right1);
1309
1310         // calculate 'right' vector for end
1311         VectorSubtract (r_vieworigin, org2, diff);
1312         CrossProduct (normal, diff, right2);
1313         VectorNormalize (right2);
1314
1315         vert[ 0] = org1[0] + width * right1[0];
1316         vert[ 1] = org1[1] + width * right1[1];
1317         vert[ 2] = org1[2] + width * right1[2];
1318         vert[ 3] = org1[0] - width * right1[0];
1319         vert[ 4] = org1[1] - width * right1[1];
1320         vert[ 5] = org1[2] - width * right1[2];
1321         vert[ 6] = org2[0] - width * right2[0];
1322         vert[ 7] = org2[1] - width * right2[1];
1323         vert[ 8] = org2[2] - width * right2[2];
1324         vert[ 9] = org2[0] + width * right2[0];
1325         vert[10] = org2[1] + width * right2[1];
1326         vert[11] = org2[2] + width * right2[2];
1327 }
1328
1329 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1330
1331 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, int depthdisable, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2, float cr, float cg, float cb, float ca)
1332 {
1333         float diff[3];
1334         rmeshstate_t m;
1335
1336         if (fogenabled)
1337         {
1338                 VectorSubtract(origin, r_vieworigin, diff);
1339                 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1340         }
1341
1342         R_Mesh_Matrix(&r_identitymatrix);
1343         GL_BlendFunc(blendfunc1, blendfunc2);
1344         GL_DepthMask(false);
1345         GL_DepthTest(!depthdisable);
1346
1347         varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1348         varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1349         varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1350         varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1351         varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1352         varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1353         varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1354         varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1355         varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1356         varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1357         varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1358         varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1359
1360         memset(&m, 0, sizeof(m));
1361         m.tex[0] = R_GetTexture(texture);
1362         m.pointer_texcoord[0] = spritetexcoord2f;
1363         m.pointer_vertex = varray_vertex3f;
1364         R_Mesh_State(&m);
1365         GL_Color(cr, cg, cb, ca);
1366         R_Mesh_Draw(0, 4, 2, polygonelements);
1367 }
1368