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