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