]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
some very slight optimization to rt light rendering setup code
[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 "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27
28 mempool_t *r_main_mempool;
29 rtexturepool_t *r_main_texturepool;
30
31 //
32 // screen size info
33 //
34 r_refdef_t r_refdef;
35
36 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
37 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
38 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
39 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
40 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
41 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
42 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
43 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
44 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
45 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
46 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
47 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
48 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
49 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
50 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
51 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
52 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling"};
53 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
54 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
55 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
56 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
57 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
58 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
59 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
60 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this)"};
61 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
62 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
63 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
64 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "2", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
65 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
66
67 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
68 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
69 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
70 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
71 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
72 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
73 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
74 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
75
76 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of hardware texture units reported by driver (note: setting this to 1 turns off gl_combine)"};
77
78 cvar_t r_glsl = {CVAR_SAVE, "r_glsl", "1", "enables use of OpenGL 2.0 pixel shaders for lighting"};
79 cvar_t r_glsl_contrastboost = {CVAR_SAVE, "r_glsl_contrastboost", "1", "by how much to multiply the contrast in dark areas (1 is no change)"};
80 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
81 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
82 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
83 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
84 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
85 cvar_t r_glsl_postprocess_contrastboost = {CVAR_SAVE, "r_glsl_postprocess_contrastboost", "1", "brightening effect (1 is no change, higher values brighten the view)"};
86 cvar_t r_glsl_usegeneric = {CVAR_SAVE, "r_glsl_usegeneric", "1", "use shaders for rendering simple geometry (rather than conventional fixed-function rendering for this purpose)"};
87
88 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
89 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
90 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
91 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
92 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
93
94 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites (requires r_lerpmodels 1)"};
95 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
96 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
97 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
98
99 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
100 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
101 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
102 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
103 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
104 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
105 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
106
107 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
108 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
109 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
110 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivilant to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
111
112 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
113
114 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
115
116 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
117
118 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
119 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
120 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
121 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
122 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
123 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
124
125 extern qboolean v_flipped_state;
126
127 static struct r_bloomstate_s
128 {
129         qboolean enabled;
130         qboolean hdr;
131
132         int bloomwidth, bloomheight;
133
134         int screentexturewidth, screentextureheight;
135         rtexture_t *texture_screen;
136
137         int bloomtexturewidth, bloomtextureheight;
138         rtexture_t *texture_bloom;
139
140         // arrays for rendering the screen passes
141         float screentexcoord2f[8];
142         float bloomtexcoord2f[8];
143         float offsettexcoord2f[8];
144 }
145 r_bloomstate;
146
147 typedef struct r_waterstate_waterplane_s
148 {
149         rtexture_t *texture_refraction;
150         rtexture_t *texture_reflection;
151         mplane_t plane;
152         int materialflags; // combined flags of all water surfaces on this plane
153         unsigned char pvsbits[(32768+7)>>3]; // FIXME: buffer overflow on huge maps
154         qboolean pvsvalid;
155 }
156 r_waterstate_waterplane_t;
157
158 #define MAX_WATERPLANES 16
159
160 static struct r_waterstate_s
161 {
162         qboolean enabled;
163
164         qboolean renderingscene; // true while rendering a refraction or reflection texture, disables water surfaces
165
166         int waterwidth, waterheight;
167         int texturewidth, textureheight;
168
169         int maxwaterplanes; // same as MAX_WATERPLANES
170         int numwaterplanes;
171         r_waterstate_waterplane_t waterplanes[MAX_WATERPLANES];
172
173         float screenscale[2];
174         float screencenter[2];
175 }
176 r_waterstate;
177
178 // shadow volume bsp struct with automatically growing nodes buffer
179 svbsp_t r_svbsp;
180
181 rtexture_t *r_texture_blanknormalmap;
182 rtexture_t *r_texture_white;
183 rtexture_t *r_texture_grey128;
184 rtexture_t *r_texture_black;
185 rtexture_t *r_texture_notexture;
186 rtexture_t *r_texture_whitecube;
187 rtexture_t *r_texture_normalizationcube;
188 rtexture_t *r_texture_fogattenuation;
189 //rtexture_t *r_texture_fogintensity;
190
191 char r_qwskincache[MAX_SCOREBOARD][MAX_QPATH];
192 skinframe_t *r_qwskincache_skinframe[MAX_SCOREBOARD];
193
194 // vertex coordinates for a quad that covers the screen exactly
195 const static float r_screenvertex3f[12] =
196 {
197         0, 0, 0,
198         1, 0, 0,
199         1, 1, 0,
200         0, 1, 0
201 };
202
203 extern void R_DrawModelShadows(void);
204
205 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
206 {
207         int i;
208         for (i = 0;i < verts;i++)
209         {
210                 out[0] = in[0] * r;
211                 out[1] = in[1] * g;
212                 out[2] = in[2] * b;
213                 out[3] = in[3];
214                 in += 4;
215                 out += 4;
216         }
217 }
218
219 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
220 {
221         int i;
222         for (i = 0;i < verts;i++)
223         {
224                 out[0] = r;
225                 out[1] = g;
226                 out[2] = b;
227                 out[3] = a;
228                 out += 4;
229         }
230 }
231
232 // FIXME: move this to client?
233 void FOG_clear(void)
234 {
235         if (gamemode == GAME_NEHAHRA)
236         {
237                 Cvar_Set("gl_fogenable", "0");
238                 Cvar_Set("gl_fogdensity", "0.2");
239                 Cvar_Set("gl_fogred", "0.3");
240                 Cvar_Set("gl_foggreen", "0.3");
241                 Cvar_Set("gl_fogblue", "0.3");
242         }
243         r_refdef.fog_density = 0;
244         r_refdef.fog_red = 0;
245         r_refdef.fog_green = 0;
246         r_refdef.fog_blue = 0;
247         r_refdef.fog_alpha = 1;
248         r_refdef.fog_start = 0;
249         r_refdef.fog_end = 0;
250 }
251
252 float FogForDistance(vec_t dist)
253 {
254         unsigned int fogmasktableindex = (unsigned int)(dist * r_refdef.fogmasktabledistmultiplier);
255         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
256 }
257
258 float FogPoint_World(const vec3_t p)
259 {
260         return FogForDistance(VectorDistance((p), r_refdef.view.origin));
261 }
262
263 float FogPoint_Model(const vec3_t p)
264 {
265         return FogForDistance(VectorDistance((p), rsurface.modelorg));
266 }
267
268 static void R_BuildBlankTextures(void)
269 {
270         unsigned char data[4];
271         data[2] = 128; // normal X
272         data[1] = 128; // normal Y
273         data[0] = 255; // normal Z
274         data[3] = 128; // height
275         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
276         data[0] = 255;
277         data[1] = 255;
278         data[2] = 255;
279         data[3] = 255;
280         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
281         data[0] = 128;
282         data[1] = 128;
283         data[2] = 128;
284         data[3] = 255;
285         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
286         data[0] = 0;
287         data[1] = 0;
288         data[2] = 0;
289         data[3] = 255;
290         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_PERSISTENT, NULL);
291 }
292
293 static void R_BuildNoTexture(void)
294 {
295         int x, y;
296         unsigned char pix[16][16][4];
297         // this makes a light grey/dark grey checkerboard texture
298         for (y = 0;y < 16;y++)
299         {
300                 for (x = 0;x < 16;x++)
301                 {
302                         if ((y < 8) ^ (x < 8))
303                         {
304                                 pix[y][x][0] = 128;
305                                 pix[y][x][1] = 128;
306                                 pix[y][x][2] = 128;
307                                 pix[y][x][3] = 255;
308                         }
309                         else
310                         {
311                                 pix[y][x][0] = 64;
312                                 pix[y][x][1] = 64;
313                                 pix[y][x][2] = 64;
314                                 pix[y][x][3] = 255;
315                         }
316                 }
317         }
318         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
319 }
320
321 static void R_BuildWhiteCube(void)
322 {
323         unsigned char data[6*1*1*4];
324         memset(data, 255, sizeof(data));
325         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
326 }
327
328 static void R_BuildNormalizationCube(void)
329 {
330         int x, y, side;
331         vec3_t v;
332         vec_t s, t, intensity;
333 #define NORMSIZE 64
334         unsigned char data[6][NORMSIZE][NORMSIZE][4];
335         for (side = 0;side < 6;side++)
336         {
337                 for (y = 0;y < NORMSIZE;y++)
338                 {
339                         for (x = 0;x < NORMSIZE;x++)
340                         {
341                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
342                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
343                                 switch(side)
344                                 {
345                                 default:
346                                 case 0:
347                                         v[0] = 1;
348                                         v[1] = -t;
349                                         v[2] = -s;
350                                         break;
351                                 case 1:
352                                         v[0] = -1;
353                                         v[1] = -t;
354                                         v[2] = s;
355                                         break;
356                                 case 2:
357                                         v[0] = s;
358                                         v[1] = 1;
359                                         v[2] = t;
360                                         break;
361                                 case 3:
362                                         v[0] = s;
363                                         v[1] = -1;
364                                         v[2] = -t;
365                                         break;
366                                 case 4:
367                                         v[0] = s;
368                                         v[1] = -t;
369                                         v[2] = 1;
370                                         break;
371                                 case 5:
372                                         v[0] = -s;
373                                         v[1] = -t;
374                                         v[2] = -1;
375                                         break;
376                                 }
377                                 intensity = 127.0f / sqrt(DotProduct(v, v));
378                                 data[side][y][x][2] = (unsigned char)(128.0f + intensity * v[0]);
379                                 data[side][y][x][1] = (unsigned char)(128.0f + intensity * v[1]);
380                                 data[side][y][x][0] = (unsigned char)(128.0f + intensity * v[2]);
381                                 data[side][y][x][3] = 255;
382                         }
383                 }
384         }
385         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, &data[0][0][0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
386 }
387
388 static void R_BuildFogTexture(void)
389 {
390         int x, b;
391 #define FOGWIDTH 256
392         unsigned char data1[FOGWIDTH][4];
393         //unsigned char data2[FOGWIDTH][4];
394         double d, r, alpha;
395
396         r_refdef.fogmasktable_start = r_refdef.fog_start;
397         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
398         r_refdef.fogmasktable_range = r_refdef.fogrange;
399         r_refdef.fogmasktable_density = r_refdef.fog_density;
400
401         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
402         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
403         {
404                 d = (x * r - r_refdef.fogmasktable_start);
405                 if(developer.integer >= 100)
406                         Con_Printf("%f ", d);
407                 d = max(0, d);
408                 if (r_fog_exp2.integer)
409                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
410                 else
411                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
412                 if(developer.integer >= 100)
413                         Con_Printf(" : %f ", alpha);
414                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
415                 if(developer.integer >= 100)
416                         Con_Printf(" = %f\n", alpha);
417                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
418         }
419
420         for (x = 0;x < FOGWIDTH;x++)
421         {
422                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
423                 data1[x][0] = b;
424                 data1[x][1] = b;
425                 data1[x][2] = b;
426                 data1[x][3] = 255;
427                 //data2[x][0] = 255 - b;
428                 //data2[x][1] = 255 - b;
429                 //data2[x][2] = 255 - b;
430                 //data2[x][3] = 255;
431         }
432         if (r_texture_fogattenuation)
433         {
434                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
435                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
436         }
437         else
438         {
439                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, NULL);
440                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_PRECACHE | TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
441         }
442 }
443
444 static const char *builtinshaderstring =
445 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
446 "// written by Forest 'LordHavoc' Hale\n"
447 "\n"
448 "// common definitions between vertex shader and fragment shader:\n"
449 "\n"
450 "//#ifdef __GLSL_CG_DATA_TYPES\n"
451 "//# define myhalf half\n"
452 "//# define myhalf2 half2\n"
453 "//# define myhalf3 half3\n"
454 "//# define myhalf4 half4\n"
455 "//#else\n"
456 "# define myhalf float\n"
457 "# define myhalf2 vec2\n"
458 "# define myhalf3 vec3\n"
459 "# define myhalf4 vec4\n"
460 "//#endif\n"
461 "\n"
462 "#ifdef MODE_DEPTH_OR_SHADOW\n"
463 "\n"
464 "# ifdef VERTEX_SHADER\n"
465 "void main(void)\n"
466 "{\n"
467 "       gl_Position = ftransform();\n"
468 "}\n"
469 "# endif\n"
470 "\n"
471 "#else\n"
472 "\n"
473 "#ifdef MODE_POSTPROCESS\n"
474 "# ifdef VERTEX_SHADER\n"
475 "void main(void)\n"
476 "{\n"
477 "       gl_FrontColor = gl_Color;\n"
478 "       gl_Position = ftransform();\n"
479 "       gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
480 "#ifdef USEGLOW\n"
481 "       gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
482 "#endif\n"
483 "}\n"
484 "# endif\n"
485 "# ifdef FRAGMENT_SHADER\n"
486 "\n"
487 "uniform sampler2D Texture_First;\n"
488 "#ifdef USEGLOW\n"
489 "uniform sampler2D Texture_Second;\n"
490 "#endif\n"
491 "#ifdef USEVERTEXTEXTUREBLEND\n"
492 "uniform vec4 TintColor;\n"
493 "#endif\n"
494 "#ifdef USECOLORMOD\n"
495 "uniform vec3 Gamma;\n"
496 "#endif\n"
497 "#ifdef USECONTRASTBOOST\n"
498 "uniform float ContrastBoostCoeff;\n"
499 "#endif\n"
500 "void main(void)\n"
501 "{\n"
502 "       gl_FragColor = texture2D(Texture_First, gl_TexCoord[0].xy);\n"
503 "#ifdef USEGLOW\n"
504 "       gl_FragColor += texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
505 "#endif\n"
506 "#ifdef USECONTRASTBOOST\n"
507 "       gl_FragColor.rgb /= (ContrastBoostCoeff * gl_FragColor.rgb + vec3(1.0, 1.0, 1.0));\n"
508 "       gl_FragColor.rgb *= (ContrastBoostCoeff + 1.0);\n"
509 "#endif\n"
510 "#ifdef USEVERTEXTEXTUREBLEND\n"
511 "       gl_FragColor = mix(TintColor, gl_FragColor, TintColor.a);\n"
512 "#endif\n"
513 "\n"
514 "}\n"
515 "# endif\n"
516 "\n"
517 "\n"
518 "#else\n"
519 "#ifdef MODE_GENERIC\n"
520 "# ifdef VERTEX_SHADER\n"
521 "void main(void)\n"
522 "{\n"
523 "       gl_FrontColor = gl_Color;\n"
524 "#  ifdef USEDIFFUSE\n"
525 "       gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
526 "#  endif\n"
527 "#  ifdef USESPECULAR\n"
528 "       gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;\n"
529 "#  endif\n"
530 "       gl_Position = ftransform();\n"
531 "}\n"
532 "# endif\n"
533 "# ifdef FRAGMENT_SHADER\n"
534 "\n"
535 "#  ifdef USEDIFFUSE\n"
536 "uniform sampler2D Texture_First;\n"
537 "#  endif\n"
538 "#  ifdef USESPECULAR\n"
539 "uniform sampler2D Texture_Second;\n"
540 "#  endif\n"
541 "\n"
542 "void main(void)\n"
543 "{\n"
544 "       gl_FragColor = gl_Color;\n"
545 "#  ifdef USEDIFFUSE\n"
546 "       gl_FragColor *= texture2D(Texture_First, gl_TexCoord[0].xy);\n"
547 "#  endif\n"
548 "\n"
549 "#  ifdef USESPECULAR\n"
550 "       vec4 tex2 = texture2D(Texture_Second, gl_TexCoord[1].xy);\n"
551 "#  endif\n"
552 "#  ifdef USECOLORMAPPING\n"
553 "       gl_FragColor *= tex2;\n"
554 "#  endif\n"
555 "#  ifdef USEGLOW\n"
556 "       gl_FragColor += tex2;\n"
557 "#  endif\n"
558 "#  ifdef USEVERTEXTEXTUREBLEND\n"
559 "       gl_FragColor = mix(tex2, gl_FragColor, tex2.a);\n"
560 "#  endif\n"
561 "}\n"
562 "# endif\n"
563 "\n"
564 "#else // !MODE_GENERIC\n"
565 "\n"
566 "varying vec2 TexCoord;\n"
567 "varying vec2 TexCoordLightmap;\n"
568 "\n"
569 "#ifdef MODE_LIGHTSOURCE\n"
570 "varying vec3 CubeVector;\n"
571 "#endif\n"
572 "\n"
573 "#ifdef MODE_LIGHTSOURCE\n"
574 "varying vec3 LightVector;\n"
575 "#endif\n"
576 "#ifdef MODE_LIGHTDIRECTION\n"
577 "varying vec3 LightVector;\n"
578 "#endif\n"
579 "\n"
580 "varying vec3 EyeVector;\n"
581 "#ifdef USEFOG\n"
582 "varying vec3 EyeVectorModelSpace;\n"
583 "#endif\n"
584 "\n"
585 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
586 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
587 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
588 "\n"
589 "#ifdef MODE_WATER\n"
590 "varying vec4 ModelViewProjectionPosition;\n"
591 "#ifdef MODE_REFRACTION\n"
592 "varying vec4 ModelViewProjectionPosition;\n"
593 "#else\n"
594 "# ifdef USEREFLECTION\n"
595 "varying vec4 ModelViewProjectionPosition;\n"
596 "# endif\n"
597 "#endif\n"
598 "#endif\n"
599 "\n"
600 "\n"
601 "\n"
602 "\n"
603 "\n"
604 "// vertex shader specific:\n"
605 "#ifdef VERTEX_SHADER\n"
606 "\n"
607 "uniform vec3 LightPosition;\n"
608 "uniform vec3 EyePosition;\n"
609 "uniform vec3 LightDir;\n"
610 "\n"
611 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
612 "\n"
613 "void main(void)\n"
614 "{\n"
615 "       gl_FrontColor = gl_Color;\n"
616 "       // copy the surface texcoord\n"
617 "       TexCoord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);\n"
618 "#ifndef MODE_LIGHTSOURCE\n"
619 "# ifndef MODE_LIGHTDIRECTION\n"
620 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
621 "# endif\n"
622 "#endif\n"
623 "\n"
624 "#ifdef MODE_LIGHTSOURCE\n"
625 "       // transform vertex position into light attenuation/cubemap space\n"
626 "       // (-1 to +1 across the light box)\n"
627 "       CubeVector = vec3(gl_TextureMatrix[3] * gl_Vertex);\n"
628 "\n"
629 "       // transform unnormalized light direction into tangent space\n"
630 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
631 "       //  normalize it per pixel)\n"
632 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
633 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
634 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
635 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
636 "#endif\n"
637 "\n"
638 "#ifdef MODE_LIGHTDIRECTION\n"
639 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
640 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
641 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
642 "#endif\n"
643 "\n"
644 "       // transform unnormalized eye direction into tangent space\n"
645 "#ifndef USEFOG\n"
646 "       vec3 EyeVectorModelSpace;\n"
647 "#endif\n"
648 "       EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
649 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
650 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
651 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
652 "\n"
653 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
654 "       VectorS = gl_MultiTexCoord1.xyz;\n"
655 "       VectorT = gl_MultiTexCoord2.xyz;\n"
656 "       VectorR = gl_MultiTexCoord3.xyz;\n"
657 "#endif\n"
658 "\n"
659 "//#if defined(MODE_WATER) || defined(MODE_REFRACTION) || defined(USEREFLECTION)\n"
660 "//     ModelViewProjectionPosition = gl_Vertex * gl_ModelViewProjectionMatrix;\n"
661 "//     //ModelViewProjectionPosition_svector = (gl_Vertex + vec4(gl_MultiTexCoord1.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
662 "//     //ModelViewProjectionPosition_tvector = (gl_Vertex + vec4(gl_MultiTexCoord2.xyz, 0)) * gl_ModelViewProjectionMatrix - ModelViewProjectionPosition;\n"
663 "//#endif\n"
664 "\n"
665 "// transform vertex to camera space, using ftransform to match non-VS\n"
666 "       // rendering\n"
667 "       gl_Position = ftransform();\n"
668 "\n"
669 "#ifdef MODE_WATER\n"
670 "       ModelViewProjectionPosition = gl_Position;\n"
671 "#endif\n"
672 "#ifdef MODE_REFRACTION\n"
673 "       ModelViewProjectionPosition = gl_Position;\n"
674 "#endif\n"
675 "#ifdef USEREFLECTION\n"
676 "       ModelViewProjectionPosition = gl_Position;\n"
677 "#endif\n"
678 "}\n"
679 "\n"
680 "#endif // VERTEX_SHADER\n"
681 "\n"
682 "\n"
683 "\n"
684 "\n"
685 "// fragment shader specific:\n"
686 "#ifdef FRAGMENT_SHADER\n"
687 "\n"
688 "// 13 textures, we can only use up to 16 on DX9-class hardware\n"
689 "uniform sampler2D Texture_Normal;\n"
690 "uniform sampler2D Texture_Color;\n"
691 "uniform sampler2D Texture_Gloss;\n"
692 "uniform sampler2D Texture_Glow;\n"
693 "uniform sampler2D Texture_SecondaryNormal;\n"
694 "uniform sampler2D Texture_SecondaryColor;\n"
695 "uniform sampler2D Texture_SecondaryGloss;\n"
696 "uniform sampler2D Texture_SecondaryGlow;\n"
697 "uniform sampler2D Texture_Pants;\n"
698 "uniform sampler2D Texture_Shirt;\n"
699 "uniform sampler2D Texture_FogMask;\n"
700 "uniform sampler2D Texture_Lightmap;\n"
701 "uniform sampler2D Texture_Deluxemap;\n"
702 "uniform sampler2D Texture_Refraction;\n"
703 "uniform sampler2D Texture_Reflection;\n"
704 "uniform sampler2D Texture_Attenuation;\n"
705 "uniform samplerCube Texture_Cube;\n"
706 "\n"
707 "uniform myhalf3 LightColor;\n"
708 "uniform myhalf3 AmbientColor;\n"
709 "uniform myhalf3 DiffuseColor;\n"
710 "uniform myhalf3 SpecularColor;\n"
711 "uniform myhalf3 Color_Pants;\n"
712 "uniform myhalf3 Color_Shirt;\n"
713 "uniform myhalf3 FogColor;\n"
714 "\n"
715 "uniform myhalf4 TintColor;\n"
716 "\n"
717 "\n"
718 "//#ifdef MODE_WATER\n"
719 "uniform vec4 DistortScaleRefractReflect;\n"
720 "uniform vec4 ScreenScaleRefractReflect;\n"
721 "uniform vec4 ScreenCenterRefractReflect;\n"
722 "uniform myhalf4 RefractColor;\n"
723 "uniform myhalf4 ReflectColor;\n"
724 "uniform myhalf ReflectFactor;\n"
725 "uniform myhalf ReflectOffset;\n"
726 "//#else\n"
727 "//# ifdef MODE_REFRACTION\n"
728 "//uniform vec4 DistortScaleRefractReflect;\n"
729 "//uniform vec4 ScreenScaleRefractReflect;\n"
730 "//uniform vec4 ScreenCenterRefractReflect;\n"
731 "//uniform myhalf4 RefractColor;\n"
732 "//#  ifdef USEREFLECTION\n"
733 "//uniform myhalf4 ReflectColor;\n"
734 "//#  endif\n"
735 "//# else\n"
736 "//#  ifdef USEREFLECTION\n"
737 "//uniform vec4 DistortScaleRefractReflect;\n"
738 "//uniform vec4 ScreenScaleRefractReflect;\n"
739 "//uniform vec4 ScreenCenterRefractReflect;\n"
740 "//uniform myhalf4 ReflectColor;\n"
741 "//#  endif\n"
742 "//# endif\n"
743 "//#endif\n"
744 "\n"
745 "uniform myhalf GlowScale;\n"
746 "uniform myhalf SceneBrightness;\n"
747 "#ifdef USECONTRASTBOOST\n"
748 "uniform myhalf ContrastBoostCoeff;\n"
749 "#endif\n"
750 "\n"
751 "uniform float OffsetMapping_Scale;\n"
752 "uniform float OffsetMapping_Bias;\n"
753 "uniform float FogRangeRecip;\n"
754 "\n"
755 "uniform myhalf AmbientScale;\n"
756 "uniform myhalf DiffuseScale;\n"
757 "uniform myhalf SpecularScale;\n"
758 "uniform myhalf SpecularPower;\n"
759 "\n"
760 "#ifdef USEOFFSETMAPPING\n"
761 "vec2 OffsetMapping(vec2 TexCoord)\n"
762 "{\n"
763 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
764 "       // 14 sample relief mapping: linear search and then binary search\n"
765 "       // this basically steps forward a small amount repeatedly until it finds\n"
766 "       // itself inside solid, then jitters forward and back using decreasing\n"
767 "       // amounts to find the impact\n"
768 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
769 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
770 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
771 "       vec3 RT = vec3(TexCoord, 1);\n"
772 "       OffsetVector *= 0.1;\n"
773 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
774 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
775 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
776 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
777 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
778 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
779 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
780 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
781 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
782 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
783 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
784 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
785 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
786 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
787 "       return RT.xy;\n"
788 "#else\n"
789 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
790 "       // this basically moves forward the full distance, and then backs up based\n"
791 "       // on height of samples\n"
792 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
793 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
794 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
795 "       TexCoord += OffsetVector;\n"
796 "       OffsetVector *= 0.333;\n"
797 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
798 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
799 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
800 "       return TexCoord;\n"
801 "#endif\n"
802 "}\n"
803 "#endif // USEOFFSETMAPPING\n"
804 "\n"
805 "#ifdef MODE_WATER\n"
806 "\n"
807 "// water pass\n"
808 "void main(void)\n"
809 "{\n"
810 "#ifdef USEOFFSETMAPPING\n"
811 "       // apply offsetmapping\n"
812 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
813 "#define TexCoord TexCoordOffset\n"
814 "#endif\n"
815 "\n"
816 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
817 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
818 "       vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
819 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
820 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
821 "}\n"
822 "\n"
823 "#else // !MODE_WATER\n"
824 "#ifdef MODE_REFRACTION\n"
825 "\n"
826 "// refraction pass\n"
827 "void main(void)\n"
828 "{\n"
829 "#ifdef USEOFFSETMAPPING\n"
830 "       // apply offsetmapping\n"
831 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
832 "#define TexCoord TexCoordOffset\n"
833 "#endif\n"
834 "\n"
835 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
836 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
837 "       vec2 ScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy + vec2(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
838 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
839 "}\n"
840 "\n"
841 "#else // !MODE_REFRACTION\n"
842 "void main(void)\n"
843 "{\n"
844 "#ifdef USEOFFSETMAPPING\n"
845 "       // apply offsetmapping\n"
846 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
847 "#define TexCoord TexCoordOffset\n"
848 "#endif\n"
849 "\n"
850 "       // combine the diffuse textures (base, pants, shirt)\n"
851 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
852 "#ifdef USECOLORMAPPING\n"
853 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
854 "#endif\n"
855 "#ifdef USEVERTEXTEXTUREBLEND\n"
856 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
857 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
858 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
859 "       color = mix(myhalf4(texture2D(Texture_SecondaryColor, TexCoord)), color, terrainblend);\n"
860 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
861 "#endif\n"
862 "\n"
863 "#ifdef USEDIFFUSE\n"
864 "       // get the surface normal and the gloss color\n"
865 "# ifdef USEVERTEXTEXTUREBLEND\n"
866 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
867 "#  ifdef USESPECULAR\n"
868 "       myhalf3 glosscolor = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
869 "#  endif\n"
870 "# else\n"
871 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5));\n"
872 "#  ifdef USESPECULAR\n"
873 "       myhalf3 glosscolor = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
874 "#  endif\n"
875 "# endif\n"
876 "#endif\n"
877 "\n"
878 "\n"
879 "\n"
880 "#ifdef MODE_LIGHTSOURCE\n"
881 "       // light source\n"
882 "\n"
883 "       // calculate surface normal, light normal, and specular normal\n"
884 "       // compute color intensity for the two textures (colormap and glossmap)\n"
885 "       // scale by light color and attenuation as efficiently as possible\n"
886 "       // (do as much scalar math as possible rather than vector math)\n"
887 "# ifdef USEDIFFUSE\n"
888 "       // get the light normal\n"
889 "       myhalf3 diffusenormal = myhalf3(normalize(LightVector));\n"
890 "# endif\n"
891 "# ifdef USESPECULAR\n"
892 "       myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
893 "\n"
894 "       // calculate directional shading\n"
895 "       color.rgb = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (color.rgb * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))) + (SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower)) * glosscolor);\n"
896 "# else\n"
897 "#  ifdef USEDIFFUSE\n"
898 "       // calculate directional shading\n"
899 "       color.rgb = color.rgb * (myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0))) * (AmbientScale + DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0))));\n"
900 "#  else\n"
901 "       // calculate directionless shading\n"
902 "       color.rgb = color.rgb * myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
903 "#  endif\n"
904 "# endif\n"
905 "\n"
906 "# ifdef USECUBEFILTER\n"
907 "       // apply light cubemap filter\n"
908 "       //color.rgb *= normalize(CubeVector) * 0.5 + 0.5;//vec3(textureCube(Texture_Cube, CubeVector));\n"
909 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
910 "# endif\n"
911 "#endif // MODE_LIGHTSOURCE\n"
912 "\n"
913 "\n"
914 "\n"
915 "\n"
916 "#ifdef MODE_LIGHTDIRECTION\n"
917 "       // directional model lighting\n"
918 "# ifdef USEDIFFUSE\n"
919 "       // get the light normal\n"
920 "       myhalf3 diffusenormal = myhalf3(LightVector);\n"
921 "# endif\n"
922 "# ifdef USESPECULAR\n"
923 "       // calculate directional shading\n"
924 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
925 "       myhalf3 specularnormal = normalize(diffusenormal + myhalf3(normalize(EyeVector)));\n"
926 "       color.rgb += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularColor * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
927 "# else\n"
928 "#  ifdef USEDIFFUSE\n"
929 "\n"
930 "       // calculate directional shading\n"
931 "       color.rgb *= AmbientColor + DiffuseColor * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0));\n"
932 "#  else\n"
933 "       color.rgb *= AmbientColor;\n"
934 "#  endif\n"
935 "# endif\n"
936 "#endif // MODE_LIGHTDIRECTION\n"
937 "\n"
938 "\n"
939 "\n"
940 "\n"
941 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
942 "       // deluxemap lightmapping using light vectors in modelspace (evil q3map2)\n"
943 "\n"
944 "       // get the light normal\n"
945 "       myhalf3 diffusenormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5);\n"
946 "       myhalf3 diffusenormal = normalize(myhalf3(dot(diffusenormal_modelspace, myhalf3(VectorS)), dot(diffusenormal_modelspace, myhalf3(VectorT)), dot(diffusenormal_modelspace, myhalf3(VectorR))));\n"
947 "       // calculate directional shading\n"
948 "       myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
949 "# ifdef USESPECULAR\n"
950 "       myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
951 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
952 "# endif\n"
953 "\n"
954 "       // apply lightmap color\n"
955 "       color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
956 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
957 "\n"
958 "\n"
959 "\n"
960 "\n"
961 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
962 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
963 "\n"
964 "       // get the light normal\n"
965 "       myhalf3 diffusenormal = normalize(myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) - myhalf3(0.5));\n"
966 "       // calculate directional shading\n"
967 "       myhalf3 tempcolor = color.rgb * (DiffuseScale * myhalf(max(float(dot(surfacenormal, diffusenormal)), 0.0)));\n"
968 "# ifdef USESPECULAR\n"
969 "       myhalf3 specularnormal = myhalf3(normalize(diffusenormal + myhalf3(normalize(EyeVector))));\n"
970 "       tempcolor += myhalf3(texture2D(Texture_Gloss, TexCoord)) * SpecularScale * pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
971 "# endif\n"
972 "\n"
973 "       // apply lightmap color\n"
974 "       color.rgb = color.rgb * AmbientScale + tempcolor * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
975 "#endif // MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
976 "\n"
977 "\n"
978 "\n"
979 "\n"
980 "#ifdef MODE_LIGHTMAP\n"
981 "       // apply lightmap color\n"
982 "       color.rgb = color.rgb * myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * DiffuseScale + color.rgb * AmbientScale;\n"
983 "#endif // MODE_LIGHTMAP\n"
984 "\n"
985 "\n"
986 "\n"
987 "\n"
988 "#ifdef MODE_VERTEXCOLOR\n"
989 "       // apply lightmap color\n"
990 "       color.rgb = color.rgb * myhalf3(gl_Color.rgb) * DiffuseScale + color.rgb * AmbientScale;\n"
991 "#endif // MODE_VERTEXCOLOR\n"
992 "\n"
993 "\n"
994 "\n"
995 "\n"
996 "#ifdef MODE_FLATCOLOR\n"
997 "#endif // MODE_FLATCOLOR\n"
998 "\n"
999 "\n"
1000 "\n"
1001 "\n"
1002 "\n"
1003 "\n"
1004 "\n"
1005 "       color *= TintColor;\n"
1006 "\n"
1007 "#ifdef USEGLOW\n"
1008 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * GlowScale;\n"
1009 "#endif\n"
1010 "\n"
1011 "#ifdef USECONTRASTBOOST\n"
1012 "       color.rgb = color.rgb / (ContrastBoostCoeff * color.rgb + myhalf3(1, 1, 1));\n"
1013 "#endif\n"
1014 "\n"
1015 "       color.rgb *= SceneBrightness;\n"
1016 "\n"
1017 "       // apply fog after Contrastboost/SceneBrightness because its color is already modified appropriately\n"
1018 "#ifdef USEFOG\n"
1019 "       color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n"
1020 "#endif\n"
1021 "\n"
1022 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1023 "#ifdef USEREFLECTION\n"
1024 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1025 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1026 "       vec4 ScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xyxy * DistortScaleRefractReflect;\n"
1027 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord.zw)) * ReflectColor.rgb, ReflectColor.a);\n"
1028 "#endif\n"
1029 "\n"
1030 "       gl_FragColor = vec4(color);\n"
1031 "}\n"
1032 "#endif // !MODE_REFRACTION\n"
1033 "#endif // !MODE_WATER\n"
1034 "\n"
1035 "#endif // FRAGMENT_SHADER\n"
1036 "\n"
1037 "#endif // !MODE_GENERIC\n"
1038 "#endif // !MODE_POSTPROCESS\n"
1039 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1040 ;
1041
1042 typedef struct shaderpermutationinfo_s
1043 {
1044         const char *pretext;
1045         const char *name;
1046 }
1047 shaderpermutationinfo_t;
1048
1049 typedef struct shadermodeinfo_s
1050 {
1051         const char *vertexfilename;
1052         const char *geometryfilename;
1053         const char *fragmentfilename;
1054         const char *pretext;
1055         const char *name;
1056 }
1057 shadermodeinfo_t;
1058
1059 typedef enum shaderpermutation_e
1060 {
1061         SHADERPERMUTATION_DIFFUSE = 1<<0, // (lightsource) whether to use directional shading
1062         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, // indicates this is a two-layer material blend based on vertex alpha (q3bsp)
1063         SHADERPERMUTATION_COLORMAPPING = 1<<2, // indicates this is a colormapped skin
1064         SHADERPERMUTATION_CONTRASTBOOST = 1<<3, // r_glsl_contrastboost boosts the contrast at low color levels (similar to gamma)
1065         SHADERPERMUTATION_FOG = 1<<4, // tint the color by fog color or black if using additive blend mode
1066         SHADERPERMUTATION_CUBEFILTER = 1<<5, // (lightsource) use cubemap light filter
1067         SHADERPERMUTATION_GLOW = 1<<6, // (lightmap) blend in an additive glow texture
1068         SHADERPERMUTATION_SPECULAR = 1<<7, // (lightsource or deluxemapping) render specular effects
1069         SHADERPERMUTATION_REFLECTION = 1<<8, // normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
1070         SHADERPERMUTATION_OFFSETMAPPING = 1<<9, // adjust texcoords to roughly simulate a displacement mapped surface
1071         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<10, // adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
1072         SHADERPERMUTATION_LIMIT = 1<<11, // size of permutations array
1073         SHADERPERMUTATION_COUNT = 11 // size of shaderpermutationinfo array
1074 }
1075 shaderpermutation_t;
1076
1077 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
1078 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
1079 {
1080         {"#define USEDIFFUSE\n", " diffuse"},
1081         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
1082         {"#define USECOLORMAPPING\n", " colormapping"},
1083         {"#define USECONTRASTBOOST\n", " contrastboost"},
1084         {"#define USEFOG\n", " fog"},
1085         {"#define USECUBEFILTER\n", " cubefilter"},
1086         {"#define USEGLOW\n", " glow"},
1087         {"#define USESPECULAR\n", " specular"},
1088         {"#define USEREFLECTION\n", " reflection"},
1089         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
1090         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
1091 };
1092
1093 // this enum is multiplied by SHADERPERMUTATION_MODEBASE
1094 typedef enum shadermode_e
1095 {
1096         SHADERMODE_GENERIC, // (particles/HUD/etc) vertex color, optionally multiplied by one texture
1097         SHADERMODE_POSTPROCESS, // postprocessing shader (r_glsl_postprocess)
1098         SHADERMODE_DEPTH_OR_SHADOW, // (depthfirst/shadows) vertex shader only
1099         SHADERMODE_FLATCOLOR, // (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
1100         SHADERMODE_VERTEXCOLOR, // (lightmap) modulate texture by vertex colors (q3bsp)
1101         SHADERMODE_LIGHTMAP, // (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
1102         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, // (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
1103         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, // (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
1104         SHADERMODE_LIGHTDIRECTION, // (lightmap) use directional pixel shading from fixed light direction (q3bsp)
1105         SHADERMODE_LIGHTSOURCE, // (lightsource) use directional pixel shading from light source (rtlight)
1106         SHADERMODE_REFRACTION, // refract background (the material is rendered normally after this pass)
1107         SHADERMODE_WATER, // refract background and reflection (the material is rendered normally after this pass)
1108         SHADERMODE_COUNT
1109 }
1110 shadermode_t;
1111
1112 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
1113 shadermodeinfo_t shadermodeinfo[SHADERMODE_COUNT] =
1114 {
1115         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
1116         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
1117         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
1118         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
1119         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
1120         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
1121         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
1122         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
1123         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
1124         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
1125         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
1126         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
1127 };
1128
1129 typedef struct r_glsl_permutation_s
1130 {
1131         // indicates if we have tried compiling this permutation already
1132         qboolean compiled;
1133         // 0 if compilation failed
1134         int program;
1135         // locations of detected uniforms in program object, or -1 if not found
1136         int loc_Texture_First;
1137         int loc_Texture_Second;
1138         int loc_Texture_Normal;
1139         int loc_Texture_Color;
1140         int loc_Texture_Gloss;
1141         int loc_Texture_Glow;
1142         int loc_Texture_SecondaryNormal;
1143         int loc_Texture_SecondaryColor;
1144         int loc_Texture_SecondaryGloss;
1145         int loc_Texture_SecondaryGlow;
1146         int loc_Texture_Pants;
1147         int loc_Texture_Shirt;
1148         int loc_Texture_FogMask;
1149         int loc_Texture_Lightmap;
1150         int loc_Texture_Deluxemap;
1151         int loc_Texture_Attenuation;
1152         int loc_Texture_Cube;
1153         int loc_Texture_Refraction;
1154         int loc_Texture_Reflection;
1155         int loc_FogColor;
1156         int loc_LightPosition;
1157         int loc_EyePosition;
1158         int loc_Color_Pants;
1159         int loc_Color_Shirt;
1160         int loc_FogRangeRecip;
1161         int loc_AmbientScale;
1162         int loc_DiffuseScale;
1163         int loc_SpecularScale;
1164         int loc_SpecularPower;
1165         int loc_GlowScale;
1166         int loc_SceneBrightness; // or: Scenebrightness * ContrastBoost
1167         int loc_OffsetMapping_Scale;
1168         int loc_TintColor;
1169         int loc_AmbientColor;
1170         int loc_DiffuseColor;
1171         int loc_SpecularColor;
1172         int loc_LightDir;
1173         int loc_ContrastBoostCoeff; // 1 - 1/ContrastBoost
1174         int loc_DistortScaleRefractReflect;
1175         int loc_ScreenScaleRefractReflect;
1176         int loc_ScreenCenterRefractReflect;
1177         int loc_RefractColor;
1178         int loc_ReflectColor;
1179         int loc_ReflectFactor;
1180         int loc_ReflectOffset;
1181 }
1182 r_glsl_permutation_t;
1183
1184 // information about each possible shader permutation
1185 r_glsl_permutation_t r_glsl_permutations[SHADERMODE_COUNT][SHADERPERMUTATION_LIMIT];
1186 // currently selected permutation
1187 r_glsl_permutation_t *r_glsl_permutation;
1188
1189 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
1190 {
1191         char *shaderstring;
1192         if (!filename || !filename[0])
1193                 return NULL;
1194         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1195         if (shaderstring)
1196         {
1197                 if (printfromdisknotice)
1198                         Con_DPrint("from disk... ");
1199                 return shaderstring;
1200         }
1201         else if (!strcmp(filename, "glsl/default.glsl"))
1202         {
1203                 shaderstring = Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
1204                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
1205         }
1206         return shaderstring;
1207 }
1208
1209 static void R_GLSL_CompilePermutation(shadermode_t mode, shaderpermutation_t permutation)
1210 {
1211         int i;
1212         shadermodeinfo_t *modeinfo = shadermodeinfo + mode;
1213         r_glsl_permutation_t *p = &r_glsl_permutations[mode][permutation];
1214         int vertstrings_count = 0;
1215         int geomstrings_count = 0;
1216         int fragstrings_count = 0;
1217         char *vertexstring, *geometrystring, *fragmentstring;
1218         const char *vertstrings_list[32+3];
1219         const char *geomstrings_list[32+3];
1220         const char *fragstrings_list[32+3];
1221         char permutationname[256];
1222
1223         if (p->compiled)
1224                 return;
1225         p->compiled = true;
1226         p->program = 0;
1227
1228         permutationname[0] = 0;
1229         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1230         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1231         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1232
1233         strlcat(permutationname, shadermodeinfo[mode].vertexfilename, sizeof(permutationname));
1234
1235         // the first pretext is which type of shader to compile as
1236         // (later these will all be bound together as a program object)
1237         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1238         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1239         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1240
1241         // the second pretext is the mode (for example a light source)
1242         vertstrings_list[vertstrings_count++] = shadermodeinfo[mode].pretext;
1243         geomstrings_list[geomstrings_count++] = shadermodeinfo[mode].pretext;
1244         fragstrings_list[fragstrings_count++] = shadermodeinfo[mode].pretext;
1245         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1246
1247         // now add all the permutation pretexts
1248         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1249         {
1250                 if (permutation & (1<<i))
1251                 {
1252                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1253                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1254                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1255                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1256                 }
1257                 else
1258                 {
1259                         // keep line numbers correct
1260                         vertstrings_list[vertstrings_count++] = "\n";
1261                         geomstrings_list[geomstrings_count++] = "\n";
1262                         fragstrings_list[fragstrings_count++] = "\n";
1263                 }
1264         }
1265
1266         // now append the shader text itself
1267         vertstrings_list[vertstrings_count++] = vertexstring;
1268         geomstrings_list[geomstrings_count++] = geometrystring;
1269         fragstrings_list[fragstrings_count++] = fragmentstring;
1270
1271         // if any sources were NULL, clear the respective list
1272         if (!vertexstring)
1273                 vertstrings_count = 0;
1274         if (!geometrystring)
1275                 geomstrings_count = 0;
1276         if (!fragmentstring)
1277                 fragstrings_count = 0;
1278
1279         // compile the shader program
1280         if (vertstrings_count + geomstrings_count + fragstrings_count)
1281                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1282         if (p->program)
1283         {
1284                 CHECKGLERROR
1285                 qglUseProgramObjectARB(p->program);CHECKGLERROR
1286                 // look up all the uniform variable names we care about, so we don't
1287                 // have to look them up every time we set them
1288                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
1289                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
1290                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
1291                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
1292                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
1293                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
1294                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
1295                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
1296                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
1297                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
1298                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
1299                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
1300                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
1301                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
1302                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
1303                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
1304                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
1305                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
1306                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
1307                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
1308                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
1309                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
1310                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
1311                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
1312                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
1313                 p->loc_AmbientScale               = qglGetUniformLocationARB(p->program, "AmbientScale");
1314                 p->loc_DiffuseScale               = qglGetUniformLocationARB(p->program, "DiffuseScale");
1315                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
1316                 p->loc_SpecularScale              = qglGetUniformLocationARB(p->program, "SpecularScale");
1317                 p->loc_GlowScale                  = qglGetUniformLocationARB(p->program, "GlowScale");
1318                 p->loc_SceneBrightness            = qglGetUniformLocationARB(p->program, "SceneBrightness");
1319                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
1320                 p->loc_TintColor                  = qglGetUniformLocationARB(p->program, "TintColor");
1321                 p->loc_AmbientColor               = qglGetUniformLocationARB(p->program, "AmbientColor");
1322                 p->loc_DiffuseColor               = qglGetUniformLocationARB(p->program, "DiffuseColor");
1323                 p->loc_SpecularColor              = qglGetUniformLocationARB(p->program, "SpecularColor");
1324                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
1325                 p->loc_ContrastBoostCoeff         = qglGetUniformLocationARB(p->program, "ContrastBoostCoeff");
1326                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
1327                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
1328                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
1329                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
1330                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
1331                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
1332                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
1333                 // initialize the samplers to refer to the texture units we use
1334                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
1335                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
1336                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
1337                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
1338                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
1339                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
1340                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
1341                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
1342                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
1343                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
1344                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
1345                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
1346                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
1347                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
1348                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
1349                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
1350                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
1351                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
1352                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
1353                 CHECKGLERROR
1354                 if (developer.integer)
1355                         Con_Printf("GLSL shader %s compiled.\n", permutationname);
1356         }
1357         else
1358                 Con_Printf("GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1359
1360         // free the strings
1361         if (vertexstring)
1362                 Mem_Free(vertexstring);
1363         if (geometrystring)
1364                 Mem_Free(geometrystring);
1365         if (fragmentstring)
1366                 Mem_Free(fragmentstring);
1367 }
1368
1369 void R_GLSL_Restart_f(void)
1370 {
1371         shadermode_t mode;
1372         shaderpermutation_t permutation;
1373         for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1374                 for (permutation = 0;permutation < SHADERPERMUTATION_LIMIT;permutation++)
1375                         if (r_glsl_permutations[mode][permutation].program)
1376                                 GL_Backend_FreeProgram(r_glsl_permutations[mode][permutation].program);
1377         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
1378 }
1379
1380 void R_GLSL_DumpShader_f(void)
1381 {
1382         int i;
1383
1384         qfile_t *file = FS_Open("glsl/default.glsl", "w", false, false);
1385         if(!file)
1386         {
1387                 Con_Printf("failed to write to glsl/default.glsl\n");
1388                 return;
1389         }
1390
1391         FS_Print(file, "// The engine may define the following macros:\n");
1392         FS_Print(file, "// #define VERTEX_SHADER\n// #define GEOMETRY_SHADER\n// #define FRAGMENT_SHADER\n");
1393         for (i = 0;i < SHADERMODE_COUNT;i++)
1394                 FS_Printf(file, "// %s", shadermodeinfo[i].pretext);
1395         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1396                 FS_Printf(file, "// %s", shaderpermutationinfo[i].pretext);
1397         FS_Print(file, "\n");
1398         FS_Print(file, builtinshaderstring);
1399         FS_Close(file);
1400
1401         Con_Printf("glsl/default.glsl written\n");
1402 }
1403
1404 void R_SetupShader_SetPermutation(shadermode_t mode, unsigned int permutation)
1405 {
1406         r_glsl_permutation_t *perm = &r_glsl_permutations[mode][permutation];
1407         if (r_glsl_permutation != perm)
1408         {
1409                 r_glsl_permutation = perm;
1410                 if (!r_glsl_permutation->program)
1411                 {
1412                         if (!r_glsl_permutation->compiled)
1413                                 R_GLSL_CompilePermutation(mode, permutation);
1414                         if (!r_glsl_permutation->program)
1415                         {
1416                                 // remove features until we find a valid permutation
1417                                 int i;
1418                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1419                                 {
1420                                         // reduce i more quickly whenever it would not remove any bits
1421                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1422                                         if (!(permutation & j))
1423                                                 continue;
1424                                         permutation -= j;
1425                                         r_glsl_permutation = &r_glsl_permutations[mode][permutation];
1426                                         if (!r_glsl_permutation->compiled)
1427                                                 R_GLSL_CompilePermutation(mode, permutation);
1428                                         if (r_glsl_permutation->program)
1429                                                 break;
1430                                 }
1431                                 if (i >= SHADERPERMUTATION_COUNT)
1432                                 {
1433                                         Con_Printf("OpenGL 2.0 shaders disabled - unable to find a working shader permutation fallback on this driver (set r_glsl 1 if you want to try again)\n");
1434                                         Cvar_SetValueQuick(&r_glsl, 0);
1435                                         R_GLSL_Restart_f(); // unload shaders
1436                                         return; // no bit left to clear
1437                                 }
1438                         }
1439                 }
1440                 CHECKGLERROR
1441                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
1442         }
1443 }
1444
1445 void R_SetupGenericShader(qboolean usetexture)
1446 {
1447         if (gl_support_fragment_shader)
1448         {
1449                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1450                         R_SetupShader_SetPermutation(SHADERMODE_GENERIC, usetexture ? SHADERPERMUTATION_DIFFUSE : 0);
1451                 else if (r_glsl_permutation)
1452                 {
1453                         r_glsl_permutation = NULL;
1454                         qglUseProgramObjectARB(0);CHECKGLERROR
1455                 }
1456         }
1457 }
1458
1459 void R_SetupGenericTwoTextureShader(int texturemode)
1460 {
1461         if (gl_support_fragment_shader)
1462         {
1463                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1464                         R_SetupShader_SetPermutation(SHADERMODE_GENERIC, SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1465                 else if (r_glsl_permutation)
1466                 {
1467                         r_glsl_permutation = NULL;
1468                         qglUseProgramObjectARB(0);CHECKGLERROR
1469                 }
1470         }
1471         if (!r_glsl_permutation)
1472         {
1473                 if (texturemode == GL_DECAL && gl_combine.integer)
1474                         texturemode = GL_INTERPOLATE_ARB;
1475                 R_Mesh_TexCombine(1, texturemode, texturemode, 1, 1);
1476         }
1477 }
1478
1479 void R_SetupDepthOrShadowShader(void)
1480 {
1481         if (gl_support_fragment_shader)
1482         {
1483                 if (r_glsl.integer && r_glsl_usegeneric.integer)
1484                         R_SetupShader_SetPermutation(SHADERMODE_DEPTH_OR_SHADOW, 0);
1485                 else if (r_glsl_permutation)
1486                 {
1487                         r_glsl_permutation = NULL;
1488                         qglUseProgramObjectARB(0);CHECKGLERROR
1489                 }
1490         }
1491 }
1492
1493 extern rtexture_t *r_shadow_attenuationgradienttexture;
1494 extern rtexture_t *r_shadow_attenuation2dtexture;
1495 extern rtexture_t *r_shadow_attenuation3dtexture;
1496 void R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
1497 {
1498         // select a permutation of the lighting shader appropriate to this
1499         // combination of texture, entity, light source, and fogging, only use the
1500         // minimum features necessary to avoid wasting rendering time in the
1501         // fragment shader on features that are not being used
1502         unsigned int permutation = 0;
1503         shadermode_t mode = 0;
1504         // TODO: implement geometry-shader based shadow volumes someday
1505         if (r_glsl_offsetmapping.integer)
1506         {
1507                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1508                 if (r_glsl_offsetmapping_reliefmapping.integer)
1509                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1510         }
1511         if (rsurfacepass == RSURFPASS_BACKGROUND)
1512         {
1513                 // distorted background
1514                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
1515                         mode = SHADERMODE_WATER;
1516                 else
1517                         mode = SHADERMODE_REFRACTION;
1518         }
1519         else if (rsurfacepass == RSURFPASS_RTLIGHT)
1520         {
1521                 // light source
1522                 mode = SHADERMODE_LIGHTSOURCE;
1523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1524                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1525                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
1526                         permutation |= SHADERPERMUTATION_CUBEFILTER;
1527                 if (diffusescale > 0)
1528                         permutation |= SHADERPERMUTATION_DIFFUSE;
1529                 if (specularscale > 0)
1530                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1531                 if (r_refdef.fogenabled)
1532                         permutation |= SHADERPERMUTATION_FOG;
1533                 if (rsurface.texture->colormapping)
1534                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1535                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1536                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1537         }
1538         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
1539         {
1540                 // unshaded geometry (fullbright or ambient model lighting)
1541                 mode = SHADERMODE_FLATCOLOR;
1542                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1543                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1544                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1545                         permutation |= SHADERPERMUTATION_GLOW;
1546                 if (r_refdef.fogenabled)
1547                         permutation |= SHADERPERMUTATION_FOG;
1548                 if (rsurface.texture->colormapping)
1549                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1550                 if (r_glsl_offsetmapping.integer)
1551                 {
1552                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
1553                         if (r_glsl_offsetmapping_reliefmapping.integer)
1554                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
1555                 }
1556                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1557                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1558                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1559                         permutation |= SHADERPERMUTATION_REFLECTION;
1560         }
1561         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
1562         {
1563                 // directional model lighting
1564                 mode = SHADERMODE_LIGHTDIRECTION;
1565                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1566                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1567                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1568                         permutation |= SHADERPERMUTATION_GLOW;
1569                 permutation |= SHADERPERMUTATION_DIFFUSE;
1570                 if (specularscale > 0)
1571                         permutation |= SHADERPERMUTATION_SPECULAR;
1572                 if (r_refdef.fogenabled)
1573                         permutation |= SHADERPERMUTATION_FOG;
1574                 if (rsurface.texture->colormapping)
1575                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1576                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1577                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1578                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1579                         permutation |= SHADERPERMUTATION_REFLECTION;
1580         }
1581         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
1582         {
1583                 // ambient model lighting
1584                 mode = SHADERMODE_LIGHTDIRECTION;
1585                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1586                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1587                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1588                         permutation |= SHADERPERMUTATION_GLOW;
1589                 if (r_refdef.fogenabled)
1590                         permutation |= SHADERPERMUTATION_FOG;
1591                 if (rsurface.texture->colormapping)
1592                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1593                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1594                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1595                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1596                         permutation |= SHADERPERMUTATION_REFLECTION;
1597         }
1598         else
1599         {
1600                 // lightmapped wall
1601                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
1602                 {
1603                         // deluxemapping (light direction texture)
1604                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
1605                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
1606                         else
1607                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1608                         permutation |= SHADERPERMUTATION_DIFFUSE;
1609                         if (specularscale > 0)
1610                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1611                 }
1612                 else if (r_glsl_deluxemapping.integer >= 2)
1613                 {
1614                         // fake deluxemapping (uniform light direction in tangentspace)
1615                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
1616                         permutation |= SHADERPERMUTATION_DIFFUSE;
1617                         if (specularscale > 0)
1618                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
1619                 }
1620                 else if (rsurface.uselightmaptexture)
1621                 {
1622                         // ordinary lightmapping (q1bsp, q3bsp)
1623                         mode = SHADERMODE_LIGHTMAP;
1624                 }
1625                 else
1626                 {
1627                         // ordinary vertex coloring (q3bsp)
1628                         mode = SHADERMODE_VERTEXCOLOR;
1629                 }
1630                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
1631                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1632                 if (rsurface.texture->currentskinframe->glow && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
1633                         permutation |= SHADERPERMUTATION_GLOW;
1634                 if (r_refdef.fogenabled)
1635                         permutation |= SHADERPERMUTATION_FOG;
1636                 if (rsurface.texture->colormapping)
1637                         permutation |= SHADERPERMUTATION_COLORMAPPING;
1638                 if(r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)
1639                         permutation |= SHADERPERMUTATION_CONTRASTBOOST;
1640                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
1641                         permutation |= SHADERPERMUTATION_REFLECTION;
1642         }
1643         R_SetupShader_SetPermutation(mode, permutation);
1644         if (mode == SHADERMODE_LIGHTSOURCE)
1645         {
1646                 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
1647                 if (permutation & SHADERPERMUTATION_DIFFUSE)
1648                 {
1649                         if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2], rsurface.texture->lightmapcolor[3]);
1650                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, ambientscale);
1651                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, diffusescale);
1652                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, specularscale);
1653                 }
1654                 else
1655                 {
1656                         // ambient only is simpler
1657                         if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, lightcolorbase[0] * ambientscale, lightcolorbase[1] * ambientscale, lightcolorbase[2] * ambientscale, rsurface.texture->lightmapcolor[3]);
1658                         if (r_glsl_permutation->loc_AmbientScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, 1);
1659                         if (r_glsl_permutation->loc_DiffuseScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, 0);
1660                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, 0);
1661                 }
1662                 // additive passes are only darkened by fog, not tinted
1663                 if (r_glsl_permutation->loc_FogColor >= 0)
1664                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1665         }
1666         else
1667         {
1668                 if (mode == SHADERMODE_LIGHTDIRECTION)
1669                 {
1670                         if (r_glsl_permutation->loc_AmbientColor  >= 0) qglUniform3fARB(r_glsl_permutation->loc_AmbientColor , rsurface.modellight_ambient[0] * ambientscale  * 0.5f, rsurface.modellight_ambient[1] * ambientscale  * 0.5f, rsurface.modellight_ambient[2] * ambientscale  * 0.5f);
1671                         if (r_glsl_permutation->loc_DiffuseColor  >= 0) qglUniform3fARB(r_glsl_permutation->loc_DiffuseColor , rsurface.modellight_diffuse[0] * diffusescale  * 0.5f, rsurface.modellight_diffuse[1] * diffusescale  * 0.5f, rsurface.modellight_diffuse[2] * diffusescale  * 0.5f);
1672                         if (r_glsl_permutation->loc_SpecularColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_SpecularColor, rsurface.modellight_diffuse[0] * specularscale * 0.5f, rsurface.modellight_diffuse[1] * specularscale * 0.5f, rsurface.modellight_diffuse[2] * specularscale * 0.5f);
1673                         if (r_glsl_permutation->loc_LightDir      >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
1674                 }
1675                 else
1676                 {
1677                         if (r_glsl_permutation->loc_AmbientScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_AmbientScale, r_ambient.value * 1.0f / 128.0f);
1678                         if (r_glsl_permutation->loc_DiffuseScale  >= 0) qglUniform1fARB(r_glsl_permutation->loc_DiffuseScale, r_refdef.lightmapintensity);
1679                         if (r_glsl_permutation->loc_SpecularScale >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularScale, r_refdef.lightmapintensity * specularscale);
1680                 }
1681                 if (r_glsl_permutation->loc_TintColor >= 0) qglUniform4fARB(r_glsl_permutation->loc_TintColor, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2], rsurface.texture->lightmapcolor[3]);
1682                 if (r_glsl_permutation->loc_GlowScale     >= 0) qglUniform1fARB(r_glsl_permutation->loc_GlowScale, r_hdr_glowintensity.value);
1683                 // additive passes are only darkened by fog, not tinted
1684                 if (r_glsl_permutation->loc_FogColor >= 0)
1685                 {
1686                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
1687                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
1688                         else
1689                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
1690                 }
1691                 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
1692                 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
1693                 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
1694                 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
1695                 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
1696                 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
1697                 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
1698         }
1699         if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
1700         {
1701                 // The formula used is actually:
1702                 //   color.rgb *= ContrastBoost / ((ContrastBoost - 1) * color.rgb + 1);
1703                 //   color.rgb *= SceneBrightness;
1704                 // simplified:
1705                 //   color.rgb = [[SceneBrightness * ContrastBoost]] * color.rgb / ([[ContrastBoost - 1]] * color.rgb + 1);
1706                 // and do [[calculations]] here in the engine
1707                 qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_contrastboost.value - 1);
1708                 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale * r_glsl_contrastboost.value);
1709         }
1710         else
1711                 if (r_glsl_permutation->loc_SceneBrightness >= 0) qglUniform1fARB(r_glsl_permutation->loc_SceneBrightness, r_refdef.view.colorscale);
1712         if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.modelorg[0], rsurface.modelorg[1], rsurface.modelorg[2]);
1713         if (r_glsl_permutation->loc_Color_Pants >= 0)
1714         {
1715                 if (rsurface.texture->currentskinframe->pants)
1716                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
1717                 else
1718                         qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
1719         }
1720         if (r_glsl_permutation->loc_Color_Shirt >= 0)
1721         {
1722                 if (rsurface.texture->currentskinframe->shirt)
1723                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
1724                 else
1725                         qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
1726         }
1727         if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip);
1728         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower);
1729         if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
1730         CHECKGLERROR
1731 }
1732
1733 #define SKINFRAME_HASH 1024
1734
1735 struct
1736 {
1737         int loadsequence; // incremented each level change
1738         memexpandablearray_t array;
1739         skinframe_t *hash[SKINFRAME_HASH];
1740 }
1741 r_skinframe;
1742
1743 void R_SkinFrame_PrepareForPurge(void)
1744 {
1745         r_skinframe.loadsequence++;
1746         // wrap it without hitting zero
1747         if (r_skinframe.loadsequence >= 200)
1748                 r_skinframe.loadsequence = 1;
1749 }
1750
1751 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
1752 {
1753         if (!skinframe)
1754                 return;
1755         // mark the skinframe as used for the purging code
1756         skinframe->loadsequence = r_skinframe.loadsequence;
1757 }
1758
1759 void R_SkinFrame_Purge(void)
1760 {
1761         int i;
1762         skinframe_t *s;
1763         for (i = 0;i < SKINFRAME_HASH;i++)
1764         {
1765                 for (s = r_skinframe.hash[i];s;s = s->next)
1766                 {
1767                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
1768                         {
1769                                 if (s->merged == s->base)
1770                                         s->merged = NULL;
1771                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
1772                                 R_PurgeTexture(s->stain );s->stain  = NULL;
1773                                 R_PurgeTexture(s->merged);s->merged = NULL;
1774                                 R_PurgeTexture(s->base  );s->base   = NULL;
1775                                 R_PurgeTexture(s->pants );s->pants  = NULL;
1776                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
1777                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
1778                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
1779                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
1780                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
1781                                 s->loadsequence = 0;
1782                         }
1783                 }
1784         }
1785 }
1786
1787 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
1788         skinframe_t *item;
1789         char basename[MAX_QPATH];
1790
1791         Image_StripImageExtension(name, basename, sizeof(basename));
1792
1793         if( last == NULL ) {
1794                 int hashindex;
1795                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1796                 item = r_skinframe.hash[hashindex];
1797         } else {
1798                 item = last->next;
1799         }
1800
1801         // linearly search through the hash bucket
1802         for( ; item ; item = item->next ) {
1803                 if( !strcmp( item->basename, basename ) ) {
1804                         return item;
1805                 }
1806         }
1807         return NULL;
1808 }
1809
1810 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
1811 {
1812         skinframe_t *item;
1813         int hashindex;
1814         char basename[MAX_QPATH];
1815
1816         Image_StripImageExtension(name, basename, sizeof(basename));
1817
1818         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
1819         for (item = r_skinframe.hash[hashindex];item;item = item->next)
1820                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
1821                         break;
1822
1823         if (!item) {
1824                 rtexture_t *dyntexture;
1825                 // check whether its a dynamic texture
1826                 dyntexture = CL_GetDynTexture( basename );
1827                 if (!add && !dyntexture)
1828                         return NULL;
1829                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
1830                 memset(item, 0, sizeof(*item));
1831                 strlcpy(item->basename, basename, sizeof(item->basename));
1832                 item->base = dyntexture; // either NULL or dyntexture handle
1833                 item->textureflags = textureflags;
1834                 item->comparewidth = comparewidth;
1835                 item->compareheight = compareheight;
1836                 item->comparecrc = comparecrc;
1837                 item->next = r_skinframe.hash[hashindex];
1838                 r_skinframe.hash[hashindex] = item;
1839         }
1840         else if( item->base == NULL )
1841         {
1842                 rtexture_t *dyntexture;
1843                 // check whether its a dynamic texture
1844                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
1845                 dyntexture = CL_GetDynTexture( basename );
1846                 item->base = dyntexture; // either NULL or dyntexture handle
1847         }
1848
1849         R_SkinFrame_MarkUsed(item);
1850         return item;
1851 }
1852
1853 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
1854 {
1855         // FIXME: it should be possible to disable loading various layers using
1856         // cvars, to prevent wasted loading time and memory usage if the user does
1857         // not want them
1858         qboolean loadnormalmap = true;
1859         qboolean loadgloss = true;
1860         qboolean loadpantsandshirt = true;
1861         qboolean loadglow = true;
1862         int j;
1863         unsigned char *pixels;
1864         unsigned char *bumppixels;
1865         unsigned char *basepixels = NULL;
1866         int basepixels_width;
1867         int basepixels_height;
1868         skinframe_t *skinframe;
1869
1870         if (cls.state == ca_dedicated)
1871                 return NULL;
1872
1873         // return an existing skinframe if already loaded
1874         // if loading of the first image fails, don't make a new skinframe as it
1875         // would cause all future lookups of this to be missing
1876         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
1877         if (skinframe && skinframe->base)
1878                 return skinframe;
1879
1880         basepixels = loadimagepixelsbgra(name, complain, true);
1881         if (basepixels == NULL)
1882                 return NULL;
1883
1884         // we've got some pixels to store, so really allocate this new texture now
1885         if (!skinframe)
1886                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
1887         skinframe->stain = NULL;
1888         skinframe->merged = NULL;
1889         skinframe->base = r_texture_notexture;
1890         skinframe->pants = NULL;
1891         skinframe->shirt = NULL;
1892         skinframe->nmap = r_texture_blanknormalmap;
1893         skinframe->gloss = NULL;
1894         skinframe->glow = NULL;
1895         skinframe->fog = NULL;
1896
1897         basepixels_width = image_width;
1898         basepixels_height = image_height;
1899         skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1900
1901         if (textureflags & TEXF_ALPHA)
1902         {
1903                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
1904                         if (basepixels[j] < 255)
1905                                 break;
1906                 if (j < basepixels_width * basepixels_height * 4)
1907                 {
1908                         // has transparent pixels
1909                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1910                         for (j = 0;j < image_width * image_height * 4;j += 4)
1911                         {
1912                                 pixels[j+0] = 255;
1913                                 pixels[j+1] = 255;
1914                                 pixels[j+2] = 255;
1915                                 pixels[j+3] = basepixels[j+3];
1916                         }
1917                         skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1918                         Mem_Free(pixels);
1919                 }
1920         }
1921
1922         // _norm is the name used by tenebrae and has been adopted as standard
1923         if (loadnormalmap)
1924         {
1925                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
1926                 {
1927                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1928                         Mem_Free(pixels);
1929                         pixels = NULL;
1930                 }
1931                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
1932                 {
1933                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
1934                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
1935                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1936                         Mem_Free(pixels);
1937                         Mem_Free(bumppixels);
1938                 }
1939                 else if (r_shadow_bumpscale_basetexture.value > 0)
1940                 {
1941                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
1942                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
1943                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), NULL);
1944                         Mem_Free(pixels);
1945                 }
1946         }
1947         // _luma is supported for tenebrae compatibility
1948         // (I think it's a very stupid name, but oh well)
1949         // _glow is the preferred name
1950         if (loadglow          && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false)) != NULL || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false)) != NULL)) {skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1951         if (loadgloss         && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)) != NULL) {skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1952         if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)) != NULL) {skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1953         if (loadpantsandshirt && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)) != NULL) {skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), NULL);Mem_Free(pixels);pixels = NULL;}
1954
1955         if (basepixels)
1956                 Mem_Free(basepixels);
1957
1958         return skinframe;
1959 }
1960
1961 static rtexture_t *R_SkinFrame_TextureForSkinLayer(const unsigned char *in, int width, int height, const char *name, const unsigned int *palette, int textureflags, qboolean force)
1962 {
1963         int i;
1964         if (!force)
1965         {
1966                 for (i = 0;i < width*height;i++)
1967                         if (((unsigned char *)&palette[in[i]])[3] > 0)
1968                                 break;
1969                 if (i == width*height)
1970                         return NULL;
1971         }
1972         return R_LoadTexture2D (r_main_texturepool, name, width, height, in, TEXTYPE_PALETTE, textureflags, palette);
1973 }
1974
1975 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
1976 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
1977 {
1978         int i;
1979         unsigned char *temp1, *temp2;
1980         skinframe_t *skinframe;
1981
1982         if (cls.state == ca_dedicated)
1983                 return NULL;
1984
1985         // if already loaded just return it, otherwise make a new skinframe
1986         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
1987         if (skinframe && skinframe->base)
1988                 return skinframe;
1989
1990         skinframe->stain = NULL;
1991         skinframe->merged = NULL;
1992         skinframe->base = r_texture_notexture;
1993         skinframe->pants = NULL;
1994         skinframe->shirt = NULL;
1995         skinframe->nmap = r_texture_blanknormalmap;
1996         skinframe->gloss = NULL;
1997         skinframe->glow = NULL;
1998         skinframe->fog = NULL;
1999
2000         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2001         if (!skindata)
2002                 return NULL;
2003
2004         if (r_shadow_bumpscale_basetexture.value > 0)
2005         {
2006                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2007                 temp2 = temp1 + width * height * 4;
2008                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2009                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2010                 Mem_Free(temp1);
2011         }
2012         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2013         if (textureflags & TEXF_ALPHA)
2014         {
2015                 for (i = 3;i < width * height * 4;i += 4)
2016                         if (skindata[i] < 255)
2017                                 break;
2018                 if (i < width * height * 4)
2019                 {
2020                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
2021                         memcpy(fogpixels, skindata, width * height * 4);
2022                         for (i = 0;i < width * height * 4;i += 4)
2023                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
2024                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
2025                         Mem_Free(fogpixels);
2026                 }
2027         }
2028
2029         return skinframe;
2030 }
2031
2032 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
2033 {
2034         int i;
2035         unsigned char *temp1, *temp2;
2036         skinframe_t *skinframe;
2037
2038         if (cls.state == ca_dedicated)
2039                 return NULL;
2040
2041         // if already loaded just return it, otherwise make a new skinframe
2042         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
2043         if (skinframe && skinframe->base)
2044                 return skinframe;
2045
2046         skinframe->stain = NULL;
2047         skinframe->merged = NULL;
2048         skinframe->base = r_texture_notexture;
2049         skinframe->pants = NULL;
2050         skinframe->shirt = NULL;
2051         skinframe->nmap = r_texture_blanknormalmap;
2052         skinframe->gloss = NULL;
2053         skinframe->glow = NULL;
2054         skinframe->fog = NULL;
2055
2056         // if no data was provided, then clearly the caller wanted to get a blank skinframe
2057         if (!skindata)
2058                 return NULL;
2059
2060         if (r_shadow_bumpscale_basetexture.value > 0)
2061         {
2062                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
2063                 temp2 = temp1 + width * height * 4;
2064                 // use either a custom palette or the quake palette
2065                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
2066                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
2067                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
2068                 Mem_Free(temp1);
2069         }
2070         // use either a custom palette, or the quake palette
2071         skinframe->base = skinframe->merged = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_merged", skinframe->basename), (loadglowtexture ? palette_bgra_nofullbrights : ((skinframe->textureflags & TEXF_ALPHA) ? palette_bgra_transparent : palette_bgra_complete)), skinframe->textureflags, true); // all
2072         if (loadglowtexture)
2073                 skinframe->glow = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_glow", skinframe->basename), palette_bgra_onlyfullbrights, skinframe->textureflags, false); // glow
2074         if (loadpantsandshirt)
2075         {
2076                 skinframe->pants = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_pants", skinframe->basename), palette_bgra_pantsaswhite, skinframe->textureflags, false); // pants
2077                 skinframe->shirt = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_shirt", skinframe->basename), palette_bgra_shirtaswhite, skinframe->textureflags, false); // shirt
2078         }
2079         if (skinframe->pants || skinframe->shirt)
2080                 skinframe->base = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_nospecial", skinframe->basename), loadglowtexture ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap, skinframe->textureflags, false); // no special colors
2081         if (textureflags & TEXF_ALPHA)
2082         {
2083                 for (i = 0;i < width * height;i++)
2084                         if (((unsigned char *)palette_bgra_alpha)[skindata[i]*4+3] < 255)
2085                                 break;
2086                 if (i < width * height)
2087                         skinframe->fog = R_SkinFrame_TextureForSkinLayer(skindata, width, height, va("%s_fog", skinframe->basename), palette_bgra_alpha, skinframe->textureflags, true); // fog mask
2088         }
2089
2090         return skinframe;
2091 }
2092
2093 skinframe_t *R_SkinFrame_LoadMissing(void)
2094 {
2095         skinframe_t *skinframe;
2096
2097         if (cls.state == ca_dedicated)
2098                 return NULL;
2099
2100         skinframe = R_SkinFrame_Find("missing", TEXF_PRECACHE, 0, 0, 0, true);
2101         skinframe->stain = NULL;
2102         skinframe->merged = NULL;
2103         skinframe->base = r_texture_notexture;
2104         skinframe->pants = NULL;
2105         skinframe->shirt = NULL;
2106         skinframe->nmap = r_texture_blanknormalmap;
2107         skinframe->gloss = NULL;
2108         skinframe->glow = NULL;
2109         skinframe->fog = NULL;
2110
2111         return skinframe;
2112 }
2113
2114 void gl_main_start(void)
2115 {
2116         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2117         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2118
2119         // set up r_skinframe loading system for textures
2120         memset(&r_skinframe, 0, sizeof(r_skinframe));
2121         r_skinframe.loadsequence = 1;
2122         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2123
2124         r_main_texturepool = R_AllocTexturePool();
2125         R_BuildBlankTextures();
2126         R_BuildNoTexture();
2127         if (gl_texturecubemap)
2128         {
2129                 R_BuildWhiteCube();
2130                 R_BuildNormalizationCube();
2131         }
2132         r_texture_fogattenuation = NULL;
2133         //r_texture_fogintensity = NULL;
2134         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2135         memset(&r_waterstate, 0, sizeof(r_waterstate));
2136         memset(r_glsl_permutations, 0, sizeof(r_glsl_permutations));
2137         memset(&r_svbsp, 0, sizeof (r_svbsp));
2138
2139         r_refdef.fogmasktable_density = 0;
2140 }
2141
2142 void gl_main_shutdown(void)
2143 {
2144         memset(r_qwskincache, 0, sizeof(r_qwskincache));
2145         memset(r_qwskincache_skinframe, 0, sizeof(r_qwskincache_skinframe));
2146
2147         // clear out the r_skinframe state
2148         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2149         memset(&r_skinframe, 0, sizeof(r_skinframe));
2150
2151         if (r_svbsp.nodes)
2152                 Mem_Free(r_svbsp.nodes);
2153         memset(&r_svbsp, 0, sizeof (r_svbsp));
2154         R_FreeTexturePool(&r_main_texturepool);
2155         r_texture_blanknormalmap = NULL;
2156         r_texture_white = NULL;
2157         r_texture_grey128 = NULL;
2158         r_texture_black = NULL;
2159         r_texture_whitecube = NULL;
2160         r_texture_normalizationcube = NULL;
2161         r_texture_fogattenuation = NULL;
2162         //r_texture_fogintensity = NULL;
2163         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2164         memset(&r_waterstate, 0, sizeof(r_waterstate));
2165         R_GLSL_Restart_f();
2166 }
2167
2168 extern void CL_ParseEntityLump(char *entitystring);
2169 void gl_main_newmap(void)
2170 {
2171         // FIXME: move this code to client
2172         int l;
2173         char *entities, entname[MAX_QPATH];
2174         if (cl.worldmodel)
2175         {
2176                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2177                 l = (int)strlen(entname) - 4;
2178                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2179                 {
2180                         memcpy(entname + l, ".ent", 5);
2181                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2182                         {
2183                                 CL_ParseEntityLump(entities);
2184                                 Mem_Free(entities);
2185                                 return;
2186                         }
2187                 }
2188                 if (cl.worldmodel->brush.entities)
2189                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
2190         }
2191 }
2192
2193 void GL_Main_Init(void)
2194 {
2195         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
2196
2197         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
2198         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
2199         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
2200         if (gamemode == GAME_NEHAHRA)
2201         {
2202                 Cvar_RegisterVariable (&gl_fogenable);
2203                 Cvar_RegisterVariable (&gl_fogdensity);
2204                 Cvar_RegisterVariable (&gl_fogred);
2205                 Cvar_RegisterVariable (&gl_foggreen);
2206                 Cvar_RegisterVariable (&gl_fogblue);
2207                 Cvar_RegisterVariable (&gl_fogstart);
2208                 Cvar_RegisterVariable (&gl_fogend);
2209                 Cvar_RegisterVariable (&gl_skyclip);
2210         }
2211         Cvar_RegisterVariable(&r_depthfirst);
2212         Cvar_RegisterVariable(&r_nearclip);
2213         Cvar_RegisterVariable(&r_showbboxes);
2214         Cvar_RegisterVariable(&r_showsurfaces);
2215         Cvar_RegisterVariable(&r_showtris);
2216         Cvar_RegisterVariable(&r_shownormals);
2217         Cvar_RegisterVariable(&r_showlighting);
2218         Cvar_RegisterVariable(&r_showshadowvolumes);
2219         Cvar_RegisterVariable(&r_showcollisionbrushes);
2220         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
2221         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
2222         Cvar_RegisterVariable(&r_showdisabledepthtest);
2223         Cvar_RegisterVariable(&r_drawportals);
2224         Cvar_RegisterVariable(&r_drawentities);
2225         Cvar_RegisterVariable(&r_cullentities_trace);
2226         Cvar_RegisterVariable(&r_cullentities_trace_samples);
2227         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
2228         Cvar_RegisterVariable(&r_cullentities_trace_delay);
2229         Cvar_RegisterVariable(&r_drawviewmodel);
2230         Cvar_RegisterVariable(&r_speeds);
2231         Cvar_RegisterVariable(&r_fullbrights);
2232         Cvar_RegisterVariable(&r_wateralpha);
2233         Cvar_RegisterVariable(&r_dynamic);
2234         Cvar_RegisterVariable(&r_fullbright);
2235         Cvar_RegisterVariable(&r_shadows);
2236         Cvar_RegisterVariable(&r_shadows_throwdistance);
2237         Cvar_RegisterVariable(&r_q1bsp_skymasking);
2238         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
2239         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
2240         Cvar_RegisterVariable(&r_fog_exp2);
2241         Cvar_RegisterVariable(&r_textureunits);
2242         Cvar_RegisterVariable(&r_glsl);
2243         Cvar_RegisterVariable(&r_glsl_contrastboost);
2244         Cvar_RegisterVariable(&r_glsl_deluxemapping);
2245         Cvar_RegisterVariable(&r_glsl_offsetmapping);
2246         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
2247         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
2248         Cvar_RegisterVariable(&r_glsl_postprocess);
2249         Cvar_RegisterVariable(&r_glsl_postprocess_contrastboost);
2250         Cvar_RegisterVariable(&r_glsl_usegeneric);
2251         Cvar_RegisterVariable(&r_water);
2252         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
2253         Cvar_RegisterVariable(&r_water_clippingplanebias);
2254         Cvar_RegisterVariable(&r_water_refractdistort);
2255         Cvar_RegisterVariable(&r_water_reflectdistort);
2256         Cvar_RegisterVariable(&r_lerpsprites);
2257         Cvar_RegisterVariable(&r_lerpmodels);
2258         Cvar_RegisterVariable(&r_lerplightstyles);
2259         Cvar_RegisterVariable(&r_waterscroll);
2260         Cvar_RegisterVariable(&r_bloom);
2261         Cvar_RegisterVariable(&r_bloom_colorscale);
2262         Cvar_RegisterVariable(&r_bloom_brighten);
2263         Cvar_RegisterVariable(&r_bloom_blur);
2264         Cvar_RegisterVariable(&r_bloom_resolution);
2265         Cvar_RegisterVariable(&r_bloom_colorexponent);
2266         Cvar_RegisterVariable(&r_bloom_colorsubtract);
2267         Cvar_RegisterVariable(&r_hdr);
2268         Cvar_RegisterVariable(&r_hdr_scenebrightness);
2269         Cvar_RegisterVariable(&r_hdr_glowintensity);
2270         Cvar_RegisterVariable(&r_hdr_range);
2271         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
2272         Cvar_RegisterVariable(&developer_texturelogging);
2273         Cvar_RegisterVariable(&gl_lightmaps);
2274         Cvar_RegisterVariable(&r_test);
2275         Cvar_RegisterVariable(&r_batchmode);
2276         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
2277                 Cvar_SetValue("r_fullbrights", 0);
2278         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
2279
2280         Cvar_RegisterVariable(&r_track_sprites);
2281         Cvar_RegisterVariable(&r_track_sprites_flags);
2282         Cvar_RegisterVariable(&r_track_sprites_scalew);
2283         Cvar_RegisterVariable(&r_track_sprites_scaleh);
2284 }
2285
2286 extern void R_Textures_Init(void);
2287 extern void GL_Draw_Init(void);
2288 extern void GL_Main_Init(void);
2289 extern void R_Shadow_Init(void);
2290 extern void R_Sky_Init(void);
2291 extern void GL_Surf_Init(void);
2292 extern void R_Particles_Init(void);
2293 extern void R_Explosion_Init(void);
2294 extern void gl_backend_init(void);
2295 extern void Sbar_Init(void);
2296 extern void R_LightningBeams_Init(void);
2297 extern void Mod_RenderInit(void);
2298
2299 void Render_Init(void)
2300 {
2301         gl_backend_init();
2302         R_Textures_Init();
2303         GL_Main_Init();
2304         GL_Draw_Init();
2305         R_Shadow_Init();
2306         R_Sky_Init();
2307         GL_Surf_Init();
2308         Sbar_Init();
2309         R_Particles_Init();
2310         R_Explosion_Init();
2311         R_LightningBeams_Init();
2312         Mod_RenderInit();
2313 }
2314
2315 /*
2316 ===============
2317 GL_Init
2318 ===============
2319 */
2320 extern char *ENGINE_EXTENSIONS;
2321 void GL_Init (void)
2322 {
2323         VID_CheckExtensions();
2324
2325         // LordHavoc: report supported extensions
2326         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
2327
2328         // clear to black (loading plaque will be seen over this)
2329         CHECKGLERROR
2330         qglClearColor(0,0,0,1);CHECKGLERROR
2331         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
2332 }
2333
2334 int R_CullBox(const vec3_t mins, const vec3_t maxs)
2335 {
2336         int i;
2337         mplane_t *p;
2338         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2339         {
2340                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
2341                 if (i == 4)
2342                         continue;
2343                 p = r_refdef.view.frustum + i;
2344                 switch(p->signbits)
2345                 {
2346                 default:
2347                 case 0:
2348                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2349                                 return true;
2350                         break;
2351                 case 1:
2352                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2353                                 return true;
2354                         break;
2355                 case 2:
2356                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2357                                 return true;
2358                         break;
2359                 case 3:
2360                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2361                                 return true;
2362                         break;
2363                 case 4:
2364                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2365                                 return true;
2366                         break;
2367                 case 5:
2368                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2369                                 return true;
2370                         break;
2371                 case 6:
2372                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2373                                 return true;
2374                         break;
2375                 case 7:
2376                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2377                                 return true;
2378                         break;
2379                 }
2380         }
2381         return false;
2382 }
2383
2384 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
2385 {
2386         int i;
2387         const mplane_t *p;
2388         for (i = 0;i < numplanes;i++)
2389         {
2390                 p = planes + i;
2391                 switch(p->signbits)
2392                 {
2393                 default:
2394                 case 0:
2395                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2396                                 return true;
2397                         break;
2398                 case 1:
2399                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
2400                                 return true;
2401                         break;
2402                 case 2:
2403                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2404                                 return true;
2405                         break;
2406                 case 3:
2407                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
2408                                 return true;
2409                         break;
2410                 case 4:
2411                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2412                                 return true;
2413                         break;
2414                 case 5:
2415                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
2416                                 return true;
2417                         break;
2418                 case 6:
2419                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2420                                 return true;
2421                         break;
2422                 case 7:
2423                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
2424                                 return true;
2425                         break;
2426                 }
2427         }
2428         return false;
2429 }
2430
2431 //==================================================================================
2432
2433 static void R_View_UpdateEntityVisible (void)
2434 {
2435         int i, renderimask;
2436         entity_render_t *ent;
2437
2438         if (!r_drawentities.integer)
2439                 return;
2440
2441         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
2442         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
2443         {
2444                 // worldmodel can check visibility
2445                 for (i = 0;i < r_refdef.scene.numentities;i++)
2446                 {
2447                         ent = r_refdef.scene.entities[i];
2448                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs));
2449
2450                 }
2451                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
2452                 {
2453                         for (i = 0;i < r_refdef.scene.numentities;i++)
2454                         {
2455                                 ent = r_refdef.scene.entities[i];
2456                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
2457                                 {
2458                                         if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.scene.worldmodel, r_refdef.view.origin, ent->mins, ent->maxs))
2459                                                 ent->last_trace_visibility = realtime;
2460                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
2461                                                 r_refdef.viewcache.entityvisible[i] = 0;
2462                                 }
2463                         }
2464                 }
2465         }
2466         else
2467         {
2468                 // no worldmodel or it can't check visibility
2469                 for (i = 0;i < r_refdef.scene.numentities;i++)
2470                 {
2471                         ent = r_refdef.scene.entities[i];
2472                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
2473                 }
2474         }
2475 }
2476
2477 // only used if skyrendermasked, and normally returns false
2478 int R_DrawBrushModelsSky (void)
2479 {
2480         int i, sky;
2481         entity_render_t *ent;
2482
2483         if (!r_drawentities.integer)
2484                 return false;
2485
2486         sky = false;
2487         for (i = 0;i < r_refdef.scene.numentities;i++)
2488         {
2489                 if (!r_refdef.viewcache.entityvisible[i])
2490                         continue;
2491                 ent = r_refdef.scene.entities[i];
2492                 if (!ent->model || !ent->model->DrawSky)
2493                         continue;
2494                 ent->model->DrawSky(ent);
2495                 sky = true;
2496         }
2497         return sky;
2498 }
2499
2500 static void R_DrawNoModel(entity_render_t *ent);
2501 static void R_DrawModels(void)
2502 {
2503         int i;
2504         entity_render_t *ent;
2505
2506         if (!r_drawentities.integer)
2507                 return;
2508
2509         for (i = 0;i < r_refdef.scene.numentities;i++)
2510         {
2511                 if (!r_refdef.viewcache.entityvisible[i])
2512                         continue;
2513                 ent = r_refdef.scene.entities[i];
2514                 r_refdef.stats.entities++;
2515                 if (ent->model && ent->model->Draw != NULL)
2516                         ent->model->Draw(ent);
2517                 else
2518                         R_DrawNoModel(ent);
2519         }
2520 }
2521
2522 static void R_DrawModelsDepth(void)
2523 {
2524         int i;
2525         entity_render_t *ent;
2526
2527         if (!r_drawentities.integer)
2528                 return;
2529
2530         for (i = 0;i < r_refdef.scene.numentities;i++)
2531         {
2532                 if (!r_refdef.viewcache.entityvisible[i])
2533                         continue;
2534                 ent = r_refdef.scene.entities[i];
2535                 if (ent->model && ent->model->DrawDepth != NULL)
2536                         ent->model->DrawDepth(ent);
2537         }
2538 }
2539
2540 static void R_DrawModelsDebug(void)
2541 {
2542         int i;
2543         entity_render_t *ent;
2544
2545         if (!r_drawentities.integer)
2546                 return;
2547
2548         for (i = 0;i < r_refdef.scene.numentities;i++)
2549         {
2550                 if (!r_refdef.viewcache.entityvisible[i])
2551                         continue;
2552                 ent = r_refdef.scene.entities[i];
2553                 if (ent->model && ent->model->DrawDebug != NULL)
2554                         ent->model->DrawDebug(ent);
2555         }
2556 }
2557
2558 static void R_DrawModelsAddWaterPlanes(void)
2559 {
2560         int i;
2561         entity_render_t *ent;
2562
2563         if (!r_drawentities.integer)
2564                 return;
2565
2566         for (i = 0;i < r_refdef.scene.numentities;i++)
2567         {
2568                 if (!r_refdef.viewcache.entityvisible[i])
2569                         continue;
2570                 ent = r_refdef.scene.entities[i];
2571                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
2572                         ent->model->DrawAddWaterPlanes(ent);
2573         }
2574 }
2575
2576 static void R_View_SetFrustum(void)
2577 {
2578         int i;
2579         double slopex, slopey;
2580         vec3_t forward, left, up, origin;
2581
2582         // we can't trust r_refdef.view.forward and friends in reflected scenes
2583         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
2584
2585 #if 0
2586         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
2587         r_refdef.view.frustum[0].normal[1] = 0 - 0;
2588         r_refdef.view.frustum[0].normal[2] = -1 - 0;
2589         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
2590         r_refdef.view.frustum[1].normal[1] = 0 + 0;
2591         r_refdef.view.frustum[1].normal[2] = -1 + 0;
2592         r_refdef.view.frustum[2].normal[0] = 0 - 0;
2593         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
2594         r_refdef.view.frustum[2].normal[2] = -1 - 0;
2595         r_refdef.view.frustum[3].normal[0] = 0 + 0;
2596         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
2597         r_refdef.view.frustum[3].normal[2] = -1 + 0;
2598 #endif
2599
2600 #if 0
2601         zNear = r_refdef.nearclip;
2602         nudge = 1.0 - 1.0 / (1<<23);
2603         r_refdef.view.frustum[4].normal[0] = 0 - 0;
2604         r_refdef.view.frustum[4].normal[1] = 0 - 0;
2605         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
2606         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
2607         r_refdef.view.frustum[5].normal[0] = 0 + 0;
2608         r_refdef.view.frustum[5].normal[1] = 0 + 0;
2609         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
2610         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
2611 #endif
2612
2613
2614
2615 #if 0
2616         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
2617         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
2618         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
2619         r_refdef.view.frustum[0].dist = m[15] - m[12];
2620
2621         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
2622         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
2623         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
2624         r_refdef.view.frustum[1].dist = m[15] + m[12];
2625
2626         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
2627         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
2628         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
2629         r_refdef.view.frustum[2].dist = m[15] - m[13];
2630
2631         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
2632         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
2633         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
2634         r_refdef.view.frustum[3].dist = m[15] + m[13];
2635
2636         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
2637         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
2638         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
2639         r_refdef.view.frustum[4].dist = m[15] - m[14];
2640
2641         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
2642         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
2643         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
2644         r_refdef.view.frustum[5].dist = m[15] + m[14];
2645 #endif
2646
2647         if (r_refdef.view.useperspective)
2648         {
2649                 slopex = 1.0 / r_refdef.view.frustum_x;
2650                 slopey = 1.0 / r_refdef.view.frustum_y;
2651                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
2652                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
2653                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
2654                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
2655                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2656
2657                 // Leaving those out was a mistake, those were in the old code, and they
2658                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
2659                 // I couldn't reproduce it after adding those normalizations. --blub
2660                 VectorNormalize(r_refdef.view.frustum[0].normal);
2661                 VectorNormalize(r_refdef.view.frustum[1].normal);
2662                 VectorNormalize(r_refdef.view.frustum[2].normal);
2663                 VectorNormalize(r_refdef.view.frustum[3].normal);
2664
2665                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
2666                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[0]);
2667                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left, -1024 * slopey, up, r_refdef.view.frustumcorner[1]);
2668                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[2]);
2669                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * slopex, left,  1024 * slopey, up, r_refdef.view.frustumcorner[3]);
2670
2671                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
2672                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
2673                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
2674                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
2675                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2676         }
2677         else
2678         {
2679                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
2680                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
2681                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
2682                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
2683                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
2684                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
2685                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
2686                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
2687                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
2688                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
2689         }
2690         r_refdef.view.numfrustumplanes = 5;
2691
2692         if (r_refdef.view.useclipplane)
2693         {
2694                 r_refdef.view.numfrustumplanes = 6;
2695                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
2696         }
2697
2698         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
2699                 PlaneClassify(r_refdef.view.frustum + i);
2700
2701         // LordHavoc: note to all quake engine coders, Quake had a special case
2702         // for 90 degrees which assumed a square view (wrong), so I removed it,
2703         // Quake2 has it disabled as well.
2704
2705         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
2706         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
2707         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
2708         //PlaneClassify(&frustum[0]);
2709
2710         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
2711         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
2712         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
2713         //PlaneClassify(&frustum[1]);
2714
2715         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
2716         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
2717         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
2718         //PlaneClassify(&frustum[2]);
2719
2720         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
2721         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
2722         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
2723         //PlaneClassify(&frustum[3]);
2724
2725         // nearclip plane
2726         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
2727         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
2728         //PlaneClassify(&frustum[4]);
2729 }
2730
2731 void R_View_Update(void)
2732 {
2733         R_View_SetFrustum();
2734         R_View_WorldVisibility(r_refdef.view.useclipplane);
2735         R_View_UpdateEntityVisible();
2736 }
2737
2738 void R_SetupView(qboolean allowwaterclippingplane)
2739 {
2740         if (!r_refdef.view.useperspective)
2741                 GL_SetupView_Mode_Ortho(-r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
2742         else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
2743                 GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip);
2744         else
2745                 GL_SetupView_Mode_Perspective(r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
2746
2747         GL_SetupView_Orientation_FromEntity(&r_refdef.view.matrix);
2748
2749         if (r_refdef.view.useclipplane && allowwaterclippingplane)
2750         {
2751                 // LordHavoc: couldn't figure out how to make this approach the
2752                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
2753                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
2754                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
2755                         dist = r_refdef.view.clipplane.dist;
2756                 GL_SetupView_ApplyCustomNearClipPlane(r_refdef.view.clipplane.normal[0], r_refdef.view.clipplane.normal[1], r_refdef.view.clipplane.normal[2], dist);
2757         }
2758 }
2759
2760 void R_ResetViewRendering2D(void)
2761 {
2762         DrawQ_Finish();
2763
2764         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2765         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2766         GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
2767         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2768         GL_Color(1, 1, 1, 1);
2769         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2770         GL_BlendFunc(GL_ONE, GL_ZERO);
2771         GL_AlphaTest(false);
2772         GL_ScissorTest(false);
2773         GL_DepthMask(false);
2774         GL_DepthRange(0, 1);
2775         GL_DepthTest(false);
2776         R_Mesh_Matrix(&identitymatrix);
2777         R_Mesh_ResetTextureState();
2778         GL_PolygonOffset(0, 0);
2779         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2780         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2781         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2782         qglStencilMask(~0);CHECKGLERROR
2783         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2784         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2785         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
2786         R_SetupGenericShader(true);
2787 }
2788
2789 void R_ResetViewRendering3D(void)
2790 {
2791         DrawQ_Finish();
2792
2793         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
2794         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2795         R_SetupView(true);
2796         GL_Scissor(r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
2797         GL_Color(1, 1, 1, 1);
2798         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
2799         GL_BlendFunc(GL_ONE, GL_ZERO);
2800         GL_AlphaTest(false);
2801         GL_ScissorTest(true);
2802         GL_DepthMask(true);
2803         GL_DepthRange(0, 1);
2804         GL_DepthTest(true);
2805         R_Mesh_Matrix(&identitymatrix);
2806         R_Mesh_ResetTextureState();
2807         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
2808         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
2809         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
2810         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
2811         qglStencilMask(~0);CHECKGLERROR
2812         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
2813         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
2814         GL_CullFace(r_refdef.view.cullface_back);
2815         R_SetupGenericShader(true);
2816 }
2817
2818 void R_RenderScene(qboolean addwaterplanes);
2819
2820 static void R_Water_StartFrame(void)
2821 {
2822         int i;
2823         int waterwidth, waterheight, texturewidth, textureheight;
2824         r_waterstate_waterplane_t *p;
2825
2826         // set waterwidth and waterheight to the water resolution that will be
2827         // used (often less than the screen resolution for faster rendering)
2828         waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
2829         waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
2830
2831         // calculate desired texture sizes
2832         // can't use water if the card does not support the texture size
2833         if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size)
2834                 texturewidth = textureheight = waterwidth = waterheight = 0;
2835         else if (gl_support_arb_texture_non_power_of_two)
2836         {
2837                 texturewidth = waterwidth;
2838                 textureheight = waterheight;
2839         }
2840         else
2841         {
2842                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
2843                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
2844         }
2845
2846         // allocate textures as needed
2847         if (r_waterstate.waterwidth != waterwidth || r_waterstate.waterheight != waterheight || r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
2848         {
2849                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2850                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
2851                 {
2852                         if (p->texture_refraction)
2853                                 R_FreeTexture(p->texture_refraction);
2854                         p->texture_refraction = NULL;
2855                         if (p->texture_reflection)
2856                                 R_FreeTexture(p->texture_reflection);
2857                         p->texture_reflection = NULL;
2858                 }
2859                 memset(&r_waterstate, 0, sizeof(r_waterstate));
2860                 r_waterstate.waterwidth = waterwidth;
2861                 r_waterstate.waterheight = waterheight;
2862                 r_waterstate.texturewidth = texturewidth;
2863                 r_waterstate.textureheight = textureheight;
2864         }
2865
2866         if (r_waterstate.waterwidth)
2867         {
2868                 r_waterstate.enabled = true;
2869
2870                 // set up variables that will be used in shader setup
2871                 r_waterstate.screenscale[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2872                 r_waterstate.screenscale[1] = 0.5f * (float)waterheight / (float)textureheight;
2873                 r_waterstate.screencenter[0] = 0.5f * (float)waterwidth / (float)texturewidth;
2874                 r_waterstate.screencenter[1] = 0.5f * (float)waterheight / (float)textureheight;
2875         }
2876
2877         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
2878         r_waterstate.numwaterplanes = 0;
2879 }
2880
2881 static void R_Water_AddWaterPlane(msurface_t *surface)
2882 {
2883         int triangleindex, planeindex;
2884         const int *e;
2885         vec3_t vert[3];
2886         vec3_t normal;
2887         vec3_t center;
2888         r_waterstate_waterplane_t *p;
2889         // just use the first triangle with a valid normal for any decisions
2890         VectorClear(normal);
2891         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
2892         {
2893                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
2894                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
2895                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
2896                 TriangleNormal(vert[0], vert[1], vert[2], normal);
2897                 if (VectorLength2(normal) >= 0.001)
2898                         break;
2899         }
2900
2901         // find a matching plane if there is one
2902         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2903                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
2904                         break;
2905         if (planeindex >= r_waterstate.maxwaterplanes)
2906                 return; // nothing we can do, out of planes
2907
2908         // if this triangle does not fit any known plane rendered this frame, add one
2909         if (planeindex >= r_waterstate.numwaterplanes)
2910         {
2911                 // store the new plane
2912                 r_waterstate.numwaterplanes++;
2913                 VectorCopy(normal, p->plane.normal);
2914                 VectorNormalize(p->plane.normal);
2915                 p->plane.dist = DotProduct(vert[0], p->plane.normal);
2916                 PlaneClassify(&p->plane);
2917                 // flip the plane if it does not face the viewer
2918                 if (PlaneDiff(r_refdef.view.origin, &p->plane) < 0)
2919                 {
2920                         VectorNegate(p->plane.normal, p->plane.normal);
2921                         p->plane.dist *= -1;
2922                         PlaneClassify(&p->plane);
2923                 }
2924                 // clear materialflags and pvs
2925                 p->materialflags = 0;
2926                 p->pvsvalid = false;
2927         }
2928         // merge this surface's materialflags into the waterplane
2929         p->materialflags |= surface->texture->currentframe->currentmaterialflags;
2930         // merge this surface's PVS into the waterplane
2931         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
2932         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
2933          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
2934         {
2935                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
2936                 p->pvsvalid = true;
2937         }
2938 }
2939
2940 static void R_Water_ProcessPlanes(void)
2941 {
2942         r_refdef_view_t originalview;
2943         int planeindex;
2944         r_waterstate_waterplane_t *p;
2945
2946         originalview = r_refdef.view;
2947
2948         // make sure enough textures are allocated
2949         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2950         {
2951                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2952                 {
2953                         if (!p->texture_refraction)
2954                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2955                         if (!p->texture_refraction)
2956                                 goto error;
2957                 }
2958
2959                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2960                 {
2961                         if (!p->texture_reflection)
2962                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
2963                         if (!p->texture_reflection)
2964                                 goto error;
2965                 }
2966         }
2967
2968         // render views
2969         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
2970         {
2971                 r_refdef.view.showdebug = false;
2972                 r_refdef.view.width = r_waterstate.waterwidth;
2973                 r_refdef.view.height = r_waterstate.waterheight;
2974                 r_refdef.view.useclipplane = true;
2975                 r_waterstate.renderingscene = true;
2976
2977                 // render the normal view scene and copy into texture
2978                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
2979                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
2980                 {
2981                         r_refdef.view.clipplane = p->plane;
2982                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
2983                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
2984                         PlaneClassify(&r_refdef.view.clipplane);
2985
2986                         R_RenderScene(false);
2987
2988                         // copy view into the screen texture
2989                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
2990                         GL_ActiveTexture(0);
2991                         CHECKGLERROR
2992                         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
2993                 }
2994
2995                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
2996                 {
2997                         // render reflected scene and copy into texture
2998                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
2999                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
3000                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
3001                         r_refdef.view.clipplane = p->plane;
3002                         // reverse the cullface settings for this render
3003                         r_refdef.view.cullface_front = GL_FRONT;
3004                         r_refdef.view.cullface_back = GL_BACK;
3005                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
3006                         {
3007                                 r_refdef.view.usecustompvs = true;
3008                                 if (p->pvsvalid)
3009                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3010                                 else
3011                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
3012                         }
3013
3014                         R_ResetViewRendering3D();
3015                         R_ClearScreen(r_refdef.fogenabled);
3016                         if (r_timereport_active)
3017                                 R_TimeReport("viewclear");
3018
3019                         R_RenderScene(false);
3020
3021                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
3022                         GL_ActiveTexture(0);
3023                         CHECKGLERROR
3024                         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3025
3026                         R_ResetViewRendering3D();
3027                         R_ClearScreen(r_refdef.fogenabled);
3028                         if (r_timereport_active)
3029                                 R_TimeReport("viewclear");
3030                 }
3031
3032                 r_refdef.view = originalview;
3033                 r_refdef.view.clear = true;
3034                 r_waterstate.renderingscene = false;
3035         }
3036         return;
3037 error:
3038         r_refdef.view = originalview;
3039         r_waterstate.renderingscene = false;
3040         Cvar_SetValueQuick(&r_water, 0);
3041         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
3042         return;
3043 }
3044
3045 void R_Bloom_StartFrame(void)
3046 {
3047         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
3048
3049         // set bloomwidth and bloomheight to the bloom resolution that will be
3050         // used (often less than the screen resolution for faster rendering)
3051         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
3052         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
3053         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
3054         r_bloomstate.bloomwidth = min(r_bloomstate.bloomwidth, gl_max_texture_size);
3055         r_bloomstate.bloomheight = min(r_bloomstate.bloomheight, gl_max_texture_size);
3056
3057         // calculate desired texture sizes
3058         if (gl_support_arb_texture_non_power_of_two)
3059         {
3060                 screentexturewidth = r_refdef.view.width;
3061                 screentextureheight = r_refdef.view.height;
3062                 bloomtexturewidth = r_bloomstate.bloomwidth;
3063                 bloomtextureheight = r_bloomstate.bloomheight;
3064         }
3065         else
3066         {
3067                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
3068                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
3069                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
3070                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
3071         }
3072
3073         if ((r_hdr.integer || r_bloom.integer) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > gl_max_texture_size || r_refdef.view.height > gl_max_texture_size))
3074         {
3075                 Cvar_SetValueQuick(&r_hdr, 0);
3076                 Cvar_SetValueQuick(&r_bloom, 0);
3077         }
3078
3079         if (!(r_glsl.integer && r_glsl_postprocess.integer) && !r_bloom.integer)
3080                 screentexturewidth = screentextureheight = 0;
3081         if (!r_hdr.integer && !r_bloom.integer)
3082                 bloomtexturewidth = bloomtextureheight = 0;
3083
3084         // allocate textures as needed
3085         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
3086         {
3087                 if (r_bloomstate.texture_screen)
3088                         R_FreeTexture(r_bloomstate.texture_screen);
3089                 r_bloomstate.texture_screen = NULL;
3090                 r_bloomstate.screentexturewidth = screentexturewidth;
3091                 r_bloomstate.screentextureheight = screentextureheight;
3092                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
3093                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3094         }
3095         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
3096         {
3097                 if (r_bloomstate.texture_bloom)
3098                         R_FreeTexture(r_bloomstate.texture_bloom);
3099                 r_bloomstate.texture_bloom = NULL;
3100                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
3101                 r_bloomstate.bloomtextureheight = bloomtextureheight;
3102                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
3103                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALWAYSPRECACHE, NULL);
3104         }
3105
3106         // set up a texcoord array for the full resolution screen image
3107         // (we have to keep this around to copy back during final render)
3108         r_bloomstate.screentexcoord2f[0] = 0;
3109         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3110         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3111         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
3112         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
3113         r_bloomstate.screentexcoord2f[5] = 0;
3114         r_bloomstate.screentexcoord2f[6] = 0;
3115         r_bloomstate.screentexcoord2f[7] = 0;
3116
3117         // set up a texcoord array for the reduced resolution bloom image
3118         // (which will be additive blended over the screen image)
3119         r_bloomstate.bloomtexcoord2f[0] = 0;
3120         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3121         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3122         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3123         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
3124         r_bloomstate.bloomtexcoord2f[5] = 0;
3125         r_bloomstate.bloomtexcoord2f[6] = 0;
3126         r_bloomstate.bloomtexcoord2f[7] = 0;
3127
3128         if (r_hdr.integer || r_bloom.integer)
3129         {
3130                 r_bloomstate.enabled = true;
3131                 r_bloomstate.hdr = r_hdr.integer != 0;
3132         }
3133 }
3134
3135 void R_Bloom_CopyBloomTexture(float colorscale)
3136 {
3137         r_refdef.stats.bloom++;
3138
3139         // scale down screen texture to the bloom texture size
3140         CHECKGLERROR
3141         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3142         GL_BlendFunc(GL_ONE, GL_ZERO);
3143         GL_Color(colorscale, colorscale, colorscale, 1);
3144         // TODO: optimize with multitexture or GLSL
3145         R_SetupGenericShader(true);
3146         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3147         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3148         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3149         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3150
3151         // we now have a bloom image in the framebuffer
3152         // copy it into the bloom image texture for later processing
3153         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3154         GL_ActiveTexture(0);
3155         CHECKGLERROR
3156         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3157         r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3158 }
3159
3160 void R_Bloom_CopyHDRTexture(void)
3161 {
3162         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3163         GL_ActiveTexture(0);
3164         CHECKGLERROR
3165         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3166         r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3167 }
3168
3169 void R_Bloom_MakeTexture(void)
3170 {
3171         int x, range, dir;
3172         float xoffset, yoffset, r, brighten;
3173
3174         r_refdef.stats.bloom++;
3175
3176         R_ResetViewRendering2D();
3177         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3178         R_Mesh_ColorPointer(NULL, 0, 0);
3179         R_SetupGenericShader(true);
3180
3181         // we have a bloom image in the framebuffer
3182         CHECKGLERROR
3183         qglViewport(r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3184
3185         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
3186         {
3187                 x *= 2;
3188                 r = bound(0, r_bloom_colorexponent.value / x, 1);
3189                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
3190                 GL_Color(r, r, r, 1);
3191                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3192                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3193                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3194                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3195
3196                 // copy the vertically blurred bloom view to a texture
3197                 GL_ActiveTexture(0);
3198                 CHECKGLERROR
3199                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3200                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3201         }
3202
3203         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
3204         brighten = r_bloom_brighten.value;
3205         if (r_hdr.integer)
3206                 brighten *= r_hdr_range.value;
3207         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3208         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
3209
3210         for (dir = 0;dir < 2;dir++)
3211         {
3212                 // blend on at multiple vertical offsets to achieve a vertical blur
3213                 // TODO: do offset blends using GLSL
3214                 GL_BlendFunc(GL_ONE, GL_ZERO);
3215                 for (x = -range;x <= range;x++)
3216                 {
3217                         if (!dir){xoffset = 0;yoffset = x;}
3218                         else {xoffset = x;yoffset = 0;}
3219                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
3220                         yoffset /= (float)r_bloomstate.bloomtextureheight;
3221                         // compute a texcoord array with the specified x and y offset
3222                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
3223                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3224                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3225                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
3226                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
3227                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
3228                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
3229                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
3230                         // this r value looks like a 'dot' particle, fading sharply to
3231                         // black at the edges
3232                         // (probably not realistic but looks good enough)
3233                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
3234                         //r = (dir ? 1.0f : brighten)/(range*2+1);
3235                         r = (dir ? 1.0f : brighten)/(range*2+1)*(1 - x*x/(float)(range*range));
3236                         GL_Color(r, r, r, 1);
3237                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3238                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3239                         GL_BlendFunc(GL_ONE, GL_ONE);
3240                 }
3241
3242                 // copy the vertically blurred bloom view to a texture
3243                 GL_ActiveTexture(0);
3244                 CHECKGLERROR
3245                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3246                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3247         }
3248
3249         // apply subtract last
3250         // (just like it would be in a GLSL shader)
3251         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
3252         {
3253                 GL_BlendFunc(GL_ONE, GL_ZERO);
3254                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3255                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3256                 GL_Color(1, 1, 1, 1);
3257                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3258                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3259
3260                 GL_BlendFunc(GL_ONE, GL_ONE);
3261                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
3262                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
3263                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3264                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
3265                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3266                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3267                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
3268
3269                 // copy the darkened bloom view to a texture
3270                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3271                 GL_ActiveTexture(0);
3272                 CHECKGLERROR
3273                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_bloomstate.bloomheight), r_bloomstate.bloomwidth, r_bloomstate.bloomheight);CHECKGLERROR
3274                 r_refdef.stats.bloom_copypixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
3275         }
3276 }
3277
3278 void R_HDR_RenderBloomTexture(void)
3279 {
3280         int oldwidth, oldheight;
3281         float oldcolorscale;
3282
3283         oldcolorscale = r_refdef.view.colorscale;
3284         oldwidth = r_refdef.view.width;
3285         oldheight = r_refdef.view.height;
3286         r_refdef.view.width = r_bloomstate.bloomwidth;
3287         r_refdef.view.height = r_bloomstate.bloomheight;
3288
3289         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
3290         // TODO: add exposure compensation features
3291         // TODO: add fp16 framebuffer support
3292
3293         r_refdef.view.showdebug = false;
3294         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
3295
3296         R_ClearScreen(r_refdef.fogenabled);
3297         if (r_timereport_active)
3298                 R_TimeReport("HDRclear");
3299
3300         r_waterstate.numwaterplanes = 0;
3301         R_RenderScene(r_waterstate.enabled);
3302         r_refdef.view.showdebug = true;
3303
3304         R_ResetViewRendering2D();
3305
3306         R_Bloom_CopyHDRTexture();
3307         R_Bloom_MakeTexture();
3308
3309         // restore the view settings
3310         r_refdef.view.width = oldwidth;
3311         r_refdef.view.height = oldheight;
3312         r_refdef.view.colorscale = oldcolorscale;
3313
3314         R_ResetViewRendering3D();
3315
3316         R_ClearScreen(r_refdef.fogenabled);
3317         if (r_timereport_active)
3318                 R_TimeReport("viewclear");
3319 }
3320
3321 static void R_BlendView(void)
3322 {
3323         if (r_bloomstate.texture_screen)
3324         {
3325                 // copy view into the screen texture
3326                 R_ResetViewRendering2D();
3327                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3328                 R_Mesh_ColorPointer(NULL, 0, 0);
3329                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3330                 GL_ActiveTexture(0);CHECKGLERROR
3331                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.view.x, vid.height - (r_refdef.view.y + r_refdef.view.height), r_refdef.view.width, r_refdef.view.height);CHECKGLERROR
3332                 r_refdef.stats.bloom_copypixels += r_refdef.view.width * r_refdef.view.height;
3333         }
3334
3335         if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
3336         {
3337                 unsigned int permutation = (r_bloomstate.texture_bloom ? SHADERPERMUTATION_GLOW : 0) | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0) | (r_glsl_postprocess_contrastboost.value != 1 ? SHADERPERMUTATION_CONTRASTBOOST : 0);
3338
3339                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
3340                 {
3341                         // render simple bloom effect
3342                         // copy the screen and shrink it and darken it for the bloom process
3343                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3344                         // make the bloom texture
3345                         R_Bloom_MakeTexture();
3346                 }
3347
3348                 R_ResetViewRendering2D();
3349                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3350                 R_Mesh_ColorPointer(NULL, 0, 0);
3351                 GL_Color(1, 1, 1, 1);
3352                 GL_BlendFunc(GL_ONE, GL_ZERO);
3353                 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
3354                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3355                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3356                 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
3357                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3358                 if (r_glsl_permutation->loc_TintColor >= 0)
3359                         qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3360                 if (r_glsl_permutation->loc_ContrastBoostCoeff >= 0)
3361                         qglUniform1fARB(r_glsl_permutation->loc_ContrastBoostCoeff, r_glsl_postprocess_contrastboost.value - 1);
3362                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3363                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3364                 return;
3365         }
3366
3367
3368
3369         if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
3370         {
3371                 // render high dynamic range bloom effect
3372                 // the bloom texture was made earlier this render, so we just need to
3373                 // blend it onto the screen...
3374                 R_ResetViewRendering2D();
3375                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3376                 R_Mesh_ColorPointer(NULL, 0, 0);
3377                 R_SetupGenericShader(true);
3378                 GL_Color(1, 1, 1, 1);
3379                 GL_BlendFunc(GL_ONE, GL_ONE);
3380                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3381                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3382                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3383                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3384         }
3385         else if (r_bloomstate.texture_bloom)
3386         {
3387                 // render simple bloom effect
3388                 // copy the screen and shrink it and darken it for the bloom process
3389                 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
3390                 // make the bloom texture
3391                 R_Bloom_MakeTexture();
3392                 // put the original screen image back in place and blend the bloom
3393                 // texture on it
3394                 R_ResetViewRendering2D();
3395                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3396                 R_Mesh_ColorPointer(NULL, 0, 0);
3397                 GL_Color(1, 1, 1, 1);
3398                 GL_BlendFunc(GL_ONE, GL_ZERO);
3399                 // do both in one pass if possible
3400                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
3401                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
3402                 if (r_textureunits.integer >= 2 && gl_combine.integer)
3403                 {
3404                         R_SetupGenericTwoTextureShader(GL_ADD);
3405                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
3406                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
3407                 }
3408                 else
3409                 {
3410                         R_SetupGenericShader(true);
3411                         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3412                         r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3413                         // now blend on the bloom texture
3414                         GL_BlendFunc(GL_ONE, GL_ONE);
3415                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
3416                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
3417                 }
3418                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3419                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
3420         }
3421         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
3422         {
3423                 // apply a color tint to the whole view
3424                 R_ResetViewRendering2D();
3425                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
3426                 R_Mesh_ColorPointer(NULL, 0, 0);
3427                 R_SetupGenericShader(false);
3428                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3429                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
3430                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
3431         }
3432 }
3433
3434 void R_RenderScene(qboolean addwaterplanes);
3435
3436 matrix4x4_t r_waterscrollmatrix;
3437
3438 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
3439 {
3440         if (r_refdef.fog_density)
3441         {
3442                 r_refdef.fogcolor[0] = r_refdef.fog_red;
3443                 r_refdef.fogcolor[1] = r_refdef.fog_green;
3444                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
3445
3446                 {
3447                         vec3_t fogvec;
3448                         VectorCopy(r_refdef.fogcolor, fogvec);
3449                         if(r_glsl.integer && (r_glsl_contrastboost.value > 1 || r_glsl_contrastboost.value < 0)) // need to support contrast boost
3450                         {
3451                                 //   color.rgb /= ((ContrastBoost - 1) * color.rgb + 1);
3452                                 fogvec[0] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[0] + 1);
3453                                 fogvec[1] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[1] + 1);
3454                                 fogvec[2] *= r_glsl_contrastboost.value / ((r_glsl_contrastboost.value - 1) * fogvec[2] + 1);
3455                         }
3456                         //   color.rgb *= ContrastBoost * SceneBrightness;
3457                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
3458                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
3459                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
3460                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
3461                 }
3462         }
3463 }
3464
3465 void R_UpdateVariables(void)
3466 {
3467         R_Textures_Frame();
3468
3469         r_refdef.farclip = 4096;
3470         if (r_refdef.scene.worldmodel)
3471                 r_refdef.farclip += VectorDistance(r_refdef.scene.worldmodel->normalmins, r_refdef.scene.worldmodel->normalmaxs);
3472         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
3473
3474         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
3475                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
3476         r_refdef.polygonfactor = 0;
3477         r_refdef.polygonoffset = 0;
3478         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3479         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
3480
3481         r_refdef.rtworld = r_shadow_realtime_world.integer;
3482         r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
3483         r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
3484         r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
3485         r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
3486         if (r_showsurfaces.integer)
3487         {
3488                 r_refdef.rtworld = false;
3489                 r_refdef.rtworldshadows = false;
3490                 r_refdef.rtdlight = false;
3491                 r_refdef.rtdlightshadows = false;
3492                 r_refdef.lightmapintensity = 0;
3493         }
3494
3495         if (gamemode == GAME_NEHAHRA)
3496         {
3497                 if (gl_fogenable.integer)
3498                 {
3499                         r_refdef.oldgl_fogenable = true;
3500                         r_refdef.fog_density = gl_fogdensity.value;
3501                         r_refdef.fog_red = gl_fogred.value;
3502                         r_refdef.fog_green = gl_foggreen.value;
3503                         r_refdef.fog_blue = gl_fogblue.value;
3504                         r_refdef.fog_alpha = 1;
3505                         r_refdef.fog_start = 0;
3506                         r_refdef.fog_end = gl_skyclip.value;
3507                 }
3508                 else if (r_refdef.oldgl_fogenable)
3509                 {
3510                         r_refdef.oldgl_fogenable = false;
3511                         r_refdef.fog_density = 0;
3512                         r_refdef.fog_red = 0;
3513                         r_refdef.fog_green = 0;
3514                         r_refdef.fog_blue = 0;
3515                         r_refdef.fog_alpha = 0;
3516                         r_refdef.fog_start = 0;
3517                         r_refdef.fog_end = 0;
3518                 }
3519         }
3520
3521         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
3522         r_refdef.fog_start = max(0, r_refdef.fog_start);
3523         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
3524
3525         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
3526
3527         if (r_refdef.fog_density)
3528         {
3529                 r_refdef.fogenabled = true;
3530                 // this is the point where the fog reaches 0.9986 alpha, which we
3531                 // consider a good enough cutoff point for the texture
3532                 // (0.9986 * 256 == 255.6)
3533                 if (r_fog_exp2.integer)
3534                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
3535                 else
3536                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
3537                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
3538                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
3539                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
3540                 // fog color was already set
3541                 // update the fog texture
3542                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
3543                         R_BuildFogTexture();
3544         }
3545         else
3546                 r_refdef.fogenabled = false;
3547 }
3548
3549 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
3550 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
3551 /*
3552 ================
3553 R_SelectScene
3554 ================
3555 */
3556 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
3557         if( scenetype != r_currentscenetype ) {
3558                 // store the old scenetype
3559                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
3560                 r_currentscenetype = scenetype;
3561                 // move in the new scene
3562                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
3563         }
3564 }
3565
3566 /*
3567 ================
3568 R_GetScenePointer
3569 ================
3570 */
3571 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
3572 {
3573         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
3574         if( scenetype == r_currentscenetype ) {
3575                 return &r_refdef.scene;
3576         } else {
3577                 return &r_scenes_store[ scenetype ];
3578         }
3579 }
3580
3581 /*
3582 ================
3583 R_RenderView
3584 ================
3585 */
3586 void R_RenderView(void)
3587 {
3588         if (!r_refdef.scene.entities/* || !r_refdef.scene.worldmodel*/)
3589                 return; //Host_Error ("R_RenderView: NULL worldmodel");
3590
3591         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
3592
3593         // break apart the view matrix into vectors for various purposes
3594         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
3595         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
3596         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
3597         VectorNegate(r_refdef.view.left, r_refdef.view.right);
3598         // make an inverted copy of the view matrix for tracking sprites
3599         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
3600
3601         R_Shadow_UpdateWorldLightSelection();
3602
3603         R_Bloom_StartFrame();
3604         R_Water_StartFrame();
3605
3606         CHECKGLERROR
3607         if (r_timereport_active)
3608                 R_TimeReport("viewsetup");
3609
3610         R_ResetViewRendering3D();
3611
3612         if (r_refdef.view.clear || r_refdef.fogenabled)
3613         {
3614                 R_ClearScreen(r_refdef.fogenabled);
3615                 if (r_timereport_active)
3616                         R_TimeReport("viewclear");
3617         }
3618         r_refdef.view.clear = true;
3619
3620         r_refdef.view.showdebug = true;
3621
3622         // this produces a bloom texture to be used in R_BlendView() later
3623         if (r_hdr.integer)
3624                 R_HDR_RenderBloomTexture();
3625
3626         r_waterstate.numwaterplanes = 0;
3627         R_RenderScene(r_waterstate.enabled);
3628
3629         R_BlendView();
3630         if (r_timereport_active)
3631                 R_TimeReport("blendview");
3632
3633         GL_Scissor(0, 0, vid.width, vid.height);
3634         GL_ScissorTest(false);
3635         CHECKGLERROR
3636 }
3637
3638 extern void R_DrawLightningBeams (void);
3639 extern void VM_CL_AddPolygonsToMeshQueue (void);
3640 extern void R_DrawPortals (void);
3641 extern cvar_t cl_locs_show;
3642 static void R_DrawLocs(void);
3643 static void R_DrawEntityBBoxes(void);
3644 void R_RenderScene(qboolean addwaterplanes)
3645 {
3646         r_refdef.stats.renders++;
3647
3648         R_UpdateFogColor();
3649
3650         if (addwaterplanes)
3651         {
3652                 R_ResetViewRendering3D();
3653
3654                 R_View_Update();
3655                 if (r_timereport_active)
3656                         R_TimeReport("watervis");
3657
3658                 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
3659                 {
3660                         r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
3661                         if (r_timereport_active)
3662                                 R_TimeReport("waterworld");
3663                 }
3664
3665                 // don't let sound skip if going slow
3666                 if (r_refdef.scene.extraupdate)
3667                         S_ExtraUpdate ();
3668
3669                 R_DrawModelsAddWaterPlanes();
3670                 if (r_timereport_active)
3671                         R_TimeReport("watermodels");
3672
3673                 R_Water_ProcessPlanes();
3674                 if (r_timereport_active)
3675                         R_TimeReport("waterscenes");
3676         }
3677
3678         R_ResetViewRendering3D();
3679
3680         // don't let sound skip if going slow
3681         if (r_refdef.scene.extraupdate)
3682                 S_ExtraUpdate ();
3683
3684         R_MeshQueue_BeginScene();
3685
3686         R_SkyStartFrame();
3687
3688         R_View_Update();
3689         if (r_timereport_active)
3690                 R_TimeReport("visibility");
3691
3692         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
3693
3694         if (cl.csqc_vidvars.drawworld)
3695         {
3696                 // don't let sound skip if going slow
3697                 if (r_refdef.scene.extraupdate)
3698                         S_ExtraUpdate ();
3699
3700                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
3701                 {
3702                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
3703                         if (r_timereport_active)
3704                                 R_TimeReport("worldsky");
3705                 }
3706
3707                 if (R_DrawBrushModelsSky() && r_timereport_active)
3708                         R_TimeReport("bmodelsky");
3709         }
3710
3711         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
3712         {
3713                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
3714                 if (r_timereport_active)
3715                         R_TimeReport("worlddepth");
3716         }
3717         if (r_depthfirst.integer >= 2)
3718         {
3719                 R_DrawModelsDepth();
3720                 if (r_timereport_active)
3721                         R_TimeReport("modeldepth");
3722         }
3723
3724         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
3725         {
3726                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
3727                 if (r_timereport_active)
3728                         R_TimeReport("world");
3729         }
3730
3731         // don't let sound skip if going slow
3732         if (r_refdef.scene.extraupdate)
3733                 S_ExtraUpdate ();
3734
3735         R_DrawModels();
3736         if (r_timereport_active)
3737                 R_TimeReport("models");
3738
3739         // don't let sound skip if going slow
3740         if (r_refdef.scene.extraupdate)
3741                 S_ExtraUpdate ();
3742
3743         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
3744         {
3745                 R_DrawModelShadows();
3746
3747                 R_ResetViewRendering3D();
3748
3749                 // don't let sound skip if going slow
3750                 if (r_refdef.scene.extraupdate)
3751                         S_ExtraUpdate ();
3752         }
3753
3754         R_ShadowVolumeLighting(false);
3755         if (r_timereport_active)
3756                 R_TimeReport("rtlights");
3757
3758         // don't let sound skip if going slow
3759         if (r_refdef.scene.extraupdate)
3760                 S_ExtraUpdate ();
3761
3762         if (cl.csqc_vidvars.drawworld)
3763         {
3764                 R_DrawLightningBeams();
3765                 if (r_timereport_active)
3766                         R_TimeReport("lightning");
3767
3768                 R_DrawDecals();
3769                 if (r_timereport_active)
3770                         R_TimeReport("decals");
3771
3772                 R_DrawParticles();
3773                 if (r_timereport_active)
3774                         R_TimeReport("particles");
3775
3776                 R_DrawExplosions();
3777                 if (r_timereport_active)
3778                         R_TimeReport("explosions");
3779         }
3780
3781         R_SetupGenericShader(true);
3782         VM_CL_AddPolygonsToMeshQueue();
3783
3784         if (r_refdef.view.showdebug)
3785         {
3786                 if (cl_locs_show.integer)
3787                 {
3788                         R_DrawLocs();
3789                         if (r_timereport_active)
3790                                 R_TimeReport("showlocs");
3791                 }
3792
3793                 if (r_drawportals.integer)
3794                 {
3795                         R_DrawPortals();
3796                         if (r_timereport_active)
3797                                 R_TimeReport("portals");
3798                 }
3799
3800                 if (r_showbboxes.value > 0)
3801                 {
3802                         R_DrawEntityBBoxes();
3803                         if (r_timereport_active)
3804                                 R_TimeReport("bboxes");
3805                 }
3806         }
3807
3808         R_SetupGenericShader(true);
3809         R_MeshQueue_RenderTransparent();
3810         if (r_timereport_active)
3811                 R_TimeReport("drawtrans");
3812
3813         R_SetupGenericShader(true);
3814
3815         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value > 0 || r_showcollisionbrushes.value > 0))
3816         {
3817                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
3818                 if (r_timereport_active)
3819                         R_TimeReport("worlddebug");
3820                 R_DrawModelsDebug();
3821                 if (r_timereport_active)
3822                         R_TimeReport("modeldebug");
3823         }
3824
3825         R_SetupGenericShader(true);
3826
3827         if (cl.csqc_vidvars.drawworld)
3828         {
3829                 R_DrawCoronas();
3830                 if (r_timereport_active)
3831                         R_TimeReport("coronas");
3832         }
3833
3834         // don't let sound skip if going slow
3835         if (r_refdef.scene.extraupdate)
3836                 S_ExtraUpdate ();
3837
3838         R_ResetViewRendering2D();
3839 }
3840
3841 static const int bboxelements[36] =
3842 {
3843         5, 1, 3, 5, 3, 7,
3844         6, 2, 0, 6, 0, 4,
3845         7, 3, 2, 7, 2, 6,
3846         4, 0, 1, 4, 1, 5,
3847         4, 5, 7, 4, 7, 6,
3848         1, 0, 2, 1, 2, 3,
3849 };
3850
3851 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
3852 {
3853         int i;
3854         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
3855         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3856         GL_DepthMask(false);
3857         GL_DepthRange(0, 1);
3858         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3859         R_Mesh_Matrix(&identitymatrix);
3860         R_Mesh_ResetTextureState();
3861
3862         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
3863         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
3864         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
3865         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
3866         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
3867         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
3868         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
3869         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
3870         R_FillColors(color4f, 8, cr, cg, cb, ca);
3871         if (r_refdef.fogenabled)
3872         {
3873                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
3874                 {
3875                         f1 = FogPoint_World(v);
3876                         f2 = 1 - f1;
3877                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
3878                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
3879                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
3880                 }
3881         }
3882         R_Mesh_VertexPointer(vertex3f, 0, 0);
3883         R_Mesh_ColorPointer(color4f, 0, 0);
3884         R_Mesh_ResetTextureState();
3885         R_SetupGenericShader(false);
3886         R_Mesh_Draw(0, 8, 12, bboxelements, 0, 0);
3887 }
3888
3889 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3890 {
3891         int i;
3892         float color[4];
3893         prvm_edict_t *edict;
3894         // this function draws bounding boxes of server entities
3895         if (!sv.active)
3896                 return;
3897         R_SetupGenericShader(false);
3898         SV_VM_Begin();
3899         for (i = 0;i < numsurfaces;i++)
3900         {
3901                 edict = PRVM_EDICT_NUM(surfacelist[i]);
3902                 switch ((int)edict->fields.server->solid)
3903                 {
3904                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
3905                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
3906                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
3907                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
3908                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
3909                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
3910                 }
3911                 color[3] *= r_showbboxes.value;
3912                 color[3] = bound(0, color[3], 1);
3913                 GL_DepthTest(!r_showdisabledepthtest.integer);
3914                 GL_CullFace(r_refdef.view.cullface_front);
3915                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
3916         }
3917         SV_VM_End();
3918 }
3919
3920 static void R_DrawEntityBBoxes(void)
3921 {
3922         int i;
3923         prvm_edict_t *edict;
3924         vec3_t center;
3925         // this function draws bounding boxes of server entities
3926         if (!sv.active)
3927                 return;
3928         SV_VM_Begin();
3929         for (i = 0;i < prog->num_edicts;i++)
3930         {
3931                 edict = PRVM_EDICT_NUM(i);
3932                 if (edict->priv.server->free)
3933                         continue;
3934                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
3935                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
3936         }
3937         SV_VM_End();
3938 }
3939
3940 int nomodelelements[24] =
3941 {
3942         5, 2, 0,
3943         5, 1, 2,
3944         5, 0, 3,
3945         5, 3, 1,
3946         0, 2, 4,
3947         2, 1, 4,
3948         3, 0, 4,
3949         1, 3, 4
3950 };
3951
3952 float nomodelvertex3f[6*3] =
3953 {
3954         -16,   0,   0,
3955          16,   0,   0,
3956           0, -16,   0,
3957           0,  16,   0,
3958           0,   0, -16,
3959           0,   0,  16
3960 };
3961
3962 float nomodelcolor4f[6*4] =
3963 {
3964         0.0f, 0.0f, 0.5f, 1.0f,
3965         0.0f, 0.0f, 0.5f, 1.0f,
3966         0.0f, 0.5f, 0.0f, 1.0f,
3967         0.0f, 0.5f, 0.0f, 1.0f,
3968         0.5f, 0.0f, 0.0f, 1.0f,
3969         0.5f, 0.0f, 0.0f, 1.0f
3970 };
3971
3972 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
3973 {
3974         int i;
3975         float f1, f2, *c;
3976         float color4f[6*4];
3977         // this is only called once per entity so numsurfaces is always 1, and
3978         // surfacelist is always {0}, so this code does not handle batches
3979         R_Mesh_Matrix(&ent->matrix);
3980
3981         if (ent->flags & EF_ADDITIVE)
3982         {
3983                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
3984                 GL_DepthMask(false);
3985         }
3986         else if (ent->alpha < 1)
3987         {
3988                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3989                 GL_DepthMask(false);
3990         }
3991         else
3992         {
3993                 GL_BlendFunc(GL_ONE, GL_ZERO);
3994                 GL_DepthMask(true);
3995         }
3996         GL_DepthRange(0, (ent->flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
3997         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3998         GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
3999         GL_CullFace((ent->effects & EF_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
4000         R_SetupGenericShader(false);
4001         R_Mesh_VertexPointer(nomodelvertex3f, 0, 0);
4002         if (r_refdef.fogenabled)
4003         {
4004                 vec3_t org;
4005                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4006                 R_Mesh_ColorPointer(color4f, 0, 0);
4007                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4008                 f1 = FogPoint_World(org);
4009                 f2 = 1 - f1;
4010                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4011                 {
4012                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
4013                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
4014                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
4015                         c[3] *= ent->alpha;
4016                 }
4017         }
4018         else if (ent->alpha != 1)
4019         {
4020                 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
4021                 R_Mesh_ColorPointer(color4f, 0, 0);
4022                 for (i = 0, c = color4f;i < 6;i++, c += 4)
4023                         c[3] *= ent->alpha;
4024         }
4025         else
4026                 R_Mesh_ColorPointer(nomodelcolor4f, 0, 0);
4027         R_Mesh_ResetTextureState();
4028         R_Mesh_Draw(0, 6, 8, nomodelelements, 0, 0);
4029 }
4030
4031 void R_DrawNoModel(entity_render_t *ent)
4032 {
4033         vec3_t org;
4034         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4035         //if ((ent->effects & EF_ADDITIVE) || (ent->alpha < 1))
4036                 R_MeshQueue_AddTransparent(ent->effects & EF_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
4037         //else
4038         //      R_DrawNoModelCallback(ent, 0);
4039 }
4040
4041 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
4042 {
4043         vec3_t right1, right2, diff, normal;
4044
4045         VectorSubtract (org2, org1, normal);
4046
4047         // calculate 'right' vector for start
4048         VectorSubtract (r_refdef.view.origin, org1, diff);
4049         CrossProduct (normal, diff, right1);
4050         VectorNormalize (right1);
4051
4052         // calculate 'right' vector for end
4053         VectorSubtract (r_refdef.view.origin, org2, diff);
4054         CrossProduct (normal, diff, right2);
4055         VectorNormalize (right2);
4056
4057         vert[ 0] = org1[0] + width * right1[0];
4058         vert[ 1] = org1[1] + width * right1[1];
4059         vert[ 2] = org1[2] + width * right1[2];
4060         vert[ 3] = org1[0] - width * right1[0];
4061         vert[ 4] = org1[1] - width * right1[1];
4062         vert[ 5] = org1[2] - width * right1[2];
4063         vert[ 6] = org2[0] - width * right2[0];
4064         vert[ 7] = org2[1] - width * right2[1];
4065         vert[ 8] = org2[2] - width * right2[2];
4066         vert[ 9] = org2[0] + width * right2[0];
4067         vert[10] = org2[1] + width * right2[1];
4068         vert[11] = org2[2] + width * right2[2];
4069 }
4070
4071 float spritetexcoord2f[4*2] = {0, 1, 0, 0, 1, 0, 1, 1};
4072
4073 void R_DrawSprite(int blendfunc1, int blendfunc2, rtexture_t *texture, rtexture_t *fogtexture, qboolean depthdisable, qboolean depthshort, 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)
4074 {
4075         float fog = 1.0f;
4076         float vertex3f[12];
4077
4078         if (r_refdef.fogenabled && !depthdisable) // TODO maybe make the unfog effect a separate flag?
4079                 fog = FogPoint_World(origin);
4080
4081         R_Mesh_Matrix(&identitymatrix);
4082         GL_BlendFunc(blendfunc1, blendfunc2);
4083
4084         if(v_flipped_state)
4085         {
4086                 scalex1 = -scalex1;
4087                 scalex2 = -scalex2;
4088                 GL_CullFace(r_refdef.view.cullface_front);
4089         }
4090         else
4091                 GL_CullFace(r_refdef.view.cullface_back);
4092         GL_CullFace(GL_NONE);
4093
4094         GL_DepthMask(false);
4095         GL_DepthRange(0, depthshort ? 0.0625 : 1);
4096         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
4097         GL_DepthTest(!depthdisable);
4098
4099         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
4100         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
4101         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
4102         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
4103         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
4104         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
4105         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
4106         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
4107         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
4108         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
4109         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
4110         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
4111
4112         R_Mesh_VertexPointer(vertex3f, 0, 0);
4113         R_Mesh_ColorPointer(NULL, 0, 0);
4114         R_Mesh_ResetTextureState();
4115         R_SetupGenericShader(true);
4116         R_Mesh_TexBind(0, R_GetTexture(texture));
4117         R_Mesh_TexCoordPointer(0, 2, spritetexcoord2f, 0, 0);
4118         // FIXME: fixed function path can't properly handle r_refdef.view.colorscale > 1
4119         GL_Color(cr * fog * r_refdef.view.colorscale, cg * fog * r_refdef.view.colorscale, cb * fog * r_refdef.view.colorscale, ca);
4120         R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4121
4122         if (blendfunc2 == GL_ONE_MINUS_SRC_ALPHA)
4123         {
4124                 R_Mesh_TexBind(0, R_GetTexture(fogtexture));
4125                 GL_BlendFunc(blendfunc1, GL_ONE);
4126                 fog = 1 - fog;
4127                 GL_Color(r_refdef.fogcolor[0] * fog, r_refdef.fogcolor[1] * fog, r_refdef.fogcolor[2] * fog, ca);
4128                 R_Mesh_Draw(0, 4, 2, polygonelements, 0, 0);
4129         }
4130 }
4131
4132 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
4133 {
4134         int i;
4135         float *vertex3f;
4136         float v[3];
4137         VectorSet(v, x, y, z);
4138         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
4139                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
4140                         break;
4141         if (i == mesh->numvertices)
4142         {
4143                 if (mesh->numvertices < mesh->maxvertices)
4144                 {
4145                         VectorCopy(v, vertex3f);
4146                         mesh->numvertices++;
4147                 }
4148                 return mesh->numvertices;
4149         }
4150         else
4151                 return i;
4152 }
4153
4154 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
4155 {
4156         int i;
4157         int *e, element[3];
4158         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4159         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
4160         e = mesh->element3i + mesh->numtriangles * 3;
4161         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
4162         {
4163                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
4164                 if (mesh->numtriangles < mesh->maxtriangles)
4165                 {
4166                         *e++ = element[0];
4167                         *e++ = element[1];
4168                         *e++ = element[2];
4169                         mesh->numtriangles++;
4170                 }
4171                 element[1] = element[2];
4172         }
4173 }
4174
4175 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
4176 {
4177         int i;
4178         int *e, element[3];
4179         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4180         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
4181         e = mesh->element3i + mesh->numtriangles * 3;
4182         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
4183         {
4184                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
4185                 if (mesh->numtriangles < mesh->maxtriangles)
4186                 {
4187                         *e++ = element[0];
4188                         *e++ = element[1];
4189                         *e++ = element[2];
4190                         mesh->numtriangles++;
4191                 }
4192                 element[1] = element[2];
4193         }
4194 }
4195
4196 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
4197 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
4198 {
4199         int planenum, planenum2;
4200         int w;
4201         int tempnumpoints;
4202         mplane_t *plane, *plane2;
4203         double maxdist;
4204         double temppoints[2][256*3];
4205         // figure out how large a bounding box we need to properly compute this brush
4206         maxdist = 0;
4207         for (w = 0;w < numplanes;w++)
4208                 maxdist = max(maxdist, planes[w].dist);
4209         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
4210         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
4211         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
4212         {
4213                 w = 0;
4214                 tempnumpoints = 4;
4215                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
4216                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
4217                 {
4218                         if (planenum2 == planenum)
4219                                 continue;
4220                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
4221                         w = !w;
4222                 }
4223                 if (tempnumpoints < 3)
4224                         continue;
4225                 // generate elements forming a triangle fan for this polygon
4226                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
4227         }
4228 }
4229
4230 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
4231 {
4232         texturelayer_t *layer;
4233         layer = t->currentlayers + t->currentnumlayers++;
4234         layer->type = type;
4235         layer->depthmask = depthmask;
4236         layer->blendfunc1 = blendfunc1;
4237         layer->blendfunc2 = blendfunc2;
4238         layer->texture = texture;
4239         layer->texmatrix = *matrix;
4240         layer->color[0] = r * r_refdef.view.colorscale;
4241         layer->color[1] = g * r_refdef.view.colorscale;
4242         layer->color[2] = b * r_refdef.view.colorscale;
4243         layer->color[3] = a;
4244 }
4245
4246 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
4247 {
4248         double index, f;
4249         index = parms[2] + r_refdef.scene.time * parms[3];
4250         index -= floor(index);
4251         switch (func)
4252         {
4253         default:
4254         case Q3WAVEFUNC_NONE:
4255         case Q3WAVEFUNC_NOISE:
4256         case Q3WAVEFUNC_COUNT:
4257                 f = 0;
4258                 break;
4259         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
4260         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
4261         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
4262         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
4263         case Q3WAVEFUNC_TRIANGLE:
4264                 index *= 4;
4265                 f = index - floor(index);
4266                 if (index < 1)
4267                         f = f;
4268                 else if (index < 2)
4269                         f = 1 - f;
4270                 else if (index < 3)
4271                         f = -f;
4272                 else
4273                         f = -(1 - f);
4274                 break;
4275         }
4276         return (float)(parms[0] + parms[1] * f);
4277 }
4278
4279 void R_UpdateTextureInfo(const entity_render_t *ent, texture_t *t)
4280 {
4281         int i;
4282         model_t *model = ent->model;
4283         float f;
4284         float tcmat[12];
4285         q3shaderinfo_layer_tcmod_t *tcmod;
4286
4287         // switch to an alternate material if this is a q1bsp animated material
4288         {
4289                 texture_t *texture = t;
4290                 int s = ent->skinnum;
4291                 if ((unsigned int)s >= (unsigned int)model->numskins)
4292                         s = 0;
4293                 if (model->skinscenes)
4294                 {
4295                         if (model->skinscenes[s].framecount > 1)
4296                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
4297                         else
4298                                 s = model->skinscenes[s].firstframe;
4299                 }
4300                 if (s > 0)
4301                         t = t + s * model->num_surfaces;
4302                 if (t->animated)
4303                 {
4304                         // use an alternate animation if the entity's frame is not 0,
4305                         // and only if the texture has an alternate animation
4306                         if (ent->frame2 != 0 && t->anim_total[1])
4307                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
4308                         else
4309                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
4310                 }
4311                 texture->currentframe = t;
4312         }
4313
4314         // update currentskinframe to be a qw skin or animation frame
4315         if ((i = ent->entitynumber - 1) >= 0 && i < cl.maxclients)
4316         {
4317                 if (strcmp(r_qwskincache[i], cl.scores[i].qw_skin))
4318                 {
4319                         strlcpy(r_qwskincache[i], cl.scores[i].qw_skin, sizeof(r_qwskincache[i]));
4320                         Con_DPrintf("loading skins/%s\n", r_qwskincache[i]);
4321                         r_qwskincache_skinframe[i] = R_SkinFrame_LoadExternal(va("skins/%s", r_qwskincache[i]), TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS, developer.integer > 0);
4322                 }
4323                 t->currentskinframe = r_qwskincache_skinframe[i];
4324                 if (t->currentskinframe == NULL)
4325                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4326         }
4327         else if (t->numskinframes >= 2)
4328                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes];
4329         if (t->backgroundnumskinframes >= 2)
4330                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes];
4331
4332         t->currentmaterialflags = t->basematerialflags;
4333         t->currentalpha = ent->alpha;
4334         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
4335         {
4336                 t->currentalpha *= r_wateralpha.value;
4337                 /*
4338                  * FIXME what is this supposed to do?
4339                 // if rendering refraction/reflection, disable transparency
4340                 if (r_waterstate.enabled && (t->currentalpha < 1 || (t->currentmaterialflags & MATERIALFLAG_ALPHA)))
4341                         t->currentmaterialflags |= MATERIALFLAG_WATERSHADER;
4342                 */
4343         }
4344         if(!r_waterstate.enabled)
4345                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4346         if (!(ent->flags & RENDER_LIGHT))
4347                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
4348         else if (rsurface.modeltexcoordlightmap2f == NULL)
4349         {
4350                 // pick a model lighting mode
4351                 if (VectorLength2(ent->modellight_diffuse) >= (1.0f / 256.0f))
4352                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
4353                 else
4354                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
4355         }
4356         if (ent->effects & EF_ADDITIVE)
4357                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4358         else if (t->currentalpha < 1)
4359                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
4360         if (ent->effects & EF_DOUBLESIDED)
4361                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
4362         if (ent->effects & EF_NODEPTHTEST)
4363                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4364         if (ent->flags & RENDER_VIEWMODEL)
4365                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
4366         if (t->backgroundnumskinframes)
4367                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
4368         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
4369         {
4370                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
4371                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
4372         }
4373         else
4374                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
4375
4376         // there is no tcmod
4377         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4378                 t->currenttexmatrix = r_waterscrollmatrix;
4379
4380         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
4381         {
4382                 matrix4x4_t matrix;
4383                 switch(tcmod->tcmod)
4384                 {
4385                 case Q3TCMOD_COUNT:
4386                 case Q3TCMOD_NONE:
4387                         if (t->currentmaterialflags & MATERIALFLAG_WATER && r_waterscroll.value != 0)
4388                                 matrix = r_waterscrollmatrix;
4389                         else
4390                                 matrix = identitymatrix;
4391                         break;
4392                 case Q3TCMOD_ENTITYTRANSLATE:
4393                         // this is used in Q3 to allow the gamecode to control texcoord
4394                         // scrolling on the entity, which is not supported in darkplaces yet.
4395                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
4396                         break;
4397                 case Q3TCMOD_ROTATE:
4398                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
4399                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
4400                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
4401                         break;
4402                 case Q3TCMOD_SCALE:
4403                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
4404                         break;
4405                 case Q3TCMOD_SCROLL:
4406                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
4407                         break;
4408                 case Q3TCMOD_STRETCH:
4409                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
4410                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
4411                         break;
4412                 case Q3TCMOD_TRANSFORM:
4413                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
4414                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
4415                         VectorSet(tcmat +  6, 0                   , 0                , 1);
4416                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
4417                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
4418                         break;
4419                 case Q3TCMOD_TURBULENT:
4420                         // this is handled in the RSurf_PrepareVertices function
4421                         matrix = identitymatrix;
4422                         break;
4423                 }
4424                 // either replace or concatenate the transformation
4425                 if (i < 1)
4426                         t->currenttexmatrix = matrix;
4427                 else
4428                 {
4429                         matrix4x4_t temp = t->currenttexmatrix;
4430                         Matrix4x4_Concat(&t->currenttexmatrix, &matrix, &temp);
4431                 }
4432         }
4433
4434         t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
4435         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
4436         t->glosstexture = r_texture_black;
4437         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
4438         t->backgroundglosstexture = r_texture_black;
4439         t->specularpower = r_shadow_glossexponent.value;
4440         // TODO: store reference values for these in the texture?
4441         t->specularscale = 0;
4442         if (r_shadow_gloss.integer > 0)
4443         {
4444                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
4445                 {
4446                         if (r_shadow_glossintensity.value > 0)
4447                         {
4448                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
4449                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
4450                                 t->specularscale = r_shadow_glossintensity.value;
4451                         }
4452                 }
4453                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
4454                 {
4455                         t->glosstexture = r_texture_white;
4456                         t->backgroundglosstexture = r_texture_white;
4457                         t->specularscale = r_shadow_gloss2intensity.value;
4458                 }
4459         }
4460
4461         // lightmaps mode looks bad with dlights using actual texturing, so turn
4462         // off the colormap and glossmap, but leave the normalmap on as it still
4463         // accurately represents the shading involved
4464         if (gl_lightmaps.integer)
4465         {
4466                 t->basetexture = r_texture_grey128;
4467                 t->backgroundbasetexture = NULL;
4468                 t->specularscale = 0;
4469                 t->currentmaterialflags &= ~(MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_WATERALPHA | MATERIALFLAG_WATER | MATERIALFLAG_SKY | MATERIALFLAG_ALPHATEST | MATERIALFLAG_BLENDED | MATERIALFLAG_CUSTOMBLEND | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
4470                 t->currentmaterialflags |= MATERIALFLAG_WALL;
4471         }
4472
4473         Vector4Set(t->lightmapcolor, ent->colormod[0], ent->colormod[1], ent->colormod[2], t->currentalpha);
4474         VectorClear(t->dlightcolor);
4475         t->currentnumlayers = 0;
4476         if (!(t->currentmaterialflags & MATERIALFLAG_NODRAW))
4477         {
4478                 if (!(t->currentmaterialflags & MATERIALFLAG_SKY))
4479                 {
4480                         int blendfunc1, blendfunc2, depthmask;
4481                         if (t->currentmaterialflags & MATERIALFLAG_ADD)
4482                         {
4483                                 blendfunc1 = GL_SRC_ALPHA;
4484                                 blendfunc2 = GL_ONE;
4485                         }
4486                         else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
4487                         {
4488                                 blendfunc1 = GL_SRC_ALPHA;
4489                                 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
4490                         }
4491                         else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
4492                         {
4493                                 blendfunc1 = t->customblendfunc[0];
4494                                 blendfunc2 = t->customblendfunc[1];
4495                         }
4496                         else
4497                         {
4498                                 blendfunc1 = GL_ONE;
4499                                 blendfunc2 = GL_ZERO;
4500                         }
4501                         depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
4502                         if (t->currentmaterialflags & (MATERIALFLAG_WATER | MATERIALFLAG_WALL))
4503                         {
4504                                 int layerflags = 0;
4505                                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
4506                                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
4507                                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4508                                 {
4509                                         // fullbright is not affected by r_refdef.lightmapintensity
4510                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4511                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4512                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4513                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4514                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4515                                 }
4516                                 else
4517                                 {
4518                                         vec3_t ambientcolor;
4519                                         float colorscale;
4520                                         // set the color tint used for lights affecting this surface
4521                                         VectorSet(t->dlightcolor, ent->colormod[0] * t->lightmapcolor[3], ent->colormod[1] * t->lightmapcolor[3], ent->colormod[2] * t->lightmapcolor[3]);
4522                                         colorscale = 2;
4523                                         // q3bsp has no lightmap updates, so the lightstylevalue that
4524                                         // would normally be baked into the lightmap must be
4525                                         // applied to the color
4526                                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
4527                                         if (ent->model->type == mod_brushq3)
4528                                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
4529                                         colorscale *= r_refdef.lightmapintensity;
4530                                         VectorScale(t->lightmapcolor, r_ambient.value * (1.0f / 64.0f), ambientcolor);
4531                                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
4532                                         // basic lit geometry
4533                                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
4534                                         // add pants/shirt if needed
4535                                         if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4536                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * t->lightmapcolor[0], ent->colormap_pantscolor[1] * t->lightmapcolor[1], ent->colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
4537                                         if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4538                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * t->lightmapcolor[0], ent->colormap_shirtcolor[1] * t->lightmapcolor[1], ent->colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
4539                                         // now add ambient passes if needed
4540                                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
4541                                         {
4542                                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
4543                                                 if (VectorLength2(ent->colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
4544                                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->pants, &t->currenttexmatrix, ent->colormap_pantscolor[0] * ambientcolor[0], ent->colormap_pantscolor[1] * ambientcolor[1], ent->colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4545                                                 if (VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
4546                                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->shirt, &t->currenttexmatrix, ent->colormap_shirtcolor[0] * ambientcolor[0], ent->colormap_shirtcolor[1] * ambientcolor[1], ent->colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
4547                                         }
4548                                 }
4549                                 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
4550                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->currentskinframe->glow, &t->currenttexmatrix, r_hdr_glowintensity.value, r_hdr_glowintensity.value, r_hdr_glowintensity.value, t->lightmapcolor[3]);
4551                                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
4552                                 {
4553                                         // if this is opaque use alpha blend which will darken the earlier
4554                                         // passes cheaply.
4555                                         //
4556                                         // if this is an alpha blended material, all the earlier passes
4557                                         // were darkened by fog already, so we only need to add the fog
4558                                         // color ontop through the fog mask texture
4559                                         //
4560                                         // if this is an additive blended material, all the earlier passes
4561                                         // were darkened by fog already, and we should not add fog color
4562                                         // (because the background was not darkened, there is no fog color
4563                                         // that was lost behind it).
4564                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->currentskinframe->fog, &identitymatrix, r_refdef.fogcolor[0] / r_refdef.view.colorscale, r_refdef.fogcolor[1] / r_refdef.view.colorscale, r_refdef.fogcolor[2] / r_refdef.view.colorscale, t->lightmapcolor[3]);
4565                                 }
4566                         }
4567                 }
4568         }
4569 }
4570
4571 void R_UpdateAllTextureInfo(entity_render_t *ent)
4572 {
4573         int i;
4574         if (ent->model)
4575                 for (i = 0;i < ent->model->num_texturesperskin;i++)
4576                         R_UpdateTextureInfo(ent, ent->model->data_textures + i);
4577 }
4578
4579 rsurfacestate_t rsurface;
4580
4581 void R_Mesh_ResizeArrays(int newvertices)
4582 {
4583         float *base;
4584         if (rsurface.array_size >= newvertices)
4585                 return;
4586         if (rsurface.array_modelvertex3f)
4587                 Mem_Free(rsurface.array_modelvertex3f);
4588         rsurface.array_size = (newvertices + 1023) & ~1023;
4589         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
4590         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
4591         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
4592         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
4593         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
4594         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
4595         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
4596         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
4597         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
4598         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
4599         rsurface.array_color4f           = base + rsurface.array_size * 27;
4600         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
4601 }
4602
4603 void RSurf_ActiveWorldEntity(void)
4604 {
4605         model_t *model = r_refdef.scene.worldmodel;
4606         if (rsurface.array_size < model->surfmesh.num_vertices)
4607                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4608         rsurface.matrix = identitymatrix;
4609         rsurface.inversematrix = identitymatrix;
4610         R_Mesh_Matrix(&identitymatrix);
4611         VectorCopy(r_refdef.view.origin, rsurface.modelorg);
4612         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
4613         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
4614         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
4615         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
4616         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
4617         rsurface.frameblend[0].frame = 0;
4618         rsurface.frameblend[0].lerp = 1;
4619         rsurface.frameblend[1].frame = 0;
4620         rsurface.frameblend[1].lerp = 0;
4621         rsurface.frameblend[2].frame = 0;
4622         rsurface.frameblend[2].lerp = 0;
4623         rsurface.frameblend[3].frame = 0;
4624         rsurface.frameblend[3].lerp = 0;
4625         rsurface.basepolygonfactor = r_refdef.polygonfactor;
4626         rsurface.basepolygonoffset = r_refdef.polygonoffset;
4627         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4628         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4629         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4630         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4631         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4632         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4633         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4634         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4635         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4636         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4637         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4638         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4639         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4640         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4641         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4642         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4643         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4644         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4645         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4646         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4647         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4648         rsurface.modelelement3i = model->surfmesh.data_element3i;
4649         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4650         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4651         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4652         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4653         rsurface.modelsurfaces = model->data_surfaces;
4654         rsurface.generatedvertex = false;
4655         rsurface.vertex3f  = rsurface.modelvertex3f;
4656         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4657         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4658         rsurface.svector3f = rsurface.modelsvector3f;
4659         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4660         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4661         rsurface.tvector3f = rsurface.modeltvector3f;
4662         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4663         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4664         rsurface.normal3f  = rsurface.modelnormal3f;
4665         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4666         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4667         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4668 }
4669
4670 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4671 {
4672         model_t *model = ent->model;
4673         if (rsurface.array_size < model->surfmesh.num_vertices)
4674                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
4675         rsurface.matrix = ent->matrix;
4676         rsurface.inversematrix = ent->inversematrix;
4677         R_Mesh_Matrix(&rsurface.matrix);
4678         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.modelorg);
4679         rsurface.modellight_ambient[0] = ent->modellight_ambient[0] * ent->colormod[0];
4680         rsurface.modellight_ambient[1] = ent->modellight_ambient[1] * ent->colormod[1];
4681         rsurface.modellight_ambient[2] = ent->modellight_ambient[2] * ent->colormod[2];
4682         rsurface.modellight_diffuse[0] = ent->modellight_diffuse[0] * ent->colormod[0];
4683         rsurface.modellight_diffuse[1] = ent->modellight_diffuse[1] * ent->colormod[1];
4684         rsurface.modellight_diffuse[2] = ent->modellight_diffuse[2] * ent->colormod[2];
4685         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
4686         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
4687         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
4688         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
4689         rsurface.frameblend[0] = ent->frameblend[0];
4690         rsurface.frameblend[1] = ent->frameblend[1];
4691         rsurface.frameblend[2] = ent->frameblend[2];
4692         rsurface.frameblend[3] = ent->frameblend[3];
4693         rsurface.basepolygonfactor = r_refdef.polygonfactor;
4694         rsurface.basepolygonoffset = r_refdef.polygonoffset;
4695         if (ent->model->brush.submodel)
4696         {
4697                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
4698                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
4699         }
4700         if (model->surfmesh.isanimated && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].frame != 0))
4701         {
4702                 if (wanttangents)
4703                 {
4704                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4705                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4706                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4707                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4708                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
4709                 }
4710                 else if (wantnormals)
4711                 {
4712                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4713                         rsurface.modelsvector3f = NULL;
4714                         rsurface.modeltvector3f = NULL;
4715                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4716                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
4717                 }
4718                 else
4719                 {
4720                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
4721                         rsurface.modelsvector3f = NULL;
4722                         rsurface.modeltvector3f = NULL;
4723                         rsurface.modelnormal3f = NULL;
4724                         Mod_Alias_GetMesh_Vertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
4725                 }
4726                 rsurface.modelvertex3f_bufferobject = 0;
4727                 rsurface.modelvertex3f_bufferoffset = 0;
4728                 rsurface.modelsvector3f_bufferobject = 0;
4729                 rsurface.modelsvector3f_bufferoffset = 0;
4730                 rsurface.modeltvector3f_bufferobject = 0;
4731                 rsurface.modeltvector3f_bufferoffset = 0;
4732                 rsurface.modelnormal3f_bufferobject = 0;
4733                 rsurface.modelnormal3f_bufferoffset = 0;
4734                 rsurface.generatedvertex = true;
4735         }
4736         else
4737         {
4738                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
4739                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
4740                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
4741                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
4742                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
4743                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
4744                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
4745                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
4746                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
4747                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
4748                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
4749                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
4750                 rsurface.generatedvertex = false;
4751         }
4752         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
4753         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
4754         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
4755         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
4756         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
4757         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
4758         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
4759         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
4760         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
4761         rsurface.modelelement3i = model->surfmesh.data_element3i;
4762         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo;
4763         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
4764         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
4765         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
4766         rsurface.modelsurfaces = model->data_surfaces;
4767         rsurface.vertex3f  = rsurface.modelvertex3f;
4768         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4769         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4770         rsurface.svector3f = rsurface.modelsvector3f;
4771         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4772         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4773         rsurface.tvector3f = rsurface.modeltvector3f;
4774         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4775         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4776         rsurface.normal3f  = rsurface.modelnormal3f;
4777         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4778         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4779         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
4780 }
4781
4782 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
4783 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, msurface_t **texturesurfacelist)
4784 {
4785         int deformindex;
4786         int texturesurfaceindex;
4787         int i, j;
4788         float amplitude;
4789         float animpos;
4790         float scale;
4791         const float *v1, *in_tc;
4792         float *out_tc;
4793         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
4794         float waveparms[4];
4795         q3shaderinfo_deform_t *deform;
4796         // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself
4797         if (rsurface.generatedvertex)
4798         {
4799                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
4800                         generatenormals = true;
4801                 for (i = 0;i < Q3MAXDEFORMS;i++)
4802                 {
4803                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
4804                         {
4805                                 generatetangents = true;
4806                                 generatenormals = true;
4807                         }
4808                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
4809                                 generatenormals = true;
4810                 }
4811                 if (generatenormals && !rsurface.modelnormal3f)
4812                 {
4813                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
4814                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
4815                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
4816                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer);
4817                 }
4818                 if (generatetangents && !rsurface.modelsvector3f)
4819                 {
4820                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
4821                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
4822                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
4823                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
4824                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
4825                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
4826                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer);
4827                 }
4828         }
4829         rsurface.vertex3f  = rsurface.modelvertex3f;
4830         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
4831         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
4832         rsurface.svector3f = rsurface.modelsvector3f;
4833         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
4834         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
4835         rsurface.tvector3f = rsurface.modeltvector3f;
4836         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
4837         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
4838         rsurface.normal3f  = rsurface.modelnormal3f;
4839         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
4840         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
4841         // if vertices are deformed (sprite flares and things in maps, possibly
4842         // water waves, bulges and other deformations), generate them into
4843         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
4844         // (may be static model data or generated data for an animated model, or
4845         //  the previous deform pass)
4846         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
4847         {
4848                 switch (deform->deform)
4849                 {
4850                 default:
4851                 case Q3DEFORM_PROJECTIONSHADOW:
4852                 case Q3DEFORM_TEXT0:
4853                 case Q3DEFORM_TEXT1:
4854                 case Q3DEFORM_TEXT2:
4855                 case Q3DEFORM_TEXT3:
4856                 case Q3DEFORM_TEXT4:
4857                 case Q3DEFORM_TEXT5:
4858                 case Q3DEFORM_TEXT6:
4859                 case Q3DEFORM_TEXT7:
4860                 case Q3DEFORM_NONE:
4861                         break;
4862                 case Q3DEFORM_AUTOSPRITE:
4863                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4864                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4865                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4866                         VectorNormalize(newforward);
4867                         VectorNormalize(newright);
4868                         VectorNormalize(newup);
4869                         // make deformed versions of only the model vertices used by the specified surfaces
4870                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4871                         {
4872                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4873                                 // a single autosprite surface can contain multiple sprites...
4874                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
4875                                 {
4876                                         VectorClear(center);
4877                                         for (i = 0;i < 4;i++)
4878                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4879                                         VectorScale(center, 0.25f, center);
4880                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
4881                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
4882                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
4883                                         for (i = 0;i < 4;i++)
4884                                         {
4885                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
4886                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
4887                                         }
4888                                 }
4889                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
4890                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
4891                         }
4892                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
4893                         rsurface.vertex3f_bufferobject = 0;
4894                         rsurface.vertex3f_bufferoffset = 0;
4895                         rsurface.svector3f = rsurface.array_deformedsvector3f;
4896                         rsurface.svector3f_bufferobject = 0;
4897                         rsurface.svector3f_bufferoffset = 0;
4898                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
4899                         rsurface.tvector3f_bufferobject = 0;
4900                         rsurface.tvector3f_bufferoffset = 0;
4901                         rsurface.normal3f = rsurface.array_deformednormal3f;
4902                         rsurface.normal3f_bufferobject = 0;
4903                         rsurface.normal3f_bufferoffset = 0;
4904                         break;
4905                 case Q3DEFORM_AUTOSPRITE2:
4906                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
4907                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
4908                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
4909                         VectorNormalize(newforward);
4910                         VectorNormalize(newright);
4911                         VectorNormalize(newup);
4912                         // make deformed versions of only the model vertices used by the specified surfaces
4913                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
4914                         {
4915                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
4916                                 const float *v1, *v2;
4917                                 vec3_t start, end;
4918                                 float f, l;
4919                                 struct
4920                                 {
4921                                         float length2;
4922                                         const float *v1;
4923                                         const float *v2;
4924                                 }
4925                                 shortest[2];
4926                                 memset(shortest, 0, sizeof(shortest));
4927                                 // a single autosprite surface can contain multiple sprites...
4928                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
4929                                 {
4930                                         VectorClear(center);
4931                                         for (i = 0;i < 4;i++)
4932                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
4933                                         VectorScale(center, 0.25f, center);
4934                                         // find the two shortest edges, then use them to define the
4935                                         // axis vectors for rotating around the central axis
4936                                         for (i = 0;i < 6;i++)
4937                                         {
4938                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
4939                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
4940 #if 0
4941                                                 Debug_PolygonBegin(NULL, 0);
4942                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
4943                                                 Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
4944                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
4945                                                 Debug_PolygonEnd();
4946 #endif
4947                                                 l = VectorDistance2(v1, v2);
4948                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
4949                                                 if (v1[2] != v2[2])
4950                                                         l += (1.0f / 1024.0f);
4951                                                 if (shortest[0].length2 > l || i == 0)
4952                                                 {
4953                                                         shortest[1] = shortest[0];
4954                                                         shortest[0].length2 = l;
4955                                                         shortest[0].v1 = v1;
4956                                                         shortest[0].v2 = v2;
4957                                                 }
4958                                                 else if (shortest[1].length2 > l || i == 1)
4959                                                 {
4960                                                         shortest[1].length2 = l;
4961                                                         shortest[1].v1 = v1;
4962                                                         shortest[1].v2 = v2;
4963                                                 }
4964                                         }
4965                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
4966                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
4967 #if 0
4968                                         Debug_PolygonBegin(NULL, 0);
4969                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
4970                                         Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
4971                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
4972                                         Debug_PolygonEnd();
4973 #endif
4974                                         // this calculates the right vector from the shortest edge
4975                                         // and the up vector from the edge midpoints
4976                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
4977                                         VectorNormalize(right);
4978                                         VectorSubtract(end, start, up);
4979                                         VectorNormalize(up);
4980                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
4981                                         //VectorSubtract(rsurface.modelorg, center, forward);
4982                                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
4983                                         VectorNegate(forward, forward);
4984                                         VectorReflect(forward, 0, up, forward);
4985                                         VectorNormalize(forward);
4986                                         CrossProduct(up, forward, newright);
4987                                         VectorNormalize(newright);
4988 #if 0
4989                                         Debug_PolygonBegin(NULL, 0);
4990                                         Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
4991                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
4992                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
4993                                         Debug_PolygonEnd();
4994 #endif
4995 #if 0
4996                                         Debug_PolygonBegin(NULL, 0);
4997                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
4998                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
4999                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
5000                                         Debug_PolygonEnd();
5001 #endif
5002                                         // rotate the quad around the up axis vector, this is made
5003                                         // especially easy by the fact we know the quad is flat,
5004                                         // so we only have to subtract the center position and
5005                                         // measure distance along the right vector, and then
5006                                         // multiply that by the newright vector and add back the
5007                                         // center position
5008                                         // we also need to subtract the old position to undo the
5009                                         // displacement from the center, which we do with a
5010                                         // DotProduct, the subtraction/addition of center is also
5011                                         // optimized into DotProducts here
5012                                         l = DotProduct(right, center);
5013                                         for (i = 0;i < 4;i++)
5014                                         {
5015                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
5016                                                 f = DotProduct(right, v1) - l;
5017                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
5018                                         }
5019                                 }
5020                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer);
5021                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
5022                         }
5023                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5024                         rsurface.vertex3f_bufferobject = 0;
5025                         rsurface.vertex3f_bufferoffset = 0;
5026                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5027                         rsurface.svector3f_bufferobject = 0;
5028                         rsurface.svector3f_bufferoffset = 0;
5029                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5030                         rsurface.tvector3f_bufferobject = 0;
5031                         rsurface.tvector3f_bufferoffset = 0;
5032                         rsurface.normal3f = rsurface.array_deformednormal3f;
5033                         rsurface.normal3f_bufferobject = 0;
5034                         rsurface.normal3f_bufferoffset = 0;
5035                         break;
5036                 case Q3DEFORM_NORMAL:
5037                         // deform the normals to make reflections wavey
5038                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5039                         {
5040                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5041                                 for (j = 0;j < surface->num_vertices;j++)
5042                                 {
5043                                         float vertex[3];
5044                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
5045                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
5046                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
5047                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5048                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5049                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
5050                                         VectorNormalize(normal);
5051                                 }
5052                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer);
5053                         }
5054                         rsurface.svector3f = rsurface.array_deformedsvector3f;
5055                         rsurface.svector3f_bufferobject = 0;
5056                         rsurface.svector3f_bufferoffset = 0;
5057                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
5058                         rsurface.tvector3f_bufferobject = 0;
5059                         rsurface.tvector3f_bufferoffset = 0;
5060                         rsurface.normal3f = rsurface.array_deformednormal3f;
5061                         rsurface.normal3f_bufferobject = 0;
5062                         rsurface.normal3f_bufferoffset = 0;
5063                         break;
5064                 case Q3DEFORM_WAVE:
5065                         // deform vertex array to make wavey water and flags and such
5066                         waveparms[0] = deform->waveparms[0];
5067                         waveparms[1] = deform->waveparms[1];
5068                         waveparms[2] = deform->waveparms[2];
5069                         waveparms[3] = deform->waveparms[3];
5070                         // this is how a divisor of vertex influence on deformation
5071                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
5072                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5073                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5074                         {
5075                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5076                                 for (j = 0;j < surface->num_vertices;j++)
5077                                 {
5078                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
5079                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5080                                         // if the wavefunc depends on time, evaluate it per-vertex
5081                                         if (waveparms[3])
5082                                         {
5083                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
5084                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
5085                                         }
5086                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
5087                                 }
5088                         }
5089                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5090                         rsurface.vertex3f_bufferobject = 0;
5091                         rsurface.vertex3f_bufferoffset = 0;
5092                         break;
5093                 case Q3DEFORM_BULGE:
5094                         // deform vertex array to make the surface have moving bulges
5095                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5096                         {
5097                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5098                                 for (j = 0;j < surface->num_vertices;j++)
5099                                 {
5100                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
5101                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5102                                 }
5103                         }
5104                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5105                         rsurface.vertex3f_bufferobject = 0;
5106                         rsurface.vertex3f_bufferoffset = 0;
5107                         break;
5108                 case Q3DEFORM_MOVE:
5109                         // deform vertex array
5110                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
5111                         VectorScale(deform->parms, scale, waveparms);
5112                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5113                         {
5114                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5115                                 for (j = 0;j < surface->num_vertices;j++)
5116                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
5117                         }
5118                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
5119                         rsurface.vertex3f_bufferobject = 0;
5120                         rsurface.vertex3f_bufferoffset = 0;
5121                         break;
5122                 }
5123         }
5124         // generate texcoords based on the chosen texcoord source
5125         switch(rsurface.texture->tcgen.tcgen)
5126         {
5127         default:
5128         case Q3TCGEN_TEXTURE:
5129                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
5130                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
5131                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
5132                 break;
5133         case Q3TCGEN_LIGHTMAP:
5134                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
5135                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
5136                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
5137                 break;
5138         case Q3TCGEN_VECTOR:
5139                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5140                 {
5141                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5142                         for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
5143                         {
5144                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
5145                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
5146                         }
5147                 }
5148                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5149                 rsurface.texcoordtexture2f_bufferobject  = 0;
5150                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5151                 break;
5152         case Q3TCGEN_ENVIRONMENT:
5153                 // make environment reflections using a spheremap
5154                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5155                 {
5156                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5157                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
5158                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
5159                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
5160                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
5161                         {
5162                                 float l, d, eyedir[3];
5163                                 VectorSubtract(rsurface.modelorg, vertex, eyedir);
5164                                 l = 0.5f / VectorLength(eyedir);
5165                                 d = DotProduct(normal, eyedir)*2;
5166                                 out_tc[0] = 0.5f + (normal[1]*d - eyedir[1])*l;
5167                                 out_tc[1] = 0.5f - (normal[2]*d - eyedir[2])*l;
5168                         }
5169                 }
5170                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5171                 rsurface.texcoordtexture2f_bufferobject  = 0;
5172                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5173                 break;
5174         }
5175         // the only tcmod that needs software vertex processing is turbulent, so
5176         // check for it here and apply the changes if needed
5177         // and we only support that as the first one
5178         // (handling a mixture of turbulent and other tcmods would be problematic
5179         //  without punting it entirely to a software path)
5180         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
5181         {
5182                 amplitude = rsurface.texture->tcmods[0].parms[1];
5183                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
5184                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5185                 {
5186                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5187                         for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
5188                         {
5189                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5190                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
5191                         }
5192                 }
5193                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
5194                 rsurface.texcoordtexture2f_bufferobject  = 0;
5195                 rsurface.texcoordtexture2f_bufferoffset  = 0;
5196         }
5197         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
5198         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
5199         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
5200         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5201 }
5202
5203 void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
5204 {
5205         int i, j;
5206         const msurface_t *surface = texturesurfacelist[0];
5207         const msurface_t *surface2;
5208         int firstvertex;
5209         int endvertex;
5210         int numvertices;
5211         int numtriangles;
5212         // TODO: lock all array ranges before render, rather than on each surface
5213         if (texturenumsurfaces == 1)
5214         {
5215                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5216                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5217         }
5218         else if (r_batchmode.integer == 2)
5219         {
5220                 #define MAXBATCHTRIANGLES 4096
5221                 int batchtriangles = 0;
5222                 int batchelements[MAXBATCHTRIANGLES*3];
5223                 for (i = 0;i < texturenumsurfaces;i = j)
5224                 {
5225                         surface = texturesurfacelist[i];
5226                         j = i + 1;
5227                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5228                         {
5229                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5230                                 continue;
5231                         }
5232                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5233                         batchtriangles = surface->num_triangles;
5234                         firstvertex = surface->num_firstvertex;
5235                         endvertex = surface->num_firstvertex + surface->num_vertices;
5236                         for (;j < texturenumsurfaces;j++)
5237                         {
5238                                 surface2 = texturesurfacelist[j];
5239                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5240                                         break;
5241                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5242                                 batchtriangles += surface2->num_triangles;
5243                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5244                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5245                         }
5246                         surface2 = texturesurfacelist[j-1];
5247                         numvertices = endvertex - firstvertex;
5248                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5249                 }
5250         }
5251         else if (r_batchmode.integer == 1)
5252         {
5253                 for (i = 0;i < texturenumsurfaces;i = j)
5254                 {
5255                         surface = texturesurfacelist[i];
5256                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5257                                 if (texturesurfacelist[j] != surface2)
5258                                         break;
5259                         surface2 = texturesurfacelist[j-1];
5260                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5261                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5262                         GL_LockArrays(surface->num_firstvertex, numvertices);
5263                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5264                 }
5265         }
5266         else
5267         {
5268                 for (i = 0;i < texturenumsurfaces;i++)
5269                 {
5270                         surface = texturesurfacelist[i];
5271                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5272                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5273                 }
5274         }
5275 }
5276
5277 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
5278 {
5279         int i, planeindex, vertexindex;
5280         float d, bestd;
5281         vec3_t vert;
5282         const float *v;
5283         r_waterstate_waterplane_t *p, *bestp;
5284         msurface_t *surface;
5285         if (r_waterstate.renderingscene)
5286                 return;
5287         for (i = 0;i < texturenumsurfaces;i++)
5288         {
5289                 surface = texturesurfacelist[i];
5290                 if (lightmaptexunit >= 0)
5291                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5292                 if (deluxemaptexunit >= 0)
5293                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5294                 // pick the closest matching water plane
5295                 bestd = 0;
5296                 bestp = NULL;
5297                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5298                 {
5299                         d = 0;
5300                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
5301                         {
5302                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
5303                                 d += fabs(PlaneDiff(vert, &p->plane));
5304                         }
5305                         if (bestd > d || !bestp)
5306                         {
5307                                 bestd = d;
5308                                 bestp = p;
5309                         }
5310                 }
5311                 if (bestp)
5312                 {
5313                         if (refractiontexunit >= 0)
5314                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
5315                         if (reflectiontexunit >= 0)
5316                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
5317                 }
5318                 else
5319                 {
5320                         if (refractiontexunit >= 0)
5321                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
5322                         if (reflectiontexunit >= 0)
5323                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
5324                 }
5325                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5326                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5327         }
5328 }
5329
5330 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
5331 {
5332         int i;
5333         int j;
5334         const msurface_t *surface = texturesurfacelist[0];
5335         const msurface_t *surface2;
5336         int firstvertex;
5337         int endvertex;
5338         int numvertices;
5339         int numtriangles;
5340         // TODO: lock all array ranges before render, rather than on each surface
5341         if (texturenumsurfaces == 1)
5342         {
5343                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5344                 if (deluxemaptexunit >= 0)
5345                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5346                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5347                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5348         }
5349         else if (r_batchmode.integer == 2)
5350         {
5351                 #define MAXBATCHTRIANGLES 4096
5352                 int batchtriangles = 0;
5353                 int batchelements[MAXBATCHTRIANGLES*3];
5354                 for (i = 0;i < texturenumsurfaces;i = j)
5355                 {
5356                         surface = texturesurfacelist[i];
5357                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5358                         if (deluxemaptexunit >= 0)
5359                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5360                         j = i + 1;
5361                         if (surface->num_triangles > MAXBATCHTRIANGLES)
5362                         {
5363                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5364                                 continue;
5365                         }
5366                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
5367                         batchtriangles = surface->num_triangles;
5368                         firstvertex = surface->num_firstvertex;
5369                         endvertex = surface->num_firstvertex + surface->num_vertices;
5370                         for (;j < texturenumsurfaces;j++)
5371                         {
5372                                 surface2 = texturesurfacelist[j];
5373                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
5374                                         break;
5375                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
5376                                 batchtriangles += surface2->num_triangles;
5377                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
5378                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
5379                         }
5380                         surface2 = texturesurfacelist[j-1];
5381                         numvertices = endvertex - firstvertex;
5382                         R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements, 0, 0);
5383                 }
5384         }
5385         else if (r_batchmode.integer == 1)
5386         {
5387 #if 0
5388                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
5389                 for (i = 0;i < texturenumsurfaces;i = j)
5390                 {
5391                         surface = texturesurfacelist[i];
5392                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5393                                 if (texturesurfacelist[j] != surface2)
5394                                         break;
5395                         Con_Printf(" %i", j - i);
5396                 }
5397                 Con_Printf("\n");
5398                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
5399 #endif
5400                 for (i = 0;i < texturenumsurfaces;i = j)
5401                 {
5402                         surface = texturesurfacelist[i];
5403                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5404                         if (deluxemaptexunit >= 0)
5405                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5406                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
5407                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
5408                                         break;
5409 #if 0
5410                         Con_Printf(" %i", j - i);
5411 #endif
5412                         surface2 = texturesurfacelist[j-1];
5413                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
5414                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
5415                         GL_LockArrays(surface->num_firstvertex, numvertices);
5416                         R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5417                 }
5418 #if 0
5419                 Con_Printf("\n");
5420 #endif
5421         }
5422         else
5423         {
5424                 for (i = 0;i < texturenumsurfaces;i++)
5425                 {
5426                         surface = texturesurfacelist[i];
5427                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
5428                         if (deluxemaptexunit >= 0)
5429                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
5430                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5431                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5432                 }
5433         }
5434 }
5435
5436 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
5437 {
5438         int j;
5439         int texturesurfaceindex;
5440         if (r_showsurfaces.integer == 2)
5441         {
5442                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5443                 {
5444                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5445                         for (j = 0;j < surface->num_triangles;j++)
5446                         {
5447                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
5448                                 GL_Color(f, f, f, 1);
5449                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, 1, (rsurface.modelelement3i + 3 * (j + surface->num_firsttriangle)), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * (j + surface->num_firsttriangle)));
5450                         }
5451                 }
5452         }
5453         else
5454         {
5455                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5456                 {
5457                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5458                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
5459                         GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
5460                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
5461                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface.modelelement3i + 3 * surface->num_firsttriangle), rsurface.modelelement3i_bufferobject, (sizeof(int[3]) * surface->num_firsttriangle));
5462                 }
5463         }
5464 }
5465
5466 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, msurface_t **texturesurfacelist)
5467 {
5468         int texturesurfaceindex;
5469         int i;
5470         float f;
5471         float *v, *c, *c2;
5472         if (rsurface.lightmapcolor4f)
5473         {
5474                 // generate color arrays for the surfaces in this list
5475                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5476                 {
5477                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5478                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
5479                         {
5480                                 f = FogPoint_Model(v);
5481                                 c2[0] = c[0] * f;
5482                                 c2[1] = c[1] * f;
5483                                 c2[2] = c[2] * f;
5484                                 c2[3] = c[3];
5485                         }
5486                 }
5487         }
5488         else
5489         {
5490                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5491                 {
5492                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5493                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
5494                         {
5495                                 f = FogPoint_Model(v);
5496                                 c2[0] = f;
5497                                 c2[1] = f;
5498                                 c2[2] = f;
5499                                 c2[3] = 1;
5500                         }
5501                 }
5502         }
5503         rsurface.lightmapcolor4f = rsurface.array_color4f;
5504         rsurface.lightmapcolor4f_bufferobject = 0;
5505         rsurface.lightmapcolor4f_bufferoffset = 0;
5506 }
5507
5508 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a)
5509 {
5510         int texturesurfaceindex;
5511         int i;
5512         float *c, *c2;
5513         if (!rsurface.lightmapcolor4f)
5514                 return;
5515         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5516         {
5517                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5518                 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
5519                 {
5520                         c2[0] = c[0] * r;
5521                         c2[1] = c[1] * g;
5522                         c2[2] = c[2] * b;
5523                         c2[3] = c[3] * a;
5524                 }
5525         }
5526         rsurface.lightmapcolor4f = rsurface.array_color4f;
5527         rsurface.lightmapcolor4f_bufferobject = 0;
5528         rsurface.lightmapcolor4f_bufferoffset = 0;
5529 }
5530
5531 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5532 {
5533         // TODO: optimize
5534         rsurface.lightmapcolor4f = NULL;
5535         rsurface.lightmapcolor4f_bufferobject = 0;
5536         rsurface.lightmapcolor4f_bufferoffset = 0;
5537         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5538         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5539         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5540         GL_Color(r, g, b, a);
5541         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
5542 }
5543
5544 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5545 {
5546         // TODO: optimize applyfog && applycolor case
5547         // just apply fog if necessary, and tint the fog color array if necessary
5548         rsurface.lightmapcolor4f = NULL;
5549         rsurface.lightmapcolor4f_bufferobject = 0;
5550         rsurface.lightmapcolor4f_bufferoffset = 0;
5551         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5552         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5553         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5554         GL_Color(r, g, b, a);
5555         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5556 }
5557
5558 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5559 {
5560         int texturesurfaceindex;
5561         int i;
5562         float *c;
5563         // TODO: optimize
5564         if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
5565         {
5566                 // generate color arrays for the surfaces in this list
5567                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5568                 {
5569                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5570                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
5571                         {
5572                                 if (surface->lightmapinfo->samples)
5573                                 {
5574                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
5575                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
5576                                         VectorScale(lm, scale, c);
5577                                         if (surface->lightmapinfo->styles[1] != 255)
5578                                         {
5579                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
5580                                                 lm += size3;
5581                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
5582                                                 VectorMA(c, scale, lm, c);
5583                                                 if (surface->lightmapinfo->styles[2] != 255)
5584                                                 {
5585                                                         lm += size3;
5586                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
5587                                                         VectorMA(c, scale, lm, c);
5588                                                         if (surface->lightmapinfo->styles[3] != 255)
5589                                                         {
5590                                                                 lm += size3;
5591                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
5592                                                                 VectorMA(c, scale, lm, c);
5593                                                         }
5594                                                 }
5595                                         }
5596                                 }
5597                                 else
5598                                         VectorClear(c);
5599                                 c[3] = 1;
5600                         }
5601                 }
5602                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5603                 rsurface.lightmapcolor4f_bufferobject = 0;
5604                 rsurface.lightmapcolor4f_bufferoffset = 0;
5605         }
5606         else
5607         {
5608                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
5609                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
5610                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
5611         }
5612         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5613         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5614         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5615         GL_Color(r, g, b, a);
5616         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5617 }
5618
5619 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
5620 {
5621         int texturesurfaceindex;
5622         int i;
5623         float f;
5624         float *v, *c, *c2;
5625         vec3_t ambientcolor;
5626         vec3_t diffusecolor;
5627         vec3_t lightdir;
5628         // TODO: optimize
5629         // model lighting
5630         VectorCopy(rsurface.modellight_lightdir, lightdir);
5631         f = 0.5f * r_refdef.lightmapintensity;
5632         ambientcolor[0] = rsurface.modellight_ambient[0] * r * f;
5633         ambientcolor[1] = rsurface.modellight_ambient[1] * g * f;
5634         ambientcolor[2] = rsurface.modellight_ambient[2] * b * f;
5635         diffusecolor[0] = rsurface.modellight_diffuse[0] * r * f;
5636         diffusecolor[1] = rsurface.modellight_diffuse[1] * g * f;
5637         diffusecolor[2] = rsurface.modellight_diffuse[2] * b * f;
5638         if (VectorLength2(diffusecolor) > 0)
5639         {
5640                 // generate color arrays for the surfaces in this list
5641                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5642                 {
5643                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5644                         int numverts = surface->num_vertices;
5645                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
5646                         c2 = rsurface.normal3f + 3 * surface->num_firstvertex;
5647                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
5648                         // q3-style directional shading
5649                         for (i = 0;i < numverts;i++, v += 3, c2 += 3, c += 4)
5650                         {
5651                                 if ((f = DotProduct(c2, lightdir)) > 0)
5652                                         VectorMA(ambientcolor, f, diffusecolor, c);
5653                                 else
5654                                         VectorCopy(ambientcolor, c);
5655                                 c[3] = a;
5656                         }
5657                 }
5658                 r = 1;
5659                 g = 1;
5660                 b = 1;
5661                 a = 1;
5662                 applycolor = false;
5663                 rsurface.lightmapcolor4f = rsurface.array_color4f;
5664                 rsurface.lightmapcolor4f_bufferobject = 0;
5665                 rsurface.lightmapcolor4f_bufferoffset = 0;
5666         }
5667         else
5668         {
5669                 r = ambientcolor[0];
5670                 g = ambientcolor[1];
5671                 b = ambientcolor[2];
5672                 rsurface.lightmapcolor4f = NULL;
5673                 rsurface.lightmapcolor4f_bufferobject = 0;
5674                 rsurface.lightmapcolor4f_bufferoffset = 0;
5675         }
5676         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
5677         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
5678         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
5679         GL_Color(r, g, b, a);
5680         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5681 }
5682
5683 void RSurf_SetupDepthAndCulling(void)
5684 {
5685         // submodels are biased to avoid z-fighting with world surfaces that they
5686         // may be exactly overlapping (avoids z-fighting artifacts on certain
5687         // doors and things in Quake maps)
5688         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
5689         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
5690         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
5691         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
5692 }
5693
5694 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, msurface_t **texturesurfacelist)
5695 {
5696         // transparent sky would be ridiculous
5697         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
5698                 return;
5699         R_SetupGenericShader(false);
5700         if (skyrendernow)
5701         {
5702                 skyrendernow = false;
5703                 // we have to force off the water clipping plane while rendering sky
5704                 R_SetupView(false);
5705                 R_Sky();
5706                 R_SetupView(true);
5707                 // restore entity matrix
5708                 R_Mesh_Matrix(&rsurface.matrix);
5709         }
5710         RSurf_SetupDepthAndCulling();
5711         GL_DepthMask(true);
5712         // LordHavoc: HalfLife maps have freaky skypolys so don't use
5713         // skymasking on them, and Quake3 never did sky masking (unlike
5714         // software Quake and software Quake2), so disable the sky masking
5715         // in Quake3 maps as it causes problems with q3map2 sky tricks,
5716         // and skymasking also looks very bad when noclipping outside the
5717         // level, so don't use it then either.
5718         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
5719         {
5720                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
5721                 R_Mesh_ColorPointer(NULL, 0, 0);
5722                 R_Mesh_ResetTextureState();
5723                 if (skyrendermasked)
5724                 {
5725                         R_SetupDepthOrShadowShader();
5726                         // depth-only (masking)
5727                         GL_ColorMask(0,0,0,0);
5728                         // just to make sure that braindead drivers don't draw
5729                         // anything despite that colormask...
5730                         GL_BlendFunc(GL_ZERO, GL_ONE);
5731                 }
5732                 else
5733                 {
5734                         R_SetupGenericShader(false);
5735                         // fog sky
5736                         GL_BlendFunc(GL_ONE, GL_ZERO);
5737                 }
5738                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
5739                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5740                 if (skyrendermasked)
5741                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5742         }
5743         R_Mesh_ResetTextureState();
5744         GL_Color(1, 1, 1, 1);
5745 }
5746
5747 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5748 {
5749         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
5750                 return;
5751
5752         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
5753         R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
5754         R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
5755         R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
5756         R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
5757         if (rsurface.texture->backgroundcurrentskinframe)
5758         {
5759                 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
5760                 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
5761                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
5762                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
5763         }
5764         R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
5765         R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
5766         R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
5767         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5768                 R_Mesh_ColorPointer(NULL, 0, 0);
5769         else
5770                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5771
5772         if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5773         {
5774                 // render background
5775                 GL_BlendFunc(GL_ONE, GL_ZERO);
5776                 GL_DepthMask(true);
5777                 GL_AlphaTest(false);
5778
5779                 GL_Color(1, 1, 1, 1);
5780                 R_Mesh_ColorPointer(NULL, 0, 0);
5781
5782                 R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
5783                 if (r_glsl_permutation)
5784                 {
5785                         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
5786                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5787                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5788                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5789                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5790                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5791                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5792                 }
5793                 GL_LockArrays(0, 0);
5794
5795                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5796                 GL_DepthMask(false);
5797                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
5798                         R_Mesh_ColorPointer(NULL, 0, 0);
5799                 else
5800                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
5801                 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
5802                 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
5803         }
5804
5805         R_SetupSurfaceShader(vec3_origin, rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
5806         if (!r_glsl_permutation)
5807                 return;
5808
5809         RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
5810         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
5811         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
5812         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
5813         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
5814         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
5815
5816         if (r_glsl_permutation->loc_Texture_Refraction >= 0)
5817         {
5818                 GL_BlendFunc(GL_ONE, GL_ZERO);
5819                 GL_DepthMask(true);
5820                 GL_AlphaTest(false);
5821         }
5822         else
5823         {
5824                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5825                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
5826                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5827         }
5828
5829         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
5830         {
5831                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5832                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5833                 else
5834                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
5835         }
5836         else
5837         {
5838                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
5839                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist, -1, -1, r_glsl_permutation->loc_Texture_Refraction >= 0 ? GL20TU_REFRACTION : -1, r_glsl_permutation->loc_Texture_Reflection >= 0 ? GL20TU_REFLECTION : -1);
5840                 else
5841                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5842         }
5843         GL_LockArrays(0, 0);
5844 }
5845
5846 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5847 {
5848         // OpenGL 1.3 path - anything not completely ancient
5849         int texturesurfaceindex;
5850         qboolean applycolor;
5851         qboolean applyfog;
5852         rmeshstate_t m;
5853         int layerindex;
5854         const texturelayer_t *layer;
5855         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5856
5857         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5858         {
5859                 vec4_t layercolor;
5860                 int layertexrgbscale;
5861                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5862                 {
5863                         if (layerindex == 0)
5864                                 GL_AlphaTest(true);
5865                         else
5866                         {
5867                                 GL_AlphaTest(false);
5868                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5869                         }
5870                 }
5871                 GL_DepthMask(layer->depthmask && writedepth);
5872                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5873                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
5874                 {
5875                         layertexrgbscale = 4;
5876                         VectorScale(layer->color, 0.25f, layercolor);
5877                 }
5878                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
5879                 {
5880                         layertexrgbscale = 2;
5881                         VectorScale(layer->color, 0.5f, layercolor);
5882                 }
5883                 else
5884                 {
5885                         layertexrgbscale = 1;
5886                         VectorScale(layer->color, 1.0f, layercolor);
5887                 }
5888                 layercolor[3] = layer->color[3];
5889                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
5890                 R_Mesh_ColorPointer(NULL, 0, 0);
5891                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5892                 switch (layer->type)
5893                 {
5894                 case TEXTURELAYERTYPE_LITTEXTURE:
5895                         memset(&m, 0, sizeof(m));
5896                         m.tex[0] = R_GetTexture(r_texture_white);
5897                         m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
5898                         m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
5899                         m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
5900                         m.tex[1] = R_GetTexture(layer->texture);
5901                         m.texmatrix[1] = layer->texmatrix;
5902                         m.texrgbscale[1] = layertexrgbscale;
5903                         m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
5904                         m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
5905                         m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
5906                         R_Mesh_TextureState(&m);
5907                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5908                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5909                         else if (rsurface.uselightmaptexture)
5910                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5911                         else
5912                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5913                         break;
5914                 case TEXTURELAYERTYPE_TEXTURE:
5915                         memset(&m, 0, sizeof(m));
5916                         m.tex[0] = R_GetTexture(layer->texture);
5917                         m.texmatrix[0] = layer->texmatrix;
5918                         m.texrgbscale[0] = layertexrgbscale;
5919                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5920                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5921                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5922                         R_Mesh_TextureState(&m);
5923                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
5924                         break;
5925                 case TEXTURELAYERTYPE_FOG:
5926                         memset(&m, 0, sizeof(m));
5927                         m.texrgbscale[0] = layertexrgbscale;
5928                         if (layer->texture)
5929                         {
5930                                 m.tex[0] = R_GetTexture(layer->texture);
5931                                 m.texmatrix[0] = layer->texmatrix;
5932                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
5933                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
5934                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
5935                         }
5936                         R_Mesh_TextureState(&m);
5937                         // generate a color array for the fog pass
5938                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
5939                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
5940                         {
5941                                 int i;
5942                                 float f, *v, *c;
5943                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
5944                                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
5945                                 {
5946                                         f = 1 - FogPoint_Model(v);
5947                                         c[0] = layercolor[0];
5948                                         c[1] = layercolor[1];
5949                                         c[2] = layercolor[2];
5950                                         c[3] = f * layercolor[3];
5951                                 }
5952                         }
5953                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
5954                         break;
5955                 default:
5956                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
5957                 }
5958                 GL_LockArrays(0, 0);
5959         }
5960         CHECKGLERROR
5961         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5962         {
5963                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
5964                 GL_AlphaTest(false);
5965         }
5966 }
5967
5968 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
5969 {
5970         // OpenGL 1.1 - crusty old voodoo path
5971         int texturesurfaceindex;
5972         qboolean applyfog;
5973         rmeshstate_t m;
5974         int layerindex;
5975         const texturelayer_t *layer;
5976         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
5977
5978         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
5979         {
5980                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5981                 {
5982                         if (layerindex == 0)
5983                                 GL_AlphaTest(true);
5984                         else
5985                         {
5986                                 GL_AlphaTest(false);
5987                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
5988                         }
5989                 }
5990                 GL_DepthMask(layer->depthmask && writedepth);
5991                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
5992                 R_Mesh_ColorPointer(NULL, 0, 0);
5993                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
5994                 switch (layer->type)
5995                 {
5996                 case TEXTURELAYERTYPE_LITTEXTURE:
5997                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
5998                         {
5999                                 // two-pass lit texture with 2x rgbscale
6000                                 // first the lightmap pass
6001                                 memset(&m, 0, sizeof(m));
6002                                 m.tex[0] = R_GetTexture(r_texture_white);
6003                                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
6004                                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
6005                                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
6006                                 R_Mesh_TextureState(&m);
6007                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6008                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6009                                 else if (rsurface.uselightmaptexture)
6010                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6011                                 else
6012                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
6013                                 GL_LockArrays(0, 0);
6014                                 // then apply the texture to it
6015                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6016                                 memset(&m, 0, sizeof(m));
6017                                 m.tex[0] = R_GetTexture(layer->texture);
6018                                 m.texmatrix[0] = layer->texmatrix;
6019                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6020                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6021                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6022                                 R_Mesh_TextureState(&m);
6023                                 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
6024                         }
6025                         else
6026                         {
6027                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
6028                                 memset(&m, 0, sizeof(m));
6029                                 m.tex[0] = R_GetTexture(layer->texture);
6030                                 m.texmatrix[0] = layer->texmatrix;
6031                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6032                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6033                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6034                                 R_Mesh_TextureState(&m);
6035                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
6036                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
6037                                 else
6038                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
6039                         }
6040                         break;
6041                 case TEXTURELAYERTYPE_TEXTURE:
6042                         // singletexture unlit texture with transparency support
6043                         memset(&m, 0, sizeof(m));
6044                         m.tex[0] = R_GetTexture(layer->texture);
6045                         m.texmatrix[0] = layer->texmatrix;
6046                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6047                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6048                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6049                         R_Mesh_TextureState(&m);
6050                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
6051                         break;
6052                 case TEXTURELAYERTYPE_FOG:
6053                         // singletexture fogging
6054                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
6055                         if (layer->texture)
6056                         {
6057                                 memset(&m, 0, sizeof(m));
6058                                 m.tex[0] = R_GetTexture(layer->texture);
6059                                 m.texmatrix[0] = layer->texmatrix;
6060                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
6061                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
6062                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
6063                                 R_Mesh_TextureState(&m);
6064                         }
6065                         else
6066                                 R_Mesh_ResetTextureState();
6067                         // generate a color array for the fog pass
6068                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6069                         {
6070                                 int i;
6071                                 float f, *v, *c;
6072                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6073                                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
6074                                 {
6075                                         f = 1 - FogPoint_Model(v);
6076                                         c[0] = layer->color[0];
6077                                         c[1] = layer->color[1];
6078                                         c[2] = layer->color[2];
6079                                         c[3] = f * layer->color[3];
6080                                 }
6081                         }
6082                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6083                         break;
6084                 default:
6085                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
6086                 }
6087                 GL_LockArrays(0, 0);
6088         }
6089         CHECKGLERROR
6090         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
6091         {
6092                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6093                 GL_AlphaTest(false);
6094         }
6095 }
6096
6097 static void R_DrawTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth)
6098 {
6099         CHECKGLERROR
6100         RSurf_SetupDepthAndCulling();
6101         if (r_glsl.integer && gl_support_fragment_shader)
6102                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
6103         else if (gl_combine.integer && r_textureunits.integer >= 2)
6104                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
6105         else
6106                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
6107         CHECKGLERROR
6108 }
6109
6110 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6111 {
6112         int i, j;
6113         int texturenumsurfaces, endsurface;
6114         texture_t *texture;
6115         msurface_t *surface;
6116         msurface_t *texturesurfacelist[1024];
6117
6118         // if the model is static it doesn't matter what value we give for
6119         // wantnormals and wanttangents, so this logic uses only rules applicable
6120         // to a model, knowing that they are meaningless otherwise
6121         if (ent == r_refdef.scene.worldentity)
6122                 RSurf_ActiveWorldEntity();
6123         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6124                 RSurf_ActiveModelEntity(ent, false, false);
6125         else
6126                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
6127
6128         for (i = 0;i < numsurfaces;i = j)
6129         {
6130                 j = i + 1;
6131                 surface = rsurface.modelsurfaces + surfacelist[i];
6132                 texture = surface->texture;
6133                 R_UpdateTextureInfo(ent, texture);
6134                 rsurface.texture = texture->currentframe;
6135                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
6136                 // scan ahead until we find a different texture
6137                 endsurface = min(i + 1024, numsurfaces);
6138                 texturenumsurfaces = 0;
6139                 texturesurfacelist[texturenumsurfaces++] = surface;
6140                 for (;j < endsurface;j++)
6141                 {
6142                         surface = rsurface.modelsurfaces + surfacelist[j];
6143                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
6144                                 break;
6145                         texturesurfacelist[texturenumsurfaces++] = surface;
6146                 }
6147                 // render the range of surfaces
6148                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
6149         }
6150         GL_AlphaTest(false);
6151 }
6152
6153 static void R_ProcessTextureSurfaceList(int texturenumsurfaces, msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
6154 {
6155         CHECKGLERROR
6156         if (depthonly)
6157         {
6158                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
6159                         return;
6160                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
6161                         return;
6162                 RSurf_SetupDepthAndCulling();
6163                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6164                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6165         }
6166         else if (r_showsurfaces.integer)
6167         {
6168                 RSurf_SetupDepthAndCulling();
6169                 GL_DepthTest(true);
6170                 GL_BlendFunc(GL_ONE, GL_ZERO);
6171                 GL_DepthMask(true);
6172                 GL_AlphaTest(false);
6173                 R_Mesh_ColorPointer(NULL, 0, 0);
6174                 R_Mesh_ResetTextureState();
6175                 R_SetupGenericShader(false);
6176                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
6177                 if (!r_refdef.view.showdebug)
6178                 {
6179                         GL_Color(0, 0, 0, 1);
6180                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
6181                 }
6182                 else
6183                         RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
6184         }
6185         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
6186                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
6187         else if (!rsurface.texture->currentnumlayers)
6188                 return;
6189         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) && queueentity)
6190         {
6191                 // transparent surfaces get pushed off into the transparent queue
6192                 int surfacelistindex;
6193                 const msurface_t *surface;
6194                 vec3_t tempcenter, center;
6195                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
6196                 {
6197                         surface = texturesurfacelist[surfacelistindex];
6198                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
6199                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
6200                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
6201                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
6202                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
6203                 }
6204         }
6205         else
6206         {
6207                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
6208                 R_DrawTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
6209         }
6210         CHECKGLERROR
6211 }
6212
6213 void R_QueueSurfaceList(entity_render_t *ent, int numsurfaces, msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes)
6214 {
6215         int i, j;
6216         texture_t *texture;
6217         // if we're rendering water textures (extra scene renders), use a separate loop to avoid burdening the main one
6218         if (addwaterplanes)
6219         {
6220                 for (i = 0;i < numsurfaces;i++)
6221                         if (surfacelist[i]->texture->currentframe->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION))
6222                                 R_Water_AddWaterPlane(surfacelist[i]);
6223                 return;
6224         }
6225         // break the surface list down into batches by texture and use of lightmapping
6226         for (i = 0;i < numsurfaces;i = j)
6227         {
6228                 j = i + 1;
6229                 // texture is the base texture pointer, rsurface.texture is the
6230                 // current frame/skin the texture is directing us to use (for example
6231                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
6232                 // use skin 1 instead)
6233                 texture = surfacelist[i]->texture;
6234                 rsurface.texture = texture->currentframe;
6235                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
6236                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
6237                 {
6238                         // if this texture is not the kind we want, skip ahead to the next one
6239                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
6240                                 ;
6241                         continue;
6242                 }
6243                 // simply scan ahead until we find a different texture or lightmap state
6244                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
6245                         ;
6246                 // render the range of surfaces
6247                 R_ProcessTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
6248         }
6249 }
6250
6251 float locboxvertex3f[6*4*3] =
6252 {
6253         1,0,1, 1,0,0, 1,1,0, 1,1,1,
6254         0,1,1, 0,1,0, 0,0,0, 0,0,1,
6255         1,1,1, 1,1,0, 0,1,0, 0,1,1,
6256         0,0,1, 0,0,0, 1,0,0, 1,0,1,
6257         0,0,1, 1,0,1, 1,1,1, 0,1,1,
6258         1,0,0, 0,0,0, 0,1,0, 1,1,0
6259 };
6260
6261 int locboxelement3i[6*2*3] =
6262 {
6263          0, 1, 2, 0, 2, 3,
6264          4, 5, 6, 4, 6, 7,
6265          8, 9,10, 8,10,11,
6266         12,13,14, 12,14,15,
6267         16,17,18, 16,18,19,
6268         20,21,22, 20,22,23
6269 };
6270
6271 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6272 {
6273         int i, j;
6274         cl_locnode_t *loc = (cl_locnode_t *)ent;
6275         vec3_t mins, size;
6276         float vertex3f[6*4*3];
6277         CHECKGLERROR
6278         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6279         GL_DepthMask(false);
6280         GL_DepthRange(0, 1);
6281         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6282         GL_DepthTest(true);
6283         GL_CullFace(GL_NONE);
6284         R_Mesh_Matrix(&identitymatrix);
6285
6286         R_Mesh_VertexPointer(vertex3f, 0, 0);
6287         R_Mesh_ColorPointer(NULL, 0, 0);
6288         R_Mesh_ResetTextureState();
6289         R_SetupGenericShader(false);
6290
6291         i = surfacelist[0];
6292         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6293                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6294                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
6295                         surfacelist[0] < 0 ? 0.5f : 0.125f);
6296
6297         if (VectorCompare(loc->mins, loc->maxs))
6298         {
6299                 VectorSet(size, 2, 2, 2);
6300                 VectorMA(loc->mins, -0.5f, size, mins);
6301         }
6302         else
6303         {
6304                 VectorCopy(loc->mins, mins);
6305                 VectorSubtract(loc->maxs, loc->mins, size);
6306         }
6307
6308         for (i = 0;i < 6*4*3;)
6309                 for (j = 0;j < 3;j++, i++)
6310                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
6311
6312         R_Mesh_Draw(0, 6*4, 6*2, locboxelement3i, 0, 0);
6313 }
6314
6315 void R_DrawLocs(void)
6316 {
6317         int index;
6318         cl_locnode_t *loc, *nearestloc;
6319         vec3_t center;
6320         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
6321         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
6322         {
6323                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
6324                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
6325         }
6326 }
6327
6328 void R_DrawDebugModel(entity_render_t *ent)
6329 {
6330         int i, j, k, l, flagsmask;
6331         const int *elements;
6332         q3mbrush_t *brush;
6333         msurface_t *surface;
6334         model_t *model = ent->model;
6335         vec3_t v;
6336
6337         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WATER | MATERIALFLAG_WALL;
6338
6339         R_Mesh_ColorPointer(NULL, 0, 0);
6340         R_Mesh_ResetTextureState();
6341         R_SetupGenericShader(false);
6342         GL_DepthRange(0, 1);
6343         GL_DepthTest(!r_showdisabledepthtest.integer);
6344         GL_DepthMask(false);
6345         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6346
6347         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
6348         {
6349                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
6350                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
6351                 {
6352                         if (brush->colbrushf && brush->colbrushf->numtriangles)
6353                         {
6354                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
6355                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6356                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, brush->colbrushf->numtriangles, brush->colbrushf->elements, 0, 0);
6357                         }
6358                 }
6359                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
6360                 {
6361                         if (surface->num_collisiontriangles)
6362                         {
6363                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
6364                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
6365                                 R_Mesh_Draw(0, surface->num_collisionvertices, surface->num_collisiontriangles, surface->data_collisionelement3i, 0, 0);
6366                         }
6367                 }
6368         }
6369
6370         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6371
6372         if (r_showtris.integer || r_shownormals.integer)
6373         {
6374                 if (r_showdisabledepthtest.integer)
6375                 {
6376                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6377                         GL_DepthMask(false);
6378                 }
6379                 else
6380                 {
6381                         GL_BlendFunc(GL_ONE, GL_ZERO);
6382                         GL_DepthMask(true);
6383                 }
6384                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
6385                 {
6386                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
6387                                 continue;
6388                         rsurface.texture = surface->texture->currentframe;
6389                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
6390                         {
6391                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
6392                                 if (r_showtris.value > 0)
6393                                 {
6394                                         if (!rsurface.texture->currentlayers->depthmask)
6395                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
6396                                         else if (ent == r_refdef.scene.worldentity)
6397                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
6398                                         else
6399                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
6400                                         elements = (ent->model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
6401                                         CHECKGLERROR
6402                                         qglBegin(GL_LINES);
6403                                         for (k = 0;k < surface->num_triangles;k++, elements += 3)
6404                                         {
6405 #define GLVERTEXELEMENT(n) qglVertex3f(rsurface.vertex3f[elements[n]*3+0], rsurface.vertex3f[elements[n]*3+1], rsurface.vertex3f[elements[n]*3+2])
6406                                                 GLVERTEXELEMENT(0);GLVERTEXELEMENT(1);
6407                                                 GLVERTEXELEMENT(1);GLVERTEXELEMENT(2);
6408                                                 GLVERTEXELEMENT(2);GLVERTEXELEMENT(0);
6409                                         }
6410                                         qglEnd();
6411                                         CHECKGLERROR
6412                                 }
6413                                 if (r_shownormals.value > 0)
6414                                 {
6415                                         qglBegin(GL_LINES);
6416                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6417                                         {
6418                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6419                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
6420                                                 qglVertex3f(v[0], v[1], v[2]);
6421                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
6422                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6423                                                 qglVertex3f(v[0], v[1], v[2]);
6424                                         }
6425                                         qglEnd();
6426                                         CHECKGLERROR
6427                                         qglBegin(GL_LINES);
6428                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6429                                         {
6430                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6431                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
6432                                                 qglVertex3f(v[0], v[1], v[2]);
6433                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
6434                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6435                                                 qglVertex3f(v[0], v[1], v[2]);
6436                                         }
6437                                         qglEnd();
6438                                         CHECKGLERROR
6439                                         qglBegin(GL_LINES);
6440                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
6441                                         {
6442                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
6443                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
6444                                                 qglVertex3f(v[0], v[1], v[2]);
6445                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
6446                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
6447                                                 qglVertex3f(v[0], v[1], v[2]);
6448                                         }
6449                                         qglEnd();
6450                                         CHECKGLERROR
6451                                 }
6452                         }
6453                 }
6454                 rsurface.texture = NULL;
6455         }
6456 }
6457
6458 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
6459 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6460 {
6461         int i, j, endj, f, flagsmask;
6462         msurface_t *surface;
6463         texture_t *t;
6464         model_t *model = r_refdef.scene.worldmodel;
6465         const int maxsurfacelist = 1024;
6466         int numsurfacelist = 0;
6467         msurface_t *surfacelist[1024];
6468         if (model == NULL)
6469                 return;
6470
6471         RSurf_ActiveWorldEntity();
6472
6473         // update light styles on this submodel
6474         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6475         {
6476                 model_brush_lightstyleinfo_t *style;
6477                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6478                 {
6479                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
6480                         {
6481                                 msurface_t *surfaces = model->data_surfaces;
6482                                 int *list = style->surfacelist;
6483                                 style->value = r_refdef.scene.lightstylevalue[style->style];
6484                                 for (j = 0;j < style->numsurfaces;j++)
6485                                         surfaces[list[j]].cached_dlight = true;
6486                         }
6487                 }
6488         }
6489
6490         R_UpdateAllTextureInfo(r_refdef.scene.worldentity);
6491         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6492
6493         if (debug)
6494         {
6495                 R_DrawDebugModel(r_refdef.scene.worldentity);
6496                 return;
6497         }
6498
6499         f = 0;
6500         t = NULL;
6501         rsurface.uselightmaptexture = false;
6502         rsurface.texture = NULL;
6503         rsurface.rtlight = NULL;
6504         numsurfacelist = 0;
6505         j = model->firstmodelsurface;
6506         endj = j + model->nummodelsurfaces;
6507         while (j < endj)
6508         {
6509                 // quickly skip over non-visible surfaces
6510                 for (;j < endj && !r_refdef.viewcache.world_surfacevisible[j];j++)
6511                         ;
6512                 // quickly iterate over visible surfaces
6513                 for (;j < endj && r_refdef.viewcache.world_surfacevisible[j];j++)
6514                 {
6515                         // process this surface
6516                         surface = model->data_surfaces + j;
6517                         // if this surface fits the criteria, add it to the list
6518                         if (surface->num_triangles)
6519                         {
6520                                 // if lightmap parameters changed, rebuild lightmap texture
6521                                 if (surface->cached_dlight)
6522                                         R_BuildLightMap(r_refdef.scene.worldentity, surface);
6523                                 // add face to draw list
6524                                 surfacelist[numsurfacelist++] = surface;
6525                                 r_refdef.stats.world_triangles += surface->num_triangles;
6526                                 if (numsurfacelist >= maxsurfacelist)
6527                                 {
6528                                         r_refdef.stats.world_surfaces += numsurfacelist;
6529                                         R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6530                                         numsurfacelist = 0;
6531                                 }
6532                         }
6533                 }
6534         }
6535         r_refdef.stats.world_surfaces += numsurfacelist;
6536         if (numsurfacelist)
6537                 R_QueueSurfaceList(r_refdef.scene.worldentity, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6538         GL_AlphaTest(false);
6539 }
6540
6541 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean addwaterplanes, qboolean debug)
6542 {
6543         int i, j, f, flagsmask;
6544         msurface_t *surface, *endsurface;
6545         texture_t *t;
6546         model_t *model = ent->model;
6547         const int maxsurfacelist = 1024;
6548         int numsurfacelist = 0;
6549         msurface_t *surfacelist[1024];
6550         if (model == NULL)
6551                 return;
6552
6553         // if the model is static it doesn't matter what value we give for
6554         // wantnormals and wanttangents, so this logic uses only rules applicable
6555         // to a model, knowing that they are meaningless otherwise
6556         if (ent == r_refdef.scene.worldentity)
6557                 RSurf_ActiveWorldEntity();
6558         else if ((ent->effects & EF_FULLBRIGHT) || r_showsurfaces.integer || VectorLength2(ent->modellight_diffuse) < (1.0f / 256.0f))
6559                 RSurf_ActiveModelEntity(ent, false, false);
6560         else
6561                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
6562
6563         // update light styles
6564         if (!skysurfaces && !depthonly && !addwaterplanes && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
6565         {
6566                 model_brush_lightstyleinfo_t *style;
6567                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
6568                 {
6569                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
6570                         {
6571                                 msurface_t *surfaces = model->data_surfaces;
6572                                 int *list = style->surfacelist;
6573                                 style->value = r_refdef.scene.lightstylevalue[style->style];
6574                                 for (j = 0;j < style->numsurfaces;j++)
6575                                         surfaces[list[j]].cached_dlight = true;
6576                         }
6577                 }
6578         }
6579
6580         R_UpdateAllTextureInfo(ent);
6581         flagsmask = addwaterplanes ? (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) : (skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL));
6582
6583         if (debug)
6584         {
6585                 R_DrawDebugModel(ent);
6586                 return;
6587         }
6588
6589         f = 0;
6590         t = NULL;
6591         rsurface.uselightmaptexture = false;
6592         rsurface.texture = NULL;
6593         rsurface.rtlight = NULL;
6594         numsurfacelist = 0;
6595         surface = model->data_surfaces + model->firstmodelsurface;
6596         endsurface = surface + model->nummodelsurfaces;
6597         for (;surface < endsurface;surface++)
6598         {
6599                 // if this surface fits the criteria, add it to the list
6600                 if (surface->num_triangles)
6601                 {
6602                         // if lightmap parameters changed, rebuild lightmap texture
6603                         if (surface->cached_dlight)
6604                                 R_BuildLightMap(ent, surface);
6605                         // add face to draw list
6606                         surfacelist[numsurfacelist++] = surface;
6607                         r_refdef.stats.entities_triangles += surface->num_triangles;
6608                         if (numsurfacelist >= maxsurfacelist)
6609                         {
6610                                 r_refdef.stats.entities_surfaces += numsurfacelist;
6611                                 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6612                                 numsurfacelist = 0;
6613                         }
6614                 }
6615         }
6616         r_refdef.stats.entities_surfaces += numsurfacelist;
6617         if (numsurfacelist)
6618                 R_QueueSurfaceList(ent, numsurfacelist, surfacelist, flagsmask, writedepth, depthonly, addwaterplanes);
6619         GL_AlphaTest(false);
6620 }