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