]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fb0821df1aafc0210ae01deba26731b0b4edd338
[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
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 r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1"};
108
109 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0"};
110
111 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0"};
112
113 rtexturepool_t *r_main_texturepool;
114 rtexture_t *r_bloom_texture_screen;
115 rtexture_t *r_bloom_texture_bloom;
116 rtexture_t *r_texture_blanknormalmap;
117 rtexture_t *r_texture_white;
118 rtexture_t *r_texture_black;
119 rtexture_t *r_texture_notexture;
120 rtexture_t *r_texture_whitecube;
121 rtexture_t *r_texture_normalizationcube;
122 rtexture_t *r_texture_detailtextures[NUM_DETAILTEXTURES];
123 rtexture_t *r_texture_distorttexture[64];
124
125 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
126 {
127         int i;
128         for (i = 0;i < verts;i++)
129         {
130                 out[0] = in[0] * r;
131                 out[1] = in[1] * g;
132                 out[2] = in[2] * b;
133                 out[3] = in[3];
134                 in += 4;
135                 out += 4;
136         }
137 }
138
139 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
140 {
141         int i;
142         for (i = 0;i < verts;i++)
143         {
144                 out[0] = r;
145                 out[1] = g;
146                 out[2] = b;
147                 out[3] = a;
148                 out += 4;
149         }
150 }
151
152 vec3_t fogcolor;
153 vec_t fogdensity;
154 float fog_density, fog_red, fog_green, fog_blue;
155 qboolean fogenabled;
156 qboolean oldgl_fogenable;
157 void R_UpdateFog(void)
158 {
159         if (gamemode == GAME_NEHAHRA)
160         {
161                 if (gl_fogenable.integer)
162                 {
163                         oldgl_fogenable = true;
164                         fog_density = gl_fogdensity.value;
165                         fog_red = gl_fogred.value;
166                         fog_green = gl_foggreen.value;
167                         fog_blue = gl_fogblue.value;
168                 }
169                 else if (oldgl_fogenable)
170                 {
171                         oldgl_fogenable = false;
172                         fog_density = 0;
173                         fog_red = 0;
174                         fog_green = 0;
175                         fog_blue = 0;
176                 }
177         }
178         if (fog_density)
179         {
180                 fogcolor[0] = fog_red   = bound(0.0f, fog_red  , 1.0f);
181                 fogcolor[1] = fog_green = bound(0.0f, fog_green, 1.0f);
182                 fogcolor[2] = fog_blue  = bound(0.0f, fog_blue , 1.0f);
183         }
184         if (fog_density)
185         {
186                 fogenabled = true;
187                 fogdensity = -4000.0f / (fog_density * fog_density);
188                 // fog color was already set
189         }
190         else
191                 fogenabled = false;
192 }
193
194 // FIXME: move this to client?
195 void FOG_clear(void)
196 {
197         if (gamemode == GAME_NEHAHRA)
198         {
199                 Cvar_Set("gl_fogenable", "0");
200                 Cvar_Set("gl_fogdensity", "0.2");
201                 Cvar_Set("gl_fogred", "0.3");
202                 Cvar_Set("gl_foggreen", "0.3");
203                 Cvar_Set("gl_fogblue", "0.3");
204         }
205         fog_density = fog_red = fog_green = fog_blue = 0.0f;
206 }
207
208 // FIXME: move this to client?
209 void FOG_registercvars(void)
210 {
211         if (gamemode == GAME_NEHAHRA)
212         {
213                 Cvar_RegisterVariable (&gl_fogenable);
214                 Cvar_RegisterVariable (&gl_fogdensity);
215                 Cvar_RegisterVariable (&gl_fogred);
216                 Cvar_RegisterVariable (&gl_foggreen);
217                 Cvar_RegisterVariable (&gl_fogblue);
218                 Cvar_RegisterVariable (&gl_fogstart);
219                 Cvar_RegisterVariable (&gl_fogend);
220         }
221 }
222
223 static void R_BuildDetailTextures (void)
224 {
225         int i, x, y, light;
226         float vc[3], vx[3], vy[3], vn[3], lightdir[3];
227 #define DETAILRESOLUTION 256
228         qbyte (*data)[DETAILRESOLUTION][4];
229         qbyte (*noise)[DETAILRESOLUTION];
230
231         // Allocate the buffers dynamically to avoid having such big guys on the stack
232         data = Mem_Alloc(tempmempool, DETAILRESOLUTION * sizeof(*data));
233         noise = Mem_Alloc(tempmempool, DETAILRESOLUTION * sizeof(*noise));
234
235         lightdir[0] = 0.5;
236         lightdir[1] = 1;
237         lightdir[2] = -0.25;
238         VectorNormalize(lightdir);
239         for (i = 0;i < NUM_DETAILTEXTURES;i++)
240         {
241                 fractalnoise(&noise[0][0], DETAILRESOLUTION, DETAILRESOLUTION >> 4);
242                 for (y = 0;y < DETAILRESOLUTION;y++)
243                 {
244                         for (x = 0;x < DETAILRESOLUTION;x++)
245                         {
246                                 vc[0] = x;
247                                 vc[1] = y;
248                                 vc[2] = noise[y][x] * (1.0f / 32.0f);
249                                 vx[0] = x + 1;
250                                 vx[1] = y;
251                                 vx[2] = noise[y][(x + 1) % DETAILRESOLUTION] * (1.0f / 32.0f);
252                                 vy[0] = x;
253                                 vy[1] = y + 1;
254                                 vy[2] = noise[(y + 1) % DETAILRESOLUTION][x] * (1.0f / 32.0f);
255                                 VectorSubtract(vx, vc, vx);
256                                 VectorSubtract(vy, vc, vy);
257                                 CrossProduct(vx, vy, vn);
258                                 VectorNormalize(vn);
259                                 light = 128 - DotProduct(vn, lightdir) * 128;
260                                 light = bound(0, light, 255);
261                                 data[y][x][0] = data[y][x][1] = data[y][x][2] = light;
262                                 data[y][x][3] = 255;
263                         }
264                 }
265                 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);
266         }
267
268         Mem_Free(noise);
269         Mem_Free(data);
270 }
271
272 static qbyte R_MorphDistortTexture (double y0, double y1, double y2, double y3, double morph)
273 {
274         int m = (int)(((y1 + y3 - (y0 + y2)) * morph * morph * morph) +
275                         ((2 * (y0 - y1) + y2 - y3) * morph * morph) +
276                         ((y2 - y0) * morph) +
277                         (y1));
278         return (qbyte)bound(0, m, 255);
279 }
280
281 static void R_BuildDistortTexture (void)
282 {
283         int x, y, i, j;
284 #define DISTORTRESOLUTION 32
285         qbyte data[5][DISTORTRESOLUTION][DISTORTRESOLUTION][2];
286
287         for (i=0; i<4; i++)
288         {
289                 for (y=0; y<DISTORTRESOLUTION; y++)
290                 {
291                         for (x=0; x<DISTORTRESOLUTION; x++)
292                         {
293                                 data[i][y][x][0] = rand () & 255;
294                                 data[i][y][x][1] = rand () & 255;
295                         }
296                 }
297         }
298
299         for (i=0; i<4; i++)
300         {
301                 for (j=0; j<16; j++)
302                 {
303                         r_texture_distorttexture[i*16+j] = NULL;
304                         if (gl_textureshader)
305                         {
306                                 for (y=0; y<DISTORTRESOLUTION; y++)
307                                 {
308                                         for (x=0; x<DISTORTRESOLUTION; x++)
309                                         {
310                                                 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);
311                                                 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);
312                                         }
313                                 }
314                                 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);
315                         }
316                 }
317         }
318 }
319
320 static void R_BuildBlankTextures(void)
321 {
322         qbyte data[4];
323         data[0] = 128; // normal X
324         data[1] = 128; // normal Y
325         data[2] = 255; // normal Z
326         data[3] = 128; // height
327         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
328         data[0] = 255;
329         data[1] = 255;
330         data[2] = 255;
331         data[3] = 255;
332         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
333         data[0] = 0;
334         data[1] = 0;
335         data[2] = 0;
336         data[3] = 255;
337         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_RGBA, TEXF_PRECACHE, NULL);
338 }
339
340 static void R_BuildNoTexture(void)
341 {
342         int x, y;
343         qbyte pix[16][16][4];
344         // this makes a light grey/dark grey checkerboard texture
345         for (y = 0;y < 16;y++)
346         {
347                 for (x = 0;x < 16;x++)
348                 {
349                         if ((y < 8) ^ (x < 8))
350                         {
351                                 pix[y][x][0] = 128;
352                                 pix[y][x][1] = 128;
353                                 pix[y][x][2] = 128;
354                                 pix[y][x][3] = 255;
355                         }
356                         else
357                         {
358                                 pix[y][x][0] = 64;
359                                 pix[y][x][1] = 64;
360                                 pix[y][x][2] = 64;
361                                 pix[y][x][3] = 255;
362                         }
363                 }
364         }
365         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_RGBA, TEXF_MIPMAP, NULL);
366 }
367
368 static void R_BuildWhiteCube(void)
369 {
370         qbyte data[6*1*1*4];
371         data[ 0] = 255;data[ 1] = 255;data[ 2] = 255;data[ 3] = 255;
372         data[ 4] = 255;data[ 5] = 255;data[ 6] = 255;data[ 7] = 255;
373         data[ 8] = 255;data[ 9] = 255;data[10] = 255;data[11] = 255;
374         data[12] = 255;data[13] = 255;data[14] = 255;data[15] = 255;
375         data[16] = 255;data[17] = 255;data[18] = 255;data[19] = 255;
376         data[20] = 255;data[21] = 255;data[22] = 255;data[23] = 255;
377         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
378 }
379
380 static void R_BuildNormalizationCube(void)
381 {
382         int x, y, side;
383         vec3_t v;
384         vec_t s, t, intensity;
385 #define NORMSIZE 64
386         qbyte data[6][NORMSIZE][NORMSIZE][4];
387         for (side = 0;side < 6;side++)
388         {
389                 for (y = 0;y < NORMSIZE;y++)
390                 {
391                         for (x = 0;x < NORMSIZE;x++)
392                         {
393                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
394                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
395                                 switch(side)
396                                 {
397                                 case 0:
398                                         v[0] = 1;
399                                         v[1] = -t;
400                                         v[2] = -s;
401                                         break;
402                                 case 1:
403                                         v[0] = -1;
404                                         v[1] = -t;
405                                         v[2] = s;
406                                         break;
407                                 case 2:
408                                         v[0] = s;
409                                         v[1] = 1;
410                                         v[2] = t;
411                                         break;
412                                 case 3:
413                                         v[0] = s;
414                                         v[1] = -1;
415                                         v[2] = -t;
416                                         break;
417                                 case 4:
418                                         v[0] = s;
419                                         v[1] = -t;
420                                         v[2] = 1;
421                                         break;
422                                 case 5:
423                                         v[0] = -s;
424                                         v[1] = -t;
425                                         v[2] = -1;
426                                         break;
427                                 }
428                                 intensity = 127.0f / sqrt(DotProduct(v, v));
429                                 data[side][y][x][0] = 128.0f + intensity * v[0];
430                                 data[side][y][x][1] = 128.0f + intensity * v[1];
431                                 data[side][y][x][2] = 128.0f + intensity * v[2];
432                                 data[side][y][x][3] = 255;
433                         }
434                 }
435         }
436         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_RGBA, TEXF_PRECACHE | TEXF_CLAMP, NULL);
437 }
438
439 void gl_main_start(void)
440 {
441         r_main_texturepool = R_AllocTexturePool();
442         r_bloom_texture_screen = NULL;
443         r_bloom_texture_bloom = NULL;
444         R_BuildBlankTextures();
445         R_BuildNoTexture();
446         R_BuildDetailTextures();
447         R_BuildDistortTexture();
448         if (gl_texturecubemap)
449         {
450                 R_BuildWhiteCube();
451                 R_BuildNormalizationCube();
452         }
453 }
454
455 void gl_main_shutdown(void)
456 {
457         R_FreeTexturePool(&r_main_texturepool);
458         r_bloom_texture_screen = NULL;
459         r_bloom_texture_bloom = NULL;
460         r_texture_blanknormalmap = NULL;
461         r_texture_white = NULL;
462         r_texture_black = NULL;
463         r_texture_whitecube = NULL;
464         r_texture_normalizationcube = NULL;
465 }
466
467 extern void CL_ParseEntityLump(char *entitystring);
468 void gl_main_newmap(void)
469 {
470         // FIXME: move this code to client
471         int l;
472         char *entities, entname[MAX_QPATH];
473         r_framecount = 1;
474         if (cl.worldmodel)
475         {
476                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
477                 l = (int)strlen(entname) - 4;
478                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
479                 {
480                         strcpy(entname + l, ".ent");
481                         if ((entities = FS_LoadFile(entname, tempmempool, true)))
482                         {
483                                 CL_ParseEntityLump(entities);
484                                 Mem_Free(entities);
485                                 return;
486                         }
487                 }
488                 if (cl.worldmodel->brush.entities)
489                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
490         }
491 }
492
493 void GL_Main_Init(void)
494 {
495         Matrix4x4_CreateIdentity(&r_identitymatrix);
496 // FIXME: move this to client?
497         FOG_registercvars();
498         Cvar_RegisterVariable(&r_showtris);
499         Cvar_RegisterVariable(&r_drawentities);
500         Cvar_RegisterVariable(&r_drawviewmodel);
501         Cvar_RegisterVariable(&r_speeds);
502         Cvar_RegisterVariable(&r_fullbrights);
503         Cvar_RegisterVariable(&r_wateralpha);
504         Cvar_RegisterVariable(&r_dynamic);
505         Cvar_RegisterVariable(&r_fullbright);
506         Cvar_RegisterVariable(&r_textureunits);
507         Cvar_RegisterVariable(&r_lerpsprites);
508         Cvar_RegisterVariable(&r_lerpmodels);
509         Cvar_RegisterVariable(&r_waterscroll);
510         Cvar_RegisterVariable(&r_drawcollisionbrushes);
511         Cvar_RegisterVariable(&r_bloom);
512         Cvar_RegisterVariable(&r_bloom_intensity);
513         Cvar_RegisterVariable(&r_bloom_blur);
514         Cvar_RegisterVariable(&r_bloom_resolution);
515         Cvar_RegisterVariable(&r_bloom_power);
516         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
517         Cvar_RegisterVariable(&developer_texturelogging);
518         Cvar_RegisterVariable(&gl_lightmaps);
519         if (gamemode == GAME_NEHAHRA || gamemode == GAME_NEXUIZ || gamemode == GAME_TENEBRAE)
520                 Cvar_SetValue("r_fullbrights", 0);
521         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
522 }
523
524 static vec3_t r_farclip_origin;
525 static vec3_t r_farclip_direction;
526 static vec_t r_farclip_directiondist;
527 static vec_t r_farclip_meshfarclip;
528 static int r_farclip_directionbit0;
529 static int r_farclip_directionbit1;
530 static int r_farclip_directionbit2;
531
532 // enlarge farclip to accomodate box
533 static void R_FarClip_Box(vec3_t mins, vec3_t maxs)
534 {
535         float d;
536         d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
537           + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
538           + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
539         if (r_farclip_meshfarclip < d)
540                 r_farclip_meshfarclip = d;
541 }
542
543 // return farclip value
544 static float R_FarClip(vec3_t origin, vec3_t direction, vec_t startfarclip)
545 {
546         int i;
547
548         VectorCopy(origin, r_farclip_origin);
549         VectorCopy(direction, r_farclip_direction);
550         r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
551         r_farclip_directionbit0 = r_farclip_direction[0] < 0;
552         r_farclip_directionbit1 = r_farclip_direction[1] < 0;
553         r_farclip_directionbit2 = r_farclip_direction[2] < 0;
554         r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
555
556         if (r_refdef.worldmodel)
557                 R_FarClip_Box(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
558         for (i = 0;i < r_refdef.numentities;i++)
559                 R_FarClip_Box(r_refdef.entities[i]->mins, r_refdef.entities[i]->maxs);
560
561         return r_farclip_meshfarclip - r_farclip_directiondist;
562 }
563
564 extern void R_Textures_Init(void);
565 extern void GL_Draw_Init(void);
566 extern void GL_Main_Init(void);
567 extern void R_Shadow_Init(void);
568 extern void R_Sky_Init(void);
569 extern void GL_Surf_Init(void);
570 extern void R_Crosshairs_Init(void);
571 extern void R_Light_Init(void);
572 extern void R_Particles_Init(void);
573 extern void R_Explosion_Init(void);
574 extern void gl_backend_init(void);
575 extern void Sbar_Init(void);
576 extern void R_LightningBeams_Init(void);
577 extern void Mod_RenderInit(void);
578
579 void Render_Init(void)
580 {
581         gl_backend_init();
582         R_Textures_Init();
583         R_MeshQueue_Init();
584         GL_Main_Init();
585         GL_Draw_Init();
586         R_Shadow_Init();
587         R_Sky_Init();
588         GL_Surf_Init();
589         R_Crosshairs_Init();
590         R_Light_Init();
591         R_Particles_Init();
592         R_Explosion_Init();
593         UI_Init();
594         Sbar_Init();
595         R_LightningBeams_Init();
596         Mod_RenderInit();
597 }
598
599 /*
600 ===============
601 GL_Init
602 ===============
603 */
604 extern char *ENGINE_EXTENSIONS;
605 void GL_Init (void)
606 {
607         VID_CheckExtensions();
608
609         // LordHavoc: report supported extensions
610         Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
611
612         // clear to black (loading plaque will be seen over this)
613         qglClearColor(0,0,0,1);
614         qglClear(GL_COLOR_BUFFER_BIT);
615 }
616
617 int R_CullBox(const vec3_t mins, const vec3_t maxs)
618 {
619         int i;
620         mplane_t *p;
621         for (i = 0;i < 4;i++)
622         {
623                 p = frustum + i;
624                 switch(p->signbits)
625                 {
626                 default:
627                 case 0:
628                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
629                                 return true;
630                         break;
631                 case 1:
632                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
633                                 return true;
634                         break;
635                 case 2:
636                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
637                                 return true;
638                         break;
639                 case 3:
640                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
641                                 return true;
642                         break;
643                 case 4:
644                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
645                                 return true;
646                         break;
647                 case 5:
648                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
649                                 return true;
650                         break;
651                 case 6:
652                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
653                                 return true;
654                         break;
655                 case 7:
656                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
657                                 return true;
658                         break;
659                 }
660         }
661         return false;
662 }
663
664 //==================================================================================
665
666 static void R_MarkEntities (void)
667 {
668         int i, renderimask;
669         entity_render_t *ent;
670
671         if (!r_drawentities.integer)
672                 return;
673
674         r_refdef.worldentity->visframe = r_framecount;
675         renderimask = envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : (chase_active.integer ? 0 : RENDER_EXTERIORMODEL);
676         if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
677         {
678                 // worldmodel can check visibility
679                 for (i = 0;i < r_refdef.numentities;i++)
680                 {
681                         ent = r_refdef.entities[i];
682                         Mod_CheckLoaded(ent->model);
683                         // some of the renderer still relies on origin...
684                         Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
685                         // some of the renderer still relies on scale...
686                         ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
687                         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)))
688                         {
689                                 R_UpdateEntLights(ent);
690                                 ent->visframe = r_framecount;
691                         }
692                 }
693         }
694         else
695         {
696                 // no worldmodel or it can't check visibility
697                 for (i = 0;i < r_refdef.numentities;i++)
698                 {
699                         ent = r_refdef.entities[i];
700                         Mod_CheckLoaded(ent->model);
701                         // some of the renderer still relies on origin...
702                         Matrix4x4_OriginFromMatrix(&ent->matrix, ent->origin);
703                         // some of the renderer still relies on scale...
704                         ent->scale = Matrix4x4_ScaleFromMatrix(&ent->matrix);
705                         if (!(ent->flags & renderimask) && !R_CullBox(ent->mins, ent->maxs) && (ent->effects & EF_NODEPTHTEST))
706                         {
707                                 R_UpdateEntLights(ent);
708                                 ent->visframe = r_framecount;
709                         }
710                 }
711         }
712 }
713
714 // only used if skyrendermasked, and normally returns false
715 int R_DrawBrushModelsSky (void)
716 {
717         int i, sky;
718         entity_render_t *ent;
719
720         if (!r_drawentities.integer)
721                 return false;
722
723         sky = false;
724         for (i = 0;i < r_refdef.numentities;i++)
725         {
726                 ent = r_refdef.entities[i];
727                 if (ent->visframe == r_framecount && ent->model && ent->model->DrawSky)
728                 {
729                         ent->model->DrawSky(ent);
730                         sky = true;
731                 }
732         }
733         return sky;
734 }
735
736 void R_DrawNoModel(entity_render_t *ent);
737 void R_DrawModels(void)
738 {
739         int i;
740         entity_render_t *ent;
741
742         if (!r_drawentities.integer)
743                 return;
744
745         for (i = 0;i < r_refdef.numentities;i++)
746         {
747                 ent = r_refdef.entities[i];
748                 if (ent->visframe == r_framecount)
749                 {
750                         if (ent->model && ent->model->Draw != NULL)
751                                 ent->model->Draw(ent);
752                         else
753                                 R_DrawNoModel(ent);
754                 }
755         }
756 }
757
758 static void R_SetFrustum(void)
759 {
760         // break apart the view matrix into vectors for various purposes
761         Matrix4x4_ToVectors(&r_view_matrix, r_viewforward, r_viewleft, r_viewup, r_vieworigin);
762         VectorNegate(r_viewleft, r_viewright);
763
764         // LordHavoc: note to all quake engine coders, the special case for 90
765         // degrees assumed a square view (wrong), so I removed it, Quake2 has it
766         // disabled as well.
767
768         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
769         RotatePointAroundVector( frustum[0].normal, r_viewup, r_viewforward, -(90 - r_view_fov_x / 2));
770         frustum[0].dist = DotProduct (r_vieworigin, frustum[0].normal);
771         PlaneClassify(&frustum[0]);
772
773         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
774         RotatePointAroundVector( frustum[1].normal, r_viewup, r_viewforward, (90 - r_view_fov_x / 2));
775         frustum[1].dist = DotProduct (r_vieworigin, frustum[1].normal);
776         PlaneClassify(&frustum[1]);
777
778         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
779         RotatePointAroundVector( frustum[2].normal, r_viewleft, r_viewforward, -(90 - r_view_fov_y / 2));
780         frustum[2].dist = DotProduct (r_vieworigin, frustum[2].normal);
781         PlaneClassify(&frustum[2]);
782
783         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
784         RotatePointAroundVector( frustum[3].normal, r_viewleft, r_viewforward, (90 - r_view_fov_y / 2));
785         frustum[3].dist = DotProduct (r_vieworigin, frustum[3].normal);
786         PlaneClassify(&frustum[3]);
787
788         // nearclip plane
789         VectorCopy(r_viewforward, frustum[4].normal);
790         frustum[4].dist = DotProduct (r_vieworigin, frustum[4].normal) + 1.0f;
791         PlaneClassify(&frustum[4]);
792 }
793
794 static void R_BlendView(void)
795 {
796         rmeshstate_t m;
797
798         if (r_refdef.viewblend[3] < 0.01f && !r_bloom.integer)
799                 return;
800
801         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
802         GL_DepthMask(true);
803         GL_DepthTest(false);
804         R_Mesh_Matrix(&r_identitymatrix);
805         // vertex coordinates for a quad that covers the screen exactly
806         varray_vertex3f[0] = 0;varray_vertex3f[1] = 0;varray_vertex3f[2] = 0;
807         varray_vertex3f[3] = 1;varray_vertex3f[4] = 0;varray_vertex3f[5] = 0;
808         varray_vertex3f[6] = 1;varray_vertex3f[7] = 1;varray_vertex3f[8] = 0;
809         varray_vertex3f[9] = 0;varray_vertex3f[10] = 1;varray_vertex3f[11] = 0;
810         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)
811         {
812                 int screenwidth, screenheight, bloomwidth, bloomheight, x, dobloomblend, range;
813                 float xoffset, yoffset, r;
814                 c_bloom++;
815                 // set the (poorly named) screenwidth and screenheight variables to
816                 // a power of 2 at least as large as the screen, these will define the
817                 // size of the texture to allocate
818                 for (screenwidth = 1;screenwidth < vid.width;screenwidth *= 2);
819                 for (screenheight = 1;screenheight < vid.height;screenheight *= 2);
820                 // allocate textures as needed
821                 if (!r_bloom_texture_screen)
822                         r_bloom_texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
823                 if (!r_bloom_texture_bloom)
824                         r_bloom_texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", screenwidth, screenheight, NULL, TEXTYPE_RGBA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
825                 // set bloomwidth and bloomheight to the bloom resolution that will be
826                 // used (often less than the screen resolution for faster rendering)
827                 bloomwidth = min(r_view_width, r_bloom_resolution.integer);
828                 bloomheight = min(r_view_height, bloomwidth * r_view_height / r_view_width);
829                 // set up a texcoord array for the full resolution screen image
830                 // (we have to keep this around to copy back during final render)
831                 varray_texcoord2f[0][0] = 0;
832                 varray_texcoord2f[0][1] = (float)r_view_height / (float)screenheight;
833                 varray_texcoord2f[0][2] = (float)r_view_width / (float)screenwidth;
834                 varray_texcoord2f[0][3] = (float)r_view_height / (float)screenheight;
835                 varray_texcoord2f[0][4] = (float)r_view_width / (float)screenwidth;
836                 varray_texcoord2f[0][5] = 0;
837                 varray_texcoord2f[0][6] = 0;
838                 varray_texcoord2f[0][7] = 0;
839                 // set up a texcoord array for the reduced resolution bloom image
840                 // (which will be additive blended over the screen image)
841                 varray_texcoord2f[1][0] = 0;
842                 varray_texcoord2f[1][1] = (float)bloomheight / (float)screenheight;
843                 varray_texcoord2f[1][2] = (float)bloomwidth / (float)screenwidth;
844                 varray_texcoord2f[1][3] = (float)bloomheight / (float)screenheight;
845                 varray_texcoord2f[1][4] = (float)bloomwidth / (float)screenwidth;
846                 varray_texcoord2f[1][5] = 0;
847                 varray_texcoord2f[1][6] = 0;
848                 varray_texcoord2f[1][7] = 0;
849                 memset(&m, 0, sizeof(m));
850                 m.pointer_vertex = varray_vertex3f;
851                 m.pointer_texcoord[0] = varray_texcoord2f[0];
852                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
853                 R_Mesh_State(&m);
854                 // copy view into the full resolution screen image texture
855                 GL_ActiveTexture(0);
856                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
857                 c_bloomcopies++;
858                 c_bloomcopypixels += r_view_width * r_view_height;
859                 // now scale it down to the bloom size and raise to a power of itself
860                 // to darken it (this leaves the really bright stuff bright, and
861                 // everything else becomes very dark)
862                 // TODO: optimize with multitexture or GLSL
863                 qglViewport(r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
864                 GL_BlendFunc(GL_ONE, GL_ZERO);
865                 GL_Color(1, 1, 1, 1);
866                 R_Mesh_Draw(0, 4, 2, polygonelements);
867                 c_bloomdraws++;
868                 c_bloomdrawpixels += bloomwidth * bloomheight;
869                 // render multiple times with a multiply blendfunc to raise to a power
870                 GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
871                 for (x = 1;x < r_bloom_power.integer;x++)
872                 {
873                         R_Mesh_Draw(0, 4, 2, polygonelements);
874                         c_bloomdraws++;
875                         c_bloomdrawpixels += bloomwidth * bloomheight;
876                 }
877                 // we now have a darkened bloom image in the framebuffer, copy it into
878                 // the bloom image texture for more processing
879                 memset(&m, 0, sizeof(m));
880                 m.pointer_vertex = varray_vertex3f;
881                 m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
882                 m.pointer_texcoord[0] = varray_texcoord2f[2];
883                 R_Mesh_State(&m);
884                 GL_ActiveTexture(0);
885                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
886                 c_bloomcopies++;
887                 c_bloomcopypixels += bloomwidth * bloomheight;
888                 // blend on at multiple vertical offsets to achieve a vertical blur
889                 // TODO: do offset blends using GLSL
890                 range = r_bloom_blur.integer * bloomwidth / 320;
891                 GL_BlendFunc(GL_ONE, GL_ZERO);
892                 for (x = -range;x <= range;x++)
893                 {
894                         xoffset = 0 / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
895                         yoffset = x / (float)bloomheight * (float)bloomheight / (float)screenheight;
896                         // compute a texcoord array with the specified x and y offset
897                         varray_texcoord2f[2][0] = xoffset+0;
898                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
899                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
900                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
901                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
902                         varray_texcoord2f[2][5] = yoffset+0;
903                         varray_texcoord2f[2][6] = xoffset+0;
904                         varray_texcoord2f[2][7] = yoffset+0;
905                         // this r value looks like a 'dot' particle, fading sharply to
906                         // black at the edges
907                         // (probably not realistic but looks good enough)
908                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
909                         if (r < 0.01f)
910                                 continue;
911                         GL_Color(r, r, r, 1);
912                         R_Mesh_Draw(0, 4, 2, polygonelements);
913                         c_bloomdraws++;
914                         c_bloomdrawpixels += bloomwidth * bloomheight;
915                         GL_BlendFunc(GL_ONE, GL_ONE);
916                 }
917                 // copy the vertically blurred bloom view to a texture
918                 GL_ActiveTexture(0);
919                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
920                 c_bloomcopies++;
921                 c_bloomcopypixels += bloomwidth * bloomheight;
922                 // blend the vertically blurred image at multiple offsets horizontally
923                 // to finish the blur effect
924                 // TODO: do offset blends using GLSL
925                 range = r_bloom_blur.integer * bloomwidth / 320;
926                 GL_BlendFunc(GL_ONE, GL_ZERO);
927                 for (x = -range;x <= range;x++)
928                 {
929                         xoffset = x / (float)bloomwidth * (float)bloomwidth / (float)screenwidth;
930                         yoffset = 0 / (float)bloomheight * (float)bloomheight / (float)screenheight;
931                         // compute a texcoord array with the specified x and y offset
932                         varray_texcoord2f[2][0] = xoffset+0;
933                         varray_texcoord2f[2][1] = yoffset+(float)bloomheight / (float)screenheight;
934                         varray_texcoord2f[2][2] = xoffset+(float)bloomwidth / (float)screenwidth;
935                         varray_texcoord2f[2][3] = yoffset+(float)bloomheight / (float)screenheight;
936                         varray_texcoord2f[2][4] = xoffset+(float)bloomwidth / (float)screenwidth;
937                         varray_texcoord2f[2][5] = yoffset+0;
938                         varray_texcoord2f[2][6] = xoffset+0;
939                         varray_texcoord2f[2][7] = yoffset+0;
940                         // this r value looks like a 'dot' particle, fading sharply to
941                         // black at the edges
942                         // (probably not realistic but looks good enough)
943                         r = r_bloom_intensity.value/(range*2+1)*(1 - x*x/(float)(range*range));
944                         if (r < 0.01f)
945                                 continue;
946                         GL_Color(r, r, r, 1);
947                         R_Mesh_Draw(0, 4, 2, polygonelements);
948                         c_bloomdraws++;
949                         c_bloomdrawpixels += bloomwidth * bloomheight;
950                         GL_BlendFunc(GL_ONE, GL_ONE);
951                 }
952                 // copy the blurred bloom view to a texture
953                 GL_ActiveTexture(0);
954                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view_x, vid.height - (r_view_y + bloomheight), bloomwidth, bloomheight);
955                 c_bloomcopies++;
956                 c_bloomcopypixels += bloomwidth * bloomheight;
957                 // go back to full view area
958                 qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
959                 // put the original screen image back in place and blend the bloom
960                 // texture on it
961                 memset(&m, 0, sizeof(m));
962                 m.pointer_vertex = varray_vertex3f;
963                 m.tex[0] = R_GetTexture(r_bloom_texture_screen);
964                 m.pointer_texcoord[0] = varray_texcoord2f[0];
965 #if 0
966                 dobloomblend = false;
967 #else
968                 // do both in one pass if possible
969                 if (r_textureunits.integer >= 2 && gl_combine.integer)
970                 {
971                         dobloomblend = false;
972                         m.texcombinergb[1] = GL_ADD;
973                         m.tex[1] = R_GetTexture(r_bloom_texture_bloom);
974                         m.pointer_texcoord[1] = varray_texcoord2f[1];
975                 }
976                 else
977                         dobloomblend = true;
978 #endif
979                 R_Mesh_State(&m);
980                 GL_BlendFunc(GL_ONE, GL_ZERO);
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                 // now blend on the bloom texture if multipass
986                 if (dobloomblend)
987                 {
988                         memset(&m, 0, sizeof(m));
989                         m.pointer_vertex = varray_vertex3f;
990                         m.tex[0] = R_GetTexture(r_bloom_texture_bloom);
991                         m.pointer_texcoord[0] = varray_texcoord2f[1];
992                         R_Mesh_State(&m);
993                         GL_BlendFunc(GL_ONE, GL_ONE);
994                         GL_Color(1,1,1,1);
995                         R_Mesh_Draw(0, 4, 2, polygonelements);
996                         c_bloomdraws++;
997                         c_bloomdrawpixels += r_view_width * r_view_height;
998                 }
999         }
1000         if (r_refdef.viewblend[3] >= 0.01f)
1001         {
1002                 // apply a color tint to the whole view
1003                 memset(&m, 0, sizeof(m));
1004                 m.pointer_vertex = varray_vertex3f;
1005                 R_Mesh_State(&m);
1006                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1007                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
1008                 R_Mesh_Draw(0, 4, 2, polygonelements);
1009         }
1010 }
1011
1012 void R_RenderScene(void);
1013
1014 matrix4x4_t r_waterscrollmatrix;
1015
1016 /*
1017 ================
1018 R_RenderView
1019 ================
1020 */
1021 void R_RenderView(void)
1022 {
1023         if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
1024                 return; //Host_Error ("R_RenderView: NULL worldmodel");
1025
1026         r_view_width = bound(0, r_refdef.width, vid.width);
1027         r_view_height = bound(0, r_refdef.height, vid.height);
1028         r_view_depth = 1;
1029         r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
1030         r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
1031         r_view_z = 0;
1032         r_view_fov_x = bound(1, r_refdef.fov_x, 170);
1033         r_view_fov_y = bound(1, r_refdef.fov_y, 170);
1034         r_view_matrix = r_refdef.viewentitymatrix;
1035         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1036         r_rtworld = r_shadow_realtime_world.integer;
1037         r_rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
1038         r_rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
1039         r_rtdlightshadows = r_rtdlight && (r_rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
1040         r_lightmapintensity = r_rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
1041
1042         // GL is weird because it's bottom to top, r_view_y is top to bottom
1043         qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
1044         GL_Scissor(r_view_x, r_view_y, r_view_width, r_view_height);
1045         GL_ScissorTest(true);
1046         GL_DepthMask(true);
1047         R_ClearScreen();
1048         R_Textures_Frame();
1049         R_UpdateFog();
1050         R_UpdateLights();
1051         R_TimeReport("setup");
1052
1053         qglDepthFunc(GL_LEQUAL);
1054         qglPolygonOffset(0, 0);
1055         qglEnable(GL_POLYGON_OFFSET_FILL);
1056
1057         R_RenderScene();
1058
1059         qglPolygonOffset(0, 0);
1060         qglDisable(GL_POLYGON_OFFSET_FILL);
1061
1062         R_BlendView();
1063         R_TimeReport("blendview");
1064
1065         GL_Scissor(0, 0, vid.width, vid.height);
1066         GL_ScissorTest(false);
1067 }
1068
1069 extern void R_DrawLightningBeams (void);
1070 void R_RenderScene(void)
1071 {
1072         // don't let sound skip if going slow
1073         if (r_refdef.extraupdate)
1074                 S_ExtraUpdate ();
1075
1076         r_framecount++;
1077
1078         R_MeshQueue_BeginScene();
1079
1080         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1081
1082         R_SetFrustum();
1083
1084         r_farclip = R_FarClip(r_vieworigin, r_viewforward, 768.0f) + 256.0f;
1085         if (r_rtworldshadows || r_rtdlightshadows)
1086                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view_fov_x, r_view_fov_y, 1.0f);
1087         else
1088                 GL_SetupView_Mode_Perspective(r_view_fov_x, r_view_fov_y, 1.0f, r_farclip);
1089
1090         GL_SetupView_Orientation_FromEntity(&r_view_matrix);
1091
1092         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
1093
1094         R_SkyStartFrame();
1095
1096         R_WorldVisibility();
1097         R_TimeReport("worldvis");
1098
1099         R_MarkEntities();
1100         R_TimeReport("markentity");
1101
1102         R_Shadow_UpdateWorldLightSelection();
1103
1104         // don't let sound skip if going slow
1105         if (r_refdef.extraupdate)
1106                 S_ExtraUpdate ();
1107
1108         GL_ShowTrisColor(0.025, 0.025, 0, 1);
1109         if (r_refdef.worldmodel && r_refdef.worldmodel->DrawSky)
1110         {
1111                 r_refdef.worldmodel->DrawSky(r_refdef.worldentity);
1112                 R_TimeReport("worldsky");
1113         }
1114
1115         if (R_DrawBrushModelsSky())
1116                 R_TimeReport("bmodelsky");
1117
1118         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1119         if (r_refdef.worldmodel && r_refdef.worldmodel->Draw)
1120         {
1121                 r_refdef.worldmodel->Draw(r_refdef.worldentity);
1122                 R_TimeReport("world");
1123         }
1124
1125         // don't let sound skip if going slow
1126         if (r_refdef.extraupdate)
1127                 S_ExtraUpdate ();
1128
1129         GL_ShowTrisColor(0, 0.015, 0, 1);
1130
1131         R_DrawModels();
1132         R_TimeReport("models");
1133
1134         // don't let sound skip if going slow
1135         if (r_refdef.extraupdate)
1136                 S_ExtraUpdate ();
1137
1138         GL_ShowTrisColor(0, 0, 0.033, 1);
1139         R_ShadowVolumeLighting(false);
1140         R_TimeReport("rtlights");
1141
1142         // don't let sound skip if going slow
1143         if (r_refdef.extraupdate)
1144                 S_ExtraUpdate ();
1145
1146         GL_ShowTrisColor(0.1, 0, 0, 1);
1147
1148         R_DrawLightningBeams();
1149         R_TimeReport("lightning");
1150
1151         R_DrawParticles();
1152         R_TimeReport("particles");
1153
1154         R_DrawExplosions();
1155         R_TimeReport("explosions");
1156
1157         R_MeshQueue_RenderTransparent();
1158         R_TimeReport("drawtrans");
1159
1160         R_DrawCoronas();
1161         R_TimeReport("coronas");
1162
1163         R_DrawWorldCrosshair();
1164         R_TimeReport("crosshair");
1165
1166         R_MeshQueue_Render();
1167         R_MeshQueue_EndScene();
1168
1169         if ((r_shadow_visiblelighting.integer || r_shadow_visiblevolumes.integer) && !r_showtrispass)
1170         {
1171                 R_ShadowVolumeLighting(true);
1172                 R_TimeReport("visiblevolume");
1173         }
1174
1175         GL_ShowTrisColor(0.05, 0.05, 0.05, 1);
1176
1177         // don't let sound skip if going slow
1178         if (r_refdef.extraupdate)
1179                 S_ExtraUpdate ();
1180 }
1181
1182 /*
1183 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
1184 {
1185         int i;
1186         float *v, *c, f1, f2, diff[3], vertex3f[8*3], color4f[8*4];
1187         rmeshstate_t m;
1188         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1189         GL_DepthMask(false);
1190         GL_DepthTest(true);
1191         R_Mesh_Matrix(&r_identitymatrix);
1192
1193         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2];
1194         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
1195         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
1196         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
1197         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
1198         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
1199         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
1200         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
1201         R_FillColors(color, 8, cr, cg, cb, ca);
1202         if (fogenabled)
1203         {
1204                 for (i = 0, v = vertex, c = color;i < 8;i++, v += 4, c += 4)
1205                 {
1206                         VectorSubtract(v, r_vieworigin, diff);
1207                         f2 = exp(fogdensity/DotProduct(diff, diff));
1208                         f1 = 1 - f2;
1209                         c[0] = c[0] * f1 + fogcolor[0] * f2;
1210                         c[1] = c[1] * f1 + fogcolor[1] * f2;
1211                         c[2] = c[2] * f1 + fogcolor[2] * f2;
1212                 }
1213         }
1214         memset(&m, 0, sizeof(m));
1215         m.pointer_vertex = vertex3f;
1216         m.pointer_color = color;
1217         R_Mesh_State(&m);
1218         R_Mesh_Draw(8, 12);
1219 }
1220 */
1221
1222 int nomodelelements[24] =
1223 {
1224         5, 2, 0,
1225         5, 1, 2,
1226         5, 0, 3,
1227         5, 3, 1,
1228         0, 2, 4,
1229         2, 1, 4,
1230         3, 0, 4,
1231         1, 3, 4
1232 };
1233
1234 float nomodelvertex3f[6*3] =
1235 {
1236         -16,   0,   0,
1237          16,   0,   0,
1238           0, -16,   0,
1239           0,  16,   0,
1240           0,   0, -16,
1241           0,   0,  16
1242 };
1243
1244 float nomodelcolor4f[6*4] =
1245 {
1246         0.0f, 0.0f, 0.5f, 1.0f,
1247         0.0f, 0.0f, 0.5f, 1.0f,
1248         0.0f, 0.5f, 0.0f, 1.0f,
1249         0.0f, 0.5f, 0.0f, 1.0f,
1250         0.5f, 0.0f, 0.0f, 1.0f,
1251         0.5f, 0.0f, 0.0f, 1.0f
1252 };
1253
1254 void R_DrawNoModelCallback(const void *calldata1, int calldata2)
1255 {
1256         const entity_render_t *ent = calldata1;
1257         int i;
1258         float f1, f2, *c, diff[3];
1259         float color4f[6*4];
1260         rmeshstate_t m;
1261         R_Mesh_Matrix(&ent->matrix);
1262
1263         memset(&m, 0, sizeof(m));
1264         m.pointer_vertex = nomodelvertex3f;
1265
1266         if (ent->flags & EF_ADDITIVE)
1267         {
1268                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1269                 GL_DepthMask(false);
1270         }
1271         else if (ent->alpha < 1)
1272         {
1273                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1274                 GL_DepthMask(false);
1275         }
1276         else
1277         {
1278                 GL_BlendFunc(GL_ONE, GL_ZERO);
1279                 GL_DepthMask(true);
1280         }
1281         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
1282         if (fogenabled)
1283         {
1284                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1285                 m.pointer_color = color4f;
1286                 VectorSubtract(ent->origin, r_vieworigin, diff);
1287                 f2 = exp(fogdensity/DotProduct(diff, diff));
1288                 f1 = 1 - f2;
1289                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1290                 {
1291                         c[0] = (c[0] * f1 + fogcolor[0] * f2);
1292                         c[1] = (c[1] * f1 + fogcolor[1] * f2);
1293                         c[2] = (c[2] * f1 + fogcolor[2] * f2);
1294                         c[3] *= ent->alpha;
1295                 }
1296         }
1297         else if (ent->alpha != 1)
1298         {
1299                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
1300                 m.pointer_color = color4f;
1301                 for (i = 0, c = color4f;i < 6;i++, c += 4)
1302                         c[3] *= ent->alpha;
1303         }
1304         else
1305                 m.pointer_color = nomodelcolor4f;
1306         R_Mesh_State(&m);
1307         R_Mesh_Draw(0, 6, 8, nomodelelements);
1308 }
1309
1310 void R_DrawNoModel(entity_render_t *ent)
1311 {
1312         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
1313                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_vieworigin : ent->origin, R_DrawNoModelCallback, ent, 0);
1314         //else
1315         //      R_DrawNoModelCallback(ent, 0);
1316 }
1317
1318 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
1319 {
1320         vec3_t right1, right2, diff, normal;
1321
1322         VectorSubtract (org2, org1, normal);
1323
1324         // calculate 'right' vector for start
1325         VectorSubtract (r_vieworigin, org1, diff);
1326         CrossProduct (normal, diff, right1);
1327         VectorNormalize (right1);
1328
1329         // calculate 'right' vector for end
1330         VectorSubtract (r_vieworigin, org2, diff);
1331         CrossProduct (normal, diff, right2);
1332         VectorNormalize (right2);
1333
1334         vert[ 0] = org1[0] + width * right1[0];
1335         vert[ 1] = org1[1] + width * right1[1];
1336         vert[ 2] = org1[2] + width * right1[2];
1337         vert[ 3] = org1[0] - width * right1[0];
1338         vert[ 4] = org1[1] - width * right1[1];
1339         vert[ 5] = org1[2] - width * right1[2];
1340         vert[ 6] = org2[0] - width * right2[0];
1341         vert[ 7] = org2[1] - width * right2[1];
1342         vert[ 8] = org2[2] - width * right2[2];
1343         vert[ 9] = org2[0] + width * right2[0];
1344         vert[10] = org2[1] + width * right2[1];
1345         vert[11] = org2[2] + width * right2[2];
1346 }
1347
1348 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
1349
1350 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)
1351 {
1352         float diff[3];
1353         rmeshstate_t m;
1354
1355         if (fogenabled)
1356         {
1357                 VectorSubtract(origin, r_vieworigin, diff);
1358                 ca *= 1 - exp(fogdensity/DotProduct(diff,diff));
1359         }
1360
1361         R_Mesh_Matrix(&r_identitymatrix);
1362         GL_BlendFunc(blendfunc1, blendfunc2);
1363         GL_DepthMask(false);
1364         GL_DepthTest(!depthdisable);
1365
1366         varray_vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
1367         varray_vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
1368         varray_vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
1369         varray_vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
1370         varray_vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
1371         varray_vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
1372         varray_vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
1373         varray_vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
1374         varray_vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
1375         varray_vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
1376         varray_vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
1377         varray_vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
1378
1379         memset(&m, 0, sizeof(m));
1380         m.tex[0] = R_GetTexture(texture);
1381         m.pointer_texcoord[0] = spritetexcoord2f;
1382         m.pointer_vertex = varray_vertex3f;
1383         R_Mesh_State(&m);
1384         GL_Color(cr, cg, cb, ca);
1385         R_Mesh_Draw(0, 4, 2, polygonelements);
1386 }
1387
1388 int R_Mesh_AddVertex3f(rmesh_t *mesh, const float *v)
1389 {
1390         int i;
1391         float *vertex3f;
1392         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
1393                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
1394                         break;
1395         if (i == mesh->numvertices)
1396         {
1397                 if (mesh->numvertices < mesh->maxvertices)
1398                 {
1399                         VectorCopy(v, vertex3f);
1400                         mesh->numvertices++;
1401                 }
1402                 return mesh->numvertices;
1403         }
1404         else
1405                 return i;
1406 }
1407
1408 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
1409 {
1410         int i;
1411         int *e, element[3];
1412         element[0] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1413         element[1] = R_Mesh_AddVertex3f(mesh, vertex3f);vertex3f += 3;
1414         e = mesh->element3i + mesh->numtriangles * 3;
1415         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
1416         {
1417                 element[2] = R_Mesh_AddVertex3f(mesh, vertex3f);
1418                 if (mesh->numtriangles < mesh->maxtriangles)
1419                 {
1420                         *e++ = element[0];
1421                         *e++ = element[1];
1422                         *e++ = element[2];
1423                         mesh->numtriangles++;
1424                 }
1425                 element[1] = element[2];
1426         }
1427 }
1428
1429 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
1430 {
1431         int planenum, planenum2;
1432         int w;
1433         int tempnumpoints;
1434         mplane_t *plane, *plane2;
1435         float temppoints[2][256*3];
1436         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
1437         {
1438                 w = 0;
1439                 tempnumpoints = 4;
1440                 PolygonF_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->normal[3], 1024.0*1024.0*1024.0);
1441                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
1442                 {
1443                         if (planenum2 == planenum)
1444                                 continue;
1445                         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);
1446                         w = !w;
1447                 }
1448                 if (tempnumpoints < 3)
1449                         continue;
1450                 // generate elements forming a triangle fan for this polygon
1451                 R_Mesh_AddPolygon3f(mesh, tempnumpoints, temppoints[w]);
1452         }
1453 }
1454
1455 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
1456 {
1457         texture_t *texture = t;
1458         model_t *model = ent->model;
1459         int s = ent->skinnum;
1460         if ((unsigned int)s >= (unsigned int)model->numskins)
1461                 s = 0;
1462         if (s >= 1)
1463                 c_models++;
1464         if (model->skinscenes)
1465         {
1466                 if (model->skinscenes[s].framecount > 1)
1467                         s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
1468                 else
1469                         s = model->skinscenes[s].firstframe;
1470         }
1471         if (s > 0)
1472                 t = t + s * model->num_surfaces;
1473         if (t->animated)
1474                 t = t->anim_frames[ent->frame != 0][(t->anim_total[ent->frame != 0] >= 2) ? ((int)(r_refdef.time * 5.0f) % t->anim_total[ent->frame != 0]) : 0];
1475         texture->currentframe = t;
1476         t->currentmaterialflags = t->basematerialflags;
1477         t->currentalpha = ent->alpha;
1478         if (t->basematerialflags & MATERIALFLAG_WATERALPHA)
1479                 t->currentalpha *= r_wateralpha.value;
1480         if (!(ent->flags & RENDER_LIGHT))
1481                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
1482         if (ent->effects & EF_ADDITIVE)
1483                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_TRANSPARENT;
1484         else if (t->currentalpha < 1)
1485                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_TRANSPARENT;
1486         if (ent->effects & EF_NODEPTHTEST)
1487                 t->currentmaterialflags |= MATERIALFLAG_NODEPTHTEST;
1488         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1489                 t->currenttexmatrix = r_waterscrollmatrix;
1490         else
1491                 t->currenttexmatrix = r_identitymatrix;
1492 }
1493
1494 void R_UpdateAllTextureInfo(entity_render_t *ent)
1495 {
1496         int i;
1497         if (ent->model)
1498                 for (i = 0;i < ent->model->num_textures;i++)
1499                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1500 }
1501
1502 float *rsurface_vertex3f;
1503 float *rsurface_svector3f;
1504 float *rsurface_tvector3f;
1505 float *rsurface_normal3f;
1506 float *rsurface_lightmapcolor4f;
1507
1508 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1509 {
1510         int i, j;
1511         float center[3], forward[3], right[3], up[3], v[4][3];
1512         matrix4x4_t matrix1, imatrix1;
1513         if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1514         {
1515                 rsurface_vertex3f = varray_vertex3f;
1516                 rsurface_svector3f = NULL;
1517                 rsurface_tvector3f = NULL;
1518                 rsurface_normal3f = NULL;
1519                 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1520         }
1521         else
1522         {
1523                 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1524                 rsurface_svector3f = surface->groupmesh->data_svector3f;
1525                 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1526                 rsurface_normal3f = surface->groupmesh->data_normal3f;
1527         }
1528         if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1529         {
1530                 if (!rsurface_svector3f)
1531                 {
1532                         rsurface_svector3f = varray_svector3f;
1533                         rsurface_tvector3f = varray_tvector3f;
1534                         rsurface_normal3f = varray_normal3f;
1535                         Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
1536                 }
1537                 // a single autosprite surface can contain multiple sprites...
1538                 VectorClear(forward);
1539                 VectorClear(right);
1540                 VectorSet(up, 0, 0, 1);
1541                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1542                 {
1543                         VectorClear(center);
1544                         for (i = 0;i < 4;i++)
1545                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1546                         VectorScale(center, 0.25f, center);
1547                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1548                         Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
1549                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1550                         for (i = 0;i < 4;i++)
1551                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1552                         forward[0] = modelorg[0] - center[0];
1553                         forward[1] = modelorg[1] - center[1];
1554                         VectorNormalize(forward);
1555                         right[0] = forward[1];
1556                         right[1] = -forward[0];
1557                         for (i = 0;i < 4;i++)
1558                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1559                 }
1560                 rsurface_vertex3f = varray_vertex3f;
1561                 rsurface_svector3f = NULL;
1562                 rsurface_tvector3f = NULL;
1563                 rsurface_normal3f = NULL;
1564         }
1565         else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1566         {
1567                 if (!rsurface_svector3f)
1568                 {
1569                         rsurface_svector3f = varray_svector3f;
1570                         rsurface_tvector3f = varray_tvector3f;
1571                         rsurface_normal3f = varray_normal3f;
1572                         Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
1573                 }
1574                 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1575                 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1576                 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1577                 // a single autosprite surface can contain multiple sprites...
1578                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1579                 {
1580                         VectorClear(center);
1581                         for (i = 0;i < 4;i++)
1582                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1583                         VectorScale(center, 0.25f, center);
1584                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1585                         Matrix4x4_FromVectors(&matrix1, (rsurface_normal3f + 3 * surface->num_firstvertex) + j*3, (rsurface_svector3f + 3 * surface->num_firstvertex) + j*3, (rsurface_tvector3f + 3 * surface->num_firstvertex) + j*3, center);
1586                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1587                         for (i = 0;i < 4;i++)
1588                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1589                         for (i = 0;i < 4;i++)
1590                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1591                 }
1592                 rsurface_vertex3f = varray_vertex3f;
1593                 rsurface_svector3f = NULL;
1594                 rsurface_tvector3f = NULL;
1595                 rsurface_normal3f = NULL;
1596         }
1597         R_Mesh_VertexPointer(rsurface_vertex3f);
1598 }
1599
1600 void RSurf_SetColorPointer(const entity_render_t *ent, const msurface_t *surface, const vec3_t modelorg, float r, float g, float b, float a, int lightmode, qboolean applycolor, qboolean applyfog)
1601 {
1602         int i;
1603         float f;
1604         float *v, *c, *c2;
1605         vec3_t diff;
1606         if (lightmode >= 2)
1607         {
1608                 vec4_t ambientcolor4f;
1609                 vec3_t diffusecolor;
1610                 vec3_t diffusenormal;
1611                 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1612                 {
1613                         rsurface_lightmapcolor4f = varray_color4f;
1614                         if (rsurface_normal3f == NULL)
1615                         {
1616                                 rsurface_normal3f = varray_normal3f;
1617                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
1618                         }
1619                         R_LightModel_CalcVertexColors(ambientcolor4f, diffusecolor, diffusenormal, surface->groupmesh->num_vertices, rsurface_vertex3f + 3 * surface->num_firstvertex, rsurface_normal3f + 3 * surface->num_firstvertex, rsurface_lightmapcolor4f + 4 * surface->num_firstvertex);
1620                         r = 1;
1621                         g = 1;
1622                         b = 1;
1623                         a = 1;
1624                         applycolor = false;
1625                 }
1626                 else
1627                 {
1628                         r = ambientcolor4f[0];
1629                         g = ambientcolor4f[1];
1630                         b = ambientcolor4f[2];
1631                         a = ambientcolor4f[3];
1632                         rsurface_lightmapcolor4f = NULL;
1633                 }
1634         }
1635         else if (lightmode >= 1)
1636         {
1637                 if (surface->lightmapinfo)
1638                 {
1639                         rsurface_lightmapcolor4f = varray_color4f;
1640                         for (i = 0, c = rsurface_lightmapcolor4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1641                         {
1642                                 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1643                                 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1644                                 VectorScale(lm, scale, c);
1645                                 if (surface->lightmapinfo->styles[1] != 255)
1646                                 {
1647                                         int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1648                                         lm += size3;
1649                                         scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1650                                         VectorMA(c, scale, lm, c);
1651                                         if (surface->lightmapinfo->styles[2] != 255)
1652                                         {
1653                                                 lm += size3;
1654                                                 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1655                                                 VectorMA(c, scale, lm, c);
1656                                                 if (surface->lightmapinfo->styles[3] != 255)
1657                                                 {
1658                                                         lm += size3;
1659                                                         scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1660                                                         VectorMA(c, scale, lm, c);
1661                                                 }
1662                                         }
1663                                 }
1664                         }
1665                 }
1666                 else
1667                         rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1668         }
1669         else
1670                 rsurface_lightmapcolor4f = NULL;
1671         if (applyfog)
1672         {
1673                 if (rsurface_lightmapcolor4f)
1674                 {
1675                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
1676                         {
1677                                 VectorSubtract(v, modelorg, diff);
1678                                 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1679                                 c2[0] = c[0] * f;
1680                                 c2[1] = c[1] * f;
1681                                 c2[2] = c[2] * f;
1682                                 c2[3] = c[3];
1683                         }
1684                 }
1685                 else
1686                 {
1687                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
1688                         {
1689                                 VectorSubtract(v, modelorg, diff);
1690                                 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1691                                 c2[0] = f;
1692                                 c2[1] = f;
1693                                 c2[2] = f;
1694                                 c2[3] = 1;
1695                         }
1696                 }
1697                 rsurface_lightmapcolor4f = varray_color4f;
1698         }
1699         if (applycolor && rsurface_lightmapcolor4f)
1700         {
1701                 for (i = 0, c = (rsurface_lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
1702                 {
1703                         c2[0] = c[0] * r;
1704                         c2[1] = c[1] * g;
1705                         c2[2] = c[2] * b;
1706                         c2[3] = c[3] * a;
1707                 }
1708         }
1709         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1710         GL_Color(r, g, b, a);
1711 }
1712
1713
1714 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1715 {
1716         int i;
1717         int texturesurfaceindex;
1718         const float *v;
1719         float *c;
1720         float diff[3];
1721         float colorpants[3], colorshirt[3];
1722         float f, r, g, b, a, colorscale;
1723         const msurface_t *surface;
1724         qboolean dolightmap;
1725         qboolean doambient;
1726         qboolean dodetail;
1727         qboolean doglow;
1728         qboolean dofogpass;
1729         qboolean fogallpasses;
1730         qboolean dopants;
1731         qboolean doshirt;
1732         qboolean dofullbrightpants;
1733         qboolean dofullbrightshirt;
1734         qboolean applycolor;
1735         qboolean lightmode = 0;
1736         rtexture_t *basetexture;
1737         rmeshstate_t m;
1738         if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1739                 return;
1740         c_faces += texturenumsurfaces;
1741         // FIXME: identify models using a better check than ent->model->shadowmesh
1742         if (!(ent->effects & EF_FULLBRIGHT) && !ent->model->brush.shadowmesh)
1743                 lightmode = 2;
1744         // gl_lightmaps debugging mode skips normal texturing
1745         if (gl_lightmaps.integer)
1746         {
1747                 GL_BlendFunc(GL_ONE, GL_ZERO);
1748                 GL_DepthMask(true);
1749                 GL_DepthTest(true);
1750                 qglDisable(GL_CULL_FACE);
1751                 GL_Color(1, 1, 1, 1);
1752                 memset(&m, 0, sizeof(m));
1753                 R_Mesh_State(&m);
1754                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1755                 {
1756                         surface = texturesurfacelist[texturesurfaceindex];
1757                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1758                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1759                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1760                         RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, lightmode ? lightmode : !surface->lightmaptexture, false, false);
1761                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1762                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1763                         GL_LockArrays(0, 0);
1764                 }
1765                 qglEnable(GL_CULL_FACE);
1766                 return;
1767         }
1768         GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1769         GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
1770         if (texture->currentmaterialflags & MATERIALFLAG_ADD)
1771                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1772         else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
1773                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1774         else
1775                 GL_BlendFunc(GL_ONE, GL_ZERO);
1776         if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1777                 qglDisable(GL_CULL_FACE);
1778         if (texture->currentmaterialflags & MATERIALFLAG_SKY)
1779         {
1780                 if (skyrendernow)
1781                 {
1782                         skyrendernow = false;
1783                         if (skyrendermasked)
1784                                 R_Sky();
1785                 }
1786                 // LordHavoc: HalfLife maps have freaky skypolys...
1787                 //if (!ent->model->brush.ishlbsp)
1788                 {
1789                         R_Mesh_Matrix(&ent->matrix);
1790                         GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
1791                         if (skyrendermasked)
1792                         {
1793                                 // depth-only (masking)
1794                                 GL_ColorMask(0,0,0,0);
1795                                 // just to make sure that braindead drivers don't draw anything
1796                                 // despite that colormask...
1797                                 GL_BlendFunc(GL_ZERO, GL_ONE);
1798                         }
1799                         else
1800                         {
1801                                 // fog sky
1802                                 GL_BlendFunc(GL_ONE, GL_ZERO);
1803                         }
1804                         GL_DepthMask(true);
1805                         GL_DepthTest(true);
1806                         memset(&m, 0, sizeof(m));
1807                         R_Mesh_State(&m);
1808                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1809                         {
1810                                 surface = texturesurfacelist[texturesurfaceindex];
1811                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1812                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1813                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1814                                 GL_LockArrays(0, 0);
1815                         }
1816                         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1817                 }
1818         }
1819         else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1820         {
1821                 // normal surface (wall or water)
1822                 dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
1823                 doambient = r_ambient.value >= (1/64.0f);
1824                 dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1825                 doglow = texture->skin.glow != NULL;
1826                 dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
1827                 fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1828                 if (ent->colormap >= 0)
1829                 {
1830                         int b;
1831                         qbyte *bcolor;
1832                         basetexture = texture->skin.base;
1833                         dopants = texture->skin.pants != NULL;
1834                         doshirt = texture->skin.shirt != NULL;
1835                         // 128-224 are backwards ranges
1836                         b = (ent->colormap & 0xF) << 4;b += (b >= 128 && b < 224) ? 4 : 12;
1837                         dofullbrightpants = b >= 224;
1838                         bcolor = (qbyte *) (&palette_complete[b]);
1839                         VectorScale(bcolor, (1.0f / 255.0f), colorpants);
1840                         // 128-224 are backwards ranges
1841                         b = (ent->colormap & 0xF0);b += (b >= 128 && b < 224) ? 4 : 12;
1842                         dofullbrightshirt = b >= 224;
1843                         bcolor = (qbyte *) (&palette_complete[b]);
1844                         VectorScale(bcolor, (1.0f / 255.0f), colorshirt);
1845                 }
1846                 else
1847                 {
1848                         basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
1849                         dopants = false;
1850                         doshirt = false;
1851                         dofullbrightshirt = false;
1852                         dofullbrightpants = false;
1853                 }
1854                 if (dolightmap && r_textureunits.integer >= 2 && gl_combine.integer)
1855                 {
1856                         memset(&m, 0, sizeof(m));
1857                         m.tex[1] = R_GetTexture(basetexture);
1858                         m.texmatrix[1] = texture->currenttexmatrix;
1859                         m.texrgbscale[1] = 2;
1860                         m.pointer_color = varray_color4f;
1861                         R_Mesh_State(&m);
1862                         // transparent is not affected by r_lightmapintensity
1863                         if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1864                                 colorscale = r_lightmapintensity;
1865                         else
1866                                 colorscale = 1;
1867                         // q3bsp has no lightmap updates, so the lightstylevalue that
1868                         // would normally be baked into the lightmaptexture must be
1869                         // applied to the color
1870                         if (ent->model->type == mod_brushq3)
1871                                 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1872                         r = ent->colormod[0] * colorscale;
1873                         g = ent->colormod[1] * colorscale;
1874                         b = ent->colormod[2] * colorscale;
1875                         a = texture->currentalpha;
1876                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1877                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1878                         {
1879                                 surface = texturesurfacelist[texturesurfaceindex];
1880                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1881                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1882                                 R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1883                                 if (surface->lightmaptexture)
1884                                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1885                                 else
1886                                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1887                                 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode ? lightmode : !surface->lightmaptexture, applycolor, fogallpasses);
1888                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1889                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1890                                 GL_LockArrays(0, 0);
1891                         }
1892                 }
1893                 else if (dolightmap && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT) && !lightmode)
1894                 {
1895                         // single texture
1896                         GL_BlendFunc(GL_ONE, GL_ZERO);
1897                         GL_DepthMask(true);
1898                         GL_Color(1, 1, 1, 1);
1899                         memset(&m, 0, sizeof(m));
1900                         R_Mesh_State(&m);
1901                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1902                         {
1903                                 surface = texturesurfacelist[texturesurfaceindex];
1904                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1905                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1906                                 if (surface->lightmaptexture)
1907                                 {
1908                                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1909                                         R_Mesh_ColorPointer(NULL);
1910                                 }
1911                                 else
1912                                 {
1913                                         R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
1914                                         R_Mesh_ColorPointer(surface->groupmesh->data_lightmapcolor4f);
1915                                 }
1916                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1917                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1918                                 GL_LockArrays(0, 0);
1919                         }
1920                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
1921                         GL_DepthMask(false);
1922                         GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
1923                         memset(&m, 0, sizeof(m));
1924                         m.tex[0] = R_GetTexture(basetexture);
1925                         m.texmatrix[0] = texture->currenttexmatrix;
1926                         R_Mesh_State(&m);
1927                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1928                         {
1929                                 surface = texturesurfacelist[texturesurfaceindex];
1930                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1931                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1932                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1933                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1934                                 GL_LockArrays(0, 0);
1935                         }
1936                 }
1937                 else
1938                 {
1939                         memset(&m, 0, sizeof(m));
1940                         m.tex[0] = R_GetTexture(basetexture);
1941                         m.texmatrix[0] = texture->currenttexmatrix;
1942                         m.pointer_color = varray_color4f;
1943                         colorscale = 2;
1944                         if (gl_combine.integer)
1945                         {
1946                                 m.texrgbscale[0] = 2;
1947                                 colorscale = 1;
1948                         }
1949                         // transparent is not affected by r_lightmapintensity
1950                         if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1951                                 colorscale *= r_lightmapintensity;
1952                         // q3bsp has no lightmap updates, so the lightstylevalue that
1953                         // would normally be baked into the lightmaptexture must be
1954                         // applied to the color
1955                         if (dolightmap && ent->model->type == mod_brushq3)
1956                                 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1957                         R_Mesh_State(&m);
1958                         r = ent->colormod[0] * colorscale;
1959                         g = ent->colormod[1] * colorscale;
1960                         b = ent->colormod[2] * colorscale;
1961                         a = texture->currentalpha;
1962                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
1963                         if (dolightmap)
1964                         {
1965                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1966                                 {
1967                                         surface = texturesurfacelist[texturesurfaceindex];
1968                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1969                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1970                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
1971                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1972                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1973                                         GL_LockArrays(0, 0);
1974                                 }
1975                         }
1976                         else
1977                         {
1978                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1979                                 {
1980                                         surface = texturesurfacelist[texturesurfaceindex];
1981                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1982                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1983                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
1984                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1985                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1986                                         GL_LockArrays(0, 0);
1987                                 }
1988                         }
1989                 }
1990                 if (dopants)
1991                 {
1992                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1993                         memset(&m, 0, sizeof(m));
1994                         m.tex[0] = R_GetTexture(texture->skin.pants);
1995                         m.texmatrix[0] = texture->currenttexmatrix;
1996                         m.pointer_color = varray_color4f;
1997                         colorscale = 2;
1998                         if (gl_combine.integer)
1999                         {
2000                                 m.texrgbscale[0] = 2;
2001                                 colorscale = 1;
2002                         }
2003                         // transparent is not affected by r_lightmapintensity
2004                         if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2005                                 colorscale *= r_lightmapintensity;
2006                         // q3bsp has no lightmap updates, so the lightstylevalue that
2007                         // would normally be baked into the lightmaptexture must be
2008                         // applied to the color
2009                         if (dolightmap && !dofullbrightpants && ent->model->type == mod_brushq3)
2010                                 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
2011                         R_Mesh_State(&m);
2012                         r = ent->colormod[0] * colorpants[0] * colorscale;
2013                         g = ent->colormod[1] * colorpants[1] * colorscale;
2014                         b = ent->colormod[2] * colorpants[2] * colorscale;
2015                         a = texture->currentalpha;
2016                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2017                         if (dolightmap && !dofullbrightpants)
2018                         {
2019                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2020                                 {
2021                                         surface = texturesurfacelist[texturesurfaceindex];
2022                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2023                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2024                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
2025                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2026                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2027                                         GL_LockArrays(0, 0);
2028                                 }
2029                         }
2030                         else
2031                         {
2032                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2033                                 {
2034                                         surface = texturesurfacelist[texturesurfaceindex];
2035                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2036                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2037                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2038                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2039                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2040                                         GL_LockArrays(0, 0);
2041                                 }
2042                         }
2043                 }
2044                 if (doshirt)
2045                 {
2046                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2047                         memset(&m, 0, sizeof(m));
2048                         m.tex[0] = R_GetTexture(texture->skin.shirt);
2049                         m.texmatrix[0] = texture->currenttexmatrix;
2050                         m.pointer_color = varray_color4f;
2051                         colorscale = 2;
2052                         if (gl_combine.integer)
2053                         {
2054                                 m.texrgbscale[0] = 2;
2055                                 colorscale *= 1;
2056                         }
2057                         // transparent is not affected by r_lightmapintensity
2058                         if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2059                                 colorscale *= r_lightmapintensity;
2060                         // q3bsp has no lightmap updates, so the lightstylevalue that
2061                         // would normally be baked into the lightmaptexture must be
2062                         // applied to the color
2063                         if (dolightmap && !dofullbrightshirt && ent->model->type == mod_brushq3)
2064                                 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
2065                         R_Mesh_State(&m);
2066                         r = ent->colormod[0] * colorshirt[0] * colorscale;
2067                         g = ent->colormod[1] * colorshirt[1] * colorscale;
2068                         b = ent->colormod[2] * colorshirt[2] * colorscale;
2069                         a = texture->currentalpha;
2070                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2071                         if (dolightmap && !dofullbrightshirt)
2072                         {
2073                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2074                                 {
2075                                         surface = texturesurfacelist[texturesurfaceindex];
2076                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2077                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2078                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
2079                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2080                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2081                                         GL_LockArrays(0, 0);
2082                                 }
2083                         }
2084                         else
2085                         {
2086                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2087                                 {
2088                                         surface = texturesurfacelist[texturesurfaceindex];
2089                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2090                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2091                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2092                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2093                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2094                                         GL_LockArrays(0, 0);
2095                                 }
2096                         }
2097                 }
2098                 if (doambient)
2099                 {
2100                         doambient = false;
2101                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2102                         GL_DepthMask(false);
2103                         memset(&m, 0, sizeof(m));
2104                         m.tex[0] = R_GetTexture(texture->skin.base);
2105                         m.texmatrix[0] = texture->currenttexmatrix;
2106                         m.pointer_color = varray_color4f;
2107                         colorscale = 1;
2108                         if (gl_combine.integer && (ent->colormod[0] > 1 || ent->colormod[1] > 1 || ent->colormod[2] > 1))
2109                         {
2110                                 m.texrgbscale[0] = 4;
2111                                 colorscale = 0.25f;
2112                         }
2113                         R_Mesh_State(&m);
2114                         colorscale *= r_ambient.value * (1.0f / 64.0f);
2115                         r = ent->colormod[0] * colorscale;
2116                         g = ent->colormod[1] * colorscale;
2117                         b = ent->colormod[2] * colorscale;
2118                         a = texture->currentalpha;
2119                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2120                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2121                         {
2122                                 surface = texturesurfacelist[texturesurfaceindex];
2123                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2124                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2125                                 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2126                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2127                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2128                                 GL_LockArrays(0, 0);
2129                         }
2130                 }
2131                 if (dodetail)
2132                 {
2133                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2134                         GL_DepthMask(false);
2135                         GL_Color(1, 1, 1, 1);
2136                         memset(&m, 0, sizeof(m));
2137                         m.tex[0] = R_GetTexture(texture->skin.detail);
2138                         R_Mesh_State(&m);
2139                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2140                         {
2141                                 surface = texturesurfacelist[texturesurfaceindex];
2142                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2143                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f);
2144                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2145                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2146                                 GL_LockArrays(0, 0);
2147                         }
2148                 }
2149                 if (doglow)
2150                 {
2151                         // if glow was not already done using multitexture, do it now.
2152                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2153                         GL_DepthMask(false);
2154                         memset(&m, 0, sizeof(m));
2155                         m.tex[0] = R_GetTexture(texture->skin.glow);
2156                         m.texmatrix[0] = texture->currenttexmatrix;
2157                         m.pointer_color = varray_color4f;
2158                         R_Mesh_State(&m);
2159                         r = 1;
2160                         g = 1;
2161                         b = 1;
2162                         a = texture->currentalpha;
2163                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2164                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2165                         {
2166                                 surface = texturesurfacelist[texturesurfaceindex];
2167                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2168                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2169                                 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2170                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2171                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2172                                 GL_LockArrays(0, 0);
2173                         }
2174                 }
2175                 if (dofogpass)
2176                 {
2177                         // if this is opaque use alpha blend which will darken the earlier
2178                         // passes cheaply.
2179                         //
2180                         // if this is an alpha blended material, all the earlier passes
2181                         // were darkened by fog already, so we only need to add the fog
2182                         // color ontop through the fog mask texture
2183                         //
2184                         // if this is an additive blended material, all the earlier passes
2185                         // were darkened by fog already, and we should not add fog color
2186                         // (because the background was not darkened, there is no fog color
2187                         // that was lost behind it).
2188                         if (fogallpasses)
2189                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2190                         else
2191                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2192                         GL_DepthMask(false);
2193                         memset(&m, 0, sizeof(m));
2194                         m.tex[0] = R_GetTexture(texture->skin.fog);
2195                         m.texmatrix[0] = texture->currenttexmatrix;
2196                         R_Mesh_State(&m);
2197                         r = fogcolor[0];
2198                         g = fogcolor[1];
2199                         b = fogcolor[2];
2200                         a = texture->currentalpha;
2201                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2202                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2203                         {
2204                                 surface = texturesurfacelist[texturesurfaceindex];
2205                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2206                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2207                                 R_Mesh_ColorPointer(varray_color4f);
2208                                 //RSurf_FogPassColors_Vertex3f_Color4f((surface->groupmesh->data_vertex3f + 3 * surface->num_firstvertex), varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], texture->currentalpha, 1, surface->num_vertices, modelorg);
2209                                 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2210                                 {
2211                                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2212                                         {
2213                                                 VectorSubtract(v, modelorg, diff);
2214                                                 f = exp(fogdensity/DotProduct(diff, diff));
2215                                                 c[0] = r;
2216                                                 c[1] = g;
2217                                                 c[2] = b;
2218                                                 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a;
2219                                         }
2220                                 }
2221                                 else
2222                                 {
2223                                         for (i = 0, v = (rsurface_vertex3f + 3 * surface->num_firstvertex), c = (varray_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
2224                                         {
2225                                                 VectorSubtract(v, modelorg, diff);
2226                                                 f = exp(fogdensity/DotProduct(diff, diff));
2227                                                 c[0] = r;
2228                                                 c[1] = g;
2229                                                 c[2] = b;
2230                                                 c[3] = f * a;
2231                                         }
2232                                 }
2233                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2234                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2235                                 GL_LockArrays(0, 0);
2236                         }
2237                 }
2238         }
2239         if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2240                 qglEnable(GL_CULL_FACE);
2241 }
2242
2243 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2244 {
2245         const entity_render_t *ent = calldata1;
2246         const msurface_t *surface = ent->model->data_surfaces + calldata2;
2247         vec3_t modelorg;
2248         texture_t *texture;
2249
2250         texture = surface->texture;
2251         if (texture->basematerialflags & MATERIALFLAG_SKY)
2252                 return; // transparent sky is too difficult
2253         R_UpdateTextureInfo(ent, texture);
2254
2255         R_Mesh_Matrix(&ent->matrix);
2256         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2257         R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2258 }
2259
2260 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2261 {
2262         int texturesurfaceindex;
2263         const msurface_t *surface;
2264         vec3_t tempcenter, center;
2265         if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2266         {
2267                 // drawing sky transparently would be too difficult
2268                 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2269                 {
2270                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2271                         {
2272                                 surface = texturesurfacelist[texturesurfaceindex];
2273                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2274                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2275                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2276                                 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2277                                 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2278                         }
2279                 }
2280         }
2281         else
2282                 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2283 }
2284
2285 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2286 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2287 {
2288         int i, j, f, flagsmask;
2289         msurface_t *surface, **surfacechain;
2290         texture_t *t, *texture;
2291         model_t *model = ent->model;
2292         vec3_t modelorg;
2293         const int maxsurfacelist = 1024;
2294         int numsurfacelist = 0;
2295         const msurface_t *surfacelist[1024];
2296         if (model == NULL)
2297                 return;
2298         R_Mesh_Matrix(&ent->matrix);
2299         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2300
2301         // update light styles
2302         if (!skysurfaces && model->brushq1.light_styleupdatechains)
2303         {
2304                 for (i = 0;i < model->brushq1.light_styles;i++)
2305                 {
2306                         if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2307                         {
2308                                 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2309                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2310                                         for (;(surface = *surfacechain);surfacechain++)
2311                                                 surface->cached_dlight = true;
2312                         }
2313                 }
2314         }
2315
2316         R_UpdateAllTextureInfo(ent);
2317         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2318         f = 0;
2319         t = NULL;
2320         texture = NULL;
2321         numsurfacelist = 0;
2322         if (ent == r_refdef.worldentity)
2323         {
2324                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2325                 {
2326                         if (!r_worldsurfacevisible[j])
2327                                 continue;
2328                         if (t != surface->texture)
2329                         {
2330                                 if (numsurfacelist)
2331                                 {
2332                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2333                                         numsurfacelist = 0;
2334                                 }
2335                                 t = surface->texture;
2336                                 texture = t->currentframe;
2337                                 f = texture->currentmaterialflags & flagsmask;
2338                         }
2339                         if (f && surface->num_triangles)
2340                         {
2341                                 // if lightmap parameters changed, rebuild lightmap texture
2342                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2343                                         R_BuildLightMap(ent, surface);
2344                                 // add face to draw list
2345                                 surfacelist[numsurfacelist++] = surface;
2346                                 if (numsurfacelist >= maxsurfacelist)
2347                                 {
2348                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2349                                         numsurfacelist = 0;
2350                                 }
2351                         }
2352                 }
2353         }
2354         else
2355         {
2356                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2357                 {
2358                         if (t != surface->texture)
2359                         {
2360                                 if (numsurfacelist)
2361                                 {
2362                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2363                                         numsurfacelist = 0;
2364                                 }
2365                                 t = surface->texture;
2366                                 texture = t->currentframe;
2367                                 f = texture->currentmaterialflags & flagsmask;
2368                         }
2369                         if (f && surface->num_triangles)
2370                         {
2371                                 // if lightmap parameters changed, rebuild lightmap texture
2372                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2373                                         R_BuildLightMap(ent, surface);
2374                                 // add face to draw list
2375                                 surfacelist[numsurfacelist++] = surface;
2376                                 if (numsurfacelist >= maxsurfacelist)
2377                                 {
2378                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2379                                         numsurfacelist = 0;
2380                                 }
2381                         }
2382                 }
2383         }
2384         if (numsurfacelist)
2385                 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2386 }
2387