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