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