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