]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
make the utf8 casting strict aliasing-safe
[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 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_frame = 0; ///< used only by R_GetCurrentTexture
33
34 qboolean r_loadnormalmap;
35 qboolean r_loadgloss;
36 qboolean r_loadfog;
37
38 //
39 // screen size info
40 //
41 r_refdef_t r_refdef;
42
43 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
44 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
45 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
46 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
47 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)"};
48 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
49 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
50 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
51
52 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
53 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
54 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
55 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
56 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
57
58 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"};
59 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
60 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
61 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
62 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
63 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
64 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)"};
65 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
66 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
67 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"};
68 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"};
69 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
70 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"};
71 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"};
72 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"};
73 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
74 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
75 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
76 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
77 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
78 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
79 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
80 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
81 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
82 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
83 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
84 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
85 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
86 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."};
87 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
88 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
89 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
90 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."};
91 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
92 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
93 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"};
94 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
95 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
96 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
97 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
98 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
99 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
100
101 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
102 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
103 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
104 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
105 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
106 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
107 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
108 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
109
110 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
111 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
112 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
113
114 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)"};
115 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
116 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
117 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
118 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
119 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)"};
120 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)"};
121 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)"};
122 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)"};
123
124 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)"};
125 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
126 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"};
127 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
128 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
129
130 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "1", "enables animation smoothing on sprites"};
131 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
132 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
133 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
134
135 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
136 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
137 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
138 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
139 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
140 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
141 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
142
143 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
144 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
145 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
146 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)"};
147
148 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"};
149
150 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"};
151
152 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
153
154 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
155 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
156 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"};
157 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
158 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
159 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
160 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
161
162 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
163
164 extern cvar_t v_glslgamma;
165
166 extern qboolean v_flipped_state;
167
168 static struct r_bloomstate_s
169 {
170         qboolean enabled;
171         qboolean hdr;
172
173         int bloomwidth, bloomheight;
174
175         int screentexturewidth, screentextureheight;
176         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
177
178         int bloomtexturewidth, bloomtextureheight;
179         rtexture_t *texture_bloom;
180
181         // arrays for rendering the screen passes
182         float screentexcoord2f[8];
183         float bloomtexcoord2f[8];
184         float offsettexcoord2f[8];
185
186         r_viewport_t viewport;
187 }
188 r_bloomstate;
189
190 r_waterstate_t r_waterstate;
191
192 /// shadow volume bsp struct with automatically growing nodes buffer
193 svbsp_t r_svbsp;
194
195 rtexture_t *r_texture_blanknormalmap;
196 rtexture_t *r_texture_white;
197 rtexture_t *r_texture_grey128;
198 rtexture_t *r_texture_black;
199 rtexture_t *r_texture_notexture;
200 rtexture_t *r_texture_whitecube;
201 rtexture_t *r_texture_normalizationcube;
202 rtexture_t *r_texture_fogattenuation;
203 rtexture_t *r_texture_gammaramps;
204 unsigned int r_texture_gammaramps_serial;
205 //rtexture_t *r_texture_fogintensity;
206
207 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
208 unsigned int r_numqueries;
209 unsigned int r_maxqueries;
210
211 typedef struct r_qwskincache_s
212 {
213         char name[MAX_QPATH];
214         skinframe_t *skinframe;
215 }
216 r_qwskincache_t;
217
218 static r_qwskincache_t *r_qwskincache;
219 static int r_qwskincache_size;
220
221 /// vertex coordinates for a quad that covers the screen exactly
222 const float r_screenvertex3f[12] =
223 {
224         0, 0, 0,
225         1, 0, 0,
226         1, 1, 0,
227         0, 1, 0
228 };
229
230 extern void R_DrawModelShadows(void);
231
232 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
233 {
234         int i;
235         for (i = 0;i < verts;i++)
236         {
237                 out[0] = in[0] * r;
238                 out[1] = in[1] * g;
239                 out[2] = in[2] * b;
240                 out[3] = in[3];
241                 in += 4;
242                 out += 4;
243         }
244 }
245
246 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
247 {
248         int i;
249         for (i = 0;i < verts;i++)
250         {
251                 out[0] = r;
252                 out[1] = g;
253                 out[2] = b;
254                 out[3] = a;
255                 out += 4;
256         }
257 }
258
259 // FIXME: move this to client?
260 void FOG_clear(void)
261 {
262         if (gamemode == GAME_NEHAHRA)
263         {
264                 Cvar_Set("gl_fogenable", "0");
265                 Cvar_Set("gl_fogdensity", "0.2");
266                 Cvar_Set("gl_fogred", "0.3");
267                 Cvar_Set("gl_foggreen", "0.3");
268                 Cvar_Set("gl_fogblue", "0.3");
269         }
270         r_refdef.fog_density = 0;
271         r_refdef.fog_red = 0;
272         r_refdef.fog_green = 0;
273         r_refdef.fog_blue = 0;
274         r_refdef.fog_alpha = 1;
275         r_refdef.fog_start = 0;
276         r_refdef.fog_end = 16384;
277         r_refdef.fog_height = 1<<30;
278         r_refdef.fog_fadedepth = 128;
279 }
280
281 static void R_BuildBlankTextures(void)
282 {
283         unsigned char data[4];
284         data[2] = 128; // normal X
285         data[1] = 128; // normal Y
286         data[0] = 255; // normal Z
287         data[3] = 128; // height
288         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
289         data[0] = 255;
290         data[1] = 255;
291         data[2] = 255;
292         data[3] = 255;
293         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
294         data[0] = 128;
295         data[1] = 128;
296         data[2] = 128;
297         data[3] = 255;
298         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
299         data[0] = 0;
300         data[1] = 0;
301         data[2] = 0;
302         data[3] = 255;
303         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
304 }
305
306 static void R_BuildNoTexture(void)
307 {
308         int x, y;
309         unsigned char pix[16][16][4];
310         // this makes a light grey/dark grey checkerboard texture
311         for (y = 0;y < 16;y++)
312         {
313                 for (x = 0;x < 16;x++)
314                 {
315                         if ((y < 8) ^ (x < 8))
316                         {
317                                 pix[y][x][0] = 128;
318                                 pix[y][x][1] = 128;
319                                 pix[y][x][2] = 128;
320                                 pix[y][x][3] = 255;
321                         }
322                         else
323                         {
324                                 pix[y][x][0] = 64;
325                                 pix[y][x][1] = 64;
326                                 pix[y][x][2] = 64;
327                                 pix[y][x][3] = 255;
328                         }
329                 }
330         }
331         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
332 }
333
334 static void R_BuildWhiteCube(void)
335 {
336         unsigned char data[6*1*1*4];
337         memset(data, 255, sizeof(data));
338         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
339 }
340
341 static void R_BuildNormalizationCube(void)
342 {
343         int x, y, side;
344         vec3_t v;
345         vec_t s, t, intensity;
346 #define NORMSIZE 64
347         unsigned char *data;
348         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
349         for (side = 0;side < 6;side++)
350         {
351                 for (y = 0;y < NORMSIZE;y++)
352                 {
353                         for (x = 0;x < NORMSIZE;x++)
354                         {
355                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
356                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
357                                 switch(side)
358                                 {
359                                 default:
360                                 case 0:
361                                         v[0] = 1;
362                                         v[1] = -t;
363                                         v[2] = -s;
364                                         break;
365                                 case 1:
366                                         v[0] = -1;
367                                         v[1] = -t;
368                                         v[2] = s;
369                                         break;
370                                 case 2:
371                                         v[0] = s;
372                                         v[1] = 1;
373                                         v[2] = t;
374                                         break;
375                                 case 3:
376                                         v[0] = s;
377                                         v[1] = -1;
378                                         v[2] = -t;
379                                         break;
380                                 case 4:
381                                         v[0] = s;
382                                         v[1] = -t;
383                                         v[2] = 1;
384                                         break;
385                                 case 5:
386                                         v[0] = -s;
387                                         v[1] = -t;
388                                         v[2] = -1;
389                                         break;
390                                 }
391                                 intensity = 127.0f / sqrt(DotProduct(v, v));
392                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
393                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
394                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
395                                 data[((side*64+y)*64+x)*4+3] = 255;
396                         }
397                 }
398         }
399         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
400         Mem_Free(data);
401 }
402
403 static void R_BuildFogTexture(void)
404 {
405         int x, b;
406 #define FOGWIDTH 256
407         unsigned char data1[FOGWIDTH][4];
408         //unsigned char data2[FOGWIDTH][4];
409         double d, r, alpha;
410
411         r_refdef.fogmasktable_start = r_refdef.fog_start;
412         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
413         r_refdef.fogmasktable_range = r_refdef.fogrange;
414         r_refdef.fogmasktable_density = r_refdef.fog_density;
415
416         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
417         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
418         {
419                 d = (x * r - r_refdef.fogmasktable_start);
420                 if(developer_extra.integer)
421                         Con_DPrintf("%f ", d);
422                 d = max(0, d);
423                 if (r_fog_exp2.integer)
424                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
425                 else
426                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
427                 if(developer_extra.integer)
428                         Con_DPrintf(" : %f ", alpha);
429                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
430                 if(developer_extra.integer)
431                         Con_DPrintf(" = %f\n", alpha);
432                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
433         }
434
435         for (x = 0;x < FOGWIDTH;x++)
436         {
437                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
438                 data1[x][0] = b;
439                 data1[x][1] = b;
440                 data1[x][2] = b;
441                 data1[x][3] = 255;
442                 //data2[x][0] = 255 - b;
443                 //data2[x][1] = 255 - b;
444                 //data2[x][2] = 255 - b;
445                 //data2[x][3] = 255;
446         }
447         if (r_texture_fogattenuation)
448         {
449                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
450                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
451         }
452         else
453         {
454                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
455                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
456         }
457 }
458
459 //=======================================================================================================================================================
460
461 static const char *builtinshaderstring =
462 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
463 "// written by Forest 'LordHavoc' Hale\n"
464 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
465 "\n"
466 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
467 "# define USEFOG\n"
468 "#endif\n"
469 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
470 "#define USELIGHTMAP\n"
471 "#endif\n"
472 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
473 "#define USEEYEVECTOR\n"
474 "#endif\n"
475 "\n"
476 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
477 "# extension GL_ARB_texture_rectangle : enable\n"
478 "#endif\n"
479 "\n"
480 "#ifdef USESHADOWMAP2D\n"
481 "# ifdef GL_EXT_gpu_shader4\n"
482 "#   extension GL_EXT_gpu_shader4 : enable\n"
483 "# endif\n"
484 "# ifdef GL_ARB_texture_gather\n"
485 "#   extension GL_ARB_texture_gather : enable\n"
486 "# else\n"
487 "#   ifdef GL_AMD_texture_texture4\n"
488 "#     extension GL_AMD_texture_texture4 : enable\n"
489 "#   endif\n"
490 "# endif\n"
491 "#endif\n"
492 "\n"
493 "#ifdef USESHADOWMAPCUBE\n"
494 "# extension GL_EXT_gpu_shader4 : enable\n"
495 "#endif\n"
496 "\n"
497 "//#ifdef USESHADOWSAMPLER\n"
498 "//# extension GL_ARB_shadow : enable\n"
499 "//#endif\n"
500 "\n"
501 "//#ifdef __GLSL_CG_DATA_TYPES\n"
502 "//# define myhalf half\n"
503 "//# define myhalf2 half2\n"
504 "//# define myhalf3 half3\n"
505 "//# define myhalf4 half4\n"
506 "//#else\n"
507 "# define myhalf float\n"
508 "# define myhalf2 vec2\n"
509 "# define myhalf3 vec3\n"
510 "# define myhalf4 vec4\n"
511 "//#endif\n"
512 "\n"
513 "#ifdef VERTEX_SHADER\n"
514 "uniform mat4 ModelViewProjectionMatrix;\n"
515 "#endif\n"
516 "\n"
517 "#ifdef MODE_DEPTH_OR_SHADOW\n"
518 "#ifdef VERTEX_SHADER\n"
519 "void main(void)\n"
520 "{\n"
521 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
522 "}\n"
523 "#endif\n"
524 "#else // !MODE_DEPTH_ORSHADOW\n"
525 "\n"
526 "\n"
527 "\n"
528 "\n"
529 "#ifdef MODE_SHOWDEPTH\n"
530 "#ifdef VERTEX_SHADER\n"
531 "void main(void)\n"
532 "{\n"
533 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
534 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
535 "}\n"
536 "#endif\n"
537 "\n"
538 "#ifdef FRAGMENT_SHADER\n"
539 "void main(void)\n"
540 "{\n"
541 "       gl_FragColor = gl_Color;\n"
542 "}\n"
543 "#endif\n"
544 "#else // !MODE_SHOWDEPTH\n"
545 "\n"
546 "\n"
547 "\n"
548 "\n"
549 "#ifdef MODE_POSTPROCESS\n"
550 "varying vec2 TexCoord1;\n"
551 "varying vec2 TexCoord2;\n"
552 "\n"
553 "#ifdef VERTEX_SHADER\n"
554 "void main(void)\n"
555 "{\n"
556 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
557 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
558 "#ifdef USEBLOOM\n"
559 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
560 "#endif\n"
561 "}\n"
562 "#endif\n"
563 "\n"
564 "#ifdef FRAGMENT_SHADER\n"
565 "uniform sampler2D Texture_First;\n"
566 "#ifdef USEBLOOM\n"
567 "uniform sampler2D Texture_Second;\n"
568 "#endif\n"
569 "#ifdef USEGAMMARAMPS\n"
570 "uniform sampler2D Texture_GammaRamps;\n"
571 "#endif\n"
572 "#ifdef USESATURATION\n"
573 "uniform float Saturation;\n"
574 "#endif\n"
575 "#ifdef USEVIEWTINT\n"
576 "uniform vec4 ViewTintColor;\n"
577 "#endif\n"
578 "//uncomment these if you want to use them:\n"
579 "uniform vec4 UserVec1;\n"
580 "// uniform vec4 UserVec2;\n"
581 "// uniform vec4 UserVec3;\n"
582 "// uniform vec4 UserVec4;\n"
583 "// uniform float ClientTime;\n"
584 "uniform vec2 PixelSize;\n"
585 "void main(void)\n"
586 "{\n"
587 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
588 "#ifdef USEBLOOM\n"
589 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
590 "#endif\n"
591 "#ifdef USEVIEWTINT\n"
592 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
593 "#endif\n"
594 "\n"
595 "#ifdef USEPOSTPROCESSING\n"
596 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
597 "// 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"
598 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
599 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
600 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
601 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
602 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
603 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
604 "#endif\n"
605 "\n"
606 "#ifdef USESATURATION\n"
607 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
608 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
609 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
610 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
611 "#endif\n"
612 "\n"
613 "#ifdef USEGAMMARAMPS\n"
614 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
615 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
616 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
617 "#endif\n"
618 "}\n"
619 "#endif\n"
620 "#else // !MODE_POSTPROCESS\n"
621 "\n"
622 "\n"
623 "\n"
624 "\n"
625 "#ifdef MODE_GENERIC\n"
626 "#ifdef USEDIFFUSE\n"
627 "varying vec2 TexCoord1;\n"
628 "#endif\n"
629 "#ifdef USESPECULAR\n"
630 "varying vec2 TexCoord2;\n"
631 "#endif\n"
632 "#ifdef VERTEX_SHADER\n"
633 "void main(void)\n"
634 "{\n"
635 "       gl_FrontColor = gl_Color;\n"
636 "#ifdef USEDIFFUSE\n"
637 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
638 "#endif\n"
639 "#ifdef USESPECULAR\n"
640 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
641 "#endif\n"
642 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
643 "}\n"
644 "#endif\n"
645 "\n"
646 "#ifdef FRAGMENT_SHADER\n"
647 "#ifdef USEDIFFUSE\n"
648 "uniform sampler2D Texture_First;\n"
649 "#endif\n"
650 "#ifdef USESPECULAR\n"
651 "uniform sampler2D Texture_Second;\n"
652 "#endif\n"
653 "\n"
654 "void main(void)\n"
655 "{\n"
656 "       gl_FragColor = gl_Color;\n"
657 "#ifdef USEDIFFUSE\n"
658 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
659 "#endif\n"
660 "\n"
661 "#ifdef USESPECULAR\n"
662 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
663 "# ifdef USECOLORMAPPING\n"
664 "       gl_FragColor *= tex2;\n"
665 "# endif\n"
666 "# ifdef USEGLOW\n"
667 "       gl_FragColor += tex2;\n"
668 "# endif\n"
669 "# ifdef USEVERTEXTEXTUREBLEND\n"
670 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
671 "# endif\n"
672 "#endif\n"
673 "}\n"
674 "#endif\n"
675 "#else // !MODE_GENERIC\n"
676 "\n"
677 "\n"
678 "\n"
679 "\n"
680 "#ifdef MODE_BLOOMBLUR\n"
681 "varying TexCoord;\n"
682 "#ifdef VERTEX_SHADER\n"
683 "void main(void)\n"
684 "{\n"
685 "       gl_FrontColor = gl_Color;\n"
686 "       TexCoord = gl_MultiTexCoord0.xy;\n"
687 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
688 "}\n"
689 "#endif\n"
690 "\n"
691 "#ifdef FRAGMENT_SHADER\n"
692 "uniform sampler2D Texture_First;\n"
693 "uniform vec4 BloomBlur_Parameters;\n"
694 "\n"
695 "void main(void)\n"
696 "{\n"
697 "       int i;\n"
698 "       vec2 tc = TexCoord;\n"
699 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
700 "       tc += BloomBlur_Parameters.xy;\n"
701 "       for (i = 1;i < SAMPLES;i++)\n"
702 "       {\n"
703 "               color += texture2D(Texture_First, tc).rgb;\n"
704 "               tc += BloomBlur_Parameters.xy;\n"
705 "       }\n"
706 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
707 "}\n"
708 "#endif\n"
709 "#else // !MODE_BLOOMBLUR\n"
710 "#ifdef MODE_REFRACTION\n"
711 "varying vec2 TexCoord;\n"
712 "varying vec4 ModelViewProjectionPosition;\n"
713 "uniform mat4 TexMatrix;\n"
714 "#ifdef VERTEX_SHADER\n"
715 "\n"
716 "void main(void)\n"
717 "{\n"
718 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
719 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
720 "       ModelViewProjectionPosition = gl_Position;\n"
721 "}\n"
722 "#endif\n"
723 "\n"
724 "#ifdef FRAGMENT_SHADER\n"
725 "uniform sampler2D Texture_Normal;\n"
726 "uniform sampler2D Texture_Refraction;\n"
727 "uniform sampler2D Texture_Reflection;\n"
728 "\n"
729 "uniform vec4 DistortScaleRefractReflect;\n"
730 "uniform vec4 ScreenScaleRefractReflect;\n"
731 "uniform vec4 ScreenCenterRefractReflect;\n"
732 "uniform vec4 RefractColor;\n"
733 "uniform vec4 ReflectColor;\n"
734 "uniform float ReflectFactor;\n"
735 "uniform float ReflectOffset;\n"
736 "\n"
737 "void main(void)\n"
738 "{\n"
739 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
740 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
741 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
742 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
743 "       // FIXME temporary hack to detect the case that the reflection\n"
744 "       // gets blackened at edges due to leaving the area that contains actual\n"
745 "       // content.\n"
746 "       // Remove this 'ack once we have a better way to stop this thing from\n"
747 "       // 'appening.\n"
748 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
749 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
750 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
751 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
752 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
753 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
754 "}\n"
755 "#endif\n"
756 "#else // !MODE_REFRACTION\n"
757 "\n"
758 "\n"
759 "\n"
760 "\n"
761 "#ifdef MODE_WATER\n"
762 "varying vec2 TexCoord;\n"
763 "varying vec3 EyeVector;\n"
764 "varying vec4 ModelViewProjectionPosition;\n"
765 "#ifdef VERTEX_SHADER\n"
766 "uniform vec3 EyePosition;\n"
767 "uniform mat4 TexMatrix;\n"
768 "\n"
769 "void main(void)\n"
770 "{\n"
771 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
772 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
773 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
774 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
775 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
776 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
777 "       ModelViewProjectionPosition = gl_Position;\n"
778 "}\n"
779 "#endif\n"
780 "\n"
781 "#ifdef FRAGMENT_SHADER\n"
782 "uniform sampler2D Texture_Normal;\n"
783 "uniform sampler2D Texture_Refraction;\n"
784 "uniform sampler2D Texture_Reflection;\n"
785 "\n"
786 "uniform vec4 DistortScaleRefractReflect;\n"
787 "uniform vec4 ScreenScaleRefractReflect;\n"
788 "uniform vec4 ScreenCenterRefractReflect;\n"
789 "uniform vec4 RefractColor;\n"
790 "uniform vec4 ReflectColor;\n"
791 "uniform float ReflectFactor;\n"
792 "uniform float ReflectOffset;\n"
793 "\n"
794 "void main(void)\n"
795 "{\n"
796 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
797 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
798 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
799 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
800 "       // FIXME temporary hack to detect the case that the reflection\n"
801 "       // gets blackened at edges due to leaving the area that contains actual\n"
802 "       // content.\n"
803 "       // Remove this 'ack once we have a better way to stop this thing from\n"
804 "       // 'appening.\n"
805 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
806 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
807 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
808 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
809 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
810 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
811 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
812 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
813 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
814 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
815 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
816 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
817 "}\n"
818 "#endif\n"
819 "#else // !MODE_WATER\n"
820 "\n"
821 "\n"
822 "\n"
823 "\n"
824 "// common definitions between vertex shader and fragment shader:\n"
825 "\n"
826 "varying vec2 TexCoord;\n"
827 "#ifdef USEVERTEXTEXTUREBLEND\n"
828 "varying vec2 TexCoord2;\n"
829 "#endif\n"
830 "#ifdef USELIGHTMAP\n"
831 "varying vec2 TexCoordLightmap;\n"
832 "#endif\n"
833 "\n"
834 "#ifdef MODE_LIGHTSOURCE\n"
835 "varying vec3 CubeVector;\n"
836 "#endif\n"
837 "\n"
838 "#ifdef MODE_LIGHTSOURCE\n"
839 "varying vec3 LightVector;\n"
840 "#endif\n"
841 "#if defined(MODE_LIGHTDIRECTION)\n"
842 "varying vec3 LightVector;\n"
843 "#endif\n"
844 "\n"
845 "#ifdef USEEYEVECTOR\n"
846 "varying vec3 EyeVector;\n"
847 "#endif\n"
848 "#ifdef USEFOG\n"
849 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
850 "#endif\n"
851 "\n"
852 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
853 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
854 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
855 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
856 "#endif\n"
857 "\n"
858 "#ifdef USEREFLECTION\n"
859 "varying vec4 ModelViewProjectionPosition;\n"
860 "#endif\n"
861 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
862 "uniform vec3 LightPosition;\n"
863 "varying vec4 ModelViewPosition;\n"
864 "#endif\n"
865 "\n"
866 "#ifdef MODE_LIGHTSOURCE\n"
867 "uniform vec3 LightPosition;\n"
868 "#endif\n"
869 "uniform vec3 EyePosition;\n"
870 "#ifdef MODE_LIGHTDIRECTION\n"
871 "uniform vec3 LightDir;\n"
872 "#endif\n"
873 "uniform vec4 FogPlane;\n"
874 "\n"
875 "\n"
876 "\n"
877 "\n"
878 "\n"
879 "// 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"
880 "\n"
881 "// fragment shader specific:\n"
882 "#ifdef FRAGMENT_SHADER\n"
883 "\n"
884 "uniform sampler2D Texture_Normal;\n"
885 "uniform sampler2D Texture_Color;\n"
886 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
887 "uniform sampler2D Texture_Gloss;\n"
888 "//#endif\n"
889 "#ifdef USEGLOW\n"
890 "uniform sampler2D Texture_Glow;\n"
891 "#endif\n"
892 "#ifdef USEVERTEXTEXTUREBLEND\n"
893 "uniform sampler2D Texture_SecondaryNormal;\n"
894 "uniform sampler2D Texture_SecondaryColor;\n"
895 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
896 "uniform sampler2D Texture_SecondaryGloss;\n"
897 "//#endif\n"
898 "#ifdef USEGLOW\n"
899 "uniform sampler2D Texture_SecondaryGlow;\n"
900 "#endif\n"
901 "#endif\n"
902 "#ifdef USECOLORMAPPING\n"
903 "uniform sampler2D Texture_Pants;\n"
904 "uniform sampler2D Texture_Shirt;\n"
905 "#endif\n"
906 "#ifdef USEFOG\n"
907 "uniform sampler2D Texture_FogMask;\n"
908 "#endif\n"
909 "#ifdef USELIGHTMAP\n"
910 "uniform sampler2D Texture_Lightmap;\n"
911 "#endif\n"
912 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
913 "uniform sampler2D Texture_Deluxemap;\n"
914 "#endif\n"
915 "#ifdef USEREFLECTION\n"
916 "uniform sampler2D Texture_Reflection;\n"
917 "#endif\n"
918 "\n"
919 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
920 "uniform sampler2DRect Texture_ScreenDepth;\n"
921 "uniform sampler2DRect Texture_ScreenNormalMap;\n"
922 "#endif\n"
923 "#ifdef USEDEFERREDLIGHTMAP\n"
924 "uniform sampler2DRect Texture_ScreenDiffuse;\n"
925 "uniform sampler2DRect Texture_ScreenSpecular;\n"
926 "#endif\n"
927 "\n"
928 "uniform myhalf3 Color_Pants;\n"
929 "uniform myhalf3 Color_Shirt;\n"
930 "uniform myhalf3 FogColor;\n"
931 "\n"
932 "#ifdef USEFOG\n"
933 "uniform float FogRangeRecip;\n"
934 "uniform float FogPlaneViewDist;\n"
935 "uniform float FogHeightFade;\n"
936 "float FogVertex(void)\n"
937 "{\n"
938 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
939 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
940 "       float fogfrac;\n"
941 "#ifdef USEFOGOUTSIDE\n"
942 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
943 "#else\n"
944 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
945 "#endif\n"
946 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
947 "}\n"
948 "#endif\n"
949 "\n"
950 "#ifdef USEOFFSETMAPPING\n"
951 "uniform float OffsetMapping_Scale;\n"
952 "vec2 OffsetMapping(vec2 TexCoord)\n"
953 "{\n"
954 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
955 "       // 14 sample relief mapping: linear search and then binary search\n"
956 "       // this basically steps forward a small amount repeatedly until it finds\n"
957 "       // itself inside solid, then jitters forward and back using decreasing\n"
958 "       // amounts to find the impact\n"
959 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
960 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
961 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
962 "       vec3 RT = vec3(TexCoord, 1);\n"
963 "       OffsetVector *= 0.1;\n"
964 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
965 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
966 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
967 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
968 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
969 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
974 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
975 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
976 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
977 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
978 "       return RT.xy;\n"
979 "#else\n"
980 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
981 "       // this basically moves forward the full distance, and then backs up based\n"
982 "       // on height of samples\n"
983 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
984 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
985 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
986 "       TexCoord += OffsetVector;\n"
987 "       OffsetVector *= 0.333;\n"
988 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
989 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
990 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
991 "       return TexCoord;\n"
992 "#endif\n"
993 "}\n"
994 "#endif // USEOFFSETMAPPING\n"
995 "\n"
996 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
997 "uniform sampler2D Texture_Attenuation;\n"
998 "uniform samplerCube Texture_Cube;\n"
999 "\n"
1000 "#ifdef USESHADOWMAPRECT\n"
1001 "# ifdef USESHADOWSAMPLER\n"
1002 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1003 "# else\n"
1004 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1005 "# endif\n"
1006 "#endif\n"
1007 "\n"
1008 "#ifdef USESHADOWMAP2D\n"
1009 "# ifdef USESHADOWSAMPLER\n"
1010 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1011 "# else\n"
1012 "uniform sampler2D Texture_ShadowMap2D;\n"
1013 "# endif\n"
1014 "#endif\n"
1015 "\n"
1016 "#ifdef USESHADOWMAPVSDCT\n"
1017 "uniform samplerCube Texture_CubeProjection;\n"
1018 "#endif\n"
1019 "\n"
1020 "#ifdef USESHADOWMAPCUBE\n"
1021 "# ifdef USESHADOWSAMPLER\n"
1022 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1023 "# else\n"
1024 "uniform samplerCube Texture_ShadowMapCube;\n"
1025 "# endif\n"
1026 "#endif\n"
1027 "\n"
1028 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1029 "uniform vec2 ShadowMap_TextureScale;\n"
1030 "uniform vec4 ShadowMap_Parameters;\n"
1031 "#endif\n"
1032 "\n"
1033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1034 "# ifndef USESHADOWMAPVSDCT\n"
1035 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1036 "{\n"
1037 "       vec3 adir = abs(dir);\n"
1038 "       vec2 tc;\n"
1039 "       vec2 offset;\n"
1040 "       float ma;\n"
1041 "       if (adir.x > adir.y)\n"
1042 "       {\n"
1043 "               if (adir.x > adir.z) // X\n"
1044 "               {\n"
1045 "                       ma = adir.x;\n"
1046 "                       tc = dir.zy;\n"
1047 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1048 "               }\n"
1049 "               else // Z\n"
1050 "               {\n"
1051 "                       ma = adir.z;\n"
1052 "                       tc = dir.xy;\n"
1053 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1054 "               }\n"
1055 "       }\n"
1056 "       else\n"
1057 "       {\n"
1058 "               if (adir.y > adir.z) // Y\n"
1059 "               {\n"
1060 "                       ma = adir.y;\n"
1061 "                       tc = dir.xz;\n"
1062 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1063 "               }\n"
1064 "               else // Z\n"
1065 "               {\n"
1066 "                       ma = adir.z;\n"
1067 "                       tc = dir.xy;\n"
1068 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1069 "               }\n"
1070 "       }\n"
1071 "\n"
1072 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1073 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1074 "       stc.z += ShadowMap_Parameters.z;\n"
1075 "       return stc;\n"
1076 "}\n"
1077 "# else\n"
1078 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1079 "{\n"
1080 "       vec3 adir = abs(dir);\n"
1081 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1082 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1083 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1084 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1085 "       stc.z += ShadowMap_Parameters.z;\n"
1086 "       return stc;\n"
1087 "}\n"
1088 "# endif\n"
1089 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1090 "\n"
1091 "#ifdef USESHADOWMAPCUBE\n"
1092 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1093 "{\n"
1094 "       vec3 adir = abs(dir);\n"
1095 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1096 "}\n"
1097 "#endif\n"
1098 "\n"
1099 "# ifdef USESHADOWMAPRECT\n"
1100 "float ShadowMapCompare(vec3 dir)\n"
1101 "{\n"
1102 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1103 "       float f;\n"
1104 "#  ifdef USESHADOWSAMPLER\n"
1105 "\n"
1106 "#    ifdef USESHADOWMAPPCF\n"
1107 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1108 "       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"
1109 "#    else\n"
1110 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1111 "#    endif\n"
1112 "\n"
1113 "#  else\n"
1114 "\n"
1115 "#    ifdef USESHADOWMAPPCF\n"
1116 "#      if USESHADOWMAPPCF > 1\n"
1117 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1118 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1119 "       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"
1120 "       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"
1121 "       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"
1122 "       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"
1123 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1124 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1125 "#      else\n"
1126 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1127 "       vec2 offset = fract(shadowmaptc.xy);\n"
1128 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1129 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1130 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1131 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1132 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1133 "#      endif\n"
1134 "#    else\n"
1135 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1136 "#    endif\n"
1137 "\n"
1138 "#  endif\n"
1139 "       return f;\n"
1140 "}\n"
1141 "# endif\n"
1142 "\n"
1143 "# ifdef USESHADOWMAP2D\n"
1144 "float ShadowMapCompare(vec3 dir)\n"
1145 "{\n"
1146 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1147 "       float f;\n"
1148 "\n"
1149 "#  ifdef USESHADOWSAMPLER\n"
1150 "#    ifdef USESHADOWMAPPCF\n"
1151 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1152 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1153 "       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"
1154 "#    else\n"
1155 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1156 "#    endif\n"
1157 "#  else\n"
1158 "#    ifdef USESHADOWMAPPCF\n"
1159 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1160 "#      ifdef GL_ARB_texture_gather\n"
1161 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
1162 "#      else\n"
1163 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x,y)*ShadowMap_TextureScale)\n"
1164 "#      endif\n"
1165 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1166 "       center *= ShadowMap_TextureScale;\n"
1167 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1168 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1169 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1170 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1171 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1172 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1173 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1174 "#     else\n"
1175 "#      ifdef GL_EXT_gpu_shader4\n"
1176 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1177 "#      else\n"
1178 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1179 "#      endif\n"
1180 "#      if USESHADOWMAPPCF > 1\n"
1181 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1182 "       center *= ShadowMap_TextureScale;\n"
1183 "       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"
1184 "       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"
1185 "       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"
1186 "       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"
1187 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1188 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1189 "#      else\n"
1190 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1191 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1192 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1193 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1194 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1195 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1196 "#      endif\n"
1197 "#     endif\n"
1198 "#    else\n"
1199 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1200 "#    endif\n"
1201 "#  endif\n"
1202 "       return f;\n"
1203 "}\n"
1204 "# endif\n"
1205 "\n"
1206 "# ifdef USESHADOWMAPCUBE\n"
1207 "float ShadowMapCompare(vec3 dir)\n"
1208 "{\n"
1209 "       // apply depth texture cubemap as light filter\n"
1210 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1211 "       float f;\n"
1212 "#  ifdef USESHADOWSAMPLER\n"
1213 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1214 "#  else\n"
1215 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1216 "#  endif\n"
1217 "       return f;\n"
1218 "}\n"
1219 "# endif\n"
1220 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1221 "#endif // FRAGMENT_SHADER\n"
1222 "\n"
1223 "\n"
1224 "\n"
1225 "\n"
1226 "#ifdef MODE_DEFERREDGEOMETRY\n"
1227 "#ifdef VERTEX_SHADER\n"
1228 "uniform mat4 TexMatrix;\n"
1229 "#ifdef USEVERTEXTEXTUREBLEND\n"
1230 "uniform mat4 BackgroundTexMatrix;\n"
1231 "#endif\n"
1232 "uniform mat4 ModelViewMatrix;\n"
1233 "void main(void)\n"
1234 "{\n"
1235 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1236 "#ifdef USEVERTEXTEXTUREBLEND\n"
1237 "       gl_FrontColor = gl_Color;\n"
1238 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1239 "#endif\n"
1240 "\n"
1241 "       // transform unnormalized eye direction into tangent space\n"
1242 "#ifdef USEOFFSETMAPPING\n"
1243 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1244 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1245 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1246 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1247 "#endif\n"
1248 "\n"
1249 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1250 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1251 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1252 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1253 "}\n"
1254 "#endif // VERTEX_SHADER\n"
1255 "\n"
1256 "#ifdef FRAGMENT_SHADER\n"
1257 "void main(void)\n"
1258 "{\n"
1259 "#ifdef USEOFFSETMAPPING\n"
1260 "       // apply offsetmapping\n"
1261 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1262 "#define TexCoord TexCoordOffset\n"
1263 "#endif\n"
1264 "\n"
1265 "#ifdef USEALPHAKILL\n"
1266 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1267 "               discard;\n"
1268 "#endif\n"
1269 "\n"
1270 "#ifdef USEVERTEXTEXTUREBLEND\n"
1271 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1272 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1273 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1274 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1275 "#endif\n"
1276 "\n"
1277 "#ifdef USEVERTEXTEXTUREBLEND\n"
1278 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1279 "#else\n"
1280 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1281 "#endif\n"
1282 "\n"
1283 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1284 "}\n"
1285 "#endif // FRAGMENT_SHADER\n"
1286 "#else // !MODE_DEFERREDGEOMETRY\n"
1287 "\n"
1288 "\n"
1289 "\n"
1290 "\n"
1291 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1292 "#ifdef VERTEX_SHADER\n"
1293 "uniform mat4 ModelViewMatrix;\n"
1294 "void main(void)\n"
1295 "{\n"
1296 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1297 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1298 "}\n"
1299 "#endif // VERTEX_SHADER\n"
1300 "\n"
1301 "#ifdef FRAGMENT_SHADER\n"
1302 "uniform mat4 ViewToLight;\n"
1303 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1304 "uniform vec2 ScreenToDepth;\n"
1305 "uniform myhalf3 DeferredColor_Ambient;\n"
1306 "uniform myhalf3 DeferredColor_Diffuse;\n"
1307 "#ifdef USESPECULAR\n"
1308 "uniform myhalf3 DeferredColor_Specular;\n"
1309 "uniform myhalf SpecularPower;\n"
1310 "#endif\n"
1311 "void main(void)\n"
1312 "{\n"
1313 "       // calculate viewspace pixel position\n"
1314 "       vec3 position;\n"
1315 "       position.z = ScreenToDepth.y / (texture2DRect(Texture_ScreenDepth, gl_FragCoord.xy).r + ScreenToDepth.x);\n"
1316 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1317 "       // decode viewspace pixel normal\n"
1318 "       myhalf4 normalmap = texture2DRect(Texture_ScreenNormalMap, gl_FragCoord.xy);\n"
1319 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1320 "       // surfacenormal = pixel normal in viewspace\n"
1321 "       // LightVector = pixel to light in viewspace\n"
1322 "       // CubeVector = position in lightspace\n"
1323 "       // eyevector = pixel to view in viewspace\n"
1324 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1325 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1326 "#ifdef USEDIFFUSE\n"
1327 "       // calculate diffuse shading\n"
1328 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1329 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1330 "#endif\n"
1331 "#ifdef USESPECULAR\n"
1332 "       // calculate directional shading\n"
1333 "       vec3 eyevector = position * -1.0;\n"
1334 "#  ifdef USEEXACTSPECULARMATH\n"
1335 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1336 "#  else\n"
1337 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1338 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1339 "#  endif\n"
1340 "#endif\n"
1341 "\n"
1342 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1343 "       fade *= ShadowMapCompare(CubeVector);\n"
1344 "#endif\n"
1345 "\n"
1346 "#ifdef USEDIFFUSE\n"
1347 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1348 "#else\n"
1349 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1350 "#endif\n"
1351 "#ifdef USESPECULAR\n"
1352 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1353 "#else\n"
1354 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1355 "#endif\n"
1356 "\n"
1357 "# ifdef USECUBEFILTER\n"
1358 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1359 "       gl_FragData[0] *= cubecolor;\n"
1360 "       gl_FragData[1] *= cubecolor;\n"
1361 "# endif\n"
1362 "}\n"
1363 "#endif // FRAGMENT_SHADER\n"
1364 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1365 "\n"
1366 "\n"
1367 "\n"
1368 "\n"
1369 "#ifdef VERTEX_SHADER\n"
1370 "uniform mat4 TexMatrix;\n"
1371 "#ifdef USEVERTEXTEXTUREBLEND\n"
1372 "uniform mat4 BackgroundTexMatrix;\n"
1373 "#endif\n"
1374 "#ifdef MODE_LIGHTSOURCE\n"
1375 "uniform mat4 ModelToLight;\n"
1376 "#endif\n"
1377 "void main(void)\n"
1378 "{\n"
1379 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1380 "       gl_FrontColor = gl_Color;\n"
1381 "#endif\n"
1382 "       // copy the surface texcoord\n"
1383 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1384 "#ifdef USEVERTEXTEXTUREBLEND\n"
1385 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1386 "#endif\n"
1387 "#ifdef USELIGHTMAP\n"
1388 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1389 "#endif\n"
1390 "\n"
1391 "#ifdef MODE_LIGHTSOURCE\n"
1392 "       // transform vertex position into light attenuation/cubemap space\n"
1393 "       // (-1 to +1 across the light box)\n"
1394 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1395 "\n"
1396 "# ifdef USEDIFFUSE\n"
1397 "       // transform unnormalized light direction into tangent space\n"
1398 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1399 "       //  normalize it per pixel)\n"
1400 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1401 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1402 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1403 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1404 "# endif\n"
1405 "#endif\n"
1406 "\n"
1407 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1408 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1409 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1410 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1411 "#endif\n"
1412 "\n"
1413 "       // transform unnormalized eye direction into tangent space\n"
1414 "#ifdef USEEYEVECTOR\n"
1415 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1416 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1417 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1418 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1419 "#endif\n"
1420 "\n"
1421 "#ifdef USEFOG\n"
1422 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1423 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1424 "#endif\n"
1425 "\n"
1426 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1427 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1428 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1429 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1430 "#endif\n"
1431 "\n"
1432 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1433 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1434 "\n"
1435 "#ifdef USEREFLECTION\n"
1436 "       ModelViewProjectionPosition = gl_Position;\n"
1437 "#endif\n"
1438 "}\n"
1439 "#endif // VERTEX_SHADER\n"
1440 "\n"
1441 "\n"
1442 "\n"
1443 "\n"
1444 "#ifdef FRAGMENT_SHADER\n"
1445 "#ifdef USEDEFERREDLIGHTMAP\n"
1446 "uniform myhalf3 DeferredMod_Diffuse;\n"
1447 "uniform myhalf3 DeferredMod_Specular;\n"
1448 "#endif\n"
1449 "uniform myhalf3 Color_Ambient;\n"
1450 "uniform myhalf3 Color_Diffuse;\n"
1451 "uniform myhalf3 Color_Specular;\n"
1452 "uniform myhalf SpecularPower;\n"
1453 "#ifdef USEGLOW\n"
1454 "uniform myhalf3 Color_Glow;\n"
1455 "#endif\n"
1456 "uniform myhalf Alpha;\n"
1457 "#ifdef USEREFLECTION\n"
1458 "uniform vec4 DistortScaleRefractReflect;\n"
1459 "uniform vec4 ScreenScaleRefractReflect;\n"
1460 "uniform vec4 ScreenCenterRefractReflect;\n"
1461 "uniform myhalf4 ReflectColor;\n"
1462 "#endif\n"
1463 "#ifdef MODE_LIGHTDIRECTION\n"
1464 "uniform myhalf3 LightColor;\n"
1465 "#endif\n"
1466 "#ifdef MODE_LIGHTSOURCE\n"
1467 "uniform myhalf3 LightColor;\n"
1468 "#endif\n"
1469 "void main(void)\n"
1470 "{\n"
1471 "#ifdef USEOFFSETMAPPING\n"
1472 "       // apply offsetmapping\n"
1473 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1474 "#define TexCoord TexCoordOffset\n"
1475 "#endif\n"
1476 "\n"
1477 "       // combine the diffuse textures (base, pants, shirt)\n"
1478 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1479 "#ifdef USEALPHAKILL\n"
1480 "       if (color.a < 0.5)\n"
1481 "               discard;\n"
1482 "#endif\n"
1483 "       color.a *= Alpha;\n"
1484 "#ifdef USECOLORMAPPING\n"
1485 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1486 "#endif\n"
1487 "#ifdef USEVERTEXTEXTUREBLEND\n"
1488 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1489 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1490 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1491 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1492 "       color.a = 1.0;\n"
1493 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1494 "#endif\n"
1495 "\n"
1496 "       // get the surface normal\n"
1497 "#ifdef USEVERTEXTEXTUREBLEND\n"
1498 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1499 "#else\n"
1500 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1501 "#endif\n"
1502 "\n"
1503 "       // get the material colors\n"
1504 "       myhalf3 diffusetex = color.rgb;\n"
1505 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1506 "# ifdef USEVERTEXTEXTUREBLEND\n"
1507 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1508 "# else\n"
1509 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1510 "# endif\n"
1511 "#endif\n"
1512 "\n"
1513 "\n"
1514 "\n"
1515 "\n"
1516 "#ifdef MODE_LIGHTSOURCE\n"
1517 "       // light source\n"
1518 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1519 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1520 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1521 "#ifdef USESPECULAR\n"
1522 "#ifdef USEEXACTSPECULARMATH\n"
1523 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1524 "#else\n"
1525 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1526 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1527 "#endif\n"
1528 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1529 "#endif\n"
1530 "       color.rgb *= LightColor;\n"
1531 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1532 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1533 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1534 "#endif\n"
1535 "# ifdef USECUBEFILTER\n"
1536 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1537 "# endif\n"
1538 "#endif // MODE_LIGHTSOURCE\n"
1539 "\n"
1540 "\n"
1541 "\n"
1542 "\n"
1543 "#ifdef MODE_LIGHTDIRECTION\n"
1544 "#define SHADING\n"
1545 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1546 "#define lightcolor LightColor\n"
1547 "#endif // MODE_LIGHTDIRECTION\n"
1548 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1549 "#define SHADING\n"
1550 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1551 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1552 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1553 "       // convert modelspace light vector to tangentspace\n"
1554 "       myhalf3 lightnormal;\n"
1555 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1556 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1557 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1558 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1559 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1560 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1561 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1562 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1563 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1564 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1565 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1566 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1567 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1568 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1569 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1570 "#define SHADING\n"
1571 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1572 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1573 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1574 "#endif\n"
1575 "\n"
1576 "\n"
1577 "\n"
1578 "\n"
1579 "#ifdef MODE_LIGHTMAP\n"
1580 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1581 "#endif // MODE_LIGHTMAP\n"
1582 "#ifdef MODE_VERTEXCOLOR\n"
1583 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1584 "#endif // MODE_VERTEXCOLOR\n"
1585 "#ifdef MODE_FLATCOLOR\n"
1586 "       color.rgb = diffusetex * Color_Ambient;\n"
1587 "#endif // MODE_FLATCOLOR\n"
1588 "\n"
1589 "\n"
1590 "\n"
1591 "\n"
1592 "#ifdef SHADING\n"
1593 "# ifdef USEDIFFUSE\n"
1594 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1595 "#  ifdef USESPECULAR\n"
1596 "#   ifdef USEEXACTSPECULARMATH\n"
1597 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1598 "#   else\n"
1599 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1600 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1601 "#   endif\n"
1602 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1603 "#  else\n"
1604 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1605 "#  endif\n"
1606 "# else\n"
1607 "       color.rgb = diffusetex * Color_Ambient;\n"
1608 "# endif\n"
1609 "#endif\n"
1610 "\n"
1611 "#ifdef USEDEFERREDLIGHTMAP\n"
1612 "       color.rgb += diffusetex * myhalf3(texture2DRect(Texture_ScreenDiffuse, gl_FragCoord.xy)) * DeferredMod_Diffuse;\n"
1613 "       color.rgb += glosstex * myhalf3(texture2DRect(Texture_ScreenSpecular, gl_FragCoord.xy)) * DeferredMod_Specular;\n"
1614 "#endif\n"
1615 "\n"
1616 "#ifdef USEGLOW\n"
1617 "#ifdef USEVERTEXTEXTUREBLEND\n"
1618 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1619 "#else\n"
1620 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1621 "#endif\n"
1622 "#endif\n"
1623 "\n"
1624 "#ifdef USEFOG\n"
1625 "#ifdef MODE_LIGHTSOURCE\n"
1626 "       color.rgb *= myhalf(FogVertex());\n"
1627 "#else\n"
1628 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1629 "#endif\n"
1630 "#endif\n"
1631 "\n"
1632 "       // 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"
1633 "#ifdef USEREFLECTION\n"
1634 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1635 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1636 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1637 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1638 "       // FIXME temporary hack to detect the case that the reflection\n"
1639 "       // gets blackened at edges due to leaving the area that contains actual\n"
1640 "       // content.\n"
1641 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1642 "       // 'appening.\n"
1643 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1644 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1645 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1646 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1647 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1648 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1649 "#endif\n"
1650 "\n"
1651 "       gl_FragColor = vec4(color);\n"
1652 "}\n"
1653 "#endif // FRAGMENT_SHADER\n"
1654 "\n"
1655 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1656 "#endif // !MODE_DEFERREDGEOMETRY\n"
1657 "#endif // !MODE_WATER\n"
1658 "#endif // !MODE_REFRACTION\n"
1659 "#endif // !MODE_BLOOMBLUR\n"
1660 "#endif // !MODE_GENERIC\n"
1661 "#endif // !MODE_POSTPROCESS\n"
1662 "#endif // !MODE_SHOWDEPTH\n"
1663 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1664 ;
1665
1666 /*
1667 =========================================================================================================================================================
1668
1669
1670
1671 =========================================================================================================================================================
1672
1673
1674
1675 =========================================================================================================================================================
1676
1677
1678
1679 =========================================================================================================================================================
1680
1681
1682
1683 =========================================================================================================================================================
1684
1685
1686
1687 =========================================================================================================================================================
1688
1689
1690
1691 =========================================================================================================================================================
1692 */
1693
1694 const char *builtincgshaderstring =
1695 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1696 "// written by Forest 'LordHavoc' Hale\n"
1697 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1698 "\n"
1699 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1700 "# define USEFOG\n"
1701 "#endif\n"
1702 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1703 "#define USELIGHTMAP\n"
1704 "#endif\n"
1705 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1706 "#define USEEYEVECTOR\n"
1707 "#endif\n"
1708 "\n"
1709 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1710 "#ifdef VERTEX_SHADER\n"
1711 "void main\n"
1712 "(\n"
1713 "float4 gl_Vertex : POSITION,\n"
1714 "uniform float4x4 ModelViewProjectionMatrix,\n"
1715 "out float4 gl_Position : POSITION\n"
1716 ")\n"
1717 "{\n"
1718 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1719 "}\n"
1720 "#endif\n"
1721 "#else // !MODE_DEPTH_ORSHADOW\n"
1722 "\n"
1723 "\n"
1724 "\n"
1725 "\n"
1726 "#ifdef MODE_SHOWDEPTH\n"
1727 "#ifdef VERTEX_SHADER\n"
1728 "void main\n"
1729 "(\n"
1730 "float4 gl_Vertex : POSITION,\n"
1731 "uniform float4x4 ModelViewProjectionMatrix,\n"
1732 "out float4 gl_Position : POSITION,\n"
1733 "out float4 gl_FrontColor : COLOR0\n"
1734 ")\n"
1735 "{\n"
1736 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1737 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1738 "}\n"
1739 "#endif\n"
1740 "\n"
1741 "#ifdef FRAGMENT_SHADER\n"
1742 "void main\n"
1743 "(\n"
1744 "float4 gl_FrontColor : COLOR0,\n"
1745 "out float4 gl_FragColor : COLOR\n"
1746 ")\n"
1747 "{\n"
1748 "       gl_FragColor = gl_FrontColor;\n"
1749 "}\n"
1750 "#endif\n"
1751 "#else // !MODE_SHOWDEPTH\n"
1752 "\n"
1753 "\n"
1754 "\n"
1755 "\n"
1756 "#ifdef MODE_POSTPROCESS\n"
1757 "\n"
1758 "#ifdef VERTEX_SHADER\n"
1759 "void main\n"
1760 "(\n"
1761 "float4 gl_Vertex : POSITION,\n"
1762 "uniform float4x4 ModelViewProjectionMatrix,\n"
1763 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1764 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1765 "out float4 gl_Position : POSITION,\n"
1766 "out float2 TexCoord1 : TEXCOORD0,\n"
1767 "out float2 TexCoord2 : TEXCOORD1\n"
1768 ")\n"
1769 "{\n"
1770 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1771 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1772 "#ifdef USEBLOOM\n"
1773 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1774 "#endif\n"
1775 "}\n"
1776 "#endif\n"
1777 "\n"
1778 "#ifdef FRAGMENT_SHADER\n"
1779 "void main\n"
1780 "(\n"
1781 "float2 TexCoord1 : TEXCOORD0,\n"
1782 "float2 TexCoord2 : TEXCOORD1,\n"
1783 "uniform sampler2D Texture_First,\n"
1784 "#ifdef USEBLOOM\n"
1785 "uniform sampler2D Texture_Second,\n"
1786 "#endif\n"
1787 "#ifdef USEGAMMARAMPS\n"
1788 "uniform sampler2D Texture_GammaRamps,\n"
1789 "#endif\n"
1790 "#ifdef USESATURATION\n"
1791 "uniform float Saturation,\n"
1792 "#endif\n"
1793 "#ifdef USEVIEWTINT\n"
1794 "uniform float4 ViewTintColor,\n"
1795 "#endif\n"
1796 "uniform float4 UserVec1,\n"
1797 "uniform float4 UserVec2,\n"
1798 "uniform float4 UserVec3,\n"
1799 "uniform float4 UserVec4,\n"
1800 "uniform float ClientTime,\n"
1801 "uniform float2 PixelSize,\n"
1802 "out float4 gl_FragColor : COLOR\n"
1803 ")\n"
1804 "{\n"
1805 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1806 "#ifdef USEBLOOM\n"
1807 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1808 "#endif\n"
1809 "#ifdef USEVIEWTINT\n"
1810 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1811 "#endif\n"
1812 "\n"
1813 "#ifdef USEPOSTPROCESSING\n"
1814 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1815 "// 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"
1816 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1817 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1818 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1819 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1820 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1821 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1822 "#endif\n"
1823 "\n"
1824 "#ifdef USESATURATION\n"
1825 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1826 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1827 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1828 "       gl_FragColor.rgb = mix(float3(y), gl_FragColor.rgb, Saturation);\n"
1829 "#endif\n"
1830 "\n"
1831 "#ifdef USEGAMMARAMPS\n"
1832 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1833 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1834 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1835 "#endif\n"
1836 "}\n"
1837 "#endif\n"
1838 "#else // !MODE_POSTPROCESS\n"
1839 "\n"
1840 "\n"
1841 "\n"
1842 "\n"
1843 "#ifdef MODE_GENERIC\n"
1844 "#ifdef VERTEX_SHADER\n"
1845 "void main\n"
1846 "(\n"
1847 "float4 gl_Vertex : POSITION,\n"
1848 "uniform float4x4 ModelViewProjectionMatrix,\n"
1849 "float4 gl_Color : COLOR0,\n"
1850 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1851 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1852 "out float4 gl_Position : POSITION,\n"
1853 "out float4 gl_FrontColor : COLOR,\n"
1854 "out float2 TexCoord1 : TEXCOORD0,\n"
1855 "out float2 TexCoord2 : TEXCOORD1\n"
1856 ")\n"
1857 "{\n"
1858 "       gl_FrontColor = gl_Color;\n"
1859 "#ifdef USEDIFFUSE\n"
1860 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1861 "#endif\n"
1862 "#ifdef USESPECULAR\n"
1863 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1864 "#endif\n"
1865 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1866 "}\n"
1867 "#endif\n"
1868 "\n"
1869 "#ifdef FRAGMENT_SHADER\n"
1870 "\n"
1871 "void main\n"
1872 "(\n"
1873 "float4 gl_FrontColor : COLOR,\n"
1874 "float2 TexCoord1 : TEXCOORD0,\n"
1875 "float2 TexCoord2 : TEXCOORD1,\n"
1876 "#ifdef USEDIFFUSE\n"
1877 "uniform sampler2D Texture_First,\n"
1878 "#endif\n"
1879 "#ifdef USESPECULAR\n"
1880 "uniform sampler2D Texture_Second,\n"
1881 "#endif\n"
1882 "out float4 gl_FragColor : COLOR\n"
1883 ")\n"
1884 "{\n"
1885 "       gl_FragColor = gl_FrontColor;\n"
1886 "#ifdef USEDIFFUSE\n"
1887 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1888 "#endif\n"
1889 "\n"
1890 "#ifdef USESPECULAR\n"
1891 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1892 "# ifdef USECOLORMAPPING\n"
1893 "       gl_FragColor *= tex2;\n"
1894 "# endif\n"
1895 "# ifdef USEGLOW\n"
1896 "       gl_FragColor += tex2;\n"
1897 "# endif\n"
1898 "# ifdef USEVERTEXTEXTUREBLEND\n"
1899 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
1900 "# endif\n"
1901 "#endif\n"
1902 "}\n"
1903 "#endif\n"
1904 "#else // !MODE_GENERIC\n"
1905 "\n"
1906 "\n"
1907 "\n"
1908 "\n"
1909 "#ifdef MODE_BLOOMBLUR\n"
1910 "#ifdef VERTEX_SHADER\n"
1911 "void main\n"
1912 "(\n"
1913 "float4 gl_Vertex : POSITION,\n"
1914 "uniform float4x4 ModelViewProjectionMatrix,\n"
1915 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1916 "out float4 gl_Position : POSITION,\n"
1917 "out float2 TexCoord : TEXCOORD0\n"
1918 ")\n"
1919 "{\n"
1920 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1921 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1922 "}\n"
1923 "#endif\n"
1924 "\n"
1925 "#ifdef FRAGMENT_SHADER\n"
1926 "\n"
1927 "void main\n"
1928 "(\n"
1929 "float2 TexCoord : TEXCOORD0,\n"
1930 "uniform sampler2D Texture_First,\n"
1931 "uniform float4 BloomBlur_Parameters,\n"
1932 "out float4 gl_FragColor : COLOR\n"
1933 ")\n"
1934 "{\n"
1935 "       int i;\n"
1936 "       float2 tc = TexCoord;\n"
1937 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1938 "       tc += BloomBlur_Parameters.xy;\n"
1939 "       for (i = 1;i < SAMPLES;i++)\n"
1940 "       {\n"
1941 "               color += tex2D(Texture_First, tc).rgb;\n"
1942 "               tc += BloomBlur_Parameters.xy;\n"
1943 "       }\n"
1944 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1945 "}\n"
1946 "#endif\n"
1947 "#else // !MODE_BLOOMBLUR\n"
1948 "#ifdef MODE_REFRACTION\n"
1949 "#ifdef VERTEX_SHADER\n"
1950 "void main\n"
1951 "(\n"
1952 "float4 gl_Vertex : POSITION,\n"
1953 "uniform float4x4 ModelViewProjectionMatrix,\n"
1954 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1955 "uniform mat4 TexMatrix,\n"
1956 "uniform float3 EyePosition,\n"
1957 "out float4 gl_Position : POSITION,\n"
1958 "out float2 TexCoord : TEXCOORD0,\n"
1959 "out float3 EyeVector : TEXCOORD1,\n"
1960 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1961 ")\n"
1962 "{\n"
1963 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1964 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1965 "       ModelViewProjectionPosition = gl_Position;\n"
1966 "}\n"
1967 "#endif\n"
1968 "\n"
1969 "#ifdef FRAGMENT_SHADER\n"
1970 "void main\n"
1971 "(\n"
1972 "float2 TexCoord : TEXCOORD0,\n"
1973 "float3 EyeVector : TEXCOORD1,\n"
1974 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1975 "uniform sampler2D Texture_Normal,\n"
1976 "uniform sampler2D Texture_Refraction,\n"
1977 "uniform sampler2D Texture_Reflection,\n"
1978 "uniform float4 DistortScaleRefractReflect,\n"
1979 "uniform float4 ScreenScaleRefractReflect,\n"
1980 "uniform float4 ScreenCenterRefractReflect,\n"
1981 "uniform float4 RefractColor,\n"
1982 "out float4 gl_FragColor : COLOR\n"
1983 ")\n"
1984 "{\n"
1985 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1986 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1987 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1988 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
1989 "       // FIXME temporary hack to detect the case that the reflection\n"
1990 "       // gets blackened at edges due to leaving the area that contains actual\n"
1991 "       // content.\n"
1992 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1993 "       // 'appening.\n"
1994 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
1995 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
1996 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
1997 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
1998 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1999 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2000 "}\n"
2001 "#endif\n"
2002 "#else // !MODE_REFRACTION\n"
2003 "\n"
2004 "\n"
2005 "\n"
2006 "\n"
2007 "#ifdef MODE_WATER\n"
2008 "#ifdef VERTEX_SHADER\n"
2009 "\n"
2010 "void main\n"
2011 "(\n"
2012 "float4 gl_Vertex : POSITION,\n"
2013 "uniform float4x4 ModelViewProjectionMatrix,\n"
2014 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2015 "uniform mat4 TexMatrix,\n"
2016 "uniform float3 EyePosition,\n"
2017 "out float4 gl_Position : POSITION,\n"
2018 "out float2 TexCoord : TEXCOORD0,\n"
2019 "out float3 EyeVector : TEXCOORD1,\n"
2020 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2021 ")\n"
2022 "{\n"
2023 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2024 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2025 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2026 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2027 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2028 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2029 "       ModelViewProjectionPosition = gl_Position;\n"
2030 "}\n"
2031 "#endif\n"
2032 "\n"
2033 "#ifdef FRAGMENT_SHADER\n"
2034 "void main\n"
2035 "(\n"
2036 "float2 TexCoord : TEXCOORD0,\n"
2037 "float3 EyeVector : TEXCOORD1,\n"
2038 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2039 "uniform sampler2D Texture_Normal,\n"
2040 "uniform sampler2D Texture_Refraction,\n"
2041 "uniform sampler2D Texture_Reflection,\n"
2042 "uniform float4 DistortScaleRefractReflect,\n"
2043 "uniform float4 ScreenScaleRefractReflect,\n"
2044 "uniform float4 ScreenCenterRefractReflect,\n"
2045 "uniform float4 RefractColor,\n"
2046 "uniform float4 ReflectColor,\n"
2047 "uniform float ReflectFactor,\n"
2048 "uniform float ReflectOffset,\n"
2049 "out float4 gl_FragColor : COLOR\n"
2050 ")\n"
2051 "{\n"
2052 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2053 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2054 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2055 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2056 "       // FIXME temporary hack to detect the case that the reflection\n"
2057 "       // gets blackened at edges due to leaving the area that contains actual\n"
2058 "       // content.\n"
2059 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2060 "       // 'appening.\n"
2061 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2062 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2063 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2064 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2065 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2066 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2067 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2068 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2069 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2070 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2071 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2072 "       gl_FragColor = mix(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2073 "}\n"
2074 "#endif\n"
2075 "#else // !MODE_WATER\n"
2076 "\n"
2077 "\n"
2078 "\n"
2079 "\n"
2080 "// 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"
2081 "\n"
2082 "// fragment shader specific:\n"
2083 "#ifdef FRAGMENT_SHADER\n"
2084 "\n"
2085 "#ifdef USEFOG\n"
2086 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2087 "{\n"
2088 "       float fogfrac;\n"
2089 "#ifdef USEFOGOUTSIDE\n"
2090 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2091 "#else\n"
2092 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2093 "#endif\n"
2094 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2095 "}\n"
2096 "#endif\n"
2097 "\n"
2098 "#ifdef USEOFFSETMAPPING\n"
2099 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2100 "{\n"
2101 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2102 "       // 14 sample relief mapping: linear search and then binary search\n"
2103 "       // this basically steps forward a small amount repeatedly until it finds\n"
2104 "       // itself inside solid, then jitters forward and back using decreasing\n"
2105 "       // amounts to find the impact\n"
2106 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2107 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2108 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2109 "       float3 RT = float3(TexCoord, 1);\n"
2110 "       OffsetVector *= 0.1;\n"
2111 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2112 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2113 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2114 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2115 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2116 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2117 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2118 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2119 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2120 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2121 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2122 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2123 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2124 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2125 "       return RT.xy;\n"
2126 "#else\n"
2127 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2128 "       // this basically moves forward the full distance, and then backs up based\n"
2129 "       // on height of samples\n"
2130 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2131 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2132 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2133 "       TexCoord += OffsetVector;\n"
2134 "       OffsetVector *= 0.333;\n"
2135 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2136 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2137 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2138 "       return TexCoord;\n"
2139 "#endif\n"
2140 "}\n"
2141 "#endif // USEOFFSETMAPPING\n"
2142 "\n"
2143 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2144 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2145 "# ifndef USESHADOWMAPVSDCT\n"
2146 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2147 "{\n"
2148 "       float3 adir = abs(dir);\n"
2149 "       float2 tc;\n"
2150 "       float2 offset;\n"
2151 "       float ma;\n"
2152 "       if (adir.x > adir.y)\n"
2153 "       {\n"
2154 "               if (adir.x > adir.z) // X\n"
2155 "               {\n"
2156 "                       ma = adir.x;\n"
2157 "                       tc = dir.zy;\n"
2158 "                       offset = float2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2159 "               }\n"
2160 "               else // Z\n"
2161 "               {\n"
2162 "                       ma = adir.z;\n"
2163 "                       tc = dir.xy;\n"
2164 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2165 "               }\n"
2166 "       }\n"
2167 "       else\n"
2168 "       {\n"
2169 "               if (adir.y > adir.z) // Y\n"
2170 "               {\n"
2171 "                       ma = adir.y;\n"
2172 "                       tc = dir.xz;\n"
2173 "                       offset = float2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2174 "               }\n"
2175 "               else // Z\n"
2176 "               {\n"
2177 "                       ma = adir.z;\n"
2178 "                       tc = dir.xy;\n"
2179 "                       offset = float2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2180 "               }\n"
2181 "       }\n"
2182 "\n"
2183 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2184 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2185 "       stc.z += ShadowMap_Parameters.z;\n"
2186 "       return stc;\n"
2187 "}\n"
2188 "# else\n"
2189 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2190 "{\n"
2191 "       float3 adir = abs(dir);\n"
2192 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2193 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2194 "       float3 stc = float3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2195 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2196 "       stc.z += ShadowMap_Parameters.z;\n"
2197 "       return stc;\n"
2198 "}\n"
2199 "# endif\n"
2200 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2201 "\n"
2202 "#ifdef USESHADOWMAPCUBE\n"
2203 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2204 "{\n"
2205 "    float3 adir = abs(dir);\n"
2206 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2207 "}\n"
2208 "#endif\n"
2209 "\n"
2210 "# ifdef USESHADOWMAPRECT\n"
2211 "#ifdef USESHADOWMAPVSDCT\n"
2212 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2213 "#else\n"
2214 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2215 "#endif\n"
2216 "{\n"
2217 "#ifdef USESHADOWMAPVSDCT\n"
2218 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2219 "#else\n"
2220 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2221 "#endif\n"
2222 "       float f;\n"
2223 "#  ifdef USESHADOWSAMPLER\n"
2224 "\n"
2225 "#    ifdef USESHADOWMAPPCF\n"
2226 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2227 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2228 "#    else\n"
2229 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2230 "#    endif\n"
2231 "\n"
2232 "#  else\n"
2233 "\n"
2234 "#    ifdef USESHADOWMAPPCF\n"
2235 "#      if USESHADOWMAPPCF > 1\n"
2236 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2237 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2238 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2239 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2240 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2241 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2242 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2243 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2244 "#      else\n"
2245 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2246 "    float2 offset = fract(shadowmaptc.xy);\n"
2247 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2248 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2249 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2250 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2251 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2252 "#      endif\n"
2253 "#    else\n"
2254 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2255 "#    endif\n"
2256 "\n"
2257 "#  endif\n"
2258 "       return f;\n"
2259 "}\n"
2260 "# endif\n"
2261 "\n"
2262 "# ifdef USESHADOWMAP2D\n"
2263 "#ifdef USESHADOWMAPVSDCT\n"
2264 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2265 "#else\n"
2266 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2267 "#endif\n"
2268 "{\n"
2269 "#ifdef USESHADOWMAPVSDCT\n"
2270 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2271 "#else\n"
2272 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2273 "#endif\n"
2274 "    float f;\n"
2275 "\n"
2276 "#  ifdef USESHADOWSAMPLER\n"
2277 "#    ifdef USESHADOWMAPPCF\n"
2278 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2279 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2280 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2281 "#    else\n"
2282 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2283 "#    endif\n"
2284 "#  else\n"
2285 "#    ifdef USESHADOWMAPPCF\n"
2286 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2287 "#      ifdef GL_ARB_texture_gather\n"
2288 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2289 "#      else\n"
2290 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2291 "#      endif\n"
2292 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2293 "    center *= ShadowMap_TextureScale;\n"
2294 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2295 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2296 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2297 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2298 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2299 "                mix(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2300 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2301 "#     else\n"
2302 "#      ifdef GL_EXT_gpu_shader4\n"
2303 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, ifloat2(x, y)).r\n"
2304 "#      else\n"
2305 "#        define texval(x, y) tex2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2306 "#      endif\n"
2307 "#      if USESHADOWMAPPCF > 1\n"
2308 "    float2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
2309 "    center *= ShadowMap_TextureScale;\n"
2310 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2311 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2312 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2313 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2314 "    float4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
2315 "    f = dot(mix(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2316 "#      else\n"
2317 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
2318 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2319 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2320 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2321 "    float3 cols = row2 + mix(row1, row3, offset.y);\n"
2322 "    f = dot(mix(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2323 "#      endif\n"
2324 "#     endif\n"
2325 "#    else\n"
2326 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2327 "#    endif\n"
2328 "#  endif\n"
2329 "    return f;\n"
2330 "}\n"
2331 "# endif\n"
2332 "\n"
2333 "# ifdef USESHADOWMAPCUBE\n"
2334 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2335 "{\n"
2336 "    // apply depth texture cubemap as light filter\n"
2337 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2338 "    float f;\n"
2339 "#  ifdef USESHADOWSAMPLER\n"
2340 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2341 "#  else\n"
2342 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2343 "#  endif\n"
2344 "    return f;\n"
2345 "}\n"
2346 "# endif\n"
2347 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2348 "#endif // FRAGMENT_SHADER\n"
2349 "\n"
2350 "\n"
2351 "\n"
2352 "\n"
2353 "#ifdef MODE_DEFERREDGEOMETRY\n"
2354 "#ifdef VERTEX_SHADER\n"
2355 "void main\n"
2356 "(\n"
2357 "float4 gl_Vertex : POSITION,\n"
2358 "uniform float4x4 ModelViewProjectionMatrix,\n"
2359 "#ifdef USEVERTEXTEXTUREBLEND\n"
2360 "float4 gl_Color : COLOR0,\n"
2361 "#endif\n"
2362 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2363 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2364 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2365 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2366 "uniform mat4 TexMatrix,\n"
2367 "#ifdef USEVERTEXTEXTUREBLEND\n"
2368 "uniform mat4 BackgroundTexMatrix,\n"
2369 "#endif\n"
2370 "uniform mat4 ModelViewMatrix,\n"
2371 "out float4 gl_Position : POSITION,\n"
2372 "out float4 gl_FrontColor : COLOR,\n"
2373 "out float4 TexCoordBoth : TEXCOORD0,\n"
2374 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2375 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2376 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2377 ")\n"
2378 "{\n"
2379 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2380 "#ifdef USEVERTEXTEXTUREBLEND\n"
2381 "       gl_FrontColor = gl_Color;\n"
2382 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2383 "#endif\n"
2384 "\n"
2385 "       // transform unnormalized eye direction into tangent space\n"
2386 "#ifdef USEOFFSETMAPPING\n"
2387 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2388 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2389 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2390 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2391 "#endif\n"
2392 "\n"
2393 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2394 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2395 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2396 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2397 "}\n"
2398 "#endif // VERTEX_SHADER\n"
2399 "\n"
2400 "#ifdef FRAGMENT_SHADER\n"
2401 "void main\n"
2402 "(\n"
2403 "float4 TexCoordBoth : TEXCOORD0,\n"
2404 "float3 EyeVector : TEXCOORD2,\n"
2405 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2406 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2407 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2408 "uniform sampler2D Texture_Normal,\n"
2409 "#ifdef USEALPHAKILL\n"
2410 "uniform sampler2D Texture_Color,\n"
2411 "#endif\n"
2412 "#ifdef USEVERTEXTEXTUREBLEND\n"
2413 "uniform sampler2D Texture_SecondaryNormal,\n"
2414 "#endif\n"
2415 "#ifdef USEOFFSETMAPPING\n"
2416 "uniform float OffsetMapping_Scale,\n"
2417 "#endif\n"
2418 "uniform half SpecularPower,\n"
2419 "out float4 gl_FragColor : COLOR\n"
2420 ")\n"
2421 "{\n"
2422 "       float2 TexCoord = TexCoordBoth.xy;\n"
2423 "#ifdef USEOFFSETMAPPING\n"
2424 "       // apply offsetmapping\n"
2425 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2426 "#define TexCoord TexCoordOffset\n"
2427 "#endif\n"
2428 "\n"
2429 "#ifdef USEALPHAKILL\n"
2430 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2431 "               discard;\n"
2432 "#endif\n"
2433 "\n"
2434 "#ifdef USEVERTEXTEXTUREBLEND\n"
2435 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2436 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2437 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2438 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2439 "#endif\n"
2440 "\n"
2441 "#ifdef USEVERTEXTEXTUREBLEND\n"
2442 "       float3 surfacenormal = mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2443 "#else\n"
2444 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2445 "#endif\n"
2446 "\n"
2447 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2448 "}\n"
2449 "#endif // FRAGMENT_SHADER\n"
2450 "#else // !MODE_DEFERREDGEOMETRY\n"
2451 "\n"
2452 "\n"
2453 "\n"
2454 "\n"
2455 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2456 "#ifdef VERTEX_SHADER\n"
2457 "void main\n"
2458 "(\n"
2459 "float4 gl_Vertex : POSITION,\n"
2460 "uniform float4x4 ModelViewProjectionMatrix,\n"
2461 "uniform mat4 ModelViewMatrix,\n"
2462 "out float4 gl_Position : POSITION,\n"
2463 "out float4 ModelViewPosition : TEXCOORD0\n"
2464 ")\n"
2465 "{\n"
2466 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2467 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2468 "}\n"
2469 "#endif // VERTEX_SHADER\n"
2470 "\n"
2471 "#ifdef FRAGMENT_SHADER\n"
2472 "void main\n"
2473 "(\n"
2474 "float2 Pixel : WPOS,\n"
2475 "float4 ModelViewPosition : TEXCOORD0,\n"
2476 "uniform mat4 ViewToLight,\n"
2477 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2478 "uniform float3 LightPosition,\n"
2479 "uniform half3 DeferredColor_Ambient,\n"
2480 "uniform half3 DeferredColor_Diffuse,\n"
2481 "#ifdef USESPECULAR\n"
2482 "uniform half3 DeferredColor_Specular,\n"
2483 "uniform half SpecularPower,\n"
2484 "#endif\n"
2485 "uniform sampler2D Texture_Attenuation,\n"
2486 "uniform samplerRECT Texture_ScreenDepth,\n"
2487 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2488 "\n"
2489 "#ifdef USESHADOWMAPRECT\n"
2490 "# ifdef USESHADOWSAMPLER\n"
2491 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2492 "# else\n"
2493 "uniform samplerRECT Texture_ShadowMapRect,\n"
2494 "# endif\n"
2495 "#endif\n"
2496 "\n"
2497 "#ifdef USESHADOWMAP2D\n"
2498 "# ifdef USESHADOWSAMPLER\n"
2499 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2500 "# else\n"
2501 "uniform sampler2D Texture_ShadowMap2D,\n"
2502 "# endif\n"
2503 "#endif\n"
2504 "\n"
2505 "#ifdef USESHADOWMAPVSDCT\n"
2506 "uniform samplerCUBE Texture_CubeProjection,\n"
2507 "#endif\n"
2508 "\n"
2509 "#ifdef USESHADOWMAPCUBE\n"
2510 "# ifdef USESHADOWSAMPLER\n"
2511 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2512 "# else\n"
2513 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2514 "# endif\n"
2515 "#endif\n"
2516 "\n"
2517 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2518 "uniform float2 ShadowMap_TextureScale,\n"
2519 "uniform float4 ShadowMap_Parameters,\n"
2520 "#endif\n"
2521 "\n"
2522 "out float4 gl_FragData0 : COLOR0,\n"
2523 "out float4 gl_FragData1 : COLOR1\n"
2524 ")\n"
2525 "{\n"
2526 "       // calculate viewspace pixel position\n"
2527 "       float3 position;\n"
2528 "       position.z = ScreenToDepth.y / (texRECT(Texture_ScreenDepth, Pixel).r + ScreenToDepth.x);\n"
2529 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2530 "       // decode viewspace pixel normal\n"
2531 "       half4 normalmap = texRECT(Texture_ScreenNormalMap, Pixel);\n"
2532 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2533 "       // surfacenormal = pixel normal in viewspace\n"
2534 "       // LightVector = pixel to light in viewspace\n"
2535 "       // CubeVector = position in lightspace\n"
2536 "       // eyevector = pixel to view in viewspace\n"
2537 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2538 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2539 "#ifdef USEDIFFUSE\n"
2540 "       // calculate diffuse shading\n"
2541 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2542 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2543 "#endif\n"
2544 "#ifdef USESPECULAR\n"
2545 "       // calculate directional shading\n"
2546 "       float3 eyevector = position * -1.0;\n"
2547 "#  ifdef USEEXACTSPECULARMATH\n"
2548 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2549 "#  else\n"
2550 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2551 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2552 "#  endif\n"
2553 "#endif\n"
2554 "\n"
2555 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2556 "       fade *= ShadowMapCompare(CubeVector,\n"
2557 "# if defined(USESHADOWMAP2D)\n"
2558 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2559 "# endif\n"
2560 "# if defined(USESHADOWMAPRECT)\n"
2561 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2562 "# endif\n"
2563 "# if defined(USESHADOWMAPCUBE)\n"
2564 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2565 "# endif\n"
2566 "\n"
2567 "#ifdef USESHADOWMAPVSDCT\n"
2568 ", Texture_CubeProjection\n"
2569 "#endif\n"
2570 "       );\n"
2571 "#endif\n"
2572 "\n"
2573 "#ifdef USEDIFFUSE\n"
2574 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2575 "#else\n"
2576 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2577 "#endif\n"
2578 "#ifdef USESPECULAR\n"
2579 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2580 "#else\n"
2581 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2582 "#endif\n"
2583 "\n"
2584 "# ifdef USECUBEFILTER\n"
2585 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2586 "       gl_FragData0 *= cubecolor;\n"
2587 "       gl_FragData1 *= cubecolor;\n"
2588 "# endif\n"
2589 "}\n"
2590 "#endif // FRAGMENT_SHADER\n"
2591 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2592 "\n"
2593 "\n"
2594 "\n"
2595 "\n"
2596 "#ifdef VERTEX_SHADER\n"
2597 "void main\n"
2598 "(\n"
2599 "float4 gl_Vertex : POSITION,\n"
2600 "uniform float4x4 ModelViewProjectionMatrix,\n"
2601 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2602 "float4 gl_Color : COLOR0,\n"
2603 "#endif\n"
2604 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2605 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2606 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2607 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2608 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2609 "\n"
2610 "uniform float3 EyePosition,\n"
2611 "uniform mat4 TexMatrix,\n"
2612 "#ifdef USEVERTEXTEXTUREBLEND\n"
2613 "uniform mat4 BackgroundTexMatrix,\n"
2614 "#endif\n"
2615 "#ifdef MODE_LIGHTSOURCE\n"
2616 "uniform mat4 ModelToLight,\n"
2617 "#endif\n"
2618 "#ifdef MODE_LIGHTSOURCE\n"
2619 "uniform float3 LightPosition,\n"
2620 "#endif\n"
2621 "#ifdef MODE_LIGHTDIRECTION\n"
2622 "uniform float3 LightDir,\n"
2623 "#endif\n"
2624 "uniform float4 FogPlane,\n"
2625 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2626 "uniform float3 LightPosition,\n"
2627 "#endif\n"
2628 "\n"
2629 "out float4 gl_FrontColor : COLOR,\n"
2630 "out float4 TexCoordBoth : TEXCOORD0,\n"
2631 "#ifdef USELIGHTMAP\n"
2632 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2633 "#endif\n"
2634 "#ifdef USEEYEVECTOR\n"
2635 "out float3 EyeVector : TEXCOORD2,\n"
2636 "#endif\n"
2637 "#ifdef USEREFLECTION\n"
2638 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2639 "#endif\n"
2640 "#ifdef USEFOG\n"
2641 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2642 "#endif\n"
2643 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2644 "out float3 LightVector : TEXCOORD5,\n"
2645 "#endif\n"
2646 "#ifdef MODE_LIGHTSOURCE\n"
2647 "out float3 CubeVector : TEXCOORD3,\n"
2648 "#endif\n"
2649 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2650 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2651 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2652 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2653 "#endif\n"
2654 "out float4 gl_Position : POSITION\n"
2655 ")\n"
2656 "{\n"
2657 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2658 "       gl_FrontColor = gl_Color;\n"
2659 "#endif\n"
2660 "       // copy the surface texcoord\n"
2661 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2662 "#ifdef USEVERTEXTEXTUREBLEND\n"
2663 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2664 "#endif\n"
2665 "#ifdef USELIGHTMAP\n"
2666 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2667 "#endif\n"
2668 "\n"
2669 "#ifdef MODE_LIGHTSOURCE\n"
2670 "       // transform vertex position into light attenuation/cubemap space\n"
2671 "       // (-1 to +1 across the light box)\n"
2672 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2673 "\n"
2674 "# ifdef USEDIFFUSE\n"
2675 "       // transform unnormalized light direction into tangent space\n"
2676 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2677 "       //  normalize it per pixel)\n"
2678 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2679 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2680 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2681 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2682 "# endif\n"
2683 "#endif\n"
2684 "\n"
2685 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2686 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2687 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2688 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2689 "#endif\n"
2690 "\n"
2691 "       // transform unnormalized eye direction into tangent space\n"
2692 "#ifdef USEEYEVECTOR\n"
2693 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2694 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2695 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2696 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2697 "#endif\n"
2698 "\n"
2699 "#ifdef USEFOG\n"
2700 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2701 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2705 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2706 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2707 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2708 "#endif\n"
2709 "\n"
2710 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2711 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2712 "\n"
2713 "#ifdef USEREFLECTION\n"
2714 "       ModelViewProjectionPosition = gl_Position;\n"
2715 "#endif\n"
2716 "}\n"
2717 "#endif // VERTEX_SHADER\n"
2718 "\n"
2719 "\n"
2720 "\n"
2721 "\n"
2722 "#ifdef FRAGMENT_SHADER\n"
2723 "void main\n"
2724 "(\n"
2725 "#ifdef USEDEFERREDLIGHTMAP\n"
2726 "float2 Pixel : WPOS,\n"
2727 "#endif\n"
2728 "float4 gl_FrontColor : COLOR,\n"
2729 "float4 TexCoordBoth : TEXCOORD0,\n"
2730 "#ifdef USELIGHTMAP\n"
2731 "float2 TexCoordLightmap : TEXCOORD1,\n"
2732 "#endif\n"
2733 "#ifdef USEEYEVECTOR\n"
2734 "float3 EyeVector : TEXCOORD2,\n"
2735 "#endif\n"
2736 "#ifdef USEREFLECTION\n"
2737 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2738 "#endif\n"
2739 "#ifdef USEFOG\n"
2740 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2741 "#endif\n"
2742 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2743 "float3 LightVector : TEXCOORD5,\n"
2744 "#endif\n"
2745 "#ifdef MODE_LIGHTSOURCE\n"
2746 "float3 CubeVector : TEXCOORD3,\n"
2747 "#endif\n"
2748 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2749 "float4 ModelViewPosition : TEXCOORD0,\n"
2750 "#endif\n"
2751 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2752 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2753 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2754 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2755 "#endif\n"
2756 "\n"
2757 "uniform sampler2D Texture_Normal,\n"
2758 "uniform sampler2D Texture_Color,\n"
2759 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2760 "uniform sampler2D Texture_Gloss,\n"
2761 "#endif\n"
2762 "#ifdef USEGLOW\n"
2763 "uniform sampler2D Texture_Glow,\n"
2764 "#endif\n"
2765 "#ifdef USEVERTEXTEXTUREBLEND\n"
2766 "uniform sampler2D Texture_SecondaryNormal,\n"
2767 "uniform sampler2D Texture_SecondaryColor,\n"
2768 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2769 "uniform sampler2D Texture_SecondaryGloss,\n"
2770 "#endif\n"
2771 "#ifdef USEGLOW\n"
2772 "uniform sampler2D Texture_SecondaryGlow,\n"
2773 "#endif\n"
2774 "#endif\n"
2775 "#ifdef USECOLORMAPPING\n"
2776 "uniform sampler2D Texture_Pants,\n"
2777 "uniform sampler2D Texture_Shirt,\n"
2778 "#endif\n"
2779 "#ifdef USEFOG\n"
2780 "uniform sampler2D Texture_FogMask,\n"
2781 "#endif\n"
2782 "#ifdef USELIGHTMAP\n"
2783 "uniform sampler2D Texture_Lightmap,\n"
2784 "#endif\n"
2785 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2786 "uniform sampler2D Texture_Deluxemap,\n"
2787 "#endif\n"
2788 "#ifdef USEREFLECTION\n"
2789 "uniform sampler2D Texture_Reflection,\n"
2790 "#endif\n"
2791 "\n"
2792 "//#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2793 "uniform samplerRECT Texture_ScreenDepth,\n"
2794 "uniform samplerRECT Texture_ScreenNormalMap,\n"
2795 "//#endif\n"
2796 "#ifdef USEDEFERREDLIGHTMAP\n"
2797 "uniform samplerRECT Texture_ScreenDiffuse,\n"
2798 "uniform samplerRECT Texture_ScreenSpecular,\n"
2799 "#endif\n"
2800 "\n"
2801 "#ifdef USECOLORMAPPING\n"
2802 "uniform half3 Color_Pants,\n"
2803 "uniform half3 Color_Shirt,\n"
2804 "#endif\n"
2805 "#ifdef USEFOG\n"
2806 "uniform float3 FogColor,\n"
2807 "uniform float FogRangeRecip,\n"
2808 "uniform float FogPlaneViewDist,\n"
2809 "uniform float FogHeightFade,\n"
2810 "#endif\n"
2811 "\n"
2812 "#ifdef USEOFFSETMAPPING\n"
2813 "uniform float OffsetMapping_Scale,\n"
2814 "#endif\n"
2815 "\n"
2816 "#ifdef USEDEFERREDLIGHTMAP\n"
2817 "uniform half3 DeferredMod_Diffuse,\n"
2818 "uniform half3 DeferredMod_Specular,\n"
2819 "#endif\n"
2820 "uniform half3 Color_Ambient,\n"
2821 "uniform half3 Color_Diffuse,\n"
2822 "uniform half3 Color_Specular,\n"
2823 "uniform half SpecularPower,\n"
2824 "#ifdef USEGLOW\n"
2825 "uniform half3 Color_Glow,\n"
2826 "#endif\n"
2827 "uniform half Alpha,\n"
2828 "#ifdef USEREFLECTION\n"
2829 "uniform float4 DistortScaleRefractReflect,\n"
2830 "uniform float4 ScreenScaleRefractReflect,\n"
2831 "uniform float4 ScreenCenterRefractReflect,\n"
2832 "uniform half4 ReflectColor,\n"
2833 "#endif\n"
2834 "#ifdef MODE_LIGHTDIRECTION\n"
2835 "uniform half3 LightColor,\n"
2836 "#endif\n"
2837 "#ifdef MODE_LIGHTSOURCE\n"
2838 "uniform half3 LightColor,\n"
2839 "#endif\n"
2840 "\n"
2841 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2842 "uniform sampler2D Texture_Attenuation,\n"
2843 "uniform samplerCUBE Texture_Cube,\n"
2844 "\n"
2845 "#ifdef USESHADOWMAPRECT\n"
2846 "# ifdef USESHADOWSAMPLER\n"
2847 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2848 "# else\n"
2849 "uniform samplerRECT Texture_ShadowMapRect,\n"
2850 "# endif\n"
2851 "#endif\n"
2852 "\n"
2853 "#ifdef USESHADOWMAP2D\n"
2854 "# ifdef USESHADOWSAMPLER\n"
2855 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2856 "# else\n"
2857 "uniform sampler2D Texture_ShadowMap2D,\n"
2858 "# endif\n"
2859 "#endif\n"
2860 "\n"
2861 "#ifdef USESHADOWMAPVSDCT\n"
2862 "uniform samplerCUBE Texture_CubeProjection,\n"
2863 "#endif\n"
2864 "\n"
2865 "#ifdef USESHADOWMAPCUBE\n"
2866 "# ifdef USESHADOWSAMPLER\n"
2867 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2868 "# else\n"
2869 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2870 "# endif\n"
2871 "#endif\n"
2872 "\n"
2873 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2874 "uniform float2 ShadowMap_TextureScale,\n"
2875 "uniform float4 ShadowMap_Parameters,\n"
2876 "#endif\n"
2877 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2878 "\n"
2879 "out float4 gl_FragColor : COLOR\n"
2880 ")\n"
2881 "{\n"
2882 "       float2 TexCoord = TexCoordBoth.xy;\n"
2883 "#ifdef USEVERTEXTEXTUREBLEND\n"
2884 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2885 "#endif\n"
2886 "#ifdef USEOFFSETMAPPING\n"
2887 "       // apply offsetmapping\n"
2888 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2889 "#define TexCoord TexCoordOffset\n"
2890 "#endif\n"
2891 "\n"
2892 "       // combine the diffuse textures (base, pants, shirt)\n"
2893 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2894 "#ifdef USEALPHAKILL\n"
2895 "       if (color.a < 0.5)\n"
2896 "               discard;\n"
2897 "#endif\n"
2898 "       color.a *= Alpha;\n"
2899 "#ifdef USECOLORMAPPING\n"
2900 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2901 "#endif\n"
2902 "#ifdef USEVERTEXTEXTUREBLEND\n"
2903 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2904 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2905 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2906 "       color.rgb = half3(mix(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2907 "       color.a = 1.0;\n"
2908 "       //color = mix(half4(1, 0, 0, 1), color, terrainblend);\n"
2909 "#endif\n"
2910 "\n"
2911 "       // get the surface normal\n"
2912 "#ifdef USEVERTEXTEXTUREBLEND\n"
2913 "       half3 surfacenormal = normalize(half3(mix(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2914 "#else\n"
2915 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2916 "#endif\n"
2917 "\n"
2918 "       // get the material colors\n"
2919 "       half3 diffusetex = color.rgb;\n"
2920 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2921 "# ifdef USEVERTEXTEXTUREBLEND\n"
2922 "       half3 glosstex = half3(mix(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2923 "# else\n"
2924 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2925 "# endif\n"
2926 "#endif\n"
2927 "\n"
2928 "\n"
2929 "\n"
2930 "\n"
2931 "#ifdef MODE_LIGHTSOURCE\n"
2932 "       // light source\n"
2933 "       half3 lightnormal = half3(normalize(LightVector));\n"
2934 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2935 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2936 "#ifdef USESPECULAR\n"
2937 "#ifdef USEEXACTSPECULARMATH\n"
2938 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2939 "#else\n"
2940 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2941 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2942 "#endif\n"
2943 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2944 "#endif\n"
2945 "       color.rgb *= LightColor;\n"
2946 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2947 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2948 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2949 "# if defined(USESHADOWMAP2D)\n"
2950 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2951 "# endif\n"
2952 "# if defined(USESHADOWMAPRECT)\n"
2953 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2954 "# endif\n"
2955 "# if defined(USESHADOWMAPCUBE)\n"
2956 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2957 "# endif\n"
2958 "\n"
2959 "#ifdef USESHADOWMAPVSDCT\n"
2960 ", Texture_CubeProjection\n"
2961 "#endif\n"
2962 "       );\n"
2963 "\n"
2964 "#endif\n"
2965 "# ifdef USECUBEFILTER\n"
2966 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2967 "# endif\n"
2968 "#endif // MODE_LIGHTSOURCE\n"
2969 "\n"
2970 "\n"
2971 "\n"
2972 "\n"
2973 "#ifdef MODE_LIGHTDIRECTION\n"
2974 "#define SHADING\n"
2975 "       half3 lightnormal = half3(normalize(LightVector));\n"
2976 "#define lightcolor LightColor\n"
2977 "#endif // MODE_LIGHTDIRECTION\n"
2978 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2979 "#define SHADING\n"
2980 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
2981 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
2982 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
2983 "       // convert modelspace light vector to tangentspace\n"
2984 "       half3 lightnormal;\n"
2985 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
2986 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
2987 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
2988 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
2989 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
2990 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
2991 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
2992 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
2993 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
2994 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
2995 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
2996 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
2997 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
2998 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2999 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3000 "#define SHADING\n"
3001 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3002 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3003 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3004 "#endif\n"
3005 "\n"
3006 "\n"
3007 "\n"
3008 "\n"
3009 "#ifdef MODE_LIGHTMAP\n"
3010 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3011 "#endif // MODE_LIGHTMAP\n"
3012 "#ifdef MODE_VERTEXCOLOR\n"
3013 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3014 "#endif // MODE_VERTEXCOLOR\n"
3015 "#ifdef MODE_FLATCOLOR\n"
3016 "       color.rgb = diffusetex * Color_Ambient;\n"
3017 "#endif // MODE_FLATCOLOR\n"
3018 "\n"
3019 "\n"
3020 "\n"
3021 "\n"
3022 "#ifdef SHADING\n"
3023 "# ifdef USEDIFFUSE\n"
3024 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3025 "#  ifdef USESPECULAR\n"
3026 "#   ifdef USEEXACTSPECULARMATH\n"
3027 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3028 "#   else\n"
3029 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3030 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3031 "#   endif\n"
3032 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3033 "#  else\n"
3034 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3035 "#  endif\n"
3036 "# else\n"
3037 "       color.rgb = diffusetex * Color_Ambient;\n"
3038 "# endif\n"
3039 "#endif\n"
3040 "\n"
3041 "#ifdef USEDEFERREDLIGHTMAP\n"
3042 "       color.rgb += diffusetex * half3(texRECT(Texture_ScreenDiffuse, Pixel)) * DeferredMod_Diffuse;\n"
3043 "       color.rgb += glosstex * half3(texRECT(Texture_ScreenSpecular, Pixel)) * DeferredMod_Specular;\n"
3044 "       color.rgb = half3(texRECT(Texture_ScreenDepth, Pixel));\n"
3045 "#endif\n"
3046 "\n"
3047 "#ifdef USEGLOW\n"
3048 "#ifdef USEVERTEXTEXTUREBLEND\n"
3049 "       color.rgb += mix(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3050 "#else\n"
3051 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3052 "#endif\n"
3053 "#endif\n"
3054 "\n"
3055 "#ifdef USEFOG\n"
3056 "#ifdef MODE_LIGHTSOURCE\n"
3057 "       color.rgb *= half(FogVertex());\n"
3058 "#else\n"
3059 "       color.rgb = mix(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3060 "#endif\n"
3061 "#endif\n"
3062 "\n"
3063 "       // 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"
3064 "#ifdef USEREFLECTION\n"
3065 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3066 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3067 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3068 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3069 "       // FIXME temporary hack to detect the case that the reflection\n"
3070 "       // gets blackened at edges due to leaving the area that contains actual\n"
3071 "       // content.\n"
3072 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3073 "       // 'appening.\n"
3074 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3075 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3076 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3077 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3078 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3079 "       color.rgb = mix(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3080 "#endif\n"
3081 "\n"
3082 "       gl_FragColor = float4(color);\n"
3083 "}\n"
3084 "#endif // FRAGMENT_SHADER\n"
3085 "\n"
3086 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3087 "#endif // !MODE_DEFERREDGEOMETRY\n"
3088 "#endif // !MODE_WATER\n"
3089 "#endif // !MODE_REFRACTION\n"
3090 "#endif // !MODE_BLOOMBLUR\n"
3091 "#endif // !MODE_GENERIC\n"
3092 "#endif // !MODE_POSTPROCESS\n"
3093 "#endif // !MODE_SHOWDEPTH\n"
3094 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3095 ;
3096
3097 //=======================================================================================================================================================
3098
3099 typedef struct shaderpermutationinfo_s
3100 {
3101         const char *pretext;
3102         const char *name;
3103 }
3104 shaderpermutationinfo_t;
3105
3106 typedef struct shadermodeinfo_s
3107 {
3108         const char *vertexfilename;
3109         const char *geometryfilename;
3110         const char *fragmentfilename;
3111         const char *pretext;
3112         const char *name;
3113 }
3114 shadermodeinfo_t;
3115
3116 typedef enum shaderpermutation_e
3117 {
3118         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3119         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3120         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3121         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3122         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3123         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3124         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3125         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3126         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3127         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3128         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3129         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3130         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3131         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3132         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3133         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3134         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3135         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3136         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3137         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3138         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3139         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3140         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3141         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3142         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3143         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3144         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3145         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3146 }
3147 shaderpermutation_t;
3148
3149 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3150 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3151 {
3152         {"#define USEDIFFUSE\n", " diffuse"},
3153         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3154         {"#define USEVIEWTINT\n", " viewtint"},
3155         {"#define USECOLORMAPPING\n", " colormapping"},
3156         {"#define USESATURATION\n", " saturation"},
3157         {"#define USEFOGINSIDE\n", " foginside"},
3158         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3159         {"#define USEGAMMARAMPS\n", " gammaramps"},
3160         {"#define USECUBEFILTER\n", " cubefilter"},
3161         {"#define USEGLOW\n", " glow"},
3162         {"#define USEBLOOM\n", " bloom"},
3163         {"#define USESPECULAR\n", " specular"},
3164         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3165         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3166         {"#define USEREFLECTION\n", " reflection"},
3167         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3168         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3169         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3170         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3171         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3172         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3173         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3174         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3175         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3176         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3177         {"#define USEALPHAKILL\n", " alphakill"},
3178 };
3179
3180 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3181 typedef enum shadermode_e
3182 {
3183         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3184         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3185         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3186         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3187         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3188         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3189         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3190         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3191         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3192         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3193         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3194         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3195         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3196         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3197         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3198         SHADERMODE_COUNT
3199 }
3200 shadermode_t;
3201
3202 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3203 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3204 {
3205         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3206         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3207         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3208         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3209         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3210         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3211         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3212         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3213         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3214         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3215         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3216         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3217         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3218         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3219         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3220 };
3221
3222 #ifdef SUPPORTCG
3223 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3224 {
3225         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3226         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3227         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3228         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3229         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3230         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3231         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3232         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3233         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3234         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3235         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3236         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3237         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3238         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3239         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3240 };
3241 #endif
3242
3243 struct r_glsl_permutation_s;
3244 typedef struct r_glsl_permutation_s
3245 {
3246         /// hash lookup data
3247         struct r_glsl_permutation_s *hashnext;
3248         unsigned int mode;
3249         unsigned int permutation;
3250
3251         /// indicates if we have tried compiling this permutation already
3252         qboolean compiled;
3253         /// 0 if compilation failed
3254         int program;
3255         /// locations of detected uniforms in program object, or -1 if not found
3256         int loc_Texture_First;
3257         int loc_Texture_Second;
3258         int loc_Texture_GammaRamps;
3259         int loc_Texture_Normal;
3260         int loc_Texture_Color;
3261         int loc_Texture_Gloss;
3262         int loc_Texture_Glow;
3263         int loc_Texture_SecondaryNormal;
3264         int loc_Texture_SecondaryColor;
3265         int loc_Texture_SecondaryGloss;
3266         int loc_Texture_SecondaryGlow;
3267         int loc_Texture_Pants;
3268         int loc_Texture_Shirt;
3269         int loc_Texture_FogMask;
3270         int loc_Texture_Lightmap;
3271         int loc_Texture_Deluxemap;
3272         int loc_Texture_Attenuation;
3273         int loc_Texture_Cube;
3274         int loc_Texture_Refraction;
3275         int loc_Texture_Reflection;
3276         int loc_Texture_ShadowMapRect;
3277         int loc_Texture_ShadowMapCube;
3278         int loc_Texture_ShadowMap2D;
3279         int loc_Texture_CubeProjection;
3280         int loc_Texture_ScreenDepth;
3281         int loc_Texture_ScreenNormalMap;
3282         int loc_Texture_ScreenDiffuse;
3283         int loc_Texture_ScreenSpecular;
3284         int loc_Alpha;
3285         int loc_BloomBlur_Parameters;
3286         int loc_ClientTime;
3287         int loc_Color_Ambient;
3288         int loc_Color_Diffuse;
3289         int loc_Color_Specular;
3290         int loc_Color_Glow;
3291         int loc_Color_Pants;
3292         int loc_Color_Shirt;
3293         int loc_DeferredColor_Ambient;
3294         int loc_DeferredColor_Diffuse;
3295         int loc_DeferredColor_Specular;
3296         int loc_DeferredMod_Diffuse;
3297         int loc_DeferredMod_Specular;
3298         int loc_DistortScaleRefractReflect;
3299         int loc_EyePosition;
3300         int loc_FogColor;
3301         int loc_FogHeightFade;
3302         int loc_FogPlane;
3303         int loc_FogPlaneViewDist;
3304         int loc_FogRangeRecip;
3305         int loc_LightColor;
3306         int loc_LightDir;
3307         int loc_LightPosition;
3308         int loc_OffsetMapping_Scale;
3309         int loc_PixelSize;
3310         int loc_ReflectColor;
3311         int loc_ReflectFactor;
3312         int loc_ReflectOffset;
3313         int loc_RefractColor;
3314         int loc_Saturation;
3315         int loc_ScreenCenterRefractReflect;
3316         int loc_ScreenScaleRefractReflect;
3317         int loc_ScreenToDepth;
3318         int loc_ShadowMap_Parameters;
3319         int loc_ShadowMap_TextureScale;
3320         int loc_SpecularPower;
3321         int loc_UserVec1;
3322         int loc_UserVec2;
3323         int loc_UserVec3;
3324         int loc_UserVec4;
3325         int loc_ViewTintColor;
3326         int loc_ViewToLight;
3327         int loc_ModelToLight;
3328         int loc_TexMatrix;
3329         int loc_BackgroundTexMatrix;
3330         int loc_ModelViewProjectionMatrix;
3331         int loc_ModelViewMatrix;
3332 }
3333 r_glsl_permutation_t;
3334
3335 #define SHADERPERMUTATION_HASHSIZE 256
3336
3337 /// information about each possible shader permutation
3338 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3339 /// currently selected permutation
3340 r_glsl_permutation_t *r_glsl_permutation;
3341 /// storage for permutations linked in the hash table
3342 memexpandablearray_t r_glsl_permutationarray;
3343
3344 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3345 {
3346         //unsigned int hashdepth = 0;
3347         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3348         r_glsl_permutation_t *p;
3349         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3350         {
3351                 if (p->mode == mode && p->permutation == permutation)
3352                 {
3353                         //if (hashdepth > 10)
3354                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3355                         return p;
3356                 }
3357                 //hashdepth++;
3358         }
3359         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3360         p->mode = mode;
3361         p->permutation = permutation;
3362         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3363         r_glsl_permutationhash[mode][hashindex] = p;
3364         //if (hashdepth > 10)
3365         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3366         return p;
3367 }
3368
3369 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3370 {
3371         char *shaderstring;
3372         if (!filename || !filename[0])
3373                 return NULL;
3374         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3375         if (shaderstring)
3376         {
3377                 if (printfromdisknotice)
3378                         Con_DPrintf("from disk %s... ", filename);
3379                 return shaderstring;
3380         }
3381         else if (!strcmp(filename, "glsl/default.glsl"))
3382         {
3383                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3384                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3385         }
3386         return shaderstring;
3387 }
3388
3389 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3390 {
3391         int i;
3392         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3393         int vertstrings_count = 0;
3394         int geomstrings_count = 0;
3395         int fragstrings_count = 0;
3396         char *vertexstring, *geometrystring, *fragmentstring;
3397         const char *vertstrings_list[32+3];
3398         const char *geomstrings_list[32+3];
3399         const char *fragstrings_list[32+3];
3400         char permutationname[256];
3401
3402         if (p->compiled)
3403                 return;
3404         p->compiled = true;
3405         p->program = 0;
3406
3407         permutationname[0] = 0;
3408         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3409         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3410         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3411
3412         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3413
3414         // the first pretext is which type of shader to compile as
3415         // (later these will all be bound together as a program object)
3416         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3417         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3418         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3419
3420         // the second pretext is the mode (for example a light source)
3421         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3422         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3423         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3424         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3425
3426         // now add all the permutation pretexts
3427         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3428         {
3429                 if (permutation & (1<<i))
3430                 {
3431                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3432                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3433                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3434                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3435                 }
3436                 else
3437                 {
3438                         // keep line numbers correct
3439                         vertstrings_list[vertstrings_count++] = "\n";
3440                         geomstrings_list[geomstrings_count++] = "\n";
3441                         fragstrings_list[fragstrings_count++] = "\n";
3442                 }
3443         }
3444
3445         // now append the shader text itself
3446         vertstrings_list[vertstrings_count++] = vertexstring;
3447         geomstrings_list[geomstrings_count++] = geometrystring;
3448         fragstrings_list[fragstrings_count++] = fragmentstring;
3449
3450         // if any sources were NULL, clear the respective list
3451         if (!vertexstring)
3452                 vertstrings_count = 0;
3453         if (!geometrystring)
3454                 geomstrings_count = 0;
3455         if (!fragmentstring)
3456                 fragstrings_count = 0;
3457
3458         // compile the shader program
3459         if (vertstrings_count + geomstrings_count + fragstrings_count)
3460                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3461         if (p->program)
3462         {
3463                 CHECKGLERROR
3464                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3465                 // look up all the uniform variable names we care about, so we don't
3466                 // have to look them up every time we set them
3467
3468                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3469                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3470                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3471                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3472                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3473                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3474                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3475                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3476                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3477                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3478                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3479                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3480                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3481                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3482                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3483                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3484                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3485                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3486                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3487                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3488                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3489                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3490                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3491                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3492                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3493                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3494                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3495                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3496                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3497                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3498                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3499                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3500                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3501                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3502                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3503                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3504                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3505                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3506                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3507                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3508                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3509                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3510                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3511                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3512                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3513                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3514                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3515                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3516                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3517                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3518                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3519                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3520                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3521                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3522                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3523                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3524                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3525                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3526                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3527                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3528                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3529                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3530                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3531                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3532                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3533                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3534                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3535                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3536                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3537                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3538                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3539                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3540                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3541                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3542                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3543                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3544                 // initialize the samplers to refer to the texture units we use
3545                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3546                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3547                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3548                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3549                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3550                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3551                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3552                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3553                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3554                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3555                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3556                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3557                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3558                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3559                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3560                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3561                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3562                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3563                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3564                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3565                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3566                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3567                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3568                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3569                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3570                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3571                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3572                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3573                 CHECKGLERROR
3574                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3575         }
3576         else
3577                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3578
3579         // free the strings
3580         if (vertexstring)
3581                 Mem_Free(vertexstring);
3582         if (geometrystring)
3583                 Mem_Free(geometrystring);
3584         if (fragmentstring)
3585                 Mem_Free(fragmentstring);
3586 }
3587
3588 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3589 {
3590         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3591         if (r_glsl_permutation != perm)
3592         {
3593                 r_glsl_permutation = perm;
3594                 if (!r_glsl_permutation->program)
3595                 {
3596                         if (!r_glsl_permutation->compiled)
3597                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3598                         if (!r_glsl_permutation->program)
3599                         {
3600                                 // remove features until we find a valid permutation
3601                                 int i;
3602                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3603                                 {
3604                                         // reduce i more quickly whenever it would not remove any bits
3605                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3606                                         if (!(permutation & j))
3607                                                 continue;
3608                                         permutation -= j;
3609                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3610                                         if (!r_glsl_permutation->compiled)
3611                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3612                                         if (r_glsl_permutation->program)
3613                                                 break;
3614                                 }
3615                                 if (i >= SHADERPERMUTATION_COUNT)
3616                                 {
3617                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3618                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3619                                         qglUseProgramObjectARB(0);CHECKGLERROR
3620                                         return; // no bit left to clear, entire mode is broken
3621                                 }
3622                         }
3623                 }
3624                 CHECKGLERROR
3625                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3626         }
3627         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3628 }
3629
3630 #ifdef SUPPORTCG
3631 #include <Cg/cgGL.h>
3632 struct r_cg_permutation_s;
3633 typedef struct r_cg_permutation_s
3634 {
3635         /// hash lookup data
3636         struct r_cg_permutation_s *hashnext;
3637         unsigned int mode;
3638         unsigned int permutation;
3639
3640         /// indicates if we have tried compiling this permutation already
3641         qboolean compiled;
3642         /// 0 if compilation failed
3643         CGprogram vprogram;
3644         CGprogram fprogram;
3645         /// locations of detected parameters in programs, or NULL if not found
3646         CGparameter vp_EyePosition;
3647         CGparameter vp_FogPlane;
3648         CGparameter vp_LightDir;
3649         CGparameter vp_LightPosition;
3650         CGparameter vp_ModelToLight;
3651         CGparameter vp_TexMatrix;
3652         CGparameter vp_BackgroundTexMatrix;
3653         CGparameter vp_ModelViewProjectionMatrix;
3654         CGparameter vp_ModelViewMatrix;
3655
3656         CGparameter fp_Texture_First;
3657         CGparameter fp_Texture_Second;
3658         CGparameter fp_Texture_GammaRamps;
3659         CGparameter fp_Texture_Normal;
3660         CGparameter fp_Texture_Color;
3661         CGparameter fp_Texture_Gloss;
3662         CGparameter fp_Texture_Glow;
3663         CGparameter fp_Texture_SecondaryNormal;
3664         CGparameter fp_Texture_SecondaryColor;
3665         CGparameter fp_Texture_SecondaryGloss;
3666         CGparameter fp_Texture_SecondaryGlow;
3667         CGparameter fp_Texture_Pants;
3668         CGparameter fp_Texture_Shirt;
3669         CGparameter fp_Texture_FogMask;
3670         CGparameter fp_Texture_Lightmap;
3671         CGparameter fp_Texture_Deluxemap;
3672         CGparameter fp_Texture_Attenuation;
3673         CGparameter fp_Texture_Cube;
3674         CGparameter fp_Texture_Refraction;
3675         CGparameter fp_Texture_Reflection;
3676         CGparameter fp_Texture_ShadowMapRect;
3677         CGparameter fp_Texture_ShadowMapCube;
3678         CGparameter fp_Texture_ShadowMap2D;
3679         CGparameter fp_Texture_CubeProjection;
3680         CGparameter fp_Texture_ScreenDepth;
3681         CGparameter fp_Texture_ScreenNormalMap;
3682         CGparameter fp_Texture_ScreenDiffuse;
3683         CGparameter fp_Texture_ScreenSpecular;
3684         CGparameter fp_Alpha;
3685         CGparameter fp_BloomBlur_Parameters;
3686         CGparameter fp_ClientTime;
3687         CGparameter fp_Color_Ambient;
3688         CGparameter fp_Color_Diffuse;
3689         CGparameter fp_Color_Specular;
3690         CGparameter fp_Color_Glow;
3691         CGparameter fp_Color_Pants;
3692         CGparameter fp_Color_Shirt;
3693         CGparameter fp_DeferredColor_Ambient;
3694         CGparameter fp_DeferredColor_Diffuse;
3695         CGparameter fp_DeferredColor_Specular;
3696         CGparameter fp_DeferredMod_Diffuse;
3697         CGparameter fp_DeferredMod_Specular;
3698         CGparameter fp_DistortScaleRefractReflect;
3699         CGparameter fp_EyePosition;
3700         CGparameter fp_FogColor;
3701         CGparameter fp_FogHeightFade;
3702         CGparameter fp_FogPlane;
3703         CGparameter fp_FogPlaneViewDist;
3704         CGparameter fp_FogRangeRecip;
3705         CGparameter fp_LightColor;
3706         CGparameter fp_LightDir;
3707         CGparameter fp_LightPosition;
3708         CGparameter fp_OffsetMapping_Scale;
3709         CGparameter fp_PixelSize;
3710         CGparameter fp_ReflectColor;
3711         CGparameter fp_ReflectFactor;
3712         CGparameter fp_ReflectOffset;
3713         CGparameter fp_RefractColor;
3714         CGparameter fp_Saturation;
3715         CGparameter fp_ScreenCenterRefractReflect;
3716         CGparameter fp_ScreenScaleRefractReflect;
3717         CGparameter fp_ScreenToDepth;
3718         CGparameter fp_ShadowMap_Parameters;
3719         CGparameter fp_ShadowMap_TextureScale;
3720         CGparameter fp_SpecularPower;
3721         CGparameter fp_UserVec1;
3722         CGparameter fp_UserVec2;
3723         CGparameter fp_UserVec3;
3724         CGparameter fp_UserVec4;
3725         CGparameter fp_ViewTintColor;
3726         CGparameter fp_ViewToLight;
3727 }
3728 r_cg_permutation_t;
3729
3730 /// information about each possible shader permutation
3731 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3732 /// currently selected permutation
3733 r_cg_permutation_t *r_cg_permutation;
3734 /// storage for permutations linked in the hash table
3735 memexpandablearray_t r_cg_permutationarray;
3736
3737 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3738
3739 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3740 {
3741         //unsigned int hashdepth = 0;
3742         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3743         r_cg_permutation_t *p;
3744         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3745         {
3746                 if (p->mode == mode && p->permutation == permutation)
3747                 {
3748                         //if (hashdepth > 10)
3749                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3750                         return p;
3751                 }
3752                 //hashdepth++;
3753         }
3754         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3755         p->mode = mode;
3756         p->permutation = permutation;
3757         p->hashnext = r_cg_permutationhash[mode][hashindex];
3758         r_cg_permutationhash[mode][hashindex] = p;
3759         //if (hashdepth > 10)
3760         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3761         return p;
3762 }
3763
3764 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3765 {
3766         char *shaderstring;
3767         if (!filename || !filename[0])
3768                 return NULL;
3769         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3770         if (shaderstring)
3771         {
3772                 if (printfromdisknotice)
3773                         Con_DPrintf("from disk %s... ", filename);
3774                 return shaderstring;
3775         }
3776         else if (!strcmp(filename, "cg/default.cg"))
3777         {
3778                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3779                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3780         }
3781         return shaderstring;
3782 }
3783
3784 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3785 {
3786         int i;
3787         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3788         int vertstrings_count = 0, vertstring_length = 0;
3789         int geomstrings_count = 0, geomstring_length = 0;
3790         int fragstrings_count = 0, fragstring_length = 0;
3791         char *t;
3792         char *vertexstring, *geometrystring, *fragmentstring;
3793         char *vertstring, *geomstring, *fragstring;
3794         const char *vertstrings_list[32+3];
3795         const char *geomstrings_list[32+3];
3796         const char *fragstrings_list[32+3];
3797         char permutationname[256];
3798         CGprofile vertexProfile;
3799         CGprofile fragmentProfile;
3800
3801         if (p->compiled)
3802                 return;
3803         p->compiled = true;
3804         p->vprogram = NULL;
3805         p->fprogram = NULL;
3806
3807         permutationname[0] = 0;
3808         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3809         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3810         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3811
3812         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3813
3814         // the first pretext is which type of shader to compile as
3815         // (later these will all be bound together as a program object)
3816         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3817         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3818         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3819
3820         // the second pretext is the mode (for example a light source)
3821         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3822         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3823         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3824         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3825
3826         // now add all the permutation pretexts
3827         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3828         {
3829                 if (permutation & (1<<i))
3830                 {
3831                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3832                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3833                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3834                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3835                 }
3836                 else
3837                 {
3838                         // keep line numbers correct
3839                         vertstrings_list[vertstrings_count++] = "\n";
3840                         geomstrings_list[geomstrings_count++] = "\n";
3841                         fragstrings_list[fragstrings_count++] = "\n";
3842                 }
3843         }
3844
3845         // now append the shader text itself
3846         vertstrings_list[vertstrings_count++] = vertexstring;
3847         geomstrings_list[geomstrings_count++] = geometrystring;
3848         fragstrings_list[fragstrings_count++] = fragmentstring;
3849
3850         // if any sources were NULL, clear the respective list
3851         if (!vertexstring)
3852                 vertstrings_count = 0;
3853         if (!geometrystring)
3854                 geomstrings_count = 0;
3855         if (!fragmentstring)
3856                 fragstrings_count = 0;
3857
3858         vertstring_length = 0;
3859         for (i = 0;i < vertstrings_count;i++)
3860                 vertstring_length += strlen(vertstrings_list[i]);
3861         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3862         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3863                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3864
3865         geomstring_length = 0;
3866         for (i = 0;i < geomstrings_count;i++)
3867                 geomstring_length += strlen(geomstrings_list[i]);
3868         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3869         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3870                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3871
3872         fragstring_length = 0;
3873         for (i = 0;i < fragstrings_count;i++)
3874                 fragstring_length += strlen(fragstrings_list[i]);
3875         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3876         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3877                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3878
3879         CHECKGLERROR
3880         CHECKCGERROR
3881         //vertexProfile = CG_PROFILE_ARBVP1;
3882         //fragmentProfile = CG_PROFILE_ARBFP1;
3883         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3884         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3885         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3886         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3887         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3888         CHECKGLERROR
3889
3890         // compile the vertex program
3891         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, CG_PROFILE_ARBVP1, NULL, NULL)))
3892         {
3893                 CHECKCGERROR
3894                 cgCompileProgram(p->vprogram);CHECKCGERROR
3895                 if (!cgIsProgramCompiled(p->vprogram))
3896                 {
3897                         CHECKCGERROR
3898                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3899                         p->vprogram = 0;
3900                 }
3901                 else
3902                 {
3903                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3904                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3905                         // look up all the uniform variable names we care about, so we don't
3906                         // have to look them up every time we set them
3907                         CHECKCGERROR
3908                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3909                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3910                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3911                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3912                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3913                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3914                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3915                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3916                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3917                         CHECKCGERROR
3918                 }
3919         }
3920
3921         // compile the fragment program
3922         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, CG_PROFILE_ARBFP1, NULL, NULL)))
3923         {
3924                 cgCompileProgram(p->fprogram);CHECKCGERROR
3925                 if (!cgIsProgramCompiled(p->fprogram))
3926                 {
3927                         CHECKCGERROR
3928                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3929                         p->fprogram = 0;
3930                 }
3931                 else
3932                 {
3933                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3934                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3935                         CHECKCGERROR
3936                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3937                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3938                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3939                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3940                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3941                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3942                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3943                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3944                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3945                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3946                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3947                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3948                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3949                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3950                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3951                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3952                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3953                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3954                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3955                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3956                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3957                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3958                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3959                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3960                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3961                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3962                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3963                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3964                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
3965                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3966                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
3967                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
3968                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
3969                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
3970                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
3971                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
3972                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
3973                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
3974                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
3975                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
3976                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
3977                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
3978                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
3979                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
3980                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
3981                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
3982                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
3983                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
3984                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
3985                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
3986                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
3987                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
3988                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
3989                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
3990                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
3991                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
3992                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
3993                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
3994                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
3995                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
3996                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
3997                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
3998                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
3999                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4000                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4001                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4002                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4003                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4004                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4005                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4006                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4007                         CHECKCGERROR
4008                 }
4009         }
4010
4011         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4012                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4013         else
4014                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4015
4016         // free the strings
4017         if (vertstring)
4018                 Mem_Free(vertstring);
4019         if (geomstring)
4020                 Mem_Free(geomstring);
4021         if (fragstring)
4022                 Mem_Free(fragstring);
4023         if (vertexstring)
4024                 Mem_Free(vertexstring);
4025         if (geometrystring)
4026                 Mem_Free(geometrystring);
4027         if (fragmentstring)
4028                 Mem_Free(fragmentstring);
4029 }
4030
4031 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4032 {
4033         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4034         CHECKGLERROR
4035         CHECKCGERROR
4036         if (r_cg_permutation != perm)
4037         {
4038                 r_cg_permutation = perm;
4039                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4040                 {
4041                         if (!r_cg_permutation->compiled)
4042                                 R_CG_CompilePermutation(perm, mode, permutation);
4043                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4044                         {
4045                                 // remove features until we find a valid permutation
4046                                 int i;
4047                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4048                                 {
4049                                         // reduce i more quickly whenever it would not remove any bits
4050                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4051                                         if (!(permutation & j))
4052                                                 continue;
4053                                         permutation -= j;
4054                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4055                                         if (!r_cg_permutation->compiled)
4056                                                 R_CG_CompilePermutation(perm, mode, permutation);
4057                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4058                                                 break;
4059                                 }
4060                                 if (i >= SHADERPERMUTATION_COUNT)
4061                                 {
4062                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4063                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4064                                         return; // no bit left to clear, entire mode is broken
4065                                 }
4066                         }
4067                 }
4068                 CHECKGLERROR
4069                 CHECKCGERROR
4070                 if (r_cg_permutation->vprogram)
4071                 {
4072                         //cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4073                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4074                         //cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4075                 }
4076                 else
4077                 {
4078                         //cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4079                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4080                 }
4081                 if (r_cg_permutation->fprogram)
4082                 {
4083                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4084                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4085                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4086                 }
4087                 else
4088                 {
4089                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4090                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4091                 }
4092         }
4093         CHECKCGERROR
4094         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4095 }
4096
4097 void CG_BindTexture(CGparameter param, int texnum)
4098 {
4099         cgGLSetTextureParameter(param, texnum);
4100         cgGLEnableTextureParameter(param);
4101 }
4102 #endif
4103
4104 void R_GLSL_Restart_f(void)
4105 {
4106         unsigned int i, limit;
4107         switch(vid.renderpath)
4108         {
4109         case RENDERPATH_GL20:
4110                 {
4111                         r_glsl_permutation_t *p;
4112                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4113                         for (i = 0;i < limit;i++)
4114                         {
4115                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4116                                 {
4117                                         GL_Backend_FreeProgram(p->program);
4118                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4119                                 }
4120                         }
4121                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4122                 }
4123                 break;
4124         case RENDERPATH_CGGL:
4125 #ifdef SUPPORTCG
4126                 {
4127                         r_cg_permutation_t *p;
4128                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4129                         for (i = 0;i < limit;i++)
4130                         {
4131                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4132                                 {
4133                                         if (p->vprogram)
4134                                                 cgDestroyProgram(p->vprogram);
4135                                         if (p->fprogram)
4136                                                 cgDestroyProgram(p->fprogram);
4137                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4138                                 }
4139                         }
4140                 }
4141                 memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4142                 break;
4143 #endif
4144         case RENDERPATH_GL13:
4145         case RENDERPATH_GL11:
4146                 break;
4147         }
4148 }
4149
4150 void R_GLSL_DumpShader_f(void)
4151 {
4152         int i;
4153         qfile_t *file;
4154
4155         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4156         if (file)
4157         {
4158                 FS_Print(file, "/* The engine may define the following macros:\n");
4159                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4160                 for (i = 0;i < SHADERMODE_COUNT;i++)
4161                         FS_Print(file, glslshadermodeinfo[i].pretext);
4162                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4163                         FS_Print(file, shaderpermutationinfo[i].pretext);
4164                 FS_Print(file, "*/\n");
4165                 FS_Print(file, builtinshaderstring);
4166                 FS_Close(file);
4167                 Con_Printf("glsl/default.glsl written\n");
4168         }
4169         else
4170                 Con_Printf("failed to write to glsl/default.glsl\n");
4171
4172 #ifdef SUPPORTCG
4173         file = FS_OpenRealFile("cg/default.cg", "w", false);
4174         if (file)
4175         {
4176                 FS_Print(file, "/* The engine may define the following macros:\n");
4177                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4178                 for (i = 0;i < SHADERMODE_COUNT;i++)
4179                         FS_Print(file, cgshadermodeinfo[i].pretext);
4180                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4181                         FS_Print(file, shaderpermutationinfo[i].pretext);
4182                 FS_Print(file, "*/\n");
4183                 FS_Print(file, builtincgshaderstring);
4184                 FS_Close(file);
4185                 Con_Printf("cg/default.cg written\n");
4186         }
4187         else
4188                 Con_Printf("failed to write to cg/default.cg\n");
4189 #endif
4190 }
4191
4192 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4193 {
4194         if (!second)
4195                 texturemode = GL_MODULATE;
4196         switch (vid.renderpath)
4197         {
4198         case RENDERPATH_GL20:
4199                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4200                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4201                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4202                 break;
4203         case RENDERPATH_CGGL:
4204 #ifdef SUPPORTCG
4205                 CHECKCGERROR
4206                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4207                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4208                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4209 #endif
4210                 break;
4211         case RENDERPATH_GL13:
4212                 R_Mesh_TexBind(0, first );
4213                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4214                 R_Mesh_TexBind(1, second);
4215                 if (second)
4216                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4217                 break;
4218         case RENDERPATH_GL11:
4219                 R_Mesh_TexBind(0, first );
4220                 break;
4221         }
4222 }
4223
4224 void R_SetupShader_DepthOrShadow(void)
4225 {
4226         switch (vid.renderpath)
4227         {
4228         case RENDERPATH_GL20:
4229                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4230                 break;
4231         case RENDERPATH_CGGL:
4232 #ifdef SUPPORTCG
4233                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4234 #endif
4235                 break;
4236         case RENDERPATH_GL13:
4237                 R_Mesh_TexBind(0, 0);
4238                 R_Mesh_TexBind(1, 0);
4239                 break;
4240         case RENDERPATH_GL11:
4241                 R_Mesh_TexBind(0, 0);
4242                 break;
4243         }
4244 }
4245
4246 void R_SetupShader_ShowDepth(void)
4247 {
4248         switch (vid.renderpath)
4249         {
4250         case RENDERPATH_GL20:
4251                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4252                 break;
4253         case RENDERPATH_CGGL:
4254 #ifdef SUPPORTCG
4255                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4256 #endif
4257                 break;
4258         case RENDERPATH_GL13:
4259                 break;
4260         case RENDERPATH_GL11:
4261                 break;
4262         }
4263 }
4264
4265 extern qboolean r_shadow_usingdeferredprepass;
4266 extern cvar_t r_shadow_deferred_8bitrange;
4267 extern rtexture_t *r_shadow_attenuationgradienttexture;
4268 extern rtexture_t *r_shadow_attenuation2dtexture;
4269 extern rtexture_t *r_shadow_attenuation3dtexture;
4270 extern qboolean r_shadow_usingshadowmaprect;
4271 extern qboolean r_shadow_usingshadowmapcube;
4272 extern qboolean r_shadow_usingshadowmap2d;
4273 extern float r_shadow_shadowmap_texturescale[2];
4274 extern float r_shadow_shadowmap_parameters[4];
4275 extern qboolean r_shadow_shadowmapvsdct;
4276 extern qboolean r_shadow_shadowmapsampler;
4277 extern int r_shadow_shadowmappcf;
4278 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4279 extern rtexture_t *r_shadow_shadowmap2dtexture;
4280 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4281 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4282 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4283 extern int r_shadow_prepass_width;
4284 extern int r_shadow_prepass_height;
4285 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4286 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4287 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4288 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4289 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4290 {
4291         // select a permutation of the lighting shader appropriate to this
4292         // combination of texture, entity, light source, and fogging, only use the
4293         // minimum features necessary to avoid wasting rendering time in the
4294         // fragment shader on features that are not being used
4295         unsigned int permutation = 0;
4296         unsigned int mode = 0;
4297         float m16f[16];
4298         // TODO: implement geometry-shader based shadow volumes someday
4299         if (r_glsl_offsetmapping.integer)
4300         {
4301                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4302                 if (r_glsl_offsetmapping_reliefmapping.integer)
4303                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4304         }
4305         if (rsurfacepass == RSURFPASS_BACKGROUND)
4306         {
4307                 // distorted background
4308                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4309                         mode = SHADERMODE_WATER;
4310                 else
4311                         mode = SHADERMODE_REFRACTION;
4312         }
4313         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4314         {
4315                 // normalmap (deferred prepass), may use alpha test on diffuse
4316                 mode = SHADERMODE_DEFERREDGEOMETRY;
4317                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4318                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4319                 if (r_glsl_offsetmapping.integer)
4320                 {
4321                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4322                         if (r_glsl_offsetmapping_reliefmapping.integer)
4323                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4324                 }
4325         }
4326         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4327         {
4328                 // light source
4329                 mode = SHADERMODE_LIGHTSOURCE;
4330                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4331                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4332                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4333                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4334                 if (diffusescale > 0)
4335                         permutation |= SHADERPERMUTATION_DIFFUSE;
4336                 if (specularscale > 0)
4337                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4338                 if (r_refdef.fogenabled)
4339                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4340                 if (rsurface.texture->colormapping)
4341                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4342                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4343                 {
4344                         if (r_shadow_usingshadowmaprect)
4345                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4346                         if (r_shadow_usingshadowmap2d)
4347                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4348                         if (r_shadow_usingshadowmapcube)
4349                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4350                         else if(r_shadow_shadowmapvsdct)
4351                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4352
4353                         if (r_shadow_shadowmapsampler)
4354                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4355                         if (r_shadow_shadowmappcf > 1)
4356                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4357                         else if (r_shadow_shadowmappcf)
4358                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4359                 }
4360         }
4361         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4362         {
4363                 // unshaded geometry (fullbright or ambient model lighting)
4364                 mode = SHADERMODE_FLATCOLOR;
4365                 ambientscale = diffusescale = specularscale = 0;
4366                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4367                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4368                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4369                         permutation |= SHADERPERMUTATION_GLOW;
4370                 if (r_refdef.fogenabled)
4371                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4372                 if (rsurface.texture->colormapping)
4373                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4374                 if (r_glsl_offsetmapping.integer)
4375                 {
4376                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4377                         if (r_glsl_offsetmapping_reliefmapping.integer)
4378                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4379                 }
4380                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4381                         permutation |= SHADERPERMUTATION_REFLECTION;
4382         }
4383         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4384         {
4385                 // directional model lighting
4386                 mode = SHADERMODE_LIGHTDIRECTION;
4387                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4388                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4389                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4390                         permutation |= SHADERPERMUTATION_GLOW;
4391                 permutation |= SHADERPERMUTATION_DIFFUSE;
4392                 if (specularscale > 0)
4393                         permutation |= SHADERPERMUTATION_SPECULAR;
4394                 if (r_refdef.fogenabled)
4395                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4396                 if (rsurface.texture->colormapping)
4397                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4398                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4399                         permutation |= SHADERPERMUTATION_REFLECTION;
4400                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4401                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4402         }
4403         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4404         {
4405                 // ambient model lighting
4406                 mode = SHADERMODE_LIGHTDIRECTION;
4407                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4408                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4409                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4410                         permutation |= SHADERPERMUTATION_GLOW;
4411                 if (r_refdef.fogenabled)
4412                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4413                 if (rsurface.texture->colormapping)
4414                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4415                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4416                         permutation |= SHADERPERMUTATION_REFLECTION;
4417                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4418                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4419         }
4420         else
4421         {
4422                 // lightmapped wall
4423                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4424                 {
4425                         // deluxemapping (light direction texture)
4426                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4427                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4428                         else
4429                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4430                         permutation |= SHADERPERMUTATION_DIFFUSE;
4431                         if (specularscale > 0)
4432                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4433                 }
4434                 else if (r_glsl_deluxemapping.integer >= 2)
4435                 {
4436                         // fake deluxemapping (uniform light direction in tangentspace)
4437                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4438                         permutation |= SHADERPERMUTATION_DIFFUSE;
4439                         if (specularscale > 0)
4440                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4441                 }
4442                 else if (rsurface.uselightmaptexture)
4443                 {
4444                         // ordinary lightmapping (q1bsp, q3bsp)
4445                         mode = SHADERMODE_LIGHTMAP;
4446                 }
4447                 else
4448                 {
4449                         // ordinary vertex coloring (q3bsp)
4450                         mode = SHADERMODE_VERTEXCOLOR;
4451                 }
4452                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4453                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4454                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4455                         permutation |= SHADERPERMUTATION_GLOW;
4456                 if (r_refdef.fogenabled)
4457                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4458                 if (rsurface.texture->colormapping)
4459                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4461                         permutation |= SHADERPERMUTATION_REFLECTION;
4462                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4463                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4464         }
4465         if(permutation & SHADERPERMUTATION_SPECULAR)
4466                 if(r_shadow_glossexact.integer)
4467                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4468         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4469                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4470         switch(vid.renderpath)
4471         {
4472         case RENDERPATH_GL20:
4473                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4474                 if (mode == SHADERMODE_LIGHTSOURCE)
4475                 {
4476                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4477                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4478                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4479                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
4480                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
4481                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, specularscale, specularscale, specularscale);
4482         
4483                         // additive passes are only darkened by fog, not tinted
4484                         if (r_glsl_permutation->loc_FogColor >= 0)
4485                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4486                         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]);
4487                         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]);
4488                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4489                 }
4490                 else
4491                 {
4492                         if (mode == SHADERMODE_FLATCOLOR)
4493                         {
4494                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4495                         }
4496                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4497                         {
4498                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
4499                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);
4500                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
4501                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
4502                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
4503                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
4504                                 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]);
4505                         }
4506                         else
4507                         {
4508                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
4509                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
4510                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);
4511                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
4512                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
4513                         }
4514                         // additive passes are only darkened by fog, not tinted
4515                         if (r_glsl_permutation->loc_FogColor >= 0)
4516                         {
4517                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4518                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4519                                 else
4520                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4521                         }
4522                         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);
4523                         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]);
4524                         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]);
4525                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4526                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4527                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4528                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4529                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4530                 }
4531                 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4532                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4533                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4534                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4535                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4536                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4537                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4538                 {
4539                         if (rsurface.texture->pantstexture)
4540                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4541                         else
4542                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4543                 }
4544                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4545                 {
4546                         if (rsurface.texture->shirttexture)
4547                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4548                         else
4549                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4550                 }
4551                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
4552                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4553                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4554                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4555                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4556                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
4557
4558         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4559         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4560         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4561                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4562                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4563                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4564                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4565                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4566                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4567                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4568                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4569                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4570                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4571                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4572                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4573                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4574                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4575                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4576                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4577                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4578                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4579                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4580                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4581                 if (rsurface.rtlight)
4582                 {
4583                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4584                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4585                         if (r_shadow_usingshadowmapcube)
4586                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4587                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4588                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4589                 }
4590                 CHECKGLERROR
4591                 break;
4592         case RENDERPATH_CGGL:
4593 #ifdef SUPPORTCG
4594                 R_SetupShader_SetPermutationCG(mode, permutation);
4595                 if (mode == SHADERMODE_LIGHTSOURCE)
4596                 {
4597                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4598                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4599                 }
4600                 else
4601                 {
4602                         if (mode == SHADERMODE_LIGHTDIRECTION)
4603                         {
4604                                 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
4605                         }
4606                 }
4607                 if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4608                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4609                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4610                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4611                 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
4612                 CHECKGLERROR
4613
4614                 if (mode == SHADERMODE_LIGHTSOURCE)
4615                 {
4616                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4617                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4618                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
4619                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
4620                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, specularscale, specularscale, specularscale);CHECKCGERROR
4621
4622                         // additive passes are only darkened by fog, not tinted
4623                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4624                         if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
4625                         if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
4626                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4627                 }
4628                 else
4629                 {
4630                         if (mode == SHADERMODE_FLATCOLOR)
4631                         {
4632                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4633                         }
4634                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4635                         {
4636                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);CHECKCGERROR
4637                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity, r_refdef.lightmapintensity, r_refdef.lightmapintensity);CHECKCGERROR
4638                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
4639                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4640                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4641                                 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
4642                                 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
4643                         }
4644                         else
4645                         {
4646                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);CHECKCGERROR
4647                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
4648                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale, r_refdef.lightmapintensity * specularscale);CHECKCGERROR
4649                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4650                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4651                         }
4652                         // additive passes are only darkened by fog, not tinted
4653                         if (r_cg_permutation->fp_FogColor)
4654                         {
4655                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4656                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4657                                 else
4658                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4659                                 CHECKCGERROR
4660                         }
4661                         if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_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);CHECKCGERROR
4662                         if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
4663                         if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
4664                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4665                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4666                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4667                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4668                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4669                 }
4670                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4671                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4672                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4673                 if (r_cg_permutation->fp_Color_Pants)
4674                 {
4675                         if (rsurface.texture->pantstexture)
4676                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4677                         else
4678                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4679                         CHECKCGERROR
4680                 }
4681                 if (r_cg_permutation->fp_Color_Shirt)
4682                 {
4683                         if (rsurface.texture->shirttexture)
4684                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4685                         else
4686                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4687                         CHECKCGERROR
4688                 }
4689                 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
4690                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4691                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4692                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4693                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4694                 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
4695
4696         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4697         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4698         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4699                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4700                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4701                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4702                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4703                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4704                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4705                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4706                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4707                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4708                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4709                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4710                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4711                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4712                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4713                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4714                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4715                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4716                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4717                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4718                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4719                 if (rsurface.rtlight)
4720                 {
4721                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4722                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4723                         if (r_shadow_usingshadowmapcube)
4724                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4725                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4726                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4727                 }
4728
4729                 CHECKGLERROR
4730 #endif
4731                 break;
4732         case RENDERPATH_GL13:
4733         case RENDERPATH_GL11:
4734                 break;
4735         }
4736 }
4737
4738 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4739 {
4740         // select a permutation of the lighting shader appropriate to this
4741         // combination of texture, entity, light source, and fogging, only use the
4742         // minimum features necessary to avoid wasting rendering time in the
4743         // fragment shader on features that are not being used
4744         unsigned int permutation = 0;
4745         unsigned int mode = 0;
4746         const float *lightcolorbase = rtlight->currentcolor;
4747         float ambientscale = rtlight->ambientscale;
4748         float diffusescale = rtlight->diffusescale;
4749         float specularscale = rtlight->specularscale;
4750         // this is the location of the light in view space
4751         vec3_t viewlightorigin;
4752         // this transforms from view space (camera) to light space (cubemap)
4753         matrix4x4_t viewtolight;
4754         matrix4x4_t lighttoview;
4755         float viewtolight16f[16];
4756         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4757         // light source
4758         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4759         if (rtlight->currentcubemap != r_texture_whitecube)
4760                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4761         if (diffusescale > 0)
4762                 permutation |= SHADERPERMUTATION_DIFFUSE;
4763         if (specularscale > 0)
4764         {
4765                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4766                 if (r_shadow_glossexact.integer)
4767                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4768         }
4769         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4770         {
4771                 if (r_shadow_usingshadowmaprect)
4772                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4773                 if (r_shadow_usingshadowmap2d)
4774                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4775                 if (r_shadow_usingshadowmapcube)
4776                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4777                 else if(r_shadow_shadowmapvsdct)
4778                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4779
4780                 if (r_shadow_shadowmapsampler)
4781                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4782                 if (r_shadow_shadowmappcf > 1)
4783                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4784                 else if (r_shadow_shadowmappcf)
4785                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4786         }
4787         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4788         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4789         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4790         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4791         switch(vid.renderpath)
4792         {
4793         case RENDERPATH_GL20:
4794                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4795                 if (r_glsl_permutation->loc_ModelViewMatrix           >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix          , 1, false, gl_modelview16f);
4796                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4797                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4798                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
4799                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
4800                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
4801                 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]);
4802                 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]);
4803                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1fARB(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4804                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
4805
4806                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
4807                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
4808                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
4809                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
4810                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
4811                 if (r_shadow_usingshadowmapcube)
4812                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4813                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
4814                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
4815                 break;
4816         case RENDERPATH_CGGL:
4817 #ifdef SUPPORTCG
4818                 R_SetupShader_SetPermutationCG(mode, permutation);
4819                 if (r_cg_permutation->vp_ModelViewMatrix          ) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelviewprojection16f);CHECKCGERROR
4820                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4821                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4822                 if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
4823                 if (r_cg_permutation->fp_DeferredColor_Diffuse    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);CHECKCGERROR
4824                 if (r_cg_permutation->fp_DeferredColor_Specular   ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
4825                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
4826                 if (r_cg_permutation->fp_ShadowMap_Parameters     ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
4827                 if (r_cg_permutation->fp_SpecularPower            ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4828                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
4829
4830                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4831                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4832                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4833                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4834                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4835                 if (r_shadow_usingshadowmapcube)
4836                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4837                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4838                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4839 #endif
4840                 break;
4841         case RENDERPATH_GL13:
4842         case RENDERPATH_GL11:
4843                 break;
4844         }
4845 }
4846
4847 #define SKINFRAME_HASH 1024
4848
4849 typedef struct
4850 {
4851         int loadsequence; // incremented each level change
4852         memexpandablearray_t array;
4853         skinframe_t *hash[SKINFRAME_HASH];
4854 }
4855 r_skinframe_t;
4856 r_skinframe_t r_skinframe;
4857
4858 void R_SkinFrame_PrepareForPurge(void)
4859 {
4860         r_skinframe.loadsequence++;
4861         // wrap it without hitting zero
4862         if (r_skinframe.loadsequence >= 200)
4863                 r_skinframe.loadsequence = 1;
4864 }
4865
4866 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4867 {
4868         if (!skinframe)
4869                 return;
4870         // mark the skinframe as used for the purging code
4871         skinframe->loadsequence = r_skinframe.loadsequence;
4872 }
4873
4874 void R_SkinFrame_Purge(void)
4875 {
4876         int i;
4877         skinframe_t *s;
4878         for (i = 0;i < SKINFRAME_HASH;i++)
4879         {
4880                 for (s = r_skinframe.hash[i];s;s = s->next)
4881                 {
4882                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4883                         {
4884                                 if (s->merged == s->base)
4885                                         s->merged = NULL;
4886                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4887                                 R_PurgeTexture(s->stain );s->stain  = NULL;
4888                                 R_PurgeTexture(s->merged);s->merged = NULL;
4889                                 R_PurgeTexture(s->base  );s->base   = NULL;
4890                                 R_PurgeTexture(s->pants );s->pants  = NULL;
4891                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
4892                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
4893                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
4894                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
4895                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
4896                                 s->loadsequence = 0;
4897                         }
4898                 }
4899         }
4900 }
4901
4902 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4903         skinframe_t *item;
4904         char basename[MAX_QPATH];
4905
4906         Image_StripImageExtension(name, basename, sizeof(basename));
4907
4908         if( last == NULL ) {
4909                 int hashindex;
4910                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4911                 item = r_skinframe.hash[hashindex];
4912         } else {
4913                 item = last->next;
4914         }
4915
4916         // linearly search through the hash bucket
4917         for( ; item ; item = item->next ) {
4918                 if( !strcmp( item->basename, basename ) ) {
4919                         return item;
4920                 }
4921         }
4922         return NULL;
4923 }
4924
4925 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4926 {
4927         skinframe_t *item;
4928         int hashindex;
4929         char basename[MAX_QPATH];
4930
4931         Image_StripImageExtension(name, basename, sizeof(basename));
4932
4933         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4934         for (item = r_skinframe.hash[hashindex];item;item = item->next)
4935                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4936                         break;
4937
4938         if (!item) {
4939                 rtexture_t *dyntexture;
4940                 // check whether its a dynamic texture
4941                 dyntexture = CL_GetDynTexture( basename );
4942                 if (!add && !dyntexture)
4943                         return NULL;
4944                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4945                 memset(item, 0, sizeof(*item));
4946                 strlcpy(item->basename, basename, sizeof(item->basename));
4947                 item->base = dyntexture; // either NULL or dyntexture handle
4948                 item->textureflags = textureflags;
4949                 item->comparewidth = comparewidth;
4950                 item->compareheight = compareheight;
4951                 item->comparecrc = comparecrc;
4952                 item->next = r_skinframe.hash[hashindex];
4953                 r_skinframe.hash[hashindex] = item;
4954         }
4955         else if( item->base == NULL )
4956         {
4957                 rtexture_t *dyntexture;
4958                 // check whether its a dynamic texture
4959                 // 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]
4960                 dyntexture = CL_GetDynTexture( basename );
4961                 item->base = dyntexture; // either NULL or dyntexture handle
4962         }
4963
4964         R_SkinFrame_MarkUsed(item);
4965         return item;
4966 }
4967
4968 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
4969         { \
4970                 unsigned long long avgcolor[5], wsum; \
4971                 int pix, comp, w; \
4972                 avgcolor[0] = 0; \
4973                 avgcolor[1] = 0; \
4974                 avgcolor[2] = 0; \
4975                 avgcolor[3] = 0; \
4976                 avgcolor[4] = 0; \
4977                 wsum = 0; \
4978                 for(pix = 0; pix < cnt; ++pix) \
4979                 { \
4980                         w = 0; \
4981                         for(comp = 0; comp < 3; ++comp) \
4982                                 w += getpixel; \
4983                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
4984                         { \
4985                                 ++wsum; \
4986                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4987                                 w = getpixel; \
4988                                 for(comp = 0; comp < 3; ++comp) \
4989                                         avgcolor[comp] += getpixel * w; \
4990                                 avgcolor[3] += w; \
4991                         } \
4992                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
4993                         avgcolor[4] += getpixel; \
4994                 } \
4995                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
4996                         avgcolor[3] = 1; \
4997                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
4998                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
4999                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5000                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5001         }
5002
5003 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5004 {
5005         int j;
5006         unsigned char *pixels;
5007         unsigned char *bumppixels;
5008         unsigned char *basepixels = NULL;
5009         int basepixels_width;
5010         int basepixels_height;
5011         skinframe_t *skinframe;
5012
5013         if (cls.state == ca_dedicated)
5014                 return NULL;
5015
5016         // return an existing skinframe if already loaded
5017         // if loading of the first image fails, don't make a new skinframe as it
5018         // would cause all future lookups of this to be missing
5019         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5020         if (skinframe && skinframe->base)
5021                 return skinframe;
5022
5023         basepixels = loadimagepixelsbgra(name, complain, true);
5024         if (basepixels == NULL)
5025                 return NULL;
5026
5027         if (developer_loading.integer)
5028                 Con_Printf("loading skin \"%s\"\n", name);
5029
5030         // we've got some pixels to store, so really allocate this new texture now
5031         if (!skinframe)
5032                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5033         skinframe->stain = NULL;
5034         skinframe->merged = NULL;
5035         skinframe->base = r_texture_notexture;
5036         skinframe->pants = NULL;
5037         skinframe->shirt = NULL;
5038         skinframe->nmap = r_texture_blanknormalmap;
5039         skinframe->gloss = NULL;
5040         skinframe->glow = NULL;
5041         skinframe->fog = NULL;
5042         skinframe->hasalpha = false;
5043
5044         basepixels_width = image_width;
5045         basepixels_height = image_height;
5046         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);
5047
5048         if (textureflags & TEXF_ALPHA)
5049         {
5050                 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5051                 {
5052                         if (basepixels[j] < 255)
5053                         {
5054                                 skinframe->hasalpha = true;
5055                                 break;
5056                         }
5057                 }
5058                 if (r_loadfog && skinframe->hasalpha)
5059                 {
5060                         // has transparent pixels
5061                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5062                         for (j = 0;j < image_width * image_height * 4;j += 4)
5063                         {
5064                                 pixels[j+0] = 255;
5065                                 pixels[j+1] = 255;
5066                                 pixels[j+2] = 255;
5067                                 pixels[j+3] = basepixels[j+3];
5068                         }
5069                         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);
5070                         Mem_Free(pixels);
5071                 }
5072         }
5073
5074         R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5075         //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]);
5076
5077         // _norm is the name used by tenebrae and has been adopted as standard
5078         if (r_loadnormalmap)
5079         {
5080                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5081                 {
5082                         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);
5083                         Mem_Free(pixels);
5084                         pixels = NULL;
5085                 }
5086                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5087                 {
5088                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5089                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5090                         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);
5091                         Mem_Free(pixels);
5092                         Mem_Free(bumppixels);
5093                 }
5094                 else if (r_shadow_bumpscale_basetexture.value > 0)
5095                 {
5096                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5097                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5098                         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);
5099                         Mem_Free(pixels);
5100                 }
5101         }
5102         // _luma is supported for tenebrae compatibility
5103         // (I think it's a very stupid name, but oh well)
5104         // _glow is the preferred name
5105         if ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))) {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;}
5106         if (r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false))) {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;}
5107         if ((pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false))) {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;}
5108         if ((pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false))) {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;}
5109
5110         if (basepixels)
5111                 Mem_Free(basepixels);
5112
5113         return skinframe;
5114 }
5115
5116 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5117 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5118 {
5119         int i;
5120         unsigned char *temp1, *temp2;
5121         skinframe_t *skinframe;
5122
5123         if (cls.state == ca_dedicated)
5124                 return NULL;
5125
5126         // if already loaded just return it, otherwise make a new skinframe
5127         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5128         if (skinframe && skinframe->base)
5129                 return skinframe;
5130
5131         skinframe->stain = NULL;
5132         skinframe->merged = NULL;
5133         skinframe->base = r_texture_notexture;
5134         skinframe->pants = NULL;
5135         skinframe->shirt = NULL;
5136         skinframe->nmap = r_texture_blanknormalmap;
5137         skinframe->gloss = NULL;
5138         skinframe->glow = NULL;
5139         skinframe->fog = NULL;
5140         skinframe->hasalpha = false;
5141
5142         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5143         if (!skindata)
5144                 return NULL;
5145
5146         if (developer_loading.integer)
5147                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5148
5149         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5150         {
5151                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5152                 temp2 = temp1 + width * height * 4;
5153                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5154                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5155                 Mem_Free(temp1);
5156         }
5157         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5158         if (textureflags & TEXF_ALPHA)
5159         {
5160                 for (i = 3;i < width * height * 4;i += 4)
5161                 {
5162                         if (skindata[i] < 255)
5163                         {
5164                                 skinframe->hasalpha = true;
5165                                 break;
5166                         }
5167                 }
5168                 if (r_loadfog && skinframe->hasalpha)
5169                 {
5170                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5171                         memcpy(fogpixels, skindata, width * height * 4);
5172                         for (i = 0;i < width * height * 4;i += 4)
5173                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5174                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5175                         Mem_Free(fogpixels);
5176                 }
5177         }
5178
5179         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5180         //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]);
5181
5182         return skinframe;
5183 }
5184
5185 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5186 {
5187         int i;
5188         int featuresmask;
5189         skinframe_t *skinframe;
5190
5191         if (cls.state == ca_dedicated)
5192                 return NULL;
5193
5194         // if already loaded just return it, otherwise make a new skinframe
5195         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5196         if (skinframe && skinframe->base)
5197                 return skinframe;
5198
5199         skinframe->stain = NULL;
5200         skinframe->merged = NULL;
5201         skinframe->base = r_texture_notexture;
5202         skinframe->pants = NULL;
5203         skinframe->shirt = NULL;
5204         skinframe->nmap = r_texture_blanknormalmap;
5205         skinframe->gloss = NULL;
5206         skinframe->glow = NULL;
5207         skinframe->fog = NULL;
5208         skinframe->hasalpha = false;
5209
5210         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5211         if (!skindata)
5212                 return NULL;
5213
5214         if (developer_loading.integer)
5215                 Con_Printf("loading quake skin \"%s\"\n", name);
5216
5217         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
5218         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5219         memcpy(skinframe->qpixels, skindata, width*height);
5220         skinframe->qwidth = width;
5221         skinframe->qheight = height;
5222
5223         featuresmask = 0;
5224         for (i = 0;i < width * height;i++)
5225                 featuresmask |= palette_featureflags[skindata[i]];
5226
5227         skinframe->hasalpha = false;
5228         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5229         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5230         skinframe->qgeneratemerged = true;
5231         skinframe->qgeneratebase = skinframe->qhascolormapping;
5232         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5233
5234         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5235         //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]);
5236
5237         return skinframe;
5238 }
5239
5240 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5241 {
5242         int width;
5243         int height;
5244         unsigned char *skindata;
5245
5246         if (!skinframe->qpixels)
5247                 return;
5248
5249         if (!skinframe->qhascolormapping)
5250                 colormapped = false;
5251
5252         if (colormapped)
5253         {
5254                 if (!skinframe->qgeneratebase)
5255                         return;
5256         }
5257         else
5258         {
5259                 if (!skinframe->qgeneratemerged)
5260                         return;
5261         }
5262
5263         width = skinframe->qwidth;
5264         height = skinframe->qheight;
5265         skindata = skinframe->qpixels;
5266
5267         if (skinframe->qgeneratenmap)
5268         {
5269                 unsigned char *temp1, *temp2;
5270                 skinframe->qgeneratenmap = false;
5271                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5272                 temp2 = temp1 + width * height * 4;
5273                 // use either a custom palette or the quake palette
5274                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5275                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5276                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5277                 Mem_Free(temp1);
5278         }
5279
5280         if (skinframe->qgenerateglow)
5281         {
5282                 skinframe->qgenerateglow = false;
5283                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5284         }
5285
5286         if (colormapped)
5287         {
5288                 skinframe->qgeneratebase = false;
5289                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
5290                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5291                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5292         }
5293         else
5294         {
5295                 skinframe->qgeneratemerged = false;
5296                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5297         }
5298
5299         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5300         {
5301                 Mem_Free(skinframe->qpixels);
5302                 skinframe->qpixels = NULL;
5303         }
5304 }
5305
5306 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
5307 {
5308         int i;
5309         skinframe_t *skinframe;
5310
5311         if (cls.state == ca_dedicated)
5312                 return NULL;
5313
5314         // if already loaded just return it, otherwise make a new skinframe
5315         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5316         if (skinframe && skinframe->base)
5317                 return skinframe;
5318
5319         skinframe->stain = NULL;
5320         skinframe->merged = NULL;
5321         skinframe->base = r_texture_notexture;
5322         skinframe->pants = NULL;
5323         skinframe->shirt = NULL;
5324         skinframe->nmap = r_texture_blanknormalmap;
5325         skinframe->gloss = NULL;
5326         skinframe->glow = NULL;
5327         skinframe->fog = NULL;
5328         skinframe->hasalpha = false;
5329
5330         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5331         if (!skindata)
5332                 return NULL;
5333
5334         if (developer_loading.integer)
5335                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5336
5337         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5338         if (textureflags & TEXF_ALPHA)
5339         {
5340                 for (i = 0;i < width * height;i++)
5341                 {
5342                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5343                         {
5344                                 skinframe->hasalpha = true;
5345                                 break;
5346                         }
5347                 }
5348                 if (r_loadfog && skinframe->hasalpha)
5349                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5350         }
5351
5352         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5353         //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]);
5354
5355         return skinframe;
5356 }
5357
5358 skinframe_t *R_SkinFrame_LoadMissing(void)
5359 {
5360         skinframe_t *skinframe;
5361
5362         if (cls.state == ca_dedicated)
5363                 return NULL;
5364
5365         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5366         skinframe->stain = NULL;
5367         skinframe->merged = NULL;
5368         skinframe->base = r_texture_notexture;
5369         skinframe->pants = NULL;
5370         skinframe->shirt = NULL;
5371         skinframe->nmap = r_texture_blanknormalmap;
5372         skinframe->gloss = NULL;
5373         skinframe->glow = NULL;
5374         skinframe->fog = NULL;
5375         skinframe->hasalpha = false;
5376
5377         skinframe->avgcolor[0] = rand() / RAND_MAX;
5378         skinframe->avgcolor[1] = rand() / RAND_MAX;
5379         skinframe->avgcolor[2] = rand() / RAND_MAX;
5380         skinframe->avgcolor[3] = 1;
5381
5382         return skinframe;
5383 }
5384
5385 void R_Main_FreeViewCache(void)
5386 {
5387         if (r_refdef.viewcache.entityvisible)
5388                 Mem_Free(r_refdef.viewcache.entityvisible);
5389         if (r_refdef.viewcache.world_pvsbits)
5390                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5391         if (r_refdef.viewcache.world_leafvisible)
5392                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5393         if (r_refdef.viewcache.world_surfacevisible)
5394                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5395         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5396 }
5397
5398 void R_Main_ResizeViewCache(void)
5399 {
5400         int numentities = r_refdef.scene.numentities;
5401         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5402         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5403         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5404         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5405         if (r_refdef.viewcache.maxentities < numentities)
5406         {
5407                 r_refdef.viewcache.maxentities = numentities;
5408                 if (r_refdef.viewcache.entityvisible)
5409                         Mem_Free(r_refdef.viewcache.entityvisible);
5410                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5411         }
5412         if (r_refdef.viewcache.world_numclusters != numclusters)
5413         {
5414                 r_refdef.viewcache.world_numclusters = numclusters;
5415                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5416                 if (r_refdef.viewcache.world_pvsbits)
5417                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5418                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5419         }
5420         if (r_refdef.viewcache.world_numleafs != numleafs)
5421         {
5422                 r_refdef.viewcache.world_numleafs = numleafs;
5423                 if (r_refdef.viewcache.world_leafvisible)
5424                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5425                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5426         }
5427         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5428         {
5429                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5430                 if (r_refdef.viewcache.world_surfacevisible)
5431                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5432                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5433         }
5434 }
5435
5436 extern rtexture_t *loadingscreentexture;
5437 void gl_main_start(void)
5438 {
5439         loadingscreentexture = NULL;
5440         r_texture_blanknormalmap = NULL;
5441         r_texture_white = NULL;
5442         r_texture_grey128 = NULL;
5443         r_texture_black = NULL;
5444         r_texture_whitecube = NULL;
5445         r_texture_normalizationcube = NULL;
5446         r_texture_fogattenuation = NULL;
5447         r_texture_gammaramps = NULL;
5448
5449         switch(vid.renderpath)
5450         {
5451         case RENDERPATH_GL20:
5452         case RENDERPATH_CGGL:
5453                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5454                 Cvar_SetValueQuick(&gl_combine, 1);
5455                 Cvar_SetValueQuick(&r_glsl, 1);
5456                 r_loadnormalmap = true;
5457                 r_loadgloss = true;
5458                 r_loadfog = false;
5459                 break;
5460         case RENDERPATH_GL13:
5461                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5462                 Cvar_SetValueQuick(&gl_combine, 1);
5463                 Cvar_SetValueQuick(&r_glsl, 0);
5464                 r_loadnormalmap = false;
5465                 r_loadgloss = false;
5466                 r_loadfog = true;
5467                 break;
5468         case RENDERPATH_GL11:
5469                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5470                 Cvar_SetValueQuick(&gl_combine, 0);
5471                 Cvar_SetValueQuick(&r_glsl, 0);
5472                 r_loadnormalmap = false;
5473                 r_loadgloss = false;
5474                 r_loadfog = true;
5475                 break;
5476         }
5477
5478         R_AnimCache_Free();
5479         R_FrameData_Reset();
5480
5481         r_numqueries = 0;
5482         r_maxqueries = 0;
5483         memset(r_queries, 0, sizeof(r_queries));
5484
5485         r_qwskincache = NULL;
5486         r_qwskincache_size = 0;
5487
5488         // set up r_skinframe loading system for textures
5489         memset(&r_skinframe, 0, sizeof(r_skinframe));
5490         r_skinframe.loadsequence = 1;
5491         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5492
5493         r_main_texturepool = R_AllocTexturePool();
5494         R_BuildBlankTextures();
5495         R_BuildNoTexture();
5496         if (vid.support.arb_texture_cube_map)
5497         {
5498                 R_BuildWhiteCube();
5499                 R_BuildNormalizationCube();
5500         }
5501         r_texture_fogattenuation = NULL;
5502         r_texture_gammaramps = NULL;
5503         //r_texture_fogintensity = NULL;
5504         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5505         memset(&r_waterstate, 0, sizeof(r_waterstate));
5506         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5507         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5508 #ifdef SUPPORTCG
5509         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5510         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5511 #endif
5512         memset(&r_svbsp, 0, sizeof (r_svbsp));
5513
5514         r_refdef.fogmasktable_density = 0;
5515 }
5516
5517 void gl_main_shutdown(void)
5518 {
5519         R_AnimCache_Free();
5520         R_FrameData_Reset();
5521
5522         R_Main_FreeViewCache();
5523
5524         if (r_maxqueries)
5525                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5526
5527         r_numqueries = 0;
5528         r_maxqueries = 0;
5529         memset(r_queries, 0, sizeof(r_queries));
5530
5531         r_qwskincache = NULL;
5532         r_qwskincache_size = 0;
5533
5534         // clear out the r_skinframe state
5535         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5536         memset(&r_skinframe, 0, sizeof(r_skinframe));
5537
5538         if (r_svbsp.nodes)
5539                 Mem_Free(r_svbsp.nodes);
5540         memset(&r_svbsp, 0, sizeof (r_svbsp));
5541         R_FreeTexturePool(&r_main_texturepool);
5542         loadingscreentexture = NULL;
5543         r_texture_blanknormalmap = NULL;
5544         r_texture_white = NULL;
5545         r_texture_grey128 = NULL;
5546         r_texture_black = NULL;
5547         r_texture_whitecube = NULL;
5548         r_texture_normalizationcube = NULL;
5549         r_texture_fogattenuation = NULL;
5550         r_texture_gammaramps = NULL;
5551         //r_texture_fogintensity = NULL;
5552         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5553         memset(&r_waterstate, 0, sizeof(r_waterstate));
5554         R_GLSL_Restart_f();
5555 }
5556
5557 extern void CL_ParseEntityLump(char *entitystring);
5558 void gl_main_newmap(void)
5559 {
5560         // FIXME: move this code to client
5561         int l;
5562         char *entities, entname[MAX_QPATH];
5563         if (r_qwskincache)
5564                 Mem_Free(r_qwskincache);
5565         r_qwskincache = NULL;
5566         r_qwskincache_size = 0;
5567         if (cl.worldmodel)
5568         {
5569                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5570                 l = (int)strlen(entname) - 4;
5571                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5572                 {
5573                         memcpy(entname + l, ".ent", 5);
5574                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5575                         {
5576                                 CL_ParseEntityLump(entities);
5577                                 Mem_Free(entities);
5578                                 return;
5579                         }
5580                 }
5581                 if (cl.worldmodel->brush.entities)
5582                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5583         }
5584         R_Main_FreeViewCache();
5585
5586         R_FrameData_Reset();
5587 }
5588
5589 void GL_Main_Init(void)
5590 {
5591         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5592
5593         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5594         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5595         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5596         if (gamemode == GAME_NEHAHRA)
5597         {
5598                 Cvar_RegisterVariable (&gl_fogenable);
5599                 Cvar_RegisterVariable (&gl_fogdensity);
5600                 Cvar_RegisterVariable (&gl_fogred);
5601                 Cvar_RegisterVariable (&gl_foggreen);
5602                 Cvar_RegisterVariable (&gl_fogblue);
5603                 Cvar_RegisterVariable (&gl_fogstart);
5604                 Cvar_RegisterVariable (&gl_fogend);
5605                 Cvar_RegisterVariable (&gl_skyclip);
5606         }
5607         Cvar_RegisterVariable(&r_motionblur);
5608         Cvar_RegisterVariable(&r_motionblur_maxblur);
5609         Cvar_RegisterVariable(&r_motionblur_bmin);
5610         Cvar_RegisterVariable(&r_motionblur_vmin);
5611         Cvar_RegisterVariable(&r_motionblur_vmax);
5612         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5613         Cvar_RegisterVariable(&r_motionblur_randomize);
5614         Cvar_RegisterVariable(&r_damageblur);
5615         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5616         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5617         Cvar_RegisterVariable(&r_equalize_entities_by);
5618         Cvar_RegisterVariable(&r_equalize_entities_to);
5619         Cvar_RegisterVariable(&r_depthfirst);
5620         Cvar_RegisterVariable(&r_useinfinitefarclip);
5621         Cvar_RegisterVariable(&r_farclip_base);
5622         Cvar_RegisterVariable(&r_farclip_world);
5623         Cvar_RegisterVariable(&r_nearclip);
5624         Cvar_RegisterVariable(&r_showbboxes);
5625         Cvar_RegisterVariable(&r_showsurfaces);
5626         Cvar_RegisterVariable(&r_showtris);
5627         Cvar_RegisterVariable(&r_shownormals);
5628         Cvar_RegisterVariable(&r_showlighting);
5629         Cvar_RegisterVariable(&r_showshadowvolumes);
5630         Cvar_RegisterVariable(&r_showcollisionbrushes);
5631         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5632         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5633         Cvar_RegisterVariable(&r_showdisabledepthtest);
5634         Cvar_RegisterVariable(&r_drawportals);
5635         Cvar_RegisterVariable(&r_drawentities);
5636         Cvar_RegisterVariable(&r_cullentities_trace);
5637         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5638         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5639         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5640         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5641         Cvar_RegisterVariable(&r_drawviewmodel);
5642         Cvar_RegisterVariable(&r_speeds);
5643         Cvar_RegisterVariable(&r_fullbrights);
5644         Cvar_RegisterVariable(&r_wateralpha);
5645         Cvar_RegisterVariable(&r_dynamic);
5646         Cvar_RegisterVariable(&r_fullbright);
5647         Cvar_RegisterVariable(&r_shadows);
5648         Cvar_RegisterVariable(&r_shadows_darken);
5649         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5650         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5651         Cvar_RegisterVariable(&r_shadows_throwdistance);
5652         Cvar_RegisterVariable(&r_shadows_throwdirection);
5653         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5654         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5655         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5656         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5657         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5658         Cvar_RegisterVariable(&r_fog_exp2);
5659         Cvar_RegisterVariable(&r_drawfog);
5660         Cvar_RegisterVariable(&r_transparentdepthmasking);
5661         Cvar_RegisterVariable(&r_textureunits);
5662         Cvar_RegisterVariable(&gl_combine);
5663         Cvar_RegisterVariable(&r_glsl);
5664         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5665         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5666         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5667         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5668         Cvar_RegisterVariable(&r_glsl_postprocess);
5669         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5670         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5671         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5672         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5673         Cvar_RegisterVariable(&r_water);
5674         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5675         Cvar_RegisterVariable(&r_water_clippingplanebias);
5676         Cvar_RegisterVariable(&r_water_refractdistort);
5677         Cvar_RegisterVariable(&r_water_reflectdistort);
5678         Cvar_RegisterVariable(&r_lerpsprites);
5679         Cvar_RegisterVariable(&r_lerpmodels);
5680         Cvar_RegisterVariable(&r_lerplightstyles);
5681         Cvar_RegisterVariable(&r_waterscroll);
5682         Cvar_RegisterVariable(&r_bloom);
5683         Cvar_RegisterVariable(&r_bloom_colorscale);
5684         Cvar_RegisterVariable(&r_bloom_brighten);
5685         Cvar_RegisterVariable(&r_bloom_blur);
5686         Cvar_RegisterVariable(&r_bloom_resolution);
5687         Cvar_RegisterVariable(&r_bloom_colorexponent);
5688         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5689         Cvar_RegisterVariable(&r_hdr);
5690         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5691         Cvar_RegisterVariable(&r_hdr_glowintensity);
5692         Cvar_RegisterVariable(&r_hdr_range);
5693         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5694         Cvar_RegisterVariable(&developer_texturelogging);
5695         Cvar_RegisterVariable(&gl_lightmaps);
5696         Cvar_RegisterVariable(&r_test);
5697         Cvar_RegisterVariable(&r_batchmode);
5698         Cvar_RegisterVariable(&r_glsl_saturation);
5699         Cvar_RegisterVariable(&r_framedatasize);
5700         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5701                 Cvar_SetValue("r_fullbrights", 0);
5702         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5703
5704         Cvar_RegisterVariable(&r_track_sprites);
5705         Cvar_RegisterVariable(&r_track_sprites_flags);
5706         Cvar_RegisterVariable(&r_track_sprites_scalew);
5707         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5708 }
5709
5710 extern void R_Textures_Init(void);
5711 extern void GL_Draw_Init(void);
5712 extern void GL_Main_Init(void);
5713 extern void R_Shadow_Init(void);
5714 extern void R_Sky_Init(void);
5715 extern void GL_Surf_Init(void);
5716 extern void R_Particles_Init(void);
5717 extern void R_Explosion_Init(void);
5718 extern void gl_backend_init(void);
5719 extern void Sbar_Init(void);
5720 extern void R_LightningBeams_Init(void);
5721 extern void Mod_RenderInit(void);
5722 extern void Font_Init(void);
5723
5724 void Render_Init(void)
5725 {
5726         gl_backend_init();
5727         R_Textures_Init();
5728         GL_Main_Init();
5729         Font_Init();
5730         GL_Draw_Init();
5731         R_Shadow_Init();
5732         R_Sky_Init();
5733         GL_Surf_Init();
5734         Sbar_Init();
5735         R_Particles_Init();
5736         R_Explosion_Init();
5737         R_LightningBeams_Init();
5738         Mod_RenderInit();
5739 }
5740
5741 /*
5742 ===============
5743 GL_Init
5744 ===============
5745 */
5746 extern char *ENGINE_EXTENSIONS;
5747 void GL_Init (void)
5748 {
5749         gl_renderer = (const char *)qglGetString(GL_RENDERER);
5750         gl_vendor = (const char *)qglGetString(GL_VENDOR);
5751         gl_version = (const char *)qglGetString(GL_VERSION);
5752         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5753
5754         if (!gl_extensions)
5755                 gl_extensions = "";
5756         if (!gl_platformextensions)
5757                 gl_platformextensions = "";
5758
5759         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5760         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5761         Con_Printf("GL_VERSION: %s\n", gl_version);
5762         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5763         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5764
5765         VID_CheckExtensions();
5766
5767         // LordHavoc: report supported extensions
5768         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5769
5770         // clear to black (loading plaque will be seen over this)
5771         CHECKGLERROR
5772         qglClearColor(0,0,0,1);CHECKGLERROR
5773         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5774 }
5775
5776 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5777 {
5778         int i;
5779         mplane_t *p;
5780         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5781         {
5782                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5783                 if (i == 4)
5784                         continue;
5785                 p = r_refdef.view.frustum + i;
5786                 switch(p->signbits)
5787                 {
5788                 default:
5789                 case 0:
5790                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5791                                 return true;
5792                         break;
5793                 case 1:
5794                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5795                                 return true;
5796                         break;
5797                 case 2:
5798                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5799                                 return true;
5800                         break;
5801                 case 3:
5802                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5803                                 return true;
5804                         break;
5805                 case 4:
5806                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5807                                 return true;
5808                         break;
5809                 case 5:
5810                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5811                                 return true;
5812                         break;
5813                 case 6:
5814                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5815                                 return true;
5816                         break;
5817                 case 7:
5818                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5819                                 return true;
5820                         break;
5821                 }
5822         }
5823         return false;
5824 }
5825
5826 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5827 {
5828         int i;
5829         const mplane_t *p;
5830         for (i = 0;i < numplanes;i++)
5831         {
5832                 p = planes + i;
5833                 switch(p->signbits)
5834                 {
5835                 default:
5836                 case 0:
5837                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5838                                 return true;
5839                         break;
5840                 case 1:
5841                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5842                                 return true;
5843                         break;
5844                 case 2:
5845                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5846                                 return true;
5847                         break;
5848                 case 3:
5849                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5850                                 return true;
5851                         break;
5852                 case 4:
5853                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5854                                 return true;
5855                         break;
5856                 case 5:
5857                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5858                                 return true;
5859                         break;
5860                 case 6:
5861                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5862                                 return true;
5863                         break;
5864                 case 7:
5865                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5866                                 return true;
5867                         break;
5868                 }
5869         }
5870         return false;
5871 }
5872
5873 //==================================================================================
5874
5875 // LordHavoc: this stores temporary data used within the same frame
5876
5877 qboolean r_framedata_failed;
5878 static size_t r_framedata_size;
5879 static size_t r_framedata_current;
5880 static void *r_framedata_base;
5881
5882 void R_FrameData_Reset(void)
5883 {
5884         if (r_framedata_base)
5885                 Mem_Free(r_framedata_base);
5886         r_framedata_base = NULL;
5887         r_framedata_size = 0;
5888         r_framedata_current = 0;
5889         r_framedata_failed = false;
5890 }
5891
5892 void R_FrameData_NewFrame(void)
5893 {
5894         size_t wantedsize;
5895         if (r_framedata_failed)
5896                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
5897         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
5898         wantedsize = bound(65536, wantedsize, 128*1024*1024);
5899         if (r_framedata_size != wantedsize)
5900         {
5901                 r_framedata_size = wantedsize;
5902                 if (r_framedata_base)
5903                         Mem_Free(r_framedata_base);
5904                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
5905         }
5906         r_framedata_current = 0;
5907         r_framedata_failed = false;
5908 }
5909
5910 void *R_FrameData_Alloc(size_t size)
5911 {
5912         void *data;
5913
5914         // align to 16 byte boundary
5915         size = (size + 15) & ~15;
5916         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
5917         r_framedata_current += size;
5918
5919         // check overflow
5920         if (r_framedata_current > r_framedata_size)
5921                 r_framedata_failed = true;
5922
5923         // return NULL on everything after a failure
5924         if (r_framedata_failed)
5925                 return NULL;
5926
5927         return data;
5928 }
5929
5930 void *R_FrameData_Store(size_t size, void *data)
5931 {
5932         void *d = R_FrameData_Alloc(size);
5933         if (d)
5934                 memcpy(d, data, size);
5935         return d;
5936 }
5937
5938 //==================================================================================
5939
5940 // LordHavoc: animcache originally written by Echon, rewritten since then
5941
5942 /**
5943  * Animation cache prevents re-generating mesh data for an animated model
5944  * multiple times in one frame for lighting, shadowing, reflections, etc.
5945  */
5946
5947 void R_AnimCache_Free(void)
5948 {
5949 }
5950
5951 void R_AnimCache_ClearCache(void)
5952 {
5953         int i;
5954         entity_render_t *ent;
5955
5956         for (i = 0;i < r_refdef.scene.numentities;i++)
5957         {
5958                 ent = r_refdef.scene.entities[i];
5959                 ent->animcache_vertex3f = NULL;
5960                 ent->animcache_normal3f = NULL;
5961                 ent->animcache_svector3f = NULL;
5962                 ent->animcache_tvector3f = NULL;
5963         }
5964 }
5965
5966 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5967 {
5968         dp_model_t *model = ent->model;
5969         int numvertices;
5970         // see if it's already cached this frame
5971         if (ent->animcache_vertex3f)
5972         {
5973                 // add normals/tangents if needed
5974                 if (wantnormals || wanttangents)
5975                 {
5976                         if (ent->animcache_normal3f)
5977                                 wantnormals = false;
5978                         if (ent->animcache_svector3f)
5979                                 wanttangents = false;
5980                         if (wantnormals || wanttangents)
5981                         {
5982                                 numvertices = model->surfmesh.num_vertices;
5983                                 if (wantnormals)
5984                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5985                                 if (wanttangents)
5986                                 {
5987                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5988                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
5989                                 }
5990                                 if (!r_framedata_failed)
5991                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5992                         }
5993                 }
5994         }
5995         else
5996         {
5997                 // see if this ent is worth caching
5998                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
5999                         return false;
6000                 // get some memory for this entity and generate mesh data
6001                 numvertices = model->surfmesh.num_vertices;
6002                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6003                 if (wantnormals)
6004                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6005                 if (wanttangents)
6006                 {
6007                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6008                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6009                 }
6010                 if (!r_framedata_failed)
6011                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6012         }
6013         return !r_framedata_failed;
6014 }
6015
6016 void R_AnimCache_CacheVisibleEntities(void)
6017 {
6018         int i;
6019         qboolean wantnormals = !r_showsurfaces.integer;
6020         qboolean wanttangents = !r_showsurfaces.integer;
6021
6022         switch(vid.renderpath)
6023         {
6024         case RENDERPATH_GL20:
6025         case RENDERPATH_CGGL:
6026                 break;
6027         case RENDERPATH_GL13:
6028         case RENDERPATH_GL11:
6029                 wanttangents = false;
6030                 break;
6031         }
6032
6033         // TODO: thread this
6034         // NOTE: R_PrepareRTLights() also caches entities
6035
6036         for (i = 0;i < r_refdef.scene.numentities;i++)
6037                 if (r_refdef.viewcache.entityvisible[i])
6038                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6039
6040         if (r_shadows.integer)
6041                 for (i = 0;i < r_refdef.scene.numentities;i++)
6042                         if (!r_refdef.viewcache.entityvisible[i])
6043                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6044 }
6045
6046 //==================================================================================
6047
6048 static void R_View_UpdateEntityLighting (void)
6049 {
6050         int i;
6051         entity_render_t *ent;
6052         vec3_t tempdiffusenormal, avg;
6053         vec_t f, fa, fd, fdd;
6054
6055         for (i = 0;i < r_refdef.scene.numentities;i++)
6056         {
6057                 ent = r_refdef.scene.entities[i];
6058
6059                 // skip unseen models
6060                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6061                         continue;
6062
6063                 // skip bsp models
6064                 if (ent->model && ent->model->brush.num_leafs)
6065                 {
6066                         // TODO: use modellight for r_ambient settings on world?
6067                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6068                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6069                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6070                         continue;
6071                 }
6072
6073                 // fetch the lighting from the worldmodel data
6074                 VectorClear(ent->modellight_ambient);
6075                 VectorClear(ent->modellight_diffuse);
6076                 VectorClear(tempdiffusenormal);
6077                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6078                 {
6079                         vec3_t org;
6080                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6081                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6082                         if(ent->flags & RENDER_EQUALIZE)
6083                         {
6084                                 // first fix up ambient lighting...
6085                                 if(r_equalize_entities_minambient.value > 0)
6086                                 {
6087                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6088                                         if(fd > 0)
6089                                         {
6090                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6091                                                 if(fa < r_equalize_entities_minambient.value * fd)
6092                                                 {
6093                                                         // solve:
6094                                                         //   fa'/fd' = minambient
6095                                                         //   fa'+0.25*fd' = fa+0.25*fd
6096                                                         //   ...
6097                                                         //   fa' = fd' * minambient
6098                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6099                                                         //   ...
6100                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6101                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6102                                                         //   ...
6103                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6104                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
6105                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6106                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6107                                                 }
6108                                         }
6109                                 }
6110
6111                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6112                                 {
6113                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6114                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6115                                         if(f > 0)
6116                                         {
6117                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6118                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6119                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6120                                         }
6121                                 }
6122                         }
6123                 }
6124                 else // highly rare
6125                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6126
6127                 // move the light direction into modelspace coordinates for lighting code
6128                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6129                 if(VectorLength2(ent->modellight_lightdir) == 0)
6130                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6131                 VectorNormalize(ent->modellight_lightdir);
6132         }
6133 }
6134
6135 #define MAX_LINEOFSIGHTTRACES 64
6136
6137 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6138 {
6139         int i;
6140         vec3_t boxmins, boxmaxs;
6141         vec3_t start;
6142         vec3_t end;
6143         dp_model_t *model = r_refdef.scene.worldmodel;
6144
6145         if (!model || !model->brush.TraceLineOfSight)
6146                 return true;
6147
6148         // expand the box a little
6149         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6150         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6151         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6152         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6153         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6154         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6155
6156         // try center
6157         VectorCopy(eye, start);
6158         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6159         if (model->brush.TraceLineOfSight(model, start, end))
6160                 return true;
6161
6162         // try various random positions
6163         for (i = 0;i < numsamples;i++)
6164         {
6165                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6166                 if (model->brush.TraceLineOfSight(model, start, end))
6167                         return true;
6168         }
6169
6170         return false;
6171 }
6172
6173
6174 static void R_View_UpdateEntityVisible (void)
6175 {
6176         int i;
6177         int renderimask;
6178         int samples;
6179         entity_render_t *ent;
6180
6181         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6182         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6183         {
6184                 // worldmodel can check visibility
6185                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6186                 for (i = 0;i < r_refdef.scene.numentities;i++)
6187                 {
6188                         ent = r_refdef.scene.entities[i];
6189                         if (!(ent->flags & renderimask))
6190                         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)))
6191                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
6192                                 r_refdef.viewcache.entityvisible[i] = true;
6193                 }
6194                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6195                 {
6196                         for (i = 0;i < r_refdef.scene.numentities;i++)
6197                         {
6198                                 ent = r_refdef.scene.entities[i];
6199                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6200                                 {
6201                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6202                                         if (samples < 0)
6203                                                 continue; // temp entities do pvs only
6204                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6205                                                 ent->last_trace_visibility = realtime;
6206                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6207                                                 r_refdef.viewcache.entityvisible[i] = 0;
6208                                 }
6209                         }
6210                 }
6211         }
6212         else
6213         {
6214                 // no worldmodel or it can't check visibility
6215                 for (i = 0;i < r_refdef.scene.numentities;i++)
6216                 {
6217                         ent = r_refdef.scene.entities[i];
6218                         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));
6219                 }
6220         }
6221 }
6222
6223 /// only used if skyrendermasked, and normally returns false
6224 int R_DrawBrushModelsSky (void)
6225 {
6226         int i, sky;
6227         entity_render_t *ent;
6228
6229         sky = false;
6230         for (i = 0;i < r_refdef.scene.numentities;i++)
6231         {
6232                 if (!r_refdef.viewcache.entityvisible[i])
6233                         continue;
6234                 ent = r_refdef.scene.entities[i];
6235                 if (!ent->model || !ent->model->DrawSky)
6236                         continue;
6237                 ent->model->DrawSky(ent);
6238                 sky = true;
6239         }
6240         return sky;
6241 }
6242
6243 static void R_DrawNoModel(entity_render_t *ent);
6244 static void R_DrawModels(void)
6245 {
6246         int i;
6247         entity_render_t *ent;
6248
6249         for (i = 0;i < r_refdef.scene.numentities;i++)
6250         {
6251                 if (!r_refdef.viewcache.entityvisible[i])
6252                         continue;
6253                 ent = r_refdef.scene.entities[i];
6254                 r_refdef.stats.entities++;
6255                 if (ent->model && ent->model->Draw != NULL)
6256                         ent->model->Draw(ent);
6257                 else
6258                         R_DrawNoModel(ent);
6259         }
6260 }
6261
6262 static void R_DrawModelsDepth(void)
6263 {
6264         int i;
6265         entity_render_t *ent;
6266
6267         for (i = 0;i < r_refdef.scene.numentities;i++)
6268         {
6269                 if (!r_refdef.viewcache.entityvisible[i])
6270                         continue;
6271                 ent = r_refdef.scene.entities[i];
6272                 if (ent->model && ent->model->DrawDepth != NULL)
6273                         ent->model->DrawDepth(ent);
6274         }
6275 }
6276
6277 static void R_DrawModelsDebug(void)
6278 {
6279         int i;
6280         entity_render_t *ent;
6281
6282         for (i = 0;i < r_refdef.scene.numentities;i++)
6283         {
6284                 if (!r_refdef.viewcache.entityvisible[i])
6285                         continue;
6286                 ent = r_refdef.scene.entities[i];
6287                 if (ent->model && ent->model->DrawDebug != NULL)
6288                         ent->model->DrawDebug(ent);
6289         }
6290 }
6291
6292 static void R_DrawModelsAddWaterPlanes(void)
6293 {
6294         int i;
6295         entity_render_t *ent;
6296
6297         for (i = 0;i < r_refdef.scene.numentities;i++)
6298         {
6299                 if (!r_refdef.viewcache.entityvisible[i])
6300                         continue;
6301                 ent = r_refdef.scene.entities[i];
6302                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6303                         ent->model->DrawAddWaterPlanes(ent);
6304         }
6305 }
6306
6307 static void R_View_SetFrustum(void)
6308 {
6309         int i;
6310         double slopex, slopey;
6311         vec3_t forward, left, up, origin;
6312
6313         // we can't trust r_refdef.view.forward and friends in reflected scenes
6314         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6315
6316 #if 0
6317         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6318         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6319         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6320         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6321         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6322         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6323         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6324         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6325         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6326         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6327         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6328         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6329 #endif
6330
6331 #if 0
6332         zNear = r_refdef.nearclip;
6333         nudge = 1.0 - 1.0 / (1<<23);
6334         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6335         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6336         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6337         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6338         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6339         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6340         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6341         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6342 #endif
6343
6344
6345
6346 #if 0
6347         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6348         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6349         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6350         r_refdef.view.frustum[0].dist = m[15] - m[12];
6351
6352         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6353         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6354         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6355         r_refdef.view.frustum[1].dist = m[15] + m[12];
6356
6357         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6358         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6359         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6360         r_refdef.view.frustum[2].dist = m[15] - m[13];
6361
6362         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6363         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6364         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6365         r_refdef.view.frustum[3].dist = m[15] + m[13];
6366
6367         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6368         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6369         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6370         r_refdef.view.frustum[4].dist = m[15] - m[14];
6371
6372         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6373         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6374         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6375         r_refdef.view.frustum[5].dist = m[15] + m[14];
6376 #endif
6377
6378         if (r_refdef.view.useperspective)
6379         {
6380                 slopex = 1.0 / r_refdef.view.frustum_x;
6381                 slopey = 1.0 / r_refdef.view.frustum_y;
6382                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6383                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6384                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6385                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6386                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6387
6388                 // Leaving those out was a mistake, those were in the old code, and they
6389                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6390                 // I couldn't reproduce it after adding those normalizations. --blub
6391                 VectorNormalize(r_refdef.view.frustum[0].normal);
6392                 VectorNormalize(r_refdef.view.frustum[1].normal);
6393                 VectorNormalize(r_refdef.view.frustum[2].normal);
6394                 VectorNormalize(r_refdef.view.frustum[3].normal);
6395
6396                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6397                 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]);
6398                 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]);
6399                 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]);
6400                 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]);
6401
6402                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6403                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6404                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6405                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6406                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6407         }
6408         else
6409         {
6410                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6411                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6412                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6413                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6414                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6415                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6416                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6417                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6418                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6419                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6420         }
6421         r_refdef.view.numfrustumplanes = 5;
6422
6423         if (r_refdef.view.useclipplane)
6424         {
6425                 r_refdef.view.numfrustumplanes = 6;
6426                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6427         }
6428
6429         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6430                 PlaneClassify(r_refdef.view.frustum + i);
6431
6432         // LordHavoc: note to all quake engine coders, Quake had a special case
6433         // for 90 degrees which assumed a square view (wrong), so I removed it,
6434         // Quake2 has it disabled as well.
6435
6436         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6437         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6438         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6439         //PlaneClassify(&frustum[0]);
6440
6441         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6442         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6443         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6444         //PlaneClassify(&frustum[1]);
6445
6446         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6447         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6448         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6449         //PlaneClassify(&frustum[2]);
6450
6451         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6452         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6453         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6454         //PlaneClassify(&frustum[3]);
6455
6456         // nearclip plane
6457         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6458         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6459         //PlaneClassify(&frustum[4]);
6460 }
6461
6462 void R_View_Update(void)
6463 {
6464         R_Main_ResizeViewCache();
6465         R_View_SetFrustum();
6466         R_View_WorldVisibility(r_refdef.view.useclipplane);
6467         R_View_UpdateEntityVisible();
6468         R_View_UpdateEntityLighting();
6469 }
6470
6471 void R_SetupView(qboolean allowwaterclippingplane)
6472 {
6473         const float *customclipplane = NULL;
6474         float plane[4];
6475         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6476         {
6477                 // LordHavoc: couldn't figure out how to make this approach the
6478                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6479                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6480                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6481                         dist = r_refdef.view.clipplane.dist;
6482                 plane[0] = r_refdef.view.clipplane.normal[0];
6483                 plane[1] = r_refdef.view.clipplane.normal[1];
6484                 plane[2] = r_refdef.view.clipplane.normal[2];
6485                 plane[3] = dist;
6486                 customclipplane = plane;
6487         }
6488
6489         if (!r_refdef.view.useperspective)
6490                 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);
6491         else if (vid.stencil && r_useinfinitefarclip.integer)
6492                 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);
6493         else
6494                 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);
6495         R_SetViewport(&r_refdef.view.viewport);
6496 }
6497
6498 void R_EntityMatrix(const matrix4x4_t *matrix)
6499 {
6500         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6501         {
6502                 gl_modelmatrixchanged = false;
6503                 gl_modelmatrix = *matrix;
6504                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6505                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6506                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6507                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6508                 CHECKGLERROR
6509                 switch(vid.renderpath)
6510                 {
6511                 case RENDERPATH_GL20:
6512                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6513                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6514                         break;
6515                 case RENDERPATH_CGGL:
6516 #ifdef SUPPORTCG
6517                         CHECKCGERROR
6518                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6519                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6520 #endif
6521                         break;
6522                 case RENDERPATH_GL13:
6523                 case RENDERPATH_GL11:
6524                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6525                         break;
6526                 }
6527         }
6528 }
6529
6530 void R_ResetViewRendering2D(void)
6531 {
6532         r_viewport_t viewport;
6533         DrawQ_Finish();
6534
6535         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6536         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);
6537         R_SetViewport(&viewport);
6538         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6539         GL_Color(1, 1, 1, 1);
6540         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6541         GL_BlendFunc(GL_ONE, GL_ZERO);
6542         GL_AlphaTest(false);
6543         GL_ScissorTest(false);
6544         GL_DepthMask(false);
6545         GL_DepthRange(0, 1);
6546         GL_DepthTest(false);
6547         R_EntityMatrix(&identitymatrix);
6548         R_Mesh_ResetTextureState();
6549         GL_PolygonOffset(0, 0);
6550         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6551         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6552         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6553         qglStencilMask(~0);CHECKGLERROR
6554         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6555         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6556         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6557 }
6558
6559 void R_ResetViewRendering3D(void)
6560 {
6561         DrawQ_Finish();
6562
6563         R_SetupView(true);
6564         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6565         GL_Color(1, 1, 1, 1);
6566         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6567         GL_BlendFunc(GL_ONE, GL_ZERO);
6568         GL_AlphaTest(false);
6569         GL_ScissorTest(true);
6570         GL_DepthMask(true);
6571         GL_DepthRange(0, 1);
6572         GL_DepthTest(true);
6573         R_EntityMatrix(&identitymatrix);
6574         R_Mesh_ResetTextureState();
6575         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6576         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6577         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6578         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6579         qglStencilMask(~0);CHECKGLERROR
6580         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6581         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6582         GL_CullFace(r_refdef.view.cullface_back);
6583 }
6584
6585 void R_RenderScene(void);
6586 void R_RenderWaterPlanes(void);
6587
6588 static void R_Water_StartFrame(void)
6589 {
6590         int i;
6591         int waterwidth, waterheight, texturewidth, textureheight;
6592         r_waterstate_waterplane_t *p;
6593
6594         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6595                 return;
6596
6597         switch(vid.renderpath)
6598         {
6599         case RENDERPATH_GL20:
6600         case RENDERPATH_CGGL:
6601                 break;
6602         case RENDERPATH_GL13:
6603         case RENDERPATH_GL11:
6604                 return;
6605         }
6606
6607         // set waterwidth and waterheight to the water resolution that will be
6608         // used (often less than the screen resolution for faster rendering)
6609         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6610         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6611
6612         // calculate desired texture sizes
6613         // can't use water if the card does not support the texture size
6614         if (!r_water.integer || r_showsurfaces.integer)
6615                 texturewidth = textureheight = waterwidth = waterheight = 0;
6616         else if (vid.support.arb_texture_non_power_of_two)
6617         {
6618                 texturewidth = waterwidth;
6619                 textureheight = waterheight;
6620         }
6621         else
6622         {
6623                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6624                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6625         }
6626
6627         // allocate textures as needed
6628         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6629         {
6630                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6631                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6632                 {
6633                         if (p->texture_refraction)
6634                                 R_FreeTexture(p->texture_refraction);
6635                         p->texture_refraction = NULL;
6636                         if (p->texture_reflection)
6637                                 R_FreeTexture(p->texture_reflection);
6638                         p->texture_reflection = NULL;
6639                 }
6640                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6641                 r_waterstate.texturewidth = texturewidth;
6642                 r_waterstate.textureheight = textureheight;
6643         }
6644
6645         if (r_waterstate.texturewidth)
6646         {
6647                 r_waterstate.enabled = true;
6648
6649                 // when doing a reduced render (HDR) we want to use a smaller area
6650                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6651                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6652
6653                 // set up variables that will be used in shader setup
6654                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6655                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6656                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6657                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6658         }
6659
6660         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6661         r_waterstate.numwaterplanes = 0;
6662 }
6663
6664 void R_Water_AddWaterPlane(msurface_t *surface)
6665 {
6666         int triangleindex, planeindex;
6667         const int *e;
6668         vec3_t vert[3];
6669         vec3_t normal;
6670         vec3_t center;
6671         mplane_t plane;
6672         r_waterstate_waterplane_t *p;
6673         texture_t *t = R_GetCurrentTexture(surface->texture);
6674         // just use the first triangle with a valid normal for any decisions
6675         VectorClear(normal);
6676         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6677         {
6678                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6679                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6680                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6681                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6682                 if (VectorLength2(normal) >= 0.001)
6683                         break;
6684         }
6685
6686         VectorCopy(normal, plane.normal);
6687         VectorNormalize(plane.normal);
6688         plane.dist = DotProduct(vert[0], plane.normal);
6689         PlaneClassify(&plane);
6690         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6691         {
6692                 // skip backfaces (except if nocullface is set)
6693                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6694                         return;
6695                 VectorNegate(plane.normal, plane.normal);
6696                 plane.dist *= -1;
6697                 PlaneClassify(&plane);
6698         }
6699
6700
6701         // find a matching plane if there is one
6702         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6703                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6704                         break;
6705         if (planeindex >= r_waterstate.maxwaterplanes)
6706                 return; // nothing we can do, out of planes
6707
6708         // if this triangle does not fit any known plane rendered this frame, add one
6709         if (planeindex >= r_waterstate.numwaterplanes)
6710         {
6711                 // store the new plane
6712                 r_waterstate.numwaterplanes++;
6713                 p->plane = plane;
6714                 // clear materialflags and pvs
6715                 p->materialflags = 0;
6716                 p->pvsvalid = false;
6717         }
6718         // merge this surface's materialflags into the waterplane
6719         p->materialflags |= t->currentmaterialflags;
6720         // merge this surface's PVS into the waterplane
6721         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6722         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6723          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6724         {
6725                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6726                 p->pvsvalid = true;
6727         }
6728 }
6729
6730 static void R_Water_ProcessPlanes(void)
6731 {
6732         r_refdef_view_t originalview;
6733         r_refdef_view_t myview;
6734         int planeindex;
6735         r_waterstate_waterplane_t *p;
6736
6737         originalview = r_refdef.view;
6738
6739         // make sure enough textures are allocated
6740         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6741         {
6742                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6743                 {
6744                         if (!p->texture_refraction)
6745                                 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, NULL);
6746                         if (!p->texture_refraction)
6747                                 goto error;
6748                 }
6749
6750                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6751                 {
6752                         if (!p->texture_reflection)
6753                                 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, NULL);
6754                         if (!p->texture_reflection)
6755                                 goto error;
6756                 }
6757         }
6758
6759         // render views
6760         r_refdef.view = originalview;
6761         r_refdef.view.showdebug = false;
6762         r_refdef.view.width = r_waterstate.waterwidth;
6763         r_refdef.view.height = r_waterstate.waterheight;
6764         r_refdef.view.useclipplane = true;
6765         myview = r_refdef.view;
6766         r_waterstate.renderingscene = true;
6767         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6768         {
6769                 // render the normal view scene and copy into texture
6770                 // (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)
6771                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6772                 {
6773                         r_refdef.view = myview;
6774                         r_refdef.view.clipplane = p->plane;
6775                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6776                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6777                         PlaneClassify(&r_refdef.view.clipplane);
6778
6779                         R_ResetViewRendering3D();
6780                         R_ClearScreen(r_refdef.fogenabled);
6781                         R_View_Update();
6782                         R_RenderScene();
6783
6784                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6785                 }
6786
6787                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6788                 {
6789                         r_refdef.view = myview;
6790                         // render reflected scene and copy into texture
6791                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6792                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6793                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6794                         r_refdef.view.clipplane = p->plane;
6795                         // reverse the cullface settings for this render
6796                         r_refdef.view.cullface_front = GL_FRONT;
6797                         r_refdef.view.cullface_back = GL_BACK;
6798                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6799                         {
6800                                 r_refdef.view.usecustompvs = true;
6801                                 if (p->pvsvalid)
6802                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6803                                 else
6804                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6805                         }
6806
6807                         R_ResetViewRendering3D();
6808                         R_ClearScreen(r_refdef.fogenabled);
6809                         R_View_Update();
6810                         R_RenderScene();
6811
6812                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6813                 }
6814         }
6815         r_waterstate.renderingscene = false;
6816         r_refdef.view = originalview;
6817         R_ResetViewRendering3D();
6818         R_ClearScreen(r_refdef.fogenabled);
6819         R_View_Update();
6820         return;
6821 error:
6822         r_refdef.view = originalview;
6823         r_waterstate.renderingscene = false;
6824         Cvar_SetValueQuick(&r_water, 0);
6825         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6826         return;
6827 }
6828
6829 void R_Bloom_StartFrame(void)
6830 {
6831         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6832
6833         switch(vid.renderpath)
6834         {
6835         case RENDERPATH_GL20:
6836         case RENDERPATH_CGGL:
6837                 break;
6838         case RENDERPATH_GL13:
6839         case RENDERPATH_GL11:
6840                 return;
6841         }
6842
6843         // set bloomwidth and bloomheight to the bloom resolution that will be
6844         // used (often less than the screen resolution for faster rendering)
6845         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6846         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6847         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6848         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6849         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6850
6851         // calculate desired texture sizes
6852         if (vid.support.arb_texture_non_power_of_two)
6853         {
6854                 screentexturewidth = r_refdef.view.width;
6855                 screentextureheight = r_refdef.view.height;
6856                 bloomtexturewidth = r_bloomstate.bloomwidth;
6857                 bloomtextureheight = r_bloomstate.bloomheight;
6858         }
6859         else
6860         {
6861                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6862                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6863                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6864                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6865         }
6866
6867         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 > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6868         {
6869                 Cvar_SetValueQuick(&r_hdr, 0);
6870                 Cvar_SetValueQuick(&r_bloom, 0);
6871                 Cvar_SetValueQuick(&r_motionblur, 0);
6872                 Cvar_SetValueQuick(&r_damageblur, 0);
6873         }
6874
6875         if (!(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)))
6876                 screentexturewidth = screentextureheight = 0;
6877         if (!r_hdr.integer && !r_bloom.integer)
6878                 bloomtexturewidth = bloomtextureheight = 0;
6879
6880         // allocate textures as needed
6881         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
6882         {
6883                 if (r_bloomstate.texture_screen)
6884                         R_FreeTexture(r_bloomstate.texture_screen);
6885                 r_bloomstate.texture_screen = NULL;
6886                 r_bloomstate.screentexturewidth = screentexturewidth;
6887                 r_bloomstate.screentextureheight = screentextureheight;
6888                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6889                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
6890         }
6891         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
6892         {
6893                 if (r_bloomstate.texture_bloom)
6894                         R_FreeTexture(r_bloomstate.texture_bloom);
6895                 r_bloomstate.texture_bloom = NULL;
6896                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6897                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6898                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6899                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6900         }
6901
6902         // when doing a reduced render (HDR) we want to use a smaller area
6903         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6904         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6905         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6906         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6907         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6908
6909         // set up a texcoord array for the full resolution screen image
6910         // (we have to keep this around to copy back during final render)
6911         r_bloomstate.screentexcoord2f[0] = 0;
6912         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
6913         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
6914         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
6915         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
6916         r_bloomstate.screentexcoord2f[5] = 0;
6917         r_bloomstate.screentexcoord2f[6] = 0;
6918         r_bloomstate.screentexcoord2f[7] = 0;
6919
6920         // set up a texcoord array for the reduced resolution bloom image
6921         // (which will be additive blended over the screen image)
6922         r_bloomstate.bloomtexcoord2f[0] = 0;
6923         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6924         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6925         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6926         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6927         r_bloomstate.bloomtexcoord2f[5] = 0;
6928         r_bloomstate.bloomtexcoord2f[6] = 0;
6929         r_bloomstate.bloomtexcoord2f[7] = 0;
6930
6931         if (r_hdr.integer || r_bloom.integer)
6932         {
6933                 r_bloomstate.enabled = true;
6934                 r_bloomstate.hdr = r_hdr.integer != 0;
6935         }
6936
6937         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);
6938 }
6939
6940 void R_Bloom_CopyBloomTexture(float colorscale)
6941 {
6942         r_refdef.stats.bloom++;
6943
6944         // scale down screen texture to the bloom texture size
6945         CHECKGLERROR
6946         R_SetViewport(&r_bloomstate.viewport);
6947         GL_BlendFunc(GL_ONE, GL_ZERO);
6948         GL_Color(colorscale, colorscale, colorscale, 1);
6949         // TODO: optimize with multitexture or GLSL
6950         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
6951         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6952         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
6953         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6954
6955         // we now have a bloom image in the framebuffer
6956         // copy it into the bloom image texture for later processing
6957         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6958         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6959 }
6960
6961 void R_Bloom_CopyHDRTexture(void)
6962 {
6963         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6964         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6965 }
6966
6967 void R_Bloom_MakeTexture(void)
6968 {
6969         int x, range, dir;
6970         float xoffset, yoffset, r, brighten;
6971
6972         r_refdef.stats.bloom++;
6973
6974         R_ResetViewRendering2D();
6975         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
6976         R_Mesh_ColorPointer(NULL, 0, 0);
6977
6978         // we have a bloom image in the framebuffer
6979         CHECKGLERROR
6980         R_SetViewport(&r_bloomstate.viewport);
6981
6982         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6983         {
6984                 x *= 2;
6985                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6986                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6987                 GL_Color(r, r, r, 1);
6988                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6989                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
6990                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
6991                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6992
6993                 // copy the vertically blurred bloom view to a texture
6994                 GL_ActiveTexture(0);
6995                 CHECKGLERROR
6996                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
6997                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6998         }
6999
7000         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7001         brighten = r_bloom_brighten.value;
7002         if (r_hdr.integer)
7003                 brighten *= r_hdr_range.value;
7004         brighten = sqrt(brighten);
7005         if(range >= 1)
7006                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7007         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7008         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7009
7010         for (dir = 0;dir < 2;dir++)
7011         {
7012                 // blend on at multiple vertical offsets to achieve a vertical blur
7013                 // TODO: do offset blends using GLSL
7014                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7015                 GL_BlendFunc(GL_ONE, GL_ZERO);
7016                 for (x = -range;x <= range;x++)
7017                 {
7018                         if (!dir){xoffset = 0;yoffset = x;}
7019                         else {xoffset = x;yoffset = 0;}
7020                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7021                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7022                         // compute a texcoord array with the specified x and y offset
7023                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7024                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7025                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7026                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7027                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7028                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7029                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7030                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7031                         // this r value looks like a 'dot' particle, fading sharply to
7032                         // black at the edges
7033                         // (probably not realistic but looks good enough)
7034                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7035                         //r = brighten/(range*2+1);
7036                         r = brighten / (range * 2 + 1);
7037                         if(range >= 1)
7038                                 r *= (1 - x*x/(float)(range*range));
7039                         GL_Color(r, r, r, 1);
7040                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7041                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7042                         GL_BlendFunc(GL_ONE, GL_ONE);
7043                 }
7044
7045                 // copy the vertically blurred bloom view to a texture
7046                 GL_ActiveTexture(0);
7047                 CHECKGLERROR
7048                 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);CHECKGLERROR
7049                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7050         }
7051
7052         // apply subtract last
7053         // (just like it would be in a GLSL shader)
7054         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7055         {
7056                 GL_BlendFunc(GL_ONE, GL_ZERO);
7057                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7058                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7059                 GL_Color(1, 1, 1, 1);
7060                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7061                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7062
7063                 GL_BlendFunc(GL_ONE, GL_ONE);
7064                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7065                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7066                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7067                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7068                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7069                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7070                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7071
7072                 // copy the darkened bloom view to a texture
7073                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7074                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7075         }
7076 }
7077
7078 void R_HDR_RenderBloomTexture(void)
7079 {
7080         int oldwidth, oldheight;
7081         float oldcolorscale;
7082
7083         oldcolorscale = r_refdef.view.colorscale;
7084         oldwidth = r_refdef.view.width;
7085         oldheight = r_refdef.view.height;
7086         r_refdef.view.width = r_bloomstate.bloomwidth;
7087         r_refdef.view.height = r_bloomstate.bloomheight;
7088
7089         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7090         // TODO: add exposure compensation features
7091         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7092
7093         r_refdef.view.showdebug = false;
7094         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7095
7096         R_ResetViewRendering3D();
7097
7098         R_ClearScreen(r_refdef.fogenabled);
7099         if (r_timereport_active)
7100                 R_TimeReport("HDRclear");
7101
7102         R_View_Update();
7103         if (r_timereport_active)
7104                 R_TimeReport("visibility");
7105
7106         // only do secondary renders with HDR if r_hdr is 2 or higher
7107         r_waterstate.numwaterplanes = 0;
7108         if (r_waterstate.enabled && r_hdr.integer >= 2)
7109                 R_RenderWaterPlanes();
7110
7111         r_refdef.view.showdebug = true;
7112         R_RenderScene();
7113         r_waterstate.numwaterplanes = 0;
7114
7115         R_ResetViewRendering2D();
7116
7117         R_Bloom_CopyHDRTexture();
7118         R_Bloom_MakeTexture();
7119
7120         // restore the view settings
7121         r_refdef.view.width = oldwidth;
7122         r_refdef.view.height = oldheight;
7123         r_refdef.view.colorscale = oldcolorscale;
7124         r_frame++; // used only by R_GetCurrentTexture
7125
7126         R_ResetViewRendering3D();
7127
7128         R_ClearScreen(r_refdef.fogenabled);
7129         if (r_timereport_active)
7130                 R_TimeReport("viewclear");
7131 }
7132
7133 static void R_BlendView(void)
7134 {
7135         unsigned int permutation;
7136         float uservecs[4][4];
7137
7138         switch (vid.renderpath)
7139         {
7140         case RENDERPATH_GL20:
7141         case RENDERPATH_CGGL:
7142                 permutation =
7143                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7144                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7145                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7146                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7147                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7148
7149                 if (r_bloomstate.texture_screen)
7150                 {
7151                         // make sure the buffer is available
7152                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7153
7154                         R_ResetViewRendering2D();
7155                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7156                         R_Mesh_ColorPointer(NULL, 0, 0);
7157
7158                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7159                         {
7160                                 // declare variables
7161                                 float speed;
7162                                 static float avgspeed;
7163
7164                                 speed = VectorLength(cl.movement_velocity);
7165
7166                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7167                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7168
7169                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7170                                 speed = bound(0, speed, 1);
7171                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7172
7173                                 // calculate values into a standard alpha
7174                                 cl.motionbluralpha = 1 - exp(-
7175                                                 (
7176                                                  (r_motionblur.value * speed / 80)
7177                                                  +
7178                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7179                                                 )
7180                                                 /
7181                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7182                                            );
7183
7184                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7185                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7186                                 // apply the blur
7187                                 if (cl.motionbluralpha > 0)
7188                                 {
7189                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7190                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7191                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7192                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7193                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7194                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7195                                 }
7196                         }
7197
7198                         // copy view into the screen texture
7199                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7200                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7201                 }
7202                 else if (!r_bloomstate.texture_bloom)
7203                 {
7204                         // we may still have to do view tint...
7205                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7206                         {
7207                                 // apply a color tint to the whole view
7208                                 R_ResetViewRendering2D();
7209                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7210                                 R_Mesh_ColorPointer(NULL, 0, 0);
7211                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7212                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7213                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7214                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7215                         }
7216                         break; // no screen processing, no bloom, skip it
7217                 }
7218
7219                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7220                 {
7221                         // render simple bloom effect
7222                         // copy the screen and shrink it and darken it for the bloom process
7223                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7224                         // make the bloom texture
7225                         R_Bloom_MakeTexture();
7226                 }
7227
7228 #if _MSC_VER >= 1400
7229 #define sscanf sscanf_s
7230 #endif
7231                 memset(uservecs, 0, sizeof(uservecs));
7232                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7233                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7234                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7235                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7236
7237                 R_ResetViewRendering2D();
7238                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7239                 R_Mesh_ColorPointer(NULL, 0, 0);
7240                 GL_Color(1, 1, 1, 1);
7241                 GL_BlendFunc(GL_ONE, GL_ZERO);
7242                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7243                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7244
7245                 switch(vid.renderpath)
7246                 {
7247                 case RENDERPATH_GL20:
7248                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7249                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7250                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7251                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7252                         if (r_glsl_permutation->loc_ViewTintColor      >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7253                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7254                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7255                         if (r_glsl_permutation->loc_UserVec1           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7256                         if (r_glsl_permutation->loc_UserVec2           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7257                         if (r_glsl_permutation->loc_UserVec3           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7258                         if (r_glsl_permutation->loc_UserVec4           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7259                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7260                         break;
7261                 case RENDERPATH_CGGL:
7262 #ifdef SUPPORTCG
7263                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7264                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7265                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7266                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7267                         if (r_cg_permutation->fp_ViewTintColor     ) cgGLSetParameter4f(     r_cg_permutation->fp_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
7268                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7269                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7270                         if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
7271                         if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
7272                         if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
7273                         if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
7274                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7275 #endif
7276                         break;
7277                 default:
7278                         break;
7279                 }
7280                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7281                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7282                 break;
7283         case RENDERPATH_GL13:
7284         case RENDERPATH_GL11:
7285                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7286                 {
7287                         // apply a color tint to the whole view
7288                         R_ResetViewRendering2D();
7289                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7290                         R_Mesh_ColorPointer(NULL, 0, 0);
7291                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7292                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7293                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7294                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7295                 }
7296                 break;
7297         }
7298 }
7299
7300 matrix4x4_t r_waterscrollmatrix;
7301
7302 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7303 {
7304         if (r_refdef.fog_density)
7305         {
7306                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7307                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7308                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7309
7310                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7311                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7312                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7313                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7314
7315                 {
7316                         vec3_t fogvec;
7317                         VectorCopy(r_refdef.fogcolor, fogvec);
7318                         //   color.rgb *= ContrastBoost * SceneBrightness;
7319                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7320                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7321                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7322                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7323                 }
7324         }
7325 }
7326
7327 void R_UpdateVariables(void)
7328 {
7329         R_Textures_Frame();
7330
7331         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7332
7333         r_refdef.farclip = r_farclip_base.value;
7334         if (r_refdef.scene.worldmodel)
7335                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7336         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7337
7338         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7339                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7340         r_refdef.polygonfactor = 0;
7341         r_refdef.polygonoffset = 0;
7342         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7343         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7344
7345         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7346         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7347         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7348         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7349         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7350         if (r_showsurfaces.integer)
7351         {
7352                 r_refdef.scene.rtworld = false;
7353                 r_refdef.scene.rtworldshadows = false;
7354                 r_refdef.scene.rtdlight = false;
7355                 r_refdef.scene.rtdlightshadows = false;
7356                 r_refdef.lightmapintensity = 0;
7357         }
7358
7359         if (gamemode == GAME_NEHAHRA)
7360         {
7361                 if (gl_fogenable.integer)
7362                 {
7363                         r_refdef.oldgl_fogenable = true;
7364                         r_refdef.fog_density = gl_fogdensity.value;
7365                         r_refdef.fog_red = gl_fogred.value;
7366                         r_refdef.fog_green = gl_foggreen.value;
7367                         r_refdef.fog_blue = gl_fogblue.value;
7368                         r_refdef.fog_alpha = 1;
7369                         r_refdef.fog_start = 0;
7370                         r_refdef.fog_end = gl_skyclip.value;
7371                         r_refdef.fog_height = 1<<30;
7372                         r_refdef.fog_fadedepth = 128;
7373                 }
7374                 else if (r_refdef.oldgl_fogenable)
7375                 {
7376                         r_refdef.oldgl_fogenable = false;
7377                         r_refdef.fog_density = 0;
7378                         r_refdef.fog_red = 0;
7379                         r_refdef.fog_green = 0;
7380                         r_refdef.fog_blue = 0;
7381                         r_refdef.fog_alpha = 0;
7382                         r_refdef.fog_start = 0;
7383                         r_refdef.fog_end = 0;
7384                         r_refdef.fog_height = 1<<30;
7385                         r_refdef.fog_fadedepth = 128;
7386                 }
7387         }
7388
7389         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7390         r_refdef.fog_start = max(0, r_refdef.fog_start);
7391         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7392
7393         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7394
7395         if (r_refdef.fog_density && r_drawfog.integer)
7396         {
7397                 r_refdef.fogenabled = true;
7398                 // this is the point where the fog reaches 0.9986 alpha, which we
7399                 // consider a good enough cutoff point for the texture
7400                 // (0.9986 * 256 == 255.6)
7401                 if (r_fog_exp2.integer)
7402                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7403                 else
7404                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7405                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7406                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7407                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7408                 // fog color was already set
7409                 // update the fog texture
7410                 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)
7411                         R_BuildFogTexture();
7412         }
7413         else
7414                 r_refdef.fogenabled = false;
7415
7416         switch(vid.renderpath)
7417         {
7418         case RENDERPATH_GL20:
7419         case RENDERPATH_CGGL:
7420                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7421                 {
7422                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7423                         {
7424                                 // build GLSL gamma texture
7425 #define RAMPWIDTH 256
7426                                 unsigned short ramp[RAMPWIDTH * 3];
7427                                 unsigned char rampbgr[RAMPWIDTH][4];
7428                                 int i;
7429
7430                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7431
7432                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7433                                 for(i = 0; i < RAMPWIDTH; ++i)
7434                                 {
7435                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7436                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7437                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7438                                         rampbgr[i][3] = 0;
7439                                 }
7440                                 if (r_texture_gammaramps)
7441                                 {
7442                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7443                                 }
7444                                 else
7445                                 {
7446                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
7447                                 }
7448                         }
7449                 }
7450                 else
7451                 {
7452                         // remove GLSL gamma texture
7453                 }
7454                 break;
7455         case RENDERPATH_GL13:
7456         case RENDERPATH_GL11:
7457                 break;
7458         }
7459 }
7460
7461 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7462 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7463 /*
7464 ================
7465 R_SelectScene
7466 ================
7467 */
7468 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7469         if( scenetype != r_currentscenetype ) {
7470                 // store the old scenetype
7471                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7472                 r_currentscenetype = scenetype;
7473                 // move in the new scene
7474                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7475         }
7476 }
7477
7478 /*
7479 ================
7480 R_GetScenePointer
7481 ================
7482 */
7483 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7484 {
7485         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7486         if( scenetype == r_currentscenetype ) {
7487                 return &r_refdef.scene;
7488         } else {
7489                 return &r_scenes_store[ scenetype ];
7490         }
7491 }
7492
7493 /*
7494 ================
7495 R_RenderView
7496 ================
7497 */
7498 void R_RenderView(void)
7499 {
7500         if (r_timereport_active)
7501                 R_TimeReport("start");
7502         r_frame++; // used only by R_GetCurrentTexture
7503         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7504
7505         if (!r_drawentities.integer)
7506                 r_refdef.scene.numentities = 0;
7507
7508         R_AnimCache_ClearCache();
7509         R_FrameData_NewFrame();
7510
7511         if (r_refdef.view.isoverlay)
7512         {
7513                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7514                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7515                 R_TimeReport("depthclear");
7516
7517                 r_refdef.view.showdebug = false;
7518
7519                 r_waterstate.enabled = false;
7520                 r_waterstate.numwaterplanes = 0;
7521
7522                 R_RenderScene();
7523
7524                 CHECKGLERROR
7525                 return;
7526         }
7527
7528         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7529                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7530
7531         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7532
7533         // break apart the view matrix into vectors for various purposes
7534         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7535         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7536         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7537         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7538         // make an inverted copy of the view matrix for tracking sprites
7539         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7540
7541         R_Shadow_UpdateWorldLightSelection();
7542
7543         R_Bloom_StartFrame();
7544         R_Water_StartFrame();
7545
7546         CHECKGLERROR
7547         if (r_timereport_active)
7548                 R_TimeReport("viewsetup");
7549
7550         R_ResetViewRendering3D();
7551
7552         if (r_refdef.view.clear || r_refdef.fogenabled)
7553         {
7554                 R_ClearScreen(r_refdef.fogenabled);
7555                 if (r_timereport_active)
7556                         R_TimeReport("viewclear");
7557         }
7558         r_refdef.view.clear = true;
7559
7560         // this produces a bloom texture to be used in R_BlendView() later
7561         if (r_hdr.integer && r_bloomstate.bloomwidth)
7562                 R_HDR_RenderBloomTexture();
7563
7564         r_refdef.view.showdebug = true;
7565
7566         R_View_Update();
7567         if (r_timereport_active)
7568                 R_TimeReport("visibility");
7569
7570         r_waterstate.numwaterplanes = 0;
7571         if (r_waterstate.enabled)
7572                 R_RenderWaterPlanes();
7573
7574         R_RenderScene();
7575         r_waterstate.numwaterplanes = 0;
7576
7577         R_BlendView();
7578         if (r_timereport_active)
7579                 R_TimeReport("blendview");
7580
7581         GL_Scissor(0, 0, vid.width, vid.height);
7582         GL_ScissorTest(false);
7583         CHECKGLERROR
7584 }
7585
7586 void R_RenderWaterPlanes(void)
7587 {
7588         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7589         {
7590                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7591                 if (r_timereport_active)
7592                         R_TimeReport("waterworld");
7593         }
7594
7595         // don't let sound skip if going slow
7596         if (r_refdef.scene.extraupdate)
7597                 S_ExtraUpdate ();
7598
7599         R_DrawModelsAddWaterPlanes();
7600         if (r_timereport_active)
7601                 R_TimeReport("watermodels");
7602
7603         if (r_waterstate.numwaterplanes)
7604         {
7605                 R_Water_ProcessPlanes();
7606                 if (r_timereport_active)
7607                         R_TimeReport("waterscenes");
7608         }
7609 }
7610
7611 extern void R_DrawLightningBeams (void);
7612 extern void VM_CL_AddPolygonsToMeshQueue (void);
7613 extern void R_DrawPortals (void);
7614 extern cvar_t cl_locs_show;
7615 static void R_DrawLocs(void);
7616 static void R_DrawEntityBBoxes(void);
7617 static void R_DrawModelDecals(void);
7618 extern cvar_t cl_decals_newsystem;
7619 extern qboolean r_shadow_usingdeferredprepass;
7620 void R_RenderScene(void)
7621 {
7622         r_refdef.stats.renders++;
7623
7624         R_UpdateFogColor();
7625
7626         // don't let sound skip if going slow
7627         if (r_refdef.scene.extraupdate)
7628                 S_ExtraUpdate ();
7629
7630         R_MeshQueue_BeginScene();
7631
7632         R_SkyStartFrame();
7633
7634         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);
7635
7636         if (cl.csqc_vidvars.drawworld)
7637         {
7638                 // don't let sound skip if going slow
7639                 if (r_refdef.scene.extraupdate)
7640                         S_ExtraUpdate ();
7641
7642                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7643                 {
7644                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7645                         if (r_timereport_active)
7646                                 R_TimeReport("worldsky");
7647                 }
7648
7649                 if (R_DrawBrushModelsSky() && r_timereport_active)
7650                         R_TimeReport("bmodelsky");
7651
7652                 if (skyrendermasked && skyrenderlater)
7653                 {
7654                         // we have to force off the water clipping plane while rendering sky
7655                         R_SetupView(false);
7656                         R_Sky();
7657                         R_SetupView(true);
7658                         if (r_timereport_active)
7659                                 R_TimeReport("sky");
7660                 }
7661         }
7662
7663         R_AnimCache_CacheVisibleEntities();
7664         if (r_timereport_active)
7665                 R_TimeReport("animation");
7666
7667         R_Shadow_PrepareLights();
7668         if (r_timereport_active)
7669                 R_TimeReport("preparelights");
7670
7671         if (r_shadow_usingdeferredprepass)
7672                 R_Shadow_DrawPrepass();
7673
7674         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7675         {
7676                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7677                 if (r_timereport_active)
7678                         R_TimeReport("worlddepth");
7679         }
7680         if (r_depthfirst.integer >= 2)
7681         {
7682                 R_DrawModelsDepth();
7683                 if (r_timereport_active)
7684                         R_TimeReport("modeldepth");
7685         }
7686
7687         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7688         {
7689                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7690                 if (r_timereport_active)
7691                         R_TimeReport("world");
7692         }
7693
7694         // don't let sound skip if going slow
7695         if (r_refdef.scene.extraupdate)
7696                 S_ExtraUpdate ();
7697
7698         R_DrawModels();
7699         if (r_timereport_active)
7700                 R_TimeReport("models");
7701
7702         // don't let sound skip if going slow
7703         if (r_refdef.scene.extraupdate)
7704                 S_ExtraUpdate ();
7705
7706         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7707         {
7708                 R_DrawModelShadows();
7709                 R_ResetViewRendering3D();
7710                 // don't let sound skip if going slow
7711                 if (r_refdef.scene.extraupdate)
7712                         S_ExtraUpdate ();
7713         }
7714
7715         if (!r_shadow_usingdeferredprepass)
7716         {
7717                 R_Shadow_DrawLights();
7718                 if (r_timereport_active)
7719                         R_TimeReport("rtlights");
7720         }
7721
7722         // don't let sound skip if going slow
7723         if (r_refdef.scene.extraupdate)
7724                 S_ExtraUpdate ();
7725
7726         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7727         {
7728                 R_DrawModelShadows();
7729                 R_ResetViewRendering3D();
7730                 // don't let sound skip if going slow
7731                 if (r_refdef.scene.extraupdate)
7732                         S_ExtraUpdate ();
7733         }
7734
7735         if (cl.csqc_vidvars.drawworld)
7736         {
7737                 if (cl_decals_newsystem.integer)
7738                 {
7739                         R_DrawModelDecals();
7740                         if (r_timereport_active)
7741                                 R_TimeReport("modeldecals");
7742                 }
7743                 else
7744                 {
7745                         R_DrawDecals();
7746                         if (r_timereport_active)
7747                                 R_TimeReport("decals");
7748                 }
7749
7750                 R_DrawParticles();
7751                 if (r_timereport_active)
7752                         R_TimeReport("particles");
7753
7754                 R_DrawExplosions();
7755                 if (r_timereport_active)
7756                         R_TimeReport("explosions");
7757
7758                 R_DrawLightningBeams();
7759                 if (r_timereport_active)
7760                         R_TimeReport("lightning");
7761         }
7762
7763         VM_CL_AddPolygonsToMeshQueue();
7764
7765         if (r_refdef.view.showdebug)
7766         {
7767                 if (cl_locs_show.integer)
7768                 {
7769                         R_DrawLocs();
7770                         if (r_timereport_active)
7771                                 R_TimeReport("showlocs");
7772                 }
7773
7774                 if (r_drawportals.integer)
7775                 {
7776                         R_DrawPortals();
7777                         if (r_timereport_active)
7778                                 R_TimeReport("portals");
7779                 }
7780
7781                 if (r_showbboxes.value > 0)
7782                 {
7783                         R_DrawEntityBBoxes();
7784                         if (r_timereport_active)
7785                                 R_TimeReport("bboxes");
7786                 }
7787         }
7788
7789         R_MeshQueue_RenderTransparent();
7790         if (r_timereport_active)
7791                 R_TimeReport("drawtrans");
7792
7793         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))
7794         {
7795                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7796                 if (r_timereport_active)
7797                         R_TimeReport("worlddebug");
7798                 R_DrawModelsDebug();
7799                 if (r_timereport_active)
7800                         R_TimeReport("modeldebug");
7801         }
7802
7803         if (cl.csqc_vidvars.drawworld)
7804         {
7805                 R_Shadow_DrawCoronas();
7806                 if (r_timereport_active)
7807                         R_TimeReport("coronas");
7808         }
7809
7810         // don't let sound skip if going slow
7811         if (r_refdef.scene.extraupdate)
7812                 S_ExtraUpdate ();
7813
7814         R_ResetViewRendering2D();
7815 }
7816
7817 static const unsigned short bboxelements[36] =
7818 {
7819         5, 1, 3, 5, 3, 7,
7820         6, 2, 0, 6, 0, 4,
7821         7, 3, 2, 7, 2, 6,
7822         4, 0, 1, 4, 1, 5,
7823         4, 5, 7, 4, 7, 6,
7824         1, 0, 2, 1, 2, 3,
7825 };
7826
7827 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7828 {
7829         int i;
7830         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7831
7832         RSurf_ActiveWorldEntity();
7833
7834         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7835         GL_DepthMask(false);
7836         GL_DepthRange(0, 1);
7837         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7838         R_Mesh_ResetTextureState();
7839
7840         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7841         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7842         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7843         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7844         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7845         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7846         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7847         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7848         R_FillColors(color4f, 8, cr, cg, cb, ca);
7849         if (r_refdef.fogenabled)
7850         {
7851                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7852                 {
7853                         f1 = RSurf_FogVertex(v);
7854                         f2 = 1 - f1;
7855                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7856                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7857                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7858                 }
7859         }
7860         R_Mesh_VertexPointer(vertex3f, 0, 0);
7861         R_Mesh_ColorPointer(color4f, 0, 0);
7862         R_Mesh_ResetTextureState();
7863         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7864         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7865 }
7866
7867 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7868 {
7869         int i;
7870         float color[4];
7871         prvm_edict_t *edict;
7872         prvm_prog_t *prog_save = prog;
7873
7874         // this function draws bounding boxes of server entities
7875         if (!sv.active)
7876                 return;
7877
7878         GL_CullFace(GL_NONE);
7879         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7880
7881         prog = 0;
7882         SV_VM_Begin();
7883         for (i = 0;i < numsurfaces;i++)
7884         {
7885                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7886                 switch ((int)edict->fields.server->solid)
7887                 {
7888                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7889                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7890                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7891                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7892                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7893                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7894                 }
7895                 color[3] *= r_showbboxes.value;
7896                 color[3] = bound(0, color[3], 1);
7897                 GL_DepthTest(!r_showdisabledepthtest.integer);
7898                 GL_CullFace(r_refdef.view.cullface_front);
7899                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7900         }
7901         SV_VM_End();
7902         prog = prog_save;
7903 }
7904
7905 static void R_DrawEntityBBoxes(void)
7906 {
7907         int i;
7908         prvm_edict_t *edict;
7909         vec3_t center;
7910         prvm_prog_t *prog_save = prog;
7911
7912         // this function draws bounding boxes of server entities
7913         if (!sv.active)
7914                 return;
7915
7916         prog = 0;
7917         SV_VM_Begin();
7918         for (i = 0;i < prog->num_edicts;i++)
7919         {
7920                 edict = PRVM_EDICT_NUM(i);
7921                 if (edict->priv.server->free)
7922                         continue;
7923                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7924                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7925                         continue;
7926                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7927                         continue;
7928                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7929                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7930         }
7931         SV_VM_End();
7932         prog = prog_save;
7933 }
7934
7935 static const int nomodelelement3i[24] =
7936 {
7937         5, 2, 0,
7938         5, 1, 2,
7939         5, 0, 3,
7940         5, 3, 1,
7941         0, 2, 4,
7942         2, 1, 4,
7943         3, 0, 4,
7944         1, 3, 4
7945 };
7946
7947 static const unsigned short nomodelelement3s[24] =
7948 {
7949         5, 2, 0,
7950         5, 1, 2,
7951         5, 0, 3,
7952         5, 3, 1,
7953         0, 2, 4,
7954         2, 1, 4,
7955         3, 0, 4,
7956         1, 3, 4
7957 };
7958
7959 static const float nomodelvertex3f[6*3] =
7960 {
7961         -16,   0,   0,
7962          16,   0,   0,
7963           0, -16,   0,
7964           0,  16,   0,
7965           0,   0, -16,
7966           0,   0,  16
7967 };
7968
7969 static const float nomodelcolor4f[6*4] =
7970 {
7971         0.0f, 0.0f, 0.5f, 1.0f,
7972         0.0f, 0.0f, 0.5f, 1.0f,
7973         0.0f, 0.5f, 0.0f, 1.0f,
7974         0.0f, 0.5f, 0.0f, 1.0f,
7975         0.5f, 0.0f, 0.0f, 1.0f,
7976         0.5f, 0.0f, 0.0f, 1.0f
7977 };
7978
7979 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7980 {
7981         int i;
7982         float f1, f2, *c;
7983         float color4f[6*4];
7984
7985         RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7986
7987         // this is only called once per entity so numsurfaces is always 1, and
7988         // surfacelist is always {0}, so this code does not handle batches
7989
7990         if (rsurface.ent_flags & RENDER_ADDITIVE)
7991         {
7992                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7993                 GL_DepthMask(false);
7994         }
7995         else if (rsurface.colormod[3] < 1)
7996         {
7997                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7998                 GL_DepthMask(false);
7999         }
8000         else
8001         {
8002                 GL_BlendFunc(GL_ONE, GL_ZERO);
8003                 GL_DepthMask(true);
8004         }
8005         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8006         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8007         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8008         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8009         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8010         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8011         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8012         R_Mesh_ColorPointer(color4f, 0, 0);
8013         for (i = 0, c = color4f;i < 6;i++, c += 4)
8014         {
8015                 c[0] *= rsurface.colormod[0];
8016                 c[1] *= rsurface.colormod[1];
8017                 c[2] *= rsurface.colormod[2];
8018                 c[3] *= rsurface.colormod[3];
8019         }
8020         if (r_refdef.fogenabled)
8021         {
8022                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8023                 {
8024                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8025                         f2 = 1 - f1;
8026                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8027                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8028                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8029                 }
8030         }
8031         R_Mesh_ResetTextureState();
8032         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8033 }
8034
8035 void R_DrawNoModel(entity_render_t *ent)
8036 {
8037         vec3_t org;
8038         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8039         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8040                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8041         else
8042                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8043 }
8044
8045 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8046 {
8047         vec3_t right1, right2, diff, normal;
8048
8049         VectorSubtract (org2, org1, normal);
8050
8051         // calculate 'right' vector for start
8052         VectorSubtract (r_refdef.view.origin, org1, diff);
8053         CrossProduct (normal, diff, right1);
8054         VectorNormalize (right1);
8055
8056         // calculate 'right' vector for end
8057         VectorSubtract (r_refdef.view.origin, org2, diff);
8058         CrossProduct (normal, diff, right2);
8059         VectorNormalize (right2);
8060
8061         vert[ 0] = org1[0] + width * right1[0];
8062         vert[ 1] = org1[1] + width * right1[1];
8063         vert[ 2] = org1[2] + width * right1[2];
8064         vert[ 3] = org1[0] - width * right1[0];
8065         vert[ 4] = org1[1] - width * right1[1];
8066         vert[ 5] = org1[2] - width * right1[2];
8067         vert[ 6] = org2[0] - width * right2[0];
8068         vert[ 7] = org2[1] - width * right2[1];
8069         vert[ 8] = org2[2] - width * right2[2];
8070         vert[ 9] = org2[0] + width * right2[0];
8071         vert[10] = org2[1] + width * right2[1];
8072         vert[11] = org2[2] + width * right2[2];
8073 }
8074
8075 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
8076 {
8077         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8078         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8079         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8080         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8081         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8082         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8083         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8084         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8085         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8086         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8087         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8088         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8089 }
8090
8091 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8092 {
8093         int i;
8094         float *vertex3f;
8095         float v[3];
8096         VectorSet(v, x, y, z);
8097         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8098                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8099                         break;
8100         if (i == mesh->numvertices)
8101         {
8102                 if (mesh->numvertices < mesh->maxvertices)
8103                 {
8104                         VectorCopy(v, vertex3f);
8105                         mesh->numvertices++;
8106                 }
8107                 return mesh->numvertices;
8108         }
8109         else
8110                 return i;
8111 }
8112
8113 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8114 {
8115         int i;
8116         int *e, element[3];
8117         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8118         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8119         e = mesh->element3i + mesh->numtriangles * 3;
8120         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8121         {
8122                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8123                 if (mesh->numtriangles < mesh->maxtriangles)
8124                 {
8125                         *e++ = element[0];
8126                         *e++ = element[1];
8127                         *e++ = element[2];
8128                         mesh->numtriangles++;
8129                 }
8130                 element[1] = element[2];
8131         }
8132 }
8133
8134 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8135 {
8136         int i;
8137         int *e, element[3];
8138         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8139         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8140         e = mesh->element3i + mesh->numtriangles * 3;
8141         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8142         {
8143                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8144                 if (mesh->numtriangles < mesh->maxtriangles)
8145                 {
8146                         *e++ = element[0];
8147                         *e++ = element[1];
8148                         *e++ = element[2];
8149                         mesh->numtriangles++;
8150                 }
8151                 element[1] = element[2];
8152         }
8153 }
8154
8155 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8156 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8157 {
8158         int planenum, planenum2;
8159         int w;
8160         int tempnumpoints;
8161         mplane_t *plane, *plane2;
8162         double maxdist;
8163         double temppoints[2][256*3];
8164         // figure out how large a bounding box we need to properly compute this brush
8165         maxdist = 0;
8166         for (w = 0;w < numplanes;w++)
8167                 maxdist = max(maxdist, fabs(planes[w].dist));
8168         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8169         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8170         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8171         {
8172                 w = 0;
8173                 tempnumpoints = 4;
8174                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8175                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8176                 {
8177                         if (planenum2 == planenum)
8178                                 continue;
8179                         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);
8180                         w = !w;
8181                 }
8182                 if (tempnumpoints < 3)
8183                         continue;
8184                 // generate elements forming a triangle fan for this polygon
8185                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8186         }
8187 }
8188
8189 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)
8190 {
8191         texturelayer_t *layer;
8192         layer = t->currentlayers + t->currentnumlayers++;
8193         layer->type = type;
8194         layer->depthmask = depthmask;
8195         layer->blendfunc1 = blendfunc1;
8196         layer->blendfunc2 = blendfunc2;
8197         layer->texture = texture;
8198         layer->texmatrix = *matrix;
8199         layer->color[0] = r;
8200         layer->color[1] = g;
8201         layer->color[2] = b;
8202         layer->color[3] = a;
8203 }
8204
8205 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8206 {
8207         double index, f;
8208         index = parms[2] + r_refdef.scene.time * parms[3];
8209         index -= floor(index);
8210         switch (func)
8211         {
8212         default:
8213         case Q3WAVEFUNC_NONE:
8214         case Q3WAVEFUNC_NOISE:
8215         case Q3WAVEFUNC_COUNT:
8216                 f = 0;
8217                 break;
8218         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8219         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8220         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8221         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8222         case Q3WAVEFUNC_TRIANGLE:
8223                 index *= 4;
8224                 f = index - floor(index);
8225                 if (index < 1)
8226                         f = f;
8227                 else if (index < 2)
8228                         f = 1 - f;
8229                 else if (index < 3)
8230                         f = -f;
8231                 else
8232                         f = -(1 - f);
8233                 break;
8234         }
8235         return (float)(parms[0] + parms[1] * f);
8236 }
8237
8238 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8239 {
8240         int w, h, idx;
8241         float f;
8242         float tcmat[12];
8243         matrix4x4_t matrix, temp;
8244         switch(tcmod->tcmod)
8245         {
8246                 case Q3TCMOD_COUNT:
8247                 case Q3TCMOD_NONE:
8248                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8249                                 matrix = r_waterscrollmatrix;
8250                         else
8251                                 matrix = identitymatrix;
8252                         break;
8253                 case Q3TCMOD_ENTITYTRANSLATE:
8254                         // this is used in Q3 to allow the gamecode to control texcoord
8255                         // scrolling on the entity, which is not supported in darkplaces yet.
8256                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8257                         break;
8258                 case Q3TCMOD_ROTATE:
8259                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8260                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8261                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8262                         break;
8263                 case Q3TCMOD_SCALE:
8264                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8265                         break;
8266                 case Q3TCMOD_SCROLL:
8267                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8268                         break;
8269                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8270                         w = (int) tcmod->parms[0];
8271                         h = (int) tcmod->parms[1];
8272                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8273                         f = f - floor(f);
8274                         idx = (int) floor(f * w * h);
8275                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8276                         break;
8277                 case Q3TCMOD_STRETCH:
8278                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8279                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8280                         break;
8281                 case Q3TCMOD_TRANSFORM:
8282                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8283                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8284                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8285                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8286                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8287                         break;
8288                 case Q3TCMOD_TURBULENT:
8289                         // this is handled in the RSurf_PrepareVertices function
8290                         matrix = identitymatrix;
8291                         break;
8292         }
8293         temp = *texmatrix;
8294         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8295 }
8296
8297 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8298 {
8299         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8300         char name[MAX_QPATH];
8301         skinframe_t *skinframe;
8302         unsigned char pixels[296*194];
8303         strlcpy(cache->name, skinname, sizeof(cache->name));
8304         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8305         if (developer_loading.integer)
8306                 Con_Printf("loading %s\n", name);
8307         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8308         if (!skinframe || !skinframe->base)
8309         {
8310                 unsigned char *f;
8311                 fs_offset_t filesize;
8312                 skinframe = NULL;
8313                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8314                 if (f)
8315                 {
8316                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8317                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8318                         Mem_Free(f);
8319                 }
8320         }
8321         cache->skinframe = skinframe;
8322 }
8323
8324 texture_t *R_GetCurrentTexture(texture_t *t)
8325 {
8326         int i;
8327         const entity_render_t *ent = rsurface.entity;
8328         dp_model_t *model = ent->model;
8329         q3shaderinfo_layer_tcmod_t *tcmod;
8330
8331         if (t->update_lastrenderframe == r_frame && t->update_lastrenderentity == (void *)ent)
8332                 return t->currentframe;
8333         t->update_lastrenderframe = r_frame;
8334         t->update_lastrenderentity = (void *)ent;
8335
8336         // switch to an alternate material if this is a q1bsp animated material
8337         {
8338                 texture_t *texture = t;
8339                 int s = rsurface.ent_skinnum;
8340                 if ((unsigned int)s >= (unsigned int)model->numskins)
8341                         s = 0;
8342                 if (model->skinscenes)
8343                 {
8344                         if (model->skinscenes[s].framecount > 1)
8345                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8346                         else
8347                                 s = model->skinscenes[s].firstframe;
8348                 }
8349                 if (s > 0)
8350                         t = t + s * model->num_surfaces;
8351                 if (t->animated)
8352                 {
8353                         // use an alternate animation if the entity's frame is not 0,
8354                         // and only if the texture has an alternate animation
8355                         if (rsurface.ent_alttextures && t->anim_total[1])
8356                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8357                         else
8358                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8359                 }
8360                 texture->currentframe = t;
8361         }
8362
8363         // update currentskinframe to be a qw skin or animation frame
8364         if (rsurface.ent_qwskin >= 0)
8365         {
8366                 i = rsurface.ent_qwskin;
8367                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8368                 {
8369                         r_qwskincache_size = cl.maxclients;
8370                         if (r_qwskincache)
8371                                 Mem_Free(r_qwskincache);
8372                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8373                 }
8374                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8375                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8376                 t->currentskinframe = r_qwskincache[i].skinframe;
8377                 if (t->currentskinframe == NULL)
8378                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8379         }
8380         else if (t->numskinframes >= 2)
8381                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8382         if (t->backgroundnumskinframes >= 2)
8383                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8384
8385         t->currentmaterialflags = t->basematerialflags;
8386         t->currentalpha = rsurface.colormod[3];
8387         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8388                 t->currentalpha *= r_wateralpha.value;
8389         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8390                 t->currentalpha *= t->r_water_wateralpha;
8391         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8392                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8393         if (!(rsurface.ent_flags & RENDER_LIGHT))
8394                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8395         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8396         {
8397                 // pick a model lighting mode
8398                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8399                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8400                 else
8401                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8402         }
8403         if (rsurface.ent_flags & RENDER_ADDITIVE)
8404                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8405         else if (t->currentalpha < 1)
8406                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8407         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8408                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8409         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8410                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8411         if (t->backgroundnumskinframes)
8412                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8413         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8414         {
8415                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8416                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8417         }
8418         else
8419                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8420         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8421                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8422
8423         // there is no tcmod
8424         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8425         {
8426                 t->currenttexmatrix = r_waterscrollmatrix;
8427                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8428         }
8429         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8430         {
8431                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8432                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8433         }
8434
8435         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8436                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8437         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8438                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8439
8440         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8441         if (t->currentskinframe->qpixels)
8442                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8443         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8444         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8445         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8446         t->nmaptexture = t->currentskinframe->nmap;
8447         t->glosstexture = r_texture_black;
8448         t->glowtexture = t->currentskinframe->glow;
8449         t->fogtexture = t->currentskinframe->fog;
8450         if (t->backgroundnumskinframes)
8451         {
8452                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8453                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8454                 t->backgroundglosstexture = r_texture_black;
8455                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8456         }
8457         else
8458         {
8459                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8460                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8461                 t->backgroundglosstexture = r_texture_black;
8462                 t->backgroundglowtexture = NULL;
8463         }
8464         t->specularpower = r_shadow_glossexponent.value;
8465         // TODO: store reference values for these in the texture?
8466         t->specularscale = 0;
8467         if (r_shadow_gloss.integer > 0)
8468         {
8469                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8470                 {
8471                         if (r_shadow_glossintensity.value > 0)
8472                         {
8473                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8474                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8475                                 t->specularscale = r_shadow_glossintensity.value;
8476                         }
8477                 }
8478                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8479                 {
8480                         t->glosstexture = r_texture_white;
8481                         t->backgroundglosstexture = r_texture_white;
8482                         t->specularscale = r_shadow_gloss2intensity.value;
8483                         t->specularpower = r_shadow_gloss2exponent.value;
8484                 }
8485         }
8486         t->specularscale *= t->specularscalemod;
8487         t->specularpower *= t->specularpowermod;
8488
8489         // lightmaps mode looks bad with dlights using actual texturing, so turn
8490         // off the colormap and glossmap, but leave the normalmap on as it still
8491         // accurately represents the shading involved
8492         if (gl_lightmaps.integer)
8493         {
8494                 t->basetexture = r_texture_grey128;
8495                 t->pantstexture = r_texture_black;
8496                 t->shirttexture = r_texture_black;
8497                 t->nmaptexture = r_texture_blanknormalmap;
8498                 t->glosstexture = r_texture_black;
8499                 t->glowtexture = NULL;
8500                 t->fogtexture = NULL;
8501                 t->backgroundbasetexture = NULL;
8502                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8503                 t->backgroundglosstexture = r_texture_black;
8504                 t->backgroundglowtexture = NULL;
8505                 t->specularscale = 0;
8506                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8507         }
8508
8509         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8510         VectorClear(t->dlightcolor);
8511         t->currentnumlayers = 0;
8512         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8513         {
8514                 int blendfunc1, blendfunc2;
8515                 qboolean depthmask;
8516                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8517                 {
8518                         blendfunc1 = GL_SRC_ALPHA;
8519                         blendfunc2 = GL_ONE;
8520                 }
8521                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8522                 {
8523                         blendfunc1 = GL_SRC_ALPHA;
8524                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8525                 }
8526                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8527                 {
8528                         blendfunc1 = t->customblendfunc[0];
8529                         blendfunc2 = t->customblendfunc[1];
8530                 }
8531                 else
8532                 {
8533                         blendfunc1 = GL_ONE;
8534                         blendfunc2 = GL_ZERO;
8535                 }
8536                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8537                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8538                 {
8539                         // fullbright is not affected by r_refdef.lightmapintensity
8540                         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]);
8541                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8542                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8543                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8544                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8545                 }
8546                 else
8547                 {
8548                         vec3_t ambientcolor;
8549                         float colorscale;
8550                         // set the color tint used for lights affecting this surface
8551                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8552                         colorscale = 2;
8553                         // q3bsp has no lightmap updates, so the lightstylevalue that
8554                         // would normally be baked into the lightmap must be
8555                         // applied to the color
8556                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8557                         if (model->type == mod_brushq3)
8558                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8559                         colorscale *= r_refdef.lightmapintensity;
8560                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8561                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8562                         // basic lit geometry
8563                         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]);
8564                         // add pants/shirt if needed
8565                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8566                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
8567                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8568                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8569                         // now add ambient passes if needed
8570                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8571                         {
8572                                 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]);
8573                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8574                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8575                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8576                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8577                         }
8578                 }
8579                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8580                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8581                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8582                 {
8583                         // if this is opaque use alpha blend which will darken the earlier
8584                         // passes cheaply.
8585                         //
8586                         // if this is an alpha blended material, all the earlier passes
8587                         // were darkened by fog already, so we only need to add the fog
8588                         // color ontop through the fog mask texture
8589                         //
8590                         // if this is an additive blended material, all the earlier passes
8591                         // were darkened by fog already, and we should not add fog color
8592                         // (because the background was not darkened, there is no fog color
8593                         // that was lost behind it).
8594                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
8595                 }
8596         }
8597
8598         return t->currentframe;
8599 }
8600
8601 rsurfacestate_t rsurface;
8602
8603 void R_Mesh_ResizeArrays(int newvertices)
8604 {
8605         float *base;
8606         if (rsurface.array_size >= newvertices)
8607                 return;
8608         if (rsurface.array_modelvertex3f)
8609                 Mem_Free(rsurface.array_modelvertex3f);
8610         rsurface.array_size = (newvertices + 1023) & ~1023;
8611         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8612         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8613         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8614         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8615         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8616         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8617         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8618         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8619         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8620         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8621         rsurface.array_color4f           = base + rsurface.array_size * 27;
8622         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8623 }
8624
8625 void RSurf_ActiveWorldEntity(void)
8626 {
8627         dp_model_t *model = r_refdef.scene.worldmodel;
8628         //if (rsurface.entity == r_refdef.scene.worldentity)
8629         //      return;
8630         rsurface.entity = r_refdef.scene.worldentity;
8631         rsurface.skeleton = NULL;
8632         rsurface.ent_skinnum = 0;
8633         rsurface.ent_qwskin = -1;
8634         rsurface.ent_shadertime = 0;
8635         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8636         if (rsurface.array_size < model->surfmesh.num_vertices)
8637                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8638         rsurface.matrix = identitymatrix;
8639         rsurface.inversematrix = identitymatrix;
8640         rsurface.matrixscale = 1;
8641         rsurface.inversematrixscale = 1;
8642         R_EntityMatrix(&identitymatrix);
8643         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8644         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8645         rsurface.fograngerecip = r_refdef.fograngerecip;
8646         rsurface.fogheightfade = r_refdef.fogheightfade;
8647         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8648         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8649         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8650         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8651         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8652         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8653         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8654         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8655         rsurface.colormod[3] = 1;
8656         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8657         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8658         rsurface.frameblend[0].lerp = 1;
8659         rsurface.ent_alttextures = false;
8660         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8661         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8662         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8663         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8664         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8665         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8666         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8667         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8668         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8669         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8670         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8671         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8672         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8673         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8674         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8675         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8676         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8677         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8678         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8679         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8680         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8681         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8682         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8683         rsurface.modelelement3i = model->surfmesh.data_element3i;
8684         rsurface.modelelement3s = model->surfmesh.data_element3s;
8685         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8686         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8687         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8688         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8689         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8690         rsurface.modelsurfaces = model->data_surfaces;
8691         rsurface.generatedvertex = false;
8692         rsurface.vertex3f  = rsurface.modelvertex3f;
8693         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8694         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8695         rsurface.svector3f = rsurface.modelsvector3f;
8696         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8697         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8698         rsurface.tvector3f = rsurface.modeltvector3f;
8699         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8700         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8701         rsurface.normal3f  = rsurface.modelnormal3f;
8702         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8703         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8704         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8705 }
8706
8707 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8708 {
8709         dp_model_t *model = ent->model;
8710         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8711         //      return;
8712         rsurface.entity = (entity_render_t *)ent;
8713         rsurface.skeleton = ent->skeleton;
8714         rsurface.ent_skinnum = ent->skinnum;
8715         rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
8716         rsurface.ent_shadertime = ent->shadertime;
8717         rsurface.ent_flags = ent->flags;
8718         if (rsurface.array_size < model->surfmesh.num_vertices)
8719                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8720         rsurface.matrix = ent->matrix;
8721         rsurface.inversematrix = ent->inversematrix;
8722         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8723         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8724         R_EntityMatrix(&rsurface.matrix);
8725         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8726         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8727         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8728         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8729         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8730         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8731         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8732         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8733         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8734         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8735         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8736         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8737         rsurface.colormod[3] = ent->alpha;
8738         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8739         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8740         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8741         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8742         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8743         if (ent->model->brush.submodel && !prepass)
8744         {
8745                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8746                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8747         }
8748         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8749         {
8750                 if (ent->animcache_vertex3f && !r_framedata_failed)
8751                 {
8752                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8753                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8754                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8755                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8756                 }
8757                 else if (wanttangents)
8758                 {
8759                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8760                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8761                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8762                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8763                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8764                 }
8765                 else if (wantnormals)
8766                 {
8767                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8768                         rsurface.modelsvector3f = NULL;
8769                         rsurface.modeltvector3f = NULL;
8770                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8771                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8772                 }
8773                 else
8774                 {
8775                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8776                         rsurface.modelsvector3f = NULL;
8777                         rsurface.modeltvector3f = NULL;
8778                         rsurface.modelnormal3f = NULL;
8779                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8780                 }
8781                 rsurface.modelvertex3f_bufferobject = 0;
8782                 rsurface.modelvertex3f_bufferoffset = 0;
8783                 rsurface.modelsvector3f_bufferobject = 0;
8784                 rsurface.modelsvector3f_bufferoffset = 0;
8785                 rsurface.modeltvector3f_bufferobject = 0;
8786                 rsurface.modeltvector3f_bufferoffset = 0;
8787                 rsurface.modelnormal3f_bufferobject = 0;
8788                 rsurface.modelnormal3f_bufferoffset = 0;
8789                 rsurface.generatedvertex = true;
8790         }
8791         else
8792         {
8793                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8794                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8795                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8796                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8797                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8798                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8799                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8800                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8801                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8802                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8803                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8804                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8805                 rsurface.generatedvertex = false;
8806         }
8807         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8808         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8809         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8810         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8811         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8812         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8813         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8814         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8815         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8816         rsurface.modelelement3i = model->surfmesh.data_element3i;
8817         rsurface.modelelement3s = model->surfmesh.data_element3s;
8818         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8819         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8820         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8821         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8822         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8823         rsurface.modelsurfaces = model->data_surfaces;
8824         rsurface.vertex3f  = rsurface.modelvertex3f;
8825         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8826         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8827         rsurface.svector3f = rsurface.modelsvector3f;
8828         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8829         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8830         rsurface.tvector3f = rsurface.modeltvector3f;
8831         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8832         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8833         rsurface.normal3f  = rsurface.modelnormal3f;
8834         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8835         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8836         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8837 }
8838
8839 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
8840 {
8841         rsurface.entity = r_refdef.scene.worldentity;
8842         rsurface.skeleton = NULL;
8843         rsurface.ent_skinnum = 0;
8844         rsurface.ent_qwskin = -1;
8845         rsurface.ent_shadertime = shadertime;
8846         rsurface.ent_flags = entflags;
8847         rsurface.modelnum_vertices = numvertices;
8848         rsurface.modelnum_triangles = numtriangles;
8849         if (rsurface.array_size < rsurface.modelnum_vertices)
8850                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8851         rsurface.matrix = *matrix;
8852         rsurface.inversematrix = *inversematrix;
8853         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8854         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8855         R_EntityMatrix(&rsurface.matrix);
8856         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8857         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8858         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8859         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8860         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8861         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8862         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8863         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8864         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8865         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8866         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8867         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8868         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8869         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8870         rsurface.frameblend[0].lerp = 1;
8871         rsurface.ent_alttextures = false;
8872         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8873         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8874         if (wanttangents)
8875         {
8876                 rsurface.modelvertex3f = vertex3f;
8877                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
8878                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
8879                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8880         }
8881         else if (wantnormals)
8882         {
8883                 rsurface.modelvertex3f = vertex3f;
8884                 rsurface.modelsvector3f = NULL;
8885                 rsurface.modeltvector3f = NULL;
8886                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8887         }
8888         else
8889         {
8890                 rsurface.modelvertex3f = vertex3f;
8891                 rsurface.modelsvector3f = NULL;
8892                 rsurface.modeltvector3f = NULL;
8893                 rsurface.modelnormal3f = NULL;
8894         }
8895         rsurface.modelvertex3f_bufferobject = 0;
8896         rsurface.modelvertex3f_bufferoffset = 0;
8897         rsurface.modelsvector3f_bufferobject = 0;
8898         rsurface.modelsvector3f_bufferoffset = 0;
8899         rsurface.modeltvector3f_bufferobject = 0;
8900         rsurface.modeltvector3f_bufferoffset = 0;
8901         rsurface.modelnormal3f_bufferobject = 0;
8902         rsurface.modelnormal3f_bufferoffset = 0;
8903         rsurface.generatedvertex = true;
8904         rsurface.modellightmapcolor4f  = color4f;
8905         rsurface.modellightmapcolor4f_bufferobject = 0;
8906         rsurface.modellightmapcolor4f_bufferoffset = 0;
8907         rsurface.modeltexcoordtexture2f  = texcoord2f;
8908         rsurface.modeltexcoordtexture2f_bufferobject = 0;
8909         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8910         rsurface.modeltexcoordlightmap2f  = NULL;
8911         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
8912         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8913         rsurface.modelelement3i = element3i;
8914         rsurface.modelelement3s = element3s;
8915         rsurface.modelelement3i_bufferobject = 0;
8916         rsurface.modelelement3s_bufferobject = 0;
8917         rsurface.modellightmapoffsets = NULL;
8918         rsurface.modelsurfaces = NULL;
8919         rsurface.vertex3f  = rsurface.modelvertex3f;
8920         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8921         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8922         rsurface.svector3f = rsurface.modelsvector3f;
8923         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8924         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8925         rsurface.tvector3f = rsurface.modeltvector3f;
8926         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8927         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8928         rsurface.normal3f  = rsurface.modelnormal3f;
8929         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8930         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8931         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8932
8933         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
8934         {
8935                 if ((wantnormals || wanttangents) && !normal3f)
8936                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8937                 if (wanttangents && !svector3f)
8938                         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);
8939         }
8940 }
8941
8942 float RSurf_FogPoint(const float *v)
8943 {
8944         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8945         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8946         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8947         float FogHeightFade = r_refdef.fogheightfade;
8948         float fogfrac;
8949         unsigned int fogmasktableindex;
8950         if (r_refdef.fogplaneviewabove)
8951                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8952         else
8953                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8954         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8955         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8956 }
8957
8958 float RSurf_FogVertex(const float *v)
8959 {
8960         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8961         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8962         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8963         float FogHeightFade = rsurface.fogheightfade;
8964         float fogfrac;
8965         unsigned int fogmasktableindex;
8966         if (r_refdef.fogplaneviewabove)
8967                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8968         else
8969                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8970         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8971         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8972 }
8973
8974 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8975 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8976 {
8977         int deformindex;
8978         int texturesurfaceindex;
8979         int i, j;
8980         float amplitude;
8981         float animpos;
8982         float scale;
8983         const float *v1, *in_tc;
8984         float *out_tc;
8985         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8986         float waveparms[4];
8987         q3shaderinfo_deform_t *deform;
8988         // 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
8989         if (rsurface.generatedvertex)
8990         {
8991                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
8992                         generatenormals = true;
8993                 for (i = 0;i < Q3MAXDEFORMS;i++)
8994                 {
8995                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
8996                         {
8997                                 generatetangents = true;
8998                                 generatenormals = true;
8999                         }
9000                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9001                                 generatenormals = true;
9002                 }
9003                 if (generatenormals && !rsurface.modelnormal3f)
9004                 {
9005                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9006                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9007                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9008                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9009                 }
9010                 if (generatetangents && !rsurface.modelsvector3f)
9011                 {
9012                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9013                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9014                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9015                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9016                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9017                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9018                         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);
9019                 }
9020         }
9021         rsurface.vertex3f  = rsurface.modelvertex3f;
9022         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9023         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9024         rsurface.svector3f = rsurface.modelsvector3f;
9025         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9026         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9027         rsurface.tvector3f = rsurface.modeltvector3f;
9028         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9029         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9030         rsurface.normal3f  = rsurface.modelnormal3f;
9031         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9032         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9033         // if vertices are deformed (sprite flares and things in maps, possibly
9034         // water waves, bulges and other deformations), generate them into
9035         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9036         // (may be static model data or generated data for an animated model, or
9037         //  the previous deform pass)
9038         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9039         {
9040                 switch (deform->deform)
9041                 {
9042                 default:
9043                 case Q3DEFORM_PROJECTIONSHADOW:
9044                 case Q3DEFORM_TEXT0:
9045                 case Q3DEFORM_TEXT1:
9046                 case Q3DEFORM_TEXT2:
9047                 case Q3DEFORM_TEXT3:
9048                 case Q3DEFORM_TEXT4:
9049                 case Q3DEFORM_TEXT5:
9050                 case Q3DEFORM_TEXT6:
9051                 case Q3DEFORM_TEXT7:
9052                 case Q3DEFORM_NONE:
9053                         break;
9054                 case Q3DEFORM_AUTOSPRITE:
9055                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9056                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9057                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9058                         VectorNormalize(newforward);
9059                         VectorNormalize(newright);
9060                         VectorNormalize(newup);
9061                         // make deformed versions of only the model vertices used by the specified surfaces
9062                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9063                         {
9064                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9065                                 // a single autosprite surface can contain multiple sprites...
9066                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9067                                 {
9068                                         VectorClear(center);
9069                                         for (i = 0;i < 4;i++)
9070                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9071                                         VectorScale(center, 0.25f, center);
9072                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9073                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9074                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9075                                         for (i = 0;i < 4;i++)
9076                                         {
9077                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9078                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9079                                         }
9080                                 }
9081                                 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);
9082                                 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);
9083                         }
9084                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9085                         rsurface.vertex3f_bufferobject = 0;
9086                         rsurface.vertex3f_bufferoffset = 0;
9087                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9088                         rsurface.svector3f_bufferobject = 0;
9089                         rsurface.svector3f_bufferoffset = 0;
9090                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9091                         rsurface.tvector3f_bufferobject = 0;
9092                         rsurface.tvector3f_bufferoffset = 0;
9093                         rsurface.normal3f = rsurface.array_deformednormal3f;
9094                         rsurface.normal3f_bufferobject = 0;
9095                         rsurface.normal3f_bufferoffset = 0;
9096                         break;
9097                 case Q3DEFORM_AUTOSPRITE2:
9098                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9099                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9100                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9101                         VectorNormalize(newforward);
9102                         VectorNormalize(newright);
9103                         VectorNormalize(newup);
9104                         // make deformed versions of only the model vertices used by the specified surfaces
9105                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9106                         {
9107                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9108                                 const float *v1, *v2;
9109                                 vec3_t start, end;
9110                                 float f, l;
9111                                 struct
9112                                 {
9113                                         float length2;
9114                                         const float *v1;
9115                                         const float *v2;
9116                                 }
9117                                 shortest[2];
9118                                 memset(shortest, 0, sizeof(shortest));
9119                                 // a single autosprite surface can contain multiple sprites...
9120                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9121                                 {
9122                                         VectorClear(center);
9123                                         for (i = 0;i < 4;i++)
9124                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9125                                         VectorScale(center, 0.25f, center);
9126                                         // find the two shortest edges, then use them to define the
9127                                         // axis vectors for rotating around the central axis
9128                                         for (i = 0;i < 6;i++)
9129                                         {
9130                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9131                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9132 #if 0
9133                                                 Debug_PolygonBegin(NULL, 0);
9134                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9135                                                 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);
9136                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9137                                                 Debug_PolygonEnd();
9138 #endif
9139                                                 l = VectorDistance2(v1, v2);
9140                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9141                                                 if (v1[2] != v2[2])
9142                                                         l += (1.0f / 1024.0f);
9143                                                 if (shortest[0].length2 > l || i == 0)
9144                                                 {
9145                                                         shortest[1] = shortest[0];
9146                                                         shortest[0].length2 = l;
9147                                                         shortest[0].v1 = v1;
9148                                                         shortest[0].v2 = v2;
9149                                                 }
9150                                                 else if (shortest[1].length2 > l || i == 1)
9151                                                 {
9152                                                         shortest[1].length2 = l;
9153                                                         shortest[1].v1 = v1;
9154                                                         shortest[1].v2 = v2;
9155                                                 }
9156                                         }
9157                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9158                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9159 #if 0
9160                                         Debug_PolygonBegin(NULL, 0);
9161                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9162                                         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);
9163                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9164                                         Debug_PolygonEnd();
9165 #endif
9166                                         // this calculates the right vector from the shortest edge
9167                                         // and the up vector from the edge midpoints
9168                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9169                                         VectorNormalize(right);
9170                                         VectorSubtract(end, start, up);
9171                                         VectorNormalize(up);
9172                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9173                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9174                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9175                                         VectorNegate(forward, forward);
9176                                         VectorReflect(forward, 0, up, forward);
9177                                         VectorNormalize(forward);
9178                                         CrossProduct(up, forward, newright);
9179                                         VectorNormalize(newright);
9180 #if 0
9181                                         Debug_PolygonBegin(NULL, 0);
9182                                         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);
9183                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9184                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9185                                         Debug_PolygonEnd();
9186 #endif
9187 #if 0
9188                                         Debug_PolygonBegin(NULL, 0);
9189                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9190                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9191                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9192                                         Debug_PolygonEnd();
9193 #endif
9194                                         // rotate the quad around the up axis vector, this is made
9195                                         // especially easy by the fact we know the quad is flat,
9196                                         // so we only have to subtract the center position and
9197                                         // measure distance along the right vector, and then
9198                                         // multiply that by the newright vector and add back the
9199                                         // center position
9200                                         // we also need to subtract the old position to undo the
9201                                         // displacement from the center, which we do with a
9202                                         // DotProduct, the subtraction/addition of center is also
9203                                         // optimized into DotProducts here
9204                                         l = DotProduct(right, center);
9205                                         for (i = 0;i < 4;i++)
9206                                         {
9207                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9208                                                 f = DotProduct(right, v1) - l;
9209                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9210                                         }
9211                                 }
9212                                 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);
9213                                 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);
9214                         }
9215                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9216                         rsurface.vertex3f_bufferobject = 0;
9217                         rsurface.vertex3f_bufferoffset = 0;
9218                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9219                         rsurface.svector3f_bufferobject = 0;
9220                         rsurface.svector3f_bufferoffset = 0;
9221                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9222                         rsurface.tvector3f_bufferobject = 0;
9223                         rsurface.tvector3f_bufferoffset = 0;
9224                         rsurface.normal3f = rsurface.array_deformednormal3f;
9225                         rsurface.normal3f_bufferobject = 0;
9226                         rsurface.normal3f_bufferoffset = 0;
9227                         break;
9228                 case Q3DEFORM_NORMAL:
9229                         // deform the normals to make reflections wavey
9230                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9231                         {
9232                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9233                                 for (j = 0;j < surface->num_vertices;j++)
9234                                 {
9235                                         float vertex[3];
9236                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9237                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9238                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9239                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9240                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9241                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9242                                         VectorNormalize(normal);
9243                                 }
9244                                 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);
9245                         }
9246                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9247                         rsurface.svector3f_bufferobject = 0;
9248                         rsurface.svector3f_bufferoffset = 0;
9249                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9250                         rsurface.tvector3f_bufferobject = 0;
9251                         rsurface.tvector3f_bufferoffset = 0;
9252                         rsurface.normal3f = rsurface.array_deformednormal3f;
9253                         rsurface.normal3f_bufferobject = 0;
9254                         rsurface.normal3f_bufferoffset = 0;
9255                         break;
9256                 case Q3DEFORM_WAVE:
9257                         // deform vertex array to make wavey water and flags and such
9258                         waveparms[0] = deform->waveparms[0];
9259                         waveparms[1] = deform->waveparms[1];
9260                         waveparms[2] = deform->waveparms[2];
9261                         waveparms[3] = deform->waveparms[3];
9262                         // this is how a divisor of vertex influence on deformation
9263                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9264                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9265                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9266                         {
9267                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9268                                 for (j = 0;j < surface->num_vertices;j++)
9269                                 {
9270                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9271                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9272                                         // if the wavefunc depends on time, evaluate it per-vertex
9273                                         if (waveparms[3])
9274                                         {
9275                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9276                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9277                                         }
9278                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9279                                 }
9280                         }
9281                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9282                         rsurface.vertex3f_bufferobject = 0;
9283                         rsurface.vertex3f_bufferoffset = 0;
9284                         break;
9285                 case Q3DEFORM_BULGE:
9286                         // deform vertex array to make the surface have moving bulges
9287                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9288                         {
9289                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9290                                 for (j = 0;j < surface->num_vertices;j++)
9291                                 {
9292                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9293                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9294                                 }
9295                         }
9296                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9297                         rsurface.vertex3f_bufferobject = 0;
9298                         rsurface.vertex3f_bufferoffset = 0;
9299                         break;
9300                 case Q3DEFORM_MOVE:
9301                         // deform vertex array
9302                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9303                         VectorScale(deform->parms, scale, waveparms);
9304                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9305                         {
9306                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9307                                 for (j = 0;j < surface->num_vertices;j++)
9308                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9309                         }
9310                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9311                         rsurface.vertex3f_bufferobject = 0;
9312                         rsurface.vertex3f_bufferoffset = 0;
9313                         break;
9314                 }
9315         }
9316         // generate texcoords based on the chosen texcoord source
9317         switch(rsurface.texture->tcgen.tcgen)
9318         {
9319         default:
9320         case Q3TCGEN_TEXTURE:
9321                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9322                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9323                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9324                 break;
9325         case Q3TCGEN_LIGHTMAP:
9326                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9327                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9328                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9329                 break;
9330         case Q3TCGEN_VECTOR:
9331                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9332                 {
9333                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9334                         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)
9335                         {
9336                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9337                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9338                         }
9339                 }
9340                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9341                 rsurface.texcoordtexture2f_bufferobject  = 0;
9342                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9343                 break;
9344         case Q3TCGEN_ENVIRONMENT:
9345                 // make environment reflections using a spheremap
9346                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9347                 {
9348                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9349                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9350                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9351                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9352                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9353                         {
9354                                 // identical to Q3A's method, but executed in worldspace so
9355                                 // carried models can be shiny too
9356
9357                                 float viewer[3], d, reflected[3], worldreflected[3];
9358
9359                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9360                                 // VectorNormalize(viewer);
9361
9362                                 d = DotProduct(normal, viewer);
9363
9364                                 reflected[0] = normal[0]*2*d - viewer[0];
9365                                 reflected[1] = normal[1]*2*d - viewer[1];
9366                                 reflected[2] = normal[2]*2*d - viewer[2];
9367                                 // note: this is proportinal to viewer, so we can normalize later
9368
9369                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9370                                 VectorNormalize(worldreflected);
9371
9372                                 // note: this sphere map only uses world x and z!
9373                                 // so positive and negative y will LOOK THE SAME.
9374                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9375                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9376                         }
9377                 }
9378                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9379                 rsurface.texcoordtexture2f_bufferobject  = 0;
9380                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9381                 break;
9382         }
9383         // the only tcmod that needs software vertex processing is turbulent, so
9384         // check for it here and apply the changes if needed
9385         // and we only support that as the first one
9386         // (handling a mixture of turbulent and other tcmods would be problematic
9387         //  without punting it entirely to a software path)
9388         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9389         {
9390                 amplitude = rsurface.texture->tcmods[0].parms[1];
9391                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9392                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9393                 {
9394                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9395                         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)
9396                         {
9397                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9398                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9399                         }
9400                 }
9401                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9402                 rsurface.texcoordtexture2f_bufferobject  = 0;
9403                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9404         }
9405         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9406         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9407         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9408         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9409 }
9410
9411 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9412 {
9413         int i, j;
9414         const msurface_t *surface = texturesurfacelist[0];
9415         const msurface_t *surface2;
9416         int firstvertex;
9417         int endvertex;
9418         int numvertices;
9419         int numtriangles;
9420         // TODO: lock all array ranges before render, rather than on each surface
9421         if (texturenumsurfaces == 1)
9422         {
9423                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9424                 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);
9425         }
9426         else if (r_batchmode.integer == 2)
9427         {
9428                 #define MAXBATCHTRIANGLES 4096
9429                 int batchtriangles = 0;
9430                 static int batchelements[MAXBATCHTRIANGLES*3];
9431                 for (i = 0;i < texturenumsurfaces;i = j)
9432                 {
9433                         surface = texturesurfacelist[i];
9434                         j = i + 1;
9435                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9436                         {
9437                                 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);
9438                                 continue;
9439                         }
9440                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9441                         batchtriangles = surface->num_triangles;
9442                         firstvertex = surface->num_firstvertex;
9443                         endvertex = surface->num_firstvertex + surface->num_vertices;
9444                         for (;j < texturenumsurfaces;j++)
9445                         {
9446                                 surface2 = texturesurfacelist[j];
9447                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9448                                         break;
9449                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9450                                 batchtriangles += surface2->num_triangles;
9451                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9452                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9453                         }
9454                         surface2 = texturesurfacelist[j-1];
9455                         numvertices = endvertex - firstvertex;
9456                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9457                 }
9458         }
9459         else if (r_batchmode.integer == 1)
9460         {
9461                 for (i = 0;i < texturenumsurfaces;i = j)
9462                 {
9463                         surface = texturesurfacelist[i];
9464                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9465                                 if (texturesurfacelist[j] != surface2)
9466                                         break;
9467                         surface2 = texturesurfacelist[j-1];
9468                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9469                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9470                         GL_LockArrays(surface->num_firstvertex, numvertices);
9471                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9472                 }
9473         }
9474         else
9475         {
9476                 for (i = 0;i < texturenumsurfaces;i++)
9477                 {
9478                         surface = texturesurfacelist[i];
9479                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9480                         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);
9481                 }
9482         }
9483 }
9484
9485 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9486 {
9487         switch(vid.renderpath)
9488         {
9489         case RENDERPATH_CGGL:
9490 #ifdef SUPPORTCG
9491                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9492                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9493 #endif
9494                 break;
9495         case RENDERPATH_GL20:
9496                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9497                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9498                 break;
9499         case RENDERPATH_GL13:
9500         case RENDERPATH_GL11:
9501                 R_Mesh_TexBind(0, surface->lightmaptexture);
9502                 break;
9503         }
9504 }
9505
9506 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9507 {
9508         // pick the closest matching water plane and bind textures
9509         int planeindex, vertexindex;
9510         float d, bestd;
9511         vec3_t vert;
9512         const float *v;
9513         r_waterstate_waterplane_t *p, *bestp;
9514         bestd = 0;
9515         bestp = NULL;
9516         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9517         {
9518                 d = 0;
9519                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9520                 {
9521                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9522                         d += fabs(PlaneDiff(vert, &p->plane));
9523                 }
9524                 if (bestd > d || !bestp)
9525                 {
9526                         bestd = d;
9527                         bestp = p;
9528                 }
9529         }
9530         switch(vid.renderpath)
9531         {
9532         case RENDERPATH_CGGL:
9533 #ifdef SUPPORTCG
9534                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9535                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9536 #endif
9537                 break;
9538         case RENDERPATH_GL20:
9539                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9540                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9541                 break;
9542         case RENDERPATH_GL13:
9543         case RENDERPATH_GL11:
9544                 break;
9545         }
9546 }
9547
9548 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9549 {
9550         int i;
9551         const msurface_t *surface;
9552         if (r_waterstate.renderingscene)
9553                 return;
9554         for (i = 0;i < texturenumsurfaces;i++)
9555         {
9556                 surface = texturesurfacelist[i];
9557                 RSurf_BindLightmapForSurface(surface);
9558                 RSurf_BindReflectionForSurface(surface);
9559                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9560                 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);
9561         }
9562 }
9563
9564 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9565 {
9566         int i;
9567         int j;
9568         const msurface_t *surface = texturesurfacelist[0];
9569         const msurface_t *surface2;
9570         int firstvertex;
9571         int endvertex;
9572         int numvertices;
9573         int numtriangles;
9574         if (texturenumsurfaces == 1)
9575         {
9576                 RSurf_BindLightmapForSurface(surface);
9577                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9578                 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);
9579         }
9580         else if (r_batchmode.integer == 2)
9581         {
9582 #define MAXBATCHTRIANGLES 4096
9583                 int batchtriangles = 0;
9584                 static int batchelements[MAXBATCHTRIANGLES*3];
9585                 for (i = 0;i < texturenumsurfaces;i = j)
9586                 {
9587                         surface = texturesurfacelist[i];
9588                         RSurf_BindLightmapForSurface(surface);
9589                         j = i + 1;
9590                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9591                         {
9592                                 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);
9593                                 continue;
9594                         }
9595                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9596                         batchtriangles = surface->num_triangles;
9597                         firstvertex = surface->num_firstvertex;
9598                         endvertex = surface->num_firstvertex + surface->num_vertices;
9599                         for (;j < texturenumsurfaces;j++)
9600                         {
9601                                 surface2 = texturesurfacelist[j];
9602                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9603                                         break;
9604                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9605                                 batchtriangles += surface2->num_triangles;
9606                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9607                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9608                         }
9609                         surface2 = texturesurfacelist[j-1];
9610                         numvertices = endvertex - firstvertex;
9611                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9612                 }
9613         }
9614         else if (r_batchmode.integer == 1)
9615         {
9616 #if 0
9617                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9618                 for (i = 0;i < texturenumsurfaces;i = j)
9619                 {
9620                         surface = texturesurfacelist[i];
9621                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9622                                 if (texturesurfacelist[j] != surface2)
9623                                         break;
9624                         Con_Printf(" %i", j - i);
9625                 }
9626                 Con_Printf("\n");
9627                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9628 #endif
9629                 for (i = 0;i < texturenumsurfaces;i = j)
9630                 {
9631                         surface = texturesurfacelist[i];
9632                         RSurf_BindLightmapForSurface(surface);
9633                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9634                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9635                                         break;
9636 #if 0
9637                         Con_Printf(" %i", j - i);
9638 #endif
9639                         surface2 = texturesurfacelist[j-1];
9640                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9641                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9642                         GL_LockArrays(surface->num_firstvertex, numvertices);
9643                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9644                 }
9645 #if 0
9646                 Con_Printf("\n");
9647 #endif
9648         }
9649         else
9650         {
9651                 for (i = 0;i < texturenumsurfaces;i++)
9652                 {
9653                         surface = texturesurfacelist[i];
9654                         RSurf_BindLightmapForSurface(surface);
9655                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9656                         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);
9657                 }
9658         }
9659 }
9660
9661 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9662 {
9663         int j;
9664         int texturesurfaceindex;
9665         if (r_showsurfaces.integer == 2)
9666         {
9667                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9668                 {
9669                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9670                         for (j = 0;j < surface->num_triangles;j++)
9671                         {
9672                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9673                                 GL_Color(f, f, f, 1);
9674                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9675                         }
9676                 }
9677         }
9678         else
9679         {
9680                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9681                 {
9682                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9683                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9684                         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);
9685                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9686                         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);
9687                 }
9688         }
9689 }
9690
9691 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9692 {
9693         int texturesurfaceindex;
9694         int i;
9695         const float *v;
9696         float *c2;
9697         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9698         {
9699                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9700                 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)
9701                 {
9702                         c2[0] = 0.5;
9703                         c2[1] = 0.5;
9704                         c2[2] = 0.5;
9705                         c2[3] = 1;
9706                 }
9707         }
9708         rsurface.lightmapcolor4f = rsurface.array_color4f;
9709         rsurface.lightmapcolor4f_bufferobject = 0;
9710         rsurface.lightmapcolor4f_bufferoffset = 0;
9711 }
9712
9713 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9714 {
9715         int texturesurfaceindex;
9716         int i;
9717         float f;
9718         const float *v;
9719         const float *c;
9720         float *c2;
9721         if (rsurface.lightmapcolor4f)
9722         {
9723                 // generate color arrays for the surfaces in this list
9724                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9725                 {
9726                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9727                         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)
9728                         {
9729                                 f = RSurf_FogVertex(v);
9730                                 c2[0] = c[0] * f;
9731                                 c2[1] = c[1] * f;
9732                                 c2[2] = c[2] * f;
9733                                 c2[3] = c[3];
9734                         }
9735                 }
9736         }
9737         else
9738         {
9739                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9740                 {
9741                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9742                         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)
9743                         {
9744                                 f = RSurf_FogVertex(v);
9745                                 c2[0] = f;
9746                                 c2[1] = f;
9747                                 c2[2] = f;
9748                                 c2[3] = 1;
9749                         }
9750                 }
9751         }
9752         rsurface.lightmapcolor4f = rsurface.array_color4f;
9753         rsurface.lightmapcolor4f_bufferobject = 0;
9754         rsurface.lightmapcolor4f_bufferoffset = 0;
9755 }
9756
9757 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9758 {
9759         int texturesurfaceindex;
9760         int i;
9761         float f;
9762         const float *v;
9763         const float *c;
9764         float *c2;
9765         if (!rsurface.lightmapcolor4f)
9766                 return;
9767         // generate color arrays for the surfaces in this list
9768         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9769         {
9770                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9771                 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)
9772                 {
9773                         f = RSurf_FogVertex(v);
9774                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9775                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9776                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9777                         c2[3] = c[3];
9778                 }
9779         }
9780         rsurface.lightmapcolor4f = rsurface.array_color4f;
9781         rsurface.lightmapcolor4f_bufferobject = 0;
9782         rsurface.lightmapcolor4f_bufferoffset = 0;
9783 }
9784
9785 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9786 {
9787         int texturesurfaceindex;
9788         int i;
9789         const float *c;
9790         float *c2;
9791         if (!rsurface.lightmapcolor4f)
9792                 return;
9793         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9794         {
9795                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9796                 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)
9797                 {
9798                         c2[0] = c[0] * r;
9799                         c2[1] = c[1] * g;
9800                         c2[2] = c[2] * b;
9801                         c2[3] = c[3] * a;
9802                 }
9803         }
9804         rsurface.lightmapcolor4f = rsurface.array_color4f;
9805         rsurface.lightmapcolor4f_bufferobject = 0;
9806         rsurface.lightmapcolor4f_bufferoffset = 0;
9807 }
9808
9809 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9810 {
9811         int texturesurfaceindex;
9812         int i;
9813         const float *c;
9814         float *c2;
9815         if (!rsurface.lightmapcolor4f)
9816                 return;
9817         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9818         {
9819                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9820                 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)
9821                 {
9822                         c2[0] = c[0] + r_refdef.scene.ambient;
9823                         c2[1] = c[1] + r_refdef.scene.ambient;
9824                         c2[2] = c[2] + r_refdef.scene.ambient;
9825                         c2[3] = c[3];
9826                 }
9827         }
9828         rsurface.lightmapcolor4f = rsurface.array_color4f;
9829         rsurface.lightmapcolor4f_bufferobject = 0;
9830         rsurface.lightmapcolor4f_bufferoffset = 0;
9831 }
9832
9833 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9834 {
9835         // TODO: optimize
9836         rsurface.lightmapcolor4f = NULL;
9837         rsurface.lightmapcolor4f_bufferobject = 0;
9838         rsurface.lightmapcolor4f_bufferoffset = 0;
9839         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9840         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9841         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9842         GL_Color(r, g, b, a);
9843         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9844 }
9845
9846 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9847 {
9848         // TODO: optimize applyfog && applycolor case
9849         // just apply fog if necessary, and tint the fog color array if necessary
9850         rsurface.lightmapcolor4f = NULL;
9851         rsurface.lightmapcolor4f_bufferobject = 0;
9852         rsurface.lightmapcolor4f_bufferoffset = 0;
9853         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9854         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9855         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9856         GL_Color(r, g, b, a);
9857         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9858 }
9859
9860 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9861 {
9862         int texturesurfaceindex;
9863         int i;
9864         float *c;
9865         // TODO: optimize
9866         if (texturesurfacelist[0]->lightmapinfo)
9867         {
9868                 // generate color arrays for the surfaces in this list
9869                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9870                 {
9871                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9872                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9873                         {
9874                                 if (surface->lightmapinfo->samples)
9875                                 {
9876                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
9877                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
9878                                         VectorScale(lm, scale, c);
9879                                         if (surface->lightmapinfo->styles[1] != 255)
9880                                         {
9881                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9882                                                 lm += size3;
9883                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
9884                                                 VectorMA(c, scale, lm, c);
9885                                                 if (surface->lightmapinfo->styles[2] != 255)
9886                                                 {
9887                                                         lm += size3;
9888                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
9889                                                         VectorMA(c, scale, lm, c);
9890                                                         if (surface->lightmapinfo->styles[3] != 255)
9891                                                         {
9892                                                                 lm += size3;
9893                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
9894                                                                 VectorMA(c, scale, lm, c);
9895                                                         }
9896                                                 }
9897                                         }
9898                                 }
9899                                 else
9900                                         VectorClear(c);
9901                                 c[3] = 1;
9902                         }
9903                 }
9904                 rsurface.lightmapcolor4f = rsurface.array_color4f;
9905                 rsurface.lightmapcolor4f_bufferobject = 0;
9906                 rsurface.lightmapcolor4f_bufferoffset = 0;
9907         }
9908         else
9909         {
9910                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
9911                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
9912                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9913         }
9914         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9915         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9916         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9917         GL_Color(r, g, b, a);
9918         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9919 }
9920
9921 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
9922 {
9923         int texturesurfaceindex;
9924         int i;
9925         float f;
9926         float alpha;
9927         const float *v;
9928         const float *n;
9929         float *c;
9930         vec3_t ambientcolor;
9931         vec3_t diffusecolor;
9932         vec3_t lightdir;
9933         // TODO: optimize
9934         // model lighting
9935         VectorCopy(rsurface.modellight_lightdir, lightdir);
9936         f = 0.5f * r_refdef.lightmapintensity;
9937         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9938         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9939         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9940         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9941         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9942         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9943         alpha = *a;
9944         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
9945         {
9946                 // generate color arrays for the surfaces in this list
9947                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9948                 {
9949                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9950                         int numverts = surface->num_vertices;
9951                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
9952                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
9953                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
9954                         // q3-style directional shading
9955                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
9956                         {
9957                                 if ((f = DotProduct(n, lightdir)) > 0)
9958                                         VectorMA(ambientcolor, f, diffusecolor, c);
9959                                 else
9960                                         VectorCopy(ambientcolor, c);
9961                                 c[3] = alpha;
9962                         }
9963                 }
9964                 *r = 1;
9965                 *g = 1;
9966                 *b = 1;
9967                 *a = 1;
9968                 rsurface.lightmapcolor4f = rsurface.array_color4f;
9969                 rsurface.lightmapcolor4f_bufferobject = 0;
9970                 rsurface.lightmapcolor4f_bufferoffset = 0;
9971                 *applycolor = false;
9972         }
9973         else
9974         {
9975                 *r = ambientcolor[0];
9976                 *g = ambientcolor[1];
9977                 *b = ambientcolor[2];
9978                 rsurface.lightmapcolor4f = NULL;
9979                 rsurface.lightmapcolor4f_bufferobject = 0;
9980                 rsurface.lightmapcolor4f_bufferoffset = 0;
9981         }
9982 }
9983
9984 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9985 {
9986         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
9987         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9988         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9989         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9990         GL_Color(r, g, b, a);
9991         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9992 }
9993
9994 void RSurf_SetupDepthAndCulling(void)
9995 {
9996         // submodels are biased to avoid z-fighting with world surfaces that they
9997         // may be exactly overlapping (avoids z-fighting artifacts on certain
9998         // doors and things in Quake maps)
9999         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10000         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10001         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10002         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10003 }
10004
10005 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10006 {
10007         // transparent sky would be ridiculous
10008         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10009                 return;
10010         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10011         skyrenderlater = true;
10012         RSurf_SetupDepthAndCulling();
10013         GL_DepthMask(true);
10014         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10015         // skymasking on them, and Quake3 never did sky masking (unlike
10016         // software Quake and software Quake2), so disable the sky masking
10017         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10018         // and skymasking also looks very bad when noclipping outside the
10019         // level, so don't use it then either.
10020         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10021         {
10022                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10023                 R_Mesh_ColorPointer(NULL, 0, 0);
10024                 R_Mesh_ResetTextureState();
10025                 if (skyrendermasked)
10026                 {
10027                         R_SetupShader_DepthOrShadow();
10028                         // depth-only (masking)
10029                         GL_ColorMask(0,0,0,0);
10030                         // just to make sure that braindead drivers don't draw
10031                         // anything despite that colormask...
10032                         GL_BlendFunc(GL_ZERO, GL_ONE);
10033                 }
10034                 else
10035                 {
10036                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10037                         // fog sky
10038                         GL_BlendFunc(GL_ONE, GL_ZERO);
10039                 }
10040                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10041                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10042                 if (skyrendermasked)
10043                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10044         }
10045         R_Mesh_ResetTextureState();
10046         GL_Color(1, 1, 1, 1);
10047 }
10048
10049 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10050 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10051 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10052 {
10053         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10054         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10055
10056         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10057                 return;
10058
10059         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10060                 R_Mesh_ColorPointer(NULL, 0, 0);
10061         else
10062                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10063
10064         if (refract)
10065         {
10066                 // render background
10067                 GL_BlendFunc(GL_ONE, GL_ZERO);
10068                 GL_DepthMask(true);
10069                 GL_AlphaTest(false);
10070
10071                 GL_Color(1, 1, 1, 1);
10072                 R_Mesh_ColorPointer(NULL, 0, 0);
10073
10074                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10075                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10076                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10077                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10078                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10079                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10080                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10081                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10082                 GL_LockArrays(0, 0);
10083
10084                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10085                 GL_DepthMask(false);
10086                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10087                         R_Mesh_ColorPointer(NULL, 0, 0);
10088                 else
10089                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10090         }
10091
10092         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10093
10094         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10095         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10096         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10097         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10098         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10099         if (!prepass)
10100                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10101
10102         if (refract)
10103         {
10104                 GL_BlendFunc(GL_ONE, GL_ZERO);
10105                 GL_DepthMask(true);
10106                 GL_AlphaTest(false);
10107         }
10108         else
10109         {
10110                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10111                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10112                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10113         }
10114
10115         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10116         {
10117                 if (refract || reflect)
10118                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10119                 else
10120                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10121         }
10122         else
10123         {
10124                 if (refract || reflect)
10125                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10126                 else
10127                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10128         }
10129         GL_LockArrays(0, 0);
10130 }
10131
10132 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10133 {
10134         // OpenGL 1.3 path - anything not completely ancient
10135         int texturesurfaceindex;
10136         qboolean applycolor;
10137         qboolean applyfog;
10138         int layerindex;
10139         const texturelayer_t *layer;
10140         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10141
10142         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10143         {
10144                 vec4_t layercolor;
10145                 int layertexrgbscale;
10146                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10147                 {
10148                         if (layerindex == 0)
10149                                 GL_AlphaTest(true);
10150                         else
10151                         {
10152                                 GL_AlphaTest(false);
10153                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10154                         }
10155                 }
10156                 GL_DepthMask(layer->depthmask && writedepth);
10157                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10158                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10159                 {
10160                         layertexrgbscale = 4;
10161                         VectorScale(layer->color, 0.25f, layercolor);
10162                 }
10163                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10164                 {
10165                         layertexrgbscale = 2;
10166                         VectorScale(layer->color, 0.5f, layercolor);
10167                 }
10168                 else
10169                 {
10170                         layertexrgbscale = 1;
10171                         VectorScale(layer->color, 1.0f, layercolor);
10172                 }
10173                 layercolor[3] = layer->color[3];
10174                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10175                 R_Mesh_ColorPointer(NULL, 0, 0);
10176                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10177                 switch (layer->type)
10178                 {
10179                 case TEXTURELAYERTYPE_LITTEXTURE:
10180                         // single-pass lightmapped texture with 2x rgbscale
10181                         //R_Mesh_TexBind(0, r_texture_white);
10182                         R_Mesh_TexMatrix(0, NULL);
10183                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10184                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10185                         R_Mesh_TexBind(1, layer->texture);
10186                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10187                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10188                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10189                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10190                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10191                         else if (rsurface.uselightmaptexture)
10192                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10193                         else
10194                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10195                         break;
10196                 case TEXTURELAYERTYPE_TEXTURE:
10197                         // singletexture unlit texture with transparency support
10198                         R_Mesh_TexBind(0, layer->texture);
10199                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10200                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10201                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10202                         R_Mesh_TexBind(1, 0);
10203                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10204                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10205                         break;
10206                 case TEXTURELAYERTYPE_FOG:
10207                         // singletexture fogging
10208                         if (layer->texture)
10209                         {
10210                                 R_Mesh_TexBind(0, layer->texture);
10211                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10212                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10213                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10214                         }
10215                         else
10216                         {
10217                                 R_Mesh_TexBind(0, 0);
10218                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10219                         }
10220                         R_Mesh_TexBind(1, 0);
10221                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10222                         // generate a color array for the fog pass
10223                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10224                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10225                         {
10226                                 int i;
10227                                 float f;
10228                                 const float *v;
10229                                 float *c;
10230                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10231                                 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)
10232                                 {
10233                                         f = 1 - RSurf_FogVertex(v);
10234                                         c[0] = layercolor[0];
10235                                         c[1] = layercolor[1];
10236                                         c[2] = layercolor[2];
10237                                         c[3] = f * layercolor[3];
10238                                 }
10239                         }
10240                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10241                         break;
10242                 default:
10243                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10244                 }
10245                 GL_LockArrays(0, 0);
10246         }
10247         CHECKGLERROR
10248         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10249         {
10250                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10251                 GL_AlphaTest(false);
10252         }
10253 }
10254
10255 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10256 {
10257         // OpenGL 1.1 - crusty old voodoo path
10258         int texturesurfaceindex;
10259         qboolean applyfog;
10260         int layerindex;
10261         const texturelayer_t *layer;
10262         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10263
10264         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10265         {
10266                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10267                 {
10268                         if (layerindex == 0)
10269                                 GL_AlphaTest(true);
10270                         else
10271                         {
10272                                 GL_AlphaTest(false);
10273                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10274                         }
10275                 }
10276                 GL_DepthMask(layer->depthmask && writedepth);
10277                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10278                 R_Mesh_ColorPointer(NULL, 0, 0);
10279                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10280                 switch (layer->type)
10281                 {
10282                 case TEXTURELAYERTYPE_LITTEXTURE:
10283                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10284                         {
10285                                 // two-pass lit texture with 2x rgbscale
10286                                 // first the lightmap pass
10287                                 //R_Mesh_TexBind(0, r_texture_white);
10288                                 R_Mesh_TexMatrix(0, NULL);
10289                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10290                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10291                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10292                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10293                                 else if (rsurface.uselightmaptexture)
10294                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10295                                 else
10296                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10297                                 GL_LockArrays(0, 0);
10298                                 // then apply the texture to it
10299                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10300                                 R_Mesh_TexBind(0, layer->texture);
10301                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10302                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10303                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10304                                 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);
10305                         }
10306                         else
10307                         {
10308                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10309                                 R_Mesh_TexBind(0, layer->texture);
10310                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10311                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10312                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10313                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10314                                         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);
10315                                 else
10316                                         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);
10317                         }
10318                         break;
10319                 case TEXTURELAYERTYPE_TEXTURE:
10320                         // singletexture unlit texture with transparency support
10321                         R_Mesh_TexBind(0, layer->texture);
10322                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10323                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10324                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10325                         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);
10326                         break;
10327                 case TEXTURELAYERTYPE_FOG:
10328                         // singletexture fogging
10329                         if (layer->texture)
10330                         {
10331                                 R_Mesh_TexBind(0, layer->texture);
10332                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10333                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10334                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10335                         }
10336                         else
10337                         {
10338                                 R_Mesh_TexBind(0, 0);
10339                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10340                         }
10341                         // generate a color array for the fog pass
10342                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10343                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10344                         {
10345                                 int i;
10346                                 float f;
10347                                 const float *v;
10348                                 float *c;
10349                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10350                                 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)
10351                                 {
10352                                         f = 1 - RSurf_FogVertex(v);
10353                                         c[0] = layer->color[0];
10354                                         c[1] = layer->color[1];
10355                                         c[2] = layer->color[2];
10356                                         c[3] = f * layer->color[3];
10357                                 }
10358                         }
10359                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10360                         break;
10361                 default:
10362                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10363                 }
10364                 GL_LockArrays(0, 0);
10365         }
10366         CHECKGLERROR
10367         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10368         {
10369                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10370                 GL_AlphaTest(false);
10371         }
10372 }
10373
10374 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10375 {
10376         float c[4];
10377
10378         GL_AlphaTest(false);
10379         R_Mesh_ColorPointer(NULL, 0, 0);
10380         R_Mesh_ResetTextureState();
10381         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10382
10383         if(rsurface.texture && rsurface.texture->currentskinframe)
10384         {
10385                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10386                 c[3] *= rsurface.texture->currentalpha;
10387         }
10388         else
10389         {
10390                 c[0] = 1;
10391                 c[1] = 0;
10392                 c[2] = 1;
10393                 c[3] = 1;
10394         }
10395
10396         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10397         {
10398                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10399                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10400                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10401         }
10402
10403         // brighten it up (as texture value 127 means "unlit")
10404         c[0] *= 2 * r_refdef.view.colorscale;
10405         c[1] *= 2 * r_refdef.view.colorscale;
10406         c[2] *= 2 * r_refdef.view.colorscale;
10407
10408         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10409                 c[3] *= r_wateralpha.value;
10410
10411         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10412         {
10413                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10414                 GL_DepthMask(false);
10415         }
10416         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10417         {
10418                 GL_BlendFunc(GL_ONE, GL_ONE);
10419                 GL_DepthMask(false);
10420         }
10421         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10422         {
10423                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10424                 GL_DepthMask(false);
10425         }
10426         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10427         {
10428                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10429                 GL_DepthMask(false);
10430         }
10431         else
10432         {
10433                 GL_BlendFunc(GL_ONE, GL_ZERO);
10434                 GL_DepthMask(writedepth);
10435         }
10436
10437         rsurface.lightmapcolor4f = NULL;
10438
10439         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10440         {
10441                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10442
10443                 rsurface.lightmapcolor4f = NULL;
10444                 rsurface.lightmapcolor4f_bufferobject = 0;
10445                 rsurface.lightmapcolor4f_bufferoffset = 0;
10446         }
10447         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10448         {
10449                 qboolean applycolor = true;
10450                 float one = 1.0;
10451
10452                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10453
10454                 r_refdef.lightmapintensity = 1;
10455                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10456                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10457         }
10458         else
10459         {
10460                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10461
10462                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10463                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10464                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10465         }
10466
10467         if(!rsurface.lightmapcolor4f)
10468                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10469
10470         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10471         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10472         if(r_refdef.fogenabled)
10473                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10474
10475         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10476         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10477 }
10478
10479 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10480 {
10481         CHECKGLERROR
10482         RSurf_SetupDepthAndCulling();
10483         if (r_showsurfaces.integer == 3 && !prepass)
10484         {
10485                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10486                 return;
10487         }
10488         switch (vid.renderpath)
10489         {
10490         case RENDERPATH_GL20:
10491         case RENDERPATH_CGGL:
10492                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10493                 break;
10494         case RENDERPATH_GL13:
10495                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10496                 break;
10497         case RENDERPATH_GL11:
10498                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10499                 break;
10500         }
10501         CHECKGLERROR
10502 }
10503
10504 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10505 {
10506         CHECKGLERROR
10507         RSurf_SetupDepthAndCulling();
10508         if (r_showsurfaces.integer == 3 && !prepass)
10509         {
10510                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10511                 return;
10512         }
10513         switch (vid.renderpath)
10514         {
10515         case RENDERPATH_GL20:
10516         case RENDERPATH_CGGL:
10517                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10518                 break;
10519         case RENDERPATH_GL13:
10520                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10521                 break;
10522         case RENDERPATH_GL11:
10523                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10524                 break;
10525         }
10526         CHECKGLERROR
10527 }
10528
10529 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10530 {
10531         int i, j;
10532         int texturenumsurfaces, endsurface;
10533         texture_t *texture;
10534         const msurface_t *surface;
10535         const msurface_t *texturesurfacelist[256];
10536
10537         // if the model is static it doesn't matter what value we give for
10538         // wantnormals and wanttangents, so this logic uses only rules applicable
10539         // to a model, knowing that they are meaningless otherwise
10540         if (ent == r_refdef.scene.worldentity)
10541                 RSurf_ActiveWorldEntity();
10542         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10543                 RSurf_ActiveModelEntity(ent, false, false, false);
10544         else
10545         {
10546                 switch (vid.renderpath)
10547                 {
10548                 case RENDERPATH_GL20:
10549                 case RENDERPATH_CGGL:
10550                         RSurf_ActiveModelEntity(ent, true, true, false);
10551                         break;
10552                 case RENDERPATH_GL13:
10553                 case RENDERPATH_GL11:
10554                         RSurf_ActiveModelEntity(ent, true, false, false);
10555                         break;
10556                 }
10557         }
10558
10559         if (r_transparentdepthmasking.integer)
10560         {
10561                 qboolean setup = false;
10562                 for (i = 0;i < numsurfaces;i = j)
10563                 {
10564                         j = i + 1;
10565                         surface = rsurface.modelsurfaces + surfacelist[i];
10566                         texture = surface->texture;
10567                         rsurface.texture = R_GetCurrentTexture(texture);
10568                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10569                         // scan ahead until we find a different texture
10570                         endsurface = min(i + 1024, numsurfaces);
10571                         texturenumsurfaces = 0;
10572                         texturesurfacelist[texturenumsurfaces++] = surface;
10573                         for (;j < endsurface;j++)
10574                         {
10575                                 surface = rsurface.modelsurfaces + surfacelist[j];
10576                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10577                                         break;
10578                                 texturesurfacelist[texturenumsurfaces++] = surface;
10579                         }
10580                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10581                                 continue;
10582                         // render the range of surfaces as depth
10583                         if (!setup)
10584                         {
10585                                 setup = true;
10586                                 GL_ColorMask(0,0,0,0);
10587                                 GL_Color(1,1,1,1);
10588                                 GL_DepthTest(true);
10589                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10590                                 GL_DepthMask(true);
10591                                 GL_AlphaTest(false);
10592                                 R_Mesh_ColorPointer(NULL, 0, 0);
10593                                 R_Mesh_ResetTextureState();
10594                                 R_SetupShader_DepthOrShadow();
10595                         }
10596                         RSurf_SetupDepthAndCulling();
10597                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10598                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10599                 }
10600                 if (setup)
10601                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10602         }
10603
10604         for (i = 0;i < numsurfaces;i = j)
10605         {
10606                 j = i + 1;
10607                 surface = rsurface.modelsurfaces + surfacelist[i];
10608                 texture = surface->texture;
10609                 rsurface.texture = R_GetCurrentTexture(texture);
10610                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10611                 // scan ahead until we find a different texture
10612                 endsurface = min(i + 1024, numsurfaces);
10613                 texturenumsurfaces = 0;
10614                 texturesurfacelist[texturenumsurfaces++] = surface;
10615                 for (;j < endsurface;j++)
10616                 {
10617                         surface = rsurface.modelsurfaces + surfacelist[j];
10618                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10619                                 break;
10620                         texturesurfacelist[texturenumsurfaces++] = surface;
10621                 }
10622                 // render the range of surfaces
10623                 if (ent == r_refdef.scene.worldentity)
10624                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10625                 else
10626                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10627         }
10628         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10629         GL_AlphaTest(false);
10630 }
10631
10632 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10633 {
10634         // transparent surfaces get pushed off into the transparent queue
10635         int surfacelistindex;
10636         const msurface_t *surface;
10637         vec3_t tempcenter, center;
10638         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10639         {
10640                 surface = texturesurfacelist[surfacelistindex];
10641                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10642                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10643                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10644                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10645                 if (queueentity->transparent_offset) // transparent offset
10646                 {
10647                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10648                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10649                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10650                 }
10651                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10652         }
10653 }
10654
10655 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10656 {
10657         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10658         CHECKGLERROR
10659         if (depthonly)
10660         {
10661                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10662                         return;
10663                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10664                         return;
10665                 RSurf_SetupDepthAndCulling();
10666                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10667                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10668         }
10669         else if (prepass)
10670         {
10671                 if (!rsurface.texture->currentnumlayers)
10672                         return;
10673                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10674                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10675                 else
10676                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10677         }
10678         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10679         {
10680                 RSurf_SetupDepthAndCulling();
10681                 GL_AlphaTest(false);
10682                 R_Mesh_ColorPointer(NULL, 0, 0);
10683                 R_Mesh_ResetTextureState();
10684                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10685                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10686                 GL_DepthMask(true);
10687                 GL_BlendFunc(GL_ONE, GL_ZERO);
10688                 GL_Color(0, 0, 0, 1);
10689                 GL_DepthTest(writedepth);
10690                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10691         }
10692         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10693         {
10694                 RSurf_SetupDepthAndCulling();
10695                 GL_AlphaTest(false);
10696                 R_Mesh_ColorPointer(NULL, 0, 0);
10697                 R_Mesh_ResetTextureState();
10698                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10699                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10700                 GL_DepthMask(true);
10701                 GL_BlendFunc(GL_ONE, GL_ZERO);
10702                 GL_DepthTest(true);
10703                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10704         }
10705         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10706                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10707         else if (!rsurface.texture->currentnumlayers)
10708                 return;
10709         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10710         {
10711                 // in the deferred case, transparent surfaces were queued during prepass
10712                 if (!r_shadow_usingdeferredprepass)
10713                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10714         }
10715         else
10716         {
10717                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10718                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10719         }
10720         CHECKGLERROR
10721 }
10722
10723 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10724 {
10725         int i, j;
10726         texture_t *texture;
10727         // break the surface list down into batches by texture and use of lightmapping
10728         for (i = 0;i < numsurfaces;i = j)
10729         {
10730                 j = i + 1;
10731                 // texture is the base texture pointer, rsurface.texture is the
10732                 // current frame/skin the texture is directing us to use (for example
10733                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10734                 // use skin 1 instead)
10735                 texture = surfacelist[i]->texture;
10736                 rsurface.texture = R_GetCurrentTexture(texture);
10737                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10738                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10739                 {
10740                         // if this texture is not the kind we want, skip ahead to the next one
10741                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10742                                 ;
10743                         continue;
10744                 }
10745                 // simply scan ahead until we find a different texture or lightmap state
10746                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10747                         ;
10748                 // render the range of surfaces
10749                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10750         }
10751 }
10752
10753 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10754 {
10755         CHECKGLERROR
10756         if (depthonly)
10757         {
10758                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10759                         return;
10760                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10761                         return;
10762                 RSurf_SetupDepthAndCulling();
10763                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10764                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10765         }
10766         else if (prepass)
10767         {
10768                 if (!rsurface.texture->currentnumlayers)
10769                         return;
10770                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10771                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10772                 else
10773                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10774         }
10775         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10776         {
10777                 RSurf_SetupDepthAndCulling();
10778                 GL_AlphaTest(false);
10779                 R_Mesh_ColorPointer(NULL, 0, 0);
10780                 R_Mesh_ResetTextureState();
10781                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10782                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10783                 GL_DepthMask(true);
10784                 GL_BlendFunc(GL_ONE, GL_ZERO);
10785                 GL_Color(0, 0, 0, 1);
10786                 GL_DepthTest(writedepth);
10787                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10788         }
10789         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10790         {
10791                 RSurf_SetupDepthAndCulling();
10792                 GL_AlphaTest(false);
10793                 R_Mesh_ColorPointer(NULL, 0, 0);
10794                 R_Mesh_ResetTextureState();
10795                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10796                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10797                 GL_DepthMask(true);
10798                 GL_BlendFunc(GL_ONE, GL_ZERO);
10799                 GL_DepthTest(true);
10800                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10801         }
10802         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10803                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10804         else if (!rsurface.texture->currentnumlayers)
10805                 return;
10806         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10807         {
10808                 // in the deferred case, transparent surfaces were queued during prepass
10809                 if (!r_shadow_usingdeferredprepass)
10810                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10811         }
10812         else
10813         {
10814                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10815                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10816         }
10817         CHECKGLERROR
10818 }
10819
10820 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10821 {
10822         int i, j;
10823         texture_t *texture;
10824         // break the surface list down into batches by texture and use of lightmapping
10825         for (i = 0;i < numsurfaces;i = j)
10826         {
10827                 j = i + 1;
10828                 // texture is the base texture pointer, rsurface.texture is the
10829                 // current frame/skin the texture is directing us to use (for example
10830                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10831                 // use skin 1 instead)
10832                 texture = surfacelist[i]->texture;
10833                 rsurface.texture = R_GetCurrentTexture(texture);
10834                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10835                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10836                 {
10837                         // if this texture is not the kind we want, skip ahead to the next one
10838                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10839                                 ;
10840                         continue;
10841                 }
10842                 // simply scan ahead until we find a different texture or lightmap state
10843                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10844                         ;
10845                 // render the range of surfaces
10846                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10847         }
10848 }
10849
10850 float locboxvertex3f[6*4*3] =
10851 {
10852         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10853         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10854         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10855         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10856         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10857         1,0,0, 0,0,0, 0,1,0, 1,1,0
10858 };
10859
10860 unsigned short locboxelements[6*2*3] =
10861 {
10862          0, 1, 2, 0, 2, 3,
10863          4, 5, 6, 4, 6, 7,
10864          8, 9,10, 8,10,11,
10865         12,13,14, 12,14,15,
10866         16,17,18, 16,18,19,
10867         20,21,22, 20,22,23
10868 };
10869
10870 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10871 {
10872         int i, j;
10873         cl_locnode_t *loc = (cl_locnode_t *)ent;
10874         vec3_t mins, size;
10875         float vertex3f[6*4*3];
10876         CHECKGLERROR
10877         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10878         GL_DepthMask(false);
10879         GL_DepthRange(0, 1);
10880         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10881         GL_DepthTest(true);
10882         GL_CullFace(GL_NONE);
10883         R_EntityMatrix(&identitymatrix);
10884
10885         R_Mesh_VertexPointer(vertex3f, 0, 0);
10886         R_Mesh_ColorPointer(NULL, 0, 0);
10887         R_Mesh_ResetTextureState();
10888         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10889
10890         i = surfacelist[0];
10891         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10892                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10893                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10894                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10895
10896         if (VectorCompare(loc->mins, loc->maxs))
10897         {
10898                 VectorSet(size, 2, 2, 2);
10899                 VectorMA(loc->mins, -0.5f, size, mins);
10900         }
10901         else
10902         {
10903                 VectorCopy(loc->mins, mins);
10904                 VectorSubtract(loc->maxs, loc->mins, size);
10905         }
10906
10907         for (i = 0;i < 6*4*3;)
10908                 for (j = 0;j < 3;j++, i++)
10909                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10910
10911         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
10912 }
10913
10914 void R_DrawLocs(void)
10915 {
10916         int index;
10917         cl_locnode_t *loc, *nearestloc;
10918         vec3_t center;
10919         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10920         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10921         {
10922                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10923                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10924         }
10925 }
10926
10927 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10928 {
10929         if (decalsystem->decals)
10930                 Mem_Free(decalsystem->decals);
10931         memset(decalsystem, 0, sizeof(*decalsystem));
10932 }
10933
10934 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
10935 {
10936         tridecal_t *decal;
10937         tridecal_t *decals;
10938         int i;
10939         int maxdecals;
10940
10941         // expand or initialize the system
10942         if (decalsystem->maxdecals <= decalsystem->numdecals)
10943         {
10944                 decalsystem_t old = *decalsystem;
10945                 qboolean useshortelements;
10946                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10947                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10948                 decalsystem->decals = Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
10949                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10950                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10951                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10952                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10953                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10954                 if (decalsystem->numdecals)
10955                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10956                 if (old.decals)
10957                         Mem_Free(old.decals);
10958                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10959                         decalsystem->element3i[i] = i;
10960                 if (useshortelements)
10961                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10962                                 decalsystem->element3s[i] = i;
10963         }
10964
10965         // grab a decal and search for another free slot for the next one
10966         maxdecals = decalsystem->maxdecals;
10967         decals = decalsystem->decals;
10968         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10969         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
10970                 ;
10971         decalsystem->freedecal = i;
10972         if (decalsystem->numdecals <= i)
10973                 decalsystem->numdecals = i + 1;
10974
10975         // initialize the decal
10976         decal->lived = 0;
10977         decal->triangleindex = triangleindex;
10978         decal->surfaceindex = surfaceindex;
10979         decal->decalsequence = decalsequence;
10980         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
10981         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
10982         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
10983         decal->color4ub[0][3] = 255;
10984         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
10985         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
10986         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
10987         decal->color4ub[1][3] = 255;
10988         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
10989         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
10990         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
10991         decal->color4ub[2][3] = 255;
10992         decal->vertex3f[0][0] = v0[0];
10993         decal->vertex3f[0][1] = v0[1];
10994         decal->vertex3f[0][2] = v0[2];
10995         decal->vertex3f[1][0] = v1[0];
10996         decal->vertex3f[1][1] = v1[1];
10997         decal->vertex3f[1][2] = v1[2];
10998         decal->vertex3f[2][0] = v2[0];
10999         decal->vertex3f[2][1] = v2[1];
11000         decal->vertex3f[2][2] = v2[2];
11001         decal->texcoord2f[0][0] = t0[0];
11002         decal->texcoord2f[0][1] = t0[1];
11003         decal->texcoord2f[1][0] = t1[0];
11004         decal->texcoord2f[1][1] = t1[1];
11005         decal->texcoord2f[2][0] = t2[0];
11006         decal->texcoord2f[2][1] = t2[1];
11007 }
11008
11009 extern cvar_t cl_decals_bias;
11010 extern cvar_t cl_decals_models;
11011 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11012 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
11013 {
11014         matrix4x4_t projection;
11015         decalsystem_t *decalsystem;
11016         qboolean dynamic;
11017         dp_model_t *model;
11018         const float *vertex3f;
11019         const msurface_t *surface;
11020         const msurface_t *surfaces;
11021         const int *surfacelist;
11022         const texture_t *texture;
11023         int numvertices;
11024         int numtriangles;
11025         int numsurfacelist;
11026         int surfacelistindex;
11027         int surfaceindex;
11028         int triangleindex;
11029         int decalsurfaceindex;
11030         int cornerindex;
11031         int index;
11032         int numpoints;
11033         const int *e;
11034         float localorigin[3];
11035         float localnormal[3];
11036         float localmins[3];
11037         float localmaxs[3];
11038         float localsize;
11039         float ilocalsize;
11040         float v[9][3];
11041         float tc[9][2];
11042         float c[9][4];
11043         //float normal[3];
11044         float planes[6][4];
11045         float f;
11046         float points[2][9][3];
11047         float angles[3];
11048         float temp[3];
11049
11050         decalsystem = &ent->decalsystem;
11051         model = ent->model;
11052         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11053         {
11054                 R_DecalSystem_Reset(&ent->decalsystem);
11055                 return;
11056         }
11057
11058         if (!model->brush.data_nodes && !cl_decals_models.integer)
11059         {
11060                 if (decalsystem->model)
11061                         R_DecalSystem_Reset(decalsystem);
11062                 return;
11063         }
11064
11065         if (decalsystem->model != model)
11066                 R_DecalSystem_Reset(decalsystem);
11067         decalsystem->model = model;
11068
11069         RSurf_ActiveModelEntity(ent, false, false, false);
11070
11071         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11072         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11073         VectorNormalize(localnormal);
11074         localsize = worldsize*rsurface.inversematrixscale;
11075         ilocalsize = 1.0f / localsize;
11076         localmins[0] = localorigin[0] - localsize;
11077         localmins[1] = localorigin[1] - localsize;
11078         localmins[2] = localorigin[2] - localsize;
11079         localmaxs[0] = localorigin[0] + localsize;
11080         localmaxs[1] = localorigin[1] + localsize;
11081         localmaxs[2] = localorigin[2] + localsize;
11082
11083         //VectorCopy(localnormal, planes[4]);
11084         //VectorVectors(planes[4], planes[2], planes[0]);
11085         AnglesFromVectors(angles, localnormal, NULL, false);
11086         AngleVectors(angles, planes[0], planes[2], planes[4]);
11087         VectorNegate(planes[0], planes[1]);
11088         VectorNegate(planes[2], planes[3]);
11089         VectorNegate(planes[4], planes[5]);
11090         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11091         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11092         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11093         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11094         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11095         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11096
11097 #if 1
11098 // works
11099 {
11100         matrix4x4_t forwardprojection;
11101         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11102         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11103 }
11104 #else
11105 // broken
11106 {
11107         float projectionvector[4][3];
11108         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11109         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11110         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11111         projectionvector[0][0] = planes[0][0] * ilocalsize;
11112         projectionvector[0][1] = planes[1][0] * ilocalsize;
11113         projectionvector[0][2] = planes[2][0] * ilocalsize;
11114         projectionvector[1][0] = planes[0][1] * ilocalsize;
11115         projectionvector[1][1] = planes[1][1] * ilocalsize;
11116         projectionvector[1][2] = planes[2][1] * ilocalsize;
11117         projectionvector[2][0] = planes[0][2] * ilocalsize;
11118         projectionvector[2][1] = planes[1][2] * ilocalsize;
11119         projectionvector[2][2] = planes[2][2] * ilocalsize;
11120         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11121         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11122         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11123         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11124 }
11125 #endif
11126
11127         dynamic = model->surfmesh.isanimated;
11128         vertex3f = rsurface.modelvertex3f;
11129         numsurfacelist = model->nummodelsurfaces;
11130         surfacelist = model->sortedmodelsurfaces;
11131         surfaces = model->data_surfaces;
11132         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11133         {
11134                 surfaceindex = surfacelist[surfacelistindex];
11135                 surface = surfaces + surfaceindex;
11136                 // skip transparent surfaces
11137                 texture = surface->texture;
11138                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11139                         continue;
11140                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11141                         continue;
11142                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11143                         continue;
11144                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11145                 numvertices = surface->num_vertices;
11146                 numtriangles = surface->num_triangles;
11147                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11148                 {
11149                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11150                         {
11151                                 index = 3*e[cornerindex];
11152                                 VectorCopy(vertex3f + index, v[cornerindex]);
11153                         }
11154                         // cull backfaces
11155                         //TriangleNormal(v[0], v[1], v[2], normal);
11156                         //if (DotProduct(normal, localnormal) < 0.0f)
11157                         //      continue;
11158                         // clip by each of the box planes formed from the projection matrix
11159                         // if anything survives, we emit the decal
11160                         numpoints = PolygonF_Clip(3        , v[0]        , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11161                         if (numpoints < 3)
11162                                 continue;
11163                         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
11164                         if (numpoints < 3)
11165                                 continue;
11166                         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11167                         if (numpoints < 3)
11168                                 continue;
11169                         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
11170                         if (numpoints < 3)
11171                                 continue;
11172                         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11173                         if (numpoints < 3)
11174                                 continue;
11175                         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
11176                         if (numpoints < 3)
11177                                 continue;
11178                         // some part of the triangle survived, so we have to accept it...
11179                         if (dynamic)
11180                         {
11181                                 // dynamic always uses the original triangle
11182                                 numpoints = 3;
11183                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11184                                 {
11185                                         index = 3*e[cornerindex];
11186                                         VectorCopy(vertex3f + index, v[cornerindex]);
11187                                 }
11188                         }
11189                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11190                         {
11191                                 // convert vertex positions to texcoords
11192                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11193                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11194                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11195                                 // calculate distance fade from the projection origin
11196                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11197                                 f = bound(0.0f, f, 1.0f);
11198                                 c[cornerindex][0] = r * f;
11199                                 c[cornerindex][1] = g * f;
11200                                 c[cornerindex][2] = b * f;
11201                                 c[cornerindex][3] = 1.0f;
11202                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11203                         }
11204                         if (dynamic)
11205                                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence);
11206                         else
11207                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11208                                         R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
11209                 }
11210         }
11211 }
11212
11213 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11214 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
11215 {
11216         int renderentityindex;
11217         float worldmins[3];
11218         float worldmaxs[3];
11219         entity_render_t *ent;
11220
11221         if (!cl_decals_newsystem.integer)
11222                 return;
11223
11224         worldmins[0] = worldorigin[0] - worldsize;
11225         worldmins[1] = worldorigin[1] - worldsize;
11226         worldmins[2] = worldorigin[2] - worldsize;
11227         worldmaxs[0] = worldorigin[0] + worldsize;
11228         worldmaxs[1] = worldorigin[1] + worldsize;
11229         worldmaxs[2] = worldorigin[2] + worldsize;
11230
11231         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11232
11233         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11234         {
11235                 ent = r_refdef.scene.entities[renderentityindex];
11236                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11237                         continue;
11238
11239                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11240         }
11241 }
11242
11243 typedef struct r_decalsystem_splatqueue_s
11244 {
11245         vec3_t worldorigin;
11246         vec3_t worldnormal;
11247         float color[4];
11248         float tcrange[4];
11249         float worldsize;
11250         int decalsequence;
11251 }
11252 r_decalsystem_splatqueue_t;
11253
11254 int r_decalsystem_numqueued = 0;
11255 #define MAX_DECALSYSTEM_QUEUE 1024
11256 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11257
11258 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
11259 {
11260         r_decalsystem_splatqueue_t *queue;
11261
11262         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11263                 return;
11264
11265         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11266         VectorCopy(worldorigin, queue->worldorigin);
11267         VectorCopy(worldnormal, queue->worldnormal);
11268         Vector4Set(queue->color, r, g, b, a);
11269         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11270         queue->worldsize = worldsize;
11271         queue->decalsequence = cl.decalsequence++;
11272 }
11273
11274 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11275 {
11276         int i;
11277         r_decalsystem_splatqueue_t *queue;
11278
11279         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11280                 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
11281         r_decalsystem_numqueued = 0;
11282 }
11283
11284 extern cvar_t cl_decals_max;
11285 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11286 {
11287         int i;
11288         decalsystem_t *decalsystem = &ent->decalsystem;
11289         int numdecals;
11290         int killsequence;
11291         tridecal_t *decal;
11292         float frametime;
11293         float lifetime;
11294
11295         if (!decalsystem->numdecals)
11296                 return;
11297
11298         if (r_showsurfaces.integer)
11299                 return;
11300
11301         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11302         {
11303                 R_DecalSystem_Reset(decalsystem);
11304                 return;
11305         }
11306
11307         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11308         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11309
11310         if (decalsystem->lastupdatetime)
11311                 frametime = (cl.time - decalsystem->lastupdatetime);
11312         else
11313                 frametime = 0;
11314         decalsystem->lastupdatetime = cl.time;
11315         decal = decalsystem->decals;
11316         numdecals = decalsystem->numdecals;
11317
11318         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11319         {
11320                 if (decal->color4ub[0][3])
11321                 {
11322                         decal->lived += frametime;
11323                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11324                         {
11325                                 memset(decal, 0, sizeof(*decal));
11326                                 if (decalsystem->freedecal > i)
11327                                         decalsystem->freedecal = i;
11328                         }
11329                 }
11330         }
11331         decal = decalsystem->decals;
11332         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11333                 numdecals--;
11334
11335         // collapse the array by shuffling the tail decals into the gaps
11336         for (;;)
11337         {
11338                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11339                         decalsystem->freedecal++;
11340                 if (decalsystem->freedecal == numdecals)
11341                         break;
11342                 decal[decalsystem->freedecal] = decal[--numdecals];
11343         }
11344
11345         decalsystem->numdecals = numdecals;
11346
11347         if (numdecals <= 0)
11348         {
11349                 // if there are no decals left, reset decalsystem
11350                 R_DecalSystem_Reset(decalsystem);
11351         }
11352 }
11353
11354 extern skinframe_t *decalskinframe;
11355 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11356 {
11357         int i;
11358         decalsystem_t *decalsystem = &ent->decalsystem;
11359         int numdecals;
11360         tridecal_t *decal;
11361         float fadedelay;
11362         float faderate;
11363         float alpha;
11364         float *v3f;
11365         float *c4f;
11366         float *t2f;
11367         const int *e;
11368         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11369         int numtris = 0;
11370
11371         numdecals = decalsystem->numdecals;
11372         if (!numdecals)
11373                 return;
11374
11375         if (r_showsurfaces.integer)
11376                 return;
11377
11378         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11379         {
11380                 R_DecalSystem_Reset(decalsystem);
11381                 return;
11382         }
11383
11384         // if the model is static it doesn't matter what value we give for
11385         // wantnormals and wanttangents, so this logic uses only rules applicable
11386         // to a model, knowing that they are meaningless otherwise
11387         if (ent == r_refdef.scene.worldentity)
11388                 RSurf_ActiveWorldEntity();
11389         else
11390                 RSurf_ActiveModelEntity(ent, false, false, false);
11391
11392         decalsystem->lastupdatetime = cl.time;
11393         decal = decalsystem->decals;
11394
11395         fadedelay = cl_decals_time.value;
11396         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11397
11398         // update vertex positions for animated models
11399         v3f = decalsystem->vertex3f;
11400         c4f = decalsystem->color4f;
11401         t2f = decalsystem->texcoord2f;
11402         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11403         {
11404                 if (!decal->color4ub[0][3])
11405                         continue;
11406
11407                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11408                         continue;
11409
11410                 // update color values for fading decals
11411                 if (decal->lived >= cl_decals_time.value)
11412                 {
11413                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11414                         alpha *= (1.0f/255.0f);
11415                 }
11416                 else
11417                         alpha = 1.0f/255.0f;
11418
11419                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11420                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11421                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11422                 c4f[ 3] = 1;
11423                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11424                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11425                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11426                 c4f[ 7] = 1;
11427                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11428                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11429                 c4f[10] = decal->color4ub[2][2] * alpha;
11430                 c4f[11] = 1;
11431
11432                 t2f[0] = decal->texcoord2f[0][0];
11433                 t2f[1] = decal->texcoord2f[0][1];
11434                 t2f[2] = decal->texcoord2f[1][0];
11435                 t2f[3] = decal->texcoord2f[1][1];
11436                 t2f[4] = decal->texcoord2f[2][0];
11437                 t2f[5] = decal->texcoord2f[2][1];
11438
11439                 // update vertex positions for animated models
11440                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11441                 {
11442                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11443                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11444                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11445                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11446                 }
11447                 else
11448                 {
11449                         VectorCopy(decal->vertex3f[0], v3f);
11450                         VectorCopy(decal->vertex3f[1], v3f + 3);
11451                         VectorCopy(decal->vertex3f[2], v3f + 6);
11452                 }
11453
11454                 v3f += 9;
11455                 c4f += 12;
11456                 t2f += 6;
11457                 numtris++;
11458         }
11459
11460         if (numtris > 0)
11461         {
11462                 r_refdef.stats.drawndecals += numtris;
11463
11464                 if (r_refdef.fogenabled)
11465                 {
11466                         switch(vid.renderpath)
11467                         {
11468                         case RENDERPATH_GL20:
11469                         case RENDERPATH_CGGL:
11470                         case RENDERPATH_GL13:
11471                         case RENDERPATH_GL11:
11472                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11473                                 {
11474                                         alpha = RSurf_FogVertex(v3f);
11475                                         c4f[0] *= alpha;
11476                                         c4f[1] *= alpha;
11477                                         c4f[2] *= alpha;
11478                                 }
11479                                 break;
11480                         }
11481                 }
11482
11483                 // now render the decals all at once
11484                 // (this assumes they all use one particle font texture!)
11485                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11486                 R_Mesh_ResetTextureState();
11487                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11488                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11489                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11490                 GL_DepthMask(false);
11491                 GL_DepthRange(0, 1);
11492                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11493                 GL_DepthTest(true);
11494                 GL_CullFace(GL_NONE);
11495                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11496                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11497                 GL_LockArrays(0, numtris * 3);
11498                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11499                 GL_LockArrays(0, 0);
11500         }
11501 }
11502
11503 static void R_DrawModelDecals(void)
11504 {
11505         int i, numdecals;
11506
11507         // fade faster when there are too many decals
11508         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11509         for (i = 0;i < r_refdef.scene.numentities;i++)
11510                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11511
11512         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11513         for (i = 0;i < r_refdef.scene.numentities;i++)
11514                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11515                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11516
11517         R_DecalSystem_ApplySplatEntitiesQueue();
11518
11519         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11520         for (i = 0;i < r_refdef.scene.numentities;i++)
11521                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11522
11523         r_refdef.stats.totaldecals += numdecals;
11524
11525         if (r_showsurfaces.integer)
11526                 return;
11527
11528         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11529
11530         for (i = 0;i < r_refdef.scene.numentities;i++)
11531         {
11532                 if (!r_refdef.viewcache.entityvisible[i])
11533                         continue;
11534                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11535                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11536         }
11537 }
11538
11539 void R_DrawDebugModel(void)
11540 {
11541         entity_render_t *ent = rsurface.entity;
11542         int i, j, k, l, flagsmask;
11543         const int *elements;
11544         q3mbrush_t *brush;
11545         const msurface_t *surface;
11546         dp_model_t *model = ent->model;
11547         vec3_t v;
11548
11549         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11550
11551         R_Mesh_ColorPointer(NULL, 0, 0);
11552         R_Mesh_ResetTextureState();
11553         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11554         GL_DepthRange(0, 1);
11555         GL_DepthTest(!r_showdisabledepthtest.integer);
11556         GL_DepthMask(false);
11557         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11558
11559         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11560         {
11561                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11562                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11563                 {
11564                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11565                         {
11566                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11567                                 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);
11568                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11569                         }
11570                 }
11571                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11572                 {
11573                         if (surface->num_collisiontriangles)
11574                         {
11575                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11576                                 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);
11577                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11578                         }
11579                 }
11580         }
11581
11582         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11583
11584         if (r_showtris.integer || r_shownormals.integer)
11585         {
11586                 if (r_showdisabledepthtest.integer)
11587                 {
11588                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11589                         GL_DepthMask(false);
11590                 }
11591                 else
11592                 {
11593                         GL_BlendFunc(GL_ONE, GL_ZERO);
11594                         GL_DepthMask(true);
11595                 }
11596                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11597                 {
11598                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11599                                 continue;
11600                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11601                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11602                         {
11603                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11604                                 if (r_showtris.value > 0)
11605                                 {
11606                                         if (!rsurface.texture->currentlayers->depthmask)
11607                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11608                                         else if (ent == r_refdef.scene.worldentity)
11609                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11610                                         else
11611                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11612                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11613                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11614                                         R_Mesh_ColorPointer(NULL, 0, 0);
11615                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11616                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11617                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11618                                         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);
11619                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11620                                         CHECKGLERROR
11621                                 }
11622                                 if (r_shownormals.value < 0)
11623                                 {
11624                                         qglBegin(GL_LINES);
11625                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11626                                         {
11627                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11628                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11629                                                 qglVertex3f(v[0], v[1], v[2]);
11630                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11631                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11632                                                 qglVertex3f(v[0], v[1], v[2]);
11633                                         }
11634                                         qglEnd();
11635                                         CHECKGLERROR
11636                                 }
11637                                 if (r_shownormals.value > 0)
11638                                 {
11639                                         qglBegin(GL_LINES);
11640                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11641                                         {
11642                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11643                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11644                                                 qglVertex3f(v[0], v[1], v[2]);
11645                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11646                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11647                                                 qglVertex3f(v[0], v[1], v[2]);
11648                                         }
11649                                         qglEnd();
11650                                         CHECKGLERROR
11651                                         qglBegin(GL_LINES);
11652                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11653                                         {
11654                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11655                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11656                                                 qglVertex3f(v[0], v[1], v[2]);
11657                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11658                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11659                                                 qglVertex3f(v[0], v[1], v[2]);
11660                                         }
11661                                         qglEnd();
11662                                         CHECKGLERROR
11663                                         qglBegin(GL_LINES);
11664                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11665                                         {
11666                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11667                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11668                                                 qglVertex3f(v[0], v[1], v[2]);
11669                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11670                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11671                                                 qglVertex3f(v[0], v[1], v[2]);
11672                                         }
11673                                         qglEnd();
11674                                         CHECKGLERROR
11675                                 }
11676                         }
11677                 }
11678                 rsurface.texture = NULL;
11679         }
11680 }
11681
11682 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11683 int r_maxsurfacelist = 0;
11684 const msurface_t **r_surfacelist = NULL;
11685 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11686 {
11687         int i, j, endj, f, flagsmask;
11688         texture_t *t;
11689         dp_model_t *model = r_refdef.scene.worldmodel;
11690         msurface_t *surfaces;
11691         unsigned char *update;
11692         int numsurfacelist = 0;
11693         if (model == NULL)
11694                 return;
11695
11696         if (r_maxsurfacelist < model->num_surfaces)
11697         {
11698                 r_maxsurfacelist = model->num_surfaces;
11699                 if (r_surfacelist)
11700                         Mem_Free((msurface_t**)r_surfacelist);
11701                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11702         }
11703
11704         RSurf_ActiveWorldEntity();
11705
11706         surfaces = model->data_surfaces;
11707         update = model->brushq1.lightmapupdateflags;
11708
11709         // update light styles on this submodel
11710         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11711         {
11712                 model_brush_lightstyleinfo_t *style;
11713                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11714                 {
11715                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11716                         {
11717                                 int *list = style->surfacelist;
11718                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11719                                 for (j = 0;j < style->numsurfaces;j++)
11720                                         update[list[j]] = true;
11721                         }
11722                 }
11723         }
11724
11725         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11726
11727         if (debug)
11728         {
11729                 R_DrawDebugModel();
11730                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11731                 return;
11732         }
11733
11734         f = 0;
11735         t = NULL;
11736         rsurface.uselightmaptexture = false;
11737         rsurface.texture = NULL;
11738         rsurface.rtlight = NULL;
11739         numsurfacelist = 0;
11740         // add visible surfaces to draw list
11741         for (i = 0;i < model->nummodelsurfaces;i++)
11742         {
11743                 j = model->sortedmodelsurfaces[i];
11744                 if (r_refdef.viewcache.world_surfacevisible[j])
11745                         r_surfacelist[numsurfacelist++] = surfaces + j;
11746         }
11747         // update lightmaps if needed
11748         if (update)
11749         {
11750                 int updated = 0;
11751                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11752                 {
11753                         if (r_refdef.viewcache.world_surfacevisible[j])
11754                         {
11755                                 if (update[j])
11756                                 {
11757                                         updated++;
11758                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11759                                 }
11760                         }
11761                 }
11762         }
11763         // don't do anything if there were no surfaces
11764         if (!numsurfacelist)
11765         {
11766                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11767                 return;
11768         }
11769         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11770         GL_AlphaTest(false);
11771
11772         // add to stats if desired
11773         if (r_speeds.integer && !skysurfaces && !depthonly)
11774         {
11775                 r_refdef.stats.world_surfaces += numsurfacelist;
11776                 for (j = 0;j < numsurfacelist;j++)
11777                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11778         }
11779
11780         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11781 }
11782
11783 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11784 {
11785         int i, j, endj, f, flagsmask;
11786         texture_t *t;
11787         dp_model_t *model = ent->model;
11788         msurface_t *surfaces;
11789         unsigned char *update;
11790         int numsurfacelist = 0;
11791         if (model == NULL)
11792                 return;
11793
11794         if (r_maxsurfacelist < model->num_surfaces)
11795         {
11796                 r_maxsurfacelist = model->num_surfaces;
11797                 if (r_surfacelist)
11798                         Mem_Free((msurface_t **)r_surfacelist);
11799                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11800         }
11801
11802         // if the model is static it doesn't matter what value we give for
11803         // wantnormals and wanttangents, so this logic uses only rules applicable
11804         // to a model, knowing that they are meaningless otherwise
11805         if (ent == r_refdef.scene.worldentity)
11806                 RSurf_ActiveWorldEntity();
11807         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11808                 RSurf_ActiveModelEntity(ent, false, false, false);
11809         else if (prepass)
11810                 RSurf_ActiveModelEntity(ent, true, true, true);
11811         else if (depthonly)
11812                 RSurf_ActiveModelEntity(ent, false, false, false);
11813         else
11814         {
11815                 switch (vid.renderpath)
11816                 {
11817                 case RENDERPATH_GL20:
11818                 case RENDERPATH_CGGL:
11819                         RSurf_ActiveModelEntity(ent, true, true, false);
11820                         break;
11821                 case RENDERPATH_GL13:
11822                 case RENDERPATH_GL11:
11823                         RSurf_ActiveModelEntity(ent, true, false, false);
11824                         break;
11825                 }
11826         }
11827
11828         surfaces = model->data_surfaces;
11829         update = model->brushq1.lightmapupdateflags;
11830
11831         // update light styles
11832         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11833         {
11834                 model_brush_lightstyleinfo_t *style;
11835                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11836                 {
11837                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11838                         {
11839                                 int *list = style->surfacelist;
11840                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11841                                 for (j = 0;j < style->numsurfaces;j++)
11842                                         update[list[j]] = true;
11843                         }
11844                 }
11845         }
11846
11847         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11848
11849         if (debug)
11850         {
11851                 R_DrawDebugModel();
11852                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11853                 return;
11854         }
11855
11856         f = 0;
11857         t = NULL;
11858         rsurface.uselightmaptexture = false;
11859         rsurface.texture = NULL;
11860         rsurface.rtlight = NULL;
11861         numsurfacelist = 0;
11862         // add visible surfaces to draw list
11863         for (i = 0;i < model->nummodelsurfaces;i++)
11864                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11865         // don't do anything if there were no surfaces
11866         if (!numsurfacelist)
11867         {
11868                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11869                 return;
11870         }
11871         // update lightmaps if needed
11872         if (update)
11873         {
11874                 int updated = 0;
11875                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11876                 {
11877                         if (update[j])
11878                         {
11879                                 updated++;
11880                                 R_BuildLightMap(ent, surfaces + j);
11881                         }
11882                 }
11883         }
11884         if (update)
11885                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11886                         if (update[j])
11887                                 R_BuildLightMap(ent, surfaces + j);
11888         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11889         GL_AlphaTest(false);
11890
11891         // add to stats if desired
11892         if (r_speeds.integer && !skysurfaces && !depthonly)
11893         {
11894                 r_refdef.stats.entities_surfaces += numsurfacelist;
11895                 for (j = 0;j < numsurfacelist;j++)
11896                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11897         }
11898
11899         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11900 }
11901
11902 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11903 {
11904         static texture_t texture;
11905         static msurface_t surface;
11906         const msurface_t *surfacelist = &surface;
11907
11908         // fake enough texture and surface state to render this geometry
11909
11910         texture.update_lastrenderframe = -1; // regenerate this texture
11911         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11912         texture.currentskinframe = skinframe;
11913         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11914         texture.specularscalemod = 1;
11915         texture.specularpowermod = 1;
11916
11917         surface.texture = &texture;
11918         surface.num_triangles = numtriangles;
11919         surface.num_firsttriangle = firsttriangle;
11920         surface.num_vertices = numvertices;
11921         surface.num_firstvertex = firstvertex;
11922
11923         // now render it
11924         rsurface.texture = R_GetCurrentTexture(surface.texture);
11925         rsurface.uselightmaptexture = false;
11926         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11927 }
11928
11929 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11930 {
11931         static msurface_t surface;
11932         const msurface_t *surfacelist = &surface;
11933
11934         // fake enough texture and surface state to render this geometry
11935
11936         surface.texture = texture;
11937         surface.num_triangles = numtriangles;
11938         surface.num_firsttriangle = firsttriangle;
11939         surface.num_vertices = numvertices;
11940         surface.num_firstvertex = firstvertex;
11941
11942         // now render it
11943         rsurface.texture = R_GetCurrentTexture(surface.texture);
11944         rsurface.uselightmaptexture = false;
11945         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11946 }