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