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