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