]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
moved waterscrollmatrix handling into texture->currentexmatrix to simplify texture...
[divverent/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         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
1491                 t->currenttexmatrix = r_waterscrollmatrix;
1492         else
1493                 t->currenttexmatrix = r_identitymatrix;
1494 }
1495
1496 void R_UpdateAllTextureInfo(entity_render_t *ent)
1497 {
1498         int i;
1499         if (ent->model)
1500                 for (i = 0;i < ent->model->num_textures;i++)
1501                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
1502 }
1503
1504 float *rsurface_vertex3f;
1505 float *rsurface_svector3f;
1506 float *rsurface_tvector3f;
1507 float *rsurface_normal3f;
1508 float *rsurface_lightmapcolor4f;
1509
1510 void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg)
1511 {
1512         int i, j;
1513         float center[3], forward[3], right[3], up[3], v[4][3];
1514         matrix4x4_t matrix1, imatrix1;
1515         if ((ent->frameblend[0].lerp != 1 || ent->frameblend[0].frame != 0) && (surface->groupmesh->data_morphvertex3f || surface->groupmesh->data_vertexboneweights))
1516         {
1517                 rsurface_vertex3f = varray_vertex3f;
1518                 rsurface_svector3f = NULL;
1519                 rsurface_tvector3f = NULL;
1520                 rsurface_normal3f = NULL;
1521                 Mod_Alias_GetMesh_Vertex3f(ent->model, ent->frameblend, surface->groupmesh, rsurface_vertex3f);
1522         }
1523         else
1524         {
1525                 rsurface_vertex3f = surface->groupmesh->data_vertex3f;
1526                 rsurface_svector3f = surface->groupmesh->data_svector3f;
1527                 rsurface_tvector3f = surface->groupmesh->data_tvector3f;
1528                 rsurface_normal3f = surface->groupmesh->data_normal3f;
1529         }
1530         if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE2)
1531         {
1532                 if (!rsurface_svector3f)
1533                 {
1534                         rsurface_svector3f = varray_svector3f;
1535                         rsurface_tvector3f = varray_tvector3f;
1536                         rsurface_normal3f = varray_normal3f;
1537                         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);
1538                 }
1539                 // a single autosprite surface can contain multiple sprites...
1540                 VectorClear(forward);
1541                 VectorClear(right);
1542                 VectorSet(up, 0, 0, 1);
1543                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1544                 {
1545                         VectorClear(center);
1546                         for (i = 0;i < 4;i++)
1547                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1548                         VectorScale(center, 0.25f, center);
1549                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1550                         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);
1551                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1552                         for (i = 0;i < 4;i++)
1553                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1554                         forward[0] = modelorg[0] - center[0];
1555                         forward[1] = modelorg[1] - center[1];
1556                         VectorNormalize(forward);
1557                         right[0] = forward[1];
1558                         right[1] = -forward[0];
1559                         for (i = 0;i < 4;i++)
1560                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1561                 }
1562                 rsurface_vertex3f = varray_vertex3f;
1563                 rsurface_svector3f = NULL;
1564                 rsurface_tvector3f = NULL;
1565                 rsurface_normal3f = NULL;
1566         }
1567         else if (texture->textureflags & Q3TEXTUREFLAG_AUTOSPRITE)
1568         {
1569                 if (!rsurface_svector3f)
1570                 {
1571                         rsurface_svector3f = varray_svector3f;
1572                         rsurface_tvector3f = varray_tvector3f;
1573                         rsurface_normal3f = varray_normal3f;
1574                         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);
1575                 }
1576                 Matrix4x4_Transform(&ent->inversematrix, r_viewforward, forward);
1577                 Matrix4x4_Transform(&ent->inversematrix, r_viewright, right);
1578                 Matrix4x4_Transform(&ent->inversematrix, r_viewup, up);
1579                 // a single autosprite surface can contain multiple sprites...
1580                 for (j = 0;j < surface->num_vertices - 3;j += 4)
1581                 {
1582                         VectorClear(center);
1583                         for (i = 0;i < 4;i++)
1584                                 VectorAdd(center, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
1585                         VectorScale(center, 0.25f, center);
1586                         // FIXME: calculate vectors from triangle edges instead of using texture vectors as an easy way out?
1587                         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);
1588                         Matrix4x4_Invert_Simple(&imatrix1, &matrix1);
1589                         for (i = 0;i < 4;i++)
1590                                 Matrix4x4_Transform(&imatrix1, (rsurface_vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, v[i]);
1591                         for (i = 0;i < 4;i++)
1592                                 VectorMAMAMAM(1, center, v[i][0], forward, v[i][1], right, v[i][2], up, varray_vertex3f + (surface->num_firstvertex+i+j) * 3);
1593                 }
1594                 rsurface_vertex3f = varray_vertex3f;
1595                 rsurface_svector3f = NULL;
1596                 rsurface_tvector3f = NULL;
1597                 rsurface_normal3f = NULL;
1598         }
1599         R_Mesh_VertexPointer(rsurface_vertex3f);
1600 }
1601
1602 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)
1603 {
1604         int i;
1605         float f;
1606         float *v, *c, *c2;
1607         vec3_t diff;
1608         if (lightmode >= 2)
1609         {
1610                 vec4_t ambientcolor4f;
1611                 vec3_t diffusecolor;
1612                 vec3_t diffusenormal;
1613                 if (R_LightModel(ambientcolor4f, diffusecolor, diffusenormal, ent, r*0.5f, g*0.5f, b*0.5f, a, false))
1614                 {
1615                         rsurface_lightmapcolor4f = varray_color4f;
1616                         if (rsurface_normal3f == NULL)
1617                         {
1618                                 rsurface_normal3f = varray_normal3f;
1619                                 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);
1620                         }
1621                         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);
1622                         r = 1;
1623                         g = 1;
1624                         b = 1;
1625                         a = 1;
1626                         applycolor = false;
1627                 }
1628                 else
1629                 {
1630                         r = ambientcolor4f[0];
1631                         g = ambientcolor4f[1];
1632                         b = ambientcolor4f[2];
1633                         a = ambientcolor4f[3];
1634                         rsurface_lightmapcolor4f = NULL;
1635                 }
1636         }
1637         else if (lightmode >= 1)
1638         {
1639                 if (surface->lightmapinfo)
1640                 {
1641                         rsurface_lightmapcolor4f = varray_color4f;
1642                         for (i = 0, c = rsurface_lightmapcolor4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
1643                         {
1644                                 const qbyte *lm = surface->lightmapinfo->samples + (surface->groupmesh->data_lightmapoffsets + surface->num_firstvertex)[i];
1645                                 float scale = d_lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
1646                                 VectorScale(lm, scale, c);
1647                                 if (surface->lightmapinfo->styles[1] != 255)
1648                                 {
1649                                         int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
1650                                         lm += size3;
1651                                         scale = d_lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
1652                                         VectorMA(c, scale, lm, c);
1653                                         if (surface->lightmapinfo->styles[2] != 255)
1654                                         {
1655                                                 lm += size3;
1656                                                 scale = d_lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
1657                                                 VectorMA(c, scale, lm, c);
1658                                                 if (surface->lightmapinfo->styles[3] != 255)
1659                                                 {
1660                                                         lm += size3;
1661                                                         scale = d_lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
1662                                                         VectorMA(c, scale, lm, c);
1663                                                 }
1664                                         }
1665                                 }
1666                         }
1667                 }
1668                 else
1669                         rsurface_lightmapcolor4f = surface->groupmesh->data_lightmapcolor4f;
1670         }
1671         else
1672                 rsurface_lightmapcolor4f = NULL;
1673         if (applyfog)
1674         {
1675                 if (rsurface_lightmapcolor4f)
1676                 {
1677                         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)
1678                         {
1679                                 VectorSubtract(v, modelorg, diff);
1680                                 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1681                                 c2[0] = c[0] * f;
1682                                 c2[1] = c[1] * f;
1683                                 c2[2] = c[2] * f;
1684                                 c2[3] = c[3];
1685                         }
1686                 }
1687                 else
1688                 {
1689                         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)
1690                         {
1691                                 VectorSubtract(v, modelorg, diff);
1692                                 f = 1 - exp(fogdensity/DotProduct(diff, diff));
1693                                 c2[0] = f;
1694                                 c2[1] = f;
1695                                 c2[2] = f;
1696                                 c2[3] = 1;
1697                         }
1698                 }
1699                 rsurface_lightmapcolor4f = varray_color4f;
1700         }
1701         if (applycolor && rsurface_lightmapcolor4f)
1702         {
1703                 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)
1704                 {
1705                         c2[0] = c[0] * r;
1706                         c2[1] = c[1] * g;
1707                         c2[2] = c[2] * b;
1708                         c2[3] = c[3] * a;
1709                 }
1710         }
1711         R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
1712         GL_Color(r, g, b, a);
1713 }
1714
1715
1716 static void R_DrawTextureSurfaceList(const entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
1717 {
1718         int i;
1719         int texturesurfaceindex;
1720         const float *v;
1721         float *c;
1722         float diff[3];
1723         float colorpants[3], colorshirt[3];
1724         float f, r, g, b, a, colorscale;
1725         const msurface_t *surface;
1726         qboolean dolightmap;
1727         qboolean doambient;
1728         qboolean dodetail;
1729         qboolean doglow;
1730         qboolean dofogpass;
1731         qboolean fogallpasses;
1732         qboolean dopants;
1733         qboolean doshirt;
1734         qboolean dofullbrightpants;
1735         qboolean dofullbrightshirt;
1736         qboolean applycolor;
1737         qboolean lightmode = 0;
1738         rtexture_t *basetexture;
1739         rmeshstate_t m;
1740         if (texture->currentmaterialflags & MATERIALFLAG_NODRAW)
1741                 return;
1742         c_faces += texturenumsurfaces;
1743         // FIXME: identify models using a better check than ent->model->shadowmesh
1744         if (!(ent->effects & EF_FULLBRIGHT) && !ent->model->brush.shadowmesh)
1745                 lightmode = 2;
1746         // gl_lightmaps debugging mode skips normal texturing
1747         if (gl_lightmaps.integer)
1748         {
1749                 GL_BlendFunc(GL_ONE, GL_ZERO);
1750                 GL_DepthMask(true);
1751                 GL_DepthTest(true);
1752                 qglDisable(GL_CULL_FACE);
1753                 GL_Color(1, 1, 1, 1);
1754                 memset(&m, 0, sizeof(m));
1755                 R_Mesh_State(&m);
1756                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1757                 {
1758                         surface = texturesurfacelist[texturesurfaceindex];
1759                         R_Mesh_TexBind(0, R_GetTexture(surface->lightmaptexture));
1760                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordlightmap2f);
1761                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1762                         RSurf_SetColorPointer(ent, surface, modelorg, 1, 1, 1, 1, lightmode ? lightmode : !surface->lightmaptexture, false, false);
1763                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1764                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1765                         GL_LockArrays(0, 0);
1766                 }
1767                 qglEnable(GL_CULL_FACE);
1768                 return;
1769         }
1770         GL_DepthTest(!(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
1771         GL_DepthMask(!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT));
1772         if (texture->currentmaterialflags & MATERIALFLAG_ADD)
1773                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
1774         else if (texture->currentmaterialflags & MATERIALFLAG_ALPHA)
1775                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1776         else
1777                 GL_BlendFunc(GL_ONE, GL_ZERO);
1778         if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
1779                 qglDisable(GL_CULL_FACE);
1780         if (texture->currentmaterialflags & MATERIALFLAG_SKY)
1781         {
1782                 if (skyrendernow)
1783                 {
1784                         skyrendernow = false;
1785                         if (skyrendermasked)
1786                                 R_Sky();
1787                 }
1788                 // LordHavoc: HalfLife maps have freaky skypolys...
1789                 //if (!ent->model->brush.ishlbsp)
1790                 {
1791                         R_Mesh_Matrix(&ent->matrix);
1792                         GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
1793                         if (skyrendermasked)
1794                         {
1795                                 // depth-only (masking)
1796                                 GL_ColorMask(0,0,0,0);
1797                                 // just to make sure that braindead drivers don't draw anything
1798                                 // despite that colormask...
1799                                 GL_BlendFunc(GL_ZERO, GL_ONE);
1800                         }
1801                         else
1802                         {
1803                                 // fog sky
1804                                 GL_BlendFunc(GL_ONE, GL_ZERO);
1805                         }
1806                         GL_DepthMask(true);
1807                         GL_DepthTest(true);
1808                         memset(&m, 0, sizeof(m));
1809                         R_Mesh_State(&m);
1810                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1811                         {
1812                                 surface = texturesurfacelist[texturesurfaceindex];
1813                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1814                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1815                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1816                                 GL_LockArrays(0, 0);
1817                         }
1818                         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
1819                 }
1820         }
1821         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)
1822         {
1823                 // NVIDIA Geforce3 distortion texture shader on water
1824                 float args[4] = {0.05f,0,0,0.04f};
1825                 memset(&m, 0, sizeof(m));
1826                 m.tex[0] = R_GetTexture(r_texture_distorttexture[(int)(r_refdef.time * 16)&63]);
1827                 m.tex[1] = R_GetTexture(texture->skin.base);
1828                 m.texcombinergb[0] = GL_REPLACE;
1829                 m.texcombinergb[1] = GL_REPLACE;
1830                 Matrix4x4_CreateFromQuakeEntity(&m.texmatrix[0], 0, 0, 0, 0, 0, 0, r_watershader.value);
1831                 m.texmatrix[1] = texture->currenttexmatrix;
1832                 R_Mesh_State(&m);
1833
1834                 GL_Color(1, 1, 1, texture->currentalpha);
1835                 GL_ActiveTexture(0);
1836                 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1837                 GL_ActiveTexture(1);
1838                 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_OFFSET_TEXTURE_2D_NV);
1839                 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_PREVIOUS_TEXTURE_INPUT_NV, GL_TEXTURE0_ARB);
1840                 qglTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, &args[0]);
1841                 qglEnable(GL_TEXTURE_SHADER_NV);
1842
1843                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1844                 {
1845                         surface = texturesurfacelist[texturesurfaceindex];
1846                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1847                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1848                         R_Mesh_TexCoordPointer(1, 2, surface->groupmesh->data_texcoordtexture2f);
1849                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1850                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1851                         GL_LockArrays(0, 0);
1852                 }
1853
1854                 qglDisable(GL_TEXTURE_SHADER_NV);
1855                 qglTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
1856                 GL_ActiveTexture(0);
1857         }
1858         else if (texture->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
1859         {
1860                 // normal surface (wall or water)
1861                 dolightmap = !(texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT);
1862                 doambient = r_ambient.value >= (1/64.0f);
1863                 dodetail = r_detailtextures.integer && texture->skin.detail != NULL && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1864                 doglow = texture->skin.glow != NULL;
1865                 dofogpass = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_ADD);
1866                 fogallpasses = fogenabled && !(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT);
1867                 if (ent->colormap >= 0)
1868                 {
1869                         int b;
1870                         qbyte *bcolor;
1871                         basetexture = texture->skin.base;
1872                         dopants = texture->skin.pants != NULL;
1873                         doshirt = texture->skin.shirt != NULL;
1874                         // 128-224 are backwards ranges
1875                         b = (ent->colormap & 0xF) << 4;b += (b >= 128 && b < 224) ? 4 : 12;
1876                         dofullbrightpants = b >= 224;
1877                         bcolor = (qbyte *) (&palette_complete[b]);
1878                         VectorScale(bcolor, (1.0f / 255.0f), colorpants);
1879                         // 128-224 are backwards ranges
1880                         b = (ent->colormap & 0xF0);b += (b >= 128 && b < 224) ? 4 : 12;
1881                         dofullbrightshirt = b >= 224;
1882                         bcolor = (qbyte *) (&palette_complete[b]);
1883                         VectorScale(bcolor, (1.0f / 255.0f), colorshirt);
1884                 }
1885                 else
1886                 {
1887                         basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
1888                         dopants = false;
1889                         doshirt = false;
1890                         dofullbrightshirt = false;
1891                         dofullbrightpants = false;
1892                 }
1893                 if (dolightmap && r_textureunits.integer >= 2 && gl_combine.integer)
1894                 {
1895                         memset(&m, 0, sizeof(m));
1896                         m.tex[1] = R_GetTexture(basetexture);
1897                         m.texmatrix[1] = texture->currenttexmatrix;
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                         m.texmatrix[0] = texture->currenttexmatrix;
1965                         R_Mesh_State(&m);
1966                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
1967                         {
1968                                 surface = texturesurfacelist[texturesurfaceindex];
1969                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
1970                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
1971                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
1972                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
1973                                 GL_LockArrays(0, 0);
1974                         }
1975                 }
1976                 else
1977                 {
1978                         memset(&m, 0, sizeof(m));
1979                         m.tex[0] = R_GetTexture(basetexture);
1980                         m.texmatrix[0] = texture->currenttexmatrix;
1981                         m.pointer_color = varray_color4f;
1982                         colorscale = 2;
1983                         if (gl_combine.integer)
1984                         {
1985                                 m.texrgbscale[0] = 2;
1986                                 colorscale = 1;
1987                         }
1988                         // transparent is not affected by r_lightmapintensity
1989                         if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
1990                                 colorscale *= r_lightmapintensity;
1991                         // q3bsp has no lightmap updates, so the lightstylevalue that
1992                         // would normally be baked into the lightmaptexture must be
1993                         // applied to the color
1994                         if (dolightmap && ent->model->type == mod_brushq3)
1995                                 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
1996                         R_Mesh_State(&m);
1997                         r = ent->colormod[0] * colorscale;
1998                         g = ent->colormod[1] * colorscale;
1999                         b = ent->colormod[2] * colorscale;
2000                         a = texture->currentalpha;
2001                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2002                         if (dolightmap)
2003                         {
2004                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2005                                 {
2006                                         surface = texturesurfacelist[texturesurfaceindex];
2007                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2008                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2009                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
2010                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2011                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2012                                         GL_LockArrays(0, 0);
2013                                 }
2014                         }
2015                         else
2016                         {
2017                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2018                                 {
2019                                         surface = texturesurfacelist[texturesurfaceindex];
2020                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2021                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2022                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2023                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2024                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2025                                         GL_LockArrays(0, 0);
2026                                 }
2027                         }
2028                 }
2029                 if (dopants)
2030                 {
2031                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2032                         memset(&m, 0, sizeof(m));
2033                         m.tex[0] = R_GetTexture(texture->skin.pants);
2034                         m.texmatrix[0] = texture->currenttexmatrix;
2035                         m.pointer_color = varray_color4f;
2036                         colorscale = 2;
2037                         if (gl_combine.integer)
2038                         {
2039                                 m.texrgbscale[0] = 2;
2040                                 colorscale = 1;
2041                         }
2042                         // transparent is not affected by r_lightmapintensity
2043                         if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2044                                 colorscale *= r_lightmapintensity;
2045                         // q3bsp has no lightmap updates, so the lightstylevalue that
2046                         // would normally be baked into the lightmaptexture must be
2047                         // applied to the color
2048                         if (dolightmap && !dofullbrightpants && ent->model->type == mod_brushq3)
2049                                 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
2050                         R_Mesh_State(&m);
2051                         r = ent->colormod[0] * colorpants[0] * colorscale;
2052                         g = ent->colormod[1] * colorpants[1] * colorscale;
2053                         b = ent->colormod[2] * colorpants[2] * colorscale;
2054                         a = texture->currentalpha;
2055                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2056                         if (dolightmap && !dofullbrightpants)
2057                         {
2058                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2059                                 {
2060                                         surface = texturesurfacelist[texturesurfaceindex];
2061                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2062                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2063                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
2064                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2065                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2066                                         GL_LockArrays(0, 0);
2067                                 }
2068                         }
2069                         else
2070                         {
2071                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2072                                 {
2073                                         surface = texturesurfacelist[texturesurfaceindex];
2074                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2075                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2076                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2077                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2078                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2079                                         GL_LockArrays(0, 0);
2080                                 }
2081                         }
2082                 }
2083                 if (doshirt)
2084                 {
2085                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2086                         memset(&m, 0, sizeof(m));
2087                         m.tex[0] = R_GetTexture(texture->skin.shirt);
2088                         m.texmatrix[0] = texture->currenttexmatrix;
2089                         m.pointer_color = varray_color4f;
2090                         colorscale = 2;
2091                         if (gl_combine.integer)
2092                         {
2093                                 m.texrgbscale[0] = 2;
2094                                 colorscale *= 1;
2095                         }
2096                         // transparent is not affected by r_lightmapintensity
2097                         if (!(texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2098                                 colorscale *= r_lightmapintensity;
2099                         // q3bsp has no lightmap updates, so the lightstylevalue that
2100                         // would normally be baked into the lightmaptexture must be
2101                         // applied to the color
2102                         if (dolightmap && !dofullbrightshirt && ent->model->type == mod_brushq3)
2103                                 colorscale *= d_lightstylevalue[0] * (1.0f / 128.0f);
2104                         R_Mesh_State(&m);
2105                         r = ent->colormod[0] * colorshirt[0] * colorscale;
2106                         g = ent->colormod[1] * colorshirt[1] * colorscale;
2107                         b = ent->colormod[2] * colorshirt[2] * colorscale;
2108                         a = texture->currentalpha;
2109                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2110                         if (dolightmap && !dofullbrightshirt)
2111                         {
2112                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2113                                 {
2114                                         surface = texturesurfacelist[texturesurfaceindex];
2115                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2116                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2117                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, lightmode, applycolor, fogallpasses);
2118                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2119                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2120                                         GL_LockArrays(0, 0);
2121                                 }
2122                         }
2123                         else
2124                         {
2125                                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2126                                 {
2127                                         surface = texturesurfacelist[texturesurfaceindex];
2128                                         RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2129                                         R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2130                                         RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2131                                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2132                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2133                                         GL_LockArrays(0, 0);
2134                                 }
2135                         }
2136                 }
2137                 if (doambient)
2138                 {
2139                         doambient = false;
2140                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2141                         GL_DepthMask(false);
2142                         memset(&m, 0, sizeof(m));
2143                         m.tex[0] = R_GetTexture(texture->skin.base);
2144                         m.texmatrix[0] = texture->currenttexmatrix;
2145                         m.pointer_color = varray_color4f;
2146                         colorscale = 1;
2147                         if (gl_combine.integer && (ent->colormod[0] > 1 || ent->colormod[1] > 1 || ent->colormod[2] > 1))
2148                         {
2149                                 m.texrgbscale[0] = 4;
2150                                 colorscale = 0.25f;
2151                         }
2152                         R_Mesh_State(&m);
2153                         colorscale *= r_ambient.value * (1.0f / 64.0f);
2154                         r = ent->colormod[0] * colorscale;
2155                         g = ent->colormod[1] * colorscale;
2156                         b = ent->colormod[2] * colorscale;
2157                         a = texture->currentalpha;
2158                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2159                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2160                         {
2161                                 surface = texturesurfacelist[texturesurfaceindex];
2162                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2163                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2164                                 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2165                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2166                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2167                                 GL_LockArrays(0, 0);
2168                         }
2169                 }
2170                 if (dodetail)
2171                 {
2172                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
2173                         GL_DepthMask(false);
2174                         GL_Color(1, 1, 1, 1);
2175                         memset(&m, 0, sizeof(m));
2176                         m.tex[0] = R_GetTexture(texture->skin.detail);
2177                         R_Mesh_State(&m);
2178                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2179                         {
2180                                 surface = texturesurfacelist[texturesurfaceindex];
2181                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2182                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoorddetail2f);
2183                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2184                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2185                                 GL_LockArrays(0, 0);
2186                         }
2187                 }
2188                 if (doglow)
2189                 {
2190                         // if glow was not already done using multitexture, do it now.
2191                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2192                         GL_DepthMask(false);
2193                         memset(&m, 0, sizeof(m));
2194                         m.tex[0] = R_GetTexture(texture->skin.glow);
2195                         m.texmatrix[0] = texture->currenttexmatrix;
2196                         m.pointer_color = varray_color4f;
2197                         R_Mesh_State(&m);
2198                         r = 1;
2199                         g = 1;
2200                         b = 1;
2201                         a = texture->currentalpha;
2202                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2203                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2204                         {
2205                                 surface = texturesurfacelist[texturesurfaceindex];
2206                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2207                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2208                                 RSurf_SetColorPointer(ent, surface, modelorg, r, g, b, a, 0, applycolor, fogallpasses);
2209                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2210                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2211                                 GL_LockArrays(0, 0);
2212                         }
2213                 }
2214                 if (dofogpass)
2215                 {
2216                         // if this is opaque use alpha blend which will darken the earlier
2217                         // passes cheaply.
2218                         //
2219                         // if this is an alpha blended material, all the earlier passes
2220                         // were darkened by fog already, so we only need to add the fog
2221                         // color ontop through the fog mask texture
2222                         //
2223                         // if this is an additive blended material, all the earlier passes
2224                         // were darkened by fog already, and we should not add fog color
2225                         // (because the background was not darkened, there is no fog color
2226                         // that was lost behind it).
2227                         if (fogallpasses)
2228                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2229                         else
2230                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2231                         GL_DepthMask(false);
2232                         memset(&m, 0, sizeof(m));
2233                         m.tex[0] = R_GetTexture(texture->skin.fog);
2234                         m.texmatrix[0] = texture->currenttexmatrix;
2235                         R_Mesh_State(&m);
2236                         r = fogcolor[0];
2237                         g = fogcolor[1];
2238                         b = fogcolor[2];
2239                         a = texture->currentalpha;
2240                         applycolor = r != 1 || g != 1 || b != 1 || a != 1;
2241                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2242                         {
2243                                 surface = texturesurfacelist[texturesurfaceindex];
2244                                 RSurf_SetVertexPointer(ent, texture, surface, modelorg);
2245                                 R_Mesh_TexCoordPointer(0, 2, surface->groupmesh->data_texcoordtexture2f);
2246                                 R_Mesh_ColorPointer(varray_color4f);
2247                                 //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);
2248                                 if (!surface->lightmaptexture && surface->groupmesh->data_lightmapcolor4f && (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
2249                                 {
2250                                         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)
2251                                         {
2252                                                 VectorSubtract(v, modelorg, diff);
2253                                                 f = exp(fogdensity/DotProduct(diff, diff));
2254                                                 c[0] = r;
2255                                                 c[1] = g;
2256                                                 c[2] = b;
2257                                                 c[3] = (surface->groupmesh->data_lightmapcolor4f + 4 * surface->num_firstvertex)[i*4+3] * f * a;
2258                                         }
2259                                 }
2260                                 else
2261                                 {
2262                                         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)
2263                                         {
2264                                                 VectorSubtract(v, modelorg, diff);
2265                                                 f = exp(fogdensity/DotProduct(diff, diff));
2266                                                 c[0] = r;
2267                                                 c[1] = g;
2268                                                 c[2] = b;
2269                                                 c[3] = f * a;
2270                                         }
2271                                 }
2272                                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
2273                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle));
2274                                 GL_LockArrays(0, 0);
2275                         }
2276                 }
2277         }
2278         if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
2279                 qglEnable(GL_CULL_FACE);
2280 }
2281
2282 static void RSurfShader_Transparent_Callback(const void *calldata1, int calldata2)
2283 {
2284         const entity_render_t *ent = calldata1;
2285         const msurface_t *surface = ent->model->data_surfaces + calldata2;
2286         vec3_t modelorg;
2287         texture_t *texture;
2288
2289         texture = surface->texture;
2290         if (texture->basematerialflags & MATERIALFLAG_SKY)
2291                 return; // transparent sky is too difficult
2292         R_UpdateTextureInfo(ent, texture);
2293
2294         R_Mesh_Matrix(&ent->matrix);
2295         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2296         R_DrawTextureSurfaceList(ent, texture->currentframe, 1, &surface, modelorg);
2297 }
2298
2299 void R_QueueTextureSurfaceList(entity_render_t *ent, texture_t *texture, int texturenumsurfaces, const msurface_t **texturesurfacelist, const vec3_t modelorg)
2300 {
2301         int texturesurfaceindex;
2302         const msurface_t *surface;
2303         vec3_t tempcenter, center;
2304         if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
2305         {
2306                 // drawing sky transparently would be too difficult
2307                 if (!(texture->currentmaterialflags & MATERIALFLAG_SKY))
2308                 {
2309                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
2310                         {
2311                                 surface = texturesurfacelist[texturesurfaceindex];
2312                                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
2313                                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
2314                                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
2315                                 Matrix4x4_Transform(&ent->matrix, tempcenter, center);
2316                                 R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, RSurfShader_Transparent_Callback, ent, surface - ent->model->data_surfaces);
2317                         }
2318                 }
2319         }
2320         else
2321                 R_DrawTextureSurfaceList(ent, texture, texturenumsurfaces, texturesurfacelist, modelorg);
2322 }
2323
2324 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
2325 void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
2326 {
2327         int i, j, f, flagsmask;
2328         msurface_t *surface, **surfacechain;
2329         texture_t *t, *texture;
2330         model_t *model = ent->model;
2331         vec3_t modelorg;
2332         const int maxsurfacelist = 1024;
2333         int numsurfacelist = 0;
2334         const msurface_t *surfacelist[1024];
2335         if (model == NULL)
2336                 return;
2337         R_Mesh_Matrix(&ent->matrix);
2338         Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
2339
2340         // update light styles
2341         if (!skysurfaces && model->brushq1.light_styleupdatechains)
2342         {
2343                 for (i = 0;i < model->brushq1.light_styles;i++)
2344                 {
2345                         if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
2346                         {
2347                                 model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
2348                                 if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
2349                                         for (;(surface = *surfacechain);surfacechain++)
2350                                                 surface->cached_dlight = true;
2351                         }
2352                 }
2353         }
2354
2355         R_UpdateAllTextureInfo(ent);
2356         flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
2357         f = 0;
2358         t = NULL;
2359         texture = NULL;
2360         numsurfacelist = 0;
2361         if (ent == r_refdef.worldentity)
2362         {
2363                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2364                 {
2365                         if (!r_worldsurfacevisible[j])
2366                                 continue;
2367                         if (t != surface->texture)
2368                         {
2369                                 if (numsurfacelist)
2370                                 {
2371                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2372                                         numsurfacelist = 0;
2373                                 }
2374                                 t = surface->texture;
2375                                 texture = t->currentframe;
2376                                 f = texture->currentmaterialflags & flagsmask;
2377                         }
2378                         if (f && surface->num_triangles)
2379                         {
2380                                 // if lightmap parameters changed, rebuild lightmap texture
2381                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2382                                         R_BuildLightMap(ent, surface);
2383                                 // add face to draw list
2384                                 surfacelist[numsurfacelist++] = surface;
2385                                 if (numsurfacelist >= maxsurfacelist)
2386                                 {
2387                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2388                                         numsurfacelist = 0;
2389                                 }
2390                         }
2391                 }
2392         }
2393         else
2394         {
2395                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
2396                 {
2397                         if (t != surface->texture)
2398                         {
2399                                 if (numsurfacelist)
2400                                 {
2401                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2402                                         numsurfacelist = 0;
2403                                 }
2404                                 t = surface->texture;
2405                                 texture = t->currentframe;
2406                                 f = texture->currentmaterialflags & flagsmask;
2407                         }
2408                         if (f && surface->num_triangles)
2409                         {
2410                                 // if lightmap parameters changed, rebuild lightmap texture
2411                                 if (surface->cached_dlight && surface->lightmapinfo->samples)
2412                                         R_BuildLightMap(ent, surface);
2413                                 // add face to draw list
2414                                 surfacelist[numsurfacelist++] = surface;
2415                                 if (numsurfacelist >= maxsurfacelist)
2416                                 {
2417                                         R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2418                                         numsurfacelist = 0;
2419                                 }
2420                         }
2421                 }
2422         }
2423         if (numsurfacelist)
2424                 R_QueueTextureSurfaceList(ent, texture, numsurfacelist, surfacelist, modelorg);
2425 }
2426