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