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