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