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