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