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