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