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