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