]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
resize view cache each frame instead of at newmap
[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[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 256
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_ResizeViewCache(void)
2871 {
2872         int numentities = r_refdef.scene.numentities;
2873         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
2874         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
2875         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
2876         if (r_refdef.viewcache.maxentities < numentities)
2877         {
2878                 r_refdef.viewcache.maxentities = numentities;
2879                 if (r_refdef.viewcache.entityvisible)
2880                         Mem_Free(r_refdef.viewcache.entityvisible);
2881                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
2882         }
2883         if (r_refdef.viewcache.world_numclusters != numclusters)
2884         {
2885                 r_refdef.viewcache.world_numclusters = numclusters;
2886                 if (r_refdef.viewcache.world_pvsbits)
2887                         Mem_Free(r_refdef.viewcache.world_pvsbits);
2888                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, (r_refdef.viewcache.world_numclusters+7)>>3);
2889         }
2890         if (r_refdef.viewcache.world_numleafs != numleafs)
2891         {
2892                 r_refdef.viewcache.world_numleafs = numleafs;
2893                 if (r_refdef.viewcache.world_leafvisible)
2894                         Mem_Free(r_refdef.viewcache.world_leafvisible);
2895                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
2896         }
2897         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
2898         {
2899                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
2900                 if (r_refdef.viewcache.world_surfacevisible)
2901                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
2902                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
2903         }
2904 }
2905
2906 void gl_main_start(void)
2907 {
2908         r_numqueries = 0;
2909         r_maxqueries = 0;
2910         memset(r_queries, 0, sizeof(r_queries));
2911
2912         r_qwskincache = NULL;
2913         r_qwskincache_size = 0;
2914
2915         // set up r_skinframe loading system for textures
2916         memset(&r_skinframe, 0, sizeof(r_skinframe));
2917         r_skinframe.loadsequence = 1;
2918         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
2919
2920         r_main_texturepool = R_AllocTexturePool();
2921         R_BuildBlankTextures();
2922         R_BuildNoTexture();
2923         if (gl_texturecubemap)
2924         {
2925                 R_BuildWhiteCube();
2926                 R_BuildNormalizationCube();
2927         }
2928         r_texture_fogattenuation = NULL;
2929         r_texture_gammaramps = NULL;
2930         //r_texture_fogintensity = NULL;
2931         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2932         memset(&r_waterstate, 0, sizeof(r_waterstate));
2933         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
2934         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
2935         memset(&r_svbsp, 0, sizeof (r_svbsp));
2936
2937         r_refdef.fogmasktable_density = 0;
2938 }
2939
2940 extern rtexture_t *loadingscreentexture;
2941 void gl_main_shutdown(void)
2942 {
2943         R_Main_FreeViewCache();
2944
2945         if (r_maxqueries)
2946                 qglDeleteQueriesARB(r_maxqueries, r_queries);
2947
2948         r_numqueries = 0;
2949         r_maxqueries = 0;
2950         memset(r_queries, 0, sizeof(r_queries));
2951
2952         r_qwskincache = NULL;
2953         r_qwskincache_size = 0;
2954
2955         // clear out the r_skinframe state
2956         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
2957         memset(&r_skinframe, 0, sizeof(r_skinframe));
2958
2959         if (r_svbsp.nodes)
2960                 Mem_Free(r_svbsp.nodes);
2961         memset(&r_svbsp, 0, sizeof (r_svbsp));
2962         R_FreeTexturePool(&r_main_texturepool);
2963         loadingscreentexture = NULL;
2964         r_texture_blanknormalmap = NULL;
2965         r_texture_white = NULL;
2966         r_texture_grey128 = NULL;
2967         r_texture_black = NULL;
2968         r_texture_whitecube = NULL;
2969         r_texture_normalizationcube = NULL;
2970         r_texture_fogattenuation = NULL;
2971         r_texture_gammaramps = NULL;
2972         //r_texture_fogintensity = NULL;
2973         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
2974         memset(&r_waterstate, 0, sizeof(r_waterstate));
2975         R_GLSL_Restart_f();
2976 }
2977
2978 extern void CL_ParseEntityLump(char *entitystring);
2979 void gl_main_newmap(void)
2980 {
2981         // FIXME: move this code to client
2982         int l;
2983         char *entities, entname[MAX_QPATH];
2984         if (r_qwskincache)
2985                 Mem_Free(r_qwskincache);
2986         r_qwskincache = NULL;
2987         r_qwskincache_size = 0;
2988         if (cl.worldmodel)
2989         {
2990                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
2991                 l = (int)strlen(entname) - 4;
2992                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
2993                 {
2994                         memcpy(entname + l, ".ent", 5);
2995                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
2996                         {
2997                                 CL_ParseEntityLump(entities);
2998                                 Mem_Free(entities);
2999                                 return;
3000                         }
3001                 }
3002                 if (cl.worldmodel->brush.entities)
3003                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
3004         }
3005         R_Main_FreeViewCache();
3006 }
3007
3008 void GL_Main_Init(void)
3009 {
3010         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3011
3012         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
3013         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
3014         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
3015         if (gamemode == GAME_NEHAHRA)
3016         {
3017                 Cvar_RegisterVariable (&gl_fogenable);
3018                 Cvar_RegisterVariable (&gl_fogdensity);
3019                 Cvar_RegisterVariable (&gl_fogred);
3020                 Cvar_RegisterVariable (&gl_foggreen);
3021                 Cvar_RegisterVariable (&gl_fogblue);
3022                 Cvar_RegisterVariable (&gl_fogstart);
3023                 Cvar_RegisterVariable (&gl_fogend);
3024                 Cvar_RegisterVariable (&gl_skyclip);
3025         }
3026         Cvar_RegisterVariable(&r_motionblur);
3027         Cvar_RegisterVariable(&r_motionblur_maxblur);
3028         Cvar_RegisterVariable(&r_motionblur_bmin);
3029         Cvar_RegisterVariable(&r_motionblur_vmin);
3030         Cvar_RegisterVariable(&r_motionblur_vmax);
3031         Cvar_RegisterVariable(&r_motionblur_vcoeff);
3032         Cvar_RegisterVariable(&r_motionblur_randomize);
3033         Cvar_RegisterVariable(&r_damageblur);
3034         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
3035         Cvar_RegisterVariable(&r_equalize_entities_minambient);
3036         Cvar_RegisterVariable(&r_equalize_entities_by);
3037         Cvar_RegisterVariable(&r_equalize_entities_to);
3038         Cvar_RegisterVariable(&r_animcache);
3039         Cvar_RegisterVariable(&r_depthfirst);
3040         Cvar_RegisterVariable(&r_useinfinitefarclip);
3041         Cvar_RegisterVariable(&r_farclip_base);
3042         Cvar_RegisterVariable(&r_farclip_world);
3043         Cvar_RegisterVariable(&r_nearclip);
3044         Cvar_RegisterVariable(&r_showbboxes);
3045         Cvar_RegisterVariable(&r_showsurfaces);
3046         Cvar_RegisterVariable(&r_showtris);
3047         Cvar_RegisterVariable(&r_shownormals);
3048         Cvar_RegisterVariable(&r_showlighting);
3049         Cvar_RegisterVariable(&r_showshadowvolumes);
3050         Cvar_RegisterVariable(&r_showcollisionbrushes);
3051         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
3052         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
3053         Cvar_RegisterVariable(&r_showdisabledepthtest);
3054         Cvar_RegisterVariable(&r_drawportals);
3055         Cvar_RegisterVariable(&r_drawentities);
3056         Cvar_RegisterVariable(&r_cullentities_trace);
3057         Cvar_RegisterVariable(&r_cullentities_trace_samples);
3058         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
3059         Cvar_RegisterVariable(&r_cullentities_trace_delay);
3060         Cvar_RegisterVariable(&r_drawviewmodel);
3061         Cvar_RegisterVariable(&r_speeds);
3062         Cvar_RegisterVariable(&r_fullbrights);
3063         Cvar_RegisterVariable(&r_wateralpha);
3064         Cvar_RegisterVariable(&r_dynamic);
3065         Cvar_RegisterVariable(&r_fullbright);
3066         Cvar_RegisterVariable(&r_shadows);
3067         Cvar_RegisterVariable(&r_shadows_darken);
3068         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
3069         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
3070         Cvar_RegisterVariable(&r_shadows_throwdistance);
3071         Cvar_RegisterVariable(&r_shadows_throwdirection);
3072         Cvar_RegisterVariable(&r_q1bsp_skymasking);
3073         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
3074         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
3075         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
3076         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
3077         Cvar_RegisterVariable(&r_fog_exp2);
3078         Cvar_RegisterVariable(&r_drawfog);
3079         Cvar_RegisterVariable(&r_textureunits);
3080         Cvar_RegisterVariable(&r_glsl);
3081         Cvar_RegisterVariable(&r_glsl_deluxemapping);
3082         Cvar_RegisterVariable(&r_glsl_offsetmapping);
3083         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
3084         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
3085         Cvar_RegisterVariable(&r_glsl_postprocess);
3086         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
3087         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
3088         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
3089         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
3090         Cvar_RegisterVariable(&r_glsl_usegeneric);
3091         Cvar_RegisterVariable(&r_water);
3092         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
3093         Cvar_RegisterVariable(&r_water_clippingplanebias);
3094         Cvar_RegisterVariable(&r_water_refractdistort);
3095         Cvar_RegisterVariable(&r_water_reflectdistort);
3096         Cvar_RegisterVariable(&r_lerpsprites);
3097         Cvar_RegisterVariable(&r_lerpmodels);
3098         Cvar_RegisterVariable(&r_lerplightstyles);
3099         Cvar_RegisterVariable(&r_waterscroll);
3100         Cvar_RegisterVariable(&r_bloom);
3101         Cvar_RegisterVariable(&r_bloom_colorscale);
3102         Cvar_RegisterVariable(&r_bloom_brighten);
3103         Cvar_RegisterVariable(&r_bloom_blur);
3104         Cvar_RegisterVariable(&r_bloom_resolution);
3105         Cvar_RegisterVariable(&r_bloom_colorexponent);
3106         Cvar_RegisterVariable(&r_bloom_colorsubtract);
3107         Cvar_RegisterVariable(&r_hdr);
3108         Cvar_RegisterVariable(&r_hdr_scenebrightness);
3109         Cvar_RegisterVariable(&r_hdr_glowintensity);
3110         Cvar_RegisterVariable(&r_hdr_range);
3111         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
3112         Cvar_RegisterVariable(&developer_texturelogging);
3113         Cvar_RegisterVariable(&gl_lightmaps);
3114         Cvar_RegisterVariable(&r_test);
3115         Cvar_RegisterVariable(&r_batchmode);
3116         Cvar_RegisterVariable(&r_glsl_saturation);
3117         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
3118                 Cvar_SetValue("r_fullbrights", 0);
3119         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
3120
3121         Cvar_RegisterVariable(&r_track_sprites);
3122         Cvar_RegisterVariable(&r_track_sprites_flags);
3123         Cvar_RegisterVariable(&r_track_sprites_scalew);
3124         Cvar_RegisterVariable(&r_track_sprites_scaleh);
3125 }
3126
3127 extern void R_Textures_Init(void);
3128 extern void GL_Draw_Init(void);
3129 extern void GL_Main_Init(void);
3130 extern void R_Shadow_Init(void);
3131 extern void R_Sky_Init(void);
3132 extern void GL_Surf_Init(void);
3133 extern void R_Particles_Init(void);
3134 extern void R_Explosion_Init(void);
3135 extern void gl_backend_init(void);
3136 extern void Sbar_Init(void);
3137 extern void R_LightningBeams_Init(void);
3138 extern void Mod_RenderInit(void);
3139
3140 void Render_Init(void)
3141 {
3142         gl_backend_init();
3143         R_Textures_Init();
3144         GL_Main_Init();
3145         GL_Draw_Init();
3146         R_Shadow_Init();
3147         R_Sky_Init();
3148         GL_Surf_Init();
3149         Sbar_Init();
3150         R_Particles_Init();
3151         R_Explosion_Init();
3152         R_LightningBeams_Init();
3153         Mod_RenderInit();
3154 }
3155
3156 /*
3157 ===============
3158 GL_Init
3159 ===============
3160 */
3161 extern char *ENGINE_EXTENSIONS;
3162 void GL_Init (void)
3163 {
3164         gl_renderer = (const char *)qglGetString(GL_RENDERER);
3165         gl_vendor = (const char *)qglGetString(GL_VENDOR);
3166         gl_version = (const char *)qglGetString(GL_VERSION);
3167         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
3168
3169         if (!gl_extensions)
3170                 gl_extensions = "";
3171         if (!gl_platformextensions)
3172                 gl_platformextensions = "";
3173
3174         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
3175         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
3176         Con_Printf("GL_VERSION: %s\n", gl_version);
3177         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
3178         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
3179
3180         VID_CheckExtensions();
3181
3182         // LordHavoc: report supported extensions
3183         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
3184
3185         // clear to black (loading plaque will be seen over this)
3186         CHECKGLERROR
3187         qglClearColor(0,0,0,1);CHECKGLERROR
3188         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
3189 }
3190
3191 int R_CullBox(const vec3_t mins, const vec3_t maxs)
3192 {
3193         int i;
3194         mplane_t *p;
3195         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3196         {
3197                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
3198                 if (i == 4)
3199                         continue;
3200                 p = r_refdef.view.frustum + i;
3201                 switch(p->signbits)
3202                 {
3203                 default:
3204                 case 0:
3205                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3206                                 return true;
3207                         break;
3208                 case 1:
3209                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3210                                 return true;
3211                         break;
3212                 case 2:
3213                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3214                                 return true;
3215                         break;
3216                 case 3:
3217                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3218                                 return true;
3219                         break;
3220                 case 4:
3221                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3222                                 return true;
3223                         break;
3224                 case 5:
3225                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3226                                 return true;
3227                         break;
3228                 case 6:
3229                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3230                                 return true;
3231                         break;
3232                 case 7:
3233                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3234                                 return true;
3235                         break;
3236                 }
3237         }
3238         return false;
3239 }
3240
3241 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
3242 {
3243         int i;
3244         const mplane_t *p;
3245         for (i = 0;i < numplanes;i++)
3246         {
3247                 p = planes + i;
3248                 switch(p->signbits)
3249                 {
3250                 default:
3251                 case 0:
3252                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3253                                 return true;
3254                         break;
3255                 case 1:
3256                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
3257                                 return true;
3258                         break;
3259                 case 2:
3260                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3261                                 return true;
3262                         break;
3263                 case 3:
3264                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
3265                                 return true;
3266                         break;
3267                 case 4:
3268                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3269                                 return true;
3270                         break;
3271                 case 5:
3272                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
3273                                 return true;
3274                         break;
3275                 case 6:
3276                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3277                                 return true;
3278                         break;
3279                 case 7:
3280                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
3281                                 return true;
3282                         break;
3283                 }
3284         }
3285         return false;
3286 }
3287
3288 //==================================================================================
3289
3290 // LordHavoc: animcache written by Echon, refactored and reformatted by me
3291
3292 /**
3293  * Animation cache helps save re-animating a player mesh if it's re-rendered again in a given frame
3294  * (reflections, lighting, etc). All animation cache becomes invalid on the next frame and is flushed
3295  * (well, over-wrote). The memory for each cache is kept around to save on allocation thrashing.
3296  */
3297
3298 typedef struct r_animcache_entity_s
3299 {
3300         float *vertex3f;
3301         float *normal3f;
3302         float *svector3f;
3303         float *tvector3f;
3304         int maxvertices;
3305         qboolean wantnormals;
3306         qboolean wanttangents;
3307 }
3308 r_animcache_entity_t;
3309
3310 typedef struct r_animcache_s
3311 {
3312         r_animcache_entity_t entity[MAX_EDICTS];
3313         int maxindex;
3314         int currentindex;
3315 }
3316 r_animcache_t;
3317
3318 static r_animcache_t r_animcachestate;
3319
3320 void R_AnimCache_Free(void)
3321 {
3322         int idx;
3323         for (idx=0 ; idx<r_animcachestate.maxindex ; idx++)
3324         {
3325                 r_animcachestate.entity[idx].maxvertices = 0;
3326                 Mem_Free(r_animcachestate.entity[idx].vertex3f);
3327                 r_animcachestate.entity[idx].vertex3f = NULL;
3328                 r_animcachestate.entity[idx].normal3f = NULL;
3329                 r_animcachestate.entity[idx].svector3f = NULL;
3330                 r_animcachestate.entity[idx].tvector3f = NULL;
3331         }
3332         r_animcachestate.currentindex = 0;
3333         r_animcachestate.maxindex = 0;
3334 }
3335
3336 void R_AnimCache_ResizeEntityCache(const int cacheIdx, const int numvertices)
3337 {
3338         int arraySize;
3339         float *base;
3340         r_animcache_entity_t *cache = &r_animcachestate.entity[cacheIdx];
3341
3342         if (cache->maxvertices >= numvertices)
3343                 return;
3344
3345         // Release existing memory
3346         if (cache->vertex3f)
3347                 Mem_Free(cache->vertex3f);
3348
3349         // Pad by 1024 verts
3350         cache->maxvertices = (numvertices + 1023) & ~1023;
3351         arraySize = cache->maxvertices * 3;
3352
3353         // Allocate, even if we don't need this memory in this instance it will get ignored and potentially used later
3354         base = (float *)Mem_Alloc(r_main_mempool, arraySize * sizeof(float) * 4);
3355         r_animcachestate.entity[cacheIdx].vertex3f = base;
3356         r_animcachestate.entity[cacheIdx].normal3f = base + arraySize;
3357         r_animcachestate.entity[cacheIdx].svector3f = base + arraySize*2;
3358         r_animcachestate.entity[cacheIdx].tvector3f = base + arraySize*3;
3359
3360 //      Con_Printf("allocated cache for %i (%f KB)\n", cacheIdx, (arraySize*sizeof(float)*4)/1024.0f);
3361 }
3362
3363 void R_AnimCache_NewFrame(void)
3364 {
3365         int i;
3366
3367         if (r_animcache.integer && r_drawentities.integer)
3368                 r_animcachestate.maxindex = sizeof(r_animcachestate.entity) / sizeof(r_animcachestate.entity[0]);
3369         else if (r_animcachestate.maxindex)
3370                 R_AnimCache_Free();
3371
3372         r_animcachestate.currentindex = 0;
3373
3374         for (i = 0;i < r_refdef.scene.numentities;i++)
3375                 r_refdef.scene.entities[i]->animcacheindex = -1;
3376 }
3377
3378 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
3379 {
3380         dp_model_t *model = ent->model;
3381         r_animcache_entity_t *c;
3382         // see if it's already cached this frame
3383         if (ent->animcacheindex >= 0)
3384         {
3385                 // add normals/tangents if needed
3386                 c = r_animcachestate.entity + ent->animcacheindex;
3387                 if (c->wantnormals)
3388                         wantnormals = false;
3389                 if (c->wanttangents)
3390                         wanttangents = false;
3391                 if (wantnormals || wanttangents)
3392                         model->AnimateVertices(model, ent->frameblend, NULL, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3393         }
3394         else
3395         {
3396                 // see if this ent is worth caching
3397                 if (r_animcachestate.maxindex <= r_animcachestate.currentindex)
3398                         return false;
3399                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0))
3400                         return false;
3401                 // assign it a cache entry and make sure the arrays are big enough
3402                 R_AnimCache_ResizeEntityCache(r_animcachestate.currentindex, model->surfmesh.num_vertices);
3403                 ent->animcacheindex = r_animcachestate.currentindex++;
3404                 c = r_animcachestate.entity + ent->animcacheindex;
3405                 c->wantnormals = wantnormals;
3406                 c->wanttangents = wanttangents;
3407                 model->AnimateVertices(model, ent->frameblend, c->vertex3f, wantnormals ? c->normal3f : NULL, wanttangents ? c->svector3f : NULL, wanttangents ? c->tvector3f : NULL);
3408         }
3409         return true;
3410 }
3411
3412 void R_AnimCache_CacheVisibleEntities(void)
3413 {
3414         int i;
3415         qboolean wantnormals;
3416         qboolean wanttangents;
3417
3418         if (!r_animcachestate.maxindex)
3419                 return;
3420
3421         wantnormals = !r_showsurfaces.integer;
3422         wanttangents = !r_showsurfaces.integer && (r_glsl.integer || r_refdef.scene.rtworld || r_refdef.scene.rtdlight);
3423
3424         // TODO: thread this?
3425
3426         for (i = 0;i < r_refdef.scene.numentities;i++)
3427         {
3428                 if (!r_refdef.viewcache.entityvisible[i])
3429                         continue;
3430                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
3431         }
3432 }
3433
3434 //==================================================================================
3435
3436 static void R_View_UpdateEntityLighting (void)
3437 {
3438         int i;
3439         entity_render_t *ent;
3440         vec3_t tempdiffusenormal, avg;
3441         vec_t f, fa, fd, fdd;
3442
3443         for (i = 0;i < r_refdef.scene.numentities;i++)
3444         {
3445                 ent = r_refdef.scene.entities[i];
3446
3447                 // skip unseen models
3448                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
3449                         continue;
3450
3451                 // skip bsp models
3452                 if (ent->model && ent->model->brush.num_leafs)
3453                 {
3454                         // TODO: use modellight for r_ambient settings on world?
3455                         VectorSet(ent->modellight_ambient, 0, 0, 0);
3456                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
3457                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
3458                         continue;
3459                 }
3460
3461                 // fetch the lighting from the worldmodel data
3462                 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));
3463                 VectorClear(ent->modellight_diffuse);
3464                 VectorClear(tempdiffusenormal);
3465                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
3466                 {
3467                         vec3_t org;
3468                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
3469                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
3470                         if(ent->flags & RENDER_EQUALIZE)
3471                         {
3472                                 // first fix up ambient lighting...
3473                                 if(r_equalize_entities_minambient.value > 0)
3474                                 {
3475                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
3476                                         if(fd > 0)
3477                                         {
3478                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
3479                                                 if(fa < r_equalize_entities_minambient.value * fd)
3480                                                 {
3481                                                         // solve:
3482                                                         //   fa'/fd' = minambient
3483                                                         //   fa'+0.25*fd' = fa+0.25*fd
3484                                                         //   ...
3485                                                         //   fa' = fd' * minambient
3486                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
3487                                                         //   ...
3488                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
3489                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
3490                                                         //   ...
3491                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
3492                                                         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
3493                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
3494                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3495                                                 }
3496                                         }
3497                                 }
3498
3499                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
3500                                 {
3501                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
3502                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
3503                                         if(f > 0)
3504                                         {
3505                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
3506                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
3507                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
3508                                         }
3509                                 }
3510                         }
3511                 }
3512                 else // highly rare
3513                         VectorSet(ent->modellight_ambient, 1, 1, 1);
3514
3515                 // move the light direction into modelspace coordinates for lighting code
3516                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
3517                 if(VectorLength2(ent->modellight_lightdir) == 0)
3518                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
3519                 VectorNormalize(ent->modellight_lightdir);
3520         }
3521 }
3522
3523 #define MAX_LINEOFSIGHTTRACES 64
3524
3525 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
3526 {
3527         int i;
3528         vec3_t boxmins, boxmaxs;
3529         vec3_t start;
3530         vec3_t end;
3531         dp_model_t *model = r_refdef.scene.worldmodel;
3532         
3533         if (!model || !model->brush.TraceLineOfSight)
3534                 return true;
3535
3536         // expand the box a little
3537         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
3538         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
3539         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
3540         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
3541         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
3542         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
3543
3544         // try center
3545         VectorCopy(eye, start);
3546         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
3547         if (model->brush.TraceLineOfSight(model, start, end))
3548                 return true;
3549
3550         // try various random positions
3551         for (i = 0;i < numsamples;i++)
3552         {
3553                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
3554                 if (model->brush.TraceLineOfSight(model, start, end))
3555                         return true;
3556         }
3557
3558         return false;
3559 }
3560
3561
3562 static void R_View_UpdateEntityVisible (void)
3563 {
3564         int i, renderimask;
3565         entity_render_t *ent;
3566
3567         if (!r_drawentities.integer)
3568                 return;
3569
3570         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
3571         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
3572         {
3573                 // worldmodel can check visibility
3574                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
3575                 for (i = 0;i < r_refdef.scene.numentities;i++)
3576                 {
3577                         ent = r_refdef.scene.entities[i];
3578                         if (!(ent->flags & renderimask))
3579                         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)))
3580                         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))
3581                                 r_refdef.viewcache.entityvisible[i] = true;
3582                 }
3583                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
3584                 {
3585                         for (i = 0;i < r_refdef.scene.numentities;i++)
3586                         {
3587                                 ent = r_refdef.scene.entities[i];
3588                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
3589                                 {
3590                                         if(R_CanSeeBox(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
3591                                                 ent->last_trace_visibility = realtime;
3592                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
3593                                                 r_refdef.viewcache.entityvisible[i] = 0;
3594                                 }
3595                         }
3596                 }
3597         }
3598         else
3599         {
3600                 // no worldmodel or it can't check visibility
3601                 for (i = 0;i < r_refdef.scene.numentities;i++)
3602                 {
3603                         ent = r_refdef.scene.entities[i];
3604                         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));
3605                 }
3606         }
3607 }
3608
3609 /// only used if skyrendermasked, and normally returns false
3610 int R_DrawBrushModelsSky (void)
3611 {
3612         int i, sky;
3613         entity_render_t *ent;
3614
3615         if (!r_drawentities.integer)
3616                 return false;
3617
3618         sky = false;
3619         for (i = 0;i < r_refdef.scene.numentities;i++)
3620         {
3621                 if (!r_refdef.viewcache.entityvisible[i])
3622                         continue;
3623                 ent = r_refdef.scene.entities[i];
3624                 if (!ent->model || !ent->model->DrawSky)
3625                         continue;
3626                 ent->model->DrawSky(ent);
3627                 sky = true;
3628         }
3629         return sky;
3630 }
3631
3632 static void R_DrawNoModel(entity_render_t *ent);
3633 static void R_DrawModels(void)
3634 {
3635         int i;
3636         entity_render_t *ent;
3637
3638         if (!r_drawentities.integer)
3639                 return;
3640
3641         for (i = 0;i < r_refdef.scene.numentities;i++)
3642         {
3643                 if (!r_refdef.viewcache.entityvisible[i])
3644                         continue;
3645                 ent = r_refdef.scene.entities[i];
3646                 r_refdef.stats.entities++;
3647                 if (ent->model && ent->model->Draw != NULL)
3648                         ent->model->Draw(ent);
3649                 else
3650                         R_DrawNoModel(ent);
3651         }
3652 }
3653
3654 static void R_DrawModelsDepth(void)
3655 {
3656         int i;
3657         entity_render_t *ent;
3658
3659         if (!r_drawentities.integer)
3660                 return;
3661
3662         for (i = 0;i < r_refdef.scene.numentities;i++)
3663         {
3664                 if (!r_refdef.viewcache.entityvisible[i])
3665                         continue;
3666                 ent = r_refdef.scene.entities[i];
3667                 if (ent->model && ent->model->DrawDepth != NULL)
3668                         ent->model->DrawDepth(ent);
3669         }
3670 }
3671
3672 static void R_DrawModelsDebug(void)
3673 {
3674         int i;
3675         entity_render_t *ent;
3676
3677         if (!r_drawentities.integer)
3678                 return;
3679
3680         for (i = 0;i < r_refdef.scene.numentities;i++)
3681         {
3682                 if (!r_refdef.viewcache.entityvisible[i])
3683                         continue;
3684                 ent = r_refdef.scene.entities[i];
3685                 if (ent->model && ent->model->DrawDebug != NULL)
3686                         ent->model->DrawDebug(ent);
3687         }
3688 }
3689
3690 static void R_DrawModelsAddWaterPlanes(void)
3691 {
3692         int i;
3693         entity_render_t *ent;
3694
3695         if (!r_drawentities.integer)
3696                 return;
3697
3698         for (i = 0;i < r_refdef.scene.numentities;i++)
3699         {
3700                 if (!r_refdef.viewcache.entityvisible[i])
3701                         continue;
3702                 ent = r_refdef.scene.entities[i];
3703                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
3704                         ent->model->DrawAddWaterPlanes(ent);
3705         }
3706 }
3707
3708 static void R_DrawModelDecals_Entity(entity_render_t *ent);
3709 static void R_DrawModelDecals(void)
3710 {
3711         int i;
3712         entity_render_t *ent;
3713
3714         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
3715
3716         if (!r_drawentities.integer || r_showsurfaces.integer)
3717                 return;
3718
3719         for (i = 0;i < r_refdef.scene.numentities;i++)
3720         {
3721                 if (!r_refdef.viewcache.entityvisible[i])
3722                         continue;
3723                 ent = r_refdef.scene.entities[i];
3724                 r_refdef.stats.entities++;
3725                 if (ent->decalsystem.numdecals)
3726                         R_DrawModelDecals_Entity(ent);
3727         }
3728 }
3729
3730 static void R_View_SetFrustum(void)
3731 {
3732         int i;
3733         double slopex, slopey;
3734         vec3_t forward, left, up, origin;
3735
3736         // we can't trust r_refdef.view.forward and friends in reflected scenes
3737         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
3738
3739 #if 0
3740         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
3741         r_refdef.view.frustum[0].normal[1] = 0 - 0;
3742         r_refdef.view.frustum[0].normal[2] = -1 - 0;
3743         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
3744         r_refdef.view.frustum[1].normal[1] = 0 + 0;
3745         r_refdef.view.frustum[1].normal[2] = -1 + 0;
3746         r_refdef.view.frustum[2].normal[0] = 0 - 0;
3747         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
3748         r_refdef.view.frustum[2].normal[2] = -1 - 0;
3749         r_refdef.view.frustum[3].normal[0] = 0 + 0;
3750         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
3751         r_refdef.view.frustum[3].normal[2] = -1 + 0;
3752 #endif
3753
3754 #if 0
3755         zNear = r_refdef.nearclip;
3756         nudge = 1.0 - 1.0 / (1<<23);
3757         r_refdef.view.frustum[4].normal[0] = 0 - 0;
3758         r_refdef.view.frustum[4].normal[1] = 0 - 0;
3759         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
3760         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
3761         r_refdef.view.frustum[5].normal[0] = 0 + 0;
3762         r_refdef.view.frustum[5].normal[1] = 0 + 0;
3763         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
3764         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
3765 #endif
3766
3767
3768
3769 #if 0
3770         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
3771         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
3772         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
3773         r_refdef.view.frustum[0].dist = m[15] - m[12];
3774
3775         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
3776         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
3777         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
3778         r_refdef.view.frustum[1].dist = m[15] + m[12];
3779
3780         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
3781         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
3782         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
3783         r_refdef.view.frustum[2].dist = m[15] - m[13];
3784
3785         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
3786         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
3787         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
3788         r_refdef.view.frustum[3].dist = m[15] + m[13];
3789
3790         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
3791         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
3792         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
3793         r_refdef.view.frustum[4].dist = m[15] - m[14];
3794
3795         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
3796         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
3797         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
3798         r_refdef.view.frustum[5].dist = m[15] + m[14];
3799 #endif
3800
3801         if (r_refdef.view.useperspective)
3802         {
3803                 slopex = 1.0 / r_refdef.view.frustum_x;
3804                 slopey = 1.0 / r_refdef.view.frustum_y;
3805                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
3806                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
3807                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
3808                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
3809                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3810
3811                 // Leaving those out was a mistake, those were in the old code, and they
3812                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
3813                 // I couldn't reproduce it after adding those normalizations. --blub
3814                 VectorNormalize(r_refdef.view.frustum[0].normal);
3815                 VectorNormalize(r_refdef.view.frustum[1].normal);
3816                 VectorNormalize(r_refdef.view.frustum[2].normal);
3817                 VectorNormalize(r_refdef.view.frustum[3].normal);
3818
3819                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
3820                 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]);
3821                 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]);
3822                 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]);
3823                 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]);
3824
3825                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
3826                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
3827                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
3828                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
3829                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3830         }
3831         else
3832         {
3833                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
3834                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
3835                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
3836                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
3837                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
3838                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
3839                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
3840                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
3841                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
3842                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
3843         }
3844         r_refdef.view.numfrustumplanes = 5;
3845
3846         if (r_refdef.view.useclipplane)
3847         {
3848                 r_refdef.view.numfrustumplanes = 6;
3849                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
3850         }
3851
3852         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
3853                 PlaneClassify(r_refdef.view.frustum + i);
3854
3855         // LordHavoc: note to all quake engine coders, Quake had a special case
3856         // for 90 degrees which assumed a square view (wrong), so I removed it,
3857         // Quake2 has it disabled as well.
3858
3859         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
3860         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
3861         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
3862         //PlaneClassify(&frustum[0]);
3863
3864         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
3865         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
3866         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
3867         //PlaneClassify(&frustum[1]);
3868
3869         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
3870         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
3871         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
3872         //PlaneClassify(&frustum[2]);
3873
3874         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
3875         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
3876         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
3877         //PlaneClassify(&frustum[3]);
3878
3879         // nearclip plane
3880         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
3881         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
3882         //PlaneClassify(&frustum[4]);
3883 }
3884
3885 void R_View_Update(void)
3886 {
3887         R_View_SetFrustum();
3888         R_View_WorldVisibility(r_refdef.view.useclipplane);
3889         R_View_UpdateEntityVisible();
3890         R_View_UpdateEntityLighting();
3891 }
3892
3893 void R_SetupView(qboolean allowwaterclippingplane)
3894 {
3895         const double *customclipplane = NULL;
3896         double plane[4];
3897         if (r_refdef.view.useclipplane && allowwaterclippingplane)
3898         {
3899                 // LordHavoc: couldn't figure out how to make this approach the
3900                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
3901                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
3902                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
3903                         dist = r_refdef.view.clipplane.dist;
3904                 plane[0] = r_refdef.view.clipplane.normal[0];
3905                 plane[1] = r_refdef.view.clipplane.normal[1];
3906                 plane[2] = r_refdef.view.clipplane.normal[2];
3907                 plane[3] = dist;
3908                 customclipplane = plane;
3909         }
3910
3911         if (!r_refdef.view.useperspective)
3912                 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);
3913         else if (gl_stencil && r_useinfinitefarclip.integer)
3914                 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);
3915         else
3916                 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);
3917         R_SetViewport(&r_refdef.view.viewport);
3918 }
3919
3920 void R_ResetViewRendering2D(void)
3921 {
3922         r_viewport_t viewport;
3923         DrawQ_Finish();
3924
3925         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
3926         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);
3927         R_SetViewport(&viewport);
3928         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
3929         GL_Color(1, 1, 1, 1);
3930         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3931         GL_BlendFunc(GL_ONE, GL_ZERO);
3932         GL_AlphaTest(false);
3933         GL_ScissorTest(false);
3934         GL_DepthMask(false);
3935         GL_DepthRange(0, 1);
3936         GL_DepthTest(false);
3937         R_Mesh_Matrix(&identitymatrix);
3938         R_Mesh_ResetTextureState();
3939         GL_PolygonOffset(0, 0);
3940         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3941         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3942         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3943         qglStencilMask(~0);CHECKGLERROR
3944         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3945         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3946         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
3947         R_SetupGenericShader(true);
3948 }
3949
3950 void R_ResetViewRendering3D(void)
3951 {
3952         DrawQ_Finish();
3953
3954         R_SetupView(true);
3955         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
3956         GL_Color(1, 1, 1, 1);
3957         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
3958         GL_BlendFunc(GL_ONE, GL_ZERO);
3959         GL_AlphaTest(false);
3960         GL_ScissorTest(true);
3961         GL_DepthMask(true);
3962         GL_DepthRange(0, 1);
3963         GL_DepthTest(true);
3964         R_Mesh_Matrix(&identitymatrix);
3965         R_Mesh_ResetTextureState();
3966         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
3967         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
3968         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
3969         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
3970         qglStencilMask(~0);CHECKGLERROR
3971         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
3972         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
3973         GL_CullFace(r_refdef.view.cullface_back);
3974         R_SetupGenericShader(true);
3975 }
3976
3977 void R_RenderScene(void);
3978 void R_RenderWaterPlanes(void);
3979
3980 static void R_Water_StartFrame(void)
3981 {
3982         int i;
3983         int waterwidth, waterheight, texturewidth, textureheight;
3984         r_waterstate_waterplane_t *p;
3985
3986         // set waterwidth and waterheight to the water resolution that will be
3987         // used (often less than the screen resolution for faster rendering)
3988         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
3989         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
3990
3991         // calculate desired texture sizes
3992         // can't use water if the card does not support the texture size
3993         if (!r_water.integer || !r_glsl.integer || !gl_support_fragment_shader || waterwidth > gl_max_texture_size || waterheight > gl_max_texture_size || r_showsurfaces.integer)
3994                 texturewidth = textureheight = waterwidth = waterheight = 0;
3995         else if (gl_support_arb_texture_non_power_of_two)
3996         {
3997                 texturewidth = waterwidth;
3998                 textureheight = waterheight;
3999         }
4000         else
4001         {
4002                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
4003                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
4004         }
4005
4006         // allocate textures as needed
4007         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
4008         {
4009                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4010                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
4011                 {
4012                         if (p->texture_refraction)
4013                                 R_FreeTexture(p->texture_refraction);
4014                         p->texture_refraction = NULL;
4015                         if (p->texture_reflection)
4016                                 R_FreeTexture(p->texture_reflection);
4017                         p->texture_reflection = NULL;
4018                 }
4019                 memset(&r_waterstate, 0, sizeof(r_waterstate));
4020                 r_waterstate.texturewidth = texturewidth;
4021                 r_waterstate.textureheight = textureheight;
4022         }
4023
4024         if (r_waterstate.texturewidth)
4025         {
4026                 r_waterstate.enabled = true;
4027
4028                 // when doing a reduced render (HDR) we want to use a smaller area
4029                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
4030                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
4031
4032                 // set up variables that will be used in shader setup
4033                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4034                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4035                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
4036                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
4037         }
4038
4039         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
4040         r_waterstate.numwaterplanes = 0;
4041 }
4042
4043 void R_Water_AddWaterPlane(msurface_t *surface)
4044 {
4045         int triangleindex, planeindex;
4046         const int *e;
4047         vec3_t vert[3];
4048         vec3_t normal;
4049         vec3_t center;
4050         mplane_t plane;
4051         r_waterstate_waterplane_t *p;
4052         texture_t *t = R_GetCurrentTexture(surface->texture);
4053         // just use the first triangle with a valid normal for any decisions
4054         VectorClear(normal);
4055         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
4056         {
4057                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
4058                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
4059                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
4060                 TriangleNormal(vert[0], vert[1], vert[2], normal);
4061                 if (VectorLength2(normal) >= 0.001)
4062                         break;
4063         }
4064
4065         VectorCopy(normal, plane.normal);
4066         VectorNormalize(plane.normal);
4067         plane.dist = DotProduct(vert[0], plane.normal);
4068         PlaneClassify(&plane);
4069         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
4070         {
4071                 // skip backfaces (except if nocullface is set)
4072                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
4073                         return;
4074                 VectorNegate(plane.normal, plane.normal);
4075                 plane.dist *= -1;
4076                 PlaneClassify(&plane);
4077         }
4078
4079
4080         // find a matching plane if there is one
4081         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4082                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
4083                         break;
4084         if (planeindex >= r_waterstate.maxwaterplanes)
4085                 return; // nothing we can do, out of planes
4086
4087         // if this triangle does not fit any known plane rendered this frame, add one
4088         if (planeindex >= r_waterstate.numwaterplanes)
4089         {
4090                 // store the new plane
4091                 r_waterstate.numwaterplanes++;
4092                 p->plane = plane;
4093                 // clear materialflags and pvs
4094                 p->materialflags = 0;
4095                 p->pvsvalid = false;
4096         }
4097         // merge this surface's materialflags into the waterplane
4098         p->materialflags |= t->currentmaterialflags;
4099         // merge this surface's PVS into the waterplane
4100         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
4101         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
4102          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
4103         {
4104                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
4105                 p->pvsvalid = true;
4106         }
4107 }
4108
4109 static void R_Water_ProcessPlanes(void)
4110 {
4111         r_refdef_view_t originalview;
4112         r_refdef_view_t myview;
4113         int planeindex;
4114         r_waterstate_waterplane_t *p;
4115
4116         originalview = r_refdef.view;
4117
4118         // make sure enough textures are allocated
4119         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4120         {
4121                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4122                 {
4123                         if (!p->texture_refraction)
4124                                 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);
4125                         if (!p->texture_refraction)
4126                                 goto error;
4127                 }
4128
4129                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4130                 {
4131                         if (!p->texture_reflection)
4132                                 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);
4133                         if (!p->texture_reflection)
4134                                 goto error;
4135                 }
4136         }
4137
4138         // render views
4139         r_refdef.view = originalview;
4140         r_refdef.view.showdebug = false;
4141         r_refdef.view.width = r_waterstate.waterwidth;
4142         r_refdef.view.height = r_waterstate.waterheight;
4143         r_refdef.view.useclipplane = true;
4144         myview = r_refdef.view;
4145         r_waterstate.renderingscene = true;
4146         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
4147         {
4148                 // render the normal view scene and copy into texture
4149                 // (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)
4150                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
4151                 {
4152                         r_refdef.view = myview;
4153                         r_refdef.view.clipplane = p->plane;
4154                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
4155                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
4156                         PlaneClassify(&r_refdef.view.clipplane);
4157
4158                         R_ResetViewRendering3D();
4159                         R_ClearScreen(r_refdef.fogenabled);
4160                         R_View_Update();
4161                         R_RenderScene();
4162
4163                         // copy view into the screen texture
4164                         R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
4165                         GL_ActiveTexture(0);
4166                         CHECKGLERROR
4167                         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
4168                 }
4169
4170                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
4171                 {
4172                         r_refdef.view = myview;
4173                         // render reflected scene and copy into texture
4174                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
4175                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
4176                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
4177                         r_refdef.view.clipplane = p->plane;
4178                         // reverse the cullface settings for this render
4179                         r_refdef.view.cullface_front = GL_FRONT;
4180                         r_refdef.view.cullface_back = GL_BACK;
4181                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
4182                         {
4183                                 r_refdef.view.usecustompvs = true;
4184                                 if (p->pvsvalid)
4185                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4186                                 else
4187                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
4188                         }
4189
4190                         R_ResetViewRendering3D();
4191                         R_ClearScreen(r_refdef.fogenabled);
4192                         R_View_Update();
4193                         R_RenderScene();
4194
4195                         R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
4196                         GL_ActiveTexture(0);
4197                         CHECKGLERROR
4198                         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
4199                 }
4200         }
4201         r_waterstate.renderingscene = false;
4202         r_refdef.view = originalview;
4203         R_ResetViewRendering3D();
4204         R_ClearScreen(r_refdef.fogenabled);
4205         R_View_Update();
4206         return;
4207 error:
4208         r_refdef.view = originalview;
4209         r_waterstate.renderingscene = false;
4210         Cvar_SetValueQuick(&r_water, 0);
4211         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
4212         return;
4213 }
4214
4215 void R_Bloom_StartFrame(void)
4216 {
4217         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
4218
4219         // set bloomwidth and bloomheight to the bloom resolution that will be
4220         // used (often less than the screen resolution for faster rendering)
4221         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
4222         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
4223         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
4224         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, gl_max_texture_size);
4225         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, gl_max_texture_size);
4226
4227         // calculate desired texture sizes
4228         if (gl_support_arb_texture_non_power_of_two)
4229         {
4230                 screentexturewidth = r_refdef.view.width;
4231                 screentextureheight = r_refdef.view.height;
4232                 bloomtexturewidth = r_bloomstate.bloomwidth;
4233                 bloomtextureheight = r_bloomstate.bloomheight;
4234         }
4235         else
4236         {
4237                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
4238                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
4239                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
4240                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
4241         }
4242
4243         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))
4244         {
4245                 Cvar_SetValueQuick(&r_hdr, 0);
4246                 Cvar_SetValueQuick(&r_bloom, 0);
4247                 Cvar_SetValueQuick(&r_motionblur, 0);
4248                 Cvar_SetValueQuick(&r_damageblur, 0);
4249         }
4250
4251         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)))
4252                 screentexturewidth = screentextureheight = 0;
4253         if (!r_hdr.integer && !r_bloom.integer)
4254                 bloomtexturewidth = bloomtextureheight = 0;
4255
4256         // allocate textures as needed
4257         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
4258         {
4259                 if (r_bloomstate.texture_screen)
4260                         R_FreeTexture(r_bloomstate.texture_screen);
4261                 r_bloomstate.texture_screen = NULL;
4262                 r_bloomstate.screentexturewidth = screentexturewidth;
4263                 r_bloomstate.screentextureheight = screentextureheight;
4264                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
4265                         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);
4266         }
4267         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
4268         {
4269                 if (r_bloomstate.texture_bloom)
4270                         R_FreeTexture(r_bloomstate.texture_bloom);
4271                 r_bloomstate.texture_bloom = NULL;
4272                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
4273                 r_bloomstate.bloomtextureheight = bloomtextureheight;
4274                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
4275                         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);
4276         }
4277
4278         // when doing a reduced render (HDR) we want to use a smaller area
4279         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
4280         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
4281         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
4282         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
4283         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
4284
4285         // set up a texcoord array for the full resolution screen image
4286         // (we have to keep this around to copy back during final render)
4287         r_bloomstate.screentexcoord2f[0] = 0;
4288         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
4289         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
4290         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
4291         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
4292         r_bloomstate.screentexcoord2f[5] = 0;
4293         r_bloomstate.screentexcoord2f[6] = 0;
4294         r_bloomstate.screentexcoord2f[7] = 0;
4295
4296         // set up a texcoord array for the reduced resolution bloom image
4297         // (which will be additive blended over the screen image)
4298         r_bloomstate.bloomtexcoord2f[0] = 0;
4299         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4300         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
4301         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4302         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
4303         r_bloomstate.bloomtexcoord2f[5] = 0;
4304         r_bloomstate.bloomtexcoord2f[6] = 0;
4305         r_bloomstate.bloomtexcoord2f[7] = 0;
4306
4307         if (r_hdr.integer || r_bloom.integer)
4308         {
4309                 r_bloomstate.enabled = true;
4310                 r_bloomstate.hdr = r_hdr.integer != 0;
4311         }
4312
4313         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);
4314 }
4315
4316 void R_Bloom_CopyBloomTexture(float colorscale)
4317 {
4318         r_refdef.stats.bloom++;
4319
4320         // scale down screen texture to the bloom texture size
4321         CHECKGLERROR
4322         R_SetViewport(&r_bloomstate.viewport);
4323         GL_BlendFunc(GL_ONE, GL_ZERO);
4324         GL_Color(colorscale, colorscale, colorscale, 1);
4325         // TODO: optimize with multitexture or GLSL
4326         R_SetupGenericShader(true);
4327         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4328         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4329         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4330         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4331
4332         // we now have a bloom image in the framebuffer
4333         // copy it into the bloom image texture for later processing
4334         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4335         GL_ActiveTexture(0);
4336         CHECKGLERROR
4337         qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4338         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4339 }
4340
4341 void R_Bloom_CopyHDRTexture(void)
4342 {
4343         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4344         GL_ActiveTexture(0);
4345         CHECKGLERROR
4346         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
4347         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4348 }
4349
4350 void R_Bloom_MakeTexture(void)
4351 {
4352         int x, range, dir;
4353         float xoffset, yoffset, r, brighten;
4354
4355         r_refdef.stats.bloom++;
4356
4357         R_ResetViewRendering2D();
4358         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4359         R_Mesh_ColorPointer(NULL, 0, 0);
4360         R_SetupGenericShader(true);
4361
4362         // we have a bloom image in the framebuffer
4363         CHECKGLERROR
4364         R_SetViewport(&r_bloomstate.viewport);
4365
4366         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
4367         {
4368                 x *= 2;
4369                 r = bound(0, r_bloom_colorexponent.value / x, 1);
4370                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
4371                 GL_Color(r, r, r, 1);
4372                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4373                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4374                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4375                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4376
4377                 // copy the vertically blurred bloom view to a texture
4378                 GL_ActiveTexture(0);
4379                 CHECKGLERROR
4380                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4381                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4382         }
4383
4384         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
4385         brighten = r_bloom_brighten.value;
4386         if (r_hdr.integer)
4387                 brighten *= r_hdr_range.value;
4388         brighten = sqrt(brighten);
4389         if(range >= 1)
4390                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
4391         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4392         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
4393
4394         for (dir = 0;dir < 2;dir++)
4395         {
4396                 // blend on at multiple vertical offsets to achieve a vertical blur
4397                 // TODO: do offset blends using GLSL
4398                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
4399                 GL_BlendFunc(GL_ONE, GL_ZERO);
4400                 for (x = -range;x <= range;x++)
4401                 {
4402                         if (!dir){xoffset = 0;yoffset = x;}
4403                         else {xoffset = x;yoffset = 0;}
4404                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
4405                         yoffset /= (float)r_bloomstate.bloomtextureheight;
4406                         // compute a texcoord array with the specified x and y offset
4407                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
4408                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4409                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4410                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
4411                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
4412                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
4413                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
4414                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
4415                         // this r value looks like a 'dot' particle, fading sharply to
4416                         // black at the edges
4417                         // (probably not realistic but looks good enough)
4418                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
4419                         //r = brighten/(range*2+1);
4420                         r = brighten / (range * 2 + 1);
4421                         if(range >= 1)
4422                                 r *= (1 - x*x/(float)(range*range));
4423                         GL_Color(r, r, r, 1);
4424                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4425                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4426                         GL_BlendFunc(GL_ONE, GL_ONE);
4427                 }
4428
4429                 // copy the vertically blurred bloom view to a texture
4430                 GL_ActiveTexture(0);
4431                 CHECKGLERROR
4432                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4433                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4434         }
4435
4436         // apply subtract last
4437         // (just like it would be in a GLSL shader)
4438         if (r_bloom_colorsubtract.value > 0 && gl_support_ext_blend_subtract)
4439         {
4440                 GL_BlendFunc(GL_ONE, GL_ZERO);
4441                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4442                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4443                 GL_Color(1, 1, 1, 1);
4444                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4445                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4446
4447                 GL_BlendFunc(GL_ONE, GL_ONE);
4448                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
4449                 R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
4450                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4451                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
4452                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4453                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
4454                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
4455
4456                 // copy the darkened bloom view to a texture
4457                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4458                 GL_ActiveTexture(0);
4459                 CHECKGLERROR
4460                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
4461                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
4462         }
4463 }
4464
4465 void R_HDR_RenderBloomTexture(void)
4466 {
4467         int oldwidth, oldheight;
4468         float oldcolorscale;
4469
4470         oldcolorscale = r_refdef.view.colorscale;
4471         oldwidth = r_refdef.view.width;
4472         oldheight = r_refdef.view.height;
4473         r_refdef.view.width = r_bloomstate.bloomwidth;
4474         r_refdef.view.height = r_bloomstate.bloomheight;
4475
4476         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
4477         // TODO: add exposure compensation features
4478         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
4479
4480         r_refdef.view.showdebug = false;
4481         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
4482
4483         R_ResetViewRendering3D();
4484
4485         R_ClearScreen(r_refdef.fogenabled);
4486         if (r_timereport_active)
4487                 R_TimeReport("HDRclear");
4488
4489         R_View_Update();
4490         if (r_timereport_active)
4491                 R_TimeReport("visibility");
4492
4493         // only do secondary renders with HDR if r_hdr is 2 or higher
4494         r_waterstate.numwaterplanes = 0;
4495         if (r_waterstate.enabled && r_hdr.integer >= 2)
4496                 R_RenderWaterPlanes();
4497
4498         r_refdef.view.showdebug = true;
4499         R_RenderScene();
4500         r_waterstate.numwaterplanes = 0;
4501
4502         R_ResetViewRendering2D();
4503
4504         R_Bloom_CopyHDRTexture();
4505         R_Bloom_MakeTexture();
4506
4507         // restore the view settings
4508         r_refdef.view.width = oldwidth;
4509         r_refdef.view.height = oldheight;
4510         r_refdef.view.colorscale = oldcolorscale;
4511
4512         R_ResetViewRendering3D();
4513
4514         R_ClearScreen(r_refdef.fogenabled);
4515         if (r_timereport_active)
4516                 R_TimeReport("viewclear");
4517 }
4518
4519 static void R_BlendView(void)
4520 {
4521         if (r_bloomstate.texture_screen)
4522         {
4523                 // make sure the buffer is available
4524                 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
4525
4526                 R_ResetViewRendering2D();
4527                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4528                 R_Mesh_ColorPointer(NULL, 0, 0);
4529                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4530                 GL_ActiveTexture(0);CHECKGLERROR
4531
4532                 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
4533                 {  
4534                         // declare variables
4535                         float speed;
4536                         static float avgspeed;
4537
4538                         speed = VectorLength(cl.movement_velocity);
4539
4540                         cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
4541                         avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
4542
4543                         speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
4544                         speed = bound(0, speed, 1);
4545                         speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
4546
4547                         // calculate values into a standard alpha
4548                         cl.motionbluralpha = 1 - exp(-
4549                                         (
4550                                          (r_motionblur.value * speed / 80)
4551                                          +
4552                                          (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
4553                                         )
4554                                         /
4555                                         max(0.0001, cl.time - cl.oldtime) // fps independent
4556                                    );
4557
4558                         cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
4559                         cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
4560                         // apply the blur
4561                         if (cl.motionbluralpha > 0)
4562                         {
4563                                 R_SetupGenericShader(true);
4564                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4565                                 GL_Color(1, 1, 1, cl.motionbluralpha);
4566                                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4567                                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4568                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4569                                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4570                         }
4571                 }
4572
4573                 // copy view into the screen texture
4574                 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
4575                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4576         }
4577
4578         if (r_glsl.integer && gl_support_fragment_shader && (r_bloomstate.texture_screen || r_bloomstate.texture_bloom))
4579         {
4580                 unsigned int permutation =
4581                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
4582                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
4583                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
4584                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
4585                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
4586
4587                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
4588                 {
4589                         // render simple bloom effect
4590                         // copy the screen and shrink it and darken it for the bloom process
4591                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4592                         // make the bloom texture
4593                         R_Bloom_MakeTexture();
4594                 }
4595
4596                 R_ResetViewRendering2D();
4597                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4598                 R_Mesh_ColorPointer(NULL, 0, 0);
4599                 GL_Color(1, 1, 1, 1);
4600                 GL_BlendFunc(GL_ONE, GL_ZERO);
4601                 R_SetupShader_SetPermutation(SHADERMODE_POSTPROCESS, permutation);
4602                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4603                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4604                 R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_bloom));
4605                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4606                 if (r_glsl_permutation->loc_Texture_GammaRamps >= 0)
4607                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, R_GetTexture(r_texture_gammaramps));
4608                 if (r_glsl_permutation->loc_TintColor >= 0)
4609                         qglUniform4fARB(r_glsl_permutation->loc_TintColor, r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4610                 if (r_glsl_permutation->loc_ClientTime >= 0)
4611                         qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4612                 if (r_glsl_permutation->loc_PixelSize >= 0)
4613                         qglUniform2fARB(r_glsl_permutation->loc_PixelSize, 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
4614                 if (r_glsl_permutation->loc_UserVec1 >= 0)
4615                 {
4616                         float a=0, b=0, c=0, d=0;
4617 #if _MSC_VER >= 1400
4618 #define sscanf sscanf_s
4619 #endif
4620                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &a, &b, &c, &d);
4621                         qglUniform4fARB(r_glsl_permutation->loc_UserVec1, a, b, c, d);
4622                 }
4623                 if (r_glsl_permutation->loc_UserVec2 >= 0)
4624                 {
4625                         float a=0, b=0, c=0, d=0;
4626                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &a, &b, &c, &d);
4627                         qglUniform4fARB(r_glsl_permutation->loc_UserVec2, a, b, c, d);
4628                 }
4629                 if (r_glsl_permutation->loc_UserVec3 >= 0)
4630                 {
4631                         float a=0, b=0, c=0, d=0;
4632                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &a, &b, &c, &d);
4633                         qglUniform4fARB(r_glsl_permutation->loc_UserVec3, a, b, c, d);
4634                 }
4635                 if (r_glsl_permutation->loc_UserVec4 >= 0)
4636                 {
4637                         float a=0, b=0, c=0, d=0;
4638                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &a, &b, &c, &d);
4639                         qglUniform4fARB(r_glsl_permutation->loc_UserVec4, a, b, c, d);
4640                 }
4641                 if (r_glsl_permutation->loc_Saturation >= 0)
4642                         qglUniform1fARB(r_glsl_permutation->loc_Saturation, r_glsl_saturation.value);
4643                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4644                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4645                 return;
4646         }
4647
4648
4649
4650         if (r_bloomstate.texture_bloom && r_bloomstate.hdr)
4651         {
4652                 // render high dynamic range bloom effect
4653                 // the bloom texture was made earlier this render, so we just need to
4654                 // blend it onto the screen...
4655                 R_ResetViewRendering2D();
4656                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4657                 R_Mesh_ColorPointer(NULL, 0, 0);
4658                 R_SetupGenericShader(true);
4659                 GL_Color(1, 1, 1, 1);
4660                 GL_BlendFunc(GL_ONE, GL_ONE);
4661                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4662                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4663                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4664                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4665         }
4666         else if (r_bloomstate.texture_bloom)
4667         {
4668                 // render simple bloom effect
4669                 // copy the screen and shrink it and darken it for the bloom process
4670                 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
4671                 // make the bloom texture
4672                 R_Bloom_MakeTexture();
4673                 // put the original screen image back in place and blend the bloom
4674                 // texture on it
4675                 R_ResetViewRendering2D();
4676                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4677                 R_Mesh_ColorPointer(NULL, 0, 0);
4678                 GL_Color(1, 1, 1, 1);
4679                 GL_BlendFunc(GL_ONE, GL_ZERO);
4680                 // do both in one pass if possible
4681                 R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_bloom));
4682                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
4683                 if (r_textureunits.integer >= 2 && gl_combine.integer)
4684                 {
4685                         R_SetupGenericTwoTextureShader(GL_ADD);
4686                         R_Mesh_TexBind(1, R_GetTexture(r_bloomstate.texture_screen));
4687                         R_Mesh_TexCoordPointer(1, 2, r_bloomstate.screentexcoord2f, 0, 0);
4688                 }
4689                 else
4690                 {
4691                         R_SetupGenericShader(true);
4692                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4693                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4694                         // now blend on the bloom texture
4695                         GL_BlendFunc(GL_ONE, GL_ONE);
4696                         R_Mesh_TexBind(0, R_GetTexture(r_bloomstate.texture_screen));
4697                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
4698                 }
4699                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4700                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
4701         }
4702         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
4703         {
4704                 // apply a color tint to the whole view
4705                 R_ResetViewRendering2D();
4706                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
4707                 R_Mesh_ColorPointer(NULL, 0, 0);
4708                 R_SetupGenericShader(false);
4709                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4710                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
4711                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
4712         }
4713 }
4714
4715 matrix4x4_t r_waterscrollmatrix;
4716
4717 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
4718 {
4719         if (r_refdef.fog_density)
4720         {
4721                 r_refdef.fogcolor[0] = r_refdef.fog_red;
4722                 r_refdef.fogcolor[1] = r_refdef.fog_green;
4723                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
4724
4725                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
4726                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
4727                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
4728                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
4729
4730                 {
4731                         vec3_t fogvec;
4732                         VectorCopy(r_refdef.fogcolor, fogvec);
4733                         //   color.rgb *= ContrastBoost * SceneBrightness;
4734                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
4735                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
4736                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
4737                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
4738                 }
4739         }
4740 }
4741
4742 void R_UpdateVariables(void)
4743 {
4744         R_Textures_Frame();
4745
4746         r_refdef.scene.ambient = r_ambient.value;
4747
4748         r_refdef.farclip = r_farclip_base.value;
4749         if (r_refdef.scene.worldmodel)
4750                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
4751         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
4752
4753         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
4754                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
4755         r_refdef.polygonfactor = 0;
4756         r_refdef.polygonoffset = 0;
4757         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4758         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
4759
4760         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
4761         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
4762         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
4763         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
4764         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
4765         if (r_showsurfaces.integer)
4766         {
4767                 r_refdef.scene.rtworld = false;
4768                 r_refdef.scene.rtworldshadows = false;
4769                 r_refdef.scene.rtdlight = false;
4770                 r_refdef.scene.rtdlightshadows = false;
4771                 r_refdef.lightmapintensity = 0;
4772         }
4773
4774         if (gamemode == GAME_NEHAHRA)
4775         {
4776                 if (gl_fogenable.integer)
4777                 {
4778                         r_refdef.oldgl_fogenable = true;
4779                         r_refdef.fog_density = gl_fogdensity.value;
4780                         r_refdef.fog_red = gl_fogred.value;
4781                         r_refdef.fog_green = gl_foggreen.value;
4782                         r_refdef.fog_blue = gl_fogblue.value;
4783                         r_refdef.fog_alpha = 1;
4784                         r_refdef.fog_start = 0;
4785                         r_refdef.fog_end = gl_skyclip.value;
4786                         r_refdef.fog_height = 1<<30;
4787                         r_refdef.fog_fadedepth = 128;
4788                 }
4789                 else if (r_refdef.oldgl_fogenable)
4790                 {
4791                         r_refdef.oldgl_fogenable = false;
4792                         r_refdef.fog_density = 0;
4793                         r_refdef.fog_red = 0;
4794                         r_refdef.fog_green = 0;
4795                         r_refdef.fog_blue = 0;
4796                         r_refdef.fog_alpha = 0;
4797                         r_refdef.fog_start = 0;
4798                         r_refdef.fog_end = 0;
4799                         r_refdef.fog_height = 1<<30;
4800                         r_refdef.fog_fadedepth = 128;
4801                 }
4802         }
4803
4804         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
4805         r_refdef.fog_start = max(0, r_refdef.fog_start);
4806         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
4807
4808         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
4809
4810         if (r_refdef.fog_density && r_drawfog.integer)
4811         {
4812                 r_refdef.fogenabled = true;
4813                 // this is the point where the fog reaches 0.9986 alpha, which we
4814                 // consider a good enough cutoff point for the texture
4815                 // (0.9986 * 256 == 255.6)
4816                 if (r_fog_exp2.integer)
4817                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
4818                 else
4819                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
4820                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
4821                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
4822                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
4823                 // fog color was already set
4824                 // update the fog texture
4825                 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)
4826                         R_BuildFogTexture();
4827         }
4828         else
4829                 r_refdef.fogenabled = false;
4830
4831         if(r_glsl.integer && v_glslgamma.integer && !vid_gammatables_trivial)
4832         {
4833                 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
4834                 {
4835                         // build GLSL gamma texture
4836 #define RAMPWIDTH 256
4837                         unsigned short ramp[RAMPWIDTH * 3];
4838                         unsigned char rampbgr[RAMPWIDTH][4];
4839                         int i;
4840
4841                         r_texture_gammaramps_serial = vid_gammatables_serial;
4842
4843                         VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
4844                         for(i = 0; i < RAMPWIDTH; ++i)
4845                         {
4846                                 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4847                                 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
4848                                 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
4849                                 rampbgr[i][3] = 0;
4850                         }
4851                         if (r_texture_gammaramps)
4852                         {
4853                                 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
4854                         }
4855                         else
4856                         {
4857                                 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);
4858                         }
4859                 }
4860         }
4861         else
4862         {
4863                 // remove GLSL gamma texture
4864         }
4865 }
4866
4867 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
4868 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
4869 /*
4870 ================
4871 R_SelectScene
4872 ================
4873 */
4874 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
4875         if( scenetype != r_currentscenetype ) {
4876                 // store the old scenetype
4877                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
4878                 r_currentscenetype = scenetype;
4879                 // move in the new scene
4880                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
4881         }
4882 }
4883
4884 /*
4885 ================
4886 R_GetScenePointer
4887 ================
4888 */
4889 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
4890 {
4891         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
4892         if( scenetype == r_currentscenetype ) {
4893                 return &r_refdef.scene;
4894         } else {
4895                 return &r_scenes_store[ scenetype ];
4896         }
4897 }
4898
4899 /*
4900 ================
4901 R_RenderView
4902 ================
4903 */
4904 void R_RenderView(void)
4905 {
4906         if (r_timereport_active)
4907                 R_TimeReport("start");
4908         r_frame++; // used only by R_GetCurrentTexture
4909         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
4910
4911         R_AnimCache_NewFrame();
4912
4913         if (r_refdef.view.isoverlay)
4914         {
4915                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
4916                 GL_Clear( GL_DEPTH_BUFFER_BIT );
4917                 R_TimeReport("depthclear");
4918
4919                 r_refdef.view.showdebug = false;
4920
4921                 r_waterstate.enabled = false;
4922                 r_waterstate.numwaterplanes = 0;
4923
4924                 R_RenderScene();
4925
4926                 CHECKGLERROR
4927                 return;
4928         }
4929
4930         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
4931                 return; //Host_Error ("R_RenderView: NULL worldmodel");
4932
4933         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
4934
4935         // break apart the view matrix into vectors for various purposes
4936         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
4937         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
4938         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
4939         VectorNegate(r_refdef.view.left, r_refdef.view.right);
4940         // make an inverted copy of the view matrix for tracking sprites
4941         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
4942
4943         R_Shadow_UpdateWorldLightSelection();
4944
4945         R_Bloom_StartFrame();
4946         R_Water_StartFrame();
4947
4948         CHECKGLERROR
4949         if (r_timereport_active)
4950                 R_TimeReport("viewsetup");
4951
4952         R_ResetViewRendering3D();
4953
4954         if (r_refdef.view.clear || r_refdef.fogenabled)
4955         {
4956                 R_ClearScreen(r_refdef.fogenabled);
4957                 if (r_timereport_active)
4958                         R_TimeReport("viewclear");
4959         }
4960         r_refdef.view.clear = true;
4961
4962         // this produces a bloom texture to be used in R_BlendView() later
4963         if (r_hdr.integer)
4964                 R_HDR_RenderBloomTexture();
4965
4966         r_refdef.view.showdebug = true;
4967
4968         R_View_Update();
4969         if (r_timereport_active)
4970                 R_TimeReport("visibility");
4971
4972         r_waterstate.numwaterplanes = 0;
4973         if (r_waterstate.enabled)
4974                 R_RenderWaterPlanes();
4975
4976         R_RenderScene();
4977         r_waterstate.numwaterplanes = 0;
4978
4979         R_BlendView();
4980         if (r_timereport_active)
4981                 R_TimeReport("blendview");
4982
4983         GL_Scissor(0, 0, vid.width, vid.height);
4984         GL_ScissorTest(false);
4985         CHECKGLERROR
4986 }
4987
4988 void R_RenderWaterPlanes(void)
4989 {
4990         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
4991         {
4992                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
4993                 if (r_timereport_active)
4994                         R_TimeReport("waterworld");
4995         }
4996
4997         // don't let sound skip if going slow
4998         if (r_refdef.scene.extraupdate)
4999                 S_ExtraUpdate ();
5000
5001         R_DrawModelsAddWaterPlanes();
5002         if (r_timereport_active)
5003                 R_TimeReport("watermodels");
5004
5005         if (r_waterstate.numwaterplanes)
5006         {
5007                 R_Water_ProcessPlanes();
5008                 if (r_timereport_active)
5009                         R_TimeReport("waterscenes");
5010         }
5011 }
5012
5013 extern void R_DrawLightningBeams (void);
5014 extern void VM_CL_AddPolygonsToMeshQueue (void);
5015 extern void R_DrawPortals (void);
5016 extern cvar_t cl_locs_show;
5017 static void R_DrawLocs(void);
5018 static void R_DrawEntityBBoxes(void);
5019 extern cvar_t cl_decals_newsystem;
5020 void R_RenderScene(void)
5021 {
5022         r_refdef.stats.renders++;
5023
5024         R_Main_ResizeViewCache();
5025
5026         R_UpdateFogColor();
5027
5028         // don't let sound skip if going slow
5029         if (r_refdef.scene.extraupdate)
5030                 S_ExtraUpdate ();
5031
5032         R_MeshQueue_BeginScene();
5033
5034         R_SkyStartFrame();
5035
5036         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);
5037
5038         if (cl.csqc_vidvars.drawworld)
5039         {
5040                 // don't let sound skip if going slow
5041                 if (r_refdef.scene.extraupdate)
5042                         S_ExtraUpdate ();
5043
5044                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
5045                 {
5046                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
5047                         if (r_timereport_active)
5048                                 R_TimeReport("worldsky");
5049                 }
5050
5051                 if (R_DrawBrushModelsSky() && r_timereport_active)
5052                         R_TimeReport("bmodelsky");
5053
5054                 if (skyrendermasked && skyrenderlater)
5055                 {
5056                         // we have to force off the water clipping plane while rendering sky
5057                         R_SetupView(false);
5058                         R_Sky();
5059                         R_SetupView(true);
5060                 }
5061         }
5062
5063         R_AnimCache_CacheVisibleEntities();
5064
5065         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
5066         {
5067                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
5068                 if (r_timereport_active)
5069                         R_TimeReport("worlddepth");
5070         }
5071         if (r_depthfirst.integer >= 2)
5072         {
5073                 R_DrawModelsDepth();
5074                 if (r_timereport_active)
5075                         R_TimeReport("modeldepth");
5076         }
5077
5078         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
5079         {
5080                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
5081                 if (r_timereport_active)
5082                         R_TimeReport("world");
5083         }
5084
5085         // don't let sound skip if going slow
5086         if (r_refdef.scene.extraupdate)
5087                 S_ExtraUpdate ();
5088
5089         R_DrawModels();
5090         if (r_timereport_active)
5091                 R_TimeReport("models");
5092
5093         // don't let sound skip if going slow
5094         if (r_refdef.scene.extraupdate)
5095                 S_ExtraUpdate ();
5096
5097         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5098         {
5099                 R_DrawModelShadows();
5100                 R_ResetViewRendering3D();
5101                 // don't let sound skip if going slow
5102                 if (r_refdef.scene.extraupdate)
5103                         S_ExtraUpdate ();
5104         }
5105
5106         R_ShadowVolumeLighting(false);
5107         if (r_timereport_active)
5108                 R_TimeReport("rtlights");
5109
5110         // don't let sound skip if going slow
5111         if (r_refdef.scene.extraupdate)
5112                 S_ExtraUpdate ();
5113
5114         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
5115         {
5116                 R_DrawModelShadows();
5117                 R_ResetViewRendering3D();
5118                 // don't let sound skip if going slow
5119                 if (r_refdef.scene.extraupdate)
5120                         S_ExtraUpdate ();
5121         }
5122
5123         if (cl.csqc_vidvars.drawworld)
5124         {
5125                 if (cl_decals_newsystem.integer)
5126                 {
5127                         R_DrawModelDecals();
5128                         if (r_timereport_active)
5129                                 R_TimeReport("modeldecals");
5130                 }
5131                 else
5132                 {
5133                         R_DrawDecals();
5134                         if (r_timereport_active)
5135                                 R_TimeReport("decals");
5136                 }
5137
5138                 R_DrawParticles();
5139                 if (r_timereport_active)
5140                         R_TimeReport("particles");
5141
5142                 R_DrawExplosions();
5143                 if (r_timereport_active)
5144                         R_TimeReport("explosions");
5145
5146                 R_DrawLightningBeams();
5147                 if (r_timereport_active)
5148                         R_TimeReport("lightning");
5149         }
5150
5151         R_SetupGenericShader(true);
5152         VM_CL_AddPolygonsToMeshQueue();
5153
5154         if (r_refdef.view.showdebug)
5155         {
5156                 if (cl_locs_show.integer)
5157                 {
5158                         R_DrawLocs();
5159                         if (r_timereport_active)
5160                                 R_TimeReport("showlocs");
5161                 }
5162
5163                 if (r_drawportals.integer)
5164                 {
5165                         R_DrawPortals();
5166                         if (r_timereport_active)
5167                                 R_TimeReport("portals");
5168                 }
5169
5170                 if (r_showbboxes.value > 0)
5171                 {
5172                         R_DrawEntityBBoxes();
5173                         if (r_timereport_active)
5174                                 R_TimeReport("bboxes");
5175                 }
5176         }
5177
5178         R_SetupGenericShader(true);
5179         R_MeshQueue_RenderTransparent();
5180         if (r_timereport_active)
5181                 R_TimeReport("drawtrans");
5182
5183         R_SetupGenericShader(true);
5184
5185         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))
5186         {
5187                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
5188                 if (r_timereport_active)
5189                         R_TimeReport("worlddebug");
5190                 R_DrawModelsDebug();
5191                 if (r_timereport_active)
5192                         R_TimeReport("modeldebug");
5193         }
5194
5195         R_SetupGenericShader(true);
5196
5197         if (cl.csqc_vidvars.drawworld)
5198         {
5199                 R_DrawCoronas();
5200                 if (r_timereport_active)
5201                         R_TimeReport("coronas");
5202         }
5203
5204         // don't let sound skip if going slow
5205         if (r_refdef.scene.extraupdate)
5206                 S_ExtraUpdate ();
5207
5208         R_ResetViewRendering2D();
5209 }
5210
5211 static const unsigned short bboxelements[36] =
5212 {
5213         5, 1, 3, 5, 3, 7,
5214         6, 2, 0, 6, 0, 4,
5215         7, 3, 2, 7, 2, 6,
5216         4, 0, 1, 4, 1, 5,
5217         4, 5, 7, 4, 7, 6,
5218         1, 0, 2, 1, 2, 3,
5219 };
5220
5221 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
5222 {
5223         int i;
5224         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
5225
5226         RSurf_ActiveWorldEntity();
5227
5228         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5229         GL_DepthMask(false);
5230         GL_DepthRange(0, 1);
5231         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5232         R_Mesh_ResetTextureState();
5233
5234         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
5235         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
5236         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
5237         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
5238         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
5239         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
5240         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
5241         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
5242         R_FillColors(color4f, 8, cr, cg, cb, ca);
5243         if (r_refdef.fogenabled)
5244         {
5245                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
5246                 {
5247                         f1 = RSurf_FogVertex(v);
5248                         f2 = 1 - f1;
5249                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
5250                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
5251                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
5252                 }
5253         }
5254         R_Mesh_VertexPointer(vertex3f, 0, 0);
5255         R_Mesh_ColorPointer(color4f, 0, 0);
5256         R_Mesh_ResetTextureState();
5257         R_SetupGenericShader(false);
5258         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
5259 }
5260
5261 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5262 {
5263         int i;
5264         float color[4];
5265         prvm_edict_t *edict;
5266         prvm_prog_t *prog_save = prog;
5267
5268         // this function draws bounding boxes of server entities
5269         if (!sv.active)
5270                 return;
5271
5272         GL_CullFace(GL_NONE);
5273         R_SetupGenericShader(false);
5274
5275         prog = 0;
5276         SV_VM_Begin();
5277         for (i = 0;i < numsurfaces;i++)
5278         {
5279                 edict = PRVM_EDICT_NUM(surfacelist[i]);
5280                 switch ((int)edict->fields.server->solid)
5281                 {
5282                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
5283                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
5284                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
5285                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
5286                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
5287                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
5288                 }
5289                 color[3] *= r_showbboxes.value;
5290                 color[3] = bound(0, color[3], 1);
5291                 GL_DepthTest(!r_showdisabledepthtest.integer);
5292                 GL_CullFace(r_refdef.view.cullface_front);
5293                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
5294         }
5295         SV_VM_End();
5296         prog = prog_save;
5297 }
5298
5299 static void R_DrawEntityBBoxes(void)
5300 {
5301         int i;
5302         prvm_edict_t *edict;
5303         vec3_t center;
5304         prvm_prog_t *prog_save = prog;
5305
5306         // this function draws bounding boxes of server entities
5307         if (!sv.active)
5308                 return;
5309
5310         prog = 0;
5311         SV_VM_Begin();
5312         for (i = 0;i < prog->num_edicts;i++)
5313         {
5314                 edict = PRVM_EDICT_NUM(i);
5315                 if (edict->priv.server->free)
5316                         continue;
5317                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
5318                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
5319                         continue;
5320                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
5321                         continue;
5322                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
5323                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
5324         }
5325         SV_VM_End();
5326         prog = prog_save;
5327 }
5328
5329 static const int nomodelelement3i[24] =
5330 {
5331         5, 2, 0,
5332         5, 1, 2,
5333         5, 0, 3,
5334         5, 3, 1,
5335         0, 2, 4,
5336         2, 1, 4,
5337         3, 0, 4,
5338         1, 3, 4
5339 };
5340
5341 static const unsigned short nomodelelement3s[24] =
5342 {
5343         5, 2, 0,
5344         5, 1, 2,
5345         5, 0, 3,
5346         5, 3, 1,
5347         0, 2, 4,
5348         2, 1, 4,
5349         3, 0, 4,
5350         1, 3, 4
5351 };
5352
5353 static const float nomodelvertex3f[6*3] =
5354 {
5355         -16,   0,   0,
5356          16,   0,   0,
5357           0, -16,   0,
5358           0,  16,   0,
5359           0,   0, -16,
5360           0,   0,  16
5361 };
5362
5363 static const float nomodelcolor4f[6*4] =
5364 {
5365         0.0f, 0.0f, 0.5f, 1.0f,
5366         0.0f, 0.0f, 0.5f, 1.0f,
5367         0.0f, 0.5f, 0.0f, 1.0f,
5368         0.0f, 0.5f, 0.0f, 1.0f,
5369         0.5f, 0.0f, 0.0f, 1.0f,
5370         0.5f, 0.0f, 0.0f, 1.0f
5371 };
5372
5373 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
5374 {
5375         int i;
5376         float f1, f2, *c;
5377         float color4f[6*4];
5378
5379         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);
5380
5381         // this is only called once per entity so numsurfaces is always 1, and
5382         // surfacelist is always {0}, so this code does not handle batches
5383
5384         if (rsurface.ent_flags & RENDER_ADDITIVE)
5385         {
5386                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5387                 GL_DepthMask(false);
5388         }
5389         else if (rsurface.ent_color[3] < 1)
5390         {
5391                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5392                 GL_DepthMask(false);
5393         }
5394         else
5395         {
5396                 GL_BlendFunc(GL_ONE, GL_ZERO);
5397                 GL_DepthMask(true);
5398         }
5399         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
5400         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
5401         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
5402         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
5403         R_SetupGenericShader(false);
5404         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
5405         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
5406         R_Mesh_ColorPointer(color4f, 0, 0);
5407         for (i = 0, c = color4f;i < 6;i++, c += 4)
5408         {
5409                 c[0] *= rsurface.ent_color[0];
5410                 c[1] *= rsurface.ent_color[1];
5411                 c[2] *= rsurface.ent_color[2];
5412                 c[3] *= rsurface.ent_color[3];
5413         }
5414         if (r_refdef.fogenabled)
5415         {
5416                 for (i = 0, c = color4f;i < 6;i++, c += 4)
5417                 {
5418                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
5419                         f2 = 1 - f1;
5420                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
5421                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
5422                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
5423                 }
5424         }
5425         R_Mesh_ResetTextureState();
5426         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
5427 }
5428
5429 void R_DrawNoModel(entity_render_t *ent)
5430 {
5431         vec3_t org;
5432         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5433         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
5434                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
5435         else
5436                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
5437 }
5438
5439 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
5440 {
5441         vec3_t right1, right2, diff, normal;
5442
5443         VectorSubtract (org2, org1, normal);
5444
5445         // calculate 'right' vector for start
5446         VectorSubtract (r_refdef.view.origin, org1, diff);
5447         CrossProduct (normal, diff, right1);
5448         VectorNormalize (right1);
5449
5450         // calculate 'right' vector for end
5451         VectorSubtract (r_refdef.view.origin, org2, diff);
5452         CrossProduct (normal, diff, right2);
5453         VectorNormalize (right2);
5454
5455         vert[ 0] = org1[0] + width * right1[0];
5456         vert[ 1] = org1[1] + width * right1[1];
5457         vert[ 2] = org1[2] + width * right1[2];
5458         vert[ 3] = org1[0] - width * right1[0];
5459         vert[ 4] = org1[1] - width * right1[1];
5460         vert[ 5] = org1[2] - width * right1[2];
5461         vert[ 6] = org2[0] - width * right2[0];
5462         vert[ 7] = org2[1] - width * right2[1];
5463         vert[ 8] = org2[2] - width * right2[2];
5464         vert[ 9] = org2[0] + width * right2[0];
5465         vert[10] = org2[1] + width * right2[1];
5466         vert[11] = org2[2] + width * right2[2];
5467 }
5468
5469 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)
5470 {
5471         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
5472         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
5473         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
5474         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
5475         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
5476         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
5477         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
5478         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
5479         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
5480         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
5481         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
5482         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
5483 }
5484
5485 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
5486 {
5487         int i;
5488         float *vertex3f;
5489         float v[3];
5490         VectorSet(v, x, y, z);
5491         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
5492                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
5493                         break;
5494         if (i == mesh->numvertices)
5495         {
5496                 if (mesh->numvertices < mesh->maxvertices)
5497                 {
5498                         VectorCopy(v, vertex3f);
5499                         mesh->numvertices++;
5500                 }
5501                 return mesh->numvertices;
5502         }
5503         else
5504                 return i;
5505 }
5506
5507 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
5508 {
5509         int i;
5510         int *e, element[3];
5511         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5512         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
5513         e = mesh->element3i + mesh->numtriangles * 3;
5514         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
5515         {
5516                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
5517                 if (mesh->numtriangles < mesh->maxtriangles)
5518                 {
5519                         *e++ = element[0];
5520                         *e++ = element[1];
5521                         *e++ = element[2];
5522                         mesh->numtriangles++;
5523                 }
5524                 element[1] = element[2];
5525         }
5526 }
5527
5528 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
5529 {
5530         int i;
5531         int *e, element[3];
5532         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5533         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
5534         e = mesh->element3i + mesh->numtriangles * 3;
5535         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
5536         {
5537                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
5538                 if (mesh->numtriangles < mesh->maxtriangles)
5539                 {
5540                         *e++ = element[0];
5541                         *e++ = element[1];
5542                         *e++ = element[2];
5543                         mesh->numtriangles++;
5544                 }
5545                 element[1] = element[2];
5546         }
5547 }
5548
5549 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
5550 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
5551 {
5552         int planenum, planenum2;
5553         int w;
5554         int tempnumpoints;
5555         mplane_t *plane, *plane2;
5556         double maxdist;
5557         double temppoints[2][256*3];
5558         // figure out how large a bounding box we need to properly compute this brush
5559         maxdist = 0;
5560         for (w = 0;w < numplanes;w++)
5561                 maxdist = max(maxdist, fabs(planes[w].dist));
5562         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
5563         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
5564         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
5565         {
5566                 w = 0;
5567                 tempnumpoints = 4;
5568                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
5569                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
5570                 {
5571                         if (planenum2 == planenum)
5572                                 continue;
5573                         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);
5574                         w = !w;
5575                 }
5576                 if (tempnumpoints < 3)
5577                         continue;
5578                 // generate elements forming a triangle fan for this polygon
5579                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
5580         }
5581 }
5582
5583 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)
5584 {
5585         texturelayer_t *layer;
5586         layer = t->currentlayers + t->currentnumlayers++;
5587         layer->type = type;
5588         layer->depthmask = depthmask;
5589         layer->blendfunc1 = blendfunc1;
5590         layer->blendfunc2 = blendfunc2;
5591         layer->texture = texture;
5592         layer->texmatrix = *matrix;
5593         layer->color[0] = r * r_refdef.view.colorscale;
5594         layer->color[1] = g * r_refdef.view.colorscale;
5595         layer->color[2] = b * r_refdef.view.colorscale;
5596         layer->color[3] = a;
5597 }
5598
5599 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
5600 {
5601         double index, f;
5602         index = parms[2] + r_refdef.scene.time * parms[3];
5603         index -= floor(index);
5604         switch (func)
5605         {
5606         default:
5607         case Q3WAVEFUNC_NONE:
5608         case Q3WAVEFUNC_NOISE:
5609         case Q3WAVEFUNC_COUNT:
5610                 f = 0;
5611                 break;
5612         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
5613         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
5614         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
5615         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
5616         case Q3WAVEFUNC_TRIANGLE:
5617                 index *= 4;
5618                 f = index - floor(index);
5619                 if (index < 1)
5620                         f = f;
5621                 else if (index < 2)
5622                         f = 1 - f;
5623                 else if (index < 3)
5624                         f = -f;
5625                 else
5626                         f = -(1 - f);
5627                 break;
5628         }
5629         return (float)(parms[0] + parms[1] * f);
5630 }
5631
5632 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
5633 {
5634         int w, h, idx;
5635         float f;
5636         float tcmat[12];
5637         matrix4x4_t matrix, temp;
5638         switch(tcmod->tcmod)
5639         {
5640                 case Q3TCMOD_COUNT:
5641                 case Q3TCMOD_NONE:
5642                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5643                                 matrix = r_waterscrollmatrix;
5644                         else
5645                                 matrix = identitymatrix;
5646                         break;
5647                 case Q3TCMOD_ENTITYTRANSLATE:
5648                         // this is used in Q3 to allow the gamecode to control texcoord
5649                         // scrolling on the entity, which is not supported in darkplaces yet.
5650                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
5651                         break;
5652                 case Q3TCMOD_ROTATE:
5653                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
5654                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
5655                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
5656                         break;
5657                 case Q3TCMOD_SCALE:
5658                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
5659                         break;
5660                 case Q3TCMOD_SCROLL:
5661                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
5662                         break;
5663                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
5664                         w = (int) tcmod->parms[0];
5665                         h = (int) tcmod->parms[1];
5666                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
5667                         f = f - floor(f);
5668                         idx = (int) floor(f * w * h);
5669                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
5670                         break;
5671                 case Q3TCMOD_STRETCH:
5672                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
5673                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
5674                         break;
5675                 case Q3TCMOD_TRANSFORM:
5676                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
5677                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
5678                         VectorSet(tcmat +  6, 0                   , 0                , 1);
5679                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
5680                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
5681                         break;
5682                 case Q3TCMOD_TURBULENT:
5683                         // this is handled in the RSurf_PrepareVertices function
5684                         matrix = identitymatrix;
5685                         break;
5686         }
5687         temp = *texmatrix;
5688         Matrix4x4_Concat(texmatrix, &matrix, &temp);
5689 }
5690
5691 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
5692 {
5693         int textureflags = TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
5694         char name[MAX_QPATH];
5695         skinframe_t *skinframe;
5696         unsigned char pixels[296*194];
5697         strlcpy(cache->name, skinname, sizeof(cache->name));
5698         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
5699         if (developer_loading.integer)
5700                 Con_Printf("loading %s\n", name);
5701         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5702         if (!skinframe || !skinframe->base)
5703         {
5704                 unsigned char *f;
5705                 fs_offset_t filesize;
5706                 skinframe = NULL;
5707                 f = FS_LoadFile(name, tempmempool, true, &filesize);
5708                 if (f)
5709                 {
5710                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
5711                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
5712                         Mem_Free(f);
5713                 }
5714         }
5715         cache->skinframe = skinframe;
5716 }
5717
5718 texture_t *R_GetCurrentTexture(texture_t *t)
5719 {
5720         int i;
5721         const entity_render_t *ent = rsurface.entity;
5722         dp_model_t *model = ent->model;
5723         q3shaderinfo_layer_tcmod_t *tcmod;
5724
5725         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
5726                 return t->currentframe;
5727         t->update_lastrenderframe = r_frame;
5728         t->update_lastrenderentity = (void *)ent;
5729
5730         // switch to an alternate material if this is a q1bsp animated material
5731         {
5732                 texture_t *texture = t;
5733                 int s = rsurface.ent_skinnum;
5734                 if ((unsigned int)s >= (unsigned int)model->numskins)
5735                         s = 0;
5736                 if (model->skinscenes)
5737                 {
5738                         if (model->skinscenes[s].framecount > 1)
5739                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
5740                         else
5741                                 s = model->skinscenes[s].firstframe;
5742                 }
5743                 if (s > 0)
5744                         t = t + s * model->num_surfaces;
5745                 if (t->animated)
5746                 {
5747                         // use an alternate animation if the entity's frame is not 0,
5748                         // and only if the texture has an alternate animation
5749                         if (rsurface.ent_alttextures && t->anim_total[1])
5750                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
5751                         else
5752                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
5753                 }
5754                 texture->currentframe = t;
5755         }
5756
5757         // update currentskinframe to be a qw skin or animation frame
5758         if (rsurface.ent_qwskin >= 0)
5759         {
5760                 i = rsurface.ent_qwskin;
5761                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
5762                 {
5763                         r_qwskincache_size = cl.maxclients;
5764                         if (r_qwskincache)
5765                                 Mem_Free(r_qwskincache);
5766                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
5767                 }
5768                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
5769                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
5770                 t->currentskinframe = r_qwskincache[i].skinframe;
5771                 if (t->currentskinframe == NULL)
5772                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5773         }
5774         else if (t->numskinframes >= 2)
5775                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
5776         if (t->backgroundnumskinframes >= 2)
5777                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
5778
5779         t->currentmaterialflags = t->basematerialflags;
5780         t->currentalpha = rsurface.ent_color[3];
5781         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
5782                 t->currentalpha *= r_wateralpha.value;
5783         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
5784                 t->currentalpha *= t->r_water_wateralpha;
5785         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
5786                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
5787         if (!(rsurface.ent_flags & RENDER_LIGHT))
5788                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
5789         else if (rsurface.modeltexcoordlightmap2f == NULL)
5790         {
5791                 // pick a model lighting mode
5792                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
5793                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
5794                 else
5795                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
5796         }
5797         if (rsurface.ent_flags & RENDER_ADDITIVE)
5798                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5799         else if (t->currentalpha < 1)
5800                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
5801         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
5802                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
5803         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
5804                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
5805         if (t->backgroundnumskinframes)
5806                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
5807         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
5808         {
5809                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
5810                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
5811         }
5812         else
5813                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
5814
5815         // there is no tcmod
5816         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
5817         {
5818                 t->currenttexmatrix = r_waterscrollmatrix;
5819                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
5820         }
5821         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
5822         {
5823                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
5824                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
5825         }
5826
5827         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5828                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
5829         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
5830                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
5831
5832         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
5833         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
5834         t->glosstexture = r_texture_black;
5835         t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
5836         t->backgroundglosstexture = r_texture_black;
5837         t->specularpower = r_shadow_glossexponent.value;
5838         // TODO: store reference values for these in the texture?
5839         t->specularscale = 0;
5840         if (r_shadow_gloss.integer > 0)
5841         {
5842                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
5843                 {
5844                         if (r_shadow_glossintensity.value > 0)
5845                         {
5846                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
5847                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
5848                                 t->specularscale = r_shadow_glossintensity.value;
5849                         }
5850                 }
5851                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
5852                 {
5853                         t->glosstexture = r_texture_white;
5854                         t->backgroundglosstexture = r_texture_white;
5855                         t->specularscale = r_shadow_gloss2intensity.value;
5856                         t->specularpower = r_shadow_gloss2exponent.value;
5857                 }
5858         }
5859         t->specularscale *= t->specularscalemod;
5860         t->specularpower *= t->specularpowermod;
5861
5862         // lightmaps mode looks bad with dlights using actual texturing, so turn
5863         // off the colormap and glossmap, but leave the normalmap on as it still
5864         // accurately represents the shading involved
5865         if (gl_lightmaps.integer)
5866         {
5867                 t->basetexture = r_texture_grey128;
5868                 t->backgroundbasetexture = NULL;
5869                 t->specularscale = 0;
5870                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
5871         }
5872
5873         Vector4Set(t->lightmapcolor, rsurface.ent_color[0], rsurface.ent_color[1], rsurface.ent_color[2], t->currentalpha);
5874         VectorClear(t->dlightcolor);
5875         t->currentnumlayers = 0;
5876         if (t->currentmaterialflags & MATERIALFLAG_WALL)
5877         {
5878                 int layerflags = 0;
5879                 int blendfunc1, blendfunc2;
5880                 qboolean depthmask;
5881                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
5882                 {
5883                         blendfunc1 = GL_SRC_ALPHA;
5884                         blendfunc2 = GL_ONE;
5885                 }
5886                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
5887                 {
5888                         blendfunc1 = GL_SRC_ALPHA;
5889                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
5890                 }
5891                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
5892                 {
5893                         blendfunc1 = t->customblendfunc[0];
5894                         blendfunc2 = t->customblendfunc[1];
5895                 }
5896                 else
5897                 {
5898                         blendfunc1 = GL_ONE;
5899                         blendfunc2 = GL_ZERO;
5900                 }
5901                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
5902                 if (r_refdef.fogenabled && (t->currentmaterialflags & MATERIALFLAG_BLENDED))
5903                         layerflags |= TEXTURELAYERFLAG_FOGDARKEN;
5904                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5905                 {
5906                         // fullbright is not affected by r_refdef.lightmapintensity
5907                         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]);
5908                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5909                                 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]);
5910                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5911                                 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]);
5912                 }
5913                 else
5914                 {
5915                         vec3_t ambientcolor;
5916                         float colorscale;
5917                         // set the color tint used for lights affecting this surface
5918                         VectorSet(t->dlightcolor, rsurface.ent_color[0] * t->lightmapcolor[3], rsurface.ent_color[1] * t->lightmapcolor[3], rsurface.ent_color[2] * t->lightmapcolor[3]);
5919                         colorscale = 2;
5920                         // q3bsp has no lightmap updates, so the lightstylevalue that
5921                         // would normally be baked into the lightmap must be
5922                         // applied to the color
5923                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
5924                         if (model->type == mod_brushq3)
5925                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
5926                         colorscale *= r_refdef.lightmapintensity;
5927                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient * (1.0f / 64.0f), ambientcolor);
5928                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
5929                         // basic lit geometry
5930                         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]);
5931                         // add pants/shirt if needed
5932                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5933                                 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]);
5934                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5935                                 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]);
5936                         // now add ambient passes if needed
5937                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
5938                         {
5939                                 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]);
5940                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->currentskinframe->pants)
5941                                         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]);
5942                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->currentskinframe->shirt)
5943                                         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]);
5944                         }
5945                 }
5946                 if (t->currentskinframe->glow != NULL && !gl_lightmaps.integer)
5947                         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]);
5948                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
5949                 {
5950                         // if this is opaque use alpha blend which will darken the earlier
5951                         // passes cheaply.
5952                         //
5953                         // if this is an alpha blended material, all the earlier passes
5954                         // were darkened by fog already, so we only need to add the fog
5955                         // color ontop through the fog mask texture
5956                         //
5957                         // if this is an additive blended material, all the earlier passes
5958                         // were darkened by fog already, and we should not add fog color
5959                         // (because the background was not darkened, there is no fog color
5960                         // that was lost behind it).
5961                         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]);
5962                 }
5963         }
5964
5965         return t->currentframe;
5966 }
5967
5968 rsurfacestate_t rsurface;
5969
5970 void R_Mesh_ResizeArrays(int newvertices)
5971 {
5972         float *base;
5973         if (rsurface.array_size >= newvertices)
5974                 return;
5975         if (rsurface.array_modelvertex3f)
5976                 Mem_Free(rsurface.array_modelvertex3f);
5977         rsurface.array_size = (newvertices + 1023) & ~1023;
5978         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
5979         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
5980         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
5981         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
5982         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
5983         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
5984         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
5985         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
5986         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
5987         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
5988         rsurface.array_color4f           = base + rsurface.array_size * 27;
5989         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
5990 }
5991
5992 void RSurf_ActiveWorldEntity(void)
5993 {
5994         dp_model_t *model = r_refdef.scene.worldmodel;
5995         //if (rsurface.entity == r_refdef.scene.worldentity)
5996         //      return;
5997         rsurface.entity = r_refdef.scene.worldentity;
5998         rsurface.ent_skinnum = 0;
5999         rsurface.ent_qwskin = -1;
6000         rsurface.ent_shadertime = 0;
6001         Vector4Set(rsurface.ent_color, 1, 1, 1, 1);
6002         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
6003         if (rsurface.array_size < model->surfmesh.num_vertices)
6004                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6005         rsurface.matrix = identitymatrix;
6006         rsurface.inversematrix = identitymatrix;
6007         rsurface.matrixscale = 1;
6008         rsurface.inversematrixscale = 1;
6009         R_Mesh_Matrix(&identitymatrix);
6010         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
6011         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
6012         rsurface.fograngerecip = r_refdef.fograngerecip;
6013         rsurface.fogheightfade = r_refdef.fogheightfade;
6014         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
6015         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6016         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6017         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6018         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6019         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6020         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6021         VectorSet(rsurface.glowmod, 1, 1, 1);
6022         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6023         rsurface.frameblend[0].lerp = 1;
6024         rsurface.ent_alttextures = false;
6025         rsurface.basepolygonfactor = r_refdef.polygonfactor;
6026         rsurface.basepolygonoffset = r_refdef.polygonoffset;
6027         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
6028         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6029         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6030         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6031         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6032         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6033         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6034         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6035         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6036         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
6037         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6038         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6039         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
6040         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6041         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6042         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
6043         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6044         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6045         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
6046         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6047         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6048         rsurface.modelelement3i = model->surfmesh.data_element3i;
6049         rsurface.modelelement3s = model->surfmesh.data_element3s;
6050         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6051         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6052         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6053         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6054         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6055         rsurface.modelsurfaces = model->data_surfaces;
6056         rsurface.generatedvertex = false;
6057         rsurface.vertex3f  = rsurface.modelvertex3f;
6058         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6059         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6060         rsurface.svector3f = rsurface.modelsvector3f;
6061         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6062         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6063         rsurface.tvector3f = rsurface.modeltvector3f;
6064         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6065         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6066         rsurface.normal3f  = rsurface.modelnormal3f;
6067         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6068         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6069         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6070 }
6071
6072 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6073 {
6074         dp_model_t *model = ent->model;
6075         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
6076         //      return;
6077         rsurface.entity = (entity_render_t *)ent;
6078         rsurface.ent_skinnum = ent->skinnum;
6079         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;
6080         rsurface.ent_shadertime = ent->shadertime;
6081         Vector4Set(rsurface.ent_color, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha);
6082         rsurface.ent_flags = ent->flags;
6083         if (rsurface.array_size < model->surfmesh.num_vertices)
6084                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
6085         rsurface.matrix = ent->matrix;
6086         rsurface.inversematrix = ent->inversematrix;
6087         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6088         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6089         R_Mesh_Matrix(&rsurface.matrix);
6090         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6091         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6092         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6093         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6094         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6095         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6096         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
6097         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
6098         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
6099         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
6100         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
6101         VectorCopy(ent->glowmod, rsurface.glowmod);
6102         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
6103         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
6104         rsurface.basepolygonfactor = r_refdef.polygonfactor;
6105         rsurface.basepolygonoffset = r_refdef.polygonoffset;
6106         if (ent->model->brush.submodel)
6107         {
6108                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
6109                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
6110         }
6111         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
6112         {
6113                 if (R_AnimCache_GetEntity((entity_render_t *)ent, wantnormals, wanttangents))
6114                 {
6115                         rsurface.modelvertex3f = r_animcachestate.entity[ent->animcacheindex].vertex3f;
6116                         rsurface.modelsvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].svector3f : NULL;
6117                         rsurface.modeltvector3f = wanttangents ? r_animcachestate.entity[ent->animcacheindex].tvector3f : NULL;
6118                         rsurface.modelnormal3f = wantnormals ? r_animcachestate.entity[ent->animcacheindex].normal3f : NULL;
6119                 }
6120                 else if (wanttangents)
6121                 {
6122                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6123                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6124                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6125                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6126                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
6127                 }
6128                 else if (wantnormals)
6129                 {
6130                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6131                         rsurface.modelsvector3f = NULL;
6132                         rsurface.modeltvector3f = NULL;
6133                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6134                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
6135                 }
6136                 else
6137                 {
6138                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
6139                         rsurface.modelsvector3f = NULL;
6140                         rsurface.modeltvector3f = NULL;
6141                         rsurface.modelnormal3f = NULL;
6142                         model->AnimateVertices(model, rsurface.frameblend, rsurface.array_modelvertex3f, NULL, NULL, NULL);
6143                 }
6144                 rsurface.modelvertex3f_bufferobject = 0;
6145                 rsurface.modelvertex3f_bufferoffset = 0;
6146                 rsurface.modelsvector3f_bufferobject = 0;
6147                 rsurface.modelsvector3f_bufferoffset = 0;
6148                 rsurface.modeltvector3f_bufferobject = 0;
6149                 rsurface.modeltvector3f_bufferoffset = 0;
6150                 rsurface.modelnormal3f_bufferobject = 0;
6151                 rsurface.modelnormal3f_bufferoffset = 0;
6152                 rsurface.generatedvertex = true;
6153         }
6154         else
6155         {
6156                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
6157                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
6158                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
6159                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
6160                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
6161                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
6162                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
6163                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
6164                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
6165                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
6166                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
6167                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
6168                 rsurface.generatedvertex = false;
6169         }
6170         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
6171         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
6172         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
6173         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
6174         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
6175         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
6176         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
6177         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
6178         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
6179         rsurface.modelelement3i = model->surfmesh.data_element3i;
6180         rsurface.modelelement3s = model->surfmesh.data_element3s;
6181         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
6182         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
6183         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
6184         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
6185         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
6186         rsurface.modelsurfaces = model->data_surfaces;
6187         rsurface.vertex3f  = rsurface.modelvertex3f;
6188         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6189         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6190         rsurface.svector3f = rsurface.modelsvector3f;
6191         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6192         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6193         rsurface.tvector3f = rsurface.modeltvector3f;
6194         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6195         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6196         rsurface.normal3f  = rsurface.modelnormal3f;
6197         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6198         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6199         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6200 }
6201
6202 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)
6203 {
6204         rsurface.entity = r_refdef.scene.worldentity;
6205         rsurface.ent_skinnum = 0;
6206         rsurface.ent_qwskin = -1;
6207         rsurface.ent_shadertime = shadertime;
6208         Vector4Set(rsurface.ent_color, r, g, b, a);
6209         rsurface.ent_flags = entflags;
6210         rsurface.modelnum_vertices = numvertices;
6211         rsurface.modelnum_triangles = numtriangles;
6212         if (rsurface.array_size < rsurface.modelnum_vertices)
6213                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
6214         rsurface.matrix = *matrix;
6215         rsurface.inversematrix = *inversematrix;
6216         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
6217         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
6218         R_Mesh_Matrix(&rsurface.matrix);
6219         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
6220         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
6221         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
6222         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
6223         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
6224         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
6225         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
6226         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
6227         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
6228         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
6229         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
6230         VectorSet(rsurface.glowmod, 1, 1, 1);
6231         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
6232         rsurface.frameblend[0].lerp = 1;
6233         rsurface.ent_alttextures = false;
6234         rsurface.basepolygonfactor = r_refdef.polygonfactor;
6235         rsurface.basepolygonoffset = r_refdef.polygonoffset;
6236         if (wanttangents)
6237         {
6238                 rsurface.modelvertex3f = vertex3f;
6239                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
6240                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
6241                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6242         }
6243         else if (wantnormals)
6244         {
6245                 rsurface.modelvertex3f = vertex3f;
6246                 rsurface.modelsvector3f = NULL;
6247                 rsurface.modeltvector3f = NULL;
6248                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
6249         }
6250         else
6251         {
6252                 rsurface.modelvertex3f = vertex3f;
6253                 rsurface.modelsvector3f = NULL;
6254                 rsurface.modeltvector3f = NULL;
6255                 rsurface.modelnormal3f = NULL;
6256         }
6257         rsurface.modelvertex3f_bufferobject = 0;
6258         rsurface.modelvertex3f_bufferoffset = 0;
6259         rsurface.modelsvector3f_bufferobject = 0;
6260         rsurface.modelsvector3f_bufferoffset = 0;
6261         rsurface.modeltvector3f_bufferobject = 0;
6262         rsurface.modeltvector3f_bufferoffset = 0;
6263         rsurface.modelnormal3f_bufferobject = 0;
6264         rsurface.modelnormal3f_bufferoffset = 0;
6265         rsurface.generatedvertex = true;
6266         rsurface.modellightmapcolor4f  = color4f;
6267         rsurface.modellightmapcolor4f_bufferobject = 0;
6268         rsurface.modellightmapcolor4f_bufferoffset = 0;
6269         rsurface.modeltexcoordtexture2f  = texcoord2f;
6270         rsurface.modeltexcoordtexture2f_bufferobject = 0;
6271         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
6272         rsurface.modeltexcoordlightmap2f  = NULL;
6273         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
6274         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
6275         rsurface.modelelement3i = element3i;
6276         rsurface.modelelement3s = element3s;
6277         rsurface.modelelement3i_bufferobject = 0;
6278         rsurface.modelelement3s_bufferobject = 0;
6279         rsurface.modellightmapoffsets = NULL;
6280         rsurface.modelsurfaces = NULL;
6281         rsurface.vertex3f  = rsurface.modelvertex3f;
6282         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6283         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6284         rsurface.svector3f = rsurface.modelsvector3f;
6285         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6286         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6287         rsurface.tvector3f = rsurface.modeltvector3f;
6288         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6289         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6290         rsurface.normal3f  = rsurface.modelnormal3f;
6291         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6292         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6293         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
6294
6295         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
6296         {
6297                 if ((wantnormals || wanttangents) && !normal3f)
6298                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6299                 if (wanttangents && !svector3f)
6300                         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);
6301         }
6302 }
6303
6304 float RSurf_FogPoint(const float *v)
6305 {
6306         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6307         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
6308         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
6309         float FogHeightFade = r_refdef.fogheightfade;
6310         float fogfrac;
6311         unsigned int fogmasktableindex;
6312         if (r_refdef.fogplaneviewabove)
6313                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6314         else
6315                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6316         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
6317         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6318 }
6319
6320 float RSurf_FogVertex(const float *v)
6321 {
6322         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
6323         float FogPlaneViewDist = rsurface.fogplaneviewdist;
6324         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
6325         float FogHeightFade = rsurface.fogheightfade;
6326         float fogfrac;
6327         unsigned int fogmasktableindex;
6328         if (r_refdef.fogplaneviewabove)
6329                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
6330         else
6331                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
6332         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
6333         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
6334 }
6335
6336 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
6337 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
6338 {
6339         int deformindex;
6340         int texturesurfaceindex;
6341         int i, j;
6342         float amplitude;
6343         float animpos;
6344         float scale;
6345         const float *v1, *in_tc;
6346         float *out_tc;
6347         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
6348         float waveparms[4];
6349         q3shaderinfo_deform_t *deform;
6350         // 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
6351         if (rsurface.generatedvertex)
6352         {
6353                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
6354                         generatenormals = true;
6355                 for (i = 0;i < Q3MAXDEFORMS;i++)
6356                 {
6357                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
6358                         {
6359                                 generatetangents = true;
6360                                 generatenormals = true;
6361                         }
6362                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
6363                                 generatenormals = true;
6364                 }
6365                 if (generatenormals && !rsurface.modelnormal3f)
6366                 {
6367                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
6368                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
6369                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
6370                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
6371                 }
6372                 if (generatetangents && !rsurface.modelsvector3f)
6373                 {
6374                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
6375                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
6376                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
6377                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
6378                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
6379                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
6380                         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);
6381                 }
6382         }
6383         rsurface.vertex3f  = rsurface.modelvertex3f;
6384         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
6385         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
6386         rsurface.svector3f = rsurface.modelsvector3f;
6387         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
6388         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
6389         rsurface.tvector3f = rsurface.modeltvector3f;
6390         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
6391         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
6392         rsurface.normal3f  = rsurface.modelnormal3f;
6393         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
6394         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
6395         // if vertices are deformed (sprite flares and things in maps, possibly
6396         // water waves, bulges and other deformations), generate them into
6397         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
6398         // (may be static model data or generated data for an animated model, or
6399         //  the previous deform pass)
6400         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
6401         {
6402                 switch (deform->deform)
6403                 {
6404                 default:
6405                 case Q3DEFORM_PROJECTIONSHADOW:
6406                 case Q3DEFORM_TEXT0:
6407                 case Q3DEFORM_TEXT1:
6408                 case Q3DEFORM_TEXT2:
6409                 case Q3DEFORM_TEXT3:
6410                 case Q3DEFORM_TEXT4:
6411                 case Q3DEFORM_TEXT5:
6412                 case Q3DEFORM_TEXT6:
6413                 case Q3DEFORM_TEXT7:
6414                 case Q3DEFORM_NONE:
6415                         break;
6416                 case Q3DEFORM_AUTOSPRITE:
6417                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6418                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6419                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6420                         VectorNormalize(newforward);
6421                         VectorNormalize(newright);
6422                         VectorNormalize(newup);
6423                         // make deformed versions of only the model vertices used by the specified surfaces
6424                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6425                         {
6426                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6427                                 // a single autosprite surface can contain multiple sprites...
6428                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
6429                                 {
6430                                         VectorClear(center);
6431                                         for (i = 0;i < 4;i++)
6432                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6433                                         VectorScale(center, 0.25f, center);
6434                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
6435                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
6436                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
6437                                         for (i = 0;i < 4;i++)
6438                                         {
6439                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
6440                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6441                                         }
6442                                 }
6443                                 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);
6444                                 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);
6445                         }
6446                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6447                         rsurface.vertex3f_bufferobject = 0;
6448                         rsurface.vertex3f_bufferoffset = 0;
6449                         rsurface.svector3f = rsurface.array_deformedsvector3f;
6450                         rsurface.svector3f_bufferobject = 0;
6451                         rsurface.svector3f_bufferoffset = 0;
6452                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
6453                         rsurface.tvector3f_bufferobject = 0;
6454                         rsurface.tvector3f_bufferoffset = 0;
6455                         rsurface.normal3f = rsurface.array_deformednormal3f;
6456                         rsurface.normal3f_bufferobject = 0;
6457                         rsurface.normal3f_bufferoffset = 0;
6458                         break;
6459                 case Q3DEFORM_AUTOSPRITE2:
6460                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
6461                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
6462                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
6463                         VectorNormalize(newforward);
6464                         VectorNormalize(newright);
6465                         VectorNormalize(newup);
6466                         // make deformed versions of only the model vertices used by the specified surfaces
6467                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6468                         {
6469                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6470                                 const float *v1, *v2;
6471                                 vec3_t start, end;
6472                                 float f, l;
6473                                 struct
6474                                 {
6475                                         float length2;
6476                                         const float *v1;
6477                                         const float *v2;
6478                                 }
6479                                 shortest[2];
6480                                 memset(shortest, 0, sizeof(shortest));
6481                                 // a single autosprite surface can contain multiple sprites...
6482                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
6483                                 {
6484                                         VectorClear(center);
6485                                         for (i = 0;i < 4;i++)
6486                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
6487                                         VectorScale(center, 0.25f, center);
6488                                         // find the two shortest edges, then use them to define the
6489                                         // axis vectors for rotating around the central axis
6490                                         for (i = 0;i < 6;i++)
6491                                         {
6492                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
6493                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
6494 #if 0
6495                                                 Debug_PolygonBegin(NULL, 0);
6496                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
6497                                                 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);
6498                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
6499                                                 Debug_PolygonEnd();
6500 #endif
6501                                                 l = VectorDistance2(v1, v2);
6502                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
6503                                                 if (v1[2] != v2[2])
6504                                                         l += (1.0f / 1024.0f);
6505                                                 if (shortest[0].length2 > l || i == 0)
6506                                                 {
6507                                                         shortest[1] = shortest[0];
6508                                                         shortest[0].length2 = l;
6509                                                         shortest[0].v1 = v1;
6510                                                         shortest[0].v2 = v2;
6511                                                 }
6512                                                 else if (shortest[1].length2 > l || i == 1)
6513                                                 {
6514                                                         shortest[1].length2 = l;
6515                                                         shortest[1].v1 = v1;
6516                                                         shortest[1].v2 = v2;
6517                                                 }
6518                                         }
6519                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
6520                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
6521 #if 0
6522                                         Debug_PolygonBegin(NULL, 0);
6523                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
6524                                         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);
6525                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
6526                                         Debug_PolygonEnd();
6527 #endif
6528                                         // this calculates the right vector from the shortest edge
6529                                         // and the up vector from the edge midpoints
6530                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
6531                                         VectorNormalize(right);
6532                                         VectorSubtract(end, start, up);
6533                                         VectorNormalize(up);
6534                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
6535                                         VectorSubtract(rsurface.localvieworigin, center, forward);
6536                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
6537                                         VectorNegate(forward, forward);
6538                                         VectorReflect(forward, 0, up, forward);
6539                                         VectorNormalize(forward);
6540                                         CrossProduct(up, forward, newright);
6541                                         VectorNormalize(newright);
6542 #if 0
6543                                         Debug_PolygonBegin(NULL, 0);
6544                                         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);
6545                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
6546                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
6547                                         Debug_PolygonEnd();
6548 #endif
6549 #if 0
6550                                         Debug_PolygonBegin(NULL, 0);
6551                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
6552                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
6553                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
6554                                         Debug_PolygonEnd();
6555 #endif
6556                                         // rotate the quad around the up axis vector, this is made
6557                                         // especially easy by the fact we know the quad is flat,
6558                                         // so we only have to subtract the center position and
6559                                         // measure distance along the right vector, and then
6560                                         // multiply that by the newright vector and add back the
6561                                         // center position
6562                                         // we also need to subtract the old position to undo the
6563                                         // displacement from the center, which we do with a
6564                                         // DotProduct, the subtraction/addition of center is also
6565                                         // optimized into DotProducts here
6566                                         l = DotProduct(right, center);
6567                                         for (i = 0;i < 4;i++)
6568                                         {
6569                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
6570                                                 f = DotProduct(right, v1) - l;
6571                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
6572                                         }
6573                                 }
6574                                 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);
6575                                 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);
6576                         }
6577                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6578                         rsurface.vertex3f_bufferobject = 0;
6579                         rsurface.vertex3f_bufferoffset = 0;
6580                         rsurface.svector3f = rsurface.array_deformedsvector3f;
6581                         rsurface.svector3f_bufferobject = 0;
6582                         rsurface.svector3f_bufferoffset = 0;
6583                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
6584                         rsurface.tvector3f_bufferobject = 0;
6585                         rsurface.tvector3f_bufferoffset = 0;
6586                         rsurface.normal3f = rsurface.array_deformednormal3f;
6587                         rsurface.normal3f_bufferobject = 0;
6588                         rsurface.normal3f_bufferoffset = 0;
6589                         break;
6590                 case Q3DEFORM_NORMAL:
6591                         // deform the normals to make reflections wavey
6592                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6593                         {
6594                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6595                                 for (j = 0;j < surface->num_vertices;j++)
6596                                 {
6597                                         float vertex[3];
6598                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
6599                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
6600                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
6601                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6602                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6603                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
6604                                         VectorNormalize(normal);
6605                                 }
6606                                 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);
6607                         }
6608                         rsurface.svector3f = rsurface.array_deformedsvector3f;
6609                         rsurface.svector3f_bufferobject = 0;
6610                         rsurface.svector3f_bufferoffset = 0;
6611                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
6612                         rsurface.tvector3f_bufferobject = 0;
6613                         rsurface.tvector3f_bufferoffset = 0;
6614                         rsurface.normal3f = rsurface.array_deformednormal3f;
6615                         rsurface.normal3f_bufferobject = 0;
6616                         rsurface.normal3f_bufferoffset = 0;
6617                         break;
6618                 case Q3DEFORM_WAVE:
6619                         // deform vertex array to make wavey water and flags and such
6620                         waveparms[0] = deform->waveparms[0];
6621                         waveparms[1] = deform->waveparms[1];
6622                         waveparms[2] = deform->waveparms[2];
6623                         waveparms[3] = deform->waveparms[3];
6624                         // this is how a divisor of vertex influence on deformation
6625                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
6626                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6627                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6628                         {
6629                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6630                                 for (j = 0;j < surface->num_vertices;j++)
6631                                 {
6632                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
6633                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
6634                                         // if the wavefunc depends on time, evaluate it per-vertex
6635                                         if (waveparms[3])
6636                                         {
6637                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
6638                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
6639                                         }
6640                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
6641                                 }
6642                         }
6643                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6644                         rsurface.vertex3f_bufferobject = 0;
6645                         rsurface.vertex3f_bufferoffset = 0;
6646                         break;
6647                 case Q3DEFORM_BULGE:
6648                         // deform vertex array to make the surface have moving bulges
6649                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6650                         {
6651                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6652                                 for (j = 0;j < surface->num_vertices;j++)
6653                                 {
6654                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
6655                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6656                                 }
6657                         }
6658                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6659                         rsurface.vertex3f_bufferobject = 0;
6660                         rsurface.vertex3f_bufferoffset = 0;
6661                         break;
6662                 case Q3DEFORM_MOVE:
6663                         // deform vertex array
6664                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
6665                         VectorScale(deform->parms, scale, waveparms);
6666                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6667                         {
6668                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6669                                 for (j = 0;j < surface->num_vertices;j++)
6670                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
6671                         }
6672                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
6673                         rsurface.vertex3f_bufferobject = 0;
6674                         rsurface.vertex3f_bufferoffset = 0;
6675                         break;
6676                 }
6677         }
6678         // generate texcoords based on the chosen texcoord source
6679         switch(rsurface.texture->tcgen.tcgen)
6680         {
6681         default:
6682         case Q3TCGEN_TEXTURE:
6683                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
6684                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
6685                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
6686                 break;
6687         case Q3TCGEN_LIGHTMAP:
6688                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
6689                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
6690                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
6691                 break;
6692         case Q3TCGEN_VECTOR:
6693                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6694                 {
6695                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6696                         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)
6697                         {
6698                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
6699                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
6700                         }
6701                 }
6702                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
6703                 rsurface.texcoordtexture2f_bufferobject  = 0;
6704                 rsurface.texcoordtexture2f_bufferoffset  = 0;
6705                 break;
6706         case Q3TCGEN_ENVIRONMENT:
6707                 // make environment reflections using a spheremap
6708                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6709                 {
6710                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6711                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
6712                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
6713                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
6714                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
6715                         {
6716                                 // identical to Q3A's method, but executed in worldspace so
6717                                 // carried models can be shiny too
6718
6719                                 float viewer[3], d, reflected[3], worldreflected[3];
6720
6721                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
6722                                 // VectorNormalize(viewer);
6723
6724                                 d = DotProduct(normal, viewer);
6725
6726                                 reflected[0] = normal[0]*2*d - viewer[0];
6727                                 reflected[1] = normal[1]*2*d - viewer[1];
6728                                 reflected[2] = normal[2]*2*d - viewer[2];
6729                                 // note: this is proportinal to viewer, so we can normalize later
6730
6731                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
6732                                 VectorNormalize(worldreflected);
6733
6734                                 // note: this sphere map only uses world x and z!
6735                                 // so positive and negative y will LOOK THE SAME.
6736                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
6737                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
6738                         }
6739                 }
6740                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
6741                 rsurface.texcoordtexture2f_bufferobject  = 0;
6742                 rsurface.texcoordtexture2f_bufferoffset  = 0;
6743                 break;
6744         }
6745         // the only tcmod that needs software vertex processing is turbulent, so
6746         // check for it here and apply the changes if needed
6747         // and we only support that as the first one
6748         // (handling a mixture of turbulent and other tcmods would be problematic
6749         //  without punting it entirely to a software path)
6750         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
6751         {
6752                 amplitude = rsurface.texture->tcmods[0].parms[1];
6753                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
6754                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
6755                 {
6756                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
6757                         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)
6758                         {
6759                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6760                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
6761                         }
6762                 }
6763                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
6764                 rsurface.texcoordtexture2f_bufferobject  = 0;
6765                 rsurface.texcoordtexture2f_bufferoffset  = 0;
6766         }
6767         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
6768         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
6769         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
6770         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
6771 }
6772
6773 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
6774 {
6775         int i, j;
6776         const msurface_t *surface = texturesurfacelist[0];
6777         const msurface_t *surface2;
6778         int firstvertex;
6779         int endvertex;
6780         int numvertices;
6781         int numtriangles;
6782         // TODO: lock all array ranges before render, rather than on each surface
6783         if (texturenumsurfaces == 1)
6784         {
6785                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6786                 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);
6787         }
6788         else if (r_batchmode.integer == 2)
6789         {
6790                 #define MAXBATCHTRIANGLES 4096
6791                 int batchtriangles = 0;
6792                 int batchelements[MAXBATCHTRIANGLES*3];
6793                 for (i = 0;i < texturenumsurfaces;i = j)
6794                 {
6795                         surface = texturesurfacelist[i];
6796                         j = i + 1;
6797                         if (surface->num_triangles > MAXBATCHTRIANGLES)
6798                         {
6799                                 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);
6800                                 continue;
6801                         }
6802                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6803                         batchtriangles = surface->num_triangles;
6804                         firstvertex = surface->num_firstvertex;
6805                         endvertex = surface->num_firstvertex + surface->num_vertices;
6806                         for (;j < texturenumsurfaces;j++)
6807                         {
6808                                 surface2 = texturesurfacelist[j];
6809                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6810                                         break;
6811                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6812                                 batchtriangles += surface2->num_triangles;
6813                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
6814                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6815                         }
6816                         surface2 = texturesurfacelist[j-1];
6817                         numvertices = endvertex - firstvertex;
6818                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6819                 }
6820         }
6821         else if (r_batchmode.integer == 1)
6822         {
6823                 for (i = 0;i < texturenumsurfaces;i = j)
6824                 {
6825                         surface = texturesurfacelist[i];
6826                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6827                                 if (texturesurfacelist[j] != surface2)
6828                                         break;
6829                         surface2 = texturesurfacelist[j-1];
6830                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6831                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6832                         GL_LockArrays(surface->num_firstvertex, numvertices);
6833                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6834                 }
6835         }
6836         else
6837         {
6838                 for (i = 0;i < texturenumsurfaces;i++)
6839                 {
6840                         surface = texturesurfacelist[i];
6841                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6842                         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);
6843                 }
6844         }
6845 }
6846
6847 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit, int refractiontexunit, int reflectiontexunit)
6848 {
6849         int i, planeindex, vertexindex;
6850         float d, bestd;
6851         vec3_t vert;
6852         const float *v;
6853         r_waterstate_waterplane_t *p, *bestp;
6854         const msurface_t *surface;
6855         if (r_waterstate.renderingscene)
6856                 return;
6857         for (i = 0;i < texturenumsurfaces;i++)
6858         {
6859                 surface = texturesurfacelist[i];
6860                 if (lightmaptexunit >= 0)
6861                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6862                 if (deluxemaptexunit >= 0)
6863                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6864                 // pick the closest matching water plane
6865                 bestd = 0;
6866                 bestp = NULL;
6867                 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6868                 {
6869                         d = 0;
6870                         for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
6871                         {
6872                                 Matrix4x4_Transform(&rsurface.matrix, v, vert);
6873                                 d += fabs(PlaneDiff(vert, &p->plane));
6874                         }
6875                         if (bestd > d || !bestp)
6876                         {
6877                                 bestd = d;
6878                                 bestp = p;
6879                         }
6880                 }
6881                 if (bestp)
6882                 {
6883                         if (refractiontexunit >= 0)
6884                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(bestp->texture_refraction));
6885                         if (reflectiontexunit >= 0)
6886                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(bestp->texture_reflection));
6887                 }
6888                 else
6889                 {
6890                         if (refractiontexunit >= 0)
6891                                 R_Mesh_TexBind(refractiontexunit, R_GetTexture(r_texture_black));
6892                         if (reflectiontexunit >= 0)
6893                                 R_Mesh_TexBind(reflectiontexunit, R_GetTexture(r_texture_black));
6894                 }
6895                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6896                 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);
6897         }
6898 }
6899
6900 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
6901 {
6902         int i;
6903         int j;
6904         const msurface_t *surface = texturesurfacelist[0];
6905         const msurface_t *surface2;
6906         int firstvertex;
6907         int endvertex;
6908         int numvertices;
6909         int numtriangles;
6910         // TODO: lock all array ranges before render, rather than on each surface
6911         if (texturenumsurfaces == 1)
6912         {
6913                 R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6914                 if (deluxemaptexunit >= 0)
6915                         R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6916                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
6917                 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);
6918         }
6919         else if (r_batchmode.integer == 2)
6920         {
6921                 #define MAXBATCHTRIANGLES 4096
6922                 int batchtriangles = 0;
6923                 int batchelements[MAXBATCHTRIANGLES*3];
6924                 for (i = 0;i < texturenumsurfaces;i = j)
6925                 {
6926                         surface = texturesurfacelist[i];
6927                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6928                         if (deluxemaptexunit >= 0)
6929                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6930                         j = i + 1;
6931                         if (surface->num_triangles > MAXBATCHTRIANGLES)
6932                         {
6933                                 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);
6934                                 continue;
6935                         }
6936                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
6937                         batchtriangles = surface->num_triangles;
6938                         firstvertex = surface->num_firstvertex;
6939                         endvertex = surface->num_firstvertex + surface->num_vertices;
6940                         for (;j < texturenumsurfaces;j++)
6941                         {
6942                                 surface2 = texturesurfacelist[j];
6943                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
6944                                         break;
6945                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
6946                                 batchtriangles += surface2->num_triangles;
6947                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
6948                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
6949                         }
6950                         surface2 = texturesurfacelist[j-1];
6951                         numvertices = endvertex - firstvertex;
6952                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
6953                 }
6954         }
6955         else if (r_batchmode.integer == 1)
6956         {
6957 #if 0
6958                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
6959                 for (i = 0;i < texturenumsurfaces;i = j)
6960                 {
6961                         surface = texturesurfacelist[i];
6962                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6963                                 if (texturesurfacelist[j] != surface2)
6964                                         break;
6965                         Con_Printf(" %i", j - i);
6966                 }
6967                 Con_Printf("\n");
6968                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
6969 #endif
6970                 for (i = 0;i < texturenumsurfaces;i = j)
6971                 {
6972                         surface = texturesurfacelist[i];
6973                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6974                         if (deluxemaptexunit >= 0)
6975                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
6976                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
6977                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
6978                                         break;
6979 #if 0
6980                         Con_Printf(" %i", j - i);
6981 #endif
6982                         surface2 = texturesurfacelist[j-1];
6983                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
6984                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
6985                         GL_LockArrays(surface->num_firstvertex, numvertices);
6986                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
6987                 }
6988 #if 0
6989                 Con_Printf("\n");
6990 #endif
6991         }
6992         else
6993         {
6994                 for (i = 0;i < texturenumsurfaces;i++)
6995                 {
6996                         surface = texturesurfacelist[i];
6997                         R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
6998                         if (deluxemaptexunit >= 0)
6999                                 R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
7000                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7001                         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);
7002                 }
7003         }
7004 }
7005
7006 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7007 {
7008         int j;
7009         int texturesurfaceindex;
7010         if (r_showsurfaces.integer == 2)
7011         {
7012                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7013                 {
7014                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7015                         for (j = 0;j < surface->num_triangles;j++)
7016                         {
7017                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
7018                                 GL_Color(f, f, f, 1);
7019                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
7020                         }
7021                 }
7022         }
7023         else
7024         {
7025                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7026                 {
7027                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7028                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
7029                         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);
7030                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
7031                         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);
7032                 }
7033         }
7034 }
7035
7036 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7037 {
7038         int texturesurfaceindex;
7039         int i;
7040         const float *v;
7041         float *c2;
7042         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7043         {
7044                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7045                 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)
7046                 {
7047                         c2[0] = 0.5;
7048                         c2[1] = 0.5;
7049                         c2[2] = 0.5;
7050                         c2[3] = 1;
7051                 }
7052         }
7053         rsurface.lightmapcolor4f = rsurface.array_color4f;
7054         rsurface.lightmapcolor4f_bufferobject = 0;
7055         rsurface.lightmapcolor4f_bufferoffset = 0;
7056 }
7057
7058 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7059 {
7060         int texturesurfaceindex;
7061         int i;
7062         float f;
7063         const float *v;
7064         const float *c;
7065         float *c2;
7066         if (rsurface.lightmapcolor4f)
7067         {
7068                 // generate color arrays for the surfaces in this list
7069                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7070                 {
7071                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7072                         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)
7073                         {
7074                                 f = RSurf_FogVertex(v);
7075                                 c2[0] = c[0] * f;
7076                                 c2[1] = c[1] * f;
7077                                 c2[2] = c[2] * f;
7078                                 c2[3] = c[3];
7079                         }
7080                 }
7081         }
7082         else
7083         {
7084                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7085                 {
7086                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7087                         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)
7088                         {
7089                                 f = RSurf_FogVertex(v);
7090                                 c2[0] = f;
7091                                 c2[1] = f;
7092                                 c2[2] = f;
7093                                 c2[3] = 1;
7094                         }
7095                 }
7096         }
7097         rsurface.lightmapcolor4f = rsurface.array_color4f;
7098         rsurface.lightmapcolor4f_bufferobject = 0;
7099         rsurface.lightmapcolor4f_bufferoffset = 0;
7100 }
7101
7102 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7103 {
7104         int texturesurfaceindex;
7105         int i;
7106         float f;
7107         const float *v;
7108         const float *c;
7109         float *c2;
7110         if (!rsurface.lightmapcolor4f)
7111                 return;
7112         // generate color arrays for the surfaces in this list
7113         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7114         {
7115                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7116                 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)
7117                 {
7118                         f = RSurf_FogVertex(v);
7119                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
7120                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
7121                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
7122                         c2[3] = c[3];
7123                 }
7124         }
7125         rsurface.lightmapcolor4f = rsurface.array_color4f;
7126         rsurface.lightmapcolor4f_bufferobject = 0;
7127         rsurface.lightmapcolor4f_bufferoffset = 0;
7128 }
7129
7130 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
7131 {
7132         int texturesurfaceindex;
7133         int i;
7134         const float *c;
7135         float *c2;
7136         if (!rsurface.lightmapcolor4f)
7137                 return;
7138         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7139         {
7140                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7141                 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)
7142                 {
7143                         c2[0] = c[0] * r;
7144                         c2[1] = c[1] * g;
7145                         c2[2] = c[2] * b;
7146                         c2[3] = c[3] * a;
7147                 }
7148         }
7149         rsurface.lightmapcolor4f = rsurface.array_color4f;
7150         rsurface.lightmapcolor4f_bufferobject = 0;
7151         rsurface.lightmapcolor4f_bufferoffset = 0;
7152 }
7153
7154 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7155 {
7156         int texturesurfaceindex;
7157         int i;
7158         const float *c;
7159         float *c2;
7160         if (!rsurface.lightmapcolor4f)
7161                 return;
7162         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7163         {
7164                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7165                 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)
7166                 {
7167                         c2[0] = c[0] + r_refdef.scene.ambient / 128.0;
7168                         c2[1] = c[1] + r_refdef.scene.ambient / 128.0;
7169                         c2[2] = c[2] + r_refdef.scene.ambient / 128.0;
7170                         c2[3] = c[3];
7171                 }
7172         }
7173         rsurface.lightmapcolor4f = rsurface.array_color4f;
7174         rsurface.lightmapcolor4f_bufferobject = 0;
7175         rsurface.lightmapcolor4f_bufferoffset = 0;
7176 }
7177
7178 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7179 {
7180         // TODO: optimize
7181         rsurface.lightmapcolor4f = NULL;
7182         rsurface.lightmapcolor4f_bufferobject = 0;
7183         rsurface.lightmapcolor4f_bufferoffset = 0;
7184         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7185         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7186         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7187         GL_Color(r, g, b, a);
7188         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
7189 }
7190
7191 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7192 {
7193         // TODO: optimize applyfog && applycolor case
7194         // just apply fog if necessary, and tint the fog color array if necessary
7195         rsurface.lightmapcolor4f = NULL;
7196         rsurface.lightmapcolor4f_bufferobject = 0;
7197         rsurface.lightmapcolor4f_bufferoffset = 0;
7198         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7199         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7200         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7201         GL_Color(r, g, b, a);
7202         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7203 }
7204
7205 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7206 {
7207         int texturesurfaceindex;
7208         int i;
7209         float *c;
7210         // TODO: optimize
7211         if (texturesurfacelist[0]->lightmapinfo)
7212         {
7213                 // generate color arrays for the surfaces in this list
7214                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7215                 {
7216                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7217                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
7218                         {
7219                                 if (surface->lightmapinfo->samples)
7220                                 {
7221                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
7222                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
7223                                         VectorScale(lm, scale, c);
7224                                         if (surface->lightmapinfo->styles[1] != 255)
7225                                         {
7226                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
7227                                                 lm += size3;
7228                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
7229                                                 VectorMA(c, scale, lm, c);
7230                                                 if (surface->lightmapinfo->styles[2] != 255)
7231                                                 {
7232                                                         lm += size3;
7233                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
7234                                                         VectorMA(c, scale, lm, c);
7235                                                         if (surface->lightmapinfo->styles[3] != 255)
7236                                                         {
7237                                                                 lm += size3;
7238                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
7239                                                                 VectorMA(c, scale, lm, c);
7240                                                         }
7241                                                 }
7242                                         }
7243                                 }
7244                                 else
7245                                         VectorClear(c);
7246                                 c[3] = 1;
7247                         }
7248                 }
7249                 rsurface.lightmapcolor4f = rsurface.array_color4f;
7250                 rsurface.lightmapcolor4f_bufferobject = 0;
7251                 rsurface.lightmapcolor4f_bufferoffset = 0;
7252         }
7253         else
7254         {
7255                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7256                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7257                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7258         }
7259         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7260         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7261         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7262         GL_Color(r, g, b, a);
7263         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7264 }
7265
7266 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
7267 {
7268         int texturesurfaceindex;
7269         int i;
7270         float f;
7271         float alpha;
7272         const float *v;
7273         const float *n;
7274         float *c;
7275         vec3_t ambientcolor;
7276         vec3_t diffusecolor;
7277         vec3_t lightdir;
7278         // TODO: optimize
7279         // model lighting
7280         VectorCopy(rsurface.modellight_lightdir, lightdir);
7281         f = 0.5f * r_refdef.lightmapintensity;
7282         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
7283         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
7284         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
7285         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
7286         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
7287         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
7288         alpha = *a;
7289         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
7290         {
7291                 // generate color arrays for the surfaces in this list
7292                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7293                 {
7294                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7295                         int numverts = surface->num_vertices;
7296                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
7297                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
7298                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
7299                         // q3-style directional shading
7300                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
7301                         {
7302                                 if ((f = DotProduct(n, lightdir)) > 0)
7303                                         VectorMA(ambientcolor, f, diffusecolor, c);
7304                                 else
7305                                         VectorCopy(ambientcolor, c);
7306                                 c[3] = alpha;
7307                         }
7308                 }
7309                 *r = 1;
7310                 *g = 1;
7311                 *b = 1;
7312                 *a = 1;
7313                 rsurface.lightmapcolor4f = rsurface.array_color4f;
7314                 rsurface.lightmapcolor4f_bufferobject = 0;
7315                 rsurface.lightmapcolor4f_bufferoffset = 0;
7316                 *applycolor = false;
7317         }
7318         else
7319         {
7320                 *r = ambientcolor[0];
7321                 *g = ambientcolor[1];
7322                 *b = ambientcolor[2];
7323                 rsurface.lightmapcolor4f = NULL;
7324                 rsurface.lightmapcolor4f_bufferobject = 0;
7325                 rsurface.lightmapcolor4f_bufferoffset = 0;
7326         }
7327 }
7328
7329 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
7330 {
7331         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
7332         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
7333         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
7334         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7335         GL_Color(r, g, b, a);
7336         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7337 }
7338
7339 void RSurf_SetupDepthAndCulling(void)
7340 {
7341         // submodels are biased to avoid z-fighting with world surfaces that they
7342         // may be exactly overlapping (avoids z-fighting artifacts on certain
7343         // doors and things in Quake maps)
7344         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
7345         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
7346         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
7347         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
7348 }
7349
7350 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
7351 {
7352         // transparent sky would be ridiculous
7353         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
7354                 return;
7355         R_SetupGenericShader(false);
7356         skyrenderlater = true;
7357         RSurf_SetupDepthAndCulling();
7358         GL_DepthMask(true);
7359         // LordHavoc: HalfLife maps have freaky skypolys so don't use
7360         // skymasking on them, and Quake3 never did sky masking (unlike
7361         // software Quake and software Quake2), so disable the sky masking
7362         // in Quake3 maps as it causes problems with q3map2 sky tricks,
7363         // and skymasking also looks very bad when noclipping outside the
7364         // level, so don't use it then either.
7365         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
7366         {
7367                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
7368                 R_Mesh_ColorPointer(NULL, 0, 0);
7369                 R_Mesh_ResetTextureState();
7370                 if (skyrendermasked)
7371                 {
7372                         R_SetupDepthOrShadowShader();
7373                         // depth-only (masking)
7374                         GL_ColorMask(0,0,0,0);
7375                         // just to make sure that braindead drivers don't draw
7376                         // anything despite that colormask...
7377                         GL_BlendFunc(GL_ZERO, GL_ONE);
7378                 }
7379                 else
7380                 {
7381                         R_SetupGenericShader(false);
7382                         // fog sky
7383                         GL_BlendFunc(GL_ONE, GL_ZERO);
7384                 }
7385                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7386                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7387                 if (skyrendermasked)
7388                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7389         }
7390         R_Mesh_ResetTextureState();
7391         GL_Color(1, 1, 1, 1);
7392 }
7393
7394 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7395 {
7396         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
7397                 return;
7398
7399         R_Mesh_TexMatrix(0, &rsurface.texture->currenttexmatrix);
7400         R_Mesh_TexMatrix(1, &rsurface.texture->currentbackgroundtexmatrix);
7401         R_Mesh_TexBind(GL20TU_NORMAL, R_GetTexture(rsurface.texture->currentskinframe->nmap));
7402         R_Mesh_TexBind(GL20TU_COLOR, R_GetTexture(rsurface.texture->basetexture));
7403         R_Mesh_TexBind(GL20TU_GLOSS, R_GetTexture(rsurface.texture->glosstexture));
7404         R_Mesh_TexBind(GL20TU_GLOW, R_GetTexture(rsurface.texture->currentskinframe->glow));
7405         if (rsurface.texture->backgroundcurrentskinframe)
7406         {
7407                 R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->nmap));
7408                 R_Mesh_TexBind(GL20TU_SECONDARY_COLOR, R_GetTexture(rsurface.texture->backgroundbasetexture));
7409                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS, R_GetTexture(rsurface.texture->backgroundglosstexture));
7410                 R_Mesh_TexBind(GL20TU_SECONDARY_GLOW, R_GetTexture(rsurface.texture->backgroundcurrentskinframe->glow));
7411         }
7412         if(rsurface.texture->colormapping)
7413         {
7414                 R_Mesh_TexBind(GL20TU_PANTS, R_GetTexture(rsurface.texture->currentskinframe->pants));
7415                 R_Mesh_TexBind(GL20TU_SHIRT, R_GetTexture(rsurface.texture->currentskinframe->shirt));
7416         }
7417         R_Mesh_TexBind(GL20TU_FOGMASK, R_GetTexture(r_texture_fogattenuation));
7418         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7419                 R_Mesh_ColorPointer(NULL, 0, 0);
7420         else
7421                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7422
7423         if (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7424         {
7425                 // render background
7426                 GL_BlendFunc(GL_ONE, GL_ZERO);
7427                 GL_DepthMask(true);
7428                 GL_AlphaTest(false);
7429
7430                 GL_Color(1, 1, 1, 1);
7431                 R_Mesh_ColorPointer(NULL, 0, 0);
7432
7433                 R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
7434                 if (r_glsl_permutation)
7435                 {
7436                         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
7437                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7438                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7439                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7440                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7441                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7442                         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);
7443                 }
7444                 GL_LockArrays(0, 0);
7445
7446                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7447                 GL_DepthMask(false);
7448                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
7449                         R_Mesh_ColorPointer(NULL, 0, 0);
7450                 else
7451                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
7452                 R_Mesh_TexBind(GL20TU_REFRACTION, R_GetTexture(r_texture_white)); // changed per surface
7453                 R_Mesh_TexBind(GL20TU_REFLECTION, R_GetTexture(r_texture_white)); // changed per surface
7454         }
7455
7456         R_SetupSurfaceShader(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
7457         if (!r_glsl_permutation)
7458                 return;
7459
7460         RSurf_PrepareVerticesForBatch(r_glsl_permutation->loc_Texture_Normal >= 0 || r_glsl_permutation->loc_LightDir >= 0, r_glsl_permutation->loc_Texture_Normal >= 0, texturenumsurfaces, texturesurfacelist);
7461         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
7462         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
7463         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
7464         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
7465         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
7466
7467         if (r_glsl_permutation->loc_Texture_Refraction >= 0)
7468         {
7469                 GL_BlendFunc(GL_ONE, GL_ZERO);
7470                 GL_DepthMask(true);
7471                 GL_AlphaTest(false);
7472         }
7473         else
7474         {
7475                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
7476                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
7477                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
7478         }
7479
7480         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7481         {
7482                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7483                         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);
7484                 else
7485                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, GL20TU_LIGHTMAP, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? GL20TU_DELUXEMAP : -1);
7486         }
7487         else
7488         {
7489                 if (r_glsl_permutation->loc_Texture_Refraction >= 0 || r_glsl_permutation->loc_Texture_Reflection >= 0)
7490                         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);
7491                 else
7492                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7493         }
7494         GL_LockArrays(0, 0);
7495 }
7496
7497 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7498 {
7499         // OpenGL 1.3 path - anything not completely ancient
7500         int texturesurfaceindex;
7501         qboolean applycolor;
7502         qboolean applyfog;
7503         rmeshstate_t m;
7504         int layerindex;
7505         const texturelayer_t *layer;
7506         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7507
7508         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7509         {
7510                 vec4_t layercolor;
7511                 int layertexrgbscale;
7512                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7513                 {
7514                         if (layerindex == 0)
7515                                 GL_AlphaTest(true);
7516                         else
7517                         {
7518                                 GL_AlphaTest(false);
7519                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7520                         }
7521                 }
7522                 GL_DepthMask(layer->depthmask && writedepth);
7523                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7524                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
7525                 {
7526                         layertexrgbscale = 4;
7527                         VectorScale(layer->color, 0.25f, layercolor);
7528                 }
7529                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
7530                 {
7531                         layertexrgbscale = 2;
7532                         VectorScale(layer->color, 0.5f, layercolor);
7533                 }
7534                 else
7535                 {
7536                         layertexrgbscale = 1;
7537                         VectorScale(layer->color, 1.0f, layercolor);
7538                 }
7539                 layercolor[3] = layer->color[3];
7540                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
7541                 R_Mesh_ColorPointer(NULL, 0, 0);
7542                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7543                 switch (layer->type)
7544                 {
7545                 case TEXTURELAYERTYPE_LITTEXTURE:
7546                         memset(&m, 0, sizeof(m));
7547                         m.tex[0] = R_GetTexture(r_texture_white);
7548                         m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7549                         m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7550                         m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7551                         m.tex[1] = R_GetTexture(layer->texture);
7552                         m.texmatrix[1] = layer->texmatrix;
7553                         m.texrgbscale[1] = layertexrgbscale;
7554                         m.pointer_texcoord[1] = rsurface.texcoordtexture2f;
7555                         m.pointer_texcoord_bufferobject[1] = rsurface.texcoordtexture2f_bufferobject;
7556                         m.pointer_texcoord_bufferoffset[1] = rsurface.texcoordtexture2f_bufferoffset;
7557                         R_Mesh_TextureState(&m);
7558                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7559                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7560                         else if (rsurface.uselightmaptexture)
7561                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7562                         else
7563                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7564                         break;
7565                 case TEXTURELAYERTYPE_TEXTURE:
7566                         memset(&m, 0, sizeof(m));
7567                         m.tex[0] = R_GetTexture(layer->texture);
7568                         m.texmatrix[0] = layer->texmatrix;
7569                         m.texrgbscale[0] = layertexrgbscale;
7570                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7571                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7572                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7573                         R_Mesh_TextureState(&m);
7574                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
7575                         break;
7576                 case TEXTURELAYERTYPE_FOG:
7577                         memset(&m, 0, sizeof(m));
7578                         m.texrgbscale[0] = layertexrgbscale;
7579                         if (layer->texture)
7580                         {
7581                                 m.tex[0] = R_GetTexture(layer->texture);
7582                                 m.texmatrix[0] = layer->texmatrix;
7583                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7584                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7585                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7586                         }
7587                         R_Mesh_TextureState(&m);
7588                         // generate a color array for the fog pass
7589                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7590                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7591                         {
7592                                 int i;
7593                                 float f;
7594                                 const float *v;
7595                                 float *c;
7596                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7597                                 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)
7598                                 {
7599                                         f = 1 - RSurf_FogVertex(v);
7600                                         c[0] = layercolor[0];
7601                                         c[1] = layercolor[1];
7602                                         c[2] = layercolor[2];
7603                                         c[3] = f * layercolor[3];
7604                                 }
7605                         }
7606                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7607                         break;
7608                 default:
7609                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7610                 }
7611                 GL_LockArrays(0, 0);
7612         }
7613         CHECKGLERROR
7614         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7615         {
7616                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7617                 GL_AlphaTest(false);
7618         }
7619 }
7620
7621 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7622 {
7623         // OpenGL 1.1 - crusty old voodoo path
7624         int texturesurfaceindex;
7625         qboolean applyfog;
7626         rmeshstate_t m;
7627         int layerindex;
7628         const texturelayer_t *layer;
7629         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7630
7631         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
7632         {
7633                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7634                 {
7635                         if (layerindex == 0)
7636                                 GL_AlphaTest(true);
7637                         else
7638                         {
7639                                 GL_AlphaTest(false);
7640                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
7641                         }
7642                 }
7643                 GL_DepthMask(layer->depthmask && writedepth);
7644                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
7645                 R_Mesh_ColorPointer(NULL, 0, 0);
7646                 applyfog = (layer->flags & TEXTURELAYERFLAG_FOGDARKEN) != 0;
7647                 switch (layer->type)
7648                 {
7649                 case TEXTURELAYERTYPE_LITTEXTURE:
7650                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
7651                         {
7652                                 // two-pass lit texture with 2x rgbscale
7653                                 // first the lightmap pass
7654                                 memset(&m, 0, sizeof(m));
7655                                 m.tex[0] = R_GetTexture(r_texture_white);
7656                                 m.pointer_texcoord[0] = rsurface.modeltexcoordlightmap2f;
7657                                 m.pointer_texcoord_bufferobject[0] = rsurface.modeltexcoordlightmap2f_bufferobject;
7658                                 m.pointer_texcoord_bufferoffset[0] = rsurface.modeltexcoordlightmap2f_bufferoffset;
7659                                 R_Mesh_TextureState(&m);
7660                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7661                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7662                                 else if (rsurface.uselightmaptexture)
7663                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7664                                 else
7665                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
7666                                 GL_LockArrays(0, 0);
7667                                 // then apply the texture to it
7668                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7669                                 memset(&m, 0, sizeof(m));
7670                                 m.tex[0] = R_GetTexture(layer->texture);
7671                                 m.texmatrix[0] = layer->texmatrix;
7672                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7673                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7674                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7675                                 R_Mesh_TextureState(&m);
7676                                 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);
7677                         }
7678                         else
7679                         {
7680                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
7681                                 memset(&m, 0, sizeof(m));
7682                                 m.tex[0] = R_GetTexture(layer->texture);
7683                                 m.texmatrix[0] = layer->texmatrix;
7684                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7685                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7686                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7687                                 R_Mesh_TextureState(&m);
7688                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7689                                         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);
7690                                 else
7691                                         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);
7692                         }
7693                         break;
7694                 case TEXTURELAYERTYPE_TEXTURE:
7695                         // singletexture unlit texture with transparency support
7696                         memset(&m, 0, sizeof(m));
7697                         m.tex[0] = R_GetTexture(layer->texture);
7698                         m.texmatrix[0] = layer->texmatrix;
7699                         m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7700                         m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7701                         m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7702                         R_Mesh_TextureState(&m);
7703                         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);
7704                         break;
7705                 case TEXTURELAYERTYPE_FOG:
7706                         // singletexture fogging
7707                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
7708                         if (layer->texture)
7709                         {
7710                                 memset(&m, 0, sizeof(m));
7711                                 m.tex[0] = R_GetTexture(layer->texture);
7712                                 m.texmatrix[0] = layer->texmatrix;
7713                                 m.pointer_texcoord[0] = rsurface.texcoordtexture2f;
7714                                 m.pointer_texcoord_bufferobject[0] = rsurface.texcoordtexture2f_bufferobject;
7715                                 m.pointer_texcoord_bufferoffset[0] = rsurface.texcoordtexture2f_bufferoffset;
7716                                 R_Mesh_TextureState(&m);
7717                         }
7718                         else
7719                                 R_Mesh_ResetTextureState();
7720                         // generate a color array for the fog pass
7721                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
7722                         {
7723                                 int i;
7724                                 float f;
7725                                 const float *v;
7726                                 float *c;
7727                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
7728                                 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)
7729                                 {
7730                                         f = 1 - RSurf_FogVertex(v);
7731                                         c[0] = layer->color[0];
7732                                         c[1] = layer->color[1];
7733                                         c[2] = layer->color[2];
7734                                         c[3] = f * layer->color[3];
7735                                 }
7736                         }
7737                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7738                         break;
7739                 default:
7740                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
7741                 }
7742                 GL_LockArrays(0, 0);
7743         }
7744         CHECKGLERROR
7745         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7746         {
7747                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7748                 GL_AlphaTest(false);
7749         }
7750 }
7751
7752 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7753 {
7754         float c[4];
7755
7756         GL_AlphaTest(false);
7757         R_Mesh_ColorPointer(NULL, 0, 0);
7758         R_Mesh_ResetTextureState();
7759         R_SetupGenericShader(false);
7760
7761         if(rsurface.texture && rsurface.texture->currentskinframe)
7762         {
7763                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
7764                 c[3] *= rsurface.texture->currentalpha;
7765         }
7766         else
7767         {
7768                 c[0] = 1;
7769                 c[1] = 0;
7770                 c[2] = 1;
7771                 c[3] = 1;
7772         }
7773
7774         if (rsurface.texture->currentskinframe->pants || rsurface.texture->currentskinframe->shirt)
7775         {
7776                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
7777                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
7778                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
7779         }
7780
7781         // brighten it up (as texture value 127 means "unlit")
7782         c[0] *= 2 * r_refdef.view.colorscale;
7783         c[1] *= 2 * r_refdef.view.colorscale;
7784         c[2] *= 2 * r_refdef.view.colorscale;
7785
7786         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
7787                 c[3] *= r_wateralpha.value;
7788
7789         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
7790         {
7791                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7792                 GL_DepthMask(false);
7793         }
7794         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
7795         {
7796                 GL_BlendFunc(GL_ONE, GL_ONE);
7797                 GL_DepthMask(false);
7798         }
7799         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
7800         {
7801                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
7802                 GL_DepthMask(false);
7803         }
7804         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7805         {
7806                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
7807                 GL_DepthMask(false);
7808         }
7809         else
7810         {
7811                 GL_BlendFunc(GL_ONE, GL_ZERO);
7812                 GL_DepthMask(writedepth);
7813         }
7814
7815         rsurface.lightmapcolor4f = NULL;
7816
7817         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7818         {
7819                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7820
7821                 rsurface.lightmapcolor4f = NULL;
7822                 rsurface.lightmapcolor4f_bufferobject = 0;
7823                 rsurface.lightmapcolor4f_bufferoffset = 0;
7824         }
7825         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
7826         {
7827                 qboolean applycolor = true;
7828                 float one = 1.0;
7829
7830                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
7831
7832                 r_refdef.lightmapintensity = 1;
7833                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
7834                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
7835         }
7836         else
7837         {
7838                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7839
7840                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
7841                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
7842                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
7843         }
7844
7845         if(!rsurface.lightmapcolor4f)
7846                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
7847
7848         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
7849         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
7850         if(r_refdef.fogenabled)
7851                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
7852
7853         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
7854         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7855 }
7856
7857 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7858 {
7859         CHECKGLERROR
7860         RSurf_SetupDepthAndCulling();
7861         if (r_showsurfaces.integer == 3)
7862                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7863         else if (r_glsl.integer && gl_support_fragment_shader)
7864                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7865         else if (gl_combine.integer && r_textureunits.integer >= 2)
7866                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7867         else
7868                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7869         CHECKGLERROR
7870 }
7871
7872 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
7873 {
7874         CHECKGLERROR
7875         RSurf_SetupDepthAndCulling();
7876         if (r_showsurfaces.integer == 3)
7877                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
7878         else if (r_glsl.integer && gl_support_fragment_shader)
7879                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth);
7880         else if (gl_combine.integer && r_textureunits.integer >= 2)
7881                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
7882         else
7883                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
7884         CHECKGLERROR
7885 }
7886
7887 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7888 {
7889         int i, j;
7890         int texturenumsurfaces, endsurface;
7891         texture_t *texture;
7892         const msurface_t *surface;
7893         const msurface_t *texturesurfacelist[1024];
7894
7895         // if the model is static it doesn't matter what value we give for
7896         // wantnormals and wanttangents, so this logic uses only rules applicable
7897         // to a model, knowing that they are meaningless otherwise
7898         if (ent == r_refdef.scene.worldentity)
7899                 RSurf_ActiveWorldEntity();
7900         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7901                 RSurf_ActiveModelEntity(ent, false, false);
7902         else
7903                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
7904
7905         for (i = 0;i < numsurfaces;i = j)
7906         {
7907                 j = i + 1;
7908                 surface = rsurface.modelsurfaces + surfacelist[i];
7909                 texture = surface->texture;
7910                 rsurface.texture = R_GetCurrentTexture(texture);
7911                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
7912                 // scan ahead until we find a different texture
7913                 endsurface = min(i + 1024, numsurfaces);
7914                 texturenumsurfaces = 0;
7915                 texturesurfacelist[texturenumsurfaces++] = surface;
7916                 for (;j < endsurface;j++)
7917                 {
7918                         surface = rsurface.modelsurfaces + surfacelist[j];
7919                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
7920                                 break;
7921                         texturesurfacelist[texturenumsurfaces++] = surface;
7922                 }
7923                 // render the range of surfaces
7924                 if (ent == r_refdef.scene.worldentity)
7925                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7926                 else
7927                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false);
7928         }
7929         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7930         GL_AlphaTest(false);
7931 }
7932
7933 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly)
7934 {
7935         const entity_render_t *queueentity = r_refdef.scene.worldentity;
7936         CHECKGLERROR
7937         if (depthonly)
7938         {
7939                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
7940                         return;
7941                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
7942                         return;
7943                 RSurf_SetupDepthAndCulling();
7944                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7945                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7946         }
7947         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
7948         {
7949                 RSurf_SetupDepthAndCulling();
7950                 GL_AlphaTest(false);
7951                 R_Mesh_ColorPointer(NULL, 0, 0);
7952                 R_Mesh_ResetTextureState();
7953                 R_SetupGenericShader(false);
7954                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7955                 GL_DepthMask(true);
7956                 GL_BlendFunc(GL_ONE, GL_ZERO);
7957                 GL_Color(0, 0, 0, 1);
7958                 GL_DepthTest(writedepth);
7959                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
7960         }
7961         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
7962         {
7963                 RSurf_SetupDepthAndCulling();
7964                 GL_AlphaTest(false);
7965                 R_Mesh_ColorPointer(NULL, 0, 0);
7966                 R_Mesh_ResetTextureState();
7967                 R_SetupGenericShader(false);
7968                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
7969                 GL_DepthMask(true);
7970                 GL_BlendFunc(GL_ONE, GL_ZERO);
7971                 GL_DepthTest(true);
7972                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
7973         }
7974         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
7975                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
7976         else if (!rsurface.texture->currentnumlayers)
7977                 return;
7978         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
7979         {
7980                 // transparent surfaces get pushed off into the transparent queue
7981                 int surfacelistindex;
7982                 const msurface_t *surface;
7983                 vec3_t tempcenter, center;
7984                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
7985                 {
7986                         surface = texturesurfacelist[surfacelistindex];
7987                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
7988                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
7989                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
7990                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
7991                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
7992                 }
7993         }
7994         else
7995         {
7996                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
7997                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
7998         }
7999         CHECKGLERROR
8000 }
8001
8002 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8003 {
8004         int i, j;
8005         texture_t *texture;
8006         // break the surface list down into batches by texture and use of lightmapping
8007         for (i = 0;i < numsurfaces;i = j)
8008         {
8009                 j = i + 1;
8010                 // texture is the base texture pointer, rsurface.texture is the
8011                 // current frame/skin the texture is directing us to use (for example
8012                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8013                 // use skin 1 instead)
8014                 texture = surfacelist[i]->texture;
8015                 rsurface.texture = R_GetCurrentTexture(texture);
8016                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8017                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8018                 {
8019                         // if this texture is not the kind we want, skip ahead to the next one
8020                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8021                                 ;
8022                         continue;
8023                 }
8024                 // simply scan ahead until we find a different texture or lightmap state
8025                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8026                         ;
8027                 // render the range of surfaces
8028                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly);
8029         }
8030 }
8031
8032 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity)
8033 {
8034         CHECKGLERROR
8035         if (depthonly)
8036         {
8037                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
8038                         return;
8039                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
8040                         return;
8041                 RSurf_SetupDepthAndCulling();
8042                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8043                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8044         }
8045         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
8046         {
8047                 RSurf_SetupDepthAndCulling();
8048                 GL_AlphaTest(false);
8049                 R_Mesh_ColorPointer(NULL, 0, 0);
8050                 R_Mesh_ResetTextureState();
8051                 R_SetupGenericShader(false);
8052                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8053                 GL_DepthMask(true);
8054                 GL_BlendFunc(GL_ONE, GL_ZERO);
8055                 GL_Color(0, 0, 0, 1);
8056                 GL_DepthTest(writedepth);
8057                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
8058         }
8059         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8060         {
8061                 RSurf_SetupDepthAndCulling();
8062                 GL_AlphaTest(false);
8063                 R_Mesh_ColorPointer(NULL, 0, 0);
8064                 R_Mesh_ResetTextureState();
8065                 R_SetupGenericShader(false);
8066                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
8067                 GL_DepthMask(true);
8068                 GL_BlendFunc(GL_ONE, GL_ZERO);
8069                 GL_DepthTest(true);
8070                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
8071         }
8072         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
8073                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
8074         else if (!rsurface.texture->currentnumlayers)
8075                 return;
8076         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
8077         {
8078                 // transparent surfaces get pushed off into the transparent queue
8079                 int surfacelistindex;
8080                 const msurface_t *surface;
8081                 vec3_t tempcenter, center;
8082                 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
8083                 {
8084                         surface = texturesurfacelist[surfacelistindex];
8085                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
8086                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
8087                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
8088                         Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
8089                         if (queueentity->transparent_offset) // transparent offset
8090                         {
8091                                 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
8092                                 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
8093                                 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
8094                         }
8095                         R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
8096                 }
8097         }
8098         else
8099         {
8100                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
8101                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST));
8102         }
8103         CHECKGLERROR
8104 }
8105
8106 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly)
8107 {
8108         int i, j;
8109         texture_t *texture;
8110         // break the surface list down into batches by texture and use of lightmapping
8111         for (i = 0;i < numsurfaces;i = j)
8112         {
8113                 j = i + 1;
8114                 // texture is the base texture pointer, rsurface.texture is the
8115                 // current frame/skin the texture is directing us to use (for example
8116                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
8117                 // use skin 1 instead)
8118                 texture = surfacelist[i]->texture;
8119                 rsurface.texture = R_GetCurrentTexture(texture);
8120                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
8121                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
8122                 {
8123                         // if this texture is not the kind we want, skip ahead to the next one
8124                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
8125                                 ;
8126                         continue;
8127                 }
8128                 // simply scan ahead until we find a different texture or lightmap state
8129                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
8130                         ;
8131                 // render the range of surfaces
8132                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent);
8133         }
8134 }
8135
8136 float locboxvertex3f[6*4*3] =
8137 {
8138         1,0,1, 1,0,0, 1,1,0, 1,1,1,
8139         0,1,1, 0,1,0, 0,0,0, 0,0,1,
8140         1,1,1, 1,1,0, 0,1,0, 0,1,1,
8141         0,0,1, 0,0,0, 1,0,0, 1,0,1,
8142         0,0,1, 1,0,1, 1,1,1, 0,1,1,
8143         1,0,0, 0,0,0, 0,1,0, 1,1,0
8144 };
8145
8146 unsigned short locboxelements[6*2*3] =
8147 {
8148          0, 1, 2, 0, 2, 3,
8149          4, 5, 6, 4, 6, 7,
8150          8, 9,10, 8,10,11,
8151         12,13,14, 12,14,15,
8152         16,17,18, 16,18,19,
8153         20,21,22, 20,22,23
8154 };
8155
8156 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8157 {
8158         int i, j;
8159         cl_locnode_t *loc = (cl_locnode_t *)ent;
8160         vec3_t mins, size;
8161         float vertex3f[6*4*3];
8162         CHECKGLERROR
8163         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8164         GL_DepthMask(false);
8165         GL_DepthRange(0, 1);
8166         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8167         GL_DepthTest(true);
8168         GL_CullFace(GL_NONE);
8169         R_Mesh_Matrix(&identitymatrix);
8170
8171         R_Mesh_VertexPointer(vertex3f, 0, 0);
8172         R_Mesh_ColorPointer(NULL, 0, 0);
8173         R_Mesh_ResetTextureState();
8174         R_SetupGenericShader(false);
8175
8176         i = surfacelist[0];
8177         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8178                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8179                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
8180                         surfacelist[0] < 0 ? 0.5f : 0.125f);
8181
8182         if (VectorCompare(loc->mins, loc->maxs))
8183         {
8184                 VectorSet(size, 2, 2, 2);
8185                 VectorMA(loc->mins, -0.5f, size, mins);
8186         }
8187         else
8188         {
8189                 VectorCopy(loc->mins, mins);
8190                 VectorSubtract(loc->maxs, loc->mins, size);
8191         }
8192
8193         for (i = 0;i < 6*4*3;)
8194                 for (j = 0;j < 3;j++, i++)
8195                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
8196
8197         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
8198 }
8199
8200 void R_DrawLocs(void)
8201 {
8202         int index;
8203         cl_locnode_t *loc, *nearestloc;
8204         vec3_t center;
8205         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
8206         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
8207         {
8208                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
8209                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
8210         }
8211 }
8212
8213 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
8214 {
8215         if (decalsystem->decals)
8216                 Mem_Free(decalsystem->decals);
8217         memset(decalsystem, 0, sizeof(*decalsystem));
8218 }
8219
8220 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)
8221 {
8222         float *v3f;
8223         float *tc2f;
8224         float *c4f;
8225         float ca;
8226         tridecal_t *decal;
8227         tridecal_t *decals;
8228         int i;
8229         int maxdecals;
8230
8231         // expand or initialize the system
8232         if (decalsystem->maxdecals <= decalsystem->numdecals)
8233         {
8234                 decalsystem_t old = *decalsystem;
8235                 qboolean useshortelements;
8236                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
8237                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
8238                 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)));
8239                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
8240                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
8241                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
8242                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
8243                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
8244                 if (decalsystem->numdecals)
8245                 {
8246                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
8247                         memcpy(decalsystem->vertex3f, old.vertex3f, decalsystem->numdecals * sizeof(float[3][3]));
8248                         memcpy(decalsystem->texcoord2f, old.texcoord2f, decalsystem->numdecals * sizeof(float[3][2]));
8249                         memcpy(decalsystem->color4f, old.color4f, decalsystem->numdecals * sizeof(float[3][4]));
8250                 }
8251                 Mem_Free(old.decals);
8252                 for (i = 0;i < decalsystem->maxdecals*3;i++)
8253                         decalsystem->element3i[i] = i;
8254                 if (useshortelements)
8255                         for (i = 0;i < decalsystem->maxdecals*3;i++)
8256                                 decalsystem->element3s[i] = i;
8257         }
8258
8259         // grab a decal and search for another free slot for the next one
8260         maxdecals = decalsystem->maxdecals;
8261         decals = decalsystem->decals;
8262         decal = decalsystem->decals + (i = decalsystem->freedecal++);
8263         v3f = decalsystem->vertex3f + 9*i;
8264         tc2f = decalsystem->texcoord2f + 6*i;
8265         c4f = decalsystem->color4f + 12*i;
8266         for (i = decalsystem->freedecal;i < maxdecals && decals[i].colors[0][3];i++)
8267                 ;
8268         decalsystem->freedecal = i;
8269         if (decalsystem->numdecals <= i)
8270                 decalsystem->numdecals = i + 1;
8271
8272         // initialize the decal
8273         decal->lived = 0;
8274         decal->triangleindex = triangleindex;
8275         decal->colors[0][0] = (unsigned char)(c0[0]*255.0f);
8276         decal->colors[0][1] = (unsigned char)(c0[1]*255.0f);
8277         decal->colors[0][2] = (unsigned char)(c0[2]*255.0f);
8278         decal->colors[0][3] = 255;
8279         decal->colors[1][0] = (unsigned char)(c1[0]*255.0f);
8280         decal->colors[1][1] = (unsigned char)(c1[1]*255.0f);
8281         decal->colors[1][2] = (unsigned char)(c1[2]*255.0f);
8282         decal->colors[1][3] = 255;
8283         decal->colors[2][0] = (unsigned char)(c2[0]*255.0f);
8284         decal->colors[2][1] = (unsigned char)(c2[1]*255.0f);
8285         decal->colors[2][2] = (unsigned char)(c2[2]*255.0f);
8286         decal->colors[2][3] = 255;
8287         v3f[0] = v0[0];
8288         v3f[1] = v0[1];
8289         v3f[2] = v0[2];
8290         v3f[3] = v1[0];
8291         v3f[4] = v1[1];
8292         v3f[5] = v1[2];
8293         v3f[6] = v2[0];
8294         v3f[7] = v2[1];
8295         v3f[8] = v2[2];
8296         tc2f[0] = t0[0];
8297         tc2f[1] = t0[1];
8298         tc2f[2] = t1[0];
8299         tc2f[3] = t1[1];
8300         tc2f[4] = t2[0];
8301         tc2f[5] = t2[1];
8302         ca = (1.0f/255.0f);
8303         c4f[ 0] = decal->colors[0][0] * ca;
8304         c4f[ 1] = decal->colors[0][1] * ca;
8305         c4f[ 2] = decal->colors[0][2] * ca;
8306         c4f[ 3] = 1;
8307         c4f[ 4] = decal->colors[1][0] * ca;
8308         c4f[ 5] = decal->colors[1][1] * ca;
8309         c4f[ 6] = decal->colors[1][2] * ca;
8310         c4f[ 7] = 1;
8311         c4f[ 8] = decal->colors[2][0] * ca;
8312         c4f[ 9] = decal->colors[2][1] * ca;
8313         c4f[10] = decal->colors[2][2] * ca;
8314         c4f[11] = 1;
8315 }
8316
8317 extern cvar_t cl_decals_bias;
8318 extern cvar_t cl_decals_models;
8319 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)
8320 {
8321         matrix4x4_t projection;
8322         decalsystem_t *decalsystem;
8323         qboolean dynamic;
8324         dp_model_t *model;
8325         const float *vertex3f;
8326         const msurface_t *surface;
8327         const msurface_t *surfaces;
8328         const int *surfacelist;
8329         const texture_t *texture;
8330         int numvertices;
8331         int numtriangles;
8332         int numsurfacelist;
8333         int surfacelistindex;
8334         int triangleindex;
8335         int cornerindex;
8336         int index;
8337         int numpoints;
8338         const int *e;
8339         float localorigin[3];
8340         float localnormal[3];
8341         float localmins[3];
8342         float localmaxs[3];
8343         float localsize;
8344         float ilocalsize;
8345         float v[9][3];
8346         float tc[9][2];
8347         float c[9][4];
8348         //float normal[3];
8349         float planes[6][4];
8350         float f;
8351         float points[2][9][3];
8352         float angles[3];
8353         float temp[3];
8354
8355         decalsystem = &ent->decalsystem;
8356         model = ent->model;
8357         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
8358         {
8359                 R_DecalSystem_Reset(&ent->decalsystem);
8360                 return;
8361         }
8362
8363         if (!model->brush.data_nodes && !cl_decals_models.integer)
8364         {
8365                 if (decalsystem->model)
8366                         R_DecalSystem_Reset(decalsystem);
8367                 return;
8368         }
8369
8370         if (decalsystem->model != model)
8371                 R_DecalSystem_Reset(decalsystem);
8372         decalsystem->model = model;
8373
8374         RSurf_ActiveModelEntity(ent, false, false);
8375
8376         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
8377         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
8378         VectorNormalize(localnormal);
8379         localsize = worldsize*rsurface.inversematrixscale;
8380         ilocalsize = 1.0f / localsize;
8381         localmins[0] = localorigin[0] - localsize;
8382         localmins[1] = localorigin[1] - localsize;
8383         localmins[2] = localorigin[2] - localsize;
8384         localmaxs[0] = localorigin[0] + localsize;
8385         localmaxs[1] = localorigin[1] + localsize;
8386         localmaxs[2] = localorigin[2] + localsize;
8387
8388         //VectorCopy(localnormal, planes[4]);
8389         //VectorVectors(planes[4], planes[2], planes[0]);
8390         AnglesFromVectors(angles, localnormal, NULL, false);
8391         AngleVectors(angles, planes[0], planes[2], planes[4]);
8392         VectorNegate(planes[0], planes[1]);
8393         VectorNegate(planes[2], planes[3]);
8394         VectorNegate(planes[4], planes[5]);
8395         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
8396         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
8397         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
8398         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
8399         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
8400         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
8401
8402 #if 1
8403 // works
8404 {
8405         matrix4x4_t forwardprojection;
8406         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
8407         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
8408 }
8409 #else
8410 // broken
8411 {
8412         float projectionvector[4][3];
8413         VectorScale(planes[0], ilocalsize, projectionvector[0]);
8414         VectorScale(planes[2], ilocalsize, projectionvector[1]);
8415         VectorScale(planes[4], ilocalsize, projectionvector[2]);
8416         projectionvector[0][0] = planes[0][0] * ilocalsize;
8417         projectionvector[0][1] = planes[1][0] * ilocalsize;
8418         projectionvector[0][2] = planes[2][0] * ilocalsize;
8419         projectionvector[1][0] = planes[0][1] * ilocalsize;
8420         projectionvector[1][1] = planes[1][1] * ilocalsize;
8421         projectionvector[1][2] = planes[2][1] * ilocalsize;
8422         projectionvector[2][0] = planes[0][2] * ilocalsize;
8423         projectionvector[2][1] = planes[1][2] * ilocalsize;
8424         projectionvector[2][2] = planes[2][2] * ilocalsize;
8425         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
8426         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
8427         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
8428         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
8429 }
8430 #endif
8431
8432         dynamic = model->surfmesh.isanimated;
8433         vertex3f = rsurface.modelvertex3f;
8434         numsurfacelist = model->nummodelsurfaces;
8435         surfacelist = model->sortedmodelsurfaces;
8436         surfaces = model->data_surfaces;
8437         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
8438         {
8439                 surface = surfaces + surfacelist[surfacelistindex];
8440                 // skip transparent surfaces
8441                 texture = surface->texture;
8442                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8443                         continue;
8444                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
8445                         continue;
8446                 if (texture->currentalpha < 1)
8447                         continue;
8448                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
8449                         continue;
8450                 numvertices = surface->num_vertices;
8451                 numtriangles = surface->num_triangles;
8452                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
8453                 {
8454                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
8455                         {
8456                                 index = 3*e[cornerindex];
8457                                 VectorCopy(vertex3f + index, v[cornerindex]);
8458                         }
8459                         // cull backfaces
8460                         //TriangleNormal(v[0], v[1], v[2], normal);
8461                         //if (DotProduct(normal, localnormal) < 0.0f)
8462                         //      continue;
8463                         // clip by each of the box planes formed from the projection matrix
8464                         // if anything survives, we emit the decal
8465                         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]);
8466                         if (numpoints < 3)
8467                                 continue;
8468                         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]);
8469                         if (numpoints < 3)
8470                                 continue;
8471                         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]);
8472                         if (numpoints < 3)
8473                                 continue;
8474                         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]);
8475                         if (numpoints < 3)
8476                                 continue;
8477                         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]);
8478                         if (numpoints < 3)
8479                                 continue;
8480                         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]);
8481                         if (numpoints < 3)
8482                                 continue;
8483                         // some part of the triangle survived, so we have to accept it...
8484                         if (dynamic)
8485                         {
8486                                 // dynamic always uses the original triangle
8487                                 numpoints = 3;
8488                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
8489                                 {
8490                                         index = 3*e[cornerindex];
8491                                         VectorCopy(vertex3f + index, v[cornerindex]);
8492                                 }
8493                         }
8494                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
8495                         {
8496                                 // convert vertex positions to texcoords
8497                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
8498                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
8499                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
8500                                 // calculate distance fade from the projection origin
8501                                 f = a * (1.0f-fabs(temp[0]));
8502                                 f = max(0.0f, f);
8503                                 c[cornerindex][0] = r * f;
8504                                 c[cornerindex][1] = g * f;
8505                                 c[cornerindex][2] = b * f;
8506                                 c[cornerindex][3] = 1.0f;
8507                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
8508                         }
8509                         if (dynamic)
8510                                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex);
8511                         else
8512                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
8513                                         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);
8514                 }
8515         }
8516 }
8517
8518 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)
8519 {
8520         int renderentityindex;
8521         float worldmins[3];
8522         float worldmaxs[3];
8523         entity_render_t *ent;
8524
8525         worldmins[0] = worldorigin[0] - worldsize;
8526         worldmins[1] = worldorigin[1] - worldsize;
8527         worldmins[2] = worldorigin[2] - worldsize;
8528         worldmaxs[0] = worldorigin[0] + worldsize;
8529         worldmaxs[1] = worldorigin[1] + worldsize;
8530         worldmaxs[2] = worldorigin[2] + worldsize;
8531
8532         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8533
8534         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
8535         {
8536                 ent = r_refdef.scene.entities[renderentityindex];
8537                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
8538                         continue;
8539
8540                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize);
8541         }
8542 }
8543
8544 extern skinframe_t *decalskinframe;
8545 static void R_DrawModelDecals_Entity(entity_render_t *ent)
8546 {
8547         int i;
8548         decalsystem_t *decalsystem = &ent->decalsystem;
8549         int numdecals;
8550         tridecal_t *decal;
8551         float frametime;
8552         float fadedelay;
8553         float faderate;
8554         float alpha;
8555         float *v3f;
8556         float *c4f;
8557         const int *e;
8558
8559         if (!decalsystem->numdecals)
8560                 return;
8561
8562         if (r_showsurfaces.integer)
8563                 return;
8564
8565         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
8566         {
8567                 R_DecalSystem_Reset(decalsystem);
8568                 return;
8569         }
8570
8571         // if the model is static it doesn't matter what value we give for
8572         // wantnormals and wanttangents, so this logic uses only rules applicable
8573         // to a model, knowing that they are meaningless otherwise
8574         if (ent == r_refdef.scene.worldentity)
8575                 RSurf_ActiveWorldEntity();
8576         else
8577                 RSurf_ActiveModelEntity(ent, false, false);
8578
8579         if (decalsystem->lastupdatetime)
8580                 frametime = cl.time - decalsystem->lastupdatetime;
8581         else
8582                 frametime = 0;
8583         decalsystem->lastupdatetime = cl.time;
8584         decal = decalsystem->decals;
8585         numdecals = decalsystem->numdecals;
8586
8587         fadedelay = cl_decals_time.value;
8588         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
8589
8590         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
8591         {
8592                 if (!decal->colors[0][3])
8593                         continue;
8594
8595                 decal->lived += frametime;
8596                 if (decal->lived >= fadedelay)
8597                 {
8598                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
8599                         if (alpha <= 0)
8600                         {
8601                                 // kill the decal by zeroing vertex data
8602                                 memset(decalsystem->vertex3f + 9*i, 0, sizeof(float[3][3]));
8603                                 memset(decalsystem->texcoord2f + 6*i, 0, sizeof(float[3][2]));
8604                                 memset(decalsystem->color4f + 12*i, 0, sizeof(float[3][4]));
8605                                 memset(decal, 0, sizeof(*decal));
8606                                 if (decalsystem->freedecal > i)
8607                                         decalsystem->freedecal = i;
8608                                 continue;
8609                         }
8610
8611                         // update color values for fading decals
8612                         alpha *= (1.0f/255.0f);
8613                         c4f = decalsystem->color4f + 12*i;
8614                         c4f[ 0] = decal->colors[0][0] * alpha;
8615                         c4f[ 1] = decal->colors[0][1] * alpha;
8616                         c4f[ 2] = decal->colors[0][2] * alpha;
8617                         c4f[ 3] = 1;
8618                         c4f[ 4] = decal->colors[1][0] * alpha;
8619                         c4f[ 5] = decal->colors[1][1] * alpha;
8620                         c4f[ 6] = decal->colors[1][2] * alpha;
8621                         c4f[ 7] = 1;
8622                         c4f[ 8] = decal->colors[2][0] * alpha;
8623                         c4f[ 9] = decal->colors[2][1] * alpha;
8624                         c4f[10] = decal->colors[2][2] * alpha;
8625                         c4f[11] = 1;
8626                 }
8627
8628                 // update vertex positions for animated models
8629                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
8630                 {
8631                         e = rsurface.modelelement3i + 3*decal->triangleindex;
8632                         v3f = decalsystem->vertex3f + 9*i;
8633                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
8634                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
8635                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
8636                 }
8637         }
8638
8639         // reduce numdecals if possible
8640         while (numdecals > 0 && !decalsystem->decals[numdecals - 1].colors[0][3])
8641                 numdecals--;
8642         decalsystem->numdecals = numdecals;
8643
8644         if (numdecals > 0)
8645         {
8646                 r_refdef.stats.decals += numdecals;
8647                 // now render the decals all at once
8648                 // (this assumes they all use one particle font texture!)
8649                 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);
8650                 R_Mesh_ResetTextureState();
8651                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
8652                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
8653                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
8654                 R_SetupGenericShader(true);
8655                 GL_DepthMask(false);
8656                 GL_DepthRange(0, 1);
8657                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
8658                 GL_DepthTest(true);
8659                 GL_CullFace(GL_NONE);
8660                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
8661                 R_Mesh_TexBind(0, R_GetTexture(decalskinframe->base));
8662                 //R_Mesh_TexBind(0, R_GetTexture(r_texture_white));
8663                 GL_LockArrays(0, numdecals * 3);
8664                 R_Mesh_Draw(0, numdecals * 3, 0, numdecals, decalsystem->element3i, decalsystem->element3s, 0, 0);
8665                 GL_LockArrays(0, 0);
8666         }
8667
8668         if (numdecals <= 0)
8669         {
8670                 // if there are no decals left, reset decalsystem
8671                 R_DecalSystem_Reset(decalsystem);
8672         }
8673 }
8674
8675 void R_DrawDebugModel(void)
8676 {
8677         entity_render_t *ent = rsurface.entity;
8678         int i, j, k, l, flagsmask;
8679         const int *elements;
8680         q3mbrush_t *brush;
8681         const msurface_t *surface;
8682         dp_model_t *model = ent->model;
8683         vec3_t v;
8684
8685         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
8686
8687         R_Mesh_ColorPointer(NULL, 0, 0);
8688         R_Mesh_ResetTextureState();
8689         R_SetupGenericShader(false);
8690         GL_DepthRange(0, 1);
8691         GL_DepthTest(!r_showdisabledepthtest.integer);
8692         GL_DepthMask(false);
8693         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8694
8695         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
8696         {
8697                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
8698                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
8699                 {
8700                         if (brush->colbrushf && brush->colbrushf->numtriangles)
8701                         {
8702                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
8703                                 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);
8704                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
8705                         }
8706                 }
8707                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
8708                 {
8709                         if (surface->num_collisiontriangles)
8710                         {
8711                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
8712                                 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);
8713                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
8714                         }
8715                 }
8716         }
8717
8718         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8719
8720         if (r_showtris.integer || r_shownormals.integer)
8721         {
8722                 if (r_showdisabledepthtest.integer)
8723                 {
8724                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8725                         GL_DepthMask(false);
8726                 }
8727                 else
8728                 {
8729                         GL_BlendFunc(GL_ONE, GL_ZERO);
8730                         GL_DepthMask(true);
8731                 }
8732                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
8733                 {
8734                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
8735                                 continue;
8736                         rsurface.texture = R_GetCurrentTexture(surface->texture);
8737                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
8738                         {
8739                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
8740                                 if (r_showtris.value > 0)
8741                                 {
8742                                         if (!rsurface.texture->currentlayers->depthmask)
8743                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
8744                                         else if (ent == r_refdef.scene.worldentity)
8745                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
8746                                         else
8747                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
8748                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
8749                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
8750                                         R_Mesh_ColorPointer(NULL, 0, 0);
8751                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
8752                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
8753                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
8754                                         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);
8755                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
8756                                         CHECKGLERROR
8757                                 }
8758                                 if (r_shownormals.value < 0)
8759                                 {
8760                                         qglBegin(GL_LINES);
8761                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8762                                         {
8763                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
8764                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8765                                                 qglVertex3f(v[0], v[1], v[2]);
8766                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
8767                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8768                                                 qglVertex3f(v[0], v[1], v[2]);
8769                                         }
8770                                         qglEnd();
8771                                         CHECKGLERROR
8772                                 }
8773                                 if (r_shownormals.value > 0)
8774                                 {
8775                                         qglBegin(GL_LINES);
8776                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8777                                         {
8778                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
8779                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
8780                                                 qglVertex3f(v[0], v[1], v[2]);
8781                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
8782                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8783                                                 qglVertex3f(v[0], v[1], v[2]);
8784                                         }
8785                                         qglEnd();
8786                                         CHECKGLERROR
8787                                         qglBegin(GL_LINES);
8788                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8789                                         {
8790                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
8791                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
8792                                                 qglVertex3f(v[0], v[1], v[2]);
8793                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
8794                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8795                                                 qglVertex3f(v[0], v[1], v[2]);
8796                                         }
8797                                         qglEnd();
8798                                         CHECKGLERROR
8799                                         qglBegin(GL_LINES);
8800                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
8801                                         {
8802                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
8803                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
8804                                                 qglVertex3f(v[0], v[1], v[2]);
8805                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
8806                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
8807                                                 qglVertex3f(v[0], v[1], v[2]);
8808                                         }
8809                                         qglEnd();
8810                                         CHECKGLERROR
8811                                 }
8812                         }
8813                 }
8814                 rsurface.texture = NULL;
8815         }
8816 }
8817
8818 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
8819 int r_maxsurfacelist = 0;
8820 const msurface_t **r_surfacelist = NULL;
8821 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8822 {
8823         int i, j, endj, f, flagsmask;
8824         texture_t *t;
8825         dp_model_t *model = r_refdef.scene.worldmodel;
8826         msurface_t *surfaces;
8827         unsigned char *update;
8828         int numsurfacelist = 0;
8829         if (model == NULL)
8830                 return;
8831
8832         if (r_maxsurfacelist < model->num_surfaces)
8833         {
8834                 r_maxsurfacelist = model->num_surfaces;
8835                 if (r_surfacelist)
8836                         Mem_Free(r_surfacelist);
8837                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8838         }
8839
8840         RSurf_ActiveWorldEntity();
8841
8842         surfaces = model->data_surfaces;
8843         update = model->brushq1.lightmapupdateflags;
8844
8845         // update light styles on this submodel
8846         if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8847         {
8848                 model_brush_lightstyleinfo_t *style;
8849                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8850                 {
8851                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
8852                         {
8853                                 int *list = style->surfacelist;
8854                                 style->value = r_refdef.scene.lightstylevalue[style->style];
8855                                 for (j = 0;j < style->numsurfaces;j++)
8856                                         update[list[j]] = true;
8857                         }
8858                 }
8859         }
8860
8861         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8862
8863         if (debug)
8864         {
8865                 R_DrawDebugModel();
8866                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8867                 return;
8868         }
8869
8870         f = 0;
8871         t = NULL;
8872         rsurface.uselightmaptexture = false;
8873         rsurface.texture = NULL;
8874         rsurface.rtlight = NULL;
8875         numsurfacelist = 0;
8876         // add visible surfaces to draw list
8877         for (i = 0;i < model->nummodelsurfaces;i++)
8878         {
8879                 j = model->sortedmodelsurfaces[i];
8880                 if (r_refdef.viewcache.world_surfacevisible[j])
8881                         r_surfacelist[numsurfacelist++] = surfaces + j;
8882         }
8883         // update lightmaps if needed
8884         if (update)
8885                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8886                         if (r_refdef.viewcache.world_surfacevisible[j])
8887                                 if (update[j])
8888                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
8889         // don't do anything if there were no surfaces
8890         if (!numsurfacelist)
8891         {
8892                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8893                 return;
8894         }
8895         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8896         GL_AlphaTest(false);
8897
8898         // add to stats if desired
8899         if (r_speeds.integer && !skysurfaces && !depthonly)
8900         {
8901                 r_refdef.stats.world_surfaces += numsurfacelist;
8902                 for (j = 0;j < numsurfacelist;j++)
8903                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
8904         }
8905
8906         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8907 }
8908
8909 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug)
8910 {
8911         int i, j, endj, f, flagsmask;
8912         texture_t *t;
8913         dp_model_t *model = ent->model;
8914         msurface_t *surfaces;
8915         unsigned char *update;
8916         int numsurfacelist = 0;
8917         if (model == NULL)
8918                 return;
8919
8920         if (r_maxsurfacelist < model->num_surfaces)
8921         {
8922                 r_maxsurfacelist = model->num_surfaces;
8923                 if (r_surfacelist)
8924                         Mem_Free(r_surfacelist);
8925                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
8926         }
8927
8928         // if the model is static it doesn't matter what value we give for
8929         // wantnormals and wanttangents, so this logic uses only rules applicable
8930         // to a model, knowing that they are meaningless otherwise
8931         if (ent == r_refdef.scene.worldentity)
8932                 RSurf_ActiveWorldEntity();
8933         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
8934                 RSurf_ActiveModelEntity(ent, false, false);
8935         else
8936                 RSurf_ActiveModelEntity(ent, true, r_glsl.integer && gl_support_fragment_shader && !depthonly);
8937
8938         surfaces = model->data_surfaces;
8939         update = model->brushq1.lightmapupdateflags;
8940
8941         // update light styles
8942         if (!skysurfaces && !depthonly && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
8943         {
8944                 model_brush_lightstyleinfo_t *style;
8945                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
8946                 {
8947                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
8948                         {
8949                                 int *list = style->surfacelist;
8950                                 style->value = r_refdef.scene.lightstylevalue[style->style];
8951                                 for (j = 0;j < style->numsurfaces;j++)
8952                                         update[list[j]] = true;
8953                         }
8954                 }
8955         }
8956
8957         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
8958
8959         if (debug)
8960         {
8961                 R_DrawDebugModel();
8962                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8963                 return;
8964         }
8965
8966         f = 0;
8967         t = NULL;
8968         rsurface.uselightmaptexture = false;
8969         rsurface.texture = NULL;
8970         rsurface.rtlight = NULL;
8971         numsurfacelist = 0;
8972         // add visible surfaces to draw list
8973         for (i = 0;i < model->nummodelsurfaces;i++)
8974                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
8975         // don't do anything if there were no surfaces
8976         if (!numsurfacelist)
8977         {
8978                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8979                 return;
8980         }
8981         // update lightmaps if needed
8982         if (update)
8983                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
8984                         if (update[j])
8985                                 R_BuildLightMap(ent, surfaces + j);
8986         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly);
8987         GL_AlphaTest(false);
8988
8989         // add to stats if desired
8990         if (r_speeds.integer && !skysurfaces && !depthonly)
8991         {
8992                 r_refdef.stats.entities_surfaces += numsurfacelist;
8993                 for (j = 0;j < numsurfacelist;j++)
8994                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
8995         }
8996
8997         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8998 }
8999
9000 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth)
9001 {
9002         static texture_t texture;
9003         static msurface_t surface;
9004         const msurface_t *surfacelist = &surface;
9005
9006         // fake enough texture and surface state to render this geometry
9007
9008         texture.update_lastrenderframe = -1; // regenerate this texture
9009         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
9010         texture.currentskinframe = skinframe;
9011         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
9012         texture.specularscalemod = 1;
9013         texture.specularpowermod = 1;
9014
9015         surface.texture = &texture;
9016         surface.num_triangles = numtriangles;
9017         surface.num_firsttriangle = firsttriangle;
9018         surface.num_vertices = numvertices;
9019         surface.num_firstvertex = firstvertex;
9020
9021         // now render it
9022         rsurface.texture = R_GetCurrentTexture(surface.texture);
9023         rsurface.uselightmaptexture = false;
9024         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth);
9025 }