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