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