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