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