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