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