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