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